Jump to content
Sign in to follow this  
ElectroEsper

Adding players to an array with condition?

Recommended Posts

Hi,

So here is my problem.

I'm trying to make a script that will simulate a mortar attack into a certain zone (that much actually work), and to do that will create an explosion at a random distance from a randomly selected player.

Now the problem is that I can't seem to find a way to reliably make it happen.

if (isServer) then {

_mortartype = "Sh_82mm_AMOS";
_time = _this select 0;
_mortarcrew = _this select 1;
_mortarpit = _this select 2;
_mortarzone = _this select 3;


//List of targets



//Run in loop until crew is dead.
while {alive _mortarcrew} do 
       {
        //Select a random target
	 _target = [{_x in list _mortarzone} count playableUnits];
	 _unit =  _target select floor random count _target;

                                //If the target is inside the "range" of the mortar and further away or equal to 20 meters, mortar "shoots".
	                 if (_unit in list _mortarzone && (_unit distance _mortarcrew) >= 20) then {

                                //Find the unit's location
                                _mortarLoc = (getPos _unit);
                                _mortarLocX = ((getPos _unit) select 0);
                                _mortarLocY = ((getPos _unit) select 1);
                                _mortarLocZ = ((getPos _unit) select 2);
                                _mortar = _mortartype createVehicle [_mortarLocX + random 150 - random 150, _mortarLocY + random 150 - random 150, _mortarLocZ + 30];
			_mortar setVelocity [0,0,-10];

                                                                //If the mortar shell is under 75 meters of the mortar, it is deleted to protect the mortar crew from FF.
                                                                if ((_mortar distance _mortarcrew) <= 75) then {
							         deleteVehicle _mortar;
							 };
							 sleep 1;
							 sleep _time + random _time - random _time;
					 }else {
					 sleep 0.01;
					 };



	 };

};

Now the part that causes the problem is this one:

       _target = [{_x in list _mortarzone} count playableUnits];
	 _unit =  _target select floor random count _target;

I also tried using this without better results...

_target = [];
{
 if ((isPlayer _x) && (_x in list _mortarzone) then {
   _target pushBack _x;
 }
} foreach playableUnits;
_unit =  _target select floor random count _target

Let me explain what I'm trying to do.

Simply said:

-I want to randomly select a player (that will then be _unit)

-But I want the script to only use players that are in the radius of a certain trigger (_mortarzone) for the randomization.

-Since its in a loop, the player selection will "refresh" then redo the "lottery" draw.

Now I went around and searched many thread on many forums and so far none have solved my issue.

I hope you can help me!

Have a good day.

Edited by ElectroEsper

Share this post


Link to post
Share on other sites

       
_target = [{_x in list _mortarzone} count playableUnits];	       
_unit =  _target select floor random count _target;

If you use count this way, you end up with _target being an array containing the number/amount of playableUnits that would be in _mortarZone. something like [2] for example, which causes the rest of your script to fall apart.

For your second try, I also recall some issue I had with the list command - in my case it was related to my onactivation/triggeractivation settings. JShock's advice is going to cure this, but if the area you're checking can be a circle... Why not use a marker (i.e. named "MortarCenter") instead of a trigger? A trigger will also have it's condition checked once per frame which I don't think is necessary in your case.

_targets = []; 
_mortarCenter = getmarkerpos "MortarCenter";
{ 
 if (isPlayer _x) then {
   if (_x distance _mortarCenter > 20) then {
      if (_x distance _mortarCenter < 500) then {       //replace 500 by whatever maxRange you like
         _targets pushBack _x; 
      };
   };
 };
} foreach playableUnits; 
_unit =  _targets select (floor random count _targets);

I may be coming across as a smartass when recommending performance saving and lazy eval but is still a good habit I guess.

Share this post


Link to post
Share on other sites

Ok, I made changes base on your answers and ended up with this.

15:24:57 Error in expression <t (floor random count _targets);  

if (_unit in list _mortarzone && (_unit dist>
15:24:57   Error position: <_unit in list _mortarzone && (_unit dist>
15:24:57   Error Undefined variable in expression: _unit
15:24:57 File C:\Users\William\Documents\Arma 3 - Other Profiles\Esper%20[AM%201]\missions\co45_rock_n_arrow_500.pja305\scripts\mortar_upgraded.sqf, line 39

Updated code:

if (isServer) then {

_mortartype = "Sh_82mm_AMOS";
_time = _this select 0;
_mortarcrew = _this select 1;
_mortarpit = _this select 2;
_mortarCenter = _this select 3;


//List of targets



//Run in loop until crew is dead or no player in range.
while {alive _mortarcrew} do 
       {
     //Select a random target
	 _targets = [];  
        _mortarPos = getmarkerpos _mortarCenter; 
       {  
               if (isPlayer _x) then { 
                       if (_x distance _mortarPos > 20) then { 
                               if (_x distance _mortarPos < 750) then {       //replace 750 by whatever maxRange you like 
                                   _targets pushBack _x;  
                               }; 
                       }; 
               }; 
       } foreach playableUnits;  
       _unit =  _targets select (floor random count _targets);  

	                 if (_unit in list _mortarzone && (_unit distance _mortarcrew) >= 20) then {   //<------ Line 39
	                         //Find the unit's location
                                _mortarLoc = (getPos _unit);
                                _mortarLocX = ((getPos _unit) select 0);
                                _mortarLocY = ((getPos _unit) select 1);
                                _mortarLocZ = ((getPos _unit) select 2);
							 _mortar = _mortartype createVehicle [_mortarLocX + random 150 - random 150, _mortarLocY + random 150 - random 150, _mortarLocZ + 30];
						     _mortar setVelocity [0,0,-10];
							 if ((_mortar distance _mortarcrew) <= 75) then {
							         deleteVehicle _mortar;
							 };
							 sleep 1;
							 sleep _time + random _time - random _time;
					 }else {
					 sleep 1;
					 };



	 };

};

I'm kind-of at the same state I was.

Any clue on why it does that?

Edit: Did some progress, was not testing in a MP environment so the game disliked it much. Now I'm on for more debuging, will ask if more help is needed. Thanks people :)

Edited by ElectroEsper

Share this post


Link to post
Share on other sites

Ok, now I made the whole script work properly, however there is a small problem with it.

Because of its nature the script run non-stop, creating monstruous RPT in a few seconds. So I would like to use WaitUntil the very line following

while {alive _mortarcrew} do

and make it "stop waiting" when x number of player enter the mortar range.

Now here I'm kind-of at a lost as to what to do.

I tried this:

waitUntil { {(isPlayer _x) && (_x in list _mortarRange)} count playableUnits >0 };

Do not work...

Hope you can help me again!

Thanks in advance.

Edit: Figured it out, had to write it this way...

waitUntil ({ {(isPlayer _x) && (_x in list _mortarRange)} count playableUnits >0 });

Edited by ElectroEsper

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  

×