Jump to content
Sign in to follow this  
MichaelGER

setVariable in multiplayer

Recommended Posts

In MP, the variable space of the object is local to each client. Changes are not broadcast, except in Arma 2 via public parameter for supported types.

An object is one of these supported types but it doesnt work.

Let me describe the problem:

I spawn a object (generator, but also tested with a hummwv) local to the server. Lets name it object1.

Then i use this command on the server:

object1 setVariable ["test",true,true];

On client:

diag_log [object1 getVariable "test"]

it will write in the .rpt:

<null>

Execute setVariable on the client will also return <null> on the server.

A object like a generator or a vehicle should be a supported type of the public value, am I right?

If no, is there a workaround for it?

Share this post


Link to post
Share on other sites

Does object1 return the object on clients? Meaning, do they even know what variable object1 should contain. How are you naming the object? You probably need to do something like this:

_o = createvehicle blabla

_o setvehicleinit "object1 = this"

processinitcommands

That will sync the object1 var to point to the spawned object. Thus, enabling clients to actually use it.

Share this post


Link to post
Share on other sites

The "name" of the object is the return value of createvehicle.

In case of creating a hummwv it will be named as

0,203b7800# 438969: hmmwv.p3d REMOTE

on the client

I will try your way to name it.

---------- Post added at 03:58 PM ---------- Previous post was at 03:22 PM ----------

Bit more difficult to implement than I thought.

I will describe it better:

I spawn an object on the server. The return value of the createVehicle is written in an array. This array is publicvariabled to all clients. The client adds an action to every element of this array. The script called by addaction uses the setVariable command.

The problem is i cant use a constant name because its a dynamic spawning system.

Tried your way of naming the object but the client is still saying the object is

0,203b7800# 438969: hmmwv.p3d REMOTE

Share this post


Link to post
Share on other sites

Can you reference the index of the array, rather than the actual object? For instance, pass the index of the object within the global/public array to your script, then have your script retrieve that array position. Indeed, it isn't as easy as a just passing the object, but it may help.

Also, I would do the diag_log differently:

_testVar = object1 getVariable "test";
diag_log text format ["setvar %1", _testVar];

Probably doesn't make much difference, though?

Share this post


Link to post
Share on other sites

Not sure what you mean.

Here are some significant parts of the code:

	
_com = createVehicle [comobj, position _x, [], 0, "none"];
activecoms = activecoms + [_com];
.
.
.
publicVariable "activecoms";

in the other script:

{
_x addAction [....]
}
forEach activecoms;

Share this post


Link to post
Share on other sites

Copy paste from some old mission (before you could assemble weapons).

_v = "AGS_RU" createvehicle ([sHK_origo,random 360,random 5] call SHK_pos);
_v setvehicleinit "player reveal this";
_v setVehicleInit "this addaction [""Pack AGS"",""SHK_statics.sqf"",[""pack"",""AGS"",2,0],2,false,false,"""",""isnull (_target turretunit [0])""]";
processInitCommands;

Share this post


Link to post
Share on other sites

I added the action now via setVehicleInit. That way seems to be a little bit faster than with publicvariable and the pubvareventhandler btw. But it doesn't fix the error, the setVariable still wont be broadcasted.

Share this post


Link to post
Share on other sites

Any variable with an underscore in front of it is local to that script; the variable name will be meaningless outside of it. Use a global variable (no underscore) for your created vehicle instead.

Share this post


Link to post
Share on other sites
Um, can you not add the addaction when you create it?

The script that spawns the object is running serverside and addaction is a local command if you mean that.

But its possible to add the action global with setVehicleInit (thx @shk btw :) ) which I use directly after creating the object.

Any variable with an underscore in front of it is local to that script; the variable name will be meaningless outside of it. Use a global variable (no underscore) for your created vehicle instead.

Yeah, but the value is transferred, thats all I want :)

The other script gets the value by _this select.

E: btw I dont use the activecoms as pubvar anymore because shk's better solution of setvehicleinit.

Edited by MichaelGER

Share this post


Link to post
Share on other sites

Hey - this may be a crazy idea, but have you tried PublicVariable on the object itself?

Share this post


Link to post
Share on other sites

you mean something like this

_com = createVehicle [comobj, position _x, [], 0, "none"];
publicVariable "_com";

?

Share this post


Link to post
Share on other sites

hehe

Yeah, I know it sounds crazy (and it probably is). I've just never tried it before. :)

Share this post


Link to post
Share on other sites

You cannot publicVariable a local variable. That is why I said that you need to make it global. The whole reason that setVariable isn't working is that it is being attached to a vehicle that has no globally recognized name.

Share this post


Link to post
Share on other sites

If the problem is still client not knowing the name of the object. You can add: "object1 = this" into the setvehicleinit.

Share this post


Link to post
Share on other sites

I'm interested in this because I'm trying to make my mine addon more MP-friendly, and I'm using setVariable quite a bit. :) So - VERY helpful discussion!

So, would using a call compile format implementation be useful? Something like

_count = count PublicVariableObjectArray;
_str = "ComObject_"+ str(_count);
call compile format ["%1 = createVehicle [comobj, position _x, [], 0, ""none""]", _str];
call compile format ["PublicVariableObjectArray = PublicVariableObjectArray + [%1]", _str];
publicVariable "PublicVariableObjectArray";

??

Edit:

Or, for the array:

call compile format ["PublicVariableObjectArray set [_count, %1]", _str];

??

Edited by TRexian

Share this post


Link to post
Share on other sites

@TRexian:

Yes, I think a dynamic variable approach like that could work out nicely.

Share this post


Link to post
Share on other sites

hehe

Good f'n luck trying something that *I* suggest, though. :) Hardly ever works out for me.... :D

Share this post


Link to post
Share on other sites
You cannot publicVariable a local variable. That is why I said that you need to make it global. The whole reason that setVariable isn't working is that it is being attached to a vehicle that has no globally recognized name.

Ok, misunderstood you. Yes, I know what you mean.

The name of the object on the client is something like this

0,203b7800# 438969: hmmwv.p3d REMOTE

while the name on the server is different. Both mean the same object but setVariable doesn't recognize that, am I right?

Share this post


Link to post
Share on other sites

I did some advanced testing (I restarted the server and the client every time because of this bug.)

First run:

server.sqf (is called via radio with [1] execVM.... or [2] execVM...)

if (!isServer) exitWith{};

private ["_obj","_method"];

_method = _this select 0;

if (_method==1) then
{
_obj = createVehicle ["HMMWV_DES_EP1", position spawnpos, [], 0, "none"];
globalvar = _obj;
publicVariable "globalvar";
_obj setVariable ["test",true,true];
};

if (_method==2) then
{
_obj = createVehicle ["HMMWV_DES_EP1", position spawnpos, [], 0, "none"];
_obj setVehicleInit "testobject = this";
processInitCommands;
globalvar = _obj;
publicVariable "globalvar";
testobject setVariable ["test",true,true];
};

The diaglog.sqf (to log everything)

while {true} do
{
diag_log text format ["the value of globalvar: %1",globalvar];
diag_log text format ["the value of testobj: %1",testobject];
diag_log text format ["the value of the setvar test: %1",globalvar getVariable "test"];
sleep 5.0;
};

The results:

With setvehicleinit

Client:

the value of globalvar: 10a3e100# 438937: hmmwv.p3d REMOTE

the value of testobj: 10a3e100# 438937: hmmwv.p3d REMOTE

the value of the setvar test: true

Server:

the value of globalvar: 17d39600# 438912: hmmwv.p3d

the value of testobj: 17d39600# 438912: hmmwv.p3d

the value of the setvar test: true

Without setvehicleinit (testobj == any because its not defined in the second way)

Client:

the value of globalvar: 20fdf000# 438946: hmmwv.p3d REMOTE

the value of testobj: any

the value of the setvar test: true

Server:

the value of globalvar: 18109600# 438912: hmmwv.p3d

the value of testobj: any

the value of the setvar test: true

The second run (without publicVariable the object and only used the first method)

changed server.sqf:

if (!isServer) exitWith{};

private ["_obj","_method"];

_method = _this select 0;

if (_method==1) then
{
_obj = createVehicle ["HMMWV_DES_EP1", position spawnpos, [], 0, "none"];
globalvar = _obj;
//publicVariable "globalvar";
_obj setVariable ["test",true,true];
};

if (_method==2) then
{
_obj = createVehicle ["HMMWV_DES_EP1", position spawnpos, [], 0, "none"];
_obj setVehicleInit "testobject = this";
processInitCommands;
globalvar = _obj;
publicVariable "globalvar";
testobject setVariable ["test",true,true];
};

results:

Client:

the value of globalvar: any

the value of testobj: any

the value of the setvar test: any

Server:

the value of globalvar: 12179600# 438912: hmmwv.p3d

the value of testobj: any

the value of the setvar test: true

I think the problem has been solved (thx @ST_Dux for the tip and of course all others that helped) and hopefully the results of the test can help other people to understand setVariable better.

E: Sorry for the double post but I thought this test shouldn't be mixed up with other stuff.

Edited by MichaelGER

Share this post


Link to post
Share on other sites
I did some advanced testing (I restarted the server and the client every time because of this bug.)

That bug is completely unrelated to your problem.

First of all, try to avoid setVehicleInits for JIP MP missions wherever possible (including init lines in the editor as it is exactly the same).

SVI has some unwanted side effects (SVIs get stacked, SVIs are transferred to JIP clients even for deleted vehicles, and so on)...

Second, there are various ways to check publiced object variables on clients.

For example, after JIP let a loop run on the client over all vehicles (vehicles command) and check if the publiced variable is nil or not ({if (!isNil {_x getVariable "test"}) then {//whatever}} forEach vehicles; )

setVariable ["bla", true, true] gets tansfered to JIP clients too.

For new created vehicles on the server simply send the object reference as a publicVariable and let a publicVariable EH on the clients execute whatever code you need or use the publicVariable directly as reference.

Xeno

Share this post


Link to post
Share on other sites

First of all, try to avoid setVehicleInits for JIP MP missions wherever possible (including init lines in the editor as it is exactly the same).

SVI has some unwanted side effects (SVIs get stacked, SVIs are transferred to JIP clients even for deleted vehicles, and so on)...

Alright, I'll use the other way again with publicVariable and the EH to add the action.

For new created vehicles on the server simply send the object reference as a publicVariable and let a publicVariable EH on the clients execute whatever code you need or use the publicVariable directly as reference.

Yes, I'm using this for add the action to the new created objects.

Thank you, Xeno. Very helpful post!

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  

×