LSValmont 789 Posted September 19, 2019 Hello A3 Community! Since there is no topic on HoldAction optimization and tweaking I wanted to create one so we could perhaps answer some questions and share our findings. I love the holdActions implementation in Arma 3 far better than addAction but there is always the concern about performance and multiplayer compatibility. My first question would be: 1) Are Lazy evaluation/Successive condition check doable and beneficial for holdAction conditions and if so how could I implement it and optimize this example holdAction: Spoiler // vTakeDown.sqf vTakeDown_ID = -1; vTakeDown_Action = { vTakeDown_ID = [ player, "Perform Takedown", "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_forceRespawn_ca.paa", "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_thumbsdown_ca.paa", " !isNull cursorTarget && alive cursorTarget && cursorTarget isKindOf ""Man"" && lifeState cursorTarget != ""INCAPACITATED"" && speed cursorTarget < 0.3 && player distance cursorTarget < 3 ", " !isNull cursorTarget && alive cursorTarget && cursorTarget isKindOf ""Man"" && lifeState cursorTarget != ""INCAPACITATED"" && speed cursorTarget < 0.3 && player distance cursorTarget < 3 ", {}, {}, { _trg = cursorTarget; if (alive _trg) then { _trg setVariable ["vTakeDown",true]; if (currentWeapon player isEqualTo "") then { [player, "AwopPercMstpSgthWnonDnon_end"] remoteExec ["switchMove", 0]; } else {[player, "ThrowGrenade"] remoteExec ["playActionNow", 0];}; _trg setUnconscious true; _trg setHitPointDamage ["hitLegs", 0.6]; [_trg] spawn { params ["_unit"]; sleep (20 + (random 40)); _unit setUnconscious false; _unit setVariable ["vTakeDown",false]; [_unit, "ApanPpneMstpSnonWnonDnon_G02"] remoteExecCall ["playMove", 0]; }; }; }, {[player, "ThrowGrenade"] remoteExec ["playActionNow", 0];}, [], 1.1, 999, false, false ] remoteExec ["BIS_fnc_holdActionAdd", 0, player]; }; // Init waitUntil { !isNull player }; [] spawn vTakeDown_Action; player addEventHandler ["Respawn", { [] spawn { sleep 1; [] spawn vTakeDown_Action; }; }]; hint "takedown working!"; The holdAction is added to the players and displayed when the conditions are met. The script that adds the holdAction is executed from init.sqf: nul = [] execVM "vTakeDown.sqf"; The conditions are: Spoiler !isNull cursorTarget && alive cursorTarget && cursorTarget isKindOf ""Man"" && lifeState cursorTarget != ""INCAPACITATED"" && speed cursorTarget < 0.3 && player distance cursorTarget < 3 I worry that these many conditions might affect performance specially when adding other similar player holdActions but targeting only civilians etc. Question nber 2: How many holdActions can we add to a player before it starts lagging things out for that particular client? 1 Share this post Link to post Share on other sites
Vandeanson 1677 Posted September 19, 2019 Hi mate, Very interessting topic in my view. I use holdactions a lot and i am interested to see what we can collect on the subject. My thoughts: It seems to me that first you need to include delays for the condition checks. Right now all your checks are done at max frequency with no delays inbetween. It should be enough if the cond. are only checked every 0.5 or even 1 sec. Not sure if this can be built right into the string. If not, i would move your cond. check into a seperate loop (with addequate delay) that returns true to a variable, if met. Then only add the variable as cond. to the holdaction. This way, atleast it only checks 1 boolean at max frequency. Second: make sure that each condition check is as optimized as possible, e.g is there a quicker way to get to the result. Further, in your example ALL conditions must be met, if one is not met, no point in checking the others. hence lazy evaluation should indeed be applied as you mentioned. Here is how: Here, also rethink the priority of your conditions, if no target is in range, you dont need to check if its alive first, right? So maybe: ! Isnil - > range - > not Incapacitated - > alive - > moving slow TLDR: tune code compexity and frequency of code execution down Just my 2 cents:) Cheers Vd 1 Share this post Link to post Share on other sites
Dedmen 2714 Posted September 20, 2019 12 hours ago, LSValmont said: 1) Are Lazy evaluation/Successive condition check doable and beneficial for holdAction conditions and if so how could I implement it and optimize this example holdAction: Yes ofcourse. You do it the same as everywhere else, and it has the same benefit as everywhere else. Maybe even more as (not sure how often) holdAction condition is checked very often while you look at the target object. Important is also to order the conditions such that the ones most likely to be false are up front, to quit the checking early. And the heaviest checks should be at the end. Taking this example: " !isNull cursorTarget && alive cursorTarget && cursorTarget isKindOf ""Man"" && lifeState cursorTarget != ""INCAPACITATED"" && speed cursorTarget < 0.3 && player distance cursorTarget < 3 " 1st the isNull check is nonsense, alive will return false if it were null. distance check is expensive so that being at end makes sense. isKindOf check is even more expensive though. But on the other hand, distance and isKindOf checks are more likely to be false, so it makes more sense to put them on the front. I would write it like this: " alive cursorTarget && { player distance cursorTarget < 3 && {cursorTarget isKindOf ""Man""} {speed cursorTarget < 0.3 &&} {lifeState cursorTarget != ""INCAPACITATED""} && } " in most cases cursorTarget will probably be null, so in that case we can just skip everything. For the rest it doesn't make sense readability wise to use nested lazy eval, although it might be more performant. Readability wise I'd also recommend you fix your indentation, it's probably the most important readability factor. 12 hours ago, LSValmont said: Question nber 2: How many holdActions can we add to a player before it starts lagging things out for that particular client? 0. Even at one holdAction you cause script evaluation, which causes a fps decrease. If you want to ask at what point it becomes significant, then the answer is: it depends. On the conditions, target, users computer hardware, users running background processes, users graphics settings... 10 hours ago, Vandeanson said: It should be enough if the cond. are only checked every 0.5 or even 1 sec. Not sure if this can be built right into the string. You'd need to add some caching, which is quite advanced stuff and most likely not worth it. 10 hours ago, Vandeanson said: If not, i would move your cond. check into a seperate loop (with addequate delay) that returns true to a variable, if met. Then only add the variable as cond. to the holdaction. This way, atleast it only checks 1 boolean at max frequency. That's a very nice idea. On the other side this might add lag, and if you do that in scheduled (which you would and should) then it might be delayed by 10 seconds or more on a badly scripted mission. Which for a "takedown" action would be unacceptable. 2 1 Share this post Link to post Share on other sites
Larrow 2822 Posted September 20, 2019 Change that distance check for distanceSqr and your required distance to 3^2. As @Dedmen said distance is a very expensive operation even more so if it has to work out the square root. Where as power of 2 or (3*3) is less computationally expensive. 3 1 Share this post Link to post Share on other sites
LSValmont 789 Posted September 20, 2019 First of all thank you @Vandeanson, @Dedmen and @Larrow for your invaluable wisdom and specially sharing it with all of us. Any novice and even more advanced scripters/mission creators will surely benefit from everything you've stated here. In any case it seems that the holdAction is a useful tool that must be used wisely and not wildly in order to keep everything above those golden 60 FPSs. Last question from me... in your experience you would say that a holdAction is more expensive than a addAction computationally wise given both have the same checks and conditions or both tools are more or less on par in terms of performance impact? Share this post Link to post Share on other sites
Larrow 2822 Posted September 21, 2019 13 hours ago, LSValmont said: in your experience you would say that a holdAction is more expensive than a addAction computationally wise A holdAction is an addAction. It just does something like... addAction[ _title, { call _codeOnStart; disable action menu while { not max frame || progress abort } do { waitUntil{ time > next frame }; work out icon to display call _progressCode }; if ( frame == max frame ) then { remove action call _codeComplete; }else{ call _codeInterrupted }; reset icon re-enable action menu }]; 1 Share this post Link to post Share on other sites