diff --git a/ui/raidboss/data/07-dt/ultimate/dancing_mad.ts b/ui/raidboss/data/07-dt/ultimate/dancing_mad.ts index 23ed3a8757..3ba33a4242 100644 --- a/ui/raidboss/data/07-dt/ultimate/dancing_mad.ts +++ b/ui/raidboss/data/07-dt/ultimate/dancing_mad.ts @@ -1,11 +1,19 @@ +import Conditions from '../../../../../resources/conditions'; +import Outputs from '../../../../../resources/outputs'; +import { Responses } from '../../../../../resources/responses'; import ZoneId from '../../../../../resources/zone_id'; import { RaidbossData } from '../../../../../types/data'; -import { TriggerSet } from '../../../../../types/trigger'; +import { OutputStrings, TriggerSet } from '../../../../../types/trigger'; -type Phase = 'p1' | 'p2' | 'p3'; +// TODO: P1 Tele-Portent configuration options +// 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; @@ -14,8 +22,151 @@ const phases: { [id: string]: Phase } = { export interface Data extends RaidbossData { // General phase: Phase | 'unknown'; + // Phase 1 + actorPositions: { [id: string]: { x: number; y: number; heading: number } }; + gravenImageCount: number; + blueTowerIds: string[]; + purpleTowerIds: string[]; + yellowTowerIds: string[]; + eyeTowerIds: string[]; + fakeEyeTowerIds: string[]; + gravenImageTether?: + | 'pulse' + | 'gravitas' + | 'vitrophyre' + | 'indulgent' + | 'idyllic' + | 'unknown'; + fireMarker?: string; + isFireTrue?: boolean; + isIceTrue?: boolean; + isThunderTrue?: boolean; + waveCannonTargets: string[]; + doubleTroubleTrapTargets: string[]; + myTelePortent1?: 'up' | 'down' | 'right' | 'left'; + myTelePortent2?: 'up' | 'down' | 'right' | 'left'; + // Phase 2 } +const headMarkerData = { + // Phase 1 Boss + 'fakeFire': '02A1', + 'trueFire': '02A2', + 'fakeIce': '02A3', + 'trueIce': '02A4', + 'fakeThunder': '02A5', + 'trueThunder': '02A6', + // Phase 1 Players + 'tankbuster': '00DA', // Revolting Ruin III tankbuster + 'dorito': '007F', // spread (real) or stack (fake) + 'stack': '0080', // spread (fake) or stack (real) + // Phase 1 Tethers + 'imageTether': '002D', + // Phase 2 + 'sharedBuster': '0103', // Ultimate Embrace shared tankbuster + 'stackPath': '02CB', // When standing in Path of Light tower, causes BAC0 Spelldriver (3-person stack) + 'conePath': '02CD', // When standing in Path of Light tower, causes BAC2 Spellwave (cone targetting nearest player) + 'spreadPath': '02CC', // When standing in Path of Light tower, causes BAC1 Spellscatter (small aoe on the player) +} as const; + +const mysteryMagicOutputStrings: OutputStrings = { + puddle: { + en: 'Bait Puddle', + de: 'Fläche ködern', + fr: 'Déposez', + ja: 'AOE誘導', + cn: '诱导AOE', + ko: '장판 유도', + tc: '誘導AOE', + }, + spread: Outputs.spread, + middle: Outputs.goIntoMiddle, + stack: { + en: 'Stack', + de: 'Stacken', + fr: 'Packez-vous', + ja: 'スタック', + cn: '集合', + ko: '집합', + tc: '集合', + }, + trueThunder: { + en: 'Avoid Tell', + }, + fakeThunder: { + en: 'In Line', + }, + trueIce: { + en: 'Avoid Tell', + }, + fakeIce: { + en: 'In Cone', + }, + trueIcePuddle: { + en: '${mech1} + ${mech2} => ${mech3}', + }, + fakeIcePuddle: { + en: '${mech1} + ${mech2} => ${mech3}', + }, + stackTrueIce: { + en: '${mech} + ${ice}', + }, + stackFakeIce: { + en: '${mech} + ${ice}', + }, + spreadTrueIce: { + en: '${mech} + ${ice}', + }, + spreadFakeIce: { + en: '${mech} + ${ice}', + }, + trueIceTrueThunder: { + en: 'Avoid Tells', + }, + fakeIceTrueThunder: { + en: 'Cone (only)', + }, + trueIceFakeThunder: { + en: 'Line (only)', + }, + fakeIceFakeThunder: { + en: 'Cone + Line', + }, + stackTrueThunder: { + en: '${mech} + ${thunder}', + }, + stackFakeThunder: { + en: '${mech} + ${thunder}', + }, + spreadTrueThunder: { + en: '${mech} + ${thunder}', + }, + spreadFakeThunder: { + en: '${mech} + ${thunder}', + }, +}; + +const trapOutputStrings: OutputStrings = { + knockbackFrom1: { + en: 'Knockback from ${players}', + }, + knockbackFrom2: { + en: 'Knockback from ${players}', + }, + knockbackFrom3: { + en: 'Knockback from ${players} => Debuffs', + }, + knockbackFrom3Sleep: { + en: 'Knockback from ${players} => Sleep', + }, + knockbackFrom3Confuse: { + en: 'Knockback from ${players} => Confuse', + }, + knockbackFromLater: { + en: 'Knockback from ${players} (later)', + }, +}; + const triggerSet: TriggerSet = { id: 'DancingMadUltimate', zoneId: ZoneId.DancingMadUltimate, @@ -23,6 +174,17 @@ const triggerSet: TriggerSet = { initData: () => { return { phase: 'p1', + // Phase 1 + actorPositions: {}, + gravenImageCount: 0, + blueTowerIds: [], + purpleTowerIds: [], + yellowTowerIds: [], + eyeTowerIds: [], + fakeEyeTowerIds: [], + waveCannonTargets: [], + doubleTroubleTrapTargets: [], + // Phase 2 }; }, triggers: [ @@ -32,12 +194,1161 @@ const triggerSet: TriggerSet = { netRegex: { id: Object.keys(phases) }, run: (data, matches) => data.phase = phases[matches.id] ?? 'unknown', }, + { + id: 'DMU ActorSetPos Tracker', + // Only in use for P1 Graven Image tethers + type: 'ActorSetPos', + netRegex: { id: '4[0-9A-Fa-f]{7}', capture: true }, + run: (data, matches) => + data.actorPositions[matches.id] = { + x: parseFloat(matches.x), + y: parseFloat(matches.y), + heading: parseFloat(matches.heading), + }, + }, + { + id: 'DMU P1 Revolting Ruin III', + // Tankbuster targets highest enmity then second highest enmity + // A tank swap can happen to have MT take both hits + type: 'HeadMarker', + netRegex: { id: headMarkerData['tankbuster'], capture: true }, + alertText: (data, matches, output) => { + const target = matches.target; + if (target === data.me) + return output.cleaveOnYou!(); + + if (data.role === 'tank') + return output.cleaveSwap!({ + player: data.party.member(target), + }); + + if (data.role === 'healer') + return output.cleaveOnPlayer!({ + player: data.party.member(target), + }); + + return output.avoidCleaves!(); + }, + outputStrings: { + in: Outputs.in, + out: Outputs.out, + cleaveOnYou: Outputs.tankCleaveOnYou, + avoidCleaves: Outputs.avoidTankCleaves, + cleaveOnPlayer: { + en: 'Tank Cleave on ${player}', + }, + cleaveSwap: { // Defaulting to same output as cleaveOnPlayer + en: 'Tank Cleave on ${player}', + }, + }, + }, + { + id: 'DMU P1 Graven Image Counter', + // Used for timing of tether triggers + type: 'StartsUsing', + netRegex: { id: 'BCF2', source: 'Kefka', capture: false }, + run: (data) => data.gravenImageCount = data.gravenImageCount + 1, + }, + { + id: 'DMU P1 Graven Image Tether Collect', + // 271 ActorSetPos lines indicate where the tether is coming from + // 261 CombatantMemory lines may also indicate this + // Graven Image 1: + // (100, 56, 18.5) Center Tether, Will be target of BAA9 Pulse Wave (knockback) + // Graven Image 2: + // (102.5, 27, 22.5) Center Tether, Will be target of BAAC Gravitas (puddles) + // (126, 41.5, 7) Right Tether, Will be target of BAB0 Vitrophyre (rocks) + // Graven Image 3: + // (95, 25, 27) Left Tether, Will be target of BAB5 Indulgent Will which causes 503 Confused + // (107, 43, 8.5) Right tether, Will be target of BAB6 Idyllic Will which causes 131E Sleep + type: 'Tether', + netRegex: { id: headMarkerData['imageTether'], capture: true }, + condition: Conditions.targetIsYou(), + delaySeconds: 0.1, // Actor position data can come after tether in log + run: (data, matches) => { + const actor = data.actorPositions[matches.sourceId]; + if (actor === undefined) { + data.gravenImageTether = 'unknown'; + return; + } + + const x = actor.x; + // Graven Image 1: Pulse Wave target + if (x < 101 && x > 99) + data.gravenImageTether = 'pulse'; + else if (x < 103 && x > 101) // Graven Image 2: Gravitas target + data.gravenImageTether = 'gravitas'; + else if (x > 125) // Graven Image 2: Vitrophyre target + data.gravenImageTether = 'vitrophyre'; + else if (x < 100) // Graven Image 3: Indulgent Will target + data.gravenImageTether = 'indulgent'; + else if (x < 108 && x > 106) // Graven Image 3: Idyllic Will target + data.gravenImageTether = 'idyllic'; + else + data.gravenImageTether = 'unknown'; + }, + }, + { + id: 'DMU P1 Pulse Wave Tethers', + type: 'Tether', + netRegex: { id: headMarkerData['imageTether'], capture: true }, + condition: (data, matches) => { + return data.me === matches.target && data.gravenImageCount === 1; + }, + delaySeconds: 0.1, // Actor position data can come after tether in log + durationSeconds: 7, + infoText: (data, matches, output) => { + const actor = data.actorPositions[matches.sourceId]; + if (actor === undefined) + return output.tetherOnYou!(); + + const x = actor.x; + // Graven Image 1: Pulse Wave target + if (x < 101 && x > 99) + return output.pulse!(); + return output.tetherOnYou!(); + }, + outputStrings: { + tetherOnYou: { + en: 'Tether on YOU', + de: 'Verbindung auf DIR', + fr: 'Lien sur VOUS', + ja: '線ついた', + cn: '连线点名', + ko: '선 대상자 지정됨', + tc: '連線點名', + }, + pulse: Outputs.knockback, // Cannot be immuned, happens within 6s of tether + }, + }, + { + id: 'DMU P1 Mystery Magic Collect', + type: 'HeadMarker', + netRegex: { + id: [ + headMarkerData['trueFire'], + headMarkerData['trueIce'], + headMarkerData['trueThunder'], + headMarkerData['fakeFire'], + headMarkerData['fakeIce'], + headMarkerData['fakeThunder'], + ], + capture: true, + }, + run: (data, matches) => { + switch (matches.id) { + case headMarkerData['trueFire']: + data.isFireTrue = true; + return; + case headMarkerData['fakeFire']: + data.isFireTrue = false; + return; + case headMarkerData['trueIce']: + data.isIceTrue = true; + return; + case headMarkerData['fakeIce']: + data.isIceTrue = false; + return; + case headMarkerData['trueThunder']: + data.isThunderTrue = true; + return; + case headMarkerData['fakeThunder']: + data.isThunderTrue = false; + return; + } + }, + }, + { + id: 'DMU P1 Fire Head Marker Collect', + type: 'HeadMarker', + netRegex: { id: [headMarkerData['dorito'], headMarkerData['stack']], capture: true }, + suppressSeconds: 2, + run: (data, matches) => data.fireMarker = matches.id, + }, + { + id: 'DMU P1 Mystery Magic Ice and Fire', + // Set 1: Only Ice and Fire should be set + type: 'StartsUsing', + netRegex: { id: 'BA94', source: 'Kefka', capture: false }, + condition: (data) => { + return data.isIceTrue !== undefined && data.isFireTrue !== undefined; + }, + infoText: (data, _matches, output) => { + const fireMarker = data.fireMarker; + if ( + (fireMarker === headMarkerData['dorito'] && data.isFireTrue) || + (fireMarker === headMarkerData['stack'] && !data.isFireTrue) + ) + return data.isIceTrue + ? output.spreadTrueIce!({ mech: output.spread!(), ice: output.trueIce!() }) + : output.spreadFakeIce!({ mech: output.spread!(), ice: output.fakeIce!() }); + + if ( + (fireMarker === headMarkerData['dorito'] && !data.isFireTrue) || + (fireMarker === headMarkerData['stack'] && data.isFireTrue) + ) { + return data.isIceTrue + ? output.stackTrueIce!({ mech: output.stack!(), ice: output.trueIce!() }) + : output.stackFakeIce!({ mech: output.stack!(), ice: output.fakeIce!() }); + } + }, + outputStrings: mysteryMagicOutputStrings, + }, + { + id: 'DMU P1 Graven Image Tether Cleanup', + // Clear on Ability: + // BAA9 Pulse Wave + // BAAC Gravitas + // BAB0 vitrophyre + // BAB5 Indulgent Will + // BAB6 Idyllic Will + type: 'Ability', + netRegex: { + id: ['BAA9', 'BAAC', 'BAB0', 'BAB5', 'BAB6'], + source: 'Graven Image', + capture: true, + }, + suppressSeconds: 1, + run: (data, matches) => { + // Player could die and this ability then not target them + // Need intelligent way to remove once related ability has executed + // Clear data if ability matches our tether + const abilityMap = { + 'pulse': 'BAAC', + 'gravitas': 'BAA9', + 'vitrophyre': 'BAB0', + 'indulgent': 'BAB5', + 'idyllic': 'BAB6', + 'unknown': 'unknown', + }; + const tether = data.gravenImageTether ?? 'unknown'; + const tetherAbilityId = abilityMap[tether]; + if (tetherAbilityId === matches.id || tether === 'unknown') + delete data.gravenImageTether; + }, + }, + { + id: 'DMU P1 Graven Image Collect', + // Tower entity actions + // The CombatantMemory Add lines are added prior to combat + // OverlayPlugin can retrieve the matching BNpcID + // However, these entities seem to always spawn in the same order and the + // first tower is the highest ID and the towers are in sequential order + // These are the BNpcID values: + // 1EBFBB (2015163) => Wave Cannon entity (blue) + // 1EBFBC (2015164) => Gravitational Wave entity (purple) + // 1EBFBD (2015165) => Intemperate Will entity (yellow) + // 1EBFBE (2015166) => Indolent Will entity (eye) + // 1EBFBF (2015167) => Ave Maria entity (fake eye) + // There are two of each, they are added at start of fight + type: 'ActorControlExtra', + netRegex: { category: '019D', param1: '40', param2: '80', capture: true }, + preRun: (data, matches) => { + const id = parseInt(matches.id, 16); + const blueTowers = [id, id - 1]; // First tower is blue and highest ID + const purpleTowers = [id - 2, id - 4]; // Next are in pair with yellow + const yellowTowers = [id - 3, id - 5]; + const eyeTowers = [id - 7, id - 9]; // Next are in paire with fake + const fakeEyeTowers = [id - 6, id - 8]; + + const toStringId = (id: number): string => { + return id.toString(16).toUpperCase(); + }; + data.blueTowerIds = blueTowers.map((id) => toStringId(id)); + data.purpleTowerIds = purpleTowers.map((id) => toStringId(id)); + data.yellowTowerIds = yellowTowers.map((id) => toStringId(id)); + data.eyeTowerIds = eyeTowers.map((id) => toStringId(id)); + data.fakeEyeTowerIds = fakeEyeTowers.map((id) => toStringId(id)); + }, + suppressSeconds: 99999, + }, + { + id: 'DMU P1 Wave Cannon', + // BAA8 Wave Cannon is an instant cast from Graven Image + // This gives a ~5 second warning to spread + type: 'ActorControlExtra', + netRegex: { category: '019D', param1: '40', param2: '80', capture: false }, + suppressSeconds: 99999, // First instance is a blue tower + alertText: (_data, _matches, output) => output.waveCannonLine!(), + outputStrings: { + waveCannonLine: { + en: 'E/W Spread', + }, + }, + }, + { + id: 'DMU P1 Wave Cannon Collect', + // Collect players hit by Wave Cannon to tell who soaks tower followup and who avoids tower + type: 'Ability', + netRegex: { id: 'BAA8', source: 'Graven Image', capture: true }, + run: (data, matches) => data.waveCannonTargets.push(matches.target), + }, + { + id: 'DMU P1 Double-trouble Trap Collect', + // Times are 5s, 68s, and 49s + type: 'GainsEffect', + netRegex: { effectId: '13D6', capture: true }, + run: (data, matches) => data.doubleTroubleTrapTargets.push(matches.target), + }, + { + id: 'DMU P1 Wave Cannon Explosion Towers', + // Wave Cannon gives a vulnerability which causes death to BAAA Explosion soaks + // Sacraficing a player who clipped to prevent party 90% damage down from + // BAAB Unmitigated Explosion seems ideal, although different clients may + // get different order + // Suprisingly the Unmitigated Explosion doesn't deal damage + // Players have ~4s to soak the tower + type: 'Ability', + netRegex: { id: 'BAA8', source: 'Graven Image', capture: false }, + delaySeconds: 0.1, + suppressSeconds: 1, + response: (data, _matches, output) => { + // cactbot-builtin-response + output.responseOutputStrings = { + getTowers: Outputs.getTowers, + avoid: { + en: 'Avoid towers', + de: 'Türme vermeiden', + fr: 'Évitez les tours', + ja: '塔回避', + cn: '远离塔', + ko: '기둥 피하기', + tc: '遠離塔', + }, + extra: { + en: 'Extra Tower', + }, + }; + const avoidedCannon = data.waveCannonTargets.indexOf(data.me) !== -1; + + // Option for player to soak the tower for p1 prog? + if (avoidedCannon && data.waveCannonTargets.length > 4) + return { infoText: output.extra!() }; + + // Avoid the tower + if (avoidedCannon) + return { alertText: output.avoid!() }; + + // Player didn't get hit, they will need to soak a tower + return { alertText: output.getTowers!() }; + }, + }, + { + id: 'DMU P1 Double-trouble Trap Knockback', + type: 'GainsEffect', + netRegex: { effectId: '13D6', capture: true }, + delaySeconds: (_data, matches) => parseFloat(matches.duration) - 3.9, // First one needs 0.1 delay for collect + durationSeconds: 3.9, + suppressSeconds: 1, + response: (data, matches, output) => { + // cactbot-builtin-response + output.responseOutputStrings = trapOutputStrings; + + // If players died before the duration ended + if (data.doubleTroubleTrapTargets.length === 0) + return; + + const severity = data.doubleTroubleTrapTargets.includes(data.me) ? 'alertText' : 'infoText'; + const players = data.doubleTroubleTrapTargets.map( + (player) => { + if (player === data.me) + return 'YOU'; + return data.party.member(player); + }, + ); + const msg = players?.join(', '); + + const duration = parseFloat(matches.duration); + if (duration < 6) + return { [severity]: output.knockbackFrom1!({ players: msg }) }; + if (duration > 67) + return { [severity]: output.knockbackFrom2!({ players: msg }) }; + + if (data.gravenImageTether === 'idyllic') + return { [severity]: output.knockbackFrom3Sleep!({ players: msg }) }; + if (data.gravenImageTether === 'indulgent') + return { [severity]: output.knockbackFrom3Confuse!({ players: msg }) }; + return { [severity]: output.knockbackFrom3!({ players: msg }) }; + }, + }, + { + id: 'DMU P1 Double-trouble Trap Cleanup', + // Players dying will also trigger this + type: 'LosesEffect', + netRegex: { effectId: '13D6', capture: true }, + run: (data, matches) => { + data.doubleTroubleTrapTargets = data.doubleTroubleTrapTargets.filter( + (target) => target !== matches.target, + ); + }, + }, + { + id: 'DMU P1 Double-trouble Trap 2 Early', + type: 'GainsEffect', + netRegex: { effectId: '13D6', capture: true }, + delaySeconds: 0.3, // Time between debuff and dying from the application + suppressSeconds: 1, + infoText: (data, matches, output) => { + // Ignore first set and third set + if (parseFloat(matches.duration) < 67) + return; + + // Check if players died + if (data.doubleTroubleTrapTargets.length === 0) + return; + + const players = data.doubleTroubleTrapTargets.map( + (player) => { + if (player === data.me) + return 'YOU'; + return data.party.member(player); + }, + ); + const msg = players?.join(', '); + return output.knockbackFromLater!({ players: msg }); + }, + outputStrings: trapOutputStrings, + }, + { + id: 'DMU P1 Mystery Magic Ice and Thunder', + // Set 2: Only Ice and Thunder should be set + type: 'StartsUsing', + netRegex: { id: 'BA94', source: 'Kefka', capture: false }, + condition: (data) => { + return data.isIceTrue !== undefined && data.isThunderTrue !== undefined; + }, + infoText: (data, _matches, output) => { + if (data.isThunderTrue) { + return data.isIceTrue + ? output.trueIceTrueThunder!() + : output.fakeIceTrueThunder!(); + } + return data.isIceTrue + ? output.trueIceFakeThunder!() + : output.fakeIceFakeThunder!(); + }, + outputStrings: mysteryMagicOutputStrings, + }, + { + id: 'DMU P1 Light of Judgment', + type: 'StartsUsing', + netRegex: { id: 'C622', source: 'Kefka', capture: false }, + response: Responses.bigAoe(), + }, + { + id: 'DMU P1 Hyperdrive', + // This hits three times + // Occurs 3.1s after C622 Light of Judgment, which is a 5s cast + type: 'StartsUsing', + netRegex: { id: 'C622', source: 'Kefka', capture: true }, + delaySeconds: (_data, matches) => parseFloat(matches.castTime) - 2, // Result in ~5.1s warning + response: Responses.tankBuster(), + }, + { + id: 'DMU P1 Mystery Magic Ice, and Gravitas and Vitrophyre Tethers 1', + // Occurs between Set 2 and Set 3 + // BA95 Blizzard Blowout III cast + type: 'StartsUsing', + netRegex: { id: 'BA95', source: 'Kefka', capture: false }, + condition: (data) => { + if ( + data.isIceTrue !== undefined && + data.isThunderTrue === undefined && + data.isFireTrue === undefined + ) + return true; + return false; + }, + infoText: (data, _matches, output) => { + const hasVitrophyre = data.gravenImageTether === 'vitrophyre'; + return data.isIceTrue + ? output.trueIcePuddle!({ + mech1: output.trueIce!(), + mech2: output.puddle!(), + mech3: hasVitrophyre ? output.spread!() : output.middle!(), + }) + : output.fakeIcePuddle!({ + mech1: output.fakeIce!(), + mech2: output.puddle!(), + mech3: hasVitrophyre ? output.spread!() : output.middle!(), + }); + }, + outputStrings: mysteryMagicOutputStrings, + }, + { + id: 'DMU P1 Vitrophyre', + // Trigger on BAAC Gravitas, ~4s to get away + type: 'Ability', + netRegex: { id: 'BAAC', source: 'Graven Image', capture: false }, + suppressSeconds: 1, + alertText: (data, _matches, output) => { + if (data.gravenImageTether === 'vitrophyre') + return output.spread!(); + return output.avoidTethers!(); + }, + outputStrings: { + avoidTethers: { + en: 'Avoid Tethered Players', + }, + spread: { + en: 'Spread (avoid puddles)', + }, + }, + }, + { + id: 'DMU P1 Double-trouble Trap 3 Early', + type: 'GainsEffect', + netRegex: { effectId: '13D6', capture: true }, + delaySeconds: 0.3, // Time between debuff and dying from the application + suppressSeconds: 1, + infoText: (data, matches, output) => { + const duration = parseFloat(matches.duration); + // Only capture 3rd set + if (duration < 48 || duration > 50) + return; + + // Check if players died + if (data.doubleTroubleTrapTargets.length === 0) + return; + + const players = data.doubleTroubleTrapTargets.map( + (player) => { + if (player === data.me) + return 'YOU'; + return data.party.member(player); + }, + ); + const msg = players?.join(', '); + return output.knockbackFromLater!({ players: msg }); + }, + outputStrings: trapOutputStrings, + }, + { + id: 'DMU P1 Impertinent Will', + type: 'ActorControlExtra', + netRegex: { category: '019D', param1: '40', param2: '80', capture: true }, + condition: (data, matches) => data.yellowTowerIds.includes(matches.id), + alertText: (_data, _matches, output) => output.goWest!(), + outputStrings: { + goWest: Outputs.getLeftAndWest, + }, + }, + { + id: 'DMU P1 Gravitational Wave', + type: 'ActorControlExtra', + netRegex: { category: '019D', param1: '40', param2: '80', capture: true }, + condition: (data, matches) => data.purpleTowerIds.includes(matches.id), + alertText: (_data, _matches, output) => output.goEast!(), + outputStrings: { + goEast: Outputs.getRightAndEast, + }, + }, + { + id: 'DMU P1 Gravitas and Vitrophyre Tethers 2', + type: 'Tether', + netRegex: { id: headMarkerData['imageTether'], capture: true }, + condition: (data, matches) => { + return data.me === matches.target && + data.isIceTrue !== undefined && + data.isThunderTrue === undefined && + data.isFireTrue === undefined; + }, + delaySeconds: 2, + durationSeconds: 6, + infoText: (data, matches, output) => { + const actor = data.actorPositions[matches.sourceId]; + if (actor === undefined) + return output.tetherOnYou!(); + + const x = actor.x; + if (x < 103 && x > 101) // Graven Image 2: Gravitas target + return output.gravitas!({ + mech1: output.puddle!(), + mech2: output.middle!(), + }); + if (x > 125) // Graven Image 2: Vitrophyre target + return output.vitrophyre!({ + mech1: output.puddle!(), + mech2: output.spread!(), + }); + return output.tetherOnYou!(); + }, + outputStrings: { + puddle: { + en: 'Bait Puddle', + de: 'Fläche ködern', + fr: 'Déposez', + ja: 'AOE誘導', + cn: '诱导AOE', + ko: '장판 유도', + tc: '誘導AOE', + }, + middle: Outputs.goIntoMiddle, + spread: Outputs.spread, + tetherOnYou: { + en: 'Tether on YOU', + de: 'Verbindung auf DIR', + fr: 'Lien sur VOUS', + ja: '線ついた', + cn: '连线点名', + ko: '선 대상자 지정됨', + tc: '連線點名', + }, + gravitas: { + en: '${mech1} => ${mech2}', + }, + vitrophyre: { + en: '${mech1} => ${mech2}', + }, + indulgent: { + en: 'Confuse Tether on YOU', + }, + idyllic: { + en: 'Sleep Tether on YOU', + }, + }, + }, + { + id: 'DMU P1 Tele-Portent Collect', + // Debuffs distributed to 8 players: + // Players with 2 of the same are always: + // 130F Left (7s) + 130F Left (10s) + // 130E Right (7s) + 130E Right (10s) + // 130D Down (7s) + 130D Down (10s) + // 130C Up (7s) + 130C Up (10s) + // + // The remaining players may have differing patterns: + // Pattern 1: + // 130D Down (7s) + 13DA Left (10s) + // 13D9 Right (7s) + 130C Up (10s) + // 13D8 Down (7s) + 130E Right (10s) + // 130F Left (7s) + 13D7 Up (10s) + // + // Pattern 2: + // 130D Down (7s) + 13DA Left (10s) + // 13D9 Right (7s) + 130C Up (10s) + // 130E Right (7s) + 13D8 Down (10s) + // 13D7 Up (7s) + 130F Left (10s) + // + // Pattern 3: + // 130D Down (7s) + 13DA Left (10s) + // 13D9 Right (7s) + 130C Up (10s) + // 130E Right (7s) + 13D8 Down (10s) + // 130F Left (7s) + 13D7 Up (10s) + // + // Pattern 4: + // 13DA Left (7s) + 130D Down (10s) + // 130C Up (7s) + 13D9 Right (10s) + // 130E Right (7s) + 13D8 Down (10s) + // 130F Left (7s) + 13D7 Up (10s) + // + // Possibly More? + // Varying strategies to resolve + // Players with the same arrows will get a 6s 503 Confused which causes them to target nearest players + // Players with different arrows will cause a 6s 131E Sleep aoe + type: 'GainsEffect', + netRegex: { + effectId: [ + '130C', // Up + '130D', // Down + '130E', // Right + '130F', // Left + '13D7', // Up + '13D8', // Down + '13D9', // Right + '13DA', // Left + ], + capture: true, + }, + condition: Conditions.targetIsYou(), + run: (data, matches) => { + const effectMap: { [effectId: string]: typeof data.myTelePortent1 } = { + '130C': 'up', + '130D': 'down', + '130E': 'right', + '130F': 'left', + '13D7': 'up', + '13D8': 'down', + '13D9': 'right', + '13DA': 'left', + }; + const duration = parseFloat(matches.duration); + if (duration < 8) { + data.myTelePortent1 = effectMap[matches.effectId]; + return; + } + data.myTelePortent2 = effectMap[matches.effectId]; + }, + }, + { + id: 'DMU P1 Tele-Portents', + type: 'GainsEffect', + netRegex: { + effectId: [ + '130C', // Up + '130D', // Down + '130E', // Right + '130F', // Left + '13D7', // Up + '13D8', // Down + '13D9', // Right + '13DA', // Left + ], + capture: true, + }, + condition: Conditions.targetIsYou(), + durationSeconds: 7, + infoText: (data, _matches, output) => { + if (data.myTelePortent1 === undefined || data.myTelePortent2 === undefined) + return; + const portents = data.myTelePortent1 + data.myTelePortent2; + return output[portents]!(); + }, + outputStrings: { + upup: { + en: 'Up Portents', + }, + downdown: { + en: 'Down Portents', + }, + rightright: { + en: 'Right Portents', + }, + leftleft: { + en: 'Left Portents', + }, + downleft: { + en: 'Down => Left Portent', + }, + downright: { + en: 'Down => Right Portent', + }, + rightup: { + en: 'Right => Up Portent', + }, + rightdown: { + en: 'Right => Down Portent', + }, + leftup: { + en: 'Left => Up Portent', + }, + leftdown: { + en: 'Left => Down Portent', + }, + upright: { + en: 'Up => Right Portent', + }, + upleft: { + en: 'Up => Left Portent', + }, + }, + }, + { + id: 'DMU P1 Tele-Portent 2', + // Not enough time to have lengthy TTS, but could configure this to give direction instead of move + type: 'LosesEffect', + netRegex: { + effectId: [ + '130C', // Up + '130D', // Down + '130E', // Right + '130F', // Left + '13D7', // Up + '13D8', // Down + '13D9', // Right + '13DA', // Left + ], + capture: true, + }, + condition: (data, matches) => { + if (data.me === matches.target) + if (data.myTelePortent1 !== undefined) + return true; + return false; + }, + durationSeconds: 3, + response: Responses.moveAway('alert'), + }, + { + id: 'DMU P1 Tele-Portent Cleanup', + type: 'LosesEffect', + netRegex: { + effectId: [ + '130C', // Up + '130D', // Down + '130E', // Right + '130F', // Left + '13D7', // Up + '13D8', // Down + '13D9', // Right + '13DA', // Left + ], + capture: true, + }, + condition: Conditions.targetIsYou(), + suppressSeconds: 1, + run: (data) => { + delete data.myTelePortent1; + delete data.myTelePortent2; + }, + }, + { + id: 'DMU P1 Indulgent Will and Idyllic Will Tethers', + type: 'Tether', + netRegex: { id: headMarkerData['imageTether'], capture: true }, + condition: (data, matches) => { + return data.me === matches.target && data.gravenImageCount === 3; + }, + delaySeconds: 0.1, // Delay for collect of tower type + infoText: (data, matches, output) => { + const actor = data.actorPositions[matches.sourceId]; + if (actor === undefined) + return output.tetherOnYou!(); + + const x = actor.x; + if (x < 100) // Graven Image 3: Indulgent Will target + return output.indulgent!(); + if (x < 108 && x > 106) // Graven Image 3: Idyllic Will target + return output.idyllic!(); + return output.tetherOnYou!(); + }, + outputStrings: { + tetherOnYou: { + en: 'Tether on YOU', + de: 'Verbindung auf DIR', + fr: 'Lien sur VOUS', + ja: '線ついた', + cn: '连线点名', + ko: '선 대상자 지정됨', + tc: '連線點名', + }, + indulgent: { + en: 'Confuse Tether on YOU', + }, + idyllic: { + en: 'Sleep Tether on YOU', + }, + }, + }, + { + id: 'DMU P1 Ave Maria', + // BAB3 Ave Maria + // The animation is visible ~9.89s before cast goes off, however + // When animation becomes visible, the players will be asleep or + // confused for another ~3.4s. Once the debuff ends the players have + // ~6.4s to turn character + type: 'ActorControlExtra', + netRegex: { category: '019D', param1: '40', param2: '80', capture: true }, + condition: (data, matches) => data.fakeEyeTowerIds.includes(matches.id), + durationSeconds: 9.5, + countdownSeconds: 3.4, // Estimated time debuff would expire + infoText: (_data, _matches, output) => output.lookAt!(), + outputStrings: { + lookAt: { + en: 'Look At Statue', + de: 'Statue anschauen', + fr: 'Regardez la statue', + ja: '像を見る!', + cn: '面对神像', + ko: '시선 바라보기', + tc: '面對神像', + }, + }, + }, + { + id: 'DMU P1 Indolent Will', + // BAB4 Indolent Will + type: 'ActorControlExtra', + netRegex: { category: '019D', param1: '40', param2: '80', capture: true }, + condition: (data, matches) => data.eyeTowerIds.includes(matches.id), + durationSeconds: 9.5, + countdownSeconds: 3.4, // Estimated time debuff would expire + infoText: (_data, _matches, output) => output.lookAway!(), + outputStrings: { + lookAway: { + en: 'Look Away From Statue', + de: 'Von Statue wegschauen', + fr: 'Ne regardez pas la statue', + ja: '塔を見ない!', + cn: '背对神像', + ko: '시선 피하기', + tc: '背對神像', + }, + }, + }, + { + id: 'DMU P1 Mystery Magic Fire and Thunder', + // Set 3: Only Fire and Thunder should be set + type: 'StartsUsing', + netRegex: { id: 'BA94', source: 'Kefka', capture: false }, + condition: (data) => { + return data.isFireTrue !== undefined && data.isThunderTrue !== undefined; + }, + infoText: (data, _matches, output) => { + const fireMarker = data.fireMarker; + if ( + (fireMarker === headMarkerData['dorito'] && data.isFireTrue) || + (fireMarker === headMarkerData['stack'] && !data.isFireTrue) + ) + return data.isThunderTrue + ? output.spreadTrueThunder!({ + mech: output.spread!(), + thunder: output.trueThunder!(), + }) + : output.spreadFakeThunder!({ + mech: output.spread!(), + thunder: output.fakeThunder!(), + }); + + if ( + (fireMarker === headMarkerData['dorito'] && !data.isFireTrue) || + (fireMarker === headMarkerData['stack'] && data.isFireTrue) + ) { + return data.isThunderTrue + ? output.stackTrueThunder!({ + mech: output.stack!(), + thunder: output.trueThunder!(), + }) + : output.stackFakeThunder!({ + mech: output.stack!(), + thunder: output.fakeThunder!(), + }); + } + }, + outputStrings: mysteryMagicOutputStrings, + }, + { + id: 'DMU P1 Mystery Magic Cleanup', + // C622 Light of Judgment to reset for the Graven Image 2 + type: 'StartsUsing', + netRegex: { id: ['BA94', 'C622'], source: 'Kefka', capture: false }, + run: (data) => { + delete data.isFireTrue; + delete data.isIceTrue; + delete data.isThunderTrue; + delete data.fireMarker; + }, + }, + { + id: 'DMU P2 Ultimate Embrace', + type: 'StartsUsing', + netRegex: { id: 'C24C', source: 'Kefka', capture: true }, + response: Responses.sharedTankBuster(), + }, + { + id: 'DMU P2 Forsaken', + // 7s cast + type: 'StartsUsing', + netRegex: { id: 'BABC', source: 'Kefka', capture: false }, + durationSeconds: 6.7, + response: Responses.bigAoe('alert'), + }, + { + id: 'DMU P2 Path of Light Headmarker', + type: 'HeadMarker', + netRegex: { + id: [ + headMarkerData['stackPath'], + headMarkerData['conePath'], + headMarkerData['spreadPath'], + ], + capture: true, + }, + condition: Conditions.targetIsYou(), + infoText: (_data, matches, output) => { + const id = matches.id; + type markerMap = { + [key: string]: 'stack' | 'cone' | 'spread'; + }; + const markers: markerMap = { + '02CB': 'stack', + '02CD': 'cone', + '02CC': 'spread', + }; + const marker = markers[id]; + if (marker === undefined) + return; + return output[marker]!(); + }, + outputStrings: { + stack: { + en: 'Stack Path on YOU', + }, + cone: { + en: 'Cone Path on YOU', + }, + spread: { + en: 'Spread Path on YOU', + }, + }, + }, + { + id: 'DMU P2 Future\'s End/Past\'s End', + // There are four end casts + type: 'StartsUsing', + netRegex: { id: ['BAD2', 'BAD3'], source: 'Kefka', capture: true }, + infoText: (_data, matches, output) => { + return matches.id === 'BAD2' ? output.future!() : output.past!(); + }, + outputStrings: { + future: { + en: 'Future', + }, + past: { + en: 'Past', + }, + }, + }, + { + id: 'DMU P2 Light of Judgment', + type: 'StartsUsing', + netRegex: { id: 'BABD', source: 'Kefka', capture: false }, + response: Responses.bigAoe('alert'), + }, + { + id: 'DMU Single Wing of Destruction', + // BACD Wings of Destruction, Left wing highlight + // BACE Wingso of Desctruction, Right wing highlight + // Halfroom cleaves + type: 'StartsUsing', + netRegex: { id: ['BACD', 'BACE'], source: 'Kefka', capture: true }, + infoText: (_data, matches, output) => { + if (matches.id === 'BACD') + return output.right!(); + return output.left!(); + }, + outputStrings: { + right: Outputs.right, + left: Outputs.left, + }, + }, + { + id: 'DMU Wings of Destruction', + type: 'StartsUsing', + netRegex: { id: 'C487', source: 'Kefka', capture: false }, + response: (data, _matches, output) => { + // cactbot-builtin-response + output.responseOutputStrings = { + maxMeleeAvoidTanks: { + en: 'Max Melee: Avoid Tanks', + de: 'Max Nahkampf: Weg von den Tanks', + fr: 'Max mêlée : éloignez-vous des tanks', + ja: '近接最大レンジ タンクから離れる', + cn: '最大近战距离,避开坦克', + ko: '칼끝딜: 탱커 피하기', + tc: '最大近戰距離,避開坦克', + }, + wingsBeNearFar: { + en: 'Wings: Be Near/Far', + de: 'Schwingen: Nah/Fern', + fr: 'Ailes : Placez-vous près/loin', + ja: '翼: めり込む/離れる', + cn: '双翅膀:近或远', + ko: '양날개: 가까이/멀리', + tc: '雙翅膀:近或遠', + }, + }; + if (data.role === 'tank') + return { alertText: output.wingsBeNearFar!() }; + return { infoText: output.maxMeleeAvoidTanks!() }; + }, + }, + { + id: 'DMU P2 Aero III Assault', + // Knockback from boss that can't be resisted + // Applies 306 Down for the Count + type: 'StartsUsing', + netRegex: { id: 'C3F7', source: 'Kefka', capture: false }, + response: Responses.getUnder('alert'), + }, + { + id: 'DMU P3 Epic Hero/Fated Hero Debuffs', + // Applied to 4 nearest players when Chaos and Exdeath finish casting + // C2E2/C2E3 The Decisive Battle + // 1060 Epic Hero: Can only damage Chaos, preferred by Melee DPS + // 1062 Fated Hero: Can only damage Exdeath, preferred by Ranged DPS + // These fall off once Exdeath casts BB12 Thunder III + type: 'GainsEffect', + netRegex: { effectId: ['1060', '1062'], capture: true }, + condition: Conditions.targetIsYou(), + infoText: (_data, matches, output) => { + return matches.effectId === '1060' ? output.epic!() : output.fated!(); + }, + outputStrings: { + epic: { + en: 'Attack Chaos', + }, + fated: { + en: 'Attack Exdeath', + }, + }, + }, + { + id: 'DMU P3 Headwind/Tailwind Debuffs', + // Applied at BAF2 Bowels of Agony + // Debuffs trigger if hit by certain sources, causing a knockback + // 642 Headwind: Face away from damage source + // 643 Tailwind: Face towards damage source + type: 'GainsEffect', + netRegex: { effectId: ['642', '643'], capture: true }, + condition: Conditions.targetIsYou(), + infoText: (_data, matches, output) => { + return matches.effectId === '642' ? output.headwind!() : output.tailwind!(); + }, + outputStrings: { + headwind: { + en: 'Headwind on YOU', + }, + tailwind: { + en: 'Tailwind on You', + }, + }, + }, + { + id: 'DMU P3 Longitudinal Implosion', + type: 'StartsUsing', + netRegex: { id: 'BAFD', source: 'Chaos', capture: false }, + infoText: (_data, _matches, output) => output.sides!(), + outputStrings: { + sides: Outputs.sidesThenFrontBack, + }, + }, + { + id: 'DMU P3 Latitudinal Implosion', + type: 'StartsUsing', + netRegex: { id: 'BAFE', source: 'Chaos', capture: false }, + infoText: (_data, _matches, output) => output.frontBack!(), + outputStrings: { + frontBack: Outputs.frontBackThenSides, + }, + }, + { + id: 'DMU P3 Vaccuum Wave', + type: 'StartsUsing', + netRegex: { id: 'BB13', source: 'Chaos', capture: true }, + infoText: (_data, matches, output) => { + return output.knockbackFromBoss!({ chaos: matches.source }); + }, + outputStrings: { + knockbackFromBoss: { + en: 'Knockback from ${chaos}', + }, + }, + }, + { + id: 'DMU P3 Damning Edict', + type: 'StartsUsing', + netRegex: { id: 'BB01', source: 'Chaos', capture: false }, + response: Responses.getBehind(), + }, ], timelineReplace: [ { 'locale': 'en', 'replaceText': { 'Future\'s End/Past\'s End': 'Future/Past\'s End', + 'Spelldriver/Spellscatter/Spellwave': 'Spelldriver/scatter/wave', + 'Longitudinal Implosion/Latitudinal Implosion': 'Long/Lat Implosion', }, }, ], diff --git a/ui/raidboss/data/07-dt/ultimate/dancing_mad.txt b/ui/raidboss/data/07-dt/ultimate/dancing_mad.txt index 97fe98c9a0..840f236f6c 100644 --- a/ui/raidboss/data/07-dt/ultimate/dancing_mad.txt +++ b/ui/raidboss/data/07-dt/ultimate/dancing_mad.txt @@ -1,8 +1,8 @@ ### DANCING MAD (ULTIMATE) # ZoneId: 1363 -# -ii C250 C252 BA9E BAA0 BAAB BA95 BAAF BAAD BAD6 BAD8 BAD7 BAD9 -# -p C403:15.6 C24C:216.5 C3F7:500.0 +# -ii C250 C252 BA9E BAA0 BAAB BA95 BAAF BAAD BAD6 BAD8 BAD7 BAD9 BACF BAF9 BAF1 +# -p C403:15.6 C24C:216.5 C3F7:500.0 C2DC:1000.0 BB40:1300.0 # -it Kefka Chaos Exdeath hideall "--Reset--" @@ -26,9 +26,10 @@ hideall "--sync--" 37.4 "Blizzard III Blowout" #Ability { id: ["BA9B", "BA98"], source: "Kefka" } 38.3 "Flagrant Fire III" Ability { id: ["BAA2", "BAA3"], source: "Kefka" } 42.5 "Wave Cannon" Ability { id: "BAA8", source: "Graven Image" } -44.6 "Double-trouble Trap" Ability { id: "BAA6", source: "Kefka" } +44.6 "Double-trouble Trap 1" Ability { id: "BAA6", source: "Kefka" } 46.0 "Explosion" Ability { id: "BAAA", source: "Kefka" } -49.7 "Double-trouble Trap" Ability { id: "BAA7", source: "Kefka" } +49.6 "--knockback--" # From Double-trouble Trap 1 +49.7 "Double-trouble Trap 2" Ability { id: "BAA7", source: "Kefka" } 53.7 "Mystery Magic" Ability { id: "BA94", source: "Kefka" } 53.7 "Thrumming Thunder III" #Ability { id: ["BAA1", "BA9F"], source: "Kefka" } 53.7 "Blizzard III Blowout" #Ability { id: ["BA9B", "BA98"], source: "Kefka" } @@ -48,8 +49,9 @@ hideall "--sync--" 105.8 "Gravitas" Ability { id: "BAAC", source: "Graven Image" } 109.8 "Vitrophyre" Ability { id: "BAB0", source: "Graven Image" } 114.4 "Intemperate Will/Gravitational Wave" Ability { id: ["BAB2", "BAB1"], source: "Graven Image" } -118.9 "Double-Trouble Trap" Ability { id: "BAA7", source: "Kefka" } # NOTE: If it was passed after first set. -121.3 "Gravity III" #Ability { id: "BAAF", source: "Kefka" } # TODO: Adjust timing/wording to puddles safe to pop, make it a duration? +117.0 "Gravity III (Pop Window)" #Ability { id: "BAAF", source: "Kefka" } duration 6 # ~1s remaining on debuff and until 45s on next +118.0 "--knockback--" # From Double-trouble Trap 2 +118.1 "Double-Trouble Trap 3" Ability { id: "BAA7", source: "Kefka" } # NOTE: If it was passed after first set. 132.4 "Light of Judgment" Ability { id: "C622", source: "Kefka" } 135.6 "Hyperdrive 1" #Ability { id: "C24B", source: "Kefka" } 137.7 "Hyperdrive 2" #Ability { id: "C24B", source: "Kefka" } @@ -60,123 +62,382 @@ hideall "--sync--" 163.6 "Graven Image 3" Ability { id: "BCF2", source: "Kefka" } 168.7 "--sync--" Ability { id: "C554", source: "Kefka" } +170.6 "--knockback--" # From Double-trouble Trap 3 173.4 "Indulgent Will" Ability { id: "BAB5", source: "Graven Image" } 173.4 "Idyllic Will" #Ability { id: "BAB6", source: "Graven Image" } 177.7 "--sync--" Ability { id: "C555", source: "Kefka" } 179.7 "--middle--" Ability { id: "C3FD", source: "Kefka" } 186.3 "Mystery Magic" Ability { id: "BA94", source: "Kefka" } 186.3 "Thrumming Thunder III" #Ability { id: ["BAA1", "BA9F"], source: "Kefka" } -186.3 "Indolent Will/Ave Maria" #Ability { id: ["BAB4", "BAB3"], source: "Graven Image" } +186.3 "Ave Maria/Indolent Will" #Ability { id: ["BAB3", "BAB4"], source: "Graven Image" } 187.1 "Flagrant Fire III" Ability { id: ["BAA2", "BAA3"], source: "Kefka" } 202.5 "Light of Judgment (Enrage)?" Ability { id: "BABB", source: "Kefka" } # Kefka >15% HP ### Phase 2 - God Kefka # TODO: Update with network log, this uses FFLOGS -# TODO: Get enrage # TODO: Get fake ending route? -# TODO: Add voiceline sync? +# TODO: Add voiceline sync / branch to complete? +# Fake Duty Complete Path: # en: 'Yes... I am filled with glorious purpose!' +# Duty Complete Path: +# en: 'How boring. Guess I'll have to spice things up!' 216.5 "Ultimate Embrace" Ability { id: "C24C", source: "Kefka" } window 220,5 231.7 "Forsaken" Ability { id: "BABC", source: "Kefka" } -244.9 "The Path of Light 1" Ability { id: "BABE", source: "Kefka" } -245.6 "Spelldriver" #Ability { id: "BAC0", source: "Kefka" } -245.6 "Spellwave" #Ability { id: "BAC2", source: "Kefka" } -245.6 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } -245.6 "Spelldriver" #Ability { id: "BAC0", source: "Kefka" } -254.3 "Future's End/Past's End" Ability { id: ["BAD2", "BAD3"], source: "Kefka" } +# Set 1 +# NOTE: The BAC0 Spelldriver, BAC2 Spellwave, BAC0 Spellscatter can be resolved in different orders +244.9 "The Path of Light 1" Ability { id: "BABE", source: "Kefka" } +245.6 "Spelldriver/Spellscatter/Spellwave" Ability { id: ["BAC0", "BAC1", "BAC2"], source: "Kefka" } +254.3 "Future's End/Past's End 1" Ability { id: ["BAD2", "BAD3"], source: "Kefka" } 255.0 "The Path of Light 2" Ability { id: "BABE", source: "Kefka" } -255.7 "Spellwave" #Ability { id: "BAC2", source: "Kefka" } -255.7 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } -265.7 "All Things Ending" #Ability { id: ["BACD", "BADD"], source: "Kefka" } +255.7 "Spelldriver/Spellscatter/Spellwave" Ability { id: ["BAC0", "BAC1", "BAC2"], source: "Kefka" } +265.7 "All Things Ending" #Ability { id: ["BADC", "BADD"], source: "Kefka" } +# Set 2 265.9 "The Path of Light 3" Ability { id: "BABE", source: "Kefka" } -266.4 "Spelldriver" #Ability { id: "BAC0", source: "Kefka" } -266.4 "Spellwave" #Ability { id: "BAC2", source: "Kefka" } -266.4 "Spelldriver" #Ability { id: "BAC0", source: "Kefka" } -266.4 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } -275.4 "Future's End/Past's End" Ability { id: ["BAD2", "BAD3"], source: "Kefka" } - +266.4 "Spelldriver/Spellscatter/Spellwave" Ability { id: ["BAC0", "BAC1", "BAC2"], source: "Kefka" } +275.4 "Future's End/Past's End 2" Ability { id: ["BAD2", "BAD3"], source: "Kefka" } 275.8 "The Path of Light 4" Ability { id: "BABE", source: "Kefka" } -276.5 "Spellwave" #Ability { id: "BAC2", source: "Kefka" } -276.5 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } -276.5 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } -286.7 "All Things Ending" #Ability { id: ["BACD", "BADD"], source: "Kefka" } +276.5 "Spelldriver/Spellscatter/Spellwave" Ability { id: ["BAC0", "BAC1", "BAC2"], source: "Kefka" } +286.7 "All Things Ending" #Ability { id: ["BADC", "BADD"], source: "Kefka" } +# Set 3 286.7 "The Path of Light 5" Ability { id: "BABE", source: "Kefka" } -287.1 "Spelldriver" #Ability { id: "BAC0", source: "Kefka" } -287.1 "Spellwave" #Ability { id: "BAC2", source: "Kefka" } -287.1 "Spelldriver" #Ability { id: "BAC0", source: "Kefka" } -287.1 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } -296.1 "Future's End/Past's End" Ability { id: ["BAD2", "BAD3"], source: "Kefka" } - +287.1 "Spelldriver/Spellscatter/Spellwave" Ability { id: ["BAC0", "BAC1", "BAC2"], source: "Kefka" } +296.1 "Future's End/Past's End 3" Ability { id: ["BAD2", "BAD3"], source: "Kefka" } 296.4 "The Path of Light 6" Ability { id: "BABE", source: "Kefka" } -297.1 "Spellwave" #Ability { id: "BAC2", source: "Kefka" } -297.1 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } +297.1 "Spelldriver/Spellscatter/Spellwave" Ability { id: ["BAC0", "BAC1", "BAC2"], source: "Kefka" } +307.5 "All Things Ending" #Ability { id: ["BADC", "BADD"], source: "Kefka" } +# Set 4 307.5 "The Path of Light 7" Ability { id: "BABE", source: "Kefka" } -307.5 "All Things Ending" #Ability { id: ["BACD", "BADD"], source: "Kefka" } -308.0 "Spelldriver" #Ability { id: "BAC0", source: "Kefka" } -308.0 "Spellwave" #Ability { id: "BAC2", source: "Kefka" } -308.0 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } -308.0 "Spelldriver" #Ability { id: "BAC0", source: "Kefka" } -317.0 "Future's End/Past's End" Ability { id: ["BAD2", "BAD3"], source: "Kefka" } - +308.0 "Spelldriver/Spellscatter/Spellwave" Ability { id: ["BAC0", "BAC1", "BAC2"], source: "Kefka" } +317.0 "Future's End/Past's End 4" Ability { id: ["BAD2", "BAD3"], source: "Kefka" } 317.4 "The Path of Light 8" Ability { id: "BABE", source: "Kefka" } -318.1 "Spellwave" #Ability { id: "BAC2", source: "Kefka" } -318.1 "Spellscatter" #Ability { id: "BAC1", source: "Kefka" } -328.3 "All Things Ending" #Ability { id: ["BACD", "BADD"], source: "Kefka" } +318.1 "Spelldriver/Spellscatter/Spellwave" Ability { id: ["BAC0", "BAC1", "BAC2"], source: "Kefka" } +328.3 "All Things Ending" Ability { id: ["BADC", "BADD"], source: "Kefka" } +# Trines 337.4 "Light of Judgment" Ability { id: "BABD", source: "Kefka" } 348.6 "Trine" Ability { id: "BADF", source: "Kefka" } -355.7 "Wings of Destruction" Ability { id: "BACD", source: "Kefka" } +355.7 "Wings of Destruction" Ability { id: ["BACD", "BACE"], source: "Kefka" } 361.5 "Trine 1" #Ability { id: "BAE0", source: "Kefka" } 363.5 "Trine 2" #Ability { id: "BAE0", source: "Kefka" } 365.5 "Trine 3" #Ability { id: "BAE0", source: "Kefka" } 365.9 "Wings of Destruction" Ability { id: "C487", source: "Kefka" } -365.9 "Wings of Destruction" #Ability { id: "BACF", source: "Kefka" } 372.9 "Ultimate Embrace" Ability { id: "C24C", source: "Kefka" } 376.2 "--sync--" StartsUsing { id: "BAE1", source: "Kefka" } jump "p2-enrage" -379.3 "--sync--" StartsUsing { id: "C3F7", source: "Kefka" } jump "p2-success" +379.3 "--sync--" StartsUsing { id: "C3F7", source: "Kefka" } window 220,5 jump "p2-success" # Kefka will skip mechanics at 0% HP 381.2 "Light of Judgment (Enrage)?" #Ability { id: "BAE1", source: "Kefka" } # Kefka > 0% HP 382.3 "Aero III Assault?" Ability { id: "C3F7", source: "Kefka" } forcejump "p2-success" +# TODO: Earlier sync on jump middle 497.0 label "p2-success" 500.0 "Aero III Assault" Ability { id: "C3F7", source: "Kefka" } window 500,20 +500.8 "Down for the Count" GainsEffect { effectId: '306' } duration 32.5 ### Phase 3 - Chaos and Exdeath +# TODO: Cleanup p3 as there are multiple sequences that could happen # TODO: Update with network log # TODO: Add voiceline sync? -537.6 "Definition of Insanity" Ability { id: "BAE2", source: "Kefka" } -543.7 "the Decisive Battle" Ability { id: "C2E3", source: "Exdeath" } -543.7 "the Decisive Battle" #Ability { id: "C2E2", source: "Chaos" } -547.8 "--sync--" Ability { id: "C554", source: "Kefka" } -562.9 "Bowels of Agony" Ability { id: "BAF2", source: "Chaos" } -581.9 "Thunder III" #Ability { id: "BB12", source: "Exdeath" } -581.9 "Stray Flames" #Ability { id: "BAF3", source: "Kefka" } -582.9 "Inferno" Ability { id: "BAF4", source: "Chaos" } -584.6 "Cyclone" Ability { id: "BAF8", source: "Chaos" } -590.9 "Thunder III" #Ability { id: "BB09", source: "Exdeath" } -590.9 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } -592.1 "Cyclone" Ability { id: "BAF8", source: "Chaos" } -593.9 "Thunder III" Ability { id: "BB0C", source: "Exdeath" } -595.1 "Cyclone" #Ability { id: "BAF8", source: "Chaos" } -596.5 "--sync--" Ability { id: "C555", source: "Kefka" } -596.7 "Cyclone" #Ability { id: "BAF8", source: "Chaos" } -599.6 "Stray Spray" Ability { id: "BAF6", source: "Chaos" } -600.6 "Cyclone" #Ability { id: "BAF8", source: "Chaos" } -600.6 "Tsunami" Ability { id: "BAF5", source: "Chaos" } -602.3 "Cyclone" #Ability { id: "BAF8", source: "Chaos" } -602.3 "Trance" Ability { id: "C2D6", source: "Kefka" } -603.5 "Longitudinal Implosion" Ability { id: "BAFD", source: "Chaos" } -604.3 "Shockwave" #Ability { id: "BAFF", source: "Chaos" } -606.3 "Shockwave" #Ability { id: "BAFF", source: "Chaos" } +# en: 'Hmph. I see what's going on here.' +537.7 "Definition of Insanity" Ability { id: "BAE2", source: "Kefka" } +543.8 "the Decisive Battle" Ability { id: "C2E3", source: "Exdeath" } +543.8 "the Decisive Battle" #Ability { id: "C2E2", source: "Chaos" } +548.0 "--sync--" Ability { id: "C554", source: "Kefka" } + +# Fire, Water, and Wind Elements +563.1 "Bowels of Agony" Ability { id: "BAF2", source: "Chaos" } +582.1 "Stray Spray" Ability { id: "BAF6", source: "Kefka" } +582.1 "Thunder III" #Ability { id: "BB12", source: "Exdeath" } +583.1 "Tsunami" Ability { id: "BAF5", source: "Kefka" } +584.9 "Cyclone" Ability { id: "BAF8", source: "Chaos" } +591.3 "Thunder III" Ability { id: "BB09", source: "Exdeath" } +591.3 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +594.3 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +597.0 "--sync--" Ability { id: "C555", source: "Kefka" } +603.0 "Trance" Ability { id: "C2D6", source: "Kefka" } +604.2 "Longitudinal Implosion/Latitudinal Implosion" Ability { id: ["BAFD", "BAFE"], source: "Chaos" } +605.0 "Shockwave" #Ability { id: "BAFF", source: "Chaos" } +607.0 "Shockwave" #Ability { id: "BAFF", source: "Chaos" } +609.0 "Stray Flames" Ability { id: "BAF3", source: "Chaos" } +610.0 "Inferno" Ability { id: "BAF4", source: "Chaos" } +611.7 "Cyclone" Ability { id: "BAF8", source: "Chaos" } + +# Limit Cut Preview +620.3 "Ultima Blaster" #Ability { id: "BAE3", source: "Kefka" } +622.3 "Ultima Blaster" #Ability { id: "BAE3", source: "Kefka" } +624.3 "Ultima Blaster" #Ability { id: "BAE3", source: "Kefka" } +624.4 "Umbra Smash" Ability { id: "BB00", source: "Chaos" } +626.3 "Ultima Blaster" #Ability { id: "BAE3", source: "Kefka" } +627.3 "Vacuum Wave" Ability { id: "BB13", source: "Exdeath" } +628.3 "Ultima Blaster" #Ability { id: "BAE3", source: "Kefka" } +630.3 "Ultima Blaster" #Ability { id: "BAE3", source: "Kefka" } +631.3 "Cyclone" Ability { id: "BAF8", source: "Chaos" } +632.4 "Ultima Blaster" #Ability { id: "BAE3", source: "Kefka" } +632.7 "Aetherlink" #Ability { id: "C2E5", source: "Exdeath" } +632.7 "Aetherlink" #Ability { id: "C2E4", source: "Chaos" } + +# Limit Cut +634.4 "Ultima Blaster" #Ability { id: "BAE3", source: "Kefka" } +642.4 "Ultima Blaster 1" #Ability { id: "BAE4", source: "Kefka" } +642.6 "Ultima Blaster 2" #Ability { id: "BAE4", source: "Kefka" } +642.8 "Ultima Blaster 3" #Ability { id: "BAE4", source: "Kefka" } +643.0 "Ultima Blaster 4" #Ability { id: "BAE4", source: "Kefka" } +643.2 "Ultima Blaster 5" #Ability { id: "BAE4", source: "Kefka" } +643.4 "Ultima Blaster 6" #Ability { id: "BAE4", source: "Kefka" } +643.6 "Ultima Blaster 7" #Ability { id: "BAE4", source: "Kefka" } +643.8 "Ultima Blaster 8" #Ability { id: "BAE4", source: "Kefka" } +649.7 "Thunder III" Ability { id: "BB09", source: "Exdeath" } +649.7 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +652.7 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +657.7 "the Decisive Battle" Ability { id: "C2E3", source: "Exdeath" } +657.7 "the Decisive Battle" #Ability { id: "C2E2", source: "Chaos" } +666.8 "Thunder III" Ability { id: "BB09", source: "Exdeath" } +666.8 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +# Giant Kefka + Earth Element +668.6 "Max" Ability { id: "BAE5", source: "Kefka" } +669.8 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +671.8 "Earthquake" Ability { id: "C571", source: "Chaos" } +671.8 "Earthquake" #Ability { id: "C572", source: "Chaos" } +680.5 "Earthquake" Ability { id: "BAFA", source: "Chaos" } +684.1 "Earthquake" Ability { id: "BAFA", source: "Chaos" } +687.4 "Slap Happy" Ability { id: "BAE7", source: "Kefka" } +688.2 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +688.9 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +689.7 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +690.9 "Slap Happy" Ability { id: "BAE9", source: "Kefka" } +690.9 "Shockwave" #Ability { id: "BAEB", source: "Kefka" } + +691.2 "Black Hole" Ability { id: "BAFB", source: "Exdeath" } +698.3 "Nothingness" Ability { id: "BAFC", source: "Black Hole" } +698.3 "Aetherlink" #Ability { id: "C2E5", source: "Exdeath" } +698.3 "Aetherlink" #Ability { id: "C2E4", source: "Chaos" } +705.3 "Nothingness" Ability { id: "BAFC", source: "Black Hole" } +708.4 "Thunder III" Ability { id: "BB09", source: "Exdeath" } +708.4 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +711.4 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +712.7 "Earthquake" Ability { id: "BAFA", source: "Chaos" } +716.5 "Damning Edict" Ability { id: "BB01", source: "Chaos" } +717.7 "Slap Happy" Ability { id: "BAE7", source: "Kefka" } +718.5 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +719.2 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +720.0 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +721.2 "Slap Happy" Ability { id: "BAE9", source: "Kefka" } +721.2 "Shockwave" #Ability { id: "BAEB", source: "Kefka" } +724.6 "Black Spark" Ability { id: "BCCD", source: "Black Hole" } +728.6 "Nothingness" Ability { id: "BAFC", source: "Black Hole" } +730.2 "Earthquake" Ability { id: "BAFA", source: "Chaos" } +733.8 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +733.8 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +735.4 "Earthquake" Ability { id: "BAFA", source: "Chaos" } +739.0 "Nothingness" Ability { id: "BAFC", source: "Black Hole" } +744.0 "Damning Edict" Ability { id: "BB01", source: "Chaos" } +744.4 "Look upon Me and Despair" Ability { id: "BAEC", source: "Kefka" } +745.4 "Look upon Me and Despair" Ability { id: "BAEE", source: "Kefka" } +747.5 "Blackblood" Ability { id: "C4BA", source: "Kefka" } +747.5 "Earthquake" Ability { id: "BAFA", source: "Chaos" } +749.7 "Thunder III" Ability { id: "BB09", source: "Exdeath" } +749.7 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +752.7 "Thunder III" #Ability { id: "BB0C", source: "Exdeath" } +762.8 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +762.8 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +764.4 "Earthquake" Ability { id: "BAFA", source: "Chaos" } +765.0 "Aetherlink" Ability { id: "C2E5", source: "Exdeath" } +765.0 "Aetherlink" #Ability { id: "C2E4", source: "Chaos" } +768.0 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +768.0 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +769.6 "Earthquake" Ability { id: "BAFA", source: "Chaos" } +773.2 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +773.2 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } + +784.2 "White Hole" Ability { id: "BD66", source: "Exdeath" } +784.2 "Longitudinal Implosion/Latitudinal Implosion" Ability { id: ["BAFD", "BAFE"], source: "Chaos" } +785.0 "Shockwave" #Ability { id: "BAFF", source: "Kefka" } +785.9 "Slap Happy" Ability { id: "BAE6", source: "Kefka" } +786.8 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +787.2 "Shockwave" #Ability { id: "BAFF", source: "Chaos" } +787.4 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +788.1 "Slap Happy" #Ability { id: "BAE8", source: "Kefka" } +789.3 "Slap Happy" Ability { id: "BAE9", source: "Kefka" } +789.3 "Shocking Impact" Ability { id: "BAEA", source: "Kefka" } +792.5 "Black Spark" Ability { id: "BCCD", source: "Kefka" } +796.5 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +796.5 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } +802.2 "Look upon Me and Despair" Ability { id: "BAED", source: "Kefka" } +803.2 "Look upon Me and Despair" Ability { id: "BAEE", source: "Kefka" } +803.5 "Nothingness" #Ability { id: "BAFC", source: "Black Hole" } + +# Blizzards and Towers +# Summary: +# 1. Bait 2 Puddles +# 2. Role 1 4-Stack +# 3. Role 2 2-NW Towers +# 4. Role 2 2-NE Towers +# 5. Role 1 2-NW Towers +# 6. Role 1 2-NE Towers +# 7. Role 2 4-Stack +# 8. Deep Freeze (Blizzard) +805.3 "--sync--" Ability { id: "C533", source: "Kefka" } +812.4 "Blizzard III (castbar)" Ability { id: "BB0F", source: "Exdeath" } +814.3 "Earthquake?" #Ability { id: "BAFA", source: "Chaos" } +815.4 "Blizzard III 1" Ability { id: "BB0D", source: "Exdeath" } +816.3 "Stomp-a-Mole (castbar)" Ability { id: "BAEF", source: "Kefka" } # Possibly determines which foot he starts with and/or its based on facing? +817.9 "Knock Down 1" Ability { id: "BB02", source: "Chaos" } +818.0 "Stomp-a-Mole 1" Ability { id: "BAF0", source: "Kefka" } +818.4 "Blizzard III 2" Ability { id: "BB0D", source: "Exdeath" } +819.3 "Stomp-a-Mole 2" Ability { id: "BAF0", source: "Kefka" } +820.6 "Stomp-a-Mole 3" Ability { id: "BAF0", source: "Kefka" } +821.9 "Stomp-a-Mole 4" Ability { id: "BAF0", source: "Kefka" } +823.3 "Knock Down 2" Ability { id: "BB03", source: "Chaos" } +826.4 "Blizzard III" Ability { id: "BB11", source: "Exdeath" } +827.4 "Big Bang" Ability { id: "BB05", source: "Chaos" } +827.4 "Big Bang" #Ability { id: "BB06", source: "Chaos" } + +839.0 "--sync--" StartsUsing { id: "C61E", source: "Exdeath" } window 839,3 jump "p3-exdeath-enrage" # Possibly this starts when Chaos dies? +# Possibly there is another if Exdeath is instead killed first, but Chaos triggers untargetable? + +840.8 "--sync--" StartsUsing { id: "C258", source: "Exdeath" } jump "p3-enrage" +840.8 "--sync--" StartsUsing { id: "C259", source: "Chaos" } jump "p3-enrage" +840.8 "--Chaos untargetable--" +840.8 "--Exdeath untargetable?--" +845.8 "Bowels of Agony (Enrage)?" #Ability { id: "C259", source: "Chaos" } # Chaos >0% HP +845.8 "Meteor (Enrage)?" #Ability { id: "C258", source: "Exdeath" } # Exdeath >0% HP + + +### Phase 4 - Kefka with Chaos and Neo Exdeath +# TODO: Cleanup p4 as there are multiple sequences that could happen +# TODO: Update with network log +# TODO: Add voiceline sync? +# en: 'Boring!' +# NOTE: Label not used due to unknown timing between Chaos/Exdeath kill order and time from Kefka Says +995.0 "--sync--" StartsUsing { id: "C2DC", source: "Kefka" } window 995,12000 # Escape from the p3 exdeath enrage or chaos +1000.0 "Kefka Says" Ability { id: "C2DC", source: "Kefka" } +1003.1 "--middle--" Ability { id: "C3FD", source: "Kefka" } + +1009.4 "Mystery Magic 1" Ability { id: "BA94", source: "Kefka" } +1009.4 "Thrumming Thunder III" #Ability { id: "BA9F", source: "Kefka" } +1009.4 "Blizzard III Blowout" #Ability { id: "BA9B", source: "Kefka" } +1013.7 "Grand Cross" Ability { id: "BB14", source: "Neo Exdeath" } +1018.7 "Inferno/Tsunami" Ability { id: ["BB20","BB21"], source: "Chaos" } + +1024.1 "Mystery Magic 2" Ability { id: "BA94", source: "Kefka" } +1024.1 "Thrumming Thunder III" #Ability { id: "BAA1", source: "Kefka" } +1024.1 "Blizzard III Blowout" #Ability { id: "BA9B", source: "Kefka" } +1028.4 "Grand Cross" Ability { id: "BB14", source: "Neo Exdeath" } +1033.5 "Tsunami/Inferno" Ability { id: ["BB21", "BB20"], source: "Chaos" } + +1039.2 "Mystery Magic 3" Ability { id: "BA94", source: "Kefka" } +1039.2 "Thrumming Thunder III" #Ability { id: "BAA1", source: "Kefka" } +1039.2 "Blizzard III Blowout" #Ability { id: "BA9B", source: "Kefka" } +1043.3 "Grand Cross" Ability { id: "BB14", source: "Neo Exdeath" } + +1045.3 "--sync--" Ability { id: "C554", source: "Kefka" } + +1055.4 "Flood of Naught" Ability { id: "C393", source: "Neo Exdeath" } +1055.8 "Edge of Death" Ability { id: "C396", source: "Neo Exdeath" } +1055.8 "White Antilight" #Ability { id: "C394", source: "Neo Exdeath" } +1055.8 "Black Antilight" #Ability { id: "C395", source: "Neo Exdeath" } +1059.0 "--sync--" Ability { id: "C555", source: "Kefka" } +1059.7 "Death Surge" Ability { id: "BB1D", source: "Neo Exdeath" } +1064.1 "Mana Charge" Ability { id: "BAA4", source: "Kefka" } +1064.4 "Death Bolt" #Ability { id: "BB18", source: "Neo Exdeath" } +1064.4 "Death Wave" #Ability { id: "BB1A", source: "Neo Exdeath" } +1072.4 "Thrumming Thunder III" Ability { id: "C5DE", source: "Kefka" } +1072.4 "Thrumming Thunder III" #Ability { id: "BA9F", source: "Kefka" } +1073.4 "Death Shriek" Ability { id: "BB16", source: "Neo Exdeath" } +1082.5 "Ultima Upsurge" Ability { id: "C24A", source: "Kefka" } +1085.3 "Stray Flames" Ability { id: "BB23", source: "Chaos" } +1089.4 "Death Wave" Ability { id: "BB1B", source: "Neo Exdeath" } +1089.4 "Death Bolt" #Ability { id: "BB19", source: "Neo Exdeath" } +1089.4 "Death Bomb" #Ability { id: "BB15", source: "Neo Exdeath" } +1090.4 "Blizzard III Blowout" Ability { id: "BA9B", source: "Kefka" } +1094.6 "Stray Spray" #Ability { id: "BB25", source: "Chaos" } +1095.9 "Stray Spray" #Ability { id: "BB25", source: "Chaos" } +1097.2 "Death Shriek" Ability { id: "BB17", source: "Neo Exdeath" } +1103.5 "Mana Release" Ability { id: "BAA5", source: "Kefka" } +1107.6 "Stray Spray" Ability { id: "BB25", source: "Chaos" } +1108.5 "Thrumming Thunder III" #Ability { id: "BA9F", source: "Kefka" } +1108.5 "Blizzard III Blowout" #Ability { id: "BA9B", source: "Kefka" } + +1112.8 "--sync--" StartsUsing { id: "BABB", source: "Kefka" } jump "p4-enrage" +1112.8 "--untargetable?--" +1114.8 "--middle?--" Ability { id: "C3FD", source: "Kefka" } window 90,5 jump "p4-success" # Kefka <20% HP +1117.8 "Light of Judgment (Enrage)?" #Ability { id: "BABB", source: "Kefka" } # Kefka >20% HP +1121.3 "Ultima Upsurge?" #Ability { id: "C24A", source: "Kefka" } +1159.2 "Ultima Repeater (castbar)?" #Ability { id: "BB40", source: "Kefka" } + + +### Phase 5 - Kefka +# TODO: Add voiceline sync? +# en: 'Destruction is the fate of all things.' +1255.6 label "p4-success" +1255.6 "--middle--" Ability { id: "C3FD", source: "Kefka" } +1261.9 "Ultima Upsurge" Ability { id: "C24A", source: "Kefka" } +1300.0 "Ultima Repeater (castbar)" Ability { id: "BB40", source: "Kefka" } +1301.1 "Ultima Repeater 1" #Ability { id: "BB41", source: "Kefka" } +1301.9 "Ultima Repeater 2" #Ability { id: "BB41", source: "Kefka" } +1302.6 "Ultima Repeater 3" #Ability { id: "BB41", source: "Kefka" } +1303.4 "Ultima Repeater 4" #Ability { id: "BB41", source: "Kefka" } +1305.4 "--sync--" Ability { id: "C652", source: "Kefka" } +1306.3 "Fell Forces" Ability { id: "C654", source: "Kefka" } +1306.3 "Fell Forces" #Ability { id: "C655", source: "Kefka" } +1306.3 "Fell Forces" #Ability { id: "C653", source: "Kefka" } +1308.6 "--sync--" Ability { id: "C652", source: "Kefka" } +1309.5 "Fell Forces" Ability { id: "C654", source: "Kefka" } +1309.5 "Fell Forces" #Ability { id: "C655", source: "Kefka" } +1309.5 "Fell Forces" #Ability { id: "C653", source: "Kefka" } +1311.8 "--sync--" Ability { id: "C652", source: "Kefka" } +1312.7 "Fell Forces" Ability { id: "C654", source: "Kefka" } +1312.7 "Fell Forces" #Ability { id: "C655", source: "Kefka" } +1312.7 "Fell Forces" #Ability { id: "C653", source: "Kefka" } +1314.6 "--sync--" #Ability { id: "C183", source: "Kefka" } +1315.6 "--sync--" #Ability { id: "C183", source: "Kefka" } +1316.6 "--sync--" #Ability { id: "C183", source: "Kefka" } +1317.6 "--sync--" #Ability { id: "C183", source: "Kefka" } +1317.9 "Flood" Ability { id: "C13F", source: "Kefka" } +1318.9 "Chaotic Flood" #Ability { id: "BB4F", source: "Kefka" } +1318.9 "Flood" #Ability { id: "C269", source: "Kefka" } +1319.9 "Chaotic Flood" #Ability { id: "BB4F", source: "Kefka" } +1319.9 "Flood" #Ability { id: "C269", source: "Kefka" } +1320.8 "Chaotic Flood" #Ability { id: "BB4F", source: "Kefka" } +1320.9 "Flood" #Ability { id: "C269", source: "Kefka" } +1321.8 "Chaotic Flood" #Ability { id: "BB4F", source: "Kefka" } +1321.9 "Flood" #Ability { id: "C269", source: "Kefka" } +1330.9 "Maddening Orchestra" Ability { id: "BB50", source: "Kefka" } +1331.8 "Holy" Ability { id: "BB54", source: "Kefka" } +1331.8 "Flare" #Ability { id: "BB52", source: "Kefka" } +1334.0 "Maddening Orchestra" Ability { id: "BB51", source: "Kefka" } +1334.9 "Holy" Ability { id: "BB54", source: "Kefka" } +1334.9 "Chaotic Flare" #Ability { id: "BB53", source: "Kefka" } +1335.6 "Chaotic Holy" Ability { id: "BB56", source: "Kefka" } +1336.3 "Flare Diffusion" Ability { id: "BB55", source: "Kefka" } +1342.3 "--sync--" Ability { id: "C652", source: "Kefka" } +1343.2 "Fell Forces" Ability { id: "C653", source: "Kefka" } +1345.5 "--sync--" Ability { id: "C652", source: "Kefka" } +1352.3 "Celestriad" Ability { id: "BB42", source: "Kefka" } +# TODO: Get up to the enrage # Phase 2 Enrage Sequence 10376.2 label "p2-enrage" -10381.2 "Light of Judgment (Enrage)" #Ability { id: "BAE1", source: "Kefka" } # Kefka > 0% HP +10381.2 "Light of Judgment (Enrage)" Ability { id: "BAE1", source: "Kefka" } # Kefka >0% HP + +# Phase 3 Enrage Sequence +10840.8 label "p3-enrage" +10845.8 "Bowels of Agony (Enrage)" Ability { id: "C259", source: "Chaos" } # Chaos >0% HP +10845.8 "Meteor (Enrage)" Ability { id: "C258", source: "Exdeath" } # Exdeath >0% HP + +# Phase 3 Exdeath Enrage Sequence +11839.0 label "p3-exdeath-enrage" +11849.0 "Meteor (Exdeath Enrage)" StartsUsing { id: "C61E", source: "Exdeath" } # Exdeath >0% HP +# NOTE: Using a window to jump back to p4, TBD if killing Exdeath first triggers a separate sequence + +# Phase 4 Enrage Sequence +12000.0 label "p4-enrage" +12005.0 "Light of Judgment (Enrage)" Ability { id: "BABB", source: "Kefka" } # Kefka >20% HP + # IGNORED ABILITIES # C252 Attack: P1 Kefka attack and P3 Chaos attack @@ -190,7 +451,10 @@ hideall "--sync--" # BAD7 Past's End: Damage (On 1 player) # BAD8 Future's End: Damage (On 3 players) # BAD9 Past's End: Damage (On 3 players) +# BACF Wings of Destruction: AOE Damage (On nearest/furthest players) # C250 Attack: P3 Exdeath attack +# BAF9 Stray Earth: Some sort of failed P3 mechanic +# BAF1 Unmitigated Impact: P3 Failing to soak a tower # ALL ENCOUNTER ABILITIES # BA94 Mystery Magic @@ -203,6 +467,8 @@ hideall "--sync--" # BAA1 Thrumming Thunder III: Damage (paired with BAA0) # BAA2 Flagrant Fire III: Spread Damage # BAA3 Flagrant Fire III: Stack Damage +# BAA4 Mana Charge +# BAA5 Mana Release # BAA6 Double-Trouble Trap: VFX # BAA7 Double-Trouble Trap # BAA8 Wave Cannon @@ -221,7 +487,7 @@ hideall "--sync--" # BAB6 Idyllic Will # BAB9 Tele-Trouncing: VFX # BABA Tele-Trouncing -# BABB Light of Judgment: P1 Enrage +# BABB Light of Judgment: P1 Enrage and P4 Enrage # BABC Forsaken # BABD Light of Judgment: P2 version # BABE The Path of Light @@ -229,44 +495,124 @@ hideall "--sync--" # BAC0 Spelldriver # BAC1 Spellscatter # BAC2 Spellwave -# BACE Wings of Destruction -# BACF Wings of Destruction +# BACD Wings of Destruction: Left wing +# BACE Wings of Destruction: Right wing +# BACF Wings of Destruction: AOE Damage (On nearest/furthest players) # BAD2 Future's End: VFX # BAD3 Past's End: VFX # BAD6 Future's End: Damage (On 1 player) # BAD7 Past's End: Damage (On 1 player) # BAD8 Future's End: Damage (On 3 players) # BAD9 Past's End: Damage (On 3 players) -# BADC All Things Ending -# BADD All Things Ending +# BADC All Things Ending: Followup to BAD2 Future's End +# BADD All Things Ending: Followup to BAD3 Past's End # BADF Trine # BAE0 Trine +# BAE1 Light of Judgment: P2 Enrage # BAE2 Definition of Insanity +# BAE3 Ultima Blaster +# BAE4 Ultima Blaster +# BAE5 Max +# BAE6 Slap Happy +# BAE7 Slap Happy +# BAE8 Slap Happy +# BAE9 Slap Happy +# BAEA Shocking Impact +# BAEB Shockwave +# BAEC Look upon Me and Despair +# BAED Look upon Me and Despair +# BAEE Look upon Me and Despair +# BAEF Stomp-a-Mole +# BAF0 Stomp-a-Mole +# BAF1 Unmitigated Impact # BAF2 Bowels of Agony # BAF3 Stray Flames # BAF4 Inferno # BAF5 Tsunami # BAF6 Stray Spray # BAF8 Cyclone +# BAF9 Stray Earth: Some sort of failed P3 mechanic +# BAFA Earthquake +# BAFB Black Hole +# BAFC Nothingness # BAFD Longitudinal Implosion +# BAFE Latitudinal Implosion # BAFF Shockwave +# BB00 Umbra Smash +# BB01 Damning Edict +# BB02 Knock Down: VFX +# BB03 Knock Down: Damage +# BB05 Big Bang +# BB06 Big Bang # BB09 Thunder III # BB0C Thunder III +# BB0D Blizzard III +# BB0F Blizzard III +# BB11 Blizzard III # BB12 Thunder III -# BAE1 Light of Judgment: P2 Enrage +# BB13 Vacuum Wave +# BB14 Grand Cross +# BB15 Death Bomb +# BB16 Death Shriek +# BB17 Death Shriek +# BB18 Death Bolt +# BB19 Death Bolt +# BB1A Death Wave +# BB1B Death Wave +# BB1D Death Surge +# BB20 Inferno +# BB21 Tsunami +# BB23 Stray Flames +# BB25 Stray Spray +# BCCD Black Spark +# BB40 Ultima Repeater +# BB41 Ultima Repeater +# BB42 Celestriad +# BB4F Chaotic Flood +# BB50 Maddening Orchestra +# BB51 Maddening Orchestra +# BB52 Flare +# BB53 Chaotic Flare +# BB54 Holy +# BB55 Flare Diffusion +# BB56 Chaotic Holy # BCF2 Graven Image +# BD66 White Hole +# C13F Flood +# C183 --sync-- +# C24A Ultima Upsurge # C24B Hyperdrive # C24C Ultimate Embrace # C250 Attack: P3 Exdeath attack # C252 Attack: P1 Kefka attack and P3 Chaos attack +# C258 Meteor: P3 Chaos Enrage +# C259 Bowels of Agony: P3 Exdeath Enrage +# C269 Flood # C2D6 Trance +# C2DC Kefka Says # C2E2 the Decisive Battle # C2E3 the Decisive Battle +# C2E4 Aetherlink +# C2E5 Aetherlink +# C392 Flood of Naught +# C393 Flood of Naught +# C394 White Antilight +# C395 Black Antilight +# C396 Edge of Death # C3F7 Aero III Assault # C3FD --sync--: Boss jumps to middle # C403 Revolting Ruin III -# C487 Wings of Destruction +# C487 Wings of Destruction: VFX/castbar for BACF +# C4BA Blackblood # C4E1 Revolting Ruin III +# C533 --sync-- # C554 --sync-- # C555 --sync-- +# C571 Earthquake +# C572 Earthquake +# C5DE Thrumming Thunder III # C622 Light of Judgment: P1 version +# C652 --sync-- +# C653 Fell Forces +# C654 Fell Forces +# C655 Fell Forces