Skip to content

Commit

Permalink
jobs: VPR 7.05 changes (#304)
Browse files Browse the repository at this point in the history
- Add vipersight support for Honed buffs
- Rename Dread combo to Vice combo
- Remove Noxious Gnash Timer

---------

Co-authored-by: Maiko Tan <[email protected]>
  • Loading branch information
Echoring and MaikoTan authored Aug 2, 2024
1 parent 4043ff4 commit cd0d387
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 81 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ Verstone Ready duration, Verfire Ready duration, Fleche cooldown, Contre Sixte c
|<img src="./resources/ffxiv/jobs/nin-large.png" width="30px"/><br> Ninja|**Resource zone**: Ninki amount, Kazematoi stack, combo timer. <br> **Tracking zone**: Trick Attack duration & cooldown, Bunshin cooldown, Mudra cooldown.|
|<img src="./resources/ffxiv/jobs/sam-large.png" width="30px"/><br> Samurai|**Resource zone**: Kenki amount, Meditation stack, combo timer, held Sen. <br> **Tracking zone**: Fugetsu buff duration, Fuka buff duration, Higanbana DoT duration, Ikishoten cooldown.|
|<img src="./resources/ffxiv/jobs/rpr-large.png" width="30px"/><br> Reaper|**Resource zone**: Soul amount, Shroud amount, combo timer, Lemure Shroud/Void Shroud stack (under Enshroud). <br> **Tracking zone**: Death's Design duration, Soul Slice/Soul Scythe cooldown, Gluttony cooldown, Arcane Circle duration & cooldown.|
|<img src="./resources/ffxiv/jobs/vpr.png" width="30px"/><br> Viper|**Resource zone**: Rattling Coil Stack, Serpent Offerings amount, combo timer, ViperSight gauge. <br> **Tracking zone**: Noxious Gnash duration, Hunter's Instinct duration, Swiftscaled duration, Dreadwinder cooldown.|
|<img src="./resources/ffxiv/jobs/vpr.png" width="30px"/><br> Viper|**Resource zone**: Rattling Coil Stack, Serpent Offerings amount, combo timer, ViperSight gauge. <br> **Tracking zone**: Hunter's Instinct duration, Swiftscaled duration, Vice Combo cooldown.|
|<img src="./resources/ffxiv/jobs/brd-large.png" width="30px"/><br> Bard|**Resource zone**: Repertoire stack, Soul Voice amount, Repertoire tick timer, held Coda. <br> **Tracking zone**: Windbite/Venomous Bite DoT duration, Song duration, Empyreal Arrow cooldown, Hawk's Eyes/Barrage proc duration.|
|<img src="./resources/ffxiv/jobs/mch-large.png" width="30px"/><br> Machinist|**Resource zone**: Heat/Overheated stack, Battery/Automaton Queen duration, combo timer, Wildfire GCD counter (if Wildfire active). <br> **Tracking zone**: Drill/Bioblaster cooldown, Air Anchor cooldown, Chain Saw cooldown, Wildfire duration & cooldown.|
|<img src="./resources/ffxiv/jobs/dnc-large.png" width="30px"/><br> Dancer|**Resource zone**: Fourfold Feather amount, Esprit amount, combo timer. <br> **Tracking zone**: Standard Step cooldown, Technical Step duration & cooldown, Flourish duration & cooldown.|
Expand Down
4 changes: 2 additions & 2 deletions plugin/CactbotEventSource/FFXIVProcessIntl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -935,10 +935,10 @@ public struct ReaperJobMemory {
[StructLayout(LayoutKind.Explicit)]
public struct ViperJobMemory {
public enum AdvancedCombo : byte {
Dreadwinder = 1,
Vicewinder = 1,
HuntersCoil = 2,
SwiftskinsCoil = 3,
PitOfDread = 4,
Vicepit = 4,
HuntersDen = 5,
SwiftskinsDen = 6,
Reawaken = 7,
Expand Down
4 changes: 2 additions & 2 deletions types/event.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ export interface JobDetail {
anguineTribute: number;
serpentOffering: number;
advancedCombo:
| 'Dreadwinder'
| 'Vicewinder'
| 'HuntersCoil'
| 'SwiftskinsCoil'
| 'PitOfDread'
| 'Vicepit'
| 'HuntersDen'
| 'SwiftskinsDen'
| 'Reawaken'
Expand Down
135 changes: 66 additions & 69 deletions ui/jobs/components/vpr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,33 @@ export class VPRComponent extends BaseComponent {
rattlingCoil: ResourceBox;
serpentOfferings: ResourceBox;
comboTimer: TimerBar;
noxiousGnashTimer: TimerBox;
huntersInstinctTimer: TimerBox;
swiftscaledTimer: TimerBox;
dreadComboTimer: TimerBox;
viceComboTimer: TimerBox;

vipersight: HTMLDivElement;
currentVenomEffect = '';
currentComboAction = '';
Combo = '';
Venom = '';
Honed = '';
tid1 = 0;

static comboStage: Record<string, string> = {
[kAbility.SteelFangs]: '1',
[kAbility.DreadFangs]: '1',
[kAbility.HuntersSting]: '2',
[kAbility.SwiftskinsSting]: '2',
[kAbility.SteelMaw]: '1',
[kAbility.DreadMaw]: '1',
[kAbility.HuntersBite]: '2',
[kAbility.SwiftskinsBite]: '2',
['']: '0',
};

static honedMap: Record<string, string> = {
[EffectId.HonedSteel]: 'left',
[EffectId.HonedReavers]: 'right',
};

static vipersightMap: Record<string, Record<string, 'left' | 'right'>> = {
// Single target - first skill
[kAbility.SteelFangs]: {
Expand Down Expand Up @@ -72,11 +89,6 @@ export class VPRComponent extends BaseComponent {
fgColor: 'combo-color',
});

this.noxiousGnashTimer = this.bars.addProcBox({
id: 'vpr-timers-noxious-gnash',
fgColor: 'vpr-color-noxious-gnash',
});

this.huntersInstinctTimer = this.bars.addProcBox({
id: 'vpr-timers-hunters-instinct',
fgColor: 'vpr-color-hunters-instinct',
Expand All @@ -87,9 +99,9 @@ export class VPRComponent extends BaseComponent {
fgColor: 'vpr-color-swiftscaled',
});

this.dreadComboTimer = this.bars.addProcBox({
id: 'vpr-timers-dreadcombo',
fgColor: 'vpr-color-dreadcombo',
this.viceComboTimer = this.bars.addProcBox({
id: 'vpr-timers-vicecombo',
fgColor: 'vpr-color-vicecombo',
});

const stackContainer = document.createElement('div');
Expand All @@ -107,19 +119,22 @@ export class VPRComponent extends BaseComponent {
}
}

override onUseAbility(id: string, matches: PartialFieldMatches<'Ability'>): void {
if (id in VPRComponent.vipersightMap && matches.targetId !== 'E0000000') {
this.currentComboAction = id;
const side = VPRComponent.vipersightMap[id]?.[this.currentVenomEffect];
this.vipersight.dataset.side = side ?? 'both';
this.vipersight.classList.add('active');
refreshVipersight(combo: string, venom: string, honed: string): void {
const stage = VPRComponent.comboStage[combo];
this.vipersight.dataset.stacks = stage;
if (stage !== '0') {
this.vipersight.dataset.side = VPRComponent.vipersightMap[combo]?.[venom] ?? 'both';
} else {
this.vipersight.dataset.side = VPRComponent.honedMap[honed] ?? 'both';
}
}

override onUseAbility(id: string, matches: PartialFieldMatches<'Ability'>): void {
switch (id) {
case kAbility.Dreadwinder:
case kAbility.PitOfDread:
case kAbility.Vicewinder:
case kAbility.Vicepit:
if (matches.targetIndex === '0') {
this.dreadComboTimer.duration = 40 + (this.dreadComboTimer.value ?? 0);
this.viceComboTimer.duration = 40 + (this.viceComboTimer.value ?? 0);
}
break;
// Due to viper auto combo, combo action cannot be used out of combo.
Expand All @@ -128,32 +143,23 @@ export class VPRComponent extends BaseComponent {
case kAbility.DreadFangs:
case kAbility.SteelMaw:
case kAbility.DreadMaw:
if (matches.targetId !== 'E0000000') {
this.comboTimer.duration = this.comboDuration;
this.vipersight.dataset.stacks = '1';
window.clearTimeout(this.tid1);
this.tid1 = window.setTimeout(() => {
this.vipersight.classList.remove('active');
}, kComboDelay * 1000);
} else {
this.comboTimer.duration = 0;
this.vipersight.classList.remove('active');
}
break;
case kAbility.HuntersSting:
case kAbility.SwiftskinsSting:
case kAbility.HuntersBite:
case kAbility.SwiftskinsBite:
if (matches.targetId !== 'E0000000') {
this.comboTimer.duration = this.comboDuration;
this.vipersight.dataset.stacks = '2';
this.Combo = id;
this.refreshVipersight(this.Combo, this.Venom, this.Honed);
window.clearTimeout(this.tid1);
this.tid1 = window.setTimeout(() => {
this.vipersight.classList.remove('active');
this.Combo = '';
this.refreshVipersight(this.Combo, this.Venom, this.Honed);
}, kComboDelay * 1000);
} else {
this.comboTimer.duration = 0;
this.vipersight.classList.remove('active');
this.Combo = '';
this.refreshVipersight(this.Combo, this.Venom, this.Honed);
}
break;
case kAbility.FlankstingStrike:
Expand All @@ -163,9 +169,8 @@ export class VPRComponent extends BaseComponent {
case kAbility.JaggedMaw:
case kAbility.BloodiedMaw:
this.comboTimer.duration = 0;
// Disable Vipersight when player deliver any third combo skill
this.vipersight.classList.remove('active');
this.vipersight.dataset.stacks = '0';
this.Combo = '';
this.refreshVipersight(this.Combo, this.Venom, this.Honed);
window.clearTimeout(this.tid1);
break;
}
Expand All @@ -189,7 +194,11 @@ export class VPRComponent extends BaseComponent {
case EffectId.FlankstungVenom:
case EffectId.GrimhuntersVenom:
case EffectId.GrimskinsVenom:
this.currentVenomEffect = id;
this.Venom = id;
break;
case EffectId.HonedSteel:
case EffectId.HonedReavers:
this.Honed = id;
break;
}
}
Expand All @@ -209,30 +218,14 @@ export class VPRComponent extends BaseComponent {
case EffectId.FlankstungVenom:
case EffectId.GrimhuntersVenom:
case EffectId.GrimskinsVenom:
this.currentVenomEffect = '';
if (this.vipersight.dataset.stacks !== '0') {
this.vipersight.dataset.side = 'both';
this.vipersight.classList.add('active');
}
this.Venom = '';
this.refreshVipersight(this.Combo, this.Venom, this.Honed);
break;
}
}

override onMobGainsEffectFromYou(id: string, matches: PartialFieldMatches<'GainsEffect'>): void {
switch (id) {
case EffectId.NoxiousGnash_E53: {
// FIXME:
// Noxious Gnash can be different duration on multiple target,
// and this condition will only monitor the longest one.
// If you defeat a target with longer Noxious Gnash duration remains
// and move to a new or shorter duration target,
// This timer will not work well until new Noxious Gnash duration exceed timer.
// For the same reason, timer will not reset when target with debuff is defeated.
const duration = parseFloat(matches.duration ?? '0') || 0;
if (this.noxiousGnashTimer.value < duration)
this.noxiousGnashTimer.duration = duration - 0.5; // debuff delay
case EffectId.HonedSteel:
case EffectId.HonedReavers:
this.Honed = '';
this.refreshVipersight(this.Combo, this.Venom, this.Honed);
break;
}
}
}

Expand All @@ -253,21 +246,25 @@ export class VPRComponent extends BaseComponent {
}

override onStatChange({ gcdSkill }: { gcdSkill: number }): void {
// Can safely use Reawaken than use Dread Combo to extend buffs
this.noxiousGnashTimer.threshold = gcdSkill * 5 + 1;
// Can safely use Reawaken than use Vice Combo to extend buffs
this.huntersInstinctTimer.threshold = gcdSkill * 8 + 1;
this.swiftscaledTimer.threshold = gcdSkill * 8 + 1;
this.dreadComboTimer.threshold = gcdSkill * 5 + 1;
this.viceComboTimer.threshold = gcdSkill * 5 + 1;
}

override reset(): void {
this.rattlingCoil.innerText = '0';
this.noxiousGnashTimer.duration = 0;
this.rattlingCoil.parentNode.classList.remove('pulse');
this.serpentOfferings.innerText = '0';
this.serpentOfferings.parentNode.classList.remove('high', 'active', 'pulse');
this.comboTimer.duration = 0;
this.huntersInstinctTimer.duration = 0;
this.swiftscaledTimer.duration = 0;
this.vipersight.classList.remove('active');
this.vipersight.dataset.stacks = '0';
this.vipersight.dataset.side = '';
this.viceComboTimer.duration = 0;
this.Combo = '';
this.Venom = '';
this.Honed = '';
this.refreshVipersight(this.Combo, this.Venom, this.Honed);
window.clearTimeout(this.tid1);
}
}
4 changes: 2 additions & 2 deletions ui/jobs/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ export const kAbility = {
SwiftskinsBite: '8739',
JaggedMaw: '873A',
BloodiedMaw: '873B',
Dreadwinder: '873C',
PitOfDread: '873F',
Vicewinder: '873C',
Vicepit: '873F',
// BRD
BattleVoice: '76',
MagesBallad: '72',
Expand Down
14 changes: 9 additions & 5 deletions ui/jobs/jobs.css
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@ div.justbuffs div#procs-container {
background-color: rgb(255 0 255);
}

#vpr-stacks-vipersight[data-stacks="0"] {
--bg-color: rgb(255 255 0);
}

#vpr-stacks-vipersight[data-stacks="1"] {
--bg-color: rgb(255 0 0);
}
Expand All @@ -450,10 +454,10 @@ div.justbuffs div#procs-container {
--bg-color: rgb(20 200 255);
}

#vpr-stacks-vipersight.active[data-side="both"] > div.left,
#vpr-stacks-vipersight.active[data-side="both"] > div.right,
#vpr-stacks-vipersight.active[data-side="left"] > div.left,
#vpr-stacks-vipersight.active[data-side="right"] > div.right {
#vpr-stacks-vipersight[data-side="both"] > div.left,
#vpr-stacks-vipersight[data-side="both"] > div.right,
#vpr-stacks-vipersight[data-side="left"] > div.left,
#vpr-stacks-vipersight[data-side="right"] > div.right {
background-color: var(--bg-color);
}

Expand Down Expand Up @@ -1147,7 +1151,7 @@ div.justbuffs div#procs-container {
background-color: rgb(255 200 60);
}

.vpr-color-dreadcombo {
.vpr-color-vicecombo {
background-color: rgb(99 123 77);
}

Expand Down

0 comments on commit cd0d387

Please sign in to comment.