From 5e37706f3232a80d762742653c9e6b0e2b6e005c Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Tue, 16 Jun 2026 15:31:04 +0200 Subject: [PATCH] Add skill base stat entry --- README.md | 3 ++- app.js | 49 ++++++++++++++++++++++++++++--------------------- styles.css | 1 + 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 45e19ad..b6cde64 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Forge Master characters can equip: - 8 items - 1 mount - 3 pets +- 1 skill base-stat entry Each equipped piece has: @@ -31,7 +32,7 @@ The 8 core item slots are fixed and cannot be renamed or have their base stat ed | Item 7 | Boots | 1,850,000 health | | Item 8 | Belt | 1,150,000 health | -Mount and pet base stats remain editable, and each has separate damage and health base values because they can provide both stats at once. +Mount and pet base stats remain editable, and each has separate damage and health base values because they can provide both stats at once. Skill base stats are entered separately as damage and health and do not have effects. ## Supported effects diff --git a/app.js b/app.js index caad668..0d21aa1 100644 --- a/app.js +++ b/app.js @@ -58,6 +58,7 @@ const slots = [ ...FIXED_ITEMS.map((item, i) => ({ type: "item", title: `Item ${i + 1}`, fixed: item })), { type: "mount", title: "Mount" }, ...Array.from({ length: 3 }, (_, i) => ({ type: "pet", title: `Pet ${i + 1}` })), + { type: "skill", title: "Skill", noEffects: true }, ]; const $ = (selector) => document.querySelector(selector); @@ -86,7 +87,8 @@ function createDefaultPiece(slot, index) { baseDamage: slot.fixed?.baseType === "damage" ? slot.fixed.baseValue : 0, baseHealth: slot.fixed?.baseType === "health" ? slot.fixed.baseValue : 0, fixedBase: Boolean(slot.fixed), - effects: [{ type: "", value: 1 }, { type: "", value: 1 }], + noEffects: Boolean(slot.noEffects), + effects: slot.noEffects ? [] : [{ type: "", value: 1 }, { type: "", value: 1 }], }; } @@ -117,7 +119,8 @@ function normalizeState(candidate) { ...(candidate?.pieces?.[index] || {}), baseDamage: Number(candidate?.pieces?.[index]?.baseDamage ?? (candidate?.pieces?.[index]?.baseType === "damage" ? candidate?.pieces?.[index]?.baseValue : piece.baseDamage) ?? 0), baseHealth: Number(candidate?.pieces?.[index]?.baseHealth ?? (candidate?.pieces?.[index]?.baseType === "health" ? candidate?.pieces?.[index]?.baseValue : piece.baseHealth) ?? 0), - effects: [0, 1].map((effectIndex) => ({ + noEffects: piece.noEffects || Boolean(candidate?.pieces?.[index]?.noEffects), + effects: piece.noEffects ? [] : [0, 1].map((effectIndex) => ({ type: candidate?.pieces?.[index]?.effects?.[effectIndex]?.type || "", value: clampEffectValue( candidate?.pieces?.[index]?.effects?.[effectIndex]?.type || "", @@ -187,25 +190,29 @@ function renderGear() { } const effects = node.querySelector(".effects"); - piece.effects.forEach((effect, effectIndex) => { - const row = document.createElement("div"); - row.className = "effect-row"; - row.innerHTML = ` - - `; - row.querySelector("select").value = effect.type; - const hint = row.querySelector(".cap-hint"); - hint.textContent = effect.type ? `Cap: ${effectById(effect.type).cap}%` : "Ignored"; - effects.appendChild(row); - }); + if (piece.noEffects) { + effects.innerHTML = '

Base stats only. No effects.

'; + } else { + piece.effects.forEach((effect, effectIndex) => { + const row = document.createElement("div"); + row.className = "effect-row"; + row.innerHTML = ` + + `; + row.querySelector("select").value = effect.type; + const hint = row.querySelector(".cap-hint"); + hint.textContent = effect.type ? `Cap: ${effectById(effect.type).cap}%` : "Ignored"; + effects.appendChild(row); + }); + } grid.appendChild(node); }); diff --git a/styles.css b/styles.css index 8bf40c2..6f0eb94 100644 --- a/styles.css +++ b/styles.css @@ -207,6 +207,7 @@ h3 { margin-bottom: 0; } .effect-row { display: grid; grid-template-columns: 1fr; gap: 0.45rem; align-items: end; } .gear-card .effect-row input[data-effect-value] { width: 100%; } .cap-hint { color: var(--muted); font-size: 0.8rem; margin-top: 0.2rem; } +.no-effects-note { color: var(--muted); font-size: 0.9rem; margin: 0; } @media (max-width: 900px) { .hero, .results { grid-template-columns: 1fr; }