MKhayle / XIVComboExpanded

Plugin version of the icon replacement features in dalamud
GNU General Public License v3.0
75 stars 59 forks source link

[Enhancement]: CooldownData.cs Refining #217

Closed vitharr137 closed 3 months ago

vitharr137 commented 1 year ago

Hello,

I've been working on optimizing some of the ways the cooldown data works in the addon, and while I'm not confident enough in it yet to open a real pull, I do want to let you know about the advancements we've discovered in some of the other forks of this project to see if you'd like to use any of them! The main reason currently that I avoid a pull is it seems to mess with other aspects of code that rely on the durations of cooldowns being set to 0 manually in CooldownData.cs

These are used in the CooldownData.cs section, and require: using FFXIVClientStructs.FFXIV.Client.Game

The major one is it's been discovered how to get the haste/speed adjusted cooldown of a given actionID:

public float BaseCooldown => ActionManager.GetAdjustedRecastTime(ActionType.Spell, this.ActionID) / 1000f;

public float TotalBaseCooldown
{
    get
    {
        var (cur, max) = Service.ComboCache.GetMaxCharges(this.ActionID);

        // Rebase to the current charge count
        var total = this.BaseCooldown / max * cur;

        return total * cur;
    }
}

public float TotalCooldownElapsed => this.cooldownElapsed;

public float TotalCooldownRemaining => this.TotalBaseCooldown - this.TotalCooldownElapsed;

That line alone has allowed functions such as tracking uptime for combo based rotations like Twin Snakes or Demolish, by using code like such:

double gcd = GetCooldown(MNK.Bootshine).BaseCooldown;
double remainingGCD = GetCooldown(MNK.Bootshine).CooldownRemaining;
double rotate = remainingGCD + (gcd * 3);

The rotate double can now be used to check if the Twin Snakes or Demolish duration remaining is less than it, providing an easy switch for combos to adjust to

Another set of useful data has been the easy calculation of time until a certain actionID is able to be used after the next usage:

public float ChargeCooldownRemaining
{
    get
    {
        var (cur, _) = Service.ComboCache.GetMaxCharges(this.ActionID);

        return this.TotalCooldownRemaining % (this.TotalBaseCooldown / cur);
    }
}

public float RecoveryTime => this.CooldownRemaining + this.BaseCooldown;

public float ChargeRecoveryTime
{
    get
    {
        if ((this.RemainingCharges - 1) >= 0)
        {
            return this.ChargeCooldownRemaining;
        }

        return this.ChargeCooldownRemaining + this.BaseCooldown;
    }
}

public float TotalChargeCooldownRemaining => this.MaxCharges - this.RemainingCharges > 0
        ? this.MaxCharges - this.RemainingCharges == 1
            ? this.ChargeCooldownRemaining
            : (this.BaseCooldown * ((this.MaxCharges - this.RemainingCharges) - 1)) + this.ChargeCooldownRemaining
        : 0;

These can assist for timing/reserving charge based actionIDs for certain buff windows, allowing checks to see if the full charge recovery time would occur prior to a given cooldown.

I've uploaded the txt version of the modified CooldownData.cs which contains some commented lines for the functionality, hope you can find some useful additions!

CooldownData.txt

MKhayle commented 3 months ago

alright, this is a very old issue and it is interesting in some points I'm sorry I never took the time to acknowledge/delve into it, but I have just tested & updated it to use it in https://github.com/MKhayle/XIVComboExpanded/commit/9373f8fa32fd5cef8d710197e93690efa4479afa

MKhayle commented 3 months ago

Monk has been changed significantly since you published this and I am less aiming at optimization than other forks, but this is still very nice to have overall if I need it at some point

Thanks!

vitharr137 commented 3 months ago

Glad it helped! I am not great at github protocol and hope this isn't some wrong way to notify, but here's something a bit more up to date than the one from last year, it includes a check for Haste Adjusted Cast Time (CastTime) and resource Cost, as well as another check in the form of TotalChargeRecoveryRemaining which has been useful for redmage and blackmage

CooldownData.txt

MKhayle commented 3 months ago

@kaedys idk if you're still interested in this over what you did there, but just in case

vitharr137 commented 3 months ago

One other place to look at is the IsOnCooldown() and IsOffCooldown() for a sanity check just to see if those are still doing what is intended on line 400+ in CustomCombo.cs. I think what was discussed in the paladin section fixes it, but just for certainty

kaedys commented 3 months ago

So, looks like IsOnCooldown and IsOffCooldown both just call and return IsCooldown, Off inverting the result first. So both of those are also fixed by the change I made.

kaedys commented 3 months ago

I'm comparing the above snippet to the existing code, though, and I'll see how easily it can be integrated without (hopefully) breaking anything else >.<

kaedys commented 3 months ago

Ok @vitharr137, so, I'm super confused by some of the implementations here, both in the original and the updated, and I think it's causing issues for some of the combos.

Edit: Ok, digging into it, it looks like the first return of GetMaxCharges is not the current number of charges, but the maximum at the current level (very silly naming, imo). So that obviates at least some of the above.

Edit2: Ok, further observations/questions after re-reading it with the above.

vitharr137 commented 3 months ago

I do want to preface this with it was coding by trial and error, and I am not a well educated coder in general by any stretch so there is plenty of room for mistakes that I've made along the way, but so far these have been my observations. Most of this is cobbled together from other forks, or directly dragged out of the structs themselves and put into code here in the best way I could (which is not well):

FFXIV's reverse engineering chains are split between some of Dalamud's intepretations, and the FFXIVClientStructs themselves, and several references to Excel sheets made from the game engine itself. The lines from 14 to 23 in CooldownData.cs are the ones I was having the most problems with in general, especially cooldownTotal, which does seem to return 0 in many more instances than would be logical, and since a majority of already written combos were using those returns, most of CooldownTotal was rather hackedly put together to match logic that was already being used by other forks, such as the very weird bit with return 0 if 0

It looks like you may be here right now, so I'll post this part of the explaining and continue editing further :)

Your last comment is the main reason for the difference, yes. Haste adjusted values were extremely vital to Monk prior to Dawntrail in order to determine which combo to fall into and how to prepare for burst windows, and allow for smoother calculation overall that fall more in line with game state rather than flat cooldowns on a number of other niche cases like haste applying somewhere, or cast times changing, or simply things like Gnashing Fang for GNB that are cooldown based moves using skill speed like standard weaponskills

Please let me know if there are more questions, I tried to take time to be exact for my definitions but there has been some time since I looked over the code like this so I am likely not explaining well enough

vitharr137 commented 3 months ago

In case it doesn't ping properly, the more complete description for your questions has been edited in

kaedys commented 3 months ago

Ok, I'm going to need to look at this in more depth tomorrow when my brain is against functioning properly, and see if I can figured out how to adapt CalcBestAction for the changes.

kaedys commented 3 months ago

Conversation on this will continue in #305