damageemter-breakdown
This commit is contained in:
@@ -1540,6 +1540,34 @@ function formatDamagePartsWithIcons(parts) {
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
function renderDamageBar(composition = [], total = 0) {
|
||||
const iconMap = {
|
||||
slashing: { icon: "ra ra-sword", color: "#e3c000" },
|
||||
piercing: { icon: "ra ra-spear-head", color: "#2c7be5" },
|
||||
bludgeoning: { icon: "ra ra-large-hammer", color: "#e03131" },
|
||||
fire: { icon: "ra ra-fire", color: "#f76707" },
|
||||
cold: { icon: "ra ra-snowflake", color: "#3bc9db" },
|
||||
electricity: { icon: "ra ra-lightning-bolt", color: "#f0c419" },
|
||||
acid: { icon: "ra ra-round-bottom-flask", color: "#2f9e44" },
|
||||
sonic: { icon: "ra ra-megaphone", color: "#22b8cf" },
|
||||
force: { icon: "ra ra-crystal-ball", color: "#845ef7" },
|
||||
negative: { icon: "ra ra-skull", color: "#7950f2" },
|
||||
positive: { icon: "ra ra-sun", color: "#fab005" },
|
||||
precision: { icon: "ra ra-target-arrows", color: "#000" },
|
||||
nonlethal: { icon: "ra ra-hand", color: "#000" },
|
||||
untyped: { icon: "ra ra-uncertainty", color: "#666" },
|
||||
};
|
||||
if (!total || !composition.length) return "";
|
||||
const segments = composition.map((c) => {
|
||||
const pct = Math.max(2, Math.round((c.value / total) * 100));
|
||||
const entry = iconMap[c.type?.toLowerCase?.()] ?? iconMap.untyped;
|
||||
return `<div style="width:${pct}%; background:${entry.color}; height:10px; display:flex; align-items:center; justify-content:center;">
|
||||
<i class="${entry.icon}" style="color:#fff; font-size:10px;"></i>
|
||||
</div>`;
|
||||
});
|
||||
return `<div style="display:flex; width:100%; background:#e0e0e0; border-radius:4px; overflow:hidden; height:10px; margin-bottom:4px;">${segments.join("")}</div>`;
|
||||
}
|
||||
|
||||
function resolveParticipantName(participant) {
|
||||
if (!participant) return "Unknown";
|
||||
|
||||
@@ -1695,13 +1723,37 @@ function computeDamageMeterData() {
|
||||
const filtered = currentEncounterId ? entries.filter((e) => e.encounterId === currentEncounterId) : entries;
|
||||
if (!filtered.length) continue;
|
||||
|
||||
const total = filtered.reduce((sum, e) => sum + (Number(e.amount) || 0), 0);
|
||||
const typeTotals = new Map();
|
||||
let total = 0;
|
||||
for (const e of filtered) {
|
||||
const amount = Number(e.amount) || 0;
|
||||
total += amount;
|
||||
const parts = e.damageDetails?.parts;
|
||||
if (Array.isArray(parts) && parts.length) {
|
||||
for (const p of parts) {
|
||||
const t = (p.types && p.types[0]) || p.customTypes?.[0] || p.materials?.[0] || "untyped";
|
||||
const prev = typeTotals.get(t) ?? 0;
|
||||
typeTotals.set(t, prev + (Number(p.total) || 0));
|
||||
}
|
||||
} else {
|
||||
const prev = typeTotals.get("untyped") ?? 0;
|
||||
typeTotals.set("untyped", prev + amount);
|
||||
}
|
||||
}
|
||||
|
||||
const composition = Array.from(typeTotals.entries())
|
||||
.map(([type, value]) => ({ type, value }))
|
||||
.sort((a, b) => b.value - a.value);
|
||||
|
||||
const img = actor.prototypeToken?.texture?.src || actor.img || "";
|
||||
totals.push({
|
||||
actorId: actor.id,
|
||||
name: actor.name,
|
||||
total,
|
||||
hits: filtered.length,
|
||||
last: filtered[0],
|
||||
img,
|
||||
composition,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1721,16 +1773,16 @@ function buildDamageMeterContent() {
|
||||
(t, idx) => {
|
||||
const max = totals[0]?.total || 1;
|
||||
const pct = Math.max(1, Math.round((t.total / max) * 100));
|
||||
const bar = renderDamageBar(t.composition, t.total) || `<div style="background:#e0e0e0; border-radius:4px; overflow:hidden; height:10px; margin-bottom:4px;"><div style="width:${pct}%; background:#ff9800; height:10px;"></div></div>`;
|
||||
const avatar = t.img ? `<img src="${t.img}" style="width:18px; height:18px; object-fit:cover; border-radius:3px; margin-right:6px;" />` : "";
|
||||
return `
|
||||
<tr>
|
||||
<td style="padding:4px 6px;">${idx + 1}</td>
|
||||
<td style="padding:4px 6px;">${t.name}</td>
|
||||
<td style="padding:4px 6px; display:flex; align-items:center;">${avatar}${t.name}</td>
|
||||
<td style="padding:4px 6px; text-align:right;">${t.total}</td>
|
||||
<td style="padding:4px 6px; text-align:right;">${t.hits}</td>
|
||||
<td style="padding:4px 6px; max-width: 220px;">
|
||||
<div style="background:#e0e0e0; border-radius:4px; overflow:hidden; height:10px; margin-bottom:4px;">
|
||||
<div style="width:${pct}%; background:#ff9800; height:10px;"></div>
|
||||
</div>
|
||||
${bar}
|
||||
${t.last?.breakdown ?? ""}
|
||||
</td>
|
||||
</tr>`;
|
||||
|
||||
Reference in New Issue
Block a user