zwobot 22 Posted September 24, 2011 Hi community in short: using publicVariable in my killed eventHandler script does not broadcast the respective variable when the human players are in different groups in Multiplayer. Please, can you help me figure out why it does not work? Long version: I want to count friendly and enemy casualties in a coop mission, reward points for kills and substract points for losses. Everything worked fine on a dedicated server when the players are inside the same group. However if the players were in different groups the casualty counter variable was not updated correctly despite using the publicVariable command, e. g. in my test there were 2 players on the server in different groups; both killed 1 enemy unit but for both players the Opfor casualty count showed only 1 kill. Find below some background information on how I call the scripts and the scripts themselves: init.sqf where the casualty counting variables are setup and the eventHandlers are added: // Casualty counting menPointLoss = 1; specialMenPointLoss = 2; // currently not used specialMen = []; // currently not used vehiclePointLoss = 6; // currently not used // timelimit timeLimit = 60; sleep 1; westCasualties = 0; countWestUnits = count west_units; // west_units is filled with all west units in a editor placed trigger "Blufor present" trigger (west_units = thislist) menPointLossWest = 0; vehiclePointLossWest = 0; eastCasualties = 0; countEastUnits = count east_units; // east_units is filled with all east units in a editor placed "Opfor present" trigger (east_units = thislist) menPointLossEast = 0; {_x addEventHandler ["killed", {0 = _this execVM "killed.sqf";}]} forEach west_units; {_x addEventHandler ["killed", {0 = _this execVM "killed.sqf";}]} forEach east_units; killed.sqf called from the added killed eventHandlers private ["_unit"]; _unit = _this select 0; if(time < (timeLimit * 2)) then { if(_unit in west_units) then { westCasualties = westCasualties + 1; publicVariable "westCasualties"; menPointLossWest = menPointLossWest + menPointLoss; publicVariable "menPointLossWest"; }; if(_unit in east_units) then { eastCasualties = eastCasualties + 1; publicVariable "eastCasualties"; menPointLossEast = menPointLossEast + menPointLoss; publicVariable "menPointLossEast"; }; }; Share this post Link to post Share on other sites
shuko 59 Posted September 24, 2011 Make server do everything, just have a PVEH on clients to catch score updates sent from server. Share this post Link to post Share on other sites
zwobot 22 Posted September 24, 2011 I don't fully understand your answer Shuko. Do you mean I should add the eventHandlers only on the server? The comref says that "killed" eventHandlers are executed where the killed unit is local. Would you please elaborate you answer? What do you mean by PVEH? Share this post Link to post Share on other sites
neokika 62 Posted September 24, 2011 Hi zwobot, Have you noticed that you are overriding all those global variables at mission start for every player? Meaning that, when a player joins, his machine will override the last PublicVariable'd value. So my guess is that those IF statements are not returning true in MP for the clients. Your init.sqf should look like this instead: if (isServer) then { //assign and public variable the global variables here }; _neo_ Share this post Link to post Share on other sites
zwobot 22 Posted September 24, 2011 neokika, thanks for your answer. I don't think JIP is the immediate problem since everything worked as intended when both players were in the very same group. Nevertheless I tested your suggestion with 2 Arma2 instances on a LAN server and now the global variables seem to be nonexistant on the client instance (returning "any" and "scalar" in debug hints)... Share this post Link to post Share on other sites
neokika 62 Posted September 24, 2011 neokika, thanks for your answer. I don't think JIP is the immediate problem since everything worked as intended when both players were in the very same group.Nevertheless I tested your suggestion with 2 Arma2 instances on a LAN server and now the global variables seem to be nonexistant on the client instance (returning "any" and "scalar" in debug hints)... Can you post what you have tried? _neo_ Share this post Link to post Share on other sites
zwobot 22 Posted September 24, 2011 (edited) Sure, I updated the init.sqf like this: execVM "briefing.sqf"; if(isServer) then { // Casualty counting menPointLoss = 1; specialMenPointLoss = 2; specialMen = []; vehiclePointLoss = 6; // timelimit timeLimit = 60; sleep 1; westCasualties = 0; countWestUnits = count west_units; menPointLossWest = 0; vehiclePointLossWest = 0; eastCasualties = 0; countEastUnits = count east_units; menPointLossEast = 0; // objective points objectivePointsWest = 0; objectivePointsEast = 0; }; {_x addMPEventHandler ["MPKilled", {0 = _this execVM "killed.sqf";}]} forEach west_units; {_x addMPEventHandler ["MPKilled", {0 = _this execVM "killed.sqf";}]} forEach east_units; Would it be easier to setVariable and getVariable the counter variables on an editor placed game logic instead of declaring them in the init.sqf or would this open another can of worms? Edited September 24, 2011 by zwobot Share this post Link to post Share on other sites
shuko 59 Posted September 24, 2011 (edited) I havent scripted in many months, but what I was thinking was something like this. I didn't test it. if isserver then { // init functions ZWO_EH_Killed = { private ["_killed","_side"]; _killed = _this select 0; _side = _killed getvariable "ZWO_Side"; if (time < (ZWO_TimeLimit * 2)) then { //what are you trying to do with this, because it doesnt really make sense? switch (_side) do { case EAST: { ZWO_Score set [0,((ZWO_Score select 0) + 1)]; ZWO_Score set [1,((ZWO_Score select 1) + ZWO_PointLoss_Man)]; }; case WEST: { ZWO_Score set [2,((ZWO_Score select 2) + 1)]; ZWO_Score set [3,((ZWO_Score select 3) + ZWO_PointLoss_Man)]; }; }; }; // sync updated score to clients publicvariable "ZWO_Score"; // make sure the host of non dedicated MP game sees the score display as well if (!isdedicated) then {call ZWO_EH_DisplayScore}; }; // init variables ZWO_PointLoss_Man = 1; ZWO_TimeLimit = 60; private ["_side"]; { _side = side _x; if (_side in [EAST,WEST]) then { // save unit's side for later use, because side changes to civilian on death _x setvariable ["ZWO_Side",_side]; // add killed eventhandler for all east and west units _x addeventhandler ["killed",ZWO_EH_Killed]; }; } foreach allunits; /* init score array 0: casualties east 1: point loss east 2: casualties west 3: point loss west */ ZWO_Score = [0,0,0,0]; }; // clients if (!isdedicated) then { // init var in case it hasnt been sent from server yet if (isnil "ZWO_Score") then {ZWO_Score = [0,0,0,0]}; // eventhandler to catch and display score updates sent from server ZWO_EH_DisplayScore = { hintsilent format ["EAST\nCasualties: %1\nPoint Loss: %2\n\nWEST\nCasualties: %3\nPoint Loss: %4", (ZWO_Score select 0),(ZWO_Score select 1),(ZWO_Score select 2),(ZWO_Score select 3)]; }; "ZWO_Score" addpublicvariableeventhandler ZWO_EH_DisplayScore; }; Edited September 24, 2011 by Shuko Share this post Link to post Share on other sites
zwobot 22 Posted October 10, 2011 Thanks for your help guys. I just couldn't get it to work properly with eventHandlers. Instead of using eventHandlers and updating the counter variables after every kill, I decided to count the units at mission start and compare it with the number of units at mission end and calculate the points based on that. This is done only on the server and the results are broadcasted via the Multiplayer framework to the clients. Share this post Link to post Share on other sites
zonekiller 175 Posted October 10, 2011 (edited) easiest way would be to use setVariable , this will work with SP, MP and JIP have a logic or object on the map called server add to a server only file server setVariable ["westunits", 0, true]; server setVariable ["eastunits", 0, true]; {_x addEventHandler ["killed", {_score = server getVariable "westunits"; _score = _score + 1;server setVariable ["westunits", _score, true] ;}]} forEach west_units; {_x addEventHandler ["killed", {_score = server getVariable "eastunits"; _score = _score + 1;server setVariable ["eastunits", _score, true];}]} forEach east_units; on the client _side = side player; _score = 0; while {alive player} do { if (_side == west) then{ waituntil {((server getVariable "westunits") != _score)}; }else{ waituntil {((server getVariable "eastunits") != _score)}; }; _score = if (_side == west) then {(server getVariable "westunits")}else{server getVariable "eastunits")}; hint str(_score); // or what ever you want to do with that score sleep 1; }; you will have to restart the client file after respawn , the score will still be correct tho Edited October 10, 2011 by Zonekiller Share this post Link to post Share on other sites
zwobot 22 Posted October 10, 2011 Thanks Zonekiller for your late answer. I'm quite fed up with eventHandlers now and haven't got anymore motivation whatsoever to try to get it to work that way. The alternative solution I found is enough for my current requirements. Share this post Link to post Share on other sites