Files
Mana-Loop/AGENTS.md
Z User 17c6d5652d
All checks were successful
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 3m17s
Add golemancy system, combination skills, and UI redesigns
- Remove scroll crafting skill (no consumables in idle game)
- Add golem types (Earth, Metal, Crystal) with variants (Lava, Mud, Forge, Storm)
- Implement golemancy state in store with summoning/drain mechanics
- Add combination skills requiring level 5+ in two attunements:
  - Enchanter+Fabricator: Enchanted Golems, Capacity Overflow
  - Invoker+Fabricator: Pact-Bonded Golems, Guardian Infusion
  - Invoker+Enchanter: Pact Enchantments, Elemental Resonance
- Redesign CraftingTab with sub-tabs for Enchanter/Fabricator
- Redesign SpireTab to show summoned golems and DPS contribution
- Redesign StatsTab with attunement-specific stats sections
- Update documentation (README.md, AGENTS.md)
2026-03-28 07:56:52 +00:00

14 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 (~1700 lines, single page application)
│   ├── 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    # Main action buttons (Meditate, Climb, Study, etc.)
│       ├── 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
│           ├── index.ts         # Tab component exports
│           ├── CraftingTab.tsx  # Enchantment crafting UI
│           ├── LabTab.tsx       # Skill upgrade and lab features
│           ├── SpellsTab.tsx    # Spell management and equipment spells
│           └── SpireTab.tsx     # Combat and spire climbing
└── lib/
    ├── game/
    │   ├── store.ts              # Zustand store (~1650 lines, main state + tick logic)
    │   ├── computed-stats.ts     # Computed stats functions (extracted utilities)
    │   ├── navigation-slice.ts   # Floor navigation actions (setClimbDirection, changeFloor)
    │   ├── study-slice.ts        # Study system actions (startStudying*, cancelStudy)
    │   ├── crafting-slice.ts     # Equipment/enchantment logic
    │   ├── 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
    │   ├── 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)

Key Systems

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
  • Navigation Slice (navigation-slice.ts): Floor navigation (setClimbDirection, changeFloor)
  • Study Slice (study-slice.ts): Study system (startStudyingSkill, startStudyingSpell, cancelStudy)
  • Crafting Slice (crafting-slice.ts): Equipment/enchantment (createEquipmentInstance, startDesigningEnchantment)
  • Familiar Slice (familiar-slice.ts): Familiar system (addFamiliar, removeFamiliar)

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

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 Purpose
Navigation navigation-slice.ts Floor navigation (setClimbDirection, changeFloor)
Study study-slice.ts Study system (startStudyingSkill, startStudyingSpell, cancelStudy)
Crafting crafting-slice.ts Equipment/enchantment (createEquipmentInstance, startDesigningEnchantment)
Familiar familiar-slice.ts Familiar system (addFamiliar, removeFamiliar)

Attunement System

Overview

Attunements are class-like specializations tied to body slots. Each attunement provides unique capabilities and skills.

Attunement Types

Attunement Slot Primary Mana Capabilities
Enchanter Right Hand Transference Enchanting, Disenchanting
Invoker Chest (from pacts) Pacts, Guardian Powers
Fabricator Left Hand Earth Golemancy, Gear Crafting

Leveling

  • XP is earned by using attunement-specific actions
  • Enchanter: XP from enchanting equipment (1 XP per 10 capacity used)
  • Invoker: XP from signing pacts and defeating guardians
  • Fabricator: XP from crafting equipment and golems
  • Level 5+ unlocks combination skills with other attunements

Combination Skills

Unlock at level 5+ in two attunements:

Combination Skills
Enchanter + Fabricator Enchanted Golems, Capacity Overflow, Runic Golems
Invoker + Fabricator Pact-Bonded Golems, Guardian Infusion
Invoker + Enchanter Pact Enchantments, Elemental Resonance

Golemancy System

Overview

Golems are channeling summons that deal automatic damage while draining mana.

Golem Types

Type Element Base DPS Mana Cost Drain Unlock
Earth Golem Earth 22.5 50 earth 2/hr Fabricator attunement
Metal Golem Metal 50 100 metal 3/hr Metalworking skill
Crystal Golem Crystal 100 200 crystal 5/hr Golemancy Master skill

Golem Variants

Created by embedding elemental crystals (requires Crystal Embedding skill):

  • Lava Golem: Earth + Fire (1.5x damage, burn effect)
  • Mud Golem: Earth + Water (1.2x damage, slow effect)
  • Forge Golem: Metal + Fire (1.6x damage, burn effect)
  • Storm Golem: Metal + Air (1.4x damage, shock effect)

Duration

  • Base: 1 floor
  • +1 floor per Fabricator level (max 10)

Store Methods

  • canSummonGolem(golemId) - Check if golem can be summoned
  • summonGolem(golemId, variant?) - Summon a golem
  • dismissGolem(instanceId) - Dismiss an active golem
  • getGolemDuration() - Get duration in floors
  • getActiveGolemDPS() - Get total DPS from all golems

File Size Guidelines

Current File Sizes (After Refactoring)

File Lines Notes
store.ts ~1650 Core state + tick logic (reduced from 2138, 23% reduction)
page.tsx ~1695 Main UI (reduced from 2554, 34% reduction)
computed-stats.ts ~200 Extracted utility functions
navigation-slice.ts ~50 Navigation actions
study-slice.ts ~100 Study system actions

Guidelines

  • Keep page.tsx under 2000 lines by extracting to components (ActionButtons, ManaDisplay, etc.)
  • Keep store.ts under 1800 lines by extracting to slices (navigation, study, crafting, familiar)
  • Extract computed stats and utility functions to computed-stats.ts when >50 lines
  • Use barrel exports (index.ts) for clean imports
  • Follow the slice pattern for store organization (see below)