283 lines
11 KiB
Plaintext
283 lines
11 KiB
Plaintext
#include "..\script_component.hpp"
|
|
|
|
/*
|
|
* Author: IDSolutions
|
|
* Manages dynamic mission generators.
|
|
*
|
|
* Arguments:
|
|
* None
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*
|
|
* Example:
|
|
* [] call forge_server_task_fnc_missionManager
|
|
*
|
|
* Public: No
|
|
*/
|
|
|
|
if !(isServer) exitWith { false };
|
|
if !(isNil QGVAR(MissionManagerPFH)) exitWith { false };
|
|
|
|
if (
|
|
(GETGVAR(enableMissionSetup,false)) &&
|
|
{ !(GETGVAR(missionSetup_settingsApplied,false)) }
|
|
) exitWith {
|
|
if !(GETGVAR(MissionManagerSetupPending,false)) then {
|
|
SETMPVAR(GVAR(MissionManagerSetupPending),true);
|
|
["INFO", "Mission manager startup deferred until framework mission setup settings are applied."] call EFUNC(common,log);
|
|
|
|
[] spawn {
|
|
waitUntil {
|
|
sleep 1;
|
|
GETGVAR(missionSetup_settingsApplied,false)
|
|
};
|
|
|
|
SETMPVAR(GVAR(MissionManagerSetupPending),false);
|
|
call FUNC(missionManager);
|
|
};
|
|
};
|
|
|
|
true
|
|
};
|
|
|
|
if (isNil QGVAR(AttackMissionGeneratorBaseClass)) then { call FUNC(attackMissionGenerator); };
|
|
if (isNil QGVAR(DefendMissionGeneratorBaseClass)) then { call FUNC(defendMissionGenerator); };
|
|
if (isNil QGVAR(DefuseMissionGeneratorBaseClass)) then { call FUNC(defuseMissionGenerator); };
|
|
if (isNil QGVAR(DeliveryMissionGeneratorBaseClass)) then { call FUNC(deliveryMissionGenerator); };
|
|
if (isNil QGVAR(DestroyMissionGeneratorBaseClass)) then { call FUNC(destroyMissionGenerator); };
|
|
if (isNil QGVAR(HostageMissionGeneratorBaseClass)) then { call FUNC(hostageMissionGenerator); };
|
|
if (isNil QGVAR(KillHvtMissionGeneratorBaseClass)) then { call FUNC(hvtMissionGenerator); };
|
|
if (isNil QGVAR(CaptureHvtMissionGeneratorBaseClass)) then { call FUNC(captureHvtMissionGenerator); };
|
|
|
|
#pragma hemtt ignore_variables ["_self"]
|
|
GVAR(MissionManagerBaseClass) = compileFinal createHashMapFromArray [
|
|
["#type", "MissionManagerBaseClass"],
|
|
["#create", compileFinal {
|
|
_self set ["lastMissionGenerationAt", -1e10];
|
|
_self set ["recentLocationRegistry", []];
|
|
_self set ["activeMissionRegistry", createHashMap];
|
|
_self set ["generators", [
|
|
["attack", createHashMapObject [GVAR(AttackMissionGeneratorBaseClass)]],
|
|
["defend", createHashMapObject [GVAR(DefendMissionGeneratorBaseClass)]],
|
|
["defuse", createHashMapObject [GVAR(DefuseMissionGeneratorBaseClass)]],
|
|
["delivery", createHashMapObject [GVAR(DeliveryMissionGeneratorBaseClass)]],
|
|
["destroy", createHashMapObject [GVAR(DestroyMissionGeneratorBaseClass)]],
|
|
["hostage", createHashMapObject [GVAR(HostageMissionGeneratorBaseClass)]],
|
|
["hvtkill", createHashMapObject [GVAR(KillHvtMissionGeneratorBaseClass)]],
|
|
["hvtcapture", createHashMapObject [GVAR(CaptureHvtMissionGeneratorBaseClass)]]
|
|
]];
|
|
["INFO", format [
|
|
"Mission manager registered generator entries: %1",
|
|
(_self getOrDefault ["generators", []]) apply { _x param [0, ""] }
|
|
]] call EFUNC(common,log);
|
|
}],
|
|
["getGenerators", compileFinal {
|
|
(_self getOrDefault ["generators", []]) apply { _x param [1, createHashMap, [createHashMap]] }
|
|
}],
|
|
["getGeneratorEntries", compileFinal {
|
|
_self getOrDefault ["generators", []]
|
|
}],
|
|
["getGeneratorByType", compileFinal {
|
|
params [["_generatorType", "", [""]]];
|
|
|
|
private _result = createHashMap;
|
|
{
|
|
if ((_x param [0, "", [""]]) isEqualTo _generatorType) exitWith {
|
|
_result = _x param [1, createHashMap, [createHashMap]];
|
|
};
|
|
} forEach (_self call ["getGeneratorEntries", []]);
|
|
|
|
_result
|
|
}],
|
|
["getGeneratedTaskTypes", compileFinal {
|
|
private _labels = createHashMapFromArray [
|
|
["attack", "Attack"],
|
|
["defend", "Defend"],
|
|
["defuse", "Defuse"],
|
|
["delivery", "Delivery"],
|
|
["destroy", "Destroy"],
|
|
["hostage", "Hostage"],
|
|
["hvtkill", "Kill HVT"],
|
|
["hvtcapture", "Capture HVT"]
|
|
];
|
|
|
|
(_self call ["getGeneratorEntries", []]) apply {
|
|
private _generatorType = _x param [0, "", [""]];
|
|
createHashMapFromArray [
|
|
["value", _generatorType],
|
|
["label", _labels getOrDefault [_generatorType, _generatorType]]
|
|
]
|
|
}
|
|
}],
|
|
["getActiveMissionIds", compileFinal {
|
|
private _activeMissionRegistry = _self getOrDefault ["activeMissionRegistry", createHashMap];
|
|
keys _activeMissionRegistry
|
|
}],
|
|
["getActiveGeneratedMissionIds", compileFinal {
|
|
private _activeCatalog = GVAR(TaskStore) call ["getActiveTaskCatalog", []];
|
|
if !(_activeCatalog isEqualType []) exitWith { [] };
|
|
|
|
private _taskIds = [];
|
|
{
|
|
if !(_x isEqualType createHashMap) then { continue; };
|
|
if ((_x getOrDefault ["source", ""]) isNotEqualTo "mission_manager") then { continue; };
|
|
|
|
private _taskID = _x getOrDefault ["taskId", _x getOrDefault ["taskID", ""]];
|
|
if (_taskID isNotEqualTo "") then {
|
|
_taskIds pushBackUnique _taskID;
|
|
};
|
|
} forEach _activeCatalog;
|
|
|
|
_taskIds
|
|
}],
|
|
["getMaxConcurrentMissions", compileFinal {
|
|
private _maxConcurrent = 1;
|
|
{
|
|
_maxConcurrent = _maxConcurrent max (_x call ["getMaxConcurrentMissions", []]);
|
|
} forEach (_self call ["getGenerators", []]);
|
|
_maxConcurrent
|
|
}],
|
|
["getMissionInterval", compileFinal {
|
|
private _interval = 300;
|
|
private _generators = _self call ["getGenerators", []];
|
|
if (_generators isEqualTo []) exitWith { _interval };
|
|
|
|
_interval = (_generators select 0) call ["getMissionInterval", []];
|
|
{
|
|
_interval = _interval min (_x call ["getMissionInterval", []]);
|
|
} forEach _generators;
|
|
_interval
|
|
}],
|
|
["cleanupCompletedMissions", compileFinal {
|
|
{
|
|
private _taskID = _x;
|
|
private _status = GVAR(TaskStore) call ["getTaskStatus", [_taskID]];
|
|
private _hasCatalogEntry = GVAR(TaskStore) call ["hasTaskCatalogEntry", [_taskID]];
|
|
private _shouldCleanup = (_status in ["succeeded", "failed"]) || { _status isEqualTo "" && { !_hasCatalogEntry } };
|
|
if (_shouldCleanup) then {
|
|
["INFO", format [
|
|
"Mission manager cleaning up generated mission %1. Status='%2', HasCatalogEntry=%3",
|
|
_taskID,
|
|
_status,
|
|
_hasCatalogEntry
|
|
]] call EFUNC(common,log);
|
|
|
|
{
|
|
if (_x call ["completeMission", [_self, _taskID]]) exitWith {};
|
|
} forEach (_self call ["getGenerators", []]);
|
|
|
|
GVAR(TaskStore) call ["clearTaskStatus", [_taskID]];
|
|
};
|
|
} forEach (_self call ["getActiveMissionIds", []]);
|
|
|
|
true
|
|
}],
|
|
["completeMission", compileFinal {
|
|
params [["_taskID", "", [""]]];
|
|
|
|
if (_taskID isEqualTo "") exitWith { false };
|
|
|
|
{
|
|
if (_x call ["completeMission", [_self, _taskID]]) exitWith { true };
|
|
} forEach (_self call ["getGenerators", []]);
|
|
|
|
false
|
|
}],
|
|
["startAvailableMissions", compileFinal {
|
|
private _activeGeneratedMissionIds = _self call ["getActiveGeneratedMissionIds", []];
|
|
private _maxConcurrentMissions = _self call ["getMaxConcurrentMissions", []];
|
|
if (count _activeGeneratedMissionIds >= _maxConcurrentMissions) exitWith {
|
|
["INFO", format [
|
|
"Mission manager skipped generation because cap was reached. ActiveGenerated=%1, Cap=%2, TaskIDs=%3",
|
|
count _activeGeneratedMissionIds,
|
|
_maxConcurrentMissions,
|
|
_activeGeneratedMissionIds
|
|
]] call EFUNC(common,log);
|
|
""
|
|
};
|
|
|
|
private _missionConfig = missionConfigFile >> "CfgMissions";
|
|
if !(isClass _missionConfig) then {
|
|
_missionConfig = configFile >> "CfgMissions";
|
|
};
|
|
private _weightsConfig = _missionConfig >> "MissionWeights";
|
|
private _weighted = [];
|
|
private _totalWeight = 0;
|
|
{
|
|
private _generatorType = _x param [0, "", [""]];
|
|
private _generator = _x param [1, createHashMap, [createHashMap]];
|
|
if (_generatorType isEqualTo "" || { _generator isEqualTo createHashMap }) then { continue; };
|
|
|
|
private _weight = getNumber (_weightsConfig >> _generatorType);
|
|
if (_weight <= 0) then { _weight = 1; };
|
|
|
|
_totalWeight = _totalWeight + _weight;
|
|
_weighted pushBack [_generatorType, _generator, _totalWeight];
|
|
} forEach (_self call ["getGeneratorEntries", []]);
|
|
|
|
if (_weighted isEqualTo [] || { _totalWeight <= 0 }) exitWith { "" };
|
|
|
|
private _roll = random _totalWeight;
|
|
private _selected = _weighted select 0;
|
|
{
|
|
if (_roll <= (_x param [2, 0, [0]])) exitWith {
|
|
_selected = _x;
|
|
};
|
|
} forEach _weighted;
|
|
|
|
private _generatorType = _selected param [0, "", [""]];
|
|
private _generator = _selected param [1, createHashMap, [createHashMap]];
|
|
private _taskID = _generator call ["startMission", [_self]];
|
|
if (_taskID isEqualTo "") exitWith {
|
|
["WARNING", format ["Mission manager failed to start '%1' generated mission.", _generatorType]] call EFUNC(common,log);
|
|
""
|
|
};
|
|
|
|
_taskID
|
|
}]
|
|
];
|
|
|
|
GVAR(MissionManager) = createHashMapObject [GVAR(MissionManagerBaseClass)];
|
|
|
|
if (isNil QEGVAR(common,EventBus)) then { call EFUNC(common,eventBus); };
|
|
if (isNil QGVAR(MissionManagerTaskEventTokens)) then {
|
|
private _handleTaskCleared = {
|
|
params ["_event"];
|
|
|
|
private _taskID = _event getOrDefault ["taskID", ""];
|
|
if (_taskID isEqualTo "") exitWith {};
|
|
if (isNil QGVAR(MissionManager)) exitWith {};
|
|
|
|
if (GVAR(MissionManager) call ["completeMission", [_taskID]]) then {
|
|
["INFO", format ["Mission manager completed generated mission from event. TaskID=%1", _taskID]] call EFUNC(common,log);
|
|
};
|
|
};
|
|
|
|
GVAR(MissionManagerTaskEventTokens) = [
|
|
EGVAR(common,EventBus) call ["on", ["task.cleared", _handleTaskCleared, "task.missionManager.cleanup"]]
|
|
];
|
|
};
|
|
|
|
if (GVAR(enableGenerator)) then {
|
|
GVAR(MissionManagerPFH) = [{
|
|
if !(GVAR(enableGenerator)) exitWith {};
|
|
|
|
GVAR(MissionManager) call ["cleanupCompletedMissions", []];
|
|
|
|
private _now = diag_tickTime;
|
|
private _interval = GVAR(MissionManager) call ["getMissionInterval", []];
|
|
private _lastMissionGenerationAt = GVAR(MissionManager) getOrDefault ["lastMissionGenerationAt", -1e10];
|
|
if ((_now - _lastMissionGenerationAt) < _interval) exitWith {};
|
|
|
|
GVAR(MissionManager) set ["lastMissionGenerationAt", _now];
|
|
|
|
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);
|
|
};
|
|
|
|
true
|