Jump to content
codeivo

Automated Crew Creation issue

Recommended Posts

So i'm building a randomly self-generating scenario of a sort, and i'm trying to spawn a vehicle around the player and fill it with one crew at a time until it is filled, then spawn and fill another vehicle until there are 3 vehicles full, replacing the dead units with each loop aswell.

To acomplish it I put a while-true loop with this: a condition to spawn a vehicle if there are less than my 3 vehicles limit, and a foreach loop for every one of my already spawned vehicles. inside the foreach I check if the crew is empty to create one.

Now, I want to create a new crew when the old crew is dead, but crew, fullCrew, assigned, etc seem to only if they are inside the vehicle. I figured I would add each vehicle's unit into an array just as I am creating them, then check if anybody is alive in that array at the end of the loop so that then it would clear the array and the condition could run and create their replacements. I believe that for it to work each array should be private/local to it's own foreach loop, and that for it to exist outside the scope where it creates units I should define the empty array before it, at the start of each foreach loop; but then that would mean that every time it loops back the array gets cleared, thus creating more units forever since it take it as the cleared array means they died. I tried conditioning the first array declaration with isNil but  then it is private to that condition's scope and don't exist outside of it. I could just make the array global scoped containing all crew teams with a reference to their each own vehicles but it doesn't seem as correct also I'm afraid to overwriting local variables and whatnot.

Please help, this is my first time coding and have been able to work my way through it by reading old posts and the wiki, but I have trouble with this snippet.
 

[] spawn {           
_fleet = [];           
_limit = 1; 
_blacklist = []; 
while {true} do {  
sleep 1;   
 
  
if ((count (_fleet)) < _limit) then {      
veh = createVehicle ["O_G_Offroad_01_armed_F",(position player), [], 15, "NONE"];           
_fleet pushBack veh;         
}; 
  
         
{           
_crew = []; 
 
if ( !(_x in _blacklist) ) then { 
for "_i" from 1 to 3 do { 
sleep 1;
_crewmate = (createGroup east) createUnit ["O_soldier_F", (getPos _x) , [], 0, "NONE"]; 
_crewmate moveInAny _x; 
_crew pushBack _crewmate; 
};   
_blacklist pushBack _x; 
}; 

_check = count(_crew select {alive _x}); 


comment "if ( _check == 0 ) then { _blacklist deleteAt (_blacklist find _x);}; ";
 
 
} forEach _fleet;    
    
       
       
};         
}; 
 
 

I only spawn one vehicle in the code (variable _limit) because I want to have it working well on a single vehicle crew.
Also commented out the last line where it makes able for a new crew to be created because otherwise units would be created infinitely probably causing  a crash.

Thanks a lot!

Share this post


Link to post
Share on other sites
Posted (edited)

@codeivo,

Here's a working example of your request,

Spoiler

you_vehicle_crew={
	comment "this EH replaces dead crew";
	you_crew_handle= {
		{
		_x addEventHandler ["Killed", {
			params ["_unit", "_killer", "_instigator", "_useEffects"];
			_unit removeEventHandler ["killed", _thisEventHandler];
			private _veh = vehicle _unit;
			if (alive _veh) then {
				deleteVehicle _unit;
				_veh spawn { sleep (round random 5) +5;
					private	_grp=createVehicleCrew _this;
					_grp call you_crew_handle
				}
			}
		}]
		}forEach units _this
	};

	comment "this EH replaces destroyed vehicles";
	you_veh_handle={
		_this addEventHandler ["Killed", {
			params ["_unit", "_killer", "_instigator", "_useEffects"];
			_unit removeEventHandler ["killed", _thisEventHandler];
			private _arr = missionNameSpace getVariable ["_fleet", []];
			private _spawn_params= missionNameSpace getVariable ["_veh_spawn_params", []];
			_arr = _arr - [_unit];
			missionNameSpace setVariable ["_fleet", _arr];
			_spawn_params call you_vehicle_crew
		}]
	};

	comment "these parameters define the center object, desired count and vehicle type";
	params [["_caller", player], ["_count", 3], ["_type", "O_G_Offroad_01_armed_F"]];

	while {count (missionNameSpace getVariable ["_fleet", []])< _count} do {
		missionNameSpace setVariable ["_veh_spawn_params", _this];
		private _veh = createVehicle [_type, position _caller, [], 15, "NONE"]; 
		private _grp = createVehicleCrew _veh;
		private _arr = missionNameSpace getVariable ["_fleet", []];
		_arr pushBack _veh;
		missionNameSpace setVariable ["_fleet", _arr];
		_veh call you_veh_handle;
		_grp call you_crew_handle
	}
};


[this] call you_vehicle_crew

pasted in init of unit or center object

* maintain number of vehicles at center
* default number = 3, default center = player

Have fun!

Edited by wogz187
simplified, converted to call
  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Thank you so much wogz, I also ended up coming with a solution while checking your code (I'm still getting familiar with EHs).
I just set the forEach's target to both the vehicle and it's crew instead of just the vehicle, and it all came together.

here's how it ended up.
 

[] spawn {            
_fleet = [];            
_limit = 3;  
 
while {true} do {   
sleep 1;    
   
if ((count (_fleet)) < _limit) then {       
veh = createVehicle ["O_G_Offroad_01_armed_F",(position player), [], 15, "NONE"];            
_fleet pushBack [veh,[]];          
};  
          
{            

if (  (count((_x select 1) select {alive _x})) < 3 ) then {  
{moveOut _x;} forEach ((crew (_x select 0)) select { !alive _x }); 
sleep 1; 
_crewmate = (createGroup east) createUnit ["O_soldier_F", (getPos (_x select 0)) , [], 0, "NONE"];  
_crewmate moveInAny (_x select 0);  
(_x select 1) pushBack _crewmate;  
};  
 
if (!((damage (_x select 0)) < 1)) then { _fleet deleteAt (_forEachIndex); };   

} forEach _fleet;     
       
};          
};  
  
  

cheers Master Sergeant, from a designer aswell and hopefully future developer too.

 

  • Like 1

Share this post


Link to post
Share on other sites

@codeivo,

Quote

(I'm still getting familiar with EHs)

Event handlers are very important. General rule: if you can use an EH then do use an EH. Since event handlers only fire at the event they are almost always the most performant solution.

See also: mission event handlers and MP specific MP event handlers

Your while loop will be running continuously throughout the mission which, in this case, is totally preventable.

Use parameters,

[] spawn {            
_fleet = [];            
_limit = 3;  

By defining your parameters outside of the script you can customize the function with a spawn/call array instead of just leaving it blank (useless).

[[], 3, player] spawn { params ["_fleet", "_limit", "_caller"];
// code
}

And by defining default parameters the script will fallback to that variable when nothing is provided,

[[], 3] spawn { params [["_fleet", []], ["_limit", 3], ["_caller", player]];
_caller sideChat "I'm the player!"
}

Instead of bool for your loop condition use a  variable you can control,

missionNameSpace setVariable ["_do_loop", true];
while {sleep 1; missionNameSpace getVariable ["_do_loop", false]} do { //code};

missionNameSpace setVariable ["_do_loop", false]; //to exit above loop

You can use waitUntil in a similar way,

waitUntil { sleep 1; if (missionNameSpace getVariable ["_do_loop", false]) then {//code; true} else {false}} // return false to continue waiting, true to exit

I didn't do this in the script above because the loop will exit within a few frames of execution. Instead we rely on the event handler to reinitialize the function when needed. This could have been an iteration instead of a loop. Since we could have used any of 3 methods (while, waitUntil, for _i) perhaps somebody else wants to weigh in as to which solution is best for this situation, or perhaps it really doesn't matter.

Have fun!

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Thanks a lot man, love this community.

Yeah, the snippet is actually going to be spawned as a function, with the "center" parameter being one of three opfor hq, and an !alive boss condition to exit the script. The main block where I create the ai and made them occupy an area is also randomized which is why I want to make it modular and as simple as I can. Now, the continuosly looping is actually on purpose, since I want to spawn each ai every 5 mins so I encounter a considerable enemy force grown on unpatrolled areas. Also dumbed down the code to understand better myself how to make it work, while removing irrelevant parts from the post aswell.

I will probably add the killed EH just want to really wrap my head around it's structure and the way it is implemented in the script first.

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

×