Jump to content
Sign in to follow this  
Wolfenswan

Problem with addAction and dynamically placed object (related to # of players?)

Recommended Posts

I'm having a very strange and frustrating issue in a dynamic mission of mine:

In theory an object (Wreck) is placed randomly in Chernarus and after that is done a action is added to it, allowing to start a data transfer.

The problem is that apparently with a certain number of players (20+) this doesn't work reliably: the action isn't added and can't be called. However, it does work as intended when testing locally, alone on a dedi or with 3+ players on a dedi.

The relevant bit of code, executed on all clients:

waituntil {(ws_initdone)};

if (isNil "ws_uploadaction") then {
ws_uploadaction = Wreck addAction ["<t color='#dddd00'>"+"Begin transfer"+"</t>","ws_scripts\ws_uploadaction.sqf",nil,1,false,true,"","((_target distance _this) < 9) && (group _this != grpRU_Grnd)"]; 
};

ws_initdone is flipped to true once a good location for the Wreck has been found and it has been placed.

Things I've tried without success:

- Adding the action to the Wreck, then moving it

- adding the action to the Wreck via the unit init field in the editor

I'm at the end of my wits now, any ideas?

Edited by Wolfenswan

Share this post


Link to post
Share on other sites

Personally I try to never use nil, since it's quite usual in scripts that nil is overrided, and in that case it may be anything. I'd send in [] or objNull. That's maybe a long shot in this particular case, but you never know...

Have you tried command setVehicleInit that automatically executes it on all machines? Is ws_uploadaction set on clients some other way? ...

Exactly what happens when you play 20+ players?

Share this post


Link to post
Share on other sites
Exactly what happens when you play 20+ players?

Action simply doesn't appear.

Have you tried command setVehicleInit

It might work but aren't BIS significantly changing setVehicleInit due hackers on public servers and it might even be cut entirely? I'm a bit wary of using it.

I might just remove the addAction entirely from the mission init and put it into a trigger that fires once players close in on the crash site.

Edited by Wolfenswan

Share this post


Link to post
Share on other sites

I would add this action on the server side only. Remember that the addaction is local to the player that calls it so the stuff in the scrpt will not be shown to the other players. If you want others to see this stuff then you need to use the RE commads http://community.bistudio.com/wiki/Multiplayer_framework. What is the script doing that you call from the addaction?

Share this post


Link to post
Share on other sites

Is the add action shown for every one, or only for some? or is it shown for all but only works for some?

could also be that it is no longer nil by the time the 5th + player joins, thus addaction doesnt show. best bet as ghost states - make like easier use the mp framework.

Share this post


Link to post
Share on other sites

Is it maybe just a delay thing? I mean, if you had the time, would the action eventually appear? It used to be I saw some quite horrendous "script-lag" even in SP, but that was mostly due to me having too much going on. It may be the case though that you have too much going on, do you use a lot of addons in your MP sessions?

Share this post


Link to post
Share on other sites
Is the add action shown for every one, or only for some?

It should be shown for everyone but not a single unit is able to call it when the bug occurs.

Is there a better documentation for it?

I don't see how it would help me in this particular case as the issue isn't caused by locality problems.

What is the script doing that you call from the addaction?

The script (local) itself only flips a variable to true and then makes it publicvar.

A trigger listens to said variable and starts doing stuff (global) when it rings true.

This works perfectly fine in all tests where the action actually does appear (see OP).

Is it maybe just a delay thing? I mean, if you had the time, would the action eventually appear?

Players take about 5-15 minutes to get to the Wreck which doesn't even account for clearing it of hostiles.

Also there's stuff happening in the script after the action is added which works fine so this would be a very weird delay.

Thanks for your advice so far, I might try adding an isServer clause and remove the nil check; if debugging this mission only wouldn't be so painful :S

Share this post


Link to post
Share on other sites

The script is working fine, there a no script errors.

isserver is not needed in the addaction script

not in but around, as in:

if (isServer) then {

... addaction ...

};

(see below)

Post some more of your scripts.

For easier reading I've now split my init into two seperate inits, one for Server the other for client.

init.sqf starts:

ws_init_server = [] execVM "ws_scripts\ws_init_server.sqf";
ws_init = [] execVM "ws_scripts\ws_init.sqf";

ws_init_server

if !(isServer) exitWith {};

//Wolfenswan - required variables
if (isNil "ws_initdone") then {ws_initdone = false;publicvariable "ws_initdone";};
if (isNil "ws_markersdone") then {ws_markersdone = false;publicvariable "ws_markersdone";};
if (isNil "ws_uploadstarted") then {ws_uploadstarted = false;publicvariable "ws_uploadstarted";};
if (isNil "ws_uploaddone") then {ws_uploaddone = false;publicvariable "ws_uploaddone";};
if (isNil "ws_mapclicked") then {ws_mapclicked = false;publicvariable "ws_mapclicked";};

//Wolfenswan - server side scripts
ws_placewreckage = [] execVM "ws_scripts\ws_placewreckage2.sqf";
ws_wreckmarkers = [] execVM "ws_scripts\ws_wreckmarkers.sqf";

waitUntil {scriptDone f_processParamsArray};

if (f_var_debugMode == 0) then {deleteVehicle trgDBG; deleteVehicle trgDBG_1;};
if (f_param_uav == 0) then {deleteVehicle UnitRU_UAV;deleteVehicle mdlULB;deleteVehicle UnitRU_Terminal;deleteMarker "mkrTerminal";};

ws_init:

//Invisible markers
{_x setMarkerAlpha 0;} forEach ["mArea","mArea_1","mArea_2","mArea_3","mArea_4","mArea_5"];

//Precompiling stuff we need later
BIS_Effects_Burn = compile preprocessFile "\ca\Data\ParticleEffects\SCRIPTS\destruction\burn.sqf"; 
call compile preprocessfile "SHK_pos\shk_pos_init.sqf";

//Launching client side scripts - Wolfenswan
[] execVM "ws_scripts\ws_Intro.sqf";   //The script blacking out the player screens until the mission has properly loaded
[] execVM "custom\groupTeleport.sqf"; //Teleport for the Journalists & HALO for Spetsnatz

waituntil {scriptDone ws_init_server};
waituntil {(ws_initdone)};

//Set Wreck on fire
if (f_param_fire == 1) then {_fire = [Wreck,5,time,false,false] spawn BIS_Effects_Burn;};

//Action to allow Data Transfer
ws_uploadaction = Wreck addAction ["<t color='#dddd00'>"+"Begin transfer (DEBUG)"+"</t>","ws_scripts\ws_uploadaction.sqf",nil,1,false,true,"","((_target distance _this) < 9) && (group _this != grpRU_Grnd)"]; 

//Action allowing the grounded pilot to estimate his location
if (f_param_broadcastaction == 1) then {
ws_broadcastlocation = UnitRU_Grnd_P addAction ["<t color='#dddd00'>"+"Estimate location"+"</t>","ws_scripts\ws_mapclickaction.sqf",nil,1,false,true,"","(driver _target == _this)&&((Wreck distance _this)<250)"];
} else {
ws_broadcastlocation = UnitRU_Grnd_P addAction ["<t color='#dddd00'>"+"Estimate location"+"</t>","ws_scripts\ws_mapclickaction.sqf",nil,1,false,true,"","(driver _target == _this)"];};

ws_placewreckage2.sqf (the script moving the Wreck around Cherna), works perfectly fine

//Based on init_start.sqf in: Jolly Green, made by Shuko of LDD Kyllikki
sleep 0.1;
if (!isServer) exitWith {};
if (ws_initdone) exitWith {};

private ["_findFlatGround"];
 _findFlatGround =
 {
   private ["_pos","_posTL","_posTR","_posBL","_posBR","_result","_water","_gradientTooBig","_posArray","_radius","_maxFactor"];
   _pos = _this select 0;
   _radius = _this select 1;
   _maxFactor = _this select 2;

   _posTL = [(_pos select 0) - _radius, (_pos select 1) - _radius];
   _posTR = [(_pos select 0) + _radius, (_pos select 1) - _radius];
   _posBL = [(_pos select 0) - _radius, (_pos select 1) + _radius];
   _posBR = [(_pos select 0) + _radius, (_pos select 1) + _radius];

   _result = [false,_pos];

   _water = false;
   {
     if (surfaceIsWater _x) exitWith { _water = true; };
   } forEach [_pos, _posTL, _posTR, _posBL, _posBR];

   _gradientTooBig = false;

   _posArray = [_pos, _posTL, _posTR, _posBL, _posBR];

   for "_i" from 0 to ((count _posArray) - 1) do
   {
     for "_k" from 0 to ((count _posArray) - 1) do
     {
       private ["_pos1", "_pos2"];
       _pos1 = _posArray select _i;
       _pos2 = _posArray select _k;

       if (((_pos1 select 0) != (_pos2 select 0)) && ((_pos1 select 1) != (_pos2 select 1))) then
       {
         private ["_sample1", "_sample2", "_posASL1", "_posASL2"];
         _sample1 = "RoadCone" createVehicle _pos1;
         _sample2 = "RoadCone" createVehicle _pos2;
         _posASL1 = getPosASL _sample1;
         _posASL2 = getPosASL _sample2;
         deleteVehicle _sample1;
         deleteVehicle _sample2;

         private ["_heightDiff"];
         _heightDiff = abs ((_posASL1 select 2) - (_posASL2 select 2));

         if (_heightDiff > _maxFactor) then { _gradientTooBig = true; };
       };
     };
   };

   if (!_water && !_gradientTooBig) then { _result = [true,_pos]; };

   _result
 };
 //sleep (random 0.5);
 private ["_area","_centerpos","_cx","_cy","_areasize","_rx","_ry","_ad","_cd","_sd","_tx","_ty","_xout","_yout","_bomb","_found","_result"];

 switch (round random 5) do {
 case 0: {_area = "mArea";};
   case 1: {_area = "mArea_1";};
  case 2: {_area = "mArea_2";};
case 3: {_area = "mArea_3";};
	case 4: {_area = "mArea_4";};
	case 5: {_area = "mArea_5";};
	};

 _centerpos = getMarkerPos _area;
 _cx = abs(_centerpos select 0);
 _cy = abs(_centerpos select 1);
 _areasize = getMarkerSize _area;
 _rx = _areasize select 0;
 _ry = _areasize select 1;
 _ad = (markerDir _area) * -1;
 _cd = cos(_ad);
 _sd = sin(_ad);

_found = false;
 while {!_found} do {
   _tx=(random (_rx*2)) - _rx;
   _ty=(random (_ry*2)) - _ry;
   _xout=if (_ad!=0) then {_cx+ (_cd*_tx - _sd*_ty)} else {_cx+_tx};
   _yout=if (_ad!=0) then {_cy+ (_sd*_tx + _cd*_ty)} else {_cy+_ty};
   _result = [[_xout,_yout,0],2,4.5] call _findFlatGround;	
   _found = _result select 0;
 };

Wreck_loc = _result select 1;
publicvariable "Wreck_Loc";
_bomb = "Bo_GBU12_LGB" createVehicle Wreck_loc;
[_bomb] spawn {
waituntil {isNull (_this select 0)};
Wreck setPos [Wreck_loc select 0,Wreck_loc select 1,0];
Wreck setvectorup [0,0,0];
Wreck setdir (random 360);
Wreck allowdamage false;
Wreck setVelocity [0,0,0];};

ws_initdone = true;
publicvariable "ws_initdone";

ws_uploadaction.sqf:

private ["_caller"];

_caller = _this select 1;
ws_uploader = _caller;

ws_uploadstarted = true;
publicvariable "ws_uploadstarted";
publicvariable "ws_uploader";

ws_upload.sqf (started by a trigger named trgUpload that listens for ws_uploadstarted)

waitUntil {scriptDone f_processParamsArray};

private ["_time","_tick","_nearlist","_dots","_pos"];

_time = f_param_uploadtime;
_tick = 0;

Wreck removeAction ws_uploadaction;
deleteVehicle trgUpload;

_pos = getPos ws_uploader;
ws_laptop setPos _pos;

if (isNil "ws_pickuplaptop") then {
ws_pickuplaptop = ws_laptop addAction ["<t color='#dddd00'>"+"Pickup data"+"</t>","ws_scripts\ws_pickuplaptop2.sqf",nil,1,false,true,"","((_target distance _this) < 4) && (ws_uploaddone)"];
};

_mkr = createMarker ["LP", _pos];
_mkr setMarkerShape "ICON";
_mkr setMarkerType "Dot";
_mkr setMarkerColor "ColorGreen";
_mkr setMarkerText "Data";

hintsilent format ["%1 has established connection.",name ws_uploader];

while {_tick != _time} do {
_dots = "";
for "_i" from 0 to 5 do {
hintsilent format ["Transfering%1",_dots];
_dots = _dots + ".";
sleep 0.1;};
sleep 5;
_dots = "";
for "_i" from 0 to 5 do {
hintsilent format ["Transfering%1",_dots];
_dots = _dots + ".";
sleep 0.1;};
sleep 5;
_tick = _tick + 10;
};

hint format ["Transfer finished, data has been secured."];
ws_uploaddone = true;
publicvariable "ws_uploaddone";

As said, the action scripts self work perfectly fine.

What else do you need?

Edited by Wolfenswan

Share this post


Link to post
Share on other sites

ws_initdone does not seem to be set prior to the publicVariable from server. That could result in unknown behavior on the waitUntil in ws_init.sqf.

Share this post


Link to post
Share on other sites

Even if ws_initdone waits first for ws_initServer to be finished?

Anyway in an older iteration everything happened in the same script so ws_initdone was def. the same for all clients and is not related to the bug described in the OP.

I've added some redundant checks and waituntils to make sure clients are synched and connected before any addAction happens. I'll report back how that works out.

Share this post


Link to post
Share on other sites

Of course, since we're talking clients here the script will encounter the exitWith and finish immediately. This will most likely happen before the server gets to send the publicVariable.

Share this post


Link to post
Share on other sites
Of course, since we're talking clients here the script will encounter the exitWith and finish immediately. This will most likely happen before the server gets to send the publicVariable.

Oh derp, Obviously. Cheers.

As said I've now added:

sleep 0.1;
waitUntil {!(isNull player)};
waitUntil {(player == player)};
waitUntil { time > 0 };

Share this post


Link to post
Share on other sites

That still isn't a reliable solution.

if (isNil "ws_initdone") then {ws_initdone = false};

...should suffice.

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  

×