Jump to content
Sign in to follow this  
pebcak

Scripting Efficiencies

Recommended Posts

I'm in the process of attempting to break ArmA. smile_o.gif I've already found the upper group limit of 144. I've not encountered a unit limit yet after having placed over 300. Also not encountered an object limit after having placed about 500. All seem to have minimal effect on (SP) performance, even tho I am intending my mission for MP coop.

What I have noticed is a slight stutter every half second. As I understand it ArmA runs through all of it variable checks and wotnot twice per second. So, something is taking a bit long script-wise. I'm not doing anything super-impressive, just a large number of variable state change triggers, some against alive/dead members of lists all contained within the editor - no external scripts (yet).

At the moment I'm just checking the state of variables using a trigger with simple condition instructions, e.g., '(var1==1)&&(var2==0)'. Where I'm checking the status of units within a list I'm defining the list by doing a count once right at the start, e.g., 'whitechapelList = [];{whitechapelList = [_x] + whitechapelList}forEach thislist;', then running checks against that list in another trigger for effect, e.g., '{!alive _x}count whitechapelList >= 10;'.

My question is, what is the best practice to do this kind of thing to minimize the half-second stutter? I've probably got about 20 of these variables and conditions running at once.

Share this post


Link to post
Share on other sites

Id try it with scripts which would have different values for sleep. If theres something that doesnt need to be checked each 0.5s, then put it in a script loop with few second sleep.

Even though its an "external" script, I really doubt it would lag more than a trigger being checked twice per second.

Share this post


Link to post
Share on other sites

20 triggers should not cause any kind of stutter.

But how many units are in your mission? The 500 you mentioned, or were they just in your test setup?

If you have any scripts running make sure that you have a sleep statement within any loops (doesn't have to be long, .01 is normally more than enough).

Also make sure that you don't accidentally have any recursive calls happening (where a script or function could end up calling itself up endless times).

Share this post


Link to post
Share on other sites

So far there are no external scripts, just editor triggers and the like, so I'm not sure how I can factor sleep into these.

There are about 300 units and the majority do have waypoints to work through.

As far as I can find there are no recursive calls happening; again, it's all in the editor so such a thing would be tricky to set up (even accidentally)?

I could post the mission up for debugging if that would be helpful...

whistle.gif

Share this post


Link to post
Share on other sites

Maybe add a little 0.1 in the "timeout" section of the triggers? IMHO that should work even on repeating triggers.

No idea if that's what's causing the hickup though.

Regards,

Wolfrug

Share this post


Link to post
Share on other sites

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">whitechapelList = [];{whitechapelList = [_x] + whitechapelList} forEach thislist; whitechapelListCount=Count whitechapelList

You could improve on the above code a little buy replacing it with this:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">whitechapelList=+thislist

But that probably won’t have a drastic effect on your problem and I kind of revert back to your original in the next example. But still worth knowing about.

I guess this is a trigger covering the whole map or an area, that’s only used to build an array? So you can probably delete it once you have a count? One less trigger to worry about.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">whitechapelList=+thislist; DeleteVehicle This

Although I'm not sure that will work?

The other trigger is probably where the lag is comming from:

Quote[/b] ]{!alive _x}count whitechapelList >= 10;

Rather than running that count every 0.5 seconds. You could always try using the killed event. You could add this when you build your list (which brings is back to your original script):

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">whitechapelList=+thislist; {_x AddEventHandler ["killed","whitechapelList=whitechapelList-[_This Select 0]; whitechapelListActive=(whitechapelListCount-(Count whitechapelList)>=10);"]} ForEach whitechapelList

The above example assumes you are happy removing a killed unit from the array. The global variable whitechapelListActive will be set true or false according to your condition. So you can get a trigger to test that every 0.5 seconds, instead of count 300 array elements. Unless you kill 300 units in one go, it should not lag as much.

But you should really use scripts to get the best results, as everyone has said. Sometimes you can get away with larger delays than just 0.5 seconds.

Edit: fixed some code in the last example.

Share this post


Link to post
Share on other sites

UNN,

Cheers for that reply. I'm a bit new to all this, so I'm gonna ask some stupid questions most likey!

I have several of these '{!alive _x}count whitechapelList >= 10;' -style conditions going on. If this is a laggy way of doing things then that may explain it, and it doesn't need to be tested anything like every 0.5 seconds either.

Clearly I should have a script file if that is the most effecient way of doing things. Not sure how to do that tho. :S

What I'm trying to do (and it does work as is, bar the every 0.5 second lag):

The above 'whitechapel' example is to check to see if a specific group of soldiers is either killed or arrives at a location. I create an array with this in a trigger that just covers them at the start:

whitechapelList = [];{whitechapelList = [_x] + whitechapelList} forEach thislist; whitechapelListCount=Count whitechapelList

(which you say would be better off as per you example. I've not tried that yet.)

And in another trigger, the one that kicks other things off if all within the whitechapelList are dead, I have the condition:

{!alive _x}count whitechapelList >= 10;

Share this post


Link to post
Share on other sites

Okay, I tried to put this 'whitechapelList=+thislist; {_x AddEventHandler ["killed","whitechapelList=whitechapelList-[_This Select 0]; whitechapelListActive=(whitechapelListCount-(Count whitechapelList)>=10);"]} ForEach whitechapelList' in OnAct for the trigger that makes the list. I made another trigger that checks to see if whitechapelListActive is either true or false (tried both) as the condition for other messages, but it does nothing. I fiddled a bit with various elements but I either generated errors or nothing else.

banghead.gif

Share this post


Link to post
Share on other sites

Hi,

Here is an example mission called triggerlist.intro, with 11 men in a group. The trigger named W1 is used to count the units, build the array, add the eventhandler and finaly delete it's self. If you want to remove a trigger once it's done it's job, you have to give it a name, then use deleteVehicle at the end of On Act. So in this case the code at the end of the W1 trigger looks like this:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">DeleteVehicle W1

There is a second, radio Alpha trigger that shows the results. As you kill each unit you can call the trigger to display the original number of units, the number of units currently alive and the state of the global variable whitechapelListactive.

The final trigger is activated by the global variable whitechapellistActive, and will display a hint when ten units have been killed.

I've introduce a single script, Init.sqf. You can find it in the mission folder. This is executed when the mission starts. Even if you don't want to add loads of scripts, using an init scripts means you can define all your variables and what not at the start of a misison.

triggerlist.zip

Share this post


Link to post
Share on other sites

UNN,

Ah, now I understand what it's doing!  Excellent stuff.  (I'm assuming there won't be any MP issues with this method.) If I could award points on this board for helpfulness you'd get a bunch.  Have a cookie instead...

chocolate_chip_cookie_bitten.jpg

Many thanks.  

biggrin_o.gif

Share this post


Link to post
Share on other sites

Hi,

Glad it helped you out. I did occure to me that you could refine the eventhandler code a bit more. Changing this bit:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">_x AddEventHandler ["killed","whitechapelList=whitechapelList-[_This Select 0]; whitechapelListActive=(whitechapelListCount-(Count whitechapelList)>=10);"]

To This:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">_x AddEventHandler ["killed","whitechapelList=whitechapelList-[_This Select 0]; whitechapelKilledCount=whitechapelKilledCount+1; whitechapelListActive=(whitechapelKilledCount>=10);"]

Add a new line to your init.sqf:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">whitechapelKilledCount=0;

I'm working on the idea that counting a larger array is slower than just incrementing an integer, but I don't know for sure. You don't actualy need to maintain the array if you use a counter, unless you using it somewhere else?

Quote[/b] ]I'm assuming there won't be any MP issues with this method

At the moment the scripts are run on the server and all clients. If the killed event fires on all clients and the server, you should not have to broadcast any variables, as they should stay in synch. If it only executes on the server (the computer local to AI units not in a players group or vehicle) then you will have to let the server handle the counting and change your eventhandler to:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">_x AddEventHandler ["killed","If (Local (_This Slecet 0)) Then {whitechapelList=whitechapelList-[_This Select 0]; whitechapelKilledCount=whitechapelKilledCount+1; whitechapelListActive=(whitechapelKilledCount>=10); PublicVariable ""whitechapelListActive"""}]

Not sure with Arma, I've not done any MP testing. But try the first method and see how you get on.

Quote[/b] ]Have a cookie instead

I'll go and put the kettle on smile_o.gif

Share this post


Link to post
Share on other sites

As it happens I do have an AI list that will be attacked by other AI, so this check would need to be performed irrespective of player presence. (Two AI forces, first to reach 50% casualties withdraws.) I'll try it with the first method, see how that goes. smile_o.gif

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  

×