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

Commit

Permalink
refactor!: split the whole project to three libraries.
Browse files Browse the repository at this point in the history
One is basic, one is rotation, the other is plugin.
  • Loading branch information
ArchiDog1998 committed Mar 12, 2023
1 parent 2af54a9 commit 7f1016a
Show file tree
Hide file tree
Showing 304 changed files with 29,250 additions and 789 deletions.
File renamed without changes.
138 changes: 138 additions & 0 deletions RotationSolver.Basic/Actions/BaseAction/BaseAction_ActionInfo.cs
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 RotationSolver.Basic/Actions/BaseAction/BaseAction_BasicInfo.cs
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 RotationSolver.Basic/Actions/BaseAction/BaseAction_Cooldown.cs
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
}
Loading

0 comments on commit 7f1016a

Please sign in to comment.