Skip to content

raidboss: dmu p1 initial triggers#1069

Merged
Legends0 merged 43 commits into
mainfrom
dmu-p1-initial-triggers
Jun 11, 2026
Merged

raidboss: dmu p1 initial triggers#1069
Legends0 merged 43 commits into
mainfrom
dmu-p1-initial-triggers

Conversation

@Legends0

@Legends0 Legends0 commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Addon to #1068.

Adds some triggers that I worked on today.

Still to be tested, but raidemulator seemed okay. Currently missing the Graven Image 2 tell, though it is tracked.

@Legends0

Legends0 commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator Author

Also, I looked a bit at o8s to grab some of the outputs to match.

Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts Outdated
Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts
@Legends0

Legends0 commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator Author

I'll probably work on the tethers tomorrow, then it should be ready?

Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts

@wexxlee wexxlee left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Leaving some fast comments now; will hopefully be able to give a more complete review after I jump in later tonight.

Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts
Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts Outdated
Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts Outdated
Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts Outdated
@wexxlee

wexxlee commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

I'll probably work on the tethers tomorrow, then it should be ready?

In case it helps, for tethers, there's an ActorSetPos line that comes out with each tether, moving the invisible add that the player is tethered to to either:
126.0000|41.5000|7.0000| (side - will have meteor)
or
102.5000|27.0000|22.5000| (middle - will drop puddle)

@Legends0

Legends0 commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator Author

I'll probably work on the tethers tomorrow, then it should be ready?

In case it helps, for tethers, there's an ActorSetPos line that comes out with each tether, moving the invisible add that the player is tethered to to either: 126.0000|41.5000|7.0000| (side - will have meteor) or 102.5000|27.0000|22.5000| (middle - will drop puddle)

Thanks. I am almost done with the tether triggers, I am just trying to fix tts collisions at this point before pushing.

EDIT: Here is my current draft. It conflicts with left/right call and the ice call (within 1s), the pulse call is within 2s but I shortened it to knockback.

    {
      id: 'DMU ActorSetPos Tracker',
      // Only in use for P1 Graven Image tethers
      type: 'ActorSetPos',
      netRegex: { id: '4[0-9A-Fa-f]{7}', capture: true },
      run: (data, matches) =>
        data.actorPositions[matches.id] = {
          x: parseFloat(matches.x),
          y: parseFloat(matches.y),
          heading: parseFloat(matches.heading),
        },
    },
    {
      id: 'DMU Graven Image Tether Collect',
      // 271 ActorSetPos lines indicate where the tether is coming from
      // 261 CombatantMemory lines may also indicate this
      // Graven Image 1:
      // (100, 56, 18.5) Center Tether, Will be target of BAA9 Pulse Wave (knockback)
      // Graven Image 2:
      // (102.5, 27, 22.5) Center Tether, Will be target of BAAC Gravitas (puddles)
      // (126, 41.5, 7) Right Tether, Will be target of BAB0 Vitrophyre (rocks)
      // Graven Image 3:
      // (95, 25, 27) Left Tether, Will be target of BAB5 Indulgent Will which causes 503 Confused
      // (107, 43, 8.5) Right tether, Will be target of BAB6 Idyllic Will which causes 131E Sleep
      type: 'Tether',
      netRegex: { id: headMarkerData['imageTether'], capture: true },
      condition: Conditions.targetIsYou(),
      delaySeconds: 0.1, // Actor position data can come after tether in log
      run: (data, matches) => {
        const actor = data.actorPositions[matches.sourceId];
        if (actor === undefined) {
          data.gravenImageTether = 'unknown';
          return;
        }

        const x = actor.x;
        // Graven Image 1: Pulse Wave target
        if (x < 101 && x > 99)
          data.gravenImageTether = 'pulse';
        else if (x < 103 && x > 101) // Graven Image 2: Gravitas target
          data.gravenImageTether = 'gravitas';
        else if (x > 125) // Graven Image 2: Vitrophyre target
          data.gravenImageTether = 'vitrophyre';
        else if (x < 100) // Graven Image 3: Indulgent Will target
          data.gravenImageTether = 'indulgent';
        else if (x < 108 && x > 106)  // Graven Image 3: Idyllic Will target
          data.gravenImageTether = 'idyllic';
        else
          data.gravenImageTether = 'unknown';
      },
    },
    {
      id: 'DMU Graven Image Tether',
      type: 'Tether',
      netRegex: { id: headMarkerData['imageTether'], capture: true },
      condition: Conditions.targetIsYou(),
      delaySeconds: 0.1, // Actor position data can come after tether in log
      infoText: (data, matches, output) => {
        const actor = data.actorPositions[matches.sourceId];
        if (actor === undefined)
          return output.tetherOnYou!();

        const x = actor.x;
        // Graven Image 1: Pulse Wave target
        if (x < 101 && x > 99)
          return output.pulse!();
        else if (x < 103 && x > 101) // Graven Image 2: Gravitas target
          return output.gravitas!();
        else if (x > 125) // Graven Image 2: Vitrophyre target
          return output.vitrophyre!();
        else if (x < 100) // Graven Image 3: Indulgent Will target
           return output.indulgent!();
        else if (x < 108 && x > 106)  // Graven Image 3: Idyllic Will target
          return output.idyllic!();
        else
          return output.tetherOnYou!();
      },
      outputStrings: {
        tetherOnYou: {
          en: 'Tether on YOU',
          de: 'Verbindung auf DIR',
          fr: 'Lien sur VOUS',
          ja: '線ついた',
          cn: '连线点名',
          ko: '선 대상자 지정됨',
          tc: '連線點名',
        },
        pulse: Outputs.knockback, // Cannot be immuned, happens within 6s of tether
        gravitas: {
          en: 'Puddle Tether on YOU',
        },
        vitrophyre: {
          en: 'Rock Tether on YOU',
        },
        indulgent: {
          en: 'Confuse Tether on YOU',
        },
        idyllic: {
          en: 'Sleep Tether on YOU',
        },
      },
    },
    {
      id: 'DMU P1 Graven Image Tether Cleanup',
      // Clear on Ability:
      // BAA9 Pulse Wave
      // BAAC Gravitas
      // BAB0 vitrophyre
      // BAB5 Indulgent Will
      // BAB6 Idyllic Will
      type: 'Ability',
      netRegex: {
        id: ['BAA9', 'BAAC', 'BAB0', 'BAB5', 'BAB6'],
        source: 'Graven Image',
        capture: true,
      },
      suppressSeconds: 1,
      run: (data, matches) => {
        // Player could die and this ability then not target them
        // Need intelligent way to remove once related ability has executed
        // Clear data if ability matches our tether
        const abilityMap = {
          'pulse': 'BAAC',
          'gravitas': 'BAA9',
          'vitrophyre': 'BAB0',
          'indulgent': 'BAB5',
          'idyllic': 'BAB6',
          'unknown': 'unknown',
        };
        const tether = data.gravenImageTether ?? 'unknown';
        const tetherAbilityId = abilityMap[tether as keyof typeof abilityMap];
        if (tetherAbilityId === matches.id || tether === 'unknown')
          delete data.gravenImageTether;
      },
    },

Legends0 added 2 commits June 6, 2026 01:34
The animation is visible ~9.89s before cast goes off, however When animation becomes visible, the players will bbe asleep or confused for another ~3.4s. Once the debuff ends the players have ~6.4s to turn character
@JLGarber

JLGarber commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

More testing tonight, most things look good apart from Wave Cannon, Intemperate Will, and Gravitational Wave. As it stands, the call triggers seem to be racing against the collection trigger and winning. I think we need a short delay on each of the call triggers, and then to check the IDs within the popup text function bodies. For example:

    {
      id: 'DMU P1 Impertinent Will',
      type: 'ActorControlExtra',
      netRegex: { category: '019D', param1: '40', param2: '80', capture: true },
      delaySeconds: 1,
      alertText: (data, matches, output) => {
        if (data.yellowTowerId === matches.id)
          return output.goWest!();
      },
      outputStrings: {
        goWest: Outputs.getLeftAndWest,
      },
    },

Alternatively, it might make sense to do a single getCombatants call early on, perhaps during the first Graven Image cast, and then use that one call to store off all the image IDs for that current encounter. I'm less certain about this one since a short delay as I noted above still gives the player about 6 seconds to resolve the half-room, but it is worth considering.

(Do also note, I'm not going to be able to test triggers much after this week. It's getting distracting to watch for triggers while I'm running with my group, and we're getting into phase 2 enough that I need to be able to focus more. I will be able to test and review timelines though.)

Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts Outdated
Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts
@Legends0

Legends0 commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator Author

More testing tonight, most things look good apart from Wave Cannon, Intemperate Will, and Gravitational Wave. As it stands, the call triggers seem to be racing against the collection trigger and winning.

Shoot, I missed that the promise can take time to set the value.

Alternatively, it might make sense to do a single getCombatants call early on, perhaps during the first Graven Image cast, and then use that one call to store off all the image IDs for that current encounter. I'm less certain about this one since a short delay as I noted above still gives the player about 6 seconds to resolve the half-room, but it is worth considering.

Less calls to overlayplugin is good. I see this wouldn't be the first time something like this was done. R4N on the first cast by boss has a collector. We can use suppressSeconds here to just do it once.

@JLGarber

JLGarber commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Yeah, I prefer to avoid calling getCombatants myself for various reasons, but in this case I do think it's strictly necessary. There's just nothing else in the logs that I can see to use.

@Legends0

Legends0 commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator Author

Yeah, I prefer to avoid calling getCombatants myself for various reasons, but in this case I do think it's strictly necessary. There's just nothing else in the logs that I can see to use.

I tried it out, but raidemulator seems to only find the PluginCombatantStates without ID attribute for some reason, so raidemulator isn't able to store IDs to lookup later. Might have it while in game, but not sure.

Possibly a bug in the raid emulator not tacking on the ID field from the Add to the plugincombatantstate?

@Legends0

Legends0 commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator Author

Okay, well I have a solution that works without OverlayPlugin and no need to know bnpcids... It seems that the IDs follow a strict pattern so can just do this on the first tower since it seems to always be the highest ID.

        const id = parseInt(matches.id, 16);
        const blueTowers = [id, id - 1]; // First tower is blue and highest ID
        const purpleTowers = [id - 2, id - 4];
        const yellowTowers = [id - 3, id - 5];
        const eyeTowers = [id - 7, id - 9];
        const fakeEyeTowers = [id - 6, id - 8];

Legends0 added 3 commits June 6, 2026 04:52
Since first trigger of the ActorControlExtra is a blue tower, can skip the check and suppress since this only happens once in P1.
@Legends0

Legends0 commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator Author

I have a config for kefka bin and filipino teleportents, but I think it should be held off on for a separate pr.

Legends0 added 3 commits June 6, 2026 20:36
There were also cases where player could die to the knockback and still be called in the early trigger.
Legends0 added 3 commits June 7, 2026 06:02
Remove players from the output if they died between receiving the buff and knockback call.
Comment thread ui/raidboss/data/07-dt/ultimate/dancing_mad.ts

@JLGarber JLGarber left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Further testing tonight looks okay in-game. I'm not strictly happy about relying on the order of entity IDs, but I saw no errors. I think we can merge this and then handle issues as people report them.

@Legends0 Legends0 merged commit 4d97886 into main Jun 11, 2026
10 checks passed
@Legends0 Legends0 deleted the dmu-p1-initial-triggers branch June 11, 2026 05:02
github-actions Bot pushed a commit that referenced this pull request Jun 11, 2026
github-actions Bot pushed a commit that referenced this pull request Jun 11, 2026
github-actions Bot pushed a commit to Bing-su/cactbot that referenced this pull request Jun 11, 2026
@Legends0 Legends0 mentioned this pull request Jun 14, 2026
20 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants