Add skill base stat entry
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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 = `
|
||||
<label>Effect ${effectIndex + 1}
|
||||
<select data-effect-type="${effectIndex}">
|
||||
<option value="">None</option>
|
||||
${EFFECTS.map((option) => `<option value="${option.id}">${option.label} (max ${option.cap}%)</option>`).join("")}
|
||||
</select>
|
||||
</label>
|
||||
<label>Percent
|
||||
<input data-effect-value="${effectIndex}" type="number" min="1" step="0.1" value="${effect.value}" />
|
||||
<span class="cap-hint"></span>
|
||||
</label>`;
|
||||
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 = '<p class="no-effects-note">Base stats only. No effects.</p>';
|
||||
} else {
|
||||
piece.effects.forEach((effect, effectIndex) => {
|
||||
const row = document.createElement("div");
|
||||
row.className = "effect-row";
|
||||
row.innerHTML = `
|
||||
<label>Effect ${effectIndex + 1}
|
||||
<select data-effect-type="${effectIndex}">
|
||||
<option value="">None</option>
|
||||
${EFFECTS.map((option) => `<option value="${option.id}">${option.label} (max ${option.cap}%)</option>`).join("")}
|
||||
</select>
|
||||
</label>
|
||||
<label>Percent
|
||||
<input data-effect-value="${effectIndex}" type="number" min="1" step="0.1" value="${effect.value}" />
|
||||
<span class="cap-hint"></span>
|
||||
</label>`;
|
||||
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);
|
||||
});
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user