Task System Usage – Arma Reforger

From Bohemia Interactive Community
Tag: Manual revert
 
(43 intermediate revisions by 2 users not shown)
Line 1: Line 1:
As a rule, the task system is used with the Scenario Framework. In this article, you will learn how to use it separately.  
As a rule, the task system is used with the Scenario Framework. In this article, you will learn how to use it separately.


=== Setup ===
The '''SCR_TaskSystem''' game system is a tool for controlling tasks. The system is automatically registered, and you don't need to add anything to it.


==== Workbench World Editor ====
== Setup ==
You can directly place prefabs in the world. They will be automatically inserted into the task system on init.  
 
The <enforce inline>SCR_TaskSystem</enforce> game system is a tool for controlling tasks. The system is automatically registered, and you do not need to add anything to it.
 
=== World Editor ===
 
You can directly place prefabs in the world. They will be automatically inserted into the task system on init.


There are two basic task prefabs:
There are two basic task prefabs:


* <span style="color: orange;">{1D0F815858EE24AD}Prefabs/Tasks/</span><span style="color: blue;">BaseTask.et</span>
* {{Link|enfusion://ResourceManager/~ArmaReforger:Prefabs/Tasks/BaseTask.et}}
* <span style="color: orange;">{CF6A2A13DF7B1018}Prefabs/Tasks/</span><span style="color: blue;">ExtendedTask.et</span>
* {{Link|enfusion://ResourceManager/~ArmaReforger:Prefabs/Tasks/ExtendedTask.et}}


Scenario Framework tasks folder: ''Prefabs/Systems/ScenarioFramework/Tasks/''
Scenario Framework tasks folder: ''Prefabs/Systems/ScenarioFramework/Tasks/''
[[File:Task System Workbench UI.png|none|thumb|450px]]
[[File:Task System Workbench UI.png|none|thumb|450px]]
<nowiki>*</nowiki>The featured fields exist only for the extended tasks.
<nowiki>*</nowiki>The featured fields exist only for the [[#Tasks and Extended Tasks|extended tasks]].
 
Base properties:
Base properties:


Line 20: Line 24:
* '''Task UI Info:''' data to be shown in the game UI: a name, a description, an icon, and an icon set name.
* '''Task UI Info:''' data to be shown in the game UI: a name, a description, an icon, and an icon set name.
* '''Task State:''' initial state of the task.
* '''Task State:''' initial state of the task.
* '''Task Ownership:''' ownership level.
* '''Task Ownership:''' [[#Ownership and Visibility|ownership level]].
* '''Task Visibility:''' visibility level.
* '''Task Visibility:''' [[#Ownership and Visibility|visibility level]].
* '''Task UI Visibility:''' UI visibility level to determine where the task is visible for players (a task list, a map, or both).
* '''Task UI Visibility:''' UI visibility level to determine where the task is visible for players (a task list, a map, or both).
* '''Owner Faction Keys:''' key of factions that are owners or viewers of the task.  
* '''Owner Faction Keys:''' key of factions that are owners or viewers of the task.
* '''Owner Group IDs:''' group ID of groups that are owners of viewers of the task.
* '''Owner Group IDs:''' group ID of groups that are owners of viewers of the task.
* '''Owner Executors:''' task executor that is owner or viewer of the task.
* '''Owner Executors:''' [[#Task Executor|task executor]] that is owner or viewer of the task.
* '''Assignees:''' array that allows you to pre-assign players/groups/entities on init.
* '''Assignees:''' array that allows you to pre-assign players/groups/entities on init.


Extended properties:
Extended properties:


* '''Link Data To Related Tasks:''' enable or disable sharing data between parent/child tasks if you work with nested tasks.
* '''Link Data To Related Tasks:''' enable or disable sharing data between parent/child tasks if you work with [[#Task Nesting|nested tasks]].
* '''Progress:''' the initial progress of the task on init.
* '''Progress:''' the initial progress of the task on init.


==== Game User Interface ====
=== Game User Interface ===
Press and hold '''J''' to open or close the task list. Two tabs open:
 
Press and hold {{Controls|J}} to open or close the task list. Two tabs open:
[[File:Task System Game UI 1.png|none|thumb]]
[[File:Task System Game UI 1.png|none|thumb]]
The left tab shows available objectives, the right one shows completed and failed tasks.  
The left tab shows available objectives, the right one shows completed and failed tasks.


When clicking the task, a window with the details opens:
When clicking the task, a window with the details opens:
Line 44: Line 49:
If you enabled progress for extended tasks, the progress bar appears in the task entry.
If you enabled progress for extended tasks, the progress bar appears in the task entry.


If the task has a child task, you can click a dropdown icon to open a child task. If you click the parent task entry, the info panel will show child tasks required for completion. It doesn't allow to assign.  
If the task has a child task, you can click a dropdown icon to open a child task. If you click the parent task entry, the info panel will show child tasks required for completion. It does not allow to assign.


If you enabled visibility on map, you can select tasks right there by clicking their icons.  
If you enabled visibility on map, you can select tasks right there by clicking their icons.
[[File:Task System Game Assignment.png|none|thumb|500px]]
[[File:Task System Game Assignment.png|none|thumb|500px]]
To assign someone to a task, hover over the task icon on the map, and click the panel next to it.
To assign someone to a task, hover over the task icon on the map, and click the panel next to it.


==== Debug Menu ====
=== Debug Menu ===
 
The debug menu allows manipulating asks at runtime for debugging and monitoring. To enable it:
The debug menu allows manipulating asks at runtime for debugging and monitoring. To enable it:


# Press '''Win+LAlt'''
# Press {{Controls|Win|Alt}}
# Go to '''Systems → Task System'''
# Go to '''Systems → Task System'''


Line 59: Line 65:
'''Task List''' shows all the tasks that exist in the game world. You can expand the selected task to open its properties. You can open a context menu for each property that provides tools for the further configuration.
'''Task List''' shows all the tasks that exist in the game world. You can expand the selected task to open its properties. You can open a context menu for each property that provides tools for the further configuration.


=== Tasks and Extended Tasks ===
There are two classes: '''SCR_Task''' and '''SCR_ExtendedTask'''.


'''SCR_Task''' features the following:
== Tasks and Extended Tasks ==
 
There are two classes: <enforce inline>SCR_Task</enforce> and <enforce inline>SCR_ExtendedTask</enforce>.
 
<enforce inline>SCR_Task</enforce> features the following:


* basic info, such as a unique ID, a name, a description, and location
* basic info, such as a unique ID, a name, a description, and location
* array of assignee executors
* array of assignee executors
* task state, levels of ownership and visibility, and a type of UI visibility
* task state, levels of [[#Ownership and Visibility|ownership and visibility]], and a type of UI visibility
* FactionKey/GroupID/Executor array to restrict tasks in visibility and ownership
* FactionKey/GroupID/Executor array to restrict tasks in [[#Ownership and Visibility|visibility and ownership]]
 
<enforce inline>SCR_ExtendedTask</enforce> has all the same with a couple of actions in addition:
 
* creation of [[#Task Nesting|nested tasks]]. You can parent this class to another extended task or create child tasks. It allows you to create complex missions with multiple moving parts.
* monitoring progression. You can set progress in increments (0..100%). {{Feature|informative|Use progression for tasks that imply collecting multiple items.}}


'''SCR_ExtendedTask''' has all the same with a couple of actions in addition:
All the data for both types is stored in <enforce inline>SCR_TaskData</enforce> and <enforce inline>SCR_ExtendedTaskData</enforce> accordingly. Both classes provide methods for copying data or merging two instances of data. All the data is replicated as one package. Storing important information in its own separate class helps keep the codebase clean and easier to work with.


* creation of nested tasks. You can parent this class to another extended task or create child tasks. It allows you to create complex missions with multiple moving parts.
* monitoring progression. You can set progress in increments (0% - 100%).
{{Feature|informative|Use progression for tasks that imply collecting multiple items.}}
All the data for both types is stored in '''SCR_TaskData''' and '''SCR_ExtendedTaskData''' accordingly. Both classes provide methods for copying data or merging two instances of data. All the data is replicated as one package. Storing important information in its own separate class helps keep the codebase clean and easier to work with.


=== Task System API ===
== Task System API ==
 
{| class="wikitable"
{| class="wikitable"
|+
! Method
! style="width:300px;" | Method
! Parameters
!Parameters
! Description
!Description
|-
|-
| style="width:300px;" | void '''GetAssigneesForTask'''
| <enforce methods="GetAssigneesForTask">void GetAssigneesForTask</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* out array<nowiki><ref SCR_TaskExecutor> </nowiki>'''assignees'''
* out array<nowiki><ref SCR_TaskExecutor> </nowiki>'''assignees'''
* bool '''notify'''
* bool '''notify'''
|Outputs an array of assignee executors for the task.
| Outputs an array of assignee executors for the task.
{{Feature|informative|Set notify to false not to receive a warning message when the assignee list is empty.}}
{{Feature|informative|Set notify to false not to receive a warning message when the assignee list is empty.}}
|-
|-
| style="width:300px;" | bool '''IsTaskVisibleFor'''
| <enforce methods="IsTaskVisibleFor">bool IsTaskVisibleFor</enforce>
|
|
* SCR_Task task
* SCR_Task task
* SCR_TaskExecutor executor
* SCR_TaskExecutor executor
|Returns '''true''' if the task is visible to the executor.
| Returns '''true''' if the task is visible to the executor.
|-
|-
| style="width:300px;" | bool '''CanTaskBeAssignedTo'''
| <enforce methods="CanTaskBeAssignedTo">bool CanTaskBeAssignedTo</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_TaskExecutor '''executor'''
* SCR_TaskExecutor '''executor'''
|Returns '''true''' if the task is assignable to the executor. The method looks at the task ownership for comparison.
| Returns '''true''' if the task is assignable to the executor. The method looks at the [[#Ownership and Visibility|task ownership]] for comparison.
|-
|-
|style="width:300px;" | void '''GetTasksByState'''
| <enforce methods="GetTasksByState">void GetTasksByState</enforce>
|
|
* out array<SCR_Task> '''outTasks'''
* out array<SCR_Task> '''outTasks'''
Line 109: Line 118:
* FactionKey '''filterFaction'''
* FactionKey '''filterFaction'''
* int '''filterGroup'''
* int '''filterGroup'''
|Outputs an array of tasks that match the state. You can further filter tasks by factions and groups.
| Outputs an array of tasks that match the state. You can further filter tasks by factions and groups.
|-
|-
|style="width:300px;" | void '''RegisterTask'''
| <enforce methods="RegisterTask">void RegisterTask</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Registers the task into the task system.
| Registers the task into the task system.
|-
|-
|style="width:300px;" | void '''UnregisterTask'''
| <enforce methods="UnregisterTask">void UnregisterTask</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Unregisters the task from the task system.
| Unregisters the task from the task system.
|-
|-
|style="width:300px;" | void '''AssignTask'''
| <enforce methods="AssignTask">void AssignTask</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_TaskExecutor '''executor'''
* SCR_TaskExecutor '''executor'''
|Tries to assign the task to the executor.
| Tries to assign the task to the executor.
|-
|-
|style="width:300px;" | void '''UnassignTask'''
| <enforce methods="UnassignTask">void UnassignTask</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_TaskExecutor '''executor'''
* SCR_TaskExecutor '''executor'''
|Tries to unassign the task from the executor.
| Tries to unassign the task from the executor.
|-
|-
|style="width:300px;" | float '''GetTaskProgress'''
| <enforce methods="GetTaskProgress">float GetTaskProgress</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns progress of the task as float. The value ranges from 0 to 100.
| Returns progress of the task as float. The value ranges from 0 to 100.
|-
|-
|style="width:300px;" | void '''AddTaskProgress'''
| <enforce methods="AddTaskProgress">void AddTaskProgress</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* float '''percentage'''
* float '''percentage'''
|Tries to add progress to the task.
| Tries to add progress to the task.
|-
|-
|style="width:300px;" | void '''RemoveTaskProgress'''
| <enforce methods="RemoveTaskProgress">void RemoveTaskProgress</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* float '''percentage'''
* float '''percentage'''
|Tries to remove progress from the task.
| Tries to remove progress from the task.
|-
|-
|style="width:300px;" | SCR_ETaskState '''GetTaskState'''
| <enforce methods="GetTaskState">SCR_ETaskState GetTaskState</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns the state of the task.
| Returns the state of the task.
|-
|-
|style="width:300px;" | void '''SetTaskState'''
| <enforce methods="SetTaskState">void SetTaskState</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_ETaskState '''state'''
* SCR_ETaskState '''state'''
|Changes the state of the task.
| Changes the state of the task.
|-
|-
|style="width:300px;" | SCR_ETaskOwnership '''GetTaskOwnership'''
| <enforce methods="GetTaskOwnership">SCR_ETaskOwnership GetTaskOwnership</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns ownership of the task.
| Returns ownership of the task.
|-
|-
|style="width:300px;" | void '''SetTaskOwnership'''
| <enforce methods="SetTaskOwnership">void SetTaskOwnership</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_ETaskOwnership '''ownership'''
* SCR_ETaskOwnership '''ownership'''
|Tries to change ownership of the task.
| Tries to change ownership of the task.
|-
|-
|style="width:300px;" | SCR_ETaskVisibility '''GetTaskVisibility'''
| <enforce methods="GetTaskVisibility">SCR_ETaskVisibility GetTaskVisibility</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns visibility of the task.
| Returns visibility of the task.
|-
|-
|style="width:300px;" | void '''SetTaskVisibility'''
| <enforce methods="SetTaskVisibility">void SetTaskVisibility</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_ETaskVisibility '''visibility'''
* SCR_ETaskVisibility '''visibility'''
|Tries to change visibility of the task.
| Tries to change visibility of the task.
|-
|-
|style="width:300px;" | SCR_ETaskUIVisibility '''GetTaskUIVisibility'''
| <enforce methods="GetTaskUIVisibility">SCR_ETaskUIVisibility GetTaskUIVisibility</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns visibility of the task in the UI (e.g. on the map).
| Returns visibility of the task in the UI (e.g. on the map).
|-
|-
|style="width:300px;" | void '''SetTaskUIVisibility'''
| <enforce methods="SetTaskUIVisibility">void SetTaskUIVisibility</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_ETaskUIVisibility '''visibility'''
* SCR_ETaskUIVisibility '''visibility'''
|Tries to change visibility of the task in the UI (e.g. on the map).
| Tries to change visibility of the task in the UI (e.g. on the map).
|-
|-
|style="width:300px;" | array<string> '''GetTaskFactions'''
| <enforce methods="GetTaskFactions">array<string> GetTaskFactions</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns owner factions of the task.
| Returns owner factions of the task.
|-
|-
|style="width:300px;" | void '''AddTaskFaction'''
| <enforce methods="AddTaskFaction">void AddTaskFaction</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* FactionKey '''factionKey'''
* FactionKey '''factionKey'''
|Adds the owner faction to the task.
| Adds the owner faction to the task.
|-
|-
|style="width:300px;" | void '''RemoveTaskFaction'''
| <enforce methods="RemoveTaskFaction">void RemoveTaskFaction</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* FactionKey '''factionKey'''
* FactionKey '''factionKey'''
|Removes the owner faction from the task.
| Removes the owner faction from the task.
|-
|-
|style="width:300px;" | array<int> '''GetTaskGroups'''
| <enforce methods="GetTaskGroups">array<int> GetTaskGroups</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns owner group IDs of the task.
| Returns owner group IDs of the task.
|-
|-
|style="width:300px;" | void '''AddTaskGroup'''
| <enforce methods="AddTaskGroup">void AddTaskGroup</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* int '''groupID'''
* int '''groupID'''
|Adds the owner group ID to the task.
| Adds the owner group ID to the task.
|-
|-
|style="width:300px;" | void '''RemoveTaskGroup'''
| <enforce methods="RemoveTaskGroup">void RemoveTaskGroup</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* int '''groupID'''
* int '''groupID'''
|Removes the owner group ID from the task.
| Removes the owner group ID from the task.
|-
|-
|style="width:300px;" | array<nowiki><ref SCR_TaskExecutor> </nowiki>'''GetTaskExecutors'''
| <enforce methods="GetTaskExecutors">array<ref SCR_TaskExecutor> GetTaskExecutors</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns owner executors of the task.
| Returns owner executors of the task.
|-
|-
|style="width:300px;" | void '''AddTaskExecutor'''
| <enforce methods="AddTaskExecutor">void AddTaskExecutor</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_TaskExecutor executor
* SCR_TaskExecutor executor
|Adds the owner task executor to the task.
| Adds the owner [[#Task Executor|task executor]] to the task.
|-
|-
|style="width:300px;" | void '''RemoveTaskExecutor'''
| <enforce methods="RemoveTaskExecutor">void RemoveTaskExecutor</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_TaskExecutor executor
* SCR_TaskExecutor executor
|Removes the owner task executor from the task.
| Removes the owner task executor from the task.
|-
|-
|style="width:300px;" | vector '''GetTaskLocation'''
| <enforce methods="GetTaskLocation">vector GetTaskLocation</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Returns the location of the task as a vector.
| Returns the location of the task as a vector.
|-
|-
|style="width:300px;" | void '''MoveTask'''
| <enforce methods="MoveTask">void MoveTask</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* vector '''destination'''
* vector '''destination'''
|Sets the location of the task as a new one.
| Sets the location of the task as a new one.
|-
|-
|style="width:300px;" | void '''GetChildTasksFor'''
| <enforce methods="GetChildTasksFor">void GetChildTasksFor</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* out array<SCR_Task> '''childTasks'''
* out array<SCR_Task> '''childTasks'''
|Outputs an array of tasks that are parented to a particular task.
| Outputs an array of tasks that are parented to a particular task.
|-
|-
|style="width:300px;" | void '''AddChildTaskTo'''
| <enforce methods="AddChildTaskTo">void AddChildTaskTo</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_Task '''childTask'''
* SCR_Task '''childTask'''
|Tries to parent a '''childTask''' to the task.{{Feature|informative|Tasks that are already parented to a particular task cannot have their own child tasks as the maximum allowed depth is set as 1.}}
| Tries to parent a '''childTask''' to the task.{{Feature|informative|Tasks that are already parented to a particular task cannot have their own child tasks as the maximum allowed depth is set as 1.}}
|-
|-
|style="width:300px;" | void '''RemoveChildTaskFrom'''
| <enforce methods="RemoveChildTaskFrom">void RemoveChildTaskFrom</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
* SCR_Task '''childTask'''
* SCR_Task '''childTask'''
|Tries to unparent a '''childTask''' from the task
| Tries to unparent a '''childTask''' from the task
|-
|-
|style="width:300px;" | SCR_Task '''CreateTask'''
| <enforce methods="CreateTask">SCR_Task CreateTask</enforce>
|
|
* ResourceName '''taskResourceName'''
* ResourceName '''taskResourceName'''
Line 281: Line 290:
* string '''desc'''
* string '''desc'''
* vector '''position'''
* vector '''position'''
|Creates a new task and registers it into '''SCR_TaskSystem'''.
| Creates a new task and registers it into <enforce inline>SCR_TaskSystem</enforce>.
|-
|-
|style="width:300px;" | void '''DeleteTask'''
| <enforce methods="DeleteTask">void DeleteTask</enforce>
|
|
* SCR_Task '''task'''
* SCR_Task '''task'''
|Deletes the task from '''SCR_TaskSystem'''.
| Deletes the task from <enforce inline>SCR_TaskSystem</enforce>.
|-
|-
|style="width:300px;" | SCR_Task '''GetTaskFromTaskID'''
| <enforce methods="GetTaskFromTaskID">SCR_Task GetTaskFromTaskID</enforce>
|
|
* string '''taskID'''
* string '''taskID'''
* bool '''notify'''
* bool '''notify'''
|Finds the task by the '''taskID''' and returns it.{{Feature|informative|Set notify to false not to receive a warning message if the task could not be found.}}
| Finds the task by the '''taskID''' and returns it.{{Feature|informative|Set notify to false not to receive a warning message if the task could not be found.}}
|-
|style="width:300px;" | void '''PrintTasks'''
|
* SCR_TaskExecutor '''executor'''
|Formats and outputs the list of tasks to the console. If the executor is not '''null''', the task list for a specified executor is printed.
|}
|}


=== Task System Control Flow ===
== Task System Control Flow ==
The task system performs operations in strict order. Rules ensure that no sensitive data gets manipulated and potentially corrupted by external scripts.  
 
The task system performs operations in strict order. Rules ensure that no sensitive data gets manipulated and potentially corrupted by external scripts.
[[File:Control Flow.png|none|thumb|600px]]
[[File:Control Flow.png|none|thumb|600px]]
where each element of the system only performs certain actions:
where each element of the system only performs certain actions:


* '''SCR_TaskSystem''':
{| class="wikitable valign-top"
** exposes an API for the UI and external scripts
! <enforce inline>SCR_TaskSystem</enforce>
** checks if operations are allowed/valid  
! <enforce inline>SCR_Task</enforce>
** provides feedback for almost all operations (whether it is successful of failed, and the reason of fail)
! <enforce inline>SCR_TaskData</enforce>
* '''SCR_Task''':
|-
** performs operations directly
|
** handles replication
* exposes an API for the UI and external scripts
** reads and writes data
* checks if operations are allowed/valid
* '''SCR_TaskData''':
* provides feedback for almost all operations<br>(whether it is successful of failed, and the reason of fail)
** stores data
|
* performs operations directly
* handles replication
* reads and writes data
|
* stores data
|}


When handling the task system, follow the rules below:
When handling the task system, follow the rules below:


* When managing tasks on a high level (assigning to players, changing task states, etc.), only use the API provided by '''SCR_TaskSystem.'''
* When managing tasks on a high level (assigning to players, changing task states, etc.), only use the API provided by <enforce inline>SCR_TaskSystem</enforce>.
* You can retrieve information directly from '''SCR_Task''' using its public getters. However, it is not allowed invoking public methods that manipulate task data inside '''SCR_Task''' directly.
* You can retrieve information directly from <enforce inline>SCR_Task</enforce> using its public getters. However, it is not allowed invoking public methods that manipulate task data inside <enforce inline>SCR_Task</enforce> directly.
* Never modify or read data in '''SCR_TaskData''' directly. Use '''SCR_TaskSystem''' to modify data and '''SCR_Task''' to read data.
* Never modify or read data in <enforce inline>SCR_TaskData</enforce> directly. Use <enforce inline>SCR_TaskSystem</enforce> to modify data and <enforce inline>SCR_Task</enforce> to read data.
 
 
== Task Executor ==


=== Task Executor ===
A task executor serves as data collection for everything related to the player/entity/group assignment.  Whenever the task system needs to handle data related to the assignment or [[#Ownership and Visibility|task ownership]], it uses a task executor for communication of data. The <enforce inline>SCR_TaskExecutor</enforce> class inherits from <enforce inline>ScriptAndConfig</enforce> and stores the following information:
A task executor serves as data collection for everything related to the player/entity/group assignment.  Whenever the task system needs to handle data related to the assignment or task ownership, it uses a task executor for communication of data. The '''SCR_TaskExecutor''' class inherits from '''ScriptAndConfig''' and stores the following information:


* Player ID
* Player ID
Line 331: Line 345:
There are currently six ways to create a task executor:
There are currently six ways to create a task executor:
{| class="wikitable"
{| class="wikitable"
|+
! Method
!Method
! Parameters
!Parameters
! Description
!Description
|-
|-
|SCR_TaskExecutor.'''FromPlayerID'''
| <enforce methods="FromPlayerID">SCR_TaskExecutor.FromPlayerID</enforce>
|int '''playerID'''
| int '''playerID'''
|Creates and returns a new '''player''' executor. The task system treats the executor as a player.
| Creates and returns a new '''player''' executor. The task system treats the executor as a player.
|-
|-
|SCR_TaskExecutor.'''FromEntity'''
| <enforce methods="FromPlayerID">SCR_TaskExecutor.FromEntity</enforce>
|IEntity '''ent'''
| IEntity '''ent'''
|Creates and returns a new '''entity''' executor. The task system treats the executor as an entity. It can be an AI character, a vehicle, etc.
| Creates and returns a new '''entity''' executor. The task system treats the executor as an entity. It can be an AI character, a vehicle, etc.
|-
|-
|SCR_TaskExecutor.'''FromGroup'''
| <enforce methods="FromGroup">SCR_TaskExecutor.FromGroup</enforce>
|int '''groupID'''
| int '''groupID'''
|Creates and returns a new '''group''' executor. This executor is only used for group assignment.
| Creates and returns a new '''group''' executor. This executor is only used for group assignment.
|-
|-
|SCR_TaskSystem.'''TaskExecutorFromPlayerID'''
| <enforce methods="TaskExecutorFromPlayerID">SCR_TaskSystem.TaskExecutorFromPlayerID</enforce>
|int '''playerID'''
| int '''playerID'''
|Creates and returns a new '''player''' executor. The task system treats the executor as a player.
| Creates and returns a new '''player''' executor. The task system treats the executor as a player.
|-
|-
|SCR_TaskSystem.'''TaskExecutorFromEntity'''
| <enforce methods="TaskExecutorFromEntity">SCR_TaskSystem.TaskExecutorFromEntity</enforce>
|IEntity '''ent'''
| IEntity '''ent'''
|Creates and returns a new '''entity''' executor. The task system treats the executor as an entity. It can be an AI character, a vehicle, etc.
| Creates and returns a new '''entity''' executor. The task system treats the executor as an entity. It can be an AI character, a vehicle, etc.
|-
|-
|SCR_TaskSystem.'''TaskExecutorFromGroup'''
| <enforce methods="TaskExecutorFromGroup">SCR_TaskSystem.TaskExecutorFromGroup</enforce>
|int '''groupID'''
| int '''groupID'''
|Creates and returns a new '''group''' executor. This executor is only used for group assignment.
| Creates and returns a new '''group''' executor. This executor is only used for group assignment.
|}
|}


==== Working with Task Executor ====
=== Working with Task Executor ===
How to assign a task:  
 
How to assign a task:


# Create a task executor using the methods above.
# Create a task executor using the methods above.
# Call '''SCR_TaskSystem.AssignTask''' and provide the task reference and a newly created task executor.
# Call <enforce inline>SCR_TaskSystem.AssignTask</enforce> and provide the task reference and a newly created task executor.


The task system will directly insert the provided executor into the assignee list of the given task.
The task system will directly insert the provided executor into the assignee list of the given task.
Line 372: Line 386:


# Create a task executor using the methods above.
# Create a task executor using the methods above.
# Call '''SCR_TaskSystem.UnassignTask''' and provide the task reference and a newly created task executor.
# Call <enforce inline>SCR_TaskSystem.UnassignTask</enforce> and provide the task reference and a newly created task executor.


'''Deleting a task executor'''
'''Deleting a task executor'''


When you want to remove an assignee executor from a task, the task system doesn’t care about the exact object in memory. Instead, it looks at the data inside the new executor you give it (like player ID or group ID). Then, it compares this data with each executor in the task’s list. As soon as it finds a match, it removes that executor from the list.
When you want to remove an assignee executor from a task, the task system does not care about the exact object in memory.
Instead, it looks at the data inside the new executor you give it (like player ID or group ID).
Then, it compares this data with each executor in the task's list. As soon as it finds a match, it removes that executor from the list.
 
You do not have to worry about giving the system the same object as before. As long as the data matches, the system will find and remove the right one.
 
An example in Java: instead of asking if two string objects are the exact same (<syntaxhighlight lang="java" inline>==</syntaxhighlight>), you ask if their contents are equal (<syntaxhighlight lang="java" inline>.equals()</syntaxhighlight>). The task system always uses the <syntaxhighlight lang="java" inline>.equals()</syntaxhighlight> style check.


You don’t have to worry about giving the system the same object as before. As long as the data matches, the system will find and remove the right one.


An example in Java: instead of asking if two string objects are the exact same '''(==)''', you ask if their contents are equal '''(.equals())'''. The task system always uses the '''“.equals()”''' style check.
== Ownership and Visibility ==


=== Ownership and Visibility ===
Both ownership and visibility are used to restrict tasks for certain players or group of players.
Both ownership and visibility are used to restrict tasks for certain players or group of players.
Ownership determines who or what can assign to a task. There are the following levels of ownership:
Ownership determines who or what can assign to a task. There are the following levels of ownership:


* '''None:''' no one can assign
* '''None:''' no one can assign
* '''Executor:''' only specified executors can assign (it works both for players and entities).  
* '''Executor:''' only specified executors can assign (it works both for players and entities).<!--
{{Feature|informative|Such a task can only be assigned to executors presented in the owner executor array.}}
-->{{Feature|informative|Such a task can only be assigned to executors presented in the owner executor array.}}
* '''Group:''' all players inside specified groups can assign
* '''Group:''' all players inside specified groups can assign
* '''Faction:''' all players inside specified factions can assign
* '''Faction:''' all players inside specified factions can assign
* '''Everyone:''' everyone can assign
* '''Everyone:''' everyone can assign


Visibility determines who can see the task in the task list or in the map view. It has all the levels listed above, and one more: '''Assignees'''. A task can be set up in a way that players only see the task in their task list once it's assigned to them.
Visibility determines who can see the task in the task list or in the map view. It has all the levels listed above, and one more: '''Assignees'''.
{{Feature|informative|Let's imagine you want to work with the US faction.
A task can be set up in a way that players only see the task in their task list once it is assigned to them.
{{Feature|informative|
Let's imagine you want to work with the US faction.


If you want the task to be owned by it, set Task Ownership as Faction, then add the US faction key to the array.
If you want the task to be owned by it, set Task Ownership as Faction, then add the US faction key to the array.


If you want the task to appear in the US players' task list or a map, set Task Visibility as Faction, then add the US faction key to the array.}}
If you want the task to appear in the US players' task list or a map, set Task Visibility as Faction, then add the US faction key to the array.
}}
 
Once ownership and visibility are set, executors/groups/etc. (depending on the set level) need to be added to owner arrays, so that anyone could assign to the task or view it.
Once ownership and visibility are set, executors/groups/etc. (depending on the set level) need to be added to owner arrays, so that anyone could assign to the task or view it.


=== Group Tasks ===
 
== Group Tasks ==
 
You can assign a task to a player group. The task needs to meet the following conditions:
You can assign a task to a player group. The task needs to meet the following conditions:


Line 407: Line 431:
* To include one or more player groups as executor instances.
* To include one or more player groups as executor instances.


If a group is included in the task’s owner list, the group leader can assign the task to their group. When the leader does this, the whole group will be assigned to the task.
If a group is included in the task's owner list, the group leader can assign the task to their group.
When the leader does this, the whole group will be assigned to the task.
[[File:Group Tasks.png|none|thumb|450px]]
[[File:Group Tasks.png|none|thumb|450px]]
Additionally to individual assignment, tasks can now be assigned to entire player groups. The way it works is a bit different and in order to allow for group assignment, a task needs to:


* Have its ownership set to '''Executor'''
{{Feature|important|
* Include one or more player groups as executor instances
Group assignment implies the group as a whole to assign to a task. It does not assign every group member one by one.
{{Important|Group assignment implies the group as a whole to assign to a task. It doesn't assign every group member one by one. If a game event requires checking a player for the assignment, the task system checks whether the player belongs to the whole group.}}
If a game event requires checking a player for the assignment, the task system checks whether the player belongs to the whole group.
}}
 
=== Assignment ===


==== Assignment ====
There are two ways of working with group tasks.
There are two ways of working with group tasks.


'''Assigning group members:'''  
'''Assigning group members:'''


# Set ownership as '''GROUP'''
# Set ownership as '''GROUP'''
Line 425: Line 451:
Every member in the group can assign himself to the task.
Every member in the group can assign himself to the task.


'''Assigning the whole group:'''  
'''Assigning the whole group:'''


# Set ownership as '''EXECUTOR'''
# Set ownership as '''EXECUTOR'''
# Insert a new group executor to the owner executor array.  
# Insert a new group executor to the owner executor array.
# In the '''executor group ID''' field, enter the group ID.  
# In the '''executor group ID''' field, enter the group ID.


A group as a whole can assign to a task.
A group as a whole can assign to a task.


=== Task Progression ===
== Task Progression ==
The progress bar is part of an extended task that allows it to be completed in increments (0-100%). It's a useful tool for tasks that require certain amounts of items to be collected. Players can track their progress in the task list.
 
The progress bar is part of an extended task that allows it to be completed in increments (0..100%).
It is a useful tool for tasks that require certain amounts of items to be collected. Players can track their progress in the task list.
[[File:Task Bar.png|none|thumb]]
[[File:Task Bar.png|none|thumb]]
Use the following '''SCR_TaskSystem''' methods to manage the task progress:


* SCR_TaskSystem.'''AddTaskProgress'''
Use the following <enforce inline>SCR_TaskSystem</enforce> methods to manage the task progress:
* SCR_TaskSystem.'''RemoveTaskProgress'''
 
<enforce methods="AddTaskProgress RemoveTaskProgress">
SCR_TaskSystem.AddTaskProgress
SCR_TaskSystem.RemoveTaskProgress
</enforce>


You can enable or disable the progress if you don't want tasks to be progressed in increments, but want to nest them.
You can enable or disable the progress if you do not want tasks to be progressed in increments, but want to nest them.


The progress behavior changes if both a parent and a child tasks have it enabled. See the Task Nesting section.
The progress behavior changes if both a parent and a child tasks have it enabled. See the [[#Task Nesting|Task Nesting section]].
 
=== The State-Progress Behavior ===


==== The State-Progress Behavior ====
The behavior follows the principles:
The behavior follows the principles:


* If the progress goes above 0%, the task state switches to '''PROGRESSED'''.
* When the progress reaches 100%, the task state switches to '''COMPLETED'''.
* When the progress reaches 100%, the task state switches to '''COMPLETED'''.
* If the progress goes above 0%, the task state switches to '''PROGRESSED'''.
* If the progress is enabled, and the task state is manually set as '''COMPLETED''', the progress will not updated and show 100%.
* If the progress is enabled, and the task state is manually set as '''COMPLETED''', the progress will not updated and show 100%.
* When the progress is added or removed, the task system caches the previous task state in the case if the progress gets reverted.
* When the progress is added or removed, the task system caches the previous task state in the case if the progress gets reverted.


=== Task Nesting ===
 
== Task Nesting ==
 
Task nesting means organizing tasks in a parent-child hierarchy, where one task can contain and manage multiple subtasks.
Task nesting means organizing tasks in a parent-child hierarchy, where one task can contain and manage multiple subtasks.


The nested task structure:
The nested task structure:
[[File:Nested Task Structure.png|none|thumb|700px]]
[[File:Nested Task Structure.png|none|thumb|700px]]
The nested tasks in the game UI:
The nested tasks in the game UI:
[[File:Nested Task Structure in UI.png|none|thumb|500px]]
[[File:Nested Task Structure in UI.png|none|thumb|500px]]


==== Setting Up Nesting Task ====
=== Setting Up Nesting Task ===
 
You can set up nested tasks both in Workbench or during the runtime.
You can set up nested tasks both in Workbench or during the runtime.


===== Workbench =====
==== Workbench ====
Both a parent and a child tasks must be '''SCR_ExtendedTask'''.
Both a parent and a child tasks must be <enforce inline>SCR_ExtendedTask</enforce>.


To create a task hierarchy, drag and drop the child task onto the parent task in the hierarchy, in the '''World Editor'''.
To create a task hierarchy, drag and drop the child task onto the parent task in the hierarchy, in the {{Link|Arma Reforger:World Editor}}.


The task system parents the child task to the parent one automatically on init.
The task system parents the child task to the parent one automatically on init.
[[File:Workbench nested tasks.png|none|thumb|450px]]
[[File:Workbench nested tasks.png|none|thumb|450px]]


===== Runtime =====
==== Runtime ====
Both a parent and a child tasks must be '''SCR_ExtendedTask'''.
Both a parent and a child tasks must be <enforce inline>SCR_ExtendedTask</enforce>.


To manage nested tasks:
To manage nested tasks:


* Call '''SCR_TaskSystem.AddChildTaskTo''' to parent the child task to the parent task.
* Call <enforce inline methods="AddChildTaskTo">SCR_TaskSystem.AddChildTaskTo</enforce> to parent the child task to the parent task.
* Call '''SCR_TaskSystem.RemoveChildTaskFrom''' to unparent it.
* Call <enforce inline methods="RemoveChildTaskFrom">SCR_TaskSystem.RemoveChildTaskFrom</enforce> to unparent it.


==== Behavior ====
=== Behavior ===
Each task can be set to share data with other tasks in the same hierarchy. This means some settings, like ownership and visibility, will automatically be inherited from the parent task.


===== Assignment =====
Each task can be set to share data with other tasks in the same hierarchy.
This means some settings, like ownership and visibility, will automatically be inherited from the parent task.
 
==== Assignment ====
Information about assignees also can be shared with parent or child tasks. The following principles work:
Information about assignees also can be shared with parent or child tasks. The following principles work:


Line 490: Line 528:
* Only one task can be assigned to the executor at a time.
* Only one task can be assigned to the executor at a time.


===== Ownership and Visibility =====
==== Ownership and Visibility ====
Since task assignment depends on ownership settings, there are some corner cases to consider when dealing with nested tasks:
Since task assignment depends on ownership settings, there are some corner cases to consider when dealing with nested tasks:


* Parent tasks can have any level of ownership.
* Parent tasks can have [[#Ownership and Visibility|any level of ownership]].
* Child tasks can only switch between ownership levels that are lower than their parent task's ownership.   Ownership Example in Nested Tasks
* Child tasks can only switch between ownership levels that are lower than their parent task's ownership.
 
<spoiler text="Ownership example in nested tasks">If the parent task's ownership is set as FACTION, the child task's ownership can only be set to GROUP, EXECUTOR, or NONE. If the child tasks are set to GROUP ownership, the main task is assigned to the whole faction, and the child tasks are then distributed to individual player groups within that faction</spoiler>


The same principles work for the visibility.
The same principles work for the visibility.


===== Progression =====
==== Progression ====
Progress for nested tasks is handled according to the following:
Progress for nested tasks is handled according to the following:


* When progress is made on a child task, that progress is averaged across all sibling tasks and then applied to the parent task. For example, if there are three child tasks and one of them reaches 100% progress, about 33% progress will be reflected on the parent task.
* When progress is made on a child task, that progress is averaged across all sibling tasks and then applied to the parent task. For example, if there are three child tasks and one of them reaches 100% progress, about 33% progress will be reflected on the parent task.
* Parent tasks can still receive progress independently from their child tasks.
* Parent tasks can still receive progress independently from their child tasks.
{{Feature|informative|
A parent task could gain 10% progress for every minute the team holds out, regardless of the status of its child tasks.
After 10 minutes, the parent task would reach 100% progress even if none of the child tasks were completed.
}}
{{GameCategory|armaR|Modding|Scenario|Guidelines}}

Latest revision as of 13:08, 8 October 2025

As a rule, the task system is used with the Scenario Framework. In this article, you will learn how to use it separately.


Setup

The SCR_TaskSystem game system is a tool for controlling tasks. The system is automatically registered, and you do not need to add anything to it.

World Editor

You can directly place prefabs in the world. They will be automatically inserted into the task system on init.

There are two basic task prefabs:

Scenario Framework tasks folder: Prefabs/Systems/ScenarioFramework/Tasks/

Task System Workbench UI.png

*The featured fields exist only for the extended tasks.

Base properties:

  • Task ID: ID to distinguish between different tasks.
  • Task UI Info: data to be shown in the game UI: a name, a description, an icon, and an icon set name.
  • Task State: initial state of the task.
  • Task Ownership: ownership level.
  • Task Visibility: visibility level.
  • Task UI Visibility: UI visibility level to determine where the task is visible for players (a task list, a map, or both).
  • Owner Faction Keys: key of factions that are owners or viewers of the task.
  • Owner Group IDs: group ID of groups that are owners of viewers of the task.
  • Owner Executors: task executor that is owner or viewer of the task.
  • Assignees: array that allows you to pre-assign players/groups/entities on init.

Extended properties:

  • Link Data To Related Tasks: enable or disable sharing data between parent/child tasks if you work with nested tasks.
  • Progress: the initial progress of the task on init.

Game User Interface

Press and hold J to open or close the task list. Two tabs open:

Task System Game UI 1.png

The left tab shows available objectives, the right one shows completed and failed tasks.

When clicking the task, a window with the details opens:

Task System Game UI 2.png

You can see the task icon, name, description, the Show on map button, the Assign button, and the list of assignees.

If you enabled progress for extended tasks, the progress bar appears in the task entry.

If the task has a child task, you can click a dropdown icon to open a child task. If you click the parent task entry, the info panel will show child tasks required for completion. It does not allow to assign.

If you enabled visibility on map, you can select tasks right there by clicking their icons.

Task System Game Assignment.png

To assign someone to a task, hover over the task icon on the map, and click the panel next to it.

Debug Menu

The debug menu allows manipulating asks at runtime for debugging and monitoring. To enable it:

  1. Press ⊞ Win + Alt
  2. Go to Systems → Task System
Debug system task system.png

Task List shows all the tasks that exist in the game world. You can expand the selected task to open its properties. You can open a context menu for each property that provides tools for the further configuration.


Tasks and Extended Tasks

There are two classes: SCR_Task and SCR_ExtendedTask.

SCR_Task features the following:

  • basic info, such as a unique ID, a name, a description, and location
  • array of assignee executors
  • task state, levels of ownership and visibility, and a type of UI visibility
  • FactionKey/GroupID/Executor array to restrict tasks in visibility and ownership

SCR_ExtendedTask has all the same with a couple of actions in addition:

  • creation of nested tasks. You can parent this class to another extended task or create child tasks. It allows you to create complex missions with multiple moving parts.
  • monitoring progression. You can set progress in increments (0..100%).
    Use progression for tasks that imply collecting multiple items.

All the data for both types is stored in SCR_TaskData and SCR_ExtendedTaskData accordingly. Both classes provide methods for copying data or merging two instances of data. All the data is replicated as one package. Storing important information in its own separate class helps keep the codebase clean and easier to work with.


Task System API

Method Parameters Description
void GetAssigneesForTask
  • SCR_Task task
  • out array<ref SCR_TaskExecutor> assignees
  • bool notify
Outputs an array of assignee executors for the task.
Set notify to false not to receive a warning message when the assignee list is empty.
bool IsTaskVisibleFor
  • SCR_Task task
  • SCR_TaskExecutor executor
Returns true if the task is visible to the executor.
bool CanTaskBeAssignedTo
  • SCR_Task task
  • SCR_TaskExecutor executor
Returns true if the task is assignable to the executor. The method looks at the task ownership for comparison.
void GetTasksByState
  • out array<SCR_Task> outTasks
  • SCR_ETaskState state
  • FactionKey filterFaction
  • int filterGroup
Outputs an array of tasks that match the state. You can further filter tasks by factions and groups.
void RegisterTask
  • SCR_Task task
Registers the task into the task system.
void UnregisterTask
  • SCR_Task task
Unregisters the task from the task system.
void AssignTask
  • SCR_Task task
  • SCR_TaskExecutor executor
Tries to assign the task to the executor.
void UnassignTask
  • SCR_Task task
  • SCR_TaskExecutor executor
Tries to unassign the task from the executor.
float GetTaskProgress
  • SCR_Task task
Returns progress of the task as float. The value ranges from 0 to 100.
void AddTaskProgress
  • SCR_Task task
  • float percentage
Tries to add progress to the task.
void RemoveTaskProgress
  • SCR_Task task
  • float percentage
Tries to remove progress from the task.
SCR_ETaskState GetTaskState
  • SCR_Task task
Returns the state of the task.
void SetTaskState
  • SCR_Task task
  • SCR_ETaskState state
Changes the state of the task.
SCR_ETaskOwnership GetTaskOwnership
  • SCR_Task task
Returns ownership of the task.
void SetTaskOwnership
  • SCR_Task task
  • SCR_ETaskOwnership ownership
Tries to change ownership of the task.
SCR_ETaskVisibility GetTaskVisibility
  • SCR_Task task
Returns visibility of the task.
void SetTaskVisibility
  • SCR_Task task
  • SCR_ETaskVisibility visibility
Tries to change visibility of the task.
SCR_ETaskUIVisibility GetTaskUIVisibility
  • SCR_Task task
Returns visibility of the task in the UI (e.g. on the map).
void SetTaskUIVisibility
  • SCR_Task task
  • SCR_ETaskUIVisibility visibility
Tries to change visibility of the task in the UI (e.g. on the map).
array<string> GetTaskFactions
  • SCR_Task task
Returns owner factions of the task.
void AddTaskFaction
  • SCR_Task task
  • FactionKey factionKey
Adds the owner faction to the task.
void RemoveTaskFaction
  • SCR_Task task
  • FactionKey factionKey
Removes the owner faction from the task.
array<int> GetTaskGroups
  • SCR_Task task
Returns owner group IDs of the task.
void AddTaskGroup
  • SCR_Task task
  • int groupID
Adds the owner group ID to the task.
void RemoveTaskGroup
  • SCR_Task task
  • int groupID
Removes the owner group ID from the task.
array<ref SCR_TaskExecutor> GetTaskExecutors
  • SCR_Task task
Returns owner executors of the task.
void AddTaskExecutor
  • SCR_Task task
  • SCR_TaskExecutor executor
Adds the owner task executor to the task.
void RemoveTaskExecutor
  • SCR_Task task
  • SCR_TaskExecutor executor
Removes the owner task executor from the task.
vector GetTaskLocation
  • SCR_Task task
Returns the location of the task as a vector.
void MoveTask
  • SCR_Task task
  • vector destination
Sets the location of the task as a new one.
void GetChildTasksFor
  • SCR_Task task
  • out array<SCR_Task> childTasks
Outputs an array of tasks that are parented to a particular task.
void AddChildTaskTo
  • SCR_Task task
  • SCR_Task childTask
Tries to parent a childTask to the task.
Tasks that are already parented to a particular task cannot have their own child tasks as the maximum allowed depth is set as 1.
void RemoveChildTaskFrom
  • SCR_Task task
  • SCR_Task childTask
Tries to unparent a childTask from the task
SCR_Task CreateTask
  • ResourceName taskResourceName
  • string taskID
  • string name
  • string desc
  • vector position
Creates a new task and registers it into SCR_TaskSystem.
void DeleteTask
  • SCR_Task task
Deletes the task from SCR_TaskSystem.
SCR_Task GetTaskFromTaskID
  • string taskID
  • bool notify
Finds the task by the taskID and returns it.
Set notify to false not to receive a warning message if the task could not be found.

Task System Control Flow

The task system performs operations in strict order. Rules ensure that no sensitive data gets manipulated and potentially corrupted by external scripts.

Control Flow.png

where each element of the system only performs certain actions:

SCR_TaskSystem SCR_Task SCR_TaskData
  • exposes an API for the UI and external scripts
  • checks if operations are allowed/valid
  • provides feedback for almost all operations
    (whether it is successful of failed, and the reason of fail)
  • performs operations directly
  • handles replication
  • reads and writes data
  • stores data

When handling the task system, follow the rules below:

  • When managing tasks on a high level (assigning to players, changing task states, etc.), only use the API provided by SCR_TaskSystem.
  • You can retrieve information directly from SCR_Task using its public getters. However, it is not allowed invoking public methods that manipulate task data inside SCR_Task directly.
  • Never modify or read data in SCR_TaskData directly. Use SCR_TaskSystem to modify data and SCR_Task to read data.


Task Executor

A task executor serves as data collection for everything related to the player/entity/group assignment.  Whenever the task system needs to handle data related to the assignment or task ownership, it uses a task executor for communication of data. The SCR_TaskExecutor class inherits from ScriptAndConfig and stores the following information:

  • Player ID
  • Entity RplID
  • Group ID

There are currently six ways to create a task executor:

Method Parameters Description
SCR_TaskExecutor.FromPlayerID
int playerID Creates and returns a new player executor. The task system treats the executor as a player.
SCR_TaskExecutor.FromEntity
IEntity ent Creates and returns a new entity executor. The task system treats the executor as an entity. It can be an AI character, a vehicle, etc.
SCR_TaskExecutor.FromGroup
int groupID Creates and returns a new group executor. This executor is only used for group assignment.
SCR_TaskSystem.TaskExecutorFromPlayerID
int playerID Creates and returns a new player executor. The task system treats the executor as a player.
SCR_TaskSystem.TaskExecutorFromEntity
IEntity ent Creates and returns a new entity executor. The task system treats the executor as an entity. It can be an AI character, a vehicle, etc.
SCR_TaskSystem.TaskExecutorFromGroup
int groupID Creates and returns a new group executor. This executor is only used for group assignment.

Working with Task Executor

How to assign a task:

  1. Create a task executor using the methods above.
  2. Call SCR_TaskSystem.AssignTask and provide the task reference and a newly created task executor.

The task system will directly insert the provided executor into the assignee list of the given task.

How to unassign a task:

  1. Create a task executor using the methods above.
  2. Call SCR_TaskSystem.UnassignTask and provide the task reference and a newly created task executor.

Deleting a task executor

When you want to remove an assignee executor from a task, the task system does not care about the exact object in memory. Instead, it looks at the data inside the new executor you give it (like player ID or group ID). Then, it compares this data with each executor in the task's list. As soon as it finds a match, it removes that executor from the list.

You do not have to worry about giving the system the same object as before. As long as the data matches, the system will find and remove the right one.

An example in Java: instead of asking if two string objects are the exact same (==), you ask if their contents are equal (.equals()). The task system always uses the .equals() style check.


Ownership and Visibility

Both ownership and visibility are used to restrict tasks for certain players or group of players. Ownership determines who or what can assign to a task. There are the following levels of ownership:

  • None: no one can assign
  • Executor: only specified executors can assign (it works both for players and entities).
    Such a task can only be assigned to executors presented in the owner executor array.
  • Group: all players inside specified groups can assign
  • Faction: all players inside specified factions can assign
  • Everyone: everyone can assign

Visibility determines who can see the task in the task list or in the map view. It has all the levels listed above, and one more: Assignees. A task can be set up in a way that players only see the task in their task list once it is assigned to them.

Let's imagine you want to work with the US faction.

If you want the task to be owned by it, set Task Ownership as Faction, then add the US faction key to the array.

If you want the task to appear in the US players' task list or a map, set Task Visibility as Faction, then add the US faction key to the array.

Once ownership and visibility are set, executors/groups/etc. (depending on the set level) need to be added to owner arrays, so that anyone could assign to the task or view it.


Group Tasks

You can assign a task to a player group. The task needs to meet the following conditions:

  • To have the ownership level set as Executor.
  • To include one or more player groups as executor instances.

If a group is included in the task's owner list, the group leader can assign the task to their group. When the leader does this, the whole group will be assigned to the task.

Group Tasks.png
Group assignment implies the group as a whole to assign to a task. It does not assign every group member one by one. If a game event requires checking a player for the assignment, the task system checks whether the player belongs to the whole group.

Assignment

There are two ways of working with group tasks.

Assigning group members:

  1. Set ownership as GROUP
  2. Insert the group ID to the owner group array.

Every member in the group can assign himself to the task.

Assigning the whole group:

  1. Set ownership as EXECUTOR
  2. Insert a new group executor to the owner executor array.
  3. In the executor group ID field, enter the group ID.

A group as a whole can assign to a task.

Task Progression

The progress bar is part of an extended task that allows it to be completed in increments (0..100%). It is a useful tool for tasks that require certain amounts of items to be collected. Players can track their progress in the task list.

Task Bar.png

Use the following SCR_TaskSystem methods to manage the task progress:

SCR_TaskSystem.AddTaskProgress SCR_TaskSystem.RemoveTaskProgress

You can enable or disable the progress if you do not want tasks to be progressed in increments, but want to nest them.

The progress behavior changes if both a parent and a child tasks have it enabled. See the Task Nesting section.

The State-Progress Behavior

The behavior follows the principles:

  • If the progress goes above 0%, the task state switches to PROGRESSED.
  • When the progress reaches 100%, the task state switches to COMPLETED.
  • If the progress is enabled, and the task state is manually set as COMPLETED, the progress will not updated and show 100%.
  • When the progress is added or removed, the task system caches the previous task state in the case if the progress gets reverted.


Task Nesting

Task nesting means organizing tasks in a parent-child hierarchy, where one task can contain and manage multiple subtasks.

The nested task structure:

Nested Task Structure.png

The nested tasks in the game UI:

Nested Task Structure in UI.png

Setting Up Nesting Task

You can set up nested tasks both in Workbench or during the runtime.

Workbench

Both a parent and a child tasks must be SCR_ExtendedTask.

To create a task hierarchy, drag and drop the child task onto the parent task in the hierarchy, in the World Editor.

The task system parents the child task to the parent one automatically on init.

Workbench nested tasks.png

Runtime

Both a parent and a child tasks must be SCR_ExtendedTask.

To manage nested tasks:

  • Call SCR_TaskSystem.AddChildTaskTo to parent the child task to the parent task.
  • Call SCR_TaskSystem.RemoveChildTaskFrom to unparent it.

Behavior

Each task can be set to share data with other tasks in the same hierarchy. This means some settings, like ownership and visibility, will automatically be inherited from the parent task.

Assignment

Information about assignees also can be shared with parent or child tasks. The following principles work:

  • If the executor is assigned to a child task, it will be assigned to a parent task as well.
  • Executors cannot be manually assigned to parent tasks (tasks with child tasks). It works so to avoid confusion about task ownership and responsibility. Only child tasks should have direct assignees.
  • Only one task can be assigned to the executor at a time.

Ownership and Visibility

Since task assignment depends on ownership settings, there are some corner cases to consider when dealing with nested tasks:

  • Parent tasks can have any level of ownership.
  • Child tasks can only switch between ownership levels that are lower than their parent task's ownership.

If the parent task's ownership is set as FACTION, the child task's ownership can only be set to GROUP, EXECUTOR, or NONE. If the child tasks are set to GROUP ownership, the main task is assigned to the whole faction, and the child tasks are then distributed to individual player groups within that faction

The same principles work for the visibility.

Progression

Progress for nested tasks is handled according to the following:

  • When progress is made on a child task, that progress is averaged across all sibling tasks and then applied to the parent task. For example, if there are three child tasks and one of them reaches 100% progress, about 33% progress will be reflected on the parent task.
  • Parent tasks can still receive progress independently from their child tasks.
A parent task could gain 10% progress for every minute the team holds out, regardless of the status of its child tasks. After 10 minutes, the parent task would reach 100% progress even if none of the child tasks were completed.