147 lines
11 KiB
Markdown
147 lines
11 KiB
Markdown
# Candy Survival: Complete Implementation & Architecture Log
|
|
|
|
This document serves as an exhaustive, technical record of all modifications, refactors, and features implemented during the transition from the legacy "Gauntlet" mode to the new "Candy Survival" mode.
|
|
|
|
---
|
|
|
|
## 1. Project-Wide Renaming & Metadata Scrubbing
|
|
- **Global Find & Replace**: Executed across `scripts/`, `scenes/`, `tests/`, and `addons/`.
|
|
- Replaced `GAUNTLET`, `GauntletManager`, `gauntlet_manager`, and `is_gauntlet_mode()`.
|
|
- Replaced UI and enum display strings `"Gauntlet Arena"` → `"Candy Survival Arena"`.
|
|
- **File System Refactoring**:
|
|
- `git mv scripts/managers/gauntlet_manager.gd scripts/managers/candy_survival_manager.gd`
|
|
- `git mv scripts/controllers/candy_cannon_controller.gd scripts/controllers/candy_survival_npc_controller.gd`
|
|
- `git mv scenes/candy_cannon.tscn scenes/candy_survival_npc.tscn`
|
|
- `git mv scenes/gauntlet_hud.tscn scenes/candy_survival_hud.tscn`
|
|
- `git mv scenes/arena/gauntlet.tscn scenes/arena/candy_survival.tscn`
|
|
- **Asset Scrubbing (`assets/models/arena/candy_survival/`)**:
|
|
- Renamed the directory and all interior files (e.g., `Gauntlet terrain.gltf` → `candy_survival_terrain.gltf`).
|
|
- Purged buried metadata: Modified `.import` and `.gltf` text structures to remove cached `"res://assets/models/arena/gauntlet/..."` paths to prevent headless Godot build corruption.
|
|
- Updated legacy entries in `version.json` for historical consistency.
|
|
|
|
---
|
|
|
|
## 2. Arena Layout & Sticky Collision Overhaul
|
|
- **Grid Properties**: Enforced strict `18x18` playable bounds via `_setup_arena()`.
|
|
- **Sticky Mechanics Rewritten**:
|
|
- *Legacy*: Sticky cells grew dynamically, gave telegraph warnings, and trapped players requiring a "cleanser".
|
|
- *New*: `TILE_STICKY` now acts exclusively as static, pure-collision boundary walls. Placed solely on the arena perimeter and the center 3x3 NPC zone to block entry.
|
|
- Movement check in `player_movement_manager.gd` strictly evaluates `if gm.is_sticky_cell(grid_position)` and rejects the move outright unless the player possesses the `is_invisible` (Ghost) buff.
|
|
- **Spawn Point Correction**: Shifted `get_spawn_points()` coordinates from `row 1` to `row 2` and `row 15` to `row 16` (`(2,2), (16,2), (2,16), (16,16)`) to prevent players from spawning inside stairs/geometry.
|
|
|
|
---
|
|
|
|
## 3. Mekton NPC (Center Boss Entity)
|
|
- **Mesh Replacement**: Scrapped the primitive Cylinder/Sphere tank meshes in `candy_survival_npc.tscn`. Instanced `static_tekton_mesh.tscn` as the visual representation.
|
|
- **Face Color Cycling**:
|
|
- Engineered `set_face_color_rpc(color_index: int)` inside `candy_survival_npc_controller.gd`.
|
|
- Dynamically extracts the surface material from the `ted_body` skeleton node.
|
|
- Duplicates the material at runtime and applies emission glow and albedo tints corresponding to the `CandyColor` enum (0: Heart/Red, 1: Diamond/Blue, 2: Star/Yellow, 3: Coin/Orange).
|
|
- **Manager Authority**: `candy_survival_manager.gd` tracks `face_timer`. Every 5.0 seconds (`COLOR_CYCLE_TIME`), it increments `current_face = CandyColor.values()[(current_face + 1) % CandyColor.size()]` and fires the RPC to visually sync the Mekton across all clients.
|
|
|
|
---
|
|
|
|
## 4. Gameplay Loop: Blueprints & Stacks
|
|
- **Auto-Pickup Integration**:
|
|
- Hooked into `player_movement_manager.gd` -> `_on_movement_finished()`.
|
|
- If `LobbyManager.game_mode == "Candy Survival"`, automatically calls `player.grab_item(player.current_position)` when stepping on a tile, assuming the `playerboard_manager` has an empty slot. Completely removes the need for manual button presses during high-speed building.
|
|
- **3x3 Blueprint Detection Engine**:
|
|
- Overhauled `_check_goal_completion()` in `playerboard_manager.gd`.
|
|
- Scans the 5x5 player board for *any* contiguous, fully-populated 3x3 block.
|
|
- Calculates the majority color (`primary_color`) within that block.
|
|
- **Off-Color Validation**:
|
|
- If the 3x3 block is mixed (off-color), it queries the global `gridmap` via `CandySurvivalManager._grid_has_color_tiles(primary_tile_id)`.
|
|
- If the primary color is mathematically extinct on the physical arena floor, the blueprint is accepted for 50% points. Otherwise, it is rejected.
|
|
- **Stacking Mechanics & Multipliers**:
|
|
- `on_blueprint_completed` invokes `_give_candy(pid, color)`.
|
|
- Tracks `player_candies` (height) and `player_candy_color`.
|
|
- Multiplier scales dynamically: `1.0 + (Stack Count * MULTI_STEP [0.1])`. Generates continuous passive points per second evaluated in `_process`.
|
|
|
|
---
|
|
|
|
## 5. Gameplay Loop: Delivery & Sugar Rush
|
|
- **Proximity Delivery Trigger**:
|
|
- Built into `player_movement_manager.gd`. During movement, it evaluates Manhattan distance to the center NPC (`abs(x - 8) + abs(y - 8)`).
|
|
- If distance is `<= 2`, the client fires `gm.try_deliver(pid)` via RPC to the server.
|
|
- **Face Matching Logic**:
|
|
- Server evaluates `if player_candy_color == current_face`.
|
|
- Rejects if the player has 0 candies or colors mismatch.
|
|
- **Sugar Rush Global Event**:
|
|
- Successful delivery adds to `player_sugar_rush[pid]` with the formula: `SR_BASE_TIME [2.0s] + (candies * SR_PER_CANDY [0.4s])`.
|
|
- While *any* player's rush timer is `> 0`, the manager forces `Engine.time_scale = SR_SPEED [2.0]`. When all timers reach 0, it restores to `1.0`.
|
|
|
|
---
|
|
|
|
## 6. Sabotage: Knock & Ghost Dynamics
|
|
- **Knock (Steal/Backfire)**:
|
|
- Input bound natively to `action_knock_tekton` inside `player_input_manager.gd`.
|
|
- Fires `try_knock(attacker, target)` when adjacent to an opponent.
|
|
- Consumes 1 of 5 starting charges (`player_knocks`).
|
|
- *Steal*: If target has candies, attacker adopts target's full stack and color; target is zeroed.
|
|
- *Backfire*: If target has 0 candies, attacker loses a charge and both suffer the knock animation state (handled by caller).
|
|
- **Ghost (Phase-Through)**:
|
|
- Input bound natively to `action_grab_tekton` inside `player_input_manager.gd` (bypasses default grab behavior in this mode).
|
|
- Consumes 1 of 5 starting charges (`player_ghosts`).
|
|
- `try_activate_ghost` sets the core `player.is_invisible = true` and `sync_modulate(Color(1, 1, 1, 0.4))` for 4.0 seconds.
|
|
- The `is_invisible` state natively bypasses the sticky collision checks, allowing phase-through of boundaries/boss zones, and renders the player immune to incoming Knocks.
|
|
|
|
---
|
|
|
|
## 7. Visuals, UI & 3D Stacking
|
|
- **HUD De-Scripting**:
|
|
- Legacy `gauntlet_manager` instantiated UI elements via GDScript. This was purged.
|
|
- Created `candy_survival_hud.tscn` using pure Godot Control nodes (VBoxContainer, HBoxContainer, ProgressBar, Label). Exposes all UI to artists for layout/theme modifications without code risk.
|
|
- Manager simply grabs node references (`hud_rush_bar`, `hud_stack_badge`, etc.) on `_ready()`.
|
|
- **Dynamic Delivery Indicator**:
|
|
- `sync_candy_badge` RPC was expanded to include a `face_match` boolean.
|
|
- When the Mekton's face color changes (every 5s), the server force-updates all clients.
|
|
- The HUD dynamically shifts `DeliveryIndicator.text` to a Green `"READY TO DELIVER!"` or Red `"Waiting for match..."` based on their currently held candy stack.
|
|
- **Physical 3D Candy Stacking**:
|
|
- Implemented `sync_candy_stack(count, color_id)` directly on `player.gd`.
|
|
- Creates a generic `Node3D` on the player's `Visuals` node.
|
|
- Instantiates raw `MeshInstance3D` tiles (`tile_heart.tres`, `tile_diamond.tres`, etc.).
|
|
- Visually stacks them vertically (`y = i * 0.4`) and scales them down (`0.5x`) corresponding exactly to the player's internal candy count. Clears them instantly upon delivery or being knocked.
|
|
|
|
---
|
|
|
|
## 8. AI & Bot Behaviors
|
|
- **Delivery Pathfinding (Priority 0.7)**:
|
|
- Injected specialized logic into `bot_controller.gd`.
|
|
- Bots actively check their held `player_candy_color` against the manager's `current_face`.
|
|
- When colors match, the Bot halts blueprint construction and immediately uses `find_path` targeting `Vector2i(8,8)` to execute a delivery and trigger Sugar Rush.
|
|
- **Ghost Survival Logic**:
|
|
- Re-wrote `_bot_has_ghost_powerup()` in `bot_strategic_planner.gd` to evaluate the new native `player_ghosts` charge counter instead of the legacy `SpecialTilesManager` inventory.
|
|
- Bots correctly evaluate proximity to sticky walls and automatically fire `try_activate_ghost` when cornered to phase out of traps.
|
|
|
|
---
|
|
|
|
## 9. Code Health & QA
|
|
- **Orphan Code Purge**: Deleted 8 specific `test_gauntlet_*.gd` files that referenced non-existent legacy mechanics (growth algorithms, bubbles, floor highlights, old cleansers).
|
|
- **Compile Integrity**: Fixed a trailing `_on_doors_update()` call in `lobby_room.gd` leftover from a different branch. Verified flawless compilation via `godot --headless --build-solutions`.
|
|
- **Gitea Documentation**: Automated the closure and deep-technical documentation of Issues #54, 55, 56, 57, 65, 66, 67, 68, 69, and 70 directly to the tracking server.
|
|
- **Wiki Accuracy**: Overhauled `Game-Modes.-.md` to perfectly mirror the new Sabotage input maps, Blueprint rules, RPC structures, and Mekton behavior.
|
|
|
|
### Completed (July 6, 2026)
|
|
- [x] **CI Pipeline Fixes**
|
|
- [x] Downgraded Godot runner version to 4.6.3 to match local engine build.
|
|
- [x] Updated Gitea API and Git clone URLs to use `https://` instead of `http://` to prevent silent redirect failures during release.
|
|
- [x] **Runtime & Compilation Crash Fixes**
|
|
- [x] Fixed `bot_controller.gd`: Replaced dead `_execute_move()` with proper `enhanced_gridmap.find_path()` logic.
|
|
- [x] Fixed `bot_controller.gd` & `player_movement_manager.gd`: Changed `.is_active` to `.active` for CandySurvivalManager checks.
|
|
- [x] Fixed `candy_survival_manager.gd`: Merged duplicate `start_game_mode()` implementations.
|
|
- [x] Fixed `special_tiles_manager.gd` indentation errors.
|
|
- [x] Fixed `main.gd` duplicate variable declarations.
|
|
- [x] **Editor & Test Environment Fixes**
|
|
- [x] Resolved "Cyclic Reference" errors in `leaderboard_panel.gd` by accessing Nakama session via `get()`.
|
|
- [x] Fixed `BackendService.gd` Autoload dependencies failing in isolated tests by using `get_node_or_null()`.
|
|
- [x] **Gacha System Fixes**
|
|
- [x] Corrected `BackendService.gd` payload to send `"banner_id"` instead of `"gacha_id"`, fixing HTTP 500 errors on pull.
|
|
- [x] Configured Unique Names (`%`) for left-side BalanceRow labels in `gacha_panel.tscn` so currency updates instantly upon rolling.
|
|
- [x] **3D Arena & GridMap Elevation Fixes**
|
|
- [x] Normalized root node transforms of all arenas (`freemode.tscn`, `stop_n_go.scn`, `candy_survival.tscn`) to `(0,0,0)` and scale `(1,1,1)`.
|
|
- [x] Removed hardcoded terrain shifts and `0.08` mesh elevations from `main.gd`.
|
|
- [x] Added `EditorTileReference` to arena scenes as a perfect 1:1 footprint guide.
|
|
- [x] Baked terrain height shifts directly into `.tscn` files to match the reference tile perfectly.
|
|
- [x] Scaled red `non-walkable` blocks (Tile 4) to 0 so they act as invisible collision walls in 3D arenas.
|
|
- [x] Fixed Stop N Go safe zone clipping by adjusting render priorities (`1` for safe zone, `-1` for baked terrain shadows).
|