ENH - allow movement while phone is open

Add Config.Phone.AllowMovement and route it through the central focus resolver. Keep camera and attention overlays authoritative over movement input, document the setting, and cover the focus-state combinations.
This commit is contained in:
Leon.Schmidt
2026-08-15 22:17:41 +02:00
parent acb71375ec
commit 9afafe4a27
5 changed files with 34 additions and 2 deletions
+1 -1
View File
@@ -106,7 +106,7 @@ set sky_phone_fliptok_password_pepper "replace-with-a-long-random-secret"
Passwords are stored as salted hashes. The pepper is read server-side from the convar and is never
included in the NUI bundle.
Standalone FiveM phone built with Vue 3, TypeScript, Pinia, Vue Router, the Sky-owned FiveM UI system, and Tailwind CSS 4. Konsta UI remains only for screens that have not yet completed their migration. The phone opens through the usable item; `/phone` is disabled unless `Config.Phone.DevelopmentCommand` is enabled explicitly. Phone identity and SIM-card behavior are selected independently through `Config.Phone.Unique` and `Config.Sim.Enabled`.
Standalone FiveM phone built with Vue 3, TypeScript, Pinia, Vue Router, the Sky-owned FiveM UI system, and Tailwind CSS 4. Konsta UI remains only for screens that have not yet completed their migration. The phone opens through the usable item; `/phone` is disabled unless `Config.Phone.DevelopmentCommand` is enabled explicitly. `Config.Phone.AllowMovement` controls whether game input remains active while the mobile phone is open. Phone identity and SIM-card behavior are selected independently through `Config.Phone.Unique` and `Config.Sim.Enabled`.
### Ingame test data
+1
View File
@@ -16,6 +16,7 @@ Config.Command = "phone"
Config.Phone = {
Item = "phone",
Unique = true, -- true: data follows each phone item; false: one persistent phone per character
AllowMovement = true, -- true: game input stays active while the mobile phone is open
DevelopmentCommand = true,
DeviceName = "iFruit Phone",
}
+1 -1
View File
@@ -16,6 +16,6 @@ function SkyPhoneFocus.Resolve(state)
or state.payphone_focus
or state.sim_picker_open
or (state.camera_active and state.camera_nui_focused),
keep_input = false,
keep_input = state.is_open and state.allow_movement and not state.camera_active,
}
end
+1
View File
@@ -292,6 +292,7 @@ end
local function update_nui_focus()
local focus = SkyPhoneFocus.Resolve({
activity_suspended = activity_suspended,
allow_movement = Config.Phone.AllowMovement,
call_focus = call_focus,
camera_active = camera_active,
camera_nui_focused = camera_nui_focused,
+30
View File
@@ -3,6 +3,7 @@ dofile("sky_phone/source/client/focus.lua")
local function resolve(overrides)
local state = {
activity_suspended = false,
allow_movement = false,
call_focus = false,
camera_active = false,
camera_nui_focused = true,
@@ -26,6 +27,24 @@ assert(not minimized_call.focused, "a replayed call without an attention claim m
local incoming_call = resolve({ call_focus = true })
assert(incoming_call.focused and not incoming_call.keep_input, "incoming call attention must focus the NUI")
local stationary_phone = resolve({ is_open = true })
assert(
stationary_phone.focused and not stationary_phone.keep_input,
"an open phone must block game input when movement is disabled"
)
local movable_phone = resolve({ allow_movement = true, is_open = true })
assert(
movable_phone.focused and movable_phone.keep_input,
"an open phone must keep game input when movement is enabled"
)
local movable_notification = resolve({ allow_movement = true, notification_focus = true })
assert(
movable_notification.focused and not movable_notification.keep_input,
"movement configuration must not affect a notification without an open phone"
)
local camera_game_input = resolve({
camera_active = true,
camera_nui_focused = false,
@@ -36,6 +55,17 @@ assert(
"unfocused camera must own game input over the open phone"
)
local focused_camera = resolve({
allow_movement = true,
camera_active = true,
camera_nui_focused = true,
is_open = true,
})
assert(
focused_camera.focused and not focused_camera.keep_input,
"focused camera must override movement configuration until Space releases NUI focus"
)
local camera_interrupted_by_call = resolve({
call_focus = true,
camera_active = true,