diff --git a/Assets/PerfectWorld/Prefab/UIManager.prefab b/Assets/PerfectWorld/Prefab/UIManager.prefab index c61b4646d2..473424f980 100644 --- a/Assets/PerfectWorld/Prefab/UIManager.prefab +++ b/Assets/PerfectWorld/Prefab/UIManager.prefab @@ -11684,6 +11684,7 @@ RectTransform: - {fileID: 984617901920738932} - {fileID: 2783469216819378410} - {fileID: 7889600498641702394} + - {fileID: 2430319032688992992} - {fileID: 8913509984865075419} - {fileID: 7306104429597638794} - {fileID: 5823843793071880086} @@ -11699,7 +11700,6 @@ RectTransform: - {fileID: 4528532603973220147} - {fileID: 4742272256638967314} - {fileID: 5087414730531131461} - - {fileID: 2430319032688992992} m_Father: {fileID: 3233441867675090637} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} diff --git a/Assets/PerfectWorld/Scripts/Common/DataProcess/generate_item_temp.cs b/Assets/PerfectWorld/Scripts/Common/DataProcess/generate_item_temp.cs index bca396a2b3..f48b60b137 100644 --- a/Assets/PerfectWorld/Scripts/Common/DataProcess/generate_item_temp.cs +++ b/Assets/PerfectWorld/Scripts/Common/DataProcess/generate_item_temp.cs @@ -1281,8 +1281,37 @@ public static class generate_item_temp skill_count ++; } - size += (uint)(Marshal.SizeOf(typeof(int))*2 * skill_count); + int pet_class; + switch(petess.id_type) + { + case 8781: // ��� + pet_class = 0; + break; + case 8782: // ս������ + pet_class = 1; + break; + case 8783: // ���ͳ��� + pet_class = 2; + break; + case 28752: // �ٻ��� + pet_class = 3; + break; + case 28913: // ֲ�� + pet_class = 4; + break; + case 37698: // �������� + pet_class = 5; + break; + default: + pet_class = 4; + break; + } + size += (uint)(sizeof(int)*2 * skill_count); + if(pet_class == 5) + { + size += (uint)Marshal.SizeOf(typeof(_evo_prop)); + } // allocate the buffer with exact length data = new byte[size]; int offset = 0; @@ -1303,35 +1332,23 @@ public static class generate_item_temp WriteInt(data, ref offset, 0); //��Ʒ��Ӧ�����ID guid WriteInt(data, ref offset, 0); //��Ʒ��Ӧ�����ID guid } + WriteInt(data, ref offset, ess.price); offset += sizeof(int); + + int content_length = 0; + int content_length_ptr = offset; + WriteInt(data, ref offset, 0); + int item_content = offset; + WriteInt(data, ref offset, 0); + content_length = (int)(size - offset); + WriteInt(data, ref content_length_ptr, content_length); + WriteInt(data, ref item_content, offset); + WriteInt(data, ref offset, petess.level_require); WriteInt(data, ref offset, (int)(petess.character_combo_id&0xFFFF)); WriteInt(data, ref offset, ess.honor_point); WriteInt(data, ref offset, (int)ess.id_pet); WriteInt(data, ref offset, 0); - WriteInt(data, ref offset, (int)ess.id); - - int pet_class; - switch(petess.id_type) - { - case 8781: // ��� - pet_class = 0; - break; - case 8782: // ս������ - pet_class = 1; - break; - case 8783: // ���ͳ��� - pet_class = 2; - break; - case 28752: // �ٻ��� - pet_class = 3; - break; - case 28913: // ֲ�� - pet_class = 4; - break; - default: - pet_class = 4; - break; - } + WriteInt(data, ref offset, (int)ess.id); WriteInt(data, ref offset, pet_class); WriteShort(data, ref offset, (short)ess.level); diff --git a/Assets/PerfectWorld/Scripts/GameData/ExpTypes.cs b/Assets/PerfectWorld/Scripts/GameData/ExpTypes.cs index d2c6fbce61..e7bb94ebd4 100644 --- a/Assets/PerfectWorld/Scripts/GameData/ExpTypes.cs +++ b/Assets/PerfectWorld/Scripts/GameData/ExpTypes.cs @@ -854,7 +854,7 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public ushort[] name; // Medicine name, max 15 characters - public string Name => ByteToStringUtils.UshortArrayToCP936String(name); + public string Name => ByteToStringUtils.UshortArrayToUnicodeString(name); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // Matter model file path @@ -2117,9 +2117,11 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public ushort[] name; // name, max 15 chars + public string Name => ByteToStringUtils.UshortArrayToUnicodeString(name); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // matter file path + public string FileMatter { get { return ByteToStringUtils.ByteArrayToCP936String(file_matter); } } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // icon file path diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs index 408d3ac2e9..c764722d2a 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs @@ -1035,7 +1035,7 @@ namespace BrewMonster.Scripts /// Get scaled price of specified count of items. /// Exact port of the C++ price scaling logic. /// - public static int GetScaledPrice(int iUnitPrice, int iCount, int iScaleType, float fScale) + public int GetScaledPrice(int iUnitPrice, int iCount, int iScaleType, float fScale) { if (iCount == 0) return 0; @@ -1047,10 +1047,9 @@ namespace BrewMonster.Scripts case ScaleType.SCALE_BUY: iPrice = (int)(iUnitPrice * fScale + 0.5f); if (iPrice >= 1000) - iPrice = ((iPrice + 99) / 100) * 100; + iPrice = (int)((iPrice + 99) / 100) * 100; else if (iPrice >= 100) - iPrice = ((iPrice + 9) / 10) * 10; - + iPrice = (int)((iPrice + 9) / 10) * 10; iPrice *= iCount; break; @@ -1141,8 +1140,6 @@ namespace BrewMonster.Scripts public virtual int GetScaledPrice() { int iPrice = m_iScaleType == (int)ScaleType.SCALE_BUY ? m_iShopPrice : m_iPrice; - string str = m_iScaleType == (int)ScaleType.SCALE_BUY ? "ShopPrice" : "Price"; - Debug.Log($"GetScaledPrice: iPrice: {iPrice} is {str}, m_iScaleType: {m_iScaleType}, m_fPriceScale: {m_fPriceScale}"); return GetScaledPrice(iPrice, m_iCount, m_iScaleType, m_fPriceScale); } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrMedicine.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrMedicine.cs index 52a948990a..e1ec11286c 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrMedicine.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrMedicine.cs @@ -97,12 +97,19 @@ namespace BrewMonster.Scripts { m_strDesc = string.Empty; - BMLogger.Log("EC_IvtrMedicine: GetNormalDesc: m_iLevelReq: " + m_iLevelReq); + CECStringTab pDescTab = EC_Game.GetItemDesc(); + int red = (int)DescriptipionMsg.ITEMDESC_COL_RED; + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int namecol = DecideNameCol(); + + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + // Level requirement if (m_iLevelReq > 0) { - BMLogger.Log("EC_IvtrMedicine: m_iLevelReq: " + m_iLevelReq); - BMLogger.Log("EC_IvtrMedicine: GetMaxLevelSofar: " + CECGameRun.Instance.GetHostPlayer().GetMaxLevelSofar()); int col = CECGameRun.Instance.GetHostPlayer().GetMaxLevelSofar() >= m_iLevelReq ? (int)DescriptipionMsg.ITEMDESC_COL_WHITE : (int)DescriptipionMsg.ITEMDESC_COL_RED; AddDescText(col, true, EC_Game.GetItemDesc().GetWideString((int)DescriptipionMsg.ITEMDESC_LEVELREQ), m_iLevelReq); } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrPetEgg.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrPetEgg.cs index 40049b5361..5ce7104a8f 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrPetEgg.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrPetEgg.cs @@ -209,9 +209,9 @@ namespace BrewMonster.Scripts // Item name: always use the name in template if (m_iCount > 1) - AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), m_pDBEssence.name/* GetName() */, m_iCount); + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), m_pDBEssence.Name/* GetName() */, m_iCount); else - AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), m_pDBEssence.name/* GetName() */); + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), m_pDBEssence.Name/* GetName() */); AddIDDescText(); @@ -238,7 +238,6 @@ namespace BrewMonster.Scripts AddDescText(-1, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLORRECT), strColor); } } - // Food type requirement AddFoodTypeDesc(); diff --git a/Assets/PerfectWorld/Scripts/UI/NPCShopDetailPanel.cs b/Assets/PerfectWorld/Scripts/UI/NPCShopDetailPanel.cs index 41bc569ac6..dee7310bae 100644 --- a/Assets/PerfectWorld/Scripts/UI/NPCShopDetailPanel.cs +++ b/Assets/PerfectWorld/Scripts/UI/NPCShopDetailPanel.cs @@ -60,9 +60,7 @@ public class NPCShopDetailPanel : MonoBehaviour if (itemDescriptionText != null) { string description = GetItemDescription((int)currentItem.id); - Debug.Log("[NPCShopDetail] RAW:\n" + description); description = SanitizeDescription(description); - Debug.Log("[NPCShopDetail] Sanitized:\n" + description); itemDescriptionText.Set(description); } @@ -180,6 +178,7 @@ public class NPCShopDetailPanel : MonoBehaviour // For NPC shop items, we typically have static data only // Try to get description using GetNormalDesc() which works with base stats + equipment.SetPriceScale((int)EC_IvtrItem.ScaleType.SCALE_BUY, 1f); string equipDesc = equipment.GetDesc(); if (!string.IsNullOrEmpty(equipDesc)) { @@ -201,6 +200,7 @@ public class NPCShopDetailPanel : MonoBehaviour { // For NPC shop, we typically have static data only, so load from local DB item.GetDetailDataFromLocal(); + item.SetPriceScale((int)EC_IvtrItem.ScaleType.SCALE_BUY, 1f); string description = item.GetDesc(); if (!string.IsNullOrEmpty(description)) { diff --git a/Assets/PerfectWorld/Scripts/UI/NPCShopUIManager.cs b/Assets/PerfectWorld/Scripts/UI/NPCShopUIManager.cs index f4f623bb84..a9160ac4b4 100644 --- a/Assets/PerfectWorld/Scripts/UI/NPCShopUIManager.cs +++ b/Assets/PerfectWorld/Scripts/UI/NPCShopUIManager.cs @@ -337,24 +337,51 @@ public class NPCShopUIManager : AUIDialog return; var page = sellService.pages[pageIndex]; - + // Create item panels if (page.goods != null) { var elementDataMan = ElementDataManProvider.GetElementDataMan(); if (elementDataMan == null) return; - + DATA_TYPE itemDataTypeCheck = DATA_TYPE.DT_INVALID; + object itemDataCheck = elementDataMan.get_data_ptr(page.goods[0].id, ID_SPACE.ID_SPACE_ESSENCE, ref itemDataTypeCheck); + if (itemDataCheck == null) + return; + int[] goodIndexSortedByRemap = new int[page.goods.Length]; + bool isRemaping = false; + // If 3C want to change shop behavior. Uncomment this code. + // if (itemDataTypeCheck == DATA_TYPE.DT_WEAPON_ESSENCE || + // itemDataTypeCheck == DATA_TYPE.DT_ARMOR_ESSENCE || + // itemDataTypeCheck == DATA_TYPE.DT_DECORATION_ESSENCE || + // itemDataTypeCheck == DATA_TYPE.DT_PROJECTILE_ESSENCE) + // { + // isRemaping = true; + // int[] remapingGoodIndex = new int[page.goods.Length]; + // for (int i = 0; i < page.goods.Length; i++) + // { + // //chnge the coord x to coord y and the viceversa with the max length of x is 8 + // int newX = i % 8; + // int newY = i / 8; + // remapingGoodIndex[i] = newX * 4 + newY; + // } + // // Original good indices 0..n-1 ordered so remapingGoodIndex[i] is ascending (display order by remap slot). + // for (int j = 0; j < goodIndexSortedByRemap.Length; j++) + // goodIndexSortedByRemap[j] = j; + // Array.Sort(goodIndexSortedByRemap, (a, b) => remapingGoodIndex[a].CompareTo(remapingGoodIndex[b])); + // } + + + for (int i = 0; i < page.goods.Length; i++) { - var good = page.goods[i]; + var good = page.goods[isRemaping? goodIndexSortedByRemap[i] : i]; if (good.id == 0) continue; // Get item essence DATA_TYPE itemDataType = DATA_TYPE.DT_INVALID; object itemData = elementDataMan.get_data_ptr(good.id, ID_SPACE.ID_SPACE_ESSENCE, ref itemDataType); - if (itemData == null) continue; @@ -364,6 +391,7 @@ public class NPCShopUIManager : AUIDialog // Create panel with absolute shop slot index (server validates npc_trade_item.index against full shop list). int absoluteShopSlotIndex = GetAbsoluteShopSlotIndex(sellService, pageIndex, i); CreateItemPanel(shopItem, absoluteShopSlotIndex); + // log the name and the position of the item } } } @@ -393,11 +421,9 @@ public class NPCShopUIManager : AUIDialog // Initialize buy array with at least one option shopItem.buy = new GShopBuyOption[4]; // GShopItem supports up to 4 buy options - // Get item name and price based on type string itemName = "Unknown"; int shopPrice = 0; - switch (itemDataType) { case DATA_TYPE.DT_WEAPON_ESSENCE: @@ -430,13 +456,45 @@ public class NPCShopUIManager : AUIDialog itemName = ByteToStringUtils.UshortArrayToUnicodeString(materialEssence.name); shopPrice = materialEssence.shop_price; break; + case DATA_TYPE.DT_PET_EGG_ESSENCE: + var petEggEssence = (PET_EGG_ESSENCE)itemData; + itemName = ByteToStringUtils.UshortArrayToUnicodeString(petEggEssence.name); + shopPrice = petEggEssence.shop_price; + break; + case DATA_TYPE.DT_PET_FOOD_ESSENCE: + var petFoodEssence = (PET_FOOD_ESSENCE)itemData; + itemName = ByteToStringUtils.UshortArrayToUnicodeString(petFoodEssence.name); + shopPrice = petFoodEssence.shop_price; + break; + case DATA_TYPE.DT_PROJECTILE_ESSENCE: + var projectileEssence = (PROJECTILE_ESSENCE)itemData; + itemName = ByteToStringUtils.UshortArrayToUnicodeString(projectileEssence.name); + shopPrice = projectileEssence.shop_price; + break; default: itemName = $"Item_{good.id}"; break; } + // This is modified item price after tax of server. + float fPriceScale = 1.0f; + int idServiceNPC = EC_Game.GetGameRun().GetHostPlayer().GetCurServiceNPC(); + CECNPC pNPC = EC_Game.GetGameRun().GetWorld().GetNPCMan().GetNPC(idServiceNPC); + CECNPCServer pServer = (CECNPCServer)pNPC; + if (pServer) + { + fPriceScale = (1.0f + pServer.GetTaxRate()) * pServer.GetPriceScale(); + } shopItem.name = itemName; - + shopPrice = (int)(shopPrice * fPriceScale); + if(shopPrice > 1000) + { + shopPrice = (shopPrice +99) /100 * 100; + } + else if (shopPrice > 100) + { + shopPrice = (shopPrice +9) /10 * 10; + } // Set price from contribution cost or shop price if (good.contrib_cost > 0) { diff --git a/Assets/Prefabs/UI/DialogNPCShop.prefab b/Assets/Prefabs/UI/DialogNPCShop.prefab index 3b88d20408..acfb6a881e 100644 --- a/Assets/Prefabs/UI/DialogNPCShop.prefab +++ b/Assets/Prefabs/UI/DialogNPCShop.prefab @@ -8459,7 +8459,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 487.261, y: 0} + m_SizeDelta: {x: 0, y: 70} m_Pivot: {x: 0, y: 1} --- !u!114 &6672743718559016642 MonoBehaviour: @@ -8483,8 +8483,8 @@ MonoBehaviour: m_StartAxis: 0 m_CellSize: {x: 168, y: 70} m_Spacing: {x: 0, y: 0} - m_Constraint: 0 - m_ConstraintCount: 2 + m_Constraint: 2 + m_ConstraintCount: 1 --- !u!114 &684255110392183903 MonoBehaviour: m_ObjectHideFlags: 0 @@ -8497,8 +8497,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} m_Name: m_EditorClassIdentifier: - m_HorizontalFit: 0 - m_VerticalFit: 2 + m_HorizontalFit: 2 + m_VerticalFit: 0 --- !u!1 &3995938121054417032 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 5a63a0e17b..4ac473a19b 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -4335,7 +4335,8 @@ namespace BrewMonster // // CECPlayer::Release(); } - } + public int GetCurServiceNPC() { return m_idSevNPC; } + } public sealed class CECHPTraceSpellMatcher : CECHPWorkMatcher { public override bool Match(CECHPWork pWork, int priority, bool isDelayWork)