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; }