feat(client): add gauntlet room timer + personal bests (#496)
GauntletHUD in UILayer shows TIMER: MM:SS (PB: MM:SS). Timer starts on room entry, resets on room change, records personal bests to user://gauntlet-stats.json. Session summary printed on disconnect. Hidden in non-gauntlet mode (anti-tedium guard). Adds room_id and gauntlet_mode fields to GameState, parsed from ObserverSnapshot. Main.gd wires update_from_state() and finalize(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,8 @@ extends Node2D
|
||||
@onready var inventory_grid = $UILayer/InventoryGrid # D-065: z-layer 7
|
||||
@onready var stance_indicator = $UILayer/StanceIndicator # D-053: z-layer 7
|
||||
@onready var cursor_renderer = $UILayer/CursorRenderer # D-056: z-layer 7
|
||||
@onready var gauntlet_hud = $UILayer/GauntletHUD # #496: room timer + personal bests
|
||||
@onready var bug_report_dialog = $ModalLayer/BugReportDialog # #495: F12 WRONG button
|
||||
|
||||
var _last_dialogue_npc_id: int = -1 # D-064: NPC entity_id for WalkAway input
|
||||
var _camera_anchored: bool = false
|
||||
@@ -49,6 +51,10 @@ func _ready() -> void:
|
||||
dialogue_box.dialogue_dismissed.connect(_on_dialogue_dismissed)
|
||||
dialogue_box.confrontation_monologue.connect(_on_confrontation_monologue)
|
||||
|
||||
# #496: Print gauntlet session summary on disconnect
|
||||
if gauntlet_hud:
|
||||
SimBridge.connection_state_changed.connect(_on_connection_state_changed)
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
# Main game loop: poll snapshot, apply state, flush input
|
||||
@@ -88,6 +94,10 @@ func _process(_delta: float) -> void:
|
||||
if fog_entities and fog_entities.has_method("update_from_state"):
|
||||
fog_entities.update_from_state()
|
||||
|
||||
# #496: Update gauntlet HUD (room timer + personal bests)
|
||||
if gauntlet_hud and gauntlet_hud.has_method("update_from_state"):
|
||||
gauntlet_hud.update_from_state()
|
||||
|
||||
# Show monologue if server sent one this tick (#414)
|
||||
_consume_monologue()
|
||||
|
||||
@@ -109,6 +119,11 @@ func _process(_delta: float) -> void:
|
||||
# Send queued input to simulation
|
||||
var inputs = InputMapper.flush_queue()
|
||||
for input in inputs:
|
||||
# #495: F12 WRONG button — client-only, trigger bug report capture
|
||||
if input.action == InputMapper.Action.BUG_REPORT:
|
||||
if bug_report_dialog and not bug_report_dialog.is_active():
|
||||
bug_report_dialog.start_capture()
|
||||
continue
|
||||
if input.action == InputMapper.Action.INTERACT:
|
||||
# D-057: prefer interaction list (multi-verb), fall back to prompt (v0.1)
|
||||
var target_id: int = -1
|
||||
@@ -197,3 +212,9 @@ func _on_dialogue_dismissed() -> void:
|
||||
"verb": "WalkAway",
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
# #496: Finalize gauntlet stats on disconnect
|
||||
func _on_connection_state_changed(old_state: SimBridge.ConnectionState, new_state: SimBridge.ConnectionState) -> void:
|
||||
if new_state == SimBridge.ConnectionState.DISCONNECTED and gauntlet_hud:
|
||||
gauntlet_hud.finalize()
|
||||
|
||||
Reference in New Issue
Block a user