Jump to content

Recommended Posts

Hi all,

 

Just starting off getting into scripting in Arma 3, so this might be a simple thing.

 

Trying to have a civilian spawn in a loop.

Scenario is that players are assaulting a tower block, whilst civilians are running the opposite way in a steady stream.

  1. Spawned at point A
    1. Using  
      civ = createVehicle ["CUP_C_TK_Man_04",getMarkerPos "spawnciv",[], 0];

      Giving it a waypoint to point B - for some reason this isn't working as there is a "generic error"? 

      _wp1 = civ addWaypoint [getmarkerpos "wyptciv", 0]; _wp1 setWaypointType "MOVE"; _wp1 setWaypointSpeed "FULL"; _wp1 setWaypointBehaviour "CARELESS";

       

  2. When it reaches point B
    1. Using
      deleteGroup civ;

       

Would like it to then respawn at position A and repeat.

I will be having a reasonable amount of civilians so need to try make it performance friendly also; so it would be helpful if they wouldn't spawn whilst the players are outside the trigger zone. I understand this can be done using the "Repeatable" and "Server Only" options in triggers. 

Would it be as simple as player present option?

 

Many Thanks,

Aurora

Share this post


Link to post
Share on other sites

You are trying to add a waypoint to a unit, while addWaypoint requires a group.

 

deleteGroup deletes the group reference, not the units therein. If there are living units in the group, the command does nothing.
 

Use createUnit to create "man" units. Using createVehicle will create units that don't move and to which you can not add waypoints.

 

0 = [] spawn { 
    while {true} do { 
        _group = createGroup [civilian, true]; 
        AUR_civ = _group createUnit ["CUP_C_TK_Man_04", getMarkerPos "spawnciv", [], 0, "NONE"]; 
        _wp1 = _group addWaypoint [getmarkerpos "wyptciv", 0];  
        _wp1 setWaypointType "MOVE";  
        _wp1 setWaypointSpeed "FULL";  
        _wp1 setWaypointBehaviour "CARELESS"; 
        _wp1 setWaypointStatements ["true", "deleteVehicle AUR_civ;"]; 
        waitUntil { 
            ({alive _x} count units _group) < 1; 
        }; 
    }; 
};

You don't need to spawn it, but it will run infinitely this way. If you just call the while loop, it will stop after 10,000 iterations.

 

You can change the condition of the while loop to a variable that you are switching true/false with your trigger.

 

Something that is unclear is how many civilians you want making this trip at one time. Currently, there is only one unit being spawned at a time.

  • Like 3

Share this post


Link to post
Share on other sites

BTW, I'm garbage with writing code, so use my example as a means to possibly understand a few things rather than a solution.

Share this post


Link to post
Share on other sites

Always use a sleep on waitUntil, otherwise it is checking the conditions on every frame and that is not really needed in this case (and most cases).

 

waitUntil {sleep (1 + (random 1)); (({alive _x} count units _group) < 1)};

 

Also, while (true) is not recommended. All loops should have an exit condition unless your mission will last less than an hour.

  • Like 3

Share this post


Link to post
Share on other sites
On 5/24/2020 at 10:23 PM, LSValmont said:

otherwise it is checking the conditions on every frame

At most every frame, rarely actually every frame.

 

On 5/24/2020 at 10:23 PM, LSValmont said:

+ (random 1)

That random is really just unnecessary overhead.

  • Like 3

Share this post


Link to post
Share on other sites
2 hours ago, Dedmen said:

At most every frame, rarely actually every frame.

Yeah, it tries to check every frame 😃 

 

2 hours ago, Dedmen said:

That random is really just unnecessary overhead.

The random part is so that it dos not hit the server at almost the same time if you run the spawn on many objects/units simultaneously. (a spawn inside a call for example).

 

In this case for example if you have 20 waitUntils executed at the same time all with a sleep of 1 is the same as having them with no sleep at all since it is checking all at basically the same time anyway, making it easier to overload the scheduler.

 

So I believe that random does help reduce that chance of overloading. (In some very specific cases)

 

Share this post


Link to post
Share on other sites
53 minutes ago, LSValmont said:

So I believe that random does help reduce that chance of overloading. (In some very specific cases)

I believe you won't even notice 200 of those checks happening at the same time.

:yay:

 

Cheers

  • Like 1

Share this post


Link to post
Share on other sites
3 hours ago, Grumpy Old Man said:

I believe you won't even notice 200 of those checks happening at the same time.

:yay:

 

Cheers

 

Yeah but it is a good practice never the less, so if you have something like this:

waitUntil {
	sleep (2 + (random 6));
    _seenBy = allUnits select {_x distance P1 < 500 || {(_x distance _pos < 1000 && {([_x,"VIEW"] checkVisibility [eyePos _x, getPosASL P1]) > 0.5})}};
	(_seenBy isEqualTo [])
};

I bet if you spawn more than 10 of these at the same time without that random 6 your server will certainly feel it.

 

So it all depends on what your are checking, but as you said on most instances it is not necessary thou. 😉 

Share this post


Link to post
Share on other sites
14 hours ago, LSValmont said:

Yeah but it is a good practice never the less

I disagree.

 

14 hours ago, LSValmont said:

I bet if you spawn more than 10 of these at the same time without that random 6 your server will certainly feel it.

The scheduler is limited to 3ms per frame anyway and if you exceed that, all other scripts will run before yours gets its next timeframe. Soo.. not really.

And due to that fact, any sleep is already so imprecise, that the stuff won't run all at once anyway.

  • Like 1

Share this post


Link to post
Share on other sites
9 hours ago, Dedmen said:

I disagree.

 

The scheduler is limited to 3ms per frame anyway and if you exceed that, all other scripts will run before yours gets its next timeframe. Soo.. not really.

And due to that fact, any sleep is already so imprecise, that the stuff won't run all at once anyway.

 

Well I can no longer argue with that!

 

Your insider status serves you well!

 

Thank you for taking your time in clearing that up!

Share this post


Link to post
Share on other sites
6 hours ago, Dedmen said:

 

That my friend should be pinned here on the EDITING forums! 😉 

How does remoteExec comes to play inside the scheduler? It works exactly like an ExecVM?

 

So if I change all my scripts to non scheduled and just use CBA's waitAndExecute as a sleep do you think overall performance will improve or that would not necessarily mean a better experience?

  • Like 1

Share this post


Link to post
Share on other sites
On 5/24/2020 at 8:28 PM, Harzach said:

You are trying to add a waypoint to a unit, while addWaypoint requires a group.

 

deleteGroup deletes the group reference, not the units therein. If there are living units in the group, the command does nothing.
 

Use createUnit to create "man" units. Using createVehicle will create units that don't move and to which you can not add waypoints.

 


0 = [] spawn { 
    while {true} do { 
        _group = createGroup [civilian, true]; 
        AUR_civ = _group createUnit ["CUP_C_TK_Man_04", getMarkerPos "spawnciv", [], 0, "NONE"]; 
        _wp1 = _group addWaypoint [getmarkerpos "wyptciv", 0];  
        _wp1 setWaypointType "MOVE";  
        _wp1 setWaypointSpeed "FULL";  
        _wp1 setWaypointBehaviour "CARELESS"; 
        _wp1 setWaypointStatements ["true", "deleteVehicle AUR_civ;"]; 
        waitUntil { 
            ({alive _x} count units _group) < 1; 
        }; 
    }; 
};

You don't need to spawn it, but it will run infinitely this way. If you just call the while loop, it will stop after 10,000 iterations.

 

You can change the condition of the while loop to a variable that you are switching true/false with your trigger.

 

Something that is unclear is how many civilians you want making this trip at one time. Currently, there is only one unit being spawned at a time.

 

Just tried this out an it works! 

I would be wanting to have between 21 units, one for each "class" of civilian. The civilians would have to spawn with an interval so there isn't just one big rush of people every minute or so.

I tried creating an array of all the  units but didn't seem to work?

0 = [] spawn { 
    while {true} do { 
        _group = createGroup [civilian, true]; 
        AUR_civ = _group createUnit [{"CUP_C_TK_Man_04","CUP_C_TK_Man_04_Jack","CUP_C_TK_MAN_04_Waist","CUP_C_TK_Man_07","CUP_C_TK_Man_07_Coat","CUP_C_TK_Man_07_Waist","CUP_C_TK_Man_08","CUP_C_TK_Man_07_Jack","CUP_C_TK_Man_07_Waist","CUP_C_TK_Man_05_Coat","CUP_C_TK_Man_07_Waist","CUP_C_TK_Man_06_Coat","CUP_C_TK_Man_06_Jack","CUP_C_TK_Man_06_Waist","CUP_C_TK_Man_02","CUP_C_TK_Man_02_Waist","CUP_C_TK_Man_01_Waist","CUP_C_TK_Man_01_Coat","CUP_C_TK_Man_03_Coat","CUP_C_TK_Man_03_Jack","CUP_C_TK_Man_03_Waist"}, getMarkerPos "spawnciv", [], 0, "NONE"]; 
        _wp1 = _group addWaypoint [getmarkerpos "wyptciv", 0];  
        _wp1 setWaypointType "MOVE";  
        _wp1 setWaypointSpeed "FULL";  
        _wp1 setWaypointBehaviour "CARELESS"; 
        _wp1 setWaypointStatements ["true", "deleteVehicle AUR_civ;"]; 
        waitUntil { 
            ({alive _x} count units _group) < 1; 
        }; 
    }; 
};

Any ideas on how to get that bit working.

Thank you everyone for your help so far! 🙂

 

Regards,

Aurora

Share this post


Link to post
Share on other sites

Well, sqf is a language with rules. You can't just jam a bunch of stuff together like that. Your "array" is in curled brackets - arrays use square brackets. Regardless, createUnit does not take an array for type. 

AUR_spawn = [] spawn { 

    AUR_civ_array = 
	[
	"CUP_C_TK_Man_04",
	"CUP_C_TK_Man_04_Jack",
	"CUP_C_TK_MAN_04_Waist",
	"CUP_C_TK_Man_07",
	"CUP_C_TK_Man_07_Coat",
	"CUP_C_TK_Man_07_Waist",
	"CUP_C_TK_Man_08",
	"CUP_C_TK_Man_07_Jack",
	"CUP_C_TK_Man_07_Waist",
	"CUP_C_TK_Man_05_Coat",
	"CUP_C_TK_Man_07_Waist",
	"CUP_C_TK_Man_06_Coat",
	"CUP_C_TK_Man_06_Jack",
	"CUP_C_TK_Man_06_Waist",
	"CUP_C_TK_Man_02",
	"CUP_C_TK_Man_02_Waist",
	"CUP_C_TK_Man_01_Waist",
	"CUP_C_TK_Man_01_Coat",
	"CUP_C_TK_Man_03_Coat",
	"CUP_C_TK_Man_03_Jack",
	"CUP_C_TK_Man_03_Waist"
	];
	
    while {true} do {
        {	
            _group = createGroup [civilian, true]; 
            _civ = _group createUnit [_x, getMarkerPos "spawnciv", [], 0, "NONE"];
            _wp1 = _group addWaypoint [getmarkerpos "wyptciv", 0];  
            _wp1 setWaypointType "MOVE";  
            _wp1 setWaypointSpeed "FULL";  
            _wp1 setWaypointBehaviour "CARELESS"; 
            _wp1 setWaypointStatements ["true", "{deleteVehicle _x} forEach units this"]; 
            sleep 1;  //delay time between each civ
        } forEach AUR_civ_array;
        sleep 30;  //delay time between waves
    };
};

You can change the value of the last sleep to adjust the time between waves of civilians. If you just want a steady stream of civs, set it to 1.
 

 

 

  • Like 2

Share this post


Link to post
Share on other sites

@Harzach

 

That is working perfectly, thanks.

One more thing - how would I be able to break the loop?

Player inside zone = loop activated

Player outisde zone = loop stopped

 

Regards,

Aurora

Share this post


Link to post
Share on other sites
3 hours ago, LSValmont said:

It works exactly like an ExecVM?

afaik yes that. or rather.. execvm is wrong. It works very much like (not exactly) spawn.

 

3 hours ago, LSValmont said:

So if I change all my scripts to non scheduled and just use CBA's waitAndExecute as a sleep do you think overall performance will improve or that would not necessarily mean a better experience?

Well it means instead of being limited to 3ms and not being able to cause bigger issues, your script will just freeze the game until it gets done..

Share this post


Link to post
Share on other sites
4 hours ago, Dedmen said:

afaik yes that. or rather.. execvm is wrong. It works very much like (not exactly) spawn.

 

Well it means instead of being limited to 3ms and not being able to cause bigger issues, your script will just freeze the game until it gets done..

 

Well a mix of both then! Because freezes are far worst than delays... Or perhaps both are bad!

Share this post


Link to post
Share on other sites
On 5/29/2020 at 2:03 AM, aurora1-4 said:

@Harzach

 

That is working perfectly, thanks.

One more thing - how would I be able to break the loop?

Player inside zone = loop activated

Player outisde zone = loop stopped

 

Regards,

Aurora

hi,  i would like to know how to stop the loop too. any help is much appreciate. thank you.

Share this post


Link to post
Share on other sites
3 hours ago, JURAGAN said:

  i would like to know how to stop the loop

which loop? what purpose?

Share this post


Link to post
Share on other sites
4 hours ago, sarogahtyp said:

which loop? what purpose?

loop by using while {} do {}.  my script : nul = [] spawn {while {true} do {jet1 = createVehicle ["O_Plane_CAS_02_dynamicLoadout_F", getMarkerPos "JetSpawn", [], 0, "FLY"]; 
createVehicleCrew jet1; jet1 FlyInHeight 500;  wp1 = group driver jet1 addWaypoint [getMarkerPos "JetPatrol",0]; null = [group driver jet1, (getMarkerPos "JetPatrol"),8000] call BIS_fnc_taskPatrol;   
 sleep 15;};};  how to make the spawn stop looping after 5 times? thank you.

 

Share this post


Link to post
Share on other sites
nul = [] spawn {
   for "_i" from 1 to 5 do 
   {
    jet1 = createVehicle ["O_Plane_CAS_02_dynamicLoadout_F", getMarkerPos "JetSpawn", [], 0, "FLY"];
    createVehicleCrew jet1;
    jet1 FlyInHeight 500;
    wp1 = group driver jet1 addWaypoint [getMarkerPos "JetPatrol",0]; 
    null = [group driver jet1, (getMarkerPos "JetPatrol"),8000] call BIS_fnc_taskPatrol;   
    sleep 15;
  };
}; 

 

https://community.bistudio.com/wiki/for

Share this post


Link to post
Share on other sites
5 minutes ago, sarogahtyp said:

nul = [] spawn {
   for "_i" from 1 to 5 do 
   {
    jet1 = createVehicle ["O_Plane_CAS_02_dynamicLoadout_F", getMarkerPos "JetSpawn", [], 0, "FLY"]; 
	createVehicleCrew jet1; 
    jet1 FlyInHeight 500;
    wp1 = group driver jet1 addWaypoint [getMarkerPos "JetPatrol",0]; 
    null = [group driver jet1, (getMarkerPos "JetPatrol"),8000] call BIS_fnc_taskPatrol;   
    sleep 15;
  };
}; 

 

Thank you so much! Its work! 🙂 

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

×