Skip to content

Dev Log: 2026-06-11

Chapter 05: "What Did We Hide?"

Chapter 05 shipped. 10 stages, 44 cutscene files, 5 new backdrops, a full terrain theme set (chemical + laboratory, 22 tiles each), and 30 hand-drawn props. The chapter is the midpoint pivot: Erika enters the research complex where ORACLE was built, finds Wilhelm's transmission logs, and confronts the truth of what she designed.

Production pipeline

The asset generation pipeline grew three new modules under tank_tactics_tools/lib/:

  • backdrop_gen.py (595 lines): renders 1280x720 backdrop images from terrain/ruin compositions using Pillow. Generates 5 backdrops from procedural noise + edge detection masks.
  • prop_gen.py (765 lines): generates 32x32–48x48 pixel-art props with palette-based tinting, shadow offset, and damage variants. Each prop gets a _damaged variant at 50% opacity with a random displacement filter.
  • terrain_gen.py (405 lines): generates 22 terrain tiles per theme (grass, forest, ruins, water, bridge NS/EW, mountain, beach) with per-theme color palettes and optional chemical stain overlay.

The chemical theme uses grey-brown dead earth tones; the laboratory theme uses cold blue-grey concrete tones. Both are designed to contrast against the green/brown military installation palette of earlier chapters. The pipeline is reusable for any future chapter: define a palette config, run the script, import.

Stage map design

Every stage received a designed terrain layout (replacing the earlier dummy all-grass maps). The chapter forms a serpentine path from east to west across two biomes: chemical contamination zone (S01-S02, S09-S10) and sealed laboratory complex (S03-S08).

Key terrain shapes per stage include coastal tide-marks, supply road drainage channels, containment channels, fire-suppression reservoirs, industrial cooling basins, archive courtyards, and coastal boundary water. Each uses the continuous-water system (validated by the new water-continuity tests, see below).

Cutscenes and narrative

44 cutscene files cover the full chapter. The arc includes: - S01-S02: Entry into the contamination zone, Alpha-Maria at the tide-mark, Drona at the gatehouse - S03-S04: Complex perimeter engagement, sealed labs, double-authorship discovery - S05-S06: Deployment order, industrial cooling basin, Wilhelm's first transmission - S07-S08: "My kind" — Katyusha names Wilhelm, archive confrontation, Drona fights alongside then powers down - S09-S10: Alpha-Maria live combat debut, boss fight at the western boundary

Each stage has a pre-cutscene (plus backdrop variant), a sector-1 interlayer cutscene (except S01, S02, S03, S05, S08, S09 which have one only on specific sectors), and a post-cutscene. The chapter's visual styleguide section was also written covering worldmap layout, backdrop requirements, and per-stage prop/landmark notes.


Reflex-move toggle and queue mode

The reflex-move mechanic — drones reacting to player movement — is one of Panzer Island's defining systems, but it can be punishing for methodical players. A new toggle in the gameplay options panel (config_manager.gd, options_menu.gd) lets the player disable reflex-move entirely. When disabled, drones only react to attacks, not to movement.

A related change: reflex-move is also suppressed when a movement is queued. If the player plots a multi-waypoint path, drones do not react until the final confirm. This prevents the feel of being punished for planning ahead, which was a consistent feedback point from playtesters.

Implementation notes

  • ConfigManager gained reflex_enabled (bool, default true), persisted to user://config.cfg
  • StageController reads the flag on each tick; if false, the _react_to_movement pass is skipped
  • OptionsMenu gained a checkbox row labeled via tr("OPT_REFLEX") with a hint string tr("OPT_REFLEX_HINT")
  • The queue-mode suppression works by setting a _queued_move_active flag during waypoint plotting; reflex triggers check it before spawning reaction moves
  • Two new CSV translation keys added for the UI

Queue mode polish

The queue system (adding to an existing move path rather than replacing it) was polished: - HUD feedback when queue mode is active - Clearer visual distinction between the active path segment and queued segments


Rocket launcher

New drone type: Rocket Launcher (Appears in Chapter 5).

Only fires once every 5 player actions but hits heavy with an AoE attack.

The docs/balancing.md first-appearance table was updated to include the rocket launcher row, which was missing from the original pass.


Testing infrastructure expansions

Water continuity tests

Two new test files verify that water tiles form continuous bodies across sectors within a stage (test_water_continuity.py, 71 lines) and across chapter transitions on the world map (test_water_continuity_worldmap.py, 152 lines). The intra-stage test checks every stage JSON for water edge matching between adjacent sectors; the world-map test checks chapter exit_coords / entry_coords pairs for water continuity at the connection point.

Terrain uniqueness tests

test_terrain_uniqueness.py (64 lines) verifies that every terrain tile in every stage has a unique terrain_theme key per theme definition, preventing asset path collisions during import.

Tutorial text key tests

test_tutorial_text_keys.py (93 lines) validates that all tutorial step text values in stage JSONs reference valid translation keys in strings.csv, catching stale or missing keys.


Stage validation rules

The Python stage validator in json_io.py gained three new rules:

Unit starting positions vs drone range

_units_not_in_drone_range() checks that no unit spawn cell is within Manhattan distance of any drone's attack range. Drones with attack_power: 0 (relay nodes, spotters, repair drones) are excluded — they cannot attack, so they shouldn't trigger the rule. Surface-only and air-only targeting are respected: flying drones cannot threaten ground-unit spawns.

Five existing violations were fixed across ch04 and ch05 stages.

Sector 1 landmark props

Every stage (Ch01+) must have at least one multi-cell prop (width x height > 1) in sector 1. This ensures each stage has a visually identifiable landmark without extra design work. Five ch05 stages were missing landmarks and received placement of primary_storage_tank, security_checkpoint, calibration_station, driftwood_memorial, and research_outpost.

Chapter 00 (debug) is exempt.

AG/AA type distribution

A post-population rule limits base-type (both) drones to 20% per sector among typable families (guard_tower, patrol, sentinel, interceptor, artillery, cruiser, rocket_launcher). The remaining 80% must be typed as AG or AA. Zero-attack types (relay_node, spotter, repair_drone) and special types (detonator, nexus, alpha bosses) are excluded from the calculation.

Chapters 00 (debug) and 01 (tutorial) are exempt — the tutorial intentionally uses base-type drones to keep the teaching surface simple.


Drone population and type conversion

Ch05 drone population

All 10 ch05 stages were populated with drone rosters following the balancing rules: 6-9 drones per sector, 60-85% ground-reachable, at least 2 anti-ground and 2 anti-air per sector. Stages 1-4 were hand-picked; stages 5-10 were script-generated via a Python helper.

A validator rule (see above) enforces the 20% cap going forward.


Mountain terrain sprites redesigned

mountain_chemical and mountain_laboratory terrain sprites were redesigned. The mountain tiles now use stepped peaks and a pillar shape, making them visibly distinct from ruins and building props. The previous design shared too much silhouette with building outlines, causing readability issues during play.


Bug fixes

  • Game freeze on sector transition: Fixed a freeze bug where the stage controller entered an infinite loop during layer transitions under specific drone alert-state conditions. The loop was in the _process call chain; fixed by adding a recursion guard in stage_controller.gd.
  • Cutscene skip button: The landing cutscene skip button was not functional on first launch. Fixed in landing_cutscene.gd by binding the skip action before the tween completes.
  • Translation compilation: Missing strings from ch05 cutscenes and UI elements were added to strings.csv and compiled. All three locale translation files (EN, JA, DE) were regenerated.
  • Stage fixes: Various minor stage data corrections across ch01 (tutorial text pluralization, objective text) and ch02-ch04 (terrain alignment, prop overlap fixes).

Solver parity

Solver checkpoints were regenerated for all five chapters (solve -qr) after the drone type changes. The solver's DroneType enum was extended with AG/AA variant entries (GUARD_TOWER_AG, GUARD_TOWER_AA, PATROL_AG, PATROL_AA, etc.), and integration tests were updated to accept any variant of a type family when looking up drones from stage data.

Four integration tests in test_engine.py were updated to match d.type in (GUARD_TOWER, GUARD_TOWER_AG, GUARD_TOWER_AA) instead of a single-type check.


Minor

  • Stage thumbnails generated for ch05 worldmap nodes (10 stages + 4 sector previews for the boss stage)
  • New props added to data/props.json: calibration_station, chemical_tide_mark, comms_array, complex_gate, damaged_drona_prop, deployment_order, drainage_channel, experiment_rig, naval_receiver, observation_point, observation_window, perimeter_fence, primary_storage_tank, research_desk, scope_expansion_binder, sealed_lab_door, ventilation_tower, archive_shelf, chain_of_command_board, chemical_vat, contamination_stake, corroded_fence, damaged_gatehouse, dead_tree, fleet_backdrop, naval_modification_record, outer_zone_fence, supply_road_marker
  • shell_scripts/stage_validator.sh run added to check.sh