From 1e4a927caa259cb6da8d6c865ba3fad05bac418b Mon Sep 17 00:00:00 2001 From: James Tanner Date: Tue, 4 Jul 2023 09:42:50 -0700 Subject: [PATCH] Add lots of common APL values --- proto/apl.proto | 28 +++++ sim/core/apl_value.go | 24 ++++ sim/core/apl_values_core.go | 29 ++++- sim/core/apl_values_encounter.go | 63 +++++++++++ sim/core/apl_values_operators.go | 9 ++ sim/core/apl_values_resources.go | 105 ++++++++++++++++++ .../individual_sim_ui/apl_values.ts | 89 +++++++++++++++ 7 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 sim/core/apl_values_encounter.go create mode 100644 sim/core/apl_values_resources.go diff --git a/proto/apl.proto b/proto/apl.proto index 4b906493a1..f531f36d3f 100644 --- a/proto/apl.proto +++ b/proto/apl.proto @@ -41,8 +41,22 @@ message APLValue { APLValueNot not = 4; APLValueCompare cmp = 5; + // Encounter values + APLValueCurrentTime current_time = 7; + APLValueCurrentTimePercent current_time_percent = 8; + APLValueRemainingTime remaining_time = 9; + APLValueRemainingTimePercent remaining_time_percent = 10; + + // Resource values + APLValueCurrentMana current_mana = 11; + APLValueCurrentManaPercent current_mana_percent = 12; + APLValueCurrentRage current_rage = 14; + APLValueCurrentEnergy current_energy = 15; + APLValueCurrentComboPoints current_combo_points = 16; + // Dot values APLValueDotIsActive dot_is_active = 6; + APLValueDotRemainingTime dot_remaining_time = 13; } } @@ -119,6 +133,20 @@ message APLValueCompare { APLValue rhs = 3; } +message APLValueCurrentTime {} +message APLValueCurrentTimePercent {} +message APLValueRemainingTime {} +message APLValueRemainingTimePercent {} + +message APLValueCurrentMana {} +message APLValueCurrentManaPercent {} +message APLValueCurrentRage {} +message APLValueCurrentEnergy {} +message APLValueCurrentComboPoints {} + message APLValueDotIsActive { ActionID spell_id = 1; +} +message APLValueDotRemainingTime { + ActionID spell_id = 1; } \ No newline at end of file diff --git a/sim/core/apl_value.go b/sim/core/apl_value.go index f8ffe2bfa7..fa3af31cd6 100644 --- a/sim/core/apl_value.go +++ b/sim/core/apl_value.go @@ -57,9 +57,33 @@ func (unit *Unit) newAPLValue(config *proto.APLValue) APLValue { case *proto.APLValue_Cmp: return unit.newValueCompare(config.GetCmp()) + // Encounter + case *proto.APLValue_CurrentTime: + return unit.newValueCurrentTime(config.GetCurrentTime()) + case *proto.APLValue_CurrentTimePercent: + return unit.newValueCurrentTimePercent(config.GetCurrentTimePercent()) + case *proto.APLValue_RemainingTime: + return unit.newValueRemainingTime(config.GetRemainingTime()) + case *proto.APLValue_RemainingTimePercent: + return unit.newValueRemainingTimePercent(config.GetRemainingTimePercent()) + + // Resources + case *proto.APLValue_CurrentMana: + return unit.newValueCurrentMana(config.GetCurrentMana()) + case *proto.APLValue_CurrentManaPercent: + return unit.newValueCurrentManaPercent(config.GetCurrentManaPercent()) + case *proto.APLValue_CurrentRage: + return unit.newValueCurrentRage(config.GetCurrentRage()) + case *proto.APLValue_CurrentEnergy: + return unit.newValueCurrentEnergy(config.GetCurrentEnergy()) + case *proto.APLValue_CurrentComboPoints: + return unit.newValueCurrentComboPoints(config.GetCurrentComboPoints()) + // Dots case *proto.APLValue_DotIsActive: return unit.newValueDotIsActive(config.GetDotIsActive()) + case *proto.APLValue_DotRemainingTime: + return unit.newValueDotRemainingTime(config.GetDotRemainingTime()) default: validationError("Unimplemented value type") diff --git a/sim/core/apl_values_core.go b/sim/core/apl_values_core.go index 60d28bb4dd..b4cb8ddae0 100644 --- a/sim/core/apl_values_core.go +++ b/sim/core/apl_values_core.go @@ -1,6 +1,8 @@ package core import ( + "time" + "github.com/wowsims/wotlk/sim/core/proto" ) @@ -23,8 +25,12 @@ type APLValueDotIsActive struct { } func (unit *Unit) newValueDotIsActive(config *proto.APLValueDotIsActive) APLValue { + dot := unit.aplGetDot(config.SpellId) + if dot == nil { + return nil + } return &APLValueDotIsActive{ - dot: unit.aplGetDot(config.SpellId), + dot: dot, } } func (value *APLValueDotIsActive) Type() proto.APLValueType { @@ -33,3 +39,24 @@ func (value *APLValueDotIsActive) Type() proto.APLValueType { func (value *APLValueDotIsActive) GetBool(sim *Simulation) bool { return value.dot.IsActive() } + +type APLValueDotRemainingTime struct { + defaultAPLValueImpl + dot *Dot +} + +func (unit *Unit) newValueDotRemainingTime(config *proto.APLValueDotRemainingTime) APLValue { + dot := unit.aplGetDot(config.SpellId) + if dot == nil { + return nil + } + return &APLValueDotRemainingTime{ + dot: dot, + } +} +func (value *APLValueDotRemainingTime) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeDuration +} +func (value *APLValueDotRemainingTime) GetDuration(sim *Simulation) time.Duration { + return value.dot.RemainingDuration(sim) +} diff --git a/sim/core/apl_values_encounter.go b/sim/core/apl_values_encounter.go new file mode 100644 index 0000000000..97b217d0ef --- /dev/null +++ b/sim/core/apl_values_encounter.go @@ -0,0 +1,63 @@ +package core + +import ( + "time" + + "github.com/wowsims/wotlk/sim/core/proto" +) + +type APLValueCurrentTime struct { + defaultAPLValueImpl +} + +func (unit *Unit) newValueCurrentTime(config *proto.APLValueCurrentTime) APLValue { + return &APLValueCurrentTime{} +} +func (value *APLValueCurrentTime) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeDuration +} +func (value *APLValueCurrentTime) GetDuration(sim *Simulation) time.Duration { + return sim.CurrentTime +} + +type APLValueCurrentTimePercent struct { + defaultAPLValueImpl +} + +func (unit *Unit) newValueCurrentTimePercent(config *proto.APLValueCurrentTimePercent) APLValue { + return &APLValueCurrentTimePercent{} +} +func (value *APLValueCurrentTimePercent) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeFloat +} +func (value *APLValueCurrentTimePercent) GetFloat(sim *Simulation) float64 { + return sim.CurrentTime.Seconds() / sim.Duration.Seconds() +} + +type APLValueRemainingTime struct { + defaultAPLValueImpl +} + +func (unit *Unit) newValueRemainingTime(config *proto.APLValueRemainingTime) APLValue { + return &APLValueRemainingTime{} +} +func (value *APLValueRemainingTime) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeDuration +} +func (value *APLValueRemainingTime) GetDuration(sim *Simulation) time.Duration { + return sim.GetRemainingDuration() +} + +type APLValueRemainingTimePercent struct { + defaultAPLValueImpl +} + +func (unit *Unit) newValueRemainingTimePercent(config *proto.APLValueRemainingTimePercent) APLValue { + return &APLValueRemainingTimePercent{} +} +func (value *APLValueRemainingTimePercent) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeFloat +} +func (value *APLValueRemainingTimePercent) GetFloat(sim *Simulation) float64 { + return sim.GetRemainingDurationPercent() +} diff --git a/sim/core/apl_values_operators.go b/sim/core/apl_values_operators.go index b8ae9ca58c..5345a05de2 100644 --- a/sim/core/apl_values_operators.go +++ b/sim/core/apl_values_operators.go @@ -39,6 +39,15 @@ func (unit *Unit) newValueConst(config *proto.APLValueConst) APLValue { return result } + if len(config.Val) > 1 && config.Val[len(config.Val)-1] == '%' { + if floatVal, err := strconv.ParseFloat(config.Val[0:len(config.Val)-1], 64); err == nil { + result.floatVal = floatVal / 100.0 + result.durationVal = DurationFromSeconds(floatVal / 100.0) + result.valType = proto.APLValueType_ValueTypeFloat + return result + } + } + if floatVal, err := strconv.ParseFloat(config.Val, 64); err == nil { result.floatVal = floatVal result.durationVal = DurationFromSeconds(floatVal) diff --git a/sim/core/apl_values_resources.go b/sim/core/apl_values_resources.go new file mode 100644 index 0000000000..a166396d0a --- /dev/null +++ b/sim/core/apl_values_resources.go @@ -0,0 +1,105 @@ +package core + +import ( + "github.com/wowsims/wotlk/sim/core/proto" +) + +type APLValueCurrentMana struct { + defaultAPLValueImpl + unit *Unit +} + +func (unit *Unit) newValueCurrentMana(config *proto.APLValueCurrentMana) APLValue { + if !unit.HasManaBar() { + return nil + } + return &APLValueCurrentMana{ + unit: unit, + } +} +func (value *APLValueCurrentMana) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeFloat +} +func (value *APLValueCurrentMana) GetFloat(sim *Simulation) float64 { + return value.unit.CurrentMana() +} + +type APLValueCurrentManaPercent struct { + defaultAPLValueImpl + unit *Unit +} + +func (unit *Unit) newValueCurrentManaPercent(config *proto.APLValueCurrentManaPercent) APLValue { + if !unit.HasManaBar() { + return nil + } + return &APLValueCurrentManaPercent{ + unit: unit, + } +} +func (value *APLValueCurrentManaPercent) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeFloat +} +func (value *APLValueCurrentManaPercent) GetFloat(sim *Simulation) float64 { + return value.unit.CurrentManaPercent() +} + +type APLValueCurrentRage struct { + defaultAPLValueImpl + unit *Unit +} + +func (unit *Unit) newValueCurrentRage(config *proto.APLValueCurrentRage) APLValue { + if !unit.HasRageBar() { + return nil + } + return &APLValueCurrentRage{ + unit: unit, + } +} +func (value *APLValueCurrentRage) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeFloat +} +func (value *APLValueCurrentRage) GetFloat(sim *Simulation) float64 { + return value.unit.CurrentRage() +} + +type APLValueCurrentEnergy struct { + defaultAPLValueImpl + unit *Unit +} + +func (unit *Unit) newValueCurrentEnergy(config *proto.APLValueCurrentEnergy) APLValue { + if !unit.HasEnergyBar() { + return nil + } + return &APLValueCurrentEnergy{ + unit: unit, + } +} +func (value *APLValueCurrentEnergy) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeFloat +} +func (value *APLValueCurrentEnergy) GetFloat(sim *Simulation) float64 { + return value.unit.CurrentEnergy() +} + +type APLValueCurrentComboPoints struct { + defaultAPLValueImpl + unit *Unit +} + +func (unit *Unit) newValueCurrentComboPoints(config *proto.APLValueCurrentComboPoints) APLValue { + if !unit.HasEnergyBar() { + return nil + } + return &APLValueCurrentComboPoints{ + unit: unit, + } +} +func (value *APLValueCurrentComboPoints) Type() proto.APLValueType { + return proto.APLValueType_ValueTypeInt +} +func (value *APLValueCurrentComboPoints) GetInt(sim *Simulation) int32 { + return value.unit.ComboPoints() +} diff --git a/ui/core/components/individual_sim_ui/apl_values.ts b/ui/core/components/individual_sim_ui/apl_values.ts index db3d0d3957..c71020ec39 100644 --- a/ui/core/components/individual_sim_ui/apl_values.ts +++ b/ui/core/components/individual_sim_ui/apl_values.ts @@ -6,7 +6,17 @@ import { APLValueCompare, APLValueCompare_ComparisonOperator as ComparisonOperator, APLValueConst, + APLValueCurrentTime, + APLValueCurrentTimePercent, + APLValueRemainingTime, + APLValueRemainingTimePercent, + APLValueCurrentMana, + APLValueCurrentManaPercent, + APLValueCurrentRage, + APLValueCurrentEnergy, + APLValueCurrentComboPoints, APLValueDotIsActive, + APLValueDotRemainingTime, } from '../../proto/apl.js'; import { EventID, TypedEvent } from '../../typed_event.js'; @@ -226,6 +236,7 @@ function inputBuilder(config: { } const valueTypeFactories: Record, ValueTypeConfig> = { + // Operators ['const']: inputBuilder({ label: 'Const', shortDescription: 'A fixed value.', @@ -282,6 +293,75 @@ const valueTypeFactories: Record, ValueTypeConfig valueFieldConfig('val'), ], }), + + // Encounter + ['currentTime']: inputBuilder({ + label: 'Current Time', + submenu: ['Encounter'], + shortDescription: 'Elapsed time of the current sim iteration.', + newValue: APLValueCurrentTime.create, + fields: [], + }), + ['currentTimePercent']: inputBuilder({ + label: 'Current Time (%)', + submenu: ['Encounter'], + shortDescription: 'Elapsed time of the current sim iteration, as a percentage.', + newValue: APLValueCurrentTimePercent.create, + fields: [], + }), + ['remainingTime']: inputBuilder({ + label: 'Remaining Time', + submenu: ['Encounter'], + shortDescription: 'Elapsed time of the remaining sim iteration.', + newValue: APLValueRemainingTime.create, + fields: [], + }), + ['remainingTimePercent']: inputBuilder({ + label: 'Remaining Time (%)', + submenu: ['Encounter'], + shortDescription: 'Elapsed time of the remaining sim iteration, as a percentage.', + newValue: APLValueRemainingTimePercent.create, + fields: [], + }), + + // Resources + ['currentMana']: inputBuilder({ + label: 'Mana', + submenu: ['Resources'], + shortDescription: 'Amount of currently available Mana.', + newValue: APLValueCurrentMana.create, + fields: [], + }), + ['currentManaPercent']: inputBuilder({ + label: 'Mana (%)', + submenu: ['Resources'], + shortDescription: 'Amount of currently available Mana, as a percentage.', + newValue: APLValueCurrentManaPercent.create, + fields: [], + }), + ['currentRage']: inputBuilder({ + label: 'Rage', + submenu: ['Resources'], + shortDescription: 'Amount of currently available Rage.', + newValue: APLValueCurrentRage.create, + fields: [], + }), + ['currentEnergy']: inputBuilder({ + label: 'Energy', + submenu: ['Resources'], + shortDescription: 'Amount of currently available Energy.', + newValue: APLValueCurrentEnergy.create, + fields: [], + }), + ['currentComboPoints']: inputBuilder({ + label: 'Combo Points', + submenu: ['Resources'], + shortDescription: 'Amount of currently available Combo Points.', + newValue: APLValueCurrentComboPoints.create, + fields: [], + }), + + // DoT ['dotIsActive']: inputBuilder({ label: 'Dot Is Active', submenu: ['DoT'], @@ -291,4 +371,13 @@ const valueTypeFactories: Record, ValueTypeConfig AplHelpers.actionIdFieldConfig('spellId', 'dot_spells'), ], }), + ['dotRemainingTime']: inputBuilder({ + label: 'Dot Remaining Time', + submenu: ['DoT'], + shortDescription: 'Time remaining before the last tick of this DoT will occur, or 0 if the DoT is not currently ticking.', + newValue: APLValueDotRemainingTime.create, + fields: [ + AplHelpers.actionIdFieldConfig('spellId', 'dot_spells'), + ], + }), }; \ No newline at end of file