Home   Help Search Login Register  

Author Topic: setVariable/getVariable behaviours  (Read 4589 times)

0 Members and 1 Guest are viewing this topic.

Offline myke13021

  • Contributing Member
  • **
  • Myke
setVariable/getVariable behaviours
« on: 25 Apr 2008, 15:06:04 »
Sadly i don't have a server where i could test it out so i have to ask here.

Quote from: setVariable
Description:
    Set variable to given value in the variable space of given object or location. In MP, the variable space of the object is local to each client. Changes are not broadcast.
Quote from: getVariable
Description:
    Return the value of variable in the variable space of given object or location.

So let me see if i get this correc: if i set an objects variable using setvariable on one client and another client running a script which uses getVariable on same object and same variablename, second client will NOT get the value i set on the first client.

To make sure, the object variable are the same on each client, i have to use publicvariable when i set the variable and on the receiving clients i have to use addPublicVariableEventHandler to catch the broadcasted variable and then use setVariable on the object to set it to the changed value.

Is this correct?

Myke out

Offline Loyalguard

  • Former Staff
  • ****
Re: setVariable/getVariable behaviours
« Reply #1 on: 25 Apr 2008, 17:22:53 »
I don't think this is as problematic as it sounds.  I have used get/setVariable on objects that have changed locality without major issue (meaning the value last set to the car was still available after a locality change).

So, if Player A uses setVariable on an object that is local to him and then Player B uses getVariable on that same object to get its vaue, even if not local to him, he will get the same value that Player A would get.   But, If Player A uses setVariable to change the value, Player B will have the incorrect value until he uses getVariable again.

So, if Player B needs to always have the most current value, you will need to make sure to use getVariable again before every critical point where the value is needed.

I hope that makes sense, here is an example:

1. Let's say we have a car named car1.  Player A is the driver (car1 is local to him) and Player B is the passenger (car1 is not local to him).  Let's also say we have a script that loops on each client that plays music like a car radio (not shown here).  The music is activated by monitoring a global variable we have created called radioOn.  If true it plays music, if false it doesn't.  When the car is created (not shown here), it is empty and hence local to the server so setVariable is used to record the default state of the radio in car1 (false/off).

Code: [Select]
car1 setVariable ["car1RadioOn", false];
2. Now, when Player A & Player B get in car1, a Get In eventhandler (not shown here) gets the value of "car1RadioOn" from car1 to determine whether or not music should be played.  This code runs on each client:

Code: [Select]
radioON = car1 getVariable "car1RadioOn";
3. Since "radioOn" was false, the global variable radioON will also be false for both clients and no music will be played for either player.

4. Now, let's say Player A decides to play some tunes  :cool2:  He runs a script on his client only that changes radioON to true and sets the same value to the vehicle.

Code: [Select]
radioOn = true;
car1 setVariable ["car1RadioOn", radioOn];

5. Now, since the loop script on Player B's client is only monitoring the global variable radioOn, he thinks the radio is still off and no music is played even though player A is grooving to the tunes.  So, until Player B runs another instance of getVariable on car1 to get the latest value of "car1RadioOn" which is used to update radioOn, he will not hear any music.

So, in order to make sure that all clients have the same value, you just have to make sure to use getVariale on all clients at the right times.
« Last Edit: 25 Apr 2008, 17:53:59 by Loyalguard »

Offline myke13021

  • Contributing Member
  • **
  • Myke
Re: setVariable/getVariable behaviours
« Reply #2 on: 25 Apr 2008, 18:32:12 »
Thanks Loyalguard, i was affraid that i have to make a script to update the values on each client. But since the scripts i have already reads the actual variables each time they run, it is guaranteed that variables are always up to date.

Offline Spooner

  • Members
  • *
  • Mostly useless
    • Community Base Addons
Re: setVariable/getVariable behaviours
« Reply #3 on: 28 Apr 2008, 15:09:21 »
I'm pretty sure that object variables don't synchronise at all, just like global variables (but normal global variables can be told to sync by using publicVariable command, which doesn't work on object variables). The only way I can think of to sync them would be to use one of the normal ways to send data (publicVariable event handlers or one of the older techniques mentioned in OFPEC's MP tutorial) to update them manually.
[Arma 2] CBA: Community Base Addons
[Arma 1] SPON Core (including links to my other scripts)

Offline Mandoble

  • Former Staff
  • ****
    • Grunt ONE and MandoMissile suite
Re: setVariable/getVariable behaviours
« Reply #4 on: 28 Apr 2008, 15:48:27 »
Correct, vehicle vars are never synced.

Offline myke13021

  • Contributing Member
  • **
  • Myke
Re: setVariable/getVariable behaviours
« Reply #5 on: 28 Apr 2008, 18:32:20 »
Let me give a practical example for my situation.

I have an object which is local to the server. At missionstart i assign several variables to it as initialization.
Code: [Select]
_object setVariable ["My_variable", true];

And i have a script which should read the variable of the object.
Code: [Select]
_local_variable = _object getVariable "My_variable";
if (! _local_variable) exitwith {};
if (_local_variable) then
{
_object setVariable ["My_variable", false];
};
This script does only run on the calling clients, NOT on the server.

So, at the beginning the variable is initialized to be FALSE, Client A runs the script which does set the variable to TRUE. What i need to know, if Client B calls the same script after Client A, what value will he get? My_variable == false since it is done in the init.sqf? Or will he get My_variable == true as the script running on Client A set it?
« Last Edit: 28 Apr 2008, 18:34:53 by myke13021 »

Offline Mandoble

  • Former Staff
  • ****
    • Grunt ONE and MandoMissile suite
Re: setVariable/getVariable behaviours
« Reply #6 on: 28 Apr 2008, 19:51:02 »
vehicle variables are always local, they are not broadcasted.

Offline Spooner

  • Members
  • *
  • Mostly useless
    • Community Base Addons
Re: setVariable/getVariable behaviours
« Reply #7 on: 28 Apr 2008, 19:53:19 »
Erm, I think you are a bit confused, since the first script (said to run at mission start) actually sets the value of the object variable to TRUE, not to false as you state in the description below. I'll ignore your example and give one of my own.

Here is an example:
1. At init time, both client A and B set the value to false.
2. Client A sets the value to true.
3. Now client B reads the value as false, but client A reads the value as true.

Remember, object variables are always LOCAL, unlike global variables (which can be publicVariabled). That is, changes cannot be automatically synchronised across machines, but you could do this manually by running code on all machines (if you are using ArmA 1.09 or higher, use addPublicVariableEventHandler, but if you are stuck with version 1.08, then use one of the techniques described in the MP tutorial).
[Arma 2] CBA: Community Base Addons
[Arma 1] SPON Core (including links to my other scripts)

Offline Loyalguard

  • Former Staff
  • ****
Re: setVariable/getVariable behaviours
« Reply #8 on: 28 Apr 2008, 20:34:46 »
Hmm...

I may have misunderstood some results I have had with this when I advised Myke earlier, if so I apoligize.   This is what I did:

I used a getin event handler to assign an addAction to a vehicle and set a boolean variable to it to note that it had that particular addAction added to it.  I also set an integer variable to it that recorded the action id of the addAction for later reference.

So, if a  unit got in the vehicle the script would check the boolean to see if an action had already been assigned and if not then add one otherwise it would exit since the action was there already.

I used a get out event handler that used getVariable to retrieve the action id and remove the action.

I may have thought that the setvariable used on one client correctly transfered to a second client because duplicate addActions did not occur, but, that may have been becuase the addActions are local to each client so you wouldn't necessarily see ones assigned on other clients anyway.

What about using setVehicleInit/processInitCommands  to setVariable a value?

Offline myke13021

  • Contributing Member
  • **
  • Myke
Re: setVariable/getVariable behaviours
« Reply #9 on: 28 Apr 2008, 21:09:06 »
So even if the Object to which i set the variables is local to the server, the values are local to each Client. So therefor if i change a variable using setvariable, this wont change the variable on the servers object and therefor any other client will not get the changed variable unless iti s changed on the client itself.

Then i guess using setvariable and getvariable are rather useless as it doesn't do anything else than normal public variables. Only benefit it has that variables are connected to an object and same variablename can be used on multiple objects.

So i have to rewrite the scripts so that every change of a variable by setvariable is broadcasted and i need a script on clientside running that catches these broadcasts and updates the variables to the new values.

I guess publicvariable doesn't work with this kind of variables.

MP scripting can really be a pain in the.....you know where.

Offline Spooner

  • Members
  • *
  • Mostly useless
    • Community Base Addons
Re: setVariable/getVariable behaviours
« Reply #10 on: 29 Apr 2008, 13:29:08 »
@LocalhostLoyalGuard: Action numbers are assigned local to the client anyway, so if they were broadcast between clients, you could end up removing the wrong action, or no action at all, on some of the clients.

@Myke: Yup, MP is a veritable nightmare for all of us. At least when they finalise 1.09/1.11/1.12 betas we will finally all have access to that new comms command (addPublicVariableEventHandler), which will make things a bit, though not enough in my opinion, easier.
« Last Edit: 29 Apr 2008, 14:21:31 by Spooner »
[Arma 2] CBA: Community Base Addons
[Arma 1] SPON Core (including links to my other scripts)

Offline myke13021

  • Contributing Member
  • **
  • Myke
Re: setVariable/getVariable behaviours
« Reply #11 on: 29 Apr 2008, 13:53:29 »
Quote
@Localhost: Action numbers are assigned local to the client anyway, so if they were broadcast between clients, you could end up removing the wrong action, or no action at all, on some of the clients.
This isn't a problem since i do not remove actions. I just call the script trhough an action and therefor the script is local to this client. I thought that when i assign a variable to an Object which is probably not local to the Client (but local to server) a getVariable will get the correct (changed) variable no matter from which client it is done.
I guessed (as i see, probably wrong) that serverlocal objects wouldn't have a clientlocal variable space.

Ok, this is no big deal, i can work this out with publicvariable and addPublicVariableEventHandler to broadcast and catch all changes made on each client. A little more work for something i guessed it would be possible easier.

:EDIT:
On the BIWIKI it says the following about addPublicVariableEventHandler:
Quote
Anunnaki
    Very important ! addPublicVariableEventHandler does NOT WORK on dedicated server or player server! This is probaly bug in 1.09beta
Anyone knows if this is fixed on later betapatches (1.11 & 1.12)?

:2nd EDIT:
Let me see if i got this correctly worked out.
In the init.sqf (which is executed on every machine) i got these 2 lines:
Code: [Select]
STM_update = [];
"STM_update" addPublicVariableEventHandler {nul = this execVM "STM_AI_CARRIER_SIM\STM_functions\STM_updater.sqf"};
To have something generic, i wrote the STM_updater.sqf
Code: [Select]
_STM_var_name = _this select 0;
_STM_var_array = _this select 1;

_STM_object = _STM_var_array select 0;
_STM_variable = _STM_var_array select 1;
_STM_value = _STM_var_array select 2;

_STM_object setVariable [_STM_variable, _STM_value];
And in the scripts which may alter variables, i have this:
Code: [Select]
_STM_carrier setvariable [_STM_callsign, false];
STM_update = [_STM_carrier, _STM_callsign, false];
publicvariable "STM_update";
So if i have this correctly understood, at mission start (init.sqf) i create the basic update variable as an empty array and attach addPublicVariableEventHandler on it.

So if the script runs (last snippet) it will first change the variables locally using setvariable, afterwards i collect the object, the variablename (set previously) and it's new value into the public array (same as defined in the init.sqf).
And finally i use publicvariable to broadcast the array.

On all clients, this publicvariable will be catched through the addPVEH which will launch the STM_updater.sqf and in there it reads the new values and sets the object variables to the new value.
« Last Edit: 29 Apr 2008, 18:49:19 by myke13021 »

Offline Spooner

  • Members
  • *
  • Mostly useless
    • Community Base Addons
Re: setVariable/getVariable behaviours
« Reply #12 on: 29 Apr 2008, 18:32:58 »
There is nothing wrong with addPublicVariableEventHandler in 1.09, 1.11 or 1.12. What I suspect your fellow is confused by is that the handler is ONLY executed on machines OTHER than the one where the publicVariable command is issued (which is as it is supposed to work). Thus, if publicVariable is used on a server, then the handler will work only on the clients. If used on a client, it will work on the server and all the other clients.

EDIT (for edit 2 above):
The code looks fine, but you really shouldn't be needlessly execVMing in this case. Try pre-compiling the script as a function instead:
Code: [Select]
STM_update = [];
_updateHandler = compile preprocessFileLineNumbers "STM_AI_CARRIER_SIM\STM_functions\STM_updater.sqf";
"STM_update" addPublicVariableEventHandler _updateHandler;
« Last Edit: 29 Apr 2008, 19:00:37 by Spooner »
[Arma 2] CBA: Community Base Addons
[Arma 1] SPON Core (including links to my other scripts)

Offline myke13021

  • Contributing Member
  • **
  • Myke
Re: setVariable/getVariable behaviours
« Reply #13 on: 30 Apr 2008, 00:12:10 »
Ok, thx Spooner, changed it according to your suggestions. As all questions are answered and the "problem" is solved...


*CLOSE*