Jump to content
Sign in to follow this  
rimblock

Variable loosing value whilst script is running.

Recommended Posts

Hi,

Am hitting a perplexing issue.

I am calling a function and receiving a value back (a number).

This value is moved to another variable.

Then a few other things happen and another function is called with the saved variable and it still has the required value.

Then a few other things happen and another function is called with the saved variable and the value has reverted to a 0.

The value is not touched in this script after it is saved to that variable.

Code snippet.

_var_db_character_id = _charData; //_var_db_character_id = a number eg. 11.

// ------------------------------------------------
// Save character Location.
//
// character_id, dir, x_coord, y_coord, z_coord

_charLocation = format ["[%1,%2,%3,%4,%5]",_var_db_character_id, var_s_Default_dir, var_s_DefaultLocX, var_s_DefaultLocY, var_s_DefaultLocZ];  //_var_db_character_id still 11.
_charLocation = call compile _charLocation;
_charData = format["[""%1"",""%2"",%3]","New","Location",_charLocation];
_charData = call compile _charData;
diag_log format["[%1] Call Details: %2",_scriptname, _charData]; 

// Save character location to DB
_charSave = [_charData] call fnc_s_db_saveCharacter;

diag_log format["[%1]: Save Character location return: %2",_scriptname, _charSave];

if (_charSave isEqualTo "Error") exitWith { diag_log format["[%1] Save Character location failed..",_scriptname];_return = "Error"; _return};

diag_log format ["[%1] Save Character location successful.",_scriptname];

// ------------------------------------------------
// Save character equipment.
//
// characterID, headgear, EyeWear, Uniform, vest, backpack, assignedItems

_charLoadout = format ["[%1,%2,%3,%4,%5,%6,%7]",_var_db_character_id,_charHeadgear,_charEyewear, _charUniform, _charVest, _charBackpack, _charAssignedItems];  //_var_db_character_id has reset to 0.
_charLoadout = call compile _charLoadout;

From my logs (a few unrelated bits cut out)

22:48:51 "[ds\addons\dominion_server\functions\playerLoad\fnc_s_createNewCharacter.sqf]: Save Character return: 11"

22:48:51 "[ds\addons\dominion_server\functions\playerLoad\fnc_s_createNewCharacter.sqf] Call Details: ["New","Location",[11,0,14779.5,16441.2,0.00143814]]"

22:48:51 "[ds\addons\dominion_server\functions\playerLoad\fnc_s_createNewCharacter.sqf] Call Details: ["New","Inventory",[0,["H_Booniehat_mcamo",""],["",""],["U_IG_Guerilla1_1",["FirstAidKit","30Rnd_65x39_caseless_mag","30Rnd_65x39_caseless_mag","Chemlight_green"],[""]],["",[""],[""]],["",[""],[""]],["ItemMap","ItemCompass","ItemWatch"]]]"

I saw the same thing with another script yesterday and could not find a cause. When I tried it again today the issue had vanished. It has now returned but in a different script (different variable etc).

Only thing I could think of is the many kill / restart server process cycles as the code is amended and spun up for testing. The client is rarely logged out but just looses connection and then I just login again once the server is visible (maybe 30 + times). I have completely restarted the client but no change.

Client Machine

OS is Win 7 Pro. Machine is a i5-2400 (3.1GHz) with 8GB ram.

Test Server

OS Win 2012R2 Essentials. Machine is a i7-4790k (4GHz) with 16GB ram.

Any ideas ?.

Share this post


Link to post
Share on other sites

One of the functions is changing the variable. Make sure to privatize your variables to avoid this.

Share this post


Link to post
Share on other sites

First line of code in that sqf file

private ["_scriptname","_player","_uniform","_vest","_backpack","_primary","_secondary","_handgun","_assigned","_hmd", "_var_db_character_id"];

However....

The function that is called (fnc_s_db_saveCharacter) has none of it's local variables set as private (they are only localised by having the _ in front of the name which seems to be a bit problematic).

I shall go through all the scripts and make sure the local vars are actually in the Private line. I was under the impression that the _ makes them local but this would appear to not be the case. It seems if they are not Privatised in every script then one in another script may affect the value in the first script even if in the first script the variable is privatised.

Thanks for the input.

Share this post


Link to post
Share on other sites

I will try to explain the difference to you and explain why it is happening like that. However, I am by no means an expert and if any/all of this is wrong, someone please correct me.

I'll probably explain some stuff you already know, but in case you don't...

Okay,

First thing, functions! Functions are essentially a global variable with code attached to them. They save time by not having to rewrite the same code over and over. Plus they keep code looking nice.

// First, define a function
FT_fnc_add = { /* addition math code here */ };

// then call that function
_params call FT_fnc_add;

// the engine sees this as
_params call { /* addition math code here */ };

Now, variables! Specifically local variables and private variables. A private variable will always be a local variable but a local variable will not always be a private variable. Now, NOT privatizing variables can be useful, but not commonly used. There are some BIS functions that will modified the original variable parameter instead of creating a new one.

I'll make a simple function to show you the adverse effects of not privatizing and having local variables with the same name.

// lets make a simple functions for adding two OR three numbers together
FT_fnc_add = { 
_var0 = _this select 0;
_var1 = _this select 1;
_var2 = if (count _this > 2) then {_this select 2} else {0}; // optional third number, 0 by default
(_var0 + _var1 + _var2)
};

notice how they are NOT private

// Now lets use that function
private ["_var0","_var1","_var2","_add"]; 
_var0 = 0;
_var1 = 1;
_var2 = 2;
hint str _var2; // will show 2
_add = [_var0,_var1] call FT_fnc_add; // adds variables 0 & 1, but not 2

hint str _add; // will show 1
hint str _var2; // will now show 0

hint format ["_var0: %1 | _var1: %2 | _var2: %3 | total: %4",_var0,_var1,_var2,_add]; // shows "_var0: 0 | _var1: 1 | _var2: 0 | total: 1"

Since _var2 was an optional parameter, default set it at 0. However, since it was not private, _var2 in my script was changed to 0 as well. That would not happen if it was private.

Long story short, using a function looks like this to the engine:

// Now lets use that function
private ["_var0","_var1","_var2","_add"]; 
_var0 = 0;
_var1 = 1;
_var2 = 2;
_add = [_var0,_var1] call { 
_var0 = _this select 0;
_var1 = _this select 1;
_var2 = if (count _this > 2) then {_this select 2} else {0}; // optional third param
(_var0 + _var1 + _var2)
};

When you look at it like that, you can see how your local variable is getting changed by another script/function.

Edited by Fight9
accidently posted before finishing

Share this post


Link to post
Share on other sites

The last code snippet explained it perfectly. Thanks.

So...

Functions that call other functions are essentially bonded in a parent / child type of hierachy.

If a variable is made private in the parent, the child can still change it unless the child also defines another variable of the same name as private too.

The child has the ability to change the parents variable value but not to read it ?.

This is only the initial cut of the character loadout framework and I was a little lazy with that child script. Good to know why what was happening was actually happening.

Thanks again.

Share this post


Link to post
Share on other sites

The child has the ability to change the parents variable value but not to read it ?.

No, the function can read it as well.

FT_fnc_add = {
   (_var0 + _var1 + _var2)
};


// no params sent to the function
_var0 = 0;
_var1 = 1;
_var2 = 2;
hint str (call FT_fnc_add); // "3"

This has some uses too but nothing that great that I can think of off the top of my head... Maybe if you are constantly defining the same local vars in different scopes... you can have a global function like that to do more complicated tasks. However, using parameters instead makes a function much more robust, since you don't always have to use the SAME local variables.

It works the same way you would use a local function or a #define function.

// essentially it looks like this to the engine 
hint str (call { (_var0 + _var1 + _var2) }); // "3

Edited by Fight9

Share this post


Link to post
Share on other sites

Ok, so a privately defined variable is actually global to any child scripts unless the child scripts redefine the same variable as private themselves.

Good to know and would completely explain my issues through me not defining the same variable in called functions.

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
Sign in to follow this  

×