damageemter-breakdown
This commit is contained in:
@@ -1540,6 +1540,34 @@ function formatDamagePartsWithIcons(parts) {
|
|||||||
.join(" ");
|
.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) {
|
function resolveParticipantName(participant) {
|
||||||
if (!participant) return "Unknown";
|
if (!participant) return "Unknown";
|
||||||
|
|
||||||
@@ -1695,13 +1723,37 @@ function computeDamageMeterData() {
|
|||||||
const filtered = currentEncounterId ? entries.filter((e) => e.encounterId === currentEncounterId) : entries;
|
const filtered = currentEncounterId ? entries.filter((e) => e.encounterId === currentEncounterId) : entries;
|
||||||
if (!filtered.length) continue;
|
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({
|
totals.push({
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
name: actor.name,
|
name: actor.name,
|
||||||
total,
|
total,
|
||||||
hits: filtered.length,
|
hits: filtered.length,
|
||||||
last: filtered[0],
|
last: filtered[0],
|
||||||
|
img,
|
||||||
|
composition,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1721,16 +1773,16 @@ function buildDamageMeterContent() {
|
|||||||
(t, idx) => {
|
(t, idx) => {
|
||||||
const max = totals[0]?.total || 1;
|
const max = totals[0]?.total || 1;
|
||||||
const pct = Math.max(1, Math.round((t.total / max) * 100));
|
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 `
|
return `
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding:4px 6px;">${idx + 1}</td>
|
<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.total}</td>
|
||||||
<td style="padding:4px 6px; text-align:right;">${t.hits}</td>
|
<td style="padding:4px 6px; text-align:right;">${t.hits}</td>
|
||||||
<td style="padding:4px 6px; max-width: 220px;">
|
<td style="padding:4px 6px; max-width: 220px;">
|
||||||
<div style="background:#e0e0e0; border-radius:4px; overflow:hidden; height:10px; margin-bottom:4px;">
|
${bar}
|
||||||
<div style="width:${pct}%; background:#ff9800; height:10px;"></div>
|
|
||||||
</div>
|
|
||||||
${t.last?.breakdown ?? ""}
|
${t.last?.breakdown ?? ""}
|
||||||
</td>
|
</td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
|
|||||||
Reference in New Issue
Block a user