Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 105 additions & 5 deletions ui/raidboss/data/07-dt/ultimate/dancing_mad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ import { LocaleText, OutputStrings, TriggerSet } from '../../../../../types/trig

// TODO: P2 Old AAAABBBB plan was found at https://raidplan.io/plan/kj2d734d36es2ugs, would like to find replacement
// TODO: P3 Better Blackhole no-config support via debuff tracking?
// TODO: Earlier phase tracking for P5 (counting the jumps to middle?)

type Phase = 'p1' | 'p2' | 'p3' | 'p4' | 'p5';
const phases: { [id: string]: Phase } = {
'C24C': 'p2', // Ultimate Embrace, God Kefka
'C3F7': 'p3', // Aero III Assault (from Kefka), Chaos and Exdeath
'C2DC': 'p4', // Kefka Says, Kefka with Chaos and Neo Exdeath
'BB40': 'p5', // Ultima Repeater, Ultima Kefka
};

const centerX = 100;
Expand All @@ -40,6 +38,7 @@ export interface Data extends RaidbossData {
};
// General
phase: Phase | 'unknown';
middleCount: number;
// Phase 1
actorPositions: { [id: string]: { x: number; y: number; heading: number } };
gravenImageCount: number;
Expand Down Expand Up @@ -1005,6 +1004,7 @@ const triggerSet: TriggerSet<Data> = {
initData: () => {
return {
phase: 'p1',
middleCount: 0,
// Phase 1
actorPositions: {},
gravenImageCount: 0,
Expand Down Expand Up @@ -1051,11 +1051,24 @@ const triggerSet: TriggerSet<Data> = {
},
triggers: [
{
id: 'DMU Phase Tracker',
id: 'DMU Phase 1-4 Tracker',
type: 'StartsUsing',
netRegex: { id: Object.keys(phases) },
run: (data, matches) => data.phase = phases[matches.id] ?? 'unknown',
},
{
id: 'DMU Phase 5 Tracker',
// Ultimate Kefka
// Track jumps to middle for earlier P5 and Ultima Upsurge
// Rather than using BB40 Ultima Repeater
type: 'Ability',
netRegex: { id: 'C3FD', source: 'Kefka', capture: false },
run: (data) => {
data.middleCount = data.middleCount + 1;
if (data.middleCount === 5)
data.phase = 'p5';
},
},
{
id: 'DMU ActorSetPos Tracker',
// P1 Graven Image tethers
Expand Down Expand Up @@ -8046,10 +8059,90 @@ const triggerSet: TriggerSet<Data> = {
},
},
{
id: 'DMU P4/P5 Ultima Upsurge',
id: 'DMU P4 Ultima Upsurge',
type: 'StartsUsing',
netRegex: { id: 'C24A', source: 'Kefka', capture: false },
response: Responses.bigAoe(),
condition: (data) => data.phase === 'p4',
durationSeconds: (data) => {
return (data.isEntropyTrue || data.isEntropyTrue === undefined)
? 5
: 7; // Time until Donuts
},
infoText: (data, _matches, output) => {
const bigAoe = output.bigAoe!();
if (data.isEntropyTrue || data.isEntropyTrue === undefined)
return bigAoe; // Player needs to move within 2.6s, TTS would be too long
const is1stTrue = data.areFirstDebuffsTrue;
const is2ndTrue = data.areThirdDebuffsTrue;
const isFirstShort = data.isFirstDebuffShort;
if (is1stTrue === undefined || is2ndTrue === undefined || isFirstShort === undefined)
return bigAoe;
const isLongTrue = isFirstShort ? is2ndTrue : is1stTrue;

const hasFork = data.longForkedPlayers.includes(data.me);
const hasCompressed = data.longCompressedPlayers.includes(data.me);
const hasFirstBomb = data.firstLongBombPlayers.includes(data.me);
const hasSecondBomb = data.secondLongBombPlayers.includes(data.me);
const isBombTrue = hasFirstBomb ? is1stTrue : is2ndTrue;

const hasSpread = (hasFork && isLongTrue) || (hasCompressed && !isLongTrue);
const hasStack = (hasFork && !isLongTrue) || (hasCompressed && isLongTrue);
const hasBomb = hasFirstBomb || hasSecondBomb;

// Handle 2 Mechs
let mechs = output.noDebuff!(); // Has nothing
if (hasSpread && hasBomb)
mechs = output.forkBomb!({
mech1: output.spread!(),
mech2: isBombTrue ? output.bomb!() : output.fakeBomb!(),
});
else if (hasStack && hasBomb)
mechs = output.compressedBomb!({
mech1: output.stack!(),
mech2: isBombTrue ? output.bomb!() : output.fakeBomb!(),
});
else if (hasSpread)
mechs = output.spread!();
else if (hasStack)
mechs = output.stack!();
else if (hasBomb)
mechs = output.bombStack!({
mech1: isBombTrue ? output.bomb!() : output.fakeBomb!(),
mech2: output.stack!(),
});

return output.aoeThenMech!({
aoe: bigAoe,
mech: mechs,
});
},
outputStrings: {
bigAoe: Outputs.bigAoe,
you: {
en: 'YOU',
},
bombStack: {
en: '${mech1} + ${mech2}',
},
forkBomb: {
en: '${mech1} + ${mech2}',
},
compressedBomb: {
en: '${mech1} + ${mech2}',
},
noDebuff: Outputs.stackMarker,
stack: Outputs.stackMarker,
spread: Outputs.spread,
bomb: {
en: 'Stillness',
},
fakeBomb: {
en: 'Motion',
},
aoeThenMech: {
en: '${aoe} => ${mech}',
},
},
},
{
id: 'DMU P4 Stray Flames and Long Debuffs',
Expand Down Expand Up @@ -8316,6 +8409,13 @@ const triggerSet: TriggerSet<Data> = {
suppressSeconds: 99999,
response: Responses.moveAway('alert'),
},
{
id: 'DMU P5 Ultima Upsurge',
type: 'StartsUsing',
netRegex: { id: 'C24A', source: 'Kefka', capture: false },
condition: (data) => data.phase === 'p5',
response: Responses.bigAoe(),
},
],
timelineReplace: [
{
Expand Down