Spaces:
Running
Running
Live-apply equipped-skill changes to the on-field hero's bar
Browse fileswriteEquipped now calls comboCtrl.setHeroSkills(resolveEquipped(hero)) so assigning/
clearing a skill bar slot (or the ★ toggle) updates the live combat bar + buttons
immediately, not just on next spawn. Rebuilt comboBattler bundle.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- web/comboBattler.js +38 -22
- web/tiny.js +6 -1
web/comboBattler.js
CHANGED
|
@@ -6157,6 +6157,38 @@ function mountComboBattler(pixi, host, opts = {}) {
|
|
| 6157 |
window.removeEventListener("pointerup", onUp);
|
| 6158 |
};
|
| 6159 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6160 |
function buildControls() {
|
| 6161 |
const wrap = document.createElement("div");
|
| 6162 |
wrap.style.cssText = "position:absolute;inset:0;pointer-events:none;z-index:5;font-family:monospace";
|
|
@@ -6214,29 +6246,12 @@ function mountComboBattler(pixi, host, opts = {}) {
|
|
| 6214 |
wrap.appendChild(base);
|
| 6215 |
const pad = document.createElement("div");
|
| 6216 |
pad.style.cssText = "position:absolute;right:20px;bottom:20px;display:flex;flex-direction:column;align-items:flex-end;gap:10px;pointer-events:none";
|
| 6217 |
-
const mk = (label, on, big) => {
|
| 6218 |
-
const b = document.createElement("button");
|
| 6219 |
-
b.textContent = label;
|
| 6220 |
-
const s = big ? 70 : 46;
|
| 6221 |
-
b.style.cssText = `pointer-events:auto;touch-action:manipulation;width:${s}px;height:${s}px;border-radius:50%;border:1px solid #20262e;background:rgba(20,24,33,.78);color:#e8e8e8;font:600 ${big ? 22 : 15}px monospace;cursor:pointer`;
|
| 6222 |
-
b.addEventListener("pointerdown", (ev) => {
|
| 6223 |
-
ev.preventDefault();
|
| 6224 |
-
on();
|
| 6225 |
-
});
|
| 6226 |
-
return b;
|
| 6227 |
-
};
|
| 6228 |
const skills = document.createElement("div");
|
| 6229 |
skills.style.cssText = "display:flex;gap:8px;align-items:flex-end";
|
| 6230 |
-
|
| 6231 |
-
|
| 6232 |
-
|
| 6233 |
-
|
| 6234 |
-
}, false);
|
| 6235 |
-
b.title = nm || "";
|
| 6236 |
-
skills.appendChild(b);
|
| 6237 |
-
});
|
| 6238 |
-
if (names.length) pad.appendChild(skills);
|
| 6239 |
-
pad.appendChild(mk("\u2694", () => {
|
| 6240 |
req.attack = true;
|
| 6241 |
}, true));
|
| 6242 |
wrap.appendChild(pad);
|
|
@@ -6422,6 +6437,7 @@ function mountComboBattler(pixi, host, opts = {}) {
|
|
| 6422 |
} catch {
|
| 6423 |
}
|
| 6424 |
controlsEl = null;
|
|
|
|
| 6425 |
try {
|
| 6426 |
markers?.destroy();
|
| 6427 |
} catch {
|
|
@@ -6649,7 +6665,7 @@ function mountComboBattler(pixi, host, opts = {}) {
|
|
| 6649 |
const p = pa();
|
| 6650 |
return p ? { name: p.name, profession: p.profession, hp: Math.round(p.hp), maxHp: Math.round(p.maxHp), skills: (p.bar || []).map((s) => s.name) } : null;
|
| 6651 |
}
|
| 6652 |
-
const ctrl = { ready, selectHero, getSpawnWorld, getSnapshot, getHero, heroEmote, resize, onChange, destroy, map, walkable: (wx, wy) => roamWalkable(wx, wy) };
|
| 6653 |
if (typeof window !== "undefined") {
|
| 6654 |
window.__comboSnap = () => ctrl.getSnapshot();
|
| 6655 |
window.__combo = ctrl;
|
|
|
|
| 6157 |
window.removeEventListener("pointerup", onUp);
|
| 6158 |
};
|
| 6159 |
}
|
| 6160 |
+
let skillRowEl = null;
|
| 6161 |
+
function roundBtn(label, on, big) {
|
| 6162 |
+
const b = document.createElement("button");
|
| 6163 |
+
b.textContent = label;
|
| 6164 |
+
const s = big ? 70 : 46;
|
| 6165 |
+
b.style.cssText = `pointer-events:auto;touch-action:manipulation;width:${s}px;height:${s}px;border-radius:50%;border:1px solid #20262e;background:rgba(20,24,33,.78);color:#e8e8e8;font:600 ${big ? 22 : 15}px monospace;cursor:pointer`;
|
| 6166 |
+
b.addEventListener("pointerdown", (ev) => {
|
| 6167 |
+
ev.preventDefault();
|
| 6168 |
+
on();
|
| 6169 |
+
});
|
| 6170 |
+
return b;
|
| 6171 |
+
}
|
| 6172 |
+
function rebuildSkillButtons() {
|
| 6173 |
+
if (!skillRowEl) return;
|
| 6174 |
+
skillRowEl.replaceChildren();
|
| 6175 |
+
const bar = pa()?.bar || [];
|
| 6176 |
+
bar.forEach((s, i) => {
|
| 6177 |
+
const b = roundBtn(String(i + 1), () => {
|
| 6178 |
+
req.skill = i + 1;
|
| 6179 |
+
}, false);
|
| 6180 |
+
b.title = s.name || "";
|
| 6181 |
+
skillRowEl.appendChild(b);
|
| 6182 |
+
});
|
| 6183 |
+
skillRowEl.style.display = bar.length ? "flex" : "none";
|
| 6184 |
+
}
|
| 6185 |
+
function setHeroSkills(skills) {
|
| 6186 |
+
const p = pa();
|
| 6187 |
+
if (!p) return;
|
| 6188 |
+
p.bar = (skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
|
| 6189 |
+
rebuildSkillButtons();
|
| 6190 |
+
emit();
|
| 6191 |
+
}
|
| 6192 |
function buildControls() {
|
| 6193 |
const wrap = document.createElement("div");
|
| 6194 |
wrap.style.cssText = "position:absolute;inset:0;pointer-events:none;z-index:5;font-family:monospace";
|
|
|
|
| 6246 |
wrap.appendChild(base);
|
| 6247 |
const pad = document.createElement("div");
|
| 6248 |
pad.style.cssText = "position:absolute;right:20px;bottom:20px;display:flex;flex-direction:column;align-items:flex-end;gap:10px;pointer-events:none";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6249 |
const skills = document.createElement("div");
|
| 6250 |
skills.style.cssText = "display:flex;gap:8px;align-items:flex-end";
|
| 6251 |
+
skillRowEl = skills;
|
| 6252 |
+
rebuildSkillButtons();
|
| 6253 |
+
pad.appendChild(skills);
|
| 6254 |
+
pad.appendChild(roundBtn("\u2694", () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6255 |
req.attack = true;
|
| 6256 |
}, true));
|
| 6257 |
wrap.appendChild(pad);
|
|
|
|
| 6437 |
} catch {
|
| 6438 |
}
|
| 6439 |
controlsEl = null;
|
| 6440 |
+
skillRowEl = null;
|
| 6441 |
try {
|
| 6442 |
markers?.destroy();
|
| 6443 |
} catch {
|
|
|
|
| 6665 |
const p = pa();
|
| 6666 |
return p ? { name: p.name, profession: p.profession, hp: Math.round(p.hp), maxHp: Math.round(p.maxHp), skills: (p.bar || []).map((s) => s.name) } : null;
|
| 6667 |
}
|
| 6668 |
+
const ctrl = { ready, selectHero, getSpawnWorld, getSnapshot, getHero, heroEmote, setHeroSkills, resize, onChange, destroy, map, walkable: (wx, wy) => roamWalkable(wx, wy) };
|
| 6669 |
if (typeof window !== "undefined") {
|
| 6670 |
window.__comboSnap = () => ctrl.getSnapshot();
|
| 6671 |
window.__combo = ctrl;
|
web/tiny.js
CHANGED
|
@@ -472,7 +472,12 @@ whenEl('battle-stage', async (el) => {
|
|
| 472 |
}
|
| 473 |
// ── Skill-bar management (equippedSkills = ordered list, max 3 = the in-combat bar) ──
|
| 474 |
const learnedSkills = () => { const cs = currentHero?.customSkills || {}; return (currentHero?.learnedSkills || []).map((id) => cs[id]).filter(Boolean) }
|
| 475 |
-
const writeEquipped = (eq) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 476 |
const toggleEquip = (id) => {
|
| 477 |
const eq = (getPersona(currentHero.id)?.equippedSkills || []).slice()
|
| 478 |
if (eq.includes(id)) writeEquipped(eq.filter((x) => x !== id))
|
|
|
|
| 472 |
}
|
| 473 |
// ── Skill-bar management (equippedSkills = ordered list, max 3 = the in-combat bar) ──
|
| 474 |
const learnedSkills = () => { const cs = currentHero?.customSkills || {}; return (currentHero?.learnedSkills || []).map((id) => cs[id]).filter(Boolean) }
|
| 475 |
+
const writeEquipped = (eq) => {
|
| 476 |
+
patchPersona(currentHero.id, { equippedSkills: eq.slice(0, 3) })
|
| 477 |
+
currentHero = getPersona(currentHero.id)
|
| 478 |
+
comboCtrl?.setHeroSkills?.(resolveEquipped(currentHero)) // live-update the on-field hero's bar + buttons
|
| 479 |
+
renderSheet()
|
| 480 |
+
}
|
| 481 |
const toggleEquip = (id) => {
|
| 482 |
const eq = (getPersona(currentHero.id)?.equippedSkills || []).slice()
|
| 483 |
if (eq.includes(id)) writeEquipped(eq.filter((x) => x !== id))
|