Compare commits

..

2 Commits

Author SHA1 Message Date
Jacob Schmidt
fd247922df feat: Add initial client-side modular addon system with core game features.
All checks were successful
Build / Build (push) Successful in 16m52s
2025-12-23 05:48:54 -06:00
Jacob Schmidt
89d0b2d8bb feat: implement new admin panel, in-game store, and arsenal management systems. 2025-12-23 05:45:17 -06:00
9 changed files with 163 additions and 43 deletions

View File

@ -1,5 +1,7 @@
PREP(adminRefresh); PREP(adminRefresh);
PREP(handleEvents);
PREP(handleTransfer); PREP(handleTransfer);
PREP(initAdmin);
PREP(openAdmin); PREP(openAdmin);
PREP(sendMessage); PREP(sendMessage);
PREP(updatePaygrade); PREP(updatePaygrade);

View File

@ -2,7 +2,12 @@
/* /*
* Author: IDSolutions * Author: IDSolutions
* Refreshes the admin interface *
* [Description]
* Refreshes the admin interface player list and resets input fields.
* This function populates the player list with names and paygrades,
* storing player UIDs as data for each entry. Only shows players
* on the same side as the admin.
* *
* Arguments: * Arguments:
* 0: Dummy <ANY> - Optional parameter, not used (for compatibility with event handlers) * 0: Dummy <ANY> - Optional parameter, not used (for compatibility with event handlers)
@ -14,9 +19,10 @@
* [] call forge_client_admin_fnc_adminRefresh; * [] call forge_client_admin_fnc_adminRefresh;
* ["dummy"] call forge_client_admin_fnc_adminRefresh; * ["dummy"] call forge_client_admin_fnc_adminRefresh;
* *
* Public: No * Public: No - Called from admin dialog controls
*/ */
private _dialog = findDisplay 202303; private _dialog = findDisplay 202303;
private _list = _dialog displayCtrl 2023001; private _list = _dialog displayCtrl 2023001;

View File

@ -0,0 +1,62 @@
#include "..\script_component.hpp"
/*
* Function: forge_client_admin_fnc_handleEvents
* Author: IDSolutions
*
* [Description]
* Handles events from the admin interface.
* This function listens for events from the admin interface
* and processes them accordingly.
*
* Arguments:
* 0: Event <STRING> - The event to handle
* 1: Data <ANY> - The data associated with the event
*
* Return Value:
* None
*
* Examples:
* ["EVENT_NAME", "DATA"] call forge_client_admin_fnc_handleEvents;
*
* Public: No - Called from admin dialog controls
*/
params ["_control", "_isConfirmDialog", "_message"];
diag_log format ["[FORGE: Admin] Received event: %1", _message];
private _messageParts = _message splitString ":";
private _event = _messageParts select 0;
private _data = _messageParts select 1;
switch (_event) do {
case "REQUEST_PLAYER_DATA": {
private _playerData = createHashMap;
private _playerList = [];
{
private _player = _x;
private _uid = getPlayerUID _player;
private _name = name _player;
private _paygrade = GETVAR(_player,FORGE_PayGrade,QUOTE(E1));
private _funds = GETVAR(_player,FORGE_BankBalance,0);
private _playerInfo = createHashMapFromArray [
["uid", _uid],
["name", _name],
["paygrade", _paygrade],
["funds", _funds],
["side", str (side _player)]
];
_playerList pushBack _playerInfo;
} forEach allPlayers;
_playerData set ["players", _playerList];
_control ctrlWebBrowserAction ["ExecJS", format ["handlePlayerDataRequest(%1)", (toJSON _playerList)]];
};
default {
diag_log format ["[FORGE: Admin] Unknown event: %1", _event];
};
};

View File

@ -1,8 +1,16 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Function: forge_client_admin_fnc_handleTransfer
* Author: IDSolutions * Author: IDSolutions
* Handles fund transfers *
* [Description]
* Handles fund transfers through the admin interface.
* This function retrieves the selected player's UID and amount
* from the admin dialog, then sends it to the server-side admin store.
* Supports multiple transfer types: advance (to single player),
* deduct (from single player), advanceAll (to all players),
* and payday (distribute based on paygrade).
* *
* Arguments: * Arguments:
* 0: Condition <STRING> - The type of transfer to perform ("advance", "deduct", "advanceAll", "payday") * 0: Condition <STRING> - The type of transfer to perform ("advance", "deduct", "advanceAll", "payday")
@ -25,8 +33,8 @@ private _index = lbCurSel _list;
private _uid = _list lbData _index; private _uid = _list lbData _index;
private _amount = round (parseNumber (ctrlText 2023005)); private _amount = round (parseNumber (ctrlText 2023005));
if ({_condition in ["advance", "deduct"]} && ((isNil "_uid") || { _uid isEqualTo "" })) exitWith { hint "You did not select a player!"; }; if (_condition in ["advance", "deduct"] && ((isNil "_uid") || { _uid isEqualTo "" })) exitWith { hint "You did not select a player!"; };
["forge_server_admin_handleEvents", ["ADMIN::TRANSFER", [_condition, _amount, _uid]]] call CFUNC(serverEvent); [_condition, _amount, _uid] remoteExec ["forge_server_admin_fnc_handleTransfer", 2];
ctrlSetText [2023005, ""]; ctrlSetText [2023005, ""];

View File

@ -16,8 +16,26 @@
* Public: Yes * Public: Yes
*/ */
private _productVersion = productVersion; disableSerialization;
private _steamBranchName = _productVersion select 8; createDialog "RscAdmin";
private _dialog = findDisplay 202303;
private _list = _dialog displayCtrl 2023001;
private _list2 = _dialog displayCtrl 2023003;
{
if (str (side _x) == str (playerSide) && isPlayer _x) then {
private _name = name (_x);
private _uid = getPlayerUID _x;
private _payGrade = GETVAR(_x,FORGE_PayGrade,QUOTE(E1));
private _index = _list lbAdd format["%1 - %2", _name, _payGrade];
_list lbSetData [_index, _uid];
};
} count (allPlayers);
lbSetCurSel [2023001, 0];
private _payGrades = (missionConfigFile >> "CfgPaygrades" >> "payGrades") call BFUNC(getCfgData); private _payGrades = (missionConfigFile >> "CfgPaygrades" >> "payGrades") call BFUNC(getCfgData);
if (_steamBranchName == "profiling") then { if (_steamBranchName == "profiling") then {

View File

@ -1,8 +1,13 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Function: forge_client_admin_fnc_sendMessage
* Author: IDSolutions * Author: IDSolutions
* Sends a message to a selected player *
* [Description]
* Sends a message to a selected player through the admin interface.
* This function retrieves the selected player's UID and message content
* from the admin dialog, then sends it to the server-side admin store.
* *
* Arguments: * Arguments:
* None * None
@ -25,6 +30,8 @@ private _message = ctrlText _control;
if ((isNil "_uid") || {_uid isEqualTo ""}) exitWith { hintSilent "You did not select a player!"; }; if ((isNil "_uid") || {_uid isEqualTo ""}) exitWith { hintSilent "You did not select a player!"; };
["forge_server_admin_handleEvents", ["ADMIN::SEND::MESSAGE", [_uid, _message]]] call CFUNC(serverEvent); [_uid, _message] remoteExec ["forge_server_admin_fnc_sendMessage", 2];
hintSilent format ["Message sent to UID %1: %2", _uid, _message];
["dummy"] call FUNC(adminRefresh); ["dummy"] call FUNC(adminRefresh);

View File

@ -1,8 +1,13 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Function: forge_client_admin_fnc_updatePaygrade
* Author: IDSolutions * Author: IDSolutions
* Updates a player's paygrade *
* [Description]
* Updates a player's paygrade in the server's admin store.
* This function retrieves the selected player's UID and the target paygrade
* from the admin dialog, then sends it to the server-side admin store.
* *
* Arguments: * Arguments:
* None * None
@ -21,12 +26,12 @@ private _list = _dialog displayCtrl 2023001;
private _list2 = _dialog displayCtrl 2023003; private _list2 = _dialog displayCtrl 2023003;
private _targetIndex = lbCurSel _list; private _targetIndex = lbCurSel _list;
private _rankIndex = lbCurSel _list2; private _rankIndex = lbCurSel _list2;
private _uid = _list lbData _targetIndex; private _targetUID = _list lbData _targetIndex;
private _rankData = call compile format ["%1", (_list2 lbData _rankIndex)]; private _rankData = call compile format ["%1", (_list2 lbData _rankIndex)];
private _paygrade = _rankData select 0; private _paygrade = _rankData select 0;
if ((isNil "_uid") || {_uid isEqualTo ""}) exitWith { hintSilent "You did not select a player!" }; if ((isNil "_targetUID") || {_targetUID isEqualTo ""}) exitWith { hintSilent "You did not select a player!" };
["forge_server_admin_handleEvents", ["ADMIN::UPDATE::PAYGRADE", [_uid, _paygrade]]] call CFUNC(serverEvent); [_targetUID, _paygrade] remoteExec ["forge_server_admin_fnc_updatePaygrade", 2];
["dummy"] call FUNC(adminRefresh); ["dummy"] call FUNC(adminRefresh);

View File

@ -2,6 +2,8 @@
/* /*
* Author: IDSolutions * Author: IDSolutions
*
* [Description]
* Initializes the arsenal system with armory and garage data * Initializes the arsenal system with armory and garage data
* *
* Arguments: * Arguments:
@ -17,8 +19,11 @@
params [["_armory_data", [], [[]]], ["_garage_data", [], [[]]]]; params [["_armory_data", [], [[]]], ["_garage_data", [], [[]]]];
if (!(_armory_data isEqualTypeArray GVAR(default_armory)) || (count _armory_data != 4)) then { _armory_data = GVAR(default_armory); }; private _defaultArmory = [[],[],[],[]];
if (!(_garage_data isEqualTypeArray GVAR(default_garage)) || (count _garage_data != 6)) then { _garage_data = GVAR(default_garage); }; private _defaultGarage = [[],[],[],[],[],[]];
if (!(_armory_data isEqualTypeArray _defaultArmory) || (count _armory_data != 4)) then { _armory_data = _defaultArmory; };
if (!(_garage_data isEqualTypeArray _defaultGarage) || (count _garage_data != 6)) then { _garage_data = _defaultGarage; };
if (GVAR(armory_type) == 0) then { if (GVAR(armory_type) == 0) then {
{ {
[GVAR(gear_box), _x, false, true, 1, _forEachIndex] call BFUNC(addVirtualItemCargo); [GVAR(gear_box), _x, false, true, 1, _forEachIndex] call BFUNC(addVirtualItemCargo);
@ -50,3 +55,8 @@ GVAR(static_unlocks) = _statics;
{ {
[_x] call FUNC(addVirtualVehicles); [_x] call FUNC(addVirtualVehicles);
} forEach GVAR(garage_unlocks); } forEach GVAR(garage_unlocks);
private _armoryCount = count (_armory_data select { count _x > 0 });
private _garageCount = count (_garage_data select { count _x > 0 });
TRACE_2("Arsenal System Initialized",_armoryCount,_garageCount);

View File

@ -1,10 +1,11 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: IDSolutions * Function: forge_store_fnc_handleDelivery
* Description:
* Handles the delivery timer and locker updates for purchased items * Handles the delivery timer and locker updates for purchased items
* *
* Arguments: * Parameters:
* 0: New Locker Contents <ARRAY> * 0: New Locker Contents <ARRAY>
* *
* Returns: * Returns:
@ -12,15 +13,16 @@
* *
* Example: * Example:
* [_newLocker] spawn forge_store_fnc_handleDelivery * [_newLocker] spawn forge_store_fnc_handleDelivery
*
* Public: No
*/ */
params [["_newLocker", [], [[]]]]; params [["_newLocker", [], [[]]]];
if (_newLocker isEqualTo []) exitWith {
["Error: Empty locker contents", "error", 5] call FUNC(notify);
};
private _deliveryTime = ["DT", 0] call BIS_fnc_getParamValue; private _deliveryTime = ["DT", 0] call BIS_fnc_getParamValue;
if (_newLocker isEqualTo []) exitWith {};
if (_deliveryTime > 0) then { if (_deliveryTime > 0) then {
[ [
format [ format [
@ -29,19 +31,19 @@ if (_deliveryTime > 0) then {
], ],
"info", "info",
3, 3,
"right" "left"
] call EFUNC(misc,notify); ] call FUNC(notify);
uiSleep (_deliveryTime / 2); sleep (_deliveryTime / 2);
[ [
"<t align='left'>Package in transit</t>", "<t align='left'>Package in transit</t>",
"warning", "warning",
2, 2,
"left" "left"
] call EFUNC(misc,notify); ] call FUNC(notify);
uiSleep (_deliveryTime / 2); sleep (_deliveryTime / 2);
SETPVAR(player,FORGE_Locker,_newLocker); SETPVAR(player,FORGE_Locker,_newLocker);
@ -50,18 +52,18 @@ if (_deliveryTime > 0) then {
"success", "success",
5, 5,
"left" "left"
] call EFUNC(misc,notify); ] call FUNC(notify);
if (hasInterface) then { playSound "FD_Finish_F"; }; if (hasInterface) then {
playSound "FD_Finish_F";
};
} else { } else {
SETPVAR(player,FORGE_Locker,_newLocker); SETPVAR(player,FORGE_Locker,_newLocker);
[ [
"<t align='left'>Order Complete!</t><br/><t size='0.8' align='left'>Items added to locker</t>", "<t align='left'>Order Complete!</t><br/><t size='0.8' align='left'>Items added to locker</t>",
"success", "success",
5, 3,
"left" "left"
] call EFUNC(misc,notify); ] call FUNC(notify);
if (hasInterface) then { playSound "FD_Finish_F"; };
}; };