mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
feat: unsafe actors
This commit is contained in:
parent
85113e263f
commit
c0ab271892
20 changed files with 441 additions and 598 deletions
|
|
@ -51,7 +51,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Warnings">
|
||||
<NoWarn>IDE0003;IDE1006;CS1591;CS1701;CS1702</NoWarn>
|
||||
<NoWarn>IDE0003;IDE0044;IDE1006;CS1591;CS1701;CS1702</NoWarn>
|
||||
<!-- IDE1006 - Naming violation -->
|
||||
<!-- CS1591 - Missing XML comment for publicly visible type or member -->
|
||||
<!-- CS1701 - Runtime policy may be needed -->
|
||||
|
|
|
|||
|
|
@ -1,22 +1,18 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Dalamud.Game.ClientState.Actors.Types;
|
||||
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
|
||||
using Dalamud.Game.ClientState.Structs;
|
||||
using JetBrains.Annotations;
|
||||
using Serilog;
|
||||
|
||||
using Actor = Dalamud.Game.ClientState.Actors.Types.Actor;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Actors
|
||||
{
|
||||
/// <summary>
|
||||
/// This collection represents the currently spawned FFXIV actors.
|
||||
/// This collection represents the currently spawned FFXIV actors.
|
||||
/// </summary>
|
||||
public class ActorTable : IReadOnlyCollection<Actor>, ICollection
|
||||
public sealed partial class ActorTable
|
||||
{
|
||||
private const int ActorTableLength = 424;
|
||||
|
||||
|
|
@ -56,37 +52,36 @@ namespace Dalamud.Game.ClientState.Actors
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
int IReadOnlyCollection<Actor>.Count => this.Length;
|
||||
|
||||
/// <inheritdoc/>
|
||||
int ICollection.Count => this.Length;
|
||||
|
||||
/// <inheritdoc/>
|
||||
bool ICollection.IsSynchronized => false;
|
||||
|
||||
/// <inheritdoc/>
|
||||
object ICollection.SyncRoot => this;
|
||||
|
||||
private ClientStateAddressResolver Address { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get an actor at the specified spawn index.
|
||||
/// Get an actor at the specified spawn index.
|
||||
/// </summary>
|
||||
/// <param name="index">Spawn index.</param>
|
||||
/// <returns><see cref="Actor" /> at the specified spawn index.</returns>
|
||||
/// <returns>An <see cref="Actor" /> at the specified spawn index.</returns>
|
||||
[CanBeNull]
|
||||
public Actor this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
var ptr = this.GetActorAddress(index);
|
||||
if (ptr != IntPtr.Zero)
|
||||
{
|
||||
return this.CreateActorReference(ptr);
|
||||
}
|
||||
var address = this.GetActorAddress(index);
|
||||
return this[address];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
/// <summary>
|
||||
/// Get an actor at the specified address.
|
||||
/// </summary>
|
||||
/// <param name="address">The actor address.</param>
|
||||
/// <returns>An <see cref="Actor" /> at the specified address.</returns>
|
||||
public Actor this[IntPtr address]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (address == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
return this.CreateActorReference(address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,31 +100,6 @@ namespace Dalamud.Game.ClientState.Actors
|
|||
return *(IntPtr*)(this.Address.ActorTable + (8 * index));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<Actor> GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < ActorTableLength; i++)
|
||||
{
|
||||
yield return this[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
for (var i = 0; i < this.Length; i++)
|
||||
{
|
||||
array.SetValue(this[i], index);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a reference to a FFXIV actor.
|
||||
/// </summary>
|
||||
|
|
@ -145,17 +115,54 @@ namespace Dalamud.Game.ClientState.Actors
|
|||
|
||||
var objKind = *(ObjectKind*)(offset + ActorOffsets.ObjectKind);
|
||||
|
||||
// TODO: This is for compatibility with legacy actor classes - superseded once ready
|
||||
var actorStruct = Marshal.PtrToStructure<Structs.Actor>(offset);
|
||||
|
||||
return objKind switch
|
||||
{
|
||||
ObjectKind.Player => new PlayerCharacter(offset, actorStruct, this.dalamud),
|
||||
ObjectKind.BattleNpc => new BattleNpc(offset, actorStruct, this.dalamud),
|
||||
ObjectKind.EventObj => new EventObj(offset, actorStruct, this.dalamud),
|
||||
ObjectKind.Companion => new Npc(offset, actorStruct, this.dalamud),
|
||||
_ => new Actor(offset, actorStruct, this.dalamud),
|
||||
ObjectKind.Player => new PlayerCharacter(offset, this.dalamud),
|
||||
ObjectKind.BattleNpc => new BattleNpc(offset, this.dalamud),
|
||||
ObjectKind.EventObj => new EventObj(offset, this.dalamud),
|
||||
ObjectKind.Companion => new Npc(offset, this.dalamud),
|
||||
_ => new Actor(offset, this.dalamud),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This collection represents the currently spawned FFXIV actors.
|
||||
/// </summary>
|
||||
public sealed partial class ActorTable : IReadOnlyCollection<Actor>, ICollection
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
int IReadOnlyCollection<Actor>.Count => this.Length;
|
||||
|
||||
/// <inheritdoc/>
|
||||
int ICollection.Count => this.Length;
|
||||
|
||||
/// <inheritdoc/>
|
||||
bool ICollection.IsSynchronized => false;
|
||||
|
||||
/// <inheritdoc/>
|
||||
object ICollection.SyncRoot => this;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<Actor> GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < ActorTableLength; i++)
|
||||
{
|
||||
yield return this[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||
|
||||
/// <inheritdoc/>
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
for (var i = 0; i < this.Length; i++)
|
||||
{
|
||||
array.SetValue(this[i], index);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,18 @@ namespace Dalamud.Game.ClientState.Actors.Resolvers
|
|||
/// </summary>
|
||||
public abstract class BaseResolver
|
||||
{
|
||||
private Dalamud dalamud;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dalamud">The Dalamud instance.</param>
|
||||
internal BaseResolver(Dalamud dalamud)
|
||||
{
|
||||
this.dalamud = dalamud;
|
||||
this.Dalamud = dalamud;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Dalamud instance.
|
||||
/// </summary>
|
||||
internal Dalamud Dalamud => this.dalamud;
|
||||
private protected Dalamud Dalamud { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,6 @@ namespace Dalamud.Game.ClientState.Actors.Resolvers
|
|||
/// </summary>
|
||||
public class ClassJob : BaseResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// ID of the ClassJob.
|
||||
/// </summary>
|
||||
public readonly uint Id;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ClassJob"/> class.
|
||||
/// Set up the ClassJob resolver with the provided ID.
|
||||
|
|
@ -22,6 +17,11 @@ namespace Dalamud.Game.ClientState.Actors.Resolvers
|
|||
this.Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of the ClassJob.
|
||||
/// </summary>
|
||||
public uint Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets GameData linked to this ClassJob.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -5,11 +5,6 @@ namespace Dalamud.Game.ClientState.Actors.Resolvers
|
|||
/// </summary>
|
||||
public class World : BaseResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// ID of the world.
|
||||
/// </summary>
|
||||
public readonly uint Id;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="World"/> class.
|
||||
/// Set up the world resolver with the provided ID.
|
||||
|
|
@ -22,6 +17,11 @@ namespace Dalamud.Game.ClientState.Actors.Resolvers
|
|||
this.Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of the world.
|
||||
/// </summary>
|
||||
public uint Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets GameData linked to this world.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace Dalamud.Game.ClientState.Actors
|
|||
/// </summary>
|
||||
public sealed class Targets
|
||||
{
|
||||
private Dalamud dalamud;
|
||||
private ClientStateAddressResolver address;
|
||||
private readonly Dalamud dalamud;
|
||||
private readonly ClientStateAddressResolver address;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Targets"/> class.
|
||||
|
|
|
|||
|
|
@ -1,101 +1,155 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Dalamud.Game.ClientState.Structs;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Memory;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Actors.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a basic FFXIV actor.
|
||||
/// This class represents a basic actor (GameObject) in FFXIV.
|
||||
/// </summary>
|
||||
public class Actor : IEquatable<Actor>
|
||||
public unsafe partial class Actor : IEquatable<Actor>
|
||||
{
|
||||
private readonly Structs.Actor actorStruct;
|
||||
private readonly Dalamud dalamud;
|
||||
|
||||
private string name;
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
internal Actor(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
|
||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||
internal Actor(IntPtr address, Dalamud dalamud)
|
||||
{
|
||||
this.actorStruct = actorStruct;
|
||||
this.dalamud = dalamud;
|
||||
this.Dalamud = dalamud;
|
||||
this.Address = address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of this <see cref="Actor" />.
|
||||
/// Gets the address of the actor in memory.
|
||||
/// </summary>
|
||||
public Position3 Position => this.ActorStruct.Position;
|
||||
public IntPtr Address { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rotation of this <see cref="Actor" />.
|
||||
/// This ranges from -pi to pi radians.
|
||||
/// Gets Dalamud itself.
|
||||
/// </summary>
|
||||
public float Rotation => this.ActorStruct.Rotation;
|
||||
private protected Dalamud Dalamud { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This allows you to <c>if (actor) {...}</c> to check for validity.
|
||||
/// </summary>
|
||||
/// <param name="actor">The actor to check.</param>
|
||||
/// <returns>True or false.</returns>
|
||||
public static implicit operator bool(Actor actor) => IsValid(actor);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this actor is still valid in memory.
|
||||
/// </summary>
|
||||
/// <param name="actor">The actor to check.</param>
|
||||
/// <returns>True or false.</returns>
|
||||
public static bool IsValid(Actor actor)
|
||||
{
|
||||
if (actor == null)
|
||||
return false;
|
||||
|
||||
if (actor.Dalamud.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<Actor>.Equals(Actor other) => this.ActorId == other?.ActorId;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj) => ((IEquatable<Actor>)this).Equals(obj as Actor);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode() => base.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class represents a basic actor (GameObject) in FFXIV.
|
||||
/// </summary>
|
||||
public unsafe partial class Actor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the displayname of this <see cref="Actor" />.
|
||||
/// </summary>
|
||||
public string Name => this.name ??= Util.GetUTF8String(this.actorStruct.Name);
|
||||
public SeString Name => MemoryHelper.ReadSeString(this.Address + ActorOffsets.Name, 32);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actor ID of this <see cref="Actor" />.
|
||||
/// </summary>
|
||||
public int ActorId => this.ActorStruct.ActorId;
|
||||
public uint ActorId => *(uint*)(this.Address + ActorOffsets.ActorId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hitbox radius of this <see cref="Actor" />.
|
||||
/// Gets the data ID for linking to other respective game data.
|
||||
/// </summary>
|
||||
public float HitboxRadius => this.ActorStruct.HitboxRadius;
|
||||
public uint DataId => *(uint*)(this.Address + ActorOffsets.DataId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of this GameObject's owner.
|
||||
/// </summary>
|
||||
public uint OwnerId => *(uint*)(this.Address + ActorOffsets.OwnerId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the 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 => *(ObjectKind*)(this.Address + ActorOffsets.ObjectKind);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sub kind of this Actor.
|
||||
/// </summary>
|
||||
public byte SubKind => *(byte*)(this.Address + ActorOffsets.SubKind);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the actor is friendly.
|
||||
/// </summary>
|
||||
public bool IsFriendly => *(int*)(this.Address + ActorOffsets.IsFriendly) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the X distance from the local player in yalms.
|
||||
/// </summary>
|
||||
public byte YalmDistanceX => this.ActorStruct.YalmDistanceFromPlayerX;
|
||||
public byte YalmDistanceX => *(byte*)(this.Address + ActorOffsets.YalmDistanceFromObjectX);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target status.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is some kind of enum. It may be <see cref="StatusEffect"/>.
|
||||
/// </remarks>
|
||||
public byte TargetStatus => *(byte*)(this.Address + ActorOffsets.TargetStatus);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Y distance from the local player in yalms.
|
||||
/// </summary>
|
||||
public byte YalmDistanceY => this.ActorStruct.YalmDistanceFromPlayerY;
|
||||
public byte YalmDistanceY => *(byte*)(this.Address + ActorOffsets.YalmDistanceFromObjectY);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target of the actor.
|
||||
/// Gets the position of this <see cref="Actor" />.
|
||||
/// </summary>
|
||||
public virtual int TargetActorID => 0;
|
||||
public Position3 Position => *(Position3*)(this.Address + ActorOffsets.Position);
|
||||
|
||||
/// <summary>
|
||||
/// Gets status Effects.
|
||||
/// Gets the rotation of this <see cref="Actor" />.
|
||||
/// This ranges from -pi to pi radians.
|
||||
/// </summary>
|
||||
public StatusEffect[] StatusEffects => this.ActorStruct.UIStatusEffects;
|
||||
public float Rotation => *(float*)(this.Address + ActorOffsets.Rotation);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of this actor in memory.
|
||||
/// Gets the hitbox radius of this <see cref="Actor" />.
|
||||
/// </summary>
|
||||
public readonly IntPtr Address;
|
||||
public float HitboxRadius => *(float*)(this.Address + ActorOffsets.HitboxRadius);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the memory representation of the base actor.
|
||||
/// Gets the current target of the Actor.
|
||||
/// </summary>
|
||||
internal Structs.Actor ActorStruct => this.actorStruct;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Dalamud"/> backing instance.
|
||||
/// </summary>
|
||||
internal Dalamud Dalamud => this.dalamud;
|
||||
|
||||
/// <inheritdoc/>
|
||||
bool IEquatable<Actor>.Equals(Actor other) => this.ActorId == other.ActorId;
|
||||
public virtual uint TargetActorID => 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
61
Dalamud/Game/ClientState/Actors/Types/ActorOffsets.cs
Normal file
61
Dalamud/Game/ClientState/Actors/Types/ActorOffsets.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Actors.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Memory offsets for the <see cref="Actor"/> type and all that inherit from it.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Document the offset usage instead.")]
|
||||
public static class ActorOffsets
|
||||
{
|
||||
// GameObject(Actor)
|
||||
// GameObject :: Character
|
||||
// GameObject :: Character :: BattleChara
|
||||
// GameObject :: Character :: Companion
|
||||
|
||||
public const int Name = 0x30;
|
||||
public const int ActorId = 0x74;
|
||||
public const int DataId = 0x80;
|
||||
public const int OwnerId = 0x84;
|
||||
public const int ObjectKind = 0x8C;
|
||||
public const int SubKind = 0x8D;
|
||||
public const int IsFriendly = 0x8E;
|
||||
public const int YalmDistanceFromObjectX = 0x90;
|
||||
public const int TargetStatus = 0x91;
|
||||
public const int YalmDistanceFromObjectY = 0x92;
|
||||
public const int Position = 0xA0;
|
||||
public const int Rotation = 0xB0;
|
||||
public const int HitboxRadius = 0xC0;
|
||||
// End GameObject 0x1A0
|
||||
|
||||
public const int CurrentHp = 0x1C4;
|
||||
public const int MaxHp = 0x1C8;
|
||||
public const int CurrentMp = 0x1CC;
|
||||
public const int MaxMp = 0x1D0;
|
||||
public const int CurrentGp = 0x1D4;
|
||||
public const int MaxGp = 0x1D6;
|
||||
public const int CurrentCp = 0x1D8;
|
||||
public const int MaxCp = 0x1DA;
|
||||
public const int ClassJob = 0x1E2;
|
||||
public const int Level = 0x1E3;
|
||||
public const int PlayerCharacterTargetActorId = 0x230;
|
||||
public const int Customize = 0x1898;
|
||||
public const int CompanyTag = 0x18B2;
|
||||
public const int BattleNpcTargetActorId = 0x18D8;
|
||||
public const int NameId = 0x1940;
|
||||
public const int CurrentWorld = 0x195C;
|
||||
public const int HomeWorld = 0x195E;
|
||||
public const int StatusFlags = 0x19A0;
|
||||
// End Character 0x19B0
|
||||
// End Companion 0x19C0
|
||||
|
||||
public const int UIStatusEffects = 0x19F8;
|
||||
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;
|
||||
// End BattleChara 0x2C00
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +1,124 @@
|
|||
using System;
|
||||
|
||||
using Dalamud.Game.ClientState.Actors.Resolvers;
|
||||
using Dalamud.Game.ClientState.Structs;
|
||||
using Dalamud.Memory;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Actors.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents the base for non-static entities.
|
||||
/// </summary>
|
||||
public class Chara : Actor
|
||||
public unsafe class Chara : Actor
|
||||
{
|
||||
/// <summary>
|
||||
/// 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>
|
||||
internal Chara(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
|
||||
: base(address, actorStruct, dalamud)
|
||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||
internal Chara(IntPtr address, Dalamud dalamud)
|
||||
: base(address, dalamud)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the level of this Chara.
|
||||
/// </summary>
|
||||
public byte Level => this.ActorStruct.Level;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ClassJob of this Chara.
|
||||
/// </summary>
|
||||
public ClassJob ClassJob => new(this.ActorStruct.ClassJob, this.Dalamud);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current HP of this Chara.
|
||||
/// </summary>
|
||||
public int CurrentHp => this.ActorStruct.CurrentHp;
|
||||
public uint CurrentHp => *(uint*)(this.Address + ActorOffsets.CurrentHp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum HP of this Chara.
|
||||
/// </summary>
|
||||
public int MaxHp => this.ActorStruct.MaxHp;
|
||||
public uint MaxHp => *(uint*)(this.Address + ActorOffsets.MaxHp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current MP of this Chara.
|
||||
/// </summary>
|
||||
public int CurrentMp => this.ActorStruct.CurrentMp;
|
||||
public uint CurrentMp => *(uint*)(this.Address + ActorOffsets.CurrentMp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum MP of this Chara.
|
||||
/// </summary>
|
||||
public int MaxMp => this.ActorStruct.MaxMp;
|
||||
public uint MaxMp => *(uint*)(this.Address + ActorOffsets.MaxMp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current GP of this Chara.
|
||||
/// </summary>
|
||||
public int CurrentGp => this.ActorStruct.CurrentGp;
|
||||
public uint CurrentGp => *(uint*)(this.Address + ActorOffsets.CurrentGp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum GP of this Chara.
|
||||
/// </summary>
|
||||
public int MaxGp => this.ActorStruct.MaxGp;
|
||||
public uint MaxGp => *(uint*)(this.Address + ActorOffsets.MaxGp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current CP of this Chara.
|
||||
/// </summary>
|
||||
public int CurrentCp => this.ActorStruct.CurrentCp;
|
||||
public uint CurrentCp => *(uint*)(this.Address + ActorOffsets.CurrentCp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum CP of this Chara.
|
||||
/// </summary>
|
||||
public int MaxCp => this.ActorStruct.MaxCp;
|
||||
public uint MaxCp => *(uint*)(this.Address + ActorOffsets.MaxCp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ClassJob of this Chara.
|
||||
/// </summary>
|
||||
public ClassJob ClassJob => new(*(byte*)(this.Address + ActorOffsets.ClassJob), this.Dalamud);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the level of this Chara.
|
||||
/// </summary>
|
||||
public byte Level => *(byte*)(this.Address + ActorOffsets.Level);
|
||||
|
||||
/// <summary>
|
||||
/// 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 => MemoryHelper.Read<byte>(this.Address + ActorOffsets.Customize, 28);
|
||||
|
||||
/// <summary>
|
||||
/// Gets status Effects.
|
||||
/// Gets the status flags.
|
||||
/// </summary>
|
||||
public StatusFlags StatusFlags => this.ActorStruct.StatusFlags;
|
||||
public StatusFlags StatusFlags => *(StatusFlags*)(this.Address + ActorOffsets.StatusFlags);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current status effects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This copies every time it is invoked, so make sure to only grab it once.
|
||||
/// </remarks>
|
||||
public StatusEffect[] StatusEffects => MemoryHelper.Read<StatusEffect>(this.Address + ActorOffsets.UIStatusEffects, 20, true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the actor is currently casting.
|
||||
/// </summary>
|
||||
public bool IsCasting => *(int*)(this.Address + ActorOffsets.IsCasting) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the actor is currently casting (again?).
|
||||
/// </summary>
|
||||
public bool IsCasting2 => *(int*)(this.Address + ActorOffsets.IsCasting2) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the spell action ID currently being cast by the actor.
|
||||
/// </summary>
|
||||
public uint CurrentCastSpellActionId => *(uint*)(this.Address + ActorOffsets.CurrentCastSpellActionId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actor ID of the target currently being cast at by the actor.
|
||||
/// </summary>
|
||||
public uint CurrentCastTargetActorId => *(uint*)(this.Address + ActorOffsets.CurrentCastTargetActorId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current casting time of the spell being cast by the actor.
|
||||
/// </summary>
|
||||
public float CurrentCastTime => *(float*)(this.Address + ActorOffsets.CurrentCastTime);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total casting time of the spell being cast by the actor.
|
||||
/// </summary>
|
||||
public float TotalCastTime => *(float*)(this.Address + ActorOffsets.TotalCastTime);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,33 +5,27 @@ namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer
|
|||
/// <summary>
|
||||
/// This class represents a battle NPC.
|
||||
/// </summary>
|
||||
public class BattleNpc : Npc
|
||||
public unsafe class BattleNpc : Npc
|
||||
{
|
||||
/// <summary>
|
||||
/// 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>
|
||||
internal BattleNpc(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
|
||||
: base(address, actorStruct, dalamud)
|
||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||
internal BattleNpc(IntPtr address, Dalamud dalamud)
|
||||
: base(address, dalamud)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the BattleNpc <see cref="BattleNpcSubKind" /> of this BattleNpc.
|
||||
/// </summary>
|
||||
public BattleNpcSubKind BattleNpcKind => (BattleNpcSubKind)this.ActorStruct.SubKind;
|
||||
public BattleNpcSubKind BattleNpcKind => *(BattleNpcSubKind*)(this.Address + ActorOffsets.SubKind);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of this BattleNpc's owner.
|
||||
/// Gets the target of the Battle NPC.
|
||||
/// </summary>
|
||||
public int OwnerId => this.ActorStruct.OwnerId;
|
||||
|
||||
/// <summary>
|
||||
/// Gets target of the Battle NPC.
|
||||
/// </summary>
|
||||
public override int TargetActorID => this.ActorStruct.BattleNpcTargetActorId;
|
||||
public override uint TargetActorID => *(uint*)(this.Address + ActorOffsets.BattleNpcTargetActorId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,23 +5,22 @@ namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer
|
|||
/// <summary>
|
||||
/// This class represents an EventObj.
|
||||
/// </summary>
|
||||
public class EventObj : Actor
|
||||
public unsafe class EventObj : Actor
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EventObj"/> class.
|
||||
/// This represents an Event Object.
|
||||
/// Set up a new EventObj 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>
|
||||
internal EventObj(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
|
||||
: base(address, actorStruct, dalamud)
|
||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||
internal EventObj(IntPtr address, Dalamud dalamud)
|
||||
: base(address, dalamud)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data ID of the NPC linking to their respective game data.
|
||||
/// Gets the event object ID of the linking to their respective game data.
|
||||
/// </summary>
|
||||
public int DataId => this.ActorStruct.DataId;
|
||||
public uint EventObjectId => *(uint*)(this.Address + ActorOffsets.DataId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,27 @@ namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer
|
|||
/// <summary>
|
||||
/// This class represents a NPC.
|
||||
/// </summary>
|
||||
public class Npc : Chara
|
||||
public unsafe class Npc : Chara
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Npc"/> class.
|
||||
/// This represents a Non-playable Character.
|
||||
/// Set up a new NPC 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>
|
||||
internal Npc(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
|
||||
: base(address, actorStruct, dalamud)
|
||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||
internal Npc(IntPtr address, Dalamud dalamud)
|
||||
: base(address, dalamud)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data ID of the NPC linking to their respective game data.
|
||||
/// Gets the data ID of the NPC linking to their assoicated BNpcBase data.
|
||||
/// </summary>
|
||||
public int DataId => this.ActorStruct.DataId;
|
||||
public uint BaseId => *(uint*)(this.Address + ActorOffsets.DataId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name ID of the NPC linking to their respective game data.
|
||||
/// </summary>
|
||||
public int NameId => this.ActorStruct.NameId;
|
||||
public uint NameId => *(uint*)(this.Address + ActorOffsets.NameId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Memory;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Actors.Types
|
||||
{
|
||||
|
|
@ -7,26 +8,6 @@ namespace Dalamud.Game.ClientState.Actors.Types
|
|||
/// </summary>
|
||||
public class PartyMember
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the character.
|
||||
/// </summary>
|
||||
public string CharacterName;
|
||||
|
||||
/// <summary>
|
||||
/// Unknown.
|
||||
/// </summary>
|
||||
public long Unknown;
|
||||
|
||||
/// <summary>
|
||||
/// The actor object that corresponds to this party member.
|
||||
/// </summary>
|
||||
public Actor Actor;
|
||||
|
||||
/// <summary>
|
||||
/// The kind or type of actor.
|
||||
/// </summary>
|
||||
public ObjectKind ObjectKind;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PartyMember"/> class.
|
||||
/// </summary>
|
||||
|
|
@ -34,9 +15,10 @@ namespace Dalamud.Game.ClientState.Actors.Types
|
|||
/// <param name="rawData">The interop data struct.</param>
|
||||
public PartyMember(ActorTable table, Structs.PartyMember rawData)
|
||||
{
|
||||
this.CharacterName = Marshal.PtrToStringAnsi(rawData.namePtr);
|
||||
this.CharacterName = MemoryHelper.ReadSeString(rawData.namePtr);
|
||||
this.Unknown = rawData.unknown;
|
||||
this.Actor = null;
|
||||
|
||||
for (var i = 0; i < table.Length; i++)
|
||||
{
|
||||
if (table[i] != null && table[i].ActorId == rawData.actorId)
|
||||
|
|
@ -48,5 +30,25 @@ namespace Dalamud.Game.ClientState.Actors.Types
|
|||
|
||||
this.ObjectKind = rawData.objectKind;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the character.
|
||||
/// </summary>
|
||||
public SeString CharacterName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets something unknown.
|
||||
/// </summary>
|
||||
public long Unknown { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actor object that corresponds to this party member.
|
||||
/// </summary>
|
||||
public Actor Actor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the kind or type of actor.
|
||||
/// </summary>
|
||||
public ObjectKind ObjectKind { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,45 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using Dalamud.Game.ClientState.Actors.Resolvers;
|
||||
using Dalamud.Game.ClientState.Structs;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Memory;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Actors.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a player character.
|
||||
/// </summary>
|
||||
public class PlayerCharacter : Chara
|
||||
public unsafe class PlayerCharacter : Chara
|
||||
{
|
||||
/// <summary>
|
||||
/// 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>
|
||||
internal PlayerCharacter(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud)
|
||||
: base(address, actorStruct, dalamud)
|
||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||
internal PlayerCharacter(IntPtr address, Dalamud dalamud)
|
||||
: base(address, 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>
|
||||
/// Gets the current <see cref="World">world</see> of the character.
|
||||
/// </summary>
|
||||
public World CurrentWorld => new(this.ActorStruct.CurrentWorld, this.Dalamud);
|
||||
public World CurrentWorld => new(*(ushort*)(this.Address + ActorOffsets.CurrentWorld), this.Dalamud);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the home <see cref="World">world</see> of the character.
|
||||
/// </summary>
|
||||
public World HomeWorld => new(this.ActorStruct.HomeWorld, this.Dalamud);
|
||||
public World HomeWorld => new(*(ushort*)(this.Address + ActorOffsets.HomeWorld), this.Dalamud);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Free Company tag of this player.
|
||||
/// </summary>
|
||||
public string CompanyTag { get; private set; }
|
||||
public SeString CompanyTag => MemoryHelper.ReadSeString(this.Address + ActorOffsets.CompanyTag, 6);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target of the PlayerCharacter.
|
||||
/// Gets the target actor ID of the PlayerCharacter.
|
||||
/// </summary>
|
||||
public override int TargetActorID => this.ActorStruct.PlayerCharacterTargetActorId;
|
||||
public override uint TargetActorID => *(uint*)(this.Address + ActorOffsets.PlayerCharacterTargetActorId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,56 +17,6 @@ namespace Dalamud.Game.ClientState
|
|||
/// </summary>
|
||||
public sealed class ClientState : INotifyPropertyChanged, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The table of all present actors.
|
||||
/// </summary>
|
||||
public readonly ActorTable Actors;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the language of the client.
|
||||
/// </summary>
|
||||
public readonly ClientLanguage ClientLanguage;
|
||||
|
||||
/// <summary>
|
||||
/// The current Territory the player resides in.
|
||||
/// </summary>
|
||||
public ushort TerritoryType;
|
||||
|
||||
/// <summary>
|
||||
/// The class facilitating Job Gauge data access.
|
||||
/// </summary>
|
||||
public JobGauges JobGauges;
|
||||
|
||||
/// <summary>
|
||||
/// The class facilitating party list data access.
|
||||
/// </summary>
|
||||
public PartyList PartyList;
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to the keypress state of keyboard keys in game.
|
||||
/// </summary>
|
||||
public KeyState KeyState;
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to the button state of gamepad buttons in game.
|
||||
/// </summary>
|
||||
public GamepadState GamepadState;
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to client conditions/player state. Allows you to check if a player is in a duty, mounted, etc.
|
||||
/// </summary>
|
||||
public Condition Condition;
|
||||
|
||||
/// <summary>
|
||||
/// The class facilitating target data access.
|
||||
/// </summary>
|
||||
public Targets Targets;
|
||||
|
||||
/// <summary>
|
||||
/// Event that gets fired when the current Territory changes.
|
||||
/// </summary>
|
||||
public EventHandler<ushort> TerritoryChanged;
|
||||
|
||||
private readonly Dalamud dalamud;
|
||||
private readonly ClientStateAddressResolver address;
|
||||
private readonly Hook<SetupTerritoryTypeDelegate> setupTerritoryTypeHook;
|
||||
|
|
@ -122,6 +72,11 @@ namespace Dalamud.Game.ClientState
|
|||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
#pragma warning restore
|
||||
|
||||
/// <summary>
|
||||
/// Event that gets fired when the current Territory changes.
|
||||
/// </summary>
|
||||
public event EventHandler<ushort> TerritoryChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Event that fires when a character is logging in.
|
||||
/// </summary>
|
||||
|
|
@ -137,22 +92,56 @@ namespace Dalamud.Game.ClientState
|
|||
/// </summary>
|
||||
public event EventHandler<ContentFinderCondition> CfPop;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the table of all present actors.
|
||||
/// </summary>
|
||||
public ActorTable Actors { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the language of the client.
|
||||
/// </summary>
|
||||
public ClientLanguage ClientLanguage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class facilitating Job Gauge data access.
|
||||
/// </summary>
|
||||
public JobGauges JobGauges { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class facilitating party list data access.
|
||||
/// </summary>
|
||||
public PartyList PartyList { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets access to the keypress state of keyboard keys in game.
|
||||
/// </summary>
|
||||
public KeyState KeyState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets access to the button state of gamepad buttons in game.
|
||||
/// </summary>
|
||||
public GamepadState GamepadState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets access to client conditions/player state. Allows you to check if a player is in a duty, mounted, etc.
|
||||
/// </summary>
|
||||
public Condition Condition { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class facilitating target data access.
|
||||
/// </summary>
|
||||
public Targets Targets { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current Territory the player resides in.
|
||||
/// </summary>
|
||||
public ushort TerritoryType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local player character, if one is present.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public PlayerCharacter LocalPlayer
|
||||
{
|
||||
get
|
||||
{
|
||||
var actor = this.Actors[0];
|
||||
|
||||
if (actor is PlayerCharacter pc)
|
||||
return pc;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public PlayerCharacter LocalPlayer => this.Actors[0] as PlayerCharacter;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content ID of the local character.
|
||||
|
|
|
|||
|
|
@ -1,296 +0,0 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
using Dalamud.Game.ClientState.Actors;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs
|
||||
{
|
||||
/// <summary>
|
||||
/// Native memory representation of an FFXIV actor.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 2)]
|
||||
public struct Actor
|
||||
{
|
||||
/// <summary>
|
||||
/// The actor name.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.Name)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
|
||||
public byte[] Name;
|
||||
|
||||
/// <summary>
|
||||
/// The actor's internal id.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.ActorId)]
|
||||
public int ActorId;
|
||||
|
||||
/// <summary>
|
||||
/// The actor's data id.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.DataId)]
|
||||
public int DataId;
|
||||
|
||||
/// <summary>
|
||||
/// The actor's owner id. This is useful for pets, summons, and the like.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.OwnerId)]
|
||||
public int OwnerId;
|
||||
|
||||
/// <summary>
|
||||
/// The type or kind of actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.ObjectKind)]
|
||||
public ObjectKind ObjectKind;
|
||||
|
||||
/// <summary>
|
||||
/// The sub-type or sub-kind of actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.SubKind)]
|
||||
public byte SubKind;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the actor is friendly.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.IsFriendly)]
|
||||
public bool IsFriendly;
|
||||
|
||||
/// <summary>
|
||||
/// The horizontal distance in game units from the player.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.YalmDistanceFromPlayerX)]
|
||||
public byte YalmDistanceFromPlayerX;
|
||||
|
||||
/// <summary>
|
||||
/// The player target status.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is some kind of enum.
|
||||
/// </remarks>
|
||||
[FieldOffset(ActorOffsets.PlayerTargetStatus)]
|
||||
public byte PlayerTargetStatus;
|
||||
|
||||
/// <summary>
|
||||
/// The vertical distance in game units from the player.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.YalmDistanceFromPlayerY)]
|
||||
public byte YalmDistanceFromPlayerY;
|
||||
|
||||
/// <summary>
|
||||
/// The (X,Z,Y) position of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.Position)]
|
||||
public Position3 Position;
|
||||
|
||||
/// <summary>
|
||||
/// The rotation of the actor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The rotation is around the vertical axis (yaw), from -pi to pi radians.
|
||||
/// </remarks>
|
||||
[FieldOffset(ActorOffsets.Rotation)]
|
||||
public float Rotation;
|
||||
|
||||
/// <summary>
|
||||
/// The hitbox radius of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.HitboxRadius)]
|
||||
public float HitboxRadius;
|
||||
|
||||
/// <summary>
|
||||
/// The current HP of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.CurrentHp)]
|
||||
public int CurrentHp;
|
||||
|
||||
/// <summary>
|
||||
/// The max HP of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.MaxHp)]
|
||||
public int MaxHp;
|
||||
|
||||
/// <summary>
|
||||
/// The current MP of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.CurrentMp)]
|
||||
public int CurrentMp;
|
||||
|
||||
/// <summary>
|
||||
/// The max MP of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.MaxMp)]
|
||||
public short MaxMp;
|
||||
|
||||
/// <summary>
|
||||
/// The current GP of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.CurrentGp)]
|
||||
public short CurrentGp;
|
||||
|
||||
/// <summary>
|
||||
/// The max GP of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.MaxGp)]
|
||||
public short MaxGp;
|
||||
|
||||
/// <summary>
|
||||
/// The current CP of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.CurrentCp)]
|
||||
public short CurrentCp;
|
||||
|
||||
/// <summary>
|
||||
/// The max CP of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.MaxCp)]
|
||||
public short MaxCp;
|
||||
|
||||
/// <summary>
|
||||
/// The class-job of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.ClassJob)]
|
||||
public byte ClassJob;
|
||||
|
||||
/// <summary>
|
||||
/// The level of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.Level)]
|
||||
public byte Level;
|
||||
|
||||
/// <summary>
|
||||
/// The (player character) actor ID being targeted by the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.PlayerCharacterTargetActorId)]
|
||||
public int PlayerCharacterTargetActorId;
|
||||
|
||||
/// <summary>
|
||||
/// The customization byte/bitfield of the actor.
|
||||
/// </summary>
|
||||
[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;
|
||||
|
||||
/// <summary>
|
||||
/// The (battle npc) actor ID being targeted by the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.BattleNpcTargetActorId)]
|
||||
public int BattleNpcTargetActorId;
|
||||
|
||||
/// <summary>
|
||||
/// The name ID of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.NameId)]
|
||||
public int NameId;
|
||||
|
||||
/// <summary>
|
||||
/// The current world ID of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.CurrentWorld)]
|
||||
public ushort CurrentWorld;
|
||||
|
||||
/// <summary>
|
||||
/// The home world ID of the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.HomeWorld)]
|
||||
public ushort HomeWorld;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the actor is currently casting.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.IsCasting)]
|
||||
public bool IsCasting;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the actor is currently casting (dup?).
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.IsCasting2)]
|
||||
public bool IsCasting2;
|
||||
|
||||
/// <summary>
|
||||
/// The spell action ID currently being cast by the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.CurrentCastSpellActionId)]
|
||||
public uint CurrentCastSpellActionId;
|
||||
|
||||
/// <summary>
|
||||
/// The actor ID of the target currently being cast at by the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.CurrentCastTargetActorId)]
|
||||
public uint CurrentCastTargetActorId;
|
||||
|
||||
/// <summary>
|
||||
/// The current casting time of the spell being cast by the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.CurrentCastTime)]
|
||||
public float CurrentCastTime;
|
||||
|
||||
/// <summary>
|
||||
/// The total casting time of the spell being cast by the actor.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.TotalCastTime)]
|
||||
public float TotalCastTime;
|
||||
|
||||
/// <summary>
|
||||
/// Actor status flags.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.StatusFlags)]
|
||||
public StatusFlags StatusFlags;
|
||||
|
||||
/// <summary>
|
||||
/// The array of status effects that the actor is currently affected by.
|
||||
/// </summary>
|
||||
[FieldOffset(ActorOffsets.UIStatusEffects)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
|
||||
public StatusEffect[] UIStatusEffects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Memory offsets for the <see cref="Actor"/> type.
|
||||
/// </summary>
|
||||
public static class ActorOffsets
|
||||
{
|
||||
// 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
|
||||
public const int DataId = 128; // 0x0080 NPCID2
|
||||
public const int OwnerId = 132; // 0x0084
|
||||
public const int ObjectKind = 140; // 0x008C Type
|
||||
public const int SubKind = 141; // 0x008D
|
||||
public const int IsFriendly = 142; // 0x008E
|
||||
public const int YalmDistanceFromPlayerX = 144; // 0x0090
|
||||
public const int PlayerTargetStatus = 145; // 0x0091
|
||||
public const int YalmDistanceFromPlayerY = 146; // 0x0092 Distance
|
||||
public const int Position = 160; // 0x00A0 (X,Z,Y)
|
||||
public const int Rotation = 176; // 0x00B0 Heading
|
||||
public const int HitboxRadius = 192; // 0x00C0
|
||||
public const int CurrentHp = 452; // 0x01C4 HPCurrent
|
||||
public const int MaxHp = 456; // 0x01C8 HPMax
|
||||
public const int CurrentMp = 460; // 0x01CC MPCurrent
|
||||
public const int MaxMp = 464; // 0x01D0 MPMax
|
||||
public const int CurrentGp = 468; // 0x01D4 GPCurrent
|
||||
public const int MaxGp = 470; // 0x01D6 GPMax
|
||||
public const int CurrentCp = 472; // 0x01D8 CPCurrent
|
||||
public const int MaxCp = 474; // 0x01DA CPMax
|
||||
public const int ClassJob = 482; // 0x01E2 Job
|
||||
public const int Level = 483; // 0x01E3 Level
|
||||
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 StatusFlags = 0x19A0;
|
||||
public const int UIStatusEffects = 0x19F8;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs
|
||||
{
|
||||
|
|
@ -40,25 +40,37 @@ namespace Dalamud.Game.ClientState.Structs
|
|||
/// <summary>
|
||||
/// Raw input, set the whole time while a button is held. See <see cref="GamepadButtons"/> for the mapping.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a bitfield.
|
||||
/// </remarks>
|
||||
[FieldOffset(0x98)]
|
||||
public ushort ButtonsRaw; // bitfield
|
||||
public ushort ButtonsRaw;
|
||||
|
||||
/// <summary>
|
||||
/// Button pressed, set once when the button is pressed. See <see cref="GamepadButtons"/> for the mapping.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a bitfield.
|
||||
/// </remarks>
|
||||
[FieldOffset(0x9C)]
|
||||
public ushort ButtonsPressed; // bitfield
|
||||
public ushort ButtonsPressed;
|
||||
|
||||
/// <summary>
|
||||
/// Button released input, set once right after the button is not hold anymore. See <see cref="GamepadButtons"/> for the mapping.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a bitfield.
|
||||
/// </remarks>
|
||||
[FieldOffset(0xA0)]
|
||||
public ushort ButtonsReleased; // bitfield
|
||||
public ushort ButtonsReleased;
|
||||
|
||||
/// <summary>
|
||||
/// Repeatedly emits the held button input in fixed intervals. See <see cref="GamepadButtons"/> for the mapping.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a bitfield.
|
||||
/// </remarks>
|
||||
[FieldOffset(0xA4)]
|
||||
public ushort ButtonsRepeat; // bitfield
|
||||
public ushort ButtonsRepeat;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,10 +37,8 @@ using System.Diagnostics.CodeAnalysis;
|
|||
// <type>Offsets.cs
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:Static elements should appear before instance elements", Justification = "Offset classes goto the end of file.", Scope = "type", Target = "~T:Dalamud.Game.ClientState.Actors.TargetOffsets")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Group offset classes with the relevant class.", Scope = "type", Target = "~T:Dalamud.Game.ClientState.Actors.TargetOffsets")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Group offset classes with the relevant class.", Scope = "type", Target = "~T:Dalamud.Game.ClientState.Structs.ActorOffsets")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Group offset classes with the relevant class.", Scope = "type", Target = "~T:Dalamud.Game.Internal.Gui.Structs.AddonOffsets")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Document the offset usage instead.", Scope = "type", Target = "~T:Dalamud.Game.ClientState.Actors.TargetOffsets")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Document the offset usage instead.", Scope = "type", Target = "~T:Dalamud.Game.ClientState.Structs.ActorOffsets")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Document the offset usage instead.", Scope = "type", Target = "~T:Dalamud.Game.Internal.Gui.Structs.AddonOffsets")]
|
||||
|
||||
// Breaking api changes: these should be split into a PartyFinder subdirectory
|
||||
|
|
@ -57,33 +55,15 @@ using System.Diagnostics.CodeAnalysis;
|
|||
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "breaking api change", Scope = "member", Target = "~E:Dalamud.Game.Internal.Gui.PartyFinderGui.ReceiveListing")]
|
||||
|
||||
// Breaking api changes
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.Actors.Resolvers.ClassJob.Id")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.Actors.Resolvers.World.Id")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.Actors.Types.Actor.Address")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.Internal.BaseAddressResolver.DebugScannedValues")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.Internal.Gui.Addon.Addon.Address")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.Internal.Gui.Addon.Addon.addonStruct")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.Internal.Gui.GameGui.GetBaseUIObject")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.Text.SeStringHandling.Payload.DataResolver")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.Actors")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.TerritoryType")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.TerritoryChanged")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.ClientLanguage")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.JobGauges")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.PartyList")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.KeyState")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.GamepadState")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.Condition")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.ClientState.Targets")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "breaking api change", Scope = "type", Target = "~T:Dalamud.Game.ClientState.Actors.Types.PartyMember")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.Actors.Types.Actor.Address")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:Elements should be ordered by access", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.Structs.JobGauge.BLMGauge.NumUmbralHearts")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:Elements should be ordered by access", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.Structs.JobGauge.DNCGauge.NumCompleteSteps")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:Elements should be ordered by access", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.ClientState.Structs.JobGauge.DRKGauge.ShadowTimeRemaining")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.Text.SeStringHandling.Payload.START_BYTE")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.Text.SeStringHandling.Payload.END_BYTE")]
|
||||
[assembly: SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Unused, but eventually, maybe.", Scope = "member", Target = "~F:Dalamud.Game.ClientState.PartyList.address")]
|
||||
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "breaking api change", Scope = "member", Target = "~E:Dalamud.Game.ClientState.ClientState.CfPop")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:Static elements should appear before instance elements", Justification = "breaking api change, move to util", Scope = "type", Target = "~T:Dalamud.Game.Text.EnumExtensions")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "breaking api change, move to util", Scope = "type", Target = "~T:Dalamud.Game.Text.EnumExtensions")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "breaking api change", Scope = "member", Target = "~F:Dalamud.Game.Internal.Framework.StatsHistory")]
|
||||
|
|
|
|||
|
|
@ -693,7 +693,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
$"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{tag}] - {actor.ObjectKind} - {actor.Name} - X{actor.Position.X} Y{actor.Position.Y} Z{actor.Position.Z} D{actor.YalmDistanceX} R{actor.Rotation} - Target: {actor.TargetActorID:X}\n";
|
||||
|
||||
if (actor is Npc npc)
|
||||
actorString += $" DataId: {npc.DataId} NameId:{npc.NameId}\n";
|
||||
actorString += $" DataId: {npc.BaseId} NameId:{npc.NameId}\n";
|
||||
|
||||
if (actor is Chara chara)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ namespace Dalamud.Memory
|
|||
/// <returns>The read in struct array.</returns>
|
||||
public static T[] Read<T>(IntPtr memoryAddress, int arrayLength, bool marshal)
|
||||
{
|
||||
var structSize = SizeOf<T>();
|
||||
var structSize = SizeOf<T>(marshal);
|
||||
var value = new T[arrayLength];
|
||||
|
||||
for (var i = 0; i < arrayLength; i++)
|
||||
|
|
@ -223,7 +223,18 @@ namespace Dalamud.Memory
|
|||
public static SeString ReadSeString(IntPtr memoryAddress, int maxLength)
|
||||
{
|
||||
ReadRaw(memoryAddress, maxLength, out var buffer);
|
||||
return seStringManager.Parse(buffer);
|
||||
|
||||
var eos = Array.IndexOf(buffer, (byte)0);
|
||||
if (eos < 0)
|
||||
{
|
||||
return seStringManager.Parse(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newBuffer = new byte[eos];
|
||||
Buffer.BlockCopy(buffer, 0, newBuffer, 0, eos);
|
||||
return seStringManager.Parse(newBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue