Skip to content

Commit

Permalink
Merge pull request #444 from wowsims/magam-ai
Browse files Browse the repository at this point in the history
Add AI to Magmaw Add and add Mage Firestarter talent
  • Loading branch information
rosenrusinov authored May 13, 2024
2 parents f9937bf + 69cbb8f commit aee8dca
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 26 deletions.
Binary file modified assets/database/db.bin
Binary file not shown.
4 changes: 2 additions & 2 deletions assets/database/db.json
Original file line number Diff line number Diff line change
Expand Up @@ -10131,8 +10131,8 @@
{"path":"Default/Movement","targets":[{"path":"Default/Movement","target":{"id":31147,"name":"Movement","level":88,"mobType":7,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,120016403,0,0,0,0,0,0,0],"minBaseDamage":210000,"damageSpread":0.4,"swingSpeed":2.5,"targetInputs":[{"inputType":1,"label":"Movement Interval","tooltip":"How often the player will move in seconds","numberValue":10},{"inputType":1,"label":"Reaction Time","tooltip":"How long the player can wait for casts to finish before moving in seconds","numberValue":1.5},{"inputType":1,"label":"Yards","tooltip":"How many yards the player moves","numberValue":5}]}}]},
{"path":"Blackwing Descent/Magmaw 10","targets":[{"path":"Blackwing Descent/Magmaw 10","target":{"id":41570,"name":"Magmaw 10","level":88,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,26798304,0,0,0,0,0,0,0],"minBaseDamage":110000,"damageSpread":0.4,"swingSpeed":2.5,"targetInputs":[{"inputType":1,"label":"Impale Reaction Time","tooltip":"How long will the Raid take to Impale Head in Seconds. (After the initial 10s)","numberValue":5}]}}]},
{"path":"Blackwing Descent/Magmaw 25","targets":[{"path":"Blackwing Descent/Magmaw 25","target":{"id":41571,"name":"Magmaw 25","level":88,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,81082048,0,0,0,0,0,0,0],"minBaseDamage":150000,"damageSpread":0.4,"swingSpeed":2.5,"targetInputs":[{"inputType":1,"label":"Impale Reaction Time","tooltip":"How long will the Raid take to Impale Head in Seconds. (After the initial 10s)","numberValue":5}]}}]},
{"path":"Blackwing Descent/Magmaw 10 H","targets":[{"path":"Blackwing Descent/Magmaw 10 H","target":{"id":41572,"name":"Magmaw 10 H","level":88,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,39200000,0,0,0,0,0,0,0],"minBaseDamage":150000,"damageSpread":0.4,"swingSpeed":2.5,"targetInputs":[{"inputType":1,"label":"Impale Reaction Time","tooltip":"How long will the Raid take to Impale Head in Seconds. (After the initial 10s)","numberValue":5}]}},{"path":"Blackwing Descent/Magmaw 10 H Blazing Construct","target":{"id":41582,"name":"Magmaw 10 H Blazing Construct","level":87,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,1410000,0,0,0,0,0,0,0],"minBaseDamage":44000,"damageSpread":0.5,"swingSpeed":2,"tankIndex":1}}]},
{"path":"Blackwing Descent/Magmaw 25 H","targets":[{"path":"Blackwing Descent/Magmaw 25 H","target":{"id":41573,"name":"Magmaw 25 H","level":88,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,120016403,0,0,0,0,0,0,0],"minBaseDamage":210000,"damageSpread":0.4,"swingSpeed":2.5,"targetInputs":[{"inputType":1,"label":"Impale Reaction Time","tooltip":"How long will the Raid take to Impale Head in Seconds. (After the initial 10s)","numberValue":5}]}},{"path":"Blackwing Descent/Magmaw 25 H Blazing Construct","target":{"id":41583,"name":"Magmaw 25 H Blazing Construct","level":87,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,4500000,0,0,0,0,0,0,0],"minBaseDamage":80000,"damageSpread":0.5,"swingSpeed":2,"tankIndex":1}}]}
{"path":"Blackwing Descent/Magmaw 10 H","targets":[{"path":"Blackwing Descent/Magmaw 10 H","target":{"id":41572,"name":"Magmaw 10 H","level":88,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,39200000,0,0,0,0,0,0,0],"minBaseDamage":150000,"damageSpread":0.4,"swingSpeed":2.5,"targetInputs":[{"inputType":1,"label":"Impale Reaction Time","tooltip":"How long will the Raid take to Impale Head in Seconds. (After the initial 10s)","numberValue":5}]}},{"path":"Blackwing Descent/Blazing Construct 10 H","target":{"id":41582,"name":"Blazing Construct 10 H","level":87,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,1410000,0,0,0,0,0,0,0],"minBaseDamage":44000,"damageSpread":0.5,"swingSpeed":2,"tankIndex":1}}]},
{"path":"Blackwing Descent/Magmaw 25 H","targets":[{"path":"Blackwing Descent/Magmaw 25 H","target":{"id":41573,"name":"Magmaw 25 H","level":88,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,120016403,0,0,0,0,0,0,0],"minBaseDamage":210000,"damageSpread":0.4,"swingSpeed":2.5,"targetInputs":[{"inputType":1,"label":"Impale Reaction Time","tooltip":"How long will the Raid take to Impale Head in Seconds. (After the initial 10s)","numberValue":5}]}},{"path":"Blackwing Descent/Blazing Construct 25 H","target":{"id":41583,"name":"Blazing Construct 25 H","level":87,"mobType":1,"stats":[0,0,0,0,0,0,0,0,0,0,0,650,0,0,0,0,0,0,11977,0,0,0,0,0,0,4500000,0,0,0,0,0,0,0],"minBaseDamage":80000,"damageSpread":0.5,"swingSpeed":2,"tankIndex":1}}]}
],
"glyphIds":[
{"itemId":40919,"spellId":54830},
Expand Down
1 change: 1 addition & 0 deletions sim/core/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func (env *Environment) construct(raidProto *proto.Raid, encounterProto *proto.E
raidTarget := env.GetUnit(raidTargetProto, nil)
if raidTarget != nil {
target.CurrentTarget = raidTarget
raidTarget.CurrentTarget = &target.Unit
}
}
}
Expand Down
70 changes: 56 additions & 14 deletions sim/encounters/bwd/magmaw_ai.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import (
"github.com/wowsims/cata/sim/core"
"github.com/wowsims/cata/sim/core/proto"
"github.com/wowsims/cata/sim/core/stats"
"github.com/wowsims/cata/sim/encounters/default_ai"
)

func createMagmawPreset(bossPrefix string, raidSize int, isHeroic bool, npcId int32, health float64, minBaseDamage float64, addHealth float64, addMinBaseDamage float64) {
targetName := fmt.Sprintf("Magmaw %d", raidSize)
targetNameAdd := fmt.Sprintf("Blazing Construct %d", raidSize)
if isHeroic {
targetName = targetName + " H"
targetNameAdd = targetNameAdd + " H"
}
targetNameAdd := targetName + " Blazing Construct"
core.AddPresetTarget(&core.PresetTarget{
PathPrefix: bossPrefix,
Config: &proto.Target{
Expand Down Expand Up @@ -92,7 +94,42 @@ func createMagmawPreset(bossPrefix string, raidSize int, isHeroic bool, npcId in
DamageSpread: 0.5,
TargetInputs: []*proto.TargetInput{},
},
AI: nil,
AI: default_ai.NewDefaultAI([]default_ai.TargetAbility{
{
InitialCD: time.Second * 5,
ChanceToUse: 0,
MakeSpell: func(target *core.Target) *core.Spell {
// Fiery Slash Next melee Spell
nextMeleeSpell := target.GetOrRegisterSpell(core.SpellConfig{
ActionID: core.ActionID{SpellID: 92144},
SpellSchool: core.SpellSchoolFire,
ProcMask: core.ProcMaskSpellDamage,

Cast: core.CastConfig{
CD: core.Cooldown{
Timer: target.NewTimer(),
Duration: time.Second * 7,
},
},

DamageMultiplier: 0.75,

ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
spell.CalcAndDealDamage(sim, target, spell.Unit.AutoAttacks.MH().EnemyWeaponDamage(sim, spell.MeleeAttackPower(), 0.5), spell.OutcomeEnemyMeleeWhite)
},
})

target.AutoAttacks.SetReplaceMHSwing(func(sim *core.Simulation, mhSwingSpell *core.Spell) *core.Spell {
if nextMeleeSpell.CanCast(sim, target.CurrentTarget) && sim.Proc(0.75, "Fiery Slash Cast") {
return nextMeleeSpell
}
return mhSwingSpell
})

return nextMeleeSpell
},
},
}),
})
core.AddPresetEncounter(targetName, []string{
bossPrefix + "/" + targetName,
Expand Down Expand Up @@ -221,6 +258,7 @@ func (ai *MagmawAI) registerSpells() {
OnExpire: func(aura *core.Aura, sim *core.Simulation) {
aura.Unit.PseudoStats.DamageTakenMultiplier /= 2

// TODO: Move this to an APL Action
if !isIndividualSim && ai.Target.Env.GetNumTargets() > 1 {
addTarget := ai.Target.Env.NextTargetUnit(&ai.Target.Unit)
if addTarget.CurrentTarget != nil {
Expand Down Expand Up @@ -457,21 +495,25 @@ func (ai *MagmawAI) registerSpells() {
} else {
// Individual sim fake tank swaps
tankUnit := &ai.Target.Env.Raid.Parties[0].Players[0].GetCharacter().Unit
if tankUnit.Metrics.IsTanking() && ai.Target.Env.GetNumTargets() > 1 {
if tankUnit.Metrics.IsTanking() {
if !ai.individualTankSwap {
ai.swelteringArmor.Get(ai.lastMangleTarget).Activate(sim)
}

// Remove boss target
ai.individualTankSwap = true
ai.Target.CurrentTarget = nil

// Set add target
addTarget := ai.Target.Env.NextTargetUnit(&ai.Target.Unit)
tankUnit.CurrentTarget = addTarget
addTarget.CurrentTarget = tankUnit
addTarget.AutoAttacks.EnableAutoSwing(sim)
} else {
ai.individualTankSwap = false
if ai.Target.Env.GetNumTargets() > 1 {
if !ai.individualTankSwap {
// Remove boss target
ai.individualTankSwap = true
ai.Target.CurrentTarget = nil

// Set add target
addTarget := ai.Target.Env.NextTargetUnit(&ai.Target.Unit)
tankUnit.CurrentTarget = addTarget
addTarget.CurrentTarget = tankUnit
addTarget.AutoAttacks.EnableAutoSwing(sim)
} else {
ai.individualTankSwap = false
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package encounters
package default_ai

import (
"time"
Expand Down
13 changes: 10 additions & 3 deletions sim/encounters/movement_ai.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func addMovementAI() {

type MovementAI struct {
Target *core.Target
LastMoveTime time.Duration
NextMoveTime time.Duration
MoveInterval time.Duration // How often moves happen
ReactionTime time.Duration // Time available to react before area should be cleared
MoveYards float64 // Duration of the move
Expand Down Expand Up @@ -97,10 +97,16 @@ func (ai *MovementAI) Initialize(target *core.Target, config *proto.Target) {
}

func (ai *MovementAI) Reset(sim *core.Simulation) {
ai.LastMoveTime = 0
ai.NextMoveTime = 0
}

func (ai *MovementAI) ExecuteCustomRotation(sim *core.Simulation) {
// This can be called from auto attacks and not only gcd
// so we return if thats the case
if sim.CurrentTime < ai.NextMoveTime {
return
}

players := sim.Raid.AllPlayerUnits

for i := 0; i < len(players); i++ {
Expand All @@ -126,7 +132,8 @@ func (ai *MovementAI) ExecuteCustomRotation(sim *core.Simulation) {
}
}

ai.Target.WaitUntil(sim, sim.CurrentTime+ai.MoveInterval)
ai.NextMoveTime = sim.CurrentTime + ai.MoveInterval
ai.Target.WaitUntil(sim, ai.NextMoveTime)
}
func (ai *MovementAI) TimeToMove(distance float64, unit *core.Unit) time.Duration {
return core.DurationFromSeconds(distance / unit.GetMovementSpeed())
Expand Down
8 changes: 8 additions & 0 deletions sim/mage/talents_fire.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ func (mage *Mage) ApplyFireTalents() {
})
}

// Firestarter
if mage.Talents.Firestarter {
mage.AddStaticMod(core.SpellModConfig{
ClassMask: MageSpellScorch,
Kind: core.SpellMod_AllowCastWhileMoving,
})
}

// Improved Flamestrike
if mage.Talents.ImprovedFlamestrike > 0 {
mage.AddStaticMod(core.SpellModConfig{
Expand Down
3 changes: 2 additions & 1 deletion ui/core/components/detailed_results/timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,8 @@ const DEFAULT_ACTION_CATEGORY = 3;

// Hard-coded spell categories for controlling rotation ordering.
const idToCategoryMap: Record<number, number> = {
[OtherAction.OtherActionAttack]: 0,
[OtherAction.OtherActionMove]: 0,
[OtherAction.OtherActionAttack]: 0.01,
[OtherAction.OtherActionShoot]: 0.5,

// Druid
Expand Down
32 changes: 27 additions & 5 deletions ui/core/components/encounter_picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,45 @@ export class EncounterPicker extends Component {
modEncounter.sim.waitForInit().then(() => {
const presetTargets = modEncounter.sim.db.getAllPresetTargets();

// new EnumPicker<Encounter>(this.rootElem, modEncounter, {
// extraCssClasses: ['damage-metrics', 'npc-picker'],
// label: 'NPC',
// labelTooltip: 'Selects a preset NPC configuration.',
// values: [{ name: 'Custom', value: -1 }].concat(
// presetTargets.map((pe, i) => {
// return {
// name: pe.path,
// value: i,
// };
// }),
// ),
// changedEvent: (encounter: Encounter) => encounter.changeEmitter,
// getValue: (encounter: Encounter) => presetTargets.findIndex(pe => equalTargetsIgnoreInputs(encounter.primaryTarget, pe.target)),
// setValue: (eventID: EventID, encounter: Encounter, newValue: number) => {
// if (newValue != -1) {
// encounter.applyPresetTarget(eventID, presetTargets[newValue], 0);
// }
// },
// });

const presetEncounters = modEncounter.sim.db.getAllPresetEncounters();
new EnumPicker<Encounter>(this.rootElem, modEncounter, {
label: 'Encounter',
//extraCssClasses: ['encounter-picker', 'mb-0', 'pe-2', 'order-first'],
extraCssClasses: ['damage-metrics', 'npc-picker'],
label: 'NPC',
labelTooltip: 'Selects a preset NPC configuration.',
values: [{ name: 'Custom', value: -1 }].concat(
presetTargets.map((pe, i) => {
presetEncounters.map((pe, i) => {
return {
name: pe.path,
value: i,
};
}),
),
changedEvent: (encounter: Encounter) => encounter.changeEmitter,
getValue: (encounter: Encounter) => presetTargets.findIndex(pe => equalTargetsIgnoreInputs(encounter.primaryTarget, pe.target)),
getValue: (encounter: Encounter) => presetEncounters.findIndex(pe => encounter.matchesPreset(pe)),
setValue: (eventID: EventID, encounter: Encounter, newValue: number) => {
if (newValue != -1) {
encounter.applyPresetTarget(eventID, presetTargets[newValue], 0);
encounter.applyPreset(eventID, presetEncounters[newValue]);
}
},
});
Expand Down

0 comments on commit aee8dca

Please sign in to comment.