diff --git a/Core/ClassConfig/ClassConfiguration.cs b/Core/ClassConfig/ClassConfiguration.cs index 77641ce3..ac4da3a1 100644 --- a/Core/ClassConfig/ClassConfiguration.cs +++ b/Core/ClassConfig/ClassConfiguration.cs @@ -238,9 +238,8 @@ private static void SetBaseActions( user.Key = baseAction.Key; - //if (!string.IsNullOrEmpty(@default.Requirement)) - // user.Requirement += " " + @default.Requirement; - //user.Requirements.AddRange(@default.Requirements); + if (!string.IsNullOrEmpty(baseAction.Requirement)) + user.Requirement += " " + baseAction.Requirement; if (user.BeforeCastDelay == @default.BeforeCastDelay) user.BeforeCastDelay = baseAction.BeforeCastDelay; diff --git a/Core/ClassConfig/ClassConfigurationBaseActions.cs b/Core/ClassConfig/ClassConfigurationBaseActions.cs index 597d4b2d..0ea8b055 100644 --- a/Core/ClassConfig/ClassConfigurationBaseActions.cs +++ b/Core/ClassConfig/ClassConfigurationBaseActions.cs @@ -34,14 +34,16 @@ public sealed partial class ClassConfiguration Key = "I", // Interact.Key Name = nameof(Approach), PressDuration = 10, - BaseAction = true + BaseAction = true, + Requirement = "!SoftTargetDead" }; public KeyAction AutoAttack { get; } = new() { Key = "I", // Interact.Key Name = nameof(AutoAttack), - BaseAction = true + BaseAction = true, + Requirement = "!AutoAttacking && !SoftTargetDead" }; public KeyAction TargetLastTarget { get; } = new() diff --git a/Core/Goals/ConsumeCorpseGoal.cs b/Core/Goals/ConsumeCorpseGoal.cs index 3fabbd01..d80df9b6 100644 --- a/Core/Goals/ConsumeCorpseGoal.cs +++ b/Core/Goals/ConsumeCorpseGoal.cs @@ -23,9 +23,8 @@ public ConsumeCorpseGoal(ILogger logger, { AddPrecondition(GoapKey.consumablecorpsenearby, true); } - AddPrecondition(GoapKey.pulled, false); - AddPrecondition(GoapKey.dangercombat, false); - AddPrecondition(GoapKey.incombat, false); + AddPrecondition(GoapKey.damagedone, false); + AddPrecondition(GoapKey.damagetaken, false); AddPrecondition(GoapKey.producedcorpse, true); AddPrecondition(GoapKey.consumecorpse, false); diff --git a/Core/Goals/LootGoal.cs b/Core/Goals/LootGoal.cs index 7bbab438..56a6335d 100644 --- a/Core/Goals/LootGoal.cs +++ b/Core/Goals/LootGoal.cs @@ -70,7 +70,6 @@ public LootGoal(ILogger logger, this.token = cts.Token; AddPrecondition(GoapKey.pulled, false); - AddPrecondition(GoapKey.incombat, false); AddPrecondition(GoapKey.dangercombat, false); AddPrecondition(GoapKey.shouldloot, true); AddEffect(GoapKey.shouldloot, false); @@ -78,7 +77,12 @@ public LootGoal(ILogger logger, public override void OnEnter() { - WaitForLootReset(); + float elapsedMs = WaitForLootReset(); + if (elapsedMs < 0) + { + LogLootStatusDidNotChangedInTime(logger, elapsedMs); + return; + } if (combatLog.DamageTakenCount() == 0) { @@ -103,9 +107,9 @@ public override void OnEnter() ClearTargetIfNeeded(); } - private void WaitForLootReset() + private float WaitForLootReset() { - wait.WhileWithTimeout(LootReset, MAX_TIME_TO_RESET_LOOT); + return wait.Until(MAX_TIME_TO_RESET_LOOT, LootStatusIsCorpse); } private void WaitForLosingTarget() @@ -151,10 +155,8 @@ private bool TryLoot() return true; } } - if (!input.KeyboardOnly) { - return LootMouse(); - } - return false; + + return !input.KeyboardOnly && LootMouse(); } private void HandleSuccessfulLoot() @@ -400,8 +402,8 @@ private bool MoveToTargetAndReached() return bits.Target() && playerReader.MinRangeZero(); } - private bool LootReset() => - (LootStatus)playerReader.LootEvent.Value != LootStatus.CORPSE; + private bool LootStatusIsCorpse() => + (LootStatus)playerReader.LootEvent.Value == LootStatus.CORPSE; #region Logging @@ -457,5 +459,11 @@ private void LogWarning(string text) Message = "Keyboard loot failed! Has target ? {hasTarget}")] static partial void LogKeyboardLootFailed(ILogger logger, bool hasTarget); + [LoggerMessage( + EventId = 0137, + Level = LogLevel.Error, + Message = "LootGoal failed to start due LootStatus did not changed within the expected time window {elapsedMs}ms")] + static partial void LogLootStatusDidNotChangedInTime(ILogger logger, float elapsedMs); + #endregion } diff --git a/Core/GoalsComponent/Wait.cs b/Core/GoalsComponent/Wait.cs index 0b7667ad..3956b722 100644 --- a/Core/GoalsComponent/Wait.cs +++ b/Core/GoalsComponent/Wait.cs @@ -131,13 +131,4 @@ public void While(Func condition) Update(); } } - - public void WhileWithTimeout(Func condition, int timeoutMs) { - DateTime start = DateTime.UtcNow; - float elapsedMs; - while ((elapsedMs = (float)(DateTime.UtcNow - start).TotalMilliseconds) < timeoutMs && condition()) - { - Update(); - } - } } diff --git a/Core/Requirement/RequirementFactory.cs b/Core/Requirement/RequirementFactory.cs index f9619d4e..9b2eb973 100644 --- a/Core/Requirement/RequirementFactory.cs +++ b/Core/Requirement/RequirementFactory.cs @@ -143,6 +143,10 @@ public RequirementFactory(IServiceProvider sp, ClassConfiguration classConfig) { "TargetsPet", playerReader.TargetsPet }, { "TargetsNone", playerReader.TargetsNone }, + // Soft Target + { "SoftTarget", bits.SoftInteract }, + { "SoftTargetDead", bits.SoftInteract_Dead }, + { AddVisible, npcNameFinder._PotentialAddsExist }, { "InCombat", bits.Combat }, diff --git a/README.md b/README.md index 24997abd..9398b109 100644 --- a/README.md +++ b/README.md @@ -1642,6 +1642,8 @@ Allow requirements about what buffs/debuffs you have or the target has or in gen | `"TargetsMe"` | The target currently targets the player | | `"TargetsPet"` | The target currently targets the player's pet | | `"TargetsNone"` | The target currently has not target | +| `"SoftTarget"` | The player has an available soft target | +| `"SoftTargetDead"` | The player has an available soft target which is dead | | `"AddVisible"` | Around the target there are possible additional NPCs | | `"InCombat"` | Player in combat. | | `"TargetCastingSpell"` | Target casts any spell |