Vandeanson 1677 Posted November 15, 2018 (edited) hiho fellow late night scripters, i am working on a script that adds a deadly infection to the player when damaged ("dammaged" EH) in a MP/COOP scenario. once infected, the player takes damage until cured. for the cure addaction, i need a boolean non local variable per connected client ("global" to the client so i can use it in various scripts, but it can not be public to all clients!) called Infection_Cured. at start, Infection_Cured will be true, and once the player is infected, its set to false until the medication is taken. then it is set back to true and the infection damage loop is stopped (exitwith). i can not test MP and am currently only on my handheld mainly i am very unsure if i understand setvariable correctly. for example, i do not understand why "_var = true;" is needed (copied from bi wiki) hence i would appreciate some opinions on my draft script and possible corrections regarding my attempt to create a variable that is available in all scripts but isolated per player thanks in advance for any help or clarifications! vd Spoiler /*content of file initplayerlocal.sqf*/ //add "dammaged" EH to player execvm "VanD_InfectionEH.sqf"; //assign variable _id = getowner; private _var = player getVariable "Infection_Cured"; if (isNil "_var") then { player setVariable ["Infection_Cured", true, _id]; _var = true; }; /////// /*content of file VanD_InfectionEH.sqf*/ player addEventHandler ["Dammaged", { params ["_unit", "_selection", "_damage", "_hitIndex", "_hitPoint", "_shooter", "_projectile"]; _unit = _this select 0; _shooter = _this select 5; if (_shooter iskindof "CAManbase") then { [_unit] execvm "VanD_Infection.sqf";}; }; }]; //////// /*content of file VanD_Infection.sqf*/ player setVariable ["Infection_Cured", false, _id]; _var = false; params ["_unit","_thisEventHandler"]; _unit = _this select 0; _EHID = _thisEventHandler; _unit removeEventHandler ["Dammaged", _EHID]; _freq = 60; while (alive _unit && damage _unit >= 0.1) do { sleep _freq; sleep (random 10); addCamShake [2, 2, 3]; _dmg = (getdamage _unit) + 0.05; _unit setdamage _dmg; _unit say2D [WoundedGuyA_01, 15, 3]; cutText ["coff coff","PLAIN DOWN",4]; sleep 0.5; cutText ["","BLACK IN",2]; _freq = _freq - 1; if (!alive _unit || damage _unit < 0.1 || Infection_Cured) exitwith { execvm "VanD_InfectionEH.sqf";}; }; //////// /*content of file VanD_TakeCure.sqf: called by an addaction*/ _id = getowner; player setVariable ["Infection_Cured", true, _id]; _var = true; Edited November 15, 2018 by Vandeanson OP updated in spoiler/code Share this post Link to post Share on other sites
HazJ 1289 Posted November 15, 2018 player setVariable ["Infection_Cured", true, _id]; // if anything, it should be _id first // the last argument is whether to make it public or not player setVariable ["someVar", <whatever>]; The last argument is whether to make it public or not. // setting variable player setVariable ["infection", true]; // not public player setVariable ["infection", true, true]; // is public // getting variable player getVariable ["infection", false]; // false is default value if not defined if (player getVariable ["infection", false]) then { // do damage... } else { // nope }; Hope this helps. This is all you need really. Tip: Put code in code tags. Easier to read. EDIT: You can also do this (I personally would just use setVariable/getVariable): infection = true; // just don't PV it 1 Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 15, 2018 Hi @HazJ, thanks for your reply! Just now, HazJ said: EDIT: You can also do this (I personally would just use setVariable/getVariable): infection = true; // just don't PV it So if infection = false; is stated in initplayerlocal.sqf, will there be a separate variable "infection = false;" for each connected client? if i change infection = false to infection = true within initplayerlocal, it should only affect the state of the specific clients infection variable. Basically, the player on client 1 (aka _id) "taking a cure pill" (addaction that triggers some code and sets infection to false) - if this is affecting all players' variable "infection" i would need to find an alternative solution. I hope i make some sense =D with regards to my use of _id in above code - i got this from the bi forums: https://community.bistudio.com/wiki/setVariable varspace setVariable [name, value, public] Spoiler public: Boolean, Number or Array of Numbers Boolean - when true, the variable broadcast is global and persistent Number - the variable is set only on the client of given owner (clientOwner) id, or if id is negative, the variable is set on every client except the given one Array of Numbers - array of owner (clientOwner) ids this seemed to perfectly take care of my desired effect - but then again, i do not fully understand it=) Cheers vd Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 15, 2018 1 hour ago, HazJ said: // getting variable player getVariable ["infection", false]; // false is default value if not defined if (player getVariable ["infection", false]) then { // do damage... } else { // nope }; ooh i think now i understand, the above must be used instead of if (infection) then {do stuff} else{dont do stuff}; correct? Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 15, 2018 updated the script following your suggested (and simplest) solution Spoiler Quote /*initplayerlocal.sqf*/ VanD_CurePill = 0; //add "dammaged" EH to player execvm "VanD_InfectionEH.sqf"; //assign variable Infection_Cured = true; //addaction player addAction [ "Take Cure Pill", { params ["_target", "_caller", "_actionId", "_arguments"]; Infection_Cured = true;]; }, [], 1.5, false, true, "", (count VanD_CurePill >= 1 && _this == _target), 1, false, "", "" ]; /////// /*VanD_InfectionEH.sqf*/ player addEventHandler ["Dammaged", { params ["_unit", "_selection", "_damage", "_hitIndex", "_hitPoint", "_shooter", "_projectile"]; _unit = _this select 0; _shooter = _this select 5; if (_shooter iskindof "CAManbase") then { [_unit] execvm "VanD_Infection.sqf";}; }; }]; //////// /*VanD_Infection.sqf*/ params ["_unit","_thisEventHandler"]; _unit = _this select 0; _EHID = _thisEventHandler; Infection_Cured = false; _unit removeEventHandler ["Dammaged", _EHID]; _freq = 60; while (true) do { sleep _freq; sleep (random 10); if (!alive player) exitwith { execvm "VanD_InfectionEH.sqf"; }; if (Infection_Cured) exitwith { cutText ["I am feeling better.","PLAIN DOWN",4]; execvm "VanD_InfectionEH.sqf"; }; addCamShake [2, 2, 3]; _dmg = (getdamage _unit) + 0.05; _unit setdamage _dmg; _unit say2D [WoundedGuyA_01, 15, 3]; cutText ["coff coff","PLAIN DOWN",4]; sleep 0.5; cutText ["","BLACK IN",2]; _freq = _freq - 1; }; will revert back as soon as i could test it alone in a hosted game - if anyone can test it in MP with 2+ players - well i would not say no to that =D cheers vd Share this post Link to post Share on other sites
HazJ 1289 Posted November 15, 2018 Sorry for late reply, was sleeping lol. You can use either, I personally would use setVariable/getVariable - If you use the other, just make sure the variable isn't broadcasted. Add me on Steam, happy to help test with you if needed. http://steamcommunity.com/id/iamhaz/ Share this post Link to post Share on other sites
pierremgi 4862 Posted November 15, 2018 [_unit] execvm "VanD_Infection.sqf" then /*VanD_Infection.sqf*/ params ["_unit","_thisEventHandler"]; _unit = _this select 0; _EHID = _thisEventHandler; If you experience some error + multiple EH , write : [_unit, _thisEventHandler] execvm "VanD_Infection.sqf" your while (true) do { sleep _freq; sleep (random 10); if (!alive player) exitwith {execvm "VanD_InfectionEH.sqf";}; will end if the player is dead, so the following if (infection_cured) seems to me impossible (if I understand). Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 16, 2018 Just now, HazJ said: Sorry for late reply, was sleeping lol. You can use either, I personally would use setVariable/getVariable - If you use the other, just make sure the variable isn't broadcasted. Add me on Steam, happy to help test with you if needed. http://steamcommunity.com/id/iamhaz/ thanks! will test both and let you know;) Share this post Link to post Share on other sites
HazJ 1289 Posted November 16, 2018 Slightly tweaked. I didn't want to change it too much as you may have been confused. This method uses setVariable/getVariable: // initPlayerLocal.sqf player setVariable ["infected", false, true]; // *** player addEventHandler ["Dammaged", { params ["_unit", "_selection", "_damage", "_hitIndex", "_hitPoint", "_shooter", "_projectile"]; if (_shooter isKindOf "CAManBase") then { [_unit, _thisEventHandler] execVM "VanD_Infection.sqf"; }; }]; // *** // VanD_Infection.sqf params ["_unit", "_EHID"]; _infected = player getVariable ["infected", false]; _freq = 60; while {_infected} do { sleep _freq + (random 10); if (!_infected) exitWith { cutText ["I am feeling better.", "PLAIN DOWN", 4]; _unit setVariable ["infected", false, true]; _unit removeEventHandler ["Dammaged", _EHID]; }; addCamShake [2, 2, 3]; _dmg = (damage _unit) + 0.05; _unit setDamage _dmg; _unit say2D [WoundedGuyA_01, 15, 3]; // I think there should be "" around unless this is a variable pointing towards a string cutText ["cough cough", "PLAIN DOWN", 4]; sleep 0.5; cutText ["", "BLACK IN", 2]; _freq = _freq - 1; }; // Respawn EH player addEventHandler ["Respawn", { params ["_unit"]; _unit setVariable ["infected", false, true]; }]; It can be cleaned up more. I personally use just do it all in the EH. I removed some stuff like select which was redundant as you used params command. I merged the two sleeps together. NOT TESTED Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 16, 2018 Just now, pierremgi said: [_unit] execvm "VanD_Infection.sqf" then /*VanD_Infection.sqf*/ params ["_unit","_thisEventHandler"]; _unit = _this select 0; _EHID = _thisEventHandler; If you experience some error + multiple EH , write : [_unit, _thisEventHandler] execvm "VanD_Infection.sqf" your while (true) do { sleep _freq; sleep (random 10); if (!alive player) exitwith {execvm "VanD_InfectionEH.sqf";}; will end if the player is dead, so the following if (infection_cured) seems to me impossible (if I understand). thanks for the tips, will test with HazJ's amended code proposal and see if such error occurs. with regards to the two exitwith: my intention was to exit the loop if the player is dead. if so, the infection check is no longer needed. in case that the player is alive, it should next check if he is still infected, if not infected anymore, the loop should stop. if he is still infected, and hence alive, the loop continues. so far i wasnt able to test it so it is still theory. but the fact that the 2nd exitwith becomes obsolete in case that the first exitwith is triggered, is the intended/desired behaviour. will keep you guys posted on my tests (hopefully tonight) cheers vd Share this post Link to post Share on other sites
HazJ 1289 Posted November 16, 2018 Ah, I forgot: // after while-loop opening: _infected = player getVariable ["infected", false]; // so like: while {_infected} do { _infected = player getVariable ["infected", false]; I used a Respawn EH to reset the infection. It may not trigger at the right time in this while loop. EDIT: I just noticed that the while loop should have {} not (). Edited post. I think I copied your original. Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 16, 2018 Just now, HazJ said: Ah, I forgot: // after while-loop opening: _infected = player getVariable ["infected", false]; // so like: while {_infected} do { _infected = player getVariable ["infected", false]; I used a Respawn EH to reset the infection. It may not trigger at the right time in this while loop. EDIT: I just noticed that the while loop should have {} not (). Edited post. I think I copied your original. yep! that looks like me, i keep putting that wrong as i just do not get why it would be code and not a condition:) ah ok, so that will pace the infected variable as local variable in the while loop space right? Share this post Link to post Share on other sites
HazJ 1289 Posted November 16, 2018 https://hazjohnson.com/ArmA/infectionTest.VR.zip Example. There are some issues but that is due to how you scripted it. You need to re-think the process as currently: - When setting infection to false, it doesn't apply instantly. - The damage you take is too much and too far apart. This means you won't really notice the effect, only once then probably instant death. For this test I did tone down the _freq variable to 15. If you need further help, just ask. // initPlayerLocal.sqf player setVariable ["infected", false, true]; player addEventHandler ["Dammaged", { params ["_unit", "_selection", "_damage", "_hitIndex", "_hitPoint", "_shooter", "_projectile"]; if (_shooter isKindOf "CAManBase") then { [_unit, _thisEventHandler] execVM "VanD_Infection.sqf"; }; }]; player addEventHandler ["Respawn", { params ["_unit"]; _unit setVariable ["infected", false, true]; systemChat format ["Am I still infected: %1", toUpper str (_unit getVariable ["infected", false])]; }]; // VanD_Infection.sqf params ["_unit", "_EHID"]; player setVariable ["infected", true, true]; _infected = player getVariable ["infected", false]; systemChat format ["Am I infected: %1", toUpper str _infected]; _freq = 15; while {_infected} do { _infected = player getVariable ["infected", false]; systemChat format ["Am I still infected: %1", toUpper str _infected]; sleep _freq + (random 10); if (!_infected) exitWith { cutText ["I am feeling better.", "PLAIN DOWN", 4]; _unit setVariable ["infected", false, true]; _unit removeEventHandler ["Dammaged", _EHID]; }; addCamShake [2, 2, 3]; _dmg = (damage _unit) + 0.05; _unit setDamage _dmg; _unit say2D ["WoundedGuyA_01", 15, 3]; // I think there should be "" around unless this is a variable pointing towards a string cutText ["cough cough", "PLAIN DOWN", 4]; sleep 0.5; cutText ["", "BLACK IN", 2]; _freq = _freq - 1; }; 1 Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 16, 2018 sweet cant wait for the vid:) yeah the numbers and timers ar just placeholders prior to testing, to be finetuned indeed. will check the process to see what order is best. thanks for your help! Share this post Link to post Share on other sites
HazJ 1289 Posted November 16, 2018 Processing stuck at 95%... Ugh. Not just the timers but the execution order too. Thinks are halted by other sleeps you added. Might need some new thread or just a whole re-think. I am too lazy to think right now though hehe. EDIT: Quick thought... I don't think the while loop is needed. Only one really, since the infection process should only happen once. Damage EH keeps doing this for you. If I feel like it later, I will re-do it and share. Video uploaded btw. 1 Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 16, 2018 oh maybe the sleep in the camshake and cuttext commands, will check! maybe its better to call these from separate scripts so the loop can flow uninterrupted 1 Share this post Link to post Share on other sites
HazJ 1289 Posted November 16, 2018 Also, change: if (_shooter isKindOf "CAManBase") then // to: if (_shooter isKindOf "CAManBase" && {!(_unit getVariable ["infected", false])}) then I am making too many mistakes lol, I am too hungry, will revise later! 1 Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 16, 2018 Just now, HazJ said: if (_shooter isKindOf "CAManBase" && {!(_unit getVariable ["infected", false])}) then oh yeah, good point! Share this post Link to post Share on other sites
Vandeanson 1677 Posted November 16, 2018 Just now, HazJ said: I am too hungry yo get some food mate;) Share this post Link to post Share on other sites