Skip to content

Commit

Permalink
Merge pull request #310 from aldros-ffxi/vpr-combos3
Browse files Browse the repository at this point in the history
Add PvP style secret combos
  • Loading branch information
MKhayle authored Jul 14, 2024
2 parents 06eb3b7 + 6d5f76d commit 8cbfdc3
Show file tree
Hide file tree
Showing 2 changed files with 278 additions and 0 deletions.
226 changes: 226 additions & 0 deletions XIVComboExpanded/Combos/VPR.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Dalamud.Game.ClientState.JobGauge.Types;
using DreadCombo = Dalamud.Game.ClientState.JobGauge.Enums.DreadCombo;

namespace XIVComboExpandedPlugin.Combos;

Expand Down Expand Up @@ -404,6 +405,231 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim
}
}

internal class PvPMainComboFeature : CustomCombo
{
protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ViperPvPMainComboFeature;

protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level)
{
if (actionID == VPR.SteelFangs)
{
if (HasEffect(VPR.Buffs.Reawakened))
{
var gauge = GetJobGauge<VPRGauge>();
var maxtribute = 4;
if (level >= VPR.Levels.Ouroboros)
maxtribute = 5;
if (gauge.AnguineTribute == maxtribute)
return VPR.FirstGeneration;
if (gauge.AnguineTribute == maxtribute - 1)
return VPR.SecondGeneration;
if (gauge.AnguineTribute == maxtribute - 2)
return VPR.ThirdGeneration;
if (gauge.AnguineTribute == maxtribute - 3)
return VPR.FourthGeneration;
}

// First step, decide whether or not we need to apply debuff
if (OriginalHook(VPR.SteelFangs) == VPR.SteelFangs)
{
var noxious = FindTargetEffect(VPR.Debuffs.NoxiousGash);
if (level >= VPR.Levels.DreadFangs && (noxious is null || noxious?.RemainingTime < 12)) // 12s hopefully means we won't miss anything on a Reawaken window
return VPR.DreadFangs;
else
return VPR.SteelFangs;
}
else
{
// Second step, if we have a third step buff use that combo, otherwise use from default combo
if (OriginalHook(VPR.SteelFangs) == VPR.HuntersSting)
{
if (HasEffect(VPR.Buffs.HindsbaneVenom) || HasEffect(VPR.Buffs.HindstungVenom))
return VPR.SwiftskinsSting;
if (HasEffect(VPR.Buffs.FlanksbaneVenom) || HasEffect(VPR.Buffs.FlankstungVenom))
return VPR.HuntersSting;

if (IsEnabled(CustomComboPreset.ViperPvPMainComboStartFlankstingFeature) || IsEnabled(CustomComboPreset.ViperPvPMainComboStartFlanksbaneFeature))
return VPR.HuntersSting;
else
return VPR.SwiftskinsSting;
}

// Third step, if we are here, prefer to use what we have buffs for, otherwise use defaults
if (OriginalHook(VPR.SteelFangs) == VPR.FlankstingStrike || OriginalHook(VPR.SteelFangs) == VPR.HindstingStrike)
{
if (HasEffect(VPR.Buffs.HindsbaneVenom))
return VPR.HindsbaneFang;
if (HasEffect(VPR.Buffs.HindstungVenom))
return VPR.HindstingStrike;
if (HasEffect(VPR.Buffs.FlanksbaneVenom))
return VPR.FlanksbaneFang;
if (HasEffect(VPR.Buffs.FlankstungVenom))
return VPR.FlankstingStrike;

if (IsEnabled(CustomComboPreset.ViperPvPMainComboStartHindstingFeature))
return VPR.HindstingStrike;
if (IsEnabled(CustomComboPreset.ViperPvPMainComboStartFlanksbaneFeature))
return VPR.FlanksbaneFang;
if (IsEnabled(CustomComboPreset.ViperPvPMainComboStartFlankstingFeature))
return VPR.FlankstingStrike;
return VPR.HindsbaneFang;
}
}
}

return actionID;
}
}

internal class PvPMainComboAoEFeature : CustomCombo
{
protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ViperPvPMainComboAoEFeature;

protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level)
{
if (actionID == VPR.SteelMaw)
{
if (HasEffect(VPR.Buffs.Reawakened))
{
var gauge = GetJobGauge<VPRGauge>();
var maxtribute = 4;
if (level >= VPR.Levels.Ouroboros)
maxtribute = 5;
if (gauge.AnguineTribute == maxtribute)
return VPR.FirstGeneration;
if (gauge.AnguineTribute == maxtribute - 1)
return VPR.SecondGeneration;
if (gauge.AnguineTribute == maxtribute - 2)
return VPR.ThirdGeneration;
if (gauge.AnguineTribute == maxtribute - 3)
return VPR.FourthGeneration;
}

// First step, decide whether or not we need to apply debuff
if (OriginalHook(VPR.SteelMaw) == VPR.SteelMaw)
{
var noxious = FindTargetEffect(VPR.Debuffs.NoxiousGash); // TODO: Would be useful to handle the case with no target
if (level >= VPR.Levels.DreadMaw && (noxious is null || noxious?.RemainingTime < 12)) // 12s hopefully means we won't miss anything on a Reawaken window
return VPR.DreadMaw;
else
return VPR.SteelMaw;
}

// Second step, since there's no requirement here, we can just use whichever has the shorter buff timer
if (OriginalHook(VPR.SteelMaw) == VPR.HuntersBite)
{
var swift = FindEffect(VPR.Buffs.Swiftscaled);
var instinct = FindEffect(VPR.Buffs.HuntersInstinct);
if (swift is null) // I think we'd always want to prioritize swift since it speeds up the rotation
return VPR.SwiftskinsBite;
if (instinct is null)
return VPR.HuntersBite;
if (swift?.RemainingTime <= instinct?.RemainingTime)
return VPR.SwiftskinsBite;
else
return VPR.HuntersBite;
}

if (OriginalHook(VPR.SteelMaw) == VPR.JaggedMaw)
{
if (HasEffect(VPR.Buffs.GrimhuntersVenom))
return VPR.JaggedMaw;
if (HasEffect(VPR.Buffs.GrimskinsVenom))
return VPR.BloodiedMaw;

if (IsEnabled(CustomComboPreset.ViperPvPMainComboAoEStartBloodiedFeature))
return VPR.BloodiedMaw;
return VPR.JaggedMaw;
}
}

return actionID;
}
}

internal class PvPWinderComboFeature : CustomCombo
{
protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ViperPvPWinderComboFeature;

protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level)
{
if (actionID == VPR.Dreadwinder)
{
var gauge = GetJobGauge<VPRGauge>();
if (level >= VPR.Levels.Ouroboros && HasEffect(VPR.Buffs.Reawakened))
{
if (gauge.AnguineTribute == 1)
return VPR.Ouroboros;
}

if (IsEnabled(CustomComboPreset.ViperPvPWinderComboStartHuntersFeature))
{
if (gauge.DreadCombo is DreadCombo.Dreadwinder and not DreadCombo.PitOfDread and not DreadCombo.HuntersDen and not DreadCombo.SwiftskinsDen)
return VPR.HuntersCoil;
if (gauge.DreadCombo is DreadCombo.HuntersCoil and not DreadCombo.PitOfDread and not DreadCombo.HuntersDen and not DreadCombo.SwiftskinsDen)
return VPR.SwiftskinsCoil;
if (gauge.DreadCombo is DreadCombo.SwiftskinsCoil and not DreadCombo.PitOfDread and not DreadCombo.HuntersDen and not DreadCombo.SwiftskinsDen)
return VPR.Dreadwinder;
return VPR.Dreadwinder;
}
else
{
if (gauge.DreadCombo is DreadCombo.Dreadwinder and not DreadCombo.PitOfDread and not DreadCombo.HuntersDen and not DreadCombo.SwiftskinsDen)
return VPR.SwiftskinsCoil;
if (gauge.DreadCombo is DreadCombo.SwiftskinsCoil and not DreadCombo.PitOfDread and not DreadCombo.HuntersDen and not DreadCombo.SwiftskinsDen)
return VPR.HuntersCoil;
if (gauge.DreadCombo is DreadCombo.HuntersCoil and not DreadCombo.PitOfDread and not DreadCombo.HuntersDen and not DreadCombo.SwiftskinsDen)
return VPR.Dreadwinder;
return VPR.Dreadwinder;
}
}

return actionID;
}
}

internal class PvPPitComboFeature : CustomCombo
{
protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ViperPvPPitComboFeature;

protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level)
{
if (actionID == VPR.PitOfDread)
{
var gauge = GetJobGauge<VPRGauge>();
if (level >= VPR.Levels.Ouroboros && HasEffect(VPR.Buffs.Reawakened))
{
if (gauge.AnguineTribute == 1)
return VPR.Ouroboros;
}

if (IsEnabled(CustomComboPreset.ViperPvPPitComboStartHuntersFeature))
{
if (gauge.DreadCombo is DreadCombo.PitOfDread and not DreadCombo.Dreadwinder and not DreadCombo.HuntersCoil and not DreadCombo.SwiftskinsCoil)
return VPR.HuntersDen;
if (gauge.DreadCombo is DreadCombo.HuntersDen and not DreadCombo.Dreadwinder and not DreadCombo.HuntersCoil and not DreadCombo.SwiftskinsCoil)
return VPR.SwiftskinsDen;
if (gauge.DreadCombo is DreadCombo.SwiftskinsDen and not DreadCombo.Dreadwinder and not DreadCombo.HuntersCoil and not DreadCombo.SwiftskinsCoil)
return VPR.PitOfDread;
return VPR.PitOfDread;
}
else
{
if (gauge.DreadCombo is DreadCombo.PitOfDread and not DreadCombo.Dreadwinder and not DreadCombo.HuntersCoil and not DreadCombo.SwiftskinsCoil)
return VPR.SwiftskinsDen;
if (gauge.DreadCombo is DreadCombo.SwiftskinsDen and not DreadCombo.Dreadwinder and not DreadCombo.HuntersCoil and not DreadCombo.SwiftskinsCoil)
return VPR.HuntersDen;
if (gauge.DreadCombo is DreadCombo.HuntersDen and not DreadCombo.Dreadwinder and not DreadCombo.HuntersCoil and not DreadCombo.SwiftskinsCoil)
return VPR.PitOfDread;
return VPR.PitOfDread;
}
}

return actionID;
}
}

// TODO: Once Gauge is implemented
internal class FuryAndIreFeature : CustomCombo
{
protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ViperFuryAndIreFeature;
Expand Down
52 changes: 52 additions & 0 deletions XIVComboExpanded/CustomComboPreset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,58 @@ public enum CustomComboPreset
[CustomComboInfo("Merge Serpent's Tail onto Twinfang/Twinblood Feature", "Merge all Serpent's Tail abilities onto Twinfang/Twinblood.", VPR.JobID)]
ViperMergeTwinsSerpentFeature = 4112,

[SecretCustomCombo]
[ConflictingCombos(ViperSteelTailFeature)]
[CustomComboInfo("Viper PvP Style Main Combo", "Condenses the main combo to a single button, like PvP.\nThe combo detects buffs and debuffs to prioritize skills.\nThe default combo ender is Hindsbane Fang, configurable below.", VPR.JobID)]
ViperPvPMainComboFeature = 4113,

[SecretCustomCombo]
[ConflictingCombos(ViperPvPMainComboStartFlankstingFeature, ViperPvPMainComboStartHindstingFeature)]
[ParentCombo(ViperPvPMainComboFeature)]
[CustomComboInfo("PvP Combo Start Flanksbane Fang", "With no buffs, end first combo with Flanksbane Fang.", VPR.JobID)]
ViperPvPMainComboStartFlanksbaneFeature = 4114,

[SecretCustomCombo]
[ConflictingCombos(ViperPvPMainComboStartFlanksbaneFeature, ViperPvPMainComboStartHindstingFeature)]
[ParentCombo(ViperPvPMainComboFeature)]
[CustomComboInfo("PvP Combo Start Flanksting Strike", "With no buffs, end first combo with Flanksting Strike.", VPR.JobID)]
ViperPvPMainComboStartFlankstingFeature = 4115,

[SecretCustomCombo]
[ConflictingCombos(ViperPvPMainComboStartFlanksbaneFeature, ViperPvPMainComboStartFlankstingFeature)]
[ParentCombo(ViperPvPMainComboFeature)]
[CustomComboInfo("PvP Combo Start Hindsting Strike", "With no buffs, end first combo with Hindsting Strike.", VPR.JobID)]
ViperPvPMainComboStartHindstingFeature = 4116,

[SecretCustomCombo]
[ConflictingCombos(ViperSteelTailAoEFeature)]
[CustomComboInfo("Viper PvP Style AoE Combo", "Condenses the main combo to a single button, like PvP.\nThe combo can only detect debuffs on the current target.\nStarts with Jagged Maw by default, configurable below.", VPR.JobID)]
ViperPvPMainComboAoEFeature = 4117,

[SecretCustomCombo]
[ParentCombo(ViperPvPMainComboAoEFeature)]
[CustomComboInfo("PvP AoE Combo Start Bloodied Maw", "With no buffs, end first combo with Bloodied Maw.", VPR.JobID)]
ViperPvPMainComboAoEStartBloodiedFeature = 4118,

[SecretCustomCombo]
[ConflictingCombos(ViperSteelTailFeature)]
[CustomComboInfo("Viper PvP Style Winder Combo", "Condenses the Dreadwinder combo to a single button, like PvP.\nStarts with Swiftskin's Coil by default.", VPR.JobID)]
ViperPvPWinderComboFeature = 4119,

[SecretCustomCombo]
[ParentCombo(ViperPvPWinderComboFeature)]
[CustomComboInfo("Start with Hunter's Coil", "Start with Hunter's Coil instead.", VPR.JobID)]
ViperPvPWinderComboStartHuntersFeature = 4120,

[SecretCustomCombo]
[CustomComboInfo("Viper PvP Style Pit Combo", "Condenses the Pit of Dread combo to a single button, like PvP.\nStarts with Swiftskin's Den by default.", VPR.JobID)]
ViperPvPPitComboFeature = 4121,

[SecretCustomCombo]
[ParentCombo(ViperPvPPitComboFeature)]
[CustomComboInfo("Start with Hunter's Den", "Start with Hunter's Den instead.", VPR.JobID)]
ViperPvPPitComboStartHuntersFeature = 4122,

#endregion
// ====================================================================================
#region WARRIOR
Expand Down

0 comments on commit 8cbfdc3

Please sign in to comment.