Player-Echo Boss: "The Curse"

Status: Design — v1.0 Created: 2026-04-07 System Category: Gameplay / Boss Encounter / Persistence Depends On: Persistence System, Relic System, Skill Tree, Archetype System, Dice Combat Manager, Enemy Data & AI, Run History


1. Overview

After the player defeats the Act 3 final boss for the first time, the game serializes their complete build — archetype, relic set, skill tree keystone snapshot, and dice pool size — into a dedicated save file ("echo save"). In every subsequent run, the Act 3 boss encounter is replaced by a fight against "The Curse": a boss entity powered entirely by that stored build. The Curse maintains its own dice pool, rolls Yahtzee hands against the player, and converts the stored relics and keystones into persistent passive abilities and reactive triggered effects. Its AI uses those tools alongside a standard enemy interference action set, making each echo encounter a direct confrontation with the player's own best build. The first playthrough uses a hand-authored "Fallen Hero" build so that new players face a meaningful, balanced challenge before any personal echo exists. The narrative wrapper — a god's curse that transforms each victor into the next dungeon's guardian — gives the mechanic emotional weight and creates a long-form "arms race" against oneself that reinforces the roguelike meta-loop.


2. Player Fantasy

Target Aesthetics (MDA)

Primary: Challenge — facing your own best build demands the most from your current run. You cannot rely on unfamiliarity; the enemy knows every trick because the tricks are yours.

Secondary: Discovery — the echo reveals how powerful your past choices actually were when played against you. Builds that felt merely "good" can become terrifying opponents.

Tertiary: Narrative / Expression — the curse ceremony at victory, the reveal cutscene showing "your" relics and archetype, and the naming of the stored echo as the "Fallen [Archetype]" create a personal mythology. Players are not fighting a stock demon; they are fighting their own legacy.

Emotional Arc

  1. Recognition (cutscene reveal): "That's MY loadout." Surprise shades into pride, then unease.
  2. Pressure (mid-fight): The boss scores hands, triggers relics you know intimately, and uses interference you have relied on. You understand what is coming and still cannot always stop it.
  3. Triumph or Lesson (resolution): Winning feels like outgrowing your past self. Losing reads as "my old build was better than my current one" — a motivation to improve.

Self-Determination Theory Alignment

  • Competence: The echo's power is explicitly tied to past player performance, making each victory a legible skill benchmark.
  • Autonomy: Players shape the future echo through current build choices. Knowing a run will be "recorded" adds meaningful stakes to every relic pick.
  • Relatedness: Narrative framing ("a hero like you") creates empathy rather than pure opposition.

3. Detailed Design

3.1 States and Transitions

RUN_START
  └─► check echo_save exists?
        ├─ NO  → load FALLEN_HERO_BUILD (default)
        └─ YES → load echo_save → construct EchoEnemy

ACT_3_BOSS_NODE_REACHED
  └─► spawn The Curse (EchoEnemy)
        └─► standard combat flow (DiceCombatManager)

COMBAT_VICTORY (player wins against The Curse)
  └─► trigger CURSE_CEREMONY cutscene
        └─► serialize current build → overwrite echo_save
              └─► return to map (run continues to victory screen)

COMBAT_DEFEAT (player loses to The Curse)
  └─► standard defeat flow — echo_save NOT updated

The echo save is only written on a successful kill of The Curse, not on any other run outcome. A run that dies on floor 30 never updates the echo.

3.2 Build Serialization Format

Stored at user://echo_save.json. The file is written as JSON (human-readable for debug, importable for community sharing in the future expansion).

{
  "version": 1,
  "timestamp": 1712500000,
  "archetype_id": "gambler",
  "display_name": "Fallen Gambler",
  "dice_count": 6,
  "relic_ids": ["loaded_dice", "twins_mirror", "lucky_streak", "sharpened_edge"],
  "keystone_ids": ["glass_cannon", "gambler"],
  "skill_points_spent": 67,
  "floor_reached": 45,
  "run_duration_sec": 2340.5
}

Field definitions:

FieldTypeDescription
versionintSchema version for migration. Current: 1.
timestampintUnix time of the winning run.
archetype_idStringNameOne of: wanderer, gambler, bruiser, trickster, strategist, elementalist, atheist
display_nameStringAuto-generated: "Fallen [Archetype Display Name]"
dice_countintTotal dice in pool at time of echo capture (5-8).
relic_idsArray[StringName]Ordered list of relic IDs the player held at end of run. Max 12.
keystone_idsArray[StringName]Keystones allocated in the skill tree snapshot. 0-3 entries.
skill_points_spentintTotal SP spent in tree (informational; used to scale base stats).
floor_reachedintAlways 45 for a valid echo (Act 3 boss kill).
run_duration_secfloatRun duration in seconds (informational display only).

What is NOT stored: specific skill tree node allocation (only keystones matter for boss behavior), consumables held at run end (consumables are one-time-use and do not translate to boss mechanics), gold (irrelevant to combat).

3.3 Boss Statistics

The Curse's combat stats are derived from the stored skill_points_spent value and a base that exceeds the Act 3 Arch Demon (see Section 4 for full formulas). The intent is that the echo is always harder than the Arch Demon but scaled by how developed the stored build was.

StatSource
Max HPFormula — see Section 4
Dice countdice_count from echo save
Rerolls per turnArchetype base rerolls (see table below) + keystone bonuses
Damage per handEcho hand scoring formula — see Section 4
Interference actionsFixed pool + archetype-specific actions

Archetype base rerolls for The Curse:

ArchetypeBase Rerolls
wanderer2
gambler3
bruiser2
trickster3
strategist1
elementalist2
atheist2

3.4 Boss Dice Mechanics — How The Curse Rolls

The Curse uses a simplified version of the player's own dice loop, executed server-side (no player interaction required):

  1. Roll Phase: The Curse rolls dice_count d6. If the stored build includes elemental keystones (Pyromaniac, Permafrost, Stormcaller, Gale Force, or Elementalist) or elemental relics, apply the corresponding elemental probability to the roll (see Section 3.6 for relic translation).
  2. Hold Phase (AI decision): The Curse evaluates all possible hold subsets using a greedy best-hand heuristic (see Section 3.7 for AI logic). It holds the dice that maximize expected hand score.
  3. Reroll Phase: The Curse spends up to its reroll budget on non-held dice. It rerolls once and re-evaluates. It does not hold-and-reroll more than once per turn — the second "reroll" budget is reserved for interference.
  4. Score Phase: The Curse scores the best valid Yahtzee hand from the final dice state. Damage is calculated using the echo scoring formula (Section 4).
  5. Elemental Combo Check: Same logic as the player. If the roll produced elemental dice that match a combo pattern, the combo triggers against the player. Combo damage uses the echo's stored multipliers.
  6. Interference Phase: After scoring, The Curse selects one interference action from its action pool (see Section 3.5). It does NOT score AND interfere in the same turn — these are mutually exclusive per-turn decisions made by the AI governor (Section 3.7).

The Curse's rolls are deterministic per seed: the run seed is combined with the floor number and turn count to produce the Curse's dice outcomes. This prevents the Curse from being trivially lucky or unlucky across attempts of the same run — the dice behave consistently, rewarding player learning.

3.5 Interference Action Pool

The Curse always has access to the base interference pool. Additional actions are added by archetype.

Base pool (all echoes):

ActionEffectWeight
SNIPESet 1 random unheld die to 120
CHAOSRe-randomize all unheld dice15
WEAKENPlayer's next hand: chips -20%20
GRAVITYForce-hold 1 random die (player cannot unhold it)15
STEAL_REROLLRemove 1 player reroll this turn15
CURSEApply 1 stack of Vulnerable to player15

Archetype-specific additions:

ArchetypeExtra ActionEffectWeight
gamblerJINXPlayer's next reroll upgrades no dice (reroll wasted)25
tricksterLOCK_HOLDPrevent player from holding any new dice this turn25
strategistRIGForce 2 specific dice to show a value The Curse chooses25
bruiserCRUSHDeal 8 direct HP damage in addition to scoring damage25
elementalistSTATICRemove elemental type from 2 random dice25
wandererSTEAL_DIERemove 1 player die from pool for 1 turn25
atheistNULLIFYPlayer's elemental combo does not trigger this turn25

Weights are used for weighted-random selection during interference decisions. The AI governor (Section 3.7) decides whether to interfere; these weights decide which interference to use when the governor opts in.

3.6 Relic-to-Passive Translation

Stored relics become persistent passive abilities on The Curse. Not every relic translates directly — they fall into three translation categories:

Category A — Direct stat boost (always applies): Relics that grant flat numeric bonuses are applied to the echo's base stats.

RelicPassive Effect on The Curse
Twin Dice+1 to The Curse's dice count
Extra Reroll+1 reroll per turn
Loaded DicePairs score +12 chips
Sequence Master+3 chips per die in longest straight
Go BigEach 6 scored: +8 chips; each 5: +4 chips
Penny PincherFives scored: +5 chips each
Ember Core / Frost Shard / Wind Chime / Spark Plug+3% corresponding elemental dice chance
Elemental Lens+2% elemental chance per die
Thick Hide Relic equivalent+20 max HP

Category B — Triggered effect (triggers on matching condition): Relics with on-score or on-combo triggers fire when The Curse scores a hand that matches the trigger condition.

RelicTrigger ConditionBoss Effect
Lucky StreakAfter a Five-of-a-Kind or betterNext attack ignores player Block
Sharpened EdgeAfter scoring any straight+0.3 to multiplier this turn
Combo CatalystAfter elemental combo triggersCombo damage +25%
Pyrrhic VictoryPlayer's HP below 40%+15% all damage dealt
Volatility EngineAfter rerolling all 5+ diceNext hand: mult x2

Category C — Untranslatable (silently dropped): Relics whose effects have no combat-applicable meaning for a boss are ignored. This is not penalized — the echo still functions from Categories A and B.

RelicReason Dropped
Gold-generating relicsEconomy irrelevant to boss
Shop discount relicsNo shop context
Heal relicsHealing ignored (boss has fixed HP)
Map navigation relicsNo map traversal
Consumable slot relicsBoss doesn't use consumables

A relic's category is declared in relic_database.gd via a new field echo_category: EchoCategory with values STAT_BOOST, TRIGGERED, UNTRANSLATABLE. Default if unset: UNTRANSLATABLE. This prevents new relics from silently becoming overpowered echoes without explicit authoring.

Cap: The Curse applies a maximum of 6 relic passives (by Category A/B priority, then order in relic_ids array). Remaining relics are dropped silently. This prevents an 8-12 relic echo from becoming undefeatable.

3.7 Keystone-to-Ability Translation

Keystones in the stored keystone_ids array become active passive modifiers on The Curse.

KeystoneBoss Passive
PyromaniacAll The Curse's dice are Fire elemental. Burn tick damage x2 if applied to player.
PermafrostIce combo damage +50%. Freeze duration on player +1 turn.
StormcallerLightning combos chain to 1 extra interference action.
Gale ForceWind combos trigger +1 additional hit.
ElementalistAll 4 elements equally distributed. Combo damage +30%.
PuristNo elemental dice. All hand scores x1.5. +1 reroll.
Glass CannonAll damage x2. Max HP halved (applied before HP formula).
Gambler+2 rerolls. 15% chance each reroll produces an elemental die.
Thick Hide+30 max HP. No other effect for boss.
Merchant PrinceNo applicable effect — dropped silently.

Multiple keystones stack. If both Pyromaniac and Glass Cannon are present, the boss deals Fire damage at x2 multiplier with halved HP — a glass-cannon fire mage the player presumably built and must now defeat carefully.

3.8 AI Governor — Scoring vs. Interference Decision

Each turn The Curse evaluates three factors to decide between scoring (rolling for hand damage) and interfering (using an interference action directly without rolling):

Decision inputs:

  • player_hp_ratio = current_player_hp / player_max_hp (0.0–1.0)
  • player_last_hand_damage = damage the player dealt last turn
  • echo_hp_ratio = echo_current_hp / echo_max_hp (0.0–1.0)
  • turns_since_last_interference = counter, resets on interference

Decision table (evaluated top-to-bottom, first match wins):

ConditionDecisionReasoning
turns_since_last_interference >= 3INTERFEREPrevent pure damage loop; force player to react
player_hp_ratio < 0.25SCOREPlayer is low; close the kill
player_last_hand_damage > echo_max_hp * 0.35INTERFEREPlayer about to burst; disrupt them
echo_hp_ratio < 0.3SCOREEcho is low; desperate aggression
player_hp_ratio > 0.7 AND echo_hp_ratio > 0.5INTERFEREEarly game pressure; establish dominance
defaultSCOREFall back to dealing damage

This ensures the boss alternates aggression and disruption without being purely random or purely predictable. The 3-turn interference guarantee creates the same rhythm pressure as the existing enemy turn system.

3.9 Default "Fallen Hero" Build (First Playthrough)

Used when no echo_save.json exists. Designed as a moderately strong mid-tier build — harder than the Arch Demon, beatable on a competent first run.

{
  "version": 1,
  "timestamp": 0,
  "archetype_id": "wanderer",
  "display_name": "The Fallen Hero",
  "dice_count": 6,
  "relic_ids": [
    "adaptable",
    "twin_dice",
    "elemental_lens",
    "sharpened_edge",
    "lucky_streak"
  ],
  "keystone_ids": ["elementalist"],
  "skill_points_spent": 45,
  "floor_reached": 45,
  "run_duration_sec": 0.0
}

Rationale: Wanderer's "Adaptable" relic rewards unique values, which maps cleanly to a CHAOS interference threat. Elementalist keystone gives the default boss elemental capabilities without a hard elemental lock. Five relics sit at the Category A/B cap. 45 SP is roughly a 3-4 run veteran's tree — aspirational but not a fully maxed build. The Fallen Hero flavor text reads: "A wanderer who found glory, and paid the price."

3.10 Cutscene Integration

Two cutscene beats hook into the Player-Echo system. Both use the existing cutscene_manager.gd framework.

Reveal Cutscene (plays when the Act 3 boss node is entered, before combat):

  • Panel 1: Darkened throne room. Silhouette of an armored figure seated on the boss throne.
  • Panel 2: Close-up of the figure's relic slots — visually shows the echo's stored relics (or the Fallen Hero relics on first run). Caption: "Once a hero, like you."
  • Panel 3: Figure rises. Caption: "The curse does not forget."
  • Panel 4: Combat screen loads.

Dynamic element: the archetype sprite for the stored archetype_id is used for the seated figure silhouette. If no echo (first run), use the Wanderer sprite.

Curse Ceremony Cutscene (plays immediately after The Curse is defeated, before the victory screen):

  • Panel 1: The defeated echo dissolves. Caption: "The curse is broken… for now."
  • Panel 2: Player character kneels. Caption: "But the throne demands a new guardian."
  • Panel 3: Caption: "Your deeds are written into the dungeon." Text shows the current archetype and two highlighted relics (first two relic_ids).
  • Panel 4: Caption: "The next hero will know your name."
  • Panel 5: Victory screen loads.

The ceremony only plays if the echo save is being updated (i.e., the player has now beaten their own previous echo). On the very first kill (defeating Fallen Hero), a shorter variant plays — Panels 1 and 4 only, with generic caption "The cycle begins."

3.11 UI / Presentation Elements

Boss nameplate: "The Curse — Fallen [Archetype Name]" e.g. "The Curse — Fallen Gambler". First run shows "The Curse — The Fallen Hero".

Relic display: During combat, The Curse's active relic passives (Category A and B only, max 6) are shown in a small sidebar panel labeled "Their Relics". Each relic icon is greyscale with a faint glow to distinguish from the player's colorful relics. Category C relics are NOT shown (already dropped).

Keystone badges: Active keystones are shown as small badge icons below the boss HP bar (same icon as the skill tree node art). Mousing over / tapping shows the translated passive description.

Pre-combat recap (summary line below the reveal cutscene, before combat begins): "[Archetype] — [X] relics — [Y] keystones — [Z] dice" e.g. "Gambler — 5 relics — 2 keystones — 6 dice."


4. Formulas

4.1 Echo HP

echo_max_hp = BASE_HP + (skill_points_spent * HP_PER_SP) + keystone_hp_bonus

BASE_HP         = 200          (flat base, higher than Arch Demon's 180)
HP_PER_SP       = 1.5          (each SP spent adds 1.5 max HP to the echo)
keystone_hp_bonus = sum of:
    Glass Cannon keystone: -0.5 * (BASE_HP + sp_component)  [applies after sum]
    Thick Hide keystone:   +30
    Stormcaller keystone:  -15
    Gale Force keystone:   -15
    (all other keystones): +0

Example — Fallen Hero (45 SP, Elementalist keystone, no HP modifiers):

echo_max_hp = 200 + (45 * 1.5) + 0
            = 200 + 67.5 + 0
            = 267 (floor to int)

Example — Glass Cannon Pyromaniac (67 SP, Glass Cannon + Pyromaniac):

base_component = 200 + (67 * 1.5) = 200 + 100.5 = 300.5
glass_cannon_penalty = -0.5 * 300.5 = -150.25
echo_max_hp = 300.5 - 150.25 = 150 (floor to int)

Valid range: 100 (minimum enforced floor) to ~400 (theoretical max: 100 SP, Thick Hide, no negative keystones = 200 + 150 + 30 = 380).

4.2 Echo Hand Scoring

The Curse scores hands using the same chip/multiplier table as the player (defined in hand_scorer.gd). The formula is:

echo_hand_damage = (base_chips + sum(scoring_die_values) + relic_chip_bonus)
                   * (base_mult + relic_mult_bonus)
                   * keystone_mult_modifier
                   * ECHO_DAMAGE_SCALAR

base_chips          = from hand type table (e.g., Full House = 14 chips)
scoring_die_values  = sum of die face values contributing to the hand
relic_chip_bonus    = sum of Category A chip bonuses from active relics
base_mult           = from hand type table (e.g., Full House = x2.0)
relic_mult_bonus    = sum of Category B mult bonuses triggered this turn
keystone_mult_modifier = product of applicable keystone multipliers:
    Glass Cannon:   x2.0
    Purist:         x1.5 (non-elemental hands only)
    Elementalist:   x1.3 (always)
    (others):       x1.0
ECHO_DAMAGE_SCALAR  = 0.85 (global tuning knob — keeps echo from one-shotting)

Example — Fallen Hero scores a Full House (3+2) with dice [3,3,3,5,5]:

base_chips        = 14
scoring_die_values = 3+3+3+5+5 = 19
relic_chip_bonus  = 0 (no relevant relics in default build for Full House)
base_mult         = 2.0
relic_mult_bonus  = 0 (no triggered bonuses this turn)
keystone_mult     = 1.3 (Elementalist)
ECHO_DAMAGE_SCALAR = 0.85

echo_hand_damage = (14 + 19 + 0) * (2.0 + 0) * 1.3 * 0.85
                 = 33 * 2.0 * 1.3 * 0.85
                 = 33 * 2.21
                 = 72.93 → floor to 72 damage

Target damage range per turn: 50-100. Maximum credible single-turn hit (Eight of a Kind equivalent with Glass Cannon): approximately 350. Player max HP at this point is ~80-120 (depending on tree), so this is a one-shot risk — by design for Glass Cannon echoes.

4.3 Echo Elemental Chance

elemental_chance_per_die = BASE_ELEM_CHANCE
                           + relic_elem_bonus
                           + keystone_elem_override

BASE_ELEM_CHANCE  = 0.05  (5% per die per roll)
relic_elem_bonus  = sum of all Category A elemental bonuses
keystone_elem_override:
    Pyromaniac:   ALL dice are Fire (chance irrelevant — deterministic)
    Permafrost:   Ice chance = 1.0, all others = 0
    Elementalist: Each element equally distributed (each = 0.25)
    Purist:       Override to 0.0 (no elementals ever)
    Others:       No override, base + relic applies

4.4 Turn Structure Timing

The Curse's full turn is resolved in a single server-side computation; results are then animated for the player. Animation timing matches the existing anim_config.gd values so the echo feels like a fast enemy, not an instant skip:

  • Roll phase animation: same as standard enemy attack animation (0.6s)
  • Hand display: 0.8s hold so the player can read the scored hand
  • Interference animation: 0.5s (same as existing interference intents)

4.5 SP-Scaling Reference Table

SP SpentEcho HPApprox Dmg/Turn (no keystones)
0 (fresh/default)20045-70
2523750-80
45 (Fallen Hero)26755-90
6730065-100
8532770-110
100 (max)35075-120

5. Edge Cases

5.1 No Echo Save (First Playthrough)

Handled by: always loading FALLEN_HERO_BUILD constant when FileAccess.file_exists("user://echo_save.json") returns false. The Fallen Hero build is hardcoded in the new echo_boss_manager.gd. No file read attempt is made; no error path triggers.

5.2 Corrupted or Malformed Echo Save

If the JSON parses but is missing required fields, each field falls back to a safe default:

  • archetype_id missing → "wanderer"
  • dice_count missing or < 5 → 5
  • relic_ids missing → [] (zero relics, Category A/B passives are empty)
  • keystone_ids missing → [] (no keystone modifiers)
  • skill_points_spent missing → 0 (produces BASE_HP echo)

If JSON parsing fails entirely (corrupted file), log a warning and fall back to the Fallen Hero build. Do NOT delete the save file automatically — present a non-blocking warning in the pre-combat UI: "Echo save may be corrupted. Fighting a default challenger."

5.3 Echo Has Zero Relics

Fully valid state. The Curse fights with base stats and archetype interference only. This is the weakest possible echo (early run builds, or a run deliberately taken without picking relics — the "No Relics" challenge). The fight is easier than the Fallen Hero, which is intentional: the echo reflects the player's actual build quality.

5.4 Echo Has More Than 6 Relics (Relic Cap Applied)

The relic cap (6 active passives) sorts relic_ids by category priority (Category A first, then B, then C is dropped), then by index in the stored array. The player sees exactly which 6 are active in the "Their Relics" sidebar. No warning is surfaced — from a narrative standpoint, only some of the hero's relics "cursed" into the dungeon.

5.5 Echo Has Conflicting Keystones

Some keystone combinations are logically contradictory (Pyromaniac + Permafrost both set elemental dice to a single element). If the player somehow allocated both (via a future design change), the first keystone in the keystone_ids array wins. Log a designer warning in debug builds: "Echo has conflicting keystones: [list]. Using first in array."

In practice, the player cannot allocate Pyromaniac + Permafrost simultaneously (they are mutually exclusive choice locks in the skill tree), so this edge case is defensive-only.

5.6 Echo Dice Count Below 5

Minimum enforced to 5 at load time. Echo save should never store fewer than 5 (base pool is 5 and cannot decrease below that in the current build), but future relics or debuffs could theoretically reduce it. The clamp prevents the boss from having an incoherent dice pool.

5.7 Echo Dice Count Above 8

The player dice pool caps at 8 (via relics). If somehow a stored value exceeds 8, clamp to 8. Future-proofing only.

5.8 Glass Cannon HP Minimum

After applying the Glass Cannon halving, echo HP is clamped to a minimum of 100. A Glass Cannon echo should feel like a threat even when fragile — 100 HP still requires 2-3 strong player hands to kill.

5.9 Player Defeats The Curse on the Same Run That Loaded It

This is the normal "beat your own echo" case. The Curse Ceremony plays. The new echo save written reflects the current run's build, not the old echo. This is correct — the cycle advances by one generation.

5.10 Player Quits Mid-Combat Against The Curse

Standard quit behavior: the run is abandoned (same as dying). The echo save is NOT updated. The same echo waits next run. This prevents players from quitting to protect a good echo from being replaced.

5.11 Community Boss Import (Future Expansion)

The JSON schema is designed to be shareable. A future "import echo" feature would write a community-supplied JSON to user://echo_save.json. Validation must reject:

  • Unknown archetype IDs
  • Relic IDs not present in relic_database.gd
  • Keystone IDs not present in skill_tree_data.gd
  • dice_count outside [5, 8]
  • skill_points_spent outside [0, 100]

Invalid imported builds fall back to the Fallen Hero rather than crashing.

5.12 Multiple Victories in a Single Play Session

If the player kills The Curse twice in one session (by restarting the run after victory), the second kill overwrites the echo save a second time. The second run's build becomes the new echo. This is correct: "the latest victor becomes the guardian."

5.13 Degenerate Strategy — Deliberately Weak Echo

A player could intentionally end a run with minimal relics and no keystones to set a weak echo for future runs. This is a valid player choice (Sirlin: respect meaningful strategy), not an exploit. The game does not penalize it. Achievers who want hard self-competition will naturally build strong echoes. Players who want easier Act 3 runs can maintain a weak echo. The Fallen Hero default prevents new players from being stuck with a zero-relic echo indefinitely (since the Fallen Hero is always the fallback when the save does not exist, not when it exists but is weak).

5.14 Degenerate Strategy — Echo Synergy Overload

A maximally built echo (100 SP, 6 translated relics, 2-3 synergistic keystones, 8 dice) could theoretically outdamage any player's survivability. The ECHO_DAMAGE_SCALAR (0.85) and the 6-relic cap are the primary mitigations. If playtesting reveals the echo is still one-shotting players, the secondary mitigation is per-turn damage cap: min(echo_hand_damage, player_max_hp * 0.6) — no single echo hand can exceed 60% of the player's max HP. This is a DISABLED tuning knob by default; enable only if needed.


6. Dependencies

6.1 What This System Consumes

SystemDependencyDirection
relic_database.gdMust expose echo_category field per relicRead
skill_tree_data.gdMust expose keystone IDs as constantsRead
archetype_data.gdMust expose base reroll count per archetype IDRead
hand_scorer.gdReused directly for echo hand evaluationRead
dice_combat_manager.gdThe Curse is registered as an enemy entityBidirectional
enemy_database.gdEcho enemy is a new EnemyData entry or subclassWrite
cutscene_manager.gdTwo new cutscene IDs must be registeredWrite
solo_game_manager.gdMust hook on_boss_victory to serialize echoWrite
run_history.gdInformational only — echo data is stored separatelyNone

6.2 What This System Provides

ConsumerWhat Is Provided
dice_combat_manager.gdEchoEnemy resource conforming to EnemyData contract
cutscene_manager.gdecho_reveal and curse_ceremony cutscene data
solo_game_manager.gdEchoBossManager singleton API: load_echo(), serialize_echo(run_data)
UI layerEchoBossManager.get_echo_display_data() → dict with display_name, archetype, active_relics, active_keystones, dice_count

6.3 New Files Required

FilePurpose
src/gameplay/echo_boss_manager.gdLoads/saves echo, constructs EchoEnemy, exposes display API
src/gameplay/echo_enemy.gdSubclass of EnemyData or parallel resource; holds echo-specific roll/score logic
assets/data/echo_boss_config.jsonAll tuning knobs (see Section 7) — never hardcoded in .gd files
assets/data/echo_fallen_hero.jsonThe default Fallen Hero build (editable by designer without code change)
user://echo_save.jsonRuntime save file — gitignored, user-owned

6.4 Bidirectional Notes

  • relic_database.gd does not depend on echo_boss_manager.gd, but it MUST be updated to add echo_category to each relic's data dict. This is a data authoring dependency, not a code dependency.
  • enemy_database.gd should be informed that a dynamic enemy type exists (EchoEnemy) that is not registered at startup but spawned at runtime.

7. Tuning Knobs

All values live in assets/data/echo_boss_config.json.

KnobCategoryDefaultSafe RangeEffect
BASE_HPCurve200150–280Echo's HP floor (zero-SP build)
HP_PER_SPCurve1.50.8–2.5How much each skill point adds to HP
ECHO_DAMAGE_SCALARCurve0.850.6–1.0Global echo damage multiplier. <0.7 makes echo trivial; >0.95 risks one-shots
RELIC_CAPGate63–8Max active relic passives. Lower = less snowball; higher = more identity fidelity
INTERFERENCE_FORCE_INTERVALGate32–5Turns before guaranteed interference. Lower = more disruption; higher = more scoring
PER_TURN_DAMAGE_CAP_ENABLEDGatefalseEnable emergency cap (player_max_hp * 0.6) if echo one-shots occur in testing
PER_TURN_DAMAGE_CAP_RATIOCurve0.60.4–0.8If cap enabled: max fraction of player max HP per echo hand. Only active when cap is enabled
MIN_ECHO_HPGate10080–150Absolute floor for Glass Cannon / low-SP echoes
MAX_RELIC_PASSIVES_CATEGORY_AGate42–6Max Category A (stat) relics applied
MAX_RELIC_PASSIVES_CATEGORY_BGate21–4Max Category B (triggered) relics applied
ECHO_ROLL_SEED_SALTFeel7919any intSalt added to run seed for echo's dice RNG. Change to alter echo dice "personality" without changing player RNG
FALLEN_HERO_BUILD_PATHGate"res://assets/data/echo_fallen_hero.json"Path to default build file. Redirect to test a specific build without a real save

Note on MAX_RELIC_PASSIVES_CATEGORY_A and MAX_RELIC_PASSIVES_CATEGORY_B: These sum to RELIC_CAP. If the sum of the two sub-caps exceeds RELIC_CAP, the lower overall cap takes precedence.


8. Acceptance Criteria

Functional Criteria

IDCriterionPass Condition
F1First playthrough loads Fallen Heroecho_save.json absent → The Curse uses Fallen Hero build. Verify boss nameplate reads "The Curse — The Fallen Hero".
F2Echo save written after victoryAfter defeating The Curse, echo_save.json exists and contains the player's archetype, relic IDs, and keystone IDs from the winning run.
F3Echo save NOT written on defeatAfter dying to The Curse, echo_save.json content unchanged from before the run.
F4Serialized build matches fight stateVerify that the echo_save.json written after run A exactly matches the build The Curse uses in run B (archetype, dice count, relics).
F5Relic cap enforcedBuild a mock echo with 10 relics (mix of categories). Verify combat UI shows exactly 6 and others are silently dropped.
F6Corrupted save falls backManually corrupt echo_save.json. Verify no crash; Fallen Hero loads; non-blocking warning appears.
F7Keystone passives apply correctlyEcho with Glass Cannon: verify echo HP is approx half of non-Glass Cannon echo at same SP. Echo with Purist: verify no elemental dice appear.
F8Interference interval enforcedPlay 5 consecutive turns against The Curse. Verify that at most 3 consecutive scoring turns occur without an interference turn.
F9Deterministic dice per run seedLoad the same run seed twice. Verify The Curse rolls the same sequence of values each time.
F10Reveal cutscene plays before combatNavigate to Act 3 boss node. Verify echo_reveal cutscene fires before the combat screen loads.
F11Curse Ceremony plays after victoryDefeat The Curse. Verify curse_ceremony cutscene fires before the victory screen.
F12Category C relics are silently ignoredBuild a mock echo with only economy relics (all Category C). Verify The Curse's sidebar shows "No active relics" or equivalent. Verify no crash.

Experiential Criteria (Playtest Validation)

IDCriterionValidation Method
E1The reveal cutscene produces a recognition momentPlaytest session: observe player reaction at the boss reveal. Target: >70% of testers verbally acknowledge recognizing their past build.
E2The fight feels meaningfully different from the Arch DemonPost-session survey: ask "Did the final boss feel unique compared to other bosses?" Target: >80% yes.
E3The Curse does not feel unfairPost-session survey: "Was the final boss's difficulty fair?" Target: <20% "unfair" responses. Adjust ECHO_DAMAGE_SCALAR if result exceeds 25%.
E4Players understand WHY they lostIf player loses to The Curse: observe if they can articulate what killed them. Target: >60% can name the specific relic or keystone responsible.
E5Curse Ceremony creates emotional weightObserve player reaction to the ceremony. Target: >50% show a behavioral pause (replaying dialogue, commenting on the narrative).
E6"Arms race" motivation triggersFollow-up survey after 3+ runs: "Did knowing your build would become the boss change how you build?" Target: >50% yes.

9. New Achievements

These achievements are added to achievement_manager.gd as part of this system. SP rewards below follow the existing achievement economy: 2-8 SP, one-time, not retroactive.

IDNameDescriptionSP RewardUnlock Condition
echo_first_killOuroborosDefeat The Curse for the first time.8First win against any echo (including Fallen Hero).
echo_beat_selfBetter Than YesterdayDefeat an echo that was your own build.5Win against an echo written from a real player victory (not Fallen Hero).
echo_glass_cannonShattered MirrorDefeat a Glass Cannon echo.3Win when the active echo has the Glass Cannon keystone.
echo_max_buildLegacyDefeat an echo built on 85+ skill points.5Win when echo_save.skill_points_spent >= 85.
echo_no_relic_echoHumble OriginsDefeat an echo with 0 active translated relics.2Win when The Curse has 0 Category A/B relics (all dropped or none stored).
echo_speed_killNo MercyDefeat The Curse in 3 turns or fewer.5Internal: track echo_turns_survived <= 3 when the kill blow lands.
echo_survive_glass_cannon_hitClose CallTake a single hit of 60+ damage from The Curse and survive.2echo_hand_damage >= 60 AND player_hp > 0 after the hit.
echo_curatorEndless CycleDefeat The Curse 10 times across all runs.3Cumulative win counter stored in achievement save: echo_kills >= 10.

Appendix A: Schema Migration Path

When echo_save.json version field is less than the current schema version, run the migration function in echo_boss_manager.gd:

FromToMigration
missing/01Treat as no save; load Fallen Hero
12 (future)Add new fields with defaults; increment version; re-save

Never delete the user's echo save during migration. Always preserve what can be preserved and default the rest.


Appendix B: Systems Index Update

This system should be added to design/gdd/systems-index.md as:

#System NameCategoryPriorityStatusDesign DocDepends On
17Player-Echo BossGameplay / PersistencePost-MVPDesigndesign/gdd/player-echo-boss.mdRelic System, Skill Tree, Archetype System, Dice Combat Manager, Run History
Built with LogoFlowershow