Jump to content
draoth

Code only works for the player that has interacted with it

Recommended Posts

I'm currently working on a money system for a gamemode I made for my friends and I. Boxes spawn all over the map and when a player gets close to it; he receives some money. The only problem I have with this script is that it only seems to work for the player who interacts with the box for the first time. This code is part of a sqf which is executed from the init.sqf.

 

Does anyone have any idea why it doesn't work for all players in the server but only for the first player who picks up a box? 

BoxAmount = 0;
for "_i" from 1 to 50 do
{
_Mcolor = "ColorGreen";
_Mtext = "$50";
_MMoney = 0;
_quality = [1,2,3] selectRandomWeighted [0.1,0.2,1.3]; 
if (round _quality == 1) then {
_Mcolor = "ColorWhite"; 
_Mtext = "$500";
_MMoney = 500;
};
if (round _quality == 2) then {
_Mcolor = "ColorYellow"; 
_Mtext = "$200";
_MMoney = 200;
};
if (round _quality == 3) then {
_Mcolor = "ColorGreen";
_Mtext = "$100";
_MMoney = 100;
};
//hint format ["%1",_quality];

private _types = [
    "BUILDING",
    "BUNKER",
    "BUSSTOP",
    "CHAPEL",
    "CHURCH",
    "FORTRESS",
    "HOSPITAL",
    "HOUSE",
    "LIGHTHOUSE",
    "POWERSTATION",
    "WATERTOWER"
];

_allBuildings = nearestTerrainObjects [[14000,18000], _types, 50000, false, true];
_allPositions = [];
_allBuildings apply {_allPositions append (_x buildingPos -1)};
_rndPos = selectRandom _allPositions;
_box = "Land_PaperBox_01_small_closed_brown_f" createVehicle [_rndPos select 0, _rndPos select 1, (_rndPos select 2) + 3];
_Mname = "marker" + str _i;

[_Mname, _rndPos, _Mcolor, _Mtext, _box, _MMoney] spawn {
_Mname = _this select 0;
_rndPos = _this select 1;
_Mcolor = _this select 2;
_Mtext = _this select 3;
_box = _this select 4;
_MMoney = _this select 5;
_dropoffmarker = createMarker [_Mname, _rndPos];
_dropoffmarker setMarkerShape "ICON";
_dropoffmarker setMarkerType "mil_box";
_dropoffmarker setMarkerColor _Mcolor;
_dropoffmarker setMarkerText _Mtext; 
private _Amoney = player getVariable [format["_Amoney_%1", player],0]; 
while {true} do {
if (player distance _box < 5) exitWith {
deleteVehicle _box;
deleteMarker _dropoffmarker;
_Amoney = _Amoney + _MMoney;
hint format ["You picked up $%1", _MMoney];
player setVariable [format["_Amoney_%1", player], _Amoney];
};
sleep 2;
};
};
};

 

Share this post


Link to post
Share on other sites

I strongly advise you to indent your code correctly. Readable code is far easier to debug and maintain.

 

My code editor showed me an invisible character at this line

_box = "Land_PaperBox_01_small_closed_brown_f" createVehicle ��[_rndPos select 0, _rndPos select 1, (_rndPos select 2) + 3];

 

  • Like 1

Share this post


Link to post
Share on other sites
3 minutes ago, cidfr said:

I strongly advise you to indent your code correctly. Readable code is far easier to debug and maintain.

 

My code editor showed me an invisible character at this line


_box = "Land_PaperBox_01_small_closed_brown_f" createVehicle ��[_rndPos select 0, _rndPos select 1, (_rndPos select 2) + 3];

 

 Yeah you are right, I usually do but this time I just wrote the code just so me and my friends could quickly play the new gamemode. 

 

The boxes seem to spawn normally and there isn't any errors thrown from that line. almost everything works. Only thing that doesn't is that only the first player that picks up the money can pick up any money during our session.

Share this post


Link to post
Share on other sites

I think it's a locality problem, since all players and the server execute init.sqf once

 

I suppose the amount of boxes is 50 * number of players

 

And each player execute their own :

[_Mname, _rndPos, _Mcolor, _Mtext, _box, _MMoney] spawn {
  // ...
};

I would rather use triggers if all you need is a player-proximity checker

  • Like 1

Share this post


Link to post
Share on other sites
2 minutes ago, cidfr said:

I think it's a locality problem, since all players and the server execute init.sqf once

 

I suppose the amount of boxes is 50 * number of players

 

And each player execute their own :


[_Mname, _rndPos, _Mcolor, _Mtext, _box, _MMoney] spawn {
  // ...
};

I would rather use triggers if all you need is a player-proximity checker

If all players execute that script themselves, then the script would compare the player from the machine it's running on to the _box, correct? So, why when the script run on all clients and someone picks up a box, the script assumes the "player" to be the one that picked it up first? 

if (player distance _box < 5) exitWith {
deleteVehicle _box;
deleteMarker _dropoffmarker;
_Amoney = _Amoney + _MMoney;
hint format ["You picked up $%1", _MMoney];
player setVariable [format["_Amoney_%1", player], _Amoney];

 

Share this post


Link to post
Share on other sites

I don't think it's the first player, I think it's the player who created this _box. The code if (player distance _box < 5) would work only with the player that created the _box, because that script is only executed on a single client (each client executing their own version)

 

If you create the boxes only server-side and execute remotely the spawned code on each clients, it may work but I wouldn't recommend this approach. Game logic should be executed server-side 

  • Like 1

Share this post


Link to post
Share on other sites
2 minutes ago, cidfr said:

I don't think it's the first player, I think it's the player who created this _box. The code if (player distance _box < 5) would work only with the player that created the _box, because that script is only executed on a single client (each client executing their own version)

 

If you create the boxes only server-side and execute remotely the spawned code on each clients, it may work but I wouldn't recommend this approach. Game logic should be executed server-side 

I think you're right. So you recommend to use triggers for this, what would your approach be? In my first version I used a trigger with (player inArea _boxtrigger) instead of (player distance _box < 5) which also only worked for one person. I tried to use setTriggerStatements and executing the code that way but that didn't work either unfortunately. 

Share this post


Link to post
Share on other sites
25 minutes ago, draoth said:

player inArea _boxtrigger

 

player is still a reference to the client who execute the code (in that case, the trigger creator?) If the trigger creator is a server, there is no "player"

Can you share the setTriggerStatements you wrote? You may be closer to the solution than you expect

  • Like 1

Share this post


Link to post
Share on other sites

This was the setTriggerStatements i wrote:

_Boxtrg setTriggerActivation ["ANYPLAYER", "PRESENT", true];
_Boxtrg setTriggerStatements ["this", "
_firstplayer = thisList select 0;
private _Amoney = _firstplayer getVariable [format['_Amoney_%1', _firstplayer],0];
deleteVehicle _box;
deleteMarker _dropoffmarker;
hint format ['You picked up $%1', _MMoney];
_Amoney = _Amoney + _MMoney;
_firstplayer setVariable [format['_Amoney_%1', _firstplayer], _Amoney];
 ",""];

But when picking up the box it just says: "you picked up $any%"

Share this post


Link to post
Share on other sites
18 minutes ago, cidfr said:

 

player is still a reference to the client who execute the code (in that case, the trigger creator?) If the trigger creator is a server, there is no "player"

Can you share the setTriggerStatements you wrote? You may be closer to the solution than you expect

This was the setTriggerStatements i wrote:

_Boxtrg setTriggerActivation ["ANYPLAYER", "PRESENT", true];
_Boxtrg setTriggerStatements ["this", "
_firstplayer = thisList select 0;
private _Amoney = _firstplayer getVariable [format['_Amoney_%1', _firstplayer],0];
deleteVehicle _box;
deleteMarker _dropoffmarker;
hint format ['You picked up $%1', _MMoney];
_Amoney = _Amoney + _MMoney;
_firstplayer setVariable [format['_Amoney_%1', _firstplayer], _Amoney];
 ",""];

But when picking up the box it just says: "you picked up $any%" and the variable wouldn't get updated (edit: It turns out that this also only works for the host and the variable does change but it sets it back at 0)

 

Share this post


Link to post
Share on other sites

_MMoney doesn't exist in the scope of the activation callback (neither _box nor _dropoffmarker)

You can inject a variable into it by setting a variable in the trigger :

 

_Boxtrg setVariable [ "_mMoney", _MMoney ];
_Boxtrg setVariable [ "_box", _box ];
_Boxtrg setVariable [ "_dropoffmarker", _dropoffmarker ];

 

And then, into the setTriggerStatements :

 

_Boxtrg setTriggerStatements [
  "this",
  
  "
   _firstplayer = thisList select 0;
   private _Amoney = _firstplayer getVariable [format['_Amoney_%1', _firstplayer],0];
   private _MMoney = thisTrigger getVariable [ '_mMoney', 0]; // <--- Check this
   private _box = thisTrigger getVariable '_box';             // <--- And this
   private _dropoffmarker = thisTrigger getVariable '_dropoffmarker'; // <--- And this
   deleteVehicle _box;
   deleteMarker _dropoffmarker;
   hint format ['You picked up $%1', _MMoney];
   _Amoney = _Amoney + _MMoney;
   _firstplayer setVariable [format['_Amoney_%1', _firstplayer], _Amoney];
   deleteVehicle thisTrigger; // Money was picked up for the trigger associated with the box and it can be deleted now
   ",
  
  ""
];

 

  • Like 1

Share this post


Link to post
Share on other sites

@cidfr

Thanks! I didn't think of setting the variables to the trigger. I'm getting closer, but now both players can interact with the box making it disappear, but only the first player (tested it with about 10 boxes for both the client and the host) that interacts with the boxes gets the money from all the boxes that are being picked up. So: player1 picks up a box: hint appears, box disappears, money gets added now player2 picks up a box and: hint appears for the player1, box disappears and the player1 gets the money. It all depends on the player who picks up the box the first time. Also, the marker doesn't get deleted now for some reason.

 

Here is my complete updated script:

 

BoxAmount = 0;
for "_i" from 1 to 50 do
{
_Mcolor = "ColorGreen";
_Mtext = "$50";
_MMoney = 0;
_quality = [1,2,3] selectRandomWeighted [0.1,0.2,1.3]; 
if (round _quality == 1) then {
_Mcolor = "ColorWhite"; 
_Mtext = "$500";
_MMoney = 500;
};
if (round _quality == 2) then {
_Mcolor = "ColorYellow"; 
_Mtext = "$200";
_MMoney = 200;
};
if (round _quality == 3) then {
_Mcolor = "ColorGreen";
_Mtext = "$100";
_MMoney = 100;
};
//hint format ["%1",_quality];

private _types = [
    "BUILDING",
    "BUNKER",
    "BUSSTOP",
    "CHAPEL",
    "CHURCH",
    "FORTRESS",
    "HOSPITAL",
    "HOUSE",
    "LIGHTHOUSE",
    "POWERSTATION",
    "WATERTOWER"
];

_allBuildings = nearestTerrainObjects [[14000,18000], _types, 50000, false, true];
_allPositions = [];
_allBuildings apply {_allPositions append (_x buildingPos -1)};
_rndPos = selectRandom _allPositions;
_box = "Land_PaperBox_01_small_closed_brown_f" createVehicle [_rndPos select 0, _rndPos select 1, (_rndPos select 2) + 3];
_Mname = "marker" + str _i;

[_Mname, _rndPos, _Mcolor, _Mtext, _box, _MMoney] spawn {
_Mname = _this select 0;
_rndPos = _this select 1;
_Mcolor = _this select 2;
_Mtext = _this select 3;
_box = _this select 4;
_MMoney = _this select 5;
["Hello"] remoteExec ["hint"];
_dropoffmarker = createMarker [_Mname, _rndPos];
_dropoffmarker setMarkerShape "ICON";
_dropoffmarker setMarkerType "mil_box";
_dropoffmarker setMarkerColor _Mcolor;
_dropoffmarker setMarkerText _Mtext; 
private _Boxtrg = createTrigger ["EmptyDetector", _rndPos, true];
_Boxtrg setTriggerArea [2, 2, 0, false];
_Boxtrg setTriggerActivation ["ANYPLAYER", "PRESENT", true];
_Boxtrg setVariable ["_mMoney", _MMoney];
_Boxtrg setVariable ["_box",_box];
_Boxtrg setVariable ["_dropoffmarker",_dropoffmarker];
_Boxtrg setTriggerStatements ["this", 
"
_firstplayer = thisList select 0;
private _Amoney = _firstplayer getVariable [format['_Amoney_%1', _firstplayer],0];
private _MMoney = thisTrigger getVariable [ '_mMoney', 0]; 
private _box = thisTrigger getVariable '_box';
private _dropoffmarker = thisTrigger getVariable
deleteVehicle _box;
deleteMarker _dropoffmarker;
hint format ['You picked up $%1', _MMoney];
_Amoney = _Amoney + _MMoney;
_firstplayer setVariable [format['_Amoney_%1', _firstplayer], _Amoney];
deleteVehicle thisTrigger; 
 ",""];
 
//private _Amoney = player getVariable [format["_Amoney_%1", player],0]; 




//while {true} do {
//if (player inArea _Boxtrg == true) exitWith {
//deleteVehicle _box;
//deleteMarker _dropoffmarker;
//deleteVehicle _Boxtrg;
//_Amoney = _Amoney + _MMoney;
//hint format ["You picked up $%1", _MMoney];
//player setVariable [format["_Amoney_%1", player], _Amoney];
//};
//sleep 2;
//};
};
};

 

Share this post


Link to post
Share on other sites

I'm still stuck, does anyone have an idea on how to properly do this? 

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

×