From 7b2cb9a14315fcd4e60f1d6f9f450c4402f608bc Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 08:14:23 -0500 Subject: [PATCH 01/31] add initial triggers and timeline for p1 --- ui/raidboss/data/07-dt/raid/r12s.ts | 1103 ++++++++++++++++++++++++++ ui/raidboss/data/07-dt/raid/r12s.txt | 454 +++++++++++ 2 files changed, 1557 insertions(+) create mode 100644 ui/raidboss/data/07-dt/raid/r12s.ts create mode 100644 ui/raidboss/data/07-dt/raid/r12s.txt diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts new file mode 100644 index 0000000000..beec50f111 --- /dev/null +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -0,0 +1,1103 @@ +import Conditions from '../../../../../resources/conditions'; +import { UnreachableCode } from '../../../../../resources/not_reached'; +import Outputs from '../../../../../resources/outputs'; +import { Responses } from '../../../../../resources/responses'; +import { Directions } from '../../../../../resources/util'; +import ZoneId from '../../../../../resources/zone_id'; +import { RaidbossData } from '../../../../../types/data'; +import { TriggerSet } from '../../../../../types/trigger'; + +export type Phase = 'doorboss' | 'curtainCall' | 'slaughtershed' | 'two'; + +export interface Data extends RaidbossData { + phase: Phase; + // Phase 1 + grotesquerieCleave?: + | 'rightCleave' + | 'leftCleave' + | 'frontCleave' + | 'rearCleave'; + myFleshBonds?: 'alpha' | 'beta'; + inLine: { [name: string]: number }; + blobTowerDirs: string[]; + fleshBondsCount: number; + cellChainCount: number; + cellTowerCount: number; + myMitoticPhase?: string; + hasRot: boolean; + // Phase 2 +} + +const headMarkerData = { + // Phase 1 + // VFX: com_share3t + 'stack': '00A1', + // VFX: tank_lockonae_6m_5s_01t + 'tankbuster': '0158', + // VFX: VFX: x6rc_cellchain_01x + 'cellChain': '0291', + // VFX: com_share3_7s0p + 'slaughterStack': '013D', + // VFX: target_ae_s7k1 + 'slaughterSpread': '0177', + 'cellChainTether': '016E', + // Phase 2 +} as const; + +const center = { + x: 100, + y: 100, +} as const; + +const phaseMap: { [id: string]: Phase } = { + 'BEC0': 'curtainCall', + 'B4C6': 'slaughtershed', +}; + +const triggerSet: TriggerSet = { + id: 'AacHeavyweightM4Savage', + zoneId: ZoneId.AacHeavyweightM4Savage, + timelineFile: 'r12s.txt', + initData: () => ({ + phase: 'doorboss', + // Phase 1 + inLine: {}, + blobTowerDirs: [], + fleshBondsCount: 0, + cellChainCount: 0, + cellTowerCount: 0, + hasRot: false, + // Phase 2 + }), + triggers: [ + { + id: 'R12S Phase Tracker', + type: 'StartsUsing', + netRegex: { id: Object.keys(phaseMap), source: 'Lindwurm' }, + suppressSeconds: 1, + run: (data, matches) => { + const phase = phaseMap[matches.id]; + if (phase === undefined) + throw new UnreachableCode(); + + data.phase = phase; + }, + }, + { + id: 'R12S The Fixer', + type: 'StartsUsing', + netRegex: { id: 'B4D7', source: 'Lindwurm', capture: false }, + durationSeconds: 4.7, + response: Responses.bigAoe('alert'), + }, + { + id: 'R12S Directed Grotesquerie Direction Collect', + // Unknown_DE6 spell contains data in its count: + // 40C, Front Cone + // 40D, Right Cone + // 40E, Rear Cone + // 40F, Left Cone + type: 'GainsEffect', + netRegex: { effectId: 'DE6', capture: true }, + condition: Conditions.targetIsYou(), + run: (data, matches) => { + switch (matches.count) { + case '40C': + data.grotesquerieCleave = 'frontCleave'; + return; + case '40D': + data.grotesquerieCleave = 'rightCleave'; + return; + case '40E': + data.grotesquerieCleave = 'rearCleave'; + return; + case '40F': + data.grotesquerieCleave = 'leftCleave'; + return; + } + }, + }, + { + id: 'R12S Shared Grotesquerie', + type: 'GainsEffect', + netRegex: { effectId: '129A', capture: true }, + delaySeconds: 0.2, + durationSeconds: 17, + infoText: (data, matches, output) => { + const cleave = data.grotesquerieCleave; + const target = matches.target; + if (target === data.me) { + if (cleave === undefined) + return output.baitThenStack!({ stack: output.stackOnYou!() }); + return output.baitThenStackCleave!({ + stack: output.stackOnYou!(), + cleave: output[cleave]!(), + }); + } + + const player = data.party.member(target); + const isDPS = data.party.isDPS(target); + if (isDPS && data.role === 'dps') { + if (cleave === undefined) + return output.baitThenStack!({ + stack: output.stackOnPlayer!({ player: player }), + }); + return output.baitThenStackCleave!({ + stack: output.stackOnPlayer!({ player: player }), + cleave: output[cleave]!(), + }); + } + if (!isDPS && data.role !== 'dps') { + if (cleave === undefined) + return output.baitThenStack!({ + stack: output.stackOnPlayer!({ player: player }), + }); + return output.baitThenStackCleave!({ + stack: output.stackOnPlayer!({ player: player }), + cleave: output[cleave]!(), + }); + } + }, + outputStrings: { + stackOnYou: Outputs.stackOnYou, + stackOnPlayer: Outputs.stackOnPlayer, + frontCleave: { + en: 'Front Cleave', + de: 'Kegel Aoe nach Vorne', + fr: 'Cleave Avant', + ja: '口からおくび', + cn: '前方扇形', + ko: '전방 부채꼴 장판', + tc: '前方扇形', + }, + rearCleave: { + en: 'Rear Cleave', + de: 'Kegel Aoe nach Hinten', + fr: 'Cleave Arrière', + ja: '尻からおなら', + cn: '背后扇形', + ko: '후방 부채꼴 장판', + tc: '背後扇形', + }, + leftCleave: { + en: 'Left Cleave', + de: 'Linker Cleave', + fr: 'Cleave gauche', + ja: '左半面へ攻撃', + cn: '左刀', + ko: '왼쪽 공격', + tc: '左刀', + }, + rightCleave: { + en: 'Right Cleave', + de: 'Rechter Cleave', + fr: 'Cleave droit', + ja: '右半面へ攻撃', + cn: '右刀', + ko: '오른쪽 공격', + tc: '右刀', + }, + baitThenStack: { + en: 'Bait 4x Puddles => ${stack}', + }, + baitThenStackCleave: { + en: 'Bait 4x Puddles => ${stack} + ${cleave}', + }, + }, + }, + { + id: 'R12S Bursting Grotesquerie', + type: 'GainsEffect', + netRegex: { effectId: '1299', capture: true }, + condition: Conditions.targetIsYou(), + delaySeconds: 0.2, + durationSeconds: 17, + infoText: (data, _matches, output) => { + const cleave = data.grotesquerieCleave; + if (cleave === undefined) + return data.phase === 'doorboss' + ? output.baitThenSpread!() + : output.spreadCurtain!(); + return data.phase === 'doorboss' + ? output.baitThenSpreadCleave!({ cleave: output[cleave]!() }) + : output.spreadCurtain!(); + }, + outputStrings: { + frontCleave: { + en: 'Front Cleave', + de: 'Kegel Aoe nach Vorne', + fr: 'Cleave Avant', + ja: '口からおくび', + cn: '前方扇形', + ko: '전방 부채꼴 장판', + tc: '前方扇形', + }, + rearCleave: { + en: 'Rear Cleave', + de: 'Kegel Aoe nach Hinten', + fr: 'Cleave Arrière', + ja: '尻からおなら', + cn: '背后扇形', + ko: '후방 부채꼴 장판', + tc: '背後扇形', + }, + leftCleave: { + en: 'Left Cleave', + de: 'Linker Cleave', + fr: 'Cleave gauche', + ja: '左半面へ攻撃', + cn: '左刀', + ko: '왼쪽 공격', + tc: '左刀', + }, + rightCleave: { + en: 'Right Cleave', + de: 'Rechter Cleave', + fr: 'Cleave droit', + ja: '右半面へ攻撃', + cn: '右刀', + ko: '오른쪽 공격', + tc: '右刀', + }, + baitThenSpread: { + en: 'Bait 4x Puddles => Spread', + }, + baitThenSpreadCleave: { + en: 'Bait 4x Puddles => Spread + ${cleave}', + }, + spreadCurtain: { + en: 'Spread Debuff on YOU', + }, + }, + }, + { + id: 'R12S Ravenous Reach 1 Safe Side', + // These two syncs indicate the animation of where the head will go to cleave + // B49A => West Safe + // B49B => East Safe + type: 'Ability', + netRegex: { id: ['B49A', 'B49B'], source: 'Lindwurm', capture: true }, + condition: (data) => data.phase === 'doorboss', + infoText: (_data, matches, output) => { + if (matches.id === 'B49A') + return output.goWest!(); + return output.goEast!(); + }, + outputStrings: { + goEast: Outputs.east, + goWest: Outputs.west, + }, + }, + { + id: 'R12S Fourth-wall Fusion Stack', + type: 'HeadMarker', + netRegex: { id: headMarkerData['stack'], capture: true }, + condition: (data) => { + if (data.role === 'tank') + return false; + return true; + }, + durationSeconds: 5.1, + response: Responses.stackMarkerOn(), + }, + { + id: 'R12S Tankbuster', + type: 'HeadMarker', + netRegex: { id: headMarkerData['tankbuster'], capture: true }, + condition: Conditions.targetIsYou(), + durationSeconds: 5.1, + response: Responses.tankBuster(), + }, + { + id: 'R12S In Line Debuff Collector', + type: 'GainsEffect', + netRegex: { effectId: ['BBC', 'BBD', 'BBE', 'D7B'] }, + run: (data, matches) => { + const effectToNum: { [effectId: string]: number } = { + BBC: 1, + BBD: 2, + BBE: 3, + D7B: 4, + } as const; + const num = effectToNum[matches.effectId]; + if (num === undefined) + return; + data.inLine[matches.target] = num; + }, + }, + { + id: 'R12S Bonds of Flesh Flesh α/β Collect', + // Bonds of Flesh has the following timings: + // 1st - 26s + // 2nd - 31s + // 3rd - 36s + // 4rth - 41s + type: 'GainsEffect', + netRegex: { effectId: ['1290', '1292'], capture: true }, + condition: Conditions.targetIsYou(), + run: (data, matches) => { + data.myFleshBonds = matches.effectId === '1290' ? 'alpha' : 'beta'; + }, + }, + { + id: 'R12S In Line Debuff', + type: 'GainsEffect', + netRegex: { effectId: ['BBC', 'BBD', 'BBE', 'D7B'], capture: false }, + delaySeconds: 0.5, + durationSeconds: 10, + suppressSeconds: 1, + infoText: (data, _matches, output) => { + const myNum = data.inLine[data.me]; + if (myNum === undefined) + return; + const flesh = data.myFleshBonds; + if (flesh === undefined) + return output.order!({ + num: myNum + }); + if (flesh === 'alpha') { + switch (myNum) { + case 1: + return output.alpha1!(); + case 2: + return output.alpha2!(); + case 3: + return output.alpha3!(); + case 4: + return output.alpha4!(); + } + } + switch (myNum) { + case 1: + return output.beta1!(); + case 2: + return output.beta2!(); + case 3: + return output.beta3!(); + case 4: + return output.beta4!(); + } + }, + outputStrings: { + alpha1: { + en: '1α: Wait for Tether 1', + }, + alpha2: { + en: '2α: Wait for Tether 2', + }, + alpha3: { + en: '3α: Blob Tower 1', + }, + alpha4: { + en: '4α: Blob Tower 2', + }, + beta1: { + en: '1β: Wait for Tether 1', + }, + beta2: { + en: '2β: Wait for Tether 2', + }, + beta3: { + en: '3β: Chain Tower 1', + }, + beta4: { + en: '4β: Chain Tower 2', + }, + order: { + en: '${num}', + de: '${num}', + fr: '${num}', + ja: '${num}', + cn: '${num}', + ko: '${num}', + tc: '${num}', + }, + unknown: Outputs.unknown, + }, + }, + { + id: 'R12S Phagocyte Spotlight Blob Tower Location Collect', + // StartsUsing and StartsUsingExtra can have bad data, there is enough time that Ability is sufficient + // Pattern 1 + // Blob 1: (104, 104) SE Inner + // Blob 2: (96, 96) NW Inner + // Blob 3: (85, 110) SW Outer + // Blob 4: (115, 90) NE Outer + // Pattern 2 + // Blob 1: (104, 96) NE Inner + // Blob 2: (96, 104) SW Inner + // Blob 3: (85, 90) NW Outer + // Blob 4: (115, 110) SE Outer + // Pattern 3 + // Blob 1: (96, 96) NW Inner + // Blob 2: (104, 104) SE Inner + // Blob 3: (115, 90) NE Outer + // Blob 4: (85, 110) SW Outer + // Pattern 4 + // Blob 1: (96, 104) SW Inner + // Blob 2: (104, 96) NE Inner + // Blob 3: (115, 110) SE Outer + // Blob 4: (86, 90) NW Outer + type: 'Ability', + netRegex: { id: 'B4B6', capture: true }, + run: (data, matches) => { + const x = parseFloat(matches.x); + const y = parseFloat(matches.y); + data.blobTowerDirs.push(Directions.xyToIntercardDirOutput(x, y, center.x, center.y)); + }, + }, + { + id: 'R12S Phagocyte Spotlight Blob Tower Location (Early)', + // 23.8s until B4B7 Rolling Mass Blob Tower Hit + type: 'Ability', + netRegex: { id: 'B4B6', capture: true }, + condition: (data) => { + if (data.myFleshBonds === 'alpha') { + const myNum = data.inLine[data.me]; + if ( + (myNum === 1 && data.blobTowerDirs.length === 3) || + (myNum === 2 && data.blobTowerDirs.length === 4) || + (myNum === 3 && data.blobTowerDirs.length === 1) || + (myNum === 4 && data.blobTowerDirs.length === 2) + ) + return true; + } + return false; + }, + delaySeconds: 0.1, + durationSeconds: (data) => { + const myNum = data.inLine[data.me]; + // Timings based on next trigger + switch (myNum) { + case 1: + return 13; + case 2: + return 16; + case 3: + return 17; + case 4: + return 15; + } + }, + infoText: (data, _matches, output) => { + const myNum = data.inLine[data.me]; + if (myNum === undefined) + return; + + type index = { + [key: number]: number; + }; + const myNumToDirIndex: index = { + 1: 2, + 2: 3, + 3: 0, + 4: 1, + }; + const dirIndex = myNumToDirIndex[myNum]; + if (dirIndex === undefined) + return; + const towerNum = dirIndex + 1; + + const dir = data.blobTowerDirs[dirIndex]; + if (dir === undefined) + return; + + if (myNum > 2) + return output.innerBlobTower!({ + num: towerNum, + dir: output[dir]!(), + }); + return output.outerBlobTower!({ num: towerNum, dir: output[dir]!() }); + }, + outputStrings: { + ...Directions.outputStringsIntercardDir, + innerBlobTower: { + en: 'Blob Tower ${num} Inner ${dir} (later)', + }, + outerBlobTower: { + en: 'Blob Tower ${num} Outer ${dir} (later)', + }, + }, + }, + { + id: 'R12S Cell Chain Counter', + type: 'Tether', + netRegex: { id: headMarkerData['cellChainTether'], capture: false }, + condition: (data) => data.phase === 'doorboss', + run: (data) => data.cellChainCount = data.cellChainCount + 1, + }, + { + id: 'R12S Cell Chain Tether Number', + // Helpful for players to keep track of which chain tower is next + // Does not output when it is their turn to break the tether + type: 'Tether', + netRegex: { id: headMarkerData['cellChainTether'], capture: false }, + condition: (data) => { + if (data.phase === 'doorboss' && data.myFleshBonds === 'beta') + return true; + return false; + }, + infoText: (data, _matches, output) => { + const myNum = data.inLine[data.me]; + const num = data.cellChainCount; + if (myNum !== num) + return output.tether!({ num: num }); + if (myNum === undefined) + return output.tether!({ num: num }); + }, + outputStrings: { + tether: { + en: 'Tether ${num}', + de: 'Verbindung ${num}', + fr: 'Lien ${num}', + ja: '線 ${num}', + cn: '线 ${num}', + ko: '선 ${num}', + tc: '線 ${num}', + }, + }, + }, + { + id: 'R12S Chain Tower Number', + // Using B4B4 Dramatic Lysis to detect chain broken + type: 'Ability', + netRegex: { id: 'B4B4', capture: false }, + condition: (data) => { + if (data.phase === 'doorboss' && data.myFleshBonds === 'beta') + return true; + return false; + }, + suppressSeconds: 1, + alertText: (data, _matches, output) => { + const mechanicNum = data.cellChainCount; + const myNum = data.inLine[data.me]; + if (myNum === undefined) + return; + + type index = { + [key: number]: number; + }; + const myNumToOrder: index = { + 1: 3, + 2: 4, + 3: 1, + 4: 2, + }; + + const myOrder = myNumToOrder[myNum]; + if (myOrder === undefined) + return; + + if (myOrder === mechanicNum) + return output.tower!({ num: mechanicNum }); + }, + outputStrings: { + tower: { + en: 'Get Chain Tower ${num}', + }, + }, + }, + { + id: 'R12S Chain Tower Counter', + // Using B4B3 Roiling Mass to detect chain tower soak + // Also using B4B2 Unmitigated Explosion if missed tower + type: 'Ability', + netRegex: { id: ['B4B3', 'B4B2'], capture: false }, + suppressSeconds: 1, + run: (data) => data.cellTowerCount = data.cellTowerCount + 1, + }, + { + id: 'R12S Chain Tower Followup', + // Using B4B3 Roiling Mass to detect chain tower soak + // Beta player leaving early may get hit by alpha's chain break aoe + type: 'Ability', + netRegex: { id: 'B4B3', capture: true }, + condition: (data, matches) => { + if (data.myFleshBonds === 'beta' && data.me === matches.target) + return true; + return false; + }, + infoText: (data, _matches, output) => { + const mechanicNum = data.cellTowerCount; + const myNum = data.inLine[data.me]; + if (myNum === undefined) + return; + + type index = { + [key: number]: number; + }; + const myNumToOrder: index = { + 1: 3, + 2: 4, + 3: 1, + 4: 2, + }; + + const myOrder = myNumToOrder[myNum]; + if (myOrder === undefined) + return; + + if (myOrder === mechanicNum) { + if (mechanicNum < 4) + return output.goIntoMiddle!(); + return output.getOut!(); + } + }, + outputStrings: { + getOut: { + en: 'Get Out', + de: 'Raus da', + fr: 'Sortez', + ja: '外へ', + cn: '远离', + ko: '밖으로', + tc: '遠離', + }, + goIntoMiddle: Outputs.goIntoMiddle, + }, + }, + { + id: 'R12S Bonds of Flesh Flesh α First Two Towers', + // These are not dependent on player timings and so can be hard coded by duration + type: 'GainsEffect', + netRegex: { effectId: '1290', capture: true }, + condition: (data, matches) => { + if (matches.target === data.me) { + const duration = parseFloat(matches.duration); + if (duration < 35) + return false; + return true; + } + return false; + }, + delaySeconds: (_data, matches) => { + const duration = parseFloat(matches.duration); + if (duration > 35) + return 27; + return 32; + }, + infoText: (data, matches, output) => { + const duration = parseFloat(matches.duration); + const dir = data.blobTowerDirs[duration > 40 ? 1 : 0]; + if (duration > 40) { + if (dir !== undefined) + return output.alpha4Dir!({ dir: output[dir]!() }); + return output.alpha4!(); + } + if (dir !== undefined) + return output.alpha3Dir!({ dir: output[dir]!() }); + return output.alpha3!(); + }, + outputStrings: { + ...Directions.outputStringsIntercardDir, + alpha3: { + en: 'Get Blob Tower 1', + }, + alpha4: { + en: 'Get Blob Tower 2', + }, + alpha3Dir: { + en: 'Blob Tower 1 (Inner ${dir})', + }, + alpha4Dir: { + en: 'Blob Tower 2 (Inner ${dir})', + }, + }, + }, + { + id: 'R12S Unbreakable Flesh α/β Chains and Last Two Towers', + type: 'GainsEffect', + netRegex: { effectId: ['1291', '1293'], capture: true }, + condition: (data, matches) => { + if (matches.target === data.me && data.phase === 'doorboss') + return true; + return false; + }, + infoText: (data, matches, output) => { + const myNum = data.inLine[data.me]; + const flesh = matches.effectId === '1291' ? 'alpha' : 'beta'; + if (flesh === 'alpha') { + if (myNum === 1) { + const dir = data.blobTowerDirs[2]; + if (dir !== undefined) + return output.alpha1Dir!({ + chains: output.breakChains!(), + dir: output[dir]!(), + }); + } + if (myNum === 2) { + const dir = data.blobTowerDirs[3]; + if (dir !== undefined) + return output.alpha2Dir!({ + chains: output.breakChains!(), + dir: output[dir]!(), + }); + } + + // dir undefined or 3rd/4rth in line + switch (myNum) { + case 1: + return output.alpha1!({ chains: output.breakChains!() }); + case 2: + return output.alpha2!({ chains: output.breakChains!() }); + case 3: + return output.alpha3!({ chains: output.breakChains!() }); + case 4: + return output.alpha4!({ chains: output.breakChains!() }); + } + } + switch (myNum) { + case 1: + return output.beta1!({ chains: output.breakChains!() }); + case 2: + return output.beta2!({ chains: output.breakChains!() }); + case 3: + return output.beta3!({ chains: output.breakChains!() }); + case 4: + return output.beta4!({ chains: output.breakChains!() }); + } + return output.getTowers!(); + }, + outputStrings: { + ...Directions.outputStringsIntercardDir, + breakChains: Outputs.breakChains, + getTowers: Outputs.getTowers, + alpha1: { + en: '${chains} 1 + Blob Tower 3 (Outer)', + }, + alpha1Dir: { + en: '${chains} 1 + Blob Tower 3 (Outer ${dir})', + }, + alpha2: { + en: '${chains} 2 + Blob Tower 4 (Outer)', + }, + alpha2Dir: { + en: '${chains} 2 + Blob Tower 4 (Outer ${dir})', + }, + alpha3: { + en: '${chains} 3 + Get Out', + }, + alpha4: { + en: '${chains} 4 + Get Out', + }, + beta1: { + en: '${chains} 1 => Get Middle', + }, + beta2: { + en: '${chains} 2 => Get Middle', + }, + beta3: { + en: '${chains} 3 => Wait for last pair', + }, + beta4: { + en: '${chains} 4 + Get Out', + }, + }, + }, + { + id: 'R12S Splattershed', + type: 'StartsUsing', + netRegex: { id: ['B9C3', 'B9C4'], source: 'Lindwurm', capture: false }, + response: Responses.aoe(), + }, + { + id: 'R12S Mitotic Phase Direction Collect', + // Unknown_DE6 spell contains data in its count + type: 'GainsEffect', + netRegex: { effectId: 'DE6', capture: true }, + condition: Conditions.targetIsYou(), + durationSeconds: 10, + infoText: (data, matches, output) => { + data.myMitoticPhase = matches.count; + switch (matches.count) { + case '436': + return output.frontTower!(); + case '437': + return output.rightTower!(); + case '438': + return output.rearTower!(); + case '439': + return output.leftTower!(); + } + }, + outputStrings: { + frontTower: { + en: 'Tower (S/SW)', + }, + rearTower: { + en: 'Tower (N/NE)', + }, + leftTower: { + en: 'Tower (E/SE)', + }, + rightTower: { + en: 'Tower (W/NW)', + }, + }, + }, + { + id: 'R12S Grand Entrance Intercards/Cardinals', + // B4A1 is only cast when cardinals are safe + // B4A2 is only cast when intercardinals are safe + // These casts more than once, so just capture first event + type: 'StartsUsing', + netRegex: { id: ['B4A1', 'B4A2'], capture: false }, + suppressSeconds: 5, + infoText: (data, matches, output) => { + const count = data.myMitoticPhase; + if (count === undefined) + return; + if (matches.id === 'B4A1') { + switch (count) { + case '436': + return output.frontCardinals!(); + case '437': + return output.rightCardinals!(); + case '438': + return output.rearCardinals!(); + case '439': + return output.leftCardinals!(); + } + } + switch (count) { + case '436': + return output.frontIntercards!(); + case '437': + return output.rightIntercards!(); + case '438': + return output.rearIntercards!(); + case '439': + return output.leftIntercards!(); + } + }, + outputStrings: { + frontIntercards: Outputs.southwest, + rearIntercards: Outputs.northeast, + leftIntercards: Outputs.southeast, + rightIntercards: Outputs.northwest, + frontCardinals: Outputs.south, + rearCardinals: Outputs.north, + leftCardinals: Outputs.east, + rightCardinals: Outputs.west, + }, + }, + { + id: 'R12S Rotting Flesh', + type: 'GainsEffect', + netRegex: { effectId: '129B', capture: true }, + condition: Conditions.targetIsYou(), + durationSeconds: 10, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Rotting Flesh on YOU', + }, + }, + }, + { + id: 'R12S Rotting Flesh Collect', + type: 'GainsEffect', + netRegex: { effectId: '129B', capture: true }, + condition: Conditions.targetIsYou(), + run: (data) => data.hasRot === true, + }, + { + id: 'R12S Ravenous Reach 2', + // These two syncs indicate the animation of where the head will go to cleave + // B49A => West Safe + // B49B => East Safe + type: 'Ability', + netRegex: { id: ['B49A', 'B49B'], source: 'Lindwurm', capture: true }, + condition: (data) => data.phase === 'curtainCall', + alertText: (data, matches, output) => { + if (matches.id === 'B49A') { + return data.hasRot ? output.getHitEast!() : output.safeWest!(); + } + return data.hasRot ? output.getHitWest!() : output.safeEast!(); + }, + outputStrings: { + getHitWest: { + en: 'Spread in West Breadth', + }, + getHitEast: { + en: 'Spread in East Breadth', + }, + safeEast: { + en: 'Spread East', + }, + safeWest: { + en: 'Spread West', + }, + }, + }, + { + id: 'R12S Split Scourge and Venomous Scourge', + // B4AB Split Scourge and B4A8 Venomous Scourge are instant casts + // This actor control happens along with boss becoming targetable + type: 'ActorControl', + netRegex: { command: '8000000D', data0: '1E01', capture: false }, + durationSeconds: 9, + suppressSeconds: 1, + infoText: (data, _matches, output) => { + if (data.role === 'tank') + return output.tank!(); + return output.party!(); + }, + outputStrings: { + tank: { + en: 'Bait Line AoE from heads', + }, + party: { + en: 'Spread, Away from heads', + }, + }, + }, + { + id: 'R12S Grotesquerie: Curtain Call Spreads', + type: 'StartsUsing', + netRegex: { id: 'BEC0', source: 'Lindwurm', capture: false }, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: 'Bait 5x Puddles', + }, + }, + { + id: 'R12S Curtain Call: Unbreakable Flesh α/β Chains', + type: 'GainsEffect', + netRegex: { effectId: ['1291', '1293'], capture: true }, + condition: (data, matches) => { + if (matches.target === data.me && data.phase === 'curtainCall') + return true; + return false; + }, + infoText: (_data, matches, output) => { + const flesh = matches.effectId === '1291' ? 'alpha' : 'beta'; + if (flesh === 'alpha') + return output.alphaChains!(); + return output.betaChains!(); + }, + outputStrings: { + alphaChains: Outputs.breakChains, + betaChains: Outputs.breakChains, + }, + }, + { + id: 'R12S Slaughtershed', + type: 'StartsUsing', + netRegex: { id: ['B4C6', 'B4C3'], source: 'Lindwurm', capture: false }, + response: Responses.bigAoe('alert'), + }, + { + id: 'R12S Slaughtershed Stack', + // TODO: Get Safe spot + type: 'HeadMarker', + netRegex: { id: headMarkerData['slaughterStack'], capture: true }, + condition: (data, matches) => { + const isDPS = data.party.isDPS(matches.target); + if (isDPS && data.role === 'dps') + return true; + if (!isDPS && data.role !== 'dps') + return true; + return false; + }, + durationSeconds: 5.1, + response: Responses.stackMarkerOn(), + }, + { + id: 'R12S Slaughtershed Spread', + // TODO: Get Safe spot + type: 'HeadMarker', + netRegex: { id: headMarkerData['slaughterSpread'], capture: true }, + condition: Conditions.targetIsYou(), + durationSeconds: 5.1, + suppressSeconds: 1, + response: Responses.spread(), + }, + { + id: 'R12S Serpintine Scourge Right Hand First', + // Left Hand first, then Right Hand + type: 'Ability', + netRegex: { id: 'B4CB', source: 'Lindwurm', capture: false }, + condition: (data) => data.phase === 'slaughtershed', + durationSeconds: 12, + infoText: (_data, _matches, output) => output.rightThenLeft!(), + outputStrings: { + rightThenLeft: Outputs.rightThenLeft, + }, + }, + { + id: 'R12S Serpintine Scourge Left Hand First', + // Right Hand first, then Left Hand + type: 'Ability', + netRegex: { id: 'B4CD', source: 'Lindwurm', capture: false }, + condition: (data) => data.phase === 'slaughtershed', + durationSeconds: 12, + infoText: (_data, _matches, output) => output.leftThenRight!(), + outputStrings: { + leftThenRight: Outputs.leftThenRight, + }, + }, + { + id: 'R12S Raptor Knuckles Right Hand First', + // Right Hand first, then Left Hand + type: 'Ability', + netRegex: { id: 'B4CC', source: 'Lindwurm', capture: false }, + condition: (data) => data.phase === 'slaughtershed', + durationSeconds: 12, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Northwest: Knockback to Northeast', + }, + }, + }, + { + id: 'R12S Raptor Knuckles Left Hand First', + // Left Hand first, then Right Hand + type: 'Ability', + netRegex: { id: 'B4CE', source: 'Lindwurm', capture: false }, + condition: (data) => data.phase === 'slaughtershed', + durationSeconds: 12, + infoText: (_data, _matches, output) => output.text!(), + outputStrings: { + text: { + en: 'Northeast: Knockback to Northwest', + }, + }, + }, + ], + timelineReplace: [ + { + 'locale': 'cn', + 'replaceSync': { + 'Lindwurm': '林德布鲁姆', + }, + 'replaceText': { + '\\(huge\\)': '(大)', + 'Bloodshed': '流血', + 'Bring Down the House': '震场', + '(? Date: Mon, 19 Jan 2026 08:24:37 -0500 Subject: [PATCH 02/31] lint --- ui/raidboss/data/07-dt/raid/r12s.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index beec50f111..aae6d5e609 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -216,8 +216,8 @@ const triggerSet: TriggerSet = { const cleave = data.grotesquerieCleave; if (cleave === undefined) return data.phase === 'doorboss' - ? output.baitThenSpread!() - : output.spreadCurtain!(); + ? output.baitThenSpread!() + : output.spreadCurtain!(); return data.phase === 'doorboss' ? output.baitThenSpreadCleave!({ cleave: output[cleave]!() }) : output.spreadCurtain!(); @@ -352,9 +352,7 @@ const triggerSet: TriggerSet = { return; const flesh = data.myFleshBonds; if (flesh === undefined) - return output.order!({ - num: myNum - }); + return output.order!({ num: myNum }); if (flesh === 'alpha') { switch (myNum) { case 1: From 4d181c4c2486aacbb5565ba6199b74d7f03fad16 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 08:27:20 -0500 Subject: [PATCH 03/31] unused capture, remove timelinereplace copy from r12n --- ui/raidboss/data/07-dt/raid/r12s.ts | 35 ++--------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index aae6d5e609..961273b747 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -448,7 +448,7 @@ const triggerSet: TriggerSet = { id: 'R12S Phagocyte Spotlight Blob Tower Location (Early)', // 23.8s until B4B7 Rolling Mass Blob Tower Hit type: 'Ability', - netRegex: { id: 'B4B6', capture: true }, + netRegex: { id: 'B4B6', capture: false }, condition: (data) => { if (data.myFleshBonds === 'alpha') { const myNum = data.inLine[data.me]; @@ -1064,38 +1064,7 @@ const triggerSet: TriggerSet = { }, }, ], - timelineReplace: [ - { - 'locale': 'cn', - 'replaceSync': { - 'Lindwurm': '林德布鲁姆', - }, - 'replaceText': { - '\\(huge\\)': '(大)', - 'Bloodshed': '流血', - 'Bring Down the House': '震场', - '(? Date: Mon, 19 Jan 2026 08:29:28 -0500 Subject: [PATCH 04/31] fix typo/paste error with labels --- ui/raidboss/data/07-dt/raid/r12s.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.txt b/ui/raidboss/data/07-dt/raid/r12s.txt index b3f0f22ee0..e3186605a4 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.txt +++ b/ui/raidboss/data/07-dt/raid/r12s.txt @@ -136,10 +136,10 @@ hideall "--sync--" 456.1 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } 459.8 "Serpentine Scourge Right" Ability { id: "B4D2", source: "Lindwurm" } 460.8 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } -464.4 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-slaughtershed2" +464.4 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed2" # Serpentine Scourge Right First -540.6 label jump "r12s-p1-scourge-right-1" +540.6 label "r12s-p1-scourge-right-1" 547.6 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } 547.6 "Fourth-wall Fusion" Ability { id: "B4D5", source: "Lindwurm" } 548.0 "Burst" Ability { id: "B49F", source: "Lindwurm" } @@ -147,7 +147,7 @@ hideall "--sync--" 554.1 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } 557.7 "Serpentine Scourge Left" Ability { id: "B4D1", source: "Lindwurm" } 558.7 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } -562.4 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-slaughtershed2" +562.4 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed2" # Raptor Knuckles Left First 641.1 label "r12s-p1-raptor-left-1" @@ -158,7 +158,7 @@ hideall "--sync--" 654.4 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } 658.3 "Raptor Knuckles Northwest" Ability { id: "B4CF", source: "Lindwurm" } 659.1 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } -662.9 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-slaughtershed2" +662.9 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed2" # Raptor Knuckles Right First 742.7 label "r12s-p1-raptor-right-1" @@ -169,10 +169,10 @@ hideall "--sync--" 756.1 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } 759.9 "Raptor Knuckles Northeast" Ability { id: "B4D0", source: "Lindwurm" } 760.7 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } -764.5 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-slaughtershed2" +764.5 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed2" # Slaughtershed 2 -864.4 label "r12s-slaughtershed2" +864.4 label "r12s-p1-slaughtershed2" 867.4 "Slaughtershed 2 (castbar)" Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } 869.8 "Slaughtershed 2" Ability { id: "ADC9", source: "Lindwurm" } From d0a69406bc9a60243f2309a5ce714ae9a77291a2 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 08:35:12 -0500 Subject: [PATCH 05/31] add missing capture --- ui/raidboss/data/07-dt/raid/r12s.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 961273b747..9394d7cf0a 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -839,7 +839,7 @@ const triggerSet: TriggerSet = { // B4A2 is only cast when intercardinals are safe // These casts more than once, so just capture first event type: 'StartsUsing', - netRegex: { id: ['B4A1', 'B4A2'], capture: false }, + netRegex: { id: ['B4A1', 'B4A2'], capture: true }, suppressSeconds: 5, infoText: (data, matches, output) => { const count = data.myMitoticPhase; From e6bbdf107ad4bfc6f1962e6b334414deabd8dfa7 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 08:35:40 -0500 Subject: [PATCH 06/31] remove erroneous 3 character --- ui/raidboss/data/07-dt/raid/r12s.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.txt b/ui/raidboss/data/07-dt/raid/r12s.txt index e3186605a4..faa2d1a78b 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.txt +++ b/ui/raidboss/data/07-dt/raid/r12s.txt @@ -245,7 +245,7 @@ hideall "--sync--" 1400.4 "--sync--" Ability { id: "B4CC", source: "Lindwurm" } jump "r12s-p1-raptor-right-3" 1407.4 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } 1407.4 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } -1407.8 "Burst" 3Ability { id: "B49F", source: "Lindwurm" } +1407.8 "Burst" Ability { id: "B49F", source: "Lindwurm" } 1412.9 "Serpentine Scourge/Raptor Knuckles?" #Ability { id: ["B4D1", "B4D2", "B4CD", "B4CE"], source: "Lindwurm" } 1413.9 "Serpentine Scourge/--knockback--?" #Ability { id: ["B9BC", "B9C7"], source: "Lindwurm" } 1417.6 "Serpentine Scourge/Raptor Knuckles?" #Ability { id: ["B4D2", "B4D1", "B4CE", "B4CD"], source: "Lindwurm" } From 4226f7bd86b4bff0b6f2d36a0d5c812c6763e0b6 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 08:39:26 -0500 Subject: [PATCH 07/31] paste error --- ui/raidboss/data/07-dt/raid/r12s.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.txt b/ui/raidboss/data/07-dt/raid/r12s.txt index faa2d1a78b..9b6e500445 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.txt +++ b/ui/raidboss/data/07-dt/raid/r12s.txt @@ -288,7 +288,7 @@ hideall "--sync--" 1636.8 "Refreshing Overkill (Enrage)?" #Ability { id: "B53A", source: "Lindwurm" } # Raptor Knuckles Left Third -1700.4 label "r12s-p1-raptor-right-3" +1700.4 label "r12s-p1-raptor-left-3" 1707.4 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } 1707.4 "Fourth-wall Fusion" Ability { id: "B4D5", source: "Lindwurm" } 1707.8 "Burst" Ability { id: "B49F", source: "Lindwurm" } From e62af8d9ec709631ddc6987c8588319b648d14ed Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 16:08:59 -0500 Subject: [PATCH 08/31] fix ravenous reach 2 calls --- ui/raidboss/data/07-dt/raid/r12s.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 9394d7cf0a..2f6cca8cdc 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -672,7 +672,7 @@ const triggerSet: TriggerSet = { const duration = parseFloat(matches.duration); if (duration > 35) return 27; - return 32; + return 34; }, infoText: (data, matches, output) => { const duration = parseFloat(matches.duration); @@ -909,9 +909,9 @@ const triggerSet: TriggerSet = { condition: (data) => data.phase === 'curtainCall', alertText: (data, matches, output) => { if (matches.id === 'B49A') { - return data.hasRot ? output.getHitEast!() : output.safeWest!(); + return data.hasRot ? output.safeWest!() : output.getHitEast!(); } - return data.hasRot ? output.getHitWest!() : output.safeEast!(); + return data.hasRot ? output.safeEast!() : output.getHitWest!(); }, outputStrings: { getHitWest: { From 2ab3724d8fda030c607dc3ca1fe1331762e0c605 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 17:15:16 -0500 Subject: [PATCH 09/31] update curtain call break chains TODO: Find safe spots. --- ui/raidboss/data/07-dt/raid/r12s.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 2f6cca8cdc..a8781ec455 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -961,6 +961,7 @@ const triggerSet: TriggerSet = { }, { id: 'R12S Curtain Call: Unbreakable Flesh α/β Chains', + // TODO: Find safe spots type: 'GainsEffect', netRegex: { effectId: ['1291', '1293'], capture: true }, condition: (data, matches) => { @@ -970,13 +971,23 @@ const triggerSet: TriggerSet = { }, infoText: (_data, matches, output) => { const flesh = matches.effectId === '1291' ? 'alpha' : 'beta'; + const safeSpots = output.safeSpots!(); + const chains = output.breakChains!(); if (flesh === 'alpha') - return output.alphaChains!(); - return output.betaChains!(); + return output.alphaChains!( chains: chains, safe: safeSpots ); + return output.betaChains!( chains: chains, safeSpots ); }, outputStrings: { - alphaChains: Outputs.breakChains, - betaChains: Outputs.breakChains, + breakChains: Outputs.breakChains, + safeSpots: { + en: 'Avoid Blobs', + }, + alphaChains: { + en: '${chains} => ${safeSpots}', + }, + betaChains: { + en: '${chains} => ${safeSpots}', + }, }, }, { From 467ee5b0f913deb39c642058706bf5417ac0c9b1 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 17:17:53 -0500 Subject: [PATCH 10/31] fix previous commit --- ui/raidboss/data/07-dt/raid/r12s.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index a8781ec455..c7455fea27 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -974,8 +974,8 @@ const triggerSet: TriggerSet = { const safeSpots = output.safeSpots!(); const chains = output.breakChains!(); if (flesh === 'alpha') - return output.alphaChains!( chains: chains, safe: safeSpots ); - return output.betaChains!( chains: chains, safeSpots ); + return output.alphaChains!({ chains: chains, safe: safeSpots }); + return output.betaChains!({ chains: chains, safe: safeSpots }); }, outputStrings: { breakChains: Outputs.breakChains, From 3a166e7ea1ba75ded13edfd16a64d7e5d07b4e72 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 18:00:59 -0500 Subject: [PATCH 11/31] blob towers called via pattern, add knockback for bind --- ui/raidboss/data/07-dt/raid/r12s.ts | 81 +++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index c7455fea27..81947c8f61 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -438,43 +438,56 @@ const triggerSet: TriggerSet = { // Blob 4: (86, 90) NW Outer type: 'Ability', netRegex: { id: 'B4B6', capture: true }, + suppressSeconds: 10, run: (data, matches) => { const x = parseFloat(matches.x); const y = parseFloat(matches.y); + const dir = Directions.xyToIntercardDirOutput(x, y, center.x, center.y); data.blobTowerDirs.push(Directions.xyToIntercardDirOutput(x, y, center.x, center.y)); + + if (dir === 'dirSE') { + data.blobTowerDirs.push('dirNW'); + data.blobTowerDirs.push('dirSW'); + data.blobTowerDirs.push('dirNE'); + } + else if (dir === 'dirNE') { + data.blobTowerDirs.push('dirSW'); + data.blobTowerDirs.push('dirNW'); + data.blobTowerDirs.push('dirSE'); + } + else if (dir === 'dirNW') { + data.blobTowerDirs.push('dirSE'); + data.blobTowerDirs.push('dirNE'); + data.blobTowerDirs.push('dirSW'); + } + else if (dir === 'dirSW') { + data.blobTowerDirs.push('dirNE'); + data.blobTowerDirs.push('dirSE'); + data.blobTowerDirs.push('dirNW'); + } }, }, { id: 'R12S Phagocyte Spotlight Blob Tower Location (Early)', // 23.8s until B4B7 Rolling Mass Blob Tower Hit + // Only need to know first blob location type: 'Ability', netRegex: { id: 'B4B6', capture: false }, - condition: (data) => { - if (data.myFleshBonds === 'alpha') { - const myNum = data.inLine[data.me]; - if ( - (myNum === 1 && data.blobTowerDirs.length === 3) || - (myNum === 2 && data.blobTowerDirs.length === 4) || - (myNum === 3 && data.blobTowerDirs.length === 1) || - (myNum === 4 && data.blobTowerDirs.length === 2) - ) - return true; - } - return false; - }, + condition: (data) => data.myFleshBonds === 'alpha', + suppressSeconds: 10, delaySeconds: 0.1, durationSeconds: (data) => { const myNum = data.inLine[data.me]; // Timings based on next trigger switch (myNum) { case 1: - return 13; + return 17; case 2: - return 16; + return 22; case 3: - return 17; + return 18; case 4: - return 15; + return 18; } }, infoText: (data, _matches, output) => { @@ -517,6 +530,16 @@ const triggerSet: TriggerSet = { }, }, }, + { + id: 'R12S Cursed Coil Bind Knocbkack', + // Using Phagocyte Spotlight, 1st one happens 7s before bind + // Delayed additionally to reduce overlap with alpha tower location calls + type: 'Ability', + netRegex: { id: 'B4B6', capture: false }, + suppressSeconds: 10, + delaySeconds: 4, // 4s warning + response: Responses.knockback(), + }, { id: 'R12S Cell Chain Counter', type: 'Tether', @@ -971,11 +994,20 @@ const triggerSet: TriggerSet = { }, infoText: (_data, matches, output) => { const flesh = matches.effectId === '1291' ? 'alpha' : 'beta'; - const safeSpots = output.safeSpots!(); - const chains = output.breakChains!(); if (flesh === 'alpha') - return output.alphaChains!({ chains: chains, safe: safeSpots }); - return output.betaChains!({ chains: chains, safe: safeSpots }); + return output.alphaChains!({ + chains: output.breakChains!(), + safe: output.safeSpots!(), + }); + if (flesh === 'beta') + return output.betaChains!({ + chains: output.breakChains!(), + safe: output.breakChains!(), + }); + return output.unknownChains!({ + chains: output.breakChains!(), + safe: output.breakChains!(), + }); }, outputStrings: { breakChains: Outputs.breakChains, @@ -983,10 +1015,13 @@ const triggerSet: TriggerSet = { en: 'Avoid Blobs', }, alphaChains: { - en: '${chains} => ${safeSpots}', + en: '${chains} => ${safe}', }, betaChains: { - en: '${chains} => ${safeSpots}', + en: '${chains} => ${safe}', + }, + unknownChains: { + en: '${chains} => ${safe}', }, }, }, From de6493fc1bd27c7608c99421a0983df82680ce6d Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 18:03:42 -0500 Subject: [PATCH 12/31] lint --- ui/raidboss/data/07-dt/raid/r12s.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 81947c8f61..eebcd89f8b 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -449,18 +449,15 @@ const triggerSet: TriggerSet = { data.blobTowerDirs.push('dirNW'); data.blobTowerDirs.push('dirSW'); data.blobTowerDirs.push('dirNE'); - } - else if (dir === 'dirNE') { + } else if (dir === 'dirNE') { data.blobTowerDirs.push('dirSW'); data.blobTowerDirs.push('dirNW'); data.blobTowerDirs.push('dirSE'); - } - else if (dir === 'dirNW') { + } else if (dir === 'dirNW') { data.blobTowerDirs.push('dirSE'); data.blobTowerDirs.push('dirNE'); data.blobTowerDirs.push('dirSW'); - } - else if (dir === 'dirSW') { + } else if (dir === 'dirSW') { data.blobTowerDirs.push('dirNE'); data.blobTowerDirs.push('dirSE'); data.blobTowerDirs.push('dirNW'); From f8651f991e14fd32dfd17b91a45a40390ba25a33 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 18:06:05 -0500 Subject: [PATCH 13/31] replace function with previous dir const --- ui/raidboss/data/07-dt/raid/r12s.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index eebcd89f8b..fa96229325 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -443,7 +443,7 @@ const triggerSet: TriggerSet = { const x = parseFloat(matches.x); const y = parseFloat(matches.y); const dir = Directions.xyToIntercardDirOutput(x, y, center.x, center.y); - data.blobTowerDirs.push(Directions.xyToIntercardDirOutput(x, y, center.x, center.y)); + data.blobTowerDirs.push(dir); if (dir === 'dirSE') { data.blobTowerDirs.push('dirNW'); From 996bab0dc754ccfebe4a593c2f63c050b0e25263 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 18:07:28 -0500 Subject: [PATCH 14/31] fix suppressSeconds order --- ui/raidboss/data/07-dt/raid/r12s.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index fa96229325..60ef978f95 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -471,7 +471,6 @@ const triggerSet: TriggerSet = { type: 'Ability', netRegex: { id: 'B4B6', capture: false }, condition: (data) => data.myFleshBonds === 'alpha', - suppressSeconds: 10, delaySeconds: 0.1, durationSeconds: (data) => { const myNum = data.inLine[data.me]; @@ -487,6 +486,7 @@ const triggerSet: TriggerSet = { return 18; } }, + suppressSeconds: 10, infoText: (data, _matches, output) => { const myNum = data.inLine[data.me]; if (myNum === undefined) @@ -533,8 +533,8 @@ const triggerSet: TriggerSet = { // Delayed additionally to reduce overlap with alpha tower location calls type: 'Ability', netRegex: { id: 'B4B6', capture: false }, - suppressSeconds: 10, delaySeconds: 4, // 4s warning + suppressSeconds: 10, response: Responses.knockback(), }, { From b81f1f649e3c9fc2b32126a649c92279f463ba8a Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 18:27:04 -0500 Subject: [PATCH 15/31] add beta Tether => Tower outputs --- ui/raidboss/data/07-dt/raid/r12s.ts | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 60ef978f95..4417cd6f9d 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -558,8 +558,27 @@ const triggerSet: TriggerSet = { infoText: (data, _matches, output) => { const myNum = data.inLine[data.me]; const num = data.cellChainCount; - if (myNum !== num) + if (myNum !== num) { + if (myNum === 1 && num === 3) + return output.beta1Tower!({ + tether: output.tether!({ num: num }) + }); + if (myNum === 2 && num === 4) + return output.beta2Tower!({ + tether: output.tether!({ num: num }), + }); + if (myNum === 3 && num === 1) + return output.beta3Tower!({ + tether: output.tether!({num: num }), + }); + if (myNum === 4 && num === 2) + return output.beta4Tower!({ + tether: output.tether!({ num: num }), + }); + return output.tether!({ num: num }); + } + if (myNum === undefined) return output.tether!({ num: num }); }, @@ -573,6 +592,18 @@ const triggerSet: TriggerSet = { ko: '선 ${num}', tc: '線 ${num}', }, + beta1Tower: { + en: '${tether} => Chain Tower 3', + }, + beta2Tower: { + en: '${tether} => Chain Tower 4', + }, + beta3Tower: { + en: '${tether} => Chain Tower 1', + }, + beta4Tower: { + en: '${tether} => Chain Tower 2', + }, }, }, { From 55173924e6c5c2717a3fbe15b31166fe7a837d6b Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 18:29:09 -0500 Subject: [PATCH 16/31] lint --- ui/raidboss/data/07-dt/raid/r12s.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 4417cd6f9d..8730fd692c 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -561,7 +561,7 @@ const triggerSet: TriggerSet = { if (myNum !== num) { if (myNum === 1 && num === 3) return output.beta1Tower!({ - tether: output.tether!({ num: num }) + tether: output.tether!({ num: num }), }); if (myNum === 2 && num === 4) return output.beta2Tower!({ @@ -569,7 +569,7 @@ const triggerSet: TriggerSet = { }); if (myNum === 3 && num === 1) return output.beta3Tower!({ - tether: output.tether!({num: num }), + tether: output.tether!({ num: num }), }); if (myNum === 4 && num === 2) return output.beta4Tower!({ From b298c9552bb7d58bc782432516a83c1d4f8a877d Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 19:06:02 -0500 Subject: [PATCH 17/31] fix delay for fist two blob towers --- ui/raidboss/data/07-dt/raid/r12s.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 8730fd692c..df32bdf2c2 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -721,20 +721,21 @@ const triggerSet: TriggerSet = { }, delaySeconds: (_data, matches) => { const duration = parseFloat(matches.duration); - if (duration > 35) - return 27; - return 34; + // The following gives 5s warning to take tower + if (duration > 37) + return 31; // Alpha4 Time + return 26; // Alpha3 Time }, infoText: (data, matches, output) => { const duration = parseFloat(matches.duration); const dir = data.blobTowerDirs[duration > 40 ? 1 : 0]; if (duration > 40) { if (dir !== undefined) - return output.alpha4Dir!({ dir: output[dir]!() }); + return output.alpha4Dir!({ dir: output[dir]!(), dur: duration }); return output.alpha4!(); } if (dir !== undefined) - return output.alpha3Dir!({ dir: output[dir]!() }); + return output.alpha3Dir!({ dir: output[dir]!(), dur: duration }); return output.alpha3!(); }, outputStrings: { @@ -746,10 +747,10 @@ const triggerSet: TriggerSet = { en: 'Get Blob Tower 2', }, alpha3Dir: { - en: 'Blob Tower 1 (Inner ${dir})', + en: 'Blob Tower 1 (Inner ${dir}) ${dur}', }, alpha4Dir: { - en: 'Blob Tower 2 (Inner ${dir})', + en: 'Blob Tower 2 (Inner ${dir}) ${dur}', }, }, }, From e502f7030ff264eaeb0efb26607c86ee32b1672d Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 19:10:45 -0500 Subject: [PATCH 18/31] add blob tower followup, reorder triggers --- ui/raidboss/data/07-dt/raid/r12s.ts | 149 ++++++++++++++++++---------- 1 file changed, 95 insertions(+), 54 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index df32bdf2c2..74bd2ae545 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -21,6 +21,7 @@ export interface Data extends RaidbossData { inLine: { [name: string]: number }; blobTowerDirs: string[]; fleshBondsCount: number; + skinsplitterCount: number; cellChainCount: number; cellTowerCount: number; myMitoticPhase?: string; @@ -63,6 +64,7 @@ const triggerSet: TriggerSet = { // Phase 1 inLine: {}, blobTowerDirs: [], + skinsplitterCount: 0, fleshBondsCount: 0, cellChainCount: 0, cellTowerCount: 0, @@ -537,6 +539,21 @@ const triggerSet: TriggerSet = { suppressSeconds: 10, response: Responses.knockback(), }, + { + id: 'R12S Skinsplitter Counter', + // These occur every 5s + // Useful for blob tower tracking that happen 2s after + // 2: Tether 1 + // 3: Tether 2 + Blob Tower 1 + // 4: Tether 3 + Blob Tower 2 + // 5: Tether 4 + Blob Tower 3 + // 6: Blob Tower 4 + // 7: Last time to exit + type: 'Ability', + netRegex: { id: 'B4BC', capture: false }, + suppressSeconds: 1, + run: (data) => data.skinsplitterCount = data.skinsplitterCount + 1, + }, { id: 'R12S Cell Chain Counter', type: 'Tether', @@ -655,56 +672,6 @@ const triggerSet: TriggerSet = { suppressSeconds: 1, run: (data) => data.cellTowerCount = data.cellTowerCount + 1, }, - { - id: 'R12S Chain Tower Followup', - // Using B4B3 Roiling Mass to detect chain tower soak - // Beta player leaving early may get hit by alpha's chain break aoe - type: 'Ability', - netRegex: { id: 'B4B3', capture: true }, - condition: (data, matches) => { - if (data.myFleshBonds === 'beta' && data.me === matches.target) - return true; - return false; - }, - infoText: (data, _matches, output) => { - const mechanicNum = data.cellTowerCount; - const myNum = data.inLine[data.me]; - if (myNum === undefined) - return; - - type index = { - [key: number]: number; - }; - const myNumToOrder: index = { - 1: 3, - 2: 4, - 3: 1, - 4: 2, - }; - - const myOrder = myNumToOrder[myNum]; - if (myOrder === undefined) - return; - - if (myOrder === mechanicNum) { - if (mechanicNum < 4) - return output.goIntoMiddle!(); - return output.getOut!(); - } - }, - outputStrings: { - getOut: { - en: 'Get Out', - de: 'Raus da', - fr: 'Sortez', - ja: '外へ', - cn: '远离', - ko: '밖으로', - tc: '遠離', - }, - goIntoMiddle: Outputs.goIntoMiddle, - }, - }, { id: 'R12S Bonds of Flesh Flesh α First Two Towers', // These are not dependent on player timings and so can be hard coded by duration @@ -844,6 +811,80 @@ const triggerSet: TriggerSet = { }, }, }, + { + id: 'R12S Chain Tower Followup', + // Using B4B3 Roiling Mass to detect chain tower soak + // Beta player leaving early may get hit by alpha's chain break aoe + type: 'Ability', + netRegex: { id: 'B4B3', capture: true }, + condition: (data, matches) => { + if (data.myFleshBonds === 'beta' && data.me === matches.target) + return true; + return false; + }, + infoText: (data, _matches, output) => { + const mechanicNum = data.cellTowerCount; + const myNum = data.inLine[data.me]; + if (myNum === undefined) + return; + + type index = { + [key: number]: number; + }; + const myNumToOrder: index = { + 1: 3, + 2: 4, + 3: 1, + 4: 2, + }; + + const myOrder = myNumToOrder[myNum]; + if (myOrder === undefined) + return; + + if (myOrder === mechanicNum) { + if (mechanicNum < 4) + return output.goIntoMiddle!(); + return output.getOut!(); + } + }, + outputStrings: { + getOut: { + en: 'Get Out', + de: 'Raus da', + fr: 'Sortez', + ja: '外へ', + cn: '远离', + ko: '밖으로', + tc: '遠離', + }, + goIntoMiddle: Outputs.goIntoMiddle, + }, + }, + { + id: 'R12S Blob Tower Followup', + // Using B4B7 Roiling Mass to detect chain tower soak + // Alpha 3 and Alpha 4 get the inner towers before their chains + type: 'Ability', + netRegex: { id: 'B4B7', capture: true }, + condition: (data, matches) => { + if (data.myFleshBonds === 'alpha' && data.me === matches.target) + return true; + return false; + }, + infoText: (data, _matches, output) => { + const mechanicNum = data.skinsplitterCount; + const myNum = data.inLine[data.me]; + if (myNum === undefined) + return; + + if (myNum === mechanicNum) + return output.goIntoMiddle!(); + }, + outputStrings: { + goIntoMiddle: Outputs.goIntoMiddle, + }, + }, { id: 'R12S Splattershed', type: 'StartsUsing', @@ -967,10 +1008,10 @@ const triggerSet: TriggerSet = { }, outputStrings: { getHitWest: { - en: 'Spread in West Breadth', + en: 'Spread in West Cleave', }, getHitEast: { - en: 'Spread in East Breadth', + en: 'Spread in East Cleave', }, safeEast: { en: 'Spread East', @@ -1116,7 +1157,7 @@ const triggerSet: TriggerSet = { type: 'Ability', netRegex: { id: 'B4CC', source: 'Lindwurm', capture: false }, condition: (data) => data.phase === 'slaughtershed', - durationSeconds: 12, + durationSeconds: 15, infoText: (_data, _matches, output) => output.text!(), outputStrings: { text: { @@ -1130,7 +1171,7 @@ const triggerSet: TriggerSet = { type: 'Ability', netRegex: { id: 'B4CE', source: 'Lindwurm', capture: false }, condition: (data) => data.phase === 'slaughtershed', - durationSeconds: 12, + durationSeconds: 15, infoText: (_data, _matches, output) => output.text!(), outputStrings: { text: { From 310a608cfcf4f6027173b51f57b504264e382e2e Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 20:25:14 -0500 Subject: [PATCH 19/31] rework chain tower to use skinsplitter count --- ui/raidboss/data/07-dt/raid/r12s.ts | 109 +++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 11 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 74bd2ae545..ce6a537fb2 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -23,7 +23,6 @@ export interface Data extends RaidbossData { fleshBondsCount: number; skinsplitterCount: number; cellChainCount: number; - cellTowerCount: number; myMitoticPhase?: string; hasRot: boolean; // Phase 2 @@ -67,7 +66,6 @@ const triggerSet: TriggerSet = { skinsplitterCount: 0, fleshBondsCount: 0, cellChainCount: 0, - cellTowerCount: 0, hasRot: false, // Phase 2 }), @@ -663,15 +661,6 @@ const triggerSet: TriggerSet = { }, }, }, - { - id: 'R12S Chain Tower Counter', - // Using B4B3 Roiling Mass to detect chain tower soak - // Also using B4B2 Unmitigated Explosion if missed tower - type: 'Ability', - netRegex: { id: ['B4B3', 'B4B2'], capture: false }, - suppressSeconds: 1, - run: (data) => data.cellTowerCount = data.cellTowerCount + 1, - }, { id: 'R12S Bonds of Flesh Flesh α First Two Towers', // These are not dependent on player timings and so can be hard coded by duration @@ -860,6 +849,104 @@ const triggerSet: TriggerSet = { }, goIntoMiddle: Outputs.goIntoMiddle, }, + }, { + id: 'R12S Chain Tower Followup', + // Using B4B3 Roiling Mass to detect chain tower soak + // Beta player leaving early may get hit by alpha's chain break aoe + type: 'Ability', + netRegex: { id: 'B4B3', capture: true }, + condition: (data, matches) => { + if (data.myFleshBonds === 'beta' && data.me === matches.target) + return true; + return false; + }, + infoText: (data, _matches, output) => { + // Possibly the count could be off if break late (giving damage and damage down) + // Ideal towers are soaked: + // Beta 1 at 5th Skinsplitter + // Beta 2 at 6th Skinsplitter + // Beta 3 at 3rd Skinsplitter + // Beta 4 at 4rth Skinsplitter + const mechanicNum = data.skinsplitterCount; + const myNum = data.inLine[data.me]; + if (myNum === undefined) { + // This can be corrected by the player later + if (mechanicNum < 5) + return output.goIntoMiddle!(); + return output.getOut!(); + } + + if (mechanicNum < 5) { + if (myNum === 1) + return output.beta1Middle!(); + if (myNum === 2) + return output.beta2Middle!(); + if (myNum === 3) + return output.beta3Middle!(); + if (myNum === 4) + return output.beta4Middle!(); + } + if (myNum === 1) + return output.beta1Out!(); + if (myNum === 2) + return output.beta2Out!(); + if (myNum === 3) + return output.beta3Out!(); + if (myNum === 4) + return output.beta4Out!(); + }, + outputStrings: { + getOut: { + en: 'Get Out', + de: 'Raus da', + fr: 'Sortez', + ja: '外へ', + cn: '远离', + ko: '밖으로', + tc: '遠離', + }, + goIntoMiddle: Outputs.goIntoMiddle, + beta1Middle: Outputs.goIntoMiddle, + beta2Middle: Outputs.goIntoMiddle, // Should not happen under ideal situation + beta3Middle: Outputs.goIntoMiddle, + beta4Middle: Outputs.goIntoMiddle, + beta1Out: { // Should not happen under ideal situation + en: 'Get Out', + de: 'Raus da', + fr: 'Sortez', + ja: '外へ', + cn: '远离', + ko: '밖으로', + tc: '遠離', + }, + beta2Out: { + en: 'Get Out', + de: 'Raus da', + fr: 'Sortez', + ja: '外へ', + cn: '远离', + ko: '밖으로', + tc: '遠離', + }, + beta3Out: { // Should not happen under ideal situation + en: 'Get Out', + de: 'Raus da', + fr: 'Sortez', + ja: '外へ', + cn: '远离', + ko: '밖으로', + tc: '遠離', + }, + beta4Out: { // Should not happen under ideal situation + en: 'Get Out', + de: 'Raus da', + fr: 'Sortez', + ja: '外へ', + cn: '远离', + ko: '밖으로', + tc: '遠離', + }, + }, }, { id: 'R12S Blob Tower Followup', From 52e9f7f859d3fa56f632ae0054f6a24ba3553050 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 20:26:21 -0500 Subject: [PATCH 20/31] remove a duration from output --- ui/raidboss/data/07-dt/raid/r12s.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index ce6a537fb2..4a309114f4 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -687,11 +687,11 @@ const triggerSet: TriggerSet = { const dir = data.blobTowerDirs[duration > 40 ? 1 : 0]; if (duration > 40) { if (dir !== undefined) - return output.alpha4Dir!({ dir: output[dir]!(), dur: duration }); + return output.alpha4Dir!({ dir: output[dir]!() }); return output.alpha4!(); } if (dir !== undefined) - return output.alpha3Dir!({ dir: output[dir]!(), dur: duration }); + return output.alpha3Dir!({ dir: output[dir]!() }); return output.alpha3!(); }, outputStrings: { @@ -703,10 +703,10 @@ const triggerSet: TriggerSet = { en: 'Get Blob Tower 2', }, alpha3Dir: { - en: 'Blob Tower 1 (Inner ${dir}) ${dur}', + en: 'Blob Tower 1 (Inner ${dir})', }, alpha4Dir: { - en: 'Blob Tower 2 (Inner ${dir}) ${dur}', + en: 'Blob Tower 2 (Inner ${dir})', }, }, }, From 29da224ebab32b97f532ea0c4f8b8d0b08e8060a Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 20:29:43 -0500 Subject: [PATCH 21/31] fix paste error --- ui/raidboss/data/07-dt/raid/r12s.ts | 49 ----------------------------- 1 file changed, 49 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 4a309114f4..ed9c8f09d5 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -801,55 +801,6 @@ const triggerSet: TriggerSet = { }, }, { - id: 'R12S Chain Tower Followup', - // Using B4B3 Roiling Mass to detect chain tower soak - // Beta player leaving early may get hit by alpha's chain break aoe - type: 'Ability', - netRegex: { id: 'B4B3', capture: true }, - condition: (data, matches) => { - if (data.myFleshBonds === 'beta' && data.me === matches.target) - return true; - return false; - }, - infoText: (data, _matches, output) => { - const mechanicNum = data.cellTowerCount; - const myNum = data.inLine[data.me]; - if (myNum === undefined) - return; - - type index = { - [key: number]: number; - }; - const myNumToOrder: index = { - 1: 3, - 2: 4, - 3: 1, - 4: 2, - }; - - const myOrder = myNumToOrder[myNum]; - if (myOrder === undefined) - return; - - if (myOrder === mechanicNum) { - if (mechanicNum < 4) - return output.goIntoMiddle!(); - return output.getOut!(); - } - }, - outputStrings: { - getOut: { - en: 'Get Out', - de: 'Raus da', - fr: 'Sortez', - ja: '外へ', - cn: '远离', - ko: '밖으로', - tc: '遠離', - }, - goIntoMiddle: Outputs.goIntoMiddle, - }, - }, { id: 'R12S Chain Tower Followup', // Using B4B3 Roiling Mass to detect chain tower soak // Beta player leaving early may get hit by alpha's chain break aoe From 01b9d528850c6d52f1830ecc37e8a7fe51f012f8 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 20:32:03 -0500 Subject: [PATCH 22/31] fix hasRot collect --- ui/raidboss/data/07-dt/raid/r12s.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index ed9c8f09d5..d391bcbab8 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -1028,7 +1028,7 @@ const triggerSet: TriggerSet = { type: 'GainsEffect', netRegex: { effectId: '129B', capture: true }, condition: Conditions.targetIsYou(), - run: (data) => data.hasRot === true, + run: (data) => data.hasRot = true, }, { id: 'R12S Ravenous Reach 2', @@ -1040,9 +1040,9 @@ const triggerSet: TriggerSet = { condition: (data) => data.phase === 'curtainCall', alertText: (data, matches, output) => { if (matches.id === 'B49A') { - return data.hasRot ? output.safeWest!() : output.getHitEast!(); + return data.hasRot ? output.getHitEast!(): output.safeWest!(); } - return data.hasRot ? output.safeEast!() : output.getHitWest!(); + return data.hasRot ? output.getHitWest!(): output.safeEast!(); }, outputStrings: { getHitWest: { From 6f4802c4b4d0f109904fc6bb83121224ba9c9e63 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 20:41:29 -0500 Subject: [PATCH 23/31] missing space --- ui/raidboss/data/07-dt/raid/r12s.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index d391bcbab8..cbf143dfae 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -1040,9 +1040,9 @@ const triggerSet: TriggerSet = { condition: (data) => data.phase === 'curtainCall', alertText: (data, matches, output) => { if (matches.id === 'B49A') { - return data.hasRot ? output.getHitEast!(): output.safeWest!(); + return data.hasRot ? output.getHitEast!() : output.safeWest!(); } - return data.hasRot ? output.getHitWest!(): output.safeEast!(); + return data.hasRot ? output.getHitWest!() : output.safeEast!(); }, outputStrings: { getHitWest: { From 17afe3c640065053007d604d9d83ea7253eea56d Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 20:43:53 -0500 Subject: [PATCH 24/31] reduce 1s delay for knockback --- ui/raidboss/data/07-dt/raid/r12s.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index cbf143dfae..de61e2d713 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -533,7 +533,7 @@ const triggerSet: TriggerSet = { // Delayed additionally to reduce overlap with alpha tower location calls type: 'Ability', netRegex: { id: 'B4B6', capture: false }, - delaySeconds: 4, // 4s warning + delaySeconds: 3, // 5s warning suppressSeconds: 10, response: Responses.knockback(), }, From a355b827545ce50affecdfeb7af588e6dfa5a4d6 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Mon, 19 Jan 2026 20:48:02 -0500 Subject: [PATCH 25/31] increase break chains to alert and adjust output slightly --- ui/raidboss/data/07-dt/raid/r12s.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index de61e2d713..703ab6cf7e 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -682,7 +682,7 @@ const triggerSet: TriggerSet = { return 31; // Alpha4 Time return 26; // Alpha3 Time }, - infoText: (data, matches, output) => { + alertText: (data, matches, output) => { const duration = parseFloat(matches.duration); const dir = data.blobTowerDirs[duration > 40 ? 1 : 0]; if (duration > 40) { @@ -703,10 +703,10 @@ const triggerSet: TriggerSet = { en: 'Get Blob Tower 2', }, alpha3Dir: { - en: 'Blob Tower 1 (Inner ${dir})', + en: 'Get Blob Tower 1 (Inner ${dir})', }, alpha4Dir: { - en: 'Blob Tower 2 (Inner ${dir})', + en: 'Get Blob Tower 2 (Inner ${dir})', }, }, }, @@ -719,7 +719,7 @@ const triggerSet: TriggerSet = { return true; return false; }, - infoText: (data, matches, output) => { + alertText: (data, matches, output) => { const myNum = data.inLine[data.me]; const flesh = matches.effectId === '1291' ? 'alpha' : 'beta'; if (flesh === 'alpha') { @@ -796,7 +796,7 @@ const triggerSet: TriggerSet = { en: '${chains} 3 => Wait for last pair', }, beta4: { - en: '${chains} 4 + Get Out', + en: '${chains} 4 => Get Out', }, }, }, From 260cebde0ce1bb4bd2c9e05c27f606ca8d000e12 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Tue, 20 Jan 2026 20:18:14 -0500 Subject: [PATCH 26/31] add refreshing overkill, some initial p2 triggers --- ui/raidboss/data/07-dt/raid/r12s.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 703ab6cf7e..892679eb11 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -1217,6 +1217,34 @@ const triggerSet: TriggerSet = { }, }, }, + { + id: 'R12S Refreshing Overkill', + // 10s castTime that could end with enrage or raidwide + type: 'StartsUsing', + netRegex: { id: 'B538', source: 'Lindwurm', capture: true }, + delaySeconds: (_data, matches) => parseFloat(matches.castTime) - 4, + durationSeconds: 4.7, + response: Responses.bigAoe('alert'), + }, + // Phase 2 + { + id: 'R12S Arcadia Aflame', + type: 'StartsUsing', + netRegex: { id: 'B528', source: 'Lindwurm', capture: false }, + response: Responses.bigAoe('alert'), + }, + { + id: 'R12S Snaking Kick', + type: 'StartsUsing', + netRegex: { id: 'B527', source: 'Lindwurm', capture: true }, + response: Responses.getBehind(), + }, + { + id: 'R12S Double Sobat', + type: 'StartsUsing', + netRegex: { id: 'B520', source: 'Lindwurm', capture: true }, + response: Responses.tankCleave(), + }, ], timelineReplace: [], }; From f6ddae7d29cbbe0d4d51ae24550091f47f9d5565 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Tue, 20 Jan 2026 20:22:29 -0500 Subject: [PATCH 27/31] fix enrage startsUsing, clean p2 output using addedcombatant sync, add transition --- ui/raidboss/data/07-dt/raid/r12s.txt | 43 +++++++++++++++++----------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.txt b/ui/raidboss/data/07-dt/raid/r12s.txt index 9b6e500445..5fb6dbf904 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.txt +++ b/ui/raidboss/data/07-dt/raid/r12s.txt @@ -11,7 +11,7 @@ hideall "--sync--" # -it "Lindwurm" 0.0 "--sync--" InCombat { inGameCombat: "1" } window 0,1 -#1.0 "--sync--" AddedCombatant { npcNameId: "", name: "Lindwurm", job: "00", level: "5A", ownerId: "0{4}", worldId: "00" } window 10,3 jump 3000.5 # Sync to P2 immediately through AddCombatant. +1.0 "--sync--" AddedCombatant { npcNameId: "14378", name: "Lindwurm", job: "00", level: "1", ownerId: "0{4}", worldId: "00" } window 10,3 jump r12s-p2-start # Sync to P2 immediately through AddCombatant. 15.6 "The Fixer" Ability { id: "B4D7", source: "Lindwurm" } window 20,10 25.8 "--sync--" Ability { id: "B7C4", source: "Lindwurm" } 40.9 "Mortal Slayer 1" Ability { id: ["B496", "B498"], source: "Lindwurm" } @@ -264,7 +264,7 @@ hideall "--sync--" 1516.9 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } 1526.5 "--sync--" StartsUsing { id: "B2C7", source: "Lindwurm" } jump "r12s-p1-enrage-alt" 1526.5 "--untargetable?--" -1527.7 "--sync--" StartsUsing { id: "B538", source: "Lindwurm" } jump "r12s-p1-enrage" +1526.7 "--sync--" StartsUsing { id: "B538", source: "Lindwurm" } jump "r12s-p1-enrage" 1531.5 "The Fixer (Enrage)?" #Ability { id: "B2C7", source: "Lindwurm" } 1536.7 "Refreshing Overkill (Enrage)?" #Ability { id: "B538", source: "Lindwurm" } 1536.8 "--untargetable?--" @@ -281,7 +281,7 @@ hideall "--sync--" 1618.6 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } 1626.5 "--sync--" StartsUsing { id: "B2C7", source: "Lindwurm" } jump "r12s-p1-enrage-alt" 1626.5 "--untargetable?--" -1627.7 "--sync--" StartsUsing { id: "B538", source: "Lindwurm" } jump "r12s-p1-enrage" +1626.7 "--sync--" StartsUsing { id: "B538", source: "Lindwurm" } jump "r12s-p1-enrage" 1631.5 "The Fixer (Enrage)?" #Ability { id: "B2C7", source: "Lindwurm" } 1636.7 "Refreshing Overkill (Enrage)?" #Ability { id: "B538", source: "Lindwurm" } 1636.8 "--untargetable?--" @@ -298,7 +298,7 @@ hideall "--sync--" 1718.3 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } 1726.5 "--sync--" StartsUsing { id: "B2C7", source: "Lindwurm" } jump "r12s-p1-enrage-alt" 1726.5 "--untargetable?--" -1727.7 "--sync--" StartsUsing { id: "B538", source: "Lindwurm" } jump "r12s-p1-enrage" +1726.7 "--sync--" StartsUsing { id: "B538", source: "Lindwurm" } jump "r12s-p1-enrage" 1731.5 "The Fixer (Enrage)?" #Ability { id: "B2C7", source: "Lindwurm" } 1736.7 "Refreshing Overkill (Enrage)?" #Ability { id: "B538", source: "Lindwurm" } 1736.8 "--untargetable?--" @@ -315,28 +315,39 @@ hideall "--sync--" 1818.3 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } 1826.5 "--sync--" StartsUsing { id: "B2C7", source: "Lindwurm" } jump "r12s-p1-enrage-alt" 1826.5 "--untargetable?--" -1827.7 "--sync--" StartsUsing { id: "B538", source: "Lindwurm" } jump "r12s-p1-enrage" +1826.7 "--sync--" StartsUsing { id: "B538", source: "Lindwurm" } jump "r12s-p1-enrage" 1831.5 "The Fixer (Enrage)?" #Ability { id: "B2C7", source: "Lindwurm" } 1836.7 "Refreshing Overkill (Enrage)?" #Ability { id: "B538", source: "Lindwurm" } 1836.8 "--untargetable?--" 1836.8 "Refreshing Overkill (Enrage)?" #Ability { id: "B53A", source: "Lindwurm" } -# Enrage sequence 1 -1927.7 label "r12s-p1-enrage" -1936.7 "Refreshing Overkill (Enrage)" Ability { id: "B538", source: "Lindwurm" } -1936.8 "--untargetable--" -1936.8 "Refreshing Overkill (Enrage)" Ability { id: "B53A", source: "Lindwurm" } +# Enrage sequence (Above 20%?) +1926.5 label "r12s-p1-enrage-alt" +1931.5 "The Fixer (Enrage)" Ability { id: "B2C7", source: "Lindwurm" } -# Enrage sequence 2 (Above 20%?) -2026.5 label "r12s-p1-enrage-alt" -2031.5 "The Fixer (Enrage)" Ability { id: "B2C7", source: "Lindwurm" } +# Enrage sequence +2027.7 label "r12s-p1-enrage" +2036.7 "Refreshing Overkill (Enrage)?" Ability { id: "B538", source: "Lindwurm" } +2036.8 "--untargetable--" +2036.8 "Refreshing Overkill (Enrage)?" Ability { id: "B53A", source: "Lindwurm" } + +# Kill/Transition sequence +2036.8 "Refreshing Overkill" Ability { id: "B539", source: "Lindwurm" } +2073.0 "--sync--" Ability { id: "BB9C", source: "Lindwurm" } +2073.5 "Down for the Count" duration 42 +2075.7 "--sync--" Ability { id: "B53B", source: "Lindwurm" } +2117.7 "--targetable--" ### Phase 2: Lindwurm II -# -p B528:3014.9 +# -p B528:3012.1 # -ii B51F -3010.2 "--sync--" StartsUsing { id: "B528", source: "Lindwurm" } window 3100,10 -3014.9 "Arcadia Aflame" Ability { id: "B528", source: "Lindwurm" } +# -it "Lindwurm" +3000.5 label "r12s-p2-start" +3007.1 "--sync--" StartsUsing { id: "B528", source: "Lindwurm" } window 3100,10 +3012.1 "Arcadia Aflame" Ability { id: "B528", source: "Lindwurm" } +3019.3 "--middle--" Ability { id: "B4D9", source: "Lindwurm" } +3024.4 "Replication" Ability { id: "B4D8", source: "Lindwurm" } # TBD # IGNORED ABILITIES From cbcc8635a71604ec37fa478f74f2591246adc1bf Mon Sep 17 00:00:00 2001 From: Legends0 Date: Tue, 20 Jan 2026 20:23:08 -0500 Subject: [PATCH 28/31] unused capture --- ui/raidboss/data/07-dt/raid/r12s.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 892679eb11..873a9b1e3b 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -1236,7 +1236,7 @@ const triggerSet: TriggerSet = { { id: 'R12S Snaking Kick', type: 'StartsUsing', - netRegex: { id: 'B527', source: 'Lindwurm', capture: true }, + netRegex: { id: 'B527', source: 'Lindwurm', capture: false }, response: Responses.getBehind(), }, { From 02615e765616000729a2e2d552f4cb36c8d11654 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Tue, 20 Jan 2026 20:23:53 -0500 Subject: [PATCH 29/31] lint --- ui/raidboss/data/07-dt/raid/r12s.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.ts b/ui/raidboss/data/07-dt/raid/r12s.ts index 873a9b1e3b..58d5066218 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.ts +++ b/ui/raidboss/data/07-dt/raid/r12s.ts @@ -1222,7 +1222,7 @@ const triggerSet: TriggerSet = { // 10s castTime that could end with enrage or raidwide type: 'StartsUsing', netRegex: { id: 'B538', source: 'Lindwurm', capture: true }, - delaySeconds: (_data, matches) => parseFloat(matches.castTime) - 4, + delaySeconds: (_data, matches) => parseFloat(matches.castTime) - 4, durationSeconds: 4.7, response: Responses.bigAoe('alert'), }, From 87a0c92bb8fa5063126516bdf2a8c97ba7f1de42 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Tue, 20 Jan 2026 20:27:34 -0500 Subject: [PATCH 30/31] add quotes to jump --- ui/raidboss/data/07-dt/raid/r12s.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.txt b/ui/raidboss/data/07-dt/raid/r12s.txt index 5fb6dbf904..e72d73a4de 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.txt +++ b/ui/raidboss/data/07-dt/raid/r12s.txt @@ -11,7 +11,7 @@ hideall "--sync--" # -it "Lindwurm" 0.0 "--sync--" InCombat { inGameCombat: "1" } window 0,1 -1.0 "--sync--" AddedCombatant { npcNameId: "14378", name: "Lindwurm", job: "00", level: "1", ownerId: "0{4}", worldId: "00" } window 10,3 jump r12s-p2-start # Sync to P2 immediately through AddCombatant. +1.0 "--sync--" AddedCombatant { npcNameId: "14378", name: "Lindwurm", job: "00", level: "1", ownerId: "0{4}", worldId: "00" } window 10,3 jump "r12s-p2-start" # Sync to P2 immediately through AddCombatant. 15.6 "The Fixer" Ability { id: "B4D7", source: "Lindwurm" } window 20,10 25.8 "--sync--" Ability { id: "B7C4", source: "Lindwurm" } 40.9 "Mortal Slayer 1" Ability { id: ["B496", "B498"], source: "Lindwurm" } From 3016544fbce2ae33e561e9d87ec9f3f991da8810 Mon Sep 17 00:00:00 2001 From: Legends0 Date: Thu, 22 Jan 2026 01:53:21 -0500 Subject: [PATCH 31/31] replace forcejumps with jumps + lookahead lines --- ui/raidboss/data/07-dt/raid/r12s.txt | 59 ++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/ui/raidboss/data/07-dt/raid/r12s.txt b/ui/raidboss/data/07-dt/raid/r12s.txt index e72d73a4de..9d3b6c1d36 100644 --- a/ui/raidboss/data/07-dt/raid/r12s.txt +++ b/ui/raidboss/data/07-dt/raid/r12s.txt @@ -136,7 +136,12 @@ hideall "--sync--" 456.1 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } 459.8 "Serpentine Scourge Right" Ability { id: "B4D2", source: "Lindwurm" } 460.8 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } -464.4 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed2" +464.4 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } jump "r12s-p1-slaughtershed2" +467.4 "Slaughtershed 2 (castbar)" #Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } +469.8 "Slaughtershed 2" #Ability { id: "ADC9", source: "Lindwurm" } +478.5 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } +478.5 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } +478.9 "Burst" #Ability { id: "B49F", source: "Lindwurm" } # Serpentine Scourge Right First 540.6 label "r12s-p1-scourge-right-1" @@ -147,7 +152,12 @@ hideall "--sync--" 554.1 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } 557.7 "Serpentine Scourge Left" Ability { id: "B4D1", source: "Lindwurm" } 558.7 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } -562.4 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed2" +562.4 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } jump "r12s-p1-slaughtershed2" +567.4 "Slaughtershed 2 (castbar)" #Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } +569.8 "Slaughtershed 2" #Ability { id: "ADC9", source: "Lindwurm" } +578.5 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } +578.5 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } +578.9 "Burst" #Ability { id: "B49F", source: "Lindwurm" } # Raptor Knuckles Left First 641.1 label "r12s-p1-raptor-left-1" @@ -158,7 +168,12 @@ hideall "--sync--" 654.4 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } 658.3 "Raptor Knuckles Northwest" Ability { id: "B4CF", source: "Lindwurm" } 659.1 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } -662.9 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed2" +662.9 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } jump "r12s-p1-slaughtershed2" +667.4 "Slaughtershed 2 (castbar)" #Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } +669.8 "Slaughtershed 2" #Ability { id: "ADC9", source: "Lindwurm" } +678.5 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } +678.5 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } +678.9 "Burst" #Ability { id: "B49F", source: "Lindwurm" } # Raptor Knuckles Right First 742.7 label "r12s-p1-raptor-right-1" @@ -169,7 +184,12 @@ hideall "--sync--" 756.1 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } 759.9 "Raptor Knuckles Northeast" Ability { id: "B4D0", source: "Lindwurm" } 760.7 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } -764.5 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed2" +764.5 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } jump "r12s-p1-slaughtershed2" +767.4 "Slaughtershed 2 (castbar)" #Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } +769.8 "Slaughtershed 2" #Ability { id: "ADC9", source: "Lindwurm" } +778.5 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } +778.5 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } +778.9 "Burst" #Ability { id: "B49F", source: "Lindwurm" } # Slaughtershed 2 864.4 label "r12s-p1-slaughtershed2" @@ -199,7 +219,13 @@ hideall "--sync--" 985.1 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } 988.7 "Serpentine Scourge Right" Ability { id: "B4D2", source: "Lindwurm" } 989.7 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } -993.3 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed3" +993.3 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } jump "r12s-p1-slaughtershed3" +996.3 "Slaughtershed 3 (castbar)" #Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } +998.7 "Slaughtershed 3" #Ability { id: "ADC9", source: "Lindwurm" } +1007.4 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } +1007.4 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } +1007.8 "Burst" #Ability { id: "B49F", source: "Lindwurm" } + # Serpentine Scourge Right Second 1069.9 label "r12s-p1-scourge-right-2" @@ -210,7 +236,13 @@ hideall "--sync--" 1083.4 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } 1087.0 "Serpentine Scourge Left" Ability { id: "B4D1", source: "Lindwurm" } 1088.0 "Serpentine Scourge" Ability { id: "B9BC", source: "Lindwurm" } -1091.7 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed3" +1091.7 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } jump "r12s-p1-slaughtershed3" +1096.3 "Slaughtershed 3 (castbar)" #Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } +1098.7 "Slaughtershed 3" #Ability { id: "ADC9", source: "Lindwurm" } +1107.4 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } +1107.4 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } +1107.8 "Burst" #Ability { id: "B49F", source: "Lindwurm" } + # Raptor Knuckles Left Second 1171.5 label "r12s-p1-raptor-left-2" @@ -221,7 +253,13 @@ hideall "--sync--" 1184.8 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } 1188.6 "Raptor Knuckles Northwest" Ability { id: "B4CF", source: "Lindwurm" } 1189.4 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } -1193.3 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed3" +1193.3 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } jump "r12s-p1-slaughtershed3" +1196.3 "Slaughtershed 3 (castbar)" #Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } +1198.7 "Slaughtershed 3" #Ability { id: "ADC9", source: "Lindwurm" } +1207.4 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } +1207.4 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } +1207.8 "Burst" #Ability { id: "B49F", source: "Lindwurm" } + # Raptor Knuckles Right Second 1271.5 label "r12s-p1-raptor-right-2" @@ -232,7 +270,12 @@ hideall "--sync--" 1284.8 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } 1288.6 "Raptor Knuckles Left" Ability { id: "B4D0", source: "Lindwurm" } 1289.4 "--knockback--" Ability { id: "B9C7", source: "Lindwurm" } -1293.3 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } forcejump "r12s-p1-slaughtershed3" +1293.3 "--sync--" StartsUsing { id: ["B4C3", "B4C6"], source: "Lindwurm" } jump "r12s-p1-slaughtershed3" +1296.3 "Slaughtershed 3 (castbar)" #Ability { id: ["B4C3", "B4C6"], source: "Lindwurm" } +1298.7 "Slaughtershed 3" #Ability { id: "ADC9", source: "Lindwurm" } +1307.4 "Dramatic Lysis x4" #Ability { id: "B4D4", source: "Lindwurm" } +1307.4 "Fourth-wall Fusion" #Ability { id: "B4D5", source: "Lindwurm" } +1307.8 "Burst" #Ability { id: "B49F", source: "Lindwurm" } # Slaughtershed 3 1393.3 label "r12s-p1-slaughtershed3"