Skip to content

Instantly share code, notes, and snippets.

@ljosberinn
Last active May 4, 2024 11:04
Show Gist options
  • Save ljosberinn/f7117e5833e365afe91b0ba8e5b1993c to your computer and use it in GitHub Desktop.
Save ljosberinn/f7117e5833e365afe91b0ba8e5b1993c to your computer and use it in GitHub Desktop.
Umbreskul's Fractured Heart - DF S4 Report Component
const itemId = 212684;
const dotId = 433522;
const executeSpell = 433549;
const title = `<ItemIcon id="${itemId}" icon="inv_elemental_eternal_air" type="4">Umbrelskul's Fractured Heart</ItemIcon>`;
getComponent = () => {
const actors = {};
const actorsById = {};
for (const actor of reportGroup.actors) {
actorsById[actor.id] = actor;
}
for (const fight of reportGroup.fights) {
for (const combatantInfoEvent of fight.combatantInfoEvents) {
for (const item of combatantInfoEvent.gear) {
if (item.id === itemId) {
const actor = actorsById[combatantInfoEvent.source.id];
const spec = fight.specForPlayer(actor);
actors[combatantInfoEvent.source.id] = {
dot: 0,
instakill: 0,
title: `<ActorIcon type="${combatantInfoEvent.source.subType}-${spec}">${combatantInfoEvent.source.name}</ActorIcon>`,
allDamageDone: 0,
};
break;
}
}
}
/** @type Record<number, number> */
const instakillCandidates = {};
for (const event of fight.allEvents) {
if (event.type === "damage") {
if (event.source.type !== "Player") {
continue;
}
const key = `${event.target.id}-${event.targetInstanceId}`;
const totalForEvent =
event.amount + (event.absorbed ?? 0) - (event.overkill ?? 0);
if (event.ability?.id === dotId) {
actors[event.source.id].dot += totalForEvent;
// initialize watching the debuffed target
instakillCandidates[key] = 0;
// setup actor in case of missing combatant info
if (!(event.source.id in actors)) {
const actor = actorsById[event.source.id];
const spec = fight.specForPlayer(actor);
actors[event.source.id] = {
dot: 0,
instakill: 0,
title: `<ActorIcon type="${event.source.subType}-${spec}">${event.source.name}</ActorIcon>`,
allDamageDone: 0,
};
}
}
if (event.source.id in actors) {
actors[event.source.id].allDamageDone += totalForEvent;
}
// remember last seen hit points per afflicted target
if (key in instakillCandidates && event.targetResources) {
instakillCandidates[key] = event.targetResources.hitPoints;
}
continue;
}
if (
event.type === "instakill" &&
event.source.id in actors &&
event.ability?.id === executeSpell
) {
const key = `${event.target.id}-${event.targetInstanceId}`;
if (!(key in instakillCandidates)) {
continue;
}
actors[event.source.id].instakill += instakillCandidates[key];
// cleanup for memory
delete instakillCandidates[key];
}
}
}
const data = [];
for (const actorId in actors) {
const actor = actors[actorId];
const total = actor.dot + actor.instakill;
const dataset = {
name: actor.title,
dot: format(actor.dot),
instakill: format(actor.instakill),
total: format(total),
percentage: ((actor.instakill / total) * 100).toFixed(2) + "%",
overallPercentage:
format((total / actor.allDamageDone) * 100).toFixed(2) + "%",
};
data.push(dataset);
}
if (data.length === 0) {
return {
component: "EnhancedMarkdown",
props: {
content: `Nobody was seen using ${title}`,
},
};
}
return {
component: "Table",
props: {
columns: {
title: {
header: title,
columns: {
name: {
header: "Name",
},
dot: {
header: "DoT",
textAlign: "right",
},
instakill: {
header: "Execute",
textAlign: "right",
},
total: {
header: "Total",
textAlign: "right",
},
percentage: {
header: "Instakill %",
textAlign: "right",
},
overallPercentage: {
header: "Overall %",
textAlign: "right",
},
},
},
},
data: data.sort((a, b) => a.total > b.total),
},
};
};
// no Intl.NumberFormatter available :sadge:
function format(number) {
if (number < 1000) {
return number;
}
if (number >= 1000 && number < 1_000_000) {
return (number / 1000).toFixed(12) + "K";
}
if (number >= 1_000_000 && number < 1_000_000_000) {
return (number / 1000000).toFixed(2) + "M";
}
if (number >= 1000000000 && number < 1000000000000) {
return (number / 1000000000).toFixed(2) + "B";
}
if (number >= 1000000000000 && number < 1000000000000000) {
return (number / 1000000000000).toFixed(2) + "T";
}
}
@quentiamem
Copy link

what exactly does it do? Can I use it?

@ljosberinn
Copy link
Author

@quentiamem
https://twitter.com/xepher1s/status/1773713050048070018?t=AGrY0kJHdm7xHwM7uHE2_Q&s=19 context here, if you have access to report components then yes you can use it!

alternatively, here's a weakauras version https://wago.io/lXT9wfXYl

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment