Skip to content

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 → PremiumBillingPremiumAccess.

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 email
Web/Other itch.io purchase link PANZER-ISLAND key dialog email

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.json gains field_repair_limit (int, default 0)
  • stage_controller.gd tracks remaining repairs per layer
  • game_manager.gd manages 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.json replaced with per-language files: credits.en.json, credits.ja.json, credits.de.json
  • credits_loader.gd rewritten to handle chapter-specific credits
  • Removed old credits_ch02.json in 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_summon now uses default drone level instead of incorrectly inherited level
  • Game freeze on sector transition: Infinite loop in stage_controller.gd during 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)
  • gitignore updated for Play Games Services plugin
  • CLAUDE.md updated with parity table and translation workflow
  • Ch1 immersion polish pass
  • publishing.md updated with IAP description, billing docs, and chapter counts
  • 619 tests pass, check.sh clean