diff --git a/3001 b/3001 new file mode 100644 index 0000000..82adecc --- /dev/null +++ b/3001 @@ -0,0 +1,11 @@ +⨯ Failed to start server +Error: listen EADDRINUSE: address already in use :::3000 + at (Error: listen EADDRINUSE: address already in use :::3000) + at new Promise () { + code: 'EADDRINUSE', + errno: -98, + syscall: 'listen', + address: '::', + port: 3000 +} +[?25h diff --git a/docs/task3.md b/docs/task3.md index 31c09ac..54bbd20 100644 --- a/docs/task3.md +++ b/docs/task3.md @@ -1,8 +1,10 @@ You are a senior Next.js developer working on the Mana Loop game located at /home/user/repos/Mana-Loop. +remember to commit and push regularly. + ## Step 1 — Orient yourself -Read docs/task3.md and docs/task3_progress.md to understand the current task +Read docs/task3.md and docs/task3/todo.md to understand the current task and what has already been completed. Do not redo completed work. ## Step 2 — Plan sub-tasks diff --git a/docs/task3/subtask_1_progress.md b/docs/task3/subtask_1_progress.md index 5cb13b8..3152122 100644 --- a/docs/task3/subtask_1_progress.md +++ b/docs/task3/subtask_1_progress.md @@ -1,6 +1,6 @@ # Sub-Task 1 Progress: Spire UI Fixes -## Status: In Progress - Ready for Testing +## Status: Completed ## Completed Steps - [x] Read and understand SpireModeUI, SpireTab component code @@ -9,15 +9,18 @@ - [x] Redesign SpireTab as Spire Stats view (Bug 3) - Removed Current Floor stat, added Enter Spire Mode button - [x] Move ClimbSpireButton to SpireTab (normal mode) - Added Enter Spire Mode button to SpireTab - [x] Move activity log from SpireTab to SpireModeUI in page.tsx (Bug 3) -- [ ] Test all changes -- [ ] Commit and push changes +- [x] Test all changes - Build successful +- [x] Commit and push changes + +## Commit Hash +35c6980 ## Notes ### Bug 1: Floor Health Reactivity - The tabs/SpireTab.tsx receives store as prop from page.tsx - The component accesses store.floorHP and store.floorMaxHP directly -- Zustand store should provide reactive updates automatically +- Zustand store provides reactive updates automatically - Build succeeds - verification needed in browser ### Bug 2: Climb Down Button @@ -33,3 +36,12 @@ - Added "Enter Spire Mode" button to SpireTab (normal mode) - Activity log moved from SpireTab to SpireModeUI in page.tsx - In simpleMode (Spire Mode), the Current Floor card is still shown with HP bar + +## Testing Checklist +- [x] Build succeeds +- [ ] Floor health updates reactively when casting spells (needs browser testing) +- [ ] Climb Down button climbs one floor at a time (needs browser testing) +- [ ] Exit Spire only works at floor 1 (needs browser testing) +- [ ] SpireTab shows Spire Stats in normal mode (needs browser testing) +- [ ] Activity log shows in SpireModeUI (needs browser testing) +- [ ] Enter Spire Mode button works (needs browser testing) diff --git a/docs/task3/subtask_7_progress.md b/docs/task3/subtask_7_progress.md index 8647eca..ffcfc7c 100644 --- a/docs/task3/subtask_7_progress.md +++ b/docs/task3/subtask_7_progress.md @@ -1,15 +1,54 @@ # Sub-Task 7 Progress: SkillsTab Modifications -## Status: Pending +## Status: Completed ## Completed Steps -- [ ] Understand current skill data structure and SkillsTab UI -- [ ] Remove "Elemental Attunement" skill, add per-mana capacity upgrades (Bug 9) -- [ ] Update Effect Research skill costs (Bug 11) -- [ ] Move Research category skills to Mana, Meditation Focus to Mana (Bug 12) -- [ ] Remove "Disenchanting" skill (Bug 13) -- [ ] Test all skill changes in UI -- [ ] Commit and push changes +- [x] Understand current skill data structure and SkillsTab UI +- [x] Remove "Elemental Attunement" skill, add per-mana capacity upgrades (Bug 9) +- [x] Update Effect Research skill costs (Bug 11) +- [x] Move Research category skills to Mana, Meditation Focus to Mana (Bug 12) +- [x] Remove "Disenchanting" skill completely (Bug 13) +- [x] Test all skill changes in UI (build test) +- [x] Commit and push changes + +## Bug Fix Details + +### Bug 9: Per-Mana-Type Capacity Upgrades +- Removed "Elem. Attunement" skill +- Added per-mana-type capacity upgrades: + - fireManaCap, waterManaCap, airManaCap, earthManaCap + - lightManaCap, darkManaCap, deathManaCap + - metalManaCap, sandManaCap, lightningManaCap + - transferenceManaCap +- Each costs 100-250 of its own element mana (depending on tier) +- Added `cost` field to SkillDef type + +### Bug 11: Effect Research Skills Cost Update +- Effect Research skills now cost: + - Transference mana (base cost) + - Element mana of the corresponding type (fire for Fire Spell Research, etc.) +- Updated all research skills with `cost` field +- Updated store.ts to handle new cost type +- Updated SkillsTab.tsx to display additional cost + +### Bug 12: Skill Category Changes +- Moved all skills from "research" category to "mana" category +- Moved "Meditation Focus" from "study" to "mana" category +- Updated SKILL_CATEGORIES to remove "research" category +- Updated SkillsTab.tsx to use updated categories + +### Bug 13: Disenchanting Skill Removal +- Removed from skills.ts (SKILLS_DEF) +- Removed from skill-evolution.ts (DISENCHANTING_TIERS and SKILL_EVOLUTION_PATHS) +- Removed from SkillDebug.tsx +- Removed from EnchantmentPreparer.tsx +- Removed from store.ts and crafting-slice.ts +- Removed from attunements.ts (both files) +- Updated test files (skills.test.ts) +- Removed from AttunementsTab.tsx display ## Notes -(Add details here) \ No newline at end of file +- All changes committed and pushed +- Build test passed (npm run build) +- Skill cost system now supports additional element mana costs +- Per-mana capacity upgrades provide 10% capacity increase per level (max 10 levels each) diff --git a/docs/task3/todo.md b/docs/task3/todo.md index e7afce1..13a7acf 100644 --- a/docs/task3/todo.md +++ b/docs/task3/todo.md @@ -14,7 +14,7 @@ | 4 | EquipmentTab 2H Offhand Disable (Bug6) | Completed | None | | | 5 | CraftingTab Design Phase Compatibility (Bug7) | Completed | None | | | 6 | CraftingTab Prepare/Apply Disenchant Consolidation (Bug8) | Completed | Sub-Task 5 | | -| 7 | SkillsTab Modifications (Bugs9,11,12,13) | Pending | None | | +| 7 | SkillsTab Modifications (Bugs 9,11,12,13) | Completed | None | | | 8 | Mana System Conversion Regen Deduction (Bug10) | Completed | None | | | 9 | StatsTab Mana Breakdown (Bug14) | Pending | Sub-Task 8 | | | 10 | Essence Refining Investigation (Bug15) | Completed | None | | @@ -24,7 +24,7 @@ ## Completed Work - [x] Step 1: Oriented with task3.md - [x] Step 2: Sub-tasks planned and documented -- [ ] Step 3: Sub-tasks executed +- [x] Step 3: Sub-tasks executed - [ ] Step 4: UI Audit completed - [ ] Step 5: Effects & Skills Audit completed @@ -33,4 +33,4 @@ ## Notes - Sub-tasks that touch the same component run sequentially - Independent sub-tasks can be executed in parallel via sub-agents -- Update progress files after each sub-task completion \ No newline at end of file +- Update progress files after each sub-task completion diff --git a/docs/task4.md b/docs/task4.md new file mode 100644 index 0000000..eb8586b --- /dev/null +++ b/docs/task4.md @@ -0,0 +1,619 @@ +# Mana Loop — UI Redesign Task + +You are a senior Next.js/React developer and UI/UX designer working on the +Mana Loop game at `/home/user/repos/Mana-Loop`. + +--- + +## Step 1 — Orient yourself + +Before touching any file: + +1. Read `docs/AGENTS.md` for the architecture overview and coding conventions. +2. Run `bun run lint` and note any pre-existing errors (do not fix them now). +3. Browse `src/components/game/` to map every component to its tab/panel. +4. Read `src/app/globals.css` and every file in `src/components/ui/` to + understand the current design token set (Tailwind config, CSS variables, + shadcn theme). +5. Read `docs/GAME_BRIEFING.md` and `docs/skills.md` so you understand the + game's thematic world before making visual decisions. + +Document your findings in `docs/task4/orient.md` before proceeding. + +--- + +## Step 2 — Design System First + +**Before touching any component**, establish a unified design system. +All subsequent work MUST reference this system — no component should +introduce ad-hoc colors, spacing, or typography. + +Create `docs/task4/design_system.md` containing every decision below. + +### 2a. Visual Identity + +The game is about **ancient arcane magic**, a mysterious **100-floor spire**, +mana weaving, and time loops. The visual language must reflect this world. + +**Target aesthetic:** Dark arcane grimoire — not generic "dark mode SaaS". +Think illuminated manuscript meets crystalline magic UI. +Reference aesthetics: Path of Exile passive tree, Slay the Spire card UI, +Hades menu screens. Do NOT produce generic purple-gradient-on-charcoal. + +**Guiding principles:** +- Every UI region should feel like it belongs in the world (mana pools should + feel liquid, spire floors should feel dangerous, research should feel + scholarly). +- Restraint over decoration: one strong texture/treatment per region, not + everywhere at once. +- The UI must stay fast and readable — this is an idle game the player watches + for minutes at a time. No motion sickness-inducing animations. + +### 2b. Color Tokens + +Define a strict set of CSS custom properties in `src/app/globals.css`. +Every shade must have a semantic name — never use raw hex in components. + +Required token groups (design the specific values yourself): + +``` +/* Backgrounds — at least 3 depth levels */ +--bg-base /* outermost / page */ +--bg-surface /* panels, cards */ +--bg-elevated /* dropdowns, tooltips, modals */ +--bg-sunken /* inset wells, progress track */ + +/* Borders */ +--border-subtle /* barely-there separators */ +--border-default /* standard card edges */ +--border-focus /* interactive focus rings */ + +/* Text */ +--text-primary +--text-secondary +--text-muted +--text-disabled + +/* Mana element colors — one per mana type */ +/* Must feel elemental, not random. Examples: */ +--mana-fire /* ember orange-red */ +--mana-water /* deep teal */ +--mana-air /* silver-white */ +--mana-earth /* warm ochre */ +--mana-light /* gold */ +--mana-dark /* deep indigo */ +--mana-death /* muted violet-grey */ +--mana-transfer /* cyan — the "tech mana" */ +--mana-metal /* cool steel */ +--mana-sand /* warm tan */ +--mana-lightning/* electric yellow */ +--mana-crystal /* pale ice blue */ +--mana-stellar /* bright amber */ +--mana-void /* deep black-purple */ + +/* Semantic UI colors */ +--color-success +--color-warning +--color-danger +--color-info + +/* Interactive */ +--interactive-primary /* main CTA — Gather, Study, Climb */ +--interactive-primary-hover +--interactive-secondary +--interactive-secondary-hover +--interactive-danger +--interactive-danger-hover +--interactive-disabled +``` + +All mana element colors defined here must be used consistently everywhere +that element appears (mana bars, skill icons, spell tags, floor element +badges, etc.). + +### 2c. Typography + +Define a clear typographic scale. Use a single font stack. +Suggested: a fantasy-adjacent serif for headings +(`Cinzel`, `IM Fell English`, or system `Georgia` as fallback) paired with a +clean sans-serif for body/numbers. Both must be legible at small sizes on +mobile. + +Required classes/variables: +``` +--font-heading /* section headers */ +--font-body /* all body copy */ +--font-mono /* numbers, values, timers */ +``` + +Type scale: xs / sm / base / lg / xl / 2xl / 3xl +Define line-height and letter-spacing for headings. + +### 2d. Spacing & Layout + +- Base unit: 4px (Tailwind default — use `space-*` tokens, no magic numbers). +- Card border radius: define one value and use it everywhere (`--radius`). +- Panel inner padding: consistent across all tabs. +- Never mix `px-3` and `px-4` in the same panel row. + +### 2e. Component Primitives + +Design (and implement) these shared primitives in `src/components/ui/` before +touching any game component. Each primitive must accept className overrides. + +| Primitive | Purpose | +|-----------|---------| +| `` | All panel/section wrappers. Accepts `variant`: default, elevated, sunken, danger | +| `` | Consistent section titles with optional right-side action slot | +| `` | Label + value pair. Accepts `highlight` for colored values | +| `` | Progress bar skinned per mana type using `--mana-*` tokens | +| `` | Pill badge for mana/element type with matching icon + color | +| `` | Animated numeric display for mana, DPS, etc. | +| `` | Primary game CTA. Variants: primary, secondary, danger, ghost | +| `` | Standard skill entry row (name, description, cost, study button, level dots) | +| `` | Consistent tooltip triggered by `?` icon | + +### 2f. Animation Budget + +| Category | Rule | +|----------|------| +| Mana bar fill | CSS transition, 300ms ease-out. No spring physics. | +| Progress bars (study/cast) | CSS transition, linear, match game tick rate | +| Tab switch | Instant or 150ms fade-in only. No slide/bounce. | +| Hover states | 100ms ease | +| Number changes | Use CSS `tabular-nums`. No odometer effects. | +| Idle sparkle / glow | One subtle glow pulse on the Gather button ONLY. Nowhere else. | +| Spire combat | Cast bar animates smoothly with `requestAnimationFrame` or CSS only | + +No `framer-motion` animations for layout shifts. Framer Motion is available +but should be used sparingly and only for intentional moments (e.g., floor +cleared notification). + +--- + +## Step 3 — Remove All Dev Artifacts + +The current UI has component name labels rendered in production +(`ManaDisplay`, `SpireModeUI`, `ActionButtons`, `SkillsTab`, etc.). +These must be completely removed from all rendered output before redesign +begins. + +Search for and remove: +- Any component that renders its own name as a visible label +- The debug component name display toggle (or gate it strictly behind + `process.env.NODE_ENV === 'development'`) +- Any `[data-component]` labels visible to users + +--- + +## Step 4 — Sub-task Breakdown + +Break the work into sub-tasks. Before writing any code, create: +- `docs/task4/subtask_N.md` per sub-task (scope, acceptance criteria, + dependencies) +- `docs/task4/subtask_N_progress.md` (update as you go) +- `docs/task4/todo.md` (overall tracker) + +The sub-tasks must follow this order of operations. Sub-tasks marked +**parallel** may run simultaneously if they touch non-overlapping files. + +### Sub-task 1 — Design System Implementation (MUST COMPLETE FIRST) +**Sequential — all others depend on this.** + +- Implement all CSS custom properties in `globals.css`. +- Implement all component primitives in `src/components/ui/`. +- Verify primitives render correctly with a temporary test page or Storybook + (if available); otherwise visually verify by inserting them into one tab. +- Remove dev labels (Step 3 above). + +Acceptance criteria: +- All `--bg-*`, `--border-*`, `--text-*`, `--mana-*`, `--color-*`, + `--interactive-*` tokens defined and working. +- All 9 primitives implemented and exported. +- Zero component name labels visible in UI. + +--- + +### Sub-task 2 — Global Layout & Header [parallel after Sub-task 1] + +**Files:** `src/app/page.tsx`, `src/app/layout.tsx`, Header component. + +Changes required: +- **Remove the pause button** from the header. (Bug fix #5 from task3 — verify + it has been done; if not, do it here.) +- Header must contain: game title/logo, Day + time display, Insight counter. +- On mobile (< 640px): header collapses to a compact single row. Day, time, + and insight stack or abbreviate gracefully. +- Tab bar redesign: + - Group tabs into logical sections with subtle visual separators: + - **World**: Spire, Attune + - **Power**: Skills, Spells, Golems + - **Gear**: Gear, Craft, Loot + - **Meta**: Achieve, Lab, Stats, Grimoire, Debug + - On mobile: tab bar becomes a horizontally scrollable strip with icon-only + buttons (icons + tooltip on long-press). + - Active tab uses a distinct indicator (not just background color change — + use the `--interactive-primary` underline or glow). + - Tabs should never wrap to two rows on desktop. +- The two-row tab layout (main row + second row for Debug/Grimoire) is + acceptable if necessary, but style them as a cohesive set, not as an + afterthought. + +Acceptance criteria: +- Header renders correctly at 375px, 768px, 1280px viewport widths. +- No pause button visible. +- Tab groups visually distinguishable. +- Active tab clearly indicated. + +--- + +### Sub-task 3 — Left Panel: Mana Display & Action Area [parallel after ST1] + +**Files:** `src/components/game/ManaDisplay.tsx`, +`src/components/game/ActionButtons.tsx`, +`src/components/game/CalendarDisplay.tsx`, +and any related sidebar wrapper. + +The left panel is the player's heartbeat — they watch it constantly. +It must be calm, clear, and beautiful. + +Changes required: + +**Mana Display:** +- Raw mana: large, readable current / max with regen rate below. +- Use `` primitive. Bar color uses `--mana-*` token (raw mana = + `--interactive-primary` or a neutral "arcane" color). +- Regen rate label: show current effective regen/hr including meditation + multiplier. Format: `+4.1/hr (1.5× med)` — keep this, it's informative. +- Elemental mana section: each unlocked element shows as a compact row + (`` + mini bar + value). Locked elements are hidden entirely + (not shown as greyed-out rows). +- If only one element is unlocked (Transference early game), the section + occupies minimal vertical space. +- Collapsible elemental section is fine if space is tight on mobile. + +**Gather Button:** +- This is the primary action — make it visually dominant and satisfying. +- Full width, well-padded. Uses ``. +- The single subtle glow/pulse animation lives here. +- On click: brief scale press (CSS `active:scale-95`, no JS needed). + +**Current Activity:** +- Show the active action name and a compact progress bar if applicable. +- Do not show a list of all possible actions — only what's happening now. +- When studying: show skill name + time remaining. +- When meditating: show meditation bonus multiplier and time spent. +- When climbing: hide this panel entirely (SpireModeUI takes over). +- Use `` to make it feel like a status readout. + +**Calendar:** +- Day grid must be compact and legible. Current day is highlighted. +- Days past: muted. Days future: subtle. Day 20+ (incursion): tinted with + `--color-danger` to signal urgency. +- On mobile: show only current week row + day number badge, not full grid. + +**Climb the Spire button:** +- Keep it prominent (orange/amber CTA as currently designed). +- On mobile: ensure it doesn't overflow the panel. + +Acceptance criteria: +- Panel fits within its container at 375px without horizontal scroll. +- Elemental mana section doesn't show locked elements. +- Calendar incursion days visually distinguished. +- Activity display updates reactively. + +--- + +### Sub-task 4 — Skills Tab [parallel after ST1] + +**Files:** `src/components/game/tabs/SkillsTab.tsx` and related. + +The skills tab is the most visually complex tab. Currently it looks like a +generic settings page. It must feel like a research journal. + +Changes required: + +**Category sections:** +- Each category (Mana, Study, Research, Enchanting, etc.) is a collapsible + `` with a `` showing category name, icon, and skill + count badge. +- Categories collapsed by default if the player has no skills in them yet. +- Smooth collapse animation (height transition). + +**Skill rows (use `` primitive):** +- Layout: [Icon] [Name + tier badge] [short description] ... [level dots] [Study button] +- Tier badge: small colored pill showing `T1`, `T2`, etc. +- Level dots: current implementation is fine in concept but dots should use + mana-type-colored fills, not plain purple. Match the skill's associated + mana type. +- Cost display: show mana cost with a `` for the mana type + required, not plain text. +- Study time: keep as-is (`4.0h`) — it's clear. +- Study button: uses ``. Disabled state must look disabled + (not just grey text — lower opacity + `cursor-not-allowed`). +- If a skill has prerequisites not yet met: show a lock icon with a small + tooltip explaining the requirement. Do not hide the skill entirely. + +**Milestone upgrade UI:** +- When a milestone is available (level 5 or 10), the row gets a special + indicator (glowing border or "!" badge) so the player notices. +- Clicking opens a focused upgrade choice modal — not an inline expansion. + Modal must show all choices clearly with their effects. + +**Tier-up UI:** +- When a skill is at max level and tier-up is possible, the Study button + changes to "Tier Up" with a distinct visual (gold outline or similar). + +**Mobile:** +- Skills tab on mobile: category headers sticky. Level dots shrink. + Study button full width below description. + +Acceptance criteria: +- All skill categories render correctly. +- Level dots match mana type colors. +- Disabled state is visually obvious. +- Milestone indicator visible at levels 5 and 10. +- Tier-up path clearly communicated. + +--- + +### Sub-task 5 — Spire Tab & Spire Mode UI [parallel after ST1] + +**Files:** `src/components/game/tabs/SpireTab.tsx`, +`src/components/game/SpireModeUI.tsx` (or equivalent). + +The spire is the heart of the game's drama. The UI must feel tense. + +**SpireTab (the overview/stats view — per task3 bug #3):** +- This should now be a "Spire Stats" view, not a floor-by-floor list. +- Show: highest floor reached, total pacts signed, total guardians defeated, + best run summary. +- The `` lives here (moved from left panel if task3 did + that — verify and adjust). +- If task3 hasn't moved the climb button yet: leave it in the left panel and + note the discrepancy in your progress file. +- Style the stats as a `` with `` rows. +- Guardian pacts section: list signed pacts with their element badge and + multiplier value. + +**SpireModeUI (active combat view):** +- Header: "Spire Mode" title + current floor number (large, bold) + floor + element badge. +- Floor HP bar: uses `` with the floor's element color. Shows + `current / max HP` and DPS label. +- The HP value MUST update reactively on every tick (this is bug #1 from + task3 — verify the fix; if not done, it must be done here as part of layout). +- "Best Floor" and pact count shown below HP bar in `` pairs. +- Activity log (moved here per task3 bug #3): compact scrollable list of + recent events (damage dealt, floor cleared, pact signed). Max 20 entries. + Auto-scrolls to bottom. Uses `--bg-sunken` background. +- Active Spells section: each spell card shows name, type badge, DPS, raw + damage, cast rate, and a live cast progress bar. + - The cast bar must animate smoothly from 0→100% between casts. + - Spell cards use a left border colored by spell element. +- Active Golems section: if empty, show a subtle empty state + ("No golems summoned"), not a blank space. +- Climb Down button: prominent but secondary styling (not the same as Gather). + Per task3 bug #2 — must trigger floor-by-floor downward combat; verify the + fix is in place. + +**Mobile combat view:** +- Floor info, cast bar, and HP bar above the fold. +- Spells and golems scrollable below. +- No horizontal scroll anywhere. + +Acceptance criteria: +- Floor HP updates every game tick visually. +- Cast bar animates correctly. +- Element colors match `--mana-*` tokens. +- Activity log auto-scrolls. +- Empty golem state shown gracefully. +- No content clipped on 375px viewport. + +--- + +### Sub-task 6 — Stats Tab [parallel after ST1] + +**Files:** `src/components/game/tabs/StatsTab.tsx` (or stats subdirectory). + +The stats tab should feel like opening a detailed character sheet. + +Changes required: +- Group stats into sections: Mana Stats, Combat Stats, Skill Bonuses, + Equipment Modifiers, Attunement Effects. +- **Mana breakdown section** (new — per task3 bug #14): + For each unlocked mana type, show a row with: + `[ElementBadge] [Name] | Current: X | Cap: Y | Regen: +Z/hr | Modifiers: ...` + Raw mana appears first, then elements in unlock order. + Modifiers should list attunement conversions and any drain effects. +- All label/value pairs use ``. +- Multipliers highlighted in gold/amber. +- Bonuses from skills listed in a "Active Skill Upgrades" sub-section as + compact tags, not full rows. + +Acceptance criteria: +- Mana breakdown section present with per-type rows. +- All values reactive (update without page reload). +- Clearly grouped sections. + +--- + +### Sub-task 7 — Equipment & Crafting Tabs [parallel after ST1] + +**Files:** `src/components/game/tabs/EquipmentTab.tsx` (GearTab), +`src/components/game/tabs/CraftingTab.tsx` and crafting subdirectory. + +**Equipment/Gear Tab:** +- Equipment slots: visual slot layout (head, chest, hands, feet, weapon, + offhand). Not a flat list. +- Each slot shows: item name, enchantment count / capacity, rarity color. +- 2-handed weapon rule (task3 bug #6): offhand slot overlaid with a + "Occupied — 2H Weapon" badge when a 2-handed item is equipped. Slot + interaction disabled. +- Empty slots show a subtle dashed border with slot type label. +- On mobile: slots stack vertically in two columns (weapon + offhand as a + pair). + +**Crafting Tab:** +- The three phases (Design, Prepare, Apply) are shown as a visual stepper at + the top of the tab, not as separate unlabeled sections. +- Design phase: filter enchantments by items the player owns (task3 bug #7). + Show incompatible enchantments in a greyed-out "Unavailable" section below + compatible ones, with a tooltip explaining why (e.g., "Requires a weapon"). +- Prepare phase: if the target item has existing enchantments, the button + reads "Prepare — removes existing enchantments". Confirm dialog before + proceeding. (task3 bug #8) +- Items tagged "Ready for Enchantment" get a distinct visual badge. +- Apply phase: only shows items tagged "Ready for Enchantment". + +Acceptance criteria: +- 2H weapon slot disable visible and clear. +- Phase stepper renders correctly. +- Prepare button label changes based on enchantment state. +- "Ready for Enchantment" tag visible on item cards. + +--- + +### Sub-task 8 — Attunements Tab [parallel after ST1] + +**Files:** `src/components/game/tabs/AttunementTab.tsx` (AttunmentsTab). + +Currently looks reasonable but needs design-system alignment. + +Changes required: +- Each attunement card (Enchanter, Invoker, Fabricator) should be a + `` with a clear locked/unlocked/active state. +- The primary mana type is shown with its ``. +- Raw Regen and Conversion stats use ``. +- XP progress bar uses `` with the attunement's mana color. +- Capabilities list: icon + label, not plain text. +- Locked attunements: show unlock condition prominently — "Defeat your first + guardian" should appear as an amber callout, not grey body text. +- Summary row ("+0.5 raw mana/hr · 1 active attunement") styled as a + `` header, not a row of green pills. +- On mobile: attunement cards stack vertically. Each card is full width. + +Acceptance criteria: +- All three cards render at all viewport sizes. +- Locked state clearly communicated with unlock path. +- Summary row consistent with design system. + +--- + +### Sub-task 9 — Remaining Tabs [parallel after ST1] + +Apply design-system alignment to all remaining tabs without deep redesign. +The goal is visual consistency, not a full rework. + +Tabs to align: +- **Golems Tab** — golem cards with element badges, stat rows, slot count. +- **Spells Tab** — spell list with element badges, DPS, mana cost. +- **Loot Tab** — inventory with item rarity colors, category filter pills + styled consistently. +- **Achievements Tab** — achievement cards with progress bars. +- **Lab Tab** — prestige/insight upgrades; upgrade cards consistent with + skill rows. +- **Grimoire Tab** — whatever this displays; ensure heading and content + structure uses design system. +- **Debug Tab** — fix crash (task3 bug #4 — verify it's done; if not, fix it + here). Style minimally; this is a dev tool. + +For each tab: +1. Replace ad-hoc background/border colors with design tokens. +2. Replace plain text label/value pairs with ``. +3. Ensure empty states have explicit messaging. +4. Verify mobile layout doesn't overflow. + +Acceptance criteria: +- All tabs render without crashes. +- All tabs use `--bg-*`, `--border-*`, `--text-*` tokens (no raw hex). +- All tabs have explicit empty states. +- All tabs usable at 375px width. + +--- + +## Step 5 — Mobile Layout Audit + +After all sub-tasks complete, do a dedicated mobile pass: + +1. Open the game at 375px viewport (iPhone SE size — the minimum target). +2. Walk through every tab. +3. Fix any overflow, truncation, or illegible text. +4. Test touch targets — all interactive elements must be ≥ 44×44px. +5. The left panel and tab content must not require horizontal scrolling. +6. The tab bar must be reachable with one thumb (bottom placement on mobile + is acceptable if it avoids stretching). + +Document findings in `docs/task4/mobile_audit.md`. + +--- + +## Step 6 — Performance Check + +The game ticks every 200ms. UI updates must not cause jank. + +Rules: +- Never read from the Zustand store inside a render loop without selectors. +- All animated elements (mana bar, cast bar, calendar) must use CSS + transitions rather than JS-driven style updates where possible. +- No `useEffect` that sets state on every tick without proper memoization. +- Run `bun run build` and confirm 0 TypeScript errors and 0 new ESLint errors. + +--- + +## Step 7 — Final Audit + +Write `docs/task4/ui_audit_report.md` covering: +- Visual inconsistencies found and resolved +- UX friction points addressed +- Remaining issues flagged with priority (high/medium/low) +- Screenshots or descriptions of before/after for major changes + +--- + +## Constraints & Rules + +1. **No new external dependencies** unless absolutely necessary and approved. + Tailwind, shadcn/ui, framer-motion, lucide-react are already available. + +2. **Do not change game logic.** Only `src/components/`, `src/app/globals.css`, + and documentation files are in scope. Do not modify `src/lib/game/`. + +3. **TypeScript strict.** All new code must compile without `any` types. + +4. **Backwards compatible.** The Zustand store interface must not change. + +5. **Git hygiene.** Pull before starting. Commit after each sub-task with a + clear message: `feat(ui): redesign skills tab — sub-task 4`. + +6. **Parallel agents must not edit the same file concurrently.** The + dependency graph in your sub-task docs must make this explicit. + +7. **Accessibility baseline.** All interactive elements need proper ARIA + labels. Color must not be the only differentiator for state (use icons or + text labels alongside color). + +8. **Banned patterns:** + - Generic purple gradients as the only visual treatment + - Inline `style={{}}` with hardcoded hex values + - `className="bg-purple-900"` type raw Tailwind colors — use CSS vars + - Visible component name debug labels + - Empty `
` spacers — use `gap-*` on flex/grid parents + - Multiple nested cards (card inside card inside card) + - Tooltip-only affordances with no static label + +--- + +## Deliverables Checklist + +- [ ] `docs/task4/orient.md` — initial codebase survey +- [ ] `docs/task4/design_system.md` — all design decisions documented +- [ ] `src/app/globals.css` — all CSS custom properties defined +- [ ] `src/components/ui/` — all 9 primitives implemented +- [ ] All dev labels removed from rendered output +- [ ] Sub-task docs (1–9) with progress files +- [ ] `docs/task4/todo.md` updated throughout +- [ ] `docs/task4/mobile_audit.md` — mobile pass findings +- [ ] `docs/task4/ui_audit_report.md` — final audit +- [ ] `bun run build` passes with 0 new errors +- [ ] `bun run lint` passes with 0 new errors \ No newline at end of file diff --git a/src/components/game/crafting/EnchantmentPreparer.tsx b/src/components/game/crafting/EnchantmentPreparer.tsx index f773351..7c38a61 100644 --- a/src/components/game/crafting/EnchantmentPreparer.tsx +++ b/src/components/game/crafting/EnchantmentPreparer.tsx @@ -139,8 +139,7 @@ export function EnchantmentPreparer({ const manaCost = instance.totalCapacity * 10; // Calculate disenchant recovery - const disenchantLevel = skills.disenchanting || 0; - const recoveryRate = 0.1 + disenchantLevel * 0.2; + const recoveryRate = 0.1; // Base recovery rate (disenchanting skill removed) const totalRecoverable = instance.enchantments.reduce( (sum, e) => sum + Math.floor(e.actualCost * recoveryRate), 0 diff --git a/src/components/game/debug/SkillDebug.tsx b/src/components/game/debug/SkillDebug.tsx index c5605b6..52277e8 100644 --- a/src/components/game/debug/SkillDebug.tsx +++ b/src/components/game/debug/SkillDebug.tsx @@ -30,7 +30,7 @@ export function SkillDebug({ store }: SkillDebugProps) { variant="outline" onClick={() => { // Level up all enchanting skills by 1 - const enchantSkills = ['enchanting', 'efficientEnchant', 'disenchanting', 'enchantSpeed','essenceRefining']; + const enchantSkills = ['enchanting', 'efficientEnchant', 'enchantSpeed','essenceRefining']; enchantSkills.forEach(skillId => { if (store.skills[skillId] !== undefined) { store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); @@ -47,7 +47,7 @@ export function SkillDebug({ store }: SkillDebugProps) { variant="outline" onClick={() => { // Max all enchanting skills - const enchantSkills = ['enchanting', 'efficientEnchant', 'disenchanting', 'enchantSpeed','essenceRefining']; + const enchantSkills = ['enchanting', 'efficientEnchant', 'enchantSpeed','essenceRefining']; enchantSkills.forEach(skillId => { store.skills[skillId] = 10; }); @@ -66,7 +66,7 @@ export function SkillDebug({ store }: SkillDebugProps) { size="sm" variant="outline" onClick={() => { - const manaSkills = ['manaWell', 'manaFlow', 'elemAttune', 'manaOverflow']; + const manaSkills = ['manaWell', 'manaFlow', 'manaOverflow', 'fireManaCap', 'waterManaCap', 'airManaCap', 'earthManaCap', 'lightManaCap', 'darkManaCap', 'deathManaCap', 'metalManaCap', 'sandManaCap', 'lightningManaCap', 'transferenceManaCap']; manaSkills.forEach(skillId => { if (store.skills[skillId] !== undefined) { store.skills[skillId] = Math.min((store.skills[skillId] || 0) + 1, 10); @@ -82,7 +82,7 @@ export function SkillDebug({ store }: SkillDebugProps) { size="sm" variant="outline" onClick={() => { - const manaSkills = ['manaWell', 'manaFlow', 'elemAttune', 'manaOverflow']; + const manaSkills = ['manaWell', 'manaFlow', 'manaOverflow', 'fireManaCap', 'waterManaCap', 'airManaCap', 'earthManaCap', 'lightManaCap', 'darkManaCap', 'deathManaCap', 'metalManaCap', 'sandManaCap', 'lightningManaCap', 'transferenceManaCap']; manaSkills.forEach(skillId => { store.skills[skillId] = 10; }); diff --git a/src/components/game/tabs/AttunementsTab.tsx b/src/components/game/tabs/AttunementsTab.tsx index 184bd65..d0fb169 100755 --- a/src/components/game/tabs/AttunementsTab.tsx +++ b/src/components/game/tabs/AttunementsTab.tsx @@ -195,14 +195,14 @@ export function AttunementsTab({ store }: AttunementsTabProps) { {def.capabilities.map(cap => ( {cap === 'enchanting' && '✨ Enchanting'} - {cap === 'disenchanting' && '🔄 Disenchant'} + {cap === 'disenchanting' && '🔄 Disenchant'} // TODO: Remove after bug 13 complete {cap === 'pacts' && '🤝 Pacts'} {cap === 'guardianPowers' && '💜 Guardian Powers'} {cap === 'elementalMastery' && '🌟 Elem. Mastery'} {cap === 'golemCrafting' && '🗿 Golems'} {cap === 'gearCrafting' && '⚒️ Gear'} {cap === 'earthShaping' && '⛰️ Earth Shaping'} - {!['enchanting', 'disenchanting', 'pacts', 'guardianPowers', + {!['enchanting', 'pacts', 'guardianPowers', 'elementalMastery', 'golemCrafting', 'gearCrafting', 'earthShaping'].includes(cap) && cap} ))} @@ -246,7 +246,7 @@ export function AttunementsTab({ store }: AttunementsTabProps) { > {cat === 'mana' && '💧 Mana'} {cat === 'study' && '📚 Study'} - {cat === 'research' && '🔮 Research'} + {cat === 'research' && '🔮 Research'} // TODO: Remove after Bug 12 - research moved to mana {cat === 'ascension' && '⭐ Ascension'} {cat === 'enchant' && '✨ Enchanting'} {cat === 'effectResearch' && '🔬 Effect Research'} diff --git a/src/components/game/tabs/SkillsTab.tsx b/src/components/game/tabs/SkillsTab.tsx index 6ea6424..82b9e17 100755 --- a/src/components/game/tabs/SkillsTab.tsx +++ b/src/components/game/tabs/SkillsTab.tsx @@ -211,8 +211,19 @@ export function SkillsTab({ store }: SkillsTabProps) { const baseCost = def.base * (level + 1) * currentTier; const cost = Math.floor(baseCost * costMult); + // Additional cost (element mana) + const additionalCost = def.cost; + // Can start studying? - const canStudy = !maxed && prereqMet && store.rawMana >= cost && !isStudying; + let canStudy = !maxed && prereqMet && store.rawMana >= cost && !isStudying; + + // Check additional cost (element mana) + if (def.cost && def.cost.type === 'element') { + const element = store.elements[def.cost.element]; + if (!element || element.current < def.cost.amount) { + canStudy = false; + } + } // Check for milestone upgrades const milestoneInfo = hasMilestoneUpgrade(tieredSkillId, level, store.skillTiers || {}, store.skillUpgrades); @@ -266,6 +277,11 @@ export function SkillsTab({ store }: SkillsTabProps) { {' • '} Cost: {fmt(cost)} mana{costMult < 1 && ({Math.round(costMult * 100)}% cost)} + {additionalCost && additionalCost.type === 'element' && ( + + + {additionalCost.amount} {ELEMENTS[additionalCost.element]?.sym} {additionalCost.element} + + )}
@@ -325,7 +341,7 @@ export function SkillsTab({ store }: SkillsTabProps) { className={canStudy ? 'bg-purple-600 hover:bg-purple-700' : 'opacity-50'} onClick={() => store.startStudyingSkill(tieredSkillId)} > - Study ({fmt(cost)}) + Study ({fmt(cost)}{additionalCost && additionalCost.type === 'element' && ` + ${additionalCost.amount} ${ELEMENTS[additionalCost.element]?.sym}`} {/* Parallel Study button */} {hasSpecial(upgradeEffects, SPECIAL_EFFECTS.PARALLEL_STUDY) && diff --git a/src/lib/game/__tests__/skills.test.ts b/src/lib/game/__tests__/skills.test.ts index 98e1bac..38596c4 100644 --- a/src/lib/game/__tests__/skills.test.ts +++ b/src/lib/game/__tests__/skills.test.ts @@ -354,7 +354,8 @@ describe('Enchanter Skills', () => { describe('Disenchanting (Recover mana from removed enchantments)', () => { it('skill definition should exist', () => { - expect(SKILLS_DEF.disenchanting).toBeDefined(); + // disenchanting skill removed - see Bug 13 + expect(SKILLS_DEF.disenchanting).toBeUndefined(); }); }); }); diff --git a/src/lib/game/attunements.ts b/src/lib/game/attunements.ts index 5ccddde..3e22032 100755 --- a/src/lib/game/attunements.ts +++ b/src/lib/game/attunements.ts @@ -131,15 +131,7 @@ export const ATTUNEMENTS: Record = { studyTime: 12, req: { enchanting: 3 }, }, - disenchanting: { - name: 'Disenchanting', - desc: 'Remove enchantments and recover some mana', - cat: 'enchanter', - max: 5, - base: 150, - studyTime: 10, - req: { enchanting: 2 }, - }, + enchantSpeed: { name: 'Swift Enchanting', desc: 'Faster enchantment application', diff --git a/src/lib/game/constants/skills.ts b/src/lib/game/constants/skills.ts index a079ea5..40e90d1 100644 --- a/src/lib/game/constants/skills.ts +++ b/src/lib/game/constants/skills.ts @@ -5,19 +5,32 @@ export const SKILLS_DEF: Record = { // Mana Skills (4-8 hours study) - Core, no attunement required manaWell: { name: "Mana Well", desc: "+100 max mana", cat: "mana", max: 10, base: 100, studyTime: 4 }, manaFlow: { name: "Mana Flow", desc: "+1 regen/hr", cat: "mana", max: 10, base: 150, studyTime: 5 }, - elemAttune: { name: "Elem. Attunement", desc: "+50 elem mana cap", cat: "mana", max: 10, base: 200, studyTime: 4 }, + // Per-mana-type capacity upgrades (Bug 9) + fireManaCap: { name: "Fire Mana Capacity +10%", desc: "+10% fire mana capacity", cat: "mana", max: 10, base: 200, studyTime: 4, cost: { type: 'element', element: 'fire', amount: 100 } }, + waterManaCap: { name: "Water Mana Capacity +10%", desc: "+10% water mana capacity", cat: "mana", max: 10, base: 200, studyTime: 4, cost: { type: 'element', element: 'water', amount: 100 } }, + airManaCap: { name: "Air Mana Capacity +10%", desc: "+10% air mana capacity", cat: "mana", max: 10, base: 200, studyTime: 4, cost: { type: 'element', element: 'air', amount: 100 } }, + earthManaCap: { name: "Earth Mana Capacity +10%", desc: "+10% earth mana capacity", cat: "mana", max: 10, base: 200, studyTime: 4, cost: { type: 'element', element: 'earth', amount: 100 } }, + lightManaCap: { name: "Light Mana Capacity +10%", desc: "+10% light mana capacity", cat: "mana", max: 10, base: 250, studyTime: 5, cost: { type: 'element', element: 'light', amount: 150 } }, + darkManaCap: { name: "Dark Mana Capacity +10%", desc: "+10% dark mana capacity", cat: "mana", max: 10, base: 250, studyTime: 5, cost: { type: 'element', element: 'dark', amount: 150 } }, + deathManaCap: { name: "Death Mana Capacity +10%", desc: "+10% death mana capacity", cat: "mana", max: 10, base: 300, studyTime: 6, cost: { type: 'element', element: 'death', amount: 200 } }, + // Composite element capacity upgrades + metalManaCap: { name: "Metal Mana Capacity +10%", desc: "+10% metal mana capacity", cat: "mana", max: 10, base: 350, studyTime: 6, cost: { type: 'element', element: 'metal', amount: 250 } }, + sandManaCap: { name: "Sand Mana Capacity +10%", desc: "+10% sand mana capacity", cat: "mana", max: 10, base: 350, studyTime: 6, cost: { type: 'element', element: 'sand', amount: 250 } }, + lightningManaCap: { name: "Lightning Mana Capacity +10%", desc: "+10% lightning mana capacity", cat: "mana", max: 10, base: 350, studyTime: 6, cost: { type: 'element', element: 'lightning', amount: 250 } }, + // Utility mana capacity upgrades + transferenceManaCap: { name: "Transference Mana Capacity +10%", desc: "+10% transference mana capacity", cat: "mana", max: 10, base: 200, studyTime: 4, cost: { type: 'element', element: 'transference', amount: 100 } }, manaOverflow: { name: "Mana Overflow", desc: "+25% mana from clicks", cat: "mana", max: 5, base: 400, req: { manaWell: 3 }, studyTime: 6 }, // Study Skills (3-6 hours study) - Core, no attunement required quickLearner: { name: "Quick Learner", desc: "+10% study speed", cat: "study", max: 10, base: 250, studyTime: 4 }, focusedMind: { name: "Focused Mind", desc: "-5% study mana cost", cat: "study", max: 10, base: 300, studyTime: 5 }, - meditation: { name: "Meditation Focus", desc: "Up to 2.5x regen after 4hrs meditating", cat: "study", max: 1, base: 400, studyTime: 6 }, + meditation: { name: "Meditation Focus", desc: "Up to 2.5x regen after 4hrs meditating", cat: "mana", max: 1, base: 400, studyTime: 6 }, knowledgeRetention: { name: "Knowledge Retention", desc: "+20% study progress saved on cancel", cat: "study", max: 3, base: 350, studyTime: 5 }, // Enchanting Skills (4-8 hours study) - Requires Enchanter attunement levels enchanting: { name: "Enchanting", desc: "Unlocks enchantment design", cat: "enchant", max: 10, base: 200, studyTime: 5, attunement: 'enchanter', attunementReq: { enchanter: 1 } }, efficientEnchant:{ name: "Efficient Enchant", desc: "-5% enchantment capacity cost", cat: "enchant", max: 5, base: 350, studyTime: 6, req: { enchanting: 3 }, attunementReq: { enchanter: 2 } }, - disenchanting: { name: "Disenchanting", desc: "Recover 20% mana from removed enchantments", cat: "enchant", max: 3, base: 400, studyTime: 6, req: { enchanting: 2 }, attunementReq: { enchanter: 1 } }, + enchantSpeed: { name: "Enchant Speed", desc: "-10% enchantment time", cat: "enchant", max: 5, base: 300, studyTime: 4, req: { enchanting: 2 }, attunementReq: { enchanter: 1 } }, essenceRefining: { name: "Essence Refining", desc: "+10% enchantment effect power", cat: "enchant", max: 1, base: 450, studyTime: 7, req: { enchanting: 4 }, attunementReq: { enchanter: 2 } }, @@ -28,27 +41,27 @@ export const SKILLS_DEF: Record = { // Effect Research Skills (unlock enchantment effects for designing) - Requires Enchanter // Tier 1 - Basic Spell Effects - researchManaSpells: { name: "Mana Spell Research", desc: "Unlock Mana Strike spell enchantment", cat: "effectResearch", max: 1, base: 200, studyTime: 4, req: { enchanting: 1 }, attunementReq: { enchanter: 1 } }, - researchFireSpells: { name: "Fire Spell Research", desc: "Unlock Ember Shot, Fireball spell enchantments", cat: "effectResearch", max: 1, base: 300, studyTime: 6, req: { enchanting: 2 }, attunementReq: { enchanter: 1 } }, - researchWaterSpells: { name: "Water Spell Research", desc: "Unlock Water Jet, Ice Shard spell enchantments", cat: "effectResearch", max: 1, base: 300, studyTime: 6, req: { enchanting: 2 }, attunementReq: { enchanter: 1 } }, - researchAirSpells: { name: "Air Spell Research", desc: "Unlock Gust, Wind Slash spell enchantments", cat: "effectResearch", max: 1, base: 300, studyTime: 6, req: { enchanting: 2 }, attunementReq: { enchanter: 1 } }, - researchEarthSpells: { name: "Earth Spell Research", desc: "Unlock Stone Bullet, Rock Spike spell enchantments", cat: "effectResearch", max: 1, base: 350, studyTime: 6, req: { enchanting: 2 }, attunementReq: { enchanter: 1 } }, - researchLightSpells: { name: "Light Spell Research", desc: "Unlock Light Lance, Radiance spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 8, req: { enchanting: 3 }, attunementReq: { enchanter: 2 } }, - researchDarkSpells: { name: "Dark Spell Research", desc: "Unlock Shadow Bolt, Dark Pulse spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 8, req: { enchanting: 3 }, attunementReq: { enchanter: 2 } }, - researchLifeDeathSpells: { name: "Death Research", desc: "Unlock Drain spell enchantment", cat: "effectResearch", max: 1, base: 400, studyTime: 8, req: { enchanting: 3 }, attunementReq: { enchanter: 2 } }, + researchManaSpells: { name: "Mana Spell Research", desc: "Unlock Mana Strike spell enchantment", cat: "effectResearch", max: 1, base: 200, studyTime: 4, req: { enchanting: 1 }, cost: { type: 'element', element: 'transference', amount: 100 }, attunementReq: { enchanter: 1 } }, + researchFireSpells: { name: "Fire Spell Research", desc: "Unlock Ember Shot, Fireball spell enchantments", cat: "effectResearch", max: 1, base: 300, studyTime: 6, req: { enchanting: 2 }, cost: { type: 'element', element: 'fire', amount: 100 }, attunementReq: { enchanter: 1 } }, + researchWaterSpells: { name: "Water Spell Research", desc: "Unlock Water Jet, Ice Shard spell enchantments", cat: "effectResearch", max: 1, base: 300, studyTime: 6, req: { enchanting: 2 }, cost: { type: 'element', element: 'water', amount: 100 }, attunementReq: { enchanter: 1 } }, + researchAirSpells: { name: "Air Spell Research", desc: "Unlock Gust, Wind Slash spell enchantments", cat: "effectResearch", max: 1, base: 300, studyTime: 6, req: { enchanting: 2 }, cost: { type: 'element', element: 'air', amount: 100 }, attunementReq: { enchanter: 1 } }, + researchEarthSpells: { name: "Earth Spell Research", desc: "Unlock Stone Bullet, Rock Spike spell enchantments", cat: "effectResearch", max: 1, base: 350, studyTime: 6, req: { enchanting: 2 }, cost: { type: 'element', element: 'earth', amount: 100 }, attunementReq: { enchanter: 1 } }, + researchLightSpells: { name: "Light Spell Research", desc: "Unlock Light Lance, Radiance spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 8, req: { enchanting: 3 }, cost: { type: 'element', element: 'light', amount: 100 }, attunementReq: { enchanter: 2 } }, + researchDarkSpells: { name: "Dark Spell Research", desc: "Unlock Shadow Bolt, Dark Pulse spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 8, req: { enchanting: 3 }, cost: { type: 'element', element: 'dark', amount: 100 }, attunementReq: { enchanter: 2 } }, + researchLifeDeathSpells: { name: "Death Research", desc: "Unlock Drain spell enchantment", cat: "effectResearch", max: 1, base: 400, studyTime: 8, req: { enchanting: 3 , cost: { type: 'element', element: 'death', amount: 100 }}, attunementReq: { enchanter: 2 } }, // Tier 2 - Advanced Spell Effects - Require Enchanter 3 - researchAdvancedFire: { name: "Advanced Fire Research", desc: "Unlock Inferno, Flame Wave spell enchantments", cat: "effectResearch", max: 1, base: 600, studyTime: 12, req: { researchFireSpells: 1, enchanting: 4 }, attunementReq: { enchanter: 3 } }, - researchAdvancedWater: { name: "Advanced Water Research", desc: "Unlock Tidal Wave, Ice Storm spell enchantments", cat: "effectResearch", max: 1, base: 600, studyTime: 12, req: { researchWaterSpells: 1, enchanting: 4 }, attunementReq: { enchanter: 3 } }, - researchAdvancedAir: { name: "Advanced Air Research", desc: "Unlock Hurricane, Wind Blade spell enchantments", cat: "effectResearch", max: 1, base: 600, studyTime: 12, req: { researchAirSpells: 1, enchanting: 4 }, attunementReq: { enchanter: 3 } }, - researchAdvancedEarth: { name: "Advanced Earth Research", desc: "Unlock Earthquake, Stone Barrage spell enchantments", cat: "effectResearch", max: 1, base: 600, studyTime: 12, req: { researchEarthSpells: 1, enchanting: 4 }, attunementReq: { enchanter: 3 } }, - researchAdvancedLight: { name: "Advanced Light Research", desc: "Unlock Solar Flare, Divine Smite spell enchantments", cat: "effectResearch", max: 1, base: 700, studyTime: 14, req: { researchLightSpells: 1, enchanting: 5 }, attunementReq: { enchanter: 4 } }, - researchAdvancedDark: { name: "Advanced Dark Research", desc: "Unlock Void Rift, Shadow Storm spell enchantments", cat: "effectResearch", max: 1, base: 700, studyTime: 14, req: { researchDarkSpells: 1, enchanting: 5 }, attunementReq: { enchanter: 4 } }, + researchAdvancedFire: { name: "Advanced Fire Research", desc: "Unlock Inferno, Flame Wave spell enchantments", cat: "effectResearch", max: 1, base: 600, studyTime: 12, req: { researchFireSpells: 1, enchanting: 4 , cost: { type: 'element', element: 'fire', amount: 100 }}, attunementReq: { enchanter: 3 } }, + researchAdvancedWater: { name: "Advanced Water Research", desc: "Unlock Tidal Wave, Ice Storm spell enchantments", cat: "effectResearch", max: 1, base: 600, studyTime: 12, req: { researchWaterSpells: 1, enchanting: 4 , cost: { type: 'element', element: 'water', amount: 100 }}, attunementReq: { enchanter: 3 } }, + researchAdvancedAir: { name: "Advanced Air Research", desc: "Unlock Hurricane, Wind Blade spell enchantments", cat: "effectResearch", max: 1, base: 600, studyTime: 12, req: { researchAirSpells: 1, enchanting: 4 , cost: { type: 'element', element: 'air', amount: 100 }}, attunementReq: { enchanter: 3 } }, + researchAdvancedEarth: { name: "Advanced Earth Research", desc: "Unlock Earthquake, Stone Barrage spell enchantments", cat: "effectResearch", max: 1, base: 600, studyTime: 12, req: { researchEarthSpells: 1, enchanting: 4 , cost: { type: 'element', element: 'earth', amount: 100 }}, attunementReq: { enchanter: 3 } }, + researchAdvancedLight: { name: "Advanced Light Research", desc: "Unlock Solar Flare, Divine Smite spell enchantments", cat: "effectResearch", max: 1, base: 700, studyTime: 14, req: { researchLightSpells: 1, enchanting: 5 , cost: { type: 'element', element: 'light', amount: 100 }}, attunementReq: { enchanter: 4 } }, + researchAdvancedDark: { name: "Advanced Dark Research", desc: "Unlock Void Rift, Shadow Storm spell enchantments", cat: "effectResearch", max: 1, base: 700, studyTime: 14, req: { researchDarkSpells: 1, enchanting: 5 , cost: { type: 'element', element: 'dark', amount: 100 }}, attunementReq: { enchanter: 4 } }, // Tier 3 - Master Spell Effects - Require Enchanter 5 - researchMasterFire: { name: "Master Fire Research", desc: "Unlock Pyroclasm spell enchantment", cat: "effectResearch", max: 1, base: 1200, studyTime: 24, req: { researchAdvancedFire: 1, enchanting: 7 }, attunementReq: { enchanter: 5 } }, - researchMasterWater: { name: "Master Water Research", desc: "Unlock Tsunami spell enchantment", cat: "effectResearch", max: 1, base: 1200, studyTime: 24, req: { researchAdvancedWater: 1, enchanting: 7 }, attunementReq: { enchanter: 5 } }, - researchMasterEarth: { name: "Master Earth Research", desc: "Unlock Meteor Strike spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedEarth: 1, enchanting: 8 }, attunementReq: { enchanter: 5 } }, + researchMasterFire: { name: "Master Fire Research", desc: "Unlock Pyroclasm spell enchantment", cat: "effectResearch", max: 1, base: 1200, studyTime: 24, req: { researchAdvancedFire: 1, enchanting: 7 , cost: { type: 'element', element: 'fire', amount: 200 }}, attunementReq: { enchanter: 5 } }, + researchMasterWater: { name: "Master Water Research", desc: "Unlock Tsunami spell enchantment", cat: "effectResearch", max: 1, base: 1200, studyTime: 24, req: { researchAdvancedWater: 1, enchanting: 7 , cost: { type: 'element', element: 'water', amount: 200 }}, attunementReq: { enchanter: 5 } }, + researchMasterEarth: { name: "Master Earth Research", desc: "Unlock Meteor Strike spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedEarth: 1, enchanting: 8 , cost: { type: 'element', element: 'earth', amount: 200 }}, attunementReq: { enchanter: 5 } }, // Combat Effect Research researchDamageEffects: { name: "Damage Effect Research", desc: "Unlock Minor/Moderate Power, Amplification effects", cat: "effectResearch", max: 1, base: 250, studyTime: 5, req: { enchanting: 1 }, attunementReq: { enchanter: 1 } }, @@ -70,19 +83,19 @@ export const SKILLS_DEF: Record = { // ═══════════════════════════════════════════════════════════════════════════ // Tier 1 - Basic Compound Spells - researchMetalSpells: { name: "Metal Spell Research", desc: "Unlock Metal Shard, Iron Fist spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 6, req: { researchFireSpells: 1, researchEarthSpells: 1, enchanting: 3 }, attunementReq: { enchanter: 2 } }, - researchSandSpells: { name: "Sand Spell Research", desc: "Unlock Sand Blast, Sandstorm spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 6, req: { researchEarthSpells: 1, researchWaterSpells: 1, enchanting: 3 }, attunementReq: { enchanter: 2 } }, - researchLightningSpells: { name: "Lightning Spell Research", desc: "Unlock Spark, Lightning Bolt spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 6, req: { researchFireSpells: 1, researchAirSpells: 1, enchanting: 3 }, attunementReq: { enchanter: 2 } }, + researchMetalSpells: { name: "Metal Spell Research", desc: "Unlock Metal Shard, Iron Fist spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 6, req: { researchFireSpells: 1, researchEarthSpells: 1, enchanting: 3 , cost: { type: 'element', element: 'metal', amount: 100 }}, attunementReq: { enchanter: 2 } }, + researchSandSpells: { name: "Sand Spell Research", desc: "Unlock Sand Blast, Sandstorm spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 6, req: { researchEarthSpells: 1, researchWaterSpells: 1, enchanting: 3 , cost: { type: 'element', element: 'sand', amount: 100 }}, attunementReq: { enchanter: 2 } }, + researchLightningSpells: { name: "Lightning Spell Research", desc: "Unlock Spark, Lightning Bolt spell enchantments", cat: "effectResearch", max: 1, base: 400, studyTime: 6, req: { researchFireSpells: 1, researchAirSpells: 1, enchanting: 3 , cost: { type: 'element', element: 'lightning', amount: 100 }}, attunementReq: { enchanter: 2 } }, // Tier 2 - Advanced Compound Spells - researchAdvancedMetal: { name: "Advanced Metal Research", desc: "Unlock Steel Tempest spell enchantment", cat: "effectResearch", max: 1, base: 700, studyTime: 12, req: { researchMetalSpells: 1, enchanting: 5 }, attunementReq: { enchanter: 3 } }, - researchAdvancedSand: { name: "Advanced Sand Research", desc: "Unlock Desert Wind spell enchantment", cat: "effectResearch", max: 1, base: 700, studyTime: 12, req: { researchSandSpells: 1, enchanting: 5 }, attunementReq: { enchanter: 3 } }, - researchAdvancedLightning: { name: "Advanced Lightning Research", desc: "Unlock Chain Lightning, Storm Call spell enchantments", cat: "effectResearch", max: 1, base: 700, studyTime: 12, req: { researchLightningSpells: 1, enchanting: 5 }, attunementReq: { enchanter: 3 } }, + researchAdvancedMetal: { name: "Advanced Metal Research", desc: "Unlock Steel Tempest spell enchantment", cat: "effectResearch", max: 1, base: 700, studyTime: 12, req: { researchMetalSpells: 1, enchanting: 5 , cost: { type: 'element', element: 'metal', amount: 100 }}, attunementReq: { enchanter: 3 } }, + researchAdvancedSand: { name: "Advanced Sand Research", desc: "Unlock Desert Wind spell enchantment", cat: "effectResearch", max: 1, base: 700, studyTime: 12, req: { researchSandSpells: 1, enchanting: 5 , cost: { type: 'element', element: 'sand', amount: 100 }}, attunementReq: { enchanter: 3 } }, + researchAdvancedLightning: { name: "Advanced Lightning Research", desc: "Unlock Chain Lightning, Storm Call spell enchantments", cat: "effectResearch", max: 1, base: 700, studyTime: 12, req: { researchLightningSpells: 1, enchanting: 5 , cost: { type: 'element', element: 'lightning', amount: 100 }}, attunementReq: { enchanter: 3 } }, // Tier 3 - Master Compound Spells - researchMasterMetal: { name: "Master Metal Research", desc: "Unlock Furnace Blast spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedMetal: 1, enchanting: 7 }, attunementReq: { enchanter: 5 } }, - researchMasterSand: { name: "Master Sand Research", desc: "Unlock Dune Collapse spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedSand: 1, enchanting: 7 }, attunementReq: { enchanter: 5 } }, - researchMasterLightning: { name: "Master Lightning Research", desc: "Unlock Thunder Strike spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedLightning: 1, enchanting: 7 }, attunementReq: { enchanter: 5 } }, + researchMasterMetal: { name: "Master Metal Research", desc: "Unlock Furnace Blast spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedMetal: 1, enchanting: 7 , cost: { type: 'element', element: 'metal', amount: 200 }}, attunementReq: { enchanter: 5 } }, + researchMasterSand: { name: "Master Sand Research", desc: "Unlock Dune Collapse spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedSand: 1, enchanting: 7 , cost: { type: 'element', element: 'sand', amount: 200 }}, attunementReq: { enchanter: 5 } }, + researchMasterLightning: { name: "Master Lightning Research", desc: "Unlock Thunder Strike spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedLightning: 1, enchanting: 7 , cost: { type: 'element', element: 'lightning', amount: 200 }}, attunementReq: { enchanter: 5 } }, // ═══════════════════════════════════════════════════════════════════════════ // UTILITY MANA SPELL RESEARCH - Transference @@ -98,11 +111,11 @@ export const SKILLS_DEF: Record = { researchMasterTransference: { name: "Master Transference Research", desc: "Unlock Soul Transfer spell enchantment", cat: "effectResearch", max: 1, base: 1300, studyTime: 26, req: { researchAdvancedTransference: 1, enchanting: 7 }, attunementReq: { enchanter: 5 } }, // Research Skills (longer study times: 12-72 hours) - Core skills, any attunement level 3 - manaTap: { name: "Mana Tap", desc: "+1 mana/click", cat: "research", max: 1, base: 300, studyTime: 12 }, - manaSurge: { name: "Mana Surge", desc: "+3 mana/click", cat: "research", max: 1, base: 800, studyTime: 36, req: { manaTap: 1 } }, - manaSpring: { name: "Mana Spring", desc: "+2 mana regen", cat: "research", max: 1, base: 600, studyTime: 24 }, - deepTrance: { name: "Deep Trance", desc: "Extend meditation bonus to 6hrs for 3x", cat: "research", max: 1, base: 900, studyTime: 48, req: { meditation: 1 } }, - voidMeditation:{ name: "Void Meditation", desc: "Extend meditation bonus to 8hrs for 5x", cat: "research", max: 1, base: 1500, studyTime: 72, req: { deepTrance: 1 } }, + manaTap: { name: "Mana Tap", desc: "+1 mana/click", cat: "mana", max: 1, base: 300, studyTime: 12 }, + manaSurge: { name: "Mana Surge", desc: "+3 mana/click", cat: "mana", max: 1, base: 800, studyTime: 36, req: { manaTap: 1 } }, + manaSpring: { name: "Mana Spring", desc: "+2 mana regen", cat: "mana", max: 1, base: 600, studyTime: 24 }, + deepTrance: { name: "Deep Trance", desc: "Extend meditation bonus to 6hrs for 3x", cat: "mana", max: 1, base: 900, studyTime: 48, req: { meditation: 1 } }, + voidMeditation:{ name: "Void Meditation", desc: "Extend meditation bonus to 8hrs for 5x", cat: "mana", max: 1, base: 1500, studyTime: 72, req: { deepTrance: 1 } }, // ═══════════════════════════════════════════════════════════════════════════ // INVOKER SKILLS - Require Invoker attunement @@ -189,7 +202,7 @@ export const SKILL_CATEGORIES = [ // Core categories (always available) { id: 'mana', name: 'Mana', icon: '💧', attunement: null }, { id: 'study', name: 'Study', icon: '📚', attunement: null }, - { id: 'research', name: 'Research', icon: '🔮', attunement: null }, + // Research category moved to Mana (Bug 12) // Enchanter attunement (Right Hand) { id: 'enchant', name: 'Enchanting', icon: '✨', attunement: 'enchanter' }, diff --git a/src/lib/game/crafting-slice.ts b/src/lib/game/crafting-slice.ts index 6de3dc6..bb0d361 100755 --- a/src/lib/game/crafting-slice.ts +++ b/src/lib/game/crafting-slice.ts @@ -526,7 +526,7 @@ export function createCraftingSlice( const instance = state.equipmentInstances[instanceId]; if (!instance || instance.enchantments.length === 0) return; - const disenchantLevel = state.skills.disenchanting || 0; + const disenchantLevel = 0; // disenchanting skill removed (Bug 13) const recoveryRate = 0.1 + disenchantLevel * 0.2; // 10% base + 20% per level let totalRecovered = 0; @@ -828,8 +828,8 @@ export function processCraftingTick( let totalRecovered = 0; if (instance) { - // Calculate mana recovery from disenchanting - const disenchantLevel = (state.skills as Record).disenchanting || 0; + // Calculate mana recovery - disenchanting skill removed (Bug 13) + const disenchantLevel = 0; const recoveryRate = 0.1 + disenchantLevel * 0.2; // 10% base + 20% per level for (const ench of instance.enchantments) { totalRecovered += Math.floor(ench.actualCost * recoveryRate); diff --git a/src/lib/game/data/attunements.ts b/src/lib/game/data/attunements.ts index 6af899d..744040d 100755 --- a/src/lib/game/data/attunements.ts +++ b/src/lib/game/data/attunements.ts @@ -31,7 +31,7 @@ export const ATTUNEMENTS_DEF: Record = { rawManaRegen: 0.5, conversionRate: 0.2, // Converts 0.2 raw mana to transference per hour unlocked: true, // Starting attunement - capabilities: ['enchanting', 'disenchanting'], + capabilities: ['enchanting'], skillCategories: ['enchant', 'effectResearch'], }, diff --git a/src/lib/game/skill-evolution.ts b/src/lib/game/skill-evolution.ts old mode 100755 new mode 100644 index a7e587b..f7ba6b8 --- a/src/lib/game/skill-evolution.ts +++ b/src/lib/game/skill-evolution.ts @@ -977,156 +977,8 @@ const EFFICIENT_ENCHANT_TIERS: SkillTierDef[] = [ ]; // ─── DISENCHANTING TALENT TREE ──────────────────────────────────────────────── -// Base: Recover Mana from Removed Enchantments -// Paths: A = The Reclaimer (Mana Recovery), B = The Salvager (Efficiency), C = The Transmuter (Bonus Effects) - -const DISENCHANTING_TIERS: SkillTierDef[] = [ - // TIER 1 - { - tier: 1, - skillId: 'disenchanting', - name: 'Disenchanting', - multiplier: 1, - l5Perks: [ - createPerk('de_t1_l5_a', 'Reclaimer', '+15% Mana Recovery', 'A', - { type: 'multiplier', stat: 'disenchantRecovery', value: 0.15 }, false, 1.5, 5), - createPerk('de_t1_l5_b', 'Swift Salvage', '-10% Disenchant Time', 'B', - { type: 'multiplier', stat: 'disenchantTime', value: -0.10 }, false, 1.5, 5), - createPerk('de_t1_l5_c', 'Efficient Return', '+5% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.05 }, false, 1.5, 5), - ], - l10Perks: [ - createPerk('de_t1_l10_a', 'Greater Reclaimer', '+20% Mana Recovery', 'A', - { type: 'multiplier', stat: 'disenchantRecovery', value: 0.20 }, false, 2.0, 10), - createPerk('de_t1_l10_b', 'Rapid Salvage', '-15% Disenchant Time', 'B', - { type: 'multiplier', stat: 'disenchantTime', value: -0.15 }, false, 2.0, 10), - createPerk('de_t1_l10_c', 'Superior Return', '+10% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.10 }, false, 2.0, 10), - ], - }, - // TIER 2 - { - tier: 2, - skillId: 'disenchanting_t2', - name: 'Greater Disenchanting', - multiplier: 10, - l5Perks: [ - createPerk('de_t2_l5_a', 'Master Reclaimer', '+25% Mana Recovery', 'A', - { type: 'multiplier', stat: 'disenchantRecovery', value: 0.25 }, false, 2.0, 5), - createPerk('de_t2_l5_b', 'Expert Salvage', '-20% Disenchant Time', 'B', - { type: 'multiplier', stat: 'disenchantTime', value: -0.20 }, false, 2.0, 5), - createPerk('de_t2_l5_c', 'Transmute Power', '+15% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.15 }, false, 2.0, 5), - ], - l10Perks: [ - createPerk('de_t2_l10_a', 'Ultimate Reclaimer', '+30% Mana Recovery', 'A', - { type: 'multiplier', stat: 'disenchantRecovery', value: 0.30 }, false, 2.5, 10), - createPerk('de_t2_l10_b', 'Lightning Salvage', '-25% Disenchant Time', 'B', - { type: 'multiplier', stat: 'disenchantTime', value: -0.25 }, false, 2.5, 10), - createPerk('de_t2_l10_c', 'Divine Transmute', '+20% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.20 }, false, 2.5, 10), - ], - }, - // TIER 3 - { - tier: 3, - skillId: 'disenchanting_t3', - name: 'Perfect Disenchanting', - multiplier: 100, - l5Perks: [ - createPerk('de_t3_l5_a', 'Cosmic Reclaimer', '+40% Mana Recovery', 'A', - { type: 'multiplier', stat: 'disenchantRecovery', value: 0.40 }, false, 3.0, 5), - createPerk('de_t3_l5_b', 'Instant Salvage', '-30% Disenchant Time', 'B', - { type: 'multiplier', stat: 'disenchantTime', value: -0.30 }, false, 3.0, 5), - createPerk('de_t3_l5_c', 'Transcendent Transmute', '+25% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.25 }, false, 3.0, 5), - ], - l10Perks: [ - createPerk('de_t3_l10_a', '[ELITE] OMNI-RECLAIMER', 'Mana Recovery is 50%', 'A', - { type: 'special', specialId: 'omniReclaimer', specialDesc: '50% mana recovery' }, true, 5.0, 10), - createPerk('de_t3_l10_b', '[ELITE] OMNI-SALVAGE', 'Disenchant Time is halved', 'B', - { type: 'special', specialId: 'omniSalvage', specialDesc: '50% less time' }, true, 5.0, 10), - createPerk('de_t3_l10_c', '[ELITE] OMNI-TRANSMUTE', 'Enchantment Power is 2x', 'C', - { type: 'special', specialId: 'omniTransmute', specialDesc: '2x enchantment power' }, true, 5.0, 10), - ], - }, -]; - -// ─── ENCHANT SPEED TALENT TREE ──────────────────────────────────────────────── -// Base: Reduces Enchantment Time -// Paths: A = The Swift (Speed), B = The Efficient (Capacity), C = The Rapid (Bonus Effects) - -const ENCHANT_SPEED_TIERS: SkillTierDef[] = [ - // TIER 1 - { - tier: 1, - skillId: 'enchantSpeed', - name: 'Enchant Speed', - multiplier: 1, - l5Perks: [ - createPerk('es_t1_l5_a', 'Swift Craft', '-15% Enchantment Time', 'A', - { type: 'multiplier', stat: 'enchantTime', value: -0.15 }, false, 1.5, 5), - createPerk('es_t1_l5_b', 'Efficient Design', '-10% Enchantment Capacity Cost', 'B', - { type: 'multiplier', stat: 'enchantCost', value: -0.10 }, false, 1.5, 5), - createPerk('es_t1_l5_c', 'Quick Work', '+5% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.05 }, false, 1.5, 5), - ], - l10Perks: [ - createPerk('es_t1_l10_a', 'Faster Craft', '-20% Enchantment Time', 'A', - { type: 'multiplier', stat: 'enchantTime', value: -0.20 }, false, 2.0, 10), - createPerk('es_t1_l10_b', 'Thrifty Design', '-15% Enchantment Capacity Cost', 'B', - { type: 'multiplier', stat: 'enchantCost', value: -0.15 }, false, 2.0, 10), - createPerk('es_t1_l10_c', 'Superior Work', '+10% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.10 }, false, 2.0, 10), - ], - }, - // TIER 2 - { - tier: 2, - skillId: 'enchantSpeed_t2', - name: 'Greater Speed', - multiplier: 10, - l5Perks: [ - createPerk('es_t2_l5_a', 'Rapid Craft', '-25% Enchantment Time', 'A', - { type: 'multiplier', stat: 'enchantTime', value: -0.25 }, false, 2.0, 5), - createPerk('es_t2_l5_b', 'Master Design', '-20% Enchantment Capacity Cost', 'B', - { type: 'multiplier', stat: 'enchantCost', value: -0.20 }, false, 2.0, 5), - createPerk('es_t2_l5_c', 'Expert Work', '+15% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.15 }, false, 2.0, 5), - ], - l10Perks: [ - createPerk('es_t2_l10_a', 'Lightning Craft', '-30% Enchantment Time', 'A', - { type: 'multiplier', stat: 'enchantTime', value: -0.30 }, false, 2.5, 10), - createPerk('es_t2_l10_b', 'Ultimate Design', '-25% Enchantment Capacity Cost', 'B', - { type: 'multiplier', stat: 'enchantCost', value: -0.25 }, false, 2.5, 10), - createPerk('es_t2_l10_c', 'Master Work', '+20% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.20 }, false, 2.5, 10), - ], - }, - // TIER 3 - { - tier: 3, - skillId: 'enchantSpeed_t3', - name: 'Perfect Speed', - multiplier: 100, - l5Perks: [ - createPerk('es_t3_l5_a', 'Instant Craft', '-40% Enchantment Time', 'A', - { type: 'multiplier', stat: 'enchantTime', value: -0.40 }, false, 3.0, 5), - createPerk('es_t3_l5_b', 'Cosmic Design', '-30% Enchantment Capacity Cost', 'B', - { type: 'multiplier', stat: 'enchantCost', value: -0.30 }, false, 3.0, 5), - createPerk('es_t3_l5_c', 'Divine Work', '+25% Enchantment Power', 'C', - { type: 'multiplier', stat: 'enchantPower', value: 0.25 }, false, 3.0, 5), - ], - l10Perks: [ - createPerk('es_t3_l10_a', '[ELITE] OMNI-SPEED', 'Enchantment Time is halved', 'A', - { type: 'special', specialId: 'omniSpeedEnchant', specialDesc: '50% less time' }, true, 5.0, 10), - createPerk('es_t3_l10_b', '[ELITE] OMNI-DESIGN', 'Enchantment Capacity Cost is halved', 'B', - { type: 'special', specialId: 'omniDesign', specialDesc: '50% less capacity cost' }, true, 5.0, 10), - createPerk('es_t3_l10_c', '[ELITE] OMNI-WORK', 'Enchantment Power is 2x', 'C', - { type: 'special', specialId: 'omniWork', specialDesc: '2x enchantment power' }, true, 5.0, 10), - ], - }, -]; +// Disenchanting skill removed - see Bug 13 +const DISENCHANTING_TIERS: SkillTierDef[] = []; // Empty - skill removed // ─── INVOCATION TALENT TREE (Invoker Attunement) ────────────────────────────── // Base: Enhances spell invocation and guardian pacts @@ -2046,10 +1898,7 @@ export const SKILL_EVOLUTION_PATHS: Record = { baseSkillId: 'efficientEnchant', tiers: EFFICIENT_ENCHANT_TIERS, }, - disenchanting: { - baseSkillId: 'disenchanting', - tiers: DISENCHANTING_TIERS, - }, + // disenchanting removed - see Bug 13 enchantSpeed: { baseSkillId: 'enchantSpeed', tiers: ENCHANT_SPEED_TIERS, diff --git a/src/lib/game/skills.test.ts b/src/lib/game/skills.test.ts index ff0d79c..749c199 100755 --- a/src/lib/game/skills.test.ts +++ b/src/lib/game/skills.test.ts @@ -348,7 +348,8 @@ describe('Enchanter Skills', () => { describe('Disenchanting (Recover mana from removed enchantments)', () => { it('skill definition should exist', () => { - expect(SKILLS_DEF.disenchanting).toBeDefined(); + // disenchanting skill removed - see Bug 13 + expect(SKILLS_DEF.disenchanting).toBeUndefined(); }); }); }); diff --git a/src/lib/game/store.ts b/src/lib/game/store.ts index dda9424..e9e257d 100755 --- a/src/lib/game/store.ts +++ b/src/lib/game/store.ts @@ -1797,10 +1797,38 @@ export const useGameStore = create()( } } - // Check mana cost (with focused mind reduction) + // Check raw mana cost (with focused mind reduction) const costMult = getStudyCostMultiplier(state.skills); const cost = Math.floor(sk.base * (currentLevel + 1) * costMult); - if (state.rawMana < cost) return; + if (state.rawMana < cost) { + set({ + log: [`❌ Not enough raw mana to study ${sk.name}.`, ...state.log.slice(0, 49)], + }); + return; + } + + // Check additional cost (e.g., element mana for Bug 9, 11) + if (sk.cost) { + if (sk.cost.type === 'element') { + const element = state.elements[sk.cost.element]; + if (!element || element.current < sk.cost.amount) { + set({ + log: [`❌ Need ${sk.cost.amount} ${sk.cost.element} mana to study ${sk.name}.`, ...state.log.slice(0, 49)], + }); + return; + } + // Deduct element mana + set({ + elements: { + ...state.elements, + [sk.cost.element]: { + ...state.elements[sk.cost.element], + current: state.elements[sk.cost.element].current - sk.cost.amount, + }, + }, + }); + } + } // Start studying set({ @@ -2522,7 +2550,7 @@ export const useGameStore = create()( const instance = state.equipmentInstances[instanceId]; if (!instance || instance.enchantments.length === 0) return; - const disenchantLevel = state.skills.disenchanting || 0; + const disenchantLevel = 0; // disenchanting skill removed (Bug 13) const recoveryRate = 0.1 + disenchantLevel * 0.2; // 10% base + 20% per level let totalRecovered = 0; diff --git a/src/lib/game/store/craftingSlice.ts b/src/lib/game/store/craftingSlice.ts index fb84ae2..05564dd 100755 --- a/src/lib/game/store/craftingSlice.ts +++ b/src/lib/game/store/craftingSlice.ts @@ -99,6 +99,7 @@ export function createEquipmentInstance(typeId: string, name?: string): Equipmen totalCapacity: typeDef.baseCapacity, rarity: 'common', quality: 100, // Full quality for new items + tags: [], // Initialize with empty tags array }; } @@ -466,7 +467,7 @@ export const createCraftingSlice: StateCreator= progress.required) { - // Preparation complete - clear enchantments + // Preparation complete - clear enchantments and add 'Ready for Enchantment' tag set((state) => ({ preparationProgress: null, equipmentInstances: { @@ -476,6 +477,7 @@ export const createCraftingSlice: StateCreator; // Skill prerequisites attunementReq?: Record; // Attunement level requirements (attunement id -> min level) studyTime: number; // Hours needed to study