HolyLight56 0 Posted December 9, 2021 (edited) I'm trying to modify an array whenever a player respawns to lower their individual respawn tickets. The current issue I am facing is changing the second value of each pair to the desired number. (Note: some code may be placeholders, full code below) The array will look something like this: playerArray = [["Player1UID", X], ["Player2UID", X], ["Player3UID", X]] Code I'm trying to use: playerArray set [((playerArray select 0) select 1), X-1]; // Lowers the old value by 1 in the array Desired Result: playerArray = [["Player1UID", X-1], ["Player2UID", X], ["Player3UID", X]] Actual Result playerArray = [["Player1UID", X], ["Player2UID", X], ["Player3UID", X], X-1] Full script: Spoiler (_this select 0) addMPEventHandler ["MPRespawn", { playerUID = getPlayerUID (_this select 0); // Grabs the player's UID _index = [playerArray, _playerUID] call BIS_fnc_findNestedElement; // Finds the position of the player's UID in the array _oldTickets = ((playerArray select (_index select 0)) select 1); // Determines the value of the player's ticket count before death _Newtickets = _oldTickets - 1; // Lowers their ticket count by one playerArray set [((playerArray select (_index select 0)) select 1), _NewTickets]; // Changes the old ticket value to the new value if (_Newtickets < 1) then {if (Spectator_After_Final_Death == 1) then ["Initialize", [_this, [], true ]] call BIS_fnc_EGSpectator;}; // starts spectator cam if they run out of lives }]; Any help, comments, or suggestions would be amazing. Thank you and have a great day. Edited December 9, 2021 by HolyLight56 added insight/resources Share this post Link to post Share on other sites
pierremgi 4945 Posted December 9, 2021 playerArray = [["Player1UID", X], ["Player2UID", X], ["Player3UID", X]]; private _index = playerArray apply {_x#0} find _playerUID; _oldTickets = playerArray #_index #1; (playerArray #_index) set [1, _oldTickets -1]; 2 Share this post Link to post Share on other sites
HolyLight56 0 Posted December 9, 2021 Thank you for the reply pierremgi. I did some more testing with your code and I ended up with something that seems to work. Working Testing Code: Spoiler _playerUID = getPlayerUID _this; // grabs the player's UID private _index = [playerArray, _playerUID] call BIS_fnc_findNestedElement; // Finds it's position in the array _oldTickets = (playerArray #(_index #0)) #1; // Determines how many tickets they had (playerArray #(_index #0)) set [1, _oldTickets -1]; // Reduces the number of tickets by one I'll be posting the full code once it's been thoroughly tested. Again, thank you for the help. (Note: I was using ZEN, so '_this' worked rather than 'this' Share this post Link to post Share on other sites
mrcurry 522 Posted December 10, 2021 Unless you have a specific reason to use arrays this would be a perfect use case for a Hashmap. Same example using a Hashmap: playerMap = createHashmapFromArray [["Player1UID", X], ["Player2UID", X], ["Player3UID", X]]; _playerUID = getPlayerUID _this; // grabs the player's UID _oldTickets = playerMap get _playerUID; // Determines how many tickets they had playerMap set [ _playerUID, _oldTickets -1]; // Reduces the number of tickets by one Less code, easier to read and lightning fast even with thousands of players in the playerMap. 3 Share this post Link to post Share on other sites
Harzach 2518 Posted December 10, 2021 8 hours ago, mrcurry said: createHashmapFromArray Man, I really need to read the SPOTREPs. Thanks for bringing this one to my attention, @mrcurry! Share this post Link to post Share on other sites
HolyLight56 0 Posted December 14, 2021 I'll be needing to add player's UIDs and set their ticket amounts throughout the mission. If it were a set list of players, i'd absoultely do as you said and use the hashmap. I'll keep looking into how to properly implement the code. @mrcurry Currently I'm having a hard time understanding how to get arrays and variables from global space, and then execute a function to change global variables and arrays. (updating the player array with a correct ticket count for each player). I'm sure there is an easy solution, the only problem is finding it. Thank you for pointing me towards hashmaps, they seem perfect this and i'll see if i might be able to implement them. Share this post Link to post Share on other sites
mrcurry 522 Posted December 15, 2021 @HolyLight56 To make an empty Hashmap use command: variable = createHashmap; To add new elements to the map: variable set [ key, value ] In your case the key would of course be the PlayerUID string and value be the number of respawn tickets remaining. The BIKI page on hashmaps is a great place to start to get to grips with them: https://community.bistudio.com/wiki/HashMap As for your respawn tickets system my tip would be: Let the server initialize the hashmap on init and set tickets for all present players. On server add a mission eventhandler to handle PlayerConnected events which add new players to the hashmap. Use remoteExec in client-code when there is need to read or update the Hashmap. Share this post Link to post Share on other sites
pierremgi 4945 Posted December 15, 2021 Yep! Don't forget that keys can't be object variables. You can (need to) use strings of playerUIDs but not p1, p2, p3... as variables of playable units. Share this post Link to post Share on other sites
HolyLight56 0 Posted December 16, 2021 So i've done some more work on the code, and after changing it to hashmaps and their corresponding codes, i've gotten approximately what @mrcurry posted previously. On 12/10/2021 at 4:49 AM, mrcurry said: _playerUID = getPlayerUID _this; // grabs the player's UID _oldTickets = playerMap get _playerUID; // Determines how many tickets they had playerMap set [ _playerUID, _oldTickets -1]; // Reduces the number of tickets by one Unfortunately, remoteExec can't target hashmaps so i've defaulted to using the above code. Which, while working on singleplayer perfectly fine, appears to not be working in multiplayer. I'm still tryin to find some way to use remoteExec with hashmaps, but again, i've hit a bit of a brick wall. The initServer file looks like this right now: Spoiler addMissionEventHandler ["PlayerConnected", { params ["_id", "_uid"]; _respawn_Tickets = ((missionNamespace getVariable "Respawn_Tickets") + 1); if (isNil {playerHashMap get _uid}) then {playerHashMap set [_uid, _respawn_Tickets];}; }]; I've added an if statement to only add the player's UID to the hashMap if it doesn't already exist there. Without being able to use remoteExec, i'm not sure how to go forward on making this work in a multiplayer environment. Share this post Link to post Share on other sites
pierremgi 4945 Posted December 17, 2021 On 12/9/2021 at 5:54 AM, HolyLight56 said: I'm trying to modify an array whenever a player respawns to lower their individual respawn tickets. The current issue I am facing is changing the second value of each pair to the desired number. (Note: some code may be placeholders, full code below) Any help, comments, or suggestions would be amazing. Thank you and have a great day. @HolyLight56 The previous answers focused on your nested array then hashmaps... but, as far as respawn tickets are concerned, why not trying: Bis_fnc_respawnTickets ? you can run it on player(s) and effect is already global. Share this post Link to post Share on other sites
mrcurry 522 Posted December 17, 2021 On 12/16/2021 at 11:35 PM, HolyLight56 said: Unfortunately, remoteExec can't target hashmaps Oh well technically it can but for this its a bit stupid to transmit the entire map across the network. Besides we don't need to... Spoiler initServer.sqf // =========== initServer.sqf =========== initial_respawn_tickes = 3; respawnTicketsMap = createHashMap; // Function to send respawn tickets back to client TAG_fnc_playerRespawnedServer = { params ["_player"]; private _uid = getPlayerUID _player; private _respawnTickets = respawnTicketsMap get _uid; respawnTicketsMap set [_uid, (_respawnTickets - 1) max 0]; [_respawnTickets] remoteExec ["TAG_fnc_playerRespawnedClient", remoteExecutedOwner]; }; // Set initial player respawn tickets { respawnTicketsMap set [ getPlayerUID _x, initial_respawn_tickes ]; } forEach allPlayers; // Add event handler to handle connecting players addMissionEventHandler [ "PlayerConnected", { params ["_id", "_uid"]; if !( _uid in respawnTicketsMap ) then { respawnTicketsMap set [_uid, initial_respawn_tickes]; }; } ]; initPlayerLocal.sqf // =========== initPlayerLocal.sqf ============= // Function to handle respawn on tickets received TAG_fnc_playerRespawnedClient = { params ["_tickets"]; respawnTicketsRemaining = _tickets; if( _tickets > 0 ) then { // Code to run on normal respawn goes here } else { // Code to run when tickets has run out goes here }; }; // Eventhandler to handle player respawn player addEventHandler [ "Respawn", { [player] remoteExec ["TAG_fnc_playerRespawnedServer", 2]; } ]; 1 Share this post Link to post Share on other sites
HolyLight56 0 Posted December 25, 2021 (edited) Thank you for the help mrcurry and pierremgi, and sorry for the long wait. I've finalized the script (included below) and now it's working properly. initServer.sqf Spoiler // =========== initServer.sqf =========== initial_respawn_tickets = 4; // NOTE: Set one higher than desired if players initially respawn Spectator_After_Final_Death = 1; respawnTicketsMap = createHashMap; // Function to send respawn tickets back to client TAG_fnc_playerRespawnedServer = { params ["_player"]; private _uid = getPlayerUID _player; private _respawnTickets = respawnTicketsMap get _uid; respawnTicketsMap set [_uid, (_respawnTickets - 1) max 0]; private _newrespawnTickets = respawnTicketsMap get _uid; [_newrespawnTickets, Spectator_After_Final_Death] remoteExec ["TAG_fnc_playerRespawnedClient", remoteExecutedOwner]; }; // Set initial player respawn tickets { respawnTicketsMap set [ getPlayerUID _x, initial_respawn_tickets ]; } forEach allPlayers; // Add event handler to handle connecting players addMissionEventHandler [ "PlayerConnected", { params ["_id", "_uid"]; if !(_uid in respawnTicketsMap) then { respawnTicketsMap set [_uid, initial_respawn_tickets]; }; } ]; // Extra scripts and functions for your pleasure // Function: to set a player's number of tickets // Example: [_this, 3] call TAG_fnc_SetPlayerRespawnTickets; TAG_fnc_SetPlayerRespawnTickets = { params ["_player", "_setTickets"]; private _networkId = owner _player; private _uid = getPlayerUID _player; private _respawnTickets = respawnTicketsMap get _uid; respawnTicketsMap set [_uid, _setTickets max 0]; [_setTickets, Spectator_After_Final_Death] remoteExec ["TAG_fnc_playerRespawnedClient", _networkId]; }; // Function: to add a number of tickets to a player (negative numbers subtract that amount, mimimum 0) // Example: [_this, 3] call TAG_fnc_AddPlayerRespawnTickets; TAG_fnc_AddPlayerRespawnTickets = { params ["_player", "_AddedTickets"]; private _networkId = owner _player; private _uid = getPlayerUID _player; private _respawnTickets = respawnTicketsMap get _uid; respawnTicketsMap set [_uid, (_AddedTickets + _respawnTickets) max 0]; private _newrespawnTickets = respawnTicketsMap get _uid; [_newrespawnTickets, Spectator_After_Final_Death] remoteExec ["TAG_fnc_playerRespawnedClient", _networkId]; }; // Script to reset all players tickets to their initial amount // {[_x, (initial_respawn_tickets - 1)] call TAG_fnc_SetPlayerRespawnTickets;} forEach allPlayers; initPlayerLocal.sqf Spoiler // =========== initPlayerLocal.sqf ============= // Function to handle respawn on tickets received TAG_fnc_playerRespawnedClient = { params ["_tickets", "_Spectator_After_Final_Death"]; private _networkId = clientOwner; if (_tickets > 0) then { ["Terminate", [player]] remoteExec ["BIS_fnc_EGSpectator", _networkId]; [player, false] remoteExec ["hideObjectGlobal", 2]; } else { if (_Spectator_After_Final_Death == 1) then {["Initialize", [player]] remoteExec ["BIS_fnc_EGSpectator",_networkId]; [player] remoteExec ["hideObjectGlobal", 2];}; }; }; // Eventhandler to handle player respawn player addEventHandler [ "Respawn", { [player] remoteExec ["TAG_fnc_playerRespawnedServer", 2]; } ]; Edited December 26, 2021 by HolyLight56 finalized script Share this post Link to post Share on other sites