Jump to content
D. Patterson

Would anyone like to help me optimize?

Recommended Posts

        I don't want to start building up scripts, and have to restart because they were all built off poorly performing scripts. If any one you would like to give me any pointers, that'd be appreciated.

        Edit: Here is pastebin ID 1Q6Cnj7Y

        For some reason pasting the code in this causes half of it to be cut-off.

 

 

 

 

 

        Basic function of the script is:

        You shoot a 3GL gas grenade. If any AI's are in a vicinity, they will be forced to animate and cannot fight back.

Share this post


Link to post
Share on other sites

Im not going to re-write it for you, but I will point you in the right direction.  It looks like this script is a constantly running script, which is really bad.  You need to convert this to a fired script.  Use addeventhandler to add a fired event handler.  In this you need to check if its the correct ammunition type and then get the final resting place of the munition by waiting until it stops moving.  Once you have this, then check for nearby units with the nearestEntities command and apply the effect to them.  If you want it to be MP compatible, you will have to do extra work in making sure the animation gets applied on the local computer. See the remoteExec command for that.

Share this post


Link to post
Share on other sites

Im not going to re-write it for you, but I will point you in the right direction.  It looks like this script is a constantly running script, which is really bad.  You need to convert this to a fired script.  Use addeventhandler to add a fired event handler.  In this you need to check if its the correct ammunition type and then get the final resting place of the munition by waiting until it stops moving.  Once you have this, then check for nearby units with the nearestEntities command and apply the effect to them.  If you want it to be MP compatible, you will have to do extra work in making sure the animation gets applied on the local computer. See the remoteExec command for that.

 

I considered an eventhandler, but it seemed like it'd be more resource intensive to run code every time a weapon is fired, than just checking every 10 seconds. 

Share this post


Link to post
Share on other sites

Might be easier to use a FiredNear EH, no loop needed just distance and conditional checks like you already have. Looping through all units every ten seconds is relatively intensive while EHs are provided inherently and don't bog down the game at all so long as you don't press the conditionals too far.

Share this post


Link to post
Share on other sites

Seems like firedNear has to do with the firing unit, and not the projectile destination?  

This is what I think I should use for the eventHandler 

 

this addEventHandler ["fired",{If(_this select 4 == "G_40mm_SmokeGreen") then {execVM "TearGasEH.sqf"};}]; 

 

 

Should this perform well and not be too intensive?

Share this post


Link to post
Share on other sites

Seems like firedNear has to do with the firing unit, and not the projectile destination?

Let's see:

 

  • unit: Object - Object the event handler is assigned to
  • firer: Object - Object which fires a weapon near the unit
  • distance: Number - Distance in meters between the unit and firer(max. distance ~69m)
  • weapon: String - Fired weapon
  • muzzle: String - Muzzle that was used
  • mode: String - Current mode of the fired weapon
  • ammo: String - Ammo used

 

Firer, the firing unit.....distance from the unit being fired at.....type of ammo used.....hmmm...everything you have in your conditional statements, seems pretty related to your needs. Now there may need to be a bit of a work around to get the actual projectile, but a Fired EH can handle that as already stated, it honestly shouldn't lag you out much.......

 

 

 

You could also lose the first 3 lines of code, and replace line 12 with:

if ( (_x getVariable ["Blinded",0]) == 0 ) then

And if you keep your loop and such, and if this is only for AI, then you don't need to iterate through all units constantly you can do:

{/*code*/} forEach allUnits - allPlayers;

And to make the loop run a bit more efficiently you may want to prioritize your conditions, for example it may be more efficient to check to see if the unit is blinded before any checks on anything else because then you avoid a bunch of distance and position calculations from the beginning.

 

And the "wearing" off of the effect you may want to make a separate function or script that you spawn in, instead of suspending the loop for a random amount of time before allowing it to continue onto the next unit.

 

And to make a point on the Fired EH (well any EH), they run no matter if you end up using them or not, they are just provided to us so that we can access said information to accomplish said scripts. So, no "checking for every bullet fired" will not bog anything down, as it happens anyways, even when the information isn't explicitly used by us. Or at least that's how I understand them.

Share this post


Link to post
Share on other sites

Let's see:

 

 

Firer, the firing unit.....distance from the unit being fired at.....type of ammo used.....hmmm...everything you have in your conditional statements, seems pretty related to your needs. Now there may need to be a bit of a work around to get the actual projectile, but a Fired EH can handle that as already stated, it honestly shouldn't lag you out much.......

The only issue with firednear is that it only works from a certain distance out.  So I would recommend just a fired event handler so you can fire your GL from over 100m and still have it work.

It is still better to use an eventhandler than a constantly running script every 10 seconds, even if it has to be checked everytime something fires.  Its like keeping your oven on because you might need to make a pizza later, you just don't do it.  As long as you set up the eventhandler correctly, it will not have a performance impact.

Share this post


Link to post
Share on other sites

The only issue with firednear is that it only works from a certain distance out.  So I would recommend just a fired event handler so you can fire your GL from over 100m and still have it work.

Fair point and I agree, I looked at the info on FiredNear a little too quickly (been a while since I used one :p), forgot it had a cap working distance.

Share this post


Link to post
Share on other sites

Okay code so far:  

 

Event Handler: this addEventHandler ["fired",{If(_this select 4 == "G_40mm_SmokeGreen") then {execVM "TearGas.sqf"};}];

TearGas Script: G6xJfMVA <- PasteBin ID   

 

Everything is still working.

Share this post


Link to post
Share on other sites

Firstly pass the projectile into the script, that way you don't need a nearestObject check, secondly, again, allUnits is highly unnecessary as you only need units within a specific radius, so I recommend:

{} forEach (getPosATL _projectile) nearEntities [["Man"], 10];

^This will only loop through AI men that are within 10 meters of the smoke grenade projectile. Instead of all possible units.

 

And again as well, for the effect wearing off portion I recommend spawning it in instead of leaving it to suspend within the script. You also don't need to keep a local array of "effected" NPCs considering this will be looping through all effected NPCs, and if you spawn in the wearing off portion, it will be handled locally on each NPC.

Share this post


Link to post
Share on other sites

Firstly pass the projectile into the script, that way you don't need a nearestObject check, secondly, again, allUnits is highly unnecessary as you only need units within a specific radius, so I recommend:

{} forEach (getPosATL _projectile) nearEntities [["Man"], 10];

^This will only loop through AI men that are within 10 meters of the smoke grenade projectile. Instead of all possible units.

 

And again as well, for the effect wearing off portion I recommend spawning it in instead of leaving it to suspend within the script. You also don't need to keep a local array of "effected" NPCs considering this will only be running locally on each NPC, in other words, you have one unit to worry about no others.

 

I'm getting a Type Number, Expected Object error on the line _Projectile = _this select 0;

This is my Init code: this addEventHandler ["fired",{If(_this select 4 == "G_40mm_SmokeGreen") then {[(_this select 6)] execVM "TearGas.sqf"};}];

_Projectile is reporting back as 1780056: ugl_slug.p3d

 

I also added: 

 

_Null = [_x] spawn 
{
_AI = _this select 0;
Sleep 65;
_AI enableAI "ANIM";
_AI setVariable ["Blinded",0,false];
};
 
to my code, I assume this is what you meant by the spawn.

Share this post


Link to post
Share on other sites

why?

Constantly running scripts eat up resources unnecessarily. The only way you should use them is if you have to have something being calculated all the time (like tickers or something like that or needed changes for visual effects), or because you cannot achieve the script via the current event handlers.

This is also not saying that you cannot make a constantly running script efficient. It's just if you can use a event handler to achieve it, it will always be more efficient because it only uses resources when it needs to.

Share this post


Link to post
Share on other sites

i agree that a script thread is not nothing, with respect to performance burden

 

but spreading the idea that a loop is really bad is not good. a scheduled loop is just another tool in a programmers toolbox. there are plenty of cases where even a while loop is more performance friendly method than even event handlers. one thing i do not like about event handlers is lack of control over concurrent evaluations (the things which can cause stuttering FPS drops). For instance with the fired event handlers, when 20 soldiers are shooting at the same time, this is very high evaluation frequency and performance will degrade during these times, whereas with a simple loop this is not the case.\\

 

I believe in using the fewest amount of evaluations necessary to get the job done

Share this post


Link to post
Share on other sites

i agree that a script thread is not nothing, with respect to performance burden

 

but spreading the idea that a loop is really bad is not good. a scheduled loop is just another tool in a programmers toolbox. there are plenty of cases where even a while loop is more performance friendly method than even event handlers. one thing i do not like about event handlers is lack of control over concurrent evaluations (the things which can cause stuttering FPS drops). For instance with the fired event handlers, when 20 soldiers are shooting at the same time, this is very high evaluation frequency and performance will degrade during these times, whereas with a simple loop this is not the case.\\

 

I believe in using the fewest amount of evaluations necessary to get the job done

In this circumstance it is the best method, hence why I am saying a constantly running script is bad. From what this looks like, it's only needed on players end, not every single AI, which means fired will not be sent for everything that fires, only when the object it's attached to fires. It's true that infinite loops are a tool in a programmers toolbox, but you need to know when to use them. You don't use a hammer to fix everything (nod to Clarkson from Top Gear)

For example, if you wanted this to work even better, you would config a GL to fire your own custom round and attach the fired event handler to that config so that it only activaes when you fire that GL.

  • Like 1

Share this post


Link to post
Share on other sites

Well I just did a performance test and it took the engine 0.0014 Milliseconds to evaluate If(AmmoGun == "SmokeShellGreen") then {[] execVM "Teargas.sqf"}; when false and 0.0088 Milliseconds when true.  So if the math scales linearly, and I will have a max of about 10 shooting simultaneously, I could technically run about 360 of these event handlers before I get a noticeable stutter.

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

×