diff --git a/OtterGui b/OtterGui index e47c15c0..e43a0f00 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit e47c15c0496d1afad41cc7b2854dfc43d9b82eee +Subproject commit e43a0f00661f319be27f606b1aa841d3234dfb0f diff --git a/Penumbra.GameData/Actors/ActorIdentifier.cs b/Penumbra.GameData/Actors/ActorIdentifier.cs index 00f54ea6..f097e578 100644 --- a/Penumbra.GameData/Actors/ActorIdentifier.cs +++ b/Penumbra.GameData/Actors/ActorIdentifier.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; +using System.Linq; using System.Runtime.InteropServices; using Dalamud.Game.ClientState.Objects.Enums; using Newtonsoft.Json.Linq; @@ -17,10 +17,10 @@ public readonly struct ActorIdentifier : IEquatable public enum RetainerType : ushort { - Both = 0, - Bell = 1, + Both = 0, + Bell = 1, Mannequin = 2, - } + } // @formatter:off [FieldOffset( 0 )] public readonly IdentifierType Type; // All @@ -75,7 +75,7 @@ public readonly struct ActorIdentifier : IEquatable var parts = name.Split(' ', 3); return string.Join(" ", parts.Length != 3 ? parts.Select(n => $"{n[0]}.") : parts[..2].Select(n => $"{n[0]}.").Append(parts[2])); - } + } public override string ToString() => Manager?.ToString(this) @@ -95,6 +95,9 @@ public readonly struct ActorIdentifier : IEquatable _ => "Invalid", }; + public string ToName() + => Manager?.ToName(this) ?? "Unknown Object"; + public override int GetHashCode() => Type switch { @@ -217,6 +220,6 @@ public static class ActorManagerExtensions ScreenActor.FittingRoom => "Fitting Room Actor", ScreenActor.DyePreview => "Dye Preview Actor", ScreenActor.Portrait => "Portrait Actor", - _ => "Invalid", + _ => "Invalid", }; } diff --git a/Penumbra.GameData/Actors/ActorManager.Identifiers.cs b/Penumbra.GameData/Actors/ActorManager.Identifiers.cs index 2a71081d..8584a32b 100644 --- a/Penumbra.GameData/Actors/ActorManager.Identifiers.cs +++ b/Penumbra.GameData/Actors/ActorManager.Identifiers.cs @@ -91,6 +91,23 @@ public partial class ActorManager }; } + /// + /// Use stored data to convert an ActorIdentifier to a name only. + /// + public string ToName(ActorIdentifier id) + { + return id.Type switch + { + IdentifierType.Player => id.PlayerName.ToString(), + IdentifierType.Retainer => id.PlayerName.ToString(), + IdentifierType.Owned => $"{id.PlayerName}s {Data.ToName(id.Kind, id.DataId)}", + IdentifierType.Special => id.Special.ToName(), + IdentifierType.Npc => Data.ToName(id.Kind, id.DataId), + IdentifierType.UnkObject => id.PlayerName.IsEmpty ? id.PlayerName.ToString() : "Unknown Object", + _ => "Invalid", + }; + } + private unsafe FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* HandleCutscene( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* main) { @@ -382,7 +399,7 @@ public partial class ActorManager public unsafe ActorIdentifier FromObject(GameObject? actor, out FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* owner, bool allowPlayerNpc, bool check, bool withoutIndex) => FromObject((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)(actor?.Address ?? IntPtr.Zero), out owner, allowPlayerNpc, - check, withoutIndex); + check, withoutIndex); public unsafe ActorIdentifier FromObject(GameObject? actor, bool allowPlayerNpc, bool check, bool withoutIndex) => FromObject(actor, out _, allowPlayerNpc, check, withoutIndex); diff --git a/Penumbra.GameData/Data/EquipmentIdentificationList.cs b/Penumbra.GameData/Data/EquipmentIdentificationList.cs index d8b946a4..5ce5e521 100644 --- a/Penumbra.GameData/Data/EquipmentIdentificationList.cs +++ b/Penumbra.GameData/Data/EquipmentIdentificationList.cs @@ -6,7 +6,7 @@ using Dalamud.Plugin; using Lumina.Excel.GeneratedSheets; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; -using PseudoEquipItem = System.ValueTuple; +using PseudoEquipItem = System.ValueTuple; namespace Penumbra.GameData.Data; @@ -51,6 +51,14 @@ internal sealed class EquipmentIdentificationList : KeyList private static IEnumerable CreateEquipmentList(DataManager gameData, ClientLanguage language) { var items = gameData.GetExcelSheet(language)!; - return items.Where(i => ((EquipSlot)i.EquipSlotCategory.Row).IsEquipmentPiece()).Select(i => (PseudoEquipItem)EquipItem.FromArmor(i)); + return items.Where(i => ((EquipSlot)i.EquipSlotCategory.Row).IsEquipmentPiece()) + .Select(i => (PseudoEquipItem)EquipItem.FromArmor(i)) + .Concat(CustomList); } + + private static IEnumerable CustomList + => new[] + { + (PseudoEquipItem)EquipItem.FromIds(0, 0, 8100, 0, 1, FullEquipType.Body, "Reaper Shroud"), + }; } diff --git a/Penumbra.GameData/Data/HumanModelList.cs b/Penumbra.GameData/Data/HumanModelList.cs index d4177e51..5ade3616 100644 --- a/Penumbra.GameData/Data/HumanModelList.cs +++ b/Penumbra.GameData/Data/HumanModelList.cs @@ -10,7 +10,7 @@ namespace Penumbra.GameData.Data; public sealed class HumanModelList : DataSharer { - public const string Tag = "HumanModels"; + public const string Tag = "HumanModels"; public const int CurrentVersion = 1; private readonly BitArray _humanModels; @@ -24,6 +24,9 @@ public sealed class HumanModelList : DataSharer public bool IsHuman(uint modelId) => modelId < _humanModels.Count && _humanModels[(int)modelId]; + public int Count + => _humanModels.Count; + protected override void DisposeInternal() { DisposeTag(Tag); diff --git a/Penumbra.GameData/Data/ItemData.cs b/Penumbra.GameData/Data/ItemData.cs index edd5e3ba..47f7b327 100644 --- a/Penumbra.GameData/Data/ItemData.cs +++ b/Penumbra.GameData/Data/ItemData.cs @@ -8,7 +8,7 @@ using Dalamud.Plugin; using Lumina.Excel.GeneratedSheets; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; -using PseudoEquipItem = System.ValueTuple; +using PseudoEquipItem = System.ValueTuple; namespace Penumbra.GameData.Data; @@ -54,7 +54,7 @@ public sealed class ItemData : DataSharer, IReadOnlyDictionary> BnpcNames; - public readonly IReadOnlyList> ModelCharaToObjects; - public readonly IReadOnlyDictionary> Actions; - private readonly ActorManager.ActorManagerData _actorData; + public IGamePathParser GamePathParser { get; } = new GamePathParser(); + public readonly IReadOnlyList> BnpcNames; + public readonly IReadOnlyList> ModelCharaToObjects; + public readonly IReadOnlyDictionary> Actions; + private readonly ActorManager.ActorManagerData _actorData; private readonly EquipmentIdentificationList _equipment; private readonly WeaponIdentificationList _weapons; @@ -49,10 +48,8 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier public void Identify(IDictionary set, string path) { if (path.EndsWith(".pap", StringComparison.OrdinalIgnoreCase) || path.EndsWith(".tmb", StringComparison.OrdinalIgnoreCase)) - { if (IdentifyVfx(set, path)) return; - } var info = GamePathParser.GetFileInfo(path); IdentifyParsed(set, info); @@ -73,6 +70,15 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier _ => _equipment.Between(setId, slot, (byte)variant), }; + public IReadOnlyList GetBnpcNames(uint bNpcId) + => bNpcId >= BnpcNames.Count ? Array.Empty() : BnpcNames[(int)bNpcId]; + + public IReadOnlyList<(string Name, ObjectKind Kind, uint Id)> ModelCharaNames(uint modelId) + => modelId >= ModelCharaToObjects.Count ? Array.Empty<(string Name, ObjectKind Kind, uint Id)>() : ModelCharaToObjects[(int)modelId]; + + public int NumModelChara + => ModelCharaToObjects.Count; + protected override void DisposeInternal() { _actorData.Dispose(); @@ -125,14 +131,14 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier { var items = _equipment.Between(info.PrimaryId, info.EquipSlot, info.Variant); foreach (var item in items) - set[item.Name.ToString()] = item; + set[item.Name] = item; } private void FindWeapon(IDictionary set, GameObjectInfo info) { var items = _weapons.Between(info.PrimaryId, info.SecondaryId, info.Variant); foreach (var item in items) - set[item.Name.ToString()] = item; + set[item.Name] = item; } private void FindModel(IDictionary set, GameObjectInfo info) @@ -142,10 +148,10 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier return; var models = _modelIdentifierToModelChara.Between(type, info.PrimaryId, (byte)info.SecondaryId, info.Variant); - foreach (var model in models.Where(m => m.RowId < ModelCharaToObjects.Count)) + foreach (var model in models.Where(m => m.RowId != 0 && m.RowId < ModelCharaToObjects.Count)) { var objectList = ModelCharaToObjects[(int)model.RowId]; - foreach (var (name, kind) in objectList) + foreach (var (name, kind, _) in objectList) set[$"{name} ({kind.ToName()})"] = model; } } @@ -172,10 +178,10 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier case FileType.Shader: AddCounterString(set, FileType.Shader.ToString()); return; - } + } switch (info.ObjectType) - { + { case ObjectType.LoadingScreen: case ObjectType.Map: case ObjectType.Interface: @@ -246,46 +252,46 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier return true; } - private IReadOnlyList> CreateModelObjects(ActorManager.ActorManagerData actors, + private IReadOnlyList> CreateModelObjects(ActorManager.ActorManagerData actors, DataManager gameData, ClientLanguage language) { var modelSheet = gameData.GetExcelSheet(language)!; - var ret = new List>((int)modelSheet.RowCount); - + var ret = new List>((int)modelSheet.RowCount); + for (var i = -1; i < modelSheet.Last().RowId; ++i) - ret.Add(new ConcurrentBag<(string Name, ObjectKind Kind)>()); + ret.Add(new ConcurrentBag<(string Name, ObjectKind Kind, uint Id)>()); - void AddChara(int modelChara, ObjectKind kind, uint dataId) + void AddChara(int modelChara, ObjectKind kind, uint dataId, uint displayId) { - if (modelChara == 0 || modelChara >= ret.Count) + if (modelChara >= ret.Count) return; if (actors.TryGetName(kind, dataId, out var name)) - ret[modelChara].Add((name, kind)); + ret[modelChara].Add((name, kind, displayId)); } var oTask = Task.Run(() => { foreach (var ornament in gameData.GetExcelSheet(language)!) - AddChara(ornament.Model, (ObjectKind)15, ornament.RowId); + AddChara(ornament.Model, ObjectKind.Ornament, ornament.RowId, ornament.RowId); }); var mTask = Task.Run(() => { foreach (var mount in gameData.GetExcelSheet(language)!) - AddChara((int)mount.ModelChara.Row, ObjectKind.MountType, mount.RowId); + AddChara((int)mount.ModelChara.Row, ObjectKind.MountType, mount.RowId, mount.RowId); }); var cTask = Task.Run(() => { foreach (var companion in gameData.GetExcelSheet(language)!) - AddChara((int)companion.Model.Row, ObjectKind.Companion, companion.RowId); + AddChara((int)companion.Model.Row, ObjectKind.Companion, companion.RowId, companion.RowId); }); var eTask = Task.Run(() => { foreach (var eNpc in gameData.GetExcelSheet(language)!) - AddChara((int)eNpc.ModelChara.Row, ObjectKind.EventNpc, eNpc.RowId); + AddChara((int)eNpc.ModelChara.Row, ObjectKind.EventNpc, eNpc.RowId, eNpc.RowId); }); var options = new ParallelOptions() @@ -296,14 +302,14 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier Parallel.ForEach(gameData.GetExcelSheet(language)!.Where(b => b.RowId < BnpcNames.Count), options, bNpc => { foreach (var name in BnpcNames[(int)bNpc.RowId]) - AddChara((int)bNpc.ModelChara.Row, ObjectKind.BattleNpc, name); + AddChara((int)bNpc.ModelChara.Row, ObjectKind.BattleNpc, name, bNpc.RowId); }); Task.WaitAll(oTask, mTask, cTask, eTask); - return ret.Select(s => s.Count > 0 + return ret.Select(s => !s.IsEmpty ? s.ToArray() - : Array.Empty<(string Name, ObjectKind Kind)>()).ToArray(); + : Array.Empty<(string Name, ObjectKind Kind, uint Id)>()).ToArray(); } public static unsafe ulong KeyFromCharacterBase(CharacterBase* drawObject) diff --git a/Penumbra.GameData/Data/WeaponIdentificationList.cs b/Penumbra.GameData/Data/WeaponIdentificationList.cs index 8f7bb131..90ef46c7 100644 --- a/Penumbra.GameData/Data/WeaponIdentificationList.cs +++ b/Penumbra.GameData/Data/WeaponIdentificationList.cs @@ -6,7 +6,7 @@ using Dalamud.Plugin; using Lumina.Excel.GeneratedSheets; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; -using PseudoEquipItem = System.ValueTuple; +using PseudoEquipItem = System.ValueTuple; namespace Penumbra.GameData.Data; diff --git a/Penumbra.GameData/Enums/EquipSlot.cs b/Penumbra.GameData/Enums/EquipSlot.cs index b23ae22d..27e5a92c 100644 --- a/Penumbra.GameData/Enums/EquipSlot.cs +++ b/Penumbra.GameData/Enums/EquipSlot.cs @@ -204,6 +204,14 @@ public static class EquipSlotExtensions public static readonly EquipSlot[] EquipmentSlots = Enum.GetValues().Where(e => e.IsEquipment()).ToArray(); public static readonly EquipSlot[] AccessorySlots = Enum.GetValues().Where(e => e.IsAccessory()).ToArray(); public static readonly EquipSlot[] EqdpSlots = EquipmentSlots.Concat(AccessorySlots).ToArray(); + + public static readonly EquipSlot[] WeaponSlots = + { + EquipSlot.MainHand, + EquipSlot.OffHand, + }; + + public static readonly EquipSlot[] FullSlots = WeaponSlots.Concat(EqdpSlots).ToArray(); } public static partial class Names diff --git a/Penumbra.GameData/GameData.cs b/Penumbra.GameData/GameData.cs index 02f7d33b..81657bff 100644 --- a/Penumbra.GameData/GameData.cs +++ b/Penumbra.GameData/GameData.cs @@ -2,8 +2,8 @@ using System; using System.Collections.Generic; using Dalamud; using Dalamud.Data; +using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Plugin; -using Lumina.Excel.GeneratedSheets; using Penumbra.GameData.Data; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; @@ -63,6 +63,14 @@ public interface IObjectIdentifier : IDisposable /// public IEnumerable Identify(SetId setId, ushort variant, EquipSlot slot) => Identify(setId, 0, variant, slot); + + /// Obtain a list of BNPC Name Ids associated with a BNPC Id. + public IReadOnlyList GetBnpcNames(uint bNpcId); + + /// Obtain a list of Names and Object Kinds associated with a ModelChara ID. + public IReadOnlyList<(string Name, ObjectKind Kind, uint Id)> ModelCharaNames(uint modelId); + + public int NumModelChara { get; } } public interface IGamePathParser diff --git a/Penumbra.GameData/Structs/CustomizeData.cs b/Penumbra.GameData/Structs/CustomizeData.cs index b7a92103..c9946bb0 100644 --- a/Penumbra.GameData/Structs/CustomizeData.cs +++ b/Penumbra.GameData/Structs/CustomizeData.cs @@ -1,76 +1,94 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using Penumbra.String.Functions; namespace Penumbra.GameData.Structs; - + [StructLayout(LayoutKind.Sequential, Size = Size)] -public unsafe struct CustomizeData : IEquatable< CustomizeData > +public unsafe struct CustomizeData : IEquatable, IReadOnlyCollection { public const int Size = 26; public fixed byte Data[Size]; - public void Read( void* source ) + public int Count + => Size; + + public IEnumerator GetEnumerator() { - fixed( byte* ptr = Data ) + for (var i = 0; i < Size; ++i) + yield return At(i); + } + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + + private unsafe byte At(int index) + => Data[index]; + + public void Read(void* source) + { + fixed (byte* ptr = Data) { - MemoryUtility.MemCpyUnchecked( ptr, source, Size ); + MemoryUtility.MemCpyUnchecked(ptr, source, Size); } } - public readonly void Write( void* target ) + public readonly void Write(void* target) { - fixed( byte* ptr = Data ) + fixed (byte* ptr = Data) { - MemoryUtility.MemCpyUnchecked( target, ptr, Size ); + MemoryUtility.MemCpyUnchecked(target, ptr, Size); } } public readonly CustomizeData Clone() { var ret = new CustomizeData(); - Write( ret.Data ); + Write(ret.Data); return ret; } - public readonly bool Equals( CustomizeData other ) + public readonly bool Equals(CustomizeData other) { - fixed( byte* ptr = Data ) + fixed (byte* ptr = Data) { - return MemoryUtility.MemCmpUnchecked( ptr, other.Data, Size ) == 0; + return MemoryUtility.MemCmpUnchecked(ptr, other.Data, Size) == 0; } } - public override bool Equals( object? obj ) - => obj is CustomizeData other && Equals( other ); + public override bool Equals(object? obj) + => obj is CustomizeData other && Equals(other); public static bool Equals(CustomizeData* lhs, CustomizeData* rhs) - => MemoryUtility.MemCmpUnchecked(lhs, rhs, Size) == 0; - + => MemoryUtility.MemCmpUnchecked(lhs, rhs, Size) == 0; + /// Compare Gender and then only from Height onwards, because all screen actors are set to Height 50, /// the Race is implicitly included in the subrace (after height), - /// and the body type is irrelevant for players.> + /// and the body type is irrelevant for players.> public static bool ScreenActorEquals(CustomizeData* lhs, CustomizeData* rhs) - => lhs->Data[1] == rhs->Data[1] && MemoryUtility.MemCmpUnchecked(lhs->Data + 4, rhs->Data + 4, Size - 4) == 0; + => lhs->Data[1] == rhs->Data[1] && MemoryUtility.MemCmpUnchecked(lhs->Data + 4, rhs->Data + 4, Size - 4) == 0; public override int GetHashCode() { - fixed( byte* ptr = Data ) + fixed (byte* ptr = Data) { - var p = ( int* )ptr; - var u = *( ushort* )( p + 6 ); - return HashCode.Combine( *p, p[ 1 ], p[ 2 ], p[ 3 ], p[ 4 ], p[ 5 ], u ); + var p = (int*)ptr; + var u = *(ushort*)(p + 6); + return HashCode.Combine(*p, p[1], p[2], p[3], p[4], p[5], u); } } public readonly string WriteBase64() { - fixed( byte* ptr = Data ) + fixed (byte* ptr = Data) { - var data = new ReadOnlySpan< byte >( ptr, Size ); - return Convert.ToBase64String( data ); + var data = new ReadOnlySpan(ptr, Size); + return Convert.ToBase64String(data); } } @@ -78,23 +96,20 @@ public unsafe struct CustomizeData : IEquatable< CustomizeData > { var sb = new StringBuilder(Size * 3); for (var i = 0; i < Size - 1; ++i) - { sb.Append($"{Data[i]:X2} "); - } sb.Append($"{Data[Size - 1]:X2}"); return sb.ToString(); } - public bool LoadBase64( string base64 ) + + public bool LoadBase64(string base64) { var buffer = stackalloc byte[Size]; - var span = new Span< byte >( buffer, Size ); - if( !Convert.TryFromBase64String( base64, span, out var written ) || written != Size ) - { + var span = new Span(buffer, Size); + if (!Convert.TryFromBase64String(base64, span, out var written) || written != Size) return false; - } - Read( buffer ); + Read(buffer); return true; } -} \ No newline at end of file +} diff --git a/Penumbra.GameData/Structs/EquipItem.cs b/Penumbra.GameData/Structs/EquipItem.cs index ccd9b691..8a7a7fae 100644 --- a/Penumbra.GameData/Structs/EquipItem.cs +++ b/Penumbra.GameData/Structs/EquipItem.cs @@ -2,7 +2,7 @@ using Dalamud.Utility; using Lumina.Excel.GeneratedSheets; using Penumbra.GameData.Enums; -using PseudoEquipItem = System.ValueTuple; +using PseudoEquipItem = System.ValueTuple; namespace Penumbra.GameData.Structs; @@ -10,13 +10,16 @@ namespace Penumbra.GameData.Structs; public readonly struct EquipItem { public readonly string Name; - public readonly uint Id; + public readonly ulong Id; public readonly ushort IconId; public readonly SetId ModelId; public readonly WeaponType WeaponType; public readonly byte Variant; public readonly FullEquipType Type; + public uint ItemId + => (uint)Id; + public bool Valid => Type != FullEquipType.Unknown; @@ -35,7 +38,7 @@ public readonly struct EquipItem public EquipItem() => Name = string.Empty; - public EquipItem(string name, uint id, ushort iconId, SetId modelId, WeaponType weaponType, byte variant, FullEquipType type) + public EquipItem(string name, ulong id, ushort iconId, SetId modelId, WeaponType weaponType, byte variant, FullEquipType type) { Name = string.Intern(name); Id = id; @@ -53,7 +56,7 @@ public readonly struct EquipItem => new(it.Item1, it.Item2, it.Item3, it.Item4, it.Item5, it.Item6, (FullEquipType)it.Item7); public static explicit operator PseudoEquipItem(EquipItem it) - => (it.Name, it.Id, it.IconId, (ushort)it.ModelId, (ushort)it.WeaponType, it.Variant, (byte)it.Type); + => (it.Name, it.ItemId, it.IconId, (ushort)it.ModelId, (ushort)it.WeaponType, it.Variant, (byte)it.Type); public static EquipItem FromArmor(Item item) { @@ -90,4 +93,28 @@ public readonly struct EquipItem var variant = (byte)(item.ModelSub >> 32); return new EquipItem(name, id, icon, model, weapon, variant, type); } + + public static EquipItem FromIds(uint itemId, ushort iconId, SetId modelId, WeaponType type, byte variant, + FullEquipType equipType = FullEquipType.Unknown, string? name = null) + { + name ??= $"Unknown ({modelId.Value}-{(type.Value != 0 ? $"{type.Value}-" : string.Empty)}{variant})"; + var fullId = itemId == 0 + ? modelId.Value | ((ulong)type.Value << 16) | ((ulong)variant << 32) | ((ulong)equipType << 40) | (1ul << 48) + : itemId; + return new EquipItem(name, fullId, iconId, modelId, type, variant, equipType); + } + + + public static EquipItem FromId(ulong id) + { + var setId = (SetId)id; + var type = (WeaponType)(id >> 16); + var variant = (byte)(id >> 32); + var equipType = (FullEquipType)(id >> 40); + return new EquipItem($"Unknown ({setId.Value}-{(type.Value != 0 ? $"{type.Value}-" : string.Empty)}{variant})", id, 0, setId, type, + variant, equipType); + } + + public override string ToString() + => Name; } diff --git a/Penumbra/Collections/Manager/IndividualCollections.cs b/Penumbra/Collections/Manager/IndividualCollections.cs index 8c58722d..065d6a79 100644 --- a/Penumbra/Collections/Manager/IndividualCollections.cs +++ b/Penumbra/Collections/Manager/IndividualCollections.cs @@ -96,7 +96,7 @@ public sealed partial class IndividualCollections identifiers = new[] { - manager.CreateRetainer(retainerName, 0), + manager.CreateRetainer(retainerName, ActorIdentifier.RetainerType.Both), }; break; case IdentifierType.Owned: @@ -131,7 +131,7 @@ public sealed partial class IndividualCollections ObjectKind.EventNpc => manager.Data.ENpcs, ObjectKind.Companion => manager.Data.Companions, ObjectKind.MountType => manager.Data.Mounts, - (ObjectKind)15 => manager.Data.Ornaments, + ObjectKind.Ornament => manager.Data.Ornaments, _ => throw new NotImplementedException(), }; return table.Where(kvp => kvp.Value == name) diff --git a/Penumbra/Interop/PathResolving/MetaState.cs b/Penumbra/Interop/PathResolving/MetaState.cs index 4d95b94a..2f6260a9 100644 --- a/Penumbra/Interop/PathResolving/MetaState.cs +++ b/Penumbra/Interop/PathResolving/MetaState.cs @@ -122,14 +122,14 @@ public unsafe class MetaState : IDisposable _gameEventManager.CharacterBaseCreated -= OnCharacterBaseCreated; } - private void OnCreatingCharacterBase(uint modelCharaId, nint customize, nint equipData) + private void OnCreatingCharacterBase(nint modelCharaId, nint customize, nint equipData) { _lastCreatedCollection = _collectionResolver.IdentifyLastGameObjectCollection(true); if (_lastCreatedCollection.Valid && _lastCreatedCollection.AssociatedGameObject != nint.Zero) _communicator.CreatingCharacterBase.Invoke(_lastCreatedCollection.AssociatedGameObject, - _lastCreatedCollection.ModCollection.Name, (nint)(&modelCharaId), customize, equipData); + _lastCreatedCollection.ModCollection.Name, modelCharaId, customize, equipData); - var decal = new DecalReverter(_config, _characterUtility, _resources, _lastCreatedCollection, UsesDecal(modelCharaId, customize)); + var decal = new DecalReverter(_config, _characterUtility, _resources, _lastCreatedCollection, UsesDecal(*(uint*)modelCharaId, customize)); var cmp = _lastCreatedCollection.ModCollection.TemporarilySetCmpFile(_characterUtility); _characterBaseCreateMetaChanges.Dispose(); // Should always be empty. _characterBaseCreateMetaChanges = new DisposableContainer(decal, cmp); diff --git a/Penumbra/Interop/Services/GameEventManager.cs b/Penumbra/Interop/Services/GameEventManager.cs index dc810f04..ea8d32d1 100644 --- a/Penumbra/Interop/Services/GameEventManager.cs +++ b/Penumbra/Interop/Services/GameEventManager.cs @@ -2,7 +2,6 @@ using Dalamud.Hooking; using Dalamud.Utility.Signatures; using Penumbra.GameData; using System; -using System.Diagnostics; using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Penumbra.Interop.Structs; @@ -154,7 +153,7 @@ public unsafe class GameEventManager : IDisposable { try { - ((CreatingCharacterBaseEvent)subscriber).Invoke(a, b, c); + ((CreatingCharacterBaseEvent)subscriber).Invoke((nint) (&a), b, c); } catch (Exception ex) { @@ -181,7 +180,7 @@ public unsafe class GameEventManager : IDisposable return ret; } - public delegate void CreatingCharacterBaseEvent(uint modelCharaId, nint customize, nint equipment); + public delegate void CreatingCharacterBaseEvent(nint modelCharaId, nint customize, nint equipment); public delegate void CharacterBaseCreatedEvent(uint modelCharaId, nint customize, nint equipment, nint drawObject); #endregion