Skip to content

Commit

Permalink
Refactor distance checks and enemy list handling
Browse files Browse the repository at this point in the history
Removed static readonly booleans from Configs.cs related to enemy list handling. Added new enum values to TargetHostileType.cs. Changed distance comparison operators from <= to < in DataCenter.cs and RotationSolverPlugin.cs. Added using directives and refactored enemy list logic in ObjectHelper.cs. Removed unused using directives in RotationSolverPlugin.cs. Refactored _debugHeader initialization in RotationConfigWindow.cs for better readability.
  • Loading branch information
LTS-FFXIV committed Sep 28, 2024
1 parent 863d0b0 commit 0f39dce
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 55 deletions.
9 changes: 8 additions & 1 deletion Resources/HostileCastingArea.json
Original file line number Diff line number Diff line change
Expand Up @@ -640,5 +640,12 @@
36610,
36612,
27145,
27181
27181,
24522,
13066,
13073,
13085,
13074,
26050,
26049
]
5 changes: 4 additions & 1 deletion Resources/HostileCastingTank.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@
33965,
35715,
37845,
29023
29023,
10542,
26040,
26041
]
8 changes: 0 additions & 8 deletions RotationSolver.Basic/Configuration/Configs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,6 @@ public const string
[UI("", Action = ActionID.ImprovisationPvE, Parent = nameof(PoslockCasting))]
public bool PosImprovisation { get; set; } = false;

[ConditionBool, UI("Add enemy list to the hostile targets.",
Filter = TargetConfig)]
private static readonly bool _addEnemyListToHostile = true;

[ConditionBool, UI("Only attack the targets in enemy list.",
Parent = nameof(AddEnemyListToHostile))]
private static readonly bool _onlyAttackInEnemyList = false;

[JobConfig, UI("Only used automatically if coded into the rotation", Filter = AutoActionUsage, PvPFilter = JobFilterType.NoJob)]
private readonly TinctureUseType _TinctureType = TinctureUseType.Nowhere;

Expand Down
12 changes: 12 additions & 0 deletions RotationSolver.Basic/Data/TargetHostileType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,16 @@ public enum TargetHostileType : byte
/// </summary>
[Description("All targets when solo, or previously engaged.")]
AllTargetsWhenSolo,

/// <summary>
/// Targets in your enemy list.
/// </summary>
[Description("Only attack targets in your parties enemy list")]
TargetIsInEnemiesList,

/// <summary>
/// All targets when solo, or only attack targets in your parties enemy list.
/// </summary>
[Description("All targets when solo, or only attack targets in your parties enemy list")]
AllTargetsWhenSoloTargetIsInEnemiesList,
}
10 changes: 5 additions & 5 deletions RotationSolver.Basic/DataCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -471,12 +471,12 @@ public static ulong[] TreasureCharas

public static bool HasHostilesInRange => NumberOfHostilesInRange > 0;
public static bool HasHostilesInMaxRange => NumberOfHostilesInMaxRange > 0;
public static int NumberOfHostilesInRange => AllHostileTargets.Count(o => o.DistanceToPlayer() <= JobRange);
public static int NumberOfHostilesInMaxRange => AllHostileTargets.Count(o => o.DistanceToPlayer() <= 25);
public static int NumberOfAllHostilesInRange => AllHostileTargets.Count(o => o.DistanceToPlayer() <= JobRange);
public static int NumberOfAllHostilesInMaxRange => AllHostileTargets.Count(o => o.DistanceToPlayer() <= 25);
public static int NumberOfHostilesInRange => AllHostileTargets.Count(o => o.DistanceToPlayer() < JobRange);
public static int NumberOfHostilesInMaxRange => AllHostileTargets.Count(o => o.DistanceToPlayer() < 25);
public static int NumberOfAllHostilesInRange => AllHostileTargets.Count(o => o.DistanceToPlayer() < JobRange);
public static int NumberOfAllHostilesInMaxRange => AllHostileTargets.Count(o => o.DistanceToPlayer() < 25);

public static bool MobsTime => AllHostileTargets.Count(o => o.DistanceToPlayer() <= JobRange && o.CanSee())
public static bool MobsTime => AllHostileTargets.Count(o => o.DistanceToPlayer() < JobRange && o.CanSee())
>= Service.Config.AutoDefenseNumber;

public static bool AreHostilesCastingKnockback => AllHostileTargets.Any(IsHostileCastingKnockback);
Expand Down
117 changes: 95 additions & 22 deletions RotationSolver.Basic/Helpers/ObjectHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
using FFXIVClientStructs.FFXIV.Client.Graphics;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Common.Component.BGCollision;
using FFXIVClientStructs.FFXIV.Component.GUI;
using RotationSolver.Basic.Configuration;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;

namespace RotationSolver.Basic.Helpers;
Expand Down Expand Up @@ -95,53 +98,123 @@ internal static bool IsAttackable(this IBattleChara battleChara)
if (tarFateId != 0 && tarFateId != DataCenter.FateId) return false;
}

if (Service.Config.AddEnemyListToHostile)
{
if (battleChara.IsInEnemiesList()) return true;
// Only attack
if (Service.Config.OnlyAttackInEnemyList) return false;
}

// Tar on me
if (battleChara.TargetObject == Player.Object
|| battleChara.TargetObject?.OwnerId == Player.Object.GameObjectId) return true;

if (battleChara.IsOthersPlayers()) return false;

if (battleChara.IsTopPriorityHostile()) return true;

if (Service.CountDownTime > 0 || DataCenter.IsPvP) return true;

return DataCenter.RightNowTargetToHostileType switch {
// Tar on me
if (battleChara.TargetObject == Player.Object
|| battleChara.TargetObject?.OwnerId == Player.Object.GameObjectId) return true;

return DataCenter.RightNowTargetToHostileType switch
{
TargetHostileType.AllTargetsCanAttack => true,
TargetHostileType.TargetsHaveTarget => battleChara.TargetObject is IBattleChara,
TargetHostileType.AllTargetsWhenSolo => DataCenter.PartyMembers.Length < 2 || battleChara.TargetObject is IBattleChara,
TargetHostileType.AllTargetsWhenSoloInDuty => (DataCenter.PartyMembers.Length < 2 && Svc.Condition[ConditionFlag.BoundByDuty])
|| battleChara.TargetObject is IBattleChara,
TargetHostileType.TargetIsInEnemiesList => battleChara.TargetObject is IBattleChara target && target.IsInEnemiesList(),
TargetHostileType.AllTargetsWhenSoloTargetIsInEnemiesList => DataCenter.PartyMembers.Length < 2 || battleChara.TargetObject is IBattleChara target && target.IsInEnemiesList(),
_ => true,
};
}

internal static unsafe bool IsInEnemiesList(this IBattleChara IBattleChara)
private static string RemoveControlCharacters(string input)
{
if (string.IsNullOrEmpty(input))
return input;

// Use a StringBuilder for efficient string manipulation
var output = new StringBuilder(input.Length);
foreach (char c in input)
{
// Exclude control characters and private use area characters
if (!char.IsControl(c) && (c < '\uE000' || c > '\uF8FF'))
{
output.Append(c);
}
}
return output.ToString();
}

//Below never returns true
internal static unsafe bool IsInEnemiesList(this IBattleChara battleChara)
{
var addons = Service.GetAddons<AddonEnemyList>();

if (!addons.Any()) return false;
if (!addons.Any())
{
return false;
}

if (!addons.Any())
{
return false;
}

var addon = addons.FirstOrDefault();
var enemy = (AddonEnemyList*)addon;
if (addon == IntPtr.Zero)
{
return false;
}

var numArray = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance()->GetUIModule()->GetRaptureAtkModule()->AtkModule.AtkArrayDataHolder.NumberArrays[19];
if (numArray == null) return false;
var enemyList = (AddonEnemyList*)addon;

const int baseIndex = 8;
const int step = 6;
// Ensure that EnemyOneComponent is valid
if (enemyList->EnemyOneComponent == null)
{
return false;
}

// EnemyCount indicates how many enemies are in the list
var enemyCount = enemyList->EnemyCount;

for (var i = 0; i < enemy->EnemyCount; i++)
for (int i = 0; i < enemyCount; i++)
{
var id = (uint)numArray->IntArray[baseIndex + i * step];
// Access each enemy component
var enemyComponentPtr = enemyList->EnemyOneComponent + i;
if (enemyComponentPtr == null || *enemyComponentPtr == null)
{
continue;
}

var enemyComponent = *enemyComponentPtr;
var atkComponentBase = enemyComponent->AtkComponentBase;

if (IBattleChara.GameObjectId == id) return true;
// Access the UldManager's NodeList
var uldManager = atkComponentBase.UldManager;

for (int j = 0; j < uldManager.NodeListCount; j++)
{
var node = uldManager.NodeList[j];
if (node == null)
continue;

if (node->Type == NodeType.Text)
{
var textNode = (AtkTextNode*)node;
if (textNode->NodeText.StringPtr == null)
continue;

// Read the enemy's name
var enemyNameRaw = Marshal.PtrToStringUTF8((IntPtr)textNode->NodeText.StringPtr);
if (string.IsNullOrEmpty(enemyNameRaw))
continue;

// Remove control characters from the enemy's name
var enemyName = RemoveControlCharacters(enemyNameRaw);

// Compare with battleChara's name
if (string.Equals(enemyName, battleChara.Name.TextValue, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
}

return false;
}

Expand Down
4 changes: 1 addition & 3 deletions RotationSolver/RotationSolverPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@
using RotationSolver.Commands;
using RotationSolver.Data;
using RotationSolver.Helpers;

using RotationSolver.UI;
using RotationSolver.UI.HighlightTeachingMode;
using RotationSolver.UI.HighlightTeachingMode.ElementSpecial;
using RotationSolver.Updaters;
using static FFXIVClientStructs.FFXIV.Client.UI.Agent.AgentPartyMember.Delegates;
using WelcomeWindow = RotationSolver.UI.WelcomeWindow;

namespace RotationSolver;
Expand Down Expand Up @@ -249,7 +247,7 @@ internal static void UpdateDisplayWindow()

isValid &= !Service.Config.OnlyShowWithHostileOrInDuty
|| Svc.Condition[ConditionFlag.BoundByDuty]
|| DataCenter.AllHostileTargets.Any(o => o.DistanceToPlayer() <= 25);
|| DataCenter.AllHostileTargets.Any(o => o.DistanceToPlayer() < 25);

_controlWindow!.IsOpen = isValid && Service.Config.ShowControlWindow;
_cooldownWindow!.IsOpen = isValid && Service.Config.ShowCooldownWindow;
Expand Down
30 changes: 15 additions & 15 deletions RotationSolver/UI/RotationConfigWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2607,21 +2607,21 @@ private static void DrawDebug()
}

private static readonly CollapsingHeaderGroup _debugHeader = new(new()
{
{() => DataCenter.RightNowRotation != null ? "Rotation" : string.Empty, DrawDebugRotationStatus},
{() => "Status", DrawStatus },
{() => "Party", DrawParty },
{() => "Target Data", DrawTargetData },
{() => "Next Action", DrawNextAction },
{() => "Last Action", DrawLastAction },
{() => "Others", DrawOthers },
{() => "Effect", () =>
{
ImGui.Text(Watcher.ShowStrSelf);
ImGui.Separator();
ImGui.Text(DataCenter.Role.ToString());
} },
});
{
{() => DataCenter.RightNowRotation != null ? "Rotation" : string.Empty, DrawDebugRotationStatus},
{() => "Status", DrawStatus },
{() => "Party", DrawParty },
{() => "Target Data", DrawTargetData },
{() => "Next Action", DrawNextAction },
{() => "Last Action", DrawLastAction },
{() => "Others", DrawOthers },
{() => "Effect", () =>
{
ImGui.Text(Watcher.ShowStrSelf);
ImGui.Separator();
ImGui.Text(DataCenter.Role.ToString());
} },
});

private static void DrawDebugRotationStatus()
{
Expand Down

0 comments on commit 0f39dce

Please sign in to comment.