From 3db860b00369a2e076eb570673d09f1415943351 Mon Sep 17 00:00:00 2001 From: Ken Mikkelsen Date: Wed, 9 Oct 2024 21:35:49 +0200 Subject: [PATCH] Improvements to taskGarrison and taskCamp 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. --- addons/wp/XEH_preInit.sqf | 10 ++--- addons/wp/functions/fnc_taskCamp.sqf | 6 +-- addons/wp/functions/fnc_taskGarrison.sqf | 47 +++++++++++++++++------- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/addons/wp/XEH_preInit.sqf b/addons/wp/XEH_preInit.sqf index 7ced66ec..d4f406a8 100644 --- a/addons/wp/XEH_preInit.sqf +++ b/addons/wp/XEH_preInit.sqf @@ -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; diff --git a/addons/wp/functions/fnc_taskCamp.sqf b/addons/wp/functions/fnc_taskCamp.sqf index 15e276a2..b62f9989 100644 --- a/addons/wp/functions/fnc_taskCamp.sqf +++ b/addons/wp/functions/fnc_taskCamp.sqf @@ -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; [ { @@ -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 @@ -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; };" ]; diff --git a/addons/wp/functions/fnc_taskGarrison.sqf b/addons/wp/functions/fnc_taskGarrison.sqf index 1c3e728c..c758dcc9 100644 --- a/addons/wp/functions/fnc_taskGarrison.sqf +++ b/addons/wp/functions/fnc_taskGarrison.sqf @@ -10,7 +10,7 @@ * 0: Group performing action, either unit or group * 1: Position to occupy, default group location * 2: Range of tracking, default is 50 meters - * 3: Area the AI Camps in, default [] + * 3: Area the AI garrisons, default [] * 4: Teleport Units to Position * 5: Sort Based on Height * 6: Exit Conditions that breaks a Unit free (-2 Random, -1 All, 0 Hit, 1 Fired, 2 FiredNear), default -2 @@ -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 @@ -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 { @@ -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 {}; @@ -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]); + }; }; } else { if (surfaceIsWater _house) exitWith {