# Mana Loop - Project Architecture Guide This document provides a comprehensive overview of the project architecture for AI agents working on this codebase. --- ## ⚠️ MANDATORY GIT WORKFLOW - MUST BE FOLLOWED **Before starting ANY work, you MUST:** 1. **Pull the latest changes:** ```bash cd /home/z/my-project && git pull origin master ``` 2. **Do your task** - Make all necessary code changes 3. **Before finishing, commit and push:** ```bash 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 (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 │ └── tabs/ # Tab-specific components │ ├── CraftingTab.tsx │ ├── LabTab.tsx │ ├── SpellsTab.tsx │ └── SpireTab.tsx └── lib/ ├── game/ │ ├── store.ts # Zustand store (state + 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 │ ├── crafting-slice.ts # Equipment/enchantment logic │ ├── 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 single Zustand store with the following key slices: ```typescript interface GameState { // Time day: number; hour: number; paused: boolean; // Mana rawMana: number; elements: Record; // Combat currentFloor: number; floorHP: number; activeSpell: string; castProgress: number; // Progression skills: Record; spells: Record; skillUpgrades: Record; skillTiers: Record; // Equipment equipmentInstances: Record; equippedInstances: Record; enchantmentDesigns: EnchantmentDesign[]; // Prestige insight: number; prestigeUpgrades: Record; signedPacts: number[]; } ``` ### 2. Effect System (`effects.ts`) **CRITICAL**: All stat modifications flow through the unified effect system. ```typescript // 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, // 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`**: ```typescript 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 } } ``` 2. **Add stat mapping in `effects.ts`** (if new stat): ```typescript // In computeEquipmentEffects() if (effect.stat === 'myNewStat') { bonuses.myNewStat = (bonuses.myNewStat || 0) + effect.value; } ``` 3. **Apply in game logic**: ```typescript 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) ## File Size Guidelines - Keep `page.tsx` under 2000 lines by extracting to tab components - Keep store functions focused; extract to helper files when >50 lines - Use barrel exports (`index.ts`) for clean imports