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/CombatGoal.cs b/Core/Goals/CombatGoal.cs index 073f0f26..4e05dbb7 100644 --- a/Core/Goals/CombatGoal.cs +++ b/Core/Goals/CombatGoal.cs @@ -203,6 +203,7 @@ private void FindNewTarget() ResetCooldowns(); logger.LogWarning("Found new target!"); + wait.Update(); return; } 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 a41d4e70..56a6335d 100644 --- a/Core/Goals/LootGoal.cs +++ b/Core/Goals/LootGoal.cs @@ -18,6 +18,7 @@ public sealed partial class LootGoal : GoapGoal, IGoapEventListener private const int MAX_TIME_TO_REACH_MELEE = 10000; private const int MAX_TIME_TO_DETECT_LOOT = 2 * CastingHandler.GCD; + private const int MAX_TIME_TO_RESET_LOOT = 800; private readonly ILogger logger; private readonly ConfigurableInput input; @@ -68,6 +69,7 @@ public LootGoal(ILogger logger, this.state = state; this.token = cts.Token; + AddPrecondition(GoapKey.pulled, false); AddPrecondition(GoapKey.dangercombat, false); AddPrecondition(GoapKey.shouldloot, true); AddEffect(GoapKey.shouldloot, false); @@ -75,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) { @@ -100,9 +107,9 @@ public override void OnEnter() ClearTargetIfNeeded(); } - private void WaitForLootReset() + private float WaitForLootReset() { - wait.While(LootReset); + return wait.Until(MAX_TIME_TO_RESET_LOOT, LootStatusIsCorpse); } private void WaitForLosingTarget() @@ -121,6 +128,7 @@ private void CaptureStateBeforeLoot() private void CheckInventoryFull() { + ClearTargetIfNeeded(); if (!bagReader.BagsFull()) return; @@ -147,10 +155,8 @@ private bool TryLoot() return true; } } - if (!input.KeyboardOnly) { - return LootMouse(); - } - return false; + + return !input.KeyboardOnly && LootMouse(); } private void HandleSuccessfulLoot() @@ -396,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 @@ -453,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/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 |