Fix Shop Price UI. Fix some item that not showing data in shop.

This commit is contained in:
Chomper9981
2026-04-10 11:18:49 +07:00
parent 9af714a807
commit 1eb07ce750
10 changed files with 135 additions and 54 deletions
+1 -1
View File
@@ -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}
@@ -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);
@@ -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
@@ -1035,7 +1035,7 @@ namespace BrewMonster.Scripts
/// Get scaled price of specified count of items.
/// Exact port of the C++ price scaling logic.
/// </summary>
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);
}
@@ -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);
}
@@ -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();
@@ -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))
{
@@ -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)
{
+5 -5
View File
@@ -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
+2 -1
View File
@@ -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)