From bea1bca43e38c1aedf536d2b97824d9f24ba0566 Mon Sep 17 00:00:00 2001 From: Aneesh Dogra Date: Thu, 5 Dec 2024 00:57:42 +0100 Subject: [PATCH 1/3] CombatGoal update to check if multiple mobs hit the player and run back to last safe spot. This is work in progress. Its still might save the bot but sometimes the run direction can have obstacles in which case it gets stuck :( works well for open fields. --- Core/Goals/CombatGoal.cs | 98 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 5 deletions(-) diff --git a/Core/Goals/CombatGoal.cs b/Core/Goals/CombatGoal.cs index 5d37fd34..42e60deb 100644 --- a/Core/Goals/CombatGoal.cs +++ b/Core/Goals/CombatGoal.cs @@ -3,32 +3,41 @@ using Microsoft.Extensions.Logging; using System; +using System.Collections; +using System.Collections.Generic; using System.Numerics; +using System.Threading; +using static System.MathF; namespace Core.Goals; public sealed class CombatGoal : GoapGoal, IGoapEventListener { public override float Cost => 4f; + public DateTime LastSafeLocationTime = new DateTime(); + Queue safeLocations = new Queue(); + private readonly ILogger logger; private readonly ConfigurableInput input; private readonly ClassConfiguration classConfig; private readonly Wait wait; + private readonly Navigation playerNavigation; private readonly PlayerReader playerReader; private readonly AddonBits bits; private readonly StopMoving stopMoving; private readonly CastingHandler castingHandler; private readonly IMountHandler mountHandler; private readonly CombatLog combatLog; - + private const float minAngleToTurn = PI / 35f; // 5.14 degree + private const float minAngleToStopBeforeTurn = PI / 2f; // 90 degree private float lastDirection; private float lastMinDistance; private float lastMaxDistance; public CombatGoal(ILogger logger, ConfigurableInput input, Wait wait, PlayerReader playerReader, StopMoving stopMoving, AddonBits bits, - ClassConfiguration classConfiguration, ClassConfiguration classConfig, + Navigation playerNavigation, ClassConfiguration classConfiguration, ClassConfiguration classConfig, CastingHandler castingHandler, CombatLog combatLog, IMountHandler mountHandler) : base(nameof(CombatGoal)) @@ -40,6 +49,7 @@ public CombatGoal(ILogger logger, ConfigurableInput input, this.playerReader = playerReader; this.bits = bits; this.combatLog = combatLog; + this.playerNavigation = playerNavigation; this.stopMoving = stopMoving; this.castingHandler = castingHandler; @@ -48,7 +58,7 @@ public CombatGoal(ILogger logger, ConfigurableInput input, AddPrecondition(GoapKey.incombat, true); AddPrecondition(GoapKey.hastarget, true); - AddPrecondition(GoapKey.targetisalive, true); + //AddPrecondition(GoapKey.targetisalive, true); AddPrecondition(GoapKey.targethostile, true); //AddPrecondition(GoapKey.targettargetsus, true); AddPrecondition(GoapKey.incombatrange, true); @@ -106,7 +116,40 @@ public override void OnExit() public override void Update() { wait.Update(); - + if (combatLog.DamageTaken.Count > 1) + { + // multiple mobs hitting us + // bail + Console.WriteLine("Multiple mob hits!"); + Console.WriteLine(safeLocations.Count); + CancellationToken token = new CancellationToken(); + if (safeLocations.Count > 1) + { + float heading = DirectionCalculator.CalculateMapHeading(playerReader.MapPos, (Vector3)safeLocations.ToArray()[1]); + safeLocations.Dequeue(); + safeLocations.Dequeue(); + input.PressClearTarget(); + Console.WriteLine("Running away!"); + float diff1 = Abs(Tau + heading - playerReader.Direction) % Tau; + float diff2 = Abs(heading - playerReader.Direction - Tau) % Tau; + float diff = Min(diff1, diff2); + if (diff > minAngleToTurn) + { + if (diff > minAngleToStopBeforeTurn) + { + stopMoving.Stop(); + } + + ConsoleKey directionKey = (Tau + heading - playerReader.Direction) % Tau < PI + ? input.TurnLeftKey : input.TurnRightKey; + float result = (Tau + heading - playerReader.Direction) % Tau; + float amount = result > PI ? Tau - result : result; + int duration = (int)(amount * 1000 / PI); + input.PressFixed(directionKey, duration, token); + input.PressFixed(ConsoleKey.W, 11_000, token); + } + } + } if (MathF.Abs(lastDirection - playerReader.Direction) > MathF.PI / 2) { logger.LogInformation("Turning too fast!"); @@ -125,6 +168,29 @@ public override void Update() if (bits.Target()) { + if (bits.Target_Dead()) + { + Console.WriteLine("Target Dead -- saving safe pos"); + if (LastSafeLocationTime == DateTime.MinValue) + { + LastSafeLocationTime = DateTime.UtcNow; + safeLocations.Enqueue(playerReader.MapPos); + } + else + { + if ((DateTime.UtcNow - LastSafeLocationTime).TotalMilliseconds > 5_000 && !bits.Combat()) + { + safeLocations.Enqueue(playerReader.MapPos); + LastSafeLocationTime = DateTime.UtcNow; + if (safeLocations.Count > 5) + { + safeLocations.Dequeue(); + } + } + } + logger.LogWarning("---- Target dead, clearing"); + input.PressClearTarget(); + } if (classConfig.AutoPetAttack && bits.Pet() && (!playerReader.PetTarget() || playerReader.PetTargetGuid != playerReader.TargetGuid) && @@ -161,6 +227,28 @@ public override void Update() { stopMoving.Stop(); FindNewTarget(); + } else + { + Console.WriteLine("Target Dead -- saving safe pos"); + Console.WriteLine(bits.Combat()); + if (LastSafeLocationTime == DateTime.MinValue) + { + LastSafeLocationTime = DateTime.UtcNow; + } + else + { + if ((DateTime.UtcNow - LastSafeLocationTime).TotalMilliseconds > 4_000) + { + safeLocations.Enqueue(playerReader.MapPos); + LastSafeLocationTime = DateTime.UtcNow; + if (safeLocations.Count > 5) + { + safeLocations.Dequeue(); + } + } + } + logger.LogWarning("---- Target dead, clearing"); + input.PressClearTarget(); } } } @@ -216,4 +304,4 @@ private Vector3 GetCorpseLocation(float distance) { return PointEstimator.GetPoint(playerReader.MapPos, playerReader.Direction, distance); } -} \ No newline at end of file +} From 852710d88a9553660a846144946004b25e61025c Mon Sep 17 00:00:00 2001 From: Aneesh Dogra Date: Thu, 5 Dec 2024 03:45:17 +0100 Subject: [PATCH 2/3] Update Combat Flee to use the Navigation GoalComponent --- Core/Goals/CombatGoal.cs | 124 ++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 66 deletions(-) diff --git a/Core/Goals/CombatGoal.cs b/Core/Goals/CombatGoal.cs index 42e60deb..0bf74f77 100644 --- a/Core/Goals/CombatGoal.cs +++ b/Core/Goals/CombatGoal.cs @@ -1,10 +1,11 @@ -using Core.GOAP; +using Core.GOAP; using Microsoft.Extensions.Logging; - +using SharpDX.WIC; using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using System.Numerics; using System.Threading; using static System.MathF; @@ -15,9 +16,9 @@ public sealed class CombatGoal : GoapGoal, IGoapEventListener { public override float Cost => 4f; public DateTime LastSafeLocationTime = new DateTime(); - Queue safeLocations = new Queue(); - + LinkedList safeLocations = new LinkedList(); + private bool runningAway; private readonly ILogger logger; private readonly ConfigurableInput input; private readonly ClassConfiguration classConfig; @@ -44,13 +45,14 @@ public CombatGoal(ILogger logger, ConfigurableInput input, { this.logger = logger; this.input = input; + this.runningAway = false; this.wait = wait; this.playerReader = playerReader; this.bits = bits; this.combatLog = combatLog; this.playerNavigation = playerNavigation; - + playerNavigation.OnWayPointReached += Flee_SafePointReached; this.stopMoving = stopMoving; this.castingHandler = castingHandler; this.mountHandler = mountHandler; @@ -116,6 +118,23 @@ public override void OnExit() public override void Update() { wait.Update(); + if (runningAway) + { + if (!bits.Combat()) + { + runningAway = false; + Console.WriteLine("NO longer in combat. We are safe!"); + safeLocations.AddLast(playerReader.MapPos); + playerNavigation.Stop(); + } + else + { + Console.WriteLine("Still running!"); + input.PressClearTarget(); + playerNavigation.Update(); + return; + } + } if (combatLog.DamageTaken.Count > 1) { // multiple mobs hitting us @@ -123,31 +142,18 @@ public override void Update() Console.WriteLine("Multiple mob hits!"); Console.WriteLine(safeLocations.Count); CancellationToken token = new CancellationToken(); - if (safeLocations.Count > 1) + if (safeLocations.Count >= 1) { - float heading = DirectionCalculator.CalculateMapHeading(playerReader.MapPos, (Vector3)safeLocations.ToArray()[1]); - safeLocations.Dequeue(); - safeLocations.Dequeue(); + runningAway = true; + Console.WriteLine("Current Pos: " + playerReader.MapPos.ToString()); + Console.WriteLine("Last safe: " + safeLocations.Last().ToString()); + playerNavigation.SetWayPoints(stackalloc Vector3[] { (Vector3)(safeLocations.Last()) }); + safeLocations.RemoveLast(); input.PressClearTarget(); - Console.WriteLine("Running away!"); - float diff1 = Abs(Tau + heading - playerReader.Direction) % Tau; - float diff2 = Abs(heading - playerReader.Direction - Tau) % Tau; - float diff = Min(diff1, diff2); - if (diff > minAngleToTurn) - { - if (diff > minAngleToStopBeforeTurn) - { - stopMoving.Stop(); - } - - ConsoleKey directionKey = (Tau + heading - playerReader.Direction) % Tau < PI - ? input.TurnLeftKey : input.TurnRightKey; - float result = (Tau + heading - playerReader.Direction) % Tau; - float amount = result > PI ? Tau - result : result; - int duration = (int)(amount * 1000 / PI); - input.PressFixed(directionKey, duration, token); - input.PressFixed(ConsoleKey.W, 11_000, token); - } + Console.WriteLine("Running away to the last safe point!"); + } else + { + Console.WriteLine("No safe points to run, just fight!"); } } if (MathF.Abs(lastDirection - playerReader.Direction) > MathF.PI / 2) @@ -170,25 +176,6 @@ public override void Update() { if (bits.Target_Dead()) { - Console.WriteLine("Target Dead -- saving safe pos"); - if (LastSafeLocationTime == DateTime.MinValue) - { - LastSafeLocationTime = DateTime.UtcNow; - safeLocations.Enqueue(playerReader.MapPos); - } - else - { - if ((DateTime.UtcNow - LastSafeLocationTime).TotalMilliseconds > 5_000 && !bits.Combat()) - { - safeLocations.Enqueue(playerReader.MapPos); - LastSafeLocationTime = DateTime.UtcNow; - if (safeLocations.Count > 5) - { - safeLocations.Dequeue(); - } - } - } - logger.LogWarning("---- Target dead, clearing"); input.PressClearTarget(); } if (classConfig.AutoPetAttack && @@ -229,30 +216,35 @@ public override void Update() FindNewTarget(); } else { - Console.WriteLine("Target Dead -- saving safe pos"); - Console.WriteLine(bits.Combat()); - if (LastSafeLocationTime == DateTime.MinValue) - { - LastSafeLocationTime = DateTime.UtcNow; - } - else - { - if ((DateTime.UtcNow - LastSafeLocationTime).TotalMilliseconds > 4_000) - { - safeLocations.Enqueue(playerReader.MapPos); - LastSafeLocationTime = DateTime.UtcNow; - if (safeLocations.Count > 5) - { - safeLocations.Dequeue(); - } - } - } + Console.WriteLine("Target Dead2 -- saving safe pos " + playerReader.MapPos.ToString()); + safeLocations.AddLast(playerReader.MapPos); logger.LogWarning("---- Target dead, clearing"); input.PressClearTarget(); } } } + private void Flee_SafePointReached() + { + Console.WriteLine("Safepoint reached, checking if combat cleared?"); + if (!bits.Combat()) { + Console.WriteLine("We are safe!"); + runningAway = false; + } else + { + Console.WriteLine("Still not safe, run to next safepoint!"); + if (safeLocations.Count >= 1) + { + playerNavigation.SetWayPoints(stackalloc Vector3[] { (Vector3)(safeLocations.Last()) }); + input.PressClearTarget(); + } else + { + Console.WriteLine("No more safepoints, Fight back!"); + runningAway = false; + playerNavigation.Stop(); + } + } + } private void FindNewTarget() { if (playerReader.PetTarget() && combatLog.DeadGuid.Value != playerReader.PetTargetGuid) @@ -265,7 +257,7 @@ private void FindNewTarget() if (!bits.Target_Dead()) { - logger.LogWarning("---- New targe from Pet target!"); + logger.LogWarning("---- New target from Pet target!"); return; } From 4c4a16f43425ddd261465e610661ea4932da5fe7 Mon Sep 17 00:00:00 2001 From: Aneesh Dogra Date: Fri, 6 Dec 2024 10:52:11 +0100 Subject: [PATCH 3/3] Update CombatGoal.cs --- Core/Goals/CombatGoal.cs | 140 +++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/Core/Goals/CombatGoal.cs b/Core/Goals/CombatGoal.cs index 0bf74f77..b0aa9d56 100644 --- a/Core/Goals/CombatGoal.cs +++ b/Core/Goals/CombatGoal.cs @@ -1,4 +1,4 @@ -using Core.GOAP; +using Core.GOAP; using Microsoft.Extensions.Logging; using SharpDX.WIC; @@ -8,7 +8,9 @@ using System.Linq; using System.Numerics; using System.Threading; +using System.Drawing; using static System.MathF; +using SixLabors.ImageSharp.Formats; namespace Core.Goals; @@ -45,14 +47,12 @@ public CombatGoal(ILogger logger, ConfigurableInput input, { this.logger = logger; this.input = input; - this.runningAway = false; this.wait = wait; this.playerReader = playerReader; this.bits = bits; this.combatLog = combatLog; this.playerNavigation = playerNavigation; - playerNavigation.OnWayPointReached += Flee_SafePointReached; this.stopMoving = stopMoving; this.castingHandler = castingHandler; this.mountHandler = mountHandler; @@ -118,49 +118,7 @@ public override void OnExit() public override void Update() { wait.Update(); - if (runningAway) - { - if (!bits.Combat()) - { - runningAway = false; - Console.WriteLine("NO longer in combat. We are safe!"); - safeLocations.AddLast(playerReader.MapPos); - playerNavigation.Stop(); - } - else - { - Console.WriteLine("Still running!"); - input.PressClearTarget(); - playerNavigation.Update(); - return; - } - } - if (combatLog.DamageTaken.Count > 1) - { - // multiple mobs hitting us - // bail - Console.WriteLine("Multiple mob hits!"); - Console.WriteLine(safeLocations.Count); - CancellationToken token = new CancellationToken(); - if (safeLocations.Count >= 1) - { - runningAway = true; - Console.WriteLine("Current Pos: " + playerReader.MapPos.ToString()); - Console.WriteLine("Last safe: " + safeLocations.Last().ToString()); - playerNavigation.SetWayPoints(stackalloc Vector3[] { (Vector3)(safeLocations.Last()) }); - safeLocations.RemoveLast(); - input.PressClearTarget(); - Console.WriteLine("Running away to the last safe point!"); - } else - { - Console.WriteLine("No safe points to run, just fight!"); - } - } - if (MathF.Abs(lastDirection - playerReader.Direction) > MathF.PI / 2) - { - logger.LogInformation("Turning too fast!"); - stopMoving.Stop(); - } + playerNavigation.Update(); lastDirection = playerReader.Direction; lastMinDistance = playerReader.MinRange(); @@ -172,12 +130,57 @@ public override void Update() return; } - if (bits.Target()) + if ((MathF.Abs(lastDirection - playerReader.Direction) > MathF.PI / 2)) + { + logger.LogInformation("Turning too fast!"); + stopMoving.Stop(); + + } + if (bits.Target() && !bits.Target_Alive()) { - if (bits.Target_Dead()) + input.PressClearTarget(); + return; + } + + if (combatLog.DamageTaken.Count > 1 || (playerReader.HealthPercent() < 50 && playerReader.ManaPercent() < 20) || (playerReader.HealthPercent() < 30)) + { + // multiple mobs hitting us + // bail + Console.WriteLine("Multiple mob hits! OR HP and mana low"); + Console.WriteLine(safeLocations.Count); + if (safeLocations.Count >= 1) { - input.PressClearTarget(); + bool foundPoint = false; + Console.WriteLine("Current Pos: " + playerReader.MapPos.ToString()); + Console.WriteLine("Safe Spots: " + safeLocations.Count); + for (LinkedListNode point = safeLocations.Last; point != null; point = point.Previous) + { + Vector2 p1 = new Vector2(point.Value.X, point.Value.Y); + Vector2 p2 = new Vector2(playerReader.MapPos.X, playerReader.MapPos.Y); + if (Vector2.Distance(p1, p2) >= 1.8) + { + // select the point far enough to lose the current mobs. + input.PressClearTarget(); + playerNavigation.Stop(); + playerNavigation.StuckResetTimeout = 500; + playerNavigation.ResetStuckParameters(); + playerNavigation.SetWayPoints(stackalloc Vector3[] { (Vector3)(point.Value) }); + playerNavigation.Update(); + Console.WriteLine("Found point " + point.Value.ToString()); + foundPoint = true; + break; + } + } + if (foundPoint) + { + Console.WriteLine("Running away to the last safe point!"); + return; + } } + } + + if (bits.Target()) + { if (classConfig.AutoPetAttack && bits.Pet() && (!playerReader.PetTarget() || playerReader.PetTargetGuid != playerReader.TargetGuid) && @@ -216,6 +219,23 @@ public override void Update() FindNewTarget(); } else { + if (LastSafeLocationTime == DateTime.MinValue) + { + LastSafeLocationTime = DateTime.UtcNow; + safeLocations.AddLast(playerReader.MapPos); + } + else + { + if ((DateTime.UtcNow - LastSafeLocationTime).TotalMilliseconds > 7_000 && !bits.Combat()) + { + safeLocations.AddLast(playerReader.MapPos); + LastSafeLocationTime = DateTime.UtcNow; + if (safeLocations.Count > 100) + { + safeLocations.RemoveFirst(); + } + } + } Console.WriteLine("Target Dead2 -- saving safe pos " + playerReader.MapPos.ToString()); safeLocations.AddLast(playerReader.MapPos); logger.LogWarning("---- Target dead, clearing"); @@ -224,29 +244,9 @@ public override void Update() } } - private void Flee_SafePointReached() - { - Console.WriteLine("Safepoint reached, checking if combat cleared?"); - if (!bits.Combat()) { - Console.WriteLine("We are safe!"); - runningAway = false; - } else - { - Console.WriteLine("Still not safe, run to next safepoint!"); - if (safeLocations.Count >= 1) - { - playerNavigation.SetWayPoints(stackalloc Vector3[] { (Vector3)(safeLocations.Last()) }); - input.PressClearTarget(); - } else - { - Console.WriteLine("No more safepoints, Fight back!"); - runningAway = false; - playerNavigation.Stop(); - } - } - } private void FindNewTarget() { + playerNavigation.Stop(); if (playerReader.PetTarget() && combatLog.DeadGuid.Value != playerReader.PetTargetGuid) { ResetCooldowns();