Jump to content
reggaeman007jah

Looking for advice on emptyPositions command

Recommended Posts

Hey folks, 

 

I have a system in my MP mission that uses emptyPositions command to find out how many free cargo slots a heli has, I then use this to inform my spawner, and spawn exactly that number of units (and get them to board the heli when it lands at base). This usually works without issue - until that is, players start to use that heli also. If I do an initial AI drop, then come back in to pick up and deploy players, on the next AI pickup I will spawn enough for the free slots but a few AI won't board. The number of refuseniks seems to correlate to the number of players I just deployed, so I am assuming this is bc somehow the players are still allocated to their cargo positions even though the emptyPositions shows them as empty. 

 

As I land with AI, I do the usual unassign heli stuff. Do I need, say, an EH (getOut, on the heli) that unassigns the unit if that unit is a player? Or is there an easier way to do this?

 

Cheers

Share this post


Link to post
Share on other sites

Not at the computer at this moment to double-check but in my experience emptyPositions only cares about currently occupied seats. Whether a unit is assigned should have no bearing on the result.

 

Hard to say more without seeing the relevant code.

 

Some things worth thinking about:

Have you checked the return of emptyPositions at the time of execution?

 

Are you sure the emptyPositions are counted when you expect them to?

 

Correlation does not prove causation and assumption is the mother of all fuck-ups.

 

 

Share this post


Link to post
Share on other sites

X) I will check all these things and come back to you. I will also post the poor excuse for SQF I have implemented, in case the answer to the issue lies in there.

 

Share this post


Link to post
Share on other sites

Alright here is the code. Apologies in advance to all here, it's not good, I know this. I scrabble together what I can and try to improve/refactor where I can. It does work for the most part, but yeah probably a painful read.

 

Firstly, I have a trigger area in the mission, activated (repeatedly) by players inside the trigger zone. On activation it does this:

call{if (CANBOARD) then { 
 [thisList] execVM "killchain\systems\boardingSystems\boardingIndifor.sqf"; 
};}

I should say here, I am execVM-ing things, I will turn these things into functions at some point, but anyway, next we have:

 

killchain\systems\boardingSystems\boardingIndifor.sqf

/* 
this script will be triggered when players land in a specific PZ at base 
it will:
- generate (nearby) reinforcement (RF) assets, and have them board the heli 
- it will generate only the number needed, no more, no less 

this script is triggered by an in-mission trigger, with this as the outcome of the trigger:

	call{if (CANBOARD) then { 
	[thisList] execVM "killchain\systems\boardingSystems\boardingIndifor.sqf"; 
	};}

CANBOARD is a global variable to inform whether the boarding / spawning action can take place 
it is useful in managing multiple pilots wishing to pick up AI 

*/

_passed = _this select 0; // thisList 

_pilot = _passed select 0; 
_heli = vehicle _pilot;

_freeCargoPositions = _heli emptyPositions "cargo";

[_freeCargoPositions, _heli] execVM "killchain\systems\boardingSystems\boardUnits.sqf"; 
CANBOARD = false;

 

Then we have a system to spawn the units and board them onto the waiting heli:

killchain\systems\boardingSystems\boardUnits.sqf

_freeCargoPositions = _this select 0;
_heli = _this select 1;

_spawn = [8478.22,6580.77]; // specific mission-based spawn point;
_float = diag_tickTime;
_stampToString = str _float;
_stampToString = createGroup [independent, true];
_stampToString setFormation "DIAMOND";

_classes = [
	"LOP_PESH_IND_Infantry_SL",
	"LOP_PESH_IND_Infantry_TL",
	"LOP_PESH_IND_Infantry_Corpsman",
	// etc 
],

_cargo = [];

for "_i" from 1 to _freeCargoPositions do {
	_class = selectRandom _classes;
	_unit = _stampToString createUnit [_class, _spawn, [], 0.1, "none"]; 
	tinmanModule addCuratorEditableObjects [[_unit], true];
	bluforZeus addCuratorEditableObjects [[_unit], true];
	_unit assignAsCargo _heli;
	[_unit] orderGetIn true;
	_cargo pushBack _unit;
	sleep 0.3;
};

_checkCanRedeploy = true;
while {_checkCanRedeploy} do {
	_heliPos = getPos _heli;
	_distance = _heliPos distance [8529.09,6579.64,0];
	if (_distance > 30) then {
		_checkCanRedeploy = false;
	};
	sleep 5;
};

CANBOARD = true;
[_heli, _cargo] execVM "killchain\systems\boardingSystems\checkDeploy.sqf";

 

And lastly we have a system to track whether the heli should deploy cargo - it checks firstly whether you are in the mission zone (marker), and when yes, checks whether you are on the ground stationary, and when you are it auto-unboards cargo:

killchain\systems\boardingSystems\checkDeploy.sqf

// this checks for altitude, and if in mission AO, will deploy troops off heli onto ground 
// automatically when heli has landed 

_heli = _this select 0;
_cargo = _this select 1;

_redCheck = true; // used to check if the heli is in the mission AO (i.e. redzone)
_altCheck = false; // when confirmed as in AO (dropzone), this is used to track AGL 

while {_redCheck} do {
	systemChat "_redCheck - not in redzone";
	if (isEngineOn _heli) then {
		_pos = getPos _heli;  
		_inRed = _pos inArea "redzone";
		if (_inRed) then {
			_redCheck = false;
			_altCheck = true;
			systemChat "_redCheck - heli is in redzone - switching to alt-check";
		};
	} else {
		// this should shut everything down if the engine is turned off
		_redCheck = false;
	};
	sleep 10;
};

while {_altCheck} do {
	systemChat "_altCheck running as heli is in redzone";

	if (isEngineOn _heli) then {
		_atl1 = (getPosATL _heli) select 2;
		_atl1 = round _atl1;

		if ((_atl1) < 2.5) then {

			// we need to ensure heli is not only low, but also stationary before unloading 
			_speed = speed _heli;
			if (_speed < 1) then {
				systemChat "debug - speed is less than 1";
				systemChat format ["_cargo: %1", _cargo];
				sleep 1;
				if (_speed < 1) then {
					// second speed check is to ensure heli is not bouncing around 
					_markerName = str _heli; 
					systemChat format ["_markerName: %1", _markerName];
					_extractLocation = position _heli;
					_extractMarker = createMarker [_markerName, _extractLocation];
					_extractMarker setMarkerShape "ELLIPSE";
					_extractMarker setMarkerColor "ColorRed";
					_extractMarker setMarkerSize [20, 20];

					sleep 1;

					{
						unassignVehicle _x;
						systemChat format ["Unassigning unit: %1", _x];
						sleep 1;
					} forEach _cargo;

					_units = allUnits inAreaArray _markerName;
					_units orderGetIn false;

					_dataStore = [];
					{
						if ((side _x) == INDEPENDENT) then { _dataStore pushback _x }
					} forEach allPlayers;

					_cnt = count _dataStore;
					if (_cnt == 1) then {
						// there is an indifor player in game - move to player pos 
						_commander = _dataStore select 0;
						_commPos = getPos _commander;
						{
							_x setBehaviour "COMBAT";
							_x move _commPos;
						} forEach _units;
					} else {
						// no indifor player in game - move AI to obj pos 
						systemChat "confirmed - no indifor player in game";
						_movePos = getMarkerPos 'REDZONE';
						_units = allUnits inAreaArray _markerName;
						_cargoCount = count _cargo;
						systemChat format ["_cargoCount: %1", _cargoCount];

						for "_i" from 1 to 4 do {
							_freeCargoPositions = _heli emptyPositions "cargo";
							systemChat format ["Empty positions: %1", _freeCargoPositions];
							_cargoCount = count _cargo;
							if (_freeCargoPositions >= _cargoCount) then {
								systemChat "heli is empty";
							};
							sleep 5;
						};

						systemChat "check has finished";
						sleep 5;
						systemChat "move orders ...";
						{
							_x setBehaviour "COMBAT";
							_x doMove _movePos;
							systemChat format ["Unit %1 moving to %2", _x, _movePos];	
							sleep 1;
						} forEach _cargo;
					};
					_altCheck = false;
					deleteMarker _markerName;
				};
			};
		};
	} else {
		// this should shut everything down if the engine is turned off
		_altCheck = false;
	};
	sleep 2;
};

 

Share this post


Link to post
Share on other sites

first of all thisList refers to a preset condition trigger (like BLUFOR PRESENT) and returns infantry and vehicles. For a helo, it returns the helo, not the pilot (except if you set trigger owner on the pilot itself (editor). So, the question is: are you sure thislist always returns the pilot of the helo as 1st element of this array? 

You should consider a simple: driver yourHelo  along with yourHelo inArea thisTrigger

  • Like 1

Share this post


Link to post
Share on other sites

Hey man, thanks for the thoughts on this. I will of course check this, but this collection of scripts seems to work without issues when just boarding AI, it is the inclusion of players into the mix that seems to mess up the boarding numbers.

Share this post


Link to post
Share on other sites

So, re-checking the trigger, I am looking for 'any players'. So the return from thisList is the player.

 

_passed = _this select 0; // thisList 

_pilot = _passed select 0; 
_heli = vehicle _pilot;

_freeCargoPositions = _heli emptyPositions "cargo";

So the above takes the player caught in the trigger, and puts it into 'thisList'. thisList select 0 grabs the name of the player, and from there I get the heli the player is in. I then get the free cargo slots of that heli, and use that number as an informer to the spawner part of the process, i.e. only spawning the number of units equal to the number of free slots. 

 

This all works fine most of the time, but as soon as players start using the same heli, there seems to be an issue caused whereby units are spawned (according to the number of free cargo slots), but not all of them get in. So, my theory is that when a player gets out their seat is somehow still assigned to them on exit? And this leftover assignment is stopping the AI from boarding. I hope that all makes sense.

 

Any ideas? 

Share this post


Link to post
Share on other sites

So I now know (at least I think this is right) that players in MP do not unassign themselves when leaving vehicles, and remain assigned to (say) a heli seat even after disembarking, and only changing/updating when they get into another vehicle. 

 

I thought I could use a getOut EH to unassign the player manually as they get out, but that didn't solve the issue. Any ideas anyone?

Share this post


Link to post
Share on other sites

 

And something like;

 

waituntil {(0 >= count ((Cargo _Truck)-[TruckDriver]))};

 

waituntil {(0 >= count ((crew _Truck)-[TruckDriver]))};

 

waituntil {(0 >= count ((Cargo _Truck)+[TruckDriver]))};

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Precision paradrop:   https://steamcommunity.com/sharedfiles/filedetails/?id=2424757668

Share this post


Link to post
Share on other sites

Hey folks, 

 

So after some experimentation, I've come to realise that players, when leaving a vehicle, will remain assigned to that vehicle up until the point they enter a new vehicle. In the above script I manually unassign AI when they disembark, but I guess players don't have the unassign carried out on them automatically when they exit vehicles. So my hacky workaround was to add a getOut EH on the relevant helis, and ifPlayer, reassign them to another vehicle. Not elegant, but it works, now no more AI boarding issues 🙂

 

Thanks everyone for taking the time to try and assist with this.

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

×