Jump to content
Sign in to follow this  
McArcher

publicVariable not working ?!

Recommended Posts

I have a problem with using publicVariable command.

At the start of the game, from init.sqf some scripts are called. Some are called for sever (with isServer check) and for clients (with not isServer check).

First of server's scripts tries to teleport players (playable units, better to say) to new location. As I understand, OFP/Arma's engine doesn't allow server to change client's (player's) coordinates at the start of the game. I killed hours for that. But I decided to make a trick.

Server's function tries to teleport a unit and then checks his coordinates. If they haven't changed, it adds a record to a public array with name of unit and its coordinates. Then it uses publicVariable to make this array public. I have checked by diag_log that it writes all data corectly.

Then... A client's script tries to read this array and find himself in it. It is done in a loop with 1 second pause after iteration.

The problem is... sometimes the script found itself, but more often it doesn't, it writes that array is empty ( [] ), but server's diag_log says it isn't empty.

Also I tried to public a boolean variable from server, client also doesn't see that it changed... (it got stuck in infinite variable checking loop)

I added sideChat format ... to client's script to watch array, but it didn't even show it! Then i put this line into call compile, it began showing empty array...

One time i was succesful and have read this array, but I think it was a miracle, 1 from a million.

Why publicVariable doesn't work?

Here are quotes from those two scripts...

Server's script:

// mca_ground_limit.sqf
// version 1.1s

if (isServer) then
{

private ["_position_found", "_tmp", "_start_pos_RU", "_start_pos_US", "_respawn_east_marker", "_respawn_west_marker", "_respawn_east_pos", "_respawn_east_pos_x", "_respawn_east_pos_y", "_respawn_west_pos", "_respawn_west_pos_x", "_respawn_west_pos_y" ];

_rnd_x_max = 14100 - 1000;
_rnd_y_max = 13500 - 1700;
_x0 = 10; _y0 = 20; _dx = 2; _dy = 5;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PHASE #1 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// creating RU base marker
_position_found = FALSE;
_start_pos_RU = [0, 0];
while {not _position_found}
do
{
	_tmp = [round (random _rnd_x_max) + 1000, round (random _rnd_y_max) + 1700];
	if ( not surfaceIsWater [_tmp select 0, _tmp select 1] ) then {_position_found = TRUE; _start_pos_RU = _tmp};
};

// _start_pos_RU -> marker
_respawn_east_marker = createMarker ["respawn_east", _start_pos_RU];
"respawn_east" setMarkerType "empty";
//diag_log format["New MHQ position is %1", _start_pos_RU];//////////////////////////////////////////////////////////////////////////////////////////////////////////
_respawn_east_pos = _start_pos_RU; //getMarkerPos "respawn_east";//
_respawn_east_pos_x = _start_pos_RU select 0;
_respawn_east_pos_y = _start_pos_RU select 1;

// creating starting base RU
RU_MHQ setPos _respawn_east_pos;
publicVariable "RU_MHQ";
RU_startVehicle_1 setPos [_respawn_east_pos_x + 15, _respawn_east_pos_y];
publicVariable "RU_startVehicle_1";
RU_startVehicle_2 setPos [_respawn_east_pos_x - 15, _respawn_east_pos_y];
publicVariable "RU_startVehicle_2";

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// creating US base marker
_position_found = FALSE;
_start_pos_US = [0, 0];
while {not _position_found}
do
{
	_tmp = [round (random _rnd_x_max) + 1000, round (random _rnd_y_max) + 1700];
	if ( not surfaceIsWater [_tmp select 0, _tmp select 1] ) then {_position_found = TRUE; _start_pos_US = _tmp};
};

// _start_pos_US -> marker
_respawn_west_marker = createMarker["respawn_west", _start_pos_US];
"respawn_west" setMarkerType "empty";
_respawn_west_pos = _start_pos_US; //getMarkerPos "respawn_west";
_respawn_west_pos_x = _start_pos_US select 0;
_respawn_west_pos_y = _start_pos_US select 1;

// creating starting base US
US_MHQ setPos _respawn_west_pos;
publicVariable "US_MHQ";
US_startVehicle_1 setPos [_respawn_west_pos_x + 15, _respawn_west_pos_y];
publicVariable "US_startVehicle_1";
US_startVehicle_2 setPos [_respawn_west_pos_x - 15, _respawn_west_pos_y];
publicVariable "US_startVehicle_2";

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PHASE #2 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////	

private ["_i", "_angle", "_cP", "_dA", "_r", "_uP"];
_dA = 9; //delta angle
_r = 25; //radius
_RetryRU = []; // array for units which don't change positions (i.e. players)
_RetryUS = [];

// moving players to base RU
_cP = position RU_MHQ; //center positon
_i = 0;
{
	_angle = _i * _dA;
	_uP = [(_cP select 0) + ((cos _angle) * _r), (_cP select 1) + ((sin _angle) * _r)]; //unit position
	_x setPos _uP;
	//diag_log format ["_cP=%1, _angle=%2, _r=%3, _uP=%4.", _cP, _angle, _r, _uP];//dbg//////////////////////////////////////////////////////////
	if (        (((position _x) select 0) != (_uP select 0))   and   (((position _x) select 1) != (_uP select 1))         ) then 
	{ 
		mcti_RetryRU = mcti_RetryRU + [[_x, _i, _uP]]; // we are added to this array, client must find himself in this array and teleport to coordinates given!
	};  // adding [RU_player_**, *, ***] to array
	_i = _i + 1; 
} foreach RU_players;
publicVariable "RU_players";
publicVariable "mcti_RetryRU";
diag_log mcti_RetryRU;//dbg///

// moving players to base RU
_cP = position US_MHQ; //center positon
_i = 0;
{
	_angle = _i * _dA;
	_uP = [(_cP select 0) + ((cos _angle) * _r), (_cP select 1) + ((sin _angle) * _r)]; //unit position
	_x setPos _uP;
	if (        (((position _x) select 0) != (_uP select 0))   and   (((position _x) select 1) != (_uP select 1))         ) then 
	{ 
		mcti_RetryUS = mcti_RetryUS + [[_x, _i, _uP]]; // we are added to this array, client must find himself in this array and teleport to coordinates given!
	};  // adding [uS_player_**, *, ***] to array
	i=i+1; 
} foreach US_players;
publicVariable "US_players";
publicVariable "mcti_RetryUS";
diag_log mcti_RetryUS;//dbg///

};

Client's script (only upper part of it is needed to understand)

// mca_jip.sqf
// version 1.1c

if (not isServer) then
{

if (time > 5) then { mcti_JIP = TRUE; } else { mcti_JIP = FALSE; };
waitUntil { time > 1};
waitUntil { not isNull player };	
player groupChat format ["Loading... Please wait..."];
removeAllWeapons player;

/////////////////////////////////////////////////////////////////////////////// updating position //////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Server: mcti_RetryRU = mcti_RetryRU + [[_x, _i, _uP]];
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

private ["_i", "_angle", "_cP", "_dA", "_r", "_uP", "_tmp", "_found", "_newCoordinates"];
_dA = 9; //delta angle
_r = 20; //radius
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if ((side player) == east) then
{
	// searching in mcti_RetryRU
	_found = FALSE;
	while {not _found} do
	{
		_found = FALSE;
		call compile "_tmp = mcti_RetryRU;";
player groupChat format ["Retry=%1", _tmp];//dbg//////////////////////
diag_log _tmp;//dbg///
		{
			if (player == 	(_x select 0)) then
			{
				_found = TRUE;
				_newCoordinates = _x select 2;
			};
			if (_found) exitWith {};
		} forEach _tmp;
		sleep 1;
	};

	// teleporting
	player setPos _newCoordinates;
	player groupChat format ["Position updated."];
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if ((side player) == west) then
{
	// searching in mcti_RetryUS
	_found = FALSE;
	while {not _found} do
	{
		_found = FALSE;
		_tmp = mcti_RetryUS;
		{
			if (player == 	(_x select 0)) then
			{
				_found = TRUE;
				_newCoordinates = _x select 2;
			};
			if (_found) exitWith {};
		} forEach _tmp;
		sleep 1;
	};

	// teleporting
	player setPos _newCoordinates;
	player groupChat format ["Position updated"];
};

//////////////////////////////////////////////////////////////////////////////////updating actions/////////////////////////////////////////////////////////////////////////////////////////////////////////////

player addAction ["Game Score", "mca_show_gameScore.sqf",[], 0, FALSE];

////////////////////////////////////////////////////////////////////////////////////updating markers/////////////////////////////////////////////////////////////////////////////////////////////////////////
//_obj SetVehicleInit "This setFlagTexture ""ca\data\flag_rus_co.paa""";
//ProcessInitCommands;
private ["_name"]; // _i was before
_i = 0;
player groupChat format ["Updatng town markers...", _i, _name, (mcti_town_markerCoords select _i) select 0, (mcti_town_markerCoords select _i) select 1, (mcti_flag_owners select _i)];
{
	//_name = "twn_" + (str _i);
	_name = _x;////////
	createMarker [_name, mcti_town_markerCoords select _i];
	_name setMarkerShape "ICON";
	_name setMarkerType "mil_circle";
	_name setMarkerColor "ColorYellow";	
	if ( (mcti_flag_owners select _i) == 0 ) then 
	{
		_name setMarkerColor "ColorBlack";
	} else { if ( (mcti_flag_owners select _i) == 1 ) then 
				{
					_name setMarkerColor "ColorRed";
				} else { if ( (mcti_flag_owners select _i) == 2 ) then 
							{
								_name setMarkerColor "ColorBlue";
							};
				};
	};
	_i = _i + 1;
} forEach mcti_towns;

////////////////////////////////////////////////////////////////////////////////////updating markers/////////////////////////////////////////////////////////////////////////////////////////////////////////

[] execVM "mca_side_markers_resync.sqf";

//////////////////////////////////////////////////////////////////////// my_side (global, but NOT public variable. don't ever use publicVariable with it !!!  /////////////

my_side = side player;	
my_resp = "MHQ";

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

[] execVM "mca_hq_clients_eh.sqf";

};

---------- Post added at 06:13 ---------- Previous post was at 06:01 ----------

server's .rpt had

2010/01/09, 4:45:01 [[RU_player_1,0,[2764.45,8567.41]]]

2010/01/09, 4:45:01 []

first array is for RU-, second - for US-players.

client's .rpt had

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

[]

---------- Post added at 06:14 ---------- Previous post was at 06:13 ----------

i check

call compile "_tmp = mcti_RetryRU;";
, so i didn't swap arrays as you could think if didn't read code Edited by McArcher

Share this post


Link to post
Share on other sites

What I would suggest: Work around using the diffuse publicVariable. Use setVariable instead. You can use a global gamelogic to store variables (or any object, players, vehicles, whatever). For example, lets call a gamelogic "MHQ_West". In it you store "US_players":

Server:

MHQ_West setVariable ["US_players",_thearray,true]; (true is send over network, false is dont)

Client:

_thearray = MHQ_West getVariable "US_players";

Share this post


Link to post
Share on other sites

Trying to do it in a way too complicated manner. Just find positions on server, put both of them in an array. Pubvar that. On clients wait for the variable. Move them. Keeping it simple; server moves AI and vehicles, players all move themselves.

Basic idea:

if (isserver) then {
 //bla bla bla
 startpos = [_start_pos_RU,_start_pos_US];
 publicvariable "startpos";
} else {
 //bla bla bla
 waituntil {!isnil "startpos"};
 switch (side player) do {
   case EAST: { player setpos (startpos select 0) };
   case WEST: { player setpos (startpos select 1) };
 };
};

Share this post


Link to post
Share on other sites
Trying to do it in a way too complicated manner. Just find positions on server, put both of them in an array. Pubvar that. On clients wait for the variable. Move them. Keeping it simple; server moves AI and vehicles, players all move themselves.

Basic idea:

if (isserver) then {
 //bla bla bla
 startpos = [_start_pos_RU,_start_pos_US];
 publicvariable "startpos";
} else {
 //bla bla bla
 waituntil {!isnil "startpos"};
 switch (side player) do {
   case EAST: { player setpos (startpos select 0) };
   case WEST: { player setpos (startpos select 1) };
 };
};

do you think it will really make that array public? I tried with array and a boolean, and they weren't visible...

waituntil {!isnil "startpos"};

is waiting for the undefined variable to become defined, but what if I already have it defined and it changes its value (like my array) ? what if I need to do this not only once, but several times during game (some other scripts for example)?

---------- Post added at 17:58 ---------- Previous post was at 17:56 ----------

What I would suggest: Work around using the diffuse publicVariable. Use setVariable instead. You can use a global gamelogic to store variables (or any object, players, vehicles, whatever). For example, lets call a gamelogic "MHQ_West". In it you store "US_players":

Server:

MHQ_West setVariable ["US_players",_thearray,true]; (true is send over network, false is dont)

Client:

_thearray = MHQ_West getVariable "US_players";

i hope it will help, I'll check soon.

---------- Post added at 17:58 ---------- Previous post was at 17:58 ----------

can I use "server" gamelogic for that?

---------- Post added at 18:08 ---------- Previous post was at 17:58 ----------

oh, I forgot how to place a gamelogic in editor :D

Share this post


Link to post
Share on other sites

If you want to do something every time a varialbe is changed, use addPublicVariableEventHandler. If you just want to use the variable and you have it defined client-side already, then you can use it, but you need to be sure that it actually has the value you want to use...

It really depends what kind of info is in that variable that you want to use and what you use it for.

Also, the only reliable way I found for checking whether or not the player is JIP is this:

in init.sqf:

if (isServer) then
{
isJIP=false;
publicVariable "isJIP";
isJIP=true;
};
onPlayerConnected "
publicVariable 'isJIP';
";

And then in order to check for JIP you run:

waitUntil {!isNil "isJIP"};
if (isJIP && !isServer) then
{
// whatever
}
else
{
// whatever
};

Of course this will only work in interruptable context, that is, you can't put it in (some?) event handlers, init lines... Note that the !isServer check is important, as the isJIP variable is true on the server even though the server is not a JIP player. isJIP WILL be true for all JIP clients and false for all non-JIP clients once it is defined. Any other kind of JIP check does not seem to be 100% reliable.

Share this post


Link to post
Share on other sites
do you think it will really make that array public?

Yes.

but what if I already have it defined and it changes its value (like my array) ? what if I need to do this not only once, but several times during game (some other scripts for example)?

Then add a pubvarEH for clients that catch the var and run the side check and setpos.

Share this post


Link to post
Share on other sites
It really depends what kind of info is in that variable that you want to use and what you use it for.

in my script JIP is ok, problem with that arrays (two arrays: 1 for RU and 1 for US):

if ( (((position _x) select 0) != (_uP select 0)) and (((position _x) select 1) != (_uP select 1)) ) then

{

mcti_RetryUS = mcti_RetryUS + [[_x, _i, _uP]]; // we are added to this array, client must find himself in this array and teleport to coordinates given!

}; // adding [uS_player_**, *, ***] to array

---------- Post added at 18:27 ---------- Previous post was at 18:21 ----------

Trying to do it in a way too complicated manner. Just find positions on server, put both of them in an array. Pubvar that. On clients wait for the variable. Move them. Keeping it simple; server moves AI and vehicles, players all move themselves.

Basic idea:

if (isserver) then {
 //bla bla bla
 startpos = [_start_pos_RU,_start_pos_US];
 publicvariable "startpos";
} else {
 //bla bla bla
 waituntil {!isnil "startpos"};
 switch (side player) do {
   case EAST: { player setpos (startpos select 0) };
   case WEST: { player setpos (startpos select 1) };
 };
};

maybe, but I wanted to make client's script as simple as possible, and it is so if you look at it - it just reads cordinates and teleports himself there.

in your metod< client should calculate his position himself according to his place in array of playable units. (positon is different for various playale units!)

---------- Post added at 18:28 ---------- Previous post was at 18:27 ----------

how to place a gamelogic in editor? I have forgotten :(

don't see in F1 or F7...

---------- Post added at 18:32 ---------- Previous post was at 18:28 ----------

i can place gamelogic in empty mission! but in my - i cannot! why so?

---------- Post added at 18:34 ---------- Previous post was at 18:32 ----------

f**k..... i need to place an object like a car first..... very interesting idea.....:D

---------- Post added at 18:37 ---------- Previous post was at 18:34 ----------

maybe publicVariable didn't work because there are no objects in mission in editor (except playable units) ? I couldn't add a gamelogic without adding a vehicle on map and deleting it after gl placing ?

Edited by McArcher

Share this post


Link to post
Share on other sites

If you want to teleport the player every time the server publicVariables the position then just use addPublicVariableEventHandler. If you want the teleportation to not necessarily happen every time, then either have a condition check in the event handler or have the server publicVariable something else (ex: a variable that holds the unit that should teleport) that will allow you to know if it should teleport or not, and add an event handler to that instead.

Share this post


Link to post
Share on other sites
If you want to teleport the player every time the server publicVariables the position then just use addPublicVariableEventHandler. If you want the teleportation to not necessarily happen every time, then either have a condition check in the event handler or have the server publicVariable something else (ex: a variable that holds the unit that should teleport) that will allow you to know if it should teleport or not, and add an event handler to that instead.

I tried to pub a single boolean, and client didn't see it! I don't know why.... :(

it was reading it in infinite loop and it didnt even change... though server changed and published it... I'm trying with GameLogic now.... lets see what will happen.....

---------- Post added at 18:58 ---------- Previous post was at 18:55 ----------

woohoo!!!!

---------- Post added at 18:59 ---------- Previous post was at 18:58 ----------

Murklor, thanks again for help! it works!!!

---------- Post added at 19:00 ---------- Previous post was at 18:59 ----------

Now, I don't know why BIS made publicVariable command/function if it is not working... maybe there are some hidden aspects of its work? like, it can transfer value before script execution but not during its execution , or something like new easter egg from BIS..... this game is a bigger surprise every thing I look into..... (publicVariable, cargo of vehicles, coin,.... what will be next bug? lol :D)

Edited by McArcher

Share this post


Link to post
Share on other sites
Now, I don't know why BIS made publicVariable command/function if it is not working... maybe there are some hidden aspects of its work? like, it can transfer value before script execution but not during its execution , or something like new easter egg from BIS..... this game is a bigger surprise every thing I look into..... (publicVariable, cargo of vehicles, coin,.... what will be next bug? lol :D)

Everything you look into.

Yet to see pubvar not work. You must have a special version of the game.

Share this post


Link to post
Share on other sites

Publicvariable is certainly working, but as I said I've found it so diffuse to work with. Much more comfortable with object->attached_variable way of thinking.

Share this post


Link to post
Share on other sites

Did you even check if the script even reaches the part where the variable is checked? Remember some things will break your script with absolutely no error messages (such as trying to access an undefined variable or using a null object for something that requires a valid object).

publicVariable is definitely working just fine when used in scripts that are written correctly...

Share this post


Link to post
Share on other sites

I have already written that. Yes, script was executed and there were no errors in .rpt. I saw "[]" on the screen as a result of sideChat command output.

I added sideChat format ... to client's script to watch array, but it didn't even show it! Then i put this line into call compile, it began showing empty array...

---------- Post added at 21:37 ---------- Previous post was at 21:25 ----------

well, array was defined in the script (init.sqf) that executed client's script , so no isNil was needed...

Share this post


Link to post
Share on other sites

isnil check would have been simple, but since that's not your way. You could do something like: waituntil {count mcti_RetryRU > 0};

What the heck is even point of doing this? :)

call compile "_tmp = mcti_RetryRU;";

Share this post


Link to post
Share on other sites
isnil check would have been simple, but since that's not your way. You could do something like: waituntil {count mcti_RetryRU > 0};

What the heck is even point of doing this? :)

call compile "_tmp = mcti_RetryRU;";

it was done to check if compile was working :D

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  

×