281 lines
11 KiB
Plaintext
281 lines
11 KiB
Plaintext
#include "..\script_component.hpp"
|
|
|
|
/*
|
|
* Object-style defuse task class.
|
|
*
|
|
* Example:
|
|
* call compile preprocessFileLineNumbers
|
|
* "\forge\forge_server\addons\task\objects\TaskInstanceBaseClass.sqf";
|
|
* call compile preprocessFileLineNumbers
|
|
* "\forge\forge_server\addons\task\objects\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) = +GVAR(TaskInstanceBaseClass);
|
|
GVAR(DefuseTaskBaseClass) merge [createHashMapFromArray [
|
|
["#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]];
|
|
_self set ["useTaskStore", _taskParams getOrDefault ["useTaskStore", false]];
|
|
_self set ["localDefuseCount", _taskParams getOrDefault ["localDefuseCount", 0]];
|
|
_self set ["iedControllers", []];
|
|
|
|
_self call ["registerInstance", []];
|
|
}],
|
|
["#delete", compileFinal {
|
|
_self call ["unregisterInstance", []];
|
|
}],
|
|
["refreshEntitiesFromStore", compileFinal {
|
|
private _taskID = _self getOrDefault ["taskID", ""];
|
|
if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { false };
|
|
|
|
private _ieds = GVAR(TaskStore) call ["getTaskEntities", ["ieds", _taskID]];
|
|
private _protected = GVAR(TaskStore) call ["getTaskEntities", ["entities", _taskID]];
|
|
_self set ["ieds", _ieds];
|
|
_self set ["protected", _protected];
|
|
|
|
private _taskParams = _self getOrDefault ["taskParams", createHashMap];
|
|
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 ["requiredDefusals", _requiredDefusals];
|
|
_self set ["maxProtectedLosses", _maxProtectedLosses];
|
|
true
|
|
}],
|
|
["trackParticipants", compileFinal {
|
|
private _taskID = _self getOrDefault ["taskID", ""];
|
|
if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { false };
|
|
|
|
GVAR(TaskStore) call ["trackParticipants", [_taskID, (_self getOrDefault ["ieds", []]) + (_self getOrDefault ["protected", []]), "", 250]];
|
|
true
|
|
}],
|
|
["waitForRequiredEntities", compileFinal {
|
|
if (_self getOrDefault ["useTaskStore", false]) then {
|
|
waitUntil {
|
|
sleep 1;
|
|
_self call ["refreshEntitiesFromStore", []];
|
|
!(_self call ["isTaskStoreOpen", []]) || { count (_self getOrDefault ["ieds", []]) > 0 }
|
|
};
|
|
} else {
|
|
waitUntil {
|
|
sleep 1;
|
|
count (_self getOrDefault ["ieds", []]) > 0
|
|
};
|
|
};
|
|
|
|
if !(_self call ["isTaskStoreOpen", []]) exitWith { false };
|
|
|
|
true
|
|
}],
|
|
["waitForAssignment", compileFinal {
|
|
private _taskID = _self getOrDefault ["taskID", ""];
|
|
|
|
if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { true };
|
|
|
|
waitUntil {
|
|
sleep 1;
|
|
!(_self call ["isTaskStoreOpen", []]) || { GVAR(TaskStore) call ["isTaskAccepted", [_taskID]] }
|
|
};
|
|
|
|
_self call ["isTaskStoreOpen", []]
|
|
}],
|
|
["startIedControllers", compileFinal {
|
|
if ((_self getOrDefault ["iedControllers", []]) isNotEqualTo []) exitWith { true };
|
|
|
|
private _taskID = _self getOrDefault ["taskID", ""];
|
|
private _defaultCountdown = _self getOrDefault ["iedTimer", 300];
|
|
private _controllers = [];
|
|
|
|
{
|
|
if (!isNull _x) then {
|
|
private _countdown = _x getVariable [QGVAR(iedCountdown), _defaultCountdown];
|
|
private _controller = createHashMapObject [
|
|
GVAR(IEDEntityController),
|
|
[
|
|
_taskID,
|
|
_x,
|
|
createHashMapFromArray [
|
|
["countdown", _countdown],
|
|
["waitForAcceptance", true]
|
|
]
|
|
]
|
|
];
|
|
|
|
_controllers pushBack _controller;
|
|
[_controller] spawn {
|
|
params ["_controller"];
|
|
_controller call ["runLoop", []];
|
|
};
|
|
};
|
|
} forEach (_self getOrDefault ["ieds", []]);
|
|
|
|
_self set ["iedControllers", _controllers];
|
|
true
|
|
}],
|
|
["countProtectedDestroyed", compileFinal {
|
|
private _protected = _self getOrDefault ["protected", []];
|
|
{ !alive _x } count _protected
|
|
}],
|
|
["getDefuseCount", compileFinal {
|
|
private _taskID = _self getOrDefault ["taskID", ""];
|
|
if (_taskID isEqualTo "") exitWith { 0 };
|
|
if !(_self getOrDefault ["useTaskStore", false]) exitWith {
|
|
_self getOrDefault ["localDefuseCount", 0]
|
|
};
|
|
|
|
GVAR(TaskStore) call ["getDefuseCount", [_taskID]]
|
|
}],
|
|
["incrementLocalDefuseCount", compileFinal {
|
|
private _next = (_self getOrDefault ["localDefuseCount", 0]) + 1;
|
|
_self set ["localDefuseCount", _next];
|
|
_next
|
|
}],
|
|
["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 } }]
|
|
]
|
|
}],
|
|
["handleFailureOutcome", compileFinal {
|
|
private _taskID = _self getOrDefault ["taskID", ""];
|
|
private _rewardData = _self getOrDefault ["rewardData", createHashMap];
|
|
private _ratingFail = _rewardData getOrDefault ["ratingFail", 0];
|
|
private _endFail = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endFail", false];
|
|
|
|
if (_self getOrDefault ["useTaskStore", false]) then {
|
|
[_taskID, "FAILED"] call BFUNC(taskSetState);
|
|
GVAR(TaskStore) call ["setTaskStatus", [_taskID, "failed"]];
|
|
|
|
sleep 1;
|
|
|
|
GVAR(TaskStore) call ["applyRatingOutcome", [_taskID, _ratingFail]];
|
|
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "warning", "Tasks", format ["Task failed: %1 reputation", _ratingFail]]];
|
|
GVAR(TaskStore) call ["clearTask", [_taskID]];
|
|
};
|
|
|
|
if (_endFail) then { "EveryoneLost" call BFUNC(endMissionServer); };
|
|
true
|
|
}],
|
|
["handleSuccessOutcome", compileFinal {
|
|
private _taskID = _self getOrDefault ["taskID", ""];
|
|
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];
|
|
|
|
if (_self getOrDefault ["useTaskStore", false]) then {
|
|
[_taskID, "SUCCEEDED"] call BFUNC(taskSetState);
|
|
GVAR(TaskStore) call ["setTaskStatus", [_taskID, "succeeded"]];
|
|
[_taskID, _rewardData] call FUNC(handleTaskRewards);
|
|
|
|
sleep 1;
|
|
|
|
GVAR(TaskStore) call ["applyRatingOutcome", [_taskID, _ratingSuccess]];
|
|
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "success", "Tasks", format ["Task completed: %1 reputation, $%2 funds", _ratingSuccess, [_funds] call EFUNC(common,formatNumber)]]];
|
|
GVAR(TaskStore) call ["clearTask", [_taskID]];
|
|
};
|
|
|
|
if (_endSuccess) then { "EveryoneWon" call BFUNC(endMissionServer); };
|
|
true
|
|
}],
|
|
["runLoop", compileFinal {
|
|
if !(_self call ["waitForRequiredEntities", []]) exitWith {
|
|
_self call ["markAborted", ["Task reached terminal status before required entities registered."]];
|
|
_self call ["cleanup", []];
|
|
false
|
|
};
|
|
if !(_self call ["waitForAssignment", []]) exitWith {
|
|
_self call ["markAborted", ["Task reached terminal status before assignment."]];
|
|
_self call ["cleanup", []];
|
|
false
|
|
};
|
|
_self call ["startIedControllers", []];
|
|
_self call ["markActive", []];
|
|
|
|
while { _self call ["isTaskLoopActive", []] } do {
|
|
_self call ["trackParticipants", []];
|
|
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;
|
|
};
|
|
|
|
private _finalStatus = _self call ["getStatus", []];
|
|
if (_finalStatus isEqualTo "failed") then {
|
|
_self call ["handleFailureOutcome", []];
|
|
};
|
|
|
|
if (_finalStatus isEqualTo "succeeded") then {
|
|
_self call ["handleSuccessOutcome", []];
|
|
};
|
|
|
|
_self call ["cleanup", []];
|
|
true
|
|
}]
|
|
], true];
|