Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 31 additions & 28 deletions proto/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -809,34 +809,37 @@ message TargetInput {
}

message Target {
// The in-game NPC ID.
int32 id = 14;
string name = 15;

int32 level = 4;
MobType mob_type = 3;
repeated double stats = 5;

// Auto attack parameters.
double min_base_damage = 7;
double damage_spread = 19; // replaces tight_enemy_damage
double swing_speed = 8;
bool dual_wield = 9;
bool dual_wield_penalty = 10;
bool parry_haste = 12;
bool suppress_dodge = 16; // Sunwell Radiance
SpellSchool spell_school = 13; // Allows elemental attacks.

// Index in Raid.tanks indicating the player tanking this mob at the
// start of each pull.
// -1 or invalid index indicates not being tanked.
int32 tank_index = 6;

// Used in tank swap AIs.
int32 second_tank_index = 100;

// Custom Target AI parameters
repeated TargetInput target_inputs = 18;
// The in-game NPC ID.
int32 id = 14;
string name = 15;

int32 level = 4;
MobType mob_type = 3;
repeated double stats = 5;

// Auto attack parameters.
double min_base_damage = 7;
double damage_spread = 19; // replaces tight_enemy_damage
double swing_speed = 8;
bool dual_wield = 9;
bool dual_wield_penalty = 10;
bool parry_haste = 12;
bool suppress_dodge = 16; // Sunwell Radiance
SpellSchool spell_school = 13; // Allows elemental attacks.

// Index in Raid.tanks indicating the player tanking this mob at the
// start of each pull.
// -1 or invalid index indicates not being tanked.
int32 tank_index = 6;

// Used in tank swap AIs.
int32 second_tank_index = 100;

// Used in dynamic target AIs.
bool disabled_at_start = 101;

// Custom Target AI parameters
repeated TargetInput target_inputs = 18;
}

message Encounter {
Expand Down
22 changes: 10 additions & 12 deletions sim/common/cata/other_effects.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func init() {
dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit)
if sim.Proc(0.1, "Vengeful Wisp") {
// select random proc target
spreadTarget := sim.Encounter.TargetUnits[int(sim.Roll(0, float64(len(sim.Encounter.TargetUnits))))]
spreadTarget := sim.Encounter.ActiveTargetUnits[int(sim.Roll(0, float64(len(sim.Encounter.ActiveTargetUnits))))]

// refresh dot on next step - refreshing potentially on aura expire
// which will cause nasty things to happen
Expand Down Expand Up @@ -85,7 +85,7 @@ func init() {

if sim.Proc(0.1, "Vengeful Wisp") {
// select random proc target
spreadTarget := sim.Encounter.TargetUnits[int(sim.Roll(0, float64(len(sim.Encounter.TargetUnits))))]
spreadTarget := sim.Encounter.ActiveTargetUnits[int(sim.Roll(0, float64(len(sim.Encounter.ActiveTargetUnits))))]
spreadDot.Dot(spreadTarget).Apply(sim) // refresh self on
}
},
Expand Down Expand Up @@ -149,7 +149,7 @@ func init() {
},
},
ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) {
for _, aoeTarget := range sim.Encounter.TargetUnits {
for _, aoeTarget := range sim.Encounter.ActiveTargetUnits {
spell.CalcAndDealDamage(sim, aoeTarget, storedMana, spell.OutcomeMagicHitAndCrit)
}
character.AddMana(sim, storedMana, manaMetric)
Expand Down Expand Up @@ -947,8 +947,6 @@ func init() {
fetishItemID := []int32{77982, 77210, 78002}[version]
core.NewItemEffect(fetishItemID, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
numTargets := character.Env.GetNumTargets()

actionID := core.ActionID{SpellID: []int32{109753, 107998, 109755}[version]}
minDmg := []float64{8029, 9063, 10230}[version]
maxDmg := []float64{12044, 13594, 15345}[version]
Expand All @@ -965,12 +963,13 @@ func init() {
ThreatMultiplier: 1,

ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
numTargets := sim.Environment.ActiveTargetCount()
results := make([]*core.SpellResult, numTargets)

for idx := int32(0); idx < numTargets; idx++ {
for idx, target := range sim.Environment.GetActiveTargets() {
baseDamage := sim.Roll(minDmg, maxDmg) +
apMod*spell.MeleeAttackPower()
results[idx] = spell.CalcDamage(sim, sim.Environment.GetTargetUnit(idx), baseDamage, spell.OutcomeMeleeSpecialCritOnly)
results[idx] = spell.CalcDamage(sim, &target.Unit, baseDamage, spell.OutcomeMeleeSpecialCritOnly)
}

for idx := int32(0); idx < numTargets; idx++ {
Expand Down Expand Up @@ -999,8 +998,6 @@ func init() {
cunningItemID := []int32{77980, 77208, 78000}[version]
core.NewItemEffect(cunningItemID, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
numTargets := character.Env.GetNumTargets()

actionID := core.ActionID{SpellID: []int32{109798, 108005, 109800}[version]}
minDmg := []float64{2498, 2820, 3183}[version]
maxDmg := []float64{3747, 4230, 4774}[version]
Expand All @@ -1021,10 +1018,11 @@ func init() {
BonusCoefficient: spMod,

ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
numTargets := sim.Environment.ActiveTargetCount()
results := make([]*core.SpellResult, numTargets)

for idx := int32(0); idx < numTargets; idx++ {
results[idx] = spell.CalcDamage(sim, sim.Environment.GetTargetUnit(idx), sim.Roll(minDmg, maxDmg), spell.OutcomeMagicCrit)
for idx, target := range sim.Environment.GetActiveTargets() {
results[idx] = spell.CalcDamage(sim, &target.Unit, sim.Roll(minDmg, maxDmg), spell.OutcomeMagicCrit)
}

spell.WaitTravelTime(sim, func(sim *core.Simulation) {
Expand Down Expand Up @@ -1322,7 +1320,7 @@ func init() {
AffectedByCastSpeed: false,

OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) {
for _, aoeTarget := range sim.Encounter.TargetUnits {
for _, aoeTarget := range sim.Encounter.ActiveTargetUnits {
result := dot.Spell.CalcAndDealPeriodicDamage(sim, aoeTarget, tickDamage, dot.Spell.OutcomeMagicCritNoHitCounter)

if result.DidCrit() {
Expand Down
4 changes: 2 additions & 2 deletions sim/common/wotlk/shadowmourne.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ func init() {
ThreatMultiplier: 1,

ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
baseDamage := sim.Roll(1900, 2100) / float64(sim.GetNumTargets())
for _, target := range sim.Encounter.TargetUnits {
baseDamage := sim.Roll(1900, 2100) / float64(sim.ActiveTargetCount())
for _, target := range sim.Encounter.ActiveTargetUnits {
spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMagicHit) // probably has a very low crit rate
}
},
Expand Down
18 changes: 8 additions & 10 deletions sim/core/apl_actions_casting.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,13 @@ func (rot *APLRotation) newActionMultidot(config *proto.APLActionMultidot) APLAc
}

maxDots := config.MaxDots
numTargets := unit.Env.GetNumTargets()
maxTargets := unit.Env.TotalTargetCount()
if spell.Flags.Matches(SpellFlagHelpful) {
numTargets = int32(len(unit.Env.Raid.AllPlayerUnits))
maxTargets = int32(len(unit.Env.Raid.AllPlayerUnits))
}
if numTargets < maxDots {
rot.ValidationMessage(proto.LogLevel_Warning, "Encounter only has %d targets. Using that for Max Dots instead of %d", numTargets, maxDots)
maxDots = numTargets
if maxTargets < maxDots {
rot.ValidationMessage(proto.LogLevel_Warning, "Encounter only has %d targets. Using that for Max Dots instead of %d", maxTargets, maxDots)
maxDots = maxTargets
}

return &APLActionMultidot{
Expand Down Expand Up @@ -177,7 +177,7 @@ func (action *APLActionMultidot) IsReady(sim *Simulation) bool {
}
} else {
for i := int32(0); i < action.maxDots; i++ {
target := sim.Encounter.TargetUnits[i]
target := sim.Encounter.AllTargetUnits[i]
dot := action.spell.Dot(target)
if (!dot.IsActive() || dot.RemainingDuration(sim) < maxOverlap) && action.spell.CanCastOrQueue(sim, target) {
action.nextTarget = target
Expand Down Expand Up @@ -228,10 +228,8 @@ func (rot *APLRotation) newActionStrictMultidot(config *proto.APLActionStrictMul
targets = unit.Env.Raid.AllPlayerUnits
numTargets = int32(len(targets))
} else {
numTargets = unit.Env.GetNumTargets()
targets = MapSlice(unit.Env.ActiveTargetUnits(), func(target *Target) *Unit {
return &target.Unit
})
numTargets = unit.Env.TotalTargetCount()
targets = unit.Env.Encounter.AllTargetUnits
}
if numTargets < maxDots {
rot.ValidationMessage(proto.LogLevel_Warning, "Encounter only has %d targets. Using that for Max Dots instead of %d", numTargets, maxDots)
Expand Down
4 changes: 2 additions & 2 deletions sim/core/apl_values_encounter.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ func (value *APLValueNumberTargets) Type() proto.APLValueType {
return proto.APLValueType_ValueTypeInt
}
func (value *APLValueNumberTargets) GetInt(sim *Simulation) int32 {
return sim.GetNumTargets()
return sim.ActiveTargetCount()
}
func (value *APLValueNumberTargets) String() string {
return "Num Targets"
return "Num Active Targets"
}

type APLValueIsExecutePhase struct {
Expand Down
2 changes: 1 addition & 1 deletion sim/core/buffs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,7 @@ func registerShatteringThrowCD(agent Agent, numShatteringThrows int32) {
return
}

stAura := ShatteringThrowAura(agent.GetCharacter().Env.Encounter.TargetUnits[0], -1)
stAura := ShatteringThrowAura(agent.GetCharacter().Env.GetTargetUnitByIndex(0), -1)

registerExternalConsecutiveCDApproximation(
agent,
Expand Down
8 changes: 8 additions & 0 deletions sim/core/cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ func (spell *Spell) makeCastFunc(config CastConfig) CastSuccessFunc {
}
}

if (target.Type != PlayerUnit) && !target.IsEnabled() {
return spell.castFailureHelper(sim, "target disabled")
}

if spell.Flags.Matches(SpellFlagSwapped) {
return spell.castFailureHelper(sim, "spell attached to an un-equipped item")
}
Expand Down Expand Up @@ -228,6 +232,10 @@ func (spell *Spell) makeCastFunc(config CastConfig) CastSuccessFunc {

func (spell *Spell) makeCastFuncSimple() CastSuccessFunc {
return func(sim *Simulation, target *Unit) bool {
if (target.Type != PlayerUnit) && !target.IsEnabled() {
return spell.castFailureHelper(sim, "target disabled")
}

if spell.Flags.Matches(SpellFlagSwapped) {
return spell.castFailureHelper(sim, "spell attached to an un-equipped item")
}
Expand Down
2 changes: 1 addition & 1 deletion sim/core/consumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ func registerExplosivesCD(agent Agent, consumes *proto.ConsumesSpec) {

ApplyEffects: func(sim *Simulation, target *Unit, spell *Spell) {
baseDamage := 5006 * sim.Encounter.AOECapMultiplier()
for _, aoeTarget := range sim.Encounter.TargetUnits {
for _, aoeTarget := range sim.Encounter.ActiveTargetUnits {
spell.CalcAndDealDamage(sim, aoeTarget, baseDamage, spell.OutcomeMagicHitAndCrit)
}
},
Expand Down
47 changes: 25 additions & 22 deletions sim/core/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func NewEnvironment(raidProto *proto.Raid, encounterProto *proto.Encounter, runF
env.finalize(raidProto, encounterProto, raidStats, runFakePrepull)

encounterStats := &proto.EncounterStats{}
for _, target := range env.Encounter.Targets {
for _, target := range env.Encounter.AllTargets {
encounterStats.Targets = append(encounterStats.Targets, &proto.TargetStats{
Metadata: target.GetMetadata(),
})
Expand All @@ -75,27 +75,27 @@ func (env *Environment) construct(raidProto *proto.Raid, encounterProto *proto.E

env.Raid.updatePlayersAndPets()

env.AllUnits = append(env.Encounter.TargetUnits, env.Raid.AllUnits...)
env.AllUnits = append(env.Encounter.AllTargetUnits, env.Raid.AllUnits...)

for unitIndex, unit := range env.AllUnits {
unit.Env = env
unit.UnitIndex = int32(unitIndex)
}

for _, unit := range env.Raid.AllUnits {
unit.CurrentTarget = env.Encounter.TargetUnits[0]
unit.CurrentTarget = env.Encounter.ActiveTargetUnits[0]
}

// Apply extra debuffs from raid.
if raidProto.Debuffs != nil && len(env.Encounter.TargetUnits) > 0 {
for targetIdx, targetUnit := range env.Encounter.TargetUnits {
if raidProto.Debuffs != nil && len(env.Encounter.AllTargetUnits) > 0 {
for targetIdx, targetUnit := range env.Encounter.AllTargetUnits {
applyDebuffEffects(targetUnit, targetIdx, raidProto.Debuffs, raidProto)
}
}

tankTargetSet := map[*Unit]bool{}
// Assign target-of-target using Tanks field.
for _, target := range env.Encounter.Targets {
for _, target := range env.Encounter.AllTargets {
if target.Index < int32(len(encounterProto.Targets)) {
targetProto := encounterProto.Targets[target.Index]
env.setupTankTarget(target, targetProto.TankIndex, raidProto.Tanks, true, tankTargetSet)
Expand All @@ -111,7 +111,7 @@ func (env *Environment) construct(raidProto *proto.Raid, encounterProto *proto.E

// The initialization phase.
func (env *Environment) initialize(raidProto *proto.Raid, encounterProto *proto.Encounter) *proto.RaidStats {
for _, target := range env.Encounter.Targets {
for _, target := range env.Encounter.AllTargets {
if target.Index < int32(len(encounterProto.Targets)) {
target.initialize(encounterProto.Targets[target.Index])
} else {
Expand Down Expand Up @@ -144,7 +144,7 @@ func (env *Environment) finalize(raidProto *proto.Raid, _ *proto.Encounter, raid
}
env.preFinalizeEffects = nil

for _, target := range env.Encounter.Targets {
for _, target := range env.Encounter.AllTargets {
target.finalize()
if target.AI != nil {
target.Rotation = target.newCustomRotation()
Expand Down Expand Up @@ -263,7 +263,7 @@ func (env *Environment) reset(sim *Simulation) {

// Targets need to be reset before the raid, so that players can check for
// the presence of permanent target auras in their Reset handlers.
for _, target := range env.Encounter.Targets {
for _, target := range env.Encounter.AllTargets {
target.Reset(sim)
}

Expand All @@ -275,33 +275,36 @@ func (env *Environment) GetMaxDuration() time.Duration {
return env.BaseDuration + env.DurationVariation
}

func (env *Environment) GetNumTargets() int32 {
func (env *Environment) ActiveTargetCount() int32 {
return int32(len(env.Encounter.ActiveTargets))
}
func (env *Environment) TotalTargetCount() int32 {
return int32(len(env.Encounter.AllTargets))
}

func (env *Environment) ActiveTargetUnits() []*Target {
func (env *Environment) GetActiveTargets() []*Target {
return env.Encounter.ActiveTargets
}

func (env *Environment) GetTarget(index int32) *Target {
return env.Encounter.Targets[index]
func (env *Environment) GetTargetByIndex(index int32) *Target {
return env.Encounter.AllTargets[index]
}
func (env *Environment) GetTargetUnit(index int32) *Unit {
return &env.Encounter.Targets[index].Unit
func (env *Environment) GetTargetUnitByIndex(index int32) *Unit {
return env.Encounter.AllTargetUnits[index]
}
func (env *Environment) NextTarget(target *Unit) *Target {
return env.Encounter.Targets[target.Index].NextTarget()
func (env *Environment) NextActiveTarget(target *Unit) *Target {
return env.Encounter.AllTargets[target.Index].NextActiveTarget()
}
func (env *Environment) NextTargetUnit(target *Unit) *Unit {
return &env.NextTarget(target).Unit
func (env *Environment) NextActiveTargetUnit(target *Unit) *Unit {
return &env.NextActiveTarget(target).Unit
}
func (env *Environment) GetAgentFromUnit(unit *Unit) Agent {
raidAgent := env.Raid.GetPlayerFromUnit(unit)
if raidAgent != nil {
return raidAgent
}

for _, target := range env.Encounter.Targets {
for _, target := range env.Encounter.AllTargets {
if unit == &target.Unit {
return target
}
Expand Down Expand Up @@ -341,8 +344,8 @@ func (env *Environment) GetUnit(ref *proto.UnitReference, contextUnit *Unit) *Un
return nil
}
case proto.UnitReference_Target:
if int(ref.Index) < len(env.Encounter.TargetUnits) {
return env.Encounter.TargetUnits[ref.Index]
if int(ref.Index) < len(env.Encounter.AllTargetUnits) {
return env.Encounter.AllTargetUnits[ref.Index]
} else {
return nil
}
Expand Down
Loading
Loading