Skip to content
This repository has been archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
fix: add affected targets
Browse files Browse the repository at this point in the history
  • Loading branch information
ArchiDog1998 committed Nov 4, 2023
1 parent bcc1433 commit 4db689a
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 38 deletions.
7 changes: 6 additions & 1 deletion Resources/HostileCastingArea.json
Original file line number Diff line number Diff line change
Expand Up @@ -461,5 +461,10 @@
35113,
34947,
34748,
34763
34763,
29895,
29906,
29896,
30508,
30532
]
2 changes: 1 addition & 1 deletion Resources/RotationSolverRecord.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"ClickingCount": 51481,
"ClickingCount": 52036,
"SaidUsers": []
}
5 changes: 4 additions & 1 deletion RotationSolver.Basic/Actions/BaseAction_ActionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public unsafe virtual bool CanUse(out IAction act, CanUseOption option = CanUseO
var player = Player.Object;
if (player == null) return false;
Target = player;
AffectedTargets = Array.Empty<BattleChara>();

if (!SkipDisable && !IsEnabled) return false;
if (!IsOnSlot) return false;
Expand Down Expand Up @@ -172,11 +173,13 @@ public unsafe virtual bool CanUse(out IAction act, CanUseOption option = CanUseO
if (IsGeneralGCD && IsEot && IsFriendly && IActionHelper.IsLastGCD(true, this)
&& DataCenter.TimeSinceLastAction.TotalSeconds < 3) return false;

if (!FindTarget(mustUse, aoeCount, out var target) || target == null) return false;
if (!FindTarget(mustUse, aoeCount, out var target, out var affectedTargets) || target == null) return false;

if (ActionCheck != null && !ActionCheck(target, mustUse)) return false;

Target = target;
AffectedTargets = affectedTargets;

if (!option.HasFlag(CanUseOption.IgnoreTarget)) _targetId = target.ObjectId;
return true;
}
Expand Down
105 changes: 81 additions & 24 deletions RotationSolver.Basic/Actions/BaseAction_Target.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ public float TimeToKill
/// </summary>
public BattleChara Target { get; private set; } = Player.Object;

/// <inheritdoc/>
public BattleChara[] AffectedTargets { get; private set; } = Array.Empty<BattleChara>();

internal bool IsTargetArea => _action.TargetArea;

/// <summary>
Expand Down Expand Up @@ -111,7 +114,8 @@ internal static bool TankBreakOtherCheck(Job id)
&& DataCenter.PartyMembersAverHP > tankHealth + 0.01f;
}

private bool FindTarget(bool mustUse, byte aoeCount, out BattleChara target)
/// <inheritdoc/>
public bool FindTarget(bool mustUse, byte aoeCount, out BattleChara target, out BattleChara[] affectedTargets)
{
aoeCount = Math.Max(aoeCount, mustUse ? (byte)1 : AOECount);

Expand All @@ -123,37 +127,48 @@ private bool FindTarget(bool mustUse, byte aoeCount, out BattleChara target)
if (range == 0 && EffectRange == 0)
{
target = player;
affectedTargets = Array.Empty<BattleChara>();
return true;
}
else if (IsTargetArea)
{
target = player;
affectedTargets = Array.Empty<BattleChara>();
return TargetArea(range, mustUse, aoeCount, player);
}
else if (_action.CanTargetParty && _action.CanTargetHostile)
{
return TargetPartyAndHostile(range, mustUse, out target);
return TargetPartyAndHostile(range, mustUse, out target, out affectedTargets);
}
else if (_action.CanTargetParty)
{
return TargetParty(range, aoeCount, mustUse, out target);
return TargetParty(range, aoeCount, mustUse, out target, out affectedTargets);
}
else if (_action.CanTargetHostile)
{
return TargetHostile(range, mustUse, aoeCount, out target);
return TargetHostile(range, mustUse, aoeCount, out target, out affectedTargets);
}
else if (_action.CanTargetSelf)
{
target = player;
return TargetSelf(mustUse, aoeCount);
return TargetSelf(mustUse, aoeCount, out affectedTargets);
}
else
{
target = Svc.Targets.Target is BattleChara battle ? battle : player;
affectedTargets = Array.Empty<BattleChara>();
return true;
}
}

private BattleChara[] GetAffectedTargets(IEnumerable<BattleChara> targets, BattleChara target)
{
return targets.Where(t =>
{
return CanGetTarget(target, t);
}).ToArray();
}

#region TargetArea
private bool TargetArea(float range, bool mustUse, int aoeCount, PlayerCharacter player)
{
Expand Down Expand Up @@ -300,24 +315,30 @@ private bool TargetAreaFriend(float range, bool mustUse, PlayerCharacter player)
}
#endregion

private bool TargetPartyAndHostile(float range, bool mustUse, out BattleChara target)
private bool TargetPartyAndHostile(float range, bool mustUse, out BattleChara target, out BattleChara[] affectedTargets)
{
var availableCharas = DataCenter.PartyMembers.Union(DataCenter.HostileTargets)
.Where(b => b.ObjectId != Player.Object.ObjectId);
availableCharas = TargetFilter.GetObjectInRadius(availableCharas, range).Where(CanUseTo);

target = ChoiceTarget(availableCharas, mustUse);
if (target == null) return false;
if (target == null)
{
affectedTargets = Array.Empty<BattleChara>();
return false;
}

affectedTargets = new BattleChara[] { target };
return true;
}

#region Target party
private bool TargetParty(float range, int aoeCount, bool mustUse, out BattleChara target)
private bool TargetParty(float range, int aoeCount, bool mustUse, out BattleChara target, out BattleChara[] affectedTargets)
{
if (_action.PrimaryCostType == 3 && _action.PrimaryCostValue == 24
|| (ActionID)ID is ActionID.AngelWhisper or ActionID.VariantRaise or ActionID.VariantRaise2)
{
return TargetDeath(out target);
return TargetDeath(out target, out affectedTargets);
}

var availableCharas = DataCenter.PartyMembers.Where(player => player.CurrentHp != 0);
Expand All @@ -333,6 +354,7 @@ private bool TargetParty(float range, int aoeCount, bool mustUse, out BattleChar
if (!availableCharas.Any())
{
target = null;
affectedTargets = Array.Empty<BattleChara>();
return false;
}

Expand All @@ -346,45 +368,59 @@ private bool TargetParty(float range, int aoeCount, bool mustUse, out BattleChar
{
availableCharas = availableCharas.Where(b => b.IsJobCategory(JobRole.Tank));
}
availableCharas = TargetFilter.GetObjectInRadius(availableCharas, range).Where(CanUseTo);
if (availableCharas == null || !availableCharas.Any())
var targetingCharas = TargetFilter.GetObjectInRadius(availableCharas, range).Where(CanUseTo);
if (targetingCharas == null || !targetingCharas.Any())
{
target = null;
affectedTargets = Array.Empty<BattleChara>();
return false;
}

target = ChoiceTarget(availableCharas, mustUse);
target = ChoiceTarget(targetingCharas, mustUse);
}
if (target == null)
{
affectedTargets = Array.Empty<BattleChara>();
return false;
}
if (target == null) return false;

affectedTargets = GetAffectedTargets(availableCharas, target);
return mustUse || CheckStatus(target);
}

private static bool TargetDeath(out BattleChara target)
private static bool TargetDeath(out BattleChara target, out BattleChara[] affectedTargets)
{
target = TargetFilter.GetDeathPeople(DataCenter.DeathPeopleAll, DataCenter.DeathPeopleParty);
if (target == null) return false;
if (target == null)
{
affectedTargets = Array.Empty<BattleChara>();
return false;
}

affectedTargets = new BattleChara[] { target };
return true;
}
#endregion

#region Target Hostile
private bool TargetHostile(float range, bool mustUse, int aoeCount, out BattleChara target)
private bool TargetHostile(float range, bool mustUse, int aoeCount, out BattleChara target, out BattleChara[] affectedTargets)
{
if (DataCenter.IsManual)
{
if (Svc.Targets.Target is BattleChara b && b.IsNPCEnemy() && b.DistanceToPlayer() <= range)
{
return TargetHostileManual(b, mustUse, aoeCount, out target);
return TargetHostileManual(b, mustUse, aoeCount, out target, out affectedTargets);
}

target = null;
affectedTargets = Array.Empty<BattleChara>();
return false;
}

if (!IsSingleTarget && NoAOE)
{
target = null;
affectedTargets = Array.Empty<BattleChara>();
return false;
}

Expand All @@ -394,18 +430,25 @@ private bool TargetHostile(float range, bool mustUse, int aoeCount, out BattleCh
if (b != null && ChoiceTarget(GetMostObjects(TargetFilterFuncEot(new BattleChara[] { b }, mustUse), Service.Config.GetValue(PluginConfigBool.CanAttackMarkAOE) ? aoeCount : int.MaxValue), mustUse) != null)
{
target = b;
affectedTargets = GetAffectedTargets(DataCenter.HostileTargets, target);
return true;
}
}

target = ChoiceTarget(GetMostObjects(TargetFilterFuncEot(DataCenter.HostileTargets, mustUse), aoeCount), mustUse);
if (target == null) return false;
if (target == null)
{
affectedTargets = Array.Empty<BattleChara>();
return false;
}
affectedTargets = GetAffectedTargets(DataCenter.HostileTargets, target);
return true;
}

private bool TargetHostileManual(BattleChara b, bool mustUse, int aoeCount, out BattleChara target)
private bool TargetHostileManual(BattleChara b, bool mustUse, int aoeCount, out BattleChara target, out BattleChara[] affectedTargets)
{
target = b;
affectedTargets = Array.Empty<BattleChara>();
if (!CanUseTo(b)) return false;
if (ChoiceTarget(TargetFilterFuncEot(new BattleChara[] { b }, mustUse), mustUse) == null) return false;

Expand All @@ -422,6 +465,7 @@ private bool TargetHostileManual(BattleChara b, bool mustUse, int aoeCount, out
if (!CheckStatus(b)) return false;
}

affectedTargets = new BattleChara[] { target };
return true;
}

Expand All @@ -430,6 +474,7 @@ private bool TargetHostileManual(BattleChara b, bool mustUse, int aoeCount, out
{
if (GetMostObjects(TargetFilterFuncEot(DataCenter.HostileTargets, mustUse), aoeCount).Contains(b))
{
affectedTargets = GetAffectedTargets(DataCenter.HostileTargets, target);
return true;
}
}
Expand All @@ -438,14 +483,24 @@ private bool TargetHostileManual(BattleChara b, bool mustUse, int aoeCount, out
}
#endregion

private bool TargetSelf(bool mustUse, int aoeCount)
private bool TargetSelf(bool mustUse, int aoeCount, out BattleChara[] affectedTargets)
{
if (EffectRange <= 0) return true;
if (EffectRange <= 0)
{
affectedTargets = new BattleChara[] { Player.Object };
return true;
}
affectedTargets = Array.Empty<BattleChara>();

if (IsFriendly)
{
var tars = TargetFilter.GetObjectInRadius(TargetFilterFuncEot(DataCenter.PartyMembers, mustUse), EffectRange);
if (tars.Count() < aoeCount) return false;
if (tars.Count() < aoeCount)
{
return false;
}

affectedTargets = GetAffectedTargets(DataCenter.PartyMembers, Player.Object);
}
else
{
Expand All @@ -462,6 +517,8 @@ private bool TargetSelf(bool mustUse, int aoeCount)

if (Service.Config.GetValue(PluginConfigBool.NoNewHostiles) && TargetFilter.GetObjectInRadius(DataCenter.AllHostileTargets, EffectRange)
.Any(t => t.TargetObject == null)) return false;

affectedTargets = GetAffectedTargets(DataCenter.HostileTargets, Player.Object);
}

return true;
Expand Down Expand Up @@ -521,7 +578,7 @@ private int CanGetTargetCount(BattleChara target, IEnumerable<BattleChara> canAt

const double _alpha = Math.PI / 3;

internal bool CanGetTarget(BattleChara target, BattleChara subTarget)
private bool CanGetTarget(BattleChara target, BattleChara subTarget)
{
if (target == null) return false;
if (IsSingleTarget) return false;
Expand Down Expand Up @@ -609,7 +666,7 @@ bool CheckStatus(BattleChara tar)
0, true, TargetStatus);
}

internal unsafe bool CanUseTo(GameObject tar)
private unsafe bool CanUseTo(GameObject tar)
{
if (tar == null || !Player.Available) return false;

Expand Down
9 changes: 8 additions & 1 deletion RotationSolver.Basic/Actions/IBaseAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,15 @@ public interface IBaseAction : IAction
float TimeToKill { get; internal set; }

/// <summary>
/// The user seted heal ratio.
/// The user set heal ratio.
/// </summary>
float AutoHealRatio { get; internal set; }

/// <summary>
/// The targets that this action affected on.
/// </summary>
BattleChara[] AffectedTargets { get; }

internal bool FindTarget(bool mustUse, byte aoeCount, out BattleChara target, out BattleChara[] affectedTargets);
#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ protected override bool IsTrueInside(ICustomRotation rotation)
BattleChara tar;
if (_action != null)
{
_action.CanUse(out _, CanUseOption.EmptyOrSkipCombo | CanUseOption.MustUse
| CanUseOption.IgnoreTarget);
tar = _action.Target;
if(!_action.FindTarget(true, 0, out tar, out _))
{
tar = null;
}
}
else
{
Expand Down
11 changes: 4 additions & 7 deletions RotationSolver/UI/PainterManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,13 @@ public override void UpdateOnFrame(XIVPainter.XIVPainter painter)
{
var SColor = ImGui.GetColorU32(Service.Config.GetValue(PluginConfigVector4.SubTargetColor));

foreach (var t in DataCenter.HostileTargets)
foreach (var t in act.AffectedTargets)
{
if (t == act.Target) continue;
if (act.CanGetTarget(act.Target, t))
subItems.Add(new Drawing3DCircularSector(t.Position, targetRadius * ratio, SColor, 3)
{
subItems.Add(new Drawing3DCircularSector(t.Position, targetRadius * ratio, SColor, 3)
{
IsFill = false,
});
}
IsFill = false,
});
}
}

Expand Down

0 comments on commit 4db689a

Please sign in to comment.