diff --git a/ui/raidboss/data/07-dt/alliance/san-doria-second-walk.ts b/ui/raidboss/data/07-dt/alliance/san-doria-second-walk.ts new file mode 100644 index 00000000000..b591c7e1188 --- /dev/null +++ b/ui/raidboss/data/07-dt/alliance/san-doria-second-walk.ts @@ -0,0 +1,1351 @@ +import Conditions from '../../../../../resources/conditions'; +import { UnreachableCode } from '../../../../../resources/not_reached'; +import Outputs from '../../../../../resources/outputs'; +import { callOverlayHandler } from '../../../../../resources/overlay_plugin_api'; +import { Responses } from '../../../../../resources/responses'; +import { DirectionOutput8, Directions } from '../../../../../resources/util'; +import ZoneId from '../../../../../resources/zone_id'; +import { RaidbossData } from '../../../../../types/data'; +import { PluginCombatantState } from '../../../../../types/event'; +import { Matches } from '../../../../../types/net_matches'; +import type { LocaleText, Output, TriggerSet } from '../../../../../types/trigger'; + +type KirinSequenceStep = + | 'out' + | 'under' + | 'sides' + | 'awayBossArms' + | 'awayBoss' + | 'awayArms' + | 'awayTethered' + | 'flank'; // | 'dodge' + +type KamSixDirection = 'dirN' | 'dirNE' | 'dirSE' | 'dirS' | 'dirSW' | 'dirNW'; + +type KamElement = 'fire' | 'earth' | 'water' | 'ice' | 'lightning' | 'wind'; + +type KamBlade = { + x: number; + y: number; + // heading: number; +}; +const kirinCenter = [-850.00, 780.00]; + +const kirinSequenceOutputStrings = { + out: Outputs.out, + under: Outputs.getUnder, + sides: Outputs.sides, + awayBossArms: { + en: 'Away from boss & arms', + }, + awayBoss: { + en: 'Away from boss', + }, + awayArms: { + en: 'Away from Arms (on boss hitbox)', + }, + awayTethered: { + en: 'Away from tethered arm (${dir})', + }, + flank: { + en: 'Max melee on flank', + }, + // dodge: { + // en: 'Dodge' + // }, + next: Outputs.next, + east: Outputs.east, + west: Outputs.west, +}; + +const kamlanautElementalOutputStrings: { [key in KamElement]: LocaleText } = { + fire: { + en: 'Fire', + }, + water: { + en: 'Water', + }, + wind: { + en: 'Wind', + }, + earth: { + en: 'Earth', + }, + lightning: { + en: 'Lightning', + }, + ice: { + en: 'Ice', + }, +}; + +const kamSixDirections = [ + 'dirSE', + 'dirS', + 'dirSW', + 'dirNW', + 'dirN', + 'dirNE', +]; + +const kamlanautElementBuffIds: { [key: string]: KamElement } = { + '3AC': 'fire', + '3AD': 'earth', + '3AE': 'water', + '3AF': 'ice', + '3B0': 'lightning', + '3B1': 'wind', +}; + +const kamlanautSublimeConeCasts: { [key: string]: KamElement } = { + 'AC93': 'fire', + 'AC94': 'earth', + 'AC95': 'water', + 'AC96': 'ice', + 'AC97': 'lightning', + 'AC98': 'wind', + // ## aoes that expand + 'AC99': 'fire', + 'AC9A': 'earth', + 'AC9B': 'water', + 'AC9C': 'ice', + 'AC9D': 'lightning', + 'AC9E': 'wind', +}; +const kamlanautSublimeBladeCasts: { [key: string]: KamElement } = { + 'AC9F': 'fire', + 'ACA0': 'earth', + 'ACA1': 'water', + 'ACA2': 'ice', + 'ACA3': 'lightning', + 'ACA4': 'wind', + // ## aoes that expand + 'ACA5': 'fire', + 'ACA6': 'earth', + 'ACA7': 'water', + 'ACA8': 'ice', + 'ACA9': 'lightning', + 'ACAA': 'wind', +}; + +const kamlanautCrystalNpcIds: { [key: string]: KamElement } = { + '1EBE84': 'fire', + '1EBE85': 'water', + '1EBE86': 'wind', + '1EBE87': 'earth', + '1EBE88': 'ice', + '1EBE89': 'lightning', +}; + +const kirinSequenceInfoOutput = ( + sequence: KirinSequenceStep[], + ability: string[], + direction?: 'east' | 'west', +) => { + return (data: Data, _matches: Matches, output: Output) => { + data.kirinSequencedSafeCallouts = {}; + const items: string[] = []; + sequence.forEach((step, index) => { + const key = ability[index]; + if (key !== undefined) { + const call = step === 'awayTethered' + ? output[step]!({ dir: output[direction!]!() }) + : output[step]!(); + data.kirinSequencedSafeCallouts[key] = call; + items.push(call); + // console.info(`${index} - ${key} => ${call}`); + } + }); + data.kirinSequenceCalls = items.length - 1; + // console.table(data.kirinSequencedSafeCallouts); + const result = items.join(output.next!()); + console.log(result); + return result; + // return { infoText: result }; + }; +}; + +const floatNear = (n1: number, n2: number, epsilon = 0.1) => { + return Math.abs(n1 - n2) < epsilon; +}; + +const isValidSiXDir = (dir: DirectionOutput8 | undefined): dir is KamSixDirection => { + return kamSixDirections.includes(dir!); +}; + +const emptySixDirections = () => { + return { + dirSE: undefined, + dirS: undefined, + dirSW: undefined, + dirNW: undefined, + dirN: undefined, + dirNE: undefined, + }; +}; + +type OrbLocation = 'north' | 'middle' | 'south'; + +const sublimeElementsBladeSafespot = ( + blades: { [p: string]: KamBlade }, + elements: KamElement[], +) => { + const cols: Record = { [-220]: null, [-200]: null, [-180]: null }; + const rows: Record = { 130: null, 150: null, 170: null }; + + for (const [ele, pos] of Object.entries(blades)) { + const x = Number(pos.x); + const y = Number(pos.y); + const val = elements.includes(ele as KamElement) ? 'BAD' : ele; + if (floatNear(y, 110, 0.5)) { + cols[x] = val; + } else { + rows[y] = val; + } + } + + const validCols = Object.values(cols).filter((v) => (v !== null) && v !== 'BAD') as string[]; + const validRows = Object.values(rows).filter((v) => (v !== null) && v !== 'BAD') as string[]; + + if (!(validCols.length >= 1 || validRows.length >= 1)) { + throw new Error('Invalid blade configuration'); + } + + const result: string[] = []; + if (validCols.length === 1) { + result.push(validCols[0]!); + if (validRows.length < 3) + result.push(validRows[0]!); + } else if (validRows.length === 1) { + result.push(validRows[0]!); + if (validCols.length < 3) + result.push(validCols[0]!); + } + + return result; +}; + +const OmegaManaScreenPatterns: { [key: string]: { [key in OrbLocation]?: string } } = { + 'ceB,nwC,seB': { middle: 'frontRight' }, + 'ceC,nwB,seC': { south: 'backLeft' }, + 'ceC,nwB,swC': { south: 'frontMiddle' }, + 'cwC,neB,seB': { north: 'backMiddle' }, + 'cwC,nwB,seB': { north: 'frontRight', middle: 'frontRight' }, +}; + +export interface Data extends RaidbossData { + tankbusterTargets: string[]; + combatantData: PluginCombatantState[]; + kirinSequencedSafeCallouts: { [key: string]: string }; + kirinSequenceCalls: number; + omegaOrbs: OrbLocation[]; + omegaManaScreens: string[]; + kamElements: KamElement[]; + kamElementalCones: Record; + kamElementalBlades: { [key: string]: KamBlade }; + kamEstocHeadings: number[]; + kamCrystalLocations: { [key: string]: KamElement }; + kamCrystalCasts: KamSixDirection[]; +} + +const triggerSet: TriggerSet = { + id: 'San d\'Oria: The Second Walk', + zoneId: ZoneId.SanDoriaTheSecondWalk, + timelineFile: 'san-doria-second-walk.txt', + initData: () => { + return { + tankbusterTargets: [], + combatantData: [], + kirinSequencedSafeCallouts: {}, + kirinSequenceCalls: 0, + omegaOrbs: [], + omegaManaScreens: [], + kamElements: [], + kamElementalCones: emptySixDirections(), + kamElementalBlades: {}, + kamEstocHeadings: [], + kamCrystalLocations: {}, + kamCrystalCasts: [], + }; + }, + triggers: [ + // ---------------------- + // Faithbound Kirin + { + id: 'San dOria Second Walk Faithbound Kirin Stonega IV', + type: 'StartsUsing', + netRegex: { id: 'ADCA', source: 'Faithbound Kirin', capture: false }, + response: Responses.aoe(), + }, + { + id: 'San dOria Second Walk Faithbound Kirin Crimson Riddle Front', + type: 'StartsUsing', + netRegex: { id: ['AFF4'], source: 'Faithbound Kirin', capture: false }, + response: Responses.getBehind(), + }, + { + id: 'San dOria Second Walk Faithbound Kirin Crimson Riddle Rear', + type: 'StartsUsing', + netRegex: { id: ['AFF5'], source: 'Faithbound Kirin', capture: false }, + response: Responses.goFront(), + }, + { + id: 'San dOria Second Walk Faithbound Kirin Punishment', + type: 'StartsUsing', + netRegex: { id: 'ADCB', source: 'Faithbound Kirin' }, + response: Responses.tankBuster(), + }, + { + // every tower must be taken, or it is a wipe + // arms also cast AF80, ADB6 (slightly different timings for some reason) + // ADBF - damage from tower (Bury) + id: 'San dOria Second Walk Faithbound Kirin Deadly Hold', + type: 'StartsUsing', + netRegex: { id: 'ADB2', source: 'Faithbound Kirin', capture: false }, + suppressSeconds: 1, + alertText: (data, _matches, output) => { + if (data.role === 'tank' || data.job === 'BLU') + return output.tankTower!(); + }, + outputStrings: { + tankTower: { + en: 'Soak Tank Tower', + }, + }, + }, + { + id: 'San dOria Second Walk Chiseled Arm Shockwave', + type: 'StartsUsing', + netRegex: { id: 'ADC0', source: 'Chiseled Arm', capture: false }, + response: Responses.aoe(), + }, + { + id: 'San dOria Second Walk Faithbound Kirin Striking Right', + type: 'StartsUsing', + netRegex: { id: 'AD93', source: 'Faithbound Kirin', capture: false }, + infoText: (_data, _matches, output) => { + return output.awayTethered!({ dir: output.east!() }); + }, + outputStrings: kirinSequenceOutputStrings, + }, + { + id: 'San dOria Second Walk Faithbound Kirin Striking Left', + type: 'StartsUsing', + netRegex: { id: 'ADAF', source: 'Faithbound Kirin', capture: false }, + infoText: (_data, _matches, output) => { + return output.awayTethered!({ dir: output.west!() }); + }, + outputStrings: kirinSequenceOutputStrings, + }, + { + // AD95 - mechanic cast + // AD96 - from boss x2 + // AD9C, AD9B - from Sculpted Arms + id: 'San dOria Second Walk Faithbound Kirin Synchronized Strike', + type: 'StartsUsing', + netRegex: { id: 'AD95', source: 'Faithbound Kirin', capture: false }, + infoText: kirinSequenceInfoOutput(['sides', 'awayArms'], ['_', 'AD95']), + outputStrings: kirinSequenceOutputStrings, + // en: 'dodge => away from Arms (on boss hitbox)', + }, + { + // ADA0 - mech cast + // ADB0 - preview line aoes from boss + // ADAD - preview out aoe -OR- ADAE (Striking Right)/ADAF (Left) + // ADA1 - line aoes from boss (Synchronized Sequence) + // AD9C,AD9B - line aoes from arms + // ADA2 - out (Wringer) -OR- ADA3 (Striking Right)/ADA4 *probably + // ADA8 - under (Dead Wringer) ADA9 -or- (Smiting Right) + id: 'San dOria Second Walk Faithbound Kirin Synchronized Sequence', + type: 'StartsUsing', + netRegex: { id: 'ADA0', source: 'Faithbound Kirin', capture: false }, + durationSeconds: 10, + infoText: kirinSequenceInfoOutput(['sides', 'awayBossArms', 'under'], ['_', 'ADA1', 'ADA2']), + outputStrings: kirinSequenceOutputStrings, + // en: 'Sides => Away from boss & arms => Under boss', + }, + { + // AD9D - mech cast + // ADAD - preview out aoe + // ADB0 - preview line aoes from boss + // AD9D - out aoe (Double Wringer) + // ADA6 - line aoes from boss (ADA5 selfcast) + // AD97 - under (Dead Wringer) + // ADAB,ADAC - line aoes from arms + id: 'San dOria Second Walk Faithbound Kirin Double Wringer', + type: 'StartsUsing', + netRegex: { id: 'AD9D', source: 'Faithbound Kirin', capture: false }, + durationSeconds: 10, + infoText: kirinSequenceInfoOutput(['out', 'flank', 'under'], ['_', 'AD9D', 'ADA6']), + outputStrings: kirinSequenceOutputStrings, + // en: 'Out => Max melee on flank => Under boss', + }, + { + id: 'San dOria Second Walk Faithbound Kirin Smiting Right Sequence', + type: 'StartsUsing', + netRegex: { id: 'AD9E', source: 'Faithbound Kirin', capture: false }, + durationSeconds: 12, + infoText: kirinSequenceInfoOutput(['awayTethered', 'awayBoss', 'under'], [ + '_', + 'AD9E', + 'ADA2', + ], 'east'), + outputStrings: kirinSequenceOutputStrings, + // en: 'Away from tethered arm (East) => away from boss => under', + }, + { + // AD9F - cast + // ADAF - left punch preview + // ADAD - out preview + // AD9F - left punch damage + // ADA2 - Wringer damage + // AD9A - arm punch (Smiting Left) + // ADA7 - under (Dead Wringer) + id: 'San dOria Second Walk Faithbound Kirin Smiting Left Sequence', + type: 'StartsUsing', + netRegex: { id: 'AD9F', source: 'Faithbound Kirin', capture: false }, + durationSeconds: 12, + infoText: kirinSequenceInfoOutput(['awayTethered', 'awayBoss', 'under'], [ + '_', + 'AD9F', + 'ADA2', + ], 'west'), + outputStrings: kirinSequenceOutputStrings, + // en: 'Away from tethered arm (West) => away from boss => under', + }, + { + // AD92 - cast + // AD97, AD98 - from Sculpted Arms + id: 'San dOria Second Walk Faithbound Kirin Wringer', + type: 'StartsUsing', + netRegex: { id: 'AD92', source: 'Faithbound Kirin', capture: false }, + infoText: kirinSequenceInfoOutput(['out', 'under'], ['_', 'AD92']), + outputStrings: kirinSequenceOutputStrings, + }, + + { + id: 'San dOria Second Walk Faithbound Kirin Sequenced Mechanics', + type: 'Ability', + netRegex: { + id: ['AD9D', 'ADA6', 'AD96', 'AD97', 'ADA1', 'AD9C', 'ADA2', 'AD9E', 'AD9F'], + source: 'Faithbound Kirin', + capture: true, + }, + condition: (data) => data.kirinSequenceCalls > 0, + suppressSeconds: 1, + alertText: (data, matches, _output) => { + if (!Object.keys(data.kirinSequencedSafeCallouts).includes(matches.id)) { + return; + } + const call = data.kirinSequencedSafeCallouts[matches.id]; + if (call === undefined) { + throw new UnreachableCode(); + } + data.kirinSequenceCalls--; + console.info(`SEQMECH - ${matches.ability} ${matches.id} => ${call}`); + return call; + }, + outputStrings: {}, + }, + // SUMMON: Seiryu + { + // AD80 - orange/CW + // AD81 - blue/CCW + id: 'San dOria Second Walk Faithbound Kirin Eastwind Wheel', + type: 'StartsUsing', + netRegex: { id: ['AD80', 'AD81'], source: 'Dawnbound Seiryu' }, + // promise: async (data, matches) => { + // data.combatantData = []; + // + // data.combatantData = (await callOverlayHandler({ + // call: 'getCombatants', + // ids: [parseInt(matches.sourceId, 16)], + // })).combatants; + // }, + infoText: (_data, matches, output) => { + // const [combatant] = data.combatantData; + // if (combatant === undefined || data.combatantData.length !== 1) + // return; //todo: remove me after verifying not needed + // Seiryu only spawns east or south but can spin either way so just +/-1 depending on the rotation. + const x = parseFloat(matches.x); + const y = parseFloat(matches.y); + const rotation = matches.id === 'AD81' ? -1 : 1; + // N = 0, E = 1, S = 2, W = 3 + const card = Directions.xyTo4DirNum(x, y, kirinCenter[0]!, kirinCenter[1]!); + const safeHalf = ['north', 'east', 'south', 'west'][(card + rotation) % 4]; + if (safeHalf !== undefined) + return output.dodgeDir!({ dir: output[safeHalf]!() }); + return output.dodge!(); + }, + outputStrings: { + dodge: { + en: 'Avoid rotating AoE', + }, + dodgeDir: { + en: '${dir} half safe', + }, + north: Outputs.north, + east: Outputs.east, + west: Outputs.west, + south: Outputs.south, + }, + }, + { + // Stonega III is used in both Seiryu (A917) and Suzaku (B07A) + id: 'San dOria Second Walk Faithbound Kirin Stonega III', + type: 'StartsUsing', + netRegex: { id: ['A917', 'B07A'], source: 'Faithbound Kirin' }, + condition: Conditions.targetIsYou(), + response: Responses.spread(), + }, + // SUMMON Genbu + { + // large AOE (dash destination) followed by get under + id: 'San dOria Second Walk Faithbound Kirin Midwinter March', + type: 'StartsUsing', + netRegex: { id: 'AD87', source: 'Moonbound Genbu', capture: false }, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Follow Moonbound Genbu => Get under', + }, + }, + }, + // { + // id: 'San dOria Second Walk Faithbound Kirin Northern Current', + // type: 'StartsUsing', + // netRegex: { id: 'AD88', source: 'Moonbound Genbu' }, + // infoText: (_data, matches, output) => { + // return output.under!({ name: matches.source }); + // }, + // outputStrings: { + // under: { + // en: 'Get under ${name}', + // }, + // }, + // }, + { + id: 'San dOria Second Walk Faithbound Kirin Shattering Stomp', + type: 'StartsUsing', + netRegex: { id: 'AD84', source: 'Moonbound Genbu', capture: false }, + response: Responses.aoe(), + }, + { + // floor explosions + id: 'San dOria Second Walk Faithbound Kirin Moontide Font', + type: 'StartsUsing', + netRegex: { id: ['AD85', 'AD86'], source: 'Moonbound Genbu', capture: false }, + suppressSeconds: 10, + infoText: (_data, _matches, output) => { + return output.avoid!(); + }, + outputStrings: { + avoid: { + en: 'Avoid geyser explosions', + }, + }, + }, + // SUMMON Byakko + { + // dashes to the panel opposite and uses Razor Fang (AD90) + id: 'San dOria Second Walk Faithbound Kirin Gloaming Gleam', + type: 'StartsUsing', + netRegex: { id: 'AD8F', source: 'Duskbound Byakko' }, + alertText: (_data, matches, output) => { + return output.sides!({ name: matches.source }); + }, + outputStrings: { + sides: { + en: 'Go to sides of ${name} (not in front)', + }, + }, + }, + { + // 3 random puddles on the floor + id: 'San dOria Second Walk Faithbound Kirin Quake', + type: 'StartsUsing', + netRegex: { id: ['B07B', 'B07C'], source: 'Faithbound Kirin', capture: false }, + // response: Responses.aoe(), // todo: probs just remove + }, + // SUMMON Suzaku + { + // self-target AD8A + id: 'San dOria Second Walk Faithbound Kirin Vermilion Flight', + type: 'StartsUsing', + netRegex: { id: 'AEFB', source: 'Sunbound Suzaku' }, + durationSeconds: 7, + alertText: (_data, matches, output) => { + return output.sides!({ name: matches.source }); + }, + outputStrings: { + sides: { + en: 'Avoid ${name} dash + dodge ground AoEs', + }, + }, + }, + + // ---------------------- + // Ultima & Omega + + { + id: 'San dOria Second Walk Omega, the One Ion Efflux', + type: 'StartsUsing', + netRegex: { id: 'AD2B', source: 'Omega, the One', capture: false }, + response: Responses.aoe(), + }, + { + id: 'San dOria Second Walk Omega, the One Citadel Buster', + type: 'StartsUsing', + netRegex: { id: 'AD1B', source: 'Ultima, the Feared', capture: false }, + response: Responses.aoe(), + }, + { + // B087 is the cast, but happens way in advance + id: 'San dOria Second Walk Omega, the One Anti-personnel Missile', + type: 'StartsUsing', + netRegex: { id: 'B088', source: 'Omega, the One' }, + condition: Conditions.targetIsYou(), + response: Responses.spread(), + }, + { + id: 'San dOria Second Walk Omega, the One Antimatter', + type: 'StartsUsing', + netRegex: { id: 'AD11', source: 'Ultima, the Feared' }, + condition: Conditions.targetIsYou(), + alertText: (_data, _matches, output) => { + return output.tankBusterOnYou!(); + }, + outputStrings: { + tankBusterOnYou: Outputs.tankBusterOnYou, + }, + }, + { + id: 'San dOria Second Walk Omega, the One Mana Screen Collect', + type: 'CombatantMemory', + netRegex: { change: 'Add', pair: [{ key: 'BNpcID', value: ['1EBE8B', '1EBE8C'] }] }, + run: (data, matches) => { + const x = parseFloat(matches.pairPosX ?? '0'); + const y = parseFloat(matches.pairPosY ?? '0'); + // both platforms are in line with each other, so for X we need to check 2 values + const col1 = floatNear(x, 725) || floatNear(x, 790); + // const col2 = floatNear(x, 745) || floatNear(x, 810); + const row1 = floatNear(y, 784); + const row2 = floatNear(y, 800); + // const row3 = floatNear(y, 816); + const direction = matches.pairBNpcID === '1EBE8B' ? 'B' : 'C'; + const key = `${row1 ? 'n' : (row2 ? 'c' : 's')}${col1 ? 'w' : 'e'}${direction}`; + data.omegaManaScreens.push(key); + }, + }, + { + id: 'San dOria Second Walk Omega, the One Energy Orb (cast)', + type: 'Ability', + netRegex: { id: 'AD08', source: 'Ultima, the Feared', capture: false }, + delaySeconds: 2, + durationSeconds: 7, + promise: async (data) => { + const actors = (await callOverlayHandler({ + call: 'getCombatants', + })).combatants; + const orbs = actors.filter((actor) => actor.BNpcID === 18714 && actor.ModelStatus === 0); + // const visibleOrbs = orbs.filter((orb) => orb.ModelStatus === 0); + // const search = (visibleOrbs.length === 0) ? orbs : visibleOrbs; + // console.info(JSON.stringify(orbs)); + // console.info('visible', JSON.stringify(visibleOrbs)); + orbs.forEach((orb) => { + const y = Number(orb.PosY); + if (floatNear(y, 784)) + data.omegaOrbs.push('north'); + else if (floatNear(y, 800)) + data.omegaOrbs.push('middle'); + else if (floatNear(y, 816)) + data.omegaOrbs.push('south'); + }); + // console.info(`Omega, the One Energy Orb: ${data.omegaOrbs.join(', ')}`); + }, + infoText: (data, _matches, output) => { + if (data.omegaOrbs.length === 1 && data.omegaManaScreens.length === 0 && data.omegaOrbs[0]) + // just one energy orb going off + return output.avoidLaserDir!({ dir: output[data.omegaOrbs[0]]!() }); + else if (data.omegaOrbs.length === 2 && data.omegaManaScreens.length === 0) + // 2 orbs is always middle + return output.middle!(); + else if (data.omegaOrbs.length === 1 && data.omegaManaScreens.length === 1) { + // simple 1 orb/1 screen pattern, just opposite corner really + const loc = data.omegaManaScreens[0]!; + if (data.omegaOrbs[0] === 'north' && loc === 'neB') { + return output.getLocation!({ dir: output.backRight!() }); + } else if (data.omegaOrbs[0] === 'south' && loc === 'seC') { + return output.getLocation!({ dir: output.backLeft!() }); + } + } else if (data.omegaOrbs.length === 1 && data.omegaManaScreens.length === 3) { + // 3 screen pattern + const key = data.omegaManaScreens.sort().join(','); + const patterns = OmegaManaScreenPatterns[key]; + if (patterns !== undefined) { + const call = patterns[data.omegaOrbs[0]!]; + if (call !== undefined) + return output.getLocation!({ dir: output[call]!() }); + } + } + console.error(`Second Walk Omega, the One Energy Orb: unknown pattern +${data.omegaOrbs.join(', ')} ${data.omegaManaScreens.join(', ')}`); + return `UNKNOWN PATTERN ${data.omegaManaScreens.join(',')}`; // TODO: Remove me + // return output.avoid!(); + }, + outputStrings: { + avoid: { + en: 'Avoid lasers', + }, + avoidLaserDir: { + en: 'Avoid ${dir} laser', + }, + getLocation: { + en: '${dir}', + }, + getMiddle: { + en: 'Get Middle', + }, + frontLeft: { + en: 'Front Left', + de: 'Vorne Links', + fr: 'Avant Gauche', + ja: '前左', + cn: '左前', + ko: '앞 왼쪽', + }, + frontMiddle: { + en: 'Front Middle', + }, + frontRight: { + en: 'Front Right', + de: 'Vorne Rechts', + fr: 'Avant Droit', + ja: '前右', + cn: '右前', + ko: '앞 오른쪽', + }, + backLeft: { + en: 'Back Left', + de: 'Hinten Links', + fr: 'Arrière Gauche', + ja: '後左', + cn: '左后', + ko: '뒤 왼쪽', + }, + backMiddle: { + en: 'Back Middle', + }, + backRight: { + en: 'Back Right', + de: 'Hinten Rechts', + fr: 'Arrière Droit', + ja: '後ろ右', + cn: '右后', + ko: '뒤 오른쪽', + }, + north: Outputs.left, + middle: Outputs.middle, + south: Outputs.right, + }, + }, + { + id: 'San dOria Second Walk Omega, the One Orb/Screen Cleanup', + type: 'Ability', + netRegex: { id: 'AD32', source: 'Energy Orb', capture: false }, + run: (data) => { + data.omegaOrbs = []; + data.omegaManaScreens = []; + }, + }, + { + id: 'San dOria Second Walk Omega, the One Hyper Pulse', + type: 'StartsUsing', + netRegex: { id: 'AD2F', source: 'Omega, the One', capture: false }, + infoText: (_data, _matches, output) => { + return output.outOfMiddle!(); + }, + outputStrings: { + outOfMiddle: { + en: 'Out of Middle', + }, + }, + }, + { + // targeted aoe drops in the direction it is moving + id: 'San dOria Second Walk Omega, the One Trajectory Projection', + type: 'HeadMarker', + netRegex: { id: ['0269', '026A', '026B', '026C'], capture: true }, + condition: Conditions.targetIsYou(), + countdownSeconds: 8.9, + infoText: (_data, matches, output) => { + switch (matches.id) { + case '0269': + return output.droppingAoeDir!({ dir: output.east!() }); + case '026A': + return output.droppingAoeDir!({ dir: output.west!() }); + case '026B': + return output.droppingAoeDir!({ dir: output.south!() }); + case '026C': + return output.droppingAoeDir!({ dir: output.north!() }); + } + return Outputs.unknown; + }, + outputStrings: { + droppingAoeDir: { + en: 'Dropping aoe to your ${dir}, move opposite in', + }, + north: Outputs.north, + east: Outputs.east, + west: Outputs.west, + south: Outputs.south, + }, + }, + { + id: 'San dOria Second Walk Omega, the One Chemical Bomb', + type: 'StartsUsing', + netRegex: { id: 'AD0E', source: 'Ultima, the Feared', capture: false }, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Rotate away from proximity markers', + de: 'Weg rotieren von den Distanzmarkierungen', + fr: 'Tournez loin des marqueurs de proximité', + ja: '距離減衰マーカー 3発目から1発目に避ける', + cn: '远离距离衰减 AoE 落点', + ko: '회전하면서 거리감쇠 징 피하기', + }, + }, + }, + { + id: 'San dOria Second Walk Omega, the One Aft-to-fore Fire', + type: 'StartsUsing', + netRegex: { id: 'AD27', source: 'Omega, the One', capture: false }, + response: Responses.getFrontThenBack(), + }, + { + id: 'San dOria Second Walk Omega, the One Fore-to-aft Fire', + type: 'StartsUsing', + netRegex: { id: 'AD25', source: 'Omega, the One', capture: false }, + response: Responses.getBackThenFront(), + }, + { + id: 'San dOria Second Walk Omega, the One Tractor Beam', + type: 'StartsUsing', + netRegex: { id: 'AD06', source: 'Ultima, the Feared', capture: false }, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Go to west edge, avoid ship', + }, + }, + }, + { + // this might be too much, could be good though? + id: 'San dOria Second Walk Omega, the One Multi-missile', + type: 'StartsUsing', + netRegex: { id: 'AFEC', source: 'Omega, the One', capture: false }, + suppressSeconds: 1, + countdownSeconds: 3.9, + soundVolume: 0, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'ground AoEs go off', + }, + }, + }, + // ---------------------- + // Kam'lanaut + { + id: 'San dOria Second Walk Kam\'lanaut Enspirited Swordplay', + type: 'StartsUsing', + netRegex: { id: 'ACBD', source: 'Kam\'lanaut', capture: false }, + response: Responses.aoe(), + }, + { + id: 'San dOria Second Walk Kam\'lanaut Shockwave', + type: 'StartsUsing', + netRegex: { id: 'ACB3', source: 'Kam\'lanaut', capture: false }, + response: Responses.aoe('alert'), + }, + { + id: 'San dOria Second Walk Kam\'lanaut Empyreal Banish III', + type: 'HeadMarker', + netRegex: { id: '0178' }, + condition: Conditions.targetIsYou(), + response: Responses.spread(), + }, + { + id: 'San dOria Second Walk Kam\'lanaut Princely Blow', + type: 'HeadMarker', + netRegex: { id: '0265', capture: true }, + alertText: (data, matches, output) => { + // targets the boss itself unfortunately, so need to use data0 + const target = data.party?.idToName_?.[matches.data0]; + data.tankbusterTargets.push(target ?? ''); + if (data.me === target) + return output.tankBusterKnockBack!(); + }, + outputStrings: { + tankBusterKnockBack: { + en: 'Tank Buster + Knockback', + }, + }, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Princely Blow Not You', + type: 'HeadMarker', + netRegex: { id: '0265', capture: false }, + delaySeconds: 0.3, + suppressSeconds: 5, + infoText: (data, _matches, output) => { + if (data.tankbusterTargets.length === 0 || data.tankbusterTargets.includes(data.me)) + return; + + if (data.role === 'healer') + return output.tankBuster!(); + + return output.avoidTankCleaves!(); + }, + run: (data, _matches) => data.tankbusterTargets = [], + outputStrings: { + tankBuster: Outputs.tankBuster, + avoidTankCleaves: Outputs.avoidTankCleaves, + }, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Light Blade', + type: 'Ability', + netRegex: { id: 'ACAB', source: 'Kam\'lanaut', capture: false }, + alertText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Behind a sword', + }, + }, + }, + { + // ACAF - aoe under boss -> cleave + // ACAE - aoe under boss => cleave + stack + // ACB1 - cleave + // ACC0 - stack Empyreal Banish IV + id: 'San dOria Second Walk Kam\'lanaut Great Wheel', + type: 'Ability', + netRegex: { id: 'ACAF', source: 'Kam\'lanaut', capture: false }, + suppressSeconds: 1, + response: Responses.getBehind(), + }, + { + id: 'San dOria Second Walk Kam\'lanaut Great Wheel Stack', + type: 'Ability', + netRegex: { id: 'ACAE', source: 'Kam\'lanaut', capture: false }, + suppressSeconds: 1, + alertText: (_data, _matches, output) => output.behindStack!(), + outputStrings: { + behindStack: { + en: 'Get behind and Stack', + }, + }, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Empyreal Banish IV', + type: 'StartsUsing', + netRegex: { id: 'ACC0', source: 'Kam\'lanaut' }, + condition: Conditions.targetIsYou(), + infoText: (_data, _matches, output) => output.stackOnYou!(), + outputStrings: { + stackOnYou: Outputs.stackOnYou, + }, + }, + { + // AD01 Elemental Edge x6 aoe + // ACB5 big damage at end + id: 'San dOria Second Walk Kam\'lanaut Transcendent Union', + type: 'StartsUsing', + netRegex: { id: 'ACB4', source: 'Kam\'lanaut', capture: false }, + delaySeconds: 2, + durationSeconds: 9, + response: Responses.bigAoe('alarm'), + }, + { + id: 'San dOria Second Walk Kam\'lanaut Illumed Estoc', + type: 'StartsUsing', + netRegex: { id: 'ACBA', source: 'Kam\'lanaut' }, + infoText: (data, matches, output) => { + data.kamEstocHeadings.push(Number(matches.heading)); + if (data.kamEstocHeadings.length === 3) { + data.kamEstocHeadings = []; + return output.text!(); + } + }, + outputStrings: { + text: { + en: 'Dodge clone line AoEs on edge', // FEEDBACK: better wording? + }, + }, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Shield Bash', + type: 'StartsUsing', + netRegex: { id: 'ACBE', source: 'Kam\'lanaut', capture: false }, + alertText: (data, _matches, output) => { + if (data.kamEstocHeadings.length === 0) { + return output.knockbackAny!(); + } else if (data.kamEstocHeadings.length === 2) { + const allDirections: DirectionOutput8[] = ['dirN', 'dirSW', 'dirSE']; + const headingsAsDir = data.kamEstocHeadings.map((h) => + Directions.output8Dir[Directions.hdgTo8DirNum(h)] + ); + const call = allDirections.filter((x) => !headingsAsDir.includes(x))[0]!; + data.kamEstocHeadings = []; + return output.knockbackDir!({ dir: output[call]!() }); + } + }, + outputStrings: { + knockbackAny: { + en: 'Get knocked down long platform', + }, + knockbackDir: { + en: 'Get knocked down ${dir} platform', + }, + dirN: Outputs.north, + dirSW: Outputs.southwest, + dirSE: Outputs.southeast, + }, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Elemental Blade Buff Collect', + type: 'GainsEffect', + netRegex: { effectId: 'B9A' }, + durationSeconds: 1.5, + soundVolume: 0, + infoText: (data, matches, output) => { + const element = kamlanautElementBuffIds[matches.count]; + if (element === undefined) + throw new UnreachableCode(); + data.kamElements.push(element); + return output[element]!(); + }, + outputStrings: kamlanautElementalOutputStrings, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Elemental Blade Blade Collect', + type: 'StartsUsingExtra', + netRegex: { id: Object.keys(kamlanautSublimeBladeCasts) }, + run: (data, matches, _output) => { + const element = kamlanautSublimeBladeCasts[matches.id]; + if (element === undefined) + throw new UnreachableCode(); + data.kamElementalBlades[element] = { + x: parseFloat(matches.x), + y: parseFloat(matches.y), + }; + }, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Elemental Blade Cone Collect', + type: 'StartsUsingExtra', + netRegex: { id: Object.keys(kamlanautSublimeConeCasts) }, + run: (data, matches, _output) => { + const element = kamlanautSublimeConeCasts[matches.id]; + if (!element) + throw new UnreachableCode(); + + const dir = + Directions.output8Dir[Directions.hdgTo8DirNum(Number.parseFloat(matches.heading))]; + + if (isValidSiXDir(dir)) + data.kamElementalCones[dir] = element; + }, + }, + { + // for both pizza slice and cross line aoe elemental mechanics + id: 'San dOria Second Walk Kam\'lanaut Sublime Elements', + type: 'StartsUsing', + netRegex: { id: 'B00A', source: 'Kam\'lanaut', capture: false }, + delaySeconds: 0.5, + durationSeconds: 7, + alertText: (data, _matches, output) => { + // crossing line aoes, of which 2 or 3 expand + // console.info('elements:', data.kamElements); + // console.info('Blades:', data.kamElementalBlades); + // console.info('Cones:', data.kamElementalCones); + if (data.kamElementalBlades['fire'] !== undefined) { + const result = sublimeElementsBladeSafespot(data.kamElementalBlades, data.kamElements); + console.info(result); + if (result.length === 2) { + return output.nextToCross!({ + ele1: output[result[0]!]!(), + ele2: output[result[1]!]!(), + }); + } else if (result.length === 1) { + return output.nextToBlade!({ ele: output[result[0]!]!() }); + } + console.error('Sublime Blades: unknown pattern'); + return 'Error'; + } + // cone aoes from the boss, of which 2 or 3 expand + // Object.entries(data.kamElementalCones).forEach(([card, element]) => { + // data.kamElementalCones[card as KamConeDirection] = data.kamElements.includes(element as KamElement) ? 'BAD' : element; + // }); + const dirs = Object.keys(data.kamElementalCones) as KamSixDirection[]; + for (let i = 0; i < dirs.length; i++) { + const d1 = dirs[i]!; + const d2 = dirs[(i + 1) % dirs.length]!; + + const e1 = data.kamElementalCones[d1]!; + const e2 = data.kamElementalCones[d2]!; + // console.info(i, d1, d2); + // console.info(i, e1, e2); + if ( + !data.kamElements.includes(e1) && e1 !== null && !data.kamElements.includes(e2) && + e2 !== null + ) { + // console.info('>>>', e1, e2); + return output.betweenSlice!({ ele1: output[e1]!(), ele2: output[e2]!() }); + } + } + }, + outputStrings: { + betweenSlice: { + en: 'Between ${ele1} and ${ele2}', + }, + nextToBlade: { + en: 'Next to ${ele}', + }, + nextToCross: { + en: 'go to ${ele1} and ${ele2} intersection', // FEEDBACK: wording? + }, + ...kamlanautElementalOutputStrings, + }, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Sublime Elements Cleanup', + type: 'Ability', + netRegex: { id: 'B00A', source: 'Kam\'lanaut', capture: false }, + run: (data) => { + data.kamElements = []; + data.kamElementalCones = emptySixDirections(); + data.kamElementalBlades = {}; + }, + }, + { + id: 'San dOria Second Walk Kam\'lanaut Crystal Spawn Collect', + type: 'CombatantMemory', + netRegex: { + change: 'Add', + pair: [{ key: 'BNpcID', value: Object.keys(kamlanautCrystalNpcIds) }], + }, + run: (data, matches, _output) => { + const element = kamlanautCrystalNpcIds[matches.pairBNpcID ?? '']; + const x = Number.parseFloat(matches.pairPosX ?? '0'); + const y = Number.parseFloat(matches.pairPosY ?? '0'); + if (!element) + throw new UnreachableCode(); + const dir = Directions.output8Dir[Directions.xyTo8DirNum(x, y, -200.00, 150.0)]; + if (isValidSiXDir(dir)) + data.kamCrystalLocations[dir] = element; + }, + }, + { + // ACB7 - initial, shorter cast + id: 'San dOria Second Walk Kam\'lanaut Elemental Resonance (crystals)', + type: 'StartsUsingExtra', + netRegex: { id: ['ACB7', 'ACB8'] }, + preRun: (data, matches) => { + const x = Number.parseFloat(matches.x); + const y = Number.parseFloat(matches.y); + const dir = Directions.output8Dir[Directions.xyTo8DirNum(x, y, -200.00, 150.0)]; + if (isValidSiXDir(dir)) { + data.kamCrystalCasts.push(dir); + } + }, + alertText: (data, _matches, output) => { + const crystalCount = Object.keys(data.kamCrystalLocations).length; + // console.info('Crystals:', crystalCount); + console.info('Casts:', data.kamCrystalCasts); + // console.info('Locations:', data.kamCrystalLocations); + if (crystalCount === 3 && data.kamCrystalCasts.length === 1) { + // SIMPLE 3 CRYSTALS - only call which to avoid + const explodingCrystal = data.kamCrystalCasts[0]!; + const explodingEle = data.kamCrystalLocations[explodingCrystal]; + data.kamCrystalCasts = []; // reset for the next pattern + if (explodingEle) { + console.info('Exploding:', explodingCrystal); + return output.avoid!({ ele: output[explodingEle]!() }); + } + } else if (crystalCount === 6 && data.kamCrystalCasts.length === 2) { + // SIX CRYSTAL PATTERN + // get the index of two crystals exploding + // const temp = Array(100).fill('O'); + const explodingIndex1 = kamSixDirections.indexOf(data.kamCrystalCasts[0]!); + const explodingIndex2 = kamSixDirections.indexOf(data.kamCrystalCasts[1]!); + if (explodingIndex1 === -1 || explodingIndex2 === -1) { + console.error('Kam\'lanaut Elemental Resonance (crystals) - invalid crystals'); + return; + } + const directDist = Math.abs(explodingIndex1 - explodingIndex2); + console.info('Exp index:', explodingIndex1, explodingIndex2, directDist); + if (Math.min(directDist, 6 - directDist) === 3) { + // TWO SAFE SPOTS - crystals far apart + // crystals are farther apart, leaving 2 safe spots farthest from each crystal. + // safe spot = area between the crystals 1 and 2 away + const lastCrystal = Math.max(explodingIndex1, explodingIndex2); + const safe1 = data.kamCrystalLocations[kamSixDirections[(lastCrystal + 1) % 6]!]; + const safe2 = data.kamCrystalLocations[kamSixDirections[(lastCrystal + 2) % 6]!]; + console.info('Exploding 2spot:', lastCrystal, safe1, safe2); + console.info('Safe6:', safe1, safe2); + data.kamCrystalCasts = []; // reset + if (safe1 && safe2) + return output.betweenCrystals!({ ele1: output[safe1]!(), ele2: output[safe2]!() }); + } + // ONE SAFE SPOT - crystal AoEs overlapping + // crystals overlap, there is one large safe spot centered on a crystal + // safe spot = crystal 2 away + let safeIndex = (explodingIndex1 + 2) % 6; + if (safeIndex === explodingIndex1 || safeIndex === explodingIndex2) + safeIndex = (safeIndex + 2) % 6; + console.info('Exploding 1spot:', explodingIndex1, explodingIndex2, '->', safeIndex); + const safe = data.kamCrystalLocations[kamSixDirections[safeIndex]!]; + data.kamCrystalCasts = []; // reset + if (safe) + return output.safeCrystal!({ ele: output[safe]!() }); + } + }, + outputStrings: { + betweenCrystals: { + en: 'Between ${ele1} and ${ele2} crystals', + }, + safeCrystal: { + en: 'Go to ${ele} crystal', + }, + avoid: { + en: 'Away from ${ele} crystal', + }, + ...kamlanautElementalOutputStrings, + }, + }, + { + // cleanup of crystals + id: 'San dOria Second Walk Kam\'lanaut Illumed Facet', + type: 'Ability', + netRegex: { id: 'ACB9', source: 'Kam\'lanaut', capture: false }, + delaySeconds: 3, + run: (data) => { + data.kamCrystalLocations = {}; + data.kamCrystalCasts = []; + }, + }, + // ---------------------- + // Eald'narche + { + id: 'San dOria Second Walk Eald\'narche Uranos Cascade', + type: 'StartsUsing', + netRegex: { id: 'AD52', source: 'Eald\'narche' }, + alertText: (data, matches, output) => { + if (matches.target === data.me) + return output.tankBusterOnYou!(); + }, + run: (data, matches) => data.tankbusterTargets.push(matches.target), + outputStrings: { + tankBusterOnYou: Outputs.tankBusterOnYou, + }, + }, + { + id: 'San dOria Second Walk Eald\'narche Uranos Cascade Not You', + type: 'StartsUsing', + netRegex: { id: 'AD52', source: 'Eald\'narche', capture: false }, + delaySeconds: 0.3, + suppressSeconds: 5, + infoText: (data, _matches, output) => { + if (data.tankbusterTargets.includes(data.me)) + return; + return output.tankBusters!(); + }, + run: (data) => data.tankbusterTargets = [], + outputStrings: { + tankBusters: Outputs.tankBusters, + }, + }, + { + id: 'San dOriea Second Walk Eald\'narche Cronos Sling Out + Right', + type: 'StartsUsing', + netRegex: { id: 'AD49', source: 'Eald\'narche', capture: false }, + alertText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Out => Right', + }, + }, + }, + { + id: 'San dOria Second Walk Eald\'narche Cronos Sling Out + Left', + type: 'StartsUsing', + netRegex: { id: 'AD4A', source: 'Eald\'narche', capture: false }, + alertText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Out => Left', + }, + }, + }, + { + id: 'San dOria Second Walk Eald\'narche Cronos Sling In + Right', + type: 'StartsUsing', + netRegex: { id: 'AD4B', source: 'Eald\'narche', capture: false }, + alertText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'In => Right', + }, + }, + }, + { + id: 'San dOria Second Walk Eald\'narche Cronos Sling In + Left', + type: 'StartsUsing', + netRegex: { id: 'AD4C', source: 'Eald\'narche', capture: false }, + alertText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'In => Left', + }, + }, + }, + { + id: 'San dOria Second Walk Eald\'narche Warp', + type: 'StartsUsing', + netRegex: { id: 'AD56', source: 'Eald\'narche', capture: false }, + alertText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Follow Warp => Get Behind', + }, + }, + }, + { + id: 'San dOria Second Walk Eald\'narche Empyreal Vortex', + type: 'StartsUsing', + netRegex: { id: 'AD6D', source: 'Eald\'narche', capture: false }, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'AoE x5', + }, + }, + }, + + // ---------------------- + // Adds + { + id: 'San dOria Second Walk Detector Electroswipe', + type: 'StartsUsing', + netRegex: { id: 'AA27', source: 'Detector' }, + suppressSeconds: 5, + response: Responses.interruptIfPossible('info'), + }, + ], + timelineReplace: [], +}; + +export default triggerSet; diff --git a/ui/raidboss/data/07-dt/alliance/san-doria-second-walk.txt b/ui/raidboss/data/07-dt/alliance/san-doria-second-walk.txt new file mode 100644 index 00000000000..6fc46952b65 --- /dev/null +++ b/ui/raidboss/data/07-dt/alliance/san-doria-second-walk.txt @@ -0,0 +1,668 @@ +### SAN D'ORIA: THE SECOND WALK +# ZoneId: 1304 + +hideall "--Reset--" +hideall "--sync--" + +0.0 "--Reset--" ActorControl { command: "4000000F" } window 0,1000000 jump 0 + +# .*is no longer sealed +0.0 "--Reset--" SystemLogMessage { id: "7DE" } window 0,1000000 jump 0 + +#~~~~~~~~~~~~~~~~~~# +# Faithbound Kirin # +#~~~~~~~~~~~~~~~~~~# + +# -ic "Alxaal" +# -ii ADCD + +# The Highland Battlefield will be sealed off +10000.0 "--sync--" SystemLogMessage { id: "7DC", param1: "148C" } window 10000,1 +10007.2 "--sync--" StartsUsing { id: "ADCA", source: "Faithbound Kirin" } window 10007.4,10 +10012.1 "Stonega IV" Ability { id: "ADCA", source: "Faithbound Kirin" } + +# Wrought Arms 1 (Tutorial) +10022.8 "Wrought Arms" Ability { id: "AD91", source: "Faithbound Kirin" } +10033.7 "Synchronized Strike" Ability { id: "AD95", source: "Faithbound Kirin" } +10034.4 "--sync--" Ability { id: "AD96", source: "Faithbound Kirin" } +10038.8 "Synchronized Smite" Ability { id: ["AD9B", "AD9C"], source: "Sculpted Arm" } +10045.8 "Synchronized Strike" Ability { id: "AD95", source: "Faithbound Kirin" } +10046.5 "--sync--" Ability { id: "AD96", source: "Faithbound Kirin" } +10050.9 "Synchronized Smite" Ability { id: ["AD9B", "AD9C"], source: "Sculpted Arm" } +10061.7 "Crimson Riddle" Ability { id: ["AFF4", "AFF5"], source: "Faithbound Kirin" } +10068.8 "Crimson Riddle" Ability { id: ["AFF4", "AFF5"], source: "Faithbound Kirin" } + +# Shijin Summoning +# +# The Combatants get added at the start of the fight, so we can't sync to +# the AddedCombatant line. Additionally, the summons do not appear to "cast" +# actions, so we can't sync to the first cast ability they use. +10083.0 "Summon Shijin" Ability { id: "AD7E", source: "Faithbound Kirin" } +10085.0 "--sync--" GameLog { code: "0044", line: "O Suzaku, conjure your infernal flames!" } jump "kirin-shijin-suzaku" +10085.0 "--sync--" GameLog { code: "0044", line: "O Genbu, entomb in rock and earth!" } jump "kirin-shijin-genbu" + +# Sunbound Suzaku +11000.0 label "kirin-shijin-suzaku" +11007.2 "Sun Powder" Ability { id: "AD89", source: "Sunbound Suzaku" } +11015.2 "Vermilion Flight" Ability { id: "AD8A", source: "Sunbound Suzaku" } +11018.3 "Arm of Purgatory" #Ability { id: "AEFC", source: "Ball of Fire" } +11018.3 "Arm of Purgatory" #Ability { id: "AEFC", source: "Ball of Fire" } +11018.7 "Vermilion Flight" Ability { id: "AEFB", source: "Sunbound Suzaku" } +11018.7 "Arm of Purgatory" Ability { id: "AEFA", source: "Sunbound Suzaku" } +11022.6 "Sun Powder" Ability { id: "AD89", source: "Sunbound Suzaku" } +11030.3 "Stonega III" Ability { id: "B079", source: "Faithbound Kirin" } +11030.5 "Vermilion Flight" Ability { id: "AD8A", source: "Sunbound Suzaku" } +11033.6 "Arm of Purgatory" Ability { id: "AEFC", source: "Ball of Fire" } +11033.9 "Vermilion Flight" Ability { id: "AEFB", source: "Sunbound Suzaku" } +11033.9 "Arm of Purgatory" Ability { id: "AEFA", source: "Sunbound Suzaku" } +11038.1 "Stonega III" Ability { id: "B07A", source: "Faithbound Kirin" } +11044.2 "--sync--" StartsUsing { id: "AD91", source: "Faithbound Kirin" } window 10,10 forcejump "kirin-wrought-arms-2" + +# Dawnbound Seiryu +12000.0 label "kirin-shijin-seiryu" + +# Moonbound Genbu +13000.0 label "kirin-shijin-genbu" +13010.2 "Shattering Stomp" Ability { id: "AD84", source: "Moonbound Genbu" } +13020.4 "Moontide Font" Ability { id: "AD86", source: "Moonbound Genbu" } +13025.4 "Moontide Font" Ability { id: "AD86", source: "Moonbound Genbu" } +13030.2 "Midwinter March" Ability { id: "AD87", source: "Moonbound Genbu" } +13031.2 "--sync--" Ability { id: "AD31", source: "Moonbound Genbu" } +13036.3 "Northern Current" Ability { id: "AD88", source: "Moonbound Genbu" } +13041.6 "Crimson Riddle" Ability { id: ["AFF4", "AFF5"], source: "Faithbound Kirin" } +13049.0 "--sync--" StartsUsing { id: "AD91", source: "Faithbound Kirin" } window 10,10 forcejump "kirin-wrought-arms-2" + +# Duskbound Byakko +14000.0 label "kirin-shijin-byakko" + +# Wrought Arms 2 +15000.0 label "kirin-wrought-arms-2" +15000.0 "--sync---" StartsUsing { id: "AD91", source: "Faithbound Kirin" } window 3950,1 +15003.3 "Wrought Arms" Ability { id: "AD91", source: "Faithbound Kirin" } +15011.7 "Wringer" Ability { id: "AD92", source: "Faithbound Kirin" } +15016.7 "Dead Wringer" Ability { id: ["AD97", "AD98"], source: "Sculpted Arm" } +15026.3 "Striking Left/Striking Right" Ability { id: ["AD93", "AD94"], source: "Faithbound Kirin" } +15031.3 "Smiting Left/Right" Ability { id: ["AD99", "AD9A"], source: "Sculpted Arm" } +15036.5 "Stonega IV" Ability { id: "ADCA", source: "Faithbound Kirin" } + +# The boss and hands will do an extremely large number of possible sequences +# which are difficult to split into separate timeline segments, due to the +# sheer number of combinations and overlap between casts. The timeline +# matching doesn't handle this very well. Instead, just show a duration +# line with an estimated length... +15042.3 "--synchronized sequence--" duration 20 + +# Adds Phase +15500.0 label "kirin-chiseled-arms" +15500.0 "--sync--" StartsUsing { id: "ADB1", source: "Faithbound Kirin" } window 500,1 +15506.9 "Mighty Grip" Ability { id: "ADB1", source: "Faithbound Kirin" } +15517.7 "Shockwave" Ability { id: "ADC0", source: "Chiseled Arm" } +15526.7 "Shockwave" Ability { id: "ADC0", source: "Chiseled Arm" } +15527.7 "Deadly Hold" Ability { id: "ADB2", source: "Faithbound Kirin" } +15535.9 "--sync--" Ability { id: "ADB4", source: "Faithbound Kirin" } +# Both Chiseled Arms must be destroyed before this cast finishes +15539.1 "Kirin Captivator" StartsUsing { id: "ADB3", source: "Faithbound Kirin" } duration 29.7 +15541.1 "Shockwave" Ability { id: "ADC0", source: "Chiseled Arm" } +15550.1 "Shockwave" Ability { id: "ADC0", source: "Chiseled Arm" } + +# TODO: +# Can we sync to the enrage canceling or adds dying? +16000.0 label "kirin-wrought-arms-3" +16000.0 "--sync--" StartsUsing { id: "AD91", source: "Faithbound Kirin" } window 395,1 +16003.5 "Wrought Arms" Ability { id: "AD91", source: "Faithbound Kirin" } + +# From this point, its extremely unclear from logs what the boss will do. It +# repeats mechanics until you kill it. Wiki says that another Shijin can be +# summoned, but I don't have logs of that. I don't know how to make a +# timeline of this... +16011.5 "--mechanics repeat...-" duration 120 +16011.5 "--goodluck!--" duration 120 + +# ALL ENCOUNTER ABILITIES +# 366 attack +# AA33 Savage Blade +# AA34 Vorpal Blade +# AA35 Spirits Within +# AC05 --sync-- +# AD7E Summon Shijin +# AD89 Sun Powder +# AD8A Vermilion Flight +# AD91 Wrought Arms +# AD92 Wringer +# AD94 Striking Left +# AD95 Synchronized Strike +# AD96 Synchronized Strike +# AD97 Dead Wringer +# AD98 Dead Wringer +# AD9A Smiting Left +# AD9B Synchronized Smite +# AD9C Synchronized Smite +# AD9F Smiting Left Sequence +# ADA0 Synchronized Sequence +# ADA1 Synchronized Sequence +# ADA2 Wringer +# ADA3 Striking Right +# ADA7 Dead Wringer +# ADA8 Dead Wringer +# ADA9 Smiting Right +# ADAD Wringer +# ADAE Striking Right +# ADAF Striking Left +# ADB0 Synchronized Strike +# ADB1 Mighty Grip +# ADB2 Deadly Hold +# ADB4 --sync-- +# ADB5 Deadly Hold +# ADB6 Deadly Hold +# ADB7 --sync-- +# ADB8 --sync-- +# ADB9 --sync-- +# ADBA --sync-- +# ADBF Bury +# ADC0 Shockwave +# ADCA Stonega IV +# ADCD --sync-- +# AEFA Arm of Purgatory +# AEFB Vermilion Flight +# AEFC Arm of Purgatory +# AF80 Deadly Hold +# AFF4 Crimson Riddle +# AFF5 Crimson Riddle +# B079 Stonega III +# B07A Stonega III +# B0FA attack + +#~~~~~~~~~~~~~~~~# +# Ultima & Omega # +#~~~~~~~~~~~~~~~~# + +# -ii AD1D AD2C AD30 +# -ic "Alxaal" + +# Armada Airship will be sealed off +20000.0 "--sync--" SystemLogMessage { id: "7DC", param1: "14B2" } window 20000,1 +20005.2 "--sync--" StartsUsing { id: "AD2B", source: "Omega, the One" } window 20005.2,10 +20011.7 "Ion Efflux" Ability { id: "AD2B", source: "Omega, the One" } +20015.5 "--sync--" Ability { id: "AD10", source: "Ultima, the Feared" } +20016.5 "Antimatter" Ability { id: "AD11", source: "Ultima, the Feared" } +20020.6 "Energy Orb" Ability { id: "AD08", source: "Ultima, the Feared" } +20028.8 "Energy Ray" Ability { id: "AD32", source: "Energy Orb" } +20031.8 "Aft-to-fore Fire/Fore-to-aft Fire" Ability { id: ["AD25", "AD27"], source: "Omega, the One" } +20032.3 "Omega Blaster" Ability { id: "AD29", source: "Omega, the One" } +20033.9 "Foreward Blaster/Aftward Blaster" Ability { id: ["AD26", "AD28"], source: "Omega, the One" } +20034.7 "Omega Blaster" Ability { id: "AD2A", source: "Omega, the One" } +20048.3 "Tractor Beam" Ability { id: "AD06", source: "Ultima, the Feared" } +20048.6 "Anti-personnel Missile" Ability { id: "B087", source: "Omega, the One" } +20048.8 "Crash" Ability { id: "AD07", source: "Ultima, the Feared" } +20048.8 "Tractor Beam" #Ability { id: "B086", source: "Ultima, the Feared" } +20053.6 "Anti-personnel Missile" Ability { id: "B088", source: "Omega, the One" } +20065.9 "Surface Missile" Ability { id: "B075", source: "Omega, the One" } +20066.9 "Surface Missile" #Ability { id: "B076", source: "Omega, the One" } +20067.9 "Energy Orb" Ability { id: "AD08", source: "Ultima, the Feared" } +20069.0 "Surface Missile" #Ability { id: "B076", source: "Omega, the One" } +20071.0 "Surface Missile" #Ability { id: "B076", source: "Omega, the One" } +20075.2 "Anti-personnel Missile" Ability { id: "B087", source: "Omega, the One" } +20076.2 "Energy Ray" Ability { id: "AD32", source: "Energy Orb" } +20080.2 "Anti-personnel Missile" #Ability { id: "B088", source: "Omega, the One" } +20080.2 "Anti-personnel Missile" #Ability { id: "B088", source: "Omega, the One" } +20083.3 "Mana Screen" Ability { id: "AD09", source: "Ultima, the Feared" } +20088.4 "Energy Orb" Ability { id: "AD08", source: "Ultima, the Feared" } +20096.6 "Energy Ray" Ability { id: "AD32", source: "Energy Orb" } +20097.4 "Energy Ray" #Ability { id: "AD0D", source: "Ultima, the Feared" } +20102.1 "Trajectory Projection" Ability { id: "AD23", source: "Omega, the One" } +20112.8 "Guided Missile" Ability { id: "AD24", source: "Omega, the One" } +20118.3 "--untargetable--" Ability { id: "AD12", source: "Ultima, the Feared" } +20118.4 "--jump--" Ability { id: "AD2C", source: "Omega, the One" } + +# Jump from the airship before it's reduced to ash! +20118.4 "Tractor Field" Ability { id: "AD12", source: "Ultima, the Feared" } +20118.8 "Tractor Field" Ability { id: "AD13", source: "Ultima, the Feared" } +20123.7 "Multi-missile" Ability { id: "AFEB", source: "Omega, the One" } +20123.7 "Citadel Siege" Ability { id: "AD14", source: "Ultima, the Feared" } +20125.5 "Multi-missile" Ability { id: "AFED", source: "Omega, the One" } +20125.6 "Multi-missile" Ability { id: "AFEC", source: "Omega, the One" } +20127.7 "Citadel Siege" Ability { id: "AD15", source: "Ultima, the Feared" } +20127.8 "Multi-missile" Ability { id: "AFEB", source: "Omega, the One" } +20128.6 "Citadel Siege" Ability { id: "AD18", source: "Ultima, the Feared" } +20129.6 "Multi-missile" Ability { id: "AFED", source: "Omega, the One" } +20129.7 "Multi-missile" Ability { id: "AFEC", source: "Omega, the One" } +20131.7 "Citadel Siege" Ability { id: "AD16", source: "Ultima, the Feared" } +20132.0 "Multi-missile" Ability { id: "AFEB", source: "Omega, the One" } +20132.7 "Citadel Siege" Ability { id: "AD18", source: "Ultima, the Feared" } +20133.9 "Multi-missile" Ability { id: "AFED", source: "Omega, the One" } +20134.0 "Multi-missile" Ability { id: "AFEC", source: "Omega, the One" } +20135.7 "Citadel Siege" Ability { id: "AD17", source: "Ultima, the Feared" } +20136.3 "Multi-missile" Ability { id: "AFEB", source: "Omega, the One" } +20136.7 "Citadel Siege" Ability { id: "AD18", source: "Ultima, the Feared" } +20138.1 "Multi-missile" Ability { id: "AFED", source: "Omega, the One" } +20138.2 "Multi-missile" #Ability { id: "AFEC", source: "Omega, the One" } +20138.2 "Multi-missile" #Ability { id: "AFEC", source: "Omega, the One" } +20140.6 "Citadel Siege" Ability { id: "AD18", source: "Ultima, the Feared" } +20145.8 "--ultima targetable--" +20152.7 "Citadel Buster" Ability { id: "AD1B", source: "Ultima, the Feared" } +20158.6 "Hyper Pulse" Ability { id: "AD2F", source: "Omega, the One" } +20160.8 "--omega targetable--" +20171.2 "--jump--" Ability { id: "AD2C", source: "Omega, the One" } + +# Phase 2 +20175.8 label "ultima-omega-p2-loop" +20175.8 "Tractor Beam" Ability { id: "AD06", source: "Ultima, the Feared" } +20176.2 "Crash" Ability { id: "AD07", source: "Ultima, the Feared" } +20176.2 "Tractor Beam" #Ability { id: "B086", source: "Ultima, the Feared" } +20176.4 "Trajectory Projection" Ability { id: "AD23", source: "Omega, the One" } +20187.0 "Mana Screen" Ability { id: "AD09", source: "Ultima, the Feared" } +20187.1 "Guided Missile" #Ability { id: "AD24", source: "Omega, the One" } +20192.1 "Energy Orb" Ability { id: "AD08", source: "Ultima, the Feared" } +20200.3 "Energy Ray" Ability { id: "AD32", source: "Energy Orb" } +20201.1 "Energy Ray" #Ability { id: "AD0C", source: "Ultima, the Feared" } +20201.4 "Anti-personnel Missile" Ability { id: "B087", source: "Omega, the One" } +20201.6 "Energy Ray" Ability { id: "AD0B", source: "Ultima, the Feared" } +20206.4 "Anti-personnel Missile" Ability { id: "B088", source: "Omega, the One" } +20215.5 "Chemical Bomb" Ability { id: "AD0F", source: "Ultima, the Feared" } +20218.5 "Chemical Bomb" Ability { id: "AD0F", source: "Ultima, the Feared" } +20221.5 "Chemical Bomb" Ability { id: "AD0F", source: "Ultima, the Feared" } +20224.5 "Chemical Bomb" Ability { id: "AD0F", source: "Ultima, the Feared" } +20233.1 "Surface Missile" Ability { id: "B075", source: "Omega, the One" } +20234.1 "Surface Missile" #Ability { id: "B076", source: "Omega, the One" } +20236.3 "Energy Orb" Ability { id: "AD08", source: "Ultima, the Feared" } +20236.3 "Surface Missile" #Ability { id: "B076", source: "Omega, the One" } +20238.3 "Surface Missile" #Ability { id: "B076", source: "Omega, the One" } +20244.1 "Aft-to-fore Fire/Fore-to-aft Fire" Ability { id: ["AD25", "AD27"], source: "Omega, the One" } +20244.5 "Energy Ray" Ability { id: "AD32", source: "Energy Orb" } +20244.6 "Omega Blaster" Ability { id: "AD29", source: "Omega, the One" } +20246.3 "Foreward Blaster/Aftward Blaster" Ability { id: ["AD26", "AD28"], source: "Omega, the One" } +20247.1 "Omega Blaster" Ability { id: "AD2A", source: "Omega, the One" } +20263.1 "Ion Efflux" Ability { id: "AD2B", source: "Omega, the One" } +20274.8 "Antimatter" Ability { id: "AD10", source: "Ultima, the Feared" } +20275.8 "Antimatter" Ability { id: "AD11", source: "Ultima, the Feared" } +20293.8 "Tractor Beam" Ability { id: "AD06", source: "Ultima, the Feared" } window 30,30 forcejump "ultima-omega-p2-loop" +20342.7 "Chemical Bomb" Ability { id: "AD0F", source: "Ultima, the Feared" } + +# IGNORED ABILITIES +# AD1D --sync-- +# AD2C --sync-- +# AD30 Energizing Equilibrium + +# ALL ENCOUNTER ABILITIES +# AD06 Tractor Beam +# AD07 Crash +# AD08 Energy Orb +# AD09 Mana Screen +# AD0B Energy Ray +# AD0C Energy Ray +# AD0D Energy Ray +# AD0E Chemical Bomb +# AD0F Chemical Bomb +# AD10 Antimatter +# AD11 Antimatter +# AD12 Tractor Field +# AD13 Tractor Field +# AD14 Citadel Siege +# AD15 Citadel Siege +# AD16 Citadel Siege +# AD17 Citadel Siege +# AD18 Citadel Siege +# AD1B Citadel Buster +# AD1C Energizing Equilibrium +# AD1D --sync-- +# AD23 Trajectory Projection +# AD24 Guided Missile +# AD25 Fore-to-aft Fire +# AD26 Foreward Blaster +# AD27 Aft-to-fore Fire +# AD28 Aftward Blaster +# AD29 Omega Blaster +# AD2A Omega Blaster +# AD2B Ion Efflux +# AD2C --sync-- +# AD2F Hyper Pulse +# AD30 Energizing Equilibrium +# AD32 Energy Ray +# AFEB Multi-missile +# AFEC Multi-missile +# AFED Multi-missile +# B075 Surface Missile +# B076 Surface Missile +# B086 Tractor Beam +# B087 Anti-personnel Missile +# B088 Anti-personnel Missile +# B0FC attack + +#~~~~~~~~~~~~~~~~~# +# Stellar Fulcrum # +#~~~~~~~~~~~~~~~~~# + +# The Stellar Fulcrum will be sealed off +30000.0 "--sync--" SystemLogMessage { id: "7DC", param1: "1488" } window 30000,1 +30006.0 "--sync--" StartsUsing { id: "ACBD", source: "Kam'lanaut" } window 30006,1 +30011.1 "Enspirited Swordplay" Ability { id: "ACBD", source: "Kam'lanaut" } +30014.3 "--sync--" Ability { id: "ACC1", source: "Kam'lanaut" } +30019.5 "Proving Ground" Ability { id: "B009", source: "Kam'lanaut" } +30024.7 "Elemental Blade" StartsUsing { id: "AC91", source: "Kam'lanaut" } duration 7.7 +30026.6 "--first charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30030.1 "--second charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30032.6 "--sync--" Ability { id: "AC91", source: "Kam'lanaut" } +30043.7 "Sublime Elements" Ability { id: "B00A", source: "Kam'lanaut" } +30046.9 "Elemental Blade" StartsUsing { id: "AC91", source: "Kam'lanaut" } duration 7.7 +30048.8 "--first charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30052.3 "--second charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30054.8 "--sync--" Ability { id: "AC91", source: "Kam'lanaut" } +30065.9 "Sublime Elements" Ability { id: "B00A", source: "Kam'lanaut" } +# TODO: Check which ablity hurts? +30076.2 "--sync--" Ability { id: "ACBB", source: "Kam'lanaut" } +30077.2 "Princely Blow" Ability { id: "ACBC", source: "Kam'lanaut" } +30082.3 "Light Blade" Ability { id: "ACAB", source: "Kam'lanaut" } +30088.3 "Sublime Estoc" #Ability { id: "ACAC", source: "Sublime Estoc" } +30088.3 "Sublime Estoc" #Ability { id: "ACAC", source: "Sublime Estoc" } +30091.4 "Great Wheel" Ability { id: ["ACAF", "ACB0"], source: "Kam'lanaut" } +30097.3 "Great Wheel" Ability { id: "ACB1", source: "Kam'lanaut" } +30104.5 "Enspirited Swordplay" Ability { id: "ACBD", source: "Kam'lanaut" } +30111.6 "--sync--" Ability { id: "ACC1", source: "Kam'lanaut" } + +# Phase Transition +# TODO: Add --untargettable--?? and maybe a duration? +30124.9 "Esoteric Scrivening" Ability { id: "ACB2", source: "Kam'lanaut" } +30130.0 "--sync--" Ability { id: "AD79", source: "Kam'lanaut" } +30143.1 "--sync--" Ability { id: "AD7A", source: "Kam'lanaut" } +30148.3 "Shockwave" Ability { id: "ACB3", source: "Kam'lanaut" } +30148.3 "--sync--" Ability { id: "A2FF", source: "Kam'lanaut" } +30156.9 "Transcendent Union" Ability { id: "ACB4", source: "Kam'lanaut" } +30157.9 "Elemental Edge" #Ability { id: "AD01", source: "Kam'lanaut" } +30158.2 "Elemental Edge" #Ability { id: "AD01", source: "Kam'lanaut" } +30158.5 "Elemental Edge" #Ability { id: "AD01", source: "Kam'lanaut" } +30158.9 "Elemental Edge" #Ability { id: "AD01", source: "Kam'lanaut" } +30159.3 "Elemental Edge" #Ability { id: "AD01", source: "Kam'lanaut" } +30160.0 "Elemental Edge" #Ability { id: "AD01", source: "Kam'lanaut" } +30163.4 "Transcendent Union" Ability { id: "ACB5", source: "Kam'lanaut" } +30174.2 "--sync--" Ability { id: "ACC1", source: "Kam'lanaut" } + +# Phase 2 +30179.4 "Esoteric Palisade" Ability { id: "ACB6", source: "Kam'lanaut" } +30185.5 "Crystalline Resonance" Ability { id: "ACB7", source: "Kam'lanaut" } +30193.4 "Elemental Resonance" Ability { id: "ACB8", source: "Kam'lanaut" } +30200.4 "Elemental Resonance" Ability { id: "ACB8", source: "Kam'lanaut" } +30207.4 "Elemental Resonance" Ability { id: "ACB8", source: "Kam'lanaut" } +30207.6 "Illumed Facet" Ability { id: "ACB9", source: "Kam'lanaut" } +30207.6 "Empyreal Banish III" #Ability { id: "ACBF", source: "Kam'lanaut" } +30218.5 "Illumed Estoc" Ability { id: "ACBA", source: "Kam'lanaut" } +30225.8 "Shield Bash" Ability { id: "ACBE", source: "Kam'lanaut" } +# TODO: check which of these matters +30234.9 "Empyreal Banish IV" Ability { id: "AF6B", source: "Kam'lanaut" } +30235.9 "Empyreal Banish IV" Ability { id: "ACC0", source: "Kam'lanaut" } +30245.2 "--sync--" Ability { id: "ACBB", source: "Kam'lanaut" } +30246.2 "Princely Blow" Ability { id: "ACBC", source: "Kam'lanaut" } +30255.4 "--sync--" Ability { id: "ACC1", source: "Kam'lanaut" } +30260.5 "Proving Ground" Ability { id: "B009", source: "Kam'lanaut" } +30263.7 "Elemental Blade" StartsUsing { id: "AC92", source: "Kam'lanaut" } duration 10.7 +30265.6 "--first charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30269.1 "--second charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30272.6 "--third charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30274.7 "--sync--" Ability { id: "AC92", source: "Kam'lanaut" } +30285.8 "Sublime Elements" Ability { id: "B00A", source: "Kam'lanaut" } +30292.9 "Light Blade" Ability { id: "ACAB", source: "Kam'lanaut" } +30298.9 "Sublime Estoc" #Ability { id: "ACAC", source: "Sublime Estoc" } +30298.9 "Sublime Estoc" #Ability { id: "ACAC", source: "Sublime Estoc" } +30298.9 "Empyreal Banish III" Ability { id: "ACBF", source: "Kam'lanaut" } +30302.0 "Great Wheel" Ability { id: ["ACAD", "ACAE", "ACAF", "ACB0"], source: "Kam'lanaut" } +30307.9 "Great Wheel" Ability { id: "ACB1", source: "Kam'lanaut" } +30308.0 "Empyreal Banish IV" Ability { id: "ACC0", source: "Kam'lanaut" } +30315.1 "Enspirited Swordplay" Ability { id: "ACBD", source: "Kam'lanaut" } +30322.3 "--sync--" Ability { id: "ACC1", source: "Kam'lanaut" } + +# Phase 2 Loop Start +30327.5 label "kamlanaut-loop" +30327.5 "Esoteric Palisade" Ability { id: "ACB6", source: "Kam'lanaut" } +30333.6 "Crystalline Resonance" Ability { id: "ACB7", source: "Kam'lanaut" } +30341.5 "Elemental Resonance" Ability { id: "ACB8", source: "Kam'lanaut" } +30348.5 "Elemental Resonance" Ability { id: "ACB8", source: "Kam'lanaut" } +30355.5 "Elemental Resonance" Ability { id: "ACB8", source: "Kam'lanaut" } +30358.7 "Light Blade" Ability { id: "ACAB", source: "Kam'lanaut" } +30364.7 "Sublime Estoc" #Ability { id: "ACAC", source: "Sublime Estoc" } +30364.7 "Sublime Estoc" #Ability { id: "ACAC", source: "Sublime Estoc" } +30364.7 "Empyreal Banish III" Ability { id: "ACBF", source: "Kam'lanaut" } +30371.5 "Elemental Resonance" Ability { id: "ACB8", source: "Kam'lanaut" } +30373.1 "Illumed Facet" Ability { id: "ACB9", source: "Kam'lanaut" } +30383.2 "Shield Bash" Ability { id: "ACBE", source: "Kam'lanaut" } +30384.0 "Illumed Estoc" Ability { id: "ACBA", source: "Kam'lanaut" } +30392.4 "Empyreal Banish IV" Ability { id: "AF6B", source: "Kam'lanaut" } +30393.4 "Empyreal Banish IV" Ability { id: "ACC0", source: "Kam'lanaut" } +30398.5 "Proving Ground" Ability { id: "B009", source: "Kam'lanaut" } +30401.7 "Elemental Blade" StartsUsing { id: "AC92", source: "Kam'lanaut" } duration 10.7 +30403.6 "--first charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30407.1 "--second charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30410.6 "--third charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30412.7 "--sync--" Ability { id: "AC92", source: "Kam'lanaut" } +30423.8 "Sublime Elements" Ability { id: "B00A", source: "Kam'lanaut" } +30431.9 "Enspirited Swordplay" Ability { id: "ACBD", source: "Kam'lanaut" } +30442.2 "--sync--" Ability { id: "ACBB", source: "Kam'lanaut" } +30443.2 "Princely Blow" Ability { id: "ACBC", source: "Kam'lanaut" } +30452.4 "--sync--" Ability { id: "ACC1", source: "Kam'lanaut" } +30457.5 "Proving Ground" Ability { id: "B009", source: "Kam'lanaut" } +30460.9 "Elemental Blade" StartsUsing { id: "AC92", source: "Kam'lanaut" } duration 10.7 +30462.6 "--first charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30466.1 "--second charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30469.6 "--third charge--" GainsEffect { effectId: "B9A", target: "Kam'lanaut" } +30471.6 "--sync--" Ability { id: "AC92", source: "Kam'lanaut" } +30482.7 "Sublime Elements" Ability { id: "B00A", source: "Kam'lanaut" } +30489.8 "Light Blade" Ability { id: "ACAB", source: "Kam'lanaut" } +30495.8 "Sublime Estoc" Ability { id: "ACAC", source: "Sublime Estoc" } +30495.8 "Empyreal Banish III" Ability { id: "ACBF", source: "Kam'lanaut" } +30498.9 "Great Wheel" Ability { id: ["ACAD", "ACAE", "ACAF", "ACB0"], source: "Kam'lanaut" } +30504.8 "Great Wheel" Ability { id: "ACB1", source: "Kam'lanaut" } +30504.9 "Empyreal Banish IV" Ability { id: "ACC0", source: "Kam'lanaut" } +30512.0 "Enspirited Swordplay" Ability { id: "ACBD", source: "Kam'lanaut" } +30519.2 "--sync--" Ability { id: "ACC1", source: "Kam'lanaut" } +30524.4 "Esoteric Palisade" Ability { id: "ACB6", source: "Kam'lanaut" } window 30,30 forcejump "kamlanaut-loop" + +# IGNORED ABILITIES +# AF4C --sync-- + +# ALL ENCOUNTER ABILITIES +# A2FF --sync-- +# AC91 Elemental Blade +# AC92 Elemental Blade +# AC93 Sublime Fire +# AC94 Sublime Earth +# AC95 Sublime Water +# AC97 Sublime Lightning +# AC98 Sublime Wind +# AC99 Sublime Fire +# AC9B Sublime Water +# AC9C Sublime Ice +# AC9D Sublime Lightning +# AC9F Fire Blade +# ACA0 Earth Blade +# ACA1 Water Blade +# ACA2 Ice Blade +# ACA3 Lightning Blade +# ACA4 Wind Blade +# ACA5 Fire Blade +# ACA6 Earth Blade +# ACA8 Ice Blade +# ACA9 Lightning Blade +# ACAA Wind Blade +# ACAB Light Blade +# ACAC Sublime Estoc +# ACAE Great Wheel +# ACAF Great Wheel +# ACB0 Great Wheel +# ACB1 Great Wheel +# ACB2 Esoteric Scrivening +# ACB3 Shockwave +# ACB4 Transcendent Union +# ACB5 Transcendent Union +# ACB6 Esoteric Palisade +# ACB7 Crystalline Resonance +# ACB8 Elemental Resonance +# ACB9 Illumed Facet +# ACBA Illumed Estoc +# ACBB Princely Blow +# ACBC Princely Blow +# ACBD Enspirited Swordplay +# ACBE Shield Bash +# ACBF Empyreal Banish III +# ACC0 Empyreal Banish IV +# ACC1 --sync-- +# AD01 Elemental Edge +# AD79 --sync-- +# AD7A --sync-- +# AF4C --sync-- +# AF6B Empyreal Banish IV +# B009 Proving Ground +# B00A Sublime Elements + +#~~~~~~~~~~~~~~~~~# +# Celestial Nexus # +#~~~~~~~~~~~~~~~~~# + +# -ii AD47 + +# Phase 1 +40000.0 "--sync--" SystemLogMessage { id: "7DC", param1: "148A" } window 40000,1 +40006.2 "--sync--" StartsUsing { id: "AD51", source: "Eald'narche" } window 40006.2,1 +40010.1 "--sync--" Ability { id: "AD51", source: "Eald'narche" } +40011.1 "Uranos Cascade" Ability { id: "AD52", source: "Eald'narche" } +40023.2 "Cronos Sling" Ability { id: ["AD49", "AD4A", "AD4B", "AD4C"], source: "Eald'narche" } +40023.6 "--sync--" Ability { id: ["AD4D", "AD4E"], source: "Eald'narche" } +40029.4 "Cronos Sling" Ability { id: ["AD4F", "AD50"], source: "Eald'narche" } +40039.7 "Empyreal Vortex" Ability { id: "AD6D", source: "Eald'narche" } duration 5.8 +40045.6 "--sync--" Ability { id: "AD70", source: "Eald'narche" } +40056.9 "Cronos Sling" Ability { id: ["AD49", "AD4A", "AD4B", "AD4C"], source: "Eald'narche" } +40057.3 "--sync--" Ability { id: ["AD4D", "AD4E"], source: "Eald'narche" } +40063.1 "Cronos Sling" Ability { id: ["AD4F", "AD50"], source: "Eald'narche" } +40070.4 "Warp" Ability { id: "AD56", source: "Eald'narche" } +40071.1 "--sync--" Ability { id: "AD48", source: "Eald'narche" } +40077.0 "Sleepga" Ability { id: "AD58", source: "Eald'narche" } +40079.1 "--sync--" Ability { id: "AD48", source: "Eald'narche" } +40084.4 "Gaea Stream" Ability { id: "AD53", source: "Eald'narche" } duration 11.1 +40090.6 "--sync--" StartsUsing { id: "AD5C", source: "Eald'narche" } window 5,5 +40094.5 "Omega Javelin" Ability { id: "AD5C", source: "Eald'narche" } +40095.6 "--sync--" Ability { id: "AD5D", source: "Eald'narche" } +40100.0 "Omega Javelin" Ability { id: "AD5E", source: "Eald'narche" } +40105.6 "Duplicate" Ability { id: "AD77", source: "Eald'narche" } duration 11.1 +40116.7 "--sync--" Ability { id: "AD78", source: "Eald'narche" } +40120.7 "Duplicate" Ability { id: "AD77", source: "Eald'narche" } duration 11.1 +40131.8 "--sync--" Ability { id: "AD78", source: "Eald'narche" } +40140.8 "--sync--" Ability { id: "AD48", source: "Eald'narche" } +40150.1 "Excelsior" Ability { id: "B040", source: "Eald'narche" } +40150.5 "--sync--" Ability { id: "AF17", source: "Eald'narche" } +40155.2 "Phase Shift" Ability { id: "AD59", source: "Eald'narche" } duration 22.2 +40155.4 "--sync--" Ability { id: "AD2E", source: "Eald'narche" } +40156.1 "--sync--" Ability { id: "AD5B", source: "Eald'narche" } +40177.4 "--sync--" Ability { id: "AD5A", source: "Eald'narche" } window 23.1,5 + +# Phase 2 Begins +40189.6 "Duplicate" Ability { id: "AD77", source: "Eald'narche" } duration 13.1 +40198.7 "Visions of Paradise" Ability { id: "AD75", source: "Eald'narche" } +40207.8 "Stellar Burst" Ability { id: "AD72", source: "Eald'narche" } +40207.8 "--sync--" Ability { id: "AD7D", source: "Eald'narche" } +40208.8 "Stellar Burst" Ability { id: "AD73", source: "Eald'narche" } +40215.5 "Stellar Burst" Ability { id: "AD74", source: "Eald'narche" } +40224.1 "--sync--" Ability { id: "AD48", source: "Eald'narche" } +# TODO: There are many variations of Ancient Triad which are not really +# worth creating branching timelines for. Just use a duration to indicate +# that mechanics are ongoing. Note that this duration likely isn't accurate +# for every variation, however the mechanics should mostly be done resolving +# by this time. +40232.4 "Ancient Triad" Ability { id: "AD5F", source: "Eald'narche" } duration 10.7 +40248.1 "Gaea Stream" Ability { id: "AD53", source: "Eald'narche" } duration 17 +40263.2 "--sync--" StartsUsing { id: "AD51", source: "Eald'narche" } window 15,5 +40266.9 "--sync--" Ability { id: "AD51", source: "Eald'narche" } +40267.9 "Uranos Cascade" Ability { id: "AD52", source: "Eald'narche" } +40274.0 "Duplicate" Ability { id: "AD77", source: "Eald'narche" } duration 13.1 +40283.1 "Visions of Paradise" Ability { id: "AD75", source: "Eald'narche" } + +# Phase 2 Loop +40292.2 label "ealdnarche-phase-2-loop" +40292.2 "Omega Javelin" Ability { id: "AD5C", source: "Eald'narche" } +40293.3 "--sync--" Ability { id: "AD5D", source: "Eald'narche" } +40295.3 "--sync--" Ability { id: "AD48", source: "Eald'narche" } +40297.7 "Omega Javelin" Ability { id: "AD5E", source: "Eald'narche" } +40300.6 "Gaea Stream" Ability { id: "AD53", source: "Eald'narche" } duration 17 +40313.7 "Cronos Sling" Ability { id: ["AD49", "AD4A", "AD4B", "AD4C"], source: "Eald'narche" } +40314.1 "--sync--" Ability { id: ["AD4D", "AD4E"], source: "Eald'narche" } +40319.8 "Cronos Sling" Ability { id: ["AD4F", "AD50"], source: "Eald'narche" } +40327.7 "Stellar Burst" Ability { id: "AD72", source: "Eald'narche" } +40327.7 "--sync--" Ability { id: "AD7D", source: "Eald'narche" } +40328.7 "Stellar Burst" Ability { id: "AD73", source: "Eald'narche" } +40335.4 "Stellar Burst" Ability { id: "AD74", source: "Eald'narche" } +40343.1 "--sync--" Ability { id: "AD48", source: "Eald'narche" } +40351.2 "Ancient Triad" Ability { id: "AD5F", source: "Eald'narche" } duration 10.7 +40359.9 "Duplicate" Ability { id: "AD77", source: "Eald'narche" } duration 13.1 +40369.1 "Visions of Paradise" Ability { id: "AD75", source: "Eald'narche" } +40373.2 "--sync--" Ability { id: "AD76", source: "Eald'narche" } +40377.2 "Empyreal Vortex" Ability { id: "AD6D", source: "Eald'narche" } duration 5.8 +40383.1 "--sync--" Ability { id: "AD70", source: "Eald'narche" } +40386.9 "Warp" Ability { id: "AD56", source: "Eald'narche" } +40387.6 "--sync--" Ability { id: "AD48", source: "Eald'narche" } +40393.5 "Sleepga" Ability { id: "AD58", source: "Eald'narche" } +40395.6 "--sync--" Ability { id: "AD48", source: "Eald'narche" } +40401.9 "Omega Javelin" Ability { id: "AD5C", source: "Eald'narche" } +40403.0 "--sync--" Ability { id: "AD5D", source: "Eald'narche" } +40407.4 "Omega Javelin" Ability { id: "AD5E", source: "Eald'narche" } +40412.0 "Cronos Sling" Ability { id: ["AD49", "AD4A", "AD4B", "AD4C"], source: "Eald'narche" } +40412.4 "--sync--" Ability { id: ["AD4D", "AD4E"], source: "Eald'narche" } +40418.2 "Cronos Sling" Ability { id: ["AD4F", "AD50"], source: "Eald'narche" } +40429.5 "--sync--" Ability { id: "AD51", source: "Eald'narche" } +40430.5 "Uranos Cascade" Ability { id: "AD52", source: "Eald'narche" } +40444.6 "Duplicate" Ability { id: "AD77", source: "Eald'narche" } duration 13.1 +40453.7 "Visions of Paradise" Ability { id: "AD75", source: "Eald'narche" } +40457.8 "--sync--" Ability { id: "AD76", source: "Eald'narche" } +40462.8 "Omega Javelin" Ability { id: "AD5C", source: "Eald'narche" } forcejump "ealdnarche-phase-2-loop" + +# IGNORED ABILITIES +# AD47 --sync-- + +# ALL ENCOUNTER ABILITIES +# AD2E Phase Shift +# AD35 Tornado +# AD47 --sync-- +# AD48 --sync-- +# AD49 Cronos Sling +# AD4B Cronos Sling +# AD4C Cronos Sling +# AD4D Cronos Sling +# AD4E Cronos Sling +# AD4F Cronos Sling +# AD50 Cronos Sling +# AD51 Uranos Cascade +# AD52 Uranos Cascade +# AD53 Gaea Stream +# AD54 Gaea Stream +# AD55 Gaea Stream +# AD56 Warp +# AD57 --sync-- +# AD58 Sleepga +# AD59 Phase Shift +# AD5A Phase Shift +# AD5B --sync-- +# AD5C Omega Javelin +# AD5D Omega Javelin +# AD5E Omega Javelin +# AD5F Ancient Triad +# AD60 Flare +# AD61 Flare +# AD64 Quake +# AD65 Freeze +# AD66 Flood +# AD67 Flood +# AD68 Flood +# AD69 Flood +# AD6A Flood +# AD6B Tornado +# AD6C Tornado +# AD6D Empyreal Vortex +# AD6E Empyreal Vortex +# AD6F Empyreal Vortex +# AD70 Empyreal Vortex +# AD71 Empyreal Vortex +# AD72 Stellar Burst +# AD73 Stellar Burst +# AD74 Stellar Burst +# AD75 Visions of Paradise +# AD76 Duplicate +# AD77 Duplicate +# AD78 Duplicate +# AD7D --sync-- +# AF17 --sync-- +# B040 Excelsior