Skip to content

Commit

Permalink
raidboss: UWU - Add ifrit phase change triggers (#5900)
Browse files Browse the repository at this point in the history
Add trigger for initial Ifrit position pre-dash, as well as safe spot
away from dashes and radiant plumes.

There might be a better way to detect Ifrit's initial positioning but I
can't think of it. Maybe our next custom log line should be
`ActorSetPos` or something, if that gets sent here?
  • Loading branch information
valarnin authored Nov 4, 2023
1 parent 1de0bc8 commit c5832a8
Showing 1 changed file with 143 additions and 1 deletion.
144 changes: 143 additions & 1 deletion ui/raidboss/data/04-sb/ultimate/ultima_weapon_ultimate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Outputs from '../../../../../resources/outputs';
import { callOverlayHandler } from '../../../../../resources/overlay_plugin_api';
import { Responses } from '../../../../../resources/responses';
import { NamedConfigEntry } from '../../../../../resources/user_config';
import Util, { Directions } from '../../../../../resources/util';
import Util, { DirectionOutputCardinal, Directions } from '../../../../../resources/util';
import ZoneId from '../../../../../resources/zone_id';
import { RaidbossData } from '../../../../../types/data';
import { PluginCombatantState } from '../../../../../types/event';
Expand Down Expand Up @@ -68,6 +68,8 @@ export interface Data extends RaidbossData {
titanGaols: string[];
seenTitanGaols?: boolean;
titanBury: NetMatches['AddedCombatant'][];
ifritRadiantPlumeLocations: DirectionOutputCardinal[];
possibleIfritIDs: string[];
}

type GaolKey = Extract<keyof Data['triggerSetConfig'], string>;
Expand Down Expand Up @@ -147,6 +149,8 @@ const triggerSet: TriggerSet<Data> = {
ifritUntargetableCount: 0,
titanGaols: [],
titanBury: [],
ifritRadiantPlumeLocations: [],
possibleIfritIDs: [],
};
},
timelineTriggers: [
Expand Down Expand Up @@ -527,6 +531,144 @@ const triggerSet: TriggerSet<Data> = {
},
},
// --------- Ifrit ----------
{
id: 'UWU Ifrit Possible ID Locator',
type: 'StartsUsing',
netRegex: { id: '2B55', source: 'Garuda', capture: false },
// Run this after the initial Garuda trigger and just piggyback off its call to `getCombatants`
// We're just looking to pluck the four possible IDs from the array pre-emptively to avoid doing
// that filter on every `CombatantMemory` line
delaySeconds: 25,
run: (data) => {
data.possibleIfritIDs = data.combatantData
.filter((c) => c.BNpcNameID === 0x4A1)
.map((c) => c.ID?.toString(16).toUpperCase() ?? '');
},
},
{
id: 'UWU Ifrit Initial Dash Collector',
type: 'CombatantMemory',
// Filter to only enemy actors for performance
netRegex: { id: '4[0-9A-Fa-f]{7}', capture: true },
condition: (data, matches) => {
if (!data.possibleIfritIDs.includes(matches.id))
return false;
const posXVal = parseFloat(matches.pairPosX ?? '0');
const posYVal = parseFloat(matches.pairPosY ?? '0');

if (posXVal === 0 || posYVal === 0)
return false;

// If the Ifrit actor has jumped to exactly 19.5 out on a cardinal, that's our dash spot
if (
Math.abs(posXVal - 100) - 19.5 < Number.EPSILON ||
Math.abs(posYVal - 100) - 19.5 < Number.EPSILON
)
return true;

return false;
},
suppressSeconds: 9999,
infoText: (data, matches, output) => {
const posXVal = parseFloat(matches.pairPosX ?? '0');
const posYVal = parseFloat(matches.pairPosY ?? '0');

let ifritDir: DirectionOutputCardinal = 'unknown';

// Flag both sides that ifrit is dashing through as unsafe, while also tracking where he's actually
// jumped to so we can use it for the infoText
if (posXVal < 95) {
data.ifritRadiantPlumeLocations.push('dirW', 'dirE');
ifritDir = 'dirW';
} else if (posXVal > 105) {
data.ifritRadiantPlumeLocations.push('dirW', 'dirE');
ifritDir = 'dirE';
} else if (posYVal < 95) {
data.ifritRadiantPlumeLocations.push('dirN', 'dirS');
ifritDir = 'dirN';
} else if (posYVal > 105) {
data.ifritRadiantPlumeLocations.push('dirN', 'dirS');
ifritDir = 'dirS';
}

// Remove duplicates
data.ifritRadiantPlumeLocations = data.ifritRadiantPlumeLocations
.filter((pos, index) => data.ifritRadiantPlumeLocations.indexOf(pos) === index);

return output.text!({ dir: output[ifritDir]!() });
},
outputStrings: {
text: {
en: 'Ifrit ${dir}',
},
unknown: Outputs.unknown,
...Directions.outputStringsCardinalDir,
},
},
{
id: 'UWU Ifrit Initial Radiant Plume Collector',
type: 'StartsUsingExtra',
netRegex: { id: '2B61' },
condition: (data, matches) => {
const posXVal = parseFloat(matches.x);
const posYVal = parseFloat(matches.y);

// Possible plume locations:
// 100.009, 106.998
// 100.009, 118.015 = south
// 100.009, 92.990
// 100.009, 82.003 = north
// 106.998, 100.009
// 110.996, 110.996
// 110.996, 88.992
// 118.015, 100.009 = east
// 82.003, 100.009 = west
// 88.992, 110.996
// 88.992, 88.992
// 92.990, 100.009

if (Math.abs(posXVal - 100) < 1) {
if (Math.abs(posYVal - 83) < 1) {
// North unsafe
data.ifritRadiantPlumeLocations.push('dirN');
} else if (Math.abs(posYVal - 118) < 1) {
// South unsafe
data.ifritRadiantPlumeLocations.push('dirS');
}
} else if (Math.abs(posYVal - 100) < 1) {
if (Math.abs(posXVal - 83) < 1) {
// West unsafe
data.ifritRadiantPlumeLocations.push('dirW');
} else if (Math.abs(posXVal - 118) < 1) {
// East unsafe
data.ifritRadiantPlumeLocations.push('dirE');
}
}

// Remove duplicates
data.ifritRadiantPlumeLocations = data.ifritRadiantPlumeLocations
.filter((pos, index) => data.ifritRadiantPlumeLocations.indexOf(pos) === index);

// 3 danger spots means we only have one safe spot left
return data.ifritRadiantPlumeLocations.length === 3;
},
suppressSeconds: 5,
infoText: (data, _matches, output) => {
if (data.ifritRadiantPlumeLocations.length < 3)
return;

const safeDir =
Directions.outputCardinalDir.filter((dir) =>
!data.ifritRadiantPlumeLocations.includes(dir)
)[0];

return output[safeDir ?? 'unknown']!();
},
outputStrings: {
unknown: Outputs.unknown,
...Directions.outputStringsCardinalDir,
},
},
{
id: 'UWU Ifrit Vulcan Burst',
type: 'StartsUsing',
Expand Down

0 comments on commit c5832a8

Please sign in to comment.