Skip to content

Commit

Permalink
Refactor PrioTarget system and enhance various functionalities
Browse files Browse the repository at this point in the history
Replaced PrioTargetNames with PrioTargetId HashSet across the codebase, updating initialization, saving, and resetting methods. Improved DataCenter's IsCastingVfx method to avoid modifying collections during enumeration. Extended IActionHelper with IsLastActionGCD and IsLastActionAbility methods. Updated ObjectHelper to remove PrioTargetNames logic and enhance ChooseAttackMark condition. Enhanced PriorityTargetHelper to handle priority target IDs via JSON. Updated solution file to include PrioTargetId.json. Refined UiString and RotationConfigWindow for new target priority system. Improved MajorUpdater's VfxNewData handling. Added PrioTargetId.json for storing priority target IDs.
  • Loading branch information
LTS-FFXIV committed Dec 4, 2024
1 parent 87b2254 commit 5bd2c35
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 111 deletions.
4 changes: 4 additions & 0 deletions PrioTargetId.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[
0x415E,
0x4642
]
16 changes: 11 additions & 5 deletions RotationSolver.Basic/Configuration/OtherConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ internal class OtherConfiguration

public static SortedList<uint, float> AnimationLockTime = [];

public static Dictionary<uint, string[]> PrioTargetNames = [];
public static Dictionary<uint, string[]> NoHostileNames = [];
public static Dictionary<uint, string[]> NoProvokeNames = [];
public static Dictionary<uint, Vector3[]> BeneficialPositions = [];
Expand All @@ -19,6 +18,7 @@ internal class OtherConfiguration
public static HashSet<uint> PriorityStatus = [];
public static HashSet<uint> InvincibleStatus = [];
public static HashSet<uint> NoCastingStatus = [];
public static HashSet<uint> PrioTargetId = [];

public static RotationSolverRecord RotationSolverRecord = new();

Expand All @@ -32,7 +32,7 @@ public static void Init()
Task.Run(() => InitOne(ref DangerousStatus, nameof(DangerousStatus)));
Task.Run(() => InitOne(ref PriorityStatus, nameof(PriorityStatus)));
Task.Run(() => InitOne(ref InvincibleStatus, nameof(InvincibleStatus)));
Task.Run(() => InitOne(ref PrioTargetNames, nameof(PrioTargetNames)));
Task.Run(() => InitOne(ref PrioTargetId, nameof(PrioTargetId)));
Task.Run(() => InitOne(ref NoHostileNames, nameof(NoHostileNames)));
Task.Run(() => InitOne(ref NoProvokeNames, nameof(NoProvokeNames)));
Task.Run(() => InitOne(ref AnimationLockTime, nameof(AnimationLockTime)));
Expand All @@ -51,7 +51,7 @@ public static Task Save()
await SavePriorityStatus();
await SaveDangerousStatus();
await SaveInvincibleStatus();
await SavePrioTargetNames();
await SavePrioTargetId();
await SaveNoHostileNames();
await SaveAnimationLockTime();
await SaveHostileCastingArea();
Expand Down Expand Up @@ -159,9 +159,15 @@ public static Task SaveBeneficialPositions()
return Task.Run(() => Save(BeneficialPositions, nameof(BeneficialPositions)));
}

public static Task SavePrioTargetNames()
public static void ResetPrioTargetId()
{
return Task.Run(() => Save(PrioTargetNames, nameof(PrioTargetNames)));
InitOne(ref PrioTargetId, nameof(PrioTargetId), true, true);
SaveHostileCastingKnockback().Wait();
}

public static Task SavePrioTargetId()
{
return Task.Run(() => Save(PrioTargetId, nameof(PrioTargetId)));
}

public static Task SaveNoHostileNames()
Expand Down
18 changes: 5 additions & 13 deletions RotationSolver.Basic/DataCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -809,24 +809,16 @@ public static bool IsCastingAreaVfx()

public static bool IsCastingVfx(Func<VfxNewData, bool> isVfx)
{
if (isVfx == null) return false;
if (DataCenter.VfxDataQueue == null) return false;
// Create a copy of the VfxDataQueue to avoid modifying the collection while enumerating
var vfxDataQueueCopy = VfxDataQueue.ToList();

try
foreach (var vfx in vfxDataQueueCopy)
{
foreach (var item in DataCenter.VfxDataQueue.OrderBy(v => v.TimeDuration))
if (isVfx(vfx))
{
if (item.TimeDuration.TotalSeconds is > 1 and < 5)
{
if (isVfx(item)) return true;
}
return true;
}
}
catch (Exception ex)
{
Svc.Log.Error(ex, "Exception in IsCastingVfx");
}

return false;
}

Expand Down
18 changes: 18 additions & 0 deletions RotationSolver.Basic/Helpers/IActionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ internal static bool IsLastAction(params ActionID[] ids)
return IsActionID(DataCenter.LastAction, ids);
}

/// <summary>
/// Determines if the last action was a GCD.
/// </summary>
/// <returns>True if the last action was a GCD, otherwise false.</returns>
public static bool IsLastActionGCD()
{
return DataCenter.LastAction == DataCenter.LastGCD;
}

/// <summary>
/// Determines if the last action was an ability.
/// </summary>
/// <returns>True if the last action was an ability, otherwise false.</returns>
public static bool IsLastActionAbility()
{
return DataCenter.LastAction == DataCenter.LastAbility;
}

/// <summary>
/// Determines if the action is the same as any of the provided actions.
/// </summary>
Expand Down
12 changes: 1 addition & 11 deletions RotationSolver.Basic/Helpers/ObjectHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,16 +310,6 @@ internal static bool IsTopPriorityNamedHostile(this IGameObject obj)
{
if (obj == null) return false;

// Fetch prioritized target names
if (OtherConfiguration.PrioTargetNames.TryGetValue(Svc.ClientState.TerritoryType, out var prioTargetNames))
{
// If the target's name matches any prioritized names, it is attackable
if (obj is IBattleChara bpnc && prioTargetNames.Any(n => !string.IsNullOrEmpty(n) && new Regex(n).Match(bpnc.Name.TextValue).Success))
{
return true;
}
}

if (obj is IBattleChara npc && DataCenter.PrioritizedNameIds.Contains(npc.NameId)) return true;

return false;
Expand Down Expand Up @@ -348,7 +338,7 @@ internal static bool IsTopPriorityHostile(this IGameObject obj)
if (b.StatusList != null && b.StatusList.Any(StatusHelper.IsPriority)) return true;
}

if (Service.Config.ChooseAttackMark && MarkingHelper.GetAttackSignTargets().FirstOrDefault(id => id != 0) == (long)obj.GameObjectId) return true;
if (Service.Config.ChooseAttackMark && MarkingHelper.GetAttackSignTargets().FirstOrDefault(id => id != 0) == (long)obj.GameObjectId && obj.IsEnemy()) return true;

// Fate
if (Service.Config.TargetFatePriority && fateId != 0 && obj.FateId() == fateId) return true;
Expand Down
30 changes: 22 additions & 8 deletions RotationSolver.Basic/Helpers/PriorityTargetHelper.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
namespace RotationSolver.Basic.Helpers
using System.IO;
using System.Text.Json;
using JsonSerializer = System.Text.Json.JsonSerializer;
using RotationSolver.Basic.Configuration;

namespace RotationSolver.Basic.Helpers
{
internal class PriorityTargetHelper
{
private static readonly string FilePath = "PriorityId.json";

// List of OIDs (DataId)
private static readonly HashSet<uint> priorityOids = new HashSet<uint>
{
0x415E, // Crystalline Debris in D022Kahderyor
0x4642 // Raw Electrope in D09YuweyawataFieldStation
// Add more OIDs here
};
private static HashSet<uint> priorityOids = LoadPriorityOids();

// Method to check if the given DataId is a priority target
public static bool IsPriorityTarget(uint dataId)
Expand All @@ -22,7 +24,19 @@ public static void AddPriorityTarget(uint dataId)
if (!priorityOids.Contains(dataId))
{
priorityOids.Add(dataId);
OtherConfiguration.SavePrioTargetId();
}
}

// Method to load priority OIDs from JSON file
private static HashSet<uint> LoadPriorityOids()
{
if (File.Exists(FilePath))
{
var json = File.ReadAllText(FilePath);
return JsonSerializer.Deserialize<HashSet<uint>>(json) ?? new HashSet<uint>();
}
return new HashSet<uint>();
}
}
}
}
7 changes: 4 additions & 3 deletions RotationSolver.sln
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8948C02A-914E-4A51-B1FE-2C608492EBF5}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
Resources\AnimationLockTime.json = Resources\AnimationLockTime.json
Directory.Build.props = Directory.Build.props
Resources\IncompatiblePlugins.json = Resources\IncompatiblePlugins.json
Resources\HostileCastingArea.json = Resources\HostileCastingArea.json
Resources\HostileCastingKnockback.json = Resources\HostileCastingKnockback.json
Resources\HostileCastingTank.json = Resources\HostileCastingTank.json
Resources\AnimationLockTime.json = Resources\AnimationLockTime.json
Resources\IncompatiblePlugins.json = Resources\IncompatiblePlugins.json
manifest.json = manifest.json
.github\workflows\publish.yaml = .github\workflows\publish.yaml
PrioTargetId.json = PrioTargetId.json
UpdateDownloads.ts = UpdateDownloads.ts
EndProjectSection
EndProject
Expand All @@ -29,7 +30,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RotationSolver.GameData", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RotationSolver.DummyRotations", "RotationSolver.DummyRotations\RotationSolver.DummyRotations.csproj", "{2C9BACA6-A791-478C-84BB-8A798123468A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RebornRotations", "BasicRotations\RebornRotations.csproj", "{054B46FA-5639-45A0-A5A1-4A8ED860DDC9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RebornRotations", "BasicRotations\RebornRotations.csproj", "{054B46FA-5639-45A0-A5A1-4A8ED860DDC9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
8 changes: 4 additions & 4 deletions RotationSolver/Data/UiString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,6 @@ internal enum UiString
[Description("Add Action")]
ConfigWindow_List_AddAction,

[Description("Prio Target")]
ConfigWindow_List_PrioTarget,

[Description("Don't target")]
ConfigWindow_List_NoHostile,

Expand All @@ -286,7 +283,7 @@ internal enum UiString
[Description("Beneficial AoE locations")]
ConfigWindow_List_BeneficialPositions,

[Description("Enemies that will be prioritized.")]
[Description("Enemies that will be prioritized. This system is under construction and experimental, but should be stable.")]
ConfigWindow_List_PrioTargetDesc,

[Description("Enemies that will never be targeted.")]
Expand Down Expand Up @@ -451,6 +448,9 @@ internal enum UiString
[Description("Hostile")]
ConfigWindow_List_Hostile,

[Description("Target Priority")]
ConfigWindow_List_TargetPriority,

[Description("Enemy targeting logic. Adding more options cycles them when using /rotation Auto.\nUse /rotation Settings TargetingTypes add <option> to add,\n/rotation Settings TargetingTypes remove <option> to remove,\nand /rotation Settings TargetingTypes removeall to remove all options.")]
ConfigWindow_Param_HostileDesc,

Expand Down
63 changes: 2 additions & 61 deletions RotationSolver/UI/RotationConfigWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2363,9 +2363,6 @@ private static void DrawListTerritories()
ImGui.TableNextColumn();
ImGui.TableHeader(UiString.ConfigWindow_List_NoHostile.GetDescription());

ImGui.TableNextColumn();
ImGui.TableHeader(UiString.ConfigWindow_List_PrioTarget.GetDescription());

ImGui.TableNextColumn();
ImGui.TableHeader(UiString.ConfigWindow_List_NoProvoke.GetDescription());

Expand Down Expand Up @@ -2414,64 +2411,6 @@ private static void DrawListTerritories()
OtherConfiguration.SaveNoHostileNames();
}




// Begin new column for Prioritized Target Names
ImGui.TableNextColumn();
ImGui.TextWrapped(UiString.ConfigWindow_List_PrioTargetDesc.GetDescription());

width = ImGui.GetColumnWidth() - ImGuiEx.CalcIconSize(FontAwesomeIcon.Ban).X - ImGui.GetStyle().ItemSpacing.X - 10 * Scale;

// Check if PrioritizedNames for the current territory exists
if (!OtherConfiguration.PrioTargetNames.TryGetValue(territoryId, out var prioNames))
{
// Initialize it as an empty list
OtherConfiguration.PrioTargetNames[territoryId] = prioNames = [];
}

// Add an empty entry if none exists
if (!prioNames.Any(string.IsNullOrEmpty))
{
OtherConfiguration.PrioTargetNames[territoryId] = [.. prioNames, string.Empty];
}

// Variable to track if we need to remove any entry
removeIndex = -1;

// Loop over each prioritized name to render input fields
for (int i = 0; i < prioNames.Length; i++)
{
ImGui.SetNextItemWidth(width);

// Render input field for prioritized name with a placeholder hint
if (ImGui.InputTextWithHint($"##Rotation Solver Prioritized Target Name {i}", UiString.ConfigWindow_List_PrioTargetName.GetDescription(), ref prioNames[i], 1024))
{
// If input changes, update the list
OtherConfiguration.PrioTargetNames[territoryId] = prioNames;
OtherConfiguration.SavePrioTargetNames();
}
ImGui.SameLine();

// Render a button to remove a name
if (ImGuiEx.IconButton(FontAwesomeIcon.Ban, $"##Rotation Solver Remove Prioritized Target Name {i}"))
{
removeIndex = i;
}
}

// If a remove button was clicked, remove the corresponding entry
if (removeIndex > -1)
{
var list = prioNames.ToList();
list.RemoveAt(removeIndex);
OtherConfiguration.PrioTargetNames[territoryId] = [.. list];
OtherConfiguration.SavePrioTargetNames();
}




ImGui.TableNextColumn();
ImGui.TextWrapped(UiString.ConfigWindow_List_NoProvokeDesc.GetDescription());

Expand Down Expand Up @@ -2844,6 +2783,8 @@ private static void DrawLastAction()
DrawAction(DataCenter.LastAbility, nameof(DataCenter.LastAbility));
DrawAction(DataCenter.LastGCD, nameof(DataCenter.LastGCD));
DrawAction(DataCenter.LastComboAction, nameof(DataCenter.LastComboAction));
ImGui.Text($"IsLastActionAbility: {IActionHelper.IsLastActionAbility()}");
ImGui.Text($"IsLastActionGCD: {IActionHelper.IsLastActionGCD()}");
}

private static void DrawOthers()
Expand Down
41 changes: 41 additions & 0 deletions RotationSolver/UI/RotationConfigWindow_Config.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Dalamud.Game.ClientState.Keys;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility.Raii;
using ECommons.DalamudServices;
using ECommons.ImGuiMethods;
using Lumina.Excel.Sheets;
using RotationSolver.Basic.Configuration;
using RotationSolver.Basic.Configuration.Conditions;
using RotationSolver.Data;
Expand Down Expand Up @@ -377,6 +379,7 @@ private static void DrawTarget()
{
{ UiString.ConfigWindow_Target_Config.GetDescription, DrawTargetConfig },
{ UiString.ConfigWindow_List_Hostile.GetDescription, DrawTargetHostile },
{ UiString.ConfigWindow_List_TargetPriority.GetDescription, DrawTargetPriority },
});

/// <summary>
Expand Down Expand Up @@ -438,6 +441,44 @@ void Down()
(Down, new[] { VirtualKey.DOWN }));
}
}

private static void DrawTargetPriority()
{
// Convert HashSet<uint> to string[] for ImGui input
var prioIdSet = OtherConfiguration.PrioTargetId;
string[] prioId = prioIdSet.Select(id => id.ToString()).ToArray();

// Begin new column for Prioritized Target Names
ImGui.TableNextColumn();
ImGui.TextWrapped(UiString.ConfigWindow_List_PrioTargetDesc.GetDescription());

// List all DataIds in the current list
ImGui.Text("Current Priority DataIds:");
foreach (var id in prioIdSet)
{
ImGui.Text(id.ToString());
}

ImGui.TableNextColumn();
if (ImGui.Button("Reset and Update Target Priority List"))
{
OtherConfiguration.ResetPrioTargetId();
}

// Render a button to add the DataId of the current target
if (ImGui.Button("Add Current Target"))
{
var currentTarget = Svc.Targets.Target;
if (currentTarget != null)
{
uint dataId = currentTarget.DataId;
PriorityTargetHelper.AddPriorityTarget(dataId);
prioIdSet.Add(dataId);
OtherConfiguration.PrioTargetId = prioIdSet;
OtherConfiguration.SavePrioTargetId();
}
}
}
#endregion

#region Extra
Expand Down
Loading

0 comments on commit 5bd2c35

Please sign in to comment.