Dev Log: 2026-06-19¶
Stage Editor and Sandbox (Chapter 0)¶
Stage Editor¶
A full in-game stage editor shipped this cycle. Players can design, edit, and play custom stages without leaving the game.
Architecture:
- stage_editor.gd (2208 lines): grid-based editor with terrain painting, unit/drone placement, prop placement, sector navigation, undo/redo, and save/load
- editor_hud.gd (349 lines): toolbar with category buttons (terrain, units, drones, props, theme, sector, objective, settings), action buttons (save, play, undo, redo, reset), and status strip
- sandbox_stage_modal.gd (80 lines): modal dialog for sandbox stages with Edit/Play buttons and unsaved-changes indicator
Features:
- 16×7 grid with 8 terrain types (grass, water, road, forest, mountain, ruins, beach, bridge)
- Unit placement (Katyusha, Nadeshiko, Maria) with drag-to-position
- Drone placement from 14 drone types including AG/AA variants
- Prop and skin picker with search
- Multi-sector support with sector navigation
- field_repair_limit exposed in stage settings
- Worldmap preview updates on save
- Godot-generated thumbnails replace manual ones
- Android back button handling for editor exit
- Unsaved-changes dot on worldmap tiles
Integration:
- World map right-click on sandbox stages opens SandboxStageModal (Edit/Play)
- main.gd:_launch_editor(stage_num) creates StageEditor instance
- Editor saves to user://stages/ch00/stage_NN_temp.json (unsaved) or data/stages/ch00/stage_NN.json (committed)
Sandbox Chapter (Chapter 0)¶
Chapter 0 is the sandbox mode: 10 empty stages players can customize freely.
Structure:
- chapter_00.json: 3×3 grid with showdown at stage 10
- data/stages/ch00/stage_01.json through stage_10.json: minimal starter stages (grass + water, 3 units, 1 guard tower)
- scripts/stages/ch00/stage_02.gd through stage_10.gd: stage hooks
Workflow: 1. Player selects a sandbox stage on the world map 2. Right-click opens SandboxStageModal (Edit or Play) 3. Edit launches the StageEditor with the stage loaded 4. Play launches the stage directly (auto-saves if unsaved changes exist) 5. Unsaved changes show an orange dot on the worldmap tile
Translation keys: TITLE_SANDBOX, BTN_SANDBOX_EDIT, BTN_SANDBOX_PLAY, LBL_SANDBOX_UNSAVED, plus save/exit confirmation dialogs
Google Play Services Integration¶
GodotPlayGameServices Plugin¶
Installed the GodotPlayGameServices plugin (v3.2.0) for Android builds. The plugin handles sign-in, achievement unlocks, and leaderboard access through Google Play Game Services.
Setup:
- Plugin binary: addons/GodotPlayGameServices/bin/release/GodotPlayGameServices-release.aar (79 KB)
- Export plugin automatically injects the Game Services Application ID (628094807607) into the Android manifest via @string/game_services_project_id
- android/build/res/values/strings.xml provides the project ID resource
- android/build/src/main/AndroidManifest.xml declares isGame="true" and appCategory="games"
play_games_manager.gd (rewritten):
- Auto sign-in on _ready() via GodotPlayGameServices.initialize() and plugin.isAuthenticated()
- unlock_achievement(play_id) queues unlocks that fire before the player has signed in
- Queue flushes on _on_user_authenticated(true) to handle offline-first play
- signed_in_changed signal for UI binding
Achievement unlock flow:
1. Game calls PlayGamesManager.unlock_achievement(play_id)
2. If signed in, unlock fires immediately via plugin.unlockAchievement(play_id)
3. If not signed in, play_id is queued
4. On sign-in, queued unlocks flush
Play Console Achievements¶
85 achievements uploaded to Google Play Console via ZIP bulk import (play_ach_icon_zip.py). The tool generates a ZIP with CSV manifest + 140×140 PNG icons for each achievement.
Removed: play_ach_upload.py and Google API code. The Publishing API has deal-breakers:
- Image upload endpoint deprecated (returns 503)
- Partial updates (PUT with incomplete body) return 404
- OAuth desktop flow required (org policy blocks service account key creation)
ZIP bulk import works reliably and keeps the tool simple.
Play Console IAP Product¶
Registered full_game SKU in Play Console:
- Type: Non-consumable
- Price: $4.99 USD
- Description: "Unlock all 6 chapters (60 stages). Chapter 1 is free; chapters 2-6 require purchase."
Product ID wired through project.godot [billing] section → PremiumBilling → PremiumAccess.
Payment Gate (Re-enabled)¶
premium_access.gd gate re-enabled for release builds:
- play_store_gate_active() returns true only on Android release builds (not demo, not editor)
- should_block_entering_chapter(2+) checks GameManager.full_game_owned
- Clearing Chapter 1 no longer auto-advances on gated builds; players tap NEXT CHAPTER, complete billing sheet
Buy Full Game Page¶
New options menu page (options_menu.gd:_build_buy_page()) with platform-aware sub-menu:
| Platform | Buy Now | Restore | Support |
|---|---|---|---|
| Android | Play Billing flow | PANZER-PLAY key dialog | |
| Web/Other | itch.io purchase link | PANZER-ISLAND key dialog |
Play Key Gate (play_key_gate.gd):
- Validates PANZER-PLAY-XXXX-XXXX format keys via SHA-256 hash
- Rejects web keys (PANZER-ISLAND prefix)
- Only active on Android release builds
Web Supporter Gate (supporter_gate.gd):
- Existing PANZER-ISLAND key validation for web/itch.io builds
Sandbox Testing¶
The payment gate is designed for closed-track testing:
- License testers in Play Console can purchase without charging
- Non-consumed acknowledgements (acknowledgePurchase) required by Billing Library rules
- Demo builds bypass the gate entirely (BuildConfig.is_demo)
- Editor builds bypass the gate (for development)
- Desktop release builds stay fully unlocked (no IAP)
Chapter 6: "What Do We Do Now?"¶
Chapter 6 shipped. The final chapter brings the ORACLE confrontation to a close.
Field Repair System¶
New mechanic: field_repair_limit per stage.
stage.jsongainsfield_repair_limit(int, default 0)stage_controller.gdtracks remaining repairs per layergame_manager.gdmanages repair inventory- Players can repair damaged units mid-stage, adding tactical flexibility
The solver's greedy planner (priorities.py) was extended with field-repair priority logic (159 lines). All solver carry states (ch01-ch06) were regenerated to account for the new mechanic.
Ch06 stage 10 was rebalanced around field repairs to be solvable.
Sector Rework¶
Ch06 received a sector rework (S10 boss stage in particular) to improve flow and difficulty曲线.
Themes and Visuals¶
New terrain themes for ch06 with custom backdrops. Mountain terrain sprites redesigned with stepped peaks and pillar shapes for better readability against building props.
Credits System Rework¶
Credits system rewritten to support per-chapter credit rolls:
credits.jsonreplaced with per-language files:credits.en.json,credits.ja.json,credits.de.jsoncredits_loader.gdrewritten to handle chapter-specific credits- Removed old
credits_ch02.jsonin favor of the new per-language structure - Tests expanded from basic load to full chapter-credit validation (246 lines)
Translations Catchup¶
JA/DE Stage Overlays¶
40 new overlay files created for ch05 and ch06:
- data/stages/ch05/ja/stage_01.json through stage_10.json
- data/stages/ch05/de/stage_01.json through stage_10.json
- data/stages/ch06/ja/stage_01.json through stage_10.json
- data/stages/ch06/de/stage_01.json through stage_10.json
Each overlay translates name, objective_text, world_map_objective, layers[].sector_name, and layers[].tutorial_text.
Translation Keys¶
7 new keys added to strings.csv for the Buy Full Game page:
- BTN_BUY_FULL_GAME, BTN_BUY_NOW, BTN_RESTORE_PURCHASE, BTN_CONNECT_SUPPORT
- LBL_BUY_FULL_GAME_INFO, LBL_PLAY_KEY_GATE_BODY, MSG_PLAY_KEY_INVALID
Steam Store Copy¶
Updated storepage_1191484_all.json (EN/DE/JA):
- "Chapters 1-3 (30 stages)" → "Chapters 1-6 (60 stages)"
- Fixed stale "1-3" reference in DE short description
- Mac min OS corrected from "macOS 10.15 Catalina" to "macOS 11.0 Big Sur"
Steam Patch Notes¶
patchnote_v0.1.4.47.csv written in EN/DE/JA with BBCode formatting. Ready for Steamworks upload.
Bug Fixes¶
- Nexus summon level:
nexus_summonnow uses default drone level instead of incorrectly inherited level - Game freeze on sector transition: Infinite loop in
stage_controller.gdduring layer transitions under specific drone alert-state conditions - Cutscene skip button: Landing cutscene skip not functional on first launch
- DE achievement names: Fixed duplicates ("Vernichter" → "Auslöschung" for Annihilator, "Entfesselt" → "Ungebändigt" for Unleashed)
- JA tutorial text: Mixed Chinese/Japanese characters in ch05 stage 01 fixed
- DE sector name length: Ch06 stage 10 "DIE ENTSCHEIDUNGSSCHLACHT" (25 chars) shortened to "ENTSCHEIDUNGSSCHLACHT" (21 chars) per styleguide limit
Minor¶
- Font updated (
NotoSansJP-game.ttf) gitignoreupdated for Play Games Services pluginCLAUDE.mdupdated with parity table and translation workflow- Ch1 immersion polish pass
publishing.mdupdated with IAP description, billing docs, and chapter counts- 619 tests pass, check.sh clean