Add review-only task prototype classes

- Add defend, delivery, destroy, and HVT prototype task flows
- Add supporting entity controller prototypes and init settings
- Gate mission manager PFH behind `enableGenerator`
This commit is contained in:
Jacob Schmidt 2026-05-02 21:54:23 -05:00
parent c3582460f9
commit 53a2bb4280
24 changed files with 1420 additions and 15 deletions

View File

@ -48,9 +48,10 @@ A review-only prototype for object-based task instances lives under
- `forge_server_task_fnc_initPrototypes`
- `prototypes/README.md`
The prototype sketches `TaskInstanceBaseClass`, `HostageTaskBaseClass`, and
`DefuseTaskBaseClass` using `createHashMapObject` so the team can review a
stateful per-task design without replacing the current procedural task flows.
The prototype sketches task classes for attack, defuse, defend, delivery,
destroy, hostage, and HVT flows using `createHashMapObject` so the team can
review a stateful per-task design without replacing the current procedural task
flows.
### Reward Handling
`fnc_handleTaskRewards.sqf` applies org-owned rewards:

View File

@ -43,4 +43,15 @@ PREP_SUBDIR(prototypes,EntityControllerBaseClass);
PREP_SUBDIR(prototypes,AttackTaskBaseClass);
PREP_SUBDIR(prototypes,HostageTaskBaseClass);
PREP_SUBDIR(prototypes,HostageEntityController);
PREP_SUBDIR(prototypes,TargetEntityController);
PREP_SUBDIR(prototypes,ShooterEntityController);
PREP_SUBDIR(prototypes,HVTEntityController);
PREP_SUBDIR(prototypes,CargoEntityController);
PREP_SUBDIR(prototypes,ProtectedEntityController);
PREP_SUBDIR(prototypes,IEDEntityController);
PREP_SUBDIR(prototypes,DefenseEnemyController);
PREP_SUBDIR(prototypes,DefuseTaskBaseClass);
PREP_SUBDIR(prototypes,DestroyTaskBaseClass);
PREP_SUBDIR(prototypes,DeliveryTaskBaseClass);
PREP_SUBDIR(prototypes,HVTTaskBaseClass);
PREP_SUBDIR(prototypes,DefendTaskBaseClass);

View File

@ -4,4 +4,8 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
private _category = [QUOTE(MOD_NAME), LLSTRING(displayName)];
#include "initSettings.inc.sqf"
call FUNC(initTaskStore);

View File

@ -131,13 +131,15 @@ GVAR(MissionManagerBaseClass) = compileFinal createHashMapFromArray [
];
GVAR(MissionManager) = createHashMapObject [GVAR(MissionManagerBaseClass)];
GVAR(MissionManagerPFH) = [{
GVAR(MissionManager) call ["cleanupCompletedMissions", []];
if (GVAR(enableGenerator)) then {
GVAR(MissionManagerPFH) = [{
GVAR(MissionManager) call ["cleanupCompletedMissions", []];
private _taskID = GVAR(MissionManager) call ["startAvailableMissions", []];
if (_taskID isEqualTo "") exitWith {};
private _taskID = GVAR(MissionManager) call ["startAvailableMissions", []];
if (_taskID isEqualTo "") exitWith {};
["INFO", format ["Mission manager started mission %1.", _taskID]] call EFUNC(common,log);
}, GVAR(MissionManager) call ["getMissionInterval", []], []] call CFUNC(addPerFrameHandler);
["INFO", format ["Mission manager started mission %1.", _taskID]] call EFUNC(common,log);
}, GVAR(MissionManager) call ["getMissionInterval", []], []] call CFUNC(addPerFrameHandler);
};
true

View File

@ -7,20 +7,42 @@ loaded for review with `[] call forge_server_task_fnc_initPrototypes;`.
Current prototypes:
- `TaskInstanceBaseClass`
- `EntityControllerBaseClass`
- `TargetEntityController`
- `ShooterEntityController`
- `AttackTaskBaseClass`
- `HostageTaskBaseClass`
- `HostageEntityController`
- `HVTEntityController`
- `CargoEntityController`
- `ProtectedEntityController`
- `IEDEntityController`
- `DefenseEnemyController`
- `DefuseTaskBaseClass`
- `DestroyTaskBaseClass`
- `DeliveryTaskBaseClass`
- `HVTTaskBaseClass`
- `DefendTaskBaseClass`
Review entry points:
- [taskObjectPrototypes.sqf](./taskObjectPrototypes.sqf)
- [fnc_initPrototypes.sqf](../functions/prototypes/fnc_initPrototypes.sqf)
- [fnc_TaskInstanceBaseClass.sqf](../functions/prototypes/fnc_TaskInstanceBaseClass.sqf)
- [fnc_EntityControllerBaseClass.sqf](../functions/prototypes/fnc_EntityControllerBaseClass.sqf)
- [fnc_TargetEntityController.sqf](../functions/prototypes/fnc_TargetEntityController.sqf)
- [fnc_ShooterEntityController.sqf](../functions/prototypes/fnc_ShooterEntityController.sqf)
- [fnc_AttackTaskBaseClass.sqf](../functions/prototypes/fnc_AttackTaskBaseClass.sqf)
- [fnc_HostageTaskBaseClass.sqf](../functions/prototypes/fnc_HostageTaskBaseClass.sqf)
- [fnc_HostageEntityController.sqf](../functions/prototypes/fnc_HostageEntityController.sqf)
- [fnc_HVTEntityController.sqf](../functions/prototypes/fnc_HVTEntityController.sqf)
- [fnc_CargoEntityController.sqf](../functions/prototypes/fnc_CargoEntityController.sqf)
- [fnc_ProtectedEntityController.sqf](../functions/prototypes/fnc_ProtectedEntityController.sqf)
- [fnc_IEDEntityController.sqf](../functions/prototypes/fnc_IEDEntityController.sqf)
- [fnc_DefenseEnemyController.sqf](../functions/prototypes/fnc_DefenseEnemyController.sqf)
- [fnc_DefuseTaskBaseClass.sqf](../functions/prototypes/fnc_DefuseTaskBaseClass.sqf)
- [fnc_DestroyTaskBaseClass.sqf](../functions/prototypes/fnc_DestroyTaskBaseClass.sqf)
- [fnc_DeliveryTaskBaseClass.sqf](../functions/prototypes/fnc_DeliveryTaskBaseClass.sqf)
- [fnc_HVTTaskBaseClass.sqf](../functions/prototypes/fnc_HVTTaskBaseClass.sqf)
- [fnc_DefendTaskBaseClass.sqf](../functions/prototypes/fnc_DefendTaskBaseClass.sqf)
Purpose:
- show what per-task instance objects could look like

View File

@ -158,7 +158,7 @@ GVAR(AttackTaskBaseClass) = createHashMapFromArray [
GVAR(TaskStore) call ["clearTask", [_taskID]];
};
if (_endFail) then { ["MissionFail", false] remoteExec ["BIS_fnc_endMission", playerSide]; };
if (_endFail) then { ["MissionFail", false] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
} else {
{ deleteVehicle _x } forEach _targets;
@ -174,7 +174,7 @@ GVAR(AttackTaskBaseClass) = createHashMapFromArray [
GVAR(TaskStore) call ["clearTask", [_taskID]];
};
if (_endSuccess) then { ["MissionSuccess", true] remoteExec ["BIS_fnc_endMission", playerSide]; };
if (_endSuccess) then { ["MissionSuccess", true] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
};
_self call ["cleanup", []];

View File

@ -0,0 +1,80 @@
#include "..\script_component.hpp"
/*
* Review-only prototype delivery cargo entity controller.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(CargoEntityController) = createHashMapFromArray [
["#base", GVAR(EntityControllerBaseClass)],
["#type", "CargoEntityController"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entity", objNull, [objNull]],
["_controllerParams", createHashMap, [createHashMap]]
];
_self call ["initializeControllerState", [_taskID, _entity, "cargo", _controllerParams]];
_self set ["damageThreshold", _controllerParams getOrDefault ["damageThreshold", 0.7]];
_self set ["damageEventId", -1];
_self call ["registerInstance", []];
}],
["#delete", compileFinal {
_self call ["cleanup", []];
}],
["installDamageWarningHandler", compileFinal {
private _entity = _self getOrDefault ["entity", objNull];
if (isNull _entity) exitWith { false };
private _threshold = _self getOrDefault ["damageThreshold", 0.7];
_entity setVariable [QGVAR(cargoDamageThreshold), _threshold];
private _eventId = _entity addEventHandler ["Dammaged", {
params ["_unit"];
private _threshold = _unit getVariable [QGVAR(cargoDamageThreshold), 0.7];
if (damage _unit < _threshold) exitWith {};
private _taskID = _unit getVariable ["assignedTask", _unit getVariable [QGVAR(assignedTask), ""]];
if (_taskID isEqualTo "") exitWith {};
if (_unit getVariable [QGVAR(cargoDamageWarned), false]) exitWith {};
_unit setVariable [QGVAR(cargoDamageWarned), true];
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "warning", "Tasks", format ["Cargo for task %1 has been severely damaged.", _taskID]]];
}];
_self set ["damageEventId", _eventId];
true
}],
["cleanup", compileFinal {
private _entity = _self getOrDefault ["entity", objNull];
private _eventId = _self getOrDefault ["damageEventId", -1];
if (!isNull _entity && { _eventId >= 0 }) then {
_entity removeEventHandler ["Dammaged", _eventId];
};
_self call ["unregisterInstance", []]
}],
["runLoop", compileFinal {
if !(_self call ["registerTaskEntity", ["cargo"]]) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
_self call ["installDamageWarningHandler", []];
_self call ["markActive", []];
waitUntil {
sleep 1;
private _entity = _self getOrDefault ["entity", objNull];
isNull _entity || { !alive _entity } || { damage _entity >= (_self getOrDefault ["damageThreshold", 0.7]) }
};
_self call ["markFinished", []];
_self call ["cleanup", []];
true
}]
];

View File

@ -0,0 +1,214 @@
#include "..\script_component.hpp"
/*
* Review-only prototype defend task class.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(DefendTaskBaseClass) = createHashMapFromArray [
["#base", GVAR(TaskInstanceBaseClass)],
["#type", "DefendTaskBaseClass"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entities", createHashMap, [createHashMap]],
["_taskParams", createHashMap, [createHashMap]]
];
_self call ["initializeBaseState", [_taskID, "defend", _entities, _taskParams]];
_self set ["defenseZone", _taskParams getOrDefault ["defenseZone", ""]];
_self set ["defendTime", _taskParams getOrDefault ["defendTime", 600]];
_self set ["waveCount", _taskParams getOrDefault ["waveCount", 3]];
_self set ["waveCooldown", _taskParams getOrDefault ["waveCooldown", 300]];
_self set ["minBlufor", _taskParams getOrDefault ["minBlufor", 1]];
_self set ["nextWaveTime", -1];
_self set ["currentWave", 0];
_self set ["zoneEmptyCounter", 0];
_self set ["warningIssued", false];
_self set ["useTaskStore", _taskParams getOrDefault ["useTaskStore", false]];
_self call ["registerInstance", []];
}],
["#delete", compileFinal {
_self call ["unregisterInstance", []];
}],
["isValidDefenseZone", compileFinal {
private _defenseZone = _self getOrDefault ["defenseZone", ""];
_defenseZone isNotEqualTo "" && { markerShape _defenseZone in ["RECTANGLE", "ELLIPSE"] }
}],
["trackParticipants", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { false };
GVAR(TaskStore) call ["trackParticipants", [_taskID, [], _self getOrDefault ["defenseZone", ""], 0]];
true
}],
["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
}],
["countBluforInZone", compileFinal {
private _defenseZone = _self getOrDefault ["defenseZone", ""];
if (_defenseZone isEqualTo "") exitWith { 0 };
count (allUnits select { _x isKindOf "CAManBase" && { side _x == west } && { alive _x }} inAreaArray _defenseZone)
}],
["waitForDefenseStart", compileFinal {
private _minBlufor = _self getOrDefault ["minBlufor", 1];
waitUntil {
sleep 1;
_self call ["trackParticipants", []];
private _ready = (_self call ["countBluforInZone", []]) >= _minBlufor;
if (_ready) then {
_self call ["markActive", []];
_self set ["nextWaveTime", serverTime];
if (_self getOrDefault ["useTaskStore", false]) then {
GVAR(TaskStore) call ["notifyParticipants", [_self getOrDefault ["taskID", ""], "info", "Tasks", "Defense has started. Hold the zone."]];
};
};
_ready
};
true
}],
["tick", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _defenseZone = _self getOrDefault ["defenseZone", ""];
private _defendTime = _self getOrDefault ["defendTime", 600];
private _waveCount = _self getOrDefault ["waveCount", 3];
private _waveCooldown = _self getOrDefault ["waveCooldown", 300];
private _minBlufor = _self getOrDefault ["minBlufor", 1];
private _currentWave = _self getOrDefault ["currentWave", 0];
private _nextWaveTime = _self getOrDefault ["nextWaveTime", -1];
private _zoneEmptyCounter = _self getOrDefault ["zoneEmptyCounter", 0];
private _warningIssued = _self getOrDefault ["warningIssued", false];
private _bluforInZone = _self call ["countBluforInZone", []];
private _elapsed = serverTime - (_self getOrDefault ["startedAt", serverTime]);
if (_bluforInZone < _minBlufor) then {
_zoneEmptyCounter = _zoneEmptyCounter + 1;
if (_zoneEmptyCounter == 15 && { !_warningIssued } && { _self getOrDefault ["useTaskStore", false] }) then {
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "warning", "Tasks", "Defense zone is empty. Return immediately."]];
_warningIssued = true;
};
} else {
_zoneEmptyCounter = 0;
_warningIssued = false;
};
if (_currentWave < _waveCount && { serverTime >= _nextWaveTime }) then {
[_defenseZone, _taskID, _currentWave] call FUNC(spawnEnemyWave);
_currentWave = _currentWave + 1;
_nextWaveTime = serverTime + _waveCooldown;
if (_self getOrDefault ["useTaskStore", false]) then {
GVAR(TaskStore) call ["notifyParticipants", [_taskID, "info", "Tasks", format ["Enemy forces approaching. Wave %1 of %2.", _currentWave, _waveCount]]];
};
};
_self set ["currentWave", _currentWave];
_self set ["nextWaveTime", _nextWaveTime];
_self set ["zoneEmptyCounter", _zoneEmptyCounter];
_self set ["warningIssued", _warningIssued];
createHashMapFromArray [
["bluforInZone", _bluforInZone],
["elapsed", _elapsed],
["currentWave", _currentWave],
["waveCount", _waveCount],
["zoneEmptyCounter", _zoneEmptyCounter],
["shouldFail", _zoneEmptyCounter >= 30],
["shouldSucceed", (_bluforInZone >= _minBlufor) && { _elapsed >= _defendTime } && { _currentWave >= _waveCount }]
]
}],
["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 ["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 _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, _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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["runLoop", compileFinal {
if !(_self call ["isValidDefenseZone", []]) exitWith {
_self call ["markFailed", ["Invalid defense zone.", createHashMap]];
_self call ["cleanup", []];
false
};
_self call ["waitForAssignment", []];
_self call ["waitForDefenseStart", []];
while { (_self call ["getStatus", []]) isEqualTo "active" } do {
_self call ["trackParticipants", []];
private _snapshot = _self call ["tick", []];
if (_snapshot getOrDefault ["shouldFail", false]) exitWith {
_self call ["markFailed", ["Defend 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", []];
};
_self call ["cleanup", []];
true
}]
];

View File

@ -0,0 +1,52 @@
#include "..\script_component.hpp"
/*
* Review-only prototype defense enemy controller.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(DefenseEnemyController) = createHashMapFromArray [
["#base", GVAR(EntityControllerBaseClass)],
["#type", "DefenseEnemyController"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entity", objNull, [objNull]],
["_controllerParams", createHashMap, [createHashMap]]
];
_self call ["initializeControllerState", [_taskID, _entity, "defense_enemy", _controllerParams]];
_self set ["defenseZone", _controllerParams getOrDefault ["defenseZone", ""]];
_self call ["registerInstance", []];
}],
["#delete", compileFinal {
_self call ["unregisterInstance", []];
}],
["applyInitialState", compileFinal {
private _entity = _self getOrDefault ["entity", objNull];
if (isNull _entity || { !alive _entity }) exitWith { false };
_self call ["assignTaskVariable", []];
_entity setBehaviour "AWARE";
_entity setSpeedMode "NORMAL";
_entity enableDynamicSimulation true;
true
}],
["runLoop", compileFinal {
if !(_self call ["applyInitialState", []]) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
_self call ["markActive", []];
waitUntil {
sleep 1;
!(_self call ["isEntityUsable", []])
};
_self call ["markFinished", []];
_self call ["cleanup", []];
true
}]
];

View File

@ -103,6 +103,58 @@ GVAR(DefuseTaskBaseClass) = createHashMapFromArray [
["shouldSucceed", (_defusedCount >= _requiredDefusals) && { _requiredDefusals > 0 } && { _protectedDestroyed < _maxProtectedLosses || { _maxProtectedLosses <= 0 } }]
]
}],
["handleFailureOutcome", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _ieds = _self getOrDefault ["ieds", []];
private _protected = _self getOrDefault ["protected", []];
private _rewardData = _self getOrDefault ["rewardData", createHashMap];
private _ratingFail = _rewardData getOrDefault ["ratingFail", 0];
private _endFail = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endFail", false];
{ deleteVehicle _x } forEach _ieds;
{ deleteVehicle _x } forEach _protected;
if (_self getOrDefault ["useTaskStore", false]) then {
[_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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["handleSuccessOutcome", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _ieds = _self getOrDefault ["ieds", []];
private _protected = _self getOrDefault ["protected", []];
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 _ieds;
{ deleteVehicle _x } forEach _protected;
if (_self getOrDefault ["useTaskStore", false]) then {
[_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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["runLoop", compileFinal {
_self call ["markActive", []];
@ -120,6 +172,12 @@ GVAR(DefuseTaskBaseClass) = createHashMapFromArray [
sleep 1;
};
if ((_self call ["getStatus", []]) isEqualTo "failed") then {
_self call ["handleFailureOutcome", []];
} else {
_self call ["handleSuccessOutcome", []];
};
_self call ["cleanup", []];
true
}]

View File

@ -0,0 +1,205 @@
#include "..\script_component.hpp"
/*
* Review-only prototype delivery task class.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(DeliveryTaskBaseClass) = createHashMapFromArray [
["#base", GVAR(TaskInstanceBaseClass)],
["#type", "DeliveryTaskBaseClass"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entities", createHashMap, [createHashMap]],
["_taskParams", createHashMap, [createHashMap]]
];
_self call ["initializeBaseState", [_taskID, "delivery", _entities, _taskParams]];
private _cargo = +(_entities getOrDefault ["cargo", []]);
private _requiredDelivered = _taskParams getOrDefault ["limitSuccess", -1];
if (_requiredDelivered < 0) then { _requiredDelivered = count _cargo; };
private _maxDamaged = _taskParams getOrDefault ["limitFail", -1];
if (_maxDamaged < 0) then { _maxDamaged = count _cargo; };
_self set ["cargo", _cargo];
_self set ["deliveryZone", _taskParams getOrDefault ["deliveryZone", ""]];
_self set ["requiredDelivered", _requiredDelivered];
_self set ["maxDamaged", _maxDamaged];
_self set ["timeLimit", _taskParams getOrDefault ["timeLimit", 0]];
_self set ["useTaskStore", _taskParams getOrDefault ["useTaskStore", false]];
_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 _cargo = GVAR(TaskStore) call ["getTaskEntities", ["cargo", _taskID]];
_self set ["cargo", _cargo];
true
}],
["trackParticipants", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { false };
GVAR(TaskStore) call ["trackParticipants", [_taskID, _self getOrDefault ["cargo", []], _self getOrDefault ["deliveryZone", ""], 125]];
true
}],
["waitForRequiredEntities", compileFinal {
if (_self getOrDefault ["useTaskStore", false]) then {
waitUntil {
sleep 1;
_self call ["refreshEntitiesFromStore", []];
_self call ["trackParticipants", []];
count (_self getOrDefault ["cargo", []]) > 0
};
} else {
waitUntil {
sleep 1;
count (_self getOrDefault ["cargo", []]) > 0
};
};
private _cargo = _self getOrDefault ["cargo", []];
private _taskParams = _self getOrDefault ["taskParams", createHashMap];
private _requiredDelivered = _taskParams getOrDefault ["limitSuccess", -1];
if (_requiredDelivered < 0) then { _requiredDelivered = count _cargo; };
private _maxDamaged = _taskParams getOrDefault ["limitFail", -1];
if (_maxDamaged < 0) then { _maxDamaged = count _cargo; };
_self set ["requiredDelivered", _requiredDelivered];
_self set ["maxDamaged", _maxDamaged];
true
}],
["waitForAssignmentIfTimed", compileFinal {
private _timeLimit = _self getOrDefault ["timeLimit", 0];
private _taskID = _self getOrDefault ["taskID", ""];
if (_timeLimit <= 0 || { _taskID isEqualTo "" } || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { true };
waitUntil {
sleep 1;
GVAR(TaskStore) call ["isTaskAccepted", [_taskID]]
};
true
}],
["countDeliveredCargo", compileFinal {
private _deliveryZone = _self getOrDefault ["deliveryZone", ""];
private _cargo = _self getOrDefault ["cargo", []];
if (_deliveryZone isEqualTo "") exitWith { 0 };
{ _x inArea _deliveryZone && { damage _x < 0.7 } } count _cargo
}],
["countDamagedCargo", compileFinal {
private _cargo = _self getOrDefault ["cargo", []];
{ damage _x >= 0.7 } count _cargo
}],
["tick", compileFinal {
private _startedAt = _self getOrDefault ["startedAt", -1];
private _timeLimit = _self getOrDefault ["timeLimit", 0];
private _delivered = _self call ["countDeliveredCargo", []];
private _damaged = _self call ["countDamagedCargo", []];
private _requiredDelivered = _self getOrDefault ["requiredDelivered", 0];
private _maxDamaged = _self getOrDefault ["maxDamaged", 0];
private _timeExpired = false;
if (_timeLimit > 0 && { _startedAt >= 0 }) then {
_timeExpired = (serverTime - _startedAt) >= _timeLimit;
};
createHashMapFromArray [
["delivered", _delivered],
["damaged", _damaged],
["requiredDelivered", _requiredDelivered],
["maxDamaged", _maxDamaged],
["timeExpired", _timeExpired],
["shouldFail", (_damaged >= _maxDamaged) || { _timeExpired && { _delivered < _requiredDelivered } }],
["shouldSucceed", (_delivered >= _requiredDelivered) && { _damaged < _maxDamaged }]
]
}],
["handleFailureOutcome", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _cargo = _self getOrDefault ["cargo", []];
private _rewardData = _self getOrDefault ["rewardData", createHashMap];
private _ratingFail = _rewardData getOrDefault ["ratingFail", 0];
private _endFail = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endFail", false];
{ deleteVehicle _x } forEach _cargo;
if (_self getOrDefault ["useTaskStore", false]) then {
[_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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["handleSuccessOutcome", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _cargo = _self getOrDefault ["cargo", []];
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 _cargo;
if (_self getOrDefault ["useTaskStore", false]) then {
[_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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["runLoop", compileFinal {
_self call ["waitForRequiredEntities", []];
_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", ["Delivery 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", []];
};
_self call ["cleanup", []];
true
}]
];

View File

@ -0,0 +1,185 @@
#include "..\script_component.hpp"
/*
* Review-only prototype destroy task class.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(DestroyTaskBaseClass) = createHashMapFromArray [
["#base", GVAR(TaskInstanceBaseClass)],
["#type", "DestroyTaskBaseClass"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entities", createHashMap, [createHashMap]],
["_taskParams", createHashMap, [createHashMap]]
];
_self call ["initializeBaseState", [_taskID, "destroy", _entities, _taskParams]];
private _targets = +(_entities getOrDefault ["targets", []]);
private _requiredDestroyed = _taskParams getOrDefault ["limitSuccess", -1];
if (_requiredDestroyed < 0) then { _requiredDestroyed = count _targets; };
_self set ["targets", _targets];
_self set ["requiredDestroyed", _requiredDestroyed];
_self set ["timeLimit", _taskParams getOrDefault ["timeLimit", 0]];
_self set ["useTaskStore", _taskParams getOrDefault ["useTaskStore", false]];
_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 _targets = GVAR(TaskStore) call ["getTaskEntities", ["targets", _taskID]];
_self set ["targets", _targets];
true
}],
["trackParticipants", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { false };
GVAR(TaskStore) call ["trackParticipants", [_taskID, _self getOrDefault ["targets", []], "", 300]];
true
}],
["waitForRequiredEntities", compileFinal {
if (_self getOrDefault ["useTaskStore", false]) then {
waitUntil {
sleep 1;
_self call ["refreshEntitiesFromStore", []];
_self call ["trackParticipants", []];
count (_self getOrDefault ["targets", []]) > 0
};
} else {
waitUntil {
sleep 1;
count (_self getOrDefault ["targets", []]) > 0
};
};
private _targets = _self getOrDefault ["targets", []];
private _taskParams = _self getOrDefault ["taskParams", createHashMap];
private _requiredDestroyed = _taskParams getOrDefault ["limitSuccess", -1];
if (_requiredDestroyed < 0) then { _requiredDestroyed = count _targets; };
_self set ["requiredDestroyed", _requiredDestroyed];
true
}],
["waitForAssignmentIfTimed", compileFinal {
private _timeLimit = _self getOrDefault ["timeLimit", 0];
private _taskID = _self getOrDefault ["taskID", ""];
if (_timeLimit <= 0 || { _taskID isEqualTo "" } || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { true };
waitUntil {
sleep 1;
GVAR(TaskStore) call ["isTaskAccepted", [_taskID]]
};
true
}],
["countDestroyedTargets", 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 _destroyed = _self call ["countDestroyedTargets", []];
private _requiredDestroyed = _self getOrDefault ["requiredDestroyed", 0];
private _timeExpired = false;
if (_timeLimit > 0 && { _startedAt >= 0 }) then {
_timeExpired = (serverTime - _startedAt) >= _timeLimit;
};
createHashMapFromArray [
["destroyed", _destroyed],
["requiredDestroyed", _requiredDestroyed],
["timeExpired", _timeExpired],
["shouldFail", _timeExpired && { _destroyed < _requiredDestroyed }],
["shouldSucceed", _destroyed >= _requiredDestroyed]
]
}],
["handleFailureOutcome", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _targets = _self getOrDefault ["targets", []];
private _rewardData = _self getOrDefault ["rewardData", createHashMap];
private _ratingFail = _rewardData getOrDefault ["ratingFail", 0];
private _endFail = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endFail", false];
{ deleteVehicle _x } forEach _targets;
if (_self getOrDefault ["useTaskStore", false]) then {
[_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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["handleSuccessOutcome", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _targets = _self getOrDefault ["targets", []];
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 _targets;
if (_self getOrDefault ["useTaskStore", false]) then {
[_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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["runLoop", compileFinal {
_self call ["waitForRequiredEntities", []];
_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", ["Destroy 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", []];
};
_self call ["cleanup", []];
true
}]
];

View File

@ -67,7 +67,39 @@ GVAR(EntityControllerBaseClass) = createHashMapFromArray [
private _entity = _self getOrDefault ["entity", objNull];
if (isNull _entity) exitWith { "" };
format ["hostage_controller_%1", netId _entity]
format ["%1_controller_%2", _self getOrDefault ["controllerType", "custom"], netId _entity]
}],
["getTaskID", compileFinal {
_self getOrDefault ["taskID", ""]
}],
["isEntityUsable", compileFinal {
private _entity = _self getOrDefault ["entity", objNull];
!isNull _entity && { alive _entity }
}],
["assignTaskVariable", compileFinal {
private _entity = _self getOrDefault ["entity", objNull];
private _taskID = _self getOrDefault ["taskID", ""];
if (isNull _entity || { _taskID isEqualTo "" }) exitWith { false };
_entity setVariable ["assignedTask", _taskID, true];
_entity setVariable [QGVAR(assignedTask), _taskID, true];
true
}],
["registerTaskEntity", compileFinal {
params [["_role", "", [""]]];
private _taskID = _self getOrDefault ["taskID", ""];
private _entity = _self getOrDefault ["entity", objNull];
private _useTaskStore = (_self getOrDefault ["controllerParams", createHashMap]) getOrDefault ["useTaskStore", true];
if (_role isEqualTo "" || { _taskID isEqualTo "" } || { isNull _entity }) exitWith { false };
_self call ["assignTaskVariable", []];
if (_useTaskStore) then {
GVAR(TaskStore) call ["registerTaskEntity", [_role, _taskID, _entity]];
};
true
}],
["registerInstance", compileFinal {
private _registryKey = _self call ["getRegistryKey", []];
@ -75,6 +107,7 @@ GVAR(EntityControllerBaseClass) = createHashMapFromArray [
private _registry = missionNamespace getVariable [QGVAR(PrototypeControllerInstances), createHashMap];
_registry set [_registryKey, _self];
missionNamespace setVariable [QGVAR(PrototypeControllerInstances), _registry];
missionNamespace setVariable [_registryKey, _self];
true
}],

View File

@ -0,0 +1,72 @@
#include "..\script_component.hpp"
/*
* Review-only prototype HVT entity controller.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(HVTEntityController) = createHashMapFromArray [
["#base", GVAR(EntityControllerBaseClass)],
["#type", "HVTEntityController"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entity", objNull, [objNull]],
["_controllerParams", createHashMap, [createHashMap]]
];
_self call ["initializeControllerState", [_taskID, _entity, "hvt", _controllerParams]];
_self set ["captureRadius", _controllerParams getOrDefault ["captureRadius", 2]];
_self call ["registerInstance", []];
}],
["#delete", compileFinal {
_self call ["unregisterInstance", []];
}],
["findNearbyCapturer", compileFinal {
private _entity = _self getOrDefault ["entity", objNull];
if (isNull _entity || { !alive _entity }) exitWith { objNull };
private _radius = _self getOrDefault ["captureRadius", 2];
private _nearPlayers = allPlayers inAreaArray [ASLToAGL getPosASL _entity, _radius, _radius, 0, false, 2];
if (_nearPlayers isEqualTo []) exitWith { objNull };
_nearPlayers select 0
}],
["transitionToCaptured", compileFinal {
private _entity = _self getOrDefault ["entity", objNull];
if (isNull _entity || { !alive _entity }) exitWith { false };
_entity setCaptive true;
doStop _entity;
true
}],
["runLoop", compileFinal {
if !(_self call ["registerTaskEntity", ["hvts"]]) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
_self call ["markActive", []];
private _capturer = objNull;
waitUntil {
sleep 1;
if !(_self call ["isEntityUsable", []]) exitWith { true };
_capturer = _self call ["findNearbyCapturer", []];
!isNull _capturer
};
if !(_self call ["isEntityUsable", []]) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
_self call ["transitionToCaptured", []];
_self call ["markFinished", []];
_self call ["cleanup", []];
true
}]
];

View File

@ -0,0 +1,212 @@
#include "..\script_component.hpp"
/*
* Review-only prototype HVT task class.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(HVTTaskBaseClass) = createHashMapFromArray [
["#base", GVAR(TaskInstanceBaseClass)],
["#type", "HVTTaskBaseClass"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entities", createHashMap, [createHashMap]],
["_taskParams", createHashMap, [createHashMap]]
];
_self call ["initializeBaseState", [_taskID, "hvt", _entities, _taskParams]];
private _hvts = +(_entities getOrDefault ["hvts", []]);
private _required = _taskParams getOrDefault ["limitSuccess", -1];
if (_required < 0) then { _required = count _hvts; };
private _maxKilled = _taskParams getOrDefault ["limitFail", -1];
if (_maxKilled < 0) then { _maxKilled = count _hvts; };
private _type = _taskParams getOrDefault ["type", []];
private _captureHvt = _taskParams getOrDefault ["captureHvt", true];
private _capture = _captureHvt;
private _eliminate = !_captureHvt;
if (_type isEqualType [] && { count _type >= 2 }) then {
_capture = _type param [0, true, [false]];
_eliminate = _type param [1, false, [false]];
};
_self set ["hvts", _hvts];
_self set ["extractionZone", _taskParams getOrDefault ["extractionZone", ""]];
_self set ["required", _required];
_self set ["maxKilled", _maxKilled];
_self set ["capture", _capture];
_self set ["eliminate", _eliminate];
_self set ["timeLimit", _taskParams getOrDefault ["timeLimit", 0]];
_self set ["useTaskStore", _taskParams getOrDefault ["useTaskStore", false]];
_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 _hvts = GVAR(TaskStore) call ["getTaskEntities", ["hvts", _taskID]];
_self set ["hvts", _hvts];
true
}],
["trackParticipants", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
if (_taskID isEqualTo "" || { !(_self getOrDefault ["useTaskStore", false]) }) exitWith { false };
GVAR(TaskStore) call ["trackParticipants", [_taskID, _self getOrDefault ["hvts", []], _self getOrDefault ["extractionZone", ""], 250]];
true
}],
["waitForRequiredEntities", compileFinal {
if (_self getOrDefault ["useTaskStore", false]) then {
waitUntil {
sleep 1;
_self call ["refreshEntitiesFromStore", []];
_self call ["trackParticipants", []];
count (_self getOrDefault ["hvts", []]) > 0
};
} else {
waitUntil {
sleep 1;
count (_self getOrDefault ["hvts", []]) > 0
};
};
private _hvts = _self getOrDefault ["hvts", []];
private _taskParams = _self getOrDefault ["taskParams", createHashMap];
private _required = _taskParams getOrDefault ["limitSuccess", -1];
if (_required < 0) then { _required = count _hvts; };
private _maxKilled = _taskParams getOrDefault ["limitFail", -1];
if (_maxKilled < 0) then { _maxKilled = count _hvts; };
_self set ["required", _required];
_self set ["maxKilled", _maxKilled];
true
}],
["waitForAssignmentIfTimed", compileFinal {
private _timeLimit = _self getOrDefault ["timeLimit", 0];
private _taskID = _self getOrDefault ["taskID", ""];
if (_timeLimit <= 0 || { _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 _hvts = _self getOrDefault ["hvts", []];
private _extZone = _self getOrDefault ["extractionZone", ""];
private _capture = _self getOrDefault ["capture", true];
private _eliminate = _self getOrDefault ["eliminate", false];
private _required = _self getOrDefault ["required", 0];
private _maxKilled = _self getOrDefault ["maxKilled", 0];
private _captives = { captive _x } count _hvts;
private _killed = { !alive _x } count _hvts;
private _inZone = if (_extZone isEqualTo "") then { 0 } else { { _x inArea _extZone } count _hvts };
private _timeExpired = false;
if (_timeLimit > 0 && { _startedAt >= 0 }) then {
_timeExpired = (serverTime - _startedAt) >= _timeLimit;
};
createHashMapFromArray [
["captives", _captives],
["killed", _killed],
["inZone", _inZone],
["required", _required],
["maxKilled", _maxKilled],
["timeExpired", _timeExpired],
["shouldFail", (_capture && { _killed >= _maxKilled }) || { _timeExpired && { (_capture && { _captives < _required }) || { _eliminate && { _killed < _required } } } }],
["shouldSucceed", (_capture && { _inZone >= _required } && { _killed < _maxKilled }) || { _eliminate && { _killed >= _required } }]
]
}],
["handleFailureOutcome", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _hvts = _self getOrDefault ["hvts", []];
private _rewardData = _self getOrDefault ["rewardData", createHashMap];
private _ratingFail = _rewardData getOrDefault ["ratingFail", 0];
private _endFail = (_self getOrDefault ["taskParams", createHashMap]) getOrDefault ["endFail", false];
{ deleteVehicle _x } forEach _hvts;
if (_self getOrDefault ["useTaskStore", false]) then {
[_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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["handleSuccessOutcome", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
private _hvts = _self getOrDefault ["hvts", []];
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 _hvts;
if (_self getOrDefault ["useTaskStore", false]) then {
[_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] remoteExecCall ["BIS_fnc_endMission", playerSide]; };
true
}],
["runLoop", compileFinal {
_self call ["waitForRequiredEntities", []];
_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", ["HVT 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", []];
};
_self call ["cleanup", []];
true
}]
];

View File

@ -60,12 +60,21 @@ GVAR(HostageTaskBaseClass) = createHashMapFromArray [
private _maxHostageLosses = _taskParams getOrDefault ["limitFail", -1];
if (_maxHostageLosses < 0) then { _maxHostageLosses = count _hostages; };
private _type = _taskParams getOrDefault ["type", []];
private _cbrn = _taskParams getOrDefault ["cbrn", false];
private _execution = _taskParams getOrDefault ["execution", false];
if (_type isEqualType [] && { count _type >= 2 }) then {
_cbrn = _type param [0, false, [false]];
_execution = _type param [1, true, [false]];
};
_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 ["execution", _execution];
_self set ["cbrn", _cbrn];
_self set ["cbrnZone", _taskParams getOrDefault ["cbrnZone", ""]];
_self set ["useTaskStore", _taskParams getOrDefault ["useTaskStore", false]];
_self set ["requiredRescues", _requiredRescues];

View File

@ -0,0 +1,88 @@
#include "..\script_component.hpp"
/*
* Review-only prototype IED entity controller.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(IEDEntityController) = createHashMapFromArray [
["#base", GVAR(EntityControllerBaseClass)],
["#type", "IEDEntityController"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entity", objNull, [objNull]],
["_controllerParams", createHashMap, [createHashMap]]
];
_self call ["initializeControllerState", [_taskID, _entity, "ied", _controllerParams]];
_self set ["countdown", _controllerParams getOrDefault ["countdown", _controllerParams getOrDefault ["iedTimer", 0]]];
_self set ["waitForAcceptance", _controllerParams getOrDefault ["waitForAcceptance", true]];
_self call ["registerInstance", []];
}],
["#delete", compileFinal {
_self call ["unregisterInstance", []];
}],
["waitForAssignment", compileFinal {
private _taskID = _self getOrDefault ["taskID", ""];
if (_taskID isEqualTo "" || { !(_self getOrDefault ["waitForAcceptance", true]) }) exitWith { true };
waitUntil {
sleep 1;
GVAR(TaskStore) call ["isTaskAccepted", [_taskID]]
};
true
}],
["playCountdownSound", compileFinal {
params [["_timeRemaining", 0, [0]]];
private _entity = _self getOrDefault ["entity", objNull];
if (isNull _entity) exitWith { false };
if (_timeRemaining > 10) exitWith { _entity say3D "FORGE_timerBeep"; true };
if (_timeRemaining > 5) exitWith { _entity say3D "FORGE_timerBeepShort"; true };
_entity say3D "FORGE_timerEnd";
true
}],
["detonate", compileFinal {
private _entity = _self getOrDefault ["entity", objNull];
if (isNull _entity || { !alive _entity }) exitWith { false };
_entity setDamage 1;
true
}],
["runLoop", compileFinal {
private _countdown = _self getOrDefault ["countdown", 0];
if (_countdown <= 0) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
if !(_self call ["registerTaskEntity", ["ieds"]]) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
_self call ["waitForAssignment", []];
_self call ["markActive", []];
while { (_self call ["isEntityUsable", []]) && { _countdown > 0 } } do {
_self call ["playCountdownSound", [_countdown]];
_countdown = _countdown - 1;
_self set ["countdown", _countdown];
sleep 1;
};
if ((_self call ["isEntityUsable", []]) && { _countdown <= 0 }) then {
_self call ["detonate", []];
};
_self call ["markFinished", []];
_self call ["cleanup", []];
true
}]
];

View File

@ -0,0 +1,41 @@
#include "..\script_component.hpp"
/*
* Review-only prototype protected entity controller.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(ProtectedEntityController) = createHashMapFromArray [
["#base", GVAR(EntityControllerBaseClass)],
["#type", "ProtectedEntityController"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entity", objNull, [objNull]],
["_controllerParams", createHashMap, [createHashMap]]
];
_self call ["initializeControllerState", [_taskID, _entity, "protected", _controllerParams]];
_self call ["registerInstance", []];
}],
["#delete", compileFinal {
_self call ["unregisterInstance", []];
}],
["runLoop", compileFinal {
if !(_self call ["registerTaskEntity", ["entities"]]) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
_self call ["markActive", []];
waitUntil {
sleep 1;
!(_self call ["isEntityUsable", []])
};
_self call ["markFinished", []];
_self call ["cleanup", []];
true
}]
];

View File

@ -0,0 +1,41 @@
#include "..\script_component.hpp"
/*
* Review-only prototype shooter entity controller.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(ShooterEntityController) = createHashMapFromArray [
["#base", GVAR(EntityControllerBaseClass)],
["#type", "ShooterEntityController"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entity", objNull, [objNull]],
["_controllerParams", createHashMap, [createHashMap]]
];
_self call ["initializeControllerState", [_taskID, _entity, "shooter", _controllerParams]];
_self call ["registerInstance", []];
}],
["#delete", compileFinal {
_self call ["unregisterInstance", []];
}],
["runLoop", compileFinal {
if !(_self call ["registerTaskEntity", ["shooters"]]) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
_self call ["markActive", []];
waitUntil {
sleep 1;
!(_self call ["isEntityUsable", []])
};
_self call ["markFinished", []];
_self call ["cleanup", []];
true
}]
];

View File

@ -0,0 +1,41 @@
#include "..\script_component.hpp"
/*
* Review-only prototype target entity controller.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(TargetEntityController) = createHashMapFromArray [
["#base", GVAR(EntityControllerBaseClass)],
["#type", "TargetEntityController"],
["#create", compileFinal {
params [
["_taskID", "", [""]],
["_entity", objNull, [objNull]],
["_controllerParams", createHashMap, [createHashMap]]
];
_self call ["initializeControllerState", [_taskID, _entity, "target", _controllerParams]];
_self call ["registerInstance", []];
}],
["#delete", compileFinal {
_self call ["unregisterInstance", []];
}],
["runLoop", compileFinal {
if !(_self call ["registerTaskEntity", ["targets"]]) exitWith {
_self call ["markAborted", []];
_self call ["cleanup", []];
false
};
_self call ["markActive", []];
waitUntil {
sleep 1;
!(_self call ["isEntityUsable", []])
};
_self call ["markFinished", []];
_self call ["cleanup", []];
true
}]
];

View File

@ -95,6 +95,7 @@ GVAR(TaskInstanceBaseClass) = createHashMapFromArray [
private _registry = missionNamespace getVariable [QGVAR(PrototypeTaskInstances), createHashMap];
_registry set [_registryKey, _self];
missionNamespace setVariable [QGVAR(PrototypeTaskInstances), _registry];
missionNamespace setVariable [_registryKey, _self];
true
}],

View File

@ -30,7 +30,18 @@
[] call FUNC(AttackTaskBaseClass);
[] call FUNC(HostageTaskBaseClass);
[] call FUNC(HostageEntityController);
[] call FUNC(TargetEntityController);
[] call FUNC(ShooterEntityController);
[] call FUNC(HVTEntityController);
[] call FUNC(CargoEntityController);
[] call FUNC(ProtectedEntityController);
[] call FUNC(IEDEntityController);
[] call FUNC(DefenseEnemyController);
[] call FUNC(DefuseTaskBaseClass);
[] call FUNC(DestroyTaskBaseClass);
[] call FUNC(DeliveryTaskBaseClass);
[] call FUNC(HVTTaskBaseClass);
[] call FUNC(DefendTaskBaseClass);
createHashMapFromArray [
["TaskInstanceBaseClass", GVAR(TaskInstanceBaseClass)],
@ -38,5 +49,16 @@ createHashMapFromArray [
["AttackTaskBaseClass", GVAR(AttackTaskBaseClass)],
["HostageTaskBaseClass", GVAR(HostageTaskBaseClass)],
["HostageEntityController", GVAR(HostageEntityController)],
["DefuseTaskBaseClass", GVAR(DefuseTaskBaseClass)]
["TargetEntityController", GVAR(TargetEntityController)],
["ShooterEntityController", GVAR(ShooterEntityController)],
["HVTEntityController", GVAR(HVTEntityController)],
["CargoEntityController", GVAR(CargoEntityController)],
["ProtectedEntityController", GVAR(ProtectedEntityController)],
["IEDEntityController", GVAR(IEDEntityController)],
["DefenseEnemyController", GVAR(DefenseEnemyController)],
["DefuseTaskBaseClass", GVAR(DefuseTaskBaseClass)],
["DestroyTaskBaseClass", GVAR(DestroyTaskBaseClass)],
["DeliveryTaskBaseClass", GVAR(DeliveryTaskBaseClass)],
["HVTTaskBaseClass", GVAR(HVTTaskBaseClass)],
["DefendTaskBaseClass", GVAR(DefendTaskBaseClass)]
]

View File

@ -0,0 +1,5 @@
[
QGVAR(enableGenerator), "CHECKBOX",
[LSTRING(enableGenerator), LSTRING(enableGeneratorTooltip)],
_category, false, true
] call CBA_fnc_addSetting;

View File

@ -4,5 +4,11 @@
<Key ID="STR_forge_server_task_displayName">
<English>Task</English>
</Key>
<Key ID="STR_forge_server_task_enableGenerator">
<English>Enable Generator</English>
</Key>
<Key ID="STR_forge_server_task_enableGeneratorTooltip">
<English>Enable Task Generator</English>
</Key>
</Package>
</Project>