Files
Mana-Loop/AGENTS.md
T
Refactoring Agent 454195cdfb
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 3m16s
Update hooks and ignore markdown files in size check
2026-04-29 12:18:08 +02:00

18 KiB
Executable File

Mana Loop - Project Architecture Guide

This document provides a comprehensive overview of the project architecture for AI agents working on this codebase.


🔑 Git Credentials (SAVE THESE)

Repository: git@gitea.tailf367e3.ts.net:Anexim/Mana-Loop.git

HTTPS URL with credentials:

https://zhipu:5LlnutmdsC2WirDwWgnZuRH7@gitea.tailf367e3.ts.net/Anexim/Mana-Loop.git

Credentials:

To configure git:

git config --global user.name "zhipu"
git config --global user.email "zhipu@local.local"

⚠️ MANDATORY GIT WORKFLOW - MUST BE FOLLOWED

Before starting ANY work, you MUST:

  1. Pull the latest changes:

    cd /home/z/my-project && git pull origin master
    
  2. Do your task - Make all necessary code changes

  3. Before finishing, commit and push:

    cd /home/z/my-project
    git add -A
    git commit -m "descriptive message about changes"
    git push origin master
    

This workflow is ENFORCED and NON-NEGOTIABLE. Every agent session must:

  • Start with git pull
  • End with git add, git commit, git push

Git Remote: git@gitea.tailf367e3.ts.net:Anexim/Mana-Loop.git


Project Overview

Mana Loop is an incremental/idle game built with:

  • Framework: Next.js 16 with App Router
  • Language: TypeScript 5
  • Styling: Tailwind CSS 4 with shadcn/ui components
  • State Management: Zustand with persist middleware
  • Database: Prisma ORM with SQLite (for persistence features)

Core Game Loop

  1. Mana Gathering: Click or auto-generate mana over time
  2. Studying: Spend mana to learn skills and spells
  3. Combat: Climb the Spire, defeat guardians, sign pacts
  4. Crafting: Enchant equipment with spell effects
  5. Prestige: Reset progress for permanent bonuses (Insight)

Directory Structure

src/
├── app/
│   ├── page.tsx          # Main game UI (~548 lines, reduced via component extraction)
│   ├── layout.tsx        # Root layout with providers
│   └── api/              # API routes (minimal use)
├── components/
│   ├── ui/               # shadcn/ui components (auto-generated)
│   └── game/
│       ├── index.ts      # Barrel exports
│       ├── ActionButtons.tsx    # Current action display with progress indicator
│       ├── CalendarDisplay.tsx  # Day calendar with incursion indicators
│       ├── CraftingProgress.tsx # Design/preparation/application progress bars
│       ├── StudyProgress.tsx    # Current study progress with cancel button
│       ├── ManaDisplay.tsx      # Mana/gathering section with progress bar
│       ├── TimeDisplay.tsx      # Day/hour display with pause toggle
│       └── tabs/                # Tab-specific components (Task 2: all tabs refactored)
│           ├── index.ts         # Tab component exports
│           ├── CraftingTab.tsx  # Enchantment crafting UI (~164 lines)
│           ├── LabTab.tsx       # Skill upgrade and lab features
│           ├── SpellsTab.tsx    # Spell management and equipment spells
│           ├── SpireTab.tsx     # Combat with Spire Mode (~354 lines, Task 2 overhaul)
│           ├── StatsTab.tsx     # Player statistics (~251 lines, Task 2: elements locked)
│           ├── SkillsTab.tsx    # Skill tree display (~371 lines, Task 2: Ascension deleted)
│           ├── EquipmentTab.tsx # Gear management (~435 lines)
│           ├── DebugTab.tsx     # Debug tools (~34 lines, Task 2: added Pact buttons)
│           └── LootTab.tsx      # Loot display (~48 lines, Task 2: Transference removed)
└── lib/
    ├── game/
    │   ├── store.ts              # Zustand store (~2812 lines, main state + tick logic)
    │   ├── crafting-slice.ts     # Equipment/enchantment logic (~1100 lines, from store.ts)
    │   ├── computed-stats.ts     # Computed stats functions (~12 lines, simplified)
    │   ├── navigation-slice.ts   # Floor navigation actions (~75 lines)
    │   ├── study-slice.ts        # Study system actions (~210 lines)
    │   ├── familiar-slice.ts     # Familiar system actions
    │   ├── effects.ts            # Unified effect computation
    │   ├── upgrade-effects.ts    # Skill upgrade effect definitions
    │   ├── constants.ts          # Game definitions (spells, skills, etc.)
    │   ├── skill-evolution.ts    # Skill tier progression paths (~3400 lines)
    │   ├── types.ts              # TypeScript interfaces
    │   ├── formatting.ts         # Display formatters
    │   ├── utils.ts              # Utility functions
    │   └── data/
    │       ├── equipment.ts      # Equipment type definitions
    │       └── enchantment-effects.ts  # Enchantment effect catalog
    └── utils.ts                  # General utilities (cn function)

Note: A complete, up-to-date project tree is automatically generated on each commit and saved to docs/project-structure.txt. This file is generated by the pre-commit hook using .husky/scripts/generate-project-tree.js and respects .gitignore rules.

Key Systems

0. Task 2 Completion Summary

Task 2 has been completed successfully (12/12 tasks done)!

Key changes made in Task 2:

  • ActionButtons Rework: Removed manual selection, auto-transition to Meditate after actions
  • SpireTab Overhaul: Added "Climb the Spire" button, implemented Spire Mode with exit condition
  • Equipment System: Added support for 2-Handed Weapons, Staves now block offhand slot
  • Research Locking: Prevent switching topics while study in progress
  • DebugTab Update: Added Invoker Debugging Buttons for Pacts
  • Combat UI Fix: Fixed Casting Bar progress animation
  • Crafting Limits: Disabled Prepare for non-enchanted items, limited Design to owned gear types
  • System Integrity: Fixed Show Component Names debug option for all components
  • StatsTab: Locked Fire/Water/Air/Earth at start, only Transference unlocked
  • LootTab: Removed Transference from essence list (not lootable)
  • Ascension Skills: Deleted all Ascension skills
  • Mana Well Fix: Fixed Deep Basin upgrade multiplier values

Context File Approach for Sub-Agents: During Task 2, context files were created in docs/ to guide sub-agents:

  • update_agents_context.md - Context for updating AGENTS.md
  • update_game_briefing_context.md - Context for updating GAME_BRIEFING.md
  • update_skills_context.md - Context for updating skills.md

This approach proved effective for delegating documentation updates to sub-agents.

1. State Management (store.ts)

The game uses a Zustand store organized with slice pattern for better maintainability:

Store Slices

  • Main Store (store.ts): Core state, tick logic, and main actions (~2812 lines)
  • Navigation Slice (navigation-slice.ts): Floor navigation (setClimbDirection, changeFloor) (~75 lines)
  • Study Slice (study-slice.ts): Study system (startStudyingSkill, startStudyingSpell, cancelStudy) (~210 lines)
  • Crafting Slice (crafting-slice.ts): Equipment/enchantment (createEquipmentInstance, startDesigningEnchantment) (~1100 lines)
  • Familiar Slice (familiar-slice.ts): Familiar system (addFamiliar, removeFamiliar) - NOTE: File does not currently exist

Computed Stats (computed-stats.ts)

Extracted utility functions for stat calculations:

  • computeMaxMana(), computeRegen(), computeEffectiveRegen()
  • calcDamage(), calcInsight(), getElementalBonus()
  • getFloorMaxHP(), getFloorElement(), getMeditationBonus()
  • canAffordSpellCost(), deductSpellCost()
interface GameState {
  // Time
  day: number;
  hour: number;
  paused: boolean;
  
  // Mana
  rawMana: number;
  elements: Record<string, ElementState>;
  
  // Combat
  currentFloor: number;
  floorHP: number;
  activeSpell: string;
  castProgress: number;
  
  // Progression
  skills: Record<string, number>;
  spells: Record<string, SpellState>;
  skillUpgrades: Record<string, string[]>;
  skillTiers: Record<string, number>;
  
  // Equipment
  equipmentInstances: Record<string, EquipmentInstance>;
  equippedInstances: Record<string, string | null>;
  enchantmentDesigns: EnchantmentDesign[];
  
  // Prestige
  insight: number;
  prestigeUpgrades: Record<string, number>;
  signedPacts: number[];
}

2. Effect System (effects.ts)

CRITICAL: All stat modifications flow through the unified effect system.

// Effects come from two sources:
// 1. Skill Upgrades (milestone bonuses)
// 2. Equipment Enchantments (crafted bonuses)

getUnifiedEffects(state) => UnifiedEffects {
  maxManaBonus, maxManaMultiplier,
  regenBonus, regenMultiplier,
  clickManaBonus, clickManaMultiplier,
  baseDamageBonus, baseDamageMultiplier,
  attackSpeedMultiplier,
  critChanceBonus, critDamageMultiplier,
  studySpeedMultiplier,
  specials: Set<string>,  // Special effect IDs
}

When adding new stats:

  1. Add to ComputedEffects interface in upgrade-effects.ts
  2. Add mapping in computeEquipmentEffects() in effects.ts
  3. Apply in the relevant game logic (tick, damage calc, etc.)

3. Combat System

Combat uses a cast speed system:

  • Each spell has castSpeed (casts per hour)
  • Cast progress accumulates: progress += castSpeed * attackSpeedMultiplier * HOURS_PER_TICK
  • When progress >= 1, spell is cast (cost deducted, damage dealt)
  • DPS = damagePerCast * castsPerSecond

Damage calculation order:

  1. Base spell damage
  2. Skill bonuses (combatTrain, arcaneFury, etc.)
  3. Upgrade effects (multipliers, bonuses)
  4. Special effects (Overpower, Berserker, etc.)
  5. Elemental modifiers (same element +25%, super effective +50%)

4. Crafting/Enchantment System

Three-stage process:

  1. Design: Select effects, takes time based on complexity
  2. Prepare: Pay mana to prepare equipment, takes time
  3. Apply: Apply design to equipment, costs mana per hour

Equipment has capacity that limits total enchantment power.

5. Skill Evolution System

Skills have 5 tiers of evolution:

  • At level 5: Choose 2 of 4 milestone upgrades
  • At level 10: Choose 2 more upgrades, then tier up
  • Each tier multiplies the skill's base effect by 10x

Important Patterns

Adding a New Effect

  1. Define in enchantment-effects.ts:
my_new_effect: {
  id: 'my_new_effect',
  name: 'Effect Name',
  description: '+10% something',
  category: 'combat',
  baseCapacityCost: 30,
  maxStacks: 3,
  allowedEquipmentCategories: ['caster', 'hands'],
  effect: { type: 'multiplier', stat: 'attackSpeed', value: 1.10 }
}
  1. Add stat mapping in effects.ts (if new stat):
// In computeEquipmentEffects()
if (effect.stat === 'myNewStat') {
  bonuses.myNewStat = (bonuses.myNewStat || 0) + effect.value;
}
  1. Apply in game logic:
const effects = getUnifiedEffects(state);
damage *= effects.myNewStatMultiplier;

Adding a New Skill

  1. Define in constants.ts SKILLS_DEF
  2. Add evolution path in skill-evolution.ts
  3. Add prerequisite checks in store.ts
  4. Update UI in page.tsx

Adding a New Spell

  1. Define in constants.ts SPELLS_DEF
  2. Add spell enchantment in enchantment-effects.ts
  3. Add research skill in constants.ts
  4. Map research to effect in EFFECT_RESEARCH_MAPPING

Git Hooks (Husky)

This project uses Husky to manage git hooks for automated checks and agent assistance:

Pre-Commit Hook (.husky/pre-commit)

Runs automatically before each commit:

  1. File Size Check: Ensures no staged file exceeds 400 lines (improves AI agent readability)
  2. Project Structure Generation: Updates docs/project-structure.txt with current tree (respects .gitignore)

Post-Merge Hook (.husky/post-merge)

Runs after merging branches:

  • Checks if package.json or package-lock.json changed
  • Automatically runs npm install to sync dependencies

Implementation Files

  • Hook scripts: .husky/ directory
  • File size check: .husky/scripts/check-file-size.js
  • Tree generator: .husky/scripts/generate-project-tree.js

Common Pitfalls

  1. Forgetting to call getUnifiedEffects(): Always use unified effects for stat calculations
  2. Direct stat modification: Never modify stats directly; use effect system
  3. Missing tier multiplier: Use getTierMultiplier(skillId) for tiered skills
  4. Ignoring special effects: Check hasSpecial(effects, SPECIAL_EFFECTS.X) for special abilities

Testing Guidelines

  • Run bun run lint after changes
  • Check dev server logs at /home/z/my-project/dev.log
  • Test with fresh game state (clear localStorage)

Slice Pattern for Store Organization

The store uses a slice pattern to organize related actions into separate files. This improves maintainability and makes the codebase more modular.

Creating a New Slice

  1. Create the slice file (e.g., my-feature-slice.ts):
// Define the actions interface
export interface MyFeatureActions {
  doSomething: (param: string) => void;
  undoSomething: () => void;
}

// Create the slice factory
export function createMyFeatureSlice(
  set: StoreApi<GameStore>['setState'],
  get: StoreApi<GameStore>['getState']
): MyFeatureActions {
  return {
    doSomething: (param: string) => {
      set((state) => {
        // Update state
      });
    },
    undoSomething: () => {
      set((state) => {
        // Update state
      });
    },
  };
}
  1. Add to main store (store.ts):
import { createMyFeatureSlice, MyFeatureActions } from './my-feature-slice';

// Extend GameStore interface
interface GameStore extends GameState, MyFeatureActions, /* other slices */ {}

// Spread into store creation
const useGameStore = create<GameStore>()(
  persist(
    (set, get) => ({
      ...createMyFeatureSlice(set, get),
      // other slices and state
    }),
    // persist config
  )
);

Existing Slices

Slice File Lines Purpose
Navigation navigation-slice.ts ~75 Floor navigation (setClimbDirection, changeFloor)
Study study-slice.ts ~210 Study system (startStudyingSkill, startStudyingSpell, cancelStudy)
Crafting crafting-slice.ts ~1100 Equipment/enchantment (createEquipmentInstance, startDesigningEnchantment)
Familiar familiar-slice.ts N/A Familiar system - File not found in current codebase

File Size Guidelines

Current File Sizes (After Task 2)

File Lines Size (bytes) Notes
store.ts ~2812 ~103KB Core state + tick logic, crafting-slice extracted
page.tsx ~548 ~22KB Main UI (heavily reduced through component extraction)
crafting-slice.ts ~1100 ~35KB Equipment/enchantment logic (extracted from store.ts)
skill-evolution.ts ~3400 ~120KB Skill tier progression paths
study-slice.ts ~210 ~8KB Study system actions
navigation-slice.ts ~75 ~3KB Navigation actions
computed-stats.ts ~12 ~1KB Extracted utility functions (some moved to slices)
components/game/tabs/*.tsx ~3000 ~95KB Tab-specific components (SpireTab, CraftingTab, etc.)

Guidelines

  • Keep page.tsx under 600 lines by extracting to components (ActionButtons, ManaDisplay, tabs, etc.)
  • Keep store.ts under 3000 lines by extracting to slices (navigation, study, crafting, familiar)
  • Extract computed stats and utility functions to appropriate slices or utils when >100 lines
  • Use barrel exports (index.ts) for clean imports
  • Follow the slice pattern for store organization (see below)
  • After Task 2: page.tsx reduced from ~2554 to ~548 lines (78% reduction)
  • After Task 2: store.ts increased due to crafting-slice integration, but better organized

Automated File Size Check

A pre-commit hook automatically checks all staged files. Files exceeding 400 lines will be rejected. The hook runs via Husky and uses .husky/scripts/check-file-size.js. If your file is too large, refactor it into smaller modules before committing.


🚫 BANNED CONTENT - NEVER ADD THESE

Lifesteal and Healing are BANNED

DO NOT add lifesteal or healing mechanics to player abilities.

This includes:

  • lifesteal spell effects
  • heal or regeneration abilities for the player
  • Any mechanic that restores player HP or mana based on damage dealt
  • Life-stealing weapons or enchantments

Rationale: The game's core design is that the player cannot take damage - only floors can. Healing/lifesteal mechanics are unnecessary and would create confusing gameplay.

Banned Mana Types

The following mana types have been removed and should never be re-added:

  • life - Healing/lifesteal themed (banned)
  • blood - Life + Water compound (banned due to lifesteal theme)
  • wood - Life + Earth compound (banned due to life connection)
  • mental - Mind/psionic themed (removed for design consistency)
  • force - Telekinetic themed (removed for design consistency)

🔮 Mana Types Overview

Base Mana Types (7)

Element Symbol Color Theme
Fire 🔥 #FF6B35 Destruction, burn damage
Water 💧 #4ECDC4 Flow, freeze effects
Air 🌬️ #00D4FF Speed, wind damage
Earth ⛰️ #F4A261 Stability, armor pierce
Light ☀️ #FFD700 Radiance, holy damage
Dark 🌑 #9B59B6 Shadows, void damage
Death 💀 #778CA3 Decay, rot damage

Utility Mana Types (1)

Element Symbol Color Theme
Transference 🔗 #1ABC9C Mana transfer, Enchanter attunement

Compound Mana Types (3)

Element Recipe Theme
Metal Fire + Earth Armor piercing, forged weapons
Sand Earth + Water AOE damage, desert winds
Lightning Fire + Air Fast damage, armor pierce, chain effects

Exotic Mana Types (3)

Element Recipe Theme
Crystal Sand + Sand + Light Prismatic, high damage
Stellar Fire + Fire + Light Cosmic, ultimate fire/light
Void Dark + Dark + Death Oblivion, ultimate dark/death

Mana Type Hierarchy

Base Elements (7) → Compound (3) → Exotic (3)
                      ↓
              Utility (1) ← Special attunement-based