D. Patterson 14 Posted March 27, 2016 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
flyinpenguin 30 Posted March 27, 2016 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
D. Patterson 14 Posted March 27, 2016 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
jshock 513 Posted March 27, 2016 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
D. Patterson 14 Posted March 27, 2016 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
jshock 513 Posted March 27, 2016 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
flyinpenguin 30 Posted March 27, 2016 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
jshock 513 Posted March 27, 2016 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
D. Patterson 14 Posted March 27, 2016 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
jshock 513 Posted March 27, 2016 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
D. Patterson 14 Posted March 27, 2016 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
fn_Quiksilver 1636 Posted March 27, 2016 It looks like this script is a constantly running script, which is really bad. why? Share this post Link to post Share on other sites
flyinpenguin 30 Posted March 27, 2016 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
fn_Quiksilver 1636 Posted March 27, 2016 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
flyinpenguin 30 Posted March 27, 2016 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. 1 Share this post Link to post Share on other sites
D. Patterson 14 Posted March 27, 2016 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