This repository has been archived by the owner on Aug 28, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor!: split the whole project to three libraries.
One is basic, one is rotation, the other is plugin.
- Loading branch information
1 parent
2af54a9
commit 7f1016a
Showing
304 changed files
with
29,250 additions
and
789 deletions.
There are no files selected for viewing
File renamed without changes.
138 changes: 138 additions & 0 deletions
138
RotationSolver.Basic/Actions/BaseAction/BaseAction_ActionInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
using Dalamud.Game.ClientState.Objects.Types; | ||
using FFXIVClientStructs.FFXIV.Client.Game; | ||
using RotationSolver.Basic; | ||
using RotationSolver.Data; | ||
using RotationSolver.Helpers; | ||
using RotationSolver.Rotations.CustomRotation; | ||
using RotationSolver.SigReplacers; | ||
|
||
namespace RotationSolver.Actions.BaseAction; | ||
|
||
public partial class BaseAction | ||
{ | ||
public float Range => ActionManager.GetActionRange(ID); | ||
|
||
public ActionID[] ComboIdsNot { private get; set; } = null; | ||
|
||
public ActionID[] ComboIds { private get; set; } = null; | ||
|
||
public StatusID[] StatusProvide { get; set; } = null; | ||
|
||
public virtual StatusID[] StatusNeed { get; set; } = null; | ||
|
||
public Func<BattleChara, bool> ActionCheck { get; set; } = null; | ||
|
||
public Func<BattleChara, bool> RotationCheck { get; set; } = null; | ||
|
||
private bool WillCooldown | ||
{ | ||
get | ||
{ | ||
if (!IsGeneralGCD && IsCoolingDown) | ||
{ | ||
if (IsRealGCD) | ||
{ | ||
if (!WillHaveOneChargeGCD()) return false; | ||
} | ||
else | ||
{ | ||
if ((ClassJobID)Service.Player.ClassJob.Id != ClassJobID.BlueMage | ||
&& ChoiceTarget != TargetFilter.FindTargetForMoving | ||
&& DataCenter.LastAction == (ActionID)AdjustedID) return false; | ||
|
||
if (!WillHaveOneCharge(DataCenter.AbilityRemain, false)) return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
|
||
public unsafe virtual bool CanUse(out IAction act, bool mustUse = false, bool emptyOrSkipCombo = false, bool skipDisable = false, uint gcdCountForAbility = 0, bool recordTarget = true) | ||
{ | ||
act = this; | ||
|
||
var player = Service.Player; | ||
if (player == null) return false; | ||
|
||
if (!skipDisable && !IsEnabled) return false; | ||
|
||
if (ConfigurationHelper.BadStatus.Contains(ActionManager.Instance()->GetActionStatus(ActionType.Spell, AdjustedID))) | ||
return false; | ||
|
||
if (!EnoughLevel) return false; | ||
|
||
if (player.CurrentMp < MPNeed) return false; | ||
|
||
if (StatusNeed != null) | ||
{ | ||
if (!player.HasStatus(true, StatusNeed)) return false; | ||
} | ||
|
||
if (StatusProvide != null && !mustUse) | ||
{ | ||
if (player.HasStatus(true, StatusProvide)) return false; | ||
} | ||
|
||
if (!WillCooldown) return false; | ||
|
||
if (!emptyOrSkipCombo) | ||
{ | ||
if (IsGeneralGCD) | ||
{ | ||
if (!CheckForCombo()) return false; | ||
} | ||
else | ||
{ | ||
if (RecastTimeRemain > DataCenter.WeaponRemain + DataCenter.WeaponTotal * gcdCountForAbility) | ||
return false; | ||
} | ||
} | ||
|
||
if (CastTime > 0 && DataCenter.IsMoving && | ||
!player.HasStatus(true, CustomRotation.Swiftcast.StatusProvide)) return false; | ||
|
||
if (!FindTarget(mustUse, out var target)) return false; | ||
|
||
if (ActionCheck != null && !ActionCheck(target)) return false; | ||
if (!skipDisable && RotationCheck != null && !RotationCheck(target)) return false; | ||
|
||
Target = target; | ||
if(recordTarget) _targetId = target.ObjectId; | ||
return true; | ||
} | ||
|
||
private bool CheckForCombo() | ||
{ | ||
if (ComboIdsNot != null) | ||
{ | ||
if (ComboIdsNot.Contains(DataCenter.LastComboAction)) return false; | ||
} | ||
|
||
var comboActions = _action.ActionCombo?.Row != 0 | ||
? new ActionID[] { (ActionID)_action.ActionCombo.Row } | ||
: new ActionID[0]; | ||
if (ComboIds != null) comboActions = comboActions.Union(ComboIds).ToArray(); | ||
|
||
if (comboActions.Length > 0) | ||
{ | ||
if (comboActions.Contains(DataCenter.LastComboAction)) | ||
{ | ||
if (DataCenter.ComboTime < DataCenter.WeaponRemain) return false; | ||
} | ||
else | ||
{ | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
public unsafe bool Use() | ||
{ | ||
var loc = new FFXIVClientStructs.FFXIV.Common.Math.Vector3() { X = _position.X, Y = _position.Y, Z = _position.Z }; | ||
|
||
return _action.TargetArea ? ActionManager.Instance()->UseActionLocation(ActionType.Spell, ID, Service.Player.ObjectId, &loc) : | ||
ActionManager.Instance()->UseAction(ActionType.Spell, AdjustedID, _targetId); | ||
} | ||
} |
128 changes: 128 additions & 0 deletions
128
RotationSolver.Basic/Actions/BaseAction/BaseAction_BasicInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
using FFXIVClientStructs.FFXIV.Client.Game; | ||
using RotationSolver.Basic; | ||
using RotationSolver.Data; | ||
using RotationSolver.Helpers; | ||
using Action = Lumina.Excel.GeneratedSheets.Action; | ||
|
||
namespace RotationSolver.Actions.BaseAction; | ||
|
||
public partial class BaseAction : IBaseAction | ||
{ | ||
|
||
public bool IsFriendly { get; } | ||
public bool IsEot { get; } | ||
Action _action; | ||
|
||
public bool ShouldEndSpecial { get; private set; } | ||
public bool IsTimeline { get; } = false; | ||
|
||
public Func<uint> GetDotGcdCount { private get; set; } | ||
|
||
/// <summary> | ||
/// EnoughLevel for using. | ||
/// </summary> | ||
public bool EnoughLevel => Service.Player.Level >= _action.ClassJobLevel; | ||
public string Name => _action.Name; | ||
|
||
public string Description => string.Empty; | ||
|
||
//public string CateName | ||
//{ | ||
// get | ||
// { | ||
// string result; | ||
|
||
// if (_isFriendly) | ||
// { | ||
// result = LocalizationManager.RightLang.Action_Friendly; | ||
// if (_isEot) | ||
// { | ||
// result += "Hot"; | ||
// } | ||
// } | ||
// else | ||
// { | ||
// result = LocalizationManager.RightLang.Action_Attack; | ||
|
||
// if (_isEot) | ||
// { | ||
// result += "Dot"; | ||
// } | ||
// } | ||
// result += "-" + (IsRealGCD ? "GCD" : LocalizationManager.RightLang.Timeline_Ability); | ||
// return result; | ||
// } | ||
//} | ||
public bool IsEnabled | ||
{ | ||
get => !Service.Config.DisabledActions.Contains(ID); | ||
set | ||
{ | ||
if (value) | ||
{ | ||
Service.Config.DisabledActions.Remove(ID); | ||
} | ||
else | ||
{ | ||
Service.Config.DisabledActions.Add(ID); | ||
} | ||
} | ||
} | ||
public uint ID => _action.RowId; | ||
public uint AdjustedID => (uint)Service.GetAdjustedActionId((ActionID)ID); | ||
|
||
public uint IconID => _action.Icon; | ||
|
||
private bool IsGeneralGCD { get; } | ||
|
||
public bool IsRealGCD { get; } | ||
|
||
private byte CoolDownGroup { get; } | ||
|
||
public unsafe float CastTime => ActionManager.GetAdjustedCastTime(ActionType.Spell, AdjustedID) / 1000f; | ||
|
||
public virtual EnemyPositional EnemyPositional | ||
{ | ||
get | ||
{ | ||
if (ConfigurationHelper.ActionPositional.TryGetValue((ActionID)ID, out var location)) | ||
{ | ||
return location.Pos; | ||
} | ||
return EnemyPositional.None; | ||
} | ||
} | ||
|
||
public virtual unsafe uint MPNeed | ||
{ | ||
get | ||
{ | ||
var mp = (uint)ActionManager.GetActionCost(ActionType.Spell, AdjustedID, 0, 0, 0, 0); | ||
if (mp < 100) return 0; | ||
return mp; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
/// <param name="actionID"></param> | ||
/// <param name="isFriendly">is a friendly or supporting action</param> | ||
/// <param name="shouldEndSpecial">end special after using it</param> | ||
/// <param name="isEot">is hot or dot action</param> | ||
/// <param name="isTimeline">should I put it to the timeline (heal and defense only)</param> | ||
public BaseAction(ActionID actionID, bool isFriendly = false, bool shouldEndSpecial = false, bool isEot = false, bool isTimeline = false) | ||
{ | ||
_action = Service.GetSheet<Action>().GetRow((uint)actionID); | ||
ShouldEndSpecial = shouldEndSpecial; | ||
IsFriendly = isFriendly; | ||
IsEot = isEot; | ||
IsTimeline = isTimeline; | ||
|
||
IsGeneralGCD = _action.IsGeneralGCD(); | ||
IsRealGCD = _action.IsRealGCD(); | ||
CoolDownGroup = _action.GetCoolDownGroup(); | ||
} | ||
|
||
public override string ToString() => Name; | ||
} |
90 changes: 90 additions & 0 deletions
90
RotationSolver.Basic/Actions/BaseAction/BaseAction_Cooldown.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
using FFXIVClientStructs.FFXIV.Client.Game; | ||
using RotationSolver.Basic; | ||
using RotationSolver.Helpers; | ||
using System; | ||
|
||
|
||
namespace RotationSolver.Actions.BaseAction; | ||
|
||
public partial class BaseAction | ||
{ | ||
public bool ElapsedAfterGCD(uint gcdCount = 0, uint abilityCount = 0) | ||
{ | ||
if (!IsCoolingDown) return false; | ||
var elapsed = RecastTimeElapsedOneCharge; | ||
return CooldownHelper.ElapsedAfterGCD(elapsed, gcdCount, abilityCount); | ||
} | ||
|
||
public bool ElapsedAfter(float time) | ||
{ | ||
if (!IsCoolingDown) return false; | ||
var elapsed = RecastTimeElapsedOneCharge; | ||
return CooldownHelper.ElapsedAfter(elapsed, time); | ||
} | ||
|
||
public bool WillHaveOneChargeGCD(uint gcdCount = 0, uint abilityCount = 0) | ||
{ | ||
if (HaveOneCharge) return true; | ||
var recast = RecastTimeRemainOneCharge; | ||
return CooldownHelper.RecastAfterGCD(recast, gcdCount, abilityCount); | ||
} | ||
|
||
public bool WillHaveOneCharge(float remain) => WillHaveOneCharge(remain, true); | ||
|
||
private bool WillHaveOneCharge(float remain, bool addWeaponRemain) | ||
{ | ||
if (HaveOneCharge) return true; | ||
var recast = RecastTimeRemainOneCharge; | ||
return CooldownHelper.RecastAfter(recast, remain, addWeaponRemain); | ||
} | ||
|
||
|
||
private unsafe RecastDetail* CoolDownDetail => ActionManager.Instance()->GetRecastGroupDetail(CoolDownGroup - 1); | ||
/// <summary> | ||
/// 复唱时间 | ||
/// </summary> | ||
private unsafe float RecastTime => CoolDownDetail->Total; | ||
|
||
/// <summary> | ||
/// 复唱经过时间 | ||
/// </summary> | ||
private unsafe float RecastTimeElapsed => CoolDownDetail->Elapsed; | ||
|
||
/// <summary> | ||
/// 是否正在冷却中 | ||
/// </summary> | ||
public unsafe bool IsCoolingDown => CoolDownDetail->IsActive != 0; | ||
|
||
/// <summary> | ||
/// 复唱剩余时间 | ||
/// </summary> | ||
private float RecastTimeRemain => RecastTime - RecastTimeElapsed; | ||
|
||
/// <summary> | ||
/// 技能的最大层数 | ||
/// </summary> | ||
public unsafe ushort MaxCharges => Math.Max(ActionManager.GetMaxCharges(AdjustedID, Service.Player.Level), (ushort)1); | ||
/// <summary> | ||
/// 是否起码有一层技能 | ||
/// </summary> | ||
private bool HaveOneCharge => IsCoolingDown ? RecastTimeElapsed >= RecastTimeOneCharge : true; | ||
/// <summary> | ||
/// 当前技能层数 | ||
/// </summary> | ||
public ushort CurrentCharges => IsCoolingDown ? (ushort)(RecastTimeElapsed / RecastTimeOneCharge) : MaxCharges; | ||
|
||
private float RecastTimeOneCharge => ActionManager.GetAdjustedRecastTime(ActionType.Spell, AdjustedID) / 1000f; | ||
|
||
/// <summary> | ||
/// 下一层转好的时间 | ||
/// </summary> | ||
private float RecastTimeRemainOneCharge => RecastTimeRemain % RecastTimeOneCharge; | ||
private float RecastTimeElapsedOneCharge => RecastTimeElapsed % RecastTimeOneCharge; | ||
|
||
#if DEBUG | ||
public bool HaveOneChargeDEBUG => HaveOneCharge; | ||
public float RecastTimeOneChargeDEBUG => RecastTimeOneCharge; | ||
public float RecastTimeElapsedDEBUG => RecastTimeElapsed; | ||
public float RecastTimeRemainDEBUG => RecastTimeRemain; | ||
#endif | ||
} |
Oops, something went wrong.