Player-Echo Boss: "The Curse"
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
- Recognition (cutscene reveal): "That's MY loadout." Surprise shades into pride, then unease.
- 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.
- 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:
| Field | Type | Description |
|---|---|---|
version | int | Schema version for migration. Current: 1. |
timestamp | int | Unix time of the winning run. |
archetype_id | StringName | One of: wanderer, gambler, bruiser, trickster, strategist, elementalist, atheist |
display_name | String | Auto-generated: "Fallen [Archetype Display Name]" |
dice_count | int | Total dice in pool at time of echo capture (5-8). |
relic_ids | Array[StringName] | Ordered list of relic IDs the player held at end of run. Max 12. |
keystone_ids | Array[StringName] | Keystones allocated in the skill tree snapshot. 0-3 entries. |
skill_points_spent | int | Total SP spent in tree (informational; used to scale base stats). |
floor_reached | int | Always 45 for a valid echo (Act 3 boss kill). |
run_duration_sec | float | Run 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.
| Stat | Source |
|---|---|
| Max HP | Formula — see Section 4 |
| Dice count | dice_count from echo save |
| Rerolls per turn | Archetype base rerolls (see table below) + keystone bonuses |
| Damage per hand | Echo hand scoring formula — see Section 4 |
| Interference actions | Fixed pool + archetype-specific actions |
Archetype base rerolls for The Curse:
| Archetype | Base Rerolls |
|---|---|
| wanderer | 2 |
| gambler | 3 |
| bruiser | 2 |
| trickster | 3 |
| strategist | 1 |
| elementalist | 2 |
| atheist | 2 |
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):
- Roll Phase: The Curse rolls
dice_countd6. 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). - 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.
- 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.
- 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).
- 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.
- 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):
| Action | Effect | Weight |
|---|---|---|
| SNIPE | Set 1 random unheld die to 1 | 20 |
| CHAOS | Re-randomize all unheld dice | 15 |
| WEAKEN | Player's next hand: chips -20% | 20 |
| GRAVITY | Force-hold 1 random die (player cannot unhold it) | 15 |
| STEAL_REROLL | Remove 1 player reroll this turn | 15 |
| CURSE | Apply 1 stack of Vulnerable to player | 15 |
Archetype-specific additions:
| Archetype | Extra Action | Effect | Weight |
|---|---|---|---|
| gambler | JINX | Player's next reroll upgrades no dice (reroll wasted) | 25 |
| trickster | LOCK_HOLD | Prevent player from holding any new dice this turn | 25 |
| strategist | RIG | Force 2 specific dice to show a value The Curse chooses | 25 |
| bruiser | CRUSH | Deal 8 direct HP damage in addition to scoring damage | 25 |
| elementalist | STATIC | Remove elemental type from 2 random dice | 25 |
| wanderer | STEAL_DIE | Remove 1 player die from pool for 1 turn | 25 |
| atheist | NULLIFY | Player's elemental combo does not trigger this turn | 25 |
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.
| Relic | Passive Effect on The Curse |
|---|---|
| Twin Dice | +1 to The Curse's dice count |
| Extra Reroll | +1 reroll per turn |
| Loaded Dice | Pairs score +12 chips |
| Sequence Master | +3 chips per die in longest straight |
| Go Big | Each 6 scored: +8 chips; each 5: +4 chips |
| Penny Pincher | Fives 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.
| Relic | Trigger Condition | Boss Effect |
|---|---|---|
| Lucky Streak | After a Five-of-a-Kind or better | Next attack ignores player Block |
| Sharpened Edge | After scoring any straight | +0.3 to multiplier this turn |
| Combo Catalyst | After elemental combo triggers | Combo damage +25% |
| Pyrrhic Victory | Player's HP below 40% | +15% all damage dealt |
| Volatility Engine | After rerolling all 5+ dice | Next 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.
| Relic | Reason Dropped |
|---|---|
| Gold-generating relics | Economy irrelevant to boss |
| Shop discount relics | No shop context |
| Heal relics | Healing ignored (boss has fixed HP) |
| Map navigation relics | No map traversal |
| Consumable slot relics | Boss 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.
| Keystone | Boss Passive |
|---|---|
| Pyromaniac | All The Curse's dice are Fire elemental. Burn tick damage x2 if applied to player. |
| Permafrost | Ice combo damage +50%. Freeze duration on player +1 turn. |
| Stormcaller | Lightning combos chain to 1 extra interference action. |
| Gale Force | Wind combos trigger +1 additional hit. |
| Elementalist | All 4 elements equally distributed. Combo damage +30%. |
| Purist | No elemental dice. All hand scores x1.5. +1 reroll. |
| Glass Cannon | All 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 Prince | No 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 turnecho_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):
| Condition | Decision | Reasoning |
|---|---|---|
turns_since_last_interference >= 3 | INTERFERE | Prevent pure damage loop; force player to react |
player_hp_ratio < 0.25 | SCORE | Player is low; close the kill |
player_last_hand_damage > echo_max_hp * 0.35 | INTERFERE | Player about to burst; disrupt them |
echo_hp_ratio < 0.3 | SCORE | Echo is low; desperate aggression |
player_hp_ratio > 0.7 AND echo_hp_ratio > 0.5 | INTERFERE | Early game pressure; establish dominance |
| default | SCORE | Fall 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 Spent | Echo HP | Approx Dmg/Turn (no keystones) |
|---|---|---|
| 0 (fresh/default) | 200 | 45-70 |
| 25 | 237 | 50-80 |
| 45 (Fallen Hero) | 267 | 55-90 |
| 67 | 300 | 65-100 |
| 85 | 327 | 70-110 |
| 100 (max) | 350 | 75-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_idmissing → "wanderer"dice_countmissing or < 5 → 5relic_idsmissing → [] (zero relics, Category A/B passives are empty)keystone_idsmissing → [] (no keystone modifiers)skill_points_spentmissing → 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_countoutside [5, 8]skill_points_spentoutside [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
| System | Dependency | Direction |
|---|---|---|
relic_database.gd | Must expose echo_category field per relic | Read |
skill_tree_data.gd | Must expose keystone IDs as constants | Read |
archetype_data.gd | Must expose base reroll count per archetype ID | Read |
hand_scorer.gd | Reused directly for echo hand evaluation | Read |
dice_combat_manager.gd | The Curse is registered as an enemy entity | Bidirectional |
enemy_database.gd | Echo enemy is a new EnemyData entry or subclass | Write |
cutscene_manager.gd | Two new cutscene IDs must be registered | Write |
solo_game_manager.gd | Must hook on_boss_victory to serialize echo | Write |
run_history.gd | Informational only — echo data is stored separately | None |
6.2 What This System Provides
| Consumer | What Is Provided |
|---|---|
dice_combat_manager.gd | EchoEnemy resource conforming to EnemyData contract |
cutscene_manager.gd | echo_reveal and curse_ceremony cutscene data |
solo_game_manager.gd | EchoBossManager singleton API: load_echo(), serialize_echo(run_data) |
| UI layer | EchoBossManager.get_echo_display_data() → dict with display_name, archetype, active_relics, active_keystones, dice_count |
6.3 New Files Required
| File | Purpose |
|---|---|
src/gameplay/echo_boss_manager.gd | Loads/saves echo, constructs EchoEnemy, exposes display API |
src/gameplay/echo_enemy.gd | Subclass of EnemyData or parallel resource; holds echo-specific roll/score logic |
assets/data/echo_boss_config.json | All tuning knobs (see Section 7) — never hardcoded in .gd files |
assets/data/echo_fallen_hero.json | The default Fallen Hero build (editable by designer without code change) |
user://echo_save.json | Runtime save file — gitignored, user-owned |
6.4 Bidirectional Notes
relic_database.gddoes not depend onecho_boss_manager.gd, but it MUST be updated to addecho_categoryto each relic's data dict. This is a data authoring dependency, not a code dependency.enemy_database.gdshould 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.
| Knob | Category | Default | Safe Range | Effect |
|---|---|---|---|---|
BASE_HP | Curve | 200 | 150–280 | Echo's HP floor (zero-SP build) |
HP_PER_SP | Curve | 1.5 | 0.8–2.5 | How much each skill point adds to HP |
ECHO_DAMAGE_SCALAR | Curve | 0.85 | 0.6–1.0 | Global echo damage multiplier. <0.7 makes echo trivial; >0.95 risks one-shots |
RELIC_CAP | Gate | 6 | 3–8 | Max active relic passives. Lower = less snowball; higher = more identity fidelity |
INTERFERENCE_FORCE_INTERVAL | Gate | 3 | 2–5 | Turns before guaranteed interference. Lower = more disruption; higher = more scoring |
PER_TURN_DAMAGE_CAP_ENABLED | Gate | false | — | Enable emergency cap (player_max_hp * 0.6) if echo one-shots occur in testing |
PER_TURN_DAMAGE_CAP_RATIO | Curve | 0.6 | 0.4–0.8 | If cap enabled: max fraction of player max HP per echo hand. Only active when cap is enabled |
MIN_ECHO_HP | Gate | 100 | 80–150 | Absolute floor for Glass Cannon / low-SP echoes |
MAX_RELIC_PASSIVES_CATEGORY_A | Gate | 4 | 2–6 | Max Category A (stat) relics applied |
MAX_RELIC_PASSIVES_CATEGORY_B | Gate | 2 | 1–4 | Max Category B (triggered) relics applied |
ECHO_ROLL_SEED_SALT | Feel | 7919 | any int | Salt added to run seed for echo's dice RNG. Change to alter echo dice "personality" without changing player RNG |
FALLEN_HERO_BUILD_PATH | Gate | "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
| ID | Criterion | Pass Condition |
|---|---|---|
| F1 | First playthrough loads Fallen Hero | echo_save.json absent → The Curse uses Fallen Hero build. Verify boss nameplate reads "The Curse — The Fallen Hero". |
| F2 | Echo save written after victory | After defeating The Curse, echo_save.json exists and contains the player's archetype, relic IDs, and keystone IDs from the winning run. |
| F3 | Echo save NOT written on defeat | After dying to The Curse, echo_save.json content unchanged from before the run. |
| F4 | Serialized build matches fight state | Verify that the echo_save.json written after run A exactly matches the build The Curse uses in run B (archetype, dice count, relics). |
| F5 | Relic cap enforced | Build a mock echo with 10 relics (mix of categories). Verify combat UI shows exactly 6 and others are silently dropped. |
| F6 | Corrupted save falls back | Manually corrupt echo_save.json. Verify no crash; Fallen Hero loads; non-blocking warning appears. |
| F7 | Keystone passives apply correctly | Echo 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. |
| F8 | Interference interval enforced | Play 5 consecutive turns against The Curse. Verify that at most 3 consecutive scoring turns occur without an interference turn. |
| F9 | Deterministic dice per run seed | Load the same run seed twice. Verify The Curse rolls the same sequence of values each time. |
| F10 | Reveal cutscene plays before combat | Navigate to Act 3 boss node. Verify echo_reveal cutscene fires before the combat screen loads. |
| F11 | Curse Ceremony plays after victory | Defeat The Curse. Verify curse_ceremony cutscene fires before the victory screen. |
| F12 | Category C relics are silently ignored | Build 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)
| ID | Criterion | Validation Method |
|---|---|---|
| E1 | The reveal cutscene produces a recognition moment | Playtest session: observe player reaction at the boss reveal. Target: >70% of testers verbally acknowledge recognizing their past build. |
| E2 | The fight feels meaningfully different from the Arch Demon | Post-session survey: ask "Did the final boss feel unique compared to other bosses?" Target: >80% yes. |
| E3 | The Curse does not feel unfair | Post-session survey: "Was the final boss's difficulty fair?" Target: <20% "unfair" responses. Adjust ECHO_DAMAGE_SCALAR if result exceeds 25%. |
| E4 | Players understand WHY they lost | If player loses to The Curse: observe if they can articulate what killed them. Target: >60% can name the specific relic or keystone responsible. |
| E5 | Curse Ceremony creates emotional weight | Observe player reaction to the ceremony. Target: >50% show a behavioral pause (replaying dialogue, commenting on the narrative). |
| E6 | "Arms race" motivation triggers | Follow-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.
| ID | Name | Description | SP Reward | Unlock Condition |
|---|---|---|---|---|
echo_first_kill | Ouroboros | Defeat The Curse for the first time. | 8 | First win against any echo (including Fallen Hero). |
echo_beat_self | Better Than Yesterday | Defeat an echo that was your own build. | 5 | Win against an echo written from a real player victory (not Fallen Hero). |
echo_glass_cannon | Shattered Mirror | Defeat a Glass Cannon echo. | 3 | Win when the active echo has the Glass Cannon keystone. |
echo_max_build | Legacy | Defeat an echo built on 85+ skill points. | 5 | Win when echo_save.skill_points_spent >= 85. |
echo_no_relic_echo | Humble Origins | Defeat an echo with 0 active translated relics. | 2 | Win when The Curse has 0 Category A/B relics (all dropped or none stored). |
echo_speed_kill | No Mercy | Defeat The Curse in 3 turns or fewer. | 5 | Internal: track echo_turns_survived <= 3 when the kill blow lands. |
echo_survive_glass_cannon_hit | Close Call | Take a single hit of 60+ damage from The Curse and survive. | 2 | echo_hand_damage >= 60 AND player_hp > 0 after the hit. |
echo_curator | Endless Cycle | Defeat The Curse 10 times across all runs. | 3 | Cumulative 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:
| From | To | Migration |
|---|---|---|
| missing/0 | 1 | Treat as no save; load Fallen Hero |
| 1 | 2 (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 Name | Category | Priority | Status | Design Doc | Depends On |
|---|---|---|---|---|---|---|
| 17 | Player-Echo Boss | Gameplay / Persistence | Post-MVP | Design | design/gdd/player-echo-boss.md | Relic System, Skill Tree, Archetype System, Dice Combat Manager, Run History |