mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-15 05:04:15 +01:00
Use EquipItem in item management and add filters to changed item types.
This commit is contained in:
parent
5fcb07487e
commit
d9c5c053cf
19 changed files with 641 additions and 375 deletions
|
|
@ -9,15 +9,15 @@ using Penumbra.GameData.Structs;
|
|||
|
||||
namespace Penumbra.GameData.Data;
|
||||
|
||||
internal sealed class EquipmentIdentificationList : KeyList<Item>
|
||||
internal sealed class EquipmentIdentificationList : KeyList<EquipItem>
|
||||
{
|
||||
private const string Tag = "EquipmentIdentification";
|
||||
private const string Tag = "EquipmentIdentification";
|
||||
|
||||
public EquipmentIdentificationList(DalamudPluginInterface pi, ClientLanguage language, DataManager gameData)
|
||||
: base(pi, Tag, language, ObjectIdentification.IdentificationVersion, CreateEquipmentList(gameData, language))
|
||||
{ }
|
||||
|
||||
public IEnumerable<Item> Between(SetId modelId, EquipSlot slot = EquipSlot.Unknown, byte variant = 0)
|
||||
public IEnumerable<EquipItem> Between(SetId modelId, EquipSlot slot = EquipSlot.Unknown, byte variant = 0)
|
||||
{
|
||||
if (slot == EquipSlot.Unknown)
|
||||
return Between(ToKey(modelId, 0, 0), ToKey(modelId, (EquipSlot)0xFF, 0xFF));
|
||||
|
|
@ -33,15 +33,10 @@ internal sealed class EquipmentIdentificationList : KeyList<Item>
|
|||
public static ulong ToKey(SetId modelId, EquipSlot slot, byte variant)
|
||||
=> ((ulong)modelId << 32) | ((ulong)slot << 16) | variant;
|
||||
|
||||
public static ulong ToKey(Item i)
|
||||
{
|
||||
var model = (SetId)((Lumina.Data.Parsing.Quad)i.ModelMain).A;
|
||||
var slot = ((EquipSlot)i.EquipSlotCategory.Row).ToSlot();
|
||||
var variant = (byte)((Lumina.Data.Parsing.Quad)i.ModelMain).B;
|
||||
return ToKey(model, slot, variant);
|
||||
}
|
||||
public static ulong ToKey(EquipItem i)
|
||||
=> ToKey(i.ModelId, i.Slot, i.Variant);
|
||||
|
||||
protected override IEnumerable<ulong> ToKeys(Item i)
|
||||
protected override IEnumerable<ulong> ToKeys(EquipItem i)
|
||||
{
|
||||
yield return ToKey(i);
|
||||
}
|
||||
|
|
@ -49,12 +44,12 @@ internal sealed class EquipmentIdentificationList : KeyList<Item>
|
|||
protected override bool ValidKey(ulong key)
|
||||
=> key != 0;
|
||||
|
||||
protected override int ValueKeySelector(Item data)
|
||||
=> (int)data.RowId;
|
||||
protected override int ValueKeySelector(EquipItem data)
|
||||
=> (int)data.Id;
|
||||
|
||||
private static IEnumerable<Item> CreateEquipmentList(DataManager gameData, ClientLanguage language)
|
||||
private static IEnumerable<EquipItem> CreateEquipmentList(DataManager gameData, ClientLanguage language)
|
||||
{
|
||||
var items = gameData.GetExcelSheet<Item>(language)!;
|
||||
return items.Where(i => ((EquipSlot)i.EquipSlotCategory.Row).IsEquipmentPiece());
|
||||
return items.Where(i => ((EquipSlot)i.EquipSlotCategory.Row).IsEquipmentPiece()).Select(EquipItem.FromArmor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,32 +5,41 @@ using System.Linq;
|
|||
using Dalamud;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Utility;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Penumbra.GameData.Data;
|
||||
|
||||
public sealed class ItemData : DataSharer, IReadOnlyDictionary<FullEquipType, IReadOnlyList<Item>>
|
||||
public sealed class ItemData : DataSharer, IReadOnlyDictionary<FullEquipType, IReadOnlyList<EquipItem>>
|
||||
{
|
||||
private readonly IReadOnlyList<IReadOnlyList<Item>> _items;
|
||||
private readonly IReadOnlyList<IReadOnlyList<EquipItem>> _items;
|
||||
|
||||
private static IReadOnlyList<IReadOnlyList<Item>> CreateItems(DataManager dataManager, ClientLanguage language)
|
||||
private static IReadOnlyList<IReadOnlyList<EquipItem>> CreateItems(DataManager dataManager, ClientLanguage language)
|
||||
{
|
||||
var tmp = Enum.GetValues<FullEquipType>().Select(t => new List<Item>(1024)).ToArray();
|
||||
var tmp = Enum.GetValues<FullEquipType>().Select(_ => new List<EquipItem>(1024)).ToArray();
|
||||
|
||||
var itemSheet = dataManager.GetExcelSheet<Item>(language)!;
|
||||
foreach (var item in itemSheet)
|
||||
foreach (var item in itemSheet.Where(i => i.Name.RawData.Length > 1))
|
||||
{
|
||||
var type = item.ToEquipType();
|
||||
if (type != FullEquipType.Unknown && item.Name.RawData.Length > 1)
|
||||
tmp[(int)type].Add(item);
|
||||
if (type.IsWeapon())
|
||||
{
|
||||
if (item.ModelMain != 0)
|
||||
tmp[(int)type].Add(EquipItem.FromMainhand(item));
|
||||
if (item.ModelSub != 0)
|
||||
tmp[(int)type].Add(EquipItem.FromOffhand(item));
|
||||
}
|
||||
else if (type != FullEquipType.Unknown)
|
||||
{
|
||||
tmp[(int)type].Add(EquipItem.FromArmor(item));
|
||||
}
|
||||
}
|
||||
|
||||
var ret = new IReadOnlyList<Item>[tmp.Length];
|
||||
ret[0] = Array.Empty<Item>();
|
||||
var ret = new IReadOnlyList<EquipItem>[tmp.Length];
|
||||
ret[0] = Array.Empty<EquipItem>();
|
||||
for (var i = 1; i < tmp.Length; ++i)
|
||||
ret[i] = tmp[i].OrderBy(item => item.Name.ToDalamudString().TextValue).ToArray();
|
||||
ret[i] = tmp[i].OrderBy(item => item.Name).ToArray();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -44,10 +53,10 @@ public sealed class ItemData : DataSharer, IReadOnlyDictionary<FullEquipType, IR
|
|||
protected override void DisposeInternal()
|
||||
=> DisposeTag("ItemList");
|
||||
|
||||
public IEnumerator<KeyValuePair<FullEquipType, IReadOnlyList<Item>>> GetEnumerator()
|
||||
public IEnumerator<KeyValuePair<FullEquipType, IReadOnlyList<EquipItem>>> GetEnumerator()
|
||||
{
|
||||
for (var i = 1; i < _items.Count; ++i)
|
||||
yield return new KeyValuePair<FullEquipType, IReadOnlyList<Item>>((FullEquipType)i, _items[i]);
|
||||
yield return new KeyValuePair<FullEquipType, IReadOnlyList<EquipItem>>((FullEquipType)i, _items[i]);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
|
|
@ -59,7 +68,7 @@ public sealed class ItemData : DataSharer, IReadOnlyDictionary<FullEquipType, IR
|
|||
public bool ContainsKey(FullEquipType key)
|
||||
=> (int)key < _items.Count && key != FullEquipType.Unknown;
|
||||
|
||||
public bool TryGetValue(FullEquipType key, out IReadOnlyList<Item> value)
|
||||
public bool TryGetValue(FullEquipType key, out IReadOnlyList<EquipItem> value)
|
||||
{
|
||||
if (ContainsKey(key))
|
||||
{
|
||||
|
|
@ -71,12 +80,12 @@ public sealed class ItemData : DataSharer, IReadOnlyDictionary<FullEquipType, IR
|
|||
return false;
|
||||
}
|
||||
|
||||
public IReadOnlyList<Item> this[FullEquipType key]
|
||||
public IReadOnlyList<EquipItem> this[FullEquipType key]
|
||||
=> TryGetValue(key, out var ret) ? ret : throw new IndexOutOfRangeException();
|
||||
|
||||
public IEnumerable<FullEquipType> Keys
|
||||
=> Enum.GetValues<FullEquipType>().Skip(1);
|
||||
|
||||
public IEnumerable<IReadOnlyList<Item>> Values
|
||||
public IEnumerable<IReadOnlyList<EquipItem>> Values
|
||||
=> _items.Skip(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier
|
|||
return ret;
|
||||
}
|
||||
|
||||
public IEnumerable<Item> Identify(SetId setId, WeaponType weaponType, ushort variant, EquipSlot slot)
|
||||
public IEnumerable<EquipItem> Identify(SetId setId, WeaponType weaponType, ushort variant, EquipSlot slot)
|
||||
=> slot switch
|
||||
{
|
||||
EquipSlot.MainHand => _weapons.Between(setId, weaponType, (byte)variant),
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ using Penumbra.GameData.Structs;
|
|||
|
||||
namespace Penumbra.GameData.Data;
|
||||
|
||||
internal sealed class WeaponIdentificationList : KeyList<Item>
|
||||
internal sealed class WeaponIdentificationList : KeyList<EquipItem>
|
||||
{
|
||||
private const string Tag = "WeaponIdentification";
|
||||
private const int Version = 1;
|
||||
|
|
@ -18,10 +18,10 @@ internal sealed class WeaponIdentificationList : KeyList<Item>
|
|||
: base(pi, Tag, language, Version, CreateWeaponList(gameData, language))
|
||||
{ }
|
||||
|
||||
public IEnumerable<Item> Between(SetId modelId)
|
||||
public IEnumerable<EquipItem> Between(SetId modelId)
|
||||
=> Between(ToKey(modelId, 0, 0), ToKey(modelId, 0xFFFF, 0xFF));
|
||||
|
||||
public IEnumerable<Item> Between(SetId modelId, WeaponType type, byte variant = 0)
|
||||
public IEnumerable<EquipItem> Between(SetId modelId, WeaponType type, byte variant = 0)
|
||||
{
|
||||
if (type == 0)
|
||||
return Between(ToKey(modelId, 0, 0), ToKey(modelId, 0xFFFF, 0xFF));
|
||||
|
|
@ -37,38 +37,31 @@ internal sealed class WeaponIdentificationList : KeyList<Item>
|
|||
public static ulong ToKey(SetId modelId, WeaponType type, byte variant)
|
||||
=> ((ulong)modelId << 32) | ((ulong)type << 16) | variant;
|
||||
|
||||
public static ulong ToKey(Item i, bool offhand)
|
||||
{
|
||||
var quad = offhand ? (Lumina.Data.Parsing.Quad)i.ModelSub : (Lumina.Data.Parsing.Quad)i.ModelMain;
|
||||
return ToKey(quad.A, quad.B, (byte)quad.C);
|
||||
}
|
||||
public static ulong ToKey(EquipItem i)
|
||||
=> ToKey(i.ModelId, i.WeaponType, i.Variant);
|
||||
|
||||
protected override IEnumerable<ulong> ToKeys(Item i)
|
||||
protected override IEnumerable<ulong> ToKeys(EquipItem data)
|
||||
{
|
||||
var key1 = 0ul;
|
||||
if (i.ModelMain != 0)
|
||||
{
|
||||
key1 = ToKey(i, false);
|
||||
yield return key1;
|
||||
}
|
||||
|
||||
if (i.ModelSub != 0)
|
||||
{
|
||||
var key2 = ToKey(i, true);
|
||||
if (key1 != key2)
|
||||
yield return key2;
|
||||
}
|
||||
yield return ToKey(data);
|
||||
}
|
||||
|
||||
protected override bool ValidKey(ulong key)
|
||||
=> key != 0;
|
||||
|
||||
protected override int ValueKeySelector(Item data)
|
||||
=> (int)data.RowId;
|
||||
protected override int ValueKeySelector(EquipItem data)
|
||||
=> (int)data.Id;
|
||||
|
||||
private static IEnumerable<Item> CreateWeaponList(DataManager gameData, ClientLanguage language)
|
||||
private static IEnumerable<EquipItem> CreateWeaponList(DataManager gameData, ClientLanguage language)
|
||||
=> gameData.GetExcelSheet<Item>(language)!.SelectMany(ToEquipItems);
|
||||
|
||||
private static IEnumerable<EquipItem> ToEquipItems(Item item)
|
||||
{
|
||||
var items = gameData.GetExcelSheet<Item>(language)!;
|
||||
return items.Where(i => (EquipSlot)i.EquipSlotCategory.Row is EquipSlot.MainHand or EquipSlot.OffHand or EquipSlot.BothHand);
|
||||
if ((EquipSlot)item.EquipSlotCategory.Row is not (EquipSlot.MainHand or EquipSlot.OffHand or EquipSlot.BothHand))
|
||||
yield break;
|
||||
|
||||
if (item.ModelMain != 0)
|
||||
yield return EquipItem.FromMainhand(item);
|
||||
if (item.ModelSub != 0)
|
||||
yield return EquipItem.FromOffhand(item);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,19 @@
|
|||
using System;
|
||||
using Dalamud.Data;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Action = Lumina.Excel.GeneratedSheets.Action;
|
||||
|
||||
namespace Penumbra.GameData.Enums;
|
||||
|
||||
public static class ChangedItemExtensions
|
||||
{
|
||||
public static (ChangedItemType, uint) ChangedItemToTypeAndId( object? item )
|
||||
public static (ChangedItemType, uint) ChangedItemToTypeAndId(object? item)
|
||||
{
|
||||
return item switch
|
||||
{
|
||||
null => ( ChangedItemType.None, 0 ),
|
||||
Item i => ( ChangedItemType.Item, i.RowId ),
|
||||
Action a => ( ChangedItemType.Action, a.RowId ),
|
||||
_ => ( ChangedItemType.Customization, 0 ),
|
||||
null => (ChangedItemType.None, 0),
|
||||
EquipItem i => (ChangedItemType.Item, i.Id),
|
||||
Action a => (ChangedItemType.Action, a.RowId),
|
||||
_ => (ChangedItemType.Customization, 0),
|
||||
};
|
||||
}
|
||||
|
||||
public static object? GetObject( this ChangedItemType type, DataManager manager, uint id )
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
ChangedItemType.None => null,
|
||||
ChangedItemType.Item => manager.GetExcelSheet< Item >()?.GetRow( id ),
|
||||
ChangedItemType.Action => manager.GetExcelSheet< Action >()?.GetRow( id ),
|
||||
ChangedItemType.Customization => null,
|
||||
_ => throw new ArgumentOutOfRangeException( nameof( type ), type, null ),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,26 +20,34 @@ public enum FullEquipType : byte
|
|||
Wrists,
|
||||
Finger,
|
||||
|
||||
Fists, // PGL, MNK
|
||||
Sword, // GLA, PLD Main
|
||||
Axe, // MRD, WAR
|
||||
Bow, // ARC, BRD
|
||||
Lance, // LNC, DRG,
|
||||
Staff, // THM, BLM, CNJ, WHM
|
||||
Wand, // THM, BLM, CNJ, WHM Main
|
||||
Book, // ACN, SMN, SCH
|
||||
Daggers, // ROG, NIN
|
||||
Fists, // PGL, MNK
|
||||
FistsOff,
|
||||
Sword, // GLA, PLD Main
|
||||
Axe, // MRD, WAR
|
||||
Bow, // ARC, BRD
|
||||
BowOff,
|
||||
Lance, // LNC, DRG,
|
||||
Staff, // THM, BLM, CNJ, WHM
|
||||
Wand, // THM, BLM, CNJ, WHM Main
|
||||
Book, // ACN, SMN, SCH
|
||||
Daggers, // ROG, NIN
|
||||
DaggersOff,
|
||||
Broadsword, // DRK,
|
||||
Gun, // MCH,
|
||||
Orrery, // AST,
|
||||
Katana, // SAM
|
||||
Rapier, // RDM
|
||||
Cane, // BLU
|
||||
Gunblade, // GNB,
|
||||
Glaives, // DNC,
|
||||
Scythe, // RPR,
|
||||
Nouliths, // SGE
|
||||
Shield, // GLA, PLD, THM, BLM, CNJ, WHM Off
|
||||
GunOff,
|
||||
Orrery, // AST,
|
||||
OrreryOff,
|
||||
Katana, // SAM
|
||||
KatanaOff,
|
||||
Rapier, // RDM
|
||||
RapierOff,
|
||||
Cane, // BLU
|
||||
Gunblade, // GNB,
|
||||
Glaives, // DNC,
|
||||
GlaivesOff,
|
||||
Scythe, // RPR,
|
||||
Nouliths, // SGE
|
||||
Shield, // GLA, PLD, THM, BLM, CNJ, WHM Off
|
||||
|
||||
Saw, // CRP
|
||||
CrossPeinHammer, // BSM
|
||||
|
|
@ -68,7 +76,7 @@ public enum FullEquipType : byte
|
|||
|
||||
public static class FullEquipTypeExtensions
|
||||
{
|
||||
public static FullEquipType ToEquipType(this Item item)
|
||||
internal static FullEquipType ToEquipType(this Item item)
|
||||
{
|
||||
var slot = (EquipSlot)item.EquipSlotCategory.Row;
|
||||
var weapon = (WeaponCategory)item.ItemUICategory.Row;
|
||||
|
|
@ -152,22 +160,30 @@ public static class FullEquipTypeExtensions
|
|||
FullEquipType.Wrists => EquipSlot.Wrists.ToName(),
|
||||
FullEquipType.Finger => "Ring",
|
||||
FullEquipType.Fists => "Fist Weapon",
|
||||
FullEquipType.FistsOff => "Fist Weapon (Offhand)",
|
||||
FullEquipType.Sword => "Sword",
|
||||
FullEquipType.Axe => "Axe",
|
||||
FullEquipType.Bow => "Bow",
|
||||
FullEquipType.BowOff => "Quiver",
|
||||
FullEquipType.Lance => "Lance",
|
||||
FullEquipType.Staff => "Staff",
|
||||
FullEquipType.Wand => "Mace",
|
||||
FullEquipType.Book => "Book",
|
||||
FullEquipType.Daggers => "Dagger",
|
||||
FullEquipType.DaggersOff => "Dagger (Offhand)",
|
||||
FullEquipType.Broadsword => "Broadsword",
|
||||
FullEquipType.Gun => "Gun",
|
||||
FullEquipType.GunOff => "Aetherotransformer",
|
||||
FullEquipType.Orrery => "Orrery",
|
||||
FullEquipType.OrreryOff => "Card Holder",
|
||||
FullEquipType.Katana => "Katana",
|
||||
FullEquipType.KatanaOff => "Sheathe",
|
||||
FullEquipType.Rapier => "Rapier",
|
||||
FullEquipType.RapierOff => "Focus",
|
||||
FullEquipType.Cane => "Cane",
|
||||
FullEquipType.Gunblade => "Gunblade",
|
||||
FullEquipType.Glaives => "Glaive",
|
||||
FullEquipType.GlaivesOff => "Glaive (Offhand)",
|
||||
FullEquipType.Scythe => "Scythe",
|
||||
FullEquipType.Nouliths => "Nouliths",
|
||||
FullEquipType.Shield => "Shield",
|
||||
|
|
@ -209,22 +225,30 @@ public static class FullEquipTypeExtensions
|
|||
FullEquipType.Wrists => EquipSlot.Wrists,
|
||||
FullEquipType.Finger => EquipSlot.RFinger,
|
||||
FullEquipType.Fists => EquipSlot.MainHand,
|
||||
FullEquipType.FistsOff => EquipSlot.OffHand,
|
||||
FullEquipType.Sword => EquipSlot.MainHand,
|
||||
FullEquipType.Axe => EquipSlot.MainHand,
|
||||
FullEquipType.Bow => EquipSlot.MainHand,
|
||||
FullEquipType.BowOff => EquipSlot.OffHand,
|
||||
FullEquipType.Lance => EquipSlot.MainHand,
|
||||
FullEquipType.Staff => EquipSlot.MainHand,
|
||||
FullEquipType.Wand => EquipSlot.MainHand,
|
||||
FullEquipType.Book => EquipSlot.MainHand,
|
||||
FullEquipType.Daggers => EquipSlot.MainHand,
|
||||
FullEquipType.DaggersOff => EquipSlot.OffHand,
|
||||
FullEquipType.Broadsword => EquipSlot.MainHand,
|
||||
FullEquipType.Gun => EquipSlot.MainHand,
|
||||
FullEquipType.GunOff => EquipSlot.OffHand,
|
||||
FullEquipType.Orrery => EquipSlot.MainHand,
|
||||
FullEquipType.OrreryOff => EquipSlot.OffHand,
|
||||
FullEquipType.Katana => EquipSlot.MainHand,
|
||||
FullEquipType.KatanaOff => EquipSlot.OffHand,
|
||||
FullEquipType.Rapier => EquipSlot.MainHand,
|
||||
FullEquipType.RapierOff => EquipSlot.OffHand,
|
||||
FullEquipType.Cane => EquipSlot.MainHand,
|
||||
FullEquipType.Gunblade => EquipSlot.MainHand,
|
||||
FullEquipType.Glaives => EquipSlot.MainHand,
|
||||
FullEquipType.GlaivesOff => EquipSlot.OffHand,
|
||||
FullEquipType.Scythe => EquipSlot.MainHand,
|
||||
FullEquipType.Nouliths => EquipSlot.MainHand,
|
||||
FullEquipType.Shield => EquipSlot.OffHand,
|
||||
|
|
@ -253,7 +277,7 @@ public static class FullEquipTypeExtensions
|
|||
_ => EquipSlot.Unknown,
|
||||
};
|
||||
|
||||
public static FullEquipType ToEquipType(this EquipSlot slot, WeaponCategory category = WeaponCategory.Unknown)
|
||||
public static FullEquipType ToEquipType(this EquipSlot slot, WeaponCategory category = WeaponCategory.Unknown, bool mainhand = true)
|
||||
=> slot switch
|
||||
{
|
||||
EquipSlot.Head => FullEquipType.Head,
|
||||
|
|
@ -273,77 +297,101 @@ public static class FullEquipTypeExtensions
|
|||
EquipSlot.BodyHands => FullEquipType.Body,
|
||||
EquipSlot.BodyLegsFeet => FullEquipType.Body,
|
||||
EquipSlot.ChestHands => FullEquipType.Body,
|
||||
EquipSlot.MainHand => category.ToEquipType(),
|
||||
EquipSlot.OffHand => category.ToEquipType(),
|
||||
EquipSlot.BothHand => category.ToEquipType(),
|
||||
EquipSlot.MainHand => category.ToEquipType(mainhand),
|
||||
EquipSlot.OffHand => category.ToEquipType(mainhand),
|
||||
EquipSlot.BothHand => category.ToEquipType(mainhand),
|
||||
_ => FullEquipType.Unknown,
|
||||
};
|
||||
|
||||
public static FullEquipType ToEquipType(this WeaponCategory category)
|
||||
public static FullEquipType ToEquipType(this WeaponCategory category, bool mainhand = true)
|
||||
=> category switch
|
||||
{
|
||||
WeaponCategory.Pugilist => FullEquipType.Fists,
|
||||
WeaponCategory.Gladiator => FullEquipType.Sword,
|
||||
WeaponCategory.Marauder => FullEquipType.Axe,
|
||||
WeaponCategory.Archer => FullEquipType.Bow,
|
||||
WeaponCategory.Lancer => FullEquipType.Lance,
|
||||
WeaponCategory.Thaumaturge1 => FullEquipType.Wand,
|
||||
WeaponCategory.Thaumaturge2 => FullEquipType.Staff,
|
||||
WeaponCategory.Conjurer1 => FullEquipType.Wand,
|
||||
WeaponCategory.Conjurer2 => FullEquipType.Staff,
|
||||
WeaponCategory.Arcanist => FullEquipType.Book,
|
||||
WeaponCategory.Shield => FullEquipType.Shield,
|
||||
WeaponCategory.CarpenterMain => FullEquipType.Saw,
|
||||
WeaponCategory.CarpenterOff => FullEquipType.ClawHammer,
|
||||
WeaponCategory.BlacksmithMain => FullEquipType.CrossPeinHammer,
|
||||
WeaponCategory.BlacksmithOff => FullEquipType.File,
|
||||
WeaponCategory.ArmorerMain => FullEquipType.RaisingHammer,
|
||||
WeaponCategory.ArmorerOff => FullEquipType.Pliers,
|
||||
WeaponCategory.GoldsmithMain => FullEquipType.LapidaryHammer,
|
||||
WeaponCategory.GoldsmithOff => FullEquipType.GrindingWheel,
|
||||
WeaponCategory.LeatherworkerMain => FullEquipType.Knife,
|
||||
WeaponCategory.LeatherworkerOff => FullEquipType.Awl,
|
||||
WeaponCategory.WeaverMain => FullEquipType.Needle,
|
||||
WeaponCategory.WeaverOff => FullEquipType.SpinningWheel,
|
||||
WeaponCategory.AlchemistMain => FullEquipType.Alembic,
|
||||
WeaponCategory.AlchemistOff => FullEquipType.Mortar,
|
||||
WeaponCategory.CulinarianMain => FullEquipType.Frypan,
|
||||
WeaponCategory.CulinarianOff => FullEquipType.CulinaryKnife,
|
||||
WeaponCategory.MinerMain => FullEquipType.Pickaxe,
|
||||
WeaponCategory.MinerOff => FullEquipType.Sledgehammer,
|
||||
WeaponCategory.BotanistMain => FullEquipType.Hatchet,
|
||||
WeaponCategory.BotanistOff => FullEquipType.GardenScythe,
|
||||
WeaponCategory.FisherMain => FullEquipType.FishingRod,
|
||||
WeaponCategory.Rogue => FullEquipType.Gig,
|
||||
WeaponCategory.DarkKnight => FullEquipType.Broadsword,
|
||||
WeaponCategory.Machinist => FullEquipType.Gun,
|
||||
WeaponCategory.Astrologian => FullEquipType.Orrery,
|
||||
WeaponCategory.Samurai => FullEquipType.Katana,
|
||||
WeaponCategory.RedMage => FullEquipType.Rapier,
|
||||
WeaponCategory.Scholar => FullEquipType.Book,
|
||||
WeaponCategory.FisherOff => FullEquipType.Gig,
|
||||
WeaponCategory.BlueMage => FullEquipType.Cane,
|
||||
WeaponCategory.Gunbreaker => FullEquipType.Gunblade,
|
||||
WeaponCategory.Dancer => FullEquipType.Glaives,
|
||||
WeaponCategory.Reaper => FullEquipType.Scythe,
|
||||
WeaponCategory.Sage => FullEquipType.Nouliths,
|
||||
_ => FullEquipType.Unknown,
|
||||
WeaponCategory.Pugilist when mainhand => FullEquipType.Fists,
|
||||
WeaponCategory.Pugilist => FullEquipType.FistsOff,
|
||||
WeaponCategory.Gladiator => FullEquipType.Sword,
|
||||
WeaponCategory.Marauder => FullEquipType.Axe,
|
||||
WeaponCategory.Archer when mainhand => FullEquipType.Bow,
|
||||
WeaponCategory.Archer => FullEquipType.BowOff,
|
||||
WeaponCategory.Lancer => FullEquipType.Lance,
|
||||
WeaponCategory.Thaumaturge1 => FullEquipType.Wand,
|
||||
WeaponCategory.Thaumaturge2 => FullEquipType.Staff,
|
||||
WeaponCategory.Conjurer1 => FullEquipType.Wand,
|
||||
WeaponCategory.Conjurer2 => FullEquipType.Staff,
|
||||
WeaponCategory.Arcanist => FullEquipType.Book,
|
||||
WeaponCategory.Shield => FullEquipType.Shield,
|
||||
WeaponCategory.CarpenterMain => FullEquipType.Saw,
|
||||
WeaponCategory.CarpenterOff => FullEquipType.ClawHammer,
|
||||
WeaponCategory.BlacksmithMain => FullEquipType.CrossPeinHammer,
|
||||
WeaponCategory.BlacksmithOff => FullEquipType.File,
|
||||
WeaponCategory.ArmorerMain => FullEquipType.RaisingHammer,
|
||||
WeaponCategory.ArmorerOff => FullEquipType.Pliers,
|
||||
WeaponCategory.GoldsmithMain => FullEquipType.LapidaryHammer,
|
||||
WeaponCategory.GoldsmithOff => FullEquipType.GrindingWheel,
|
||||
WeaponCategory.LeatherworkerMain => FullEquipType.Knife,
|
||||
WeaponCategory.LeatherworkerOff => FullEquipType.Awl,
|
||||
WeaponCategory.WeaverMain => FullEquipType.Needle,
|
||||
WeaponCategory.WeaverOff => FullEquipType.SpinningWheel,
|
||||
WeaponCategory.AlchemistMain => FullEquipType.Alembic,
|
||||
WeaponCategory.AlchemistOff => FullEquipType.Mortar,
|
||||
WeaponCategory.CulinarianMain => FullEquipType.Frypan,
|
||||
WeaponCategory.CulinarianOff => FullEquipType.CulinaryKnife,
|
||||
WeaponCategory.MinerMain => FullEquipType.Pickaxe,
|
||||
WeaponCategory.MinerOff => FullEquipType.Sledgehammer,
|
||||
WeaponCategory.BotanistMain => FullEquipType.Hatchet,
|
||||
WeaponCategory.BotanistOff => FullEquipType.GardenScythe,
|
||||
WeaponCategory.FisherMain => FullEquipType.FishingRod,
|
||||
WeaponCategory.FisherOff => FullEquipType.Gig,
|
||||
WeaponCategory.Rogue when mainhand => FullEquipType.DaggersOff,
|
||||
WeaponCategory.Rogue => FullEquipType.Daggers,
|
||||
WeaponCategory.DarkKnight => FullEquipType.Broadsword,
|
||||
WeaponCategory.Machinist when mainhand => FullEquipType.Gun,
|
||||
WeaponCategory.Machinist => FullEquipType.GunOff,
|
||||
WeaponCategory.Astrologian when mainhand => FullEquipType.Orrery,
|
||||
WeaponCategory.Astrologian => FullEquipType.OrreryOff,
|
||||
WeaponCategory.Samurai when mainhand => FullEquipType.Katana,
|
||||
WeaponCategory.Samurai => FullEquipType.KatanaOff,
|
||||
WeaponCategory.RedMage when mainhand => FullEquipType.Rapier,
|
||||
WeaponCategory.RedMage => FullEquipType.RapierOff,
|
||||
WeaponCategory.Scholar => FullEquipType.Book,
|
||||
WeaponCategory.BlueMage => FullEquipType.Cane,
|
||||
WeaponCategory.Gunbreaker => FullEquipType.Gunblade,
|
||||
WeaponCategory.Dancer when mainhand => FullEquipType.Glaives,
|
||||
WeaponCategory.Dancer => FullEquipType.GlaivesOff,
|
||||
WeaponCategory.Reaper => FullEquipType.Scythe,
|
||||
WeaponCategory.Sage => FullEquipType.Nouliths,
|
||||
_ => FullEquipType.Unknown,
|
||||
};
|
||||
|
||||
public static FullEquipType Offhand(this FullEquipType type)
|
||||
=> type switch
|
||||
{
|
||||
FullEquipType.Fists => FullEquipType.Fists,
|
||||
FullEquipType.Fists => FullEquipType.FistsOff,
|
||||
FullEquipType.Sword => FullEquipType.Shield,
|
||||
FullEquipType.Wand => FullEquipType.Shield,
|
||||
FullEquipType.Daggers => FullEquipType.Daggers,
|
||||
FullEquipType.Gun => FullEquipType.Gun,
|
||||
FullEquipType.Orrery => FullEquipType.Orrery,
|
||||
FullEquipType.Rapier => FullEquipType.Rapier,
|
||||
FullEquipType.Glaives => FullEquipType.Glaives,
|
||||
FullEquipType.Daggers => FullEquipType.DaggersOff,
|
||||
FullEquipType.Gun => FullEquipType.GunOff,
|
||||
FullEquipType.Orrery => FullEquipType.OrreryOff,
|
||||
FullEquipType.Rapier => FullEquipType.RapierOff,
|
||||
FullEquipType.Glaives => FullEquipType.GlaivesOff,
|
||||
FullEquipType.Bow => FullEquipType.BowOff,
|
||||
FullEquipType.Katana => FullEquipType.KatanaOff,
|
||||
_ => FullEquipType.Unknown,
|
||||
};
|
||||
|
||||
internal static string OffhandTypeSuffix(this FullEquipType type)
|
||||
=> type switch
|
||||
{
|
||||
FullEquipType.FistsOff => " (Offhand)",
|
||||
FullEquipType.DaggersOff => " (Offhand)",
|
||||
FullEquipType.GunOff => " (Aetherotransformer)",
|
||||
FullEquipType.OrreryOff => " (Card Holder)",
|
||||
FullEquipType.RapierOff => " (Focus)",
|
||||
FullEquipType.GlaivesOff => " (Offhand)",
|
||||
FullEquipType.BowOff => " (Quiver)",
|
||||
FullEquipType.KatanaOff => " (Sheathe)",
|
||||
_ => string.Empty,
|
||||
};
|
||||
|
||||
public static readonly IReadOnlyList<FullEquipType> WeaponTypes
|
||||
= Enum.GetValues<FullEquipType>().Where(v => v.IsWeapon()).ToArray();
|
||||
|
||||
|
|
|
|||
|
|
@ -58,10 +58,10 @@ public interface IObjectIdentifier : IDisposable
|
|||
/// <param name="weaponType">The secondary model ID for weapons, WeaponType.Zero for equipment and accessories.</param>
|
||||
/// <param name="variant">The variant ID of the model.</param>
|
||||
/// <param name="slot">The equipment slot the piece of equipment uses.</param>
|
||||
public IEnumerable<Item> Identify(SetId setId, WeaponType weaponType, ushort variant, EquipSlot slot);
|
||||
public IEnumerable<EquipItem> Identify(SetId setId, WeaponType weaponType, ushort variant, EquipSlot slot);
|
||||
|
||||
/// <inheritdoc cref="Identify(SetId, WeaponType, ushort, EquipSlot)"/>
|
||||
public IEnumerable<Item> Identify(SetId setId, ushort variant, EquipSlot slot)
|
||||
public IEnumerable<EquipItem> Identify(SetId setId, ushort variant, EquipSlot slot)
|
||||
=> Identify(setId, 0, variant, slot);
|
||||
}
|
||||
|
||||
|
|
|
|||
88
Penumbra.GameData/Structs/EquipItem.cs
Normal file
88
Penumbra.GameData/Structs/EquipItem.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Utility;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Penumbra.GameData.Structs;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public readonly struct EquipItem
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly uint Id;
|
||||
public readonly ushort IconId;
|
||||
public readonly SetId ModelId;
|
||||
public readonly WeaponType WeaponType;
|
||||
public readonly byte Variant;
|
||||
public readonly FullEquipType Type;
|
||||
public readonly EquipSlot Slot;
|
||||
|
||||
public bool Valid
|
||||
=> Type != FullEquipType.Unknown;
|
||||
|
||||
public CharacterArmor Armor()
|
||||
=> new(ModelId, Variant, 0);
|
||||
|
||||
public CharacterArmor Armor(StainId stain)
|
||||
=> new(ModelId, Variant, stain);
|
||||
|
||||
public CharacterWeapon Weapon()
|
||||
=> new(ModelId, WeaponType, Variant, 0);
|
||||
|
||||
public CharacterWeapon Weapon(StainId stain)
|
||||
=> new(ModelId, WeaponType, Variant, stain);
|
||||
|
||||
public EquipItem()
|
||||
=> Name = string.Empty;
|
||||
|
||||
public EquipItem(string name, uint id, ushort iconId, SetId modelId, WeaponType weaponType, byte variant, FullEquipType type,
|
||||
EquipSlot slot)
|
||||
{
|
||||
Name = name;
|
||||
Id = id;
|
||||
IconId = iconId;
|
||||
ModelId = modelId;
|
||||
WeaponType = weaponType;
|
||||
Variant = variant;
|
||||
Type = type;
|
||||
Slot = slot;
|
||||
}
|
||||
|
||||
|
||||
public static EquipItem FromArmor(Item item)
|
||||
{
|
||||
var type = item.ToEquipType();
|
||||
var slot = type.ToSlot();
|
||||
var name = string.Intern(item.Name.ToDalamudString().TextValue);
|
||||
var id = item.RowId;
|
||||
var icon = item.Icon;
|
||||
var model = (SetId)item.ModelMain;
|
||||
var weapon = (WeaponType)0;
|
||||
var variant = (byte)(item.ModelMain >> 16);
|
||||
return new EquipItem(name, id, icon, model, weapon, variant, type, slot);
|
||||
}
|
||||
|
||||
public static EquipItem FromMainhand(Item item)
|
||||
{
|
||||
var type = item.ToEquipType();
|
||||
var name = string.Intern(item.Name.ToDalamudString().TextValue);
|
||||
var id = item.RowId;
|
||||
var icon = item.Icon;
|
||||
var model = (SetId)item.ModelMain;
|
||||
var weapon = (WeaponType)(item.ModelMain >> 16);
|
||||
var variant = (byte)(item.ModelMain >> 32);
|
||||
return new EquipItem(name, id, icon, model, weapon, variant, type, EquipSlot.MainHand);
|
||||
}
|
||||
|
||||
public static EquipItem FromOffhand(Item item)
|
||||
{
|
||||
var type = item.ToEquipType().Offhand();
|
||||
var name = string.Intern(item.Name.ToDalamudString().TextValue + type.OffhandTypeSuffix());
|
||||
var id = item.RowId;
|
||||
var icon = item.Icon;
|
||||
var model = (SetId)item.ModelSub;
|
||||
var weapon = (WeaponType)(item.ModelSub >> 16);
|
||||
var variant = (byte)(item.ModelSub >> 32);
|
||||
return new EquipItem(name, id, icon, model, weapon, variant, type, EquipSlot.OffHand);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue