Add prototypes for entity and hostage task management
- Introduced `EntityControllerBaseClass` for managing object-based entity controllers. - Added `HostageEntityController` to handle hostage-specific behaviors and interactions. - Created `HostageTaskBaseClass` to define the structure and logic for hostage-related tasks. - Updated `README.md` to include new prototypes and their purposes. - Refactored `taskObjectPrototypes.sqf` to load new classes and maintain organization.
This commit is contained in:
parent
3535484079
commit
1b000af2e6
Binary file not shown.
@ -201,29 +201,16 @@ private _grantOrgFleet = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private _equipment = _rewards getOrDefault ["equipment", []];
|
private _equipment = _rewards getOrDefault ["equipment", []];
|
||||||
if (count _equipment > 0) then {
|
|
||||||
["equipment", _equipment] call _grantOrgAssets;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _supplies = _rewards getOrDefault ["supplies", []];
|
|
||||||
if (count _supplies > 0) then {
|
|
||||||
["supplies", _supplies] call _grantOrgAssets;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _weapons = _rewards getOrDefault ["weapons", []];
|
|
||||||
if (count _weapons > 0) then {
|
|
||||||
["weapons", _weapons] call _grantOrgAssets;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _special = _rewards getOrDefault ["special", []];
|
private _special = _rewards getOrDefault ["special", []];
|
||||||
if (count _special > 0) then {
|
private _supplies = _rewards getOrDefault ["supplies", []];
|
||||||
["special", _special] call _grantOrgAssets;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _vehicles = _rewards getOrDefault ["vehicles", []];
|
private _vehicles = _rewards getOrDefault ["vehicles", []];
|
||||||
if (count _vehicles > 0) then {
|
private _weapons = _rewards getOrDefault ["weapons", []];
|
||||||
[_vehicles] call _grantOrgFleet;
|
|
||||||
};
|
if (_equipment isNotEqualTo []) then { ["equipment", _equipment] call _grantOrgAssets; };
|
||||||
|
if (_supplies isNotEqualTo []) then {["supplies", _supplies] call _grantOrgAssets; };
|
||||||
|
if (_weapons isNotEqualTo []) then { ["weapons", _weapons] call _grantOrgAssets; };
|
||||||
|
if (_special isNotEqualTo []) then { ["special", _special] call _grantOrgAssets; };
|
||||||
|
if (_vehicles isNotEqualTo []) then { [_vehicles] call _grantOrgFleet; };
|
||||||
|
|
||||||
if (_success) then {
|
if (_success) then {
|
||||||
private _orgName = "";
|
private _orgName = "";
|
||||||
|
|||||||
@ -96,9 +96,13 @@ if (_taskType isEqualTo "" || { _taskID isEqualTo "" }) exitWith {
|
|||||||
private _iedTimer = _taskParams getOrDefault ["iedTimer", 0];
|
private _iedTimer = _taskParams getOrDefault ["iedTimer", 0];
|
||||||
|
|
||||||
{
|
{
|
||||||
private _role = _x;
|
private _role = _x;
|
||||||
private _objects = _entities getOrDefault [_role, []];
|
private _objects = _entities getOrDefault [_role, []];
|
||||||
{
|
{
|
||||||
|
if !(_x isEqualType objNull) then {
|
||||||
|
["WARNING", format ["startTask: skipping non-object entity for role '%1' in task '%2': %3", _role, _taskID, _x]] call EFUNC(common,log);
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if (isNull _x) then { continue; };
|
if (isNull _x) then { continue; };
|
||||||
switch (_role) do {
|
switch (_role) do {
|
||||||
case "targets": { [_x, _taskID] call FUNC(makeTarget); };
|
case "targets": { [_x, _taskID] call FUNC(makeTarget); };
|
||||||
|
|||||||
171
arma/server/addons/task/prototypes/AttackTaskBaseClass.sqf
Normal file
171
arma/server/addons/task/prototypes/AttackTaskBaseClass.sqf
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Review-only prototype attack task class.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\TaskInstanceBaseClass.sqf";
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\AttackTaskBaseClass.sqf";
|
||||||
|
*
|
||||||
|
* private _task = createHashMapObject [
|
||||||
|
* GVAR(AttackTaskBaseClass),
|
||||||
|
* [
|
||||||
|
* "task_attack_review",
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["targets", [unit1, unit2, unit3]]
|
||||||
|
* ],
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["limitSuccess", 3],
|
||||||
|
* ["timeLimit", 900],
|
||||||
|
* ["funds", 50000],
|
||||||
|
* ["ratingSuccess", 25]
|
||||||
|
* ]
|
||||||
|
* ]
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* [_task] spawn {
|
||||||
|
* params ["_task"];
|
||||||
|
* _task call ["runLoop", []];
|
||||||
|
* };
|
||||||
|
* _task = nil; // Safe after the spawned closure has captured the reference.
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* `runLoop` uses `sleep`, so it must be entered from scheduled code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
|
||||||
|
GVAR(AttackTaskBaseClass) = createHashMapFromArray [
|
||||||
|
["#base", GVAR(TaskInstanceBaseClass)],
|
||||||
|
["#type", "AttackTaskBaseClass"],
|
||||||
|
["#create", compileFinal {
|
||||||
|
params [
|
||||||
|
["_taskID", "", [""]],
|
||||||
|
["_entities", createHashMap, [createHashMap]],
|
||||||
|
["_taskParams", createHashMap, [createHashMap]]
|
||||||
|
];
|
||||||
|
|
||||||
|
_self call ["initializeBaseState", [_taskID, "attack", _entities, _taskParams]];
|
||||||
|
|
||||||
|
private _targets = +(_entities getOrDefault ["targets", []]);
|
||||||
|
private _requiredKills = _taskParams getOrDefault ["limitSuccess", -1];
|
||||||
|
if (_requiredKills < 0) then { _requiredKills = count _targets; };
|
||||||
|
|
||||||
|
private _maxTargetLosses = _taskParams getOrDefault ["limitFail", -1];
|
||||||
|
if (_maxTargetLosses < 0) then { _maxTargetLosses = count _targets; };
|
||||||
|
|
||||||
|
_self set ["targets", _targets];
|
||||||
|
_self set ["requiredKills", _requiredKills];
|
||||||
|
_self set ["maxTargetLosses", _maxTargetLosses];
|
||||||
|
_self set ["timeLimit", _taskParams getOrDefault ["timeLimit", 0]];
|
||||||
|
|
||||||
|
// Review-only registry entry to demonstrate where #delete is useful.
|
||||||
|
missionNamespace setVariable [_taskID, _self];
|
||||||
|
}],
|
||||||
|
["#delete", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
if (_taskID isNotEqualTo "") then {
|
||||||
|
missionNamespace setVariable [_taskID, nil];
|
||||||
|
};
|
||||||
|
}],
|
||||||
|
["countKilledTargets", compileFinal {
|
||||||
|
private _targets = _self getOrDefault ["targets", []];
|
||||||
|
{ !alive _x } count _targets
|
||||||
|
}],
|
||||||
|
["tick", compileFinal {
|
||||||
|
private _startedAt = _self getOrDefault ["startedAt", -1];
|
||||||
|
private _timeLimit = _self getOrDefault ["timeLimit", 0];
|
||||||
|
private _targetsKilled = _self call ["countKilledTargets", []];
|
||||||
|
private _requiredKills = _self getOrDefault ["requiredKills", 0];
|
||||||
|
private _maxTargetLosses = _self getOrDefault ["maxTargetLosses", 0];
|
||||||
|
private _timeExpired = false;
|
||||||
|
|
||||||
|
if (_timeLimit > 0 && { _startedAt >= 0 }) then {
|
||||||
|
_timeExpired = (serverTime - _startedAt) >= _timeLimit;
|
||||||
|
};
|
||||||
|
|
||||||
|
createHashMapFromArray [
|
||||||
|
["targetsKilled", _targetsKilled],
|
||||||
|
["requiredKills", _requiredKills],
|
||||||
|
["maxTargetLosses", _maxTargetLosses],
|
||||||
|
["timeExpired", _timeExpired],
|
||||||
|
["shouldFail", _timeExpired && { _targetsKilled < _requiredKills }],
|
||||||
|
["shouldSucceed", _targetsKilled >= _requiredKills]
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
["runLoop", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
private _targets = _self getOrDefault ["targets", []];
|
||||||
|
private _timeLimit = _self getOrDefault ["timeLimit", 0];
|
||||||
|
private _rewardData = _self getOrDefault ["rewardData", createHashMap];
|
||||||
|
private _ratingFail = _rewardData getOrDefault ["ratingFail", 0];
|
||||||
|
private _ratingSuccess = _rewardData getOrDefault ["ratingSuccess", 0];
|
||||||
|
private _funds = _rewardData getOrDefault ["funds", 0];
|
||||||
|
private _endFail = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endFail", false];
|
||||||
|
private _endSuccess = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endSuccess", false];
|
||||||
|
|
||||||
|
waitUntil {
|
||||||
|
sleep 1;
|
||||||
|
GVAR(TaskStore) call ["trackParticipants", [_taskID, _targets, "", 300]];
|
||||||
|
count _targets > 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_timeLimit isNotEqualTo 0) then {
|
||||||
|
waitUntil {
|
||||||
|
sleep 1;
|
||||||
|
GVAR(TaskStore) call ["isTaskAccepted", [_taskID]]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_self call ["markActive", []];
|
||||||
|
|
||||||
|
while { (_self call ["getStatus", []]) isEqualTo "active" } do {
|
||||||
|
GVAR(TaskStore) call ["trackParticipants", [_taskID, _targets, "", 300]];
|
||||||
|
|
||||||
|
private _snapshot = _self call ["tick", []];
|
||||||
|
|
||||||
|
if (_snapshot getOrDefault ["shouldFail", false]) exitWith {
|
||||||
|
_self call ["markFailed", ["Attack fail conditions met.", _snapshot]];
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_snapshot getOrDefault ["shouldSucceed", false]) exitWith {
|
||||||
|
_self call ["markSucceeded", [_snapshot]];
|
||||||
|
};
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((_self call ["getStatus", []]) isEqualTo "failed") then {
|
||||||
|
{ deleteVehicle _x } forEach _targets;
|
||||||
|
|
||||||
|
[_taskID, "FAILED"] call BFUNC(taskSetState);
|
||||||
|
GVAR(TaskStore) call ["setTaskStatus", [_taskID, "failed"]];
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
|
||||||
|
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "warning", "Tasks", format ["Task failed: %1 reputation", _ratingFail]]];
|
||||||
|
GVAR(TaskStore) call ["applyRatingOutcome", [_taskID, _ratingFail]];
|
||||||
|
GVAR(TaskStore) call ["clearTask", [_taskID]];
|
||||||
|
|
||||||
|
if (_endFail) then { ["MissionFail", false] remoteExec ["BIS_fnc_endMission", playerSide]; };
|
||||||
|
} else {
|
||||||
|
{ deleteVehicle _x } forEach _targets;
|
||||||
|
|
||||||
|
[_taskID, _rewardData] call FUNC(handleTaskRewards);
|
||||||
|
[_taskID, "SUCCEEDED"] call BFUNC(taskSetState);
|
||||||
|
GVAR(TaskStore) call ["setTaskStatus", [_taskID, "succeeded"]];
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
|
||||||
|
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "success", "Tasks", format ["Task completed: %1 reputation, $%2 funds", _ratingSuccess, [_funds] call EFUNC(common,formatNumber)]]];
|
||||||
|
GVAR(TaskStore) call ["applyRatingOutcome", [_taskID, _ratingSuccess]];
|
||||||
|
GVAR(TaskStore) call ["clearTask", [_taskID]];
|
||||||
|
|
||||||
|
if (_endSuccess) then { ["MissionSuccess", true] remoteExec ["BIS_fnc_endMission", playerSide]; };
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
||||||
|
}]
|
||||||
|
];
|
||||||
119
arma/server/addons/task/prototypes/DefuseTaskBaseClass.sqf
Normal file
119
arma/server/addons/task/prototypes/DefuseTaskBaseClass.sqf
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Review-only prototype defuse task class.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\TaskInstanceBaseClass.sqf";
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\DefuseTaskBaseClass.sqf";
|
||||||
|
*
|
||||||
|
* private _task = createHashMapObject [
|
||||||
|
* GVAR(DefuseTaskBaseClass),
|
||||||
|
* [
|
||||||
|
* "task_defuse_review",
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["ieds", [ied1, ied2]],
|
||||||
|
* ["protected", [truck1]]
|
||||||
|
* ],
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["limitSuccess", 2],
|
||||||
|
* ["limitFail", 1],
|
||||||
|
* ["iedTimer", 300],
|
||||||
|
* ["funds", 75000],
|
||||||
|
* ["ratingSuccess", 30]
|
||||||
|
* ]
|
||||||
|
* ]
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* [_task] spawn {
|
||||||
|
* params ["_task"];
|
||||||
|
* _task call ["runLoop", []];
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* `runLoop` uses `sleep`, so it must be entered from scheduled code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
GVAR(DefuseTaskBaseClass) = createHashMapFromArray [
|
||||||
|
["#base", GVAR(TaskInstanceBaseClass)],
|
||||||
|
["#type", "DefuseTaskBaseClass"],
|
||||||
|
["#create", compileFinal {
|
||||||
|
params [
|
||||||
|
["_taskID", "", [""]],
|
||||||
|
["_entities", createHashMap, [createHashMap]],
|
||||||
|
["_taskParams", createHashMap, [createHashMap]]
|
||||||
|
];
|
||||||
|
|
||||||
|
_self call ["initializeBaseState", [_taskID, "defuse", _entities, _taskParams]];
|
||||||
|
|
||||||
|
private _ieds = +(_entities getOrDefault ["ieds", []]);
|
||||||
|
private _protected = +(_entities getOrDefault ["protected", []]);
|
||||||
|
private _requiredDefusals = _taskParams getOrDefault ["limitSuccess", -1];
|
||||||
|
if (_requiredDefusals < 0) then { _requiredDefusals = count _ieds; };
|
||||||
|
|
||||||
|
private _maxProtectedLosses = _taskParams getOrDefault ["limitFail", -1];
|
||||||
|
if (_maxProtectedLosses < 0) then { _maxProtectedLosses = count _protected; };
|
||||||
|
|
||||||
|
_self set ["ieds", _ieds];
|
||||||
|
_self set ["protected", _protected];
|
||||||
|
_self set ["requiredDefusals", _requiredDefusals];
|
||||||
|
_self set ["maxProtectedLosses", _maxProtectedLosses];
|
||||||
|
_self set ["iedTimer", _taskParams getOrDefault ["iedTimer", 300]];
|
||||||
|
|
||||||
|
// Review-only registry entry to demonstrate where #delete is useful.
|
||||||
|
missionNamespace setVariable [_taskID, _self];
|
||||||
|
}],
|
||||||
|
["#delete", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
if (_taskID isNotEqualTo "") then {
|
||||||
|
missionNamespace setVariable [_taskID, nil];
|
||||||
|
};
|
||||||
|
}],
|
||||||
|
["countProtectedDestroyed", compileFinal {
|
||||||
|
private _protected = _self getOrDefault ["protected", []];
|
||||||
|
{ !alive _x } count _protected
|
||||||
|
}],
|
||||||
|
["getDefuseCount", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
if (_taskID isEqualTo "") exitWith { 0 };
|
||||||
|
|
||||||
|
GVAR(TaskStore) call ["getDefuseCount", [_taskID]]
|
||||||
|
}],
|
||||||
|
["tick", compileFinal {
|
||||||
|
private _defusedCount = _self call ["getDefuseCount", []];
|
||||||
|
private _protectedDestroyed = _self call ["countProtectedDestroyed", []];
|
||||||
|
private _requiredDefusals = _self getOrDefault ["requiredDefusals", 0];
|
||||||
|
private _maxProtectedLosses = _self getOrDefault ["maxProtectedLosses", 0];
|
||||||
|
|
||||||
|
createHashMapFromArray [
|
||||||
|
["defusedCount", _defusedCount],
|
||||||
|
["protectedDestroyed", _protectedDestroyed],
|
||||||
|
["requiredDefusals", _requiredDefusals],
|
||||||
|
["maxProtectedLosses", _maxProtectedLosses],
|
||||||
|
["shouldFail", (_protectedDestroyed >= _maxProtectedLosses) && { _maxProtectedLosses > 0 }],
|
||||||
|
["shouldSucceed", (_defusedCount >= _requiredDefusals) && { _requiredDefusals > 0 } && { _protectedDestroyed < _maxProtectedLosses || { _maxProtectedLosses <= 0 } }]
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
["runLoop", compileFinal {
|
||||||
|
_self call ["markActive", []];
|
||||||
|
|
||||||
|
while { (_self call ["getStatus", []]) isEqualTo "active" } do {
|
||||||
|
private _snapshot = _self call ["tick", []];
|
||||||
|
|
||||||
|
if (_snapshot getOrDefault ["shouldFail", false]) exitWith {
|
||||||
|
_self call ["markFailed", ["Defuse fail conditions met.", _snapshot]];
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_snapshot getOrDefault ["shouldSucceed", false]) exitWith {
|
||||||
|
_self call ["markSucceeded", [_snapshot]];
|
||||||
|
};
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
||||||
|
}]
|
||||||
|
];
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Review-only prototype base class for object-based entity controllers.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\EntityControllerBaseClass.sqf";
|
||||||
|
*
|
||||||
|
* private _controller = createHashMapObject [
|
||||||
|
* GVAR(EntityControllerBaseClass),
|
||||||
|
* [
|
||||||
|
* "task_review_001",
|
||||||
|
* hostage1,
|
||||||
|
* "custom",
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["radius", 2]
|
||||||
|
* ]
|
||||||
|
* ]
|
||||||
|
* ];
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
GVAR(EntityControllerBaseClass) = createHashMapFromArray [
|
||||||
|
["#type", "EntityControllerBaseClass"],
|
||||||
|
["initializeControllerState", compileFinal {
|
||||||
|
params [
|
||||||
|
["_taskID", "", [""]],
|
||||||
|
["_entity", objNull, [objNull]],
|
||||||
|
["_controllerType", "custom", [""]],
|
||||||
|
["_controllerParams", createHashMap, [createHashMap]]
|
||||||
|
];
|
||||||
|
|
||||||
|
_self set ["taskID", _taskID];
|
||||||
|
_self set ["entity", _entity];
|
||||||
|
_self set ["controllerType", _controllerType];
|
||||||
|
_self set ["controllerParams", _controllerParams];
|
||||||
|
_self set ["status", "created"];
|
||||||
|
_self set ["startedAt", -1];
|
||||||
|
_self set ["finishedAt", -1];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["#create", compileFinal {
|
||||||
|
private _taskID = "";
|
||||||
|
private _entity = objNull;
|
||||||
|
private _controllerType = "custom";
|
||||||
|
private _controllerParams = createHashMap;
|
||||||
|
|
||||||
|
if (_this isEqualType [] && { count _this > 0 }) then {
|
||||||
|
_taskID = _this param [0, "", [""]];
|
||||||
|
_entity = _this param [1, objNull, [objNull]];
|
||||||
|
|
||||||
|
if ((count _this > 2) && { (_this select 2) isEqualType "" }) then {
|
||||||
|
_controllerType = _this param [2, "custom", [""]];
|
||||||
|
_controllerParams = _this param [3, createHashMap, [createHashMap]];
|
||||||
|
} else {
|
||||||
|
_controllerParams = _this param [2, createHashMap, [createHashMap]];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_self call ["initializeControllerState", [_taskID, _entity, _controllerType, _controllerParams]];
|
||||||
|
}],
|
||||||
|
["getEntity", compileFinal {
|
||||||
|
_self getOrDefault ["entity", objNull]
|
||||||
|
}],
|
||||||
|
["markActive", compileFinal {
|
||||||
|
_self set ["status", "active"];
|
||||||
|
_self set ["startedAt", serverTime];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["markFinished", compileFinal {
|
||||||
|
_self set ["status", "finished"];
|
||||||
|
_self set ["finishedAt", serverTime];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["markAborted", compileFinal {
|
||||||
|
_self set ["status", "aborted"];
|
||||||
|
_self set ["finishedAt", serverTime];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["cleanup", compileFinal {
|
||||||
|
false
|
||||||
|
}],
|
||||||
|
["runLoop", compileFinal {
|
||||||
|
false
|
||||||
|
}]
|
||||||
|
];
|
||||||
127
arma/server/addons/task/prototypes/HostageEntityController.sqf
Normal file
127
arma/server/addons/task/prototypes/HostageEntityController.sqf
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Review-only prototype hostage entity controller.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\EntityControllerBaseClass.sqf";
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\HostageEntityController.sqf";
|
||||||
|
*
|
||||||
|
* private _controller = createHashMapObject [
|
||||||
|
* GVAR(HostageEntityController),
|
||||||
|
* [
|
||||||
|
* "task_hostage_review",
|
||||||
|
* hostage1,
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["rescueRadius", 2],
|
||||||
|
* ["loopAnimation", "acts_executionvictim_loop"],
|
||||||
|
* ["rescueAnimation", "acts_executionvictim_unbow"]
|
||||||
|
* ]
|
||||||
|
* ]
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* [_controller] spawn {
|
||||||
|
* params ["_controller"];
|
||||||
|
* _controller call ["runLoop", []];
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* `runLoop` uses `sleep`, so it must be entered from scheduled code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
GVAR(HostageEntityController) = createHashMapFromArray [
|
||||||
|
["#base", GVAR(EntityControllerBaseClass)],
|
||||||
|
["#type", "HostageEntityController"],
|
||||||
|
["#create", compileFinal {
|
||||||
|
params [
|
||||||
|
["_taskID", "", [""]],
|
||||||
|
["_entity", objNull, [objNull]],
|
||||||
|
["_controllerParams", createHashMap, [createHashMap]]
|
||||||
|
];
|
||||||
|
|
||||||
|
_self call ["initializeControllerState", [_taskID, _entity, "hostage", _controllerParams]];
|
||||||
|
_self set ["rescueRadius", _controllerParams getOrDefault ["rescueRadius", 2]];
|
||||||
|
_self set ["loopAnimation", _controllerParams getOrDefault ["loopAnimation", "acts_executionvictim_loop"]];
|
||||||
|
_self set ["rescueAnimation", _controllerParams getOrDefault ["rescueAnimation", "acts_executionvictim_unbow"]];
|
||||||
|
|
||||||
|
private _netID = if (isNull _entity) then { "" } else { netId _entity };
|
||||||
|
if (_netID isNotEqualTo "") then {
|
||||||
|
private _controllerKey = format ["hostage_controller_%1", _netID];
|
||||||
|
missionNamespace setVariable [_controllerKey, _self];
|
||||||
|
};
|
||||||
|
}],
|
||||||
|
["#delete", compileFinal {
|
||||||
|
private _entity = _self getOrDefault ["entity", objNull];
|
||||||
|
if (!isNull _entity) then {
|
||||||
|
private _controllerKey = format ["hostage_controller_%1", netId _entity];
|
||||||
|
missionNamespace setVariable [_controllerKey, nil];
|
||||||
|
};
|
||||||
|
}],
|
||||||
|
["applyInitialState", compileFinal {
|
||||||
|
private _entity = _self getOrDefault ["entity", objNull];
|
||||||
|
if (isNull _entity || { !alive _entity }) exitWith { false };
|
||||||
|
|
||||||
|
_entity setCaptive true;
|
||||||
|
_entity enableAIFeature ["MOVE", false];
|
||||||
|
_entity playMove (_self getOrDefault ["loopAnimation", "acts_executionvictim_loop"]);
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["findNearbyRescuer", compileFinal {
|
||||||
|
private _entity = _self getOrDefault ["entity", objNull];
|
||||||
|
if (isNull _entity || { !alive _entity }) exitWith { objNull };
|
||||||
|
|
||||||
|
private _radius = _self getOrDefault ["rescueRadius", 2];
|
||||||
|
private _nearPlayers = allPlayers inAreaArray [ASLToAGL getPosASL _entity, _radius, _radius, 0, false, 2];
|
||||||
|
if (_nearPlayers isEqualTo []) exitWith { objNull };
|
||||||
|
|
||||||
|
_nearPlayers select 0
|
||||||
|
}],
|
||||||
|
["transitionToRescued", compileFinal {
|
||||||
|
params [["_rescuer", objNull, [objNull]]];
|
||||||
|
|
||||||
|
private _entity = _self getOrDefault ["entity", objNull];
|
||||||
|
if (isNull _entity || { isNull _rescuer }) exitWith { false };
|
||||||
|
|
||||||
|
[_entity] joinSilent (group _rescuer);
|
||||||
|
_entity setCaptive true;
|
||||||
|
_entity enableAIFeature ["MOVE", true];
|
||||||
|
_entity playMove (_self getOrDefault ["rescueAnimation", "acts_executionvictim_unbow"]);
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["runLoop", compileFinal {
|
||||||
|
private _entity = _self getOrDefault ["entity", objNull];
|
||||||
|
if (isNull _entity) exitWith {
|
||||||
|
_self call ["markAborted", []];
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
_self call ["markActive", []];
|
||||||
|
|
||||||
|
if !(_self call ["applyInitialState", []]) exitWith {
|
||||||
|
_self call ["markAborted", []];
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
private _rescuer = objNull;
|
||||||
|
waitUntil {
|
||||||
|
sleep 1;
|
||||||
|
|
||||||
|
if (isNull _entity || { !alive _entity }) exitWith { true };
|
||||||
|
|
||||||
|
_rescuer = _self call ["findNearbyRescuer", []];
|
||||||
|
!isNull _rescuer
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isNull _entity || { !alive _entity }) exitWith {
|
||||||
|
_self call ["markAborted", []];
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
_self call ["transitionToRescued", [_rescuer]];
|
||||||
|
_self call ["markFinished", []];
|
||||||
|
true
|
||||||
|
}]
|
||||||
|
];
|
||||||
339
arma/server/addons/task/prototypes/HostageTaskBaseClass.sqf
Normal file
339
arma/server/addons/task/prototypes/HostageTaskBaseClass.sqf
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Review-only prototype hostage task class.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\TaskInstanceBaseClass.sqf";
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\HostageTaskBaseClass.sqf";
|
||||||
|
*
|
||||||
|
* private _task = createHashMapObject [
|
||||||
|
* GVAR(HostageTaskBaseClass),
|
||||||
|
* [
|
||||||
|
* "task_hostage_review",
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["hostages", [hostage1, hostage2]],
|
||||||
|
* ["shooters", [shooter1, shooter2]]
|
||||||
|
* ],
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["extractionZone", "hostage_extract"],
|
||||||
|
* ["limitSuccess", 2],
|
||||||
|
* ["limitFail", 1],
|
||||||
|
* ["execution", true],
|
||||||
|
* ["timeLimit", 900],
|
||||||
|
* ["funds", 100000],
|
||||||
|
* ["ratingSuccess", 50]
|
||||||
|
* ]
|
||||||
|
* ]
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* [_task] spawn {
|
||||||
|
* params ["_task"];
|
||||||
|
* _task call ["runLoop", []];
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* `runLoop` and the wait helpers use `sleep`, so they must be entered from
|
||||||
|
* scheduled code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
GVAR(HostageTaskBaseClass) = createHashMapFromArray [
|
||||||
|
["#base", GVAR(TaskInstanceBaseClass)],
|
||||||
|
["#type", "HostageTaskBaseClass"],
|
||||||
|
["#create", compileFinal {
|
||||||
|
params [
|
||||||
|
["_taskID", "", [""]],
|
||||||
|
["_entities", createHashMap, [createHashMap]],
|
||||||
|
["_taskParams", createHashMap, [createHashMap]]
|
||||||
|
];
|
||||||
|
|
||||||
|
_self call ["initializeBaseState", [_taskID, "hostage", _entities, _taskParams]];
|
||||||
|
|
||||||
|
private _hostages = +(_entities getOrDefault ["hostages", []]);
|
||||||
|
private _shooters = +(_entities getOrDefault ["shooters", []]);
|
||||||
|
private _requiredRescues = _taskParams getOrDefault ["limitSuccess", -1];
|
||||||
|
if (_requiredRescues < 0) then { _requiredRescues = count _hostages; };
|
||||||
|
|
||||||
|
private _maxHostageLosses = _taskParams getOrDefault ["limitFail", -1];
|
||||||
|
if (_maxHostageLosses < 0) then { _maxHostageLosses = count _hostages; };
|
||||||
|
|
||||||
|
_self set ["hostages", _hostages];
|
||||||
|
_self set ["shooters", _shooters];
|
||||||
|
_self set ["extractionZone", _taskParams getOrDefault ["extractionZone", ""]];
|
||||||
|
_self set ["timeLimit", _taskParams getOrDefault ["timeLimit", 0]];
|
||||||
|
_self set ["execution", _taskParams getOrDefault ["execution", false]];
|
||||||
|
_self set ["cbrn", _taskParams getOrDefault ["cbrn", false]];
|
||||||
|
_self set ["cbrnZone", _taskParams getOrDefault ["cbrnZone", ""]];
|
||||||
|
_self set ["requiredRescues", _requiredRescues];
|
||||||
|
_self set ["maxHostageLosses", _maxHostageLosses];
|
||||||
|
_self set ["hostageControllers", []];
|
||||||
|
|
||||||
|
_self call ["createHostageControllers", []];
|
||||||
|
|
||||||
|
// Review-only registry entry to demonstrate where #delete is useful.
|
||||||
|
missionNamespace setVariable [_taskID, _self];
|
||||||
|
}],
|
||||||
|
["#delete", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
if (_taskID isNotEqualTo "") then {
|
||||||
|
missionNamespace setVariable [_taskID, nil];
|
||||||
|
};
|
||||||
|
}],
|
||||||
|
["createHostageControllers", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
private _hostages = _self getOrDefault ["hostages", []];
|
||||||
|
private _controllers = [];
|
||||||
|
|
||||||
|
{
|
||||||
|
_controllers pushBack (createHashMapObject [
|
||||||
|
GVAR(HostageEntityController),
|
||||||
|
[
|
||||||
|
_taskID,
|
||||||
|
_x,
|
||||||
|
createHashMapFromArray [
|
||||||
|
["rescueRadius", 2],
|
||||||
|
["loopAnimation", "acts_executionvictim_loop"],
|
||||||
|
["rescueAnimation", "acts_executionvictim_unbow"]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} forEach _hostages;
|
||||||
|
|
||||||
|
_self set ["hostageControllers", _controllers];
|
||||||
|
_controllers
|
||||||
|
}],
|
||||||
|
["startHostageControllers", compileFinal {
|
||||||
|
private _controllers = _self getOrDefault ["hostageControllers", []];
|
||||||
|
|
||||||
|
{
|
||||||
|
[_x] spawn {
|
||||||
|
params ["_controller"];
|
||||||
|
_controller call ["runLoop", []];
|
||||||
|
};
|
||||||
|
} forEach _controllers;
|
||||||
|
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["refreshEntitiesFromStore", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
if (_taskID isEqualTo "") exitWith { false };
|
||||||
|
|
||||||
|
private _hostages = GVAR(TaskStore) call ["getTaskEntities", ["hostages", _taskID]];
|
||||||
|
private _shooters = GVAR(TaskStore) call ["getTaskEntities", ["shooters", _taskID]];
|
||||||
|
|
||||||
|
_self set ["hostages", _hostages];
|
||||||
|
_self set ["shooters", _shooters];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["trackParticipants", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
if (_taskID isEqualTo "") exitWith { false };
|
||||||
|
|
||||||
|
private _hostages = _self getOrDefault ["hostages", []];
|
||||||
|
private _shooters = _self getOrDefault ["shooters", []];
|
||||||
|
private _extZone = _self getOrDefault ["extractionZone", ""];
|
||||||
|
|
||||||
|
GVAR(TaskStore) call ["trackParticipants", [_taskID, _hostages + _shooters, _extZone, 250]];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["waitForRequiredEntities", compileFinal {
|
||||||
|
waitUntil {
|
||||||
|
sleep 1;
|
||||||
|
_self call ["refreshEntitiesFromStore", []];
|
||||||
|
count (_self getOrDefault ["hostages", []]) > 0
|
||||||
|
};
|
||||||
|
|
||||||
|
waitUntil {
|
||||||
|
sleep 1;
|
||||||
|
_self call ["refreshEntitiesFromStore", []];
|
||||||
|
_self call ["trackParticipants", []];
|
||||||
|
count (_self getOrDefault ["shooters", []]) > 0
|
||||||
|
};
|
||||||
|
|
||||||
|
private _hostages = _self getOrDefault ["hostages", []];
|
||||||
|
private _taskParams = _self getOrDefault ["taskParams", createHashMap];
|
||||||
|
private _requiredRescues = _taskParams getOrDefault ["limitSuccess", -1];
|
||||||
|
if (_requiredRescues < 0) then { _requiredRescues = count _hostages; };
|
||||||
|
|
||||||
|
private _maxHostageLosses = _taskParams getOrDefault ["limitFail", -1];
|
||||||
|
if (_maxHostageLosses < 0) then { _maxHostageLosses = count _hostages; };
|
||||||
|
|
||||||
|
_self set ["requiredRescues", _requiredRescues];
|
||||||
|
_self set ["maxHostageLosses", _maxHostageLosses];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["waitForAssignmentIfTimed", compileFinal {
|
||||||
|
private _timeLimit = _self getOrDefault ["timeLimit", 0];
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
|
||||||
|
if (_timeLimit <= 0 || { _taskID isEqualTo "" }) exitWith { true };
|
||||||
|
|
||||||
|
waitUntil {
|
||||||
|
sleep 1;
|
||||||
|
GVAR(TaskStore) call ["isTaskAccepted", [_taskID]]
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["countFreedHostages", compileFinal {
|
||||||
|
private _playerGroups = allPlayers apply { group _x };
|
||||||
|
private _hostages = _self getOrDefault ["hostages", []];
|
||||||
|
|
||||||
|
{
|
||||||
|
alive _x && { ((group _x) in _playerGroups) || { !captive _x } }
|
||||||
|
} count _hostages
|
||||||
|
}],
|
||||||
|
["countHostagesInZone", compileFinal {
|
||||||
|
private _extZone = _self getOrDefault ["extractionZone", ""];
|
||||||
|
private _hostages = _self getOrDefault ["hostages", []];
|
||||||
|
|
||||||
|
if (_extZone isEqualTo "") exitWith { 0 };
|
||||||
|
{ _x inArea _extZone } count _hostages
|
||||||
|
}],
|
||||||
|
["countKilledHostages", compileFinal {
|
||||||
|
private _hostages = _self getOrDefault ["hostages", []];
|
||||||
|
{ !alive _x } count _hostages
|
||||||
|
}],
|
||||||
|
["countAliveShooters", compileFinal {
|
||||||
|
private _shooters = _self getOrDefault ["shooters", []];
|
||||||
|
{ alive _x } count _shooters
|
||||||
|
}],
|
||||||
|
["tick", compileFinal {
|
||||||
|
private _startedAt = _self getOrDefault ["startedAt", -1];
|
||||||
|
private _timeLimit = _self getOrDefault ["timeLimit", 0];
|
||||||
|
private _killed = _self call ["countKilledHostages", []];
|
||||||
|
private _freed = _self call ["countFreedHostages", []];
|
||||||
|
private _inZone = _self call ["countHostagesInZone", []];
|
||||||
|
private _shootersAlive = _self call ["countAliveShooters", []];
|
||||||
|
private _requiredRescues = _self getOrDefault ["requiredRescues", 0];
|
||||||
|
private _maxHostageLosses = _self getOrDefault ["maxHostageLosses", 0];
|
||||||
|
private _timeExpired = false;
|
||||||
|
|
||||||
|
if (_timeLimit > 0 && { _startedAt >= 0 }) then {
|
||||||
|
_timeExpired = (serverTime - _startedAt) >= _timeLimit;
|
||||||
|
};
|
||||||
|
|
||||||
|
createHashMapFromArray [
|
||||||
|
["freed", _freed],
|
||||||
|
["inZone", _inZone],
|
||||||
|
["killed", _killed],
|
||||||
|
["shootersAlive", _shootersAlive],
|
||||||
|
["requiredRescues", _requiredRescues],
|
||||||
|
["maxHostageLosses", _maxHostageLosses],
|
||||||
|
["timeExpired", _timeExpired],
|
||||||
|
["shouldFail", (_killed >= _maxHostageLosses) || { _timeExpired && { _freed < _requiredRescues } }],
|
||||||
|
["shouldSucceed", ((_inZone >= _requiredRescues) && { _killed < _maxHostageLosses }) || { (_shootersAlive <= 0) && { _inZone >= _requiredRescues } && { _killed < _maxHostageLosses } }]
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
["handleFailureOutcome", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
private _hostages = _self getOrDefault ["hostages", []];
|
||||||
|
private _shooters = _self getOrDefault ["shooters", []];
|
||||||
|
private _rewardData = _self getOrDefault ["rewardData", createHashMap];
|
||||||
|
private _ratingFail = _rewardData getOrDefault ["ratingFail", 0];
|
||||||
|
private _endFail = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endFail", false];
|
||||||
|
private _cbrn = _self getOrDefault ["cbrn", false];
|
||||||
|
private _hostage = _self getOrDefault ["execution", false];
|
||||||
|
private _cbrnZone = _self getOrDefault ["cbrnZone", ""];
|
||||||
|
|
||||||
|
if (_cbrn && { _cbrnZone isNotEqualTo "" }) then {
|
||||||
|
"SmokeShellYellow" createVehicle getMarkerPos _cbrnZone;
|
||||||
|
|
||||||
|
sleep 5;
|
||||||
|
|
||||||
|
{
|
||||||
|
if (captive _x) then {
|
||||||
|
_x setDamage 0.9;
|
||||||
|
_x playMove "acts_executionvictim_kill_end";
|
||||||
|
|
||||||
|
sleep 2.75;
|
||||||
|
|
||||||
|
_x setDamage 1;
|
||||||
|
};
|
||||||
|
} forEach _hostages;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_hostage) then {
|
||||||
|
{
|
||||||
|
_x enableAIFeature ["MOVE", true];
|
||||||
|
_x playMove "";
|
||||||
|
} forEach _shooters;
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
|
||||||
|
{ _x setCaptive false; } forEach _hostages;
|
||||||
|
|
||||||
|
sleep 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
{ deleteVehicle _x } forEach _hostages;
|
||||||
|
{ deleteVehicle _x } forEach _shooters;
|
||||||
|
|
||||||
|
[_taskID, "FAILED"] call BFUNC(taskSetState);
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
|
||||||
|
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "warning", "Tasks", format ["Task failed: %1 reputation", _ratingFail]]];
|
||||||
|
GVAR(TaskStore) call ["applyRatingOutcome", [_taskID, _ratingFail]];
|
||||||
|
GVAR(TaskStore) call ["clearTask", [_taskID]];
|
||||||
|
|
||||||
|
if (_endFail) then { ["MissionFail", false] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["handleSuccessOutcome", compileFinal {
|
||||||
|
private _taskID = _self getOrDefault ["taskID", ""];
|
||||||
|
private _hostages = _self getOrDefault ["hostages", []];
|
||||||
|
private _shooters = _self getOrDefault ["shooters", []];
|
||||||
|
private _rewardData = _self getOrDefault ["rewardData", createHashMap];
|
||||||
|
private _ratingSuccess = _rewardData getOrDefault ["ratingSuccess", 0];
|
||||||
|
private _funds = _rewardData getOrDefault ["funds", 0];
|
||||||
|
private _endSuccess = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endSuccess", false];
|
||||||
|
|
||||||
|
{ deleteVehicle _x } forEach _hostages;
|
||||||
|
{ deleteVehicle _x } forEach _shooters;
|
||||||
|
|
||||||
|
[_taskID, _rewardData] call FUNC(handleTaskRewards);
|
||||||
|
[_taskID, "SUCCEEDED"] call BFUNC(taskSetState);
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
|
||||||
|
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "success", "Tasks", format ["Task completed: %1 reputation, $%2 funds", _ratingSuccess, [_funds] call EFUNC(common,formatNumber)]]];
|
||||||
|
GVAR(TaskStore) call ["applyRatingOutcome", [_taskID, _ratingSuccess]];
|
||||||
|
GVAR(TaskStore) call ["clearTask", [_taskID]];
|
||||||
|
|
||||||
|
if (_endSuccess) then { ["MissionSuccess", true] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["runLoop", compileFinal {
|
||||||
|
_self call ["waitForRequiredEntities", []];
|
||||||
|
_self call ["startHostageControllers", []];
|
||||||
|
_self call ["waitForAssignmentIfTimed", []];
|
||||||
|
_self call ["markActive", []];
|
||||||
|
|
||||||
|
while { (_self call ["getStatus", []]) isEqualTo "active" } do {
|
||||||
|
_self call ["trackParticipants", []];
|
||||||
|
private _snapshot = _self call ["tick", []];
|
||||||
|
|
||||||
|
if (_snapshot getOrDefault ["shouldFail", false]) exitWith {
|
||||||
|
_self call ["markFailed", ["Hostage fail conditions met.", _snapshot]];
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_snapshot getOrDefault ["shouldSucceed", false]) exitWith {
|
||||||
|
_self call ["markSucceeded", [_snapshot]];
|
||||||
|
};
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((_self call ["getStatus", []]) isEqualTo "failed") then {
|
||||||
|
_self call ["handleFailureOutcome", []];
|
||||||
|
} else {
|
||||||
|
_self call ["handleSuccessOutcome", []];
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
||||||
|
}]
|
||||||
|
];
|
||||||
@ -5,21 +5,37 @@ instances. They are not part of runtime initialization.
|
|||||||
|
|
||||||
Current prototypes:
|
Current prototypes:
|
||||||
- `TaskInstanceBaseClass`
|
- `TaskInstanceBaseClass`
|
||||||
|
- `EntityControllerBaseClass`
|
||||||
|
- `AttackTaskBaseClass`
|
||||||
- `HostageTaskBaseClass`
|
- `HostageTaskBaseClass`
|
||||||
|
- `HostageEntityController`
|
||||||
- `DefuseTaskBaseClass`
|
- `DefuseTaskBaseClass`
|
||||||
|
|
||||||
Source:
|
Source:
|
||||||
- [taskObjectPrototypes.sqf](./taskObjectPrototypes.sqf)
|
- [taskObjectPrototypes.sqf](./taskObjectPrototypes.sqf)
|
||||||
|
- [TaskInstanceBaseClass.sqf](./TaskInstanceBaseClass.sqf)
|
||||||
|
- [EntityControllerBaseClass.sqf](./EntityControllerBaseClass.sqf)
|
||||||
|
- [AttackTaskBaseClass.sqf](./AttackTaskBaseClass.sqf)
|
||||||
|
- [HostageTaskBaseClass.sqf](./HostageTaskBaseClass.sqf)
|
||||||
|
- [HostageEntityController.sqf](./HostageEntityController.sqf)
|
||||||
|
- [DefuseTaskBaseClass.sqf](./DefuseTaskBaseClass.sqf)
|
||||||
|
|
||||||
Purpose:
|
Purpose:
|
||||||
- show what per-task instance objects could look like
|
- show what per-task instance objects could look like
|
||||||
|
- show what per-entity heartbeat/controller objects could look like
|
||||||
- separate state ownership from the current long procedural functions
|
- separate state ownership from the current long procedural functions
|
||||||
- avoid committing the live addon to a large refactor before the model is
|
- avoid committing the live addon to a large refactor before the model is
|
||||||
reviewed
|
reviewed
|
||||||
|
- keep shared lifecycle and reward initialization in `TaskInstanceBaseClass`
|
||||||
|
so concrete task prototypes only define task-specific state
|
||||||
|
- keep heartbeat-style AI/object behavior in separate entity controllers instead
|
||||||
|
of mixing it into task outcome loops
|
||||||
|
|
||||||
Important design choice:
|
Important design choice:
|
||||||
- these prototypes use explicit `markSucceeded`, `markFailed`, and `cleanup`
|
- these prototypes use explicit `markSucceeded`, `markFailed`, and `cleanup`
|
||||||
methods instead of relying on `#delete`
|
methods instead of relying on `#delete`
|
||||||
|
- task loops that use `sleep` or `waitUntil` with `sleep` must be started from
|
||||||
|
scheduled code, typically via `spawn`
|
||||||
|
|
||||||
That is intentional. `createHashMapObject` destructor timing is reference-based,
|
That is intentional. `createHashMapObject` destructor timing is reference-based,
|
||||||
so `#delete` is not a good primitive for mission-critical task completion or
|
so `#delete` is not a good primitive for mission-critical task completion or
|
||||||
|
|||||||
120
arma/server/addons/task/prototypes/TaskInstanceBaseClass.sqf
Normal file
120
arma/server/addons/task/prototypes/TaskInstanceBaseClass.sqf
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Review-only prototype base class for object-based task instances.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* call compile preprocessFileLineNumbers
|
||||||
|
* "\forge\forge_server\addons\task\prototypes\TaskInstanceBaseClass.sqf";
|
||||||
|
*
|
||||||
|
* private _task = createHashMapObject [
|
||||||
|
* GVAR(TaskInstanceBaseClass),
|
||||||
|
* [
|
||||||
|
* "task_review_001",
|
||||||
|
* "custom",
|
||||||
|
* createHashMap,
|
||||||
|
* createHashMapFromArray [
|
||||||
|
* ["funds", 50000],
|
||||||
|
* ["ratingSuccess", 25]
|
||||||
|
* ]
|
||||||
|
* ]
|
||||||
|
* ];
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
GVAR(TaskInstanceBaseClass) = createHashMapFromArray [
|
||||||
|
["#type", "TaskInstanceBaseClass"],
|
||||||
|
["initializeBaseState", compileFinal {
|
||||||
|
params [
|
||||||
|
["_taskID", "", [""]],
|
||||||
|
["_taskType", "custom", [""]],
|
||||||
|
["_entities", createHashMap, [createHashMap]],
|
||||||
|
["_taskParams", createHashMap, [createHashMap]]
|
||||||
|
];
|
||||||
|
|
||||||
|
_self set ["taskID", _taskID];
|
||||||
|
_self set ["taskType", _taskType];
|
||||||
|
_self set ["entities", _entities];
|
||||||
|
_self set ["taskParams", _taskParams];
|
||||||
|
_self set ["status", "created"];
|
||||||
|
_self set ["startedAt", -1];
|
||||||
|
_self set ["finishedAt", -1];
|
||||||
|
_self set ["failureReason", ""];
|
||||||
|
_self set ["resultSnapshot", createHashMap];
|
||||||
|
_self set ["rewardData", createHashMapFromArray [
|
||||||
|
["funds", _taskParams getOrDefault ["funds", 0]],
|
||||||
|
["ratingFail", _taskParams getOrDefault ["ratingFail", 0]],
|
||||||
|
["ratingSuccess", _taskParams getOrDefault ["ratingSuccess", 0]],
|
||||||
|
["equipment", _taskParams getOrDefault ["equipment", []]],
|
||||||
|
["supplies", _taskParams getOrDefault ["supplies", []]],
|
||||||
|
["weapons", _taskParams getOrDefault ["weapons", []]],
|
||||||
|
["vehicles", _taskParams getOrDefault ["vehicles", []]],
|
||||||
|
["special", _taskParams getOrDefault ["special", []]]
|
||||||
|
]];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["#create", compileFinal {
|
||||||
|
private _taskID = "";
|
||||||
|
private _taskType = "custom";
|
||||||
|
private _entities = createHashMap;
|
||||||
|
private _taskParams = createHashMap;
|
||||||
|
|
||||||
|
if (_this isEqualType [] && { count _this > 0 }) then {
|
||||||
|
_taskID = _this param [0, "", [""]];
|
||||||
|
|
||||||
|
if ((count _this > 1) && { (_this select 1) isEqualType "" }) then {
|
||||||
|
_taskType = _this param [1, "custom", [""]];
|
||||||
|
_entities = _this param [2, createHashMap, [createHashMap]];
|
||||||
|
_taskParams = _this param [3, createHashMap, [createHashMap]];
|
||||||
|
} else {
|
||||||
|
_entities = _this param [1, createHashMap, [createHashMap]];
|
||||||
|
_taskParams = _this param [2, createHashMap, [createHashMap]];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_self call ["initializeBaseState", [_taskID, _taskType, _entities, _taskParams]];
|
||||||
|
}],
|
||||||
|
["getTaskID", compileFinal {
|
||||||
|
_self getOrDefault ["taskID", ""]
|
||||||
|
}],
|
||||||
|
["getTaskType", compileFinal {
|
||||||
|
_self getOrDefault ["taskType", ""]
|
||||||
|
}],
|
||||||
|
["getStatus", compileFinal {
|
||||||
|
_self getOrDefault ["status", "created"]
|
||||||
|
}],
|
||||||
|
["getRewardData", compileFinal {
|
||||||
|
_self getOrDefault ["rewardData", createHashMap]
|
||||||
|
}],
|
||||||
|
["markActive", compileFinal {
|
||||||
|
_self set ["status", "active"];
|
||||||
|
_self set ["startedAt", serverTime];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["markSucceeded", compileFinal {
|
||||||
|
params [["_resultSnapshot", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
_self set ["status", "succeeded"];
|
||||||
|
_self set ["finishedAt", serverTime];
|
||||||
|
_self set ["resultSnapshot", _resultSnapshot];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["markFailed", compileFinal {
|
||||||
|
params [["_reason", "", [""]], ["_resultSnapshot", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
_self set ["status", "failed"];
|
||||||
|
_self set ["finishedAt", serverTime];
|
||||||
|
_self set ["failureReason", _reason];
|
||||||
|
_self set ["resultSnapshot", _resultSnapshot];
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["cleanup", compileFinal {
|
||||||
|
false
|
||||||
|
}],
|
||||||
|
["tick", compileFinal {
|
||||||
|
createHashMap
|
||||||
|
}],
|
||||||
|
["runLoop", compileFinal {
|
||||||
|
false
|
||||||
|
}]
|
||||||
|
];
|
||||||
@ -1,7 +1,7 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Review-only prototype for object-based task instances.
|
* Review-only prototype loader for object-based task instances.
|
||||||
*
|
*
|
||||||
* This file is intentionally not referenced by XEH_PREP or runtime init.
|
* This file is intentionally not referenced by XEH_PREP or runtime init.
|
||||||
* It exists so the current procedural task flows can be compared against
|
* It exists so the current procedural task flows can be compared against
|
||||||
@ -30,261 +30,18 @@
|
|||||||
* ];
|
* ];
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma hemtt ignore_variables ["_self"]
|
call compile preprocessFileLineNumbers "\forge\forge_server\addons\task\prototypes\TaskInstanceBaseClass.sqf";
|
||||||
|
call compile preprocessFileLineNumbers "\forge\forge_server\addons\task\prototypes\EntityControllerBaseClass.sqf";
|
||||||
GVAR(TaskInstanceBaseClass) = createHashMapFromArray [
|
call compile preprocessFileLineNumbers "\forge\forge_server\addons\task\prototypes\AttackTaskBaseClass.sqf";
|
||||||
["#type", "TaskInstanceBaseClass"],
|
call compile preprocessFileLineNumbers "\forge\forge_server\addons\task\prototypes\HostageTaskBaseClass.sqf";
|
||||||
["#create", compileFinal {
|
call compile preprocessFileLineNumbers "\forge\forge_server\addons\task\prototypes\HostageEntityController.sqf";
|
||||||
params [
|
call compile preprocessFileLineNumbers "\forge\forge_server\addons\task\prototypes\DefuseTaskBaseClass.sqf";
|
||||||
["_taskID", "", [""]],
|
|
||||||
["_taskType", "", [""]],
|
|
||||||
["_entities", createHashMap, [createHashMap]],
|
|
||||||
["_taskParams", createHashMap, [createHashMap]]
|
|
||||||
];
|
|
||||||
|
|
||||||
_self set ["taskID", _taskID];
|
|
||||||
_self set ["taskType", _taskType];
|
|
||||||
_self set ["entities", _entities];
|
|
||||||
_self set ["taskParams", _taskParams];
|
|
||||||
_self set ["status", "created"];
|
|
||||||
_self set ["startedAt", -1];
|
|
||||||
_self set ["finishedAt", -1];
|
|
||||||
_self set ["failureReason", ""];
|
|
||||||
_self set ["outcomeData", createHashMap];
|
|
||||||
}],
|
|
||||||
["getTaskID", compileFinal {
|
|
||||||
_self getOrDefault ["taskID", ""]
|
|
||||||
}],
|
|
||||||
["getTaskType", compileFinal {
|
|
||||||
_self getOrDefault ["taskType", ""]
|
|
||||||
}],
|
|
||||||
["getStatus", compileFinal {
|
|
||||||
_self getOrDefault ["status", "created"]
|
|
||||||
}],
|
|
||||||
["markActive", compileFinal {
|
|
||||||
_self set ["status", "active"];
|
|
||||||
_self set ["startedAt", serverTime];
|
|
||||||
true
|
|
||||||
}],
|
|
||||||
["markSucceeded", compileFinal {
|
|
||||||
params [["_outcomeData", createHashMap, [createHashMap]]];
|
|
||||||
|
|
||||||
_self set ["status", "succeeded"];
|
|
||||||
_self set ["finishedAt", serverTime];
|
|
||||||
_self set ["outcomeData", _outcomeData];
|
|
||||||
true
|
|
||||||
}],
|
|
||||||
["markFailed", compileFinal {
|
|
||||||
params [["_reason", "", [""]], ["_outcomeData", createHashMap, [createHashMap]]];
|
|
||||||
|
|
||||||
_self set ["status", "failed"];
|
|
||||||
_self set ["finishedAt", serverTime];
|
|
||||||
_self set ["failureReason", _reason];
|
|
||||||
_self set ["outcomeData", _outcomeData];
|
|
||||||
true
|
|
||||||
}],
|
|
||||||
["cleanup", compileFinal {
|
|
||||||
false
|
|
||||||
}],
|
|
||||||
["tick", compileFinal {
|
|
||||||
createHashMap
|
|
||||||
}],
|
|
||||||
["runLoop", compileFinal {
|
|
||||||
false
|
|
||||||
}]
|
|
||||||
];
|
|
||||||
|
|
||||||
GVAR(HostageTaskBaseClass) = createHashMapFromArray [
|
|
||||||
["#base", GVAR(TaskInstanceBaseClass)],
|
|
||||||
["#type", "HostageTaskBaseClass"],
|
|
||||||
["#create", compileFinal {
|
|
||||||
params [
|
|
||||||
["_taskID", "", [""]],
|
|
||||||
["_entities", createHashMap, [createHashMap]],
|
|
||||||
["_taskParams", createHashMap, [createHashMap]]
|
|
||||||
];
|
|
||||||
|
|
||||||
_self set ["taskID", _taskID];
|
|
||||||
_self set ["taskType", "hostage"];
|
|
||||||
_self set ["entities", _entities];
|
|
||||||
_self set ["taskParams", _taskParams];
|
|
||||||
_self set ["status", "created"];
|
|
||||||
_self set ["startedAt", -1];
|
|
||||||
_self set ["finishedAt", -1];
|
|
||||||
_self set ["failureReason", ""];
|
|
||||||
_self set ["outcomeData", createHashMap];
|
|
||||||
|
|
||||||
private _hostages = +(_entities getOrDefault ["hostages", []]);
|
|
||||||
private _shooters = +(_entities getOrDefault ["shooters", []]);
|
|
||||||
private _requiredRescues = _taskParams getOrDefault ["limitSuccess", -1];
|
|
||||||
if (_requiredRescues < 0) then { _requiredRescues = count _hostages; };
|
|
||||||
|
|
||||||
private _maxHostageLosses = _taskParams getOrDefault ["limitFail", -1];
|
|
||||||
if (_maxHostageLosses < 0) then { _maxHostageLosses = count _hostages; };
|
|
||||||
|
|
||||||
_self set ["hostages", _hostages];
|
|
||||||
_self set ["shooters", _shooters];
|
|
||||||
_self set ["extractionZone", _taskParams getOrDefault ["extractionZone", ""]];
|
|
||||||
_self set ["timeLimit", _taskParams getOrDefault ["timeLimit", 0]];
|
|
||||||
_self set ["execution", _taskParams getOrDefault ["execution", false]];
|
|
||||||
_self set ["cbrn", _taskParams getOrDefault ["cbrn", false]];
|
|
||||||
_self set ["cbrnZone", _taskParams getOrDefault ["cbrnZone", ""]];
|
|
||||||
_self set ["requiredRescues", _requiredRescues];
|
|
||||||
_self set ["maxHostageLosses", _maxHostageLosses];
|
|
||||||
}],
|
|
||||||
["countFreedHostages", compileFinal {
|
|
||||||
private _playerGroups = allPlayers apply { group _x };
|
|
||||||
private _hostages = _self getOrDefault ["hostages", []];
|
|
||||||
|
|
||||||
{
|
|
||||||
alive _x && { ((group _x) in _playerGroups) || { !captive _x } }
|
|
||||||
} count _hostages
|
|
||||||
}],
|
|
||||||
["countHostagesInZone", compileFinal {
|
|
||||||
private _extZone = _self getOrDefault ["extractionZone", ""];
|
|
||||||
private _hostages = _self getOrDefault ["hostages", []];
|
|
||||||
|
|
||||||
if (_extZone isEqualTo "") exitWith { 0 };
|
|
||||||
{ _x inArea _extZone } count _hostages
|
|
||||||
}],
|
|
||||||
["countKilledHostages", compileFinal {
|
|
||||||
private _hostages = _self getOrDefault ["hostages", []];
|
|
||||||
{ !alive _x } count _hostages
|
|
||||||
}],
|
|
||||||
["countAliveShooters", compileFinal {
|
|
||||||
private _shooters = _self getOrDefault ["shooters", []];
|
|
||||||
{ alive _x } count _shooters
|
|
||||||
}],
|
|
||||||
["tick", compileFinal {
|
|
||||||
private _startedAt = _self getOrDefault ["startedAt", -1];
|
|
||||||
private _timeLimit = _self getOrDefault ["timeLimit", 0];
|
|
||||||
private _killed = _self call ["countKilledHostages", []];
|
|
||||||
private _freed = _self call ["countFreedHostages", []];
|
|
||||||
private _inZone = _self call ["countHostagesInZone", []];
|
|
||||||
private _shootersAlive = _self call ["countAliveShooters", []];
|
|
||||||
private _requiredRescues = _self getOrDefault ["requiredRescues", 0];
|
|
||||||
private _maxHostageLosses = _self getOrDefault ["maxHostageLosses", 0];
|
|
||||||
private _timeExpired = false;
|
|
||||||
|
|
||||||
if (_timeLimit > 0 && { _startedAt >= 0 }) then {
|
|
||||||
_timeExpired = (serverTime - _startedAt) >= _timeLimit;
|
|
||||||
};
|
|
||||||
|
|
||||||
createHashMapFromArray [
|
|
||||||
["freed", _freed],
|
|
||||||
["inZone", _inZone],
|
|
||||||
["killed", _killed],
|
|
||||||
["shootersAlive", _shootersAlive],
|
|
||||||
["requiredRescues", _requiredRescues],
|
|
||||||
["maxHostageLosses", _maxHostageLosses],
|
|
||||||
["timeExpired", _timeExpired],
|
|
||||||
["shouldFail", (_killed >= _maxHostageLosses) || { _timeExpired && { _freed < _requiredRescues } }],
|
|
||||||
["shouldSucceed", (_inZone >= _requiredRescues) && { _killed < _maxHostageLosses }]
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
["runLoop", compileFinal {
|
|
||||||
_self call ["markActive", []];
|
|
||||||
|
|
||||||
while { (_self call ["getStatus", []]) isEqualTo "active" } do {
|
|
||||||
private _snapshot = _self call ["tick", []];
|
|
||||||
|
|
||||||
if (_snapshot getOrDefault ["shouldFail", false]) exitWith {
|
|
||||||
_self call ["markFailed", ["Hostage fail conditions met.", _snapshot]];
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_snapshot getOrDefault ["shouldSucceed", false]) exitWith {
|
|
||||||
_self call ["markSucceeded", [_snapshot]];
|
|
||||||
};
|
|
||||||
|
|
||||||
sleep 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
true
|
|
||||||
}]
|
|
||||||
];
|
|
||||||
|
|
||||||
GVAR(DefuseTaskBaseClass) = createHashMapFromArray [
|
|
||||||
["#base", GVAR(TaskInstanceBaseClass)],
|
|
||||||
["#type", "DefuseTaskBaseClass"],
|
|
||||||
["#create", compileFinal {
|
|
||||||
params [
|
|
||||||
["_taskID", "", [""]],
|
|
||||||
["_entities", createHashMap, [createHashMap]],
|
|
||||||
["_taskParams", createHashMap, [createHashMap]]
|
|
||||||
];
|
|
||||||
|
|
||||||
_self set ["taskID", _taskID];
|
|
||||||
_self set ["taskType", "defuse"];
|
|
||||||
_self set ["entities", _entities];
|
|
||||||
_self set ["taskParams", _taskParams];
|
|
||||||
_self set ["status", "created"];
|
|
||||||
_self set ["startedAt", -1];
|
|
||||||
_self set ["finishedAt", -1];
|
|
||||||
_self set ["failureReason", ""];
|
|
||||||
_self set ["outcomeData", createHashMap];
|
|
||||||
|
|
||||||
private _ieds = +(_entities getOrDefault ["ieds", []]);
|
|
||||||
private _protected = +(_entities getOrDefault ["protected", []]);
|
|
||||||
private _requiredDefusals = _taskParams getOrDefault ["limitSuccess", -1];
|
|
||||||
if (_requiredDefusals < 0) then { _requiredDefusals = count _ieds; };
|
|
||||||
|
|
||||||
private _maxProtectedLosses = _taskParams getOrDefault ["limitFail", -1];
|
|
||||||
if (_maxProtectedLosses < 0) then { _maxProtectedLosses = count _protected; };
|
|
||||||
|
|
||||||
_self set ["ieds", _ieds];
|
|
||||||
_self set ["protected", _protected];
|
|
||||||
_self set ["requiredDefusals", _requiredDefusals];
|
|
||||||
_self set ["maxProtectedLosses", _maxProtectedLosses];
|
|
||||||
_self set ["iedTimer", _taskParams getOrDefault ["iedTimer", 300]];
|
|
||||||
}],
|
|
||||||
["countProtectedDestroyed", compileFinal {
|
|
||||||
private _protected = _self getOrDefault ["protected", []];
|
|
||||||
{ !alive _x } count _protected
|
|
||||||
}],
|
|
||||||
["getDefuseCount", compileFinal {
|
|
||||||
private _taskID = _self getOrDefault ["taskID", ""];
|
|
||||||
if (_taskID isEqualTo "") exitWith { 0 };
|
|
||||||
|
|
||||||
GVAR(TaskStore) call ["getDefuseCount", [_taskID]]
|
|
||||||
}],
|
|
||||||
["tick", compileFinal {
|
|
||||||
private _defusedCount = _self call ["getDefuseCount", []];
|
|
||||||
private _protectedDestroyed = _self call ["countProtectedDestroyed", []];
|
|
||||||
private _requiredDefusals = _self getOrDefault ["requiredDefusals", 0];
|
|
||||||
private _maxProtectedLosses = _self getOrDefault ["maxProtectedLosses", 0];
|
|
||||||
|
|
||||||
createHashMapFromArray [
|
|
||||||
["defusedCount", _defusedCount],
|
|
||||||
["protectedDestroyed", _protectedDestroyed],
|
|
||||||
["requiredDefusals", _requiredDefusals],
|
|
||||||
["maxProtectedLosses", _maxProtectedLosses],
|
|
||||||
["shouldFail", (_protectedDestroyed >= _maxProtectedLosses) && { _maxProtectedLosses > 0 }],
|
|
||||||
["shouldSucceed", (_defusedCount >= _requiredDefusals) && { _requiredDefusals > 0 } && { _protectedDestroyed < _maxProtectedLosses || { _maxProtectedLosses <= 0 } }]
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
["runLoop", compileFinal {
|
|
||||||
_self call ["markActive", []];
|
|
||||||
|
|
||||||
while { (_self call ["getStatus", []]) isEqualTo "active" } do {
|
|
||||||
private _snapshot = _self call ["tick", []];
|
|
||||||
|
|
||||||
if (_snapshot getOrDefault ["shouldFail", false]) exitWith {
|
|
||||||
_self call ["markFailed", ["Defuse fail conditions met.", _snapshot]];
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_snapshot getOrDefault ["shouldSucceed", false]) exitWith {
|
|
||||||
_self call ["markSucceeded", [_snapshot]];
|
|
||||||
};
|
|
||||||
|
|
||||||
sleep 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
true
|
|
||||||
}]
|
|
||||||
];
|
|
||||||
|
|
||||||
createHashMapFromArray [
|
createHashMapFromArray [
|
||||||
["TaskInstanceBaseClass", GVAR(TaskInstanceBaseClass)],
|
["TaskInstanceBaseClass", GVAR(TaskInstanceBaseClass)],
|
||||||
|
["EntityControllerBaseClass", GVAR(EntityControllerBaseClass)],
|
||||||
|
["AttackTaskBaseClass", GVAR(AttackTaskBaseClass)],
|
||||||
["HostageTaskBaseClass", GVAR(HostageTaskBaseClass)],
|
["HostageTaskBaseClass", GVAR(HostageTaskBaseClass)],
|
||||||
|
["HostageEntityController", GVAR(HostageEntityController)],
|
||||||
["DefuseTaskBaseClass", GVAR(DefuseTaskBaseClass)]
|
["DefuseTaskBaseClass", GVAR(DefuseTaskBaseClass)]
|
||||||
]
|
]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user