diff --git a/proto/apl.proto b/proto/apl.proto index 799d4d3620..990128ac81 100644 --- a/proto/apl.proto +++ b/proto/apl.proto @@ -112,6 +112,7 @@ message APLValue { APLValueCurrentEnergy current_energy = 15; APLValueCurrentComboPoints current_combo_points = 16; APLValueTimeToEnergyTick time_to_energy_tick = 66; + APLValueEnergyThreshold energy_threshold = 73; // GCD values APLValueGCDIsReady gcd_is_ready = 17; @@ -378,6 +379,9 @@ message APLValueCurrentRage {} message APLValueCurrentEnergy {} message APLValueCurrentComboPoints {} message APLValueTimeToEnergyTick {} +message APLValueEnergyThreshold { + int32 threshold = 1; +} message APLValueGCDIsReady {} message APLValueGCDTimeToReady {} diff --git a/sim/core/apl_actions_casting.go b/sim/core/apl_actions_casting.go index 91645d4f0a..4646c05e24 100644 --- a/sim/core/apl_actions_casting.go +++ b/sim/core/apl_actions_casting.go @@ -242,7 +242,7 @@ type APLActionAutocastOtherCooldowns struct { nextReadyMCD *MajorCooldown } -func (rot *APLRotation) newActionAutocastOtherCooldowns(config *proto.APLActionAutocastOtherCooldowns) APLActionImpl { +func (rot *APLRotation) newActionAutocastOtherCooldowns(_ *proto.APLActionAutocastOtherCooldowns) APLActionImpl { unit := rot.unit return &APLActionAutocastOtherCooldowns{ character: unit.Env.Raid.GetPlayerFromUnit(unit).GetCharacter(), diff --git a/sim/core/apl_value.go b/sim/core/apl_value.go index e59e308065..fab70dab67 100644 --- a/sim/core/apl_value.go +++ b/sim/core/apl_value.go @@ -35,19 +35,19 @@ type DefaultAPLValueImpl struct { func (impl DefaultAPLValueImpl) GetInnerValues() []APLValue { return nil } func (impl DefaultAPLValueImpl) Finalize(*APLRotation) {} -func (impl DefaultAPLValueImpl) GetBool(sim *Simulation) bool { +func (impl DefaultAPLValueImpl) GetBool(_ *Simulation) bool { panic("Unimplemented GetBool") } -func (impl DefaultAPLValueImpl) GetInt(sim *Simulation) int32 { +func (impl DefaultAPLValueImpl) GetInt(_ *Simulation) int32 { panic("Unimplemented GetInt") } -func (impl DefaultAPLValueImpl) GetFloat(sim *Simulation) float64 { +func (impl DefaultAPLValueImpl) GetFloat(_ *Simulation) float64 { panic("Unimplemented GetFloat") } -func (impl DefaultAPLValueImpl) GetDuration(sim *Simulation) time.Duration { +func (impl DefaultAPLValueImpl) GetDuration(_ *Simulation) time.Duration { panic("Unimplemented GetDuration") } -func (impl DefaultAPLValueImpl) GetString(sim *Simulation) string { +func (impl DefaultAPLValueImpl) GetString(_ *Simulation) string { panic("Unimplemented GetString") } @@ -111,6 +111,8 @@ func (rot *APLRotation) newAPLValue(config *proto.APLValue) APLValue { return rot.newValueCurrentComboPoints(config.GetCurrentComboPoints()) case *proto.APLValue_TimeToEnergyTick: return rot.newValueTimeToEnergyTick(config.GetTimeToEnergyTick()) + case *proto.APLValue_EnergyThreshold: + return rot.newValueEnergyThreshold(config.GetEnergyThreshold()) // GCD case *proto.APLValue_GcdIsReady: @@ -192,6 +194,6 @@ func (rot *APLRotation) newAPLValue(config *proto.APLValue) APLValue { } // Default implementation of Agent.NewAPLValue so each spec doesn't need this boilerplate. -func (unit *Unit) NewAPLValue(rot *APLRotation, config *proto.APLValue) APLValue { +func (unit *Unit) NewAPLValue(_ *APLRotation, _ *proto.APLValue) APLValue { return nil } diff --git a/sim/core/apl_values_resources.go b/sim/core/apl_values_resources.go index 5fda747779..8ebfca7143 100644 --- a/sim/core/apl_values_resources.go +++ b/sim/core/apl_values_resources.go @@ -28,7 +28,7 @@ func (rot *APLRotation) newValueCurrentHealth(config *proto.APLValueCurrentHealt func (value *APLValueCurrentHealth) Type() proto.APLValueType { return proto.APLValueType_ValueTypeFloat } -func (value *APLValueCurrentHealth) GetFloat(sim *Simulation) float64 { +func (value *APLValueCurrentHealth) GetFloat(_ *Simulation) float64 { return value.unit.Get().CurrentHealth() } func (value *APLValueCurrentHealth) String() string { @@ -56,7 +56,7 @@ func (rot *APLRotation) newValueCurrentHealthPercent(config *proto.APLValueCurre func (value *APLValueCurrentHealthPercent) Type() proto.APLValueType { return proto.APLValueType_ValueTypeFloat } -func (value *APLValueCurrentHealthPercent) GetFloat(sim *Simulation) float64 { +func (value *APLValueCurrentHealthPercent) GetFloat(_ *Simulation) float64 { return value.unit.Get().CurrentHealthPercent() } func (value *APLValueCurrentHealthPercent) String() string { @@ -84,7 +84,7 @@ func (rot *APLRotation) newValueCurrentMana(config *proto.APLValueCurrentMana) A func (value *APLValueCurrentMana) Type() proto.APLValueType { return proto.APLValueType_ValueTypeFloat } -func (value *APLValueCurrentMana) GetFloat(sim *Simulation) float64 { +func (value *APLValueCurrentMana) GetFloat(_ *Simulation) float64 { return value.unit.Get().CurrentMana() } func (value *APLValueCurrentMana) String() string { @@ -112,7 +112,7 @@ func (rot *APLRotation) newValueCurrentManaPercent(config *proto.APLValueCurrent func (value *APLValueCurrentManaPercent) Type() proto.APLValueType { return proto.APLValueType_ValueTypeFloat } -func (value *APLValueCurrentManaPercent) GetFloat(sim *Simulation) float64 { +func (value *APLValueCurrentManaPercent) GetFloat(_ *Simulation) float64 { return value.unit.Get().CurrentManaPercent() } func (value *APLValueCurrentManaPercent) String() string { @@ -124,7 +124,7 @@ type APLValueCurrentRage struct { unit *Unit } -func (rot *APLRotation) newValueCurrentRage(config *proto.APLValueCurrentRage) APLValue { +func (rot *APLRotation) newValueCurrentRage(_ *proto.APLValueCurrentRage) APLValue { unit := rot.unit if !unit.HasRageBar() { rot.ValidationWarning("%s does not use Rage", unit.Label) @@ -137,7 +137,7 @@ func (rot *APLRotation) newValueCurrentRage(config *proto.APLValueCurrentRage) A func (value *APLValueCurrentRage) Type() proto.APLValueType { return proto.APLValueType_ValueTypeFloat } -func (value *APLValueCurrentRage) GetFloat(sim *Simulation) float64 { +func (value *APLValueCurrentRage) GetFloat(_ *Simulation) float64 { return value.unit.CurrentRage() } func (value *APLValueCurrentRage) String() string { @@ -149,7 +149,7 @@ type APLValueCurrentEnergy struct { unit *Unit } -func (rot *APLRotation) newValueCurrentEnergy(config *proto.APLValueCurrentEnergy) APLValue { +func (rot *APLRotation) newValueCurrentEnergy(_ *proto.APLValueCurrentEnergy) APLValue { unit := rot.unit if !unit.HasEnergyBar() { rot.ValidationWarning("%s does not use Energy", unit.Label) @@ -162,7 +162,7 @@ func (rot *APLRotation) newValueCurrentEnergy(config *proto.APLValueCurrentEnerg func (value *APLValueCurrentEnergy) Type() proto.APLValueType { return proto.APLValueType_ValueTypeFloat } -func (value *APLValueCurrentEnergy) GetFloat(sim *Simulation) float64 { +func (value *APLValueCurrentEnergy) GetFloat(_ *Simulation) float64 { return value.unit.CurrentEnergy() } func (value *APLValueCurrentEnergy) String() string { @@ -174,7 +174,7 @@ type APLValueCurrentComboPoints struct { unit *Unit } -func (rot *APLRotation) newValueCurrentComboPoints(config *proto.APLValueCurrentComboPoints) APLValue { +func (rot *APLRotation) newValueCurrentComboPoints(_ *proto.APLValueCurrentComboPoints) APLValue { unit := rot.unit if !unit.HasEnergyBar() { rot.ValidationWarning("%s does not use Combo Points", unit.Label) @@ -187,7 +187,7 @@ func (rot *APLRotation) newValueCurrentComboPoints(config *proto.APLValueCurrent func (value *APLValueCurrentComboPoints) Type() proto.APLValueType { return proto.APLValueType_ValueTypeInt } -func (value *APLValueCurrentComboPoints) GetInt(sim *Simulation) int32 { +func (value *APLValueCurrentComboPoints) GetInt(_ *Simulation) int32 { return value.unit.ComboPoints() } func (value *APLValueCurrentComboPoints) String() string { @@ -199,7 +199,7 @@ type APLValueTimeToEnergyTick struct { unit *Unit } -func (rot *APLRotation) newValueTimeToEnergyTick(config *proto.APLValueTimeToEnergyTick) APLValue { +func (rot *APLRotation) newValueTimeToEnergyTick(_ *proto.APLValueTimeToEnergyTick) APLValue { unit := rot.unit if !unit.HasEnergyBar() { rot.ValidationWarning("%s does not use Energy", unit.Label) @@ -218,3 +218,33 @@ func (value *APLValueTimeToEnergyTick) GetDuration(sim *Simulation) time.Duratio func (value *APLValueTimeToEnergyTick) String() string { return "Time to Next Energy Tick" } + +type APLValueEnergyThreshold struct { + DefaultAPLValueImpl + unit *Unit + threshold float64 +} + +func (rot *APLRotation) newValueEnergyThreshold(config *proto.APLValueEnergyThreshold) APLValue { + unit := rot.unit + if !unit.HasEnergyBar() { + rot.ValidationWarning("%s does not use Energy", unit.Label) + return nil + } + return &APLValueEnergyThreshold{ + unit: unit, + threshold: float64(config.Threshold), + } +} +func (value *APLValueEnergyThreshold) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeBool +} +func (value *APLValueEnergyThreshold) GetBool(_ *Simulation) bool { + if value.threshold > 0 { + return value.unit.currentEnergy >= value.threshold + } + return value.unit.currentEnergy >= value.unit.maxEnergy+value.threshold +} +func (value *APLValueEnergyThreshold) String() string { + return "Energy Threshold" +} diff --git a/sim/core/major_cooldown.go b/sim/core/major_cooldown.go index 335d44c61d..0f53daf63f 100644 --- a/sim/core/major_cooldown.go +++ b/sim/core/major_cooldown.go @@ -131,7 +131,7 @@ func (mcd *MajorCooldown) shouldActivateHelper(sim *Simulation, character *Chara return sim.CurrentTime >= mcd.timings[mcd.numUsages] } - if mcd.Type.Matches(CooldownTypeSurvival) && character.cooldownConfigs.HpPercentForDefensives != 0 { + if mcd.Type.Matches(CooldownTypeSurvival) { // survival cooldowns are now skipped unless HpPercentForDefensives is > 0 if character.CurrentHealthPercent() > character.cooldownConfigs.HpPercentForDefensives { return false } @@ -227,15 +227,6 @@ func (mcdm *majorCooldownManager) finalize() { mcdm.majorCooldowns = make([]*MajorCooldown, len(mcdm.initialMajorCooldowns)) } -func findTrinketAura(character *Character, trinketID int32) *Aura { - for _, aura := range character.auras { - if aura.ActionIDForProc.ItemID == trinketID { - return aura - } - } - return nil -} - func (mcdm *majorCooldownManager) reset(_ *Simulation) { for i := range mcdm.majorCooldowns { newMCD := &MajorCooldown{} diff --git a/ui/core/components/individual_sim_ui/apl_values.ts b/ui/core/components/individual_sim_ui/apl_values.ts index 46e4346aa9..e4897e7af7 100644 --- a/ui/core/components/individual_sim_ui/apl_values.ts +++ b/ui/core/components/individual_sim_ui/apl_values.ts @@ -32,6 +32,7 @@ import { APLValueCurrentTimePercent, APLValueDotIsActive, APLValueDotRemainingTime, + APLValueEnergyThreshold, APLValueFrontOfTarget, APLValueGCDIsReady, APLValueGCDTimeToReady, @@ -62,10 +63,10 @@ import { APLValueSpellTravelTime, APLValueTimeToEnergyTick, APLValueTotemRemainingTime, - APLValueWarlockShouldRecastDrainSoul, - APLValueWarlockShouldRefreshCorruption, APLValueWarlockCurrentPetMana, APLValueWarlockCurrentPetManaPercent, + APLValueWarlockShouldRecastDrainSoul, + APLValueWarlockShouldRefreshCorruption, } from '../../proto/apl.js'; import { Class, Spec } from '../../proto/common.js'; import { ShamanTotems_TotemType as TotemType } from '../../proto/shaman.js'; @@ -642,6 +643,19 @@ const valueKindFactories: { [f in NonNullable]: ValueKindConfig, _isPrepull: boolean) => player.getClass() == Class.ClassRogue || player.getClass() == Class.ClassDruid, }), + energyThreshold: inputBuilder({ + label: 'Energy Threshold', + submenu: ['Resources'], + shortDescription: 'Compares current energy to a threshold value.', + newValue: APLValueEnergyThreshold.create, + fields: [ + AplHelpers.numberFieldConfig('threshold', false, { + label: '>=', + labelTooltip: "Energy threshold. Subtracted from maximum energy if negative.", + }), + ], + includeIf: (player: Player, _isPrepull: boolean) => player.getClass() == Class.ClassRogue || player.getClass() == Class.ClassDruid, + }), currentComboPoints: inputBuilder({ label: 'Combo Points', submenu: ['Resources'],