generated from nhcarrigan/template
feat: integrated expansion system (Vampire Mode + Goddess Mode) #131
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Overview
Add two post-apotheosis alternate game modes — Vampire Mode and Goddess Mode — as an integrated expansion system built directly into the core game state. Each expansion's state lives as first-class fields in
GameState(same pattern asprestige,transcendence,apotheosis) rather than under a separateexpansionskey.Supersedes #17 and #18.
Architecture
GameState Changes
Goddess Mode and Vampire Mode state fields are added directly to
GameStateat the top level. No nestedexpansionswrapper.Each expansion starts with fully default/locked state and is gated behind its unlock condition (see below).
Unlock Chain
Sync New Content (Force Sync Button)
The existing "sync new content" / force-sync flow must inject all expansion state fields for players whose saves pre-date the expansion. On sync, any missing goddess or vampire state properties are initialised to their defaults (all locked, all resources at zero, all progress at zero) so existing saves are never broken by the new content landing.
Tick Engine
The client-side tick engine (
apps/web/src/engine/tick.ts) calculates passive income and quest/exploration timers for all unlocked expansion states on every tick. Offline income calculation on load must also cover all unlocked expansions.UI — Mode Bar + Dynamic Tab Bar
Navigation uses two rows:
Mortal | Goddess | VampireThis scales cleanly to any number of future modes without adding new rows.
UI — Goddess Colour Theme
When Goddess is the selected mode, the entire site UI shifts to the Goddess colour scheme with a ~300ms CSS fade transition. Switching back to Mortal fades back to the default scheme. The game logo does not change.
Goddess palette:
Implementation: toggle a
.goddess-modeCSS class on the root element based on selected mode. All colours are driven by CSS custom properties so the swap is a single class change.Vampire Mode will follow the same pattern with its own
.vampire-modepalette (deep crimsons, blacks, desaturated purples) when implemented.UI — Resource Bar
The resource bar dropdown always shows goddess currencies (Prayers, Divinity, Stardust), even before Goddess Mode is unlocked. Pre-unlock they appear greyed/locked so players can see what's coming.
Vampire Mode
Theme
Gothic/vampire — Haunted Catacombs, Blood Mire, Obsidian Keep, Crimson Citadel, Shadow Court, The Eternal Abyss, etc.
Thematic Terminology (working names — open to revision)
Tuning (harder than base game)
Content Scale
Goddess Mode
Theme
Divine/celestial — Celestial Gardens, The Crystal Sanctum, Astral Cathedral, The Heavenly Forge, Empyrean Citadel, The Divine Heart, etc.
Thematic Terminology
Tuning (harder than Vampire Mode)
Implementation Progress
✅ Chunk 1 — Types
packages/typesGoddessEquipmentSet+computeGoddessSetBonusesaddedResourceGoddessStatecontainer +goddess?field onGameState✅ Chunk 2 — Data (at base game content scale)
Chunk 3 — Sync / Sanitize
validateAndSanitize— inject goddess state defaults for existing savessyncNewContent— inject missing goddess fieldsChunk 4 — API Routes
Chunk 5 — UI: Resource Bar + Mode/Tab Nav
Mortal | Goddess | Vampire.goddess-modeCSS class toggle on root when Goddess mode selectedChunk 6 — UI: Goddess Panels
Chunk 7 — Tick Engine
Chunk 8 — CSS Theme
.goddess-modeoverrides + fade transitionChunk 9 — About Page
HOW_TO_PLAYwith Goddess expansion documentation✨ This issue was created with help from Hikari~ 🌸
Palette Reference
Exact hex values agreed upon for each expansion's colour scheme:
Base Game
#7C3AED#A855F7#06B6D4#F59E0B#EC4899#0D0D1A#1A1A2EVampire Mode (
.vampire-mode)#5C0A1A#C41E3AGoddess Mode (
.goddess-mode)#C8A000#9EC8F0These are also reflected in the Discord milestone role colours (Apotheosis, Eternal Sovereignty, Deification).
The stats on the public profile page should be tabbed by expansion (base, prestige, transcendence, apotheosis) rather than shown all at once, to keep the layout manageable as the numbers grow.
✨ This issue was created with help from Hikari~ 🌸
Each prestige/transcendence/apotheosis reset should only reset the game state for its specific expansion (or the base game), leaving progress in other expansions intact.
✨ This issue was created with help from Hikari~ 🌸
Design correction noted during Goddess implementation:
The expansion order is Vampire Mode first, then Goddess Mode — not the other way around. The correct progression chain is:
Mortal → Apotheosis → Vampire Mode → [Vampire Apotheosis equivalent] → Goddess Mode → Deification
The full mode/mechanic mapping across all three tiers:
What this means for current code:
Mortal | Vampire | Goddess✅ (corrected)apotheosis.count >= 1✅ (corrected)Picking up Vampire Mode content tomorrow!
✨ This issue was created with help from Hikari~ 🌸
Post-implementation parity audit — outstanding gaps
The vampire and goddess expansions are now fully implemented. A parity audit against the base game identified three remaining gaps to address:
1.
/force-unlocksdebug endpoint — vampire & goddess not handleddebugRouter.post("/force-unlocks", ...)only propagates zone/quest/boss unlocks for the base game. If a player has a stuck lock in the vampire or goddess realms, calling this endpoint won't fix it. Needs equivalent unlock logic forstate.vampireandstate.goddess.2. Daily challenges — base game only
The daily challenges system (
src/data/dailyChallenges.ts, the/timersroute, and thedailyChallengePanel) exists only for the base game. Vampire and goddess have no equivalent. This is likely intentional — confirm whether daily challenges should remain base-game-exclusive or be extended to the expansions.3. Tick engine asymmetry — auto systems live in wrong place
Base game auto-adventurer logic runs inside
applyTick()inapps/web/src/engine/tick.ts. Vampire and goddess auto-quest/auto-thrall/auto-disciple logic runs insidegameContext.tsxinstead. Behaviour is equivalent but the code location is inconsistent. Low priority, but worth tidying for maintainability.✨ This comment was added with help from Hikari~ 🌸