mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
Merge pull request #2458 from Haselnussbomber/struct-enumerators
[API14] Use struct enumerators/types
This commit is contained in:
commit
ba0cf4c990
12 changed files with 424 additions and 344 deletions
|
|
@ -63,47 +63,37 @@ public interface IAetheryteEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class representing an aetheryte entry available to the game.
|
/// This struct represents an aetheryte entry available to the game.
|
||||||
/// </summary>
|
|
||||||
internal sealed class AetheryteEntry : IAetheryteEntry
|
|
||||||
{
|
|
||||||
private readonly TeleportInfo data;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="AetheryteEntry"/> class.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">Data read from the Aetheryte List.</param>
|
/// <param name="data">Data read from the Aetheryte List.</param>
|
||||||
internal AetheryteEntry(TeleportInfo data)
|
internal readonly struct AetheryteEntry(TeleportInfo data) : IAetheryteEntry
|
||||||
{
|
{
|
||||||
this.data = data;
|
/// <inheritdoc />
|
||||||
}
|
public uint AetheryteId => data.AetheryteId;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public uint AetheryteId => this.data.AetheryteId;
|
public uint TerritoryId => data.TerritoryId;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public uint TerritoryId => this.data.TerritoryId;
|
public byte SubIndex => data.SubIndex;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public byte SubIndex => this.data.SubIndex;
|
public byte Ward => data.Ward;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public byte Ward => this.data.Ward;
|
public byte Plot => data.Plot;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public byte Plot => this.data.Plot;
|
public uint GilCost => data.GilCost;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public uint GilCost => this.data.GilCost;
|
public bool IsFavourite => data.IsFavourite;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool IsFavourite => this.data.IsFavourite;
|
public bool IsSharedHouse => data.IsSharedHouse;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool IsSharedHouse => this.data.IsSharedHouse;
|
public bool IsApartment => data.IsApartment;
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool IsApartment => this.data.IsApartment;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public RowRef<Lumina.Excel.Sheets.Aetheryte> AetheryteData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Aetheryte>(this.AetheryteId);
|
public RowRef<Lumina.Excel.Sheets.Aetheryte> AetheryteData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Aetheryte>(this.AetheryteId);
|
||||||
|
|
|
||||||
|
|
@ -87,10 +87,7 @@ internal sealed partial class AetheryteList
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IEnumerator<IAetheryteEntry> GetEnumerator()
|
public IEnumerator<IAetheryteEntry> GetEnumerator()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < this.Length; i++)
|
return new Enumerator(this);
|
||||||
{
|
|
||||||
yield return this[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -98,4 +95,30 @@ internal sealed partial class AetheryteList
|
||||||
{
|
{
|
||||||
return this.GetEnumerator();
|
return this.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct Enumerator(AetheryteList aetheryteList) : IEnumerator<IAetheryteEntry>
|
||||||
|
{
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
public IAetheryteEntry Current { get; private set; }
|
||||||
|
|
||||||
|
object IEnumerator.Current => this.Current;
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (this.index == aetheryteList.Length) return false;
|
||||||
|
this.Current = aetheryteList[this.index];
|
||||||
|
this.index++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
this.index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ using Dalamud.Plugin.Services;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||||
|
|
||||||
|
using CSBuddy = FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy;
|
||||||
|
using CSBuddyMember = FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Buddy;
|
namespace Dalamud.Game.ClientState.Buddy;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -21,7 +24,7 @@ namespace Dalamud.Game.ClientState.Buddy;
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal sealed partial class BuddyList : IServiceType, IBuddyList
|
internal sealed partial class BuddyList : IServiceType, IBuddyList
|
||||||
{
|
{
|
||||||
private const uint InvalidObjectID = 0xE0000000;
|
private const uint InvalidEntityId = 0xE0000000;
|
||||||
|
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly ClientState clientState = Service<ClientState>.Get();
|
private readonly ClientState clientState = Service<ClientState>.Get();
|
||||||
|
|
@ -69,7 +72,7 @@ internal sealed partial class BuddyList : IServiceType, IBuddyList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy* BuddyListStruct => &UIState.Instance()->Buddy;
|
private unsafe CSBuddy* BuddyListStruct => &UIState.Instance()->Buddy;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IBuddyMember? this[int index]
|
public IBuddyMember? this[int index]
|
||||||
|
|
@ -82,37 +85,37 @@ internal sealed partial class BuddyList : IServiceType, IBuddyList
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public unsafe IntPtr GetCompanionBuddyMemberAddress()
|
public unsafe nint GetCompanionBuddyMemberAddress()
|
||||||
{
|
{
|
||||||
return (IntPtr)this.BuddyListStruct->CompanionInfo.Companion;
|
return (nint)this.BuddyListStruct->CompanionInfo.Companion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public unsafe IntPtr GetPetBuddyMemberAddress()
|
public unsafe nint GetPetBuddyMemberAddress()
|
||||||
{
|
{
|
||||||
return (IntPtr)this.BuddyListStruct->PetInfo.Pet;
|
return (nint)this.BuddyListStruct->PetInfo.Pet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public unsafe IntPtr GetBattleBuddyMemberAddress(int index)
|
public unsafe nint GetBattleBuddyMemberAddress(int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= 3)
|
if (index < 0 || index >= 3)
|
||||||
return IntPtr.Zero;
|
return 0;
|
||||||
|
|
||||||
return (IntPtr)Unsafe.AsPointer(ref this.BuddyListStruct->BattleBuddies[index]);
|
return (nint)Unsafe.AsPointer(ref this.BuddyListStruct->BattleBuddies[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IBuddyMember? CreateBuddyMemberReference(IntPtr address)
|
public unsafe IBuddyMember? CreateBuddyMemberReference(nint address)
|
||||||
{
|
{
|
||||||
|
if (address == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (this.clientState.LocalContentId == 0)
|
if (this.clientState.LocalContentId == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (address == IntPtr.Zero)
|
var buddy = new BuddyMember((CSBuddyMember*)address);
|
||||||
return null;
|
if (buddy.EntityId == InvalidEntityId)
|
||||||
|
|
||||||
var buddy = new BuddyMember(address);
|
|
||||||
if (buddy.ObjectId == InvalidObjectID)
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return buddy;
|
return buddy;
|
||||||
|
|
@ -130,12 +133,35 @@ internal sealed partial class BuddyList
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IEnumerator<IBuddyMember> GetEnumerator()
|
public IEnumerator<IBuddyMember> GetEnumerator()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < this.Length; i++)
|
return new Enumerator(this);
|
||||||
{
|
|
||||||
yield return this[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||||
|
|
||||||
|
private struct Enumerator(BuddyList buddyList) : IEnumerator<IBuddyMember>
|
||||||
|
{
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
public IBuddyMember Current { get; private set; }
|
||||||
|
|
||||||
|
object IEnumerator.Current => this.Current;
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (this.index == buddyList.Length) return false;
|
||||||
|
this.Current = buddyList[this.index];
|
||||||
|
this.index++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
this.index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,24 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
using Dalamud.Data;
|
using Dalamud.Data;
|
||||||
using Dalamud.Game.ClientState.Objects;
|
using Dalamud.Game.ClientState.Objects;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
|
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
|
|
||||||
|
using CSBuddyMember = FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Buddy;
|
namespace Dalamud.Game.ClientState.Buddy;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface representing represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties.
|
/// Interface representing represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBuddyMember
|
public interface IBuddyMember : IEquatable<IBuddyMember>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the address of the buddy in memory.
|
/// Gets the address of the buddy in memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IntPtr Address { get; }
|
nint Address { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the object ID of this buddy.
|
/// Gets the object ID of this buddy.
|
||||||
|
|
@ -67,42 +71,34 @@ public interface IBuddyMember
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties.
|
/// This struct represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal unsafe class BuddyMember : IBuddyMember
|
/// <param name="ptr">A pointer to the BuddyMember.</param>
|
||||||
|
internal readonly unsafe struct BuddyMember(CSBuddyMember* ptr) : IBuddyMember
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly ObjectTable objectTable = Service<ObjectTable>.Get();
|
private readonly ObjectTable objectTable = Service<ObjectTable>.Get();
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Initializes a new instance of the <see cref="BuddyMember"/> class.
|
public nint Address => (nint)ptr;
|
||||||
/// </summary>
|
|
||||||
/// <param name="address">Buddy address.</param>
|
|
||||||
internal BuddyMember(IntPtr address)
|
|
||||||
{
|
|
||||||
this.Address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IntPtr Address { get; }
|
public uint ObjectId => this.EntityId;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public uint ObjectId => this.Struct->EntityId;
|
public uint EntityId => ptr->EntityId;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public uint EntityId => this.Struct->EntityId;
|
public IGameObject? GameObject => this.objectTable.SearchById(this.EntityId);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IGameObject? GameObject => this.objectTable.SearchById(this.ObjectId);
|
public uint CurrentHP => ptr->CurrentHealth;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public uint CurrentHP => this.Struct->CurrentHealth;
|
public uint MaxHP => ptr->MaxHealth;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public uint MaxHP => this.Struct->MaxHealth;
|
public uint DataID => ptr->DataId;
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public uint DataID => this.Struct->DataId;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public RowRef<Lumina.Excel.Sheets.Mount> MountData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Mount>(this.DataID);
|
public RowRef<Lumina.Excel.Sheets.Mount> MountData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Mount>(this.DataID);
|
||||||
|
|
@ -113,5 +109,25 @@ internal unsafe class BuddyMember : IBuddyMember
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public RowRef<Lumina.Excel.Sheets.DawnGrowMember> TrustData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.DawnGrowMember>(this.DataID);
|
public RowRef<Lumina.Excel.Sheets.DawnGrowMember> TrustData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.DawnGrowMember>(this.DataID);
|
||||||
|
|
||||||
private FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember* Struct => (FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember*)this.Address;
|
public static bool operator ==(BuddyMember x, BuddyMember y) => x.Equals(y);
|
||||||
|
|
||||||
|
public static bool operator !=(BuddyMember x, BuddyMember y) => !(x == y);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Equals(IBuddyMember? other)
|
||||||
|
{
|
||||||
|
return this.EntityId == other.EntityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals([NotNullWhen(true)] object? obj)
|
||||||
|
{
|
||||||
|
return obj is BuddyMember fate && this.Equals(fate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return this.EntityId.GetHashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using Dalamud.Data;
|
using Dalamud.Data;
|
||||||
|
|
@ -6,10 +7,12 @@ using Dalamud.Memory;
|
||||||
|
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
|
|
||||||
|
using CSFateContext = FFXIVClientStructs.FFXIV.Client.Game.Fate.FateContext;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Fates;
|
namespace Dalamud.Game.ClientState.Fates;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface representing an fate entry that can be seen in the current area.
|
/// Interface representing a fate entry that can be seen in the current area.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IFate : IEquatable<IFate>
|
public interface IFate : IEquatable<IFate>
|
||||||
{
|
{
|
||||||
|
|
@ -111,133 +114,96 @@ public interface IFate : IEquatable<IFate>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the address of this Fate in memory.
|
/// Gets the address of this Fate in memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IntPtr Address { get; }
|
nint Address { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents an FFXIV Fate.
|
/// This struct represents a Fate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal unsafe partial class Fate
|
/// <param name="ptr">A pointer to the FateContext.</param>
|
||||||
{
|
internal readonly unsafe struct Fate(CSFateContext* ptr) : IFate
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="Fate"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="address">The address of this fate in memory.</param>
|
|
||||||
internal Fate(IntPtr address)
|
|
||||||
{
|
|
||||||
this.Address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IntPtr Address { get; }
|
|
||||||
|
|
||||||
private FFXIVClientStructs.FFXIV.Client.Game.Fate.FateContext* Struct => (FFXIVClientStructs.FFXIV.Client.Game.Fate.FateContext*)this.Address;
|
|
||||||
|
|
||||||
public static bool operator ==(Fate fate1, Fate fate2)
|
|
||||||
{
|
|
||||||
if (fate1 is null || fate2 is null)
|
|
||||||
return Equals(fate1, fate2);
|
|
||||||
|
|
||||||
return fate1.Equals(fate2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(Fate fate1, Fate fate2) => !(fate1 == fate2);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this Fate is still valid in memory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fate">The fate to check.</param>
|
|
||||||
/// <returns>True or false.</returns>
|
|
||||||
public static bool IsValid(Fate fate)
|
|
||||||
{
|
|
||||||
var clientState = Service<ClientState>.GetNullable();
|
|
||||||
|
|
||||||
if (fate == null || clientState == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (clientState.LocalContentId == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this actor is still valid in memory.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True or false.</returns>
|
|
||||||
public bool IsValid() => IsValid(this);
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
bool IEquatable<IFate>.Equals(IFate other) => this.FateId == other?.FateId;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override bool Equals(object obj) => ((IEquatable<IFate>)this).Equals(obj as IFate);
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override int GetHashCode() => this.FateId.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This class represents an FFXIV Fate.
|
|
||||||
/// </summary>
|
|
||||||
internal unsafe partial class Fate : IFate
|
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ushort FateId => this.Struct->FateId;
|
public nint Address => (nint)ptr;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ushort FateId => ptr->FateId;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public RowRef<Lumina.Excel.Sheets.Fate> GameData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Fate>(this.FateId);
|
public RowRef<Lumina.Excel.Sheets.Fate> GameData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Fate>(this.FateId);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public int StartTimeEpoch => this.Struct->StartTimeEpoch;
|
public int StartTimeEpoch => ptr->StartTimeEpoch;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public short Duration => this.Struct->Duration;
|
public short Duration => ptr->Duration;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public long TimeRemaining => this.StartTimeEpoch + this.Duration - DateTimeOffset.Now.ToUnixTimeSeconds();
|
public long TimeRemaining => this.StartTimeEpoch + this.Duration - DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public SeString Name => MemoryHelper.ReadSeString(&this.Struct->Name);
|
public SeString Name => MemoryHelper.ReadSeString(&ptr->Name);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public SeString Description => MemoryHelper.ReadSeString(&this.Struct->Description);
|
public SeString Description => MemoryHelper.ReadSeString(&ptr->Description);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public SeString Objective => MemoryHelper.ReadSeString(&this.Struct->Objective);
|
public SeString Objective => MemoryHelper.ReadSeString(&ptr->Objective);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public FateState State => (FateState)this.Struct->State;
|
public FateState State => (FateState)ptr->State;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public byte HandInCount => this.Struct->HandInCount;
|
public byte HandInCount => ptr->HandInCount;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public byte Progress => this.Struct->Progress;
|
public byte Progress => ptr->Progress;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool HasBonus => this.Struct->IsBonus;
|
public bool HasBonus => ptr->IsBonus;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint IconId => this.Struct->IconId;
|
public uint IconId => ptr->IconId;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public byte Level => this.Struct->Level;
|
public byte Level => ptr->Level;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public byte MaxLevel => this.Struct->MaxLevel;
|
public byte MaxLevel => ptr->MaxLevel;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Vector3 Position => this.Struct->Location;
|
public Vector3 Position => ptr->Location;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public float Radius => this.Struct->Radius;
|
public float Radius => ptr->Radius;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint MapIconId => this.Struct->MapIconId;
|
public uint MapIconId => ptr->MapIconId;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the territory this <see cref="Fate"/> is located in.
|
/// Gets the territory this <see cref="Fate"/> is located in.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RowRef<Lumina.Excel.Sheets.TerritoryType> TerritoryType => LuminaUtils.CreateRef<Lumina.Excel.Sheets.TerritoryType>(this.Struct->MapMarkers[0].MapMarkerData.TerritoryTypeId);
|
public RowRef<Lumina.Excel.Sheets.TerritoryType> TerritoryType => LuminaUtils.CreateRef<Lumina.Excel.Sheets.TerritoryType>(ptr->MapMarkers[0].MapMarkerData.TerritoryTypeId);
|
||||||
|
|
||||||
|
public static bool operator ==(Fate x, Fate y) => x.Equals(y);
|
||||||
|
|
||||||
|
public static bool operator !=(Fate x, Fate y) => !(x == y);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Equals(IFate? other)
|
||||||
|
{
|
||||||
|
return this.FateId == other.FateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals([NotNullWhen(true)] object? obj)
|
||||||
|
{
|
||||||
|
return obj is Fate fate && this.Equals(fate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return this.FateId.GetHashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using Dalamud.IoC;
|
||||||
using Dalamud.IoC.Internal;
|
using Dalamud.IoC.Internal;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
|
||||||
|
using CSFateContext = FFXIVClientStructs.FFXIV.Client.Game.Fate.FateContext;
|
||||||
using CSFateManager = FFXIVClientStructs.FFXIV.Client.Game.Fate.FateManager;
|
using CSFateManager = FFXIVClientStructs.FFXIV.Client.Game.Fate.FateManager;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Fates;
|
namespace Dalamud.Game.ClientState.Fates;
|
||||||
|
|
@ -25,7 +26,7 @@ internal sealed partial class FateTable : IServiceType, IFateTable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public unsafe IntPtr Address => (nint)CSFateManager.Instance();
|
public unsafe nint Address => (nint)CSFateManager.Instance();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public unsafe int Length
|
public unsafe int Length
|
||||||
|
|
@ -72,30 +73,29 @@ internal sealed partial class FateTable : IServiceType, IFateTable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public unsafe IntPtr GetFateAddress(int index)
|
public unsafe nint GetFateAddress(int index)
|
||||||
{
|
{
|
||||||
if (index >= this.Length)
|
if (index >= this.Length)
|
||||||
return IntPtr.Zero;
|
return 0;
|
||||||
|
|
||||||
var fateManager = CSFateManager.Instance();
|
var fateManager = CSFateManager.Instance();
|
||||||
if (fateManager == null)
|
if (fateManager == null)
|
||||||
return IntPtr.Zero;
|
return 0;
|
||||||
|
|
||||||
return (IntPtr)fateManager->Fates[index].Value;
|
return (nint)fateManager->Fates[index].Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IFate? CreateFateReference(IntPtr offset)
|
public unsafe IFate? CreateFateReference(IntPtr address)
|
||||||
{
|
{
|
||||||
var clientState = Service<ClientState>.Get();
|
if (address == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var clientState = Service<ClientState>.Get();
|
||||||
if (clientState.LocalContentId == 0)
|
if (clientState.LocalContentId == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (offset == IntPtr.Zero)
|
return new Fate((CSFateContext*)address);
|
||||||
return null;
|
|
||||||
|
|
||||||
return new Fate(offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,12 +110,35 @@ internal sealed partial class FateTable
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IEnumerator<IFate> GetEnumerator()
|
public IEnumerator<IFate> GetEnumerator()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < this.Length; i++)
|
return new Enumerator(this);
|
||||||
{
|
|
||||||
yield return this[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||||
|
|
||||||
|
private struct Enumerator(FateTable fateTable) : IEnumerator<IFate>
|
||||||
|
{
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
public IFate Current { get; private set; }
|
||||||
|
|
||||||
|
object IEnumerator.Current => this.Current;
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (this.index == fateTable.Length) return false;
|
||||||
|
this.Current = fateTable[this.index];
|
||||||
|
this.index++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
this.index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@ using Dalamud.Utility;
|
||||||
|
|
||||||
using FFXIVClientStructs.Interop;
|
using FFXIVClientStructs.Interop;
|
||||||
|
|
||||||
using Microsoft.Extensions.ObjectPool;
|
|
||||||
|
|
||||||
using CSGameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
|
using CSGameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
|
||||||
using CSGameObjectManager = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObjectManager;
|
using CSGameObjectManager = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObjectManager;
|
||||||
|
|
||||||
|
|
@ -34,8 +32,6 @@ internal sealed partial class ObjectTable : IServiceType, IObjectTable
|
||||||
private readonly ClientState clientState;
|
private readonly ClientState clientState;
|
||||||
private readonly CachedEntry[] cachedObjectTable;
|
private readonly CachedEntry[] cachedObjectTable;
|
||||||
|
|
||||||
private readonly Enumerator?[] frameworkThreadEnumerators = new Enumerator?[4];
|
|
||||||
|
|
||||||
[ServiceManager.ServiceConstructor]
|
[ServiceManager.ServiceConstructor]
|
||||||
private unsafe ObjectTable(ClientState clientState)
|
private unsafe ObjectTable(ClientState clientState)
|
||||||
{
|
{
|
||||||
|
|
@ -47,9 +43,6 @@ internal sealed partial class ObjectTable : IServiceType, IObjectTable
|
||||||
this.cachedObjectTable = new CachedEntry[objectTableLength];
|
this.cachedObjectTable = new CachedEntry[objectTableLength];
|
||||||
for (var i = 0; i < this.cachedObjectTable.Length; i++)
|
for (var i = 0; i < this.cachedObjectTable.Length; i++)
|
||||||
this.cachedObjectTable[i] = new(nativeObjectTable.GetPointer(i));
|
this.cachedObjectTable[i] = new(nativeObjectTable.GetPointer(i));
|
||||||
|
|
||||||
for (var i = 0; i < this.frameworkThreadEnumerators.Length; i++)
|
|
||||||
this.frameworkThreadEnumerators[i] = new(this, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -239,30 +232,14 @@ internal sealed partial class ObjectTable
|
||||||
public IEnumerator<IGameObject> GetEnumerator()
|
public IEnumerator<IGameObject> GetEnumerator()
|
||||||
{
|
{
|
||||||
ThreadSafety.AssertMainThread();
|
ThreadSafety.AssertMainThread();
|
||||||
|
return new Enumerator(this);
|
||||||
// If we're on the framework thread, see if there's an already allocated enumerator available for use.
|
|
||||||
foreach (ref var x in this.frameworkThreadEnumerators.AsSpan())
|
|
||||||
{
|
|
||||||
if (x is not null)
|
|
||||||
{
|
|
||||||
var t = x;
|
|
||||||
x = null;
|
|
||||||
t.Reset();
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No reusable enumerator is available; allocate a new temporary one.
|
|
||||||
return new Enumerator(this, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||||
|
|
||||||
private sealed class Enumerator(ObjectTable owner, int slotId) : IEnumerator<IGameObject>, IResettable
|
private struct Enumerator(ObjectTable owner) : IEnumerator<IGameObject>
|
||||||
{
|
{
|
||||||
private ObjectTable? owner = owner;
|
|
||||||
|
|
||||||
private int index = -1;
|
private int index = -1;
|
||||||
|
|
||||||
public IGameObject Current { get; private set; } = null!;
|
public IGameObject Current { get; private set; } = null!;
|
||||||
|
|
@ -274,7 +251,7 @@ internal sealed partial class ObjectTable
|
||||||
if (this.index == objectTableLength)
|
if (this.index == objectTableLength)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var cache = this.owner!.cachedObjectTable.AsSpan();
|
var cache = owner.cachedObjectTable.AsSpan();
|
||||||
for (this.index++; this.index < objectTableLength; this.index++)
|
for (this.index++; this.index < objectTableLength; this.index++)
|
||||||
{
|
{
|
||||||
if (cache[this.index].Update() is { } ao)
|
if (cache[this.index].Update() is { } ao)
|
||||||
|
|
@ -291,17 +268,6 @@ internal sealed partial class ObjectTable
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (this.owner is not { } o)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (slotId != -1)
|
|
||||||
o.frameworkThreadEnumerators[slotId] = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryReset()
|
|
||||||
{
|
|
||||||
this.Reset();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using Dalamud.IoC.Internal;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
|
||||||
using CSGroupManager = FFXIVClientStructs.FFXIV.Client.Game.Group.GroupManager;
|
using CSGroupManager = FFXIVClientStructs.FFXIV.Client.Game.Group.GroupManager;
|
||||||
|
using CSPartyMember = FFXIVClientStructs.FFXIV.Client.Game.Group.PartyMember;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Party;
|
namespace Dalamud.Game.ClientState.Party;
|
||||||
|
|
||||||
|
|
@ -42,20 +43,20 @@ internal sealed unsafe partial class PartyList : IServiceType, IPartyList
|
||||||
public bool IsAlliance => this.GroupManagerStruct->MainGroup.AllianceFlags > 0;
|
public bool IsAlliance => this.GroupManagerStruct->MainGroup.AllianceFlags > 0;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public unsafe IntPtr GroupManagerAddress => (nint)CSGroupManager.Instance();
|
public unsafe nint GroupManagerAddress => (nint)CSGroupManager.Instance();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IntPtr GroupListAddress => (IntPtr)Unsafe.AsPointer(ref GroupManagerStruct->MainGroup.PartyMembers[0]);
|
public nint GroupListAddress => (nint)Unsafe.AsPointer(ref GroupManagerStruct->MainGroup.PartyMembers[0]);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IntPtr AllianceListAddress => (IntPtr)Unsafe.AsPointer(ref this.GroupManagerStruct->MainGroup.AllianceMembers[0]);
|
public nint AllianceListAddress => (nint)Unsafe.AsPointer(ref this.GroupManagerStruct->MainGroup.AllianceMembers[0]);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public long PartyId => this.GroupManagerStruct->MainGroup.PartyId;
|
public long PartyId => this.GroupManagerStruct->MainGroup.PartyId;
|
||||||
|
|
||||||
private static int PartyMemberSize { get; } = Marshal.SizeOf<FFXIVClientStructs.FFXIV.Client.Game.Group.PartyMember>();
|
private static int PartyMemberSize { get; } = Marshal.SizeOf<CSPartyMember>();
|
||||||
|
|
||||||
private FFXIVClientStructs.FFXIV.Client.Game.Group.GroupManager* GroupManagerStruct => (FFXIVClientStructs.FFXIV.Client.Game.Group.GroupManager*)this.GroupManagerAddress;
|
private CSGroupManager* GroupManagerStruct => (CSGroupManager*)this.GroupManagerAddress;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IPartyMember? this[int index]
|
public IPartyMember? this[int index]
|
||||||
|
|
@ -80,45 +81,45 @@ internal sealed unsafe partial class PartyList : IServiceType, IPartyList
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IntPtr GetPartyMemberAddress(int index)
|
public nint GetPartyMemberAddress(int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= GroupLength)
|
if (index < 0 || index >= GroupLength)
|
||||||
return IntPtr.Zero;
|
return 0;
|
||||||
|
|
||||||
return this.GroupListAddress + (index * PartyMemberSize);
|
return this.GroupListAddress + (index * PartyMemberSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IPartyMember? CreatePartyMemberReference(IntPtr address)
|
public IPartyMember? CreatePartyMemberReference(nint address)
|
||||||
{
|
{
|
||||||
if (this.clientState.LocalContentId == 0)
|
if (this.clientState.LocalContentId == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (address == IntPtr.Zero)
|
if (address == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new PartyMember(address);
|
return new PartyMember((CSPartyMember*)address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IntPtr GetAllianceMemberAddress(int index)
|
public nint GetAllianceMemberAddress(int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= AllianceLength)
|
if (index < 0 || index >= AllianceLength)
|
||||||
return IntPtr.Zero;
|
return 0;
|
||||||
|
|
||||||
return this.AllianceListAddress + (index * PartyMemberSize);
|
return this.AllianceListAddress + (index * PartyMemberSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IPartyMember? CreateAllianceMemberReference(IntPtr address)
|
public IPartyMember? CreateAllianceMemberReference(nint address)
|
||||||
{
|
{
|
||||||
if (this.clientState.LocalContentId == 0)
|
if (this.clientState.LocalContentId == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (address == IntPtr.Zero)
|
if (address == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new PartyMember(address);
|
return new PartyMember((CSPartyMember*)address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,18 +134,44 @@ internal sealed partial class PartyList
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IEnumerator<IPartyMember> GetEnumerator()
|
public IEnumerator<IPartyMember> GetEnumerator()
|
||||||
{
|
{
|
||||||
// Normally using Length results in a recursion crash, however we know the party size via ptr.
|
return new Enumerator(this);
|
||||||
for (var i = 0; i < this.Length; i++)
|
|
||||||
{
|
|
||||||
var member = this[i];
|
|
||||||
|
|
||||||
if (member == null)
|
|
||||||
break;
|
|
||||||
|
|
||||||
yield return member;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||||
|
|
||||||
|
private struct Enumerator(PartyList partyList) : IEnumerator<IPartyMember>
|
||||||
|
{
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
public IPartyMember Current { get; private set; }
|
||||||
|
|
||||||
|
object IEnumerator.Current => this.Current;
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (this.index == partyList.Length) return false;
|
||||||
|
|
||||||
|
for (; this.index < partyList.Length; this.index++)
|
||||||
|
{
|
||||||
|
var partyMember = partyList[this.index];
|
||||||
|
if (partyMember != null)
|
||||||
|
{
|
||||||
|
this.Current = partyMember;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
this.index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,27 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
using Dalamud.Data;
|
using Dalamud.Data;
|
||||||
using Dalamud.Game.ClientState.Objects;
|
using Dalamud.Game.ClientState.Objects;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Dalamud.Game.ClientState.Statuses;
|
using Dalamud.Game.ClientState.Statuses;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Memory;
|
|
||||||
|
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
|
|
||||||
|
using CSPartyMember = FFXIVClientStructs.FFXIV.Client.Game.Group.PartyMember;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Party;
|
namespace Dalamud.Game.ClientState.Party;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface representing a party member.
|
/// Interface representing a party member.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IPartyMember
|
public interface IPartyMember : IEquatable<IPartyMember>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the address of this party member in memory.
|
/// Gets the address of this party member in memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IntPtr Address { get; }
|
nint Address { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of buffs or debuffs applied to this party member.
|
/// Gets a list of buffs or debuffs applied to this party member.
|
||||||
|
|
@ -108,69 +109,81 @@ public interface IPartyMember
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents a party member in the group manager.
|
/// This struct represents a party member in the group manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal unsafe class PartyMember : IPartyMember
|
/// <param name="ptr">A pointer to the PartyMember.</param>
|
||||||
|
internal unsafe readonly struct PartyMember(CSPartyMember* ptr) : IPartyMember
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Initializes a new instance of the <see cref="PartyMember"/> class.
|
public nint Address => (nint)ptr;
|
||||||
/// </summary>
|
|
||||||
/// <param name="address">Address of the party member.</param>
|
|
||||||
internal PartyMember(IntPtr address)
|
|
||||||
{
|
|
||||||
this.Address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IntPtr Address { get; }
|
public StatusList Statuses => new(&ptr->StatusManager);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public StatusList Statuses => new(&this.Struct->StatusManager);
|
public Vector3 Position => ptr->Position;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Vector3 Position => this.Struct->Position;
|
public long ContentId => (long)ptr->ContentId;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public long ContentId => (long)this.Struct->ContentId;
|
public uint ObjectId => ptr->EntityId;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint ObjectId => this.Struct->EntityId;
|
public uint EntityId => ptr->EntityId;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public uint EntityId => this.Struct->EntityId;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IGameObject? GameObject => Service<ObjectTable>.Get().SearchById(this.EntityId);
|
public IGameObject? GameObject => Service<ObjectTable>.Get().SearchById(this.EntityId);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint CurrentHP => this.Struct->CurrentHP;
|
public uint CurrentHP => ptr->CurrentHP;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint MaxHP => this.Struct->MaxHP;
|
public uint MaxHP => ptr->MaxHP;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ushort CurrentMP => this.Struct->CurrentMP;
|
public ushort CurrentMP => ptr->CurrentMP;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ushort MaxMP => this.Struct->MaxMP;
|
public ushort MaxMP => ptr->MaxMP;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public RowRef<Lumina.Excel.Sheets.TerritoryType> Territory => LuminaUtils.CreateRef<Lumina.Excel.Sheets.TerritoryType>(this.Struct->TerritoryType);
|
public RowRef<Lumina.Excel.Sheets.TerritoryType> Territory => LuminaUtils.CreateRef<Lumina.Excel.Sheets.TerritoryType>(ptr->TerritoryType);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public RowRef<Lumina.Excel.Sheets.World> World => LuminaUtils.CreateRef<Lumina.Excel.Sheets.World>(this.Struct->HomeWorld);
|
public RowRef<Lumina.Excel.Sheets.World> World => LuminaUtils.CreateRef<Lumina.Excel.Sheets.World>(ptr->HomeWorld);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public SeString Name => SeString.Parse(this.Struct->Name);
|
public SeString Name => SeString.Parse(ptr->Name);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public byte Sex => this.Struct->Sex;
|
public byte Sex => ptr->Sex;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public RowRef<Lumina.Excel.Sheets.ClassJob> ClassJob => LuminaUtils.CreateRef<Lumina.Excel.Sheets.ClassJob>(this.Struct->ClassJob);
|
public RowRef<Lumina.Excel.Sheets.ClassJob> ClassJob => LuminaUtils.CreateRef<Lumina.Excel.Sheets.ClassJob>(ptr->ClassJob);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public byte Level => this.Struct->Level;
|
public byte Level => ptr->Level;
|
||||||
|
|
||||||
private FFXIVClientStructs.FFXIV.Client.Game.Group.PartyMember* Struct => (FFXIVClientStructs.FFXIV.Client.Game.Group.PartyMember*)this.Address;
|
public static bool operator ==(PartyMember x, PartyMember y) => x.Equals(y);
|
||||||
|
|
||||||
|
public static bool operator !=(PartyMember x, PartyMember y) => !(x == y);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Equals(IPartyMember? other)
|
||||||
|
{
|
||||||
|
return this.EntityId == other.EntityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals([NotNullWhen(true)] object? obj)
|
||||||
|
{
|
||||||
|
return obj is PartyMember fate && this.Equals(fate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return this.EntityId.GetHashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,49 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
using Dalamud.Data;
|
using Dalamud.Data;
|
||||||
using Dalamud.Game.ClientState.Objects;
|
using Dalamud.Game.ClientState.Objects;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
|
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
|
|
||||||
|
using CSStatus = FFXIVClientStructs.FFXIV.Client.Game.Status;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Statuses;
|
namespace Dalamud.Game.ClientState.Statuses;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents a status effect an actor is afflicted by.
|
/// Interface representing a status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe class Status
|
public interface IStatus : IEquatable<IStatus>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="Status"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="address">Status address.</param>
|
|
||||||
internal Status(IntPtr address)
|
|
||||||
{
|
|
||||||
this.Address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the address of the status in memory.
|
/// Gets the address of the status in memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IntPtr Address { get; }
|
nint Address { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the status ID of this status.
|
/// Gets the status ID of this status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint StatusId => this.Struct->StatusId;
|
uint StatusId { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the GameData associated with this status.
|
/// Gets the GameData associated with this status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RowRef<Lumina.Excel.Sheets.Status> GameData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Status>(this.Struct->StatusId);
|
RowRef<Lumina.Excel.Sheets.Status> GameData { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the parameter value of the status.
|
/// Gets the parameter value of the status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort Param => this.Struct->Param;
|
ushort Param { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the stack count of this status.
|
|
||||||
/// Only valid if this is a non-food status.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete($"Replaced with {nameof(Param)}", true)]
|
|
||||||
public byte StackCount => (byte)this.Struct->Param;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the time remaining of this status.
|
/// Gets the time remaining of this status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float RemainingTime => this.Struct->RemainingTime;
|
float RemainingTime { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the source ID of this status.
|
/// Gets the source ID of this status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint SourceId => this.Struct->SourceObject.ObjectId;
|
uint SourceId { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the source actor associated with this status.
|
/// Gets the source actor associated with this status.
|
||||||
|
|
@ -63,7 +51,55 @@ public unsafe class Status
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This iterates the actor table, it should be used with care.
|
/// This iterates the actor table, it should be used with care.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
IGameObject? SourceObject { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This struct represents a status effect an actor is afflicted by.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ptr">A pointer to the Status.</param>
|
||||||
|
internal unsafe readonly struct Status(CSStatus* ptr) : IStatus
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public nint Address => (nint)ptr;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public uint StatusId => ptr->StatusId;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public RowRef<Lumina.Excel.Sheets.Status> GameData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Status>(ptr->StatusId);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ushort Param => ptr->Param;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public float RemainingTime => ptr->RemainingTime;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public uint SourceId => ptr->SourceObject.ObjectId;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public IGameObject? SourceObject => Service<ObjectTable>.Get().SearchById(this.SourceId);
|
public IGameObject? SourceObject => Service<ObjectTable>.Get().SearchById(this.SourceId);
|
||||||
|
|
||||||
private FFXIVClientStructs.FFXIV.Client.Game.Status* Struct => (FFXIVClientStructs.FFXIV.Client.Game.Status*)this.Address;
|
public static bool operator ==(Status x, Status y) => x.Equals(y);
|
||||||
|
|
||||||
|
public static bool operator !=(Status x, Status y) => !(x == y);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Equals(IStatus? other)
|
||||||
|
{
|
||||||
|
return this.StatusId == other.StatusId && this.SourceId == other.SourceId && this.Param == other.Param && this.RemainingTime == other.RemainingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals([NotNullWhen(true)] object? obj)
|
||||||
|
{
|
||||||
|
return obj is Status fate && this.Equals(fate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(this.StatusId, this.SourceId, this.Param, this.RemainingTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using CSStatus = FFXIVClientStructs.FFXIV.Client.Game.Status;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Statuses;
|
namespace Dalamud.Game.ClientState.Statuses;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -14,7 +16,7 @@ public sealed unsafe partial class StatusList
|
||||||
/// Initializes a new instance of the <see cref="StatusList"/> class.
|
/// Initializes a new instance of the <see cref="StatusList"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Address of the status list.</param>
|
/// <param name="address">Address of the status list.</param>
|
||||||
internal StatusList(IntPtr address)
|
internal StatusList(nint address)
|
||||||
{
|
{
|
||||||
this.Address = address;
|
this.Address = address;
|
||||||
}
|
}
|
||||||
|
|
@ -24,14 +26,14 @@ public sealed unsafe partial class StatusList
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pointer">Pointer to the status list.</param>
|
/// <param name="pointer">Pointer to the status list.</param>
|
||||||
internal unsafe StatusList(void* pointer)
|
internal unsafe StatusList(void* pointer)
|
||||||
: this((IntPtr)pointer)
|
: this((nint)pointer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the address of the status list in memory.
|
/// Gets the address of the status list in memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IntPtr Address { get; }
|
public nint Address { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the amount of status effect slots the actor has.
|
/// Gets the amount of status effect slots the actor has.
|
||||||
|
|
@ -47,7 +49,7 @@ public sealed unsafe partial class StatusList
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">Status Index.</param>
|
/// <param name="index">Status Index.</param>
|
||||||
/// <returns>The status at the specified index.</returns>
|
/// <returns>The status at the specified index.</returns>
|
||||||
public Status? this[int index]
|
public IStatus? this[int index]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +66,7 @@ public sealed unsafe partial class StatusList
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">The address of the status list in memory.</param>
|
/// <param name="address">The address of the status list in memory.</param>
|
||||||
/// <returns>The status object containing the requested data.</returns>
|
/// <returns>The status object containing the requested data.</returns>
|
||||||
public static StatusList? CreateStatusListReference(IntPtr address)
|
public static StatusList? CreateStatusListReference(nint address)
|
||||||
{
|
{
|
||||||
// The use case for CreateStatusListReference and CreateStatusReference to be static is so
|
// The use case for CreateStatusListReference and CreateStatusReference to be static is so
|
||||||
// fake status lists can be generated. Since they aren't exposed as services, it's either
|
// fake status lists can be generated. Since they aren't exposed as services, it's either
|
||||||
|
|
@ -74,7 +76,7 @@ public sealed unsafe partial class StatusList
|
||||||
if (clientState.LocalContentId == 0)
|
if (clientState.LocalContentId == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (address == IntPtr.Zero)
|
if (address == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new StatusList(address);
|
return new StatusList(address);
|
||||||
|
|
@ -85,17 +87,17 @@ public sealed unsafe partial class StatusList
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">The address of the status effect in memory.</param>
|
/// <param name="address">The address of the status effect in memory.</param>
|
||||||
/// <returns>The status object containing the requested data.</returns>
|
/// <returns>The status object containing the requested data.</returns>
|
||||||
public static Status? CreateStatusReference(IntPtr address)
|
public static IStatus? CreateStatusReference(nint address)
|
||||||
{
|
{
|
||||||
var clientState = Service<ClientState>.Get();
|
var clientState = Service<ClientState>.Get();
|
||||||
|
|
||||||
if (clientState.LocalContentId == 0)
|
if (clientState.LocalContentId == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (address == IntPtr.Zero)
|
if (address == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new Status(address);
|
return new Status((CSStatus*)address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -103,22 +105,22 @@ public sealed unsafe partial class StatusList
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The index of the status.</param>
|
/// <param name="index">The index of the status.</param>
|
||||||
/// <returns>The memory address of the status.</returns>
|
/// <returns>The memory address of the status.</returns>
|
||||||
public IntPtr GetStatusAddress(int index)
|
public nint GetStatusAddress(int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= this.Length)
|
if (index < 0 || index >= this.Length)
|
||||||
return IntPtr.Zero;
|
return 0;
|
||||||
|
|
||||||
return (IntPtr)Unsafe.AsPointer(ref this.Struct->Status[index]);
|
return (nint)Unsafe.AsPointer(ref this.Struct->Status[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This collection represents the status effects an actor is afflicted by.
|
/// This collection represents the status effects an actor is afflicted by.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class StatusList : IReadOnlyCollection<Status>, ICollection
|
public sealed partial class StatusList : IReadOnlyCollection<IStatus>, ICollection
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
int IReadOnlyCollection<Status>.Count => this.Length;
|
int IReadOnlyCollection<IStatus>.Count => this.Length;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
int ICollection.Count => this.Length;
|
int ICollection.Count => this.Length;
|
||||||
|
|
@ -130,17 +132,9 @@ public sealed partial class StatusList : IReadOnlyCollection<Status>, ICollectio
|
||||||
object ICollection.SyncRoot => this;
|
object ICollection.SyncRoot => this;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IEnumerator<Status> GetEnumerator()
|
public IEnumerator<IStatus> GetEnumerator()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < this.Length; i++)
|
return new Enumerator(this);
|
||||||
{
|
|
||||||
var status = this[i];
|
|
||||||
|
|
||||||
if (status == null || status.StatusId == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
yield return status;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -155,4 +149,39 @@ public sealed partial class StatusList : IReadOnlyCollection<Status>, ICollectio
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct Enumerator(StatusList statusList) : IEnumerator<IStatus>
|
||||||
|
{
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
public IStatus Current { get; private set; }
|
||||||
|
|
||||||
|
object IEnumerator.Current => this.Current;
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (this.index == statusList.Length) return false;
|
||||||
|
|
||||||
|
for (; this.index < statusList.Length; this.index++)
|
||||||
|
{
|
||||||
|
var status = statusList[this.index];
|
||||||
|
if (status != null && status.StatusId != 0)
|
||||||
|
{
|
||||||
|
this.Current = status;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
this.index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Structs;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Native memory representation of a FFXIV status effect.
|
|
||||||
/// </summary>
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct StatusEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The effect ID.
|
|
||||||
/// </summary>
|
|
||||||
public short EffectId;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// How many stacks are present.
|
|
||||||
/// </summary>
|
|
||||||
public byte StackCount;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Additional parameters.
|
|
||||||
/// </summary>
|
|
||||||
public byte Param;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The duration remaining.
|
|
||||||
/// </summary>
|
|
||||||
public float Duration;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The ID of the actor that caused this effect.
|
|
||||||
/// </summary>
|
|
||||||
public int OwnerId;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue