Jump to content
Sign in to follow this  
jwllorens

Multiplayer coding. Am I doing it right?

Recommended Posts

I wrote a script to set up all the areas that can be captured around my map.  Each area consists of a flag, a marker (ellipse that covers the area of interest), and one to three game logics that mark respawn positions.  All of these use a naming convention so they can be found by my scripts easily during setup.  Basically, I just type the name into the init script, and add the flag, marker, and logics where I want them around the area, and it creates a new sector.

 

The idea is that I have several sectors.  Each sector is captured by using a hold action on a flag pole in that sector for 10 seconds.  This hold action is added to all clients via remoteExec, but only appears if the sector is not under your side's control which is determined by a public variable that is updated whenever the side of the sector changes.  Capturing a sector also remoteExecs a function to the server which basically re-jiggers the local server variable containing all the pertinent information about that sector, and changes flag textures and marker colors and enables and disables respawns.  This function also remoteExecs another function to all clients that alerts them that the area has been taken by CSAT or NATO, and plays a little sound depending on whether the side that took it is your enemy or not.

 

What I want to know is if I am doing this horribly wrong.  I can't test it because I only have one machine.  Although I hope to be able to test it in a few months.  Is this the proper way to do multiplayer coding?  I am trying to do everything I can on the server, and keep only the really really local stuff on the clients.  I am also trying to not publicvariable much at all and when I do trying to make sure they are not spammed.

 

It all works (in singleplayer at least) but I just wanted to get some advice from more experienced coders to see if I am going in the wrong direction with tackling this problem.  

 

Here are the functions:

 

 

 

initServer.sqf

_areaNames = ["LumberYard","CommsAlpha","DieselPlant"];


//create a unique identifier for server variables that can't be fucked with by publicvariable.
_nums = ["1","2","3","4","5","6","7","8","9","0"];
JWL_KeyCode = "";
for "_i" from 1 to 10 do {
  JWL_KeyCode = (JWL_KeyCode + (selectRandom _nums));
};
_nums = nil;

//add respawn trucks as initial spawn point
[west,JWL_SpawnTruck_west] call BIS_fnc_addRespawnPosition;
[east,JWL_SpawnTruck_east] call BIS_fnc_addRespawnPosition;
//start setting up all the objectives.
{
  _area = _x;
  //get the flag variable, store it, delete global public variable.
  _flag = missionNamespace getVariable ("JWL_flag_" + _area);
  missionNamespace setVariable [("JWL_flag_" + _area),nil,true];
  //Create readable name from variable name by inserting spaces
  _name = _area call JWL_fnc_insertSpace;
  //create respawn array
  _rArr = [];
  {
    _logic = missionNamespace getVariable ("JWL_respawn_" + _area + "_" + _x);
    if (!(isNil "_logic")) then {
      _rArr pushBack _logic;
      missionNamespace setVariable [("JWL_respawn_" + _area + "_" + _x),nil,true];
    };
  } count ["1","2","3"];
  //set keyed areaData variable
  missionNamespace setVariable [("JWL_areaData_" + _x + "_" + JWL_KeyCode),[_name,independent,_flag,_rArr,[[[WEST,-1],[WEST,-1],[WEST,-1]],[[EAST,-1],[EAST,-1],[EAST,-1]]]],false];
  missionNamespace setVariable [("JWL_areaSide_" + _x),independent,true];
  //set flag texture and marker color
  _flag setFlagTexture "a3\data_f_exp\flags\flag_synd_co.paa";
  ("JWL_areaMarker_" + _x) setMarkerColor "colorIndependent";
  //add capture action to all the flags, make sure JIP = true
  _grbg = [
    _flag,
    (format ["Capture %1",_name]),
    "\A3\ui_f\data\igui\cfg\simpleTasks\types\interact_ca.paa",
    "\a3\3DEN\Data\CfgWaypoints\Scripted_ca.paa",
    (format ["((_target distance _this) < 5) && ((missionNameSpace getVariable ""JWL_areaSide_%1"") != (side _this))",_x]),
    "true",
    {},
    {},
    {[((_this select 3) select 0),((_this select 3) select 1),(side (_this select 1))] remoteExecCall ["JWL_fnc_captureArea",2];},
    {},
    [_x,_name],
    10,
    0,
    false,
    false
  ] remoteExecCall ["BIS_fnc_holdActionAdd",([0,-2] select (isMultiplayer && isDedicated)),true];
} count _areaNames;


//update areaSide on all computers for the local holdaction condition
_areaNames spawn {
  _sideOld = [];
  while {true} do {
    {
      _aVar = missionNamespace getVariable ("JWL_areaData_" + _x + "_" + JWL_KeyCode);
      _sideNew = _aVar select 1;
      if (_sideNew != (_sideOld select _forEachIndex)) then {
        missionNamespace setVariable [("JWL_areaSide_" + _x),_sideNew,true];
        hint "updated";
      };
      _sideOld set [_forEachIndex,_sideNew];
    } forEach _this;
    sleep 1;
  };
}; 

fn_captureArea.sqf

params [  ["_area", "", [""], 1],
  ["_name", "", [""], 1],
  ["_side", independent, [west], 1]
];
//get keyed area variable
_aVar = missionNamespace getVariable ("JWL_areaData_" + _area + "_" + JWL_KeyCode);
//set side of keyed area variable
_aVar set [1, _side];
//flag object
_flag = _aVar select 2;
//logic entities for spawn locations
_spawnLogics = _aVar select 3;
//pull out respawn indices of area variable to work with it
_spawnIndices = _aVar select 4;
//empty variable to work with later
_spawnIndicesSide = [];


_color = switch (_side) do {
  case west: {
    {
      _spawnIndicesSide pushBack ([west,_x] call BIS_fnc_addRespawnPosition);
      _aVar set [4,_spawnIndices];
    } count _spawnLogics;
    _spawnIndices set [0,_spawnIndicesSide];
    {
      if ((_x select 1) != -1) then {
        _x call BIS_fnc_removeRespawnPosition;
      };
      true
    } count (_spawnIndices select 1);
    ["a3\data_f\flags\flag_nato_co.paa","colorBLUFOR"]
  };
  case east: {
    {
      _spawnIndicesSide pushBack ([east,_x] call BIS_fnc_addRespawnPosition);
      _aVar set [4,_spawnIndices];
    } count _spawnLogics;
    _spawnIndices set [1,_spawnIndicesSide];
    {
      if ((_x select 1) != -1) then {
        _x call BIS_fnc_removeRespawnPosition;
      };
      true
    } count (_spawnIndices select 0);
    ["a3\data_f\flags\flag_csat_co.paa","colorOPFOR"]
  };
};
//set flag and marker colors/textures
_flag setFlagTexture (_color select 0);
("JWL_areaMarker_" + _area) setMarkerColor (_color select 1);


//alert all players
[(_aVar select 0),_side] remoteExecCall ["JWL_fnc_alertCapture",([0,-2] select (isMultiplayer && isDedicated)),false];


missionNamespace setVariable [("JWL_areaData_" + _area + "_" + JWL_KeyCode),_aVar,true];

fn_alertCapture.sqf

params [["_area", "NONE", [], 1],
["_side", civilian, [civilian], 1]
];


if (!((_area == "NONE") || ((_side != west) || (_side != east)))) exitWith {diag_log "ERROR: Must define both side and area!";};
_team = call {
if (_side == west) exitWith {["NATO","2443D1"]};
if (_side == east) exitWith {["CSAT","D12424"]};
};
[(format["<t size='0.65' color='#%1'>%2</t>",(_team select 1),(_team select 0)]),(format["<t size='0.6' color='#E0E0E0'> captured %1!</t>",_area])] call BIS_fnc_showSubtitle;
if ((side player) == _side) then [{playSound "FD_Timer_F";},{playSound "addItemFailed";}];


Share this post


Link to post
Share on other sites
I can't test it because I only have one machine.

 

If your PC has good CPU you can easily run 2 clients and dedicated all on the same PC

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  

×