Home   Help Search Login Register  

Author Topic: MultiTask - Multiplayer tasks made easy  (Read 2261 times)

0 Members and 1 Guest are viewing this topic.

Offline Deadfast

  • Members
  • *
MultiTask - Multiplayer tasks made easy
« on: 19 Aug 2010, 14:50:47 »
Why?
ARMA 2 introduced a brand new task system. Unfortunately for mutliplayer mission makers this system in local and getting tasks synchronized across the network can be a bit of a hassle.

How?
MultiTask is a system which eliminates the synchronization issue by introducing a set of functions equivalent to the game's own task commands (DFS_ prefix + command name), plus a function to broadcast these local changes to all currently connected clients and those who might join in progress later. The system also fully supports stringtable and task descriptions and displays will be shown to the clients in their game language should the mission maker opt for this.

Technical background
MultiTask uses setVariable to handle JIP and public broadcast.
Remote Execution's rSPAWN is used to execute client-side update functions on each machine.

Example mission
A simple practical Utes example mission is included in the ZIP. ARMA 2 or Combined Operations are required to run it.

Readme
Quote
MultiTask - Multiplayer tasks made easy
Version 0.1.2

Created by Deadfast (http://deadfast.armaholic.eu)
Licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (http://creativecommons.org/licenses/by-nc-sa/3.0/)
   - You are free to adopt this work as long as credit is given to all the previous authors in your readme and your work is licensed under the same license.


Important:
----------
   - Requires a functions module to be present!
   - The task names are global variables, therefore same rules apply (use of TAG_ prefix is strongly recommended - http://www.ofpec.com/faq/index.php?action=read&cat=202&id=56)
   - Never use a global variable with the same name as one of your tasks
   - All arguments marked as <COMPILE STRING> expect a code that will be compiled to form a string. This allows you to insert local values using the format command:
      "format[""%1, you have to destroy the tanks!"", name player]"
     You can also use the localize command if you use a stringtable:
      "localize ""STR_dfs_text1"""
     If you do not wish to do either simply wrap the text in strings twice:
       " ""Sample Task"" "

     Do not forget to escape the strings by adding another quote mark to every present one for each string level you enter:

     Level      #      Example
     1.      1      "word"
     2.      2      ""word""
     3.      3      """"word"""
     4.      4      """"""""word""""""""
     n.       2^(n-1)

     IMPORTANT:   You mustn't use apostrophes (') in anything that interacts with MultiTask (including stringtable entries). If you need to use it for possessives you may use the XML break code instead:   &apos;   (yes, both the ampersand and the semicolon belong there).
               Unfortunately this only works for the task description, not the title.

Implementation:
---------------
   Insert a functions module to your mission and give it a unique name (let's assume it would be TAG_core).
   Extract "multitask.sqf" from the ZIP archive and place it in the root of your mission.
   Create "init.sqf" in the root of your mission.
   Insert     <Functions module name> execVM "multitask.sqf"     to the top of "init.sqf", <Functions module name> is the name you had previously given to the functions module:
            TAG_core execVM "multitask.sqf";
   Insert     [] call DFS_tasksSync;     under the execVM line from above. This will make sure all clients joining in progress will have their tasks in sync with the server.
   Use the functions described bellow to achieve a multiplayer-compatible task system. See the example mission (multitask_example.utes) for a practical example.


Functions:
----------
   DFS_taskCommit - applies changes to the given task on all clients, task has to be created using DFS_createSimpleTask beforehand.
      - Arguments:
         Task name <STRING>
      - Returns:
         Nothing
      - Examples:
         "TAG_task1" call DFS_taskCommit;
      - Notes:
         Function has global effect and can be executed on any machine.

   DFS_taskCommitLocal - applies changes to the given task on machine where executed, task has to be created using DFS_createSimpleTask beforehand.
      - Arguments:
         Task name <STRING>
      - Returns:
         Nothing
      - Examples:
         "TAG_task1" call DFS_taskCommitLocal;
      - Notes:
         Function has only local effect and has to be executed on the machine where results are intended.

   DFS_tasksSync - makes sure the machine's tasks are in sync, should be called after joining in progress.
      - Arguments:
         [] <EMPTY ARRAY>
      - Returns:
         Nothing
      - Examples:
         [] call DFS_taskCommitJIP;
      - Notes:
         Function has only local effect and has to be executed on the machine where results are intended.

   DFS_taskExists - checks whether the given task already exists
      - Arguments:
         Task name <STRING>
      - Returns:
         true/false <BOOL>
      - Examples:
         if (!("DFS_test1" call DFS_taskExists)) then
         {
            ["DFS_test1", ""Destroy enemy tanks""] call DFS_createSimpleTask;
         };
      - Notes:
         Checks the global value shared among the multiplayer clients/server rather than the local one. You can use     isNil _taskName     for that.

   DFS_createSimpleTask - createSimpleTask counterpart.
      - Arguments:
         [Task name <STRING>, Title <COMPILE STRING>] <ARRAY>
            OR
         [Task name <STRING>, Title <COMPILE STRING>, Parent task name <STRING>] <ARRAY>
      - Returns:
         Nothing
      - Examples:
         ["TAG_task1", "STR_TAG_task1"] call DFS_createSimpleTask;
         ["TAG_task1_a", ""Do not get spotted"", "TAG_task1"] call DFS_createSimpleTask;
      - Notes:
         Task name must follow the rules of a global variable name - only alphabetical characters for the first character and must be unique.
         Requires a call to DFS_taskCommit for the clients to add the task.
         Function has global effect and can be executed on any machine.

   DFS_createTask - createSimpleTask counterpart, same as and alternative to DFS_createSimpleTask.
      See DFS_createSimpleTask...

   DFS_setSimpleTaskDescription - setSimpleTask counterpart.
      - Arguments:
         [Task name <STRING>, Full description <COMPILE STRING>, Task title <COMPILE STRING>, Map caption <COMPILE STRING>] <ARRAY>
      - Returns:
         Nothing
      - Examples:
         ["TAG_task1", "STR_TAG_task1desc", "STR_TAG_task1", ""Enemy tanks""] call DFS_setSimpleTaskDescription;
      - Notes:
         Not required for the task to work.
         Requires a call to DFS_taskCommit for the change to take effect on all clients.
         Function has global effect and can be executed on any machine.

   DFS_setTaskDescription - setSimpleTask counterpart, same as and alternative to DFS_setSimpleTaskDescription.
      See DFS_setSimpleTaskDescription...

   DFS_taskDescription - taskDescription counterpart.
      - Arguments:
         Task name <STRING>
      - Returns:
         [Full description <COMPILE STRING>, Task title <COMPILE STRING>, Map caption <COMPILE STRING>] <ARRAY>
      - Examples:
         _taskTitle = ("TAG_task1" call DFS_taskDescription) select 1;
      - Notes:
         Differs from the taskDescription command by returning the global value shared among the multiplayer clients/server rather than the local one

   DFS_getSimpleTaskDescription - taskDescription counterpart, same as and alternative to DFS_taskDescription.
      See DFS_taskDescription...

   DFS_getTaskDescription - taskDescription counterpart, same as and alternative to DFS_taskDescription.
      See DFS_taskDescription...

   DFS_setSimpleTaskDestination - setSimpleTaskDestination counterpart.
      - Arguments:
         [Task name <STRING>, Position <POSITION 3D or POSITION 2D>] <ARRAY>
      - Returns:
         Nothing
      - Examples:
         ["TAG_task1", (getPos DFS_u_tank1)] call DFS_setSimpleTaskDestination;
         ["TAG_task1", (getMarkerPos "DFS_m_tanks")] call DFS_setSimpleTaskDestination;
      - Notes:
         Not required for the task to work.
         Requires a call to DFS_taskCommit for the change to take effect on all clients.
         Function has global effect and can be executed on any machine.

   DFS_setTaskDestination - setSimpleTaskDestination counterpart, same as and alternative to DFS_setSimpleTaskDestination.
      See DFS_setSimpleTaskDestination...

   DFS_taskDestination - taskDestination counterpart.
      - Arguments:
         Task name <STRING>
      - Returns:
         Position <POSITION 3D>
      - Examples:
         _pos = "TAG_task1" call DFS_taskDestination;
      - Notes:
         Differs from the taskDestination command by returning the global value shared among the multiplayer clients/server rather than the local one.

   DFS_getSimpleTaskDestination - taskDestination counterpart, same as and alternative to DFS_taskDestination.
      See DFS_taskDestination...

   DFS_getTaskDestination - taskDestination counterpart, same as and alternative to DFS_taskDestination.
      See DFS_taskDestination...

   DFS_setTaskState - setTaskState counterpart.
      - Arguments:
         [Task name <STRING>, Task state <STRING>] <ARRAY>
      - Examples:
         ["TAG_task1_a", "Failed"] call DFS_setTaskState;
      - Returns:
         Nothing
      - Notes:
         Task state has to be one of the following, argument is not case-sensitive:
            - "Succeeded"
            - "Failed"
            - "Canceled"
            - "Created"
            - "Assigned"
         Requires a call to DFS_taskCommit for the change to take effect on all clients.
         Function has global effect and can be executed on any machine.

   DFS_taskState - taskState counterpart.
      - Arguments:
         Task name <STRING>
      - Returns:
         Task state <STRING>
      - Examples:
         if (("DFS_test1" call DFS_taskState) == "failed") then
         ...
      - Notes:
         Returns one of the following values:
            - "succeeded"
            - "failed"
            - "canceled"
            - "created"
            - "assigned"
         Differs from the taskState command by returning the global value shared among the multiplayer clients/server rather than the local one.

   DFS_getTaskState - taskState counterpart, same as and alternative to DFS_taskState.
      See DFS_taskState...

   DFS_setTaskUnits - sets which units will have the specified task added.
      - Arguments:
         [Task name <STRING>, Units <ARRAY of OBJECTS>] <ARRAY>
      - Returns:
         Nothing
      - Examples:
         ["TAG_task1", [DFS_u_guy1, DFS_u_guy2, DFS_u_guy3]] call DFS_setTaskUnits;
      - Notes:
         Unit can be null when added with the array.
         Not required for the task to work, if not specified all players will receive the task.
         You can use empty array to remove any unit limitation.
         Requires a call to DFS_taskCommit for the change to take effect on all clients.
         Function has global effect and can be executed on any machine.

   DFS_addTaskUnit - adds a unit to the list of those who will have the specified task added.
      - Arguments:
         [Task name <STRING>, Unit <OBJECT>] <ARRAY>
      - Returns:
         Nothing
      - Examples:
         ["TAG_task1", DFS_u_guy4] call DFS_addTaskUnit;
      - Notes:
         Unit can be null when added.
         Not required for the task to work, if not specified all players will receive the task.
         Requires a call to DFS_taskCommit for the change to take effect on all clients.
         Function has global effect and can be executed on any machine.

   DFS_taskUnits - Returns array of units who will have the specified task added.
      - Arguments:
         Task name <STRING>
      - Returns:
         Units <ARRAY of OBJECTS>
      - Examples:
         _units = "TAG_task1" call DFS_taskUnits;
         _units =+ ("TAG_task1" call DFS_taskUnits);
      - Notes:
         WARNING: Returned array acts like a POINTER to the task's local array! Any changes (+, -, set, = nil) will be automatically applied to the source array too. See example #2 for how to avoid it.

   DFS_getTaskUnits - Returns array of units who will have the specified task added., same as and alternative to DFS_taskUnits
      See DFS_taskUnits...

   DFS_setTaskGroups - sets which groups will have the specified task added.
      - Arguments:
         [Task name <STRING>, Groups <ARRAY of GROUPS>] <ARRAY>
      - Returns:
         Nothing
      - Examples:
         ["TAG_task1", [DFS_group1, DFS_group2, DFS_group3]] call DFS_setTaskGroups;
      - Notes:
         Group's units can be null when added with the array.
         Not required for the task to work, if not specified all players will receive the task.
         You can use empty array to remove any group limitation.
         Requires a call to DFS_taskCommit for the change to take effect on all clients.
         Function has global effect and can be executed on any machine.

   DFS_addTaskGroup - adds a group to the list of those who will have the specified task added.
      - Arguments:
         [Task name <STRING>, Group <GROUP>] <ARRAY>
      - Returns:
         Nothing
      - Examples:
         ["TAG_task1", group DFS_u_guy4] call DFS_addTaskUnit;
      - Notes:
         Group's unit can be null when added.
         Not required for the task to work, if not specified all players will receive the task.
         Requires a call to DFS_taskCommit for the change to take effect on all clients.
         Function has global effect and can be executed on any machine.

   DFS_taskGroups - Returns array of units who will have the specified task added.
      - Arguments:
         Task name <STRING>
      - Returns:
         Groups <ARRAY of GROUPS>
      - Examples:
         _units = "TAG_task1" call DFS_taskGroups;
         _units =+ ("TAG_task1" call DFS_taskGroups);
      - Notes:
         WARNING: Returns a POINTER to the original array! Any changes (+, -, set, = nil) to the returned array will be automatically applied to the local task's array. See example #2 for how to avoid it.

   DFS_getTaskGroups - Returns array of units who will have the specified task added, same as and alternative to DFS_taskGroups
      See DFS_taskGroups...

   DFS_removeSimpleTask - removeSimpleTask counterpart.
      - Arguments:
         Task name <STRING>
      - Returns:
         Nothing
      - Examples:
         "TAG_task1" call DFS_removeSimpleTask;
      - Notes:
         Does NOT require a call to DFS_taskCommit for the change to take effect on all clients.
         Function has global effect and can be executed on any machine.

   DFS_removeSimpleTaskLocal - removeSimpleTask counterpart.
      - Arguments:
         Task name <STRING>
      - Returns:
         Nothing
      - Examples:
         "TAG_task1" call DFS_removeSimpleTaskLocal;
      - Notes:
         Function has only local effect and has to be executed on the machine where results are intended.

   DFS_taskHint - shows a taskHint for the specified task on all currently connected clients.
      - Arguments:
         Task name <STRING>
      - Returns:
         Nothing
      - Examples:
         "TAG_task1_a" call DFS_taskHint
      - Notes:
         Function has global effect and can be executed on any machine.

   DFS_taskHintLocal - shows a taskHint for the specified task only on the machine the functions is called on.
      - Arguments:
         Task name <STRING>
      - Returns:
         Nothing
      - Examples:
         "TAG_task1_a" call DFS_taskHintLocal
      - Notes:
         Function has only local effect and has to be executed on the machine where results are intended.


Reserved variables:
-------------------
   Please ensure your mission does not use any of the following variables:
      - DFS_missionCore
      - DFS_errorDisplay
      - DFS_taskCommit
      - DFS_taskCommitLocal
      - DFS_tasksSync
      - DFS_taskExists
      - DFS_createSimpleTask
      - DFS_createTask
      - DFS_setSimpleTaskDescription
      - DFS_setTaskDescription
      - DFS_taskDescription
      - DFS_getSimpleTaskDescription
      - DFS_getTaskDescription
      - DFS_setSimpleTaskDestination
      - DFS_setTaskDestination
      - DFS_taskDestination
      - DFS_getSimpleTaskDestination
      - DFS_setTaskDestination
      - DFS_setTaskState
      - DFS_taskState
      - DFS_getTaskState
      - DFS_setTaskUnits
      - DFS_addTaskUnit
      - DFS_taskUnits
      - DFS_getTaskUnits
      - DFS_setTaskGroups
      - DFS_addTaskGroup
      - DFS_taskGroups
      - DFS_getTaskGroups
      - DFS_removeSimpleTask
      - DFS_removeSimpleTaskLocal
      - DFS_taskHint
      - DFS_taskHintLocal

Offline kju

  • Members
  • *
    • PvPScene - The ArmA II multiplayer community
Re: MultiTask - Multiplayer tasks made easy
« Reply #1 on: 19 Aug 2010, 19:04:51 »
Thanks for sharing.  :good: