leysard 10 Posted August 31, 2013 Hy, I want to assign tasks randomly to a team (Multiplayer). Say that task 00 starts at the beginning of mission. When task 00 is finisched, I want to assign to all players a task between task N° 1 to N° 4. Then when that task is succeeded, assign random task not succeeded out of the 3 left, then again then again and that makes all 4 tasks finisched but in different order from one time to another. I did not find a script and complete explanation to manage that. Can someone help me out ? Share this post Link to post Share on other sites
Zenophon 110 Posted August 31, 2013 (edited) I assume you are using an editor trigger to complete the first task. The code I wrote below will run in parallel with the trigger until the first task is completed. Then, the function relies on another trigger to complete the next task, and so on. In you init.sqf, define a function like this: Zen_AssignRandomTask = { /* * Loops through the given array of tasks and uses BIS functions to set * a new random task as current when the current task is failed or succeeded * Params: 1. Array of strings, the task names * Return: Null */ if !(isServer) exitWith {}; private ["_taskArray", "_task"]; _taskArray = _this select 0; _task = _taskArray select 0; _taskArray = _taskArray - [_task]; 0 = [_task] spawn BIS_fnc_taskSetCurrent; while {((count _taskArray) > 0)} do { waitUntil { sleep 2; (([_task] call BIS_fnc_taskState) in ["failed", "succeeded"]) }; _task = (_taskArray select (floor (random ((count _taskArray) - 0.0001)))); _taskArray = _taskArray - [_task]; 0 = [_task] spawn BIS_fnc_taskSetCurrent; }; }; You could then call the function from any object's init field in the editor like so: 0 = [["task0", "task1", "task2", "task3", "task4"]] spawn Zen_AssignRandomTask; You will have to change 'task0' etc to the correct names of your tasks, and this function sets the first task a current for you. This is untested in both singleplayer and multiplayer, as I cannot test it in the context of your mission (actually giving the tasks that this script requires). If it does not work in multiplayer, try removing 'if !(isServer) exitWith {};' from the beginning of the function. I do not use the BIS task functions very much, so I do not know how well they work in multiplayer or if you need that check. I also assume from briefly looking at the BIS functions about tasks, that the units that get the task set as current are given when calling BIS_fnc_taskCreate and not BIS_fnc_taskSetCurrent. If this does not work in multiplayer, consider looking for tasks systems made by community members, as they might be able to manage tasks better than manually calling BIS functions. Edited August 31, 2013 by Zenophon Share this post Link to post Share on other sites
kylania 568 Posted August 31, 2013 So many examples of this on the forums... did you search? Share this post Link to post Share on other sites
leysard 10 Posted August 31, 2013 Kylania, Sorry, yes I did search, but not found what I was looking for. Thats the reason of my post. Zenophon, Thanks for your help, but even if removing line, it does not work. Always goes on to task4 and never moves on to next one. Maybe I'm wrong with the way I built my mission. PM'd the zip file of it so that you could have a look. I would really appreciate. Thanks, Leysard Share this post Link to post Share on other sites
Zenophon 110 Posted August 31, 2013 (edited) First, I made an obvious mistake in the example of using the function. It should be 'spawn' not 'call' that is used. I have edited my previous post to reflect that. Next, looking at your mission and poking around the mission.sqm, I saw that you used my function four times in four task modules. That would create four threads that are looping at the same time, causing odd behavior. To clarify, execute the function only once from a single object's init field in the editor. Also, I did not find a create task module named 'task00', even when searching for that word in the mission.sqm. However, the call to Zen_AssignRandomTask includes 'task00' as an argument. Make sure you create that task with a module or a script. Then, I tested in an empty mission to confirm that it worked. I set up four task modules synch'd to the player and used my function and BIS functions in the debug console to test. I found an odd issue with BIS_fnc_taskSetCurrent in which the function redefined the local variable '_task'. I am not sure if there is some error in the function itself or it is a bug. There is some issue with variable scope that I cannot track down in the BIS functions. To fix this, I have used 'spawn' instead of 'call' for BIS_fnc_taskSetCurrent; I have made this change in my previous post. Also note, in my tests I used BIS_fnc_taskSetState to complete the tasks, but I assume that a task state module works the same way. Finally, I did get the function to work in singleplayer, but I still cannot comment on multiplayer performance. Edited August 31, 2013 by Zenophon typo Share this post Link to post Share on other sites
leysard 10 Posted September 4, 2013 So, I've been trying several different things to get all that working. I would like to learn to use correctly Arma 3 Scripting and must recognize that I've got a long way to go. I had my own try to creating a script that I can call when I want with a trigger for example. But, obviously, it does not work. So, here it is and please, could someone help me make that one work ? At this point, I just want to be able to randomly select a task in my array. I get the error message at the count point. Later, I will use the selected task to open a file with the scripted task. if (!isServer) exitwith {}; if (Task != "done") then {Task = "tasks\Task.sqf";}; if (Task_1 != "done") then {Task_1 = "tasks\Task_1.sqf";}; if (Task_2 != "done") then {Task_2 = "tasks\Task_2.sqf";}; if (Task_3 != "done") then {Task_3 = "tasks\Task_3.sqf";}; if (Task != "done") then {Tasks = Task;}; if (Task_1 != "done") then {Tasks = Tasks + Task_1;}; if (Task_2 != "done") then {Tasks = Tasks + Task_2;}; if (Task_3 != "done") then {Tasks = Tasks + Task_3;}; SelectedTask = Tasks select (floor (random (count Tasks))); hint SelectedTask; Share this post Link to post Share on other sites
Zenophon 110 Posted September 4, 2013 You are using the variable 'Tasks' like it is an array without declaring it as an array. The error likely indicates that 'count' cannot act on a string. Try this method: Tasks = []; Tasks set [(count Tasks), Task]; Declare 'Tasks' before checking to add strings to it, then append the string to the array with 'set'. The 'set' command is also faster than binary addition. Furthermore, 'Task_1' etc are not defined when being compared to 'done'. I assume that since these are global variables they are being declared elsewhere; it would be helpful if you posted where and how. Share this post Link to post Share on other sites
leysard 10 Posted September 4, 2013 Zenophon, Thank you very much for your help, the random Task selector now works perfectly. Regarding the "done" of the global variables, I'm now going to look either to put them in triggers in mission or if i'm going to script them. I'm planning on creating 1 .sqf file per mission/task, that will be called by triggers or by script going to the random file. Again thanks for the help Share this post Link to post Share on other sites
kylania 568 Posted September 4, 2013 If you're using the task system you don't need global variables to keep track of if they are done or not. There are functions to check the state, just compare that to "SUCCEEDED" or not. Share this post Link to post Share on other sites