Jump to content

Recommended Posts

Hello people,
I have been struggling to make a working custom ticket system for my mission.
My goal is to have a maximum of 7 global west tickets as I have 7 available player slots. To make it more fair, I want one ticket to subtract from west side every time a new player respawns on west side, but not when they respawn again. Server should keep track of tickets subtracted and add ticket back if player chooses to change sides to east or if he disconnects the server from the west side.
My guess is, i have trouble making database work...

Now I don't have any real coding experience and this is my idea of the code which I heavily edited multiple times using logic and ChatGPT:

onPlayerRespawn.sqf

// Variable ticket system
private _uid = getPlayerUID player;

// Retrieve player data
private _playerData = [_uid] call TAG_fnc_retrievePlayerData;

private _tempSideRespawned = side player;
private _tempAlreadyRespawnedAsEast;
private _tempHasReturnedTicket;

private _lastRespawnedSide = profileNamespace getVariable ["lastRespawnedSide", east];

if (!isNull _playerData) then {
    _tempAlreadyRespawnedAsEast = _playerData select 1;
    _tempHasReturnedTicket = _playerData select 2;
} else {
    _tempAlreadyRespawnedAsEast = false;
    _tempHasReturnedTicket = false;
};

// Handle ticket decrement and increment based on the respawned side
if (_tempSideRespawned == east && _tempSideRespawned != _lastRespawnedSide) then {
    [east, -1] call BIS_fnc_respawnTickets;
    _tempHasReturnedTicket = false;
} else {
    if (_tempSideRespawned == west && _lastRespawnedSide == east && !_tempAlreadyRespawnedAsEast && !_tempHasReturnedTicket) then {
        [west, 1] call BIS_fnc_respawnTickets;
        _tempAlreadyRespawnedAsEast = true;
        _tempHasReturnedTicket = true;
    };
};

// Update the player's last respawned side
private _lastRespawnedSide = _tempSideRespawned;
profileNamespace setVariable ["lastRespawnedSide", _tempSideRespawned];

// Update the player's data in the database
[_uid, [_tempSideRespawned, _tempAlreadyRespawnedAsEast, _tempHasReturnedTicket]] call TAG_fnc_storePlayerData;

initServer.sqf

execVM "Scripts\functions.sqf";
// Global array to store each player's data in the TAG_database
if (isNil "TAG_database") then {
    TAG_database = [];
};

// Event handler for player disconnect
addMissionEventHandler ["PlayerDisconnected", {
    params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"];

    // Get the player's data from TAG_database using UID
    private _playerData = [_uid] call TAG_fnc_retrievePlayerData;

    if (count _playerData > 0) then {
        private _side = _playerData select 0;
        private _hasReturnedTicket = _playerData select 2;

        if (_side == west && !_hasReturnedTicket) then {
            [west, 1] call BIS_fnc_respawnTickets; // Add one ticket to West side on the server
            diag_log "Ticket returned to West";
            // Mark that the ticket has been returned for this player to prevent multiple returns
            [_uid, _side, true] call TAG_fnc_storePlayerData;
        };
    };

    // Remove the player's data from TAG_database upon disconnect
    TAG_database = TAG_database - [_uid];
}];

functions.sqf

TAG_fnc_storePlayerData = {
    params ["_uid", "_data"];
    private _playerIndex = -1;
    
    {
        if ((_x select 0) == _uid) then {
            _playerIndex = _forEachIndex;
            true
        } else {
            false
        };
    } forEach TAG_database;

    if (_playerIndex < 0) then {
        TAG_database pushBack [_uid, _data];
    } else {
        TAG_database set [_playerIndex, [_uid, _data]];
    };
};

TAG_fnc_retrievePlayerData = {
    params ["_uid"];
    private _playerIndex = -1;

    {
        if ((_x select 0) == _uid) then {
            _playerIndex = _forEachIndex;
            true
        } else {
            false
        };
    } forEach TAG_database;

    if (_playerIndex >= 0) then {
        TAG_database select _playerIndex select 1;
    } else {
        [];
    };
};

TAG_fnc_getPlayerIndex = {
    params ["_uid"];
    private _playerIndex = -1;

    {
        if ((_x select 0) == _uid) then {
            _playerIndex = _forEachIndex;
            true
        } else {
            false
        };
    } forEach _database;
    
    _playerIndex;
};


description.ext
 

class CfgFunctions {
    class Anthill {
        class MissionFunctions {
            class fnc_startTimer {
                file = "Scripts\functions.sqf";
            };

            class fnc_stopTimer {
                file = "Scripts\functions.sqf";
            };

            class fnc_resetTimer {
                file = "Scripts\functions.sqf";
            };

            class fnc_checkEmptyServer {
                file = "Scripts\functions.sqf";
            };

            class fnc_missionTimer {
                file = "Scripts\functions.sqf";
            };

            class fnc_scheduleTimer {
                file = "Scripts\functions.sqf";
            };
class TAG_fnc_storePlayerData {
                file = "Scripts\functions.sqf";
            };

            class TAG_fnc_retrievePlayerData {
                file = "Scripts\functions.sqf";
            };

            class TAG_fnc_getPlayerIndex {
                file = "Scripts\functions.sqf";
            };
        };
    };
};

I have sorted all errors in RPT files, and I still can't manage to execute full onplayerrespawn.sqf... I don't know where is the problem or how else i can diagnose it beside diag_log which doens't always work.

Thanks for insights

Edited by Hakoza
Problem have been solved

Share this post


Link to post
Share on other sites

I have approached this problem from totally wrong side. Whole script should be done on server side. Everything that has to do with multiple clients is server side business. There is no need for functions or database also. See below

initServer.sqf
 

//Variable ticket system by Hakoza (V2)
addMissionEventHandler ["EntityRespawned", {
    params ["_newEntity", "_oldEntity"];

    if (isPlayer _newEntity) then {
        private _sideRespawned = side _newEntity;
        private _uid = getPlayerUID _newEntity; // Get player's UID
         // Retrieve the last respawned side, or set it to the deafult east side if not already set
        private _lastRespawnedSide = missionNamespace getVariable [_uid + "lastRespawnedSide", east];
		
        private _ticket = _oldEntity getVariable ["_ticket", false];
        private _sideChanged = false;
        
        //Add or subtract tickets based on player side
        if (_sideRespawned == east && _lastRespawnedSide == west && !_ticket) then {
            [west, 1] call BIS_fnc_respawnTickets;
            _sideChanged = true;
            _ticket = true;
        } else {
            if (_sideRespawned == west && _lastRespawnedSide == east && !_ticket) then {
                [west, -1] call BIS_fnc_respawnTickets;
                _sideChanged = true;
                _ticket = true;
            };
        };
        if (_sideChanged) then {
            _newEntity setVariable ["_ticket", _ticket, false];
        };
        missionNamespace setVariable [_uid + "lastRespawnedSide", _sideRespawned]; // Store the new value based on UID	 
    };
}];

// Return lost ticket upon disconnect
addMissionEventHandler ["HandleDisconnect", {
    params ["_body", "_id", "_uid", "_name"];

    private "_lastRespawnedSide";
    _lastRespawnedSide = missionNamespace getVariable [_uid + "lastRespawnedSide", east];
    if (_lastRespawnedSide == west) then {
        [west, 1] call BIS_fnc_respawnTickets;
    };
    // Set _lastRespawnedSide to nil in the missionNamespace
    missionNamespace setVariable [_uid + "lastRespawnedSide", nil];
}];

Enjoy 🙂

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

×