Jump to content
Sign in to follow this  
khaosmatical

ARMA 3 Close Doors In Radius

Recommended Posts

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

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 by Larrow

Share this post


Link to post
Share on other sites

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 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

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×