Jump to content
Sign in to follow this  
eggbeast

how is "isServer" working in arma3??

Recommended Posts

i'm finding in my mission that some scripts called on the server (from a trigger in the mission.sqm controlled by expcond "isserver") are running many multiples of times - like between 3 and 20x when i host the mission on my pc and am alone in it, and then 1x extra for every joiner.

https://community.bistudio.com/wiki/isServer

could it be that in Arma3 at the moment "isserver" does not exclude MPclients?

the temptation is to replace the code with "isdedicated"

https://community.bistudio.com/wiki/isDedicated

but this means SP players/ local hosters will not be able to see half of the mission spawning.

i've done some testing and this is all accurate observation in my evolution mission.

problem is - we're spawning like 24 helicopters full of troops instead of 2, when 10 players are on the server.

either isserver or waituntil is failing? how can this be?

has anyone got any advice?

mission is here

http://forums.bistudio.com/showthread.php?148074-MP-COOP-GITS-EVOLUTION-main-thread

the scripts running over andover are:

scripts/air/makehip.sqf

and

scripts/makespetz.sqf

both scripts are called via the sinit.sqf (makehip is called from makeair which is called from sinit, interestingly makeka is also called from makeair and this (with almost identical scripting) does not duplicate)

desperate for some light shedding on this!

cheers

egg

Share this post


Link to post
Share on other sites

Limited tests i did recently relying on isServer, on A3 default branch, went about with no issues whatsoever.

Share this post


Link to post
Share on other sites

No problems here with such commands, can you post how you are executing those scripts and the related code of them?

Share this post


Link to post
Share on other sites

Could you use

 If (local _unitName) then { 
   hint "multi"; 
}

https://community.bistudio.com/wiki/local

---- UPDATE -----

I've just noticed this in the =BTC=_revive init script. Seems it uses both.

if (isServer) then
{
//Mobile
if (BTC_active_mobile == 1 && count BTC_vehs_mobile_west != 0) then {for "_i" from 0 to ((count BTC_vehs_mobile_west) - 1) do {_veh = (BTC_vehs_mobile_west select _i);_var = str (_veh);_veh setVariable ["BTC_mobile_west",_var,true];if (BTC_mobile_respawn == 1) then {_resp = [_veh,_var,"BTC_mobile_west"] spawn BTC_vehicle_mobile_respawn;};};} else {{deleteVehicle _x} foreach BTC_vehs_mobile_west;};
if (BTC_active_mobile == 1 && count BTC_vehs_mobile_east != 0) then {for "_i" from 0 to ((count BTC_vehs_mobile_east) - 1) do {_veh = (BTC_vehs_mobile_east select _i);_var = str (_veh);_veh setVariable ["BTC_mobile_east",_var,true];if (BTC_mobile_respawn == 1) then {_resp = [_veh,_var,"BTC_mobile_east"] spawn BTC_vehicle_mobile_respawn;};};} else {{deleteVehicle _x} foreach BTC_vehs_mobile_east;};
BTC_killed_pveh = [];publicVariable "BTC_killed_pveh";
BTC_drag_pveh = [];publicVariable "BTC_drag_pveh";
BTC_marker_pveh = [];publicVariable "BTC_marker_pveh";
};
if (isDedicated) exitWith {};

Edited by Beerkan

Share this post


Link to post
Share on other sites

isServer is working the same as it did in Arma 2, really. If you're having problems, they probably don't have anything to do with the isServer command itself. I'd try look elsewhere for where you are calling the scripts more than once.

As for the local command, I usually avoid situations that would require using it. Using it usually results in un-reliable code, as it means it might not run on any machine at all, since it doesn't necessarily run at the same time, and locality is not necessarily updated at the same time for all machines. Then again, sometimes there simply is no real reliable solution when you want to use commands that require the unit to be local and want to be sure the command gets executed exactly once - No more no less.

Share this post


Link to post
Share on other sites

What are the differences between "isServer" and "Dedicated"

I am assuming isServer is when you host of your own machine while dedicated is strictly hosting?

How is that detected?

Share this post


Link to post
Share on other sites

ok here goes...

demo mission file

http://www.gitsarma.gamingdeluxe.net/mods/beta/CO_22_GITS_Evolution_v2-0.Stratis.pbo

context

Evolution runs its core mission from a script called sinit.sqf (server init) which is supposed to be called once at mission start from the mission.sqm:

		class Item28
	{
		position[]={541.81305,0.058640175,7749.3086};
		timeoutMin=1;
		timeoutMid=1;
		timeoutMax=1;
		interruptable=1;
		age="UNKNOWN";
		text="sinit";
		name="sinit";
		expCond="isServer";
		expActiv="plays = [] execVM ""scripts\sinit.sqf"";";
		class Effects
		{
		};
	};

it also runs some subsidiary scripts that are required to run once only on the server. these control things that loop like the enemy plane patrols and enemy base raiders. clearly if these scripts run more than once or for example once for each client then the server is going to hell in a handbasket!

sinit.sqf

// main server init

if !(isServer) exitwith{};

// Common server events
_events = [] execVM "scripts\EventsS.sqf";

// Reinforcement waypoint generator
_events = [] execVM "scripts\EVO_Erefway.sqf"; 

// Fills out squads for cites
_events = [] execVM "scripts\EVO_FillInf.sqf"; 

// Recycles groups
_events = [] execVM "scripts\EVO_gRecy.sqf";

// City setup (radios,officers,group leaders)
_events = [] execVM "scripts\EVO_Erec.sqf";	

//weather, cleanup, server time synch
Mthread = [] execVM "scripts\MainThread.sqf";

//manages city surrender and rotation
_events = [] execVM "scripts\EVO_MissionManager.sqf";

//manages enemy aircraft
_handle = [] execVM "scripts\air\makeair.sqf";

//manages enemy base raiders
if (Raiders >0) then 
{
_handle = [] execVM "scripts\makespetz.sqf"
};

so far so good - this all worked perfectly in arma2

so lets look at makeair.sqf - this controls the plane spawning scripts

//makes roaming planes and choppers

if !(isServer) exitwith{};
if !(isDedicated) exitwith{};

Sleep (random 60.0);
_handle = [] execVM "scripts\air\makehip.sqf";
Sleep (random 60.0);
_handle = [] execVM "scripts\air\makeka.sqf";
Sleep (random 60.0);

lets look at makehip.sqf - it used to spawn an mi17 now it spawns a pair of ka60's with troops in.

// makes roaming Hips

if !(isServer) exitwith{};

for [{_loop=0}, {_loop<1}, {_loop=_loop}] do
{
_aircomms = 12;
if (EGG_aircomms ==0) then {_aircomms = 24};
//reinfdelay = 120, 180, 240, 300
_rf = 0.5*(reinfdelay * _aircomms);
//test
_rf=10;
sleep (round random _rf);

_startsf = ["EnemyAir01","EnemyAir02","EnemyAir03","EnemyAir04","EnemyAir05","EnemyAir06","EnemyAir07","EnemyAir08"];
_poscreate = getmarkerpos (_startsf select (round random 7));
_pilot = createGroup (east);

_rndx = random 600;
_rndy = random 600;
_kpos = [(_poscreate select 0)-300 +_rndx,(_poscreate select 1)-300+_rndy,1500];

_allunits = EGG_EVO_mepilot;
_maxu = (count _allunits)-1;
_allvecs = EGG_EVO_eastveh1;
_max = (count _allvecs)-1;

_upos = getmarkerpos "centerp";

_heli = createVehicle [_allvecs select (round random _max), _kpos, [], 50, "FLY"];Sleep EGG_EVO_GlobalSleep;
_heli setposATL [getpos _heli select 0, getpos _heli select 1, 1500];
_heli setdir (random 100);

//calculate aircrew
if((_heli emptyPositions "driver") > 0) then 
{
	_unit = _pilot createUnit [(_allunits select round random _maxu), _upos, [], 5, "NONE"];
	_unit AssignasDriver _heli;
	_unit moveinDriver _heli;
};
Sleep EGG_EVO_GlobalSleep;
if((_heli emptyPositions "gunner") > 0) then 
{
	_unit = _pilot createUnit [(_allunits select round random _maxu), _upos, [], 5, "NONE"];
	_unit AssignasGunner _heli;
	_unit moveinGunner _heli;
};		
Sleep EGG_EVO_GlobalSleep;
if((_heli emptyPositions "commander") > 0) then 
{
	_unit = _pilot createUnit [(_allunits select round random _maxu), _upos, [], 5, "NONE"];
	_unit AssignasCommander _heli;
	_unit moveinCommander _heli;
};
_heli engineon true;
_type0 = Typeof _heli;

//adding second heli

_heli1 = createVehicle [_allvecs select (round random _max), _kpos, [], 50, "FLY"];Sleep EGG_EVO_GlobalSleep;
_heli1 setposATL [getpos _heli1 select 0, getpos _heli1 select 1, 1500];
_heli1 setdir (random 100);
_sumark = [_heli] execVM "scripts\air\sumarker2.sqf";

//calculate aircrew
if((_heli1 emptyPositions "driver") > 0) then 
{
	_unit = _pilot createUnit [(_allunits select round random _maxu), _upos, [], 5, "NONE"];
	_unit AssignasDriver _heli1;
	_unit moveinDriver _heli1;
};
Sleep EGG_EVO_GlobalSleep;
if((_heli1 emptyPositions "gunner") > 0) then 
{
	_unit = _pilot createUnit [(_allunits select round random _maxu), _upos, [], 5, "NONE"];
	_unit AssignasGunner _heli1;
	_unit moveinGunner _heli1;
};		
Sleep EGG_EVO_GlobalSleep;
if((_heli1 emptyPositions "commander") > 0) then 
{
	_unit = _pilot createUnit [(_allunits select round random _maxu), _upos, [], 5, "NONE"];
	_unit AssignasCommander _heli1;
	_unit moveinCommander _heli1;
};
_heli1 engineon true;
_type1 = Typeof _heli1;

/*
(units _pilot select 0) AssignasDriver _heli;
(units _pilot select 0) moveInDriver _heli;
(units _pilot select 1) moveInTurret[_heli,[0]];
(units _pilot select 2) moveInTurret[_heli,[1]];
(units _pilot select 3) moveInTurret[_heli,[2]];

(units _pilot select 4) AssignasDriver _heli1;
(units _pilot select 4) moveInDriver _heli1;
(units _pilot select 5) moveInTurret[_heli1,[0]];
(units _pilot select 6) moveInTurret[_heli1,[1]];
(units _pilot select 7) moveInTurret[_heli1,[2]];
*/

//adding troops

_maxcrew0 = 0;
_maxcrew1 = 0;
if (enemynumdiv==1) then 
{
	_maxcrew0 = getNumber (configFile >> "CfgVehicles" >> _type0 >> "transportSoldier");
	_maxcrew1 = getNumber (configFile >> "CfgVehicles" >> _type1 >> "transportSoldier");
};

_helicount = 2;
_z = 0;
while {_z < _helicount} do 
{
	if (_z ==0) then {_vec = _heli0; _maxcrew = _maxcrew0};
	if (_z ==1) then {_vec = _heli1; _maxcrew = _maxcrew1};
	_Crewcargo = EGG_EVO_east1;
	_ccargo = (count _Crewcargo)-1;
	_n = 0;
	while {_n < _maxcrew} do 
	{
		_unit = _pilot createUnit [_Crewcargo select (round random _ccargo), _upos, [], 0, "NONE"];
		_unit AssignasCargo _vec;
		_unit moveinCargo _vec;
		_n = _n+1;
		Sleep 0.1;
	};
	_z=_z+1;
	Sleep 0.1;
};
_pilot setFormation "WEDGE";
_pilot setCombatMode "YELLOW";

_handle = [_pilot] execVM "scripts\air\flightpath.sqf";
{_x addEventHandler ["killed", {handle = [_this select 0] execVM "scripts\bury.sqf"}]} forEach (units _pilot);

_heli addEventHandler ["killed", {handle = [_this select 0] execVM "scripts\bury.sqf"}];
_spawne = [_heli] spawn {[_this select 0] call EGG_EVO_idelSVEC};
//	_killh1 = [_heli, (crew _heli)] spawn {[_this select 0, _this select 1] call EGG_killpilots};

_heli1 addEventHandler ["killed", {handle = [_this select 0] execVM "scripts\bury.sqf"}];
_spawnf = [_heli1] spawn {[_this select 0] call EGG_EVO_idelSVEC};
//	_killh2 = [_heli1, (crew _heli1)] spawn {[_this select 0, _this select 1] call EGG_killpilots};

//	_addkit = [_heli] spawn {[_this select 0] call EGG_EVO_Fillcargo};
//	_addkit1 = [_heli1] spawn {[_this select 0] call EGG_EVO_Fillcargo};

//	_nul = _heli addeventhandler ["HandleDamage", {if ((_this select 4) isKindOf "MissileCore") then {_vec setdammage 1}else{_this select 2};}];
//	_nul1 = _heli1 addeventhandler ["HandleDamage", {if ((_this select 4) isKindOf "MissileCore") then {_vec setdammage 1}else{_this select 2};}];

sleep 10.0;
waitUntil {( ((not (alive _heli)) AND (not (alive _heli1)) ) or ( (isNull (driver _heli)) AND (isNull (driver _heli1)) ) )};

sleep 1.0;
if (alive _heli) then {_heli setdammage 1};
if (alive _heli1) then {_heli1 setdammage 1};
//	sleep _rf;
//test
sleep 10;
{if (alive _x) then {_x setdammage 1}} forEach (units _pilot);
};

with multiple players on a hosted server or even try it on your own this script runs over and over - regardless of either

a) the waituntil condition OR

b) the isserver condition

not sure what is wrong?

the helis created are given a flashing orange and white radar marker to show where they are (temp to distinguish between them and the armed version)

(the makeka.sqf creates a pair of armed ka60's with one red solid radar marker)

now watch what happens with the raiders - makespetz.sqf

//makespetz.sqf - spetnaz assault event - makes truck (and soon to follow hind / boat) -borne spetnaz assault that spawns in village and seeks either the airfield or MHQ ambulance to destroy Blufor spawnbases

if !(isServer) exitwith{};
//if !(isDedicated) exitwith{};

_allspawns = [];
_allvecsNG = [];
_allvecsG = [];
_allunits = [];
_targblue = [];

_deletespetz =
{
_handle = [_spetz] execVM "scripts\delete.sqf";
{deletevehicle _x} forEach [_heli,_heli1,_heli2,_heli3];
};

//managed on and off in sinit.sqf with 
//if (Raiders >0)

for [{_loop=0}, {_loop<1}, {_loop=_loop}] do
{
//reinfdelay = 120, 180, 240, 300
_aircomms = 12;
if (EGG_aircomms ==0) then {_aircomms = 24};
_rf = 0.5*(reinfdelay * _aircomms);
//	sleep (round random _rf);
//test
sleep 10;

_spetz = createGroup (east);
//	_rand = round(random 2);
//	_rand = 1; //testing boats
_rand = 2; //testing lorries


if ( (Raiders == 1) || (_rand == 2) ) then //lorries
{
	_allspawns = ["cityBref1","cityBref2","cityBref3","cityCref1","cityCref2","cityCref3"];
	_allvecsNG = EGG_EVO_eastveh3;
	_allvecsG = EGG_EVO_eastveh4;
	_allunits = EGG_EVO_east1;
	_targblue = position hospital; 
} else
{
	if( _rand==0) then //chopper
	{
		_allspawns = ["EnemyAir01","EnemyAir02","EnemyAir03","EnemyAir04","EnemyAir05","EnemyAir06","EnemyAir07","EnemyAir08"];
		_allvecsNG = EGG_EVO_eastveh1;
		_allvecsG = EGG_EVO_eastveh2;
		_allunits = EGG_EVO_mepilot;
		_targblue = position dropoff;

	} else 
		//_rand==1 boat
	{
		_allspawns = ["wpat1","wpat2","wpat3","wpat4","wpat5","wpat6"];
		_allvecsNG = EGG_EVO_eastveh7;
		_allvecsG = EGG_EVO_eastveh8;
		_allunits = EGG_EVO_east2;
		_targblue = position beach;
	};
};

_max = (count _allspawns)-1;
_maxNG = (count _allvecsNG)-1;
_maxG = (count _allvecsG)-1;
_maxu = (count _allunits)-1;

_pos0 = GetMarkerPos (_allspawns select round random _max);
sleep 1;

if( _rand==0) then //chopper
{
	_heli = createVehicle [_allvecsG select (round random _maxG), _pos0, [], 300, "FLY"];Sleep EGG_EVO_GlobalSleep;
	_heli1 = createVehicle [_allvecsG select (round random _maxG), _pos0, [], 300, "FLY"];Sleep EGG_EVO_GlobalSleep;
	_heli2 = createVehicle [_allvecsNG select (round random _maxNG), _pos0, [], 300, "FLY"];Sleep EGG_EVO_GlobalSleep;
	_heli3 = createVehicle [_allvecsNG select (round random _maxNG), _pos0, [], 300, "FLY"];Sleep EGG_EVO_GlobalSleep;
	//calculate aircrew
	{
		_x setposATL [getpos _x select 0, getpos _x select 1, 1500];
	_x setdir (random 100);

		if((_x emptyPositions "driver") > 0) then 
		{
			_unit = _spetz createUnit [(_allunits select round random _maxu), _pos0, [], 5, "NONE"];
			_unit AssignasDriver _x;
			_unit moveinDriver _x;
		};
		Sleep 0.1;
		if((_x emptyPositions "commander") > 0) then 
		{
			_unit = _spetz createUnit [(_allunits select round random _maxu), _pos0, [], 5, "NONE"];
			_unit AssignasCommander _x;
			_unit moveinCommander _x;
		};
		Sleep 0.1;
		_x engineon true;
		_type = Typeof _x;
		_maxcrew = getNumber (configFile >> "CfgVehicles" >> _type >> "transportSoldier");
		_Crewcargo = EGG_EVO_east1;
		_ccargo = (count _Crewcargo)-1;
		_n = 0;
		while {_n < _maxcrew} do 
		{
			_unit = _spetz createUnit [_Crewcargo select (round random _ccargo), _pos0, [], 5, "FORM"];
			_unit AssignasCargo _x;
			_unit moveinCargo _x;
			_n = _n+1;
			Sleep 0.1;
		};
	} forEach [_heli,_heli1,_heli2,_heli3];
	{
		if((_x emptyPositions "gunner") > 0) then 
		{
			_unit = _spetz createUnit [(_allunits select round random _maxu), _pos0, [], 5, "NONE"];
			_unit AssignasGunner _x;
			_unit moveinGunner _x;
		};		
		_sumark = [_x] execVM "scripts\air\sumarker3.sqf";
		Sleep 0.1;
	} forEach [_heli,_heli1];

	_spetz setFormation "WEDGE";

} else //boat or lorry
{
	_heli = createVehicle [(_allvecsG select (round random _maxG)), _pos0, [], 20, "FORM"];Sleep EGG_EVO_GlobalSleep;
	_heli1 = createVehicle [(_allvecsG select (round random _maxG)), _pos0, [], 20, "FORM"];Sleep EGG_EVO_GlobalSleep;
	_heli2 = createVehicle [(_allvecsNG select (round random _maxNG)), _pos0, [], 20, "FORM"];Sleep EGG_EVO_GlobalSleep;
	_heli3 = createVehicle [(_allvecsNG select (round random _maxNG)), _pos0, [], 20, "FORM"];Sleep EGG_EVO_GlobalSleep;

	//calculate crew
	{
		if( ((_x emptyPositions "driver") > 0) and (alive _x)) then 
		{
			_unit = _spetz createUnit [(_allunits select round random _maxu), _pos0, [], 5, "NONE"];
			_unit AssignasDriver _x;
			_unit moveinDriver _x;
		};
		Sleep 0.1;
		if( ((_x emptyPositions "commander") > 0) and (alive _x)) then 
		{
			_unit = _spetz createUnit [(_allunits select round random _maxu), _pos0, [], 5, "NONE"];
			_unit AssignasCommander _x;
			_unit moveinCommander _x;
		};
		Sleep 0.1;
		_x engineon true;
		_type = Typeof _x;
		_maxcrew = getNumber (configFile >> "CfgVehicles" >> _type >> "transportSoldier");
		_n = 0;
		while {((_n < _maxcrew)and (alive _x))} do 
		{
			_unit = _spetz createUnit [_allunits select (round random _maxu), _pos0, [], 5, "FORM"];
			_unit AssignasCargo _x;
			_unit moveinCargo _x;
			_n = _n+1;
			Sleep 0.1;
		};
//temp
	_sumark = [_x] execVM "scripts\air\sumarker3.sqf";

	} forEach [_heli,_heli1,_heli2,_heli3];

	{
		if( ((_x emptyPositions "gunner") > 0)and (alive _x)) then 
		{
			_unit = _spetz createUnit [(_allunits select round random _maxu), _pos0, [], 5, "NONE"];
			_unit AssignasGunner _x;
			_unit moveinGunner _x;
		};		
		Sleep 0.1;
	} forEach [_heli,_heli1];

	if( _rand==1) then //boat
	{
		_spetz setFormation "LINE"
	};
	if( _rand==2) then //lorries
	{
		_spetz setFormation "COLUMN"
	};
};

{_x addEventHandler ["killed", {handle = [_this select 0] execVM "scripts\bury.sqf"}]} forEach (units _spetz);
{_x addEventHandler ["killed", {handle = [_this select 0] execVM "scripts\bury.sqf"}]} forEach [_heli,_heli1,_heli2,_heli3];
_recy = [objnull,_spetz] execVM "scripts\grecycle.sqf";

//send to target

_spetz setCombatMode "SAFE";
_spetz setSpeedMode "LIMITED";
_spetz setBehaviour "SAFE";


//hint format["spetsnaz embarked %1",(count units _spetz)];

sleep 20;
_wp = _spetz addWaypoint [_targblue, 200];
[_spetz, 1] setWaypointType "MOVE";

//	{(driver _x) doMove _targblue} forEach [_heli,_heli1,_heli2,_heli3];

for [{_loop2=0}, {_loop2<1}, {_loop2=_loop2}] do
{
	{if (!(canMove _x)) then {deletevehicle _x}} forEach [_heli,_heli1,_heli2,_heli3];
	if ( ({alive _x} count units _spetz) < 1) then {_loop2=1};
	if ( ( ((leader _spetz) distance _targblue) < 200) or ( (_heli distance _targblue) < 200) or ( (_heli1 distance _targblue) < 200) or ( (_heli2 distance _targblue) < 200) or ( (_heli3 distance _targblue) < 200) ) then {_loop2=1};
sleep 3;
};

_wp2 = _spetz addWaypoint [_targblue, 30];
[_spetz, 2] setWaypointType "HOLD";
_spetz setCombatMode "RED";
_spetz setSpeedMode "FULL";
_spetz move _targblue;

//special chopper landing

if( _rand==0) then //chopper
{
	{
//temporary override
		_x setposATL [_targblue select 0, _targblue select 1, 0];
//			_x setfuel 0;
//			{_y action ["getout", _x]} forEach crew _x;
		sleep 45;
		deletevehicle _x;
	}forEach [_heli,_heli1,_heli2,_heli3];
};

waitUntil {({alive _x} count units _spetz) < 1};
sleep 1.0;
[] call _deletespetz;
};

this script spawns 4 enemy vehicles with a brown andwhiteflashing radar contact marker (temporary)

you can see from this that it is called over and over so either

a) waitUntil {({alive _x} count units _spetz) < 1}; does not work OR

b) if !(isServer) exitwith{}; does not work

we are hosting this on a dedibox running steam in offline mode. and all players are JIP.

Share this post


Link to post
Share on other sites

So you execute from a editor trigger?

Editor triggers are local to each machine connected, so everyone that joins the mission, will have it's own trigger that works independently from everyone else.

Instead, just execute the sinit.sqf from the init.sqf file, if you do not have it, just create one at mission folder.

if (isServer) then {
  //This will only run once
  [] execVM "scripts\sinit.sqf";
};

Then, you can simply delete any other isServer/isDedicated check from inside the scrips, because they become useless.

What are the differences between "isServer" and "Dedicated"

I am assuming isServer is when you host of your own machine while dedicated is strictly hosting?

How is that detected?

IsServer returns true if the current machine (where this command was issued) is the Server.

IsDedicated will return true if the current machine (where this command was issued) is the Server and is a Dedicated server.

Share this post


Link to post
Share on other sites

Hey neokika,

How would you limit the execution of a radio triggered script to a player (lets say named as session_organizer).

I tried

if (isServer && player == session_organizer) then

{... script here

};

but this script can still be called by any player based on my testing results (When I host a game btw, not dedicated server).

Share this post


Link to post
Share on other sites

my bad - looks like both my scripts were bugged

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  

×