Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

raidboss: Lunar Subterrane -- Add Forsaken Fount triggers #5926

Merged
merged 3 commits into from
Nov 15, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 118 additions & 3 deletions ui/raidboss/data/06-ew/dungeon/the_lunar_subterrane.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Conditions from '../../../../../resources/conditions';
import Outputs from '../../../../../resources/outputs';
import { Responses } from '../../../../../resources/responses';
import Util from '../../../../../resources/util';
import ZoneId from '../../../../../resources/zone_id';
Expand All @@ -7,15 +8,24 @@ import { TriggerSet } from '../../../../../types/trigger';

// TODO: Dark Elf tell people where to go for hidden staves
// TODO: Antlion tell people which row to be in for landslip + towerfall
// TODO: Durante initial Forsaken Fount with orbs
// TODO: Durante Forsaken Fount+Contrapasso explosions (looks to be one pattern rotated?)

export type Data = RaidbossData;
export interface Data extends RaidbossData {
fountsSeen: number;
fountX: number[];
fountY: number[];
}

const triggerSet: TriggerSet<Data> = {
id: 'TheLunarSubteranne',
zoneId: ZoneId.TheLunarSubterrane,
timelineFile: 'the_lunar_subterrane.txt',
initData: () => {
return {
fountsSeen: 0,
fountX: [],
fountY: [],
};
},
triggers: [
{
id: 'Lunar Subterrane Dark Elf Abyssal Outburst',
Expand Down Expand Up @@ -162,6 +172,111 @@ const triggerSet: TriggerSet<Data> = {
netRegex: { id: '88C2', source: 'Durante' },
response: Responses.tankBuster(),
},
{
// Round 1 is always a non-splitting line of orbs.
id: 'Lunar Subterrane Durante Forsaken Fount 1',
type: 'Ability',
netRegex: { id: '88BB', source: 'Durante', capture: false },
condition: (data) => data.fountsSeen === 0,
delaySeconds: 1, // This collides with Fount 2 if we don't delay. ???
infoText: (_data, _matches, output) => output.avoid!(),
run: (data) => data.fountsSeen += 1,
outputStrings: {
avoid: {
en: 'Away from orbs',
},
},
},
{
// Round 2 is always a splitting line. Center is always safe.
id: 'Lunar Subterrane Durante Forsaken Fount 2',
type: 'Ability',
netRegex: { id: '88BB', source: 'Durante', capture: false },
condition: (data) => data.fountsSeen === 1,
delaySeconds: 1,
response: Responses.goMiddle('info'),
run: (data) => data.fountsSeen += 1,
},
{
// On round three and subsequently, known spawn locations for the Aetheric Charge orbs are:
// (0,-422)
// (0, -434.8)
// (0, -409.2)
// (3.65, -412.9)
// (-3.65, -412.95)
// (9.05, -412.8)
// (-9.05, -418.35)
// (9.15, -425.55)
// (9.15, -431.1)
// (-9.25, -431.1)
// (12.8, -422)
// (-12.8, -422)
// (Other spawn locations exist for rounds 1/2, but we can ignore those.)
id: 'Lunar Subterrane Durante Forsaken Fount 3 Collect',
type: 'AddedCombatant',
netRegex: { name: 'Aetheric Charge' },
condition: (data) => data.fountsSeen === 2,
run: (data, matches) => {
// Because the positions are relatively fixed, we don't need a reliable order for coordinates.
// Only the values and the count of those values really is important here.
data.fountX.push(Math.round(parseFloat(matches.x)));
data.fountY.push(Math.round(parseFloat(matches.y)) + 422); // Normalize the Y axis to 0
},
},
{
id: 'Lunar Subterrane Durante Forsaken Fount 3 Call',
type: 'AddedCombatant',
netRegex: { name: 'Aetheric Charge', capture: false },
condition: (data) => data.fountsSeen === 2,
delaySeconds: 0.5,
infoText: (data, _matches, output) => {
if (data.fountX.length < 5 || data.fountY.length < 5)
return;
// If there are five orbs on the field, three of them will, guaranteed,
// have the same X or Y value. Those three are in a straight line.
const hCount = data.fountY.filter((n) => n === 0).length;
const vCount = data.fountX.filter((n) => n === 0).length;
JLGarber marked this conversation as resolved.
Show resolved Hide resolved

if (hCount === 3) {
// Horizontal lines are always east/west safe hammer patterns.
const xSum = data.fountX.reduce((a, b) => a + b, 0);

// Don't rely on the rounded sum to be precise, but the sign will be reliable.
if (xSum > 5)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give an example of what these >5, <5, >10, <10 patterns look like in terms of values? Summing makes sense as a way to differentiate between cases when you know the full set of examples, but it's a bit confusing to a reader. (Also, minorly and mostly curiously rather than something to fix, it makes me wonder if there's some simpler way to differentiate?)

Copy link
Collaborator Author

@JLGarber JLGarber Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, here's a raw list of configurations:

West Safe
(-12.80,-422.00), (0.00,-422.00), (12.80,-422.00)
(9.15,-431.10)
(3.65,-412.90)

North Safe
(0.00,-409.20), (0.00,-422.00), (0.00,-434.80)
(9.05,-412.80)
(-9.05,-418.35)

East Safe
(-12.80,-422.00),  (0.00,-422.00), (12.80,-422.00)
(-9.25,-431.05)
(-3.65,-412.95)

Hourglass
(0.00,-409.20), (0.00,-422.00), (0.00,-434.80)
(-9.05,-418.35)
(9.15,-425.55)

And Y-normalized (for readers not as familiar, remember that positive Y values are south, not north!)

West Safe
(-12.80,0), (0,0), (12.8,0)
(9.15,-9.1)
(3.65,9.1)

North Safe
(0,12.8), (0,0), (0,-12.8)
(9.05,9.2)
(-9.05,3.65)

East Safe
(-12.8,0),  (0,0), (12.8,0)
(-9.25,-9.05)
(-3.65,9.05)

Hourglass
(0,12.8), (0,0), (0,-12.8)
(-9.05,3.65)
(9.15,-3.55)

I'm not completely sure this list is exhaustive, but I'm confident the list of orb locations in the inline comment is.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense! Can you add this as a comment somehow?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try this. I don't like how long it is, but the information is there. I also added some more in-line comments at the points where the output is actually returned.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I think that's helpful for future debugging, especially the "this probably does not exist" kind of comment.

return output.west!();
if (xSum < 5)
return output.east!();
return output.unknown!();
}
if (vCount === 3) {
// Remember that we're working with 0-normalized values here!
// Vertical lines have two possible patterns, one hammer and one hourglass.
// If it's hourglass, the rounded Y positions sum to 0.
// If it's hammer, the rounded sums total 13.
// (So far we haven't seen a situation where the rounded total is -13,
// but handle it anyway just in case.)
const ySum = data.fountY.reduce((a, b) => a + b, 0);
if (ySum > 10)
return output.north!();
if (ySum < -10)
return output.south!();
return output.center!();
}
return output.unknown!();
},
run: (data) => {
data.fountX = [];
data.fountY = [];
},
outputStrings: {
west: Outputs.west,
east: Outputs.east,
north: Outputs.north,
south: Outputs.south,
center: Outputs.goIntoMiddle,
unknown: '???',
},
},
],
timelineReplace: [
{
Expand Down