mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Add garrison zeus modules (#4555)
* Add garrison and un-garrison modules * Remove unnecessary text from garrison header * Add french translations to new strings * Add changes requested by review * Change pushback to pushBack * Move garrison funcs to ai, finish headers * Remove diag log debug * Fix typos and header issues * Add missing newlines * Fix strings, Fix typos and headers * Enable debug and disable compile cache, Add trace and comments * Rebase before review * Fix default case running instead of case 3 * Fix edge case related to players being in garrison group The player would make the enableAttack checks in ungarrison and garrisonMove fail, this is now fixed. * Fix some arrays in garrsionMove and garrison * Relax distance checks in garrisonMove, change AI behaviour while pathing to aware * Add debug view * Remove unused var, fix unit pos using the wrong format * Make debug more visually pleasing * Change garrison debug target to a waypoint icon * Change disableAI event to AISection, comment out doFollow in doMove EH * Fix locality issue
This commit is contained in:
parent
ed1e95106d
commit
bb03f55c5c
18
addons/ai/CfgEventHandlers.hpp
Normal file
18
addons/ai/CfgEventHandlers.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
class Extended_PreStart_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_preStart));
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_PreInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_preInit));
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_PostInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_postInit));
|
||||
};
|
||||
};
|
3
addons/ai/XEH_PREP.hpp
Normal file
3
addons/ai/XEH_PREP.hpp
Normal file
@ -0,0 +1,3 @@
|
||||
PREP(garrison);
|
||||
PREP(unGarrison);
|
||||
PREP(garrisonMove);
|
84
addons/ai/XEH_postInit.sqf
Normal file
84
addons/ai/XEH_postInit.sqf
Normal file
@ -0,0 +1,84 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
[QGVAR(AISection), {
|
||||
params [["_units", [], [[]]], ["_sections", [], [[]]], ["_bool", true, [true]]];
|
||||
{
|
||||
private _section = _x;
|
||||
{
|
||||
if (_bool) then {
|
||||
_x enableAI _section;
|
||||
} else {
|
||||
_x disableAI _section;
|
||||
};
|
||||
LOG(format [ARR_4("XEH_postInit: %1 disableAI %2 | ID %3", _x, _section, clientOwner)]);
|
||||
} foreach (_units select {local _x});
|
||||
} foreach _sections
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
||||
[QGVAR(unGarrison), FUNC(unGarrison)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(doMove), {
|
||||
params ["_unitsArray"];
|
||||
{
|
||||
_x params ["_unit", "_pos"];
|
||||
//_unit doFollow leader _unit;
|
||||
_unit setDestination [_pos, "LEADER PLANNED", true];
|
||||
_unit doMove _pos;
|
||||
LOG(format [ARR_4("XEH_postInit: %1 doMove %2 | ID %3", _unit, _pos, clientOwner)]);
|
||||
} foreach _unitsArray
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(setBehaviour), {
|
||||
params ["_groupsArray", "_behaviour"];
|
||||
{
|
||||
_x params ["_group"];
|
||||
_group setBehaviour _behaviour;
|
||||
LOG(format [ARR_4("XEH_postInit: %1 setBehaviour %2 | ID %3", _group, _behaviour, clientOwner)]);
|
||||
} foreach _groupsArray
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(enableAttack), {
|
||||
params ["_unitsArray", "_mode"];
|
||||
{
|
||||
_x params ["_unit"];
|
||||
_unit enableAttack _mode;
|
||||
LOG(format [ARR_4("XEH_postInit: %1 enableAttack %2 | ID %3", _unit, _mode, clientOwner)]);
|
||||
} foreach _unitsArray
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
addMissionEventHandler ["Draw3D", {
|
||||
private _unitMoveList = missionNameSpace getVariable [QGVAR(garrison_unitMoveList), []];
|
||||
|
||||
{
|
||||
_x params ["_unit", "_pos"];
|
||||
|
||||
switch true do {
|
||||
case (surfaceIsWater (getPos _unit) && {surfaceIsWater _pos}) : {
|
||||
for "_i" from 0 to 3 do {
|
||||
drawLine3D [_unit modelToWorldVisualWorld [0,0,1], (AGLtoASL _pos), [1,0,0,1]];
|
||||
};
|
||||
drawIcon3D ["\a3\ui_f\data\map\groupicons\waypoint.paa", [1,0,0,1], (AGLtoASL _pos), 0.75, 0.75, 0.75];
|
||||
};
|
||||
|
||||
case (!surfaceIsWater (getPos _unit) && {!surfaceIsWater _pos}) : {
|
||||
for "_i" from 0 to 3 do {
|
||||
drawLine3D [_unit modelToWorldVisual [0,0,1], _pos, [1,0,0,1]];
|
||||
};
|
||||
drawIcon3D ["\a3\ui_f\data\map\groupicons\waypoint.paa", [1,0,0,1], _pos, 0.75, 0.75, 0.75];
|
||||
};
|
||||
|
||||
case (!surfaceIsWater (getPos _unit) && {surfaceIsWater _pos}) : {
|
||||
for "_i" from 0 to 3 do {
|
||||
drawLine3D [_unit modelToWorldVisual [0,0,1], (AGLToASL _pos), [1,0,0,1]];
|
||||
};
|
||||
drawIcon3D ["\a3\ui_f\data\map\groupicons\waypoint.paa", [1,0,0,1], (AGLtoASL _pos), 0.75, 0.75, 0.75];
|
||||
};
|
||||
|
||||
case (surfaceIsWater (getPos _unit) && {!surfaceIsWater _pos}) : {
|
||||
for "_i" from 0 to 3 do {
|
||||
drawLine3D [_unit modelToWorldVisualWorld [0,0,1], _pos, [1,0,0,1]];
|
||||
};
|
||||
drawIcon3D ["\a3\ui_f\data\map\groupicons\waypoint.paa", [1,0,0,1], _pos, 0.75, 0.75, 0.75];
|
||||
};
|
||||
};
|
||||
} foreach _unitMoveList;
|
||||
}];
|
||||
#endif
|
9
addons/ai/XEH_preInit.sqf
Normal file
9
addons/ai/XEH_preInit.sqf
Normal file
@ -0,0 +1,9 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
ADDON = false;
|
||||
|
||||
PREP_RECOMPILE_START;
|
||||
#include "XEH_PREP.hpp"
|
||||
PREP_RECOMPILE_END;
|
||||
|
||||
ADDON = true;
|
3
addons/ai/XEH_preStart.sqf
Normal file
3
addons/ai/XEH_preStart.sqf
Normal file
@ -0,0 +1,3 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
#include "XEH_PREP.hpp"
|
@ -15,3 +15,4 @@ class CfgPatches {
|
||||
};
|
||||
|
||||
#include "CfgWeapons.hpp"
|
||||
#include "CfgEventHandlers.hpp"
|
||||
|
278
addons/ai/functions/fnc_garrison.sqf
Normal file
278
addons/ai/functions/fnc_garrison.sqf
Normal file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Author: alganthe
|
||||
* Garrison function used to garrison AI inside buildings.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The building(s) nearest this position are used <POSITION>
|
||||
* 1: Limit the building search to those type of building <ARRAY>
|
||||
* 2: Units that will be garrisoned <ARRAY>
|
||||
* 3: Radius to fill building(s) <SCALAR> (default: 50)
|
||||
* 4: 0: even filling, 1: building by building, 2: random filling <SCALAR> (default: 0)
|
||||
* 5: True to fill building(s) from top to bottom <BOOL> (default: false) (note: only works with filling mode 0 and 1)
|
||||
* 6: Teleport units <BOOL> (default: false)
|
||||
|
||||
* Return Value:
|
||||
* Units not garrisoned <ARRAY>
|
||||
*
|
||||
* Example:
|
||||
* [position, nil, [unit1, unit2, unit3, unitN], 200, 1, false, false] call ace_ai_fnc_garrison
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params [["_startingPos",[0,0,0], [[]], 3], ["_buildingTypes", ["Building"], [[]]], ["_unitsArray", [], [[]]], ["_fillingRadius", 50, [0]], ["_fillingType", 0, [0]], ["_topDownFilling", false, [true]], ["_teleport", false, [true]]];
|
||||
|
||||
TRACE_6("fnc_garrison: Start",_startingPos,_buldingTypes,count _unitsArray,_fillingRadius,_fillingTYpe,_topDownFilling);
|
||||
|
||||
_unitsArray = _unitsArray select {alive _x && {!isPlayer _x}};
|
||||
|
||||
if (_startingPos isEqualTo [0,0,0]) exitWith {
|
||||
TRACE_1("fnc_garrison: StartingPos error",_startingPos);
|
||||
[LSTRING(GarrisonInvalidPosition)] call EFUNC(common,displayTextStructured);
|
||||
};
|
||||
|
||||
if (count _unitsArray == 0 || {isNull (_unitsArray select 0)}) exitWith {
|
||||
TRACE_1("fnc_garrison: Units error",_unitsArray);
|
||||
[LSTRING(GarrisonNoUnits)] call EFUNC(common,displayTextStructured);
|
||||
};
|
||||
|
||||
private _buildings = nearestObjects [_startingPos, _buildingTypes, ([_fillingRadius, 50] select (_fillingRadius < 50))];
|
||||
if (_fillingRadius >= 50) then {
|
||||
_buildings = [_buildings] call CBA_fnc_shuffle;
|
||||
};
|
||||
|
||||
if (count _buildings == 0) exitWith {
|
||||
TRACE_1("fnc_garrison: Building error",_buildings);
|
||||
[LSTRING(GarrisonNoBuilding)] call EFUNC(common,displayTextStructured);
|
||||
};
|
||||
|
||||
private _buildingsIndex = [];
|
||||
|
||||
if (_topDownFilling) then {
|
||||
{
|
||||
private _buildingPos = _x buildingPos -1;
|
||||
|
||||
// Those reverse are necessary, as dumb as it is there's no better way to sort those subarrays in sqf
|
||||
{
|
||||
reverse _x;
|
||||
} foreach _buildingPos;
|
||||
|
||||
_buildingPos sort false;
|
||||
|
||||
{
|
||||
reverse _x;
|
||||
} foreach _buildingPos;
|
||||
|
||||
_buildingsIndex pushBack _buildingPos;
|
||||
} foreach _buildings;
|
||||
} else {
|
||||
{
|
||||
_buildingsIndex pushBack (_x buildingPos -1);
|
||||
} foreach _buildings;
|
||||
};
|
||||
|
||||
// Remove buildings without positions
|
||||
{
|
||||
_buildingsIndex deleteAt (_buildingsIndex find _x);
|
||||
} foreach (_buildingsIndex select {count _x == 0});
|
||||
|
||||
//Remove positions units are already pathing to
|
||||
_buildingsIndex = _buildingsIndex apply {
|
||||
private _testedBuilding = _x;
|
||||
|
||||
_testedBuilding select {
|
||||
private _testedPos = _x;
|
||||
(({(_x select 1) isEqualTo _testedPos} count (missionNameSpace getVariable [QGVAR(garrison_unitMoveList), []])) == 0)
|
||||
}
|
||||
};
|
||||
|
||||
// Warn the user that there's not enough positions to place all units
|
||||
private _count = 0;
|
||||
{_count = _count + count _x} foreach _buildingsIndex;
|
||||
if ( (count _unitsArray) - _count > 0) then {
|
||||
TRACE_4("fnc_garrison: Not enough spots to place all units",_unitsArray,count _unitsArray,_count,((count _unitsArray) - _count > 0));
|
||||
[LSTRING(GarrisonNotEnoughPos)] call EFUNC(common,displayTextStructured);
|
||||
};
|
||||
|
||||
private _placedUnits = [];
|
||||
private _unitMoveList = [];
|
||||
|
||||
// Force all units to un-garrison
|
||||
[QGVAR(unGarrison), [_unitsArray], _unitsArray] call CBA_fnc_targetEvent;
|
||||
|
||||
private _fnc_comparePos = {
|
||||
params ["_nearestUnits", "_pos"];
|
||||
({
|
||||
if (surfaceIsWater getPos _x) then {
|
||||
floor ((getPosASL _x) select 2) == floor ((AGLtoASL _pos) select 2)
|
||||
} else {
|
||||
floor ((getPosATL _x) select 2) == floor (_pos select 2)
|
||||
};
|
||||
} count _nearestUnits) > 0
|
||||
};
|
||||
|
||||
// Do the placement
|
||||
switch (_fillingType) do {
|
||||
|
||||
// Even filling
|
||||
case 0: {
|
||||
|
||||
while {count _unitsArray > 0} do {
|
||||
if (count _buildingsIndex == 0) exitWith {};
|
||||
private _building = _buildingsIndex select 0;
|
||||
|
||||
if (_building isEqualTo []) then {
|
||||
LOG(format [ARR_2("fnc_garrison: Empty building array | removing building from buildingsIndex | %1 buildings remaining",count _buildingsIndex)]);
|
||||
_buildingsIndex deleteAt 0;
|
||||
|
||||
} else {
|
||||
private _pos = _building select 0;
|
||||
private _nearestUnits = (_pos nearEntities ["CAManBase", 2]);
|
||||
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits, {floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
|
||||
|
||||
if (count _nearestUnits > 0 && {[_nearestUnits, _pos] call _fnc_comparePos}) then {
|
||||
LOG(format [ARR_2("fnc_garrison: Unit present | removing position | %1 positions remaining for this building",count (_buildingsIndex select (_buildingsIndex find _building)) - 1)]);
|
||||
_buildingsIndex set [0, _building - [_pos]];
|
||||
|
||||
} else {
|
||||
private _unit = _unitsArray select 0;
|
||||
private _posSurface = surfaceIsWater _pos;
|
||||
|
||||
if (_teleport) then {
|
||||
doStop _unit;
|
||||
if (_posSurface) then {
|
||||
_unit setPosASL (AGLtoASL _pos);
|
||||
} else {
|
||||
_unit setPosATL _pos;
|
||||
};
|
||||
|
||||
} else {
|
||||
_unitMoveList pushBack [_unit,[_pos, AGLToASL _pos] select (_posSurface)];
|
||||
};
|
||||
|
||||
_placedUnits pushBack _unit;
|
||||
_unitsArray deleteAt (_unitsArray find _unit);
|
||||
_building deleteAt 0;
|
||||
_buildingsIndex deleteAt 0;
|
||||
_buildingsIndex pushBackUnique _building;
|
||||
_unit setVariable [QGVAR(garrisonned), true, true];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Building by building
|
||||
case 1: {
|
||||
|
||||
while {count _unitsArray > 0} do {
|
||||
if (count _buildingsIndex == 0) exitWith {};
|
||||
private _building = _buildingsIndex select 0;
|
||||
|
||||
if (_building isEqualTo []) then {
|
||||
LOG(format [ARR_2("fnc_garrison: empty building array | removing building from buildingsIndex | %1 buildings remaining",count _buildingsIndex)]);
|
||||
_buildingsIndex deleteAt 0;
|
||||
|
||||
} else {
|
||||
private _pos = _building select 0;
|
||||
private _nearestUnits = (_pos nearEntities ["CAManBase", 2]);
|
||||
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits, {floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
|
||||
|
||||
if (count _nearestUnits > 0 && {[_nearestUnits, _pos] call _fnc_comparePos}) then {
|
||||
LOG(format [ARR_2("fnc_garrison: Unit present | removing position | %1 positions remaining for this building",count (_buildingsIndex select (_buildingsIndex find _building)) - 1)]);
|
||||
_buildingsIndex set [0, _building - [_pos]];
|
||||
|
||||
} else {
|
||||
private _unit = _unitsArray select 0;
|
||||
private _posSurface = surfaceIsWater _pos;
|
||||
|
||||
if (_teleport) then {
|
||||
doStop _unit;
|
||||
if (_posSurface) then {
|
||||
_unit setPosASL (AGLtoASL _pos);
|
||||
} else {
|
||||
_unit setPosATL _pos;
|
||||
};
|
||||
|
||||
} else {
|
||||
_unitMoveList pushBack [_unit,[_pos, AGLToASL _pos] select (_posSurface)];
|
||||
};
|
||||
|
||||
_placedUnits pushBack _unit;
|
||||
_unitsArray deleteAt (_unitsArray find _unit);
|
||||
_buildingsIndex set [0, _building - [_pos]];
|
||||
_unit setVariable [QGVAR(garrisonned), true, true];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Random
|
||||
case 2: {
|
||||
|
||||
while {count _unitsArray > 0} do {
|
||||
if (count _buildingsIndex == 0) exitWith {};
|
||||
private _building = selectRandom _buildingsIndex;
|
||||
|
||||
if (_building isEqualTo []) then {
|
||||
LOG(format [ARR_2("fnc_garrison: empty building array | removing building from buildingsIndex | %1 buildings remaining",count _buildingsIndex)]);
|
||||
_buildingsIndex deleteAt (_buildingsIndex find _building);
|
||||
|
||||
} else {
|
||||
private _pos = selectRandom _building;
|
||||
private _nearestUnits = (_pos nearEntities ["CAManBase", 2]);
|
||||
LOG(format [ARR_3("fnc_garrison: Unit detection | %1 units nearby | %2 units within height",count _nearestUnits, {floor ((getPos _x) select 2) == floor (_pos select 2)} count _nearestUnits)]);
|
||||
|
||||
if (count _nearestUnits > 0 && {[_nearestUnits, _pos] call _fnc_comparePos}) then {
|
||||
LOG(format [ARR_2("fnc_garrison: Unit present | removing position | %1 positions remaining for this building",count (_buildingsIndex select (_buildingsIndex find _building)) - 1)]);
|
||||
_buildingsIndex set [(_buildingsIndex find _building), _building - [_pos]];
|
||||
|
||||
} else {
|
||||
private _unit = _unitsArray select 0;
|
||||
private _posSurface = surfaceIsWater _pos;
|
||||
|
||||
if (_teleport) then {
|
||||
doStop _unit;
|
||||
if (_posSurface) then {
|
||||
_unit setPosASL (AGLtoASL _pos);
|
||||
} else {
|
||||
_unit setPosATL _pos;
|
||||
};
|
||||
|
||||
} else {
|
||||
_unitMoveList pushBack [_unit,[_pos, AGLToASL _pos] select (_posSurface)];
|
||||
};
|
||||
|
||||
_placedUnits pushBack _unit;
|
||||
_unitsArray deleteAt (_unitsArray find _unit);
|
||||
_buildingsIndex set [(_buildingsIndex find _building), _building - [_pos]];
|
||||
_unit setVariable [QGVAR(garrisonned), true, true];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
TRACE_1(format [ARR_2("fnc_garrison: while loop ended | %1 units ready to be treated by PFH",count _unitMoveList)], _teleport);
|
||||
|
||||
// Update the unit list and remove duplicate positions and units
|
||||
private _garrison_unitMoveList = missionNameSpace getVariable [QGVAR(garrison_unitMoveList), []];
|
||||
|
||||
_garrison_unitMoveList = _garrison_unitMoveList select {
|
||||
_x params ["_testedUnit", "_testedPos"];
|
||||
({(_x select 0) isEqualTo _testedUnit} count _unitMoveList == 0)
|
||||
};
|
||||
|
||||
_garrison_unitMoveList append _unitMoveList;
|
||||
|
||||
missionNameSpace setVariable [QGVAR(garrison_unitMoveList), _garrison_unitMoveList, true];
|
||||
|
||||
if (_teleport) then {
|
||||
[QGVAR(AISection), [_placedUnits, ["PATH"], false], _placedUnits] call CBA_fnc_targetEvent;
|
||||
|
||||
} else {
|
||||
[_unitMoveList] call FUNC(garrisonMove);
|
||||
};
|
||||
|
||||
TRACE_1(format [ARR_3("fnc_garrison: End | %1 units left | %2 buildings left", count _unitsArray, count _buildingsIndex)], _unitsArray);
|
||||
_unitsArray
|
149
addons/ai/functions/fnc_garrisonMove.sqf
Normal file
149
addons/ai/functions/fnc_garrisonMove.sqf
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Author: alganthe
|
||||
* Internal function used by ace_ai_fnc_garrison to make the units move to the positions it picked.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Array of arrays <ARRAY>
|
||||
* 0: Unit needing to be placed <UNIT>
|
||||
* 1: Position the unit need to be placed at <POSITION>
|
||||
*
|
||||
* Return Value:
|
||||
* Nothing
|
||||
*
|
||||
* Example:
|
||||
* [ [unit1, [10, 10, 10]], [unit2, [30, 30, 30]], [unitN, getPos player] ] call ace_ai_fnc_garrisonMove
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params [ ["_unitMoveList", nil, [[]]] ];
|
||||
|
||||
if (isNil "_unitMoveList") exitWith {};
|
||||
|
||||
// Start initial movement
|
||||
private _unitMoveListUnits = (_unitMoveList apply {_x select 0});
|
||||
[QGVAR(setBehaviour), [(_unitMoveListUnits select {leader _x == _x}), "AWARE"], _unitMoveListUnits] call CBA_fnc_targetEvent;
|
||||
[QGVAR(AISection), [_unitMoveListUnits, ["FSM"], false], _unitMoveListUnits] call CBA_fnc_targetEvent;
|
||||
[QGVAR(doMove), [_unitMoveList], _unitMoveListUnits] call CBA_fnc_targetEvent;
|
||||
[QGVAR(enableAttack), [_unitMoveListUnits select {leader _x == _x}, false], _unitMoveListUnits] call CBA_fnc_targetEvent;
|
||||
|
||||
{
|
||||
_x setVariable [QGVAR(garrisonMove_failSafe), nil, true];
|
||||
_x setVariable [QGVAR(garrisonMove_unitPosMemory), nil, true];
|
||||
} foreach _unitMoveListUnits;
|
||||
|
||||
// Avoid duplicate PFHs
|
||||
if (isNil QGVAR(garrison_moveUnitPFH)) then {
|
||||
missionNameSpace setVariable [QGVAR(garrison_moveUnitPFH), true, true];
|
||||
|
||||
// PFH checking if the units have reached their destination
|
||||
[{
|
||||
params ["_args", "_pfhID"];
|
||||
|
||||
private _unitMoveList = missionNameSpace getVariable [QGVAR(garrison_unitMoveList), []];
|
||||
|
||||
// End PFH if all units are placed / unable to reach position
|
||||
if (_unitMoveList isEqualTo []) then {
|
||||
missionNameSpace setVariable [QGVAR(garrison_moveUnitPFH), nil, true];
|
||||
LOG("garrisonMove PFH: PFH finished it's job | deleting PFH");
|
||||
_pfhID call CBA_fnc_removePerFrameHandler;
|
||||
|
||||
} else {
|
||||
{
|
||||
_x params ["_unit", "_pos"];
|
||||
|
||||
// Check if unit is alive or even existing
|
||||
if (!alive _unit) then {
|
||||
_unitMoveList deleteAt (_unitMoveList find _x);
|
||||
LOG(format [ARR_2("garrisonMove PFH: unit dead or deleted | %1 units left", count _unitMoveList)]);
|
||||
|
||||
} else {
|
||||
private _unitPos = getPos _unit;
|
||||
if (surfaceisWater _unitPos) then {
|
||||
_unitPos = getPosASL _unit;
|
||||
} else {
|
||||
_unitPos = getPosATL _unit;
|
||||
};
|
||||
|
||||
if (unitReady _unit) then {
|
||||
// Check for distance, doMove and AI are moody and may stop for no reason, within 6 meters and ready should be fine
|
||||
if (_unitPos distance _pos < 3) then {
|
||||
_unit setVariable [QGVAR(garrisonMove_failSafe), nil, true];
|
||||
_unit setVariable [QGVAR(garrisonMove_unitPosMemory), nil, true];
|
||||
_unit setVariable [QGVAR(garrisonned), true, true];
|
||||
_unitMoveList deleteAt (_unitMoveList find _x);
|
||||
|
||||
[QGVAR(AISection), [[_unit], ["PATH"], false], _unit] call CBA_fnc_targetEvent;
|
||||
[QGVAR(AISection), [[_unit], ["FSM"], true], _unit] call CBA_fnc_targetEvent;
|
||||
|
||||
if ({(_x select 0) in units _unit && {!isPlayer (_x select 0)}} count _unitMoveList == 0) then {
|
||||
[QGVAR(enableAttack), [[_unit], true], _unit] call CBA_fnc_targetEvent;
|
||||
};
|
||||
|
||||
LOG(format [ARR_2("garrisonMove PFH: unit in position | %1 units left", count _unitMoveList)]);
|
||||
|
||||
} else {
|
||||
// Tell the unit to move if an order wasn't given within 30s, avoid doMove spam
|
||||
(_unit getVariable [QGVAR(garrisonMove_failSafe), [CBA_missionTime, 5]]) params ["_failSafeTimer", "_failSafeRemainingAttemps"];
|
||||
|
||||
if (_failSafeTimer <= CBA_missionTime) then {
|
||||
if (_failSafeRemainingAttemps == 0 ) then {
|
||||
_unit setVariable [QGVAR(garrisonMove_failSafe), nil, true];
|
||||
_unit setVariable [QGVAR(garrisonMove_unitPosMemory), nil, true];
|
||||
[QGVAR(unGarrison), [[_unit]], _unit] call CBA_fnc_targetEvent;
|
||||
_unitMoveList deleteAt (_unitMoveList find _x);
|
||||
LOG("garrisonMove PFH unitReady: all moving commands failed | restoring AI capabilities");
|
||||
|
||||
} else {
|
||||
_unit setVariable [QGVAR(garrisonMove_failSafe), [_failSafeTimer + 15, _failSafeRemainingAttemps - 1]];
|
||||
[QGVAR(doMove), [[[_unit, _pos]]], _unit] call CBA_fnc_targetEvent;
|
||||
LOG("garrisonMove PFH unitReady: unit not close enough | Sending another doMove command");
|
||||
};
|
||||
};
|
||||
};
|
||||
} else {
|
||||
(_unit getVariable [QGVAR(garrisonMove_unitPosMemory), [CBA_missionTime, [0,0,0]]]) params ["_unitPosTimer", "_unitOldPos"];
|
||||
|
||||
// AI may sometimes not be able to report unitReady, this is to avoid the PFH running forever
|
||||
switch true do {
|
||||
case ((_unitPosTimer + 15) < CBA_missionTime && {(_unitPos distance _pos) < 3}) : {
|
||||
TRACE_1("case 1",_unit);
|
||||
_unit setVariable [QGVAR(garrisonMove_failSafe), nil, true];
|
||||
_unit setVariable [QGVAR(garrisonMove_unitPosMemory), nil, true];
|
||||
_unit setVariable [QGVAR(garrisonned), true, true];
|
||||
_unitMoveList deleteAt (_unitMoveList find _x);
|
||||
|
||||
[QGVAR(AISection), [[_unit], ["PATH"], false], _unit] call CBA_fnc_targetEvent;
|
||||
[QGVAR(AISection), [[_unit], ["FSM"], true], _unit] call CBA_fnc_targetEvent;
|
||||
|
||||
if ({(_x select 0) in units _unit && {!isPlayer (_x select 0)}} count _unitMoveList == 0) then {
|
||||
[QGVAR(enableAttack), [[_unit], true], _unit] call CBA_fnc_targetEvent;
|
||||
};
|
||||
|
||||
LOG(format [ARR_2("garrisonMove PFH unitNotReady: unit in position | %1 units left", count _unitMoveList)]);
|
||||
};
|
||||
|
||||
case ((_unitPosTimer + 15) < CBA_missionTime && {_unitOldPos distance _unitPos < 0.5}) : {
|
||||
TRACE_3("case 2",_unit, ((_unitPosTimer + 15) < CBA_missionTime), (_unitOldPos distance _unitPos < 0.5));
|
||||
_unit setVariable [QGVAR(garrisonMove_failSafe), nil, true];
|
||||
_unit setVariable [QGVAR(garrisonMove_unitPosMemory), nil, true];
|
||||
[QGVAR(unGarrison), [[_unit]], _unit] call CBA_fnc_targetEvent;
|
||||
_unitMoveList deleteAt (_unitMoveList find _x);
|
||||
LOG("garrisonMove PFH unitNotReady: all moving commands failed | restoring AI capabilities");
|
||||
};
|
||||
|
||||
case (_unitOldPos distance _unitPos < 0.5) : {};
|
||||
|
||||
default {
|
||||
_unit setVariable [QGVAR(garrisonMove_unitPosMemory), [CBA_missionTime, _unitPos]];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
} foreach _unitMoveList;
|
||||
|
||||
missionNameSpace setVariable [QGVAR(garrison_unitMoveList), _unitMoveList, true];
|
||||
};
|
||||
}, 0.5, []] call CBA_fnc_addPerFrameHandler;
|
||||
};
|
57
addons/ai/functions/fnc_unGarrison.sqf
Normal file
57
addons/ai/functions/fnc_unGarrison.sqf
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Author: alganthe
|
||||
* Used to un-garrison units.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Units to un-garrison <ARRAY>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [unit1, unit2, unit3] call ace_ai_fnc_unGarrison
|
||||
*
|
||||
* Public: Yes
|
||||
*
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params [["_units", [], [[]]]];
|
||||
|
||||
_units = _units select {local _x};
|
||||
|
||||
{
|
||||
if (!isPlayer _x && {local _x}) then {
|
||||
_x enableAI "PATH";
|
||||
_x enableAI "FSM";
|
||||
|
||||
private _leader = leader _x;
|
||||
|
||||
TRACE_3("fnc_ungarrison: unit and leader",_x , _leader, (_leader == _x));
|
||||
|
||||
_x setVariable [QGVAR(garrisonned), false, true];
|
||||
|
||||
if (_leader != _x) then {
|
||||
doStop _x;
|
||||
_x doFollow _leader;
|
||||
|
||||
} else {
|
||||
_x doMove ((nearestBuilding (getPos _x)) buildingExit 0);
|
||||
};
|
||||
|
||||
private _fnc_countGarrisonnedUnits = {
|
||||
params ["_unit", "_bool"];
|
||||
if (_bool) then {
|
||||
({(_x getVariable [QGVAR(garrisonned), false]) && {!isPlayer _x}} count units _unit)
|
||||
} else {
|
||||
({!(_x getVariable [QGVAR(garrisonned), false]) && {!isPlayer _x}} count units _unit)
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
if ([_x, true] call _fnc_countGarrisonnedUnits == ({!isPlayer _x} count (units _x)) - 1 || {[_x, false] call _fnc_countGarrisonnedUnits == {!isPlayer _x} count (units _x)}) then {
|
||||
LOG("fnc_ungarrison: enableAttack true");
|
||||
(group _x) enableAttack true;
|
||||
};
|
||||
};
|
||||
} foreach _units;
|
1
addons/ai/functions/script_component.hpp
Normal file
1
addons/ai/functions/script_component.hpp
Normal file
@ -0,0 +1 @@
|
||||
#include "\z\ace\addons\ai\script_component.hpp"
|
@ -2,8 +2,8 @@
|
||||
#define COMPONENT_BEAUTIFIED AI
|
||||
#include "\z\ace\addons\main\script_mod.hpp"
|
||||
|
||||
// #define DEBUG_MODE_FULL
|
||||
// #define DISABLE_COMPILE_CACHE
|
||||
//#define DEBUG_MODE_FULL
|
||||
//#define DISABLE_COMPILE_CACHE
|
||||
// #define ENABLE_PERFORMANCE_COUNTERS
|
||||
|
||||
#ifdef DEBUG_ENABLED_AI
|
||||
|
21
addons/ai/stringtable.xml
Normal file
21
addons/ai/stringtable.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project name="ACE">
|
||||
<Package name="ai">
|
||||
<Key ID="STR_ACE_ai_GarrisonInvalidPosition">
|
||||
<English>Invalid position provided.</English>
|
||||
<French>Position invalide fourni</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_ai_GarrisonNoUnits">
|
||||
<English>No units provided.</English>
|
||||
<French>Aucune unité fourni</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_ai_GarrisonNotEnoughPos">
|
||||
<English>There aren't enough positions to place all units.</English>
|
||||
<French>Il n'y a pas assez de positions pour placer toutes les unités</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_ai_GarrisonNoBuilding">
|
||||
<English>No building found.</English>
|
||||
<French>Aucun bâtiment trouvé</French>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
@ -221,6 +221,20 @@ class CfgVehicles {
|
||||
function = QFUNC(moduleUnconscious);
|
||||
icon = QPATHTOF(UI\Icon_Module_Zeus_Unconscious_ca.paa);
|
||||
};
|
||||
class GVAR(moduleGarrison): GVAR(moduleBase) {
|
||||
curatorCanAttach = 1;
|
||||
category = QGVAR(AI);
|
||||
displayName = CSTRING(ModuleGarrison_DisplayName);
|
||||
curatorInfoType = QGVAR(RscGarrison);
|
||||
icon = QPATHTOF(UI\Icon_Module_Zeus_Garrison_ca.paa);
|
||||
};
|
||||
class GVAR(moduleUnGarrison): GVAR(moduleBase) {
|
||||
curatorCanAttach = 1;
|
||||
category = QGVAR(AI);
|
||||
displayName = CSTRING(ModuleUnGarrison_DisplayName);
|
||||
function = QFUNC(moduleUnGarrison);
|
||||
icon = QPATHTOF(UI\Icon_Module_Zeus_UnGarrison_ca.paa);
|
||||
};
|
||||
class GVAR(moduleToggleNvg): GVAR(moduleBase) {
|
||||
curatorCanAttach = 1;
|
||||
category = QGVAR(AI);
|
||||
|
@ -11,6 +11,7 @@ PREP(moduleAddSpareTrack);
|
||||
PREP(moduleAddSpareWheel);
|
||||
PREP(moduleAddOrRemoveFRIES);
|
||||
PREP(moduleCaptive);
|
||||
PREP(moduleGarrison);
|
||||
PREP(moduleGlobalSetSkill);
|
||||
PREP(moduleGroupSide);
|
||||
PREP(moduleLoadIntoCargo);
|
||||
@ -27,12 +28,14 @@ PREP(moduleTeleportPlayers);
|
||||
PREP(moduleToggleFlashlight);
|
||||
PREP(moduleToggleNvg);
|
||||
PREP(moduleUnconscious);
|
||||
PREP(moduleUnGarrison);
|
||||
PREP(moduleZeusSettings);
|
||||
PREP(showMessage);
|
||||
PREP(ui_attributeCargo);
|
||||
//PREP(ui_attributePosition);
|
||||
PREP(ui_attributeRadius);
|
||||
PREP(ui_defendArea);
|
||||
PREP(ui_garrison);
|
||||
PREP(ui_editableObjects);
|
||||
PREP(ui_globalSetSkill);
|
||||
PREP(ui_groupSide);
|
||||
|
@ -12,6 +12,8 @@ class CfgPatches {
|
||||
QGVAR(modulePatrolArea),
|
||||
QGVAR(moduleSearchArea),
|
||||
QGVAR(moduleSearchNearby),
|
||||
QGVAR(moduleGarrison),
|
||||
QGVAR(moduleUnGarrison),
|
||||
QGVAR(moduleTeleportPlayers),
|
||||
QGVAR(moduleToggleNvg),
|
||||
QGVAR(moduleToggleFlashlight),
|
||||
@ -23,7 +25,7 @@ class CfgPatches {
|
||||
};
|
||||
weapons[] = {};
|
||||
requiredVersion = REQUIRED_VERSION;
|
||||
requiredAddons[] = {"ace_common"};
|
||||
requiredAddons[] = {"ace_common", "ace_ai"};
|
||||
author = ECSTRING(common,ACETeam);
|
||||
authors[] = {"SilentSpike"};
|
||||
url = ECSTRING(main,URL);
|
||||
|
62
addons/zeus/functions/fnc_moduleGarrison.sqf
Normal file
62
addons/zeus/functions/fnc_moduleGarrison.sqf
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Author: alganthe
|
||||
* Module calling the garrison function.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Module logic <OBJECT>
|
||||
* 1: Position of the module <POSITION>
|
||||
* 2: Radius of the task <NUMBER>
|
||||
* 3: Filling mode of the garrison function <NUMBER>
|
||||
* 4: Enable or not top down filling <BOOL>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [LOGIC, [2203.64, 2281.47, 1], 20, 2, true] call ace_zeus_fnc_moduleUngarrison
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_logic", "_pos", "_radius" ,"_mode" , "_topDownMode", "_teleport"];
|
||||
|
||||
private _unit = (attachedTo _logic);
|
||||
private _building = nearestBuilding (getPosASL _unit);
|
||||
|
||||
// Handles errors
|
||||
scopeName "Main";
|
||||
private _fnc_errorAndClose = {
|
||||
params ["_msg"];
|
||||
deleteVehicle _logic;
|
||||
[_msg] call EFUNC(common,displayTextStructured);
|
||||
breakOut "Main";
|
||||
};
|
||||
|
||||
switch (false) do {
|
||||
case !(isNull _unit): {
|
||||
[LSTRING(NothingSelected)] call _fnc_errorAndClose;
|
||||
};
|
||||
case (_unit isKindOf "CAManBase"): {
|
||||
[LSTRING(OnlyInfantry)] call _fnc_errorAndClose;
|
||||
};
|
||||
case (alive _unit): {
|
||||
[LSTRING(OnlyAlive)] call _fnc_errorAndClose;
|
||||
};
|
||||
case (_unit distance _building < 500): {
|
||||
[LSTRING(BuildingTooFar)] call _fnc_errorAndClose;
|
||||
};
|
||||
};
|
||||
|
||||
private _units = units _unit;
|
||||
// Make sure all units are disembarked
|
||||
{
|
||||
if (vehicle _x != _x) then {
|
||||
moveOut _x;
|
||||
};
|
||||
} forEach _units;
|
||||
|
||||
[_pos, ["Building"], _units, _radius, _mode, _topDownMode, _teleport] call EFUNC(ai,garrison);
|
||||
|
||||
deleteVehicle _logic;
|
51
addons/zeus/functions/fnc_moduleUnGarrison.sqf
Normal file
51
addons/zeus/functions/fnc_moduleUnGarrison.sqf
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Author: alganthe
|
||||
* Un-garrison a garrisoned group.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Module logic <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [LOGIC] call ace_zeus_fnc_moduleUngarrison
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_logic"];
|
||||
|
||||
if (!local _logic) exitWith {}; // Module is global
|
||||
|
||||
scopeName "Main";
|
||||
private _fnc_errorAndClose = {
|
||||
params ["_msg"];
|
||||
deleteVehicle _logic;
|
||||
[_msg] call EFUNC(common,displayTextStructured);
|
||||
breakOut "Main";
|
||||
};
|
||||
|
||||
private _unit = effectiveCommander (attachedTo _logic);
|
||||
|
||||
switch (false) do {
|
||||
case !(isNull _unit): {
|
||||
[LSTRING(NothingSelected)] call _fnc_errorAndClose;
|
||||
};
|
||||
case (_unit isKindOf "CAManBase"): {
|
||||
[LSTRING(OnlyInfantry)] call _fnc_errorAndClose;
|
||||
};
|
||||
case (alive _unit): {
|
||||
[LSTRING(OnlyAlive)] call _fnc_errorAndClose;
|
||||
};
|
||||
case !(isPlayer _unit): {
|
||||
[LSTRING(OnlyNonPlayer)] call _fnc_errorAndClose;
|
||||
};
|
||||
};
|
||||
private _units = units _unit;
|
||||
|
||||
[QEGVAR(ai,unGarrison), [_units], _units] call CBA_fnc_targetEvent;
|
||||
|
||||
deleteVehicle _logic;
|
104
addons/zeus/functions/fnc_ui_garrison.sqf
Normal file
104
addons/zeus/functions/fnc_ui_garrison.sqf
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Author: alganthe
|
||||
* Initalises the "Garrison" zeus module display.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Garrison controls group <CONTROL>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* onSetFocus = "_this call ace_zeus_fnc_ui_garrison"
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
disableSerialization;
|
||||
|
||||
params ["_control"];
|
||||
|
||||
//Generic Init:
|
||||
private _display = ctrlparent _control;
|
||||
private _ctrlButtonOK = _display displayctrl 1; //IDC_OK
|
||||
private _logic = GETMVAR(BIS_fnc_initCuratorAttributes_target,objnull);
|
||||
TRACE_1("logicObject",_logic);
|
||||
|
||||
_control ctrlRemoveAllEventHandlers "setFocus";
|
||||
|
||||
// Handles errors
|
||||
private _unit = effectiveCommander (attachedTo _logic);
|
||||
|
||||
scopeName "Main";
|
||||
private _fnc_errorAndClose = {
|
||||
params ["_msg"];
|
||||
_display closeDisplay 0;
|
||||
deleteVehicle _logic;
|
||||
[_msg] call FUNC(showMessage);
|
||||
breakOut "Main";
|
||||
};
|
||||
|
||||
switch (false) do {
|
||||
case !(isNull _unit): {
|
||||
[LSTRING(NothingSelected)] call _fnc_errorAndClose;
|
||||
};
|
||||
case (_unit isKindOf "CAManBase"): {
|
||||
[LSTRING(OnlyInfantry)] call _fnc_errorAndClose;
|
||||
};
|
||||
case (alive _unit): {
|
||||
[LSTRING(OnlyAlive)] call _fnc_errorAndClose;
|
||||
};
|
||||
case !(isPlayer _unit): {
|
||||
[LSTRING(OnlyNonPlayer)] call _fnc_errorAndClose;
|
||||
};
|
||||
};
|
||||
|
||||
//Specific on-load stuff:
|
||||
private _listbox = _display displayCtrl 73063;
|
||||
{
|
||||
_listbox lbSetValue [_listbox lbAdd (_x select 0), _x select 1];
|
||||
} forEach [
|
||||
[localize LSTRING(ModuleGarrison_FillingModeEven), 0],
|
||||
[localize LSTRING(ModuleGarrison_FillingModeBuilding), 1],
|
||||
[localize LSTRING(ModuleGarrison_FillingModeRandom), 2]
|
||||
];
|
||||
|
||||
_listbox lbSetCurSel 0;
|
||||
|
||||
//Specific on-load stuff:
|
||||
(_display displayCtrl 73061) cbSetChecked (_logic getVariable ["TopDownFilling",false]);
|
||||
(_display displayCtrl 73062) cbSetChecked (_logic getVariable ["Teleport",false]);
|
||||
|
||||
private _fnc_onUnload = {
|
||||
params ["_display"];
|
||||
|
||||
private _logic = GETMVAR(BIS_fnc_initCuratorAttributes_target,objnull);
|
||||
if (isNull _logic) exitWith {};
|
||||
|
||||
deleteVehicle _logic;
|
||||
};
|
||||
|
||||
private _fnc_onConfirm = {
|
||||
params [["_ctrlButtonOK", controlNull, [controlNull]]];
|
||||
|
||||
private _display = ctrlparent _ctrlButtonOK;
|
||||
if (isNull _display) exitWith {};
|
||||
|
||||
private _logic = GETMVAR(BIS_fnc_initCuratorAttributes_target,objnull);
|
||||
if (isNull _logic) exitWith {};
|
||||
|
||||
private _lb = _display displayCtrl 73063;
|
||||
|
||||
private _radius = GETVAR(_display,GVAR(radius),50);
|
||||
private _position = GETVAR(_display,GVAR(position),getPos _logic);
|
||||
private _mode = _lb lbValue (lbCurSel _lb);
|
||||
private _TopDownFilling = cbChecked (_display displayCtrl 73061);
|
||||
private _teleport = cbChecked (_display displayCtrl 73062);
|
||||
|
||||
[_logic, _position ,_radius, _mode, _TopDownFilling, _teleport] call FUNC(moduleGarrison);
|
||||
};
|
||||
|
||||
_display displayAddEventHandler ["unload", _fnc_onUnload];
|
||||
_ctrlButtonOK ctrlAddEventHandler ["buttonclick", _fnc_onConfirm];
|
@ -1116,5 +1116,45 @@
|
||||
<Italian>Aggiungi equipaggiamento</Italian>
|
||||
<Japanese>装備を追加</Japanese>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleGarrison_DisplayName">
|
||||
<English>Garrison group</English>
|
||||
<French>Garnir zone</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleGarrison_TopDownFillingText">
|
||||
<English>Fill from top to bottom</English>
|
||||
<French>Remplir de haut en bas</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleGarrison_TopDownFillingTooltip">
|
||||
<English>Fill buildings from the highest position first</English>
|
||||
<French>Remplir les bâtiments par la position la plus haute d'abord</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleGarrison_FillingModeText">
|
||||
<English>Building filling mode</English>
|
||||
<French>Mode de remplissage de bâtiment</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleGarrison_FillingModeEven">
|
||||
<English>Even filling</English>
|
||||
<French>Remplissage égal</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleGarrison_FillingModeBuilding">
|
||||
<English>Building by building</English>
|
||||
<French>Bâtiment par bâtiment</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleGarrison_FillingModeRandom">
|
||||
<English>Random filling</English>
|
||||
<French>Remplir au hasard</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleGarrison_TeleportText">
|
||||
<English>Teleport</English>
|
||||
<French>Téléporter</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_OnlyNonPlayer">
|
||||
<English>Unit must not be a player</English>
|
||||
<French>L'unité ne doit pas être un joueur</French>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Zeus_ModuleUnGarrison_DisplayName">
|
||||
<English>Un-garrison group</English>
|
||||
<French>Dégarnir zone</French>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
BIN
addons/zeus/ui/Icon_Module_Zeus_Garrison_ca.paa
Normal file
BIN
addons/zeus/ui/Icon_Module_Zeus_Garrison_ca.paa
Normal file
Binary file not shown.
BIN
addons/zeus/ui/Icon_Module_Zeus_UnGarrison_ca.paa
Normal file
BIN
addons/zeus/ui/Icon_Module_Zeus_UnGarrison_ca.paa
Normal file
Binary file not shown.
@ -473,6 +473,81 @@ class RscDisplayAttributesVehicleEmpty: RscDisplayAttributes {
|
||||
};
|
||||
};
|
||||
|
||||
class GVAR(RscGarrison): RscDisplayAttributes {
|
||||
onLoad = QUOTE([ARR_3('onLoad', _this, QUOTE(QGVAR(RscGarrison)))] call FUNC(zeusAttributes));
|
||||
onUnload = QUOTE([ARR_3('onUnload', _this, QUOTE(QGVAR(RscGarrison)))] call FUNC(zeusAttributes));
|
||||
class Controls: Controls {
|
||||
class Background: Background {};
|
||||
class Title: Title {};
|
||||
class Content: Content {
|
||||
class Controls {
|
||||
class Garrison: RscControlsGroupNoScrollbars {
|
||||
onSetFocus = QUOTE(_this call FUNC(ui_garrison));
|
||||
idc = 73060;
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = W_PART(26);
|
||||
h = H_PART(8.5);
|
||||
class controls {
|
||||
class radius: GVAR(AttributeRadius) {};
|
||||
class TopDownFillingTitle: Title {
|
||||
idc = -1;
|
||||
text = CSTRING(ModuleGarrison_TopDownFillingText);
|
||||
toolTip = CSTRING(ModuleGarrison_TopDownFillingTooltip);
|
||||
x = 0;
|
||||
y = H_PART(1.2);
|
||||
w = W_PART(10);
|
||||
h = H_PART(1);
|
||||
colorBackground[] = {0,0,0,0.5};
|
||||
};
|
||||
class TopDownFilling: RscCheckBox {
|
||||
idc = 73061;
|
||||
x = W_PART(10.1);
|
||||
y = H_PART(1.2);
|
||||
w = W_PART(1);
|
||||
h = H_PART(1);
|
||||
};
|
||||
class TeleportTitle: Title {
|
||||
idc = -1;
|
||||
text = CSTRING(ModuleGarrison_TeleportText);
|
||||
x = 0;
|
||||
y = H_PART(2.3);
|
||||
w = W_PART(10);
|
||||
h = H_PART(1);
|
||||
colorBackground[] = {0,0,0,0.5};
|
||||
};
|
||||
class Teleport: RscCheckBox {
|
||||
idc = 73062;
|
||||
x = W_PART(10.1);
|
||||
y = H_PART(2.3);
|
||||
w = W_PART(1);
|
||||
h = H_PART(1);
|
||||
};
|
||||
class FillingModeTitle: RscText {
|
||||
idc = -1;
|
||||
text = CSTRING(ModuleGarrison_FillingModeText);
|
||||
x = 0;
|
||||
y = H_PART(3.5);
|
||||
w = W_PART(26);
|
||||
h = H_PART(1);
|
||||
colorBackground[] = {0,0,0,0.5};
|
||||
};
|
||||
class FillingMode: RscListbox {
|
||||
idc = 73063;
|
||||
x = 0;
|
||||
y = H_PART(4.5);
|
||||
w = W_PART(26);
|
||||
h = H_PART(4);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
class ButtonOK: ButtonOK {};
|
||||
class ButtonCancel: ButtonCancel {};
|
||||
};
|
||||
};
|
||||
|
||||
class GVAR(RscToggleNvg): RscDisplayAttributes {
|
||||
onLoad = QUOTE([ARR_3('onLoad', _this, QUOTE(QGVAR(RscToggleNvg)))] call FUNC(zeusAttributes));
|
||||
onUnload = QUOTE([ARR_3('onUnload', _this, QUOTE(QGVAR(RscToggleNvg)))] call FUNC(zeusAttributes));
|
||||
|
Loading…
Reference in New Issue
Block a user