d3nn16 3 Posted January 2, 2009 I'm trying to make a ctf template, so I use addScore command to give a score bonus to players who touch the flag or deliver it. I made a simple system where the server tracks the state of the  flag runner and when a player touches/delivers the flag the server PVs a variable containing (a pointer to) the unit of the flag owner (obtained from the return value of flagOwner FLAG_WEST/EAST) and the score to add. The clients use an event handler on this variable to update the score of the unit (the variable for touching the flag is CTF_CAPTURED, for delivering is CTF_DELIVERED). For JIP players the server maintains 3 arrays with : names (SCORE_NAMES), unit pointers (SCORE_UNITS) and scores (SCORE_POINTS) of players with bonuses (the name array is useful to remove entries from the 3 arrays when a player disconnects). When a player touches/delivers a flag the server adds or updates an entry in each of the 3 arrays and then PVs 2 arrays : SCORE_UNITS and SCORE_POINTS. JIP clients wait until SCORE_UNITS and SCORE_POINTS are initialized then for each unit in SCORE_UNITS execute the command addScore with the corresponding score in SCORE_POINTS. Perhaps you can already see the problem with this ? When a player respawns the unit pointer added in SCORE_UNITS points to the dead unit and not on the new unit the player respawned in, so when a JIP player receives SCORE_UNITS from the server it should contain invalid unit pointers. What I consider weird is that this actually works  . Is there a reason for it to work ? To see the problem I added a radio trigger that shows me SCORE_UNITS as it is sent by the server. I tested this on my PC by running a dedicated server and 2 arma games simultaneously. In one game I go capture a flag so the server adds an entry in SCORE_UNITS. In the other game I connect as JIP player and the strange thing about it is that SCORE_UNITS contains an entry with <NULL-object> and the score of the player who touched the flag appears correctly updated. To see this by yourself you can download the ctf template map on my webpage (click on missions then on ctf template map). Remember to add a radio trigger to see what SCORE_UNITS contains. You could ask yourself as long as it works why bother posting ? The problem is I tried to reproduce this in a small test map and it doesn't work  . Here is the init.sqf of the test map : <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> if (isServer) then {      SCORE_NAMES = [];           SCORE_UNITS = [];      publicVariable "SCORE_UNITS";      SCORE_POINTS = [];      publicVariable "SCORE_POINTS";           F_SCORE_UPDATE =      {           private ["_p_unit", "_p_score", "_name", "_idx"];                     _p_unit = _this select 0;           _p_score = _this select 1;           _name = name _p_unit;           _idx = SCORE_NAMES find _name;                     if (_idx == -1) then           {                SCORE_NAMES = SCORE_NAMES + [_name];                SCORE_UNITS = SCORE_UNITS + [_p_unit];                SCORE_POINTS = SCORE_POINTS + [_p_score];           }           else           {                SCORE_POINTS set [_idx, (SCORE_POINTS select _idx) + _p_score];           };      };           "MSG" addpublicvariableeventhandler      {           MSG call F_SCORE_UPDATE;      };      "MSG2" addpublicvariableeventhandler      {           publicVariable "SCORE_UNITS";      }; } else {      [] spawn      {           waitUntil           {                !isNil "SCORE_UNITS" &&                !isNil "SCORE_POINTS"           };                     {_x addScore (SCORE_POINTS select (SCORE_UNITS find _x))} forEach SCORE_UNITS;      }; }; _trig = createTrigger["EmptyDetector", [0,0,0]]; _trig setTriggerArea [0, 0, 0, False]; _trig setTriggerActivation ["ALPHA", "PRESENT", True]; _trig setTriggerText "show SCORE_UNITS"; _trig setTriggerStatements ["this", "hint format ['%1', SCORE_UNITS]", ""]; _trig = createTrigger["EmptyDetector", [0,0,0]]; _trig setTriggerArea [0, 0, 0, False]; _trig setTriggerActivation ["bravo", "PRESENT", True]; _trig setTriggerText "send MSG"; _trig setTriggerStatements ["this", "MSG = [player, 10]; publicvariable 'MSG'", ""]; _trig = createTrigger["EmptyDetector", [0,0,0]]; _trig setTriggerArea [0, 0, 0, False]; _trig setTriggerActivation ["charlie", "PRESENT", True]; _trig setTriggerText "send MSG2"; _trig setTriggerStatements ["this", "MSG2 = time; publicvariable 'MSG2'", ""]; if (!isServer) then {      [] spawn      {           waitUntil {!isNull player};                     player addEventHandler ["killed",           {                _this spawn                {                     sleep 10;                     deleteVehicle (_this select 0);                };           }];      }; }; and description.ext : <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> respawn    = "BASE"; Anyone has an explanation ? I thought about another solution to update scores using only names of players and bonuses : JIP players test the names of all the units on the map (using a trigger) and if the name matches then updates the score. Or anyone has a better solution for updating scores ? Share this post Link to post Share on other sites
UNN 0 Posted January 4, 2009 Can't really look at this in detail but: Quote[/b] ]I connect as JIP player and the strange thing about it is that SCORE_UNITS contains an entry with <NULL-object> and the score of the player who touched the flag appears correctly updated. If the player is being returned as null, it's probably being populated by the server? From what I can see, is there a possibility that this line: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">_trig setTriggerStatements ["this", "MSG = [player, 10]; publicvariable 'MSG'", ""]; Is being called by the server, so any valid entry for player on a client, is being overwritten by the server? Just a hunch, but as a quick test you could try this: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">_trig setTriggerStatements ["this", "If !(IsNull Player) Then {MSG = [player, 10]; publicvariable 'MSG'}", ""]; Share this post Link to post Share on other sites
.kju 3245 Posted January 4, 2009 Sickboy <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">"MSG" addpublicvariableeventhandler { MSG call F_SCORE_UPDATE; }; TO <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">"MSG" addpublicvariableeventhandler { (_this select 1) call F_SCORE_UPDATE; }; Quote[/b] ]thats the only thing I would really change atmthe issue is that if 2 pveh's come by really quickly you dont know what the behaviour will be and what value will be used in both handler calls (_this select 1) is the value of MSG during the pv eh event much better than referring to the variable MSG itself, which is a changing variable Share this post Link to post Share on other sites
.kju 3245 Posted January 4, 2009 my say Quote[/b] ]well MSG => TAG_properNamewell in general better variable names with tags PVEH can overwrite each other as well or not? so he does use MSG and you do use MSG => bang Share this post Link to post Share on other sites
d3nn16 3 Posted January 5, 2009 @ UNN The 3 radio triggers i make are a way for me (the client) to know : 1- what the SCORE_UNITS variable contains for the client (trigger alpha) 2- to send the server the message telling it to add me in his SCORE_UNITS variable (trigger beta) 3- to send the server the message telling it to "publicvariable" SCORE_UNITS (trigger charlie) This line : ["this", "MSG = [player, 10]; publicvariable 'MSG'", ""] is not called by the server because the triggers are created locally (with createtrigger command) and so they get activated only on the machine where they were called (pressing 0 0 x). @ Q If I understand well your point, I can say that here the problem is not running the code of the event handler associated to MSG and MSG2 public variables at the same time. There is no problem of concurrent execution of the  codes inside addpublicvariableventhandlers because I activate the radio triggers myself pressing 0 0 x (and because those radio triggers are created with createtrigger command I suppose they are local and activate only locally). I will try to explain the problem otherwise: 1- the player command (from what I've read from the biki) returns a pointer (or something like that) on the unit the player is currently controlling 2- I put that pointer together with a number (the score) in an array variable called MSG (MSG = [player, 10]) 3- i send MSG variable to the server which takes care of putting them in an other array SCORE_UNITS 4- i disconnect and i reconnect as a JIP player, waiting for the SCORE_UNITS array to be sent to me by the server so I can run the addscore command on whatever that array contains (a pointer to the unit I controlled before and a score) So as I'm writing this I realize the test I'm making does not correspond to what happens exactly in the ctf template because in the template the server has in its SCORE_UNITS variable only pointers to players that didn't disconnected (pointers that are returned by the flagowner command). Maybe that's why it doesn't work in my small test. I'll make the small test again ... The only thing to change is instead of MSG = [player, 10] put MSG = [flagowner flag_east, 10] Share this post Link to post Share on other sites
UNN 0 Posted January 5, 2009 Quote[/b] ]is not called by the server because the triggers are created locally Ok, I assumed triggers created via scripts worked the same way they do in the mission editor, globally. Never needed to use them before. If they don't then I guess you could move those triggers into the If !(Server) scope. Quote[/b] ]so they get activated only on the machine where they were called (pressing 0 0 x) I'm sure I'm getting confused. Why would you want to manually activate the scoring, I thought it was triggered by the player getting the flag? Unless they’re for debugging, but it was the only method I could see for calling the public event handlers you posted. Quote[/b] ]If I understand well your point, I can say that here the problem is not running the code of the event handler associated to MSG and MSG2 I thought Q's original comment about the incorrect usage of the parameters returned by the publiceventhandler would the problem. i.e Your not using the name command on a valid object. If not it might be in the future. Quote[/b] ]The only thing to change is instead of MSG = [player, 10]  put MSG = [flagowner flag_east, 10] If it’s working now, then that’s the important thing. For future reference you can save yourself a bit of time if you use a few debugging techniques, for example: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">F_SCORE_UPDATE =     {     private ["_p_unit", "_p_score", "_name", "_idx"];              //Debug output to Arma.rpt (and or) Arma_Server.rpt     Localize Format ["Debug F_SCORE_UPDATE %1",_This];             _p_unit = _this select 0;     _p_score = _this select 1;     _name = name _p_unit;     _idx = SCORE_NAMES find _name;     //Debug output to Arma.rpt (and or) Arma_Server.rpt     Localize Format ["Debug Result  %1 %2",_name,_p_score];                      if (_idx == -1) then         {         SCORE_NAMES = SCORE_NAMES + [_name];         SCORE_UNITS = SCORE_UNITS + [_p_unit];         SCORE_POINTS = SCORE_POINTS + [_p_score];         }         else         {         SCORE_POINTS set [_idx, (SCORE_POINTS select _idx) + _p_score];         };     }; It might be worth adding the line anyway. Just so you’re sure it's only being called when it needs to and with the correct parameters. Share this post Link to post Share on other sites
d3nn16 3 Posted January 5, 2009 I did the small test again with this init.sqf : <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> if (isServer) then { SCORE_NAMES = []; SCORE_UNITS = []; publicVariable "SCORE_UNITS"; SCORE_POINTS = []; publicVariable "SCORE_POINTS"; F_SCORE_UPDATE = { private ["_p_unit", "_p_score", "_name", "_idx"]; _p_unit = _this select 0; _p_score = _this select 1; _name = name _p_unit; _idx = SCORE_NAMES find _name; if (_idx == -1) then { SCORE_NAMES = SCORE_NAMES + [_name]; SCORE_UNITS = SCORE_UNITS + [_p_unit]; SCORE_POINTS = SCORE_POINTS + [_p_score]; } else { SCORE_POINTS set [_idx, (SCORE_POINTS select _idx) + _p_score]; }; }; "MSG" addpublicvariableeventhandler { MSG call F_SCORE_UPDATE; }; "MSG2" addpublicvariableeventhandler { publicVariable "SCORE_UNITS"; }; } else { [] spawn { sleep 10; (flagowner flag_east) addscore 3; player globalChat "yeah ill go wait"; waitUntil { !isNil "SCORE_UNITS" && !isNil "SCORE_POINTS" }; player globalChat "yeah im ready to addscore"; {_x addScore 10; player globalChat "yeah"} forEach SCORE_UNITS; }; }; _trig = createTrigger["EmptyDetector", [0,0,0]]; _trig setTriggerArea [0, 0, 0, False]; _trig setTriggerActivation ["ALPHA", "PRESENT", True]; _trig setTriggerText "show SCORE_UNITS"; _trig setTriggerStatements ["this", "hint format ['%1', SCORE_UNITS]", ""]; _trig = createTrigger["EmptyDetector", [0,0,0]]; _trig setTriggerArea [0, 0, 0, False]; _trig setTriggerActivation ["bravo", "PRESENT", True]; _trig setTriggerText "send MSG"; _trig setTriggerStatements ["this", "MSG = [flagowner flag_east, 10]; publicvariable 'MSG'", ""]; _trig = createTrigger["EmptyDetector", [0,0,0]]; _trig setTriggerArea [0, 0, 0, False]; _trig setTriggerActivation ["charlie", "PRESENT", True]; _trig setTriggerText "send MSG2"; _trig setTriggerStatements ["this", "MSG2 = time; publicvariable 'MSG2'", ""]; if (!isServer) then { [] spawn { waitUntil {!isNull player}; player addEventHandler ["killed", { _this spawn { sleep 10; deleteVehicle (_this select 0); }; }]; }; }; The result is that the addScore command doesn't work. I put globalchat commands near the addscore command and the message is displayed but score of the flag owner is not changed. I don't see why in this small test it doesn't work and in the template it works, the score is updated Share this post Link to post Share on other sites
kadinx 12 Posted June 25, 2009 I concur. The "addscore" command run on the 1.02 beta Dedicated server is not functional. It works on a Player\host but not across clients when the mission is run on Dedicated server. If anyone wants to test it. Make a trigger activated by radio with repeated function and put this under "on activation": Player addscore 50 Place the mission on the Dedicated server and connect through your client. Use the radio button to execute the command and press "I" to see if your score is changing. Share this post Link to post Share on other sites