#include "..\script_component.hpp" /* * File: fnc_initBankStore.sqf * Author: IDSolutions * Date: 2025-12-17 * Last Update: 2026-02-17 * Public: Yes * * Description: * Initializes the bank store for managing player bank accounts. * Provides methods for syncing, saving, and applying bank accounts to the player. * * Arguments: * None * * Return Value: * Bank store object [HASHMAP OBJECT] * * Example: * call forge_server_bank_fnc_initBankStore */ #pragma hemtt ignore_variables ["_self"] GVAR(BankModel) = compileFinal createHashMapObject [[ ["#type", "BankModel"], ["defaults", compileFinal { private _account = createHashMap; _account set ["uid", ""]; _account set ["name", ""]; _account set ["bank", 0]; _account set ["cash", 0]; _account set ["earnings", 0]; _account set ["pin", 1234]; _account set ["transactions", []]; _account }], ["fromPlayer", compileFinal { params [["_player", objNull, [objNull]]]; if (_player isEqualTo objNull) exitWith { _self call ["defaults", []] }; private _account = _self call ["defaults", []]; _account set ["uid", getPlayerUID _player]; _account set ["name", name _player]; _account set ["bank", 0]; _account set ["cash", 0]; _account set ["earnings", 0]; _account set ["pin", 1234]; _account set ["transactions", []]; _account }], ["migrate", compileFinal { params [["_account", createHashMap, [createHashMap]]]; private _defaults = _self call ["defaults", []]; { if !(_x in _account) then { _account set [_x, _y]; }; } forEach _defaults; _account }], ["validate", compileFinal { params [["_account", createHashMap, [createHashMap]]]; private _uid = _account getOrDefault ["uid", ""]; private _name = _account getOrDefault ["name", ""]; private _bank = _account getOrDefault ["bank", 0]; private _cash = _account getOrDefault ["cash", 0]; private _earnings = _account getOrDefault ["earnings", 0]; private _pin = _account getOrDefault ["pin", 1234]; [_uid, _name, _bank, _cash, _earnings, _pin] try { if (_uid isEqualTo "" || !(_uid isEqualType "")) then { throw "Invalid UID!"; }; if (_name isEqualTo "" || !(_name isEqualType "")) then { throw "Invalid Name!"; }; if (_bank < 0 || !(_bank isEqualType 0)) then { throw "Invalid Bank!"; }; if (_cash < 0 || !(_cash isEqualType 0)) then { throw "Invalid Cash!"; }; if (_earnings < 0 || !(_earnings isEqualType 0)) then { throw "Invalid Earnings!"; }; if (_pin < 1000 || _pin > 9999 || !(_pin isEqualType 0)) then { throw "Invalid Pin!"; }; } catch { ["ERROR", format ["Failed to validate account %1!", _exception]] call EFUNC(common,log); false }; true }] ]]; GVAR(BankBaseStore) = compileFinal createHashMapFromArray [ ["#base", EGVAR(common,BaseStore)], ["#type", "BankBaseStore"], ["#create", compileFinal { GVAR(IndexRegistry) = createHashMap; GVAR(Registry) = createHashMap; ["INFO", "Bank Store Initialized!"] call EFUNC(common,log); }], ["init", compileFinal { params [["_uid", "", [""]]]; private _player = [_uid] call EFUNC(common,getPlayer); private _cached = GVAR(Registry) getOrDefault [_uid, nil]; if !(isNil { _cached }) exitWith { [CRPC(bank,responseInitBank), [_cached], _player] call CFUNC(targetEvent); _cached }; ["bank:exists", [_uid]] call EFUNC(extension,extCall) params ["_result", "_isSuccess"]; if !(_isSuccess) exitWith { ["ERROR", format ["Failed to check if bank account %1 exists! Using fallback account.", _uid]] call EFUNC(common,log); private _fallbackAccount = GVAR(BankModel) call ["fromPlayer", [_player]]; _fallbackAccount set ["uid", _uid]; private _regEntry = createHashMapFromArray [["uid", _uid], ["name", (name _player)]]; GVAR(IndexRegistry) set [_uid, _regEntry]; GVAR(Registry) set [_uid, _fallbackAccount]; [CRPC(bank,responseInitBank), [_fallbackAccount], _player] call CFUNC(targetEvent); _fallbackAccount }; private _finalAccount = createHashMap; if (_result == "true") then { _finalAccount = _self call ["fetch", ["bank:get", _uid]]; ["INFO", format ["Found bank account for %1", _uid]] call EFUNC(common,log); } else { _finalAccount = GVAR(BankModel) call ["fromPlayer", [_player]]; _finalAccount set ["uid", _uid]; private _json = _self call ["toJSON", [_finalAccount]]; ["bank:create", [_uid, _json]] call EFUNC(extension,extCall) params ["_result", "_isSuccess"]; if !(_isSuccess) exitWith { ["ERROR", format ["Failed to create bank account %1! Using fallback account.", _uid]] call EFUNC(common,log); private _regEntry = createHashMapFromArray [["uid", _uid], ["name", (name _player)]]; GVAR(IndexRegistry) set [_uid, _regEntry]; GVAR(Registry) set [_uid, _finalAccount]; [CRPC(bank,responseInitBank), [_finalAccount], _player] call CFUNC(targetEvent); _finalAccount }; ["INFO", format ["Created new bank account for %1", _uid]] call EFUNC(common,log); }; private _regEntry = createHashMapFromArray [["uid", _uid], ["name", (name _player)]]; GVAR(IndexRegistry) set [_uid, _regEntry]; // _finalAccount = GVAR(BankModel) call ["migrate", [_finalAccount]]; GVAR(Registry) set [_uid, _finalAccount]; [CRPC(bank,responseInitBank), [_finalAccount], _player] call CFUNC(targetEvent); _finalAccount }], ["deposit", compileFinal { params [["_uid", "", [""]], ["_amount", 0, [0]]]; ["INFO", format ["Deposit %1, for %2", _amount, _uid]] call EFUNC(common,log); private _account = GVAR(Registry) getOrDefault [_uid, nil]; if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); }; private _bank = _account getOrDefault ["bank", 0]; private _cash = _account getOrDefault ["cash", 0]; if (_cash < _amount) exitWith { ["WARNING", "Insufficient Funds!"] call EFUNC(common,log); }; private _finalAccount = createHashMapFromArray [["bank", (_bank + _amount)], ["cash", (_cash - _amount)]]; private _player = [_uid] call EFUNC(common,getPlayer); GVAR(Registry) set [_uid, _finalAccount]; [CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent); [CRPC(notifications,recieveNotification), ["info", "Bank", format ["Deposited $%1", _amount]], _player] call CFUNC(targetEvent); }], ["payment", compileFinal { params [["_uid", "", [""]], ["_amount", 0, [0]]]; ["INFO", format ["Payment %1, for %2", _amount, _uid]] call EFUNC(common,log); private _account = GVAR(Registry) getOrDefault [_uid, nil]; if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); }; private _bank = _account getOrDefault ["bank", 0]; private _finalAccount = createHashMapFromArray [["bank", (_bank + _amount)]]; private _player = [_uid] call EFUNC(common,getPlayer); GVAR(Registry) set [_uid, _finalAccount]; [CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent); [CRPC(notifications,recieveNotification), ["info", "Bank", format ["Paid $%1", _amount]], _player] call CFUNC(targetEvent); }], ["buildChargeResult", compileFinal { params [["_message", "Unable to process bank payment.", [""]]]; createHashMapFromArray [ ["success", false], ["message", _message], ["patch", createHashMap] ] }], ["chargeCheckout", compileFinal { params [ ["_uid", "", [""]], ["_source", "cash", [""]], ["_amount", 0, [0]], ["_commit", false, [false]] ]; private _result = _self call ["buildChargeResult", []]; private _field = switch (toLowerANSI _source) do { case "cash": { "cash" }; case "bank": { "bank" }; default { "" }; }; if (_field isEqualTo "") exitWith { _result set ["message", "Selected bank payment source is unsupported."]; _result }; private _account = GVAR(Registry) getOrDefault [_uid, createHashMap]; if (_account isEqualTo createHashMap) exitWith { _result set ["message", "Bank account data is unavailable for checkout."]; _result }; private _balance = _account getOrDefault [_field, 0]; if (_balance < _amount) exitWith { private _message = [ "Bank balance cannot cover this checkout.", "Cash on hand cannot cover this checkout." ] select (_field isEqualTo "cash"); _result set ["message", _message]; _result }; private _patch = createHashMapFromArray [[_field, (_balance - _amount)]]; if (_commit) then { _patch = _self call ["mset", [GVAR(Registry), "bank:update", _uid, _patch, false]]; }; _result set ["success", true]; _result set ["message", ""]; _result set ["patch", _patch]; _result }], ["transfer", compileFinal { params [["_uid", "", [""]], ["_target", "", [""]], ["_from", "", [""]], ["_amount", 0, [0]]]; if (_uid isEqualTo _target) exitWith { ["WARNING", format ["Self-transfer attempt blocked for %1", _uid]] call EFUNC(common,log); }; private _account = GVAR(Registry) getOrDefault [_uid, nil]; if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); }; private _targetAccount = GVAR(Registry) getOrDefault [_target, nil]; if (isNil "_targetAccount") exitWith { ["ERROR", "Empty/Invalid Target Account!"] call EFUNC(common,log); }; private _selected = _account getOrDefault [_from, 0]; if (_selected < _amount) exitWith { ["WARNING", "Insufficient Funds!"] call EFUNC(common,log); }; private _targetBank = _targetAccount getOrDefault ["bank", 0]; private _finalAccount = createHashMapFromArray [[_from, (_selected - _amount)]]; private _finalTargetBank = createHashMapFromArray [["bank", (_targetBank + _amount)]]; GVAR(Registry) set [_uid, _finalAccount]; GVAR(Registry) set [_target, _finalTargetBank]; private _player = [_uid] call EFUNC(common,getPlayer); private _targetPlayer = [_target] call EFUNC(common,getPlayer); [CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent); [CRPC(bank,responseSyncBank), [_finalTargetBank], _targetPlayer] call CFUNC(targetEvent); [CRPC(notifications,recieveNotification), ["info", "Bank", format ["Transferred $%1 to %2", _amount, (name _targetPlayer)]], _player] call CFUNC(targetEvent); [CRPC(notifications,recieveNotification), ["info", "Bank", format ["Received $%1 from %2", _amount, (name _player)]], _targetPlayer] call CFUNC(targetEvent); }], ["withdraw", compileFinal { params [["_uid", "", [""]], ["_amount", 0, [0]]]; ["INFO", format ["Withdraw %1, for %2", _amount, _uid]] call EFUNC(common,log); private _account = GVAR(Registry) getOrDefault [_uid, nil]; if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); }; private _bank = _account getOrDefault ["bank", 0]; private _cash = _account getOrDefault ["cash", 0]; if (_bank < _amount) exitWith { ["WARNING", "Insufficient Funds!"] call EFUNC(common,log); }; private _finalAccount = createHashMapFromArray [["bank", (_bank - _amount)], ["cash", (_cash + _amount)]]; private _player = [_uid] call EFUNC(common,getPlayer); GVAR(Registry) set [_uid, _finalAccount]; [CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent); [CRPC(notifications,recieveNotification), ["info", "Bank", format ["Withdrew $%1", _amount]], _player] call CFUNC(targetEvent); }], ["depositEarnings", compileFinal { params [["_uid", "", [""]], ["_amount", 0, [0]]]; ["INFO", format ["Deposit Earnings %1, for %2", _amount, _uid]] call EFUNC(common,log); private _account = GVAR(Registry) getOrDefault [_uid, nil]; if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); }; private _bank = _account getOrDefault ["bank", 0]; private _earnings = _account getOrDefault ["earnings", 0]; if (_earnings < _amount) exitWith { ["WARNING", "Insufficient Earnings!"] call EFUNC(common,log); }; private _finalAccount = createHashMapFromArray [["bank", (_bank + _amount)], ["earnings", (_earnings - _amount)]]; private _player = [_uid] call EFUNC(common,getPlayer); GVAR(Registry) set [_uid, _finalAccount]; [CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent); [CRPC(notifications,recieveNotification), ["info", "Bank", format ["Deposited $%1 from earnings", _amount]], _player] call CFUNC(targetEvent); }] ]; GVAR(BankStore) = createHashMapObject [GVAR(BankBaseStore)]; GVAR(BankStore)