khaosmatical 237 Posted July 22, 2014 Hi there, I have created a CQB Town Clearance for training and have set AI up in buildings with waypoints. I got everything working fine besides the fact that the doors were left open by AI going into buildings which tells the player that someone was or is in there. I did look at this : http://forums.bistudio.com/showthread.php?101935-OA-Closing-all-The-doors-within-radius/page2 but I couldn't get it working. Any help would be appreciated! Thanks! Share this post Link to post Share on other sites
Larrow 2822 Posted July 22, 2014 (edited) OK admittedly not exactly what you want but your post sent me on a journey of discovery ;) This is a test piece and as such may have errors, you are forewarned. terminate h; h = [] spawn { if(isServer) then { { if (! isPlayer _x && isNil {_x getVariable "autodoor"}) then { systemChat format["adding autodoor to %1",_x]; _x setVariable ["autodoor", format ["SEH_ID_autodoor_%1",_x]]; [format ["SEH_ID_autodoor_%1",_x], "onEachFrame", { _unit = _this; if (alive _unit) then { _building = nearestBuilding _unit; _numDoors = getNumber (configFile >> "CFGVehicles" >> typeOf _building >> "numberOfDoors"); for "_doorNum" from 1 to _numDoors do { _doorPos = _building selectionPosition (format ["Door_%1_trigger", _doorNum]); _dist = (getPosATL _unit) distance (_building modelToWorld _doorPos); if (_dist <= 2 && isNil {_unit getVariable "autodoor_current"}) then { _unit setVariable ["autodoor_current", _doorNum]; [_building, _unit, _doorNum, _doorPos] spawn { _building = _this select 0; _unit = _this select 1; _doorNum = _this select 2; _doorPos = _this select 3; waitUntil {((getPosATL _unit) distance (_building modelToWorld _doorPos)) > 2}; _building animate [ format["door_%1_rot",_doorNum], 0]; _unit setVariable ["autodoor_current", nil]; }; }; }; }; }, _x] call BIS_fnc_addStackedEventHandler; }; }forEach allUnits; }; }; As a test create a mission place you and several men under your control. Paste and execute the script from the debugConsole and order your men into buildings and watch as the lazy b*stards close the doors behind them. Commented code //commented code terminate h; h = [] spawn { //Only on server if(isServer) then { //loop around all units in mission { //if its AI and is not already checking doors if (! isPlayer _x && isNil {_x getVariable "autodoor"}) then { systemChat format["adding autodoor to %1",_x]; //unit has EH applied to it _x setVariable ["autodoor", format ["SEH_ID_autodoor_%1",_x]]; //add event handler for checking each frame [format ["SEH_ID_autodoor_%1",_x], "onEachFrame", { //unit associated with this event _unit = _this; if (alive _unit) then { //nearest building to the unit _building = nearestBuilding _unit; //get the number of doors from the buildings config _numDoors = getNumber (configFile >> "CFGVehicles" >> typeOf _building >> "numberOfDoors"); //loop around all the doors for "_doorNum" from 1 to _numDoors do { //get the doors position within the building _doorPos = _building selectionPosition (format ["Door_%1_trigger", _doorNum]); //how far is the unit from this door _dist = (getPosATL _unit) distance (_building modelToWorld _doorPos); //if we are close to a door and not currently checking another recent door if (_dist <= 2 && isNil {_unit getVariable "autodoor_current"}) then { //store the current door we are checking _unit setVariable ["autodoor_current", _doorNum]; //spawn a new thread [_building, _unit, _doorNum, _doorPos] spawn { _building = _this select 0; _unit = _this select 1; _doorNum = _this select 2; _doorPos = _this select 3; //wait until the unit moves away from the door waitUntil {((getPosATL _unit) distance (_building modelToWorld _doorPos)) > 2}; //close the door _building animate [ format["door_%1_rot",_doorNum], 0]; //free the unit to check another door _unit setVariable ["autodoor_current", nil]; }; }; }; }; //pass unit to EH }, _x] call BIS_fnc_addStackedEventHandler; }; }forEach allUnits; }; }; Edited July 22, 2014 by Larrow Share this post Link to post Share on other sites
beno_83au 1369 Posted February 20, 2020 (edited) No one likes it people necro posts do they? So anyway, on an unrelated topic, I was trying to do this exact thing but I was applying checks and event handlers to buildings and doors, what a mess. I used @Larrow's example, but I guess time got the better of it because it fails. So I went through and reworked it, and I also added checks for locked doors. Now, if an AI tries to goes through a locked door it'll be unlocked, opened, closed then locked again. I also moved away from an OnEachFrame EH to a while loop. The EH slowed things down a lot when a few AI were around. And I store all AI units in a variable first, as opposed to looping through every unit while checking them for AI. Spoiler terminate h; h = [] spawn { if (isServer) then { //add all AI to array _aiUnits = allUnits select {!isPlayer _x}; //loop around all AI units in mission { //if it is not already checking doors if (isNil {_x getVariable "autodoor"}) then { //unit registered for checking doors (prevent running script twice on unit) _x setVariable ["autodoor",format["SEH_ID_autodoor_%1",_x]]; //spawn loop private _unit = _x; nul = [_unit] spawn { params ["_unit"]; //script will run until unit dies (roughly) while {alive _unit} do { //nearest building to the unit _building = nearestBuilding _unit; //get the number of doors from the buildings config _numDoors = getNumber (configFile >> "CFGVehicles" >> typeOf _building >> "numberOfDoors"); //loop around all the doors for "_doorNum" from 1 to _numDoors do { //get the doors position within the building _doorPos = _building selectionPosition (format["Door_%1_trigger",_doorNum]); //how far is the unit from this door _dist = (getPosATL _unit) distance (_building modelToWorld _doorPos); //if we are close to a door and not currently checking another recent door if (_dist <= 2 && isNil {_unit getVariable "autodoor_current"}) then { nul = [_building,_unit,_doorNum,_doorPos] spawn { params ["_building","_unit","_doorNum","_doorPos"]; //auto open (some doors don't open when AI go through them, crummy work around) _building animate [format["door_%1_rot",_doorNum],1]; //check door lock and unlock it if needed private _doorLocked = false; if ((_building getVariable format["bis_disabled_Door_%1",_doorNum]) == 1) then { _building setVariable [format["bis_disabled_Door_%1",_doorNum],0,true]; _doorLocked = true; }; //store the current door we are checking _unit setVariable ["autodoor_current",_doorNum]; //wait until the unit moves away from the door, or dies waitUntil {( ((getPosATL _unit) distance (_building modelToWorld _doorPos)) > 2) || (!alive _unit) }; if (!alive _unit) exitWith {}; //close the door _building animate [format["door_%1_rot",_doorNum],0]; //lock door if it was locked before being opened if (_doorLocked) then { _building setVariable [format["bis_disabled_Door_%1",_doorNum],1,true]; }; //free the unit to check another door _unit setVariable ["autodoor_current",nil]; }; }; }; //sleep to slow down script and hopefully help with script lag sleep 0.1; }; }; }; } forEach _aiUnits; }; }; I run it slightly differently, but I've substituted my edits into Larrow's example, so it should still work for anyone else looking for something like this. Edited February 20, 2020 by beno_83au Added dead check to exit the script if the AI dies while passing through the door Share this post Link to post Share on other sites