huge refactor

This commit is contained in:
Boki 2026-03-02 23:45:12 -05:00
parent e5ebe05571
commit a8341e8232
29 changed files with 3184 additions and 340 deletions

View file

@ -3,66 +3,85 @@ using Roboto.GameOffsets.Natives;
namespace Roboto.GameOffsets.Components;
/// <summary>Actor component — skills, animations, deployments.</summary>
[StructLayout(LayoutKind.Explicit, Size = 0x2E8)]
public struct Actor
/// <summary>
/// Actor component offsets — confirmed from ExileCore2.
/// The struct is too large (0xC28) for a single Read, so fields are read at offsets directly.
/// </summary>
public static class ActorOffsets
{
[FieldOffset(0x00)] public ComponentHeader Header;
/// <summary>Pointer to animation controller.</summary>
[FieldOffset(0x1D8)] public nint AnimationControllerPtr;
/// <summary>Active skills StdVector (of ActiveSkillStructure).</summary>
[FieldOffset(0x2C0)] public StdVector ActiveSkills;
/// <summary>Deployed entities StdVector (of DeployedEntityStructure).</summary>
[FieldOffset(0x2D8)] public StdVector DeployedEntities;
public const int AnimationId = 0x370;
public const int ActiveSkillsVector = 0xB00;
public const int CooldownsVector = 0xB18;
public const int DeployedEntitiesVector = 0xC10;
}
/// <summary>An entry in the active skills vector.</summary>
[StructLayout(LayoutKind.Explicit, Size = 0x28)]
public struct ActiveSkillStructure
/// <summary>
/// An entry in the ActiveSkills vector: shared_ptr pair (0x10 bytes).
/// Follow ActiveSkillPtr (first pointer) for skill details.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ActiveSkillEntry
{
[FieldOffset(0x00)] public nint SkillDetailsPtr;
[FieldOffset(0x08)] public short SkillId;
[FieldOffset(0x0C)] public byte CanBeUsed;
[FieldOffset(0x0D)] public byte CanBeUsedWithWeapon;
[FieldOffset(0x10)] public nint CooldownPtr;
public nint ActiveSkillPtr;
public nint ControlBlockPtr; // shared_ptr control block, not used
}
/// <summary>Detailed info about a skill.</summary>
[StructLayout(LayoutKind.Explicit, Size = 0x20)]
/// <summary>
/// Details of an active skill, reached by following ActiveSkillEntry.ActiveSkillPtr.
/// From ExileCore2 GameOffsets.Objects.Components.ActiveSkillDetails.
/// </summary>
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct ActiveSkillDetails
{
[FieldOffset(0x00)] public nint NamePtr;
[FieldOffset(0x08)] public nint InternalNamePtr;
[FieldOffset(0x10)] public int GrantedEffectsPerLevelIdx;
[FieldOffset(0x14)] public int IconIndex;
[FieldOffset(0x08)] public int UseStage;
[FieldOffset(0x0C)] public int CastType;
[FieldOffset(0x10)] public uint UnknownIdAndEquipmentInfo;
[FieldOffset(0x18)] public nint GrantedEffectsPerLevelDatRow;
[FieldOffset(0x20)] public nint ActiveSkillsDatPtr;
[FieldOffset(0x30)] public nint GrantedEffectStatSetsPerLevelDatRow;
[FieldOffset(0x98)] public int TotalUses;
[FieldOffset(0xA8)] public int TotalCooldownTimeInMs;
}
/// <summary>Cooldown state for a skill.</summary>
[StructLayout(LayoutKind.Explicit, Size = 0x20)]
/// <summary>
/// Cooldown state for a skill. Entries in Actor+0xB18 vector.
/// From ExileCore2 GameOffsets.Objects.Components.ActiveSkillCooldown.
/// </summary>
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x48)]
public struct ActiveSkillCooldown
{
[FieldOffset(0x00)] public nint CooldownGroupPtr;
[FieldOffset(0x08)] public int MaxUses;
[FieldOffset(0x0C)] public int CurrentUses;
[FieldOffset(0x10)] public int CooldownTimer;
[FieldOffset(0x08)] public int ActiveSkillsDatId;
[FieldOffset(0x10)] public StdVector CooldownsList; // 0x10-byte entries
[FieldOffset(0x30)] public int MaxUses;
[FieldOffset(0x34)] public int TotalCooldownTimeInMs;
[FieldOffset(0x3C)] public uint UnknownIdAndEquipmentInfo;
/// <summary>Number of active cooldown timer entries.</summary>
public readonly int TotalActiveCooldowns => (int)CooldownsList.TotalElements(0x10);
/// <summary>True if all uses are on cooldown.</summary>
public readonly bool CannotBeUsed => TotalActiveCooldowns >= MaxUses;
}
/// <summary>Vaal soul tracking.</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct VaalSoulStructure
{
public nint GrantedEffectsPtr;
public int CurrentSouls;
public int SoulCost;
[FieldOffset(0x00)] public nint ActiveSkillsDatPtr;
[FieldOffset(0x08)] public nint UselessPtr;
[FieldOffset(0x10)] public int RequiredSouls;
[FieldOffset(0x14)] public int CurrentSouls;
public readonly bool CannotBeUsed => CurrentSouls < RequiredSouls;
}
/// <summary>A deployed entity (totem, mine, etc.).</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DeployedEntityStructure
{
public uint EntityId;
public int SkillIndex;
public int EntityId;
public int ActiveSkillsDatId;
public int DeployedObjectType;
public int PAD_0x014;
public int Counter;
}