diff --git a/RotationSolver.Basic/Configuration/Conditions/TargetCondition.cs b/RotationSolver.Basic/Configuration/Conditions/TargetCondition.cs index e0121853d..0e3044fac 100644 --- a/RotationSolver.Basic/Configuration/Conditions/TargetCondition.cs +++ b/RotationSolver.Basic/Configuration/Conditions/TargetCondition.cs @@ -101,6 +101,10 @@ protected override bool IsTrueInside(ICustomRotation rotation) result = tar.CurrentHp > GCD; break; + case TargetConditionType.HPRatio: + result = tar.GetHealthRatio() > DistanceOrTime; + break; + case TargetConditionType.MP: result = tar.CurrentMp > GCD; break; @@ -132,6 +136,7 @@ internal enum TargetConditionType : byte CastingActionTimeUntil, TimeToKill, HP, + HPRatio, MP, TargetName, } \ No newline at end of file diff --git a/RotationSolver.Basic/Configuration/Conditions/TerritoryCondition.cs b/RotationSolver.Basic/Configuration/Conditions/TerritoryCondition.cs index 3d36d15f7..d9085e251 100644 --- a/RotationSolver.Basic/Configuration/Conditions/TerritoryCondition.cs +++ b/RotationSolver.Basic/Configuration/Conditions/TerritoryCondition.cs @@ -4,19 +4,45 @@ internal class TerritoryCondition : DelayCondition { public TerritoryConditionType TerritoryConditionType = TerritoryConditionType.TerritoryContentType; - public int Param1 = 0; + public int Position = 0; + public int Param1 = 0, Param2 = 0; public string Name = "Not Chosen"; public int Condition; + public float TimeStart, TimeEnd; protected override bool IsTrueInside(ICustomRotation rotation) { - bool result = TerritoryConditionType switch + bool result = false; + switch (TerritoryConditionType) { - TerritoryConditionType.TerritoryContentType => (int)DataCenter.TerritoryContentType == Param1, - TerritoryConditionType.DutyName => Name == DataCenter.ContentFinderName, - TerritoryConditionType.TerritoryName => Name == DataCenter.TerritoryName, - _ => false, - }; + case TerritoryConditionType.TerritoryContentType: + result = (int)DataCenter.TerritoryContentType == Param1; + break; + + case TerritoryConditionType.DutyName: + result = Name == DataCenter.ContentFinderName; + break; + + case TerritoryConditionType.TerritoryName: + result= Name == DataCenter.TerritoryName; + break; + + case TerritoryConditionType.MapEffect: + foreach (var effect in DataCenter.MapEffects.Reverse()) + { + var time = effect.TimeDuration.TotalSeconds; + if ( time > TimeStart && time < TimeEnd + && effect.Position == Position + && effect.Param1 == Param1 + && effect.Param2 == Param2) + { + result = true; + break; + } + } + + break; + } return Condition > 0 ? !result : result; } } @@ -26,4 +52,5 @@ internal enum TerritoryConditionType : byte TerritoryContentType, TerritoryName, DutyName, + MapEffect, } diff --git a/RotationSolver.Basic/Data/MapEffectData.cs b/RotationSolver.Basic/Data/MapEffectData.cs new file mode 100644 index 000000000..963a6ca51 --- /dev/null +++ b/RotationSolver.Basic/Data/MapEffectData.cs @@ -0,0 +1,20 @@ +namespace RotationSolver.Basic.Data; + +public readonly struct MapEffectData +{ + public readonly uint Position; + + public readonly ushort Param1, Param2; + + public readonly DateTime Time; + + public readonly TimeSpan TimeDuration => DateTime.Now - Time; + + public MapEffectData(uint position, ushort param1, ushort param2) + { + Time = DateTime.Now; + Position = position; + Param1 = param1; + Param2 = param2; + } +} diff --git a/RotationSolver.Basic/DataCenter.cs b/RotationSolver.Basic/DataCenter.cs index f17206531..69386059e 100644 --- a/RotationSolver.Basic/DataCenter.cs +++ b/RotationSolver.Basic/DataCenter.cs @@ -15,6 +15,8 @@ namespace RotationSolver.Basic; internal static class DataCenter { + internal static Queue MapEffects { get; } = new(64); + /// /// This one never be null. /// @@ -449,13 +451,15 @@ internal static unsafe void AddActionRec(Action act) _actions.Enqueue(new ActionRec(_timeLastActionUsed, act)); } - internal static void ResetAllLastActions() + internal static void ResetAllRecords() { LastAction = 0; LastGCD = 0; LastAbility = 0; _timeLastActionUsed = DateTime.Now; _actions.Clear(); + + DataCenter.MapEffects.Clear(); } internal static void AddDamageRec(float damageRatio) diff --git a/RotationSolver/Localization/EnumTranslations.cs b/RotationSolver/Localization/EnumTranslations.cs index 0f60a3637..1f70bdae7 100644 --- a/RotationSolver/Localization/EnumTranslations.cs +++ b/RotationSolver/Localization/EnumTranslations.cs @@ -17,6 +17,7 @@ internal static class EnumTranslations TargetConditionType.CastingActionTimeUntil => LocalizationManager.RightLang.TargetConditionType_CastingActionTimeUntil, TargetConditionType.TimeToKill => LocalizationManager.RightLang.TargetConditionType_TimeToKill, TargetConditionType.HP => LocalizationManager.RightLang.TargetConditionType_HP, + TargetConditionType.HPRatio => LocalizationManager.RightLang.TargetConditionType_HPRatio, TargetConditionType.MP => LocalizationManager.RightLang.TargetConditionType_MP, TargetConditionType.TargetName => LocalizationManager.RightLang.TargetConditionType_TargetName, _ => string.Empty, diff --git a/RotationSolver/Localization/Strings.cs b/RotationSolver/Localization/Strings.cs index 1abc2d67c..c2262f6ef 100644 --- a/RotationSolver/Localization/Strings.cs +++ b/RotationSolver/Localization/Strings.cs @@ -386,6 +386,7 @@ internal class Strings public string TargetConditionType_CastingAction { get; set; } = "Casting Action"; public string TargetConditionType_CastingActionTimeUntil { get; set; } = "Casting Action Time Until"; public string TargetConditionType_HP { get; set; } = "HP"; + public string TargetConditionType_HPRatio { get; set; } = "HP%"; public string TargetConditionType_MP { get; set; } = "MP"; public string TargetConditionType_TargetName { get; set; } = "Target Name"; diff --git a/RotationSolver/UI/ConditionDrawer.cs b/RotationSolver/UI/ConditionDrawer.cs index 94bf765cc..f312057e7 100644 --- a/RotationSolver/UI/ConditionDrawer.cs +++ b/RotationSolver/UI/ConditionDrawer.cs @@ -899,6 +899,12 @@ void DrawStatusIcon() ImGui.DragFloat($"s##CastingActionTimeUntil{targetCondition.GetHashCode()}", ref targetCondition.DistanceOrTime, .1f); break; + case TargetConditionType.HPRatio: + ImGui.SameLine(); + ImGui.SetNextItemWidth(Math.Max(150 * ImGuiHelpers.GlobalScale, ImGui.CalcTextSize(targetCondition.DistanceOrTime.ToString()).X)); + ImGui.DragFloat($"##HPRatio{targetCondition.GetHashCode()}", ref targetCondition.DistanceOrTime, .1f); + break; + case TargetConditionType.MP: case TargetConditionType.HP: ImGui.SameLine(); @@ -929,7 +935,7 @@ void DrawStatusIcon() public static string[] DutyNames => _dutyNames ??= new HashSet(Service.GetSheet()? .Select(t => t?.Name?.RawString ?? string.Empty).Where(s => !string.IsNullOrEmpty(s)).Reverse()).ToArray(); - private static void DrawAfter(this TerritoryCondition territoryCondition, ICustomRotation rotation) + private static void DrawAfter(this TerritoryCondition territoryCondition, ICustomRotation _) { DrawByteEnum($"##Category{territoryCondition.GetHashCode()}", ref territoryCondition.TerritoryConditionType, EnumTranslations.ToName); @@ -970,6 +976,42 @@ private static void DrawAfter(this TerritoryCondition territoryCondition, ICusto territoryCondition.Name = i; }, LocalizationManager.RightLang.ConfigWindow_Condition_DutyName); break; + + case TerritoryConditionType.MapEffect: + ImGui.SameLine(); + + ImGui.Text("Pos:"); + ImGui.SameLine(); + ImGui.SetNextItemWidth(Math.Max(150 * ImGuiHelpers.GlobalScale, ImGui.CalcTextSize(territoryCondition.Position.ToString()).X)); + ImGui.DragInt($"##Position{territoryCondition.GetHashCode()}", ref territoryCondition.Position, .1f); + + ImGui.SameLine(); + + ImGui.Text("Param1:"); + ImGui.SameLine(); + ImGui.SetNextItemWidth(Math.Max(150 * ImGuiHelpers.GlobalScale, ImGui.CalcTextSize(territoryCondition.Param1.ToString()).X)); + ImGui.DragInt($"##Param1{territoryCondition.GetHashCode()}", ref territoryCondition.Param1, .1f); + + ImGui.SameLine(); + + ImGui.Text("Param2:"); + ImGui.SameLine(); + ImGui.SetNextItemWidth(Math.Max(150 * ImGuiHelpers.GlobalScale, ImGui.CalcTextSize(territoryCondition.Param2.ToString()).X)); + ImGui.DragInt($"##Param2{territoryCondition.GetHashCode()}", ref territoryCondition.Param2, .1f); + + ImGui.SameLine(); + + ImGui.Text("Time Offset:"); + ImGui.SameLine(); + const float MIN = 0, MAX = 60; + + ImGui.SetNextItemWidth(150 * ImGuiHelpers.GlobalScale); + if (ImGui.DragFloatRange2($"##TimeOffset {territoryCondition.GetHashCode()}", ref territoryCondition.TimeStart, ref territoryCondition.TimeEnd, 0.1f, MIN, MAX)) + { + territoryCondition.TimeStart = Math.Max(Math.Min(territoryCondition.TimeStart, territoryCondition.TimeEnd), MIN); + territoryCondition.TimeEnd = Math.Min(Math.Max(territoryCondition.TimeStart, territoryCondition.TimeEnd), MAX); + } + break; } } #endregion diff --git a/RotationSolver/Updaters/SocialUpdater.cs b/RotationSolver/Updaters/SocialUpdater.cs index e0aa68117..c6c6966f9 100644 --- a/RotationSolver/Updaters/SocialUpdater.cs +++ b/RotationSolver/Updaters/SocialUpdater.cs @@ -76,7 +76,7 @@ static async void DutyState_DutyCompleted(object sender, ushort e) static void ClientState_TerritoryChanged(ushort id) { - DataCenter.ResetAllLastActions(); + DataCenter.ResetAllRecords(); var territory = Service.GetSheet().GetRow(id); _canSaying = territory?.ContentFinderCondition?.Value?.RowId != 0; @@ -109,7 +109,7 @@ static void DutyState_DutyStarted(object sender, ushort e) static void DutyState_DutyWiped(object sender, ushort e) { if (!Player.Available) return; - DataCenter.ResetAllLastActions(); + DataCenter.ResetAllRecords(); } internal static void Disable() diff --git a/RotationSolver/Watcher.cs b/RotationSolver/Watcher.cs index 518a3344a..d5d6cf19a 100644 --- a/RotationSolver/Watcher.cs +++ b/RotationSolver/Watcher.cs @@ -18,7 +18,7 @@ public static class Watcher private static Dalamud.Hooking.Hook _useActionHook; #endif - public static ICallGateSubscriber IpcSubscriber; + private static ICallGateSubscriber IpcSubscriber; public static void Enable() { @@ -34,6 +34,15 @@ public static void Enable() ActionEffect.ActionEffectEvent += ActionFromEnemy; ActionEffect.ActionEffectEvent += ActionFromSelf; + MapEffect.Init((a1, position, param1, param2) => + { + if(DataCenter.MapEffects.Count >= 64) + { + DataCenter.MapEffects.TryDequeue(out _); + } + + DataCenter.MapEffects.Enqueue(new MapEffectData(position, param1, param2)); + }); } public static void Disable() @@ -42,6 +51,7 @@ public static void Disable() _useActionHook?.Dispose(); #endif IpcSubscriber.Unsubscribe(UpdateRTTDetour); + MapEffect.Dispose(); ActionEffect.ActionEffectEvent -= ActionFromEnemy; ActionEffect.ActionEffectEvent -= ActionFromSelf; }