- Add missing forge_server_actor runtime dependency to phone module (critical) - Clarify that garage and locker are event bus listeners, not emitters - Document economy runtime-only dependencies (bank, org) - Add TaskStore public API documentation (27 methods organized by category) - Update task module event emissions and hooks documentation All documentation now aligns with actual implementation verified against codebase.
10 KiB
Forge Task Module
Overview
The task addon is a server-owned mission/task system for Forge. It manages task execution, task-owned state, participant tracking, contribution-based player earnings, and org-owned rewards.
Task operational state is mission-scoped. The extension-backed task catalog, ownership, status, and defuse state are reset on task store startup, so the system intentionally starts clean after each server or mission restart.
Responsibilities
- spawn and monitor task flows on the server
- track per-task entities through
TaskStore - track task participants and engine-rating contribution
- award player earnings through the bank module
- award org funds, reputation, assets, and fleet rewards
- notify task participants and sync org updates to online members
Dependencies
forge_server_extensionforge_server_commonforge_server_actorforge_server_bankforge_server_orgforge_client_notifications
Main Components
Task Flows
fnc_attack.sqffnc_defend.sqffnc_defuse.sqffnc_delivery.sqffnc_destroy.sqffnc_hostage.sqffnc_hvt.sqf
TaskStore
fnc_initTaskStore.sqf initializes TaskStore, which owns:
- task ownership bindings
- participant snapshots
- defuse progress
- per-task entity registries for cargo, hostages, HVTs, IEDs, protected entities, shooters, and targets
Public API Methods:
- Lifecycle:
bindTaskOwnership,releaseTaskOwnership,registerTaskCatalogEntry,setTaskStatus,getTaskStatus,clearTaskStatus,clearTask - Catalog:
getActiveTaskCatalog,hasTaskCatalogEntry,getTaskCatalogEntry - Entities:
registerTaskEntity,getTaskEntities,findTaskEntityOwner,clearTaskEntities - Participants:
acceptTask,isTaskAccepted,trackParticipants,getTaskParticipants,getTaskParticipantUids,notifyParticipants - Rewards:
resolveRewardContext,applyRatingOutcome,incrementDefuseCount,getDefuseCount - Events:
emitTaskLifecycleEvent,buildTaskLifecycleEventPayload - Utilities:
callTaskState,callTaskStateEnvelope
Object Model
Object-style task instances and entity controllers live under
functions/objects/ and are initialized directly from XEH_preInit.sqf.
TaskInstanceBaseClassEntityControllerBaseClassfunctions/objects/README.md
The task functions are compatibility adapters around these object-style task
classes. This keeps the public task function names stable while moving stateful
task behavior into per-task createHashMapObject instances.
Reward Handling
fnc_handleTaskRewards.sqf applies org-owned rewards:
funds-> org fundsequipment,supplies,weapons,special-> org assetsvehicles-> org fleet
Player earnings and org reputation from task outcomes are distributed separately through TaskStore.applyRatingOutcome using Arma engine rating deltas.
Task Ownership
Tasks are bound to an owner org when they are started through fnc_handler.sqf.
- if a requester UID is provided, the task is owned by that requester's org
- if no requester UID is available, the task is bound to the
defaultorg
Org rewards always go to the bound owner org. Player earnings still use per-player contribution.
Usage
Task time limits use 0 for no limit on attack, destroy, delivery, hostage,
and HVT tasks. Defuse IED timers are different: each IED must have a positive
countdown value.
Mission designers can create tasks in four ways:
- Eden modules for editor-authored tasks.
fnc_startTask.sqffor script-authored tasks.fnc_handler.sqffor pre-registered entities with reputation gating and ownership binding. This path expects the BIS task and catalog entry to already exist if map-task and CAD visibility are required.- Direct task function calls for server-owned or mission-authored flows that
intentionally fall back to the
defaultorg. This path expects the BIS task to already exist if map-task visibility is required.
The dynamic mission manager can also generate attack tasks from config. That is system-generated content rather than a hand-authored task creation path.
CAD Compatibility
CAD hydrates assignable tasks from TaskStore.getActiveTaskCatalog. A task must
have a catalog entry and active task status before CAD can show and assign it.
CAD-compatible creation paths:
- Eden modules: compatible because they delegate to
fnc_startTask.sqf fnc_startTask.sqf: compatible because it registers the catalog entry, creates the BIS task, and dispatches throughfnc_handler.sqf- dynamic mission manager attack tasks: compatible because the mission manager
uses
fnc_startTask.sqf
Limited or incompatible paths:
fnc_handler.sqf: only compatible if a catalog entry was already registered elsewhere. The handler sets active status and ownership, but it does not create the BIS task shown in the map task tab or upsert the catalog entry- direct task function calls: not CAD-compatible by default. They bypass
fnc_startTask.sqfand usually do not register the task catalog entry or active status that CAD hydrates from. They also only callBIS_fnc_taskSetStateat completion/failure; they do not create the BIS task first
BIS Map Task Prerequisite
Only the Eden task modules and fnc_startTask.sqf create the BIS task
automatically through BIS_fnc_taskCreate.
If a mission uses fnc_handler.sqf directly or calls a task flow function such
as forge_server_task_fnc_attack, the mission must create a BIS task with the
same task ID before the Forge task completes. Otherwise the success/failure
BIS_fnc_taskSetState call has no visible map task to update.
That prerequisite can be satisfied with a vanilla Eden task creation module or
a scripted BIS_fnc_taskCreate call. fnc_startTask.sqf is the preferred Forge
path because it handles BIS task creation, Forge catalog registration, entity
registration, and handler dispatch together.
Create With Eden Modules
Eden task modules are the normal designer-facing path. Place the module, configure its attributes, and sync it to the relevant entities or grouping modules.
For a mission-designer-focused step-by-step setup guide, see:
docs/TASK_USAGE_GUIDE.md
Available task modules:
FORGE_Module_Attack: sync directly to target units or vehiclesFORGE_Module_Destroy: sync directly to objects, vehicles, or unitsFORGE_Module_Defuse: sync toFORGE_Module_Explosivesand optionallyFORGE_Module_ProtectedFORGE_Module_Delivery: sync toFORGE_Module_Cargo; the cargo module syncs to cargo objectsFORGE_Module_Hostage: sync toFORGE_Module_HostagesandFORGE_Module_ShootersFORGE_Module_HVT: sync directly to HVT unitsFORGE_Module_Defend: configure the defense marker and wave settings; sync enemy units to use their groups as wave templates
These modules delegate to fnc_startTask.sqf.
Start Through fnc_startTask.sqf
Use fnc_startTask.sqf for script-authored tasks. It registers task entities,
creates the BIS task, stores the catalog entry, and dispatches through
fnc_handler.sqf.
[
"attack",
"compound_attack_01",
getPosATL leader1,
"Attack: East Compound",
"Eliminate all hostile forces.",
createHashMapFromArray [["targets", [unit1, unit2, unit3]]],
createHashMapFromArray [
["limitFail", 0],
["limitSuccess", 3],
["funds", 50000],
["ratingFail", -10],
["ratingSuccess", 20],
["timeLimit", 900]
],
0,
getPlayerUID player,
"script"
] call forge_server_task_fnc_startTask;
Start Through The Handler
Use the handler when you want reputation gating and task ownership binding. Create the BIS task and catalog entry separately if this task should appear in the map task tab or CAD.
["attack", ["task_attack_1", 1, 2, 1500000, -75, 375, false, false], 250, getPlayerUID player] call forge_server_task_fnc_handler;
["delivery", ["task_delivery_1", 1, 3, "delivery_zone", 250000, -75, 300, false, false, 900], 0, getPlayerUID player] call forge_server_task_fnc_handler;
Arguments:
0: task type1: task-specific argument array2: minimum org reputation required to start the task3: requester UID used for ownership binding
Start Task Functions Directly
Direct task calls still work, but they do not provide a requester UID. That means task ownership falls back to the default org.
Create the BIS task separately if this task should appear in the map task tab.
Use direct starts only when that behavior is intended, such as:
- mission-authored tasks
- editor-placed tasks
- server-owned/random tasks
If you want the accepting player's org to own the task rewards, use fnc_handler.sqf instead.
["task_attack_1", 1, 2, 1500000, -75, 375, false, false] spawn forge_server_task_fnc_attack;
["task_hostage_1", 1, 2, "extract_marker", 1500000, -75, 500, [false, true], false, false] spawn forge_server_task_fnc_hostage;
Event Hooks and Bus Integration
XEH_preInit.sqf- compiles functions
- initializes
TaskStore - initializes task instance and entity controller classes
XEH_postInit.sqf- registers task lifecycle event listeners with the event bus
- handles task reward, notification, and rating events
- syncs org and bank state through event bus listeners
- registers the ACE defuse event hook
Events Emitted
Task module emits the following events to the event bus:
task.created- task instance createdtask.started- task execution startedtask.completed- task succeededtask.failed- task failedtask.cleared- task cleaned uptask.reward.requested- org rewards pending applicationtask.reward.applied- org rewards appliedtask.rating.applied- player rating appliedtask.notification.requested- participant notifications pending dispatch
Notes
- the dynamic mission manager in
fnc_missionManager.sqfis currently not started by default - it starts server-owned tasks through
fnc_handler.sqfand binds them to thedefaultorg - task lifecycle for the mission manager is tracked through
TaskStorestatus entries - task backend state is intentionally transient and resets with the active server/mission lifecycle
- task rewards are org-owned, not player-owned
- participant notifications are sent through the notifications module, not through local server UI
Authors
- J. Schmidt
- Creedcoder
- IDSolutions