quisquous / cactbot

FFXIV TypeScript Raiding Overlay
Apache License 2.0
793 stars 383 forks source link

Cactbot Limit Cut/Enumeration not working #1199

Closed xKaigetsu closed 4 years ago

xKaigetsu commented 4 years ago

With the latest ffxiv plugin, cactbot callout for Enumeration and Limit Cut is not working in TEA...

I'm not sure what would be the fix, have tried reloading overlay and plugin...

quisquous commented 4 years ago

Yes, this is not going to work for some time due to some changes in 5.2. I could come up with a workaround, but I'm going to wait to see if something more structural can be done about it, like in OverlayPlugin.

omegasrevenge commented 4 years ago

Would begging for the short term workaround work on you?^^

JLGarber commented 4 years ago

More properly, what changed in 5.2? I remember seeing something from Ravahn about those two head marker classes being encrypted, and that he wasn't willing to take the time to work that out. I haven't been back in since 5.2, so I don't know what the logs look like, but I'm possibly willing to try a fix if it's not too complex.

quisquous commented 4 years ago

In TEA, headmarkers have an arbitrary offset applied to every headmarker id. This offset is instance-based. It's like the o4s ability offset, just on headmarkers, and just in TEA at the moment.

Limit cut headmarkers are applied in order and #1 is the first headmarker. I just didn't know what to do with the rest of the markers, etc...

JLGarber commented 4 years ago

Hmm. Just hunted down a random TEA log from 5.2 and had a look at it. I feel like we could collect the first appearance of the Limit Cut markers and do some quick maths to determine the offset. We could store this as data.offset and math Limit Cut and Enumeration out from there. Am I missing something? If not, I'll have a look at that this week.

quisquous commented 4 years ago

Yeah, I think it's very do-able. You'd also have to change every headmarker regex to apply to all headmarkers and then do some math from there to figure out if it was the right one. It's not that tricky, just a bunch of places to change.

quisquous commented 4 years ago

Let me revert the change I made before when I didn't understand the problem back to before 5.2, just to keep the ids theoretically correct for the future.

quisquous commented 4 years ago

I also have a handful of 5.2 TEA logs if you need me to DM them to you.

JLGarber commented 4 years ago

If you would, please. I can't guarantee a fast fix, since I currently won't be able to test it myself, but I can at least try to math everything out. From what I can see though, there aren't a lot of places that rely on the 1B markers, since most of the non-Limit Cut/Enumeration ones are accompanied by debuffs?

JLGarber commented 4 years ago

Hmm. I need assistance thinking this through. So for finding the offset:

    {
      id: 'TEA Offset Determination',
      regex: Regexes.headMarker({ id: '....' }),
      condition: function(data) {
        return !data.decOffset;
      },
      run: function(data, matches) {
        data.decOffset = (parseInt('0x' + matches.ID) - 79);
      },
    },

(The regex there is not generally robust, but I feel like it should be good enough for TEA, since overhead markers are always left-padded to four characters.)

From there, we could do something awful like:

    {
      id: 'TEA Enumeration YOU',
      regex: Regexes.headMarker({ id: '....' }),
      condition: function(data, matches) {
        if ((parseInt(matches.ID) - data.decOffset).toString(16) != '0041')
          return false;
        return data.me == matches.target;
      },
      alertText: {
        en: 'Enumeration on YOU',
      },
    },

And so forth for each headMarker regex.

There's probably a cleaner way to approach this than just brute-forcing the calculations each time through. Maybe add "calculate-against-the-offset" as another helper function in raidboss.js?

JLGarber commented 4 years ago

Hmm, maybe never mind all that. What if we did something like this?

    {
      id: 'TEA Offset Determination',
      regex: Regexes.headMarker({ id: '....' }),
      condition: function(data) {
        return !data.decOffset;
      },
      run: function(data, matches) {
        data.decOffset = (parseInt('0x' + matches.ID) - 79);
        data.missileID = (parseInt('0x0043') - data.decOffset).toString(16);
        data.enumID = (parseInt('0x0041') - data.decOffset).toString(16);
        data.limitID = [];
        for (let i = 0; i < 8; i++)
          data.limitID.push(((79 + i) - data.decOffset).toString(16));
        // and so on and so forth
      },
    },

(We could parseInt the bare IDs first so that it's clear what each one is, or we could just decimalize them to begin with, as we see in the Limit Cut IDs loop. Whichever others think best.)

I assume data property values can be read as part of a regex replacement? If so, this would trivialize the problem. For each trigger that currently includes a bare marker ID, we instead substitute the data property value containing the calculated ID.

As a bonus, if there are later changes to the overlay that render this moot, all we would have to do is change the offset setup function to just be a map of the IDs, and then we wouldn't have to touch the actual triggers.

quisquous commented 4 years ago

Hmm. What about this suggestion?

What about a function at the top of the file like:

'use strict';

let getHeadmarkerId = (data, matches) => {
  // pseudocode here:
  // init data first headmarker if it hasn't been set
  // calculate what matches.id should be from headmarker offset
  // return it
};

[{
// triggers start here

And then something like this, everywhere:

    {
      id: 'TEA Enumeration YOU',
      regex: Regexes.headMarker(),
      condition: function(data, matches) {
        let id = getHeadmarkerId(data, matches);
        if (id != '0041')
          return;
JLGarber commented 4 years ago

That does have a significant advantage in that it keeps the marker IDs directly associated with their triggers. It means a little more cleanup in the future if something better turns up, but that's probably not worth considering.

Do you have any suggestions for finding the offset more cleanly, or is data.decOffset = (parseInt('0x' + matches.ID) - 79); likely the best we can do?

quisquous commented 4 years ago

What about parseInt(matches.id, 16) - 79? Yeah, I was thinking of just hardcoding the #1 limit break in there with a comment.