#include "..\script_component.hpp" /* * Object-style attack task class. * * Example: * call compile preprocessFileLineNumbers * "\forge\forge_server\addons\task\objects\TaskInstanceBaseClass.sqf"; * call compile preprocessFileLineNumbers * "\forge\forge_server\addons\task\objects\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]]; _self set ["useTaskStore", _taskParams getOrDefault ["useTaskStore", false]]; _self call ["registerInstance", []]; }], ["#delete", compileFinal { _self call ["unregisterInstance", []]; }], ["refreshTargetsFromStore", compileFinal { private _taskID = _self getOrDefault ["taskID", ""]; if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { false }; private _targets = GVAR(TaskStore) call ["getTaskEntities", ["targets", _taskID]]; _self set ["targets", _targets]; private _taskParams = _self getOrDefault ["taskParams", createHashMap]; 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 ["requiredKills", _requiredKills]; _self set ["maxTargetLosses", _maxTargetLosses]; true }], ["countKilledTargets", compileFinal { private _targets = _self getOrDefault ["targets", []]; { !alive _x } count _targets }], ["waitForAssignment", compileFinal { private _taskID = _self getOrDefault ["taskID", ""]; if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { true }; waitUntil { sleep 1; GVAR(TaskStore) call ["isTaskAccepted", [_taskID]] }; true }], ["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 _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]; private _useTaskStore = _self getOrDefault ["useTaskStore", false]; if (_useTaskStore) then { waitUntil { sleep 1; _self call ["refreshTargetsFromStore", []]; private _targets = _self getOrDefault ["targets", []]; GVAR(TaskStore) call ["trackParticipants", [_taskID, _targets, "", 300]]; count _targets > 0 }; } else { waitUntil { sleep 1; count (_self getOrDefault ["targets", []]) > 0 }; }; _self call ["waitForAssignment", []]; _self call ["markActive", []]; while { (_self call ["getStatus", []]) isEqualTo "active" } do { private _targets = _self getOrDefault ["targets", []]; if (_useTaskStore) then { _self call ["refreshTargetsFromStore", []]; _targets = _self getOrDefault ["targets", []]; GVAR(TaskStore) call ["trackParticipants", [_taskID, _targets, "", 300]]; }; private _snapshot = _self call ["tick", []]; if (_snapshot getOrDefault ["shouldFail", false]) exitWith { ["WARNING", format [ "Attack task %1 failed by timeout. TargetsKilled=%2, Required=%3, TimeLimit=%4s", _taskID, _snapshot getOrDefault ["targetsKilled", 0], _snapshot getOrDefault ["requiredKills", 0], _timeLimit ]] call EFUNC(common,log); _self call ["markFailed", ["Attack fail conditions met.", _snapshot]]; }; if (_snapshot getOrDefault ["shouldSucceed", false]) exitWith { ["INFO", format [ "Attack task %1 succeeded. TargetsRequired=%2, TargetsKilled=%3", _taskID, _snapshot getOrDefault ["requiredKills", 0], _snapshot getOrDefault ["targetsKilled", 0] ]] call EFUNC(common,log); _self call ["markSucceeded", [_snapshot]]; }; sleep 1; }; if ((_self call ["getStatus", []]) isEqualTo "failed") then { private _targets = _self getOrDefault ["targets", []]; { deleteVehicle _x } forEach _targets; if (_useTaskStore) 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); }; } else { private _targets = _self getOrDefault ["targets", []]; { deleteVehicle _x } forEach _targets; if (_useTaskStore) 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); }; }; _self call ["cleanup", []]; true }] ];