# TODO - Missing Mechanics & Wiring Gaps

## Critical - Game won't run without these

- [x] **Define `start_combat_enhanced()`** - called by exploration, encounter, rest, and scavenge systems. Bridge between world exploration and combat. ~~Must: accept EnemyData, call `prepforfight()` + `combat_menu()` + handle post-combat.~~ -> Fixed: accepts `EnemyData`, legacy rows, IDs, or names; selects the exact `Table_of_Random_Critters` row and runs the existing `challenge()` flow, including preparation, combat menu, and post-combat handling.
- [x] **Define `get_current_turn()`** - used by sex system cooldowns (`can_have_sex`). Return current `turns` value. -> Fixed: added in `time_system.rpy`, returns global `turns`.
- [x] **Register Bunker and core locations at init** - `start.rpy` calls `set_current_location("Bunker")` but nothing registers it. ~~Files exist in `Content/Locations/Core Mechanics/` but may not load before start. Verify init order.~~ -> Fixed in `159d4236b`: `ensure_core_start_locations_registered()` with `FALLBACK_BUNKER_LOCATION` + `CORE_START_LOCATION_SYMBOLS`, runs at init 999.
- [x] **Populate `Table_of_Random_Critters`** - combat system (`fight()`, `Challenge()`, `prepforfight()`) reads from it. ~~250+ enemies are registered via `register_enemy()` but never added to this table.~~ -> Fixed in `159d4236b`: `populate_table_of_random_critters()` builds table from `ENEMIES_REGISTRY` at init 5. `_build_critter_row()` converts EnemyData to legacy row format with full stat mapping.
- [x] **Populate `Table_of_Critter_Combat`** - monster AI table. Combat calls `_get_critter_combat_row()`. Without it, all enemies use `standardretaliate()` fallback. -> Fixed: `populate_table_of_critter_combat()` seeds the canonical core rows and builds rows for every registered `special_combat` mode, merging combat metadata and resolving callable hooks by explicit name or mode naming convention. Unported special rule bodies fall back safely until implemented.

## High - Core features broken/missing

- [x] **Define `level_up` function** - Fixed: combat consumes the HUD's current-level XP threshold, preserves excess XP, supports multiple level gains, applies Hardy's HP bonus, updates score, and announces every new level.
- [x] **Define `pet_level_up` function** - Fixed: combat delegates companion advancement to the existing `companion_level_up()` implementation.
- [x] **Define 12 late-bound combat hooks:** `monster_injury_rule`, `monster_libido_rule`, `player_injury_rule`, `loss_rule`, `AttemptToWait`, `AttemptToWaitBeforeClear`, `AttemptToWaitAndClearHyper`, `ngraphics_blank_rule`, `VoriaPostCombat`, `vorebyplayer`, `ubbyplayer`, `process_item_func`. Already defined or wired: `cock_descr_rule`, `cunt_descr_rule`, `breast_descr_rule`, `companion_level_up`. -> Fixed: all 12 added as safe no-op stubs in `combat_system.rpy`. Called via `_follow_rule(getattr(...))` - fail silently, combat behavior is incomplete but doesn't crash. **→ UPDATE (2026-06-12): `loss_rule` now fully implemented with infection-on-loss logic — resolves enemy infection, cross_infection, intensity scaling by enemy level, warded/syringe checks, and resbypass/infectbypass support.**
- [x] **Define `check_heat_rule`** - called conditionally in `time_system.rpy:351` via `hasattr` guard (safe no-op, but heat system incomplete). -> Fixed: added as no-op stub in `heat_system.rpy`.
- [x] **Populate `INFECTION_LISTS`** - Fixed: a late-init registry pass rebuilds anatomy and species lists from infection tags, names, species aliases, and cock transformation metadata. Added a general `FurryList` so explicitly furry infections work even without a taxonomy tag.
- [x] **Populate encounter tables** - Fixed: `auto_register_all_encounters()` now populates encounter buckets from top-level enemy `area` values and `encounter.areas`, normalizes the common area aliases used in content into canonical `AREA_ENCOUNTERS` regions, and skips non-random values like `Nowhere`. Random encounter tables are no longer effectively empty outside the legacy Library seed.
- [x] **Fix `companionList` -> `companion_list` mismatch** - combat AI reads `player.companionList` (5 refs in combat_system.rpy:177,691,858,2006,2262); companions system uses `player.companion_list`. -> Fixed: all 5 references changed to `companion_list`. Also fixed `EncounteredEnemies` -> `encountered_enemies` (7 refs) and added `default HardMode = False`.

## Medium - Features defined but not wired

- [x] **Wire loot drops into combat victory** - Fixed: `_post_win_xp_and_level()` now rolls enemy loot before XP, resolves loot refs by item id or display name, applies `Magpie Eyes` / `Mugger` drop bonuses, and populates `CombatTrophyList` with awarded drops. Remaining missing loot refs are now content/data issues rather than unwired combat flow.
- [x] **Wire quest system** - quest functions are now called by content (`OrangeHorned_events.rpy`, `OrangeHorned_quests.rpy`, `OrangeHorned_dialogue.rpy`, `Nuku_Valente_quests.rpy`). Quests "elusive_book", "lost_gear", "needy_rabbit_girl", "hyper_squirrel_girl" all have runtime triggers.
- [x] **Populate `Table_of_Game_Art`** - Fixed: `game_art.rpy` populates `Table_of_Game_Art` with enemy, NPC, and location image mappings via `_wire_all_art()`, and init 5 runs it before combat calls `_try_show_creature_art()`.
- [x] **Populate `Table_of_CombatPrep`** - Fixed: combat now has a canonical opt-in prep registry. `combat_system.rpy` defines `Table_of_CombatPrep`, rebuilds it at init 5 from explicit enemy metadata (`combat_prep` or `combat.prep`), exposes `register_combat_prep(...)`, and resolves hooks by enemy id/name when `prepforfight()` runs. Most creatures still do nothing by default, but any creature can now opt into pre-combat behavior cleanly.
- [x] **Populate `TailweaponList`** - Fixed: `populate_tail_weapon_support()` now carries the legacy tail-weapon names alongside tagged infection aliases, and Tail Strike resolves damage only from matching enemy rows.
- [x] **Add save/load persistence** - Fixed: promoted turn/date/navigation/companion runtime state to `default` variables, added a real `after_load` restore pass for derived registries and loaded-location safety, and migrated legacy companion state so allies and quest globals survive save/load correctly.
- [x] **Fast travel menu bug** - Fixed: `fast_travel` now builds one dynamic list from `get_nav_points_by_area()`, filters out the current location, and routes through `navigate_to(...)` instead of a hardcoded Bunker-only path.
- [x] **AREA_ENCOUNTERS auto-population wiring** - Fixed: `auto_register_all_encounters()` now reads both top-level enemy `area` values and `encounter.areas`, normalizes them through `normalize_encounter_area()`, and seeds `AREA_ENCOUNTERS` at init 5.

## Low - UI placeholders & polish

- [x] **Implement equipment management UI** - Fixed: `equipment_screen` has per-slot armor equip/unequip with AC display, weapons equip from inventory, and inventory drop now protects equipped items from desync.
- [x] **Implement item use/drop from inventory** - Fixed: `inventory_screen` supports usable consumables plus one-at-a-time and stack drops. Dropped items are returned to the current location, while dropping the last equipped weapon/armor copy is blocked until unequipped.
- [x] **Implement ward/unward random encounter menu** - Fixed: warding now opens a scrollable content flag/tag picker backed by `WardList`/`BanList`-compatible taste labels, unwarding lists currently warded random encounter categories, and ward filtering no longer falls back to blocked enemies when every candidate is blocked.
- [x] **Implement fast travel location list** - Fixed: both the `fast_travel` label and the action-panel Nav tab iterate discovered destinations through `get_nav_points_by_area()` instead of a hardcoded Bunker-only list.
- [x] **Remove duplicate `LATEX_VIXEN_COMPANION`** - Fixed: the content-level companion registration is now canonical, with the engine duplicate removed and useful aliases/stats preserved in `core_companions.rpy`.
- [x] **Fill empty content files (14 confirmed 0-byte .rpy files):** Fixed: there are currently 0 zero-byte `.rpy` files anywhere under `game/scripts/Content`.
- [x] **Fill empty infection files:** Fixed as part of the empty-file cleanup above; there are no remaining zero-byte infection/enemy `.rpy` files under `game/scripts/Content`.
- [x] **Replace body hair error text** - Fixed: body hair length 0 now describes "no noticeable body hair" instead of an error report string.
- [x] **Replace Kirov dialogue ERROR markers** - Fixed: the remaining KIRKAT003 fallback now exits the encounter with neutral in-world text.
- [x] **Replace Kristen location ERROR marker** - Fixed: Kristen's inaccessible-location branch now redirects with neutral in-world text instead of an error report string.
- [x] **Replace Hadiya event ERROR markers** - Fixed: no `ERROR-Hadiya` markers remain in `Stripes_events.rpy`.
- [x] **Replace Eric NPC ERROR marker** - Fixed: the Eric entry in `Content/NPCs/Wahn/Wahn_npcs.rpy` no longer contains the `ERROR-Eric-100A` placeholder text.
- [x] **Strip DEBUG markers from player-visible text (~25 occurrences across 10 files):** *(verified 2026-06-14; current tree only retains non-player-facing registry cleanup logic)*
  - `transformation_system.rpy` - 11 DEBUG `renpy.say()` calls during infection/transformation/resistant checks
  - `navigation_system.rpy` - 2 DEBUG lines (fast travel point checks)
  - `Stripes_events.rpy` - 8 DEBUG markers (Candy, Hadiya, Gobby, Alexandra NPC debug text + descriptions)
  - `Ssely_events.rpy` - 4 DEBUG markers (mall walk-in, otterboi)
  - `Luneth_events.rpy` - 2 DEBUG markers (Skarnoth walk-in)
  - `Speedlover_events.rpy` - 2 DEBUG markers (Korvin/Gibson walk-in)
  - `SgtPepper234_npcs.rpy` - 1 DEBUG marker (Garrett NPC description)
  - `Wahn_npcs.rpy` - 3 NPC descriptions with DEBUG headers (Chris, Eric, plus Alexandra/Bastet event debug)
  - (plus DEBUG_MODE guards in 10+ engine files — these are behind a False flag, so player-invisible by default)
- [x] **Strip TODO markers from player-visible text** - Fixed: the four Wahn Spike/Urik romance TODO tags now have neutral connecting prose.
- [x] **Replace placeholder NPC conversations** - CrimsonAsh (5 NPCs with literal `<This is nothing but a placeholder!>`), Gherod (10 NPCs with `<This is nothing but a placeholder!>` — not previously tracked), SgtPepper234 (4 NPCs with `Placeholder!`), Kernog (2 NPCs with `<Placeholder>` — not previously tracked), Dys (1 NPC with `<placeholder>.` description). Current tree scans no longer show live matches for those markers in `game/scripts/Content`.
- [x] **Replace placeholder location names** - Fixed: Stripes Down Under Pub locations now use real visible names instead of `PlaceholderforDUP` / `PlaceholderforRLD`.
- [x] **Replace placeholder location description** - ~~`Content/Locations/SgtPepper234/qytat_a_th_lundrues.rpy:301` shows literal "Placeholder" as description text.~~ -> Fixed: line 301 now has real night-time description text ("This building is far larger..." with actual gryphon city details instead of "Placeholder").
- [~] **Add more character/location images** - *(Partial: `_wire_all_art()` registers ~230 enemy art mappings (3 key variants each), ~150 NPC mappings, ~250 location mappings — ~630+ wired entries total plus fuzzy fallback matching in `_try_show_creature_image()`. With 1,509 image files on disk, about ~40% have explicit runtime mappings; the fuzzy fallback catches many more. Remaining gap: ~30% of image files have no path to display at runtime.)*

## Low - UI/UX fixes (2026-06-08)

- [x] **Main stat not set on start** - ~~player stat display is uninitialized when game loop first loads.~~ -> Fixed in `159d4236b`: HUD now uses `get_current_location()`. `start.rpy` hides HUD during intro text to avoid confusion.
- [x] **Interface changes sizes when main stat is set** - HUD/screen layout resizes when stats populate; should reserve stable dimensions. *(Partial: HUD and action bar use fixed xsize/ysize; say window centered with yanchor.)*
- [x] **Text is displayed incorrectly** - Fixed: the custom `say_hud` viewport now reserves explicit scrollbar width and bottom margin, so 16:9 / 1920x1080 dialogue text no longer wraps under the vertical bar or clips into the bottom UI area.
- [x] **Action and navmenu needs changes** - action buttons and navigation menu require redesign or logic fixes. -> Godot-style action interface implemented: `action_interface.rpy` replaces text-based game_loop menu with visual panel, compass rose, dynamic action buttons, and tab container.
- [x] **Quick menu should not be interactable when action buttons are overlayed** - quick menu remains clickable behind action overlays, causing misclicks. -> Fixed: `game_gui.rpy` quick menu sidebar now guarded by `if not renpy.get_screen("action_panel")`.

## Medium - Enemy content incomplete

- [x] **German Shepherd Male enemy basic port** — Fixed: regular encounters, generic victory/defeat scenes, all 9 generic victory sex scenes, special scarred GSD (Korvin) recurring arc system with state tracking (`gsd_special_pet`), encounter hook registered in `combat_system.rpy`, all boss fight intro text, all recruit/banish final scenes. Still missing below.
  - [ ] **Boss fight mechanics** — Korvin leads the player to fight an Orc Warrior / Tenrec / Centaur Stallion. In Inform this uses `inasituation = true`, `combat_abort = 1`, `fightoutcome = 22`, then `challenge "EnemyName"`. Ren'Py needs a way to show pre-fight intro text then chain into a new encounter within the same flow. Currently the boss fight labels show the intro text but don't actually start the boss combat.
  - [ ] **Korvin collar feat system** — Fight outcomes swap "Korvin's Pet - Pink Collar" ↔ "Korvin's Pet - Spiked Collar" feats. Losing → get pink collar, winning with pink → upgrade to spiked, winning with spiked → toy play scene. Boss fight outcomes include collar swap logic. The `gsd_special_pet` state is tracked but collar feat management is deferred.
  - [ ] **Heat system for German Shepherd Bitch** — `gsdheatstart` (increase cunt tightness or libido) and `gsdheatend` (decrease cunt tightness) trigger labels tied to the Bitch infection's heat cycle. Not yet implemented.
  - [ ] **Game endings system** — `German Shepherd Infection rule` triggers when humanity < 10 and `gsd_pet` states differ. Three ending tiers: (a) gsd_pet 1-9: succumbed to pack life with gender-specific endings, (b) gsd_pet >= 12 or 100: survived with military rescue + post-war life variations, (c) humanity >= 10: rescued by military. Not yet implemented.
  - [ ] **attk gsd rule** — `gsd_attack` flag is set when player fights back against special GSD. Used in dialogue branches to differentiate fought-vs-submitted responses. The flag exists but needs verification that combat flow properly sets it and the special defeat text checks it.

## Medium - Milk / Cum systems broken

- [x] **Register `mothers_milk` and `distilled_milk` items** - Fixed: both items are registered as usable consumables; Mother's Milk can be produced from pregnancy milking, while distilled milk is available as a microwave/crafting output.
- [x] **Register `cum` item (or equivalent)** - Fixed: `cum` is registered as a bridge material for generic microwave recipes, while cock milking only grants registered infection-specific cum items.
- [~] **Register all species-specific milk/cum items referenced by crafting** - Common bridge items (`milky`, `panther_milk`, `cum`, `distilled_cum`, `distilled_booze`) are registered and crafting filters out recipes with unresolved IDs instead of presenting dead recipes. Remaining gap: the generated species-specific legacy fluid table still needs broader item definitions before every source recipe can appear.
- [x] **Register `distilled_cum` item** - Fixed: `distilled_cum` is registered as a microwave output.
- [x] **Wire `milk_breasts` and `jerk_off` actions into game loop** - Fixed: the action tray exposes Jerk Off and Milk Breasts only when the current player state passes the milking checks, and `game_loop.rpy` routes those actions to the existing labels.
- [x] **`use_mothers_milk()` / `use_distilled_milk()` unreachable** - Fixed: registered milk/distilled items have `use_label` entries, and distilled milk/cum/booze now apply their source-shaped anatomy/alcohol effects.
- [x] **Crafting-to-inventory bridge missing** - Fixed: `craft_item()` validates recipe/input/output IDs, consumes inputs, grants outputs through `give_item()`, and reports missing ingredients; recipes with missing bridge items are hidden until their item data exists.
- [x] **No infection-to-milk/cum bridge** - Fixed: milk/cum production resolves registered infection metadata (`milk_item` / `cum_item`), normalized legacy names, registered item names, and existing generated `infection_id_milk` / `infection_id_cum` item IDs without creating generic fallback fluids for unregistered forms.
- [x] **`total_milk_produced` / `total_cum_produced` stats never displayed** - Fixed: the text status menu and character stats popup show the store-level production counters.

## Medium - Godot-style action interface for Ren'Py

FS-Godot has a rich GUI action interface. The Ren'Py version currently uses only text menus. Ren'Py's screen language can replicate most of the Godot layout at lower implementation cost. Priority order:

- [x] **Compass rose directional buttons** - 10 buttons (N, NE, NW, S, SE, SW, E, W, Up, Down) in a fixed compass layout. Reads `current_location.connections` to enable/disable each direction. Clicking calls `move_direction(direction)`. -> Implemented in `action_interface.rpy` as `compass_rose` screen, replaces text-based "Navigate" menu.
- [x] **Dynamic action button grid** - Replaced hardcoded `game_loop` menu with screen that generates buttons from room features and player state (`_get_action_buttons()`). Maps: `features.rest` -> "Rest", `is_safe==False` -> "Explore" + "Scavenge", `has_storage` -> "Storage", `cock_count>0` -> "Jerk Off", `breast_size>=2` -> "Milk Breasts", etc.
- [x] **Items tab on action panel** - `current_location.items` listed as "Pick up" buttons via `_get_room_items()`. Clicking calls `_do_pickup_item()`. Tab hidden when room has no items (shows "No items here.").
- [x] **Tab container (Actions / Items / Nav)** - `hbox` of tab buttons (`action_tab_container` screen) switching child viewport via `action_panel_tab` variable. Matches Godot's `ActionTabs` TabContainer.
- [x] **Persistent text history panel** - `viewport` with scroll (`text_history_panel` screen). Accumulates room descriptions and feedback via `add_text_history()`. Auto-scrolls to bottom (`yinitial 1.0`). Max 50 entries.
- [x] **Navigation tab (fast travel)** - Lists discovered locations from `KNOWN_LOCATIONS` via `get_nav_points_by_area()`. Clicking calls `_do_fast_travel(location_id)`. Shows "No locations discovered." when empty.
- [~] **Map viewport (stretch goal)** - graph-style map viewport panel added to the action tray, showing the current location plus direct exits and discovered nearby locations as connected nodes. Remaining gap: richer positioning, labels, and the original `Canvas`/`draw`-style polish.
- [x] **Fix quick menu during overlays** - `game_hud` quick menu sidebar now uses `if not renpy.get_screen("action_panel")` to hide itself when action panel overlay is active, preventing misclicks behind modal screens.
---
