diff --git a/arma/client/addons/actor/functions/fnc_handleUIEvents.sqf b/arma/client/addons/actor/functions/fnc_handleUIEvents.sqf index 64b30a3..cf26ae7 100644 --- a/arma/client/addons/actor/functions/fnc_handleUIEvents.sqf +++ b/arma/client/addons/actor/functions/fnc_handleUIEvents.sqf @@ -37,8 +37,22 @@ switch (_event) do { case "actor::open::bank": { [] spawn EFUNC(bank,openUI); }; case "actor::open::cad": { [] spawn EFUNC(cad,openUI); }; case "actor::open::device": { hint "Device interaction is not yet implemented."; }; - case "actor::open::garage": { [] spawn EFUNC(garage,openUI); }; - case "actor::open::vgarage": { [] spawn EFUNC(garage,openVG); }; + case "actor::open::garage": { + private _garageObject = objNull; + if (_data isEqualType createHashMap) then { + private _netId = _data getOrDefault ["netId", ""]; + if (_netId isNotEqualTo "") then { _garageObject = objectFromNetId _netId; }; + }; + [_garageObject] spawn EFUNC(garage,openUI); + }; + case "actor::open::vgarage": { + private _garageObject = objNull; + if (_data isEqualType createHashMap) then { + private _netId = _data getOrDefault ["netId", ""]; + if (_netId isNotEqualTo "") then { _garageObject = objectFromNetId _netId; }; + }; + [_garageObject] spawn EFUNC(garage,openVG); + }; case "actor::open::org": { [] spawn EFUNC(org,openUI); }; case "actor::open::vlocker": { [FORGE_Locker_Box, player, false] spawn AFUNC(arsenal,openBox) }; case "actor::open::phone": { [] spawn EFUNC(phone,openUI); }; diff --git a/arma/client/addons/actor/functions/fnc_initRepository.sqf b/arma/client/addons/actor/functions/fnc_initRepository.sqf index 3cbfb0e..9e1de3b 100644 --- a/arma/client/addons/actor/functions/fnc_initRepository.sqf +++ b/arma/client/addons/actor/functions/fnc_initRepository.sqf @@ -114,6 +114,11 @@ GVAR(ActorRepositoryBaseClass) = compileFinal createHashMapFromArray [ private _isLocker = _x getVariable ["isLocker", false]; private _isStore = _x getVariable ["isStore", false]; private _garageType = _x getVariable ["garageType", ""]; + private _garageContext = createHashMapFromArray [ + ["netId", netId _x], + ["name", vehicleVarName _x], + ["garageType", _garageType] + ]; private _deviceType = _x getVariable ["deviceType", ""]; private _isPlayer = _x isKindOf "Man" && isPlayer _x; @@ -121,8 +126,8 @@ GVAR(ActorRepositoryBaseClass) = compileFinal createHashMapFromArray [ if (_isAtm) then { _nearbyActions pushBack ["atm", true]; }; if (_isBank) then { _nearbyActions pushBack ["bank", true]; }; if (_isLocker && GVAR(enableVA)) then { _nearbyActions pushBack ["va", true]; }; - if (_isGarage) then { _nearbyActions pushBack ["garage", _garageType]; }; - if (_isGarage && GVAR(enableVG)) then { _nearbyActions pushBack ["vg", true]; }; + if (_isGarage) then { _nearbyActions pushBack ["garage", _garageContext]; }; + if (_isGarage && GVAR(enableVG)) then { _nearbyActions pushBack ["vg", _garageContext]; }; if (_deviceType isNotEqualTo "") then { _nearbyActions pushBack ["device", _deviceType]; }; if (_isPlayer && { _x isNotEqualTo player }) then { _nearbyActions pushBack ["player", name _x]; }; } forEach (player nearObjects 5); diff --git a/arma/client/addons/actor/ui/_site/script.js b/arma/client/addons/actor/ui/_site/script.js index 0a1c8a1..be33f4f 100644 --- a/arma/client/addons/actor/ui/_site/script.js +++ b/arma/client/addons/actor/ui/_site/script.js @@ -215,7 +215,21 @@ function actorReducer(state = initialState, action) { const [type, value] = actionItem; const definition = state.actionDefinitions[type]; if (definition) { - newMenuItems.push(definition); + const context = + value && typeof value === "object" + ? value + : { value }; + const garageLabel = + context.name || context.garageType || ""; + const title = + ["garage", "vg"].includes(type) && garageLabel + ? `${definition.title}: ${garageLabel}` + : definition.title; + newMenuItems.push({ + ...definition, + title, + context, + }); } else { console.warn( `No definition found for: ${type} - ${value}`, @@ -414,7 +428,7 @@ function RadialMenu() { console.log("Menu item clicked:", item); const alert = { event: item.action, - data: {}, + data: item.context || {}, }; if (typeof A3API !== "undefined") { A3API.SendAlert(JSON.stringify(alert)); diff --git a/arma/client/addons/garage/functions/fnc_initContextService.sqf b/arma/client/addons/garage/functions/fnc_initContextService.sqf index 1c156a7..345d979 100644 --- a/arma/client/addons/garage/functions/fnc_initContextService.sqf +++ b/arma/client/addons/garage/functions/fnc_initContextService.sqf @@ -22,8 +22,35 @@ #pragma hemtt ignore_variables ["_self"] GVAR(GarageContextServiceBaseClass) = compileFinal createHashMapFromArray [ ["#type", "GarageContextServiceBaseClass"], - ["#create", compileFinal { _self set ["lastContext", createHashMap]; }], - ["#delete", compileFinal { _self set ["lastContext", createHashMap]; }], + ["#create", compileFinal { + _self set ["lastContext", createHashMap]; + _self set ["activeGarageObject", objNull]; + }], + ["#delete", compileFinal { + _self set ["lastContext", createHashMap]; + _self set ["activeGarageObject", objNull]; + }], + ["setActiveGarageObject", compileFinal { + params [["_garageObject", objNull, [objNull]]]; + + if (isNull _garageObject || { !(_garageObject getVariable ["isGarage", false]) }) exitWith { + _self set ["activeGarageObject", objNull]; + false + }; + + _self set ["activeGarageObject", _garageObject]; + true + }], + ["getActiveGarageObject", compileFinal { + private _garageObject = _self getOrDefault ["activeGarageObject", objNull]; + if (isNull _garageObject || { !(_garageObject getVariable ["isGarage", false]) }) exitWith { objNull }; + if ((player distance2D _garageObject) > 12) exitWith { + _self set ["activeGarageObject", objNull]; + objNull + }; + + _garageObject + }], ["createDefaultContext", compileFinal { createHashMapFromArray [ ["name", "Vehicle Garage"], @@ -184,8 +211,16 @@ GVAR(GarageContextServiceBaseClass) = compileFinal createHashMapFromArray [ _spawnLanes getOrDefault [_normalizedCategory, createHashMap] }], ["resolveContext", compileFinal { + params [["_preferredGarageObject", objNull, [objNull]]]; + private _context = _self call ["createDefaultContext", []]; - private _garageObject = _self call ["findNearbyGarageObject", []]; + private _garageObject = _preferredGarageObject; + if (isNull _garageObject || { !(_garageObject getVariable ["isGarage", false]) }) then { + _garageObject = _self call ["getActiveGarageObject", []]; + }; + if (isNull _garageObject) then { + _garageObject = _self call ["findNearbyGarageObject", []]; + }; private _garageName = _self call ["resolveGarageName", [_garageObject]]; private _garageType = ""; private _anchorPosition = getPosATL player; @@ -215,7 +250,10 @@ GVAR(GarageContextServiceBaseClass) = compileFinal createHashMapFromArray [ _self set ["lastContext", _context]; _context }], - ["getContext", compileFinal { _self call ["resolveContext", []] }], + ["getContext", compileFinal { + params [["_preferredGarageObject", objNull, [objNull]]]; + _self call ["resolveContext", [_preferredGarageObject]] + }], ["buildNearbyState", compileFinal { private _context = _self call ["getContext", []]; private _anchorPosition = _context getOrDefault ["anchorPosition", []]; diff --git a/arma/client/addons/garage/functions/fnc_openUI.sqf b/arma/client/addons/garage/functions/fnc_openUI.sqf index 85e31bd..8c47906 100644 --- a/arma/client/addons/garage/functions/fnc_openUI.sqf +++ b/arma/client/addons/garage/functions/fnc_openUI.sqf @@ -20,6 +20,12 @@ * call forge_client_garage_fnc_openUI; */ +params [["_garageObject", objNull, [objNull]]]; + +if (!isNull _garageObject) then { + GVAR(GarageContextService) call ["setActiveGarageObject", [_garageObject]]; +}; + private _display = createDialog ["RscGarage", true]; private _ctrl = _display displayCtrl 1006; diff --git a/arma/client/addons/garage/functions/fnc_openVG.sqf b/arma/client/addons/garage/functions/fnc_openVG.sqf index 1d04905..4046b82 100644 --- a/arma/client/addons/garage/functions/fnc_openVG.sqf +++ b/arma/client/addons/garage/functions/fnc_openVG.sqf @@ -20,7 +20,13 @@ * call forge_client_garage_fnc_openVG */ -private _context = GVAR(GarageContextService) call ["getContext", []]; +params [["_garageObject", objNull, [objNull]]]; + +if (!isNull _garageObject) then { + GVAR(GarageContextService) call ["setActiveGarageObject", [_garageObject]]; +}; + +private _context = GVAR(GarageContextService) call ["getContext", [_garageObject]]; private _spawnLane = GVAR(GarageContextService) call ["getSpawnLane", [_context getOrDefault ["garageType", ""], _context]]; FORGE_VehSpawnPos = _spawnLane getOrDefault ["spawnPosition", player getPos [8, getDir player]]; diff --git a/docs/PLAYER_GUIDE.md b/docs/PLAYER_GUIDE.md index 9016ab4..ccfa656 100644 --- a/docs/PLAYER_GUIDE.md +++ b/docs/PLAYER_GUIDE.md @@ -76,7 +76,8 @@ Important task behavior: ## Phone -The phone provides contacts, messages, email, and local utility apps. +The phone provides contacts, messages, email, mobile bank access, and local +utility apps. ![Phone home screen](images/player/phone_home.jpg) @@ -90,29 +91,34 @@ entering recipient details every time. ### Messages -Messages are short player-to-player conversations. +Messages are short player-to-player conversations. Use Messages to start or +continue a conversation with a contact, read incoming messages, mark messages as +read, or delete messages you no longer need. ![Phone messages screen](images/player/phone_messages.jpg) -Use Messages to: - -- start or continue a conversation with a contact -- read incoming messages -- mark messages as read -- delete messages you no longer need +![Example phone message conversation](images/player/phone_message_example.jpg) ### Email -Email is used for longer player-to-player communication. +Email is used for longer player-to-player communication. Use Email to send a +subject and body to another player, read incoming mail, mark email as read, or +delete old email. ![Phone email screen](images/player/phone_email.jpg) -Use Email to: +![Example phone email](images/player/phone_email_example.jpg) -- send a subject and body to another player -- read incoming mail -- mark email as read -- delete old email +### Wallet + +Wallet is the phone version of the bank app. Use it to refresh your account +view, check your available balance, review cash and pending earnings, deposit all +pending earnings, and pay your organization credit line when payment is due. + +![Phone wallet app](images/player/phone_wallet.jpg) + +Deposit Earnings deposits the full pending earnings amount. Players do not enter +a custom amount for that action. ### Local Phone Apps diff --git a/docus/content/1.getting-started/5.player-guide.md b/docus/content/1.getting-started/5.player-guide.md index 0482541..cba668d 100644 --- a/docus/content/1.getting-started/5.player-guide.md +++ b/docus/content/1.getting-started/5.player-guide.md @@ -75,7 +75,8 @@ Important task behavior: ## Phone -The phone provides contacts, messages, email, and local utility apps. +The phone provides contacts, messages, email, mobile bank access, and local +utility apps. ![Phone home screen](images/player/phone_home.jpg) @@ -89,29 +90,34 @@ entering recipient details every time. ### Messages -Messages are short player-to-player conversations. +Messages are short player-to-player conversations. Use Messages to start or +continue a conversation with a contact, read incoming messages, mark messages as +read, or delete messages you no longer need. ![Phone messages screen](images/player/phone_messages.jpg) -Use Messages to: - -- start or continue a conversation with a contact -- read incoming messages -- mark messages as read -- delete messages you no longer need +![Example phone message conversation](images/player/phone_message_example.jpg) ### Email -Email is used for longer player-to-player communication. +Email is used for longer player-to-player communication. Use Email to send a +subject and body to another player, read incoming mail, mark email as read, or +delete old email. ![Phone email screen](images/player/phone_email.jpg) -Use Email to: +![Example phone email](images/player/phone_email_example.jpg) -- send a subject and body to another player -- read incoming mail -- mark email as read -- delete old email +### Wallet + +Wallet is the phone version of the bank app. Use it to refresh your account +view, check your available balance, review cash and pending earnings, deposit all +pending earnings, and pay your organization credit line when payment is due. + +![Phone wallet app](images/player/phone_wallet.jpg) + +Deposit Earnings deposits the full pending earnings amount. Players do not enter +a custom amount for that action. ### Local Phone Apps diff --git a/docus/public/images/player/phone_contacts.jpg b/docus/public/images/player/phone_contacts.jpg index cea4a26..5a16cdd 100644 Binary files a/docus/public/images/player/phone_contacts.jpg and b/docus/public/images/player/phone_contacts.jpg differ diff --git a/docus/public/images/player/phone_email.jpg b/docus/public/images/player/phone_email.jpg index b45fbba..15d90f9 100644 Binary files a/docus/public/images/player/phone_email.jpg and b/docus/public/images/player/phone_email.jpg differ diff --git a/docus/public/images/player/phone_email_example.jpg b/docus/public/images/player/phone_email_example.jpg new file mode 100644 index 0000000..2b85a58 Binary files /dev/null and b/docus/public/images/player/phone_email_example.jpg differ diff --git a/docus/public/images/player/phone_home.jpg b/docus/public/images/player/phone_home.jpg index a1038be..0017134 100644 Binary files a/docus/public/images/player/phone_home.jpg and b/docus/public/images/player/phone_home.jpg differ diff --git a/docus/public/images/player/phone_message_example.jpg b/docus/public/images/player/phone_message_example.jpg new file mode 100644 index 0000000..a700db0 Binary files /dev/null and b/docus/public/images/player/phone_message_example.jpg differ diff --git a/docus/public/images/player/phone_messages.jpg b/docus/public/images/player/phone_messages.jpg index 91b155d..e79ad37 100644 Binary files a/docus/public/images/player/phone_messages.jpg and b/docus/public/images/player/phone_messages.jpg differ diff --git a/docus/public/images/player/phone_wallet.jpg b/docus/public/images/player/phone_wallet.jpg new file mode 100644 index 0000000..a9290bb Binary files /dev/null and b/docus/public/images/player/phone_wallet.jpg differ