From 72edef4895d9fa94691d77bf53feb9aa350e2d6a Mon Sep 17 00:00:00 2001 From: ToxicKevinFerm Date: Sun, 12 May 2024 19:40:28 +0200 Subject: [PATCH 1/4] Adds basic movement encounter --- assets/database/db.bin | Bin 4531771 -> 4532168 bytes assets/database/db.json | 4 +- sim/encounters/default_ai.go | 1 + sim/encounters/light_movement.go | 89 +++++++++++++++++++++++++++++++ sim/encounters/register_all.go | 2 + 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 sim/encounters/light_movement.go diff --git a/assets/database/db.bin b/assets/database/db.bin index 5b139926273bf47b512c0b19b46b0b43c4aaec42..0766e1fbd5c95645a3526cf939b62a5ae5864a38 100644 GIT binary patch delta 247 zcmZX~zb*rD0KoCwuRXmUN{>?2a#T-U%TZcI{p;Px>J1uhpoXSHC&SlhkTkg`kchz~ zZtwz?G?Cbvcn3olqsD6de)4_mwngWoEpCty1PCHCLvCaksHrb*`iEYa4u*)75_Br5?BaW%Q z*blCpS8g8zUOi(QiY}Q2<#SNiKUK@`xwh9ezl0h&tv73zwX248;+|hLwDkpy=i{6KHej>*zad}(EV>#hS5%IFd0r8?eX6X DpT9g_ diff --git a/assets/database/db.json b/assets/database/db.json index 9204cdbb50..ba276e7b5e 100644 --- a/assets/database/db.json +++ b/assets/database/db.json @@ -9143,6 +9143,7 @@ {"id":54044,"name":"Carrion Feeder","icon":"ability_racial_cannibalize"}, {"id":54118,"name":"Improved Soul Leech","icon":"ability_warlock_improvedsoulleech"}, {"id":54151,"name":"Judgements of the Pure","icon":"ability_paladin_judgementofthepure"}, +{"id":54277,"name":"Backdraft","icon":"ability_warlock_backdraft","hasBuff":true}, {"id":54354,"name":"Prismatic Cloak","icon":"spell_arcane_prismaticcloak"}, {"id":54446,"name":"Rune of Swordbreaking","icon":"ability_parry"}, {"id":54447,"name":"Rune of Spellbreaking","icon":"spell_shadow_antimagicshell"}, @@ -10127,6 +10128,7 @@ ], "encounters":[ {"path":"Default/Raid Target","targets":[{"path":"Default/Raid Target","target":{"id":31146,"name":"Raid Target","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}}]}, +{"path":"Movement/Light","targets":[{"path":"Movement/Light","target":{"id":31147,"name":"Light","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}}]}, {"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}]}}]}, @@ -10480,4 +10482,4 @@ {"itemId":43380,"spellId":58038}, {"itemId":43379,"spellId":58039} ] -} \ No newline at end of file +} diff --git a/sim/encounters/default_ai.go b/sim/encounters/default_ai.go index 255f718053..72c3c33b47 100644 --- a/sim/encounters/default_ai.go +++ b/sim/encounters/default_ai.go @@ -66,4 +66,5 @@ func (ai *DefaultAI) ExecuteCustomRotation(sim *core.Simulation) { ability.Spell.Cast(sim, ai.Target.CurrentTarget) } } + } diff --git a/sim/encounters/light_movement.go b/sim/encounters/light_movement.go new file mode 100644 index 0000000000..eb98f0ed4a --- /dev/null +++ b/sim/encounters/light_movement.go @@ -0,0 +1,89 @@ +package encounters + +import ( + "time" + + "github.com/wowsims/cata/sim/core" + "github.com/wowsims/cata/sim/core/proto" + "github.com/wowsims/cata/sim/core/stats" +) + +func addLightMovementAI() { + core.AddPresetTarget(&core.PresetTarget{ + PathPrefix: "Movement", + Config: &proto.Target{ + Id: 31147, + Name: "Light", + Level: 88, + MobType: proto.MobType_MobTypeMechanical, + TankIndex: 0, + + Stats: stats.Stats{ + stats.Health: 120_016_403, + stats.Armor: 11977, + stats.AttackPower: 650, + }.ToFloatArray(), + + SpellSchool: proto.SpellSchool_SpellSchoolPhysical, + SwingSpeed: 2.5, + MinBaseDamage: 210000, + DamageSpread: 0.4, + SuppressDodge: false, + ParryHaste: false, + DualWield: false, + DualWieldPenalty: false, + TargetInputs: []*proto.TargetInput{}, + }, + AI: NewLightMovementAI(), + }) + core.AddPresetEncounter("Light", []string{ + "Movement/Light", + }) +} + +type LightMovementAI struct { + Target *core.Target + LastMoveTime time.Duration +} + +func NewLightMovementAI() core.AIFactory { + return func() core.TargetAI { + return &LightMovementAI{} + } +} + +func (ai *LightMovementAI) Initialize(target *core.Target, config *proto.Target) { + ai.Target = target +} + +func (ai *LightMovementAI) Reset(sim *core.Simulation) { + ai.LastMoveTime = 0 +} + +func (ai *LightMovementAI) ExecuteCustomRotation(sim *core.Simulation) { + players := sim.Raid.AllPlayerUnits + + if !ai.ShouldMove(sim) { + return + } + + for i := 0; i < len(players); i++ { + player := players[i] + moveOut := player.DistanceFromTarget + 10 + moveIn := player.DistanceFromTarget - 10 + + if moveOut <= 40 && moveIn >= 5 { + player.MoveTo(moveOut, sim) + } else if moveIn >= 5 { + player.MoveTo(moveIn, sim) + } + } +} + +func (ai *LightMovementAI) ShouldMove(sim *core.Simulation) bool { + if sim.CurrentTime-ai.LastMoveTime >= 10*time.Second { + ai.LastMoveTime = sim.CurrentTime + return true + } + return false +} diff --git a/sim/encounters/register_all.go b/sim/encounters/register_all.go index 64656a43f4..9add0e4d67 100644 --- a/sim/encounters/register_all.go +++ b/sim/encounters/register_all.go @@ -9,7 +9,9 @@ import ( func init() { AddDefaultPresetEncounter() + addLightMovementAI() bwd.Register() + } func AddSingleTargetBossEncounter(presetTarget *core.PresetTarget) { From 12c22d5c5abc6b4e554407105a52805012ebf3ab Mon Sep 17 00:00:00 2001 From: ToxicKevinFerm Date: Sun, 12 May 2024 19:55:18 +0200 Subject: [PATCH 2/4] Move a static duration instead --- sim/encounters/light_movement.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sim/encounters/light_movement.go b/sim/encounters/light_movement.go index eb98f0ed4a..2d58074700 100644 --- a/sim/encounters/light_movement.go +++ b/sim/encounters/light_movement.go @@ -69,14 +69,8 @@ func (ai *LightMovementAI) ExecuteCustomRotation(sim *core.Simulation) { for i := 0; i < len(players); i++ { player := players[i] - moveOut := player.DistanceFromTarget + 10 - moveIn := player.DistanceFromTarget - 10 - if moveOut <= 40 && moveIn >= 5 { - player.MoveTo(moveOut, sim) - } else if moveIn >= 5 { - player.MoveTo(moveIn, sim) - } + player.MoveDuration(time.Second*2, sim) } } From aaf6ce9d791f0f51c314e0d65de9e96fa72d2ce2 Mon Sep 17 00:00:00 2001 From: ToxicKevinFerm Date: Sun, 12 May 2024 20:43:31 +0200 Subject: [PATCH 3/4] Make Movement AI instead --- assets/database/db.bin | Bin 4532168 -> 4532409 bytes assets/database/db.json | 4 +- sim/encounters/light_movement.go | 83 ------------------ sim/encounters/movement_ai.go | 141 +++++++++++++++++++++++++++++++ sim/encounters/register_all.go | 2 +- 5 files changed, 144 insertions(+), 86 deletions(-) delete mode 100644 sim/encounters/light_movement.go create mode 100644 sim/encounters/movement_ai.go diff --git a/assets/database/db.bin b/assets/database/db.bin index 0766e1fbd5c95645a3526cf939b62a5ae5864a38..fe8c6e6558877b11640e890acf7367af25f76c02 100644 GIT binary patch delta 465 zcmZvWKTlI(6oalcJS2 zZqQB#H@QV8U8L!zhhA>e#~u0^;4b&L&jSV#G7RyMVIJ|A5k?s!%QzEEGQ~7cnBgfo zo{^`(EOX5BoCRL6$P&vGS>YwGez;!?6TgyeovyB^P2Wzx3AS`q8=F43to)YTS9y2H z+1~r>d`z9)?l`5ClkPejrDUwGZ7Dx<<$s2Y*|FC_U4n|$M(nzl4PP~MP3oTSOEnUT zXC&0+z^sNlj*eIzZ?!60FEH}XtLjtE$#S+7bNs+;ubtKZf H`~A;9yRw^? delta 211 zcmZX~NiIVH007YR)1sxc=DEgSV@)lssrXCoVAEiMO=E5Gj?l!;5v)Yx2CPJ4=?<Qv^~lKT)u-QpK|_X(7&T_xgh@G5rp=f& zXI?08!J;M0R;(&mvu?wtEkz~Uc9d1@+OzM#p{gUtPM)L3QurMt(`UDLwd>kVy>NPU eaaqs4|EHJcc`*uOiTK}m_^L$tW~v-L{rm!6D@bwx diff --git a/assets/database/db.json b/assets/database/db.json index ba276e7b5e..32dd634c33 100644 --- a/assets/database/db.json +++ b/assets/database/db.json @@ -10128,7 +10128,7 @@ ], "encounters":[ {"path":"Default/Raid Target","targets":[{"path":"Default/Raid Target","target":{"id":31146,"name":"Raid Target","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}}]}, -{"path":"Movement/Light","targets":[{"path":"Movement/Light","target":{"id":31147,"name":"Light","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}}]}, +{"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}]}}]}, @@ -10482,4 +10482,4 @@ {"itemId":43380,"spellId":58038}, {"itemId":43379,"spellId":58039} ] -} +} \ No newline at end of file diff --git a/sim/encounters/light_movement.go b/sim/encounters/light_movement.go deleted file mode 100644 index 2d58074700..0000000000 --- a/sim/encounters/light_movement.go +++ /dev/null @@ -1,83 +0,0 @@ -package encounters - -import ( - "time" - - "github.com/wowsims/cata/sim/core" - "github.com/wowsims/cata/sim/core/proto" - "github.com/wowsims/cata/sim/core/stats" -) - -func addLightMovementAI() { - core.AddPresetTarget(&core.PresetTarget{ - PathPrefix: "Movement", - Config: &proto.Target{ - Id: 31147, - Name: "Light", - Level: 88, - MobType: proto.MobType_MobTypeMechanical, - TankIndex: 0, - - Stats: stats.Stats{ - stats.Health: 120_016_403, - stats.Armor: 11977, - stats.AttackPower: 650, - }.ToFloatArray(), - - SpellSchool: proto.SpellSchool_SpellSchoolPhysical, - SwingSpeed: 2.5, - MinBaseDamage: 210000, - DamageSpread: 0.4, - SuppressDodge: false, - ParryHaste: false, - DualWield: false, - DualWieldPenalty: false, - TargetInputs: []*proto.TargetInput{}, - }, - AI: NewLightMovementAI(), - }) - core.AddPresetEncounter("Light", []string{ - "Movement/Light", - }) -} - -type LightMovementAI struct { - Target *core.Target - LastMoveTime time.Duration -} - -func NewLightMovementAI() core.AIFactory { - return func() core.TargetAI { - return &LightMovementAI{} - } -} - -func (ai *LightMovementAI) Initialize(target *core.Target, config *proto.Target) { - ai.Target = target -} - -func (ai *LightMovementAI) Reset(sim *core.Simulation) { - ai.LastMoveTime = 0 -} - -func (ai *LightMovementAI) ExecuteCustomRotation(sim *core.Simulation) { - players := sim.Raid.AllPlayerUnits - - if !ai.ShouldMove(sim) { - return - } - - for i := 0; i < len(players); i++ { - player := players[i] - - player.MoveDuration(time.Second*2, sim) - } -} - -func (ai *LightMovementAI) ShouldMove(sim *core.Simulation) bool { - if sim.CurrentTime-ai.LastMoveTime >= 10*time.Second { - ai.LastMoveTime = sim.CurrentTime - return true - } - return false -} diff --git a/sim/encounters/movement_ai.go b/sim/encounters/movement_ai.go new file mode 100644 index 0000000000..fbbe8d5d34 --- /dev/null +++ b/sim/encounters/movement_ai.go @@ -0,0 +1,141 @@ +package encounters + +import ( + "time" + + "github.com/wowsims/cata/sim/core" + "github.com/wowsims/cata/sim/core/proto" + "github.com/wowsims/cata/sim/core/stats" +) + +func addMovementAI() { + core.AddPresetTarget(&core.PresetTarget{ + PathPrefix: "Default", + Config: &proto.Target{ + Id: 31147, + Name: "Movement", + Level: 88, + MobType: proto.MobType_MobTypeMechanical, + TankIndex: 0, + + Stats: stats.Stats{ + stats.Health: 120_016_403, + stats.Armor: 11977, + stats.AttackPower: 650, + }.ToFloatArray(), + + SpellSchool: proto.SpellSchool_SpellSchoolPhysical, + SwingSpeed: 2.5, + MinBaseDamage: 210000, + DamageSpread: 0.4, + SuppressDodge: false, + ParryHaste: false, + DualWield: false, + DualWieldPenalty: false, + TargetInputs: []*proto.TargetInput{ + { + Label: "Movement Interval", + Tooltip: "How often the player will move in seconds", + InputType: proto.InputType_Number, + NumberValue: 10.0, + }, + { + Label: "Reaction Time", + Tooltip: "How long the player can wait for casts to finish before moving in seconds", + InputType: proto.InputType_Number, + NumberValue: 1.5, + }, + { + Label: "Yards", + Tooltip: "How many yards the player moves", + InputType: proto.InputType_Number, + NumberValue: 5, + }, + }, + }, + AI: NewMovementAI(), + }) + core.AddPresetEncounter("Movement", []string{ + "Default/Movement", + }) +} + +type MovementAI struct { + Target *core.Target + LastMoveTime 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 +} + +func NewMovementAI() core.AIFactory { + return func() core.TargetAI { + return &MovementAI{} + } +} + +func (ai *MovementAI) Initialize(target *core.Target, config *proto.Target) { + ai.Target = target + + if len(config.TargetInputs) > 0 { + ai.MoveInterval = core.DurationFromSeconds(config.TargetInputs[0].NumberValue) + } else { + ai.MoveInterval = core.DurationFromSeconds(10) + } + + if len(config.TargetInputs) > 1 { + ai.ReactionTime = core.DurationFromSeconds(config.TargetInputs[1].NumberValue) + } else { + ai.ReactionTime = core.DurationFromSeconds(1.5) + } + + if len(config.TargetInputs) > 2 { + ai.MoveYards = config.TargetInputs[2].NumberValue + } else { + ai.MoveYards = 5.0 + } +} + +func (ai *MovementAI) Reset(sim *core.Simulation) { + ai.LastMoveTime = 0 +} + +func (ai *MovementAI) ExecuteCustomRotation(sim *core.Simulation) { + players := sim.Raid.AllPlayerUnits + + if !ai.ShouldMove(sim) { + return + } + for i := 0; i < len(players); i++ { + player := players[i] + duration := ai.TimeToMove(ai.MoveYards, player) + if player.Hardcast.Expires > sim.CurrentTime && !player.Hardcast.CanMove { + castEndsAt := player.Hardcast.Expires - sim.CurrentTime + // if castEndsAt < ai.ReactionTime { + core.StartDelayedAction(sim, core.DelayedActionOptions{ + DoAt: sim.CurrentTime + castEndsAt, + Priority: core.ActionPriorityPrePull + 1, + OnAction: func(s *core.Simulation) { + player.MoveDuration(duration, sim) + }, + }) + // } else { + // // Cancel casted spell and move immediately + // // For now we do nothing in this scenario + // return + // } + } else { + player.MoveDuration(duration, sim) + } + } +} +func (ai *MovementAI) TimeToMove(distance float64, unit *core.Unit) time.Duration { + return core.DurationFromSeconds(distance / unit.GetMovementSpeed()) +} +func (ai *MovementAI) ShouldMove(sim *core.Simulation) bool { + if sim.CurrentTime-ai.LastMoveTime >= ai.MoveInterval { + ai.LastMoveTime = sim.CurrentTime + return true + } + return false +} diff --git a/sim/encounters/register_all.go b/sim/encounters/register_all.go index 9add0e4d67..de336bc9c3 100644 --- a/sim/encounters/register_all.go +++ b/sim/encounters/register_all.go @@ -9,7 +9,7 @@ import ( func init() { AddDefaultPresetEncounter() - addLightMovementAI() + addMovementAI() bwd.Register() } From 311af3a1cd4a5dd4fac74a4eb96bc06dda069e42 Mon Sep 17 00:00:00 2001 From: ToxicKevinFerm Date: Sun, 12 May 2024 20:45:43 +0200 Subject: [PATCH 4/4] Add WaitUntil --- sim/encounters/movement_ai.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/sim/encounters/movement_ai.go b/sim/encounters/movement_ai.go index fbbe8d5d34..f973af7863 100644 --- a/sim/encounters/movement_ai.go +++ b/sim/encounters/movement_ai.go @@ -103,9 +103,6 @@ func (ai *MovementAI) Reset(sim *core.Simulation) { func (ai *MovementAI) ExecuteCustomRotation(sim *core.Simulation) { players := sim.Raid.AllPlayerUnits - if !ai.ShouldMove(sim) { - return - } for i := 0; i < len(players); i++ { player := players[i] duration := ai.TimeToMove(ai.MoveYards, player) @@ -128,14 +125,9 @@ func (ai *MovementAI) ExecuteCustomRotation(sim *core.Simulation) { player.MoveDuration(duration, sim) } } + + ai.Target.WaitUntil(sim, sim.CurrentTime+ai.MoveInterval) } func (ai *MovementAI) TimeToMove(distance float64, unit *core.Unit) time.Duration { return core.DurationFromSeconds(distance / unit.GetMovementSpeed()) } -func (ai *MovementAI) ShouldMove(sim *core.Simulation) bool { - if sim.CurrentTime-ai.LastMoveTime >= ai.MoveInterval { - ai.LastMoveTime = sim.CurrentTime - return true - } - return false -}