6.4 KiB
6.4 KiB
SPEC: SpireTab Refresh & Casting Fixes
1. Objective
Fix multiple issues with the SpireTab and spell casting system:
- Cast bar not updating: Spell cast progress (
castProgress) doesn't update visually during combat - Casting doesn't cost mana: Mana costs are not deducted when spells are cast
- SpireTab full-screen experience: SpireTab should be a dedicated screen where:
- Player cannot study skills (must climb down to exit spire first)
- Layout is optimized for combat focus
- Confusing layout: Current SpireTab layout is cluttered and needs refresh for better UX
Why:
- Casting feels broken when progress bar doesn't update
- Players get free spells (no mana cost) which breaks game balance
- Spire should feel like a separate "mode" with focused combat
- Current layout confuses players about available actions
2. Controls/API
Player-Facing Controls
- Climb Up/Down buttons: Change floors (already exists)
- Spell selection: Click to set active spell (already exists)
- Enter Spire Mode: Button to enter dedicated spire screen (already exists)
- Cast progress bar: Visual indicator of spell casting progress (BROKEN - needs fix)
- Climb Down to Exit: Only way to leave spire mode (NEW behavior)
Modified Game Internals
combatStore.ts:castProgress: Should update 0-1 per tick (fix binding)processCombatTick(): Should properly deduct mana costs viadeductSpellCost()
SpireTab.tsx:- Remove study progress components (player can't study in spire)
- Remove crafting progress components (irrelevant in spire)
- Add "Climb Down" button to exit spire mode
- Refresh layout for clarity
Public API Changes
None (internal bug fixes + UI refresh)
3. Project Layout
Follow modular architecture rules from AGENTS.md:
Files to Modify
| File | Purpose | Line Count Check |
|---|---|---|
src/components/game/tabs/SpireTab.tsx |
Main SpireTab component - refresh layout, remove study/crafting | Must stay <400 lines |
src/components/game/tabs/SpireHeader.tsx |
Spire header - ensure maxFloorReached works | Must stay <400 lines |
src/components/game/tabs/FloorControls.tsx |
Floor controls - add "Climb Down to Exit" | Must stay <400 lines |
src/lib/game/stores/combat-actions.ts |
Fix mana deduction in processCombatTick() |
Must stay <400 lines |
src/lib/game/stores/combatStore.ts |
Ensure castProgress updates correctly |
Must stay <400 lines |
Files to Create
| File | Purpose | Line Count Check |
|---|---|---|
| None (modifying existing files only) |
Stores to Use (NO LEGACY STORES!)
- ✅
useCombatStorefromsrc/lib/game/stores/combatStore - ✅
useManaStorefromsrc/lib/game/stores/manaStore - ✅
usePrestigeStorefromsrc/lib/game/stores/prestigeStore - ❌ NO
import from '@/lib/game/store'(legacy!) - ❌ NO
import from '@/lib/game/store-modules/'(legacy!)
Module Ownership
- SpireTab UI:
components/game/tabs/ - Combat logic:
stores/combat-actions.ts - Store state:
stores/combatStore.ts
4. Code Style
Follow existing project conventions:
- TypeScript strict mode, explicit type annotations
- Zustand store patterns:
set(),get()for state updates - Use modular stores ONLY (AGENTS.md rule)
- Naming: camelCase for variables/functions, PascalCase for interfaces/types
- No
anytypes, use defined interfaces fromsrc/lib/game/types/ - Follow ESLint rules (run
npm run lintbefore committing) - Use existing patterns for combat/spell casting
Key Patterns
- Cast progress:
useCombatStore((s) => s.castProgress)(0-1 value) - Mana deduction: Use
deductSpellCost()fromsrc/lib/game/utils/ - Guard against undefined stores: Optional chaining
state?.castProgress
5. Testing
What to Test
- Cast bar updates:
castProgresschanges during combat ticks - Mana costs deducted: Raw mana/elements decrease when spells cast
- No studying in spire: Study components not rendered when
simpleMode=true - Climb down to exit: Button appears in spire mode, clears
spireMode - Layout refresh: SpireTab renders cleanly without clutter
How to Test
- Unit tests using Vitest (existing test framework)
- Test files in
src/lib/game/stores/__tests__/ - Mock game state to simulate combat ticks
- Assert castProgress changes over time
- Assert mana decreases after spell cast
- Use
useCombatStore.getState()for assertions
Tooling
- Vitest (test runner)
- Zustand store testing patterns (use
getState()) - Mock
deductSpellCost()to verify calls
6. Boundaries (Out-of-Scope Items)
- No changes to spell definitions or damage calculations
- No changes to attunement system (separate from spire)
- No changes to prestige/system (unless directly related to spire exit)
- No new tabs or major architectural changes
- No changes to legacy store (we're avoiding it, not fixing it here)
- No changes to other tabs (SkillsTab, CraftingTab, etc.)
Acceptance Criteria (Per Requirement)
| # | Requirement | Acceptance Criterion |
|---|---|---|
| 1 | Cast bar updates during spell casting | castProgress in combatStore changes 0→1 over time, and UI reflects this |
| 2 | Casting costs mana | rawMana or element mana decreases by spell.cost when spell completes |
| 3 | SpireTab is full-screen combat focus | Study/Crafting components NOT rendered when simpleMode=true |
| 4 | Player must climb down to exit spire | "Climb Down" button visible in spire mode, clears spireMode on click |
| 5 | Layout refresh for clarity | SpireTab has clear sections: Floor Info, Combat, Controls (no clutter) |
| 6 | Use modular stores only | Zero imports from store.ts or store-modules/ in modified files |
| 7 | All files <400 lines | Pre-commit hook passes for all modified files |
| 8 | Regression tests added | New test file spire-tab-refresh.test.ts passes in npm run test |
Verification Checklist (Do NOT implement until approved!)
- ☐ SPEC.md committed to version control (not yet)
- ☑ Every feature has explicit acceptance criterion (above)
- ☑ Out-of-scope items listed (Boundaries section)
- ☐ Human has reviewed and approved (WAITING FOR THIS)
- ☐ No implementation code exists yet (correct - spec only)
I will NOT proceed to PLAN or IMPLEMENT phases until this spec is approved by you (the human).
Please review and approve, or request changes.