Skip to content

Commit

Permalink
Improvements to taskGarrison and taskCamp (#414)
Browse files Browse the repository at this point in the history
Adds garrisoned units that are placed outside will appear to look out from building
Improves garrison behaviour when there are no outdoor locations (fixes issue #413)
Fixes units being teleported to building positions located in air
Fixes taskCamp units sometimes throwing double animation resets
Fixes taskCamp units failing to reset animations

--
Prefers using setVehiclePosition rather than setPos when placing units.  While more expensive, taskGarrison and taskCamp are not run frequently.  This neatly fixes many issues where units were spawned in the air (and fell to their deaths!)

With the new and improved eventhandlers reseting animations in taskCampReset is much more reliable. Therefore no need to run the function multiple times on all units.
  • Loading branch information
nk3nny authored Oct 14, 2024
1 parent 62abf80 commit 3dc43c4
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 22 deletions.
10 changes: 4 additions & 6 deletions addons/wp/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,10 @@ if (isServer) then {

[QGVAR(taskCampReset), {
params ["_unit"];
{
_x enableAI 'ANIM';
_x enableAI 'PATH';
[_x, _x getVariable [QGVAR(eventhandlers), []]] call EFUNC(main,removeEventhandlers);
_x setVariable [QGVAR(eventhandlers), nil];
} foreach (units _unit);
_unit enableAI 'ANIM';
_unit enableAI 'PATH';
[_unit, _unit getVariable [QGVAR(eventhandlers), []]] call EFUNC(main,removeEventhandlers);
_unit setVariable [QGVAR(eventhandlers), nil];
[_unit, "", 2] call EFUNC(main,doAnimation);
_unit setUnitPos "AUTO";
}] call CBA_fnc_addEventhandler;
Expand Down
6 changes: 3 additions & 3 deletions addons/wp/functions/fnc_taskCamp.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ reverse _units;
if ((_buildings isNotEqualTo []) && { RND(0.6) }) then {
_x setUnitPos "UP";
private _buildingPos = selectRandom ((_buildings deleteAt 0) buildingPos -1);
if (_teleport) then { _x setPos _buildingPos; };
if (_teleport) then { _x setVehiclePosition [_buildingPos, [], 0, "CAN_COLLIDE"]; };
_x doMove _buildingPos;
[
{
Expand Down Expand Up @@ -183,7 +183,7 @@ private _dir = random 360;
// teleport
if (_teleport) then {
_x setDir (_x getDir _pos);
_x setPos _campPos;
_x setVehiclePosition [_campPos, [], 0, "CAN_COLLIDE"];
};

// execute move
Expand Down Expand Up @@ -232,7 +232,7 @@ _wp setWaypointStatements ["true", "
{
_x enableAI 'ANIM';
_x enableAI 'PATH';
if (isNull objectParent _x) then {[_x, '', 2] call lambs_main_fnc_doAnimation;};
if (isNull objectParent _x && speed _x < 0.1) then {[_x, '', 2] call lambs_main_fnc_doAnimation;};
} foreach thisList;
};"
];
Expand Down
47 changes: 34 additions & 13 deletions addons/wp/functions/fnc_taskGarrison.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* 0: Group performing action, either unit <OBJECT> or group <GROUP>
* 1: Position to occupy, default group location <ARRAY or OBJECT>
* 2: Range of tracking, default is 50 meters <NUMBER>
* 3: Area the AI Camps in, default [] <ARRAY>
* 3: Area the AI garrisons, default [] <ARRAY>
* 4: Teleport Units to Position <BOOL>
* 5: Sort Based on Height <BOOL>
* 6: Exit Conditions that breaks a Unit free (-2 Random, -1 All, 0 Hit, 1 Fired, 2 FiredNear), default -2 <NUMBER>
Expand Down Expand Up @@ -51,18 +51,37 @@ private _weapons = nearestObjects [_pos, ["Landvehicle"], _radius, true];
_weapons = _weapons select { simulationEnabled _x && { !isObjectHidden _x } && { locked _x != 2 } && { (_x emptyPositions "Gunner") > 0 } };

// find buildings // remove half outdoor spots // shuffle array
private _houses = [_pos, _radius, true, false] call EFUNC(main,findBuildings);
_houses = _houses select { RND(0.5) || {lineIntersects [AGLToASL _x, (AGLToASL _x) vectorAdd [0, 0, 6]]}};
private _buildingPos = [_pos, _radius, true, false] call EFUNC(main,findBuildings);

if (_area isNotEqualTo []) then {
_area params ["_a", "_b", "_angle", "_isRectangle", ["_c", -1]];
_houses = _houses select { _x inArea [_pos, _a, _b, _angle, _isRectangle, _c] };
_buildingPos = _buildingPos select { _x inArea [_pos, _a, _b, _angle, _isRectangle, _c] };
_weapons = _weapons select {(getPos _x) inArea [_pos, _a, _b, _angle, _isRectangle, _c]};
};
[_houses, true] call CBA_fnc_Shuffle;

// sort based on height
private _outsidePos = [];
{
if !(lineIntersects [AGLToASL _x, (AGLToASL _x) vectorAdd [0, 0, 6]]) then {
_outsidePos pushBack _x;
};
} forEach _buildingPos;
_buildingPos = _buildingPos - _outsidePos;

// declare units
private _units = (units _group) select {!isPlayer _x && {isNull objectParent _x}};

// match inside positions to outside positions if possible.
if (count _units >= count _buildingPos) then {
_buildingPos append _outsidePos;
} else {
_buildingPos append ( _outsidePos select { RND(0.5) } );
};

// sort based on height or true random
if (_sortBasedOnHeight) then {
_houses = [_houses, [], { _x select 2 }, "DESCEND"] call BIS_fnc_sortBy;
_buildingPos = [_buildingPos, [], { _x select 2 }, "DESCEND"] call BIS_fnc_sortBy;
} else {
[_buildingPos, true] call CBA_fnc_Shuffle;
};

// orders
Expand All @@ -72,9 +91,6 @@ _group enableAttack false;
// set group task
_group setVariable [QEGVAR(main,currentTactic), "taskGarrison", EGVAR(main,debug_functions)];

// declare units + sort vehicles + tweak count to match house positions
private _units = (units _group) select {!isPlayer _x && {isNull objectParent _x}};

// add sub patrols
reverse _units;
if (_patrol) then {
Expand Down Expand Up @@ -126,7 +142,7 @@ if (_patrol) then {
_units = _units - [objNull];

// enter buildings
if (count _units > count _houses) then {_units resize (count _houses);};
if (count _units > count _buildingPos) then {_units resize (count _buildingPos);};
private _fnc_addEventHandler = {
params ["_unit", "_type"];
if (_type == 0) exitWith {};
Expand Down Expand Up @@ -191,16 +207,21 @@ private _fnc_addEventHandler = {
{
// prepare
doStop _x;
private _house = _houses deleteAt 0;
private _house = _buildingPos deleteAt 0;

// move and delay stopping + stance
if (_teleport) then {
if (surfaceIsWater _house) then {
_x doFollow (leader _x);
} else {
_x setPos _house;
_x setVehiclePosition [_house, [], 0, "CAN_COLLIDE"];
_x disableAI "PATH";
_x setUnitPos selectRandom ["UP", "UP", "MIDDLE"];

// look away from nearest building
if !([_x] call EFUNC(main,isIndoor)) then {
_x doWatch AGLtoASL (_x getPos [250, (nearestBuilding _house) getDir _house]);

Check notice on line 223 in addons/wp/functions/fnc_taskGarrison.sqf

View workflow job for this annotation

GitHub Actions / build

`AGLtoASL` does not match the wiki's case

non-standard command case
};
};
} else {
if (surfaceIsWater _house) exitWith {
Expand Down

0 comments on commit 3dc43c4

Please sign in to comment.