diff --git a/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll b/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll index 5577fab086..73c62b0a4a 100644 Binary files a/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll and b/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll differ diff --git a/Assets/PerfectWorld/Resources/UI/Inventory/pw show item.png.meta b/Assets/PerfectWorld/Resources/UI/Inventory/pw show item.png.meta index b435c70fe8..89a88abc59 100644 --- a/Assets/PerfectWorld/Resources/UI/Inventory/pw show item.png.meta +++ b/Assets/PerfectWorld/Resources/UI/Inventory/pw show item.png.meta @@ -113,7 +113,7 @@ TextureImporter: customData: physicsShape: [] bones: [] - spriteID: + spriteID: 5e97eb03825dee720800000000000000 internalID: 0 vertices: [] indices: diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs index 463e9229ad..907bfcbff2 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs @@ -5,6 +5,7 @@ using UnityEngine.UI; using System.Reflection; using BrewMonster.Network; using BrewMonster; +using ModelRenderer.Scripts.GameData; namespace PerfectWorld.Scripts.Managers { @@ -157,7 +158,7 @@ namespace PerfectWorld.Scripts.Managers // For equipping, we need to find an empty equipment slot // The equip location should be determined by the item type or use a default byte equipLocation = GetEquipLocationForItem(currentSelectedItem.TemplateId); - if (equipLocation == 0) + if (equipLocation >= (byte)IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR) { Debug.LogWarning($"[InventoryUI] Could not determine equip location for item {currentSelectedItem.TemplateId}"); return; @@ -199,37 +200,114 @@ namespace PerfectWorld.Scripts.Managers private byte GetEquipLocationForItem(int templateId) { - // Simple approach: use the template ID to determine equip location - // This is a basic mapping - you may need to adjust based on your game's logic + // Determine exact equipment slot index based on item type/essence try { - // Try to get equip location from ESSENCE data first var edm = ElementDataManProvider.GetElementDataMan(); - if (edm != null) + if (edm == null) { - uint id = unchecked((uint)templateId); - object data = edm.get_data_ptr(id, ID_SPACE.ID_SPACE_ESSENCE); - if (data != null) + Debug.LogWarning("[InventoryUI] ElementDataMan not initialized"); + return (byte)IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR; + } + + uint id = unchecked((uint)templateId); + + // Weapons + foreach (var it in edm.weapon_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_WEAPON; + } + + // Projectiles (quiver / projectile essence) + foreach (var it in edm.quiver_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_PROJECTILE; + } + foreach (var it in edm.projectile_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_PROJECTILE; + } + + // Flysword + foreach (var it in edm.flysword_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_FLYSWORD; + } + + // Armor -> derive from sub-type mask + foreach (var it in edm.armor_essence_array) + { + if (it.id == id) { - var equipLocationField = data.GetType().GetField("equip_location", BindingFlags.Public | BindingFlags.Instance); - if (equipLocationField != null && equipLocationField.FieldType == typeof(uint)) + var slot = ResolveArmorSlotBySubtype(edm, it.id_sub_type); + if (slot < IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR) { - uint equipLocation = (uint)equipLocationField.GetValue(data); - Debug.Log($"[InventoryUI] Found equip_location {equipLocation} for template {templateId}"); - return (byte)equipLocation; + return (byte)slot; } + break; } } - - // Fallback: use a simple mapping based on template ID ranges - // This is a basic implementation - adjust based on your game's item system - Debug.Log($"[InventoryUI] Using fallback equip location for template {templateId}"); - return GetDefaultEquipLocation(templateId); + + // Fashion -> derive from sub-type mask + foreach (var it in edm.fashion_essence_array) + { + if (it.id == id) + { + var slot = ResolveFashionSlotBySubtype(edm, it.id_sub_type); + if (slot < IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR) + { + return (byte)slot; + } + break; + } + } + + // Runes + foreach (var it in edm.damagerune_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_RUNE; + } + foreach (var it in edm.armorrune_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_RUNE; + } + + // Special slots + foreach (var it in edm.bible_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_BIBLE; + } + foreach (var it in edm.speaker_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_SPEAKER; + } + foreach (var it in edm.autohp_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_AUTOHP; + } + foreach (var it in edm.automp_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_AUTOMP; + } + foreach (var it in edm.force_token_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_FORCE_TOKEN; + } + foreach (var it in edm.sell_certificate_essence_array) + { + if (it.id == id) return (byte)IndexOfIteminEquipmentInventory.EQUIPIVTR_CERTIFICATE; + } + + // Fashion weapon (if present in your data as essence/config) + // If you add a dedicated essence array for fashion weapons, map it here + + Debug.LogWarning($"[InventoryUI] Equip index not found for template {templateId}"); + return (byte)IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR; } catch (Exception ex) { - Debug.LogWarning($"[InventoryUI] Error getting equip location for template {templateId}: {ex.Message}"); - return GetDefaultEquipLocation(templateId); + Debug.LogWarning($"[InventoryUI] Error resolving equip index for template {templateId}: {ex.Message}"); + return (byte)IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR; } } @@ -237,7 +315,7 @@ namespace PerfectWorld.Scripts.Managers { // Basic equip location mapping based on template ID // Adjust these ranges based on your game's item system - if (templateId >= 1000 && templateId < 2000) return 1; // Weapon + if (templateId >= 1000 && templateId < 2000) return 0; // Weapon if (templateId >= 2000 && templateId < 3000) return 2; // Armor if (templateId >= 3000 && templateId < 4000) return 3; // Accessory if (templateId >= 4000 && templateId < 5000) return 4; // Ring @@ -245,7 +323,7 @@ namespace PerfectWorld.Scripts.Managers // Default to slot 1 if no specific mapping Debug.Log($"[InventoryUI] Using default equip location 1 for template {templateId}"); - return 1; + return 0; } private int FindEmptyInventorySlot() @@ -264,6 +342,84 @@ namespace PerfectWorld.Scripts.Managers return -1; } + // === Equipment indices (copy kept local for clarity) === + private enum IndexOfIteminEquipmentInventory : byte + { + EQUIPIVTR_WEAPON = 0, + EQUIPIVTR_HEAD, + EQUIPIVTR_NECK, + EQUIPIVTR_SHOULDER, + EQUIPIVTR_BODY, + EQUIPIVTR_WAIST, + EQUIPIVTR_LEG, + EQUIPIVTR_FOOT, + EQUIPIVTR_WRIST, + EQUIPIVTR_FINGER1, + EQUIPIVTR_FINGER2, + EQUIPIVTR_PROJECTILE, + EQUIPIVTR_FLYSWORD, + EQUIPIVTR_FASHION_BODY, + EQUIPIVTR_FASHION_LEG, + EQUIPIVTR_FASHION_FOOT, + EQUIPIVTR_FASHION_WRIST, + EQUIPIVTR_RUNE, + EQUIPIVTR_BIBLE, + EQUIPIVTR_SPEAKER, + EQUIPIVTR_AUTOHP, + EQUIPIVTR_AUTOMP, + EQUIPIVTR_POCKET, + EQUIPIVTR_GOBLIN, + EQUIPIVTR_CERTIFICATE, + EQUIPIVTR_FASHION_HEAD, + EQUIPIVTR_FORCE_TOKEN, + EQUIPIVTR_DYNSKILLEQUIP1, + EQUIPIVTR_DYNSKILLEQUIP2, + EQUIPIVTR_FASHION_WEAPON, + SIZE_EQUIPIVTR, + } + + private static IndexOfIteminEquipmentInventory ResolveArmorSlotBySubtype(elementdataman edm, uint armorSubTypeId) + { + foreach (var sub in edm.armor_sub_type_array) + { + if (sub.id != armorSubTypeId) continue; + uint mask = sub.equip_mask; + // Map first set bit to equipment index + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_HEAD)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_HEAD; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_NECK)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_NECK; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_SHOULDER)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_SHOULDER; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_BODY)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_BODY; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_WAIST)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_WAIST; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_LEG)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_LEG; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FOOT)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FOOT; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_WRIST)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_WRIST; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER1)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER1; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER2)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER2; + // Default not found + break; + } + return IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR; + } + + private static IndexOfIteminEquipmentInventory ResolveFashionSlotBySubtype(elementdataman edm, uint fashionSubTypeId) + { + foreach (var sub in edm.fashion_sub_type_array) + { + if (sub.id != fashionSubTypeId) continue; + uint mask = sub.equip_fashion_mask; + // Map first set bit to fashion equipment index + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_HEAD)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_HEAD; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_BODY)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_BODY; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_LEG)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_LEG; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_FOOT)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_FOOT; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_WRIST)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_WRIST; + if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_WEAPON)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_WEAPON; + // Default not found + break; + } + return IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR; + } + // === MVC: Model === private class InventoryModel { diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index f9f0ccf0d0..1751ce9be4 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -211,6 +211,9 @@ public class CECHostPlayer : MonoBehaviour OnMsgHstOwnItemInfo(Msg); break; } + case int value when value == EC_MsgDef.MSG_HST_ITEMOPERATION: + Debug.Log("HungDev : MSG_HST_ITEMOPERATION"); + break; } } public void OnMsgHstOwnItemInfo(ECMSG Msg)