Skip to content

Commit

Permalink
raidboss: Basic FRU P1 triggers (#516)
Browse files Browse the repository at this point in the history
This is partially based on an experimental set of triggers @valarnin
tossed in the ACT Discord server yesterday or the day before. I wasn't
able to get the Blasting Zone safe area triggers working, but apart from
that and the tank buster trigger, everything in here is stuff I was able
to test tonight and confirm as working. The timing for delays and
durations is all stuff that fits relatively closely to match mechanics.
(Castbars in phase 1 are a little longer than we're used to.)
  • Loading branch information
JLGarber authored Dec 1, 2024
1 parent 30e8167 commit ebc1d3c
Showing 1 changed file with 250 additions and 2 deletions.
252 changes: 250 additions & 2 deletions ui/raidboss/data/07-dt/ultimate/futures_rewritten.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,263 @@
import Outputs from '../../../../../resources/outputs';
import { Responses } from '../../../../../resources/responses';
import { DirectionOutput8, Directions } from '../../../../../resources/util';
import ZoneId from '../../../../../resources/zone_id';
import { RaidbossData } from '../../../../../types/data';
import { NetMatches } from '../../../../../types/net_matches';
import { TriggerSet } from '../../../../../types/trigger';

export type Data = RaidbossData;
export interface Data extends RaidbossData {
actorSetPosTracker: { [id: string]: NetMatches['ActorSetPos'] };
p1ConcealSafeDirs: DirectionOutput8[];
p1StackSpread?: 'stack' | 'spread';
p1FallOfFaithTethers: ('fire' | 'lightning')[];
}

const triggerSet: TriggerSet<Data> = {
id: 'FuturesRewrittenUltimate',
zoneId: ZoneId.FuturesRewrittenUltimate,
timelineFile: 'futures_rewritten.txt',
initData: () => {
return {
actorSetPosTracker: {},
p1ConcealSafeDirs: [...Directions.output8Dir],
p1FallOfFaithTethers: [],
};
},
timelineTriggers: [],
triggers: [],
triggers: [
// General triggers
{
id: 'FRU ActorSetPos Collector',
type: 'ActorSetPos',
netRegex: { id: '4[0-9A-F]{7}', capture: true },
run: (data, matches) => {
data.actorSetPosTracker[matches.id] = matches;
},
},
// P1 -- Fatebreaker
{
id: 'FRU P1 Cyclonic Break Fire',
type: 'StartsUsing',
netRegex: {
id: ['9CD0', '9D89'],
source: ['Fatebreaker', 'Fatebreaker\'s Image'],
capture: false,
},
durationSeconds: 8,
alertText: (_data, _matches, output) => output.clockPairs!(),
outputStrings: {
clockPairs: {
en: 'Clock spots => Pairs',
},
},
},
{
id: 'FRU P1 Cyclonic Break Lightning',
type: 'StartsUsing',
netRegex: {
id: ['9CD4', '9D8A'],
source: ['Fatebreaker', 'Fatebreaker\'s Image'],
capture: false,
},
durationSeconds: 8,
alertText: (_data, _matches, output) => output.clockSpread!(),
outputStrings: {
clockSpread: {
en: 'Clock spots => Spread',
},
},
},
{
id: 'FRU P1 Powder Mark Trail',
type: 'StartsUsing',
netRegex: { id: '9CE8', source: 'Fatebreaker', capture: true },
response: Responses.tankBusterSwap(),
},
{
id: 'FRU P1 Utopian Sky Collector',
type: 'StartsUsing',
netRegex: { id: ['9CDA', '9CDB'], capture: true },
run: (data, matches) => {
data.p1StackSpread = matches.id === '9CDA' ? 'stack' : 'spread';
},
},
{
id: 'FRU Conceal Safe',
type: 'ActorControlExtra',
netRegex: {
category: '003F',
param1: '4',
capture: true,
},
condition: (data) => data.p1StackSpread !== undefined,
durationSeconds: 8,
alertText: (data, matches, output) => {
const clone = data.actorSetPosTracker[matches.id];
if (clone === undefined)
return;
const dir1 = Directions.hdgTo8DirNum(parseFloat(clone.heading));
const dir2 = (dir1 + 4) % 8;
data.p1ConcealSafeDirs = data.p1ConcealSafeDirs.filter((dir) =>
dir !== Directions.outputFrom8DirNum(dir1) && dir !== Directions.outputFrom8DirNum(dir2)
);

if (data.p1ConcealSafeDirs.length !== 2)
return;

const [dir1Out, dir2Out] = data.p1ConcealSafeDirs;

if (dir1Out === undefined || dir2Out === undefined)
return;

return output.combo!({
dir1: output[dir1Out]!(),
dir2: output[dir2Out]!(),
mech: output[data.p1StackSpread ?? 'unknown']!(),
});
},
outputStrings: {
...Directions.outputStrings8Dir,
combo: {
en: '${dir1} / ${dir2} => ${mech}',
},
stack: Outputs.stacks,
spread: Outputs.spread,
},
},
{
id: 'FRU P1 Burnished Glory',
type: 'StartsUsing',
netRegex: { id: '9CEA', source: 'Fatebreaker', capture: false },
response: Responses.bleedAoe(),
},
{
id: 'FRU P1 Burnt Strike Fire',
type: 'StartsUsing',
netRegex: { source: 'Fatebreaker', id: '9CC1', capture: false },
durationSeconds: 8,
alertText: (_data, _matches, output) => output.text!(),
outputStrings: {
text: {
en: 'Line Cleave => Knockback',
de: 'Linien AoE => Rückstoß',
fr: 'AoE en ligne => Poussée',
ja: '直線範囲 => ノックバック',
cn: '直线 => 击退',
ko: '직선 장판 => 넉백',
},
},
},
{
id: 'FRU P1 Burnt Strike Lightning',
type: 'StartsUsing',
netRegex: { source: 'Fatebreaker', id: '9CC5', capture: false },
durationSeconds: 8,
alertText: (_data, _matches, output) => output.text!(),
outputStrings: {
text: {
en: 'Line Cleave => Out',
de: 'Linien AoE => Raus',
fr: 'AoE en ligne => Extérieur',
ja: '直線範囲 => 離れる',
cn: '直线 => 去外侧',
ko: '직선 장판 => 바깥으로',
},
},
},
{
id: 'FRU P1 Turn of the Heavens Fire',
type: 'StartsUsing',
netRegex: { id: '9CD6', source: 'Fatebreaker\'s Image', capture: false },
durationSeconds: 10,
infoText: (_data, _matches, output) => output.lightningSafe!(),
outputStrings: {
lightningSafe: {
en: 'Lightning Safe',
},
},
},
{
id: 'FRU P1 Turn of the Heavens Lightning',
type: 'StartsUsing',
netRegex: { id: '9CD7', source: 'Fatebreaker\'s Image', capture: false },
durationSeconds: 10,
infoText: (_data, _matches, output) => output.fireSafe!(),
outputStrings: {
fireSafe: {
en: 'Fire Safe',
},
},
},
{
id: 'FRU P1 Fall of Faith Collector',
type: 'StartsUsing',
netRegex: {
id: ['9CC9', '9CCC'],
source: ['Fatebreaker', 'Fatebreaker\'s Image'],
capture: true,
},
durationSeconds: (data) => data.p1FallOfFaithTethers.length >= 3 ? 8.7 : 3,
infoText: (data, matches, output) => {
const curTether = matches.id === '9CC9' ? 'fire' : 'lightning';
data.p1FallOfFaithTethers.push(curTether);

if (data.p1FallOfFaithTethers.length < 4) {
const num = data.p1FallOfFaithTethers.length === 1
? 'one'
: (data.p1FallOfFaithTethers.length === 2 ? 'two' : 'three');
return output.tether!({
num: output[num]!(),
elem: output[curTether]!(),
});
}

const [e1, e2, e3, e4] = data.p1FallOfFaithTethers;

if (e1 === undefined || e2 === undefined || e3 === undefined || e4 === undefined)
return;

return output.all!({
e1: output[e1]!(),
e2: output[e2]!(),
e3: output[e3]!(),
e4: output[e4]!(),
});
},
outputStrings: {
fire: {
en: 'Fire',
},
lightning: {
en: 'Lightning',
},
one: {
en: '1',
},
two: {
en: '2',
},
three: {
en: '3',
},
tether: {
en: '${num}: ${elem}',
},
all: {
en: '${e1} => ${e2} => ${e3} => ${e4}',
},
},
},
// P2 -- Usurper Of Frost

// Crystals

// P3 -- Oracle Of Darkness

// P4 -- Duo

// P5 -- Pandora
],
timelineReplace: [
{
'locale': 'en',
Expand Down

0 comments on commit ebc1d3c

Please sign in to comment.