Fix framework generator CAD hydration

This commit is contained in:
Jacob Schmidt 2026-05-26 22:21:15 -05:00
parent 9c2a09eed9
commit 1e2402c332
19 changed files with 130 additions and 9 deletions

View File

@ -301,13 +301,30 @@ GVAR(CadStoreBaseClass) = compileFinal createHashMapFromArray [
private _groupRepository = _self get "GroupRepository";
private _generatedTaskTypes = [];
if (missionNamespace getVariable [QEGVAR(task,enableGenerator), false]) then {
_generatedTaskTypes = [
createHashMapFromArray [["value", "attack"], ["label", "Attack"]],
createHashMapFromArray [["value", "defend"], ["label", "Defend"]],
createHashMapFromArray [["value", "defuse"], ["label", "Defuse"]],
createHashMapFromArray [["value", "delivery"], ["label", "Delivery"]],
createHashMapFromArray [["value", "destroy"], ["label", "Destroy"]],
createHashMapFromArray [["value", "hostage"], ["label", "Hostage"]],
createHashMapFromArray [["value", "hvtkill"], ["label", "Kill HVT"]],
createHashMapFromArray [["value", "hvtcapture"], ["label", "Capture HVT"]]
];
["INFO", "CAD hydrate using framework generator fallback type list while checking task mission manager."] call EFUNC(common,log);
if (isNil QEGVAR(task,MissionManager) && { !(isNil QEFUNC(task,missionManager)) }) then {
call EFUNC(task,missionManager);
};
if !(isNil QEGVAR(task,MissionManager)) then {
_generatedTaskTypes = EGVAR(task,MissionManager) call ["getGeneratedTaskTypes", []];
["INFO", format ["CAD hydrate using task mission manager generated types: %1", _generatedTaskTypes apply { _x getOrDefault ["value", ""] }]] call EFUNC(common,log);
} else {
["INFO", "CAD hydrate task mission manager is not ready; sending fallback generated task types."] call EFUNC(common,log);
};
} else {
["INFO", "CAD hydrate generated task types disabled by forge_server_task_enableGenerator."] call EFUNC(common,log);
};
private _groupID = _groupRepository call ["getPlayerGroupId", [_uid]];

View File

@ -245,7 +245,7 @@ Task module emits the following events to the event bus:
- `task.notification.requested` - participant notifications pending dispatch
## Notes
- the dynamic mission manager in `fnc_missionManager.sqf` is initialized during task post-init; timer-based mission generation only runs when the `forge_task_enableGenerator` CBA setting is enabled
- the dynamic mission manager in `fnc_missionManager.sqf` is initialized during task post-init; timer-based mission generation only runs when the `forge_server_task_enableGenerator` CBA setting is enabled
- CAD can request a specific generated mission type through `fnc_requestMissionTask.sqf`
- it starts server-owned tasks through `fnc_handler.sqf` and binds them to the `default` org
- task lifecycle for the mission manager is tracked through `TaskStore` status entries

View File

@ -18,6 +18,34 @@
if !(isServer) exitWith { false };
if !(isNil QGVAR(MissionManagerPFH)) exitWith { false };
if (
!(missionNamespace getVariable ["forge_pmc_missionSettingsApplied", false]) &&
{ !(isNil "forge_pmc_fnc_setupMenu_applySettings") }
) exitWith {
if !(missionNamespace getVariable [QGVAR(MissionManagerStartupPending), false]) then {
missionNamespace setVariable [QGVAR(MissionManagerStartupPending), true, true];
["INFO", "Mission manager startup deferred until mission setup settings are applied."] call EFUNC(common,log);
[] spawn {
waitUntil {
sleep 1;
(missionNamespace getVariable ["forge_pmc_missionSettingsApplied", false]) || { time > 180 }
};
if !(missionNamespace getVariable ["forge_pmc_missionSettingsApplied", false]) then {
["INFO", "Mission manager startup applying mission setup fallback settings after timeout."] call EFUNC(common,log);
[] call forge_pmc_fnc_setupMenu_applySettings;
};
missionNamespace setVariable [QGVAR(MissionManagerStartupPending), false, true];
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); };
@ -44,6 +72,10 @@ GVAR(MissionManagerBaseClass) = compileFinal createHashMapFromArray [
["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]] }

View File

@ -28,19 +28,28 @@ GVAR(AttackMissionGeneratorBaseClass) = compileFinal createHashMapFromArray [
_self set ["aiGroupsConfig", (_missionConfig >> "AIGroups")];
_self set ["attackConfig", (_missionConfig >> "MissionTypes" >> "Attack")];
_self set ["generatorType", "attack"];
["INFO", format ["Mission generator registered. Type=attack, ConfigPath=%1", _missionConfig]] call EFUNC(common,log);
}],
["getGeneratorType", compileFinal {
_self getOrDefault ["generatorType", "attack"]
}],
["getMissionInterval", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _interval = getNumber (_missionConfig >> "missionInterval");
if (_settings isEqualType createHashMap) then {
_interval = _settings getOrDefault ["missionInterval", _interval];
};
if (_interval <= 0) then { _interval = 300; };
_interval
}],
["getMaxConcurrentMissions", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _maxConcurrent = getNumber (_missionConfig >> "maxConcurrentMissions");
if (_settings isEqualType createHashMap) then {
_maxConcurrent = _settings getOrDefault ["maxConcurrentMissions", _maxConcurrent];
};
if (_maxConcurrent <= 0) then { _maxConcurrent = 1; };
_maxConcurrent
}],

View File

@ -28,19 +28,28 @@ GVAR(CaptureHvtMissionGeneratorBaseClass) = compileFinal createHashMapFromArray
_self set ["aiGroupsConfig", (_missionConfig >> "AIGroups")];
_self set ["hvtConfig", (_missionConfig >> "MissionTypes" >> "HVTCapture")];
_self set ["generatorType", "hvtcapture"];
["INFO", format ["Mission generator registered. Type=hvtcapture, ConfigPath=%1", _missionConfig]] call EFUNC(common,log);
}],
["getGeneratorType", compileFinal {
_self getOrDefault ["generatorType", "hvtcapture"]
}],
["getMissionInterval", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _interval = getNumber (_missionConfig >> "missionInterval");
if (_settings isEqualType createHashMap) then {
_interval = _settings getOrDefault ["missionInterval", _interval];
};
if (_interval <= 0) then { _interval = 300; };
_interval
}],
["getMaxConcurrentMissions", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _maxConcurrent = getNumber (_missionConfig >> "maxConcurrentMissions");
if (_settings isEqualType createHashMap) then {
_maxConcurrent = _settings getOrDefault ["maxConcurrentMissions", _maxConcurrent];
};
if (_maxConcurrent <= 0) then { _maxConcurrent = 1; };
_maxConcurrent
}],

View File

@ -28,19 +28,28 @@ GVAR(DefendMissionGeneratorBaseClass) = compileFinal createHashMapFromArray [
_self set ["aiGroupsConfig", (_missionConfig >> "AIGroups")];
_self set ["defendConfig", (_missionConfig >> "MissionTypes" >> "Defend")];
_self set ["generatorType", "defend"];
["INFO", format ["Mission generator registered. Type=defend, ConfigPath=%1", _missionConfig]] call EFUNC(common,log);
}],
["getGeneratorType", compileFinal {
_self getOrDefault ["generatorType", "defend"]
}],
["getMissionInterval", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _interval = getNumber (_missionConfig >> "missionInterval");
if (_settings isEqualType createHashMap) then {
_interval = _settings getOrDefault ["missionInterval", _interval];
};
if (_interval <= 0) then { _interval = 300; };
_interval
}],
["getMaxConcurrentMissions", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _maxConcurrent = getNumber (_missionConfig >> "maxConcurrentMissions");
if (_settings isEqualType createHashMap) then {
_maxConcurrent = _settings getOrDefault ["maxConcurrentMissions", _maxConcurrent];
};
if (_maxConcurrent <= 0) then { _maxConcurrent = 1; };
_maxConcurrent
}],

View File

@ -29,19 +29,28 @@ GVAR(DefuseMissionGeneratorBaseClass) = compileFinal createHashMapFromArray [
_self set ["attackConfig", (_missionConfig >> "MissionTypes" >> "Attack")];
_self set ["defuseConfig", (_missionConfig >> "MissionTypes" >> "Defuse")];
_self set ["generatorType", "defuse"];
["INFO", format ["Mission generator registered. Type=defuse, ConfigPath=%1", _missionConfig]] call EFUNC(common,log);
}],
["getGeneratorType", compileFinal {
_self getOrDefault ["generatorType", "defuse"]
}],
["getMissionInterval", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _interval = getNumber (_missionConfig >> "missionInterval");
if (_settings isEqualType createHashMap) then {
_interval = _settings getOrDefault ["missionInterval", _interval];
};
if (_interval <= 0) then { _interval = 300; };
_interval
}],
["getMaxConcurrentMissions", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _maxConcurrent = getNumber (_missionConfig >> "maxConcurrentMissions");
if (_settings isEqualType createHashMap) then {
_maxConcurrent = _settings getOrDefault ["maxConcurrentMissions", _maxConcurrent];
};
if (_maxConcurrent <= 0) then { _maxConcurrent = 1; };
_maxConcurrent
}],

View File

@ -28,19 +28,28 @@ GVAR(DeliveryMissionGeneratorBaseClass) = compileFinal createHashMapFromArray [
_self set ["aiGroupsConfig", (_missionConfig >> "AIGroups")];
_self set ["deliveryConfig", (_missionConfig >> "MissionTypes" >> "Delivery")];
_self set ["generatorType", "delivery"];
["INFO", format ["Mission generator registered. Type=delivery, ConfigPath=%1", _missionConfig]] call EFUNC(common,log);
}],
["getGeneratorType", compileFinal {
_self getOrDefault ["generatorType", "delivery"]
}],
["getMissionInterval", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _interval = getNumber (_missionConfig >> "missionInterval");
if (_settings isEqualType createHashMap) then {
_interval = _settings getOrDefault ["missionInterval", _interval];
};
if (_interval <= 0) then { _interval = 300; };
_interval
}],
["getMaxConcurrentMissions", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _maxConcurrent = getNumber (_missionConfig >> "maxConcurrentMissions");
if (_settings isEqualType createHashMap) then {
_maxConcurrent = _settings getOrDefault ["maxConcurrentMissions", _maxConcurrent];
};
if (_maxConcurrent <= 0) then { _maxConcurrent = 1; };
_maxConcurrent
}],

View File

@ -29,19 +29,28 @@ GVAR(DestroyMissionGeneratorBaseClass) = compileFinal createHashMapFromArray [
_self set ["attackConfig", (_missionConfig >> "MissionTypes" >> "Attack")];
_self set ["destroyConfig", (_missionConfig >> "MissionTypes" >> "Destroy")];
_self set ["generatorType", "destroy"];
["INFO", format ["Mission generator registered. Type=destroy, ConfigPath=%1", _missionConfig]] call EFUNC(common,log);
}],
["getGeneratorType", compileFinal {
_self getOrDefault ["generatorType", "destroy"]
}],
["getMissionInterval", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _interval = getNumber (_missionConfig >> "missionInterval");
if (_settings isEqualType createHashMap) then {
_interval = _settings getOrDefault ["missionInterval", _interval];
};
if (_interval <= 0) then { _interval = 300; };
_interval
}],
["getMaxConcurrentMissions", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _maxConcurrent = getNumber (_missionConfig >> "maxConcurrentMissions");
if (_settings isEqualType createHashMap) then {
_maxConcurrent = _settings getOrDefault ["maxConcurrentMissions", _maxConcurrent];
};
if (_maxConcurrent <= 0) then { _maxConcurrent = 1; };
_maxConcurrent
}],

View File

@ -29,19 +29,28 @@ GVAR(HostageMissionGeneratorBaseClass) = compileFinal createHashMapFromArray [
_self set ["attackConfig", (_missionConfig >> "MissionTypes" >> "Attack")];
_self set ["hostageConfig", (_missionConfig >> "MissionTypes" >> "Hostage")];
_self set ["generatorType", "hostage"];
["INFO", format ["Mission generator registered. Type=hostage, ConfigPath=%1", _missionConfig]] call EFUNC(common,log);
}],
["getGeneratorType", compileFinal {
_self getOrDefault ["generatorType", "hostage"]
}],
["getMissionInterval", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _interval = getNumber (_missionConfig >> "missionInterval");
if (_settings isEqualType createHashMap) then {
_interval = _settings getOrDefault ["missionInterval", _interval];
};
if (_interval <= 0) then { _interval = 300; };
_interval
}],
["getMaxConcurrentMissions", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _maxConcurrent = getNumber (_missionConfig >> "maxConcurrentMissions");
if (_settings isEqualType createHashMap) then {
_maxConcurrent = _settings getOrDefault ["maxConcurrentMissions", _maxConcurrent];
};
if (_maxConcurrent <= 0) then { _maxConcurrent = 1; };
_maxConcurrent
}],

View File

@ -28,19 +28,28 @@ GVAR(KillHvtMissionGeneratorBaseClass) = compileFinal createHashMapFromArray [
_self set ["aiGroupsConfig", (_missionConfig >> "AIGroups")];
_self set ["hvtConfig", (_missionConfig >> "MissionTypes" >> "HVTKill")];
_self set ["generatorType", "hvtkill"];
["INFO", format ["Mission generator registered. Type=hvtkill, ConfigPath=%1", _missionConfig]] call EFUNC(common,log);
}],
["getGeneratorType", compileFinal {
_self getOrDefault ["generatorType", "hvtkill"]
}],
["getMissionInterval", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _interval = getNumber (_missionConfig >> "missionInterval");
if (_settings isEqualType createHashMap) then {
_interval = _settings getOrDefault ["missionInterval", _interval];
};
if (_interval <= 0) then { _interval = 300; };
_interval
}],
["getMaxConcurrentMissions", compileFinal {
private _missionConfig = _self getOrDefault ["missionConfig", configNull];
private _settings = missionNamespace getVariable ["forge_pmc_missionSettings", createHashMap];
private _maxConcurrent = getNumber (_missionConfig >> "maxConcurrentMissions");
if (_settings isEqualType createHashMap) then {
_maxConcurrent = _settings getOrDefault ["maxConcurrentMissions", _maxConcurrent];
};
if (_maxConcurrent <= 0) then { _maxConcurrent = 1; };
_maxConcurrent
}],

View File

@ -77,7 +77,7 @@ the task mission manager as `generatedTaskTypes`; the client uses that hydrated
list for the dropdown.
Generated mission requests are controlled by the server CBA setting
`forge_task_enableGenerator`:
`forge_server_task_enableGenerator`:
- Enabled: CAD receives the generated task type list and dispatchers can request
a specific generator type.

View File

@ -104,7 +104,7 @@ The dispatcher-generated task dropdown is hydrated from the server
`generatedTaskTypes` payload. The UI has a built-in fallback list for loading or
older payload compatibility, but any hydrate payload that includes
`generatedTaskTypes` replaces that fallback. An empty hydrated list disables the
request control, which is how `forge_task_enableGenerator = false` is surfaced
request control, which is how `forge_server_task_enableGenerator = false` is surfaced
client-side.
## Authorization Notes

View File

@ -740,7 +740,7 @@ framework file as the default schema and mission copies as the tuning layer.
The generated mission system supports `attack`, `defend`, `defuse`,
`delivery`, `destroy`, `hostage`, `hvtkill`, and `hvtcapture`. The
`forge_task_enableGenerator` CBA setting gates both timer-based generation and
`forge_server_task_enableGenerator` CBA setting gates both timer-based generation and
CAD dispatcher-requested generation.
The dynamic mission generator avoids rectangle and ellipse area markers whose

View File

@ -176,7 +176,7 @@ Generated mission types currently exposed by the framework are:
| Kill HVT | `hvtkill` | `hvt` |
| Capture HVT | `hvtcapture` | `hvt` |
The server CBA setting `forge_task_enableGenerator` is the single runtime gate
The server CBA setting `forge_server_task_enableGenerator` is the single runtime gate
for generated missions. When disabled, timer-based generation does not run, CAD
hydrates no generated task types, and manual dispatcher requests are rejected
server-side.

View File

@ -740,7 +740,7 @@ framework file as the default schema and mission copies as the tuning layer.
The generated mission system supports `attack`, `defend`, `defuse`,
`delivery`, `destroy`, `hostage`, `hvtkill`, and `hvtcapture`. The
`forge_task_enableGenerator` CBA setting gates both timer-based generation and
`forge_server_task_enableGenerator` CBA setting gates both timer-based generation and
CAD dispatcher-requested generation.
The dynamic mission generator avoids rectangle and ellipse area markers whose

View File

@ -175,7 +175,7 @@ Generated mission types currently exposed by the framework are:
| Kill HVT | `hvtkill` | `hvt` |
| Capture HVT | `hvtcapture` | `hvt` |
The server CBA setting `forge_task_enableGenerator` is the single runtime gate
The server CBA setting `forge_server_task_enableGenerator` is the single runtime gate
for generated missions. When disabled, timer-based generation does not run, CAD
hydrates no generated task types, and manual dispatcher requests are rejected
server-side.

View File

@ -75,7 +75,7 @@ the task mission manager as `generatedTaskTypes`; the client uses that hydrated
list for the dropdown.
Generated mission requests are controlled by the server CBA setting
`forge_task_enableGenerator`:
`forge_server_task_enableGenerator`:
- Enabled: CAD receives the generated task type list and dispatchers can request
a specific generator type.

View File

@ -103,7 +103,7 @@ The dispatcher-generated task dropdown is hydrated from the server
`generatedTaskTypes` payload. The UI has a built-in fallback list for loading or
older payload compatibility, but any hydrate payload that includes
`generatedTaskTypes` replaces that fallback. An empty hydrated list disables the
request control, which is how `forge_task_enableGenerator = false` is surfaced
request control, which is how `forge_server_task_enableGenerator = false` is surfaced
client-side.
## Authorization Notes