Jump to content
Jetrise

Loop Alternatives for better Performance

Recommended Posts

Hello All,

 

I'm currently making a medical system and I have a loop that runs every second to check bleed rate and pain rate. This loop is quite extensive as it's doing other calculations such as deciding when a player is to fall unconscious or dies.

 

Now, is there any other solution to have something update without the effects that are caused via a while loop every second?

 

Thanks,

 

Shaun

Share this post


Link to post
Share on other sites

Post the loop, otherwise it's hard to tell if there's actually anything in need of improving.

What effects are you talking about?

 

Cheers

Share this post


Link to post
Share on other sites


while {alive player} do

{

_BR = player getVariable "MedSys_V_BR";

_BL = player getVariable "MedSys_V_BL";

_BRR = player getVariable "MedSys_V_BRR";

_LS = player getVariable "MedSys_V_PlayerState";

_PL = player getVariable "MedSys_V_PainLevel";

_PLR = player getVariable "MedSys_V_PainRegen";

_NBL = _BL - _BR;

_NBL = _NBL + _BRR;

_NBR = _BR*MedSys_BCC;

player setVariable ["MedSys_V_BR", _NBR, true];

if (_NBL > 5500) then

{

_NBL = 5500;

};

if (_NBL <= 0) then

{

player setDamage 1;

};

if (_BRR > 1) then

{

_NBRR = _BRR - MedSys_RRR;

if (_NBRR < 1) then

{

_NBRR = 1;

};

if ((_NBRR > MedSys_MRR) && (_LS != 2)) then

{

"EPIOVERDOSE" spawn MedSys_F_Unconscious;

};

player setVariable ["MedSys_V_BRR", _NBRR, true];

};

if (!((_BL > 2000) && (_BRR > _BR)) && (_LS == 0)) then

{

_UC = ((1 - (_NBL-1000)/1000)*((_BR - _BRR)/10))*MedSys_V_BUC;

_UR = random 1;

if (_UR > (1 - _UC)) then

{

"LOWBLOOD" spawn MedSys_F_Unconscious;

};

};

player setVariable ["MedSys_V_BL", _NBL, true];

sleep 0.98;

};

};

};

Share this post


Link to post
Share on other sites

I'm not a performance expert at all, but your loop looks clean to me.  Math is efficient.

 

I have one suggestion, and that is to remove the these 2 getVariables.  Your code never references these 2 values.  That will save a smidge of execution time (probably unnoticeable though...but every lit bit helps).

    	  _PL = player getVariable "MedSys_V_PainLevel";
    	  _PLR = player getVariable "MedSys_V_PainRegen";

Love the precise "sleep .98"! :)

  • Like 1

Share this post


Link to post
Share on other sites

You can create a trigger by script that automatically calls your code. The trigger is called by engine and no script suspended. I got some good results with this in scriptheavy systems but I don't know if it will help in your case.

 

Example:

if(isNil("A3I_Timer")) then {
	A3I_Timer = 0;
};
if(isNil("A3I_Time")) then {
	A3I_Time = 5;
};


_DTrg=createTrigger["EmptyDetector",[0,0,0]];
_DTrg setTriggerArea[0,0,0,true];
_DTrg setTriggerActivation["NONE","PRESENT",true];
_DTrg setTriggerStatements["isServer && time>=A3I_Timer",  "[] call a3i_fnc_run;", ""]; //The function is addin A3I_Time to A3I_Timer var 

Keep in mind that timing with a trigger is not reliable and subject to server/client FPS/scriptload. So when you want time relevant stuff, you need to check it with the time variable in your function/script.

 

P.S. Forgot to name another advantage of this solution: When there is a script error in one part of your function (like a null object or a not intialized variable) the script will halt, but not the trigger, it will rerun the function in the next cycle. This is a good way to ensure that your function is always called regardless of local runtime errors.

Share this post


Link to post
Share on other sites

Your snippet looks good to me, why do you think it needs to be optimized?

Running something like that every second shouldn't cause any issues.

 

Cheers

Share this post


Link to post
Share on other sites
Guest

The only alternative would be to use eventHandler but you can't create custom EvantHandlers without cba if i'm right.

Anyway from what you provided us you can check the overdose thing each time you use epinephrin (idk how to spell it in english) that would take away this part from your loop and fir the blood use eventHandlers on damage or hit (Basicly anywhere the blood is changed).

I just took a quick look so don't mind me if I understood it wrong.

Share this post


Link to post
Share on other sites

Thanks for the help guys. 

 

Love the precise "sleep .98"! :)

 

Well, when I put it through the Debug Console where you can see how long it takes to execute, it was something like 0.2, so yeah xD 

 

 

Your snippet looks good to me, why do you think it needs to be optimized?

Running something like that every second shouldn't cause any issues.

 

To me, from experience, anything in loops tends to impact FPS somewhat. 

 

 

 

The only alternative would be to use eventHandler but you can't create custom EvantHandlers without cba if i'm right.
Anyway from what you provided us you can check the overdose thing each time you use epinephrin (idk how to spell it in english) that would take away this part from your loop and fir the blood use eventHandlers on damage or hit (Basicly anywhere the blood is changed).
I just took a quick look so don't mind me if I understood it wrong. 

 

So to clarify, only CBA can be used for custom EH's? Additionally, I have the Epi business in the Loop as the regen slows down over time. 

Share this post


Link to post
Share on other sites

You'll get the best performance boost when you don't run the code at all ;)

 

Currently you run the loop as long as a player is alive, although I think you can add more variables (eg. "isWounded", "hadTreatment", etc.) and break down the loop in separate parts.

 

 

But in comparison, ACE3 Medical has way more scripts and checks running within a single loop, and I never found it a bottleneck (performance wise).

Share this post


Link to post
Share on other sites

 

So to clarify, only CBA can be used for custom EH's? Additionally, I have the Epi business in the Loop as the regen slows down over time.

No. You can (in Theory) write your own. A single loop or trigger that checks for events and calls registred functions. Infact the code I posted is from a custom (loopless) eventhandler/scheduler system.

But that is only effective when you can use it to reduce the amount of loops from x to 1.

Share this post


Link to post
Share on other sites

To me, from experience, anything in loops tends to impact FPS somewhat.

To me, from experience, only badly written scripts made by people who have no idea what they're doing tends to impact FPS somewhat.

 

Cheers

Share this post


Link to post
Share on other sites

Typically the worst code in the world, called in a spawn context, will not impact your framerate.  The best most optimized loop on earth, if "called" directly from a trigger, init.sqf, or initialization, will happily eat all your frames until the game is frozen for 20-30 seconds at a time.  Asynchronous contexts are your friend.

  • Like 3

Share this post


Link to post
Share on other sites

..., if "called" directly from a trigger,[...] will happily eat all your frames until the game is frozen for 20-30 seconds at a time.  Asynchronous contexts are your friend.

 

If the mention of "trigger" is in response to the code I posted: A call from a trigger runs in a seperate and unscheduled context (AFAIK). Also when using this technique you normally don't add a loop to the called function. 

Share this post


Link to post
Share on other sites

 

Hello All,
 
I'm currently making a medical system and I have a loop that runs every second to check bleed rate and pain rate. This loop is quite extensive as it's doing other calculations such as deciding when a player is to fall unconscious or dies.

 

Instead of using a continuous loop, you could also store the current status in a variable, calculate when the next statuschange is going to happen and wait that long.

 

 

If something else happens during that wait, just kill the timer, recalculate the status and start the timer again.

 

 

Here's a simplified example:

 

Event: player taxes x damage to the torso

Status: deep wound, bleeding (save timestamp)

> Start timer: unconscious in 3 seconds

> Start timer: bleedout in 100 seconds

 

(3sec later)

Event: unconscious

Status: deep wound (unchanged), bleeding (unchanged), unconscious

 

(49 sec later)

Event: Recieves damage from nearby explosion

Status: deep wound, many small wounds, heavy bleeding, unconscious

> Get remaining time from "bleedout" timestamp

> Stop timer: bleedout

> Start new timer(remaining time (46sec) from old timer, adjusted with new bleeding (twice as fast)): bleedout in 23 seconds

 

(23sec later)

RIP

  • Like 1

Share this post


Link to post
Share on other sites

Thanks for all the help guys.

 

I'll try out a few things and give you a response in time, although, by the sounds of some comments, there really isn't much wrong with my code. 

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

×