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

Commit

Permalink
refactor!: changed some framework.
Browse files Browse the repository at this point in the history
  • Loading branch information
ArchiDog1998 committed Jan 24, 2024
1 parent 481749e commit 5d8eb10
Show file tree
Hide file tree
Showing 35 changed files with 32,482 additions and 1,671 deletions.
4 changes: 2 additions & 2 deletions RotationSolver.Basic/Actions/ActionConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
/// <summary>
/// User config.
/// </summary>
public struct ActionConfig()
public class ActionConfig()
{
private bool _isEnable = true;
public bool IsEnable
{
readonly get => IBaseAction.ForceEnable || _isEnable;
get => IBaseAction.ForceEnable || _isEnable;
set => _isEnable = value;
}

Expand Down
5 changes: 2 additions & 3 deletions RotationSolver.Basic/Actions/ActionCooldownInfo.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
using ECommons.GameHelpers;
using FFXIVClientStructs.FFXIV.Client.Game;
using static Dalamud.Interface.Utility.Raii.ImRaii;

namespace RotationSolver.Basic.Actions;
public readonly struct ActionCooldownInfo
{
private readonly IBaseAction _action;
public byte CoolDownGroup { get; }

unsafe RecastDetail* CoolDownDetail => ActionManager.Instance()->GetRecastGroupDetail(CoolDownGroup - 1);
unsafe RecastDetail* CoolDownDetail => ActionIdHelper.GetCoolDownDetail(CoolDownGroup);

private unsafe float RecastTime => CoolDownDetail == null ? 0 : CoolDownDetail->Total;

Expand All @@ -25,7 +24,7 @@ public readonly struct ActionCooldownInfo
/// <summary>
///
/// </summary>
public unsafe bool IsCoolingDown => CoolDownDetail != null && CoolDownDetail->IsActive != 0;
public unsafe bool IsCoolingDown => ActionIdHelper.IsCoolingDown(CoolDownGroup);

private float RecastTimeRemain => RecastTime - RecastTimeElapsedRaw;

Expand Down
7 changes: 4 additions & 3 deletions RotationSolver.Basic/Actions/ActionSetting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
/// <summary>
/// Setting from the developer.
/// </summary>
public struct ActionSetting()
public class ActionSetting()
{
public bool TargetStatusFromSelf { get; set; } = true;
public StatusID[]? TargetStatus { get; set; } = null;
public StatusID[]? TargetStatusProvide { get; set; } = null;
public StatusID[]? TargetStatusNeed { get; set; } = null;
public Func<GameObject, bool> CanTarget { get; set; } = t => true;
public ActionID[]? ComboIdsNot { get; set; }

Expand All @@ -28,7 +29,7 @@ public struct ActionSetting()
private TargetType _type = TargetType.Big;
public TargetType TargetType
{
readonly get => IBaseAction.TargetOverride ?? _type;
get => IBaseAction.TargetOverride ?? _type;
set => _type = value;
}

Expand Down
157 changes: 108 additions & 49 deletions RotationSolver.Basic/Actions/ActionTargetInfo.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using Dalamud.Game.ClientState.Objects.SubKinds;
using ECommons.DalamudServices;
using ECommons.ExcelServices;
using ECommons.GameFunctions;
using ECommons.GameHelpers;
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using RotationSolver.Basic.Configuration;
using System.Linq;
using System.Text.RegularExpressions;

namespace RotationSolver.Basic.Actions;
Expand Down Expand Up @@ -93,17 +93,34 @@ private readonly unsafe bool CanUseTo(GameObject tar)

private readonly bool GeneralCheck(GameObject gameObject)
{
if (!Service.Config.GetValue(PluginConfigBool.TargetAllForFriendly)
&& gameObject.IsAlliance() && !gameObject.IsParty())
{
return false;
}

return CheckStatus(gameObject)
&& CheckTimeToKill(gameObject)
&& CheckResistance(gameObject);
}

private readonly bool CheckStatus(GameObject gameObject)
{
if (_action.Setting.TargetStatus == null || !_action.Config.ShouldCheckStatus) return true;
if (!_action.Config.ShouldCheckStatus) return true;

if (_action.Setting.TargetStatusProvide != null)
{
if (!gameObject.WillStatusEndGCD(_action.Config.StatusGcdCount, 0,
_action.Setting.TargetStatusFromSelf, _action.Setting.TargetStatusProvide)) return false;
}

if (_action.Setting.TargetStatusNeed != null)
{
if (gameObject.WillStatusEndGCD(_action.Config.StatusGcdCount, 0,
_action.Setting.TargetStatusFromSelf, _action.Setting.TargetStatusNeed)) return false;
}

return gameObject.WillStatusEndGCD(_action.Config.StatusGcdCount, 0,
_action.Setting.TargetStatusFromSelf, _action.Setting.TargetStatus);
return true;
}

private readonly bool CheckResistance(GameObject gameObject)
Expand Down Expand Up @@ -159,7 +176,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)

var targets = GetMostCanTargetObjects(canTargets, canAffects,
skipAoeCheck ? 0 : _action.Config.AoeCount);
var target = FindTargetByType(targets, _action.Setting.TargetType);
var target = FindTargetByType(targets, _action.Setting.TargetType, _action.Config.AutoHealRatio);
if (target == null) return null;

return new(target, [.. GetAffects(target, canAffects)], target.Position);
Expand Down Expand Up @@ -194,7 +211,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
return new(target, [..GetAffects(target, canAffects)], target.Position);
}

private TargetResult? FindTargetAreaMove(float range)
private readonly TargetResult? FindTargetAreaMove(float range)
{
if (Service.Config.GetValue(PluginConfigBool.MoveAreaActionFarthest))
{
Expand All @@ -220,7 +237,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
else
{
var availableCharas = DataCenter.AllTargets.Where(b => b.ObjectId != Player.Object.ObjectId);
var target = FindTargetByType(TargetFilter.GetObjectInRadius(availableCharas, range), TargetType.Move);
var target = FindTargetByType(TargetFilter.GetObjectInRadius(availableCharas, range), TargetType.Move, _action.Config.AutoHealRatio);
if (target == null) return null;
return new(target, [], target.Position);
}
Expand Down Expand Up @@ -281,7 +298,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
else
{
var effectRange = EffectRange;
var attackT = FindTargetByType(DataCenter.AllianceMembers.GetObjectInRadius(range + effectRange), TargetType.BeAttacked);
var attackT = FindTargetByType(DataCenter.AllianceMembers.GetObjectInRadius(range + effectRange), TargetType.BeAttacked, _action.Config.AutoHealRatio);

if (attackT == null)
{
Expand Down Expand Up @@ -408,7 +425,7 @@ private readonly bool CanGetTarget(GameObject target, GameObject subTarget)
#endregion

#region TargetFind
private readonly GameObject? FindTargetByType(IEnumerable<GameObject> gameObjects, TargetType type)
private static GameObject? FindTargetByType(IEnumerable<GameObject> gameObjects, TargetType type, float healRatio)
{
switch (type) // Filter the objects.
{
Expand All @@ -430,40 +447,20 @@ private readonly bool CanGetTarget(GameObject target, GameObject subTarget)
TargetType.Dispel => FindWeakenTarget(),
TargetType.Death => FindDeathPeople(),
TargetType.Move => FindTargetForMoving(),
TargetType.Heal => FindHealTarget(_action.Config.AutoHealRatio),
TargetType.Heal => FindHealTarget(healRatio),
TargetType.BeAttacked => FindBeAttackedTarget(),
TargetType.Interrupt => FindInterruptTarget(),
TargetType.Tank => FindTankTarget(),
TargetType.Melee => RandomMeleeTarget(gameObjects),
TargetType.Range => RandomRangeTarget(gameObjects),
TargetType.Magical => RandomMagicalTarget(gameObjects),
TargetType.Physical => RandomPhysicalTarget(gameObjects),
_ => FindHostile(),
};

GameObject? FindProvokeTarget()
{
var loc = Player.Object.Position;

return gameObjects.FirstOrDefault(target =>
{
//Removed the listed names.
IEnumerable<string> names = Array.Empty<string>();
if (OtherConfiguration.NoProvokeNames.TryGetValue(Svc.ClientState.TerritoryType, out var ns1))
names = names.Union(ns1);

if (names.Any(n => !string.IsNullOrEmpty(n) && new Regex(n).Match(target.Name.ToString()).Success)) return false;

//Target can move or two big and has a target
if ((target.GetObjectNPC()?.Unknown12 == 0 || target.HitboxRadius >= 5)
&& (target.TargetObject?.IsValid() ?? false))
{
//the target is not a tank role
if (Svc.Objects.SearchById(target.TargetObjectId) is BattleChara battle
&& !battle.IsJobCategory(JobRole.Tank)
&& (Vector3.Distance(target.Position, loc) > 5))
{
return true;
}
}
return false;
});
return gameObjects.FirstOrDefault(ObjectHelper.CanProvoke);
}

GameObject? FindDeathPeople()
Expand Down Expand Up @@ -683,31 +680,67 @@ private readonly bool CanGetTarget(GameObject target, GameObject subTarget)

GameObject? FindTankTarget()
{
return TargetFilter.GetJobCategory(gameObjects, JobRole.Tank)?.FirstOrDefault()
?? gameObjects.FirstOrDefault();
return RandomPickByJobs(gameObjects, JobRole.Tank)
?? RandomObject(gameObjects);
}
}
#endregion
}

public enum TargetType : byte
{
Tank,
internal static GameObject? RandomPhysicalTarget(IEnumerable<GameObject> tars)
{
return RandomPickByJobs(tars, Job.WAR, Job.GNB, Job.MNK, Job.SAM, Job.DRG, Job.MCH, Job.DNC)
?? RandomPickByJobs(tars, Job.PLD, Job.DRK, Job.NIN, Job.BRD, Job.RDM)
?? RandomObject(tars);
}

Interrupt,
internal static GameObject? RandomMagicalTarget(IEnumerable<GameObject> tars)
{
return RandomPickByJobs(tars, Job.SCH, Job.AST, Job.SGE, Job.BLM, Job.SMN)
?? RandomPickByJobs(tars, Job.PLD, Job.DRK, Job.NIN, Job.BRD, Job.RDM)
?? RandomObject(tars);
}

Provoke,
internal static GameObject? RandomRangeTarget(IEnumerable<GameObject> tars)
{
return RandomPickByJobs(tars, JobRole.RangedMagical, JobRole.RangedPhysical, JobRole.Melee)
?? RandomPickByJobs(tars, JobRole.Tank, JobRole.Healer)
?? RandomObject(tars);
}

Death,
internal static GameObject? RandomMeleeTarget(IEnumerable<GameObject> tars)
{
return RandomPickByJobs(tars, JobRole.Melee, JobRole.RangedMagical, JobRole.RangedPhysical)
?? RandomPickByJobs(tars, JobRole.Tank, JobRole.Healer)
?? RandomObject(tars);
}
private static GameObject? RandomPickByJobs(IEnumerable<GameObject> tars, params JobRole[] roles)
{
foreach (var role in roles)
{
var tar = RandomPickByJobs(tars, role.ToJobs());
if (tar != null) return tar;
}
return null;
}

Dispel,
private static GameObject? RandomPickByJobs(IEnumerable<GameObject> tars, params Job[] jobs)
{
var targets = tars.Where(t => t.IsJobs(jobs));
if (targets.Any()) return RandomObject(targets);

Move,
return null;
}

BeAttacked,
private static GameObject RandomObject(IEnumerable<GameObject> objs)
{
Random ran = new(DateTime.Now.Millisecond);
return objs.ElementAt(ran.Next(objs.Count()));
}

Heal,
#endregion
}

public enum TargetType : byte
{
/// <summary>
/// Find the target whose hit box is biggest.
/// </summary>
Expand Down Expand Up @@ -737,6 +770,32 @@ public enum TargetType : byte
/// Find the target whose max hp is lowest.
/// </summary>
LowMaxHP,


Interrupt,

Provoke,

Death,

Dispel,

Move,

BeAttacked,

Heal,

Tank,

Melee,

Range,

Physical,

Magical,

}

public readonly record struct TargetResult(GameObject Target, GameObject[] AffectedTargets, Vector3 Position);
14 changes: 9 additions & 5 deletions RotationSolver.Basic/Actions/BaseAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace RotationSolver.Basic.Actions;
public class BaseAction : IBaseAction
{
public TargetResult? Target { get; private set; } = null;
public TargetResult? PreviewTarget { get; private set; } = null;

public Action Action { get; }

Expand Down Expand Up @@ -70,7 +71,7 @@ public virtual unsafe uint MPNeed

public ActionConfig Config { get; set; }

public BaseAction(ActionID actionID, bool isDutyAction)
internal BaseAction(ActionID actionID, bool isDutyAction)
{
Action = Service.GetSheet<Action>().GetRow((uint)actionID)!;
TargetInfo = new(this);
Expand Down Expand Up @@ -105,15 +106,18 @@ public bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool sk
if (DataCenter.CurrentMp < MPNeed) return false;
if (Setting.IsFriendly && DataCenter.AverageTimeToKill < Config.TimeToKill) return false;

Target = TargetInfo.FindTarget(skipAoeCheck);
if (Target == null) return false;
PreviewTarget = TargetInfo.FindTarget(skipAoeCheck);
if (PreviewTarget == null) return false;
if (!IBaseAction.ActionPreview)
{
Target = PreviewTarget;
}

return true;
}

public unsafe bool Use()
{
ActionCate

if (!Target.HasValue) return false;

var target = Target.Value;
Expand Down
3 changes: 2 additions & 1 deletion RotationSolver.Basic/Actions/IBaseAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ public interface IBaseAction : IAction

Action Action { get; }
TargetResult? Target { get; }
TargetResult? PreviewTarget { get; }
ActionTargetInfo TargetInfo { get; }

ActionBasicInfo Info { get; }
ActionCooldownInfo Cooldown { get; }
ActionSetting Setting { get; set; }
ActionConfig Config { get; set; }
internal ActionConfig Config { get; set; }

bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipCombo = false, bool ignoreCastingCheck = false,
bool isEmpty = false, bool onLastAbility = false, bool ignoreClippingCheck = false, bool skipAoeCheck = false, byte gcdCountForAbility = 0);
Expand Down
Loading

0 comments on commit 5d8eb10

Please sign in to comment.