Actor offsets, StyleCop

This commit is contained in:
Raymond Lynch 2021-04-13 19:52:35 -04:00
parent 2aacbee1c8
commit ff929ed5a6
9 changed files with 196 additions and 168 deletions

View file

@ -1,82 +1,98 @@
using Dalamud.Game.ClientState.Structs;
using System;
namespace Dalamud.Game.ClientState.Actors.Types {
using Dalamud.Game.ClientState.Structs;
namespace Dalamud.Game.ClientState.Actors.Types
{
/// <summary>
/// This class represents a basic FFXIV actor.
/// </summary>
public class Actor : IEquatable<Actor> {
/// <summary>
/// The memory representation of the base actor.
/// </summary>
protected Structs.Actor actorStruct;
protected Dalamud dalamud;
public class Actor : IEquatable<Actor>
{
private readonly Structs.Actor actorStruct;
// This is a breaking change. StyleCop demands it.
// private readonly IntPtr address;
private readonly Dalamud dalamud;
/// <summary>
/// The address of this actor in memory.
/// </summary>
public readonly IntPtr Address;
/// <summary>
/// Initialize a representation of a basic FFXIV actor.
/// Initializes a new instance of the <see cref="Actor"/> class.
/// This represents a basic FFXIV actor.
/// </summary>
/// <param name="actorStruct">The memory representation of the base actor.</param>
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
/// <param name="address">The address of this actor in memory.</param>
public Actor(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) {
public Actor(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
{
this.actorStruct = actorStruct;
this.dalamud = dalamud;
this.Address = address;
}
/// <summary>
/// Position of this <see cref="Actor" />.
/// Gets position of this <see cref="Actor" />.
/// </summary>
public Position3 Position => this.actorStruct.Position;
public Position3 Position => this.ActorStruct.Position;
/// <summary>
/// Rotation of this <see cref="Actor"/>.<br/>
/// Gets rotation of this <see cref="Actor" />.
/// This ranges from -pi to pi radians.
/// </summary>
public float Rotation => this.actorStruct.Rotation;
public float Rotation => this.ActorStruct.Rotation;
/// <summary>
/// Displayname of this <see cref="Actor">Actor</see>.
/// Gets displayname of this <see cref="Actor" />.
/// </summary>
public string Name => this.actorStruct.Name;
public string Name => this.ActorStruct.Name;
/// <summary>
/// Actor ID of this <see cref="Actor" />.
/// Gets actor ID of this <see cref="Actor" />.
/// </summary>
public int ActorId => this.actorStruct.ActorId;
public int ActorId => this.ActorStruct.ActorId;
/// <summary>
/// Entity kind of this <see cref="Actor">actor</see>. See <see cref="ObjectKind">the ObjectKind enum</see> for
/// possible values.
/// Gets entity kind of this <see cref="Actor" />.
/// See <see cref="ObjectKind">the ObjectKind enum</see> for possible values.
/// </summary>
public ObjectKind ObjectKind => this.actorStruct.ObjectKind;
public ObjectKind ObjectKind => this.ActorStruct.ObjectKind;
/// <summary>
/// The X distance from the local player in yalms.
/// Gets the X distance from the local player in yalms.
/// </summary>
public byte YalmDistanceX => this.actorStruct.YalmDistanceFromPlayerX;
public byte YalmDistanceX => this.ActorStruct.YalmDistanceFromPlayerX;
/// <summary>
/// The Y distance from the local player in yalms.
/// Gets the Y distance from the local player in yalms.
/// </summary>
public byte YalmDistanceY => this.actorStruct.YalmDistanceFromPlayerY;
public byte YalmDistanceY => this.ActorStruct.YalmDistanceFromPlayerY;
/// <summary>
/// The target of the actor
/// Gets the target of the actor.
/// </summary>
public virtual int TargetActorID => 0;
/// <summary>
/// Status Effects
/// Gets status Effects.
/// </summary>
public StatusEffect[] StatusEffects => this.actorStruct.UIStatusEffects;
public StatusEffect[] StatusEffects => this.ActorStruct.UIStatusEffects;
/// <summary>
/// Gets the address of this actor in memory.
/// </summary>
// TODO: This is a breaking change, StyleCop demands it.
// public IntPtr Address => this.address;
public readonly IntPtr Address;
/// <summary>
/// Gets the memory representation of the base actor.
/// </summary>
internal Structs.Actor ActorStruct => this.actorStruct;
/// <summary>
/// Gets the <see cref="Dalamud"/> backing instance.
/// </summary>
protected Dalamud Dalamud => this.dalamud;
/// <inheritdoc/>
bool IEquatable<Actor>.Equals(Actor other) => this.ActorId == other.ActorId;
}
}

View file

@ -1,72 +1,80 @@
using System;
using Dalamud.Game.ClientState.Actors.Resolvers;
namespace Dalamud.Game.ClientState.Actors.Types {
namespace Dalamud.Game.ClientState.Actors.Types
{
/// <summary>
/// This class represents the base for non-static entities.
/// This class represents the base for non-static entities.
/// </summary>
public class Chara : Actor {
public class Chara : Actor
{
/// <summary>
/// Set up a new Chara with the provided memory representation.
/// Initializes a new instance of the <see cref="Chara"/> class.
/// This represents a non-static entity.
/// </summary>
/// <param name="actorStruct">The memory representation of the base actor.</param>
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
/// <param name="address">The address of this actor in memory.</param>
protected Chara(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
protected Chara(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
: base(address, actorStruct, dalamud)
{
}
/// <summary>
/// The level of this Chara.
/// Gets the level of this Chara.
/// </summary>
public byte Level => this.actorStruct.Level;
public byte Level => this.ActorStruct.Level;
/// <summary>
/// The ClassJob of this Chara.
/// Gets the ClassJob of this Chara.
/// </summary>
public ClassJob ClassJob => new ClassJob(this.actorStruct.ClassJob, this.dalamud);
public ClassJob ClassJob => new ClassJob(this.ActorStruct.ClassJob, this.Dalamud);
/// <summary>
/// The current HP of this Chara.
/// Gets the current HP of this Chara.
/// </summary>
public int CurrentHp => this.actorStruct.CurrentHp;
public int CurrentHp => this.ActorStruct.CurrentHp;
/// <summary>
/// The maximum HP of this Chara.
/// Gets the maximum HP of this Chara.
/// </summary>
public int MaxHp => this.actorStruct.MaxHp;
public int MaxHp => this.ActorStruct.MaxHp;
/// <summary>
/// The current MP of this Chara.
/// Gets the current MP of this Chara.
/// </summary>
public int CurrentMp => this.actorStruct.CurrentMp;
public int CurrentMp => this.ActorStruct.CurrentMp;
/// <summary>
/// The maximum MP of this Chara.
/// Gets the maximum MP of this Chara.
/// </summary>
public int MaxMp => this.actorStruct.MaxMp;
public int MaxMp => this.ActorStruct.MaxMp;
/// <summary>
/// The current GP of this Chara.
/// Gets the current GP of this Chara.
/// </summary>
public int CurrentGp => this.actorStruct.CurrentGp;
public int CurrentGp => this.ActorStruct.CurrentGp;
/// <summary>
/// The maximum GP of this Chara.
/// Gets the maximum GP of this Chara.
/// </summary>
public int MaxGp => this.actorStruct.MaxGp;
public int MaxGp => this.ActorStruct.MaxGp;
/// <summary>
/// The current CP of this Chara.
/// Gets the current CP of this Chara.
/// </summary>
public int CurrentCp => this.actorStruct.CurrentCp;
public int CurrentCp => this.ActorStruct.CurrentCp;
/// <summary>
/// The maximum CP of this Chara.
/// Gets the maximum CP of this Chara.
/// </summary>
public int MaxCp => this.actorStruct.MaxCp;
public int MaxCp => this.ActorStruct.MaxCp;
/// <summary>
/// Byte array describing the visual appearance of this Chara. Indexed by <see cref="CustomizeIndex"/>.
/// Gets a byte array describing the visual appearance of this Chara.
/// Indexed by <see cref="CustomizeIndex"/>.
/// </summary>
public byte[] Customize => this.actorStruct.Customize;
public byte[] Customize => this.ActorStruct.Customize;
}
}

View file

@ -1,32 +1,37 @@
using System;
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer
{
/// <summary>
/// This class represents a battle NPC.
/// This class represents a battle NPC.
/// </summary>
public class BattleNpc : Npc {
public class BattleNpc : Npc
{
/// <summary>
/// Set up a new BattleNpc with the provided memory representation.
/// Initializes a new instance of the <see cref="BattleNpc"/> class.
/// Set up a new BattleNpc with the provided memory representation.
/// </summary>
/// <param name="actorStruct">The memory representation of the base actor.</param>
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
/// <param name="address">The address of this actor in memory.</param>
public BattleNpc(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
public BattleNpc(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
: base(address, actorStruct, dalamud)
{
}
/// <summary>
/// The BattleNpc <see cref="BattleNpcSubKind" /> of this BattleNpc.
/// Gets the BattleNpc <see cref="BattleNpcSubKind" /> of this BattleNpc.
/// </summary>
public BattleNpcSubKind BattleNpcKind => (BattleNpcSubKind) this.actorStruct.SubKind;
public BattleNpcSubKind BattleNpcKind => (BattleNpcSubKind)this.ActorStruct.SubKind;
/// <summary>
/// The ID of this BattleNpc's owner.
/// Gets the ID of this BattleNpc's owner.
/// </summary>
public int OwnerId => this.actorStruct.OwnerId;
public int OwnerId => this.ActorStruct.OwnerId;
/// <summary>
/// Target of the Battle NPC
/// Gets target of the Battle NPC.
/// </summary>
public override int TargetActorID => this.actorStruct.BattleNpcTargetActorId;
public override int TargetActorID => this.ActorStruct.BattleNpcTargetActorId;
}
}

View file

@ -1,21 +1,23 @@
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer
{
/// <summary>
/// Enum describing possible BattleNpc kinds.
/// An Enum describing possible BattleNpc kinds.
/// </summary>
public enum BattleNpcSubKind : byte {
public enum BattleNpcSubKind : byte
{
/// <summary>
/// Invalid BattleNpc.
/// Invalid BattleNpc.
/// </summary>
None = 0,
/// <summary>
/// BattleNpc representing a Pet.
/// BattleNpc representing a Pet.
/// </summary>
Pet = 2,
/// <summary>
/// BattleNpc representing a standard enemy.
/// BattleNpc representing a standard enemy.
/// </summary>
Enemy = 5
Enemy = 5,
}
}

View file

@ -1,21 +1,27 @@
using System;
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer
{
/// <summary>
/// This class represents an EventObj.
/// This class represents an EventObj.
/// </summary>
public class EventObj : Actor {
public class EventObj : Actor
{
/// <summary>
/// Set up a new EventObj with the provided memory representation.
/// Initializes a new instance of the <see cref="EventObj"/> class.
/// This represents an Event Object.
/// </summary>
/// <param name="actorStruct">The memory representation of the base actor.</param>
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
/// <param name="address">The address of this actor in memory.</param>
public EventObj(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
public EventObj(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
: base(address, actorStruct, dalamud)
{
}
/// <summary>
/// The data ID of the NPC linking to their respective game data.
/// Gets the data ID of the NPC linking to their respective game data.
/// </summary>
public int DataId => this.actorStruct.DataId;
public int DataId => this.ActorStruct.DataId;
}
}

View file

@ -1,26 +1,32 @@
using System;
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer
{
/// <summary>
/// This class represents a NPC.
/// This class represents a NPC.
/// </summary>
public class Npc : Chara {
public class Npc : Chara
{
/// <summary>
/// Set up a new NPC with the provided memory representation.
/// Initializes a new instance of the <see cref="Npc"/> class.
/// This represents a Non-playable Character.
/// </summary>
/// <param name="actorStruct">The memory representation of the base actor.</param>
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
/// <param name="address">The address of this actor in memory.</param>
public Npc(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
public Npc(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
: base(address, actorStruct, dalamud)
{
}
/// <summary>
/// The data ID of the NPC linking to their respective game data.
/// Gets the data ID of the NPC linking to their respective game data.
/// </summary>
public int DataId => this.actorStruct.DataId;
public int DataId => this.ActorStruct.DataId;
/// <summary>
/// The name ID of the NPC linking to their respective game data.
/// Gets the name ID of the NPC linking to their respective game data.
/// </summary>
public int NameId => this.actorStruct.NameId;
public int NameId => this.ActorStruct.NameId;
}
}

View file

@ -1,10 +1,4 @@
using Dalamud.Game.ClientState.Structs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Game.ClientState.Actors.Types
{

View file

@ -2,48 +2,50 @@ using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Dalamud.Game.ClientState.Actors.Resolvers;
using Dalamud.Game.ClientState.Structs;
namespace Dalamud.Game.ClientState.Actors.Types {
namespace Dalamud.Game.ClientState.Actors.Types
{
/// <summary>
/// This class represents a player character.
/// This class represents a player character.
/// </summary>
public class PlayerCharacter : Chara {
public class PlayerCharacter : Chara
{
/// <summary>
/// Set up a new player character with the provided memory representation.
/// Initializes a new instance of the <see cref="PlayerCharacter"/> class.
/// This represents a player character.
/// </summary>
/// <param name="actorStruct">The memory representation of the base actor.</param>
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
/// <param name="address">The address of this actor in memory.</param>
public PlayerCharacter(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(
address, actorStruct, dalamud) {
// We need to read the FC tag here, since we can't read it in the struct due to alignment issues
var fcTagBytes = new byte[5];
Marshal.Copy(this.Address + ActorOffsets.CompanyTag, fcTagBytes, 0, fcTagBytes.Length);
CompanyTag = Encoding.UTF8.GetString(fcTagBytes.TakeWhile(x => x != 0x00).ToArray());
public PlayerCharacter(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
: base(address, actorStruct, dalamud)
{
var companyTagBytes = new byte[5];
Marshal.Copy(this.Address + ActorOffsets.CompanyTag, companyTagBytes, 0, companyTagBytes.Length);
this.CompanyTag = Encoding.UTF8.GetString(companyTagBytes.TakeWhile(c => c != 0x0).ToArray());
}
/// <summary>
/// The current <see cref="World">world</see> of the character.
/// Gets the current <see cref="World">world</see> of the character.
/// </summary>
public World CurrentWorld => new World(this.actorStruct.CurrentWorld, this.dalamud);
public World CurrentWorld => new World(this.ActorStruct.CurrentWorld, this.Dalamud);
/// <summary>
/// The home <see cref="World">world</see> of the character.
/// Gets the home <see cref="World">world</see> of the character.
/// </summary>
public World HomeWorld => new World(this.actorStruct.HomeWorld, this.dalamud);
public World HomeWorld => new World(this.ActorStruct.HomeWorld, this.Dalamud);
/// <summary>
/// The Free Company tag of this player.
/// Gets the Free Company tag of this player.
/// </summary>
public string CompanyTag { get; private set; }
/// <summary>
/// Target of the PlayerCharacter
/// Gets the target of the PlayerCharacter.
/// </summary>
public override int TargetActorID => this.actorStruct.PlayerCharacterTargetActorId;
public override int TargetActorID => this.ActorStruct.PlayerCharacterTargetActorId;
}
}

View file

@ -1,13 +1,12 @@
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Actors;
#pragma warning disable 1591
namespace Dalamud.Game.ClientState.Structs
{
public class ActorOffsets
{
// ??? Offsets based on https://github.com/FFXIVAPP/sharlayan-resources/blob/master/structures/5.4/x64.json
// Reference https://github.com/FFXIVAPP/sharlayan-resources/blob/master/structures/5.4/x64.json for more
public const int Name = 48; // 0x0030
public const int ActorId = 116; // 0x0074
// public const int ??? = 120; // 0x0078 NPCID1
@ -19,25 +18,8 @@ namespace Dalamud.Game.ClientState.Structs
public const int YalmDistanceFromPlayerX = 144; // 0x0090
public const int PlayerTargetStatus = 145; // 0x0091
public const int YalmDistanceFromPlayerY = 146; // 0x0092 Distance
// public const int ??? = 148; // 0x0094 TargetFlags
// public const int ??? = 148; // 0x0094 GatheringInvisible
public const int Position = 160; // 0x00A0 (X,Z,Y)
public const int Rotation = 176; // 0x00B0 Heading
// public const int ??? = 190; // 0x00BE EventObjectType
// public const int ??? = 192; // 0x00C0 HitBoxRadius
// public const int ??? = 228; // 0x00E4 Fate
// public const int ??? = 396; // 0x018C IsGM
// public const int ??? = 464; // 0x01D0 TargetType
// public const int ??? = 480; // 0x01E0 EntityCount
// public const int ??? = 488; // 0x01E8 GatheringStatus
public const int PlayerCharacterTargetActorId = 560; // 0x01F0 TargetID
// public const int ??? = 5297; // 0x14B1 Status
public const int Customize = 6264; // 0x17B8
public const int CompanyTag = 6290; // 0x17D0
public const int BattleNpcTargetActorId = 6328; // 0x17F8 ClaimedByID
public const int NameId = 6432; // 0x1868 ModelID
public const int CurrentWorld = 6460; // 0x1884
public const int HomeWorld = 6462; // 0x1886
public const int CurrentHp = 452; // 0x01C4 HPCurrent
public const int MaxHp = 456; // 0x01C8 HPMax
public const int CurrentMp = 460; // 0x01CC MPCurrent
@ -46,32 +28,33 @@ namespace Dalamud.Game.ClientState.Structs
public const int MaxGp = 470; // 0x01D6 GPMax
public const int CurrentCp = 472; // 0x01D8 CPCurrent
public const int MaxCp = 474; // 0x01DA CPMax
// public const int ??? = 6326; // 0x18B6 Title
// public const int ??? = 6354; // 0x18D2 Icon
// public const int ??? = 6356; // 0x18D4 ActionStatus
public const int ClassJob = 482; // 0x01E2 Job
public const int Level = 483; // 0x01E3 Level
// public const int ??? = 6367; // 0x18DF GrandCompany
// public const int ??? = 6367; // 0x18DF GrandCompanyRank
// public const int ??? = 6371; // 0x18E3 DifficultyRank
// public const int ??? = 6385; // 0x18F1 AgroFlags
// public const int ??? = 6406; // 0x1906 CombatFlags
public const int UIStatusEffects = 6616; // 0x1958 DefaultStatusEffectOffset
// public const int ??? = 6880; // 0x1AE0 IsCasting1
// public const int ??? = 6882; // 0x1AE2 IsCasting2
// public const int ??? = 6884; // 0x1AE4 CastingID
// public const int ??? = 6896; // 0x1AF0 CastingTargetID
// public const int ??? = 6932; // 0x1B14 CastingProgress
// public const int ??? = 6936; // 0x1B18 CastingTime
public const int PlayerCharacterTargetActorId = 560; // 0x01F0 TargetID
public const int Customize = 0x1898; // Needs verification
public const int CompanyTag = 0x18B2;
public const int BattleNpcTargetActorId = 0x18D8; // Needs verification
public const int NameId = 0x1940; // Needs verification
public const int CurrentWorld = 0x195C;
public const int HomeWorld = 0x195E;
public const int IsCasting = 0x1B80;
public const int IsCasting2 = 0x1B82;
public const int CurrentCastSpellActionId = 0x1B84;
public const int CurrentCastTargetActorId = 0x1B90;
public const int CurrentCastTime = 0x1BB4;
public const int TotalCastTime = 0x1BB8;
public const int UIStatusEffects = 0x19F8;
}
/// <summary>
/// Native memory representation of a FFXIV actor.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
[StructLayout(LayoutKind.Explicit, Pack = 2)]
public struct Actor
{
[FieldOffset(ActorOffsets.Name)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Name;
[FieldOffset(ActorOffsets.ActorId)] public int ActorId;
[FieldOffset(ActorOffsets.DataId)] public int DataId;
[FieldOffset(ActorOffsets.OwnerId)] public int OwnerId;
@ -82,16 +65,7 @@ namespace Dalamud.Game.ClientState.Structs
[FieldOffset(ActorOffsets.PlayerTargetStatus)] public byte PlayerTargetStatus; // This is some kind of enum
[FieldOffset(ActorOffsets.YalmDistanceFromPlayerY)] public byte YalmDistanceFromPlayerY; // and the other is z distance
[FieldOffset(ActorOffsets.Position)] public Position3 Position;
[FieldOffset(ActorOffsets.Rotation)] public float Rotation; // Rotation around the vertical axis (yaw), from -pi to pi radians
[FieldOffset(ActorOffsets.Customize)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] Customize;
[FieldOffset(ActorOffsets.PlayerCharacterTargetActorId)] public int PlayerCharacterTargetActorId;
[FieldOffset(ActorOffsets.BattleNpcTargetActorId)] public int BattleNpcTargetActorId;
[FieldOffset(ActorOffsets.NameId)] public int NameId;
[FieldOffset(ActorOffsets.CurrentWorld)] public ushort CurrentWorld;
[FieldOffset(ActorOffsets.HomeWorld)] public ushort HomeWorld;
[FieldOffset(ActorOffsets.Rotation)] public float Rotation; // Rotation around the vertical axis (yaw), from -pi to pi radians
[FieldOffset(ActorOffsets.CurrentHp)] public int CurrentHp;
[FieldOffset(ActorOffsets.MaxHp)] public int MaxHp;
[FieldOffset(ActorOffsets.CurrentMp)] public int CurrentMp;
@ -102,6 +76,21 @@ namespace Dalamud.Game.ClientState.Structs
[FieldOffset(ActorOffsets.MaxCp)] public short MaxCp;
[FieldOffset(ActorOffsets.ClassJob)] public byte ClassJob;
[FieldOffset(ActorOffsets.Level)] public byte Level;
[FieldOffset(ActorOffsets.PlayerCharacterTargetActorId)] public int PlayerCharacterTargetActorId;
[FieldOffset(ActorOffsets.Customize)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] Customize;
// Normally pack=2 should work, but ByTVal or Injection breaks this.
// [FieldOffset(ActorOffsets.CompanyTag)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public string CompanyTag;
// [FieldOffset(ActorOffsets.BattleNpcTargetActorId)] public int BattleNpcTargetActorId;
[FieldOffset(ActorOffsets.NameId)] public int NameId;
[FieldOffset(ActorOffsets.CurrentWorld)] public ushort CurrentWorld;
[FieldOffset(ActorOffsets.HomeWorld)] public ushort HomeWorld;
[FieldOffset(ActorOffsets.IsCasting)] public bool IsCasting;
[FieldOffset(ActorOffsets.IsCasting2)] public bool IsCasting2;
[FieldOffset(ActorOffsets.CurrentCastSpellActionId)] public uint CurrentCastSpellActionId;
[FieldOffset(ActorOffsets.CurrentCastTargetActorId)] public uint CurrentCastTargetActorId;
[FieldOffset(ActorOffsets.CurrentCastTime)] public float CurrentCastTime;
[FieldOffset(ActorOffsets.TotalCastTime)] public float TotalCastTime;
[FieldOffset(ActorOffsets.UIStatusEffects)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public StatusEffect[] UIStatusEffects;
}
}