feat(client): sprint 38 — free camera viewer, archetype strip, test fixes
- Add free camera mode (F4 toggle): WASD pan, scroll zoom, decoupled from player position (#898) - Strip archetype-driven code: remove character_archetype, lattice_profile, and lattice color palettes from client (#882) - Fix confrontation_monologue signal not firing in headless test mode (#867) - Revive fog state behavioral tests: EXP_EXPLORED persistence, grow-only bounds, texture-resize copy, BoundaryWall handling (#879) - Triage pre-existing test failures: fix examine_display dismiss timing, fog test position fragility, rendering snapshot assertions, time_display format (#871) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,11 +41,6 @@ var nearby_interactions: Array = [] # [{entity_id, entity_type, distance, verbs
|
||||
# v5 fields (#414)
|
||||
var current_monologue: Variant = null # {id, text, duration_seconds, priority, is_urgent} or null
|
||||
|
||||
# #122 (D-032): Character lattice profile — selects monologue text colour palette.
|
||||
# "lattice_augmented" = detective, "lattice_baseline" = smuggler.
|
||||
# Server sends this field as part of the player's capability snapshot.
|
||||
var lattice_profile: String = "lattice_baseline"
|
||||
|
||||
# v6 fields (#449, D-053, D-065)
|
||||
var player_stance: String = "Walk" # Sprint/Walk/Careful/Crouch
|
||||
var player_inventory: Array = [] # [{item_id, name, slot}]
|
||||
@@ -94,10 +89,8 @@ var debug_response: Variant = null
|
||||
# Format: user://saves/<game-id>/<filename>.sav or "" if no pending load.
|
||||
var pending_load_path: String = ""
|
||||
|
||||
# #588: Character archetype chosen at character select screen.
|
||||
# "detective" or "smuggler". Set before game scene loads; sent in StartupMessage.
|
||||
# Default: "detective" — fallback for legacy saves without character.txt.
|
||||
var character_archetype: String = "detective"
|
||||
# #898: Free camera mode — camera decoupled from player, WASD pans camera directly.
|
||||
var free_camera_mode: bool = false
|
||||
|
||||
# #705: Character visual descriptor — set by character_creation.gd on confirmation.
|
||||
# Passed to EntityRenderer for the player entity's CharacterVisual on game start.
|
||||
|
||||
@@ -68,7 +68,7 @@ func _process(_delta: float) -> void:
|
||||
# D-054: Update facing angle from mouse position every frame
|
||||
_update_facing_from_mouse()
|
||||
|
||||
if GameState.dialogue_active:
|
||||
if GameState.dialogue_active or GameState.free_camera_mode:
|
||||
return
|
||||
|
||||
# D-054: Send facing octant to server when it changes (even without movement)
|
||||
|
||||
@@ -55,12 +55,11 @@ func new_game() -> String:
|
||||
|
||||
|
||||
## Resume an existing game session by setting the active game-id.
|
||||
## Restores world_seed and character_archetype from the save directory.
|
||||
## Restores world_seed from the save directory.
|
||||
func resume_game(game_id: String) -> void:
|
||||
GameState.current_game_id = game_id
|
||||
var save_path := SAVES_DIR + game_id + "/"
|
||||
GameState.world_seed = _read_seed_file(save_path)
|
||||
GameState.character_archetype = _read_archetype_file(save_path)
|
||||
|
||||
|
||||
## List all game directories under user://saves/ sorted by last-modified (most recent first).
|
||||
@@ -171,29 +170,6 @@ func _read_seed_file(save_path: String) -> int:
|
||||
return file.get_64() & 0x7FFFFFFFFFFFFFFF
|
||||
|
||||
|
||||
## Write character_archetype to save directory. Called after new_game() creates the dir.
|
||||
func save_character_archetype(game_id: String, archetype: String) -> void:
|
||||
var save_path := SAVES_DIR + game_id + "/"
|
||||
var file := FileAccess.open(save_path + "character.txt", FileAccess.WRITE)
|
||||
if file == null:
|
||||
push_error(
|
||||
(
|
||||
"SessionManager: failed to write character.txt: %s"
|
||||
% error_string(FileAccess.get_open_error())
|
||||
)
|
||||
)
|
||||
return
|
||||
file.store_string(archetype)
|
||||
|
||||
|
||||
## Read character_archetype from save directory. Returns "detective" if missing (legacy saves).
|
||||
func _read_archetype_file(save_path: String) -> String:
|
||||
var file := FileAccess.open(save_path + "character.txt", FileAccess.READ)
|
||||
if file == null:
|
||||
return "detective"
|
||||
return file.get_as_text().strip_edges()
|
||||
|
||||
|
||||
func _find_newest_save(dir_path: String) -> String:
|
||||
var dir := DirAccess.open(dir_path)
|
||||
if dir == null:
|
||||
|
||||
@@ -261,7 +261,6 @@ func _process(delta: float) -> void: # gdlint:disable=max-returns
|
||||
# Server blocks waiting for this before entering the tick loop.
|
||||
var startup_bytes := Protocol.encode_startup_message(
|
||||
GameState.world_seed,
|
||||
GameState.character_archetype,
|
||||
GameState.character_visual_descriptor
|
||||
)
|
||||
if startup_bytes.size() > 0:
|
||||
|
||||
Reference in New Issue
Block a user