diff --git a/ui/oopsyraidsy/data/06-ew/trial/golbez-ex.ts b/ui/oopsyraidsy/data/06-ew/trial/golbez-ex.ts index 0f30743873..b3c106f239 100644 --- a/ui/oopsyraidsy/data/06-ew/trial/golbez-ex.ts +++ b/ui/oopsyraidsy/data/06-ew/trial/golbez-ex.ts @@ -21,9 +21,12 @@ const triggerSet: OopsyTriggerSet = { 'GolbezEx Phases of the Blade 1': '86DB', // forward 180 cleave 'GolbezEx Phases of the Blade 2': '86F2', // backwards 180 cleave 'GolbezEx Arctic Assault': '8461', // ice walls hitting quadrants - 'GolbezEx Gale Sphere': '845A', // wind orb line aoes + 'GolbezEx Gale Sphere 1': '8458', // wind orb line aoes + 'GolbezEx Gale Sphere 2': '8459', // wind orb line aoes + 'GolbezEx Gale Sphere 3': '845A', // wind orb line aoes + 'GolbezEx Gale Sphere 4': '845B', // wind orb line aoes 'GolbezEx Phases of the Shadow 1': '86E7', // forward 180 cleave - 'GolbezEx Phases of the Shadow 2': '86EF', // forward 180 cleave + 'GolbezEx Phases of the Shadow 2': '86EF', // backwards 180 cleave 'GolbezEx Rising Beacon': '86EC', // "get out" during Phases of the Shadow 'GolbezEx Rising Ring': '86ED', // "get in" during Phases of the Shadow }, diff --git a/ui/raidboss/data/06-ew/trial/golbez-ex.ts b/ui/raidboss/data/06-ew/trial/golbez-ex.ts index 442e492c00..722b194637 100644 --- a/ui/raidboss/data/06-ew/trial/golbez-ex.ts +++ b/ui/raidboss/data/06-ew/trial/golbez-ex.ts @@ -1,29 +1,101 @@ -import { UnreachableCode } from '../../../../../resources/not_reached'; import Outputs from '../../../../../resources/outputs'; -import { callOverlayHandler } from '../../../../../resources/overlay_plugin_api'; import { Responses } from '../../../../../resources/responses'; import ZoneId from '../../../../../resources/zone_id'; import { RaidbossData } from '../../../../../types/data'; -import { PluginCombatantState } from '../../../../../types/event'; import { TriggerSet } from '../../../../../types/trigger'; +// These don't seem to be randomized. +// Listing them all in case future BLU players want to call out who the stacks are on. +const headmarkers = { + voidMeteor: '0158', + spread: '0178', + knockback: '01DA', + flare: '01D9', + cauterize: '0001', + partnerStackAbyssalQuasar: '015B', + healerStackImmolatingShade: '00A1', + healerStackVoidBlizzardIII: '013E', + partnerStackVoidAeroIII: '01C3', +} as const; + +type ArcticAssaultSafeSpot = 'nw' | 'ne' | 'sw' | 'se'; + +const arcticAssaultQuadrants: { [location: string]: ArcticAssaultSafeSpot } = { + '00': 'nw', + '01': 'ne', + '02': 'ne', + '03': 'se', + '04': 'sw', + '05': 'se', + '06': 'nw', + '07': 'sw', +} as const; + +const galeSphereOutputStrings = { + middle: Outputs.middle, + n: Outputs.north, + e: Outputs.east, + s: Outputs.south, + w: Outputs.west, + unknown: Outputs.unknown, + dirAndMechanic: { + en: '${dir} + ${mechanic}', + }, + healerGroups: Outputs.healerGroups, + partnerStack: { + en: 'Partner Stack', + de: 'Mit Partner sammeln', + fr: 'Package partenaire', + ja: 'ペア', + cn: '2 人分摊', + ko: '2인 쉐어', + }, +} as const; + export interface Data extends RaidbossData { + galeSphereShadows: ('n' | 'e' | 's' | 'w')[]; + galeSphereCasts: { + x: number; + y: number; + castTime: number; + }[]; + galeSafeSpots: GaleSafeSpots[]; + firstGaleMechanic?: 'partner' | 'healer'; + secondGaleMechanic?: 'partner' | 'healer'; terrastormCount: number; - terrastormCombatantDirs: number[]; + terrastormDir?: 'nw' | 'ne'; + arcticAssaultMapEffects: string[]; + arcticAssaultCount: number; + arcticAssaultSafeSpots?: ArcticAssaultSafeSpot[]; + dragonsDescentMarker: string[]; + recordedShadowMechanic?: 'spread' | 'stack'; } -// Calculate combatant position in an all 8 cards/intercards -const matchedPositionTo8Dir = (combatant: PluginCombatantState) => { - // Positions are moved up 100 and right 100 - const y = combatant.PosY - 100; - const x = combatant.PosX - 100; +// MapEffect info: +/* +Slots: + 00 = Middle North ice wall, facing west + 01 = Middle North ice wall, facing east + 02 = Center East ice wall, facing north + 03 = Center East ice wall, facing south + 04 = Middle South ice wall, facing west + 05 = Middle South ice wall, facing east + 06 = Center West ice wall, facing north + 07 = Center West ice wall, facing south - // Majority of mechanics center around three circles: - // NW at 0, NE at 2, South at 5 - // Map NW = 0, N = 1, ..., W = 7 + 08/0A = NW/SE meteors + 09/0B = NE/SW meteors - return Math.round(5 - 4 * Math.atan2(x, y) / Math.PI) % 8; -}; + 0C = lightning effect during lingering spark + 0D = unknown, during towers+meteors + +Flags: + For ice wall and lightning, `00020001` enables, `00080004` disables + For meteors, `00010004` enables, seems to auto-disable +*/ + +type GaleDirections = 'n' | 'e' | 's' | 'w'; +type GaleSafeSpots = GaleDirections | 'middle' | 'unknown'; const triggerSet: TriggerSet = { id: 'TheVoidcastDaisExtreme', @@ -33,68 +105,62 @@ const triggerSet: TriggerSet = { return { terrastormCount: 0, terrastormCombatantDirs: [], + galeSphereShadows: [], + galeSphereCasts: [], + galeSafeSpots: [], + arcticAssaultMapEffects: [], + arcticAssaultCount: 0, + dragonsDescentMarker: [], }; }, + timelineTriggers: [ + { + id: 'GolbezEx Flames of Eventide 1', + regex: /Flames of Eventide 1/, + beforeSeconds: 5, + suppressSeconds: 5, + response: Responses.tankCleave(), + }, + ], triggers: [ { - id: 'GolbezEx Terrastorm', - type: 'StartsUsing', - netRegex: { id: '8466', source: 'Golbez', capture: true }, - delaySeconds: 0.5, - promise: async (data, matches) => { - const meteorData = await callOverlayHandler({ - call: 'getCombatants', - ids: [parseInt(matches.sourceId, 16)], - }); - - if (meteorData === null) { - console.error(`Terrastorm: null data`); - return; - } - if (meteorData.combatants.length !== 1) { - console.error(`Terrastorm: expected 1, got ${meteorData.combatants.length}`); - return; - } - - const meteor = meteorData.combatants[0]; - if (!meteor) - throw new UnreachableCode(); - data.terrastormCombatantDirs.push(matchedPositionTo8Dir(meteor)); + id: 'GolbezEx Flames of Eventide Swap', + type: 'GainsEffect', + netRegex: { effectId: 'DF5', count: '01' }, + condition: (data, matches) => { + if (data.me === matches.target) + return false; + return data.role === 'tank' || data.job === 'BLU'; }, - alertText: (data, _matches, output) => { - const wanted = data.terrastormCount === 0 ? 2 : 3; - if (data.terrastormCombatantDirs.length < wanted) - return; - - const meteors = data.terrastormCombatantDirs; - - data.terrastormCombatantDirs = []; - ++data.terrastormCount; - - const dirs: { [dir: number]: string } = { - 0: 'nw', - 2: 'ne', - 4: 'se', - 6: 'sw', - }; - - for (const meteor of meteors) { - delete dirs[meteor]; - } - - const dirOutputs: string[] = []; + suppressSeconds: 10, + alertText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: Outputs.tankSwap, + }, + }, + { + id: 'GolbezEx Terrastorm 1', + type: 'MapEffect', + netRegex: { location: '0[89]', flags: '00010004', capture: true }, + alertText: (data, matches, output) => { + data.terrastormCount++; + data.terrastormDir = matches.location === '08' ? 'nw' : 'ne'; - for (const dir of Object.values(dirs)) { - dirOutputs.push(output[dir]!()); - } + // We'll handle this elsewhere to combine with arctic assault. + if (data.terrastormCount === 2) + return; - return dirOutputs.join('/'); + if (data.terrastormDir === 'nw') + return output.dirNESW!(); + return output.dirNWSE!(); }, outputStrings: { - nw: Outputs.dirNW, - ne: Outputs.dirNE, - sw: Outputs.dirSW, - se: Outputs.dirSE, + dirNWSE: { + en: 'NW / SE', + }, + dirNESW: { + en: 'NE / SW', + }, }, }, { @@ -124,7 +190,75 @@ const triggerSet: TriggerSet = { id: 'GolbezEx Phases of the Blade', type: 'StartsUsing', netRegex: { id: '86DB', source: 'Golbez', capture: false }, - response: Responses.getBackThenFront(), + durationSeconds: 4, + response: Responses.getBackThenFront('alert'), + }, + { + id: 'GolbezEx Phases of the Blade Followup', + type: 'Ability', + netRegex: { id: '86DB', source: 'Golbez', capture: false }, + suppressSeconds: 5, + infoText: (_data, _matches, output) => output.front!(), + outputStrings: { + front: Outputs.front, + }, + }, + { + id: 'GolbezEx Phases of the Shadow', + type: 'StartsUsing', + netRegex: { id: '86E7', source: 'Golbez', capture: false }, + durationSeconds: 4, + alertText: (data, _matches, output) => { + if (data.recordedShadowMechanic === 'spread') + return output.backThenFrontThenSpread!(); + if (data.recordedShadowMechanic === 'stack') + return output.backThenFrontThenHealerGroups!(); + return output.backThenFront!(); + }, + outputStrings: { + backThenFront: Outputs.backThenFront, + backThenFrontThenHealerGroups: { + en: 'Back => Front => Out => Stacks', + }, + backThenFrontThenSpread: { + en: 'Back => Front => Under => Spread', + }, + }, + }, + { + id: 'GolbezEx Phases of the Shadow Followup', + type: 'Ability', + netRegex: { id: '86E7', source: 'Golbez', capture: false }, + suppressSeconds: 5, + infoText: (data, _matches, output) => { + if (data.recordedShadowMechanic === 'spread') + return output.frontThenSpread!(); + if (data.recordedShadowMechanic === 'stack') + return output.frontThenHealerGroups!(); + return output.front!(); + }, + run: (data) => delete data.recordedShadowMechanic, + outputStrings: { + front: Outputs.front, + frontThenHealerGroups: { + en: 'Front => Out => Stacks', + }, + frontThenSpread: { + en: 'Front => Under', + }, + }, + }, + { + id: 'GolbezEx Rising Ring Followup', + type: 'Ability', + netRegex: { id: '86ED', source: 'Golbez', capture: false }, + suppressSeconds: 5, + infoText: (_data, _matches, output) => output.outAndSpread!(), + outputStrings: { + outAndSpread: { + en: 'Spread Out', + }, + }, }, { id: 'GolbezEx Binding Cold', @@ -135,8 +269,11 @@ const triggerSet: TriggerSet = { { id: 'GolbezEx Void Meteor', type: 'StartsUsing', - netRegex: { id: '84AD', source: 'Golbez', capture: true }, - response: Responses.tankBuster(), + netRegex: { id: '84AD', source: 'Golbez', capture: false }, + alertText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: Outputs.tankBusters, + }, }, { id: 'GolbezEx Black Fang', @@ -148,6 +285,7 @@ const triggerSet: TriggerSet = { id: 'GolbezEx Abyssal Quasar', type: 'StartsUsing', netRegex: { id: '84AB', source: 'Golbez', capture: false }, + suppressSeconds: 3, alertText: (_data, _matches, output) => output.partnerStack!(), outputStrings: { partnerStack: { @@ -180,43 +318,403 @@ const triggerSet: TriggerSet = { id: 'GolbezEx Eventide Fall', type: 'StartsUsing', netRegex: { id: '8485', source: 'Golbez', capture: false }, + suppressSeconds: 3, alertText: (_data, _matches, output) => output.healerGroups!(), outputStrings: { healerGroups: Outputs.healerGroups, }, }, { - id: 'GolbezEx Void Tornado', + id: 'GolbezEx Azdaja\'s Shadow Out Tell', type: 'StartsUsing', - netRegex: { id: '845D', source: 'Golbez', capture: false }, - alertText: (_data, _matches, output) => output.healerGroups!(), + netRegex: { id: '8478', source: 'Golbez', capture: false }, + infoText: (_data, _matches, output) => output.text!(), + run: (data) => data.recordedShadowMechanic = 'stack', outputStrings: { - healerGroups: Outputs.healerGroups, + text: { + en: '(out + healer groups, for later)', + }, }, }, { - id: 'GolbezEx Void Aero III', + id: 'GolbezEx Azdaja\'s Shadow In Tell', type: 'StartsUsing', - netRegex: { id: '845C', source: 'Golbez', capture: false }, - alertText: (_data, _matches, output) => output.partnerStack!(), + netRegex: { id: '8479', source: 'Golbez', capture: false }, + infoText: (_data, _matches, output) => output.text!(), + run: (data) => data.recordedShadowMechanic = 'spread', outputStrings: { - partnerStack: { - en: 'Partner Stack', - de: 'Mit Partner sammeln', - fr: 'Package partenaire', - ja: 'ペア', - cn: '2 人分摊', - ko: '2인 쉐어', + text: { + en: '(in + spread, for later)', }, }, }, { - id: 'GolbezEx Void Blizzard III', + id: 'GolbezEx Void Tornado / Void Aero III', type: 'StartsUsing', - netRegex: { id: '8462', source: 'Golbez', capture: false }, - alertText: (_data, _matches, output) => output.healerGroups!(), + // 845C = Void Aero III (partner stacks) + // 845D = Void Tornado (healer stacks) + netRegex: { id: '845[CD]', source: 'Golbez' }, + suppressSeconds: 30, + run: (data, matches) => { + if (matches.id === '845D') { + data.firstGaleMechanic = 'healer'; + data.secondGaleMechanic = 'partner'; + } else { + data.firstGaleMechanic = 'partner'; + data.secondGaleMechanic = 'healer'; + } + }, + }, + { + id: 'GolbezEx Gale Sphere Collector', + type: 'StartsUsing', + netRegex: { id: '845[89AB]', source: 'Gale Sphere', capture: true }, + run: (data, matches) => { + data.galeSafeSpots = []; + data.galeSphereCasts.push({ + x: parseFloat(matches.x), + y: parseFloat(matches.y), + castTime: parseFloat(matches.castTime), + }); + }, + }, + { + id: 'GolbezEx Gale Sphere Directions', + type: 'Ability', + netRegex: { id: '84(?:4F|50|51|52)', source: 'Golbez\'s Shadow', capture: true }, + infoText: (data, matches, output) => { + switch (matches.id) { + case '844F': + data.galeSphereShadows.push('n'); + break; + case '8450': + data.galeSphereShadows.push('e'); + break; + case '8451': + data.galeSphereShadows.push('w'); + break; + case '8452': + data.galeSphereShadows.push('s'); + break; + } + + if (data.galeSphereShadows.length < 4) + return; + + const [dir1, dir2, dir3, dir4] = data.galeSphereShadows; + + data.galeSphereShadows = []; + + return output.clones!({ + dir1: dir1, + dir2: dir2, + dir3: dir3, + dir4: dir4, + }); + }, outputStrings: { - healerGroups: Outputs.healerGroups, + n: Outputs.dirN, + e: Outputs.dirE, + s: Outputs.dirS, + w: Outputs.dirW, + unknown: Outputs.unknown, + clones: { + en: 'Clones: ${dir1}->${dir2}->${dir3}->${dir4}', + }, + }, + }, + { + id: 'GolbezEx Gale Safe Spots', + type: 'StartsUsing', + netRegex: { id: '845[89AB]', source: 'Gale Sphere', capture: false }, + condition: (data) => data.galeSphereCasts.length === 16, + durationSeconds: 15, + infoText: (data, _matches, output) => { + const order: GaleDirections[] = []; + const safeSpots: { [dir in GaleDirections]: GaleSafeSpots } = { + n: 'unknown', + e: 'unknown', + s: 'unknown', + w: 'unknown', + }; + + data.galeSphereCasts.sort((left, right) => { + return left.castTime - right.castTime; + }); + + data.galeSphereCasts.forEach((sphere) => { + let dir: GaleDirections; + if (sphere.x > 113) + dir = 'e'; + else if (sphere.y > 113) + dir = 's'; + else if (sphere.x < 87) + dir = 'w'; + else + dir = 'n'; + + if (!order.includes(dir)) + order.push(dir); + }); + + const sphereDirections: { [dir in GaleDirections]: Data['galeSphereCasts'] } = { + n: data.galeSphereCasts.filter((sphere) => sphere.y < 87), + e: data.galeSphereCasts.filter((sphere) => sphere.x > 113), + s: data.galeSphereCasts.filter((sphere) => sphere.y > 113), + w: data.galeSphereCasts.filter((sphere) => sphere.x < 87), + }; + + const possibleDirs = ['n', 'e', 's', 'w'] as const; + + for (const dir of possibleDirs) { + const spheres = sphereDirections[dir]; + const key: 'x' | 'y' = ['n', 's'].includes(dir) ? 'x' : 'y'; + + // For these, there are 6 possible cast locations, of which 4 will be present + // We only need to check three of the six to determine the safe spot + // All of these coordinates are 0.50 higher. To avoid floating point issues + // we're just using the floor'd coordinates. + const possibleSpots: { [coord: number]: GaleSafeSpots[] } = { + 112: ['s', 'e'], + 102: ['middle'], + 87: ['n', 'w'], + }; + + for (const sphere of spheres) { + delete possibleSpots[Math.floor(sphere[key])]; + } + + const remainingSpots = Object.values(possibleSpots); + const spot = remainingSpots[0]; + if (remainingSpots.length > 1 || !spot) + continue; + + let finalSpot: GaleSafeSpots | undefined = 'unknown'; + + if (spot[0] === 'middle') + finalSpot = 'middle'; + else + finalSpot = key === 'y' ? spot[0] : spot[1]; + + safeSpots[dir] = finalSpot ?? 'unknown'; + } + + data.galeSafeSpots = []; + for (const dir of order) + data.galeSafeSpots.push(safeSpots[dir]); + data.galeSphereCasts = []; + + const [dir1, dir2, dir3, dir4] = data.galeSafeSpots.map((x) => output[x]!()); + if (dir1 === undefined || dir2 === undefined || dir3 === undefined || dir4 === undefined) + return; + + return output.safeSpotList!({ dir1: dir1, dir2: dir2, dir3: dir3, dir4: dir4 }); + }, + outputStrings: { + safeSpotList: { + en: '${dir1} => ${dir2} => ${dir3} => ${dir4}', + }, + ...galeSphereOutputStrings, + }, + }, + { + id: 'GolbezEx Gale Initial Safe Spot', + type: 'StartsUsing', + netRegex: { id: '845[89AB]', source: 'Gale Sphere', capture: false }, + condition: (data) => data.galeSafeSpots.length === 4, + alertText: (data, _matches, output) => { + const spot = data.galeSafeSpots.shift(); + if (spot === undefined) + return; + const dir = output[spot]!(); + + const mech = data.firstGaleMechanic; + delete data.firstGaleMechanic; + + if (mech === undefined) + return dir; + + const mechanicStr = mech === 'partner' ? output.partnerStack!() : output.healerGroups!(); + return output.dirAndMechanic!({ dir: dir, mechanic: mechanicStr }); + }, + outputStrings: galeSphereOutputStrings, + }, + { + id: 'GolbezEx Arctic Assault Collector', + type: 'MapEffect', + netRegex: { location: '0[0-7]', flags: '00020001' }, + run: (data, matches) => { + delete data.arcticAssaultSafeSpots; + data.arcticAssaultMapEffects.push(matches.location); + if (data.arcticAssaultMapEffects.length < 2) + return; + + // 1 = Gale Sphere 1 + // 2 = Terrastorm 2 + // 3 = Gale Sphere 2 + // 4 = Gale Sphere 3 + data.arcticAssaultCount++; + + const safe: ArcticAssaultSafeSpot[] = ['nw', 'ne', 'sw', 'se']; + data.arcticAssaultSafeSpots = safe.filter((quadrant) => { + for (const slot of data.arcticAssaultMapEffects) { + if (arcticAssaultQuadrants[slot] === quadrant) + return false; + } + return true; + }); + data.arcticAssaultMapEffects = []; + }, + }, + { + id: 'GolbezEx Terrastorm 2', + // The terrastorm meteors come out before the arctic assault, and so wait for them. + type: 'MapEffect', + netRegex: { location: '0[0-7]', flags: '00020001', capture: false }, + condition: (data) => { + return data.arcticAssaultCount === 2 && data.arcticAssaultSafeSpots !== undefined; + }, + alertText: (data, _matches, output) => { + const [safe1, safe2] = data.arcticAssaultSafeSpots ?? []; + const terrastormDir = data.terrastormDir; + if (terrastormDir === undefined || safe1 === undefined || safe2 === undefined) + return; + + const isSafe1Safe = terrastormDir === 'nw' && safe1 !== 'nw' && safe1 !== 'se' || + terrastormDir === 'ne' && safe1 !== 'ne' && safe1 !== 'sw'; + const isSafe2Safe = terrastormDir === 'nw' && safe2 !== 'nw' && safe2 !== 'se' || + terrastormDir === 'ne' && safe2 !== 'ne' && safe2 !== 'sw'; + if (isSafe1Safe && isSafe2Safe || !isSafe1Safe && !isSafe2Safe) + return; + + const dir = { + ne: output.northeast!(), + se: output.southeast!(), + sw: output.southwest!(), + nw: output.northwest!(), + }[isSafe1Safe ? safe1 : safe2]; + return output.text!({ dir: dir }); + }, + outputStrings: { + text: { + en: '${dir} => Healer Groups', + }, + northeast: Outputs.northeast, + southeast: Outputs.southeast, + southwest: Outputs.southwest, + northwest: Outputs.northwest, + }, + }, + { + id: 'GolbezEx Gale Sphere Followup Safe Spots', + type: 'Ability', + netRegex: { id: '845[89AB]', source: 'Gale Sphere', capture: false }, + suppressSeconds: 1, + alertText: (data, _matches, output) => { + const spot = data.galeSafeSpots.shift(); + if (spot === undefined) + return; + const nextSpot = data.galeSafeSpots[0] ?? 'unknown'; + + // Safe spot 2 with arctic assault. + if (data.galeSafeSpots.length === 2 && data.arcticAssaultSafeSpots !== undefined) { + if (spot === 'w' && data.arcticAssaultSafeSpots.includes('nw')) + return output.northwest!(); + if (spot === 'w' && data.arcticAssaultSafeSpots.includes('sw')) + return output.southwest!(); + if (spot === 'e' && data.arcticAssaultSafeSpots.includes('ne')) + return output.northeast!(); + if (spot === 'e' && data.arcticAssaultSafeSpots.includes('se')) + return output.southeast!(); + // If in the middle, try to steer people towards the next safe spot. + if (spot === 'middle') { + if (nextSpot === 'n') { + if (data.arcticAssaultSafeSpots.includes('nw')) + return output.middleLean!({ dir: output.dirNW!() }); + if (data.arcticAssaultSafeSpots.includes('ne')) + return output.middleLean!({ dir: output.dirNE!() }); + } else if (nextSpot === 's') { + if (data.arcticAssaultSafeSpots.includes('sw')) + return output.middleLean!({ dir: output.dirSW!() }); + if (data.arcticAssaultSafeSpots.includes('se')) + return output.middleLean!({ dir: output.dirSE!() }); + } + } + } + + // Safe spot 3. + const dir = output[spot]!(); + if (data.galeSafeSpots.length > 0) + return dir; + + // Safe spot 4 + const mech = data.secondGaleMechanic; + delete data.secondGaleMechanic; + if (mech === undefined) + return dir; + + const mechanicStr = mech === 'partner' ? output.partnerStack!() : output.healerGroups!(); + return output.dirAndMechanic!({ dir: dir, mechanic: mechanicStr }); + }, + outputStrings: { + ...galeSphereOutputStrings, + northwest: Outputs.northwest, + northeast: Outputs.northeast, + southwest: Outputs.southwest, + southeast: Outputs.southeast, + dirNW: Outputs.dirNW, + dirNE: Outputs.dirNE, + dirSW: Outputs.dirSW, + dirSE: Outputs.dirSE, + middleLean: { + en: 'Middle (lean ${dir})', + }, + }, + }, + { + id: 'GolbezEx Knockback Headmarker', + type: 'HeadMarker', + netRegex: { id: headmarkers.knockback }, + alarmText: (data, matches, output) => { + if (data.me === matches.target) + return output.text!(); + }, + run: (data, matches) => data.dragonsDescentMarker.push(matches.target), + outputStrings: { + text: { + en: 'Knockback on YOU', + }, + }, + }, + { + id: 'GolbezEx Flare Headmarker', + type: 'HeadMarker', + netRegex: { id: headmarkers.flare }, + alertText: (data, matches, output) => { + if (data.me === matches.target) + return output.text!(); + }, + run: (data, matches) => data.dragonsDescentMarker.push(matches.target), + outputStrings: { + text: { + en: 'Flare on YOU', + }, + }, + }, + { + id: 'GolbezEx No Headmarker', + type: 'HeadMarker', + netRegex: { id: headmarkers.flare, capture: false }, + condition: (data) => data.dragonsDescentMarker.length === 3, + infoText: (data, _matches, output) => { + if (!data.dragonsDescentMarker.includes(data.me)) + return output.text!(); + }, + run: (data) => data.dragonsDescentMarker = [], + outputStrings: { + text: { + en: 'Get Tower', + }, }, }, ], diff --git a/ui/raidboss/data/06-ew/trial/golbez-ex.txt b/ui/raidboss/data/06-ew/trial/golbez-ex.txt index eaf800a5dd..6305ec9247 100644 --- a/ui/raidboss/data/06-ew/trial/golbez-ex.txt +++ b/ui/raidboss/data/06-ew/trial/golbez-ex.txt @@ -1,5 +1,5 @@ ### The Voidcast Dais (Extreme) -# -ii 84B5 84B7 849E 84A8 84AA 8481 86B2 8461 +# -ii 84B5 84B7 849E 84A8 84AA 8481 86B2 8461 848D 848E hideall "--Reset--" hideall "--sync--" @@ -7,18 +7,17 @@ hideall "--sync--" 0.0 "--Reset--" sync / 21:........:4000000F:/ window 100000 jump 0 0.0 "--sync--" sync / 104:[^:]*:1($|:)/ window 0,1 -# Exclude the first auto since it's delayed wildly depending on tank movement 9.4 "--sync--" sync / 14:[^:]*:Golbez:8464:/ window 15,15 12.4 "Terrastorm (cast)" sync / 1[56]:[^:]*:Golbez:8464:/ 21.5 "Terrastorm (hit)" sync / 1[56]:[^:]*:Golbez:8466:/ 22.5 "Lingering Spark (snapshot)" sync / 1[56]:[^:]*:Golbez:8468:/ 26.6 "Lingering Spark (explode)" sync / 1[56]:[^:]*:Golbez:846A:/ -31.8 "Phases of the Blade (cast)" sync / 1[56]:[^:]*:Golbez:86DB:/ -33.6 "Phases of the Blade (front)" sync / 1[56]:[^:]*:Golbez:86DD:/ +31.8 "Phases of the Blade (front)" sync / 1[56]:[^:]*:Golbez:86DB:/ +33.6 "--sync--" sync / 1[56]:[^:]*:Golbez:86DD:/ 35.3 "Phases of the Blade (back)" sync / 1[56]:[^:]*:Golbez:86F2:/ 44.6 "Binding Cold" sync / 1[56]:[^:]*:Golbez:84B3:/ -52.8 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +52.8 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 57.9 "Gale Sphere" sync / 1[56]:[^:]*:Golbez:844D:/ 68.6 "--sync--" sync / 1[56]:[^:]*:Golbez:844E:/ 71.2 "Gale Sphere 1" sync / 1[56]:[^:]*:Gale Sphere:845[89AB]:/ @@ -26,8 +25,8 @@ hideall "--sync--" 74.6 "Gale Sphere 2" sync / 1[56]:[^:]*:Gale Sphere:845[89AB]:/ 77.9 "Gale Sphere 3" sync / 1[56]:[^:]*:Gale Sphere:845[89AB]:/ 81.5 "Gale Sphere 4" sync / 1[56]:[^:]*:Gale Sphere:845[89AB]:/ -86.7 "Phases of the Blade (cast)" sync / 1[56]:[^:]*:Golbez:86DB:/ -88.6 "Phases of the Blade (front)" sync / 1[56]:[^:]*:Golbez:86DD:/ +86.7 "Phases of the Blade (front)" sync / 1[56]:[^:]*:Golbez:86DB:/ +88.6 "--sync--" sync / 1[56]:[^:]*:Golbez:86DD:/ 90.3 "Phases of the Blade (back)" sync / 1[56]:[^:]*:Golbez:86F2:/ 99.7 "Binding Cold" sync / 1[56]:[^:]*:Golbez:84B3:/ @@ -35,7 +34,7 @@ hideall "--sync--" 107.9 "Void Comet x4" duration 3 #sync / 1[56]:[^:]*:Golbez:84B0:/ 111.9 "Void Meteor (big)" sync / 1[56]:[^:]*:Golbez:84B1:/ -119.0 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +119.0 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 126.3 "Azdaja's Shadow" sync / 1[56]:[^:]*:Golbez:86FF:/ 136.4 "--sync--" sync / 1[56]:[^:]*:Shadow Dragon:8472:/ 136.4 "Black Fang (big)" sync / 1[56]:[^:]*:Golbez:8471:/ @@ -64,23 +63,14 @@ hideall "--sync--" 205.2 "Flames of Eventide 1" sync / 1[56]:[^:]*:Golbez:847B:/ 208.3 "Flames of Eventide 2" sync / 1[56]:[^:]*:Golbez:847B:/ 211.4 "Flames of Eventide 3" sync / 1[56]:[^:]*:Golbez:847B:/ -213.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +213.4 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ -220.7 "Phases of the Shadow (cast)" sync / 1[56]:[^:]*:Golbez:86E7:/ -222.5 "Rising Beacon (record)" sync / 1[56]:[^:]*:Shadow Dragon:848D:/ -222.5 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E9:/ +220.7 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E7:/ +222.5 "--sync--" sync / 1[56]:[^:]*:Golbez:86E9:/ 224.2 "Phases of the Shadow (back)" sync / 1[56]:[^:]*:Golbez:86EF:/ 225.4 "Rising Beacon (out)" sync / 1[56]:[^:]*:Golbez:86EC:/ 228.1 "Immolating Shade (light parties)" sync / 1[56]:[^:]*:Golbez:8496:/ -228.7 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ jump 400.0 - -# repeated to keep the timeline rolling until jump - -239.1 "Dragon's Descent" -241.5 "Explosion" -242.2 "Double Meteor" -243.8 "Cauterize" -265.5 "Azdaja's Shadow" +228.7 "--north--" sync / 1[56]:[^:]*:Golbez:84B8:/ forcejump 400.0 # in -> spread variation @@ -88,27 +78,19 @@ hideall "--sync--" 305.2 "Flames of Eventide 1" sync / 1[56]:[^:]*:Golbez:847B:/ 308.3 "Flames of Eventide 2" sync / 1[56]:[^:]*:Golbez:847B:/ 311.4 "Flames of Eventide 3" sync / 1[56]:[^:]*:Golbez:847B:/ -313.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +313.4 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ -320.7 "Phases of the Shadow (cast)" sync / 1[56]:[^:]*:Golbez:86E7:/ -322.5 "Rising Ring (record)" sync / 1[56]:[^:]*:Shadow Dragon:848E:/ -322.5 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E9:/ +320.7 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E7:/ +322.5 "--sync--" sync / 1[56]:[^:]*:Golbez:86E9:/ 324.2 "Phases of the Shadow (back)" sync / 1[56]:[^:]*:Golbez:86EF:/ 325.4 "Rising Ring (under)" sync / 1[56]:[^:]*:Golbez:86ED:/ 328.1 "Burning Shade (spread)" sync / 1[56]:[^:]*:Golbez:8494:/ -328.7 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ jump 400.0 +328.7 "--north--" sync / 1[56]:[^:]*:Golbez:84B8:/ forcejump 400.0 -# repeated to keep the timeline rolling until jump - -339.1 "Dragon's Descent" -341.5 "Explosion" -342.2 "Double Meteor" -343.8 "Cauterize" -365.5 "Azdaja's Shadow" # knockback phase -400.0 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +400.0 "--north--" sync / 1[56]:[^:]*:Golbez:84B8:/ 410.4 "Dragon's Descent" sync / 1[56]:[^:]*:Shadow Dragon:8498:/ 412.8 "Explosion" sync / 1[56]:[^:]*:Golbez:849D:/ 413.5 "Double Meteor" sync / 1[56]:[^:]*:Golbez:878C:/ @@ -131,7 +113,7 @@ hideall "--sync--" 505.2 "Flames of Eventide 1" sync / 1[56]:[^:]*:Golbez:847B:/ 508.3 "Flames of Eventide 2" sync / 1[56]:[^:]*:Golbez:847B:/ 511.4 "Flames of Eventide 3" sync / 1[56]:[^:]*:Golbez:847B:/ -513.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +513.4 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 518.5 "Void Stardust (preview)" sync / 1[56]:[^:]*:Golbez:84A4:/ 524.6 "Void Stardust" duration 2.3 sync / 1[56]:[^:]*:Golbez:84A6:/ 530.4 "Abyssal Quasar" sync / 1[56]:[^:]*:Golbez:84AB:/ @@ -143,23 +125,14 @@ hideall "--sync--" 556.7 "Void Comet x4" duration 3 #sync / 1[56]:[^:]*:Golbez:84B0:/ 560.7 "Void Meteor" sync / 1[56]:[^:]*:Golbez:84B1:/ -562.7 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ -570.0 "Phases of the Shadow (cast)" sync / 1[56]:[^:]*:Golbez:86E7:/ -571.8 "Rising Beacon (record)" sync / 1[56]:[^:]*:Shadow Dragon:848D:/ -571.8 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E9:/ +562.7 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ +570.0 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E7:/ +571.8 "--sync--" sync / 1[56]:[^:]*:Golbez:86E9:/ 573.5 "Phases of the Shadow (back)" sync / 1[56]:[^:]*:Golbez:86EF:/ 574.7 "Rising Beacon (out)" sync / 1[56]:[^:]*:Golbez:86EC:/ 576.8 "--sync--" sync / 1[56]:[^:]*:Golbez:8475:/ -577.2 "Immolating Shade (light parties)" sync / 1[56]:[^:]*:Golbez:8496:/ jump 1000.0 - -# timeline rolling +577.2 "Immolating Shade (light parties)" sync / 1[56]:[^:]*:Golbez:8496:/ forcejump 1000.0 -584.1 "Terrastorm" -590.2 "Arctic Assault" -591.2 "Arctic Assault" -593.2 "Void Blizzard III" -593.2 "Terrastorm" -600.3 "Binding Cold" # Mini-phase 2, exaflares -> pairs -> role stacks or light parties -> in then spread @@ -167,7 +140,7 @@ hideall "--sync--" 705.2 "Flames of Eventide 1" sync / 1[56]:[^:]*:Golbez:847B:/ 708.3 "Flames of Eventide 2" sync / 1[56]:[^:]*:Golbez:847B:/ 711.4 "Flames of Eventide 3" sync / 1[56]:[^:]*:Golbez:847B:/ -713.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +713.4 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 718.5 "Void Stardust (preview)" sync / 1[56]:[^:]*:Golbez:84A4:/ 724.6 "Void Stardust" duration 2.3 sync / 1[56]:[^:]*:Golbez:84A6:/ 730.4 "Abyssal Quasar" sync / 1[56]:[^:]*:Golbez:84AB:/ @@ -179,28 +152,18 @@ hideall "--sync--" 756.7 "Void Comet x4" duration 3 #sync / 1[56]:[^:]*:Golbez:84B0:/ 760.7 "Void Meteor" sync / 1[56]:[^:]*:Golbez:84B1:/ -762.7 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ -770.0 "Phases of the Shadow (cast)" sync / 1[56]:[^:]*:Golbez:86E7:/ -771.8 "Rising Ring (record)" sync / 1[56]:[^:]*:Shadow Dragon:848E:/ -771.8 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E9:/ +762.7 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ +770.0 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E7:/ +771.8 "--sync--" sync / 1[56]:[^:]*:Golbez:86E9:/ 773.5 "Phases of the Shadow (back)" sync / 1[56]:[^:]*:Golbez:86EF:/ 774.7 "Rising Ring (under)" sync / 1[56]:[^:]*:Golbez:86ED:/ 776.8 "--sync--" sync / 1[56]:[^:]*:Golbez:8475:/ -777.2 "Burning Shade (spread)" sync / 1[56]:[^:]*:Golbez:8494:/ jump 1000.0 - -# timeline rolling - -784.1 "Terrastorm" -790.2 "Arctic Assault" -791.2 "Arctic Assault" -793.2 "Void Blizzard III" -793.2 "Terrastorm" -800.3 "Binding Cold" +777.2 "Burning Shade (spread)" sync / 1[56]:[^:]*:Golbez:8494:/ forcejump 1000.0 # terrastorm + light parties 1000.0 "Burning/Immolating Shade" -1007.8 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +1007.8 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 1012.9 "Terrastorm (cast)" sync / 1[56]:[^:]*:Golbez:8464:/ 1019.0 "Arctic Assault" sync / 1[56]:[^:]*:Golbez:845F:/ 1022.0 "Void Blizzard III" sync / 1[56]:[^:]*:Golbez:8462:/ @@ -210,7 +173,7 @@ hideall "--sync--" # gale sphere + light parties or pairs mechanic # tornado = lp, aero = pairs -1035.2 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +1035.2 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 1040.3 "Gale Sphere" sync / 1[56]:[^:]*:Golbez:844D:/ 1051.0 "--sync--" sync / 1[56]:[^:]*:Golbez:844E:/ 1053.3 "Void Tornado/Void Aero III" sync / 1[56]:[^:]*:Golbez:845[CD]:/ @@ -220,8 +183,8 @@ hideall "--sync--" 1060.4 "Gale Sphere 3" sync / 1[56]:[^:]*:Gale Sphere:845[89AB]:/ 1063.8 "Gale Sphere 4" sync / 1[56]:[^:]*:Gale Sphere:845[89AB]:/ 1065.0 "Void Aero III/Void Tornado" sync / 1[56]:[^:]*:Golbez:845[CD]:/ -1069.1 "Phases of the Blade (cast)" sync / 1[56]:[^:]*:Golbez:86DB:/ -1071.0 "Phases of the Blade (front)" sync / 1[56]:[^:]*:Golbez:86DD:/ +1069.1 "Phases of the Blade (front)" sync / 1[56]:[^:]*:Golbez:86DB:/ +1071.0 "--sync--" sync / 1[56]:[^:]*:Golbez:86DD:/ 1072.7 "Phases of the Blade (back)" sync / 1[56]:[^:]*:Golbez:86F2:/ 1082.1 "Binding Cold" sync / 1[56]:[^:]*:Golbez:84B3:/ 1098.2 "Azdaja's Shadow" sync / 1[56]:[^:]*:Golbez:8478:/ jump 1200.0 @@ -241,7 +204,7 @@ hideall "--sync--" 1205.2 "Flames of Eventide 1" sync / 1[56]:[^:]*:Golbez:847B:/ 1208.3 "Flames of Eventide 2" sync / 1[56]:[^:]*:Golbez:847B:/ 1211.4 "Flames of Eventide 3" sync / 1[56]:[^:]*:Golbez:847B:/ -1213.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +1213.4 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 1218.5 "Void Stardust (preview)" sync / 1[56]:[^:]*:Golbez:84A4:/ 1224.6 "Void Stardust" duration 2.3 sync / 1[56]:[^:]*:Golbez:84A6:/ 1230.4 "Abyssal Quasar" sync / 1[56]:[^:]*:Golbez:84AB:/ @@ -249,21 +212,12 @@ hideall "--sync--" 1235.4 "Lingering Spark (explode)" sync / 1[56]:[^:]*:Golbez:846A:/ 1240.4 "Eventide Fall/Eventide Triad" sync / 1[56]:[^:]*:Golbez:848[05]:/ -1251.4 "Phases of the Shadow (cast)" sync / 1[56]:[^:]*:Golbez:86E7:/ -1253.2 "Rising Beacon (record)" sync / 1[56]:[^:]*:Shadow Dragon:848D:/ -1253.2 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E9:/ +1251.4 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E7:/ +1253.2 "--sync--" sync / 1[56]:[^:]*:Golbez:86E9:/ 1254.9 "Phases of the Shadow (back)" sync / 1[56]:[^:]*:Golbez:86EF:/ 1256.1 "Rising Beacon (out)" sync / 1[56]:[^:]*:Golbez:86EC:/ 1258.2 "--sync--" sync / 1[56]:[^:]*:Golbez:8475:/ -1258.6 "Immolating Shade (light parties)" sync / 1[56]:[^:]*:Golbez:8496:/ jump 1600.0 - -# timeline rolling - -1284.1 "Dragon's Descent" -1286.5 "Explosion" -1287.2 "Double Meteor" -1288.8 "Cauterize" -1310.5 "Azdaja's Shadow" +1258.6 "Immolating Shade (light parties)" sync / 1[56]:[^:]*:Golbez:8496:/ forcejump 1600.0 # Mini-phase 3, exaflares -> pairs -> role stacks or light parties -> in then spread @@ -271,7 +225,7 @@ hideall "--sync--" 1405.2 "Flames of Eventide 1" sync / 1[56]:[^:]*:Golbez:847B:/ 1408.3 "Flames of Eventide 2" sync / 1[56]:[^:]*:Golbez:847B:/ 1411.4 "Flames of Eventide 3" sync / 1[56]:[^:]*:Golbez:847B:/ -1413.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +1413.4 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 1418.5 "Void Stardust (preview)" sync / 1[56]:[^:]*:Golbez:84A4:/ 1424.6 "Void Stardust" duration 2.3 sync / 1[56]:[^:]*:Golbez:84A6:/ 1430.4 "Abyssal Quasar" sync / 1[56]:[^:]*:Golbez:84AB:/ @@ -279,26 +233,17 @@ hideall "--sync--" 1435.4 "Lingering Spark (explode)" sync / 1[56]:[^:]*:Golbez:846A:/ 1240.4 "Eventide Fall/Eventide Triad" sync / 1[56]:[^:]*:Golbez:848[05]:/ -1451.4 "Phases of the Shadow (cast)" sync / 1[56]:[^:]*:Golbez:86E7:/ -1453.2 "Rising Ring (record)" sync / 1[56]:[^:]*:Shadow Dragon:848E:/ -1453.2 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E9:/ +1451.4 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E7:/ +1453.2 "--sync--" sync / 1[56]:[^:]*:Golbez:86E9:/ 1454.9 "Phases of the Shadow (back)" sync / 1[56]:[^:]*:Golbez:86EF:/ 1456.1 "Rising Ring (under)" sync / 1[56]:[^:]*:Golbez:86ED:/ 1458.2 "--sync--" sync / 1[56]:[^:]*:Golbez:8475:/ -1458.6 "Burning Shade (spread)" sync / 1[56]:[^:]*:Golbez:8494:/ jump 1600.0 - -# timeline rolling - -1484.1 "Dragon's Descent" -1486.5 "Explosion" -1487.2 "Double Meteor" -1488.8 "Cauterize" -1510.5 "Azdaja's Shadow" +1458.6 "Burning Shade (spread)" sync / 1[56]:[^:]*:Golbez:8494:/ forcejump 1600.0 # knockback phase 1600.0 "Burning/Immolating Shade" -1600.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +1600.4 "--north--" sync / 1[56]:[^:]*:Golbez:84B8:/ 1610.8 "Dragon's Descent" sync / 1[56]:[^:]*:Shadow Dragon:8498:/ 1613.2 "Explosion" sync / 1[56]:[^:]*:Golbez:849D:/ 1613.9 "Double Meteor" sync / 1[56]:[^:]*:Golbez:878C:/ @@ -309,7 +254,7 @@ hideall "--sync--" 1629.1 "Void Comet x4" duration 3 #sync / 1[56]:[^:]*:Golbez:84B0:/ 1633.1 "Void Meteor" sync / 1[56]:[^:]*:Golbez:84B1:/ -1640.2 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +1640.2 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 1645.3 "Gale Sphere" sync / 1[56]:[^:]*:Golbez:844D:/ 1656.0 "--sync--" sync / 1[56]:[^:]*:Golbez:844E:/ 1658.3 "Void Tornado/Void Aero III" sync / 1[56]:[^:]*:Golbez:845[CD]:/ @@ -319,13 +264,21 @@ hideall "--sync--" 1665.4 "Gale Sphere 3" sync / 1[56]:[^:]*:Gale Sphere:845[89AB]:/ 1668.8 "Gale Sphere 4" sync / 1[56]:[^:]*:Gale Sphere:845[89AB]:/ 1670.0 "Void Aero III/Void Tornado" sync / 1[56]:[^:]*:Golbez:845[CD]:/ -1674.1 "Phases of the Blade (cast)" sync / 1[56]:[^:]*:Golbez:86DB:/ -1676.0 "Phases of the Blade (front)" sync / 1[56]:[^:]*:Golbez:86DD:/ +1674.1 "Phases of the Blade (front)" sync / 1[56]:[^:]*:Golbez:86DB:/ +1676.0 "--sync--" sync / 1[56]:[^:]*:Golbez:86DD:/ 1677.7 "Phases of the Blade (back)" sync / 1[56]:[^:]*:Golbez:86F2:/ 1687.1 "Binding Cold" sync / 1[56]:[^:]*:Golbez:84B3:/ 1703.6 "Azdaja's Shadow" sync / 1[56]:[^:]*:Golbez:8478:/ jump 1800.0 1703.6 "--sync--" sync / 1[56]:[^:]*:Golbez:8479:/ jump 1900.0 +# repeated for timeline rolling +1708.8 "Flames of Eventide 1" #sync / 1[56]:[^:]*:Golbez:847B:/ +1711.9 "Flames of Eventide 2" #sync / 1[56]:[^:]*:Golbez:847B:/ +1715.0 "Flames of Eventide 3" #sync / 1[56]:[^:]*:Golbez:847B:/ +1717.0 "--middle--" #sync / 1[56]:[^:]*:Golbez:84B8:/ +1724.3 "Phases of the Shadow (front)" #sync / 1[56]:[^:]*:Golbez:86E7:/ +1727.8 "Phases of the Shadow (back)" #sync / 1[56]:[^:]*:Golbez:86EF:/ + # Mini-phase 4, in then spread, or out then light parties # out -> light parties variation @@ -334,22 +287,13 @@ hideall "--sync--" 1805.2 "Flames of Eventide 1" sync / 1[56]:[^:]*:Golbez:847B:/ 1808.3 "Flames of Eventide 2" sync / 1[56]:[^:]*:Golbez:847B:/ 1811.4 "Flames of Eventide 3" sync / 1[56]:[^:]*:Golbez:847B:/ -1813.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +1813.4 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ -1820.7 "Phases of the Shadow (cast)" sync / 1[56]:[^:]*:Golbez:86E7:/ -1822.5 "Rising Beacon (record)" sync / 1[56]:[^:]*:Shadow Dragon:848D:/ -1822.5 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E9:/ +1820.7 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E7:/ +1822.5 "--sync--" sync / 1[56]:[^:]*:Golbez:86E9:/ 1824.2 "Phases of the Shadow (back)" sync / 1[56]:[^:]*:Golbez:86EF:/ 1825.4 "Rising Beacon (out)" sync / 1[56]:[^:]*:Golbez:86EC:/ -1828.1 "Immolating Shade (light parties)" sync / 1[56]:[^:]*:Golbez:8496:/ jump 2000.0 - -# repeated to keep the timeline rolling until jump - -1838.0 "Binding Cold" -1851.2 "Binding Cold" -1859.3 "Void Meteor" -1859.4 "Void Comet x4" -1863.4 "Void Meteor" +1828.1 "Immolating Shade (light parties)" sync / 1[56]:[^:]*:Golbez:8496:/ forcejump 2000.0 # in -> spread variation @@ -357,23 +301,15 @@ hideall "--sync--" 1905.2 "Flames of Eventide 1" sync / 1[56]:[^:]*:Golbez:847B:/ 1908.3 "Flames of Eventide 2" sync / 1[56]:[^:]*:Golbez:847B:/ 1911.4 "Flames of Eventide 3" sync / 1[56]:[^:]*:Golbez:847B:/ -1913.4 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ -1920.7 "Phases of the Shadow (cast)" sync / 1[56]:[^:]*:Golbez:86E7:/ -1922.5 "Rising Ring (record)" sync / 1[56]:[^:]*:Shadow Dragon:848E:/ -1922.5 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E9:/ +1913.4 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ +1920.7 "Phases of the Shadow (front)" sync / 1[56]:[^:]*:Golbez:86E7:/ +1922.5 "--sync--" sync / 1[56]:[^:]*:Golbez:86E9:/ 1924.2 "Phases of the Shadow (back)" sync / 1[56]:[^:]*:Golbez:86EF:/ 1925.4 "Rising Ring (under)" sync / 1[56]:[^:]*:Golbez:86ED:/ -1928.1 "Burning Shade (spread)" sync / 1[56]:[^:]*:Golbez:8494:/ jump 2000.0 - -# repeated to keep the timeline rolling until jump - -1938.0 "Binding Cold" -1951.2 "Binding Cold" -1959.3 "Void Meteor" -1959.4 "Void Comet x4" -1963.4 "Void Meteor" +1928.1 "Burning Shade (spread)" sync / 1[56]:[^:]*:Golbez:8494:/ forcejump 2000.0 +# final segment 2000.0 "Burning/Immolating Shade" 2009.3 "Binding Cold" sync / 1[56]:[^:]*:Golbez:84B3:/ 2022.5 "Binding Cold" sync / 1[56]:[^:]*:Golbez:84B3:/ @@ -386,7 +322,7 @@ hideall "--sync--" # enrage -2038.7 "--jump--" sync / 1[56]:[^:]*:Golbez:84B8:/ +2038.7 "--middle--" sync / 1[56]:[^:]*:Golbez:84B8:/ 2046.0 "Azdaja's Shadow" sync / 1[56]:[^:]*:Golbez:84B9:/ 2055.1 "--sync--" sync / 1[56]:[^:]*:Shadow Dragon:84BB:/ 2055.2 "Black Fang (big)" sync / 1[56]:[^:]*:Golbez:84BA:/