Jump to content
Vandeanson

SetVariable for Client only

Recommended Posts

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 by Vandeanson
OP updated in spoiler/code

Share this post


Link to post
Share on other sites
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

 

  • Thanks 1

Share this post


Link to post
Share on other sites

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
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

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

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

[_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
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

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
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

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
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

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;
};

 

  • Like 1

Share this post


Link to post
Share on other sites

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

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. :happy:

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.

  • Thanks 1

Share this post


Link to post
Share on other sites

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

  • Like 1

Share this post


Link to post
Share on other sites

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!

  • Haha 1

Share this post


Link to post
Share on other sites
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
Just now, HazJ said:

I am too hungry

yo get some food mate;)

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

×