1362 lines
41 KiB
C#
1362 lines
41 KiB
C#
// Filename : NPCShopUIManager.cs
|
|
// Creator : Converted from C++ EC_Shop
|
|
// Date : 2024
|
|
|
|
using BrewMonster;
|
|
using BrewMonster.Network;
|
|
using BrewMonster.Scripts.Managers;
|
|
|
|
using BrewMonster.Scripts;
|
|
using BrewMonster.UI;
|
|
using CSNetwork.C2SCommand;
|
|
using ModelRenderer.Scripts.Common;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using static CSNetwork.Common.ExpTypes;
|
|
|
|
public class NPCShopUIManager : AUIDialog
|
|
{
|
|
[Header("UI Panels")]
|
|
public GameObject npcShopMainPanel;
|
|
public Image itemIconImage;
|
|
public GameObject contentMidBuy;
|
|
public GameObject contentRight;
|
|
public GameObject contentMidSell;
|
|
public GameObject item_info;
|
|
public ScrollRect scrollDetailItem;
|
|
public ScrollRect scrollListItem;
|
|
|
|
[Header("Texts")]
|
|
public TextMeshProUGUI itemDetailNameText;
|
|
public TextMeshProUGUI itemMoneyText;
|
|
public NPCShopDetailPanel itemDescriptionText;
|
|
public TextMeshProUGUI itemsBuyAmountText;
|
|
public TextMeshProUGUI itemsBuyTotalMoneyText;
|
|
public TextMeshProUGUI itemsSellTotalMoneyText;
|
|
|
|
[Header("Tabs")]
|
|
public Transform tabButtonContainer;
|
|
public GameObject tabButtonPrefab;
|
|
public string tabButtonTextComponentName = "Text";
|
|
|
|
[Header("Item Display")]
|
|
public Transform itemContainer;
|
|
public GameObject itemPanelPrefab;
|
|
|
|
[Header("Main Panel Components")]
|
|
public Button closeShopButton;
|
|
|
|
[Header("Sprite")]
|
|
[SerializeField] private Sprite khung_item;
|
|
|
|
[Header("Buttons")]
|
|
[SerializeField] private Button m_btn_tab_buy;
|
|
[SerializeField] private Button m_btn_tab_sell;
|
|
[SerializeField] private Button m_btn_repair;
|
|
[SerializeField] private Button m_btn_major_overhaul;
|
|
[SerializeField] private Button m_btn_reduce;
|
|
[SerializeField] private Button m_btn_incre;
|
|
[SerializeField] private Button m_btn_max;
|
|
[SerializeField] private Button m_btn_buy;
|
|
[SerializeField] private Button m_btn_sell;
|
|
[SerializeField] private Button m_use_Item;
|
|
[SerializeField] private List<Button> itemReadySell = new List<Button>();
|
|
|
|
|
|
private List<GameObject> currentItemPanels = new List<GameObject>();
|
|
private List<GameObject> currentTabButtons = new List<GameObject>();
|
|
private readonly Dictionary<int, int> sellSlotToSourceSlot = new Dictionary<int, int>();
|
|
private List<int> tabPageMapping = new List<int>(); // Maps tab index to page index
|
|
private int currentTabIndex = 0;
|
|
private uint currentNPCID = 0;
|
|
private NPC_SELL_SERVICE? cachedSellService = null;
|
|
private GShopItem currentItem;
|
|
private NPCShopUIManager shopManager;
|
|
private int shopItemIndex;
|
|
private Color colorUnActive = new Color(1f, 1f, 1f, 0f);
|
|
private Color colorActive = new Color(1f, 1f, 1f, 1f);
|
|
private int buyCount = 1;
|
|
private const int BuyCountMin = 1;
|
|
private const string BuyUiEmptyValue = "0";
|
|
private const int BuyCountFallbackMax = 99;
|
|
|
|
/// <summary>Current NPC id for this shop session. Send SEVNPC_HELLO with this before buy.</summary>
|
|
public uint CurrentNPCID => currentNPCID;
|
|
|
|
public override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
closeShopButton.onClick.AddListener(CloseShop);
|
|
if(m_btn_tab_buy != null)
|
|
{
|
|
m_btn_tab_buy.onClick.AddListener(OnClickTabButtonBuy);
|
|
}
|
|
if(m_btn_tab_sell != null)
|
|
{
|
|
m_btn_tab_sell.onClick.AddListener(OnClickTabButtonSell);
|
|
}
|
|
}
|
|
|
|
public override void OnDisable()
|
|
{
|
|
base.OnDisable();
|
|
closeShopButton.onClick.RemoveListener(CloseShop);
|
|
if(m_btn_tab_buy != null)
|
|
{
|
|
m_btn_tab_buy.onClick.RemoveListener(OnClickTabButtonBuy);
|
|
}
|
|
if(m_btn_tab_sell != null)
|
|
{
|
|
m_btn_tab_sell.onClick.RemoveListener(OnClickTabButtonSell);
|
|
}
|
|
}
|
|
|
|
public override void Start()
|
|
{
|
|
base.Start();
|
|
SetupEventListeners();
|
|
}
|
|
|
|
public void OpenNPCShop(uint npcID)
|
|
{
|
|
if (npcShopMainPanel == null)
|
|
{
|
|
Debug.LogError("NPCShopUIManager: npcShopMainPanel is null!");
|
|
return;
|
|
}
|
|
|
|
// Get NPC ID from CECUIManager
|
|
uint actualNPCID = npcID;
|
|
CECUIManager uiManager = CECUIManager.Instance;
|
|
if (uiManager != null)
|
|
{
|
|
int managerNPCID = uiManager.GetCurrentTargetNPCID();
|
|
if (managerNPCID > 0)
|
|
{
|
|
actualNPCID = (uint)managerNPCID;
|
|
}
|
|
}
|
|
|
|
currentNPCID = actualNPCID;
|
|
|
|
// Load sell service data
|
|
if (!LoadSellService(actualNPCID))
|
|
{
|
|
Debug.LogError($"NPCShopUIManager: Failed to load sell service for NPC {actualNPCID}");
|
|
return;
|
|
}
|
|
|
|
// // Show panel
|
|
// npcShopMainPanel.SetActive(true);
|
|
|
|
// Create tabs
|
|
CreateTabs();
|
|
|
|
// Select first tab
|
|
if (tabPageMapping.Count > 0)
|
|
{
|
|
OnTabSelected(0);
|
|
}
|
|
RefreshShopDisplay();
|
|
}
|
|
|
|
bool LoadSellService(uint npcID)
|
|
{
|
|
try
|
|
{
|
|
var elementDataMan = ElementDataManProvider.GetElementDataMan();
|
|
if (elementDataMan == null)
|
|
return false;
|
|
|
|
// Get NPC_ESSENCE
|
|
DATA_TYPE dataType = DATA_TYPE.DT_INVALID;
|
|
object npcData = elementDataMan.get_data_ptr(npcID, ID_SPACE.ID_SPACE_ESSENCE, ref dataType);
|
|
|
|
if (dataType != DATA_TYPE.DT_NPC_ESSENCE || npcData == null)
|
|
return false;
|
|
|
|
NPC_ESSENCE npcEssence = (NPC_ESSENCE)npcData;
|
|
uint sellServiceID = npcEssence.id_sell_service;
|
|
|
|
if (sellServiceID == 0)
|
|
return false;
|
|
|
|
// Get NPC_SELL_SERVICE
|
|
DATA_TYPE serviceDataType = DATA_TYPE.DT_INVALID;
|
|
object serviceData = elementDataMan.get_data_ptr(sellServiceID, ID_SPACE.ID_SPACE_ESSENCE, ref serviceDataType);
|
|
|
|
if (serviceDataType != DATA_TYPE.DT_NPC_SELL_SERVICE || serviceData == null)
|
|
return false;
|
|
|
|
cachedSellService = (NPC_SELL_SERVICE)serviceData;
|
|
return true;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.LogError($"NPCShopUIManager: Exception loading sell service: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void CreateTabs()
|
|
{
|
|
ClearTabs();
|
|
|
|
if (currentNPCID == 0 || tabButtonContainer == null || tabButtonPrefab == null)
|
|
return;
|
|
|
|
if (!cachedSellService.HasValue || cachedSellService.Value.pages == null)
|
|
return;
|
|
|
|
var sellService = cachedSellService.Value;
|
|
tabPageMapping.Clear();
|
|
|
|
// Create tabs for each page that has items
|
|
for (int pageIndex = 0; pageIndex < sellService.pages.Length; pageIndex++)
|
|
{
|
|
var page = sellService.pages[pageIndex];
|
|
|
|
// Check if page has any items
|
|
bool hasItems = false;
|
|
if (page.goods != null)
|
|
{
|
|
foreach (var good in page.goods)
|
|
{
|
|
if (good.id != 0)
|
|
{
|
|
hasItems = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!hasItems)
|
|
continue;
|
|
|
|
tabPageMapping.Add(pageIndex);
|
|
|
|
// Get page title
|
|
string pageTitle = ByteToStringUtils.UshortArrayToUnicodeString(page.page_title);
|
|
if (string.IsNullOrEmpty(pageTitle))
|
|
{
|
|
pageTitle = $"Page {pageIndex + 1}";
|
|
}
|
|
|
|
// Create tab button
|
|
GameObject tabButtonObj = Instantiate(tabButtonPrefab, tabButtonContainer);
|
|
tabButtonObj.name = $"Tab_Page_{pageIndex}";
|
|
tabButtonObj.SetActive(true);
|
|
|
|
// Get button component
|
|
Button tabButton = tabButtonObj.GetComponent<Button>();
|
|
if (tabButton == null)
|
|
tabButton = tabButtonObj.GetComponentInChildren<Button>();
|
|
|
|
// Get text component
|
|
TextMeshProUGUI tabText = tabButtonObj.GetComponent<TextMeshProUGUI>();
|
|
if (tabText == null)
|
|
{
|
|
Transform textTransform = tabButtonObj.transform.Find(tabButtonTextComponentName);
|
|
if (textTransform != null)
|
|
tabText = textTransform.GetComponent<TextMeshProUGUI>();
|
|
else
|
|
tabText = tabButtonObj.GetComponentInChildren<TextMeshProUGUI>();
|
|
}
|
|
|
|
if (tabText != null)
|
|
tabText.text = pageTitle;
|
|
|
|
// Setup click listener
|
|
if (tabButton != null)
|
|
{
|
|
int tabIndex = tabPageMapping.Count - 1; // Current tab index
|
|
tabButton.onClick.AddListener(() => OnTabSelected(tabIndex));
|
|
}
|
|
|
|
currentTabButtons.Add(tabButtonObj);
|
|
}
|
|
}
|
|
|
|
void ClearTabs()
|
|
{
|
|
foreach (GameObject tabButton in currentTabButtons)
|
|
{
|
|
if (tabButton != null)
|
|
Destroy(tabButton);
|
|
}
|
|
currentTabButtons.Clear();
|
|
tabPageMapping.Clear();
|
|
}
|
|
|
|
void OnTabSelected(int tabIndex)
|
|
{
|
|
if (tabIndex == currentTabIndex || tabIndex < 0 || tabIndex >= tabPageMapping.Count)
|
|
return;
|
|
|
|
currentTabIndex = tabIndex;
|
|
RefreshShopDisplay();
|
|
|
|
// Update tab button states
|
|
for (int i = 0; i < currentTabButtons.Count; i++)
|
|
{
|
|
if (currentTabButtons[i] != null)
|
|
{
|
|
Button tabButton = currentTabButtons[i].GetComponent<Button>();
|
|
if (tabButton == null)
|
|
tabButton = currentTabButtons[i].GetComponentInChildren<Button>();
|
|
|
|
if (tabButton != null)
|
|
{
|
|
tabButton.interactable = (i != tabIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void RefreshShopDisplay()
|
|
{
|
|
// Clear existing items
|
|
ClearItems();
|
|
|
|
if (itemContainer == null || itemPanelPrefab == null)
|
|
return;
|
|
|
|
if (currentTabIndex < 0 || currentTabIndex >= tabPageMapping.Count)
|
|
return;
|
|
|
|
if (!cachedSellService.HasValue)
|
|
return;
|
|
|
|
int pageIndex = tabPageMapping[currentTabIndex];
|
|
var sellService = cachedSellService.Value;
|
|
|
|
if (pageIndex >= sellService.pages.Length)
|
|
return;
|
|
|
|
var page = sellService.pages[pageIndex];
|
|
|
|
// Create item panels
|
|
if (page.goods != null)
|
|
{
|
|
var elementDataMan = ElementDataManProvider.GetElementDataMan();
|
|
if (elementDataMan == null)
|
|
return;
|
|
|
|
for (int i = 0; i < page.goods.Length; i++)
|
|
{
|
|
var good = page.goods[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;
|
|
|
|
// Create GShopItem
|
|
GShopItem shopItem = CreateShopItemFromGood(good, itemData, itemDataType);
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static int GetAbsoluteShopSlotIndex(NPC_SELL_SERVICE sellService, int pageIndex, int localIndex)
|
|
{
|
|
if (pageIndex <= 0)
|
|
return localIndex;
|
|
|
|
int offset = 0;
|
|
int safePageIndex = Mathf.Clamp(pageIndex, 0, sellService.pages?.Length ?? 0);
|
|
for (int p = 0; p < safePageIndex; p++)
|
|
{
|
|
var goods = sellService.pages[p].goods;
|
|
if (goods != null)
|
|
offset += goods.Length;
|
|
}
|
|
|
|
return offset + localIndex;
|
|
}
|
|
|
|
GShopItem CreateShopItemFromGood(NPC_SELL_SERVICE.SellGood good, object itemData, DATA_TYPE itemDataType)
|
|
{
|
|
GShopItem shopItem = new GShopItem();
|
|
shopItem.id = good.id;
|
|
shopItem.num = 1;
|
|
|
|
// 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:
|
|
var weaponEssence = (WEAPON_ESSENCE)itemData;
|
|
itemName = weaponEssence.Name;
|
|
shopPrice = weaponEssence.shop_price;
|
|
break;
|
|
case DATA_TYPE.DT_ARMOR_ESSENCE:
|
|
var armorEssence = (ARMOR_ESSENCE)itemData;
|
|
itemName = armorEssence.Name;
|
|
shopPrice = armorEssence.shop_price;
|
|
break;
|
|
case DATA_TYPE.DT_MEDICINE_ESSENCE:
|
|
var medicineEssence = (MEDICINE_ESSENCE)itemData;
|
|
itemName = ByteToStringUtils.UshortArrayToUnicodeString(medicineEssence.name);
|
|
shopPrice = medicineEssence.shop_price;
|
|
break;
|
|
case DATA_TYPE.DT_DECORATION_ESSENCE:
|
|
var decorationEssence = (DECORATION_ESSENCE)itemData;
|
|
itemName = ByteToStringUtils.UshortArrayToUnicodeString(decorationEssence.name);
|
|
shopPrice = decorationEssence.shop_price;
|
|
break;
|
|
case DATA_TYPE.DT_STONE_ESSENCE:
|
|
var stoneEssence = (STONE_ESSENCE)itemData;
|
|
itemName = ByteToStringUtils.UshortArrayToUnicodeString(stoneEssence.name);
|
|
shopPrice = stoneEssence.shop_price;
|
|
break;
|
|
case DATA_TYPE.DT_MATERIAL_ESSENCE:
|
|
var materialEssence = (MATERIAL_ESSENCE)itemData;
|
|
itemName = ByteToStringUtils.UshortArrayToUnicodeString(materialEssence.name);
|
|
shopPrice = materialEssence.shop_price;
|
|
break;
|
|
default:
|
|
itemName = $"Item_{good.id}";
|
|
break;
|
|
}
|
|
|
|
shopItem.name = itemName;
|
|
|
|
// Set price from contribution cost or shop price
|
|
if (good.contrib_cost > 0)
|
|
{
|
|
shopItem.buy[0].price = (uint)good.contrib_cost;
|
|
shopItem.buy[0].type = 0; // 0 = permanent
|
|
}
|
|
else if (shopPrice > 0)
|
|
{
|
|
shopItem.buy[0].price = (uint)shopPrice;
|
|
shopItem.buy[0].type = 0; // 0 = permanent
|
|
}
|
|
else
|
|
{
|
|
// Initialize with invalid type if no price
|
|
shopItem.buy[0].type = -1; // -1 = invalid
|
|
shopItem.buy[0].price = 0;
|
|
}
|
|
|
|
return shopItem;
|
|
}
|
|
|
|
void CreateItemPanel(GShopItem item, int shopItemIndex)
|
|
{
|
|
if (itemPanelPrefab == null || itemContainer == null)
|
|
return;
|
|
|
|
if(scrollListItem != null)
|
|
{
|
|
scrollListItem.verticalNormalizedPosition = 1f;
|
|
}
|
|
|
|
if (scrollDetailItem != null)
|
|
{
|
|
scrollDetailItem.verticalNormalizedPosition = 1f;
|
|
}
|
|
|
|
if (itemDetailNameText != null)
|
|
{
|
|
itemDetailNameText.text = string.Empty;
|
|
}
|
|
|
|
if (itemMoneyText != null)
|
|
{
|
|
itemMoneyText.text = string.Empty;
|
|
}
|
|
|
|
if (itemDescriptionText != null)
|
|
{
|
|
itemDescriptionText.ClearText();
|
|
}
|
|
|
|
if (itemIconImage != null)
|
|
{
|
|
itemIconImage.sprite = khung_item;
|
|
}
|
|
|
|
if (itemsBuyTotalMoneyText != null)
|
|
{
|
|
itemsBuyTotalMoneyText.text = string.Empty;
|
|
}
|
|
|
|
GameObject itemPanel = Instantiate(itemPanelPrefab, itemContainer);
|
|
itemPanel.SetActive(true);
|
|
|
|
NPCShopItemPanel itemPanelScript = itemPanel.GetComponent<NPCShopItemPanel>();
|
|
if (itemPanelScript == null)
|
|
itemPanelScript = itemPanel.GetComponentInChildren<NPCShopItemPanel>();
|
|
|
|
if (itemPanelScript != null)
|
|
{
|
|
itemPanelScript.SetupItem(item, this, shopItemIndex);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError($"[NPCShopUIManager] NPCShopItemPanel component not found on prefab! Prefab name: {itemPanelPrefab.name}");
|
|
}
|
|
|
|
currentItemPanels.Add(itemPanel);
|
|
}
|
|
|
|
void ClearItems()
|
|
{
|
|
foreach (GameObject panel in currentItemPanels)
|
|
{
|
|
if (panel != null)
|
|
Destroy(panel);
|
|
}
|
|
currentItemPanels.Clear();
|
|
}
|
|
|
|
public void ShowItemDetail(GShopItem item, int shopItemIndex)
|
|
{
|
|
if (item.id == 0)
|
|
return;
|
|
|
|
SetupDetailPanel(item, this, shopItemIndex);
|
|
}
|
|
|
|
|
|
public override void CloseDialogue()
|
|
{
|
|
base.CloseDialogue();
|
|
if (itemDetailNameText != null)
|
|
{
|
|
itemDetailNameText.text = string.Empty;
|
|
}
|
|
|
|
if (itemMoneyText != null)
|
|
{
|
|
itemMoneyText.text = string.Empty;
|
|
}
|
|
|
|
if (itemDescriptionText != null)
|
|
{
|
|
itemDescriptionText.ClearText();
|
|
}
|
|
|
|
if (itemIconImage != null)
|
|
{
|
|
itemIconImage.sprite = khung_item;
|
|
}
|
|
|
|
if(itemsBuyTotalMoneyText != null)
|
|
{
|
|
itemsBuyTotalMoneyText.text = string.Empty;
|
|
}
|
|
|
|
EC_Game.GetGameRun().GetUIManager().GetInGameUIMan().EndNPCService();
|
|
}
|
|
|
|
public void CloseShop()
|
|
{
|
|
|
|
ResetSellReadySlots();
|
|
UpdateSellTotalPriceText();
|
|
CloseDialogue();
|
|
if (npcShopMainPanel != null)
|
|
npcShopMainPanel.SetActive(false);
|
|
|
|
ClearTabs();
|
|
ClearItems();
|
|
|
|
cachedSellService = null;
|
|
currentNPCID = 0;
|
|
}
|
|
|
|
void SetupEventListeners()
|
|
{
|
|
if (m_btn_buy != null)
|
|
m_btn_buy.onClick.AddListener(OnBuyButtonClicked);
|
|
|
|
if (m_btn_reduce != null)
|
|
m_btn_reduce.onClick.AddListener(OnReduceBuyCountClicked);
|
|
|
|
if (m_btn_incre != null)
|
|
m_btn_incre.onClick.AddListener(OnIncreaseBuyCountClicked);
|
|
|
|
if (m_btn_max != null)
|
|
m_btn_max.onClick.AddListener(OnMaxBuyCountClicked);
|
|
|
|
if (m_btn_sell != null)
|
|
m_btn_sell.onClick.AddListener(OnSellButtonClicked);
|
|
|
|
if (m_use_Item != null)
|
|
m_use_Item.onClick.AddListener(OnUseItemClicked);
|
|
|
|
SetupSellReadySlotListeners();
|
|
|
|
}
|
|
|
|
public void SetupDetailPanel(GShopItem item, NPCShopUIManager manager, int index)
|
|
{
|
|
currentItem = item;
|
|
shopManager = manager;
|
|
shopItemIndex = index;
|
|
|
|
UpdateDisplay();
|
|
}
|
|
|
|
void UpdateDisplay()
|
|
{
|
|
if (currentItem.id == 0)
|
|
{
|
|
Debug.LogWarning("[NPCShopDetailPanel] Current item ID is 0, skipping display update");
|
|
ResetBuyUi();
|
|
return;
|
|
}
|
|
|
|
if(itemDetailNameText != null)
|
|
{
|
|
itemDetailNameText.text = currentItem.name;
|
|
}
|
|
|
|
if (itemMoneyText != null)
|
|
{
|
|
uint money = GetCurrentUnitPrice();
|
|
if(money > 0)
|
|
itemMoneyText.text = $"Giá {money.ToString()} Ngân lượng";
|
|
else
|
|
itemMoneyText.text = BuyUiEmptyValue;
|
|
}
|
|
|
|
if (scrollDetailItem != null)
|
|
{
|
|
scrollDetailItem.verticalNormalizedPosition = 1f;
|
|
}
|
|
|
|
buyCount = BuyCountMin;
|
|
UpdateBuyPriceTexts();
|
|
|
|
// Set item description
|
|
if (itemDescriptionText != null)
|
|
{
|
|
itemDescriptionText.SetupDetailPanel(currentItem, this, shopItemIndex);
|
|
}
|
|
|
|
// if (itemPriceText != null)
|
|
// itemPriceText.text = price > 0 ? $"Price: {price}" : "Price: N/A";
|
|
|
|
// Load icon
|
|
if (itemIconImage != null)
|
|
{
|
|
LoadItemIcon(itemIconImage, (int)currentItem.id);
|
|
}
|
|
}
|
|
|
|
private uint GetCurrentUnitPrice()
|
|
{
|
|
if (currentItem.id == 0)
|
|
return 0;
|
|
|
|
if (currentItem.buy == null || currentItem.buy.Length == 0)
|
|
return 0;
|
|
|
|
for (int i = 0; i < currentItem.buy.Length; i++)
|
|
{
|
|
if (currentItem.buy[i].price > 0)
|
|
return currentItem.buy[i].price;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private int GetMaxBuyCountForCurrentItem()
|
|
{
|
|
if (currentItem.id == 0)
|
|
return BuyCountMin;
|
|
|
|
int tid = (int)currentItem.id;
|
|
if (tid <= 0)
|
|
return BuyCountMin;
|
|
|
|
int pileLimit = EC_IvtrItem.GetPileLimit(tid);
|
|
// In some setups the lightweight lookup returns 1 until the local DB data is loaded.
|
|
// If it says "1", try to resolve pile limit from a temporary item instance.
|
|
if (pileLimit <= BuyCountMin)
|
|
{
|
|
try
|
|
{
|
|
var tmp = EC_IvtrItem.CreateItem(tid, 0, 1);
|
|
if (tmp != null)
|
|
{
|
|
tmp.GetDetailDataFromLocal();
|
|
int instLimit = tmp.GetPileLimitInstance();
|
|
if (instLimit > pileLimit)
|
|
pileLimit = instLimit;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Keep the original pileLimit.
|
|
}
|
|
}
|
|
if (pileLimit < BuyCountMin)
|
|
pileLimit = BuyCountMin;
|
|
|
|
return pileLimit;
|
|
}
|
|
|
|
private void SetBuyCount(int newCount)
|
|
{
|
|
int max = GetMaxBuyCountForCurrentItem();
|
|
if (newCount < BuyCountMin) newCount = BuyCountMin;
|
|
if (newCount > max) newCount = max;
|
|
|
|
buyCount = newCount;
|
|
UpdateBuyPriceTexts();
|
|
}
|
|
|
|
private void UpdateBuyPriceTexts()
|
|
{
|
|
// Only update buy UI while buy panel is active.
|
|
if (contentMidBuy != null && !contentMidBuy.activeInHierarchy)
|
|
return;
|
|
|
|
if (currentItem.id == 0)
|
|
{
|
|
ResetBuyUi();
|
|
return;
|
|
}
|
|
|
|
uint unitPrice = GetCurrentUnitPrice();
|
|
int max = GetMaxBuyCountForCurrentItem();
|
|
if (buyCount < BuyCountMin) buyCount = BuyCountMin;
|
|
if (buyCount > max) buyCount = max;
|
|
|
|
// Quantity controls:
|
|
// - Non-stackable items have max == BuyCountMin, so keep +/-/max disabled.
|
|
// - Stackable items re-enable controls automatically.
|
|
bool canChangeQty = max > BuyCountMin;
|
|
if (m_btn_reduce != null) m_btn_reduce.interactable = canChangeQty && buyCount > BuyCountMin;
|
|
if (m_btn_incre != null) m_btn_incre.interactable = canChangeQty && buyCount < max;
|
|
if (m_btn_max != null) m_btn_max.interactable = canChangeQty && buyCount < max;
|
|
|
|
long total = unitPrice > 0 ? (long)unitPrice * buyCount : 0;
|
|
if (total < 0) total = 0;
|
|
|
|
if (itemsBuyAmountText != null)
|
|
{
|
|
itemsBuyAmountText.text = buyCount.ToString();
|
|
}
|
|
|
|
if (itemsBuyTotalMoneyText != null)
|
|
{
|
|
uint playerMoney = 0;
|
|
try
|
|
{
|
|
var host = CECGameRun.Instance?.GetHostPlayer();
|
|
if (host != null)
|
|
{
|
|
playerMoney = host.GetMoneyAmount();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
playerMoney = 0;
|
|
}
|
|
|
|
|
|
string totalText = total.ToString();
|
|
string playerMoneyStr = playerMoney.ToString();
|
|
itemsBuyTotalMoneyText.text = total > playerMoney
|
|
? $"<color=red>{total}</color>/{playerMoney}"
|
|
: $"{total}/{playerMoney}";
|
|
}
|
|
|
|
if (m_btn_buy != null)
|
|
{
|
|
m_btn_buy.interactable = unitPrice > 0 && buyCount >= BuyCountMin;
|
|
}
|
|
}
|
|
|
|
private void ResetBuyUi()
|
|
{
|
|
buyCount = BuyCountMin;
|
|
if (itemsBuyAmountText != null)
|
|
itemsBuyAmountText.text = BuyUiEmptyValue;
|
|
if (itemsBuyTotalMoneyText != null)
|
|
itemsBuyTotalMoneyText.text = BuyUiEmptyValue;
|
|
if (m_btn_buy != null)
|
|
m_btn_buy.interactable = false;
|
|
if (m_btn_reduce != null) m_btn_reduce.interactable = false;
|
|
if (m_btn_incre != null) m_btn_incre.interactable = false;
|
|
if (m_btn_max != null) m_btn_max.interactable = false;
|
|
}
|
|
|
|
private void OnReduceBuyCountClicked()
|
|
{
|
|
if (currentItem.id == 0)
|
|
return;
|
|
SetBuyCount(buyCount - 1);
|
|
}
|
|
|
|
private void OnIncreaseBuyCountClicked()
|
|
{
|
|
if (currentItem.id == 0)
|
|
return;
|
|
SetBuyCount(buyCount + 1);
|
|
}
|
|
|
|
private void OnMaxBuyCountClicked()
|
|
{
|
|
if (currentItem.id == 0)
|
|
return;
|
|
SetBuyCount(GetMaxBuyCountForCurrentItem());
|
|
}
|
|
|
|
void LoadItemIcon(Image iconImage, int itemId)
|
|
{
|
|
if (itemId <= 0 || iconImage == null)
|
|
return;
|
|
|
|
// Ensure the Image component is enabled and properly configured
|
|
iconImage.enabled = true;
|
|
iconImage.preserveAspect = true;
|
|
iconImage.type = Image.Type.Simple;
|
|
|
|
// Use the existing icon loading system from EC_IvtrItemUtils
|
|
Sprite iconSprite = EC_IvtrItemUtils.Instance.ResolveItemIconSprite(itemId);
|
|
|
|
if (iconSprite != null)
|
|
{
|
|
iconImage.sprite = iconSprite;
|
|
iconImage.color = Color.white;
|
|
}
|
|
else
|
|
{
|
|
iconImage.sprite = null;
|
|
}
|
|
}
|
|
|
|
string GetItemDescription(int itemId)
|
|
{
|
|
// First check if description is already in the item data
|
|
if (!string.IsNullOrEmpty(currentItem.desc))
|
|
{
|
|
return currentItem.desc;
|
|
}
|
|
|
|
// Try to use EC_IvtrEquip description for equipment items (like EC_InventoryUI does)
|
|
try
|
|
{
|
|
// Create EC_IvtrEquip for equipment items - this will work for weapons and armor
|
|
EC_IvtrEquip equipment = (EC_IvtrEquip)EC_IvtrItem.CreateItem(itemId, 0, 1);
|
|
|
|
// For NPC shop items, we typically have static data only
|
|
// Try to get description using GetNormalDesc() which works with base stats
|
|
string equipDesc = equipment.GetDesc();
|
|
if (!string.IsNullOrEmpty(equipDesc))
|
|
{
|
|
// Replace C++ style "\r" line separators with real newlines for TMP
|
|
return equipDesc.Replace("\\r", "\n");
|
|
}
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
// If EC_IvtrEquip fails, fall through to EC_IvtrItem method
|
|
Debug.LogWarning($"[NPCShopDetailPanel] Failed to get equipment description for item {itemId}: {ex.Message}");
|
|
}
|
|
|
|
// Fallback: build description using EC_IvtrItem (for non-equipment items)
|
|
try
|
|
{
|
|
EC_IvtrItem item = EC_IvtrItem.CreateItem(itemId, 0, 1);
|
|
if (item != null)
|
|
{
|
|
// For NPC shop, we typically have static data only, so load from local DB
|
|
item.GetDetailDataFromLocal();
|
|
string description = item.GetDesc();
|
|
if (!string.IsNullOrEmpty(description))
|
|
{
|
|
return description.Replace("\\r", "\n");
|
|
}
|
|
}
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.LogWarning($"[NPCShopDetailPanel] Failed to get description for item {itemId}: {ex.Message}");
|
|
}
|
|
|
|
return "No description available.";
|
|
}
|
|
|
|
void OnBuyButtonClicked()
|
|
{
|
|
if (currentItem.id == 0)
|
|
{
|
|
Debug.LogWarning("[NPCShopDetailPanel] Cannot buy item with ID 0");
|
|
return;
|
|
}
|
|
|
|
// Get price from item
|
|
uint price = GetCurrentUnitPrice();
|
|
if (price == 0)
|
|
{
|
|
Debug.LogWarning($"[NPCShopDetailPanel] Cannot buy item {currentItem.id} with invalid price");
|
|
return;
|
|
}
|
|
|
|
int max = GetMaxBuyCountForCurrentItem();
|
|
if (buyCount < BuyCountMin) buyCount = BuyCountMin;
|
|
if (buyCount > max) buyCount = max;
|
|
|
|
// Server requires SEVNPC_HELLO with NPC id before buy, and the correct shop slot index
|
|
if (shopManager != null && shopManager.CurrentNPCID != 0)
|
|
UnityGameSession.c2s_CmdNPCSevHello((int)shopManager.CurrentNPCID);
|
|
|
|
// Create npc_trade_item: tid = template ID, index = shop slot (server validates this), count = quantity.
|
|
// For this server, multiple entries with the same index are rejected (ERROR_MESSAGE 15),
|
|
// so we must send a single entry and put the desired quantity in npc_trade_item.count.
|
|
npc_trade_item[] items = new npc_trade_item[1];
|
|
items[0] = new npc_trade_item
|
|
{
|
|
tid = (int)currentItem.id,
|
|
index = (uint)shopItemIndex,
|
|
count = (uint)buyCount
|
|
};
|
|
|
|
UnityGameSession.c2s_CmdNPCSevBuy(items.Length, items);
|
|
|
|
Debug.Log($"[NPCShopDetailPanel] Sent buy command for item {currentItem.id}, unitPrice {price}, count {buyCount}");
|
|
}
|
|
|
|
private void OnSellButtonClicked()
|
|
{
|
|
if (sellSlotToSourceSlot == null || sellSlotToSourceSlot.Count == 0)
|
|
{
|
|
Debug.LogWarning("[NPCShopUIManager] No items staged for selling");
|
|
return;
|
|
}
|
|
|
|
// Server requires greeting before NPC service commands.
|
|
if (CurrentNPCID != 0)
|
|
UnityGameSession.c2s_CmdNPCSevHello((int)CurrentNPCID);
|
|
|
|
var host = CECGameRun.Instance?.GetHostPlayer();
|
|
var inv = host?.GetInventory(0);
|
|
if (inv == null)
|
|
{
|
|
Debug.LogWarning("[NPCShopUIManager] Inventory not available; cannot sell");
|
|
return;
|
|
}
|
|
|
|
var itemsToSell = new List<npc_sell_item>(sellSlotToSourceSlot.Count);
|
|
foreach (var pair in sellSlotToSourceSlot)
|
|
{
|
|
int sourceSlot = pair.Value;
|
|
if (sourceSlot < 0 || sourceSlot >= inv.GetSize())
|
|
continue;
|
|
|
|
var item = inv.GetItem(sourceSlot, false);
|
|
if (item == null || item.m_iCount <= 0)
|
|
continue;
|
|
|
|
if (!item.IsSellable())
|
|
{
|
|
Debug.LogWarning($"[NPCShopUIManager] Item {item.m_tid} in slot {sourceSlot} is not sellable");
|
|
continue;
|
|
}
|
|
|
|
// Ensure local DB props (including price) are present when needed.
|
|
item.GetDetailDataFromLocal();
|
|
|
|
int price = item.GetScaledPrice();
|
|
itemsToSell.Add(new npc_sell_item
|
|
{
|
|
tid = item.m_tid,
|
|
index = (uint)sourceSlot,
|
|
count = (uint)item.m_iCount,
|
|
price = price
|
|
});
|
|
}
|
|
|
|
if (itemsToSell.Count == 0)
|
|
{
|
|
Debug.LogWarning("[NPCShopUIManager] No valid items to sell after filtering");
|
|
return;
|
|
}
|
|
|
|
UnityGameSession.c2s_CmdNPCSevSell(itemsToSell.Count, itemsToSell.ToArray());
|
|
Debug.Log($"[NPCShopUIManager] Sent sell command for {itemsToSell.Count} item(s) to NPC {CurrentNPCID}");
|
|
|
|
ResetSellReadySlots();
|
|
|
|
// Ask server for refreshed inventory, then repaint UI so sold items disappear.
|
|
var inventoryUI = FindFirstObjectByType<EC_InventoryUI>();
|
|
UnityGameSession.RequestInventoryAsync(0, () =>
|
|
{
|
|
if (inventoryUI != null)
|
|
inventoryUI.RefreshAll();
|
|
});
|
|
}
|
|
|
|
private void OnUseItemClicked()
|
|
{
|
|
if (!TryGetSelectedInventoryItem(out var selectedItem, out var selectedSlot))
|
|
return;
|
|
|
|
if (itemReadySell == null || itemReadySell.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach(var pair in sellSlotToSourceSlot)
|
|
{
|
|
if(pair.Value == selectedSlot)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
int targetSellSlotIndex = GetFirstEmptySellSlotIndex();
|
|
if(targetSellSlotIndex < 0)
|
|
{
|
|
Debug.LogWarning("[NPCShopDetailPanel] No empty sell slot available");
|
|
return;
|
|
}
|
|
|
|
var sellSlotBtn = itemReadySell[targetSellSlotIndex];
|
|
var sellSlotBtnImg = GetButtonImage(sellSlotBtn);
|
|
if (sellSlotBtnImg == null)
|
|
return;
|
|
|
|
Sprite icon = EC_IvtrItemUtils.Instance.ResolveItemIconSprite((int)selectedItem.m_tid);
|
|
if (icon == null)
|
|
return;
|
|
if (icon == null)
|
|
return;
|
|
|
|
sellSlotBtnImg.sprite = icon;
|
|
sellSlotBtnImg.enabled = true;
|
|
sellSlotBtnImg.color = Color.white;
|
|
sellSlotBtnImg.preserveAspect = true;
|
|
sellSlotBtnImg.type = Image.Type.Simple;
|
|
|
|
Button sourceButton = FindInventoryButtonBySlot(selectedSlot);
|
|
SetInventorySlotGray(sourceButton, true);
|
|
sellSlotToSourceSlot[targetSellSlotIndex] = selectedSlot;
|
|
item_info.SetActive(false);
|
|
UpdateSellTotalPriceText();
|
|
}
|
|
|
|
private Image GetButtonImage(Button button)
|
|
{
|
|
if(button == null)
|
|
return null;
|
|
|
|
var childImage = button.GetComponentsInChildren<Image>(true);
|
|
if (childImage != null)
|
|
{
|
|
for(int i=0; i<childImage.Length; i++)
|
|
{
|
|
if (childImage[i] != null && childImage[i].gameObject != button.gameObject)
|
|
return childImage[i];
|
|
}
|
|
}
|
|
|
|
return button.GetComponent<Image>();
|
|
}
|
|
|
|
private int GetFirstEmptySellSlotIndex()
|
|
{
|
|
if(itemReadySell == null)
|
|
return -1;
|
|
|
|
for(int i=0; i<itemReadySell.Count; i++)
|
|
{
|
|
if(!sellSlotToSourceSlot.ContainsKey(i))
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
private void ResetSellReadySlots()
|
|
{
|
|
if (itemReadySell != null)
|
|
{
|
|
for(int i=0; i<itemReadySell.Count; i++)
|
|
{
|
|
var image = GetButtonImage(itemReadySell[i]);
|
|
if(image == null)
|
|
continue;
|
|
|
|
image.sprite = khung_item;
|
|
image.enabled = true;
|
|
image.color = Color.white;
|
|
image.preserveAspect = true;
|
|
image.type = Image.Type.Simple;
|
|
}
|
|
}
|
|
|
|
foreach (var pair in sellSlotToSourceSlot)
|
|
{
|
|
var sourceBtn = FindInventoryButtonBySlot(pair.Value);
|
|
SetInventorySlotGray(sourceBtn, false);
|
|
}
|
|
sellSlotToSourceSlot.Clear();
|
|
UpdateSellTotalPriceText();
|
|
}
|
|
|
|
private bool TryGetSelectedInventoryItem(out EC_IvtrItem item, out int slot)
|
|
{
|
|
item = null;
|
|
slot = -1;
|
|
|
|
var inventoryUI = FindFirstObjectByType<EC_InventoryUI>();
|
|
if(inventoryUI == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var type = typeof(EC_InventoryUI);
|
|
var packageField = type.GetField("currentSelectedPackage", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
var slotField = type.GetField("currentSelectedSlot", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
var itemField = type.GetField("currentSelectedItem", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
|
|
if (packageField == null || slotField == null || itemField == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var selectedPackage = (byte)packageField.GetValue(inventoryUI);
|
|
if (selectedPackage != 0)
|
|
return false;
|
|
|
|
slot = (int)slotField.GetValue(inventoryUI);
|
|
item = itemField.GetValue(inventoryUI) as EC_IvtrItem;
|
|
|
|
return item != null && slot >= 0;
|
|
}
|
|
|
|
private Button FindInventoryButtonBySlot(int slot)
|
|
{
|
|
var inventoryUI = FindFirstObjectByType<EC_InventoryUI>();
|
|
if (inventoryUI == null)
|
|
return null;
|
|
|
|
var field = typeof(EC_InventoryUI)
|
|
.GetField("inventoryPackButtons",
|
|
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
|
|
if (field == null)
|
|
return null;
|
|
|
|
var list = field.GetValue(inventoryUI) as List<Button>;
|
|
if (list == null || slot < 0 || slot >= list.Count)
|
|
return null;
|
|
|
|
return list[slot];
|
|
}
|
|
|
|
private void SetInventorySlotGray(Button btn, bool gray)
|
|
{
|
|
if (btn == null)
|
|
return;
|
|
|
|
var img = btn.GetComponent<Image>();
|
|
if (img == null)
|
|
return;
|
|
|
|
img.color = gray
|
|
? new Color(0.3f, 0.3f, 0.3f, 1f)
|
|
: Color.white;
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
ClearTabs();
|
|
ClearItems();
|
|
ResetSellReadySlots();
|
|
CleanupSellReadySlotListeners();
|
|
if (m_btn_buy != null)
|
|
m_btn_buy.onClick.RemoveListener(OnBuyButtonClicked);
|
|
|
|
if (m_btn_reduce != null)
|
|
m_btn_reduce.onClick.RemoveListener(OnReduceBuyCountClicked);
|
|
|
|
if (m_btn_incre != null)
|
|
m_btn_incre.onClick.RemoveListener(OnIncreaseBuyCountClicked);
|
|
|
|
if (m_btn_max != null)
|
|
m_btn_max.onClick.RemoveListener(OnMaxBuyCountClicked);
|
|
|
|
if (m_btn_sell != null)
|
|
m_btn_sell.onClick.RemoveListener(OnSellButtonClicked);
|
|
|
|
if(m_use_Item != null)
|
|
m_use_Item.onClick.RemoveListener(OnUseItemClicked);
|
|
}
|
|
|
|
private void SetupSellReadySlotListeners()
|
|
{
|
|
if (itemReadySell == null)
|
|
return;
|
|
|
|
for (int i = 0; i < itemReadySell.Count; i++)
|
|
{
|
|
var btn = itemReadySell[i];
|
|
if(btn == null)
|
|
continue;
|
|
|
|
int capturedIndex = i;
|
|
btn.onClick.RemoveAllListeners();
|
|
btn.onClick.AddListener(() => OnSellReadySlotClicked(capturedIndex));
|
|
}
|
|
}
|
|
|
|
private void CleanupSellReadySlotListeners()
|
|
{
|
|
if (itemReadySell == null)
|
|
return;
|
|
|
|
for(int i = 0; i < itemReadySell.Count; i++)
|
|
{
|
|
if (itemReadySell[i] != null)
|
|
{
|
|
itemReadySell[i].onClick.RemoveAllListeners();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnSellReadySlotClicked(int sellSlotIndex)
|
|
{
|
|
if(!sellSlotToSourceSlot.TryGetValue(sellSlotIndex, out int sourceSlot))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var sourceBtn = FindInventoryButtonBySlot(sourceSlot);
|
|
SetInventorySlotGray(sourceBtn, false);
|
|
|
|
var sellBtn = itemReadySell[sellSlotIndex];
|
|
var sellImg = GetButtonImage(sellBtn);
|
|
if(sellImg != null)
|
|
{
|
|
sellImg.sprite = khung_item;
|
|
sellImg.enabled = true;
|
|
sellImg.color = Color.white;
|
|
sellImg.preserveAspect = true;
|
|
sellImg.type = Image.Type.Simple;
|
|
}
|
|
sellSlotToSourceSlot.Remove(sellSlotIndex);
|
|
UpdateSellTotalPriceText();
|
|
}
|
|
|
|
private void OnClickTabButtonBuy()
|
|
{
|
|
m_btn_tab_buy.image.color = colorActive;
|
|
m_btn_tab_sell.image.color = colorUnActive;
|
|
contentMidBuy.SetActive(true);
|
|
contentRight.SetActive(true);
|
|
contentMidSell.SetActive(false);
|
|
UpdateBuyPriceTexts();
|
|
}
|
|
|
|
private void OnClickTabButtonSell()
|
|
{
|
|
m_btn_tab_buy.image.color = colorUnActive;
|
|
m_btn_tab_sell.image.color = colorActive;
|
|
contentMidBuy.SetActive(false);
|
|
contentRight.SetActive(false);
|
|
contentMidSell.SetActive(true);
|
|
UpdateSellTotalPriceText();
|
|
}
|
|
|
|
private void UpdateSellTotalPriceText()
|
|
{
|
|
long totalSellValue = 0;
|
|
int stageCount = 0;
|
|
|
|
try
|
|
{
|
|
var host = CECGameRun.Instance?.GetHostPlayer();
|
|
var inv = host?.GetInventory(0);
|
|
|
|
if (inv == null || sellSlotToSourceSlot == null)
|
|
{
|
|
if (itemsSellTotalMoneyText != null)
|
|
itemsSellTotalMoneyText.text = BuyUiEmptyValue;
|
|
if (m_btn_sell != null)
|
|
m_btn_sell.interactable = false;
|
|
|
|
return;
|
|
}
|
|
|
|
foreach (var pair in sellSlotToSourceSlot)
|
|
{
|
|
int sourceSlot = pair.Value;
|
|
if (sourceSlot < 0 || sourceSlot >= inv.GetSize())
|
|
continue;
|
|
|
|
var item = inv.GetItem(sourceSlot, false);
|
|
if (item == null || item.m_iCount <= 0)
|
|
continue;
|
|
|
|
if (!item.IsSellable())
|
|
continue;
|
|
|
|
try
|
|
{
|
|
item.GetDetailDataFromLocal();
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
|
|
int unitPrice = item.GetScaledPrice();
|
|
long itemTotal = (long)unitPrice * item.m_iCount;
|
|
if (itemTotal > 0)
|
|
{
|
|
totalSellValue += itemTotal;
|
|
stageCount++;
|
|
}
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
|
|
}
|
|
|
|
if (itemsSellTotalMoneyText != null)
|
|
{
|
|
if(stageCount == 0 || totalSellValue <= 0)
|
|
{
|
|
itemsSellTotalMoneyText.text = BuyUiEmptyValue;
|
|
}
|
|
else
|
|
{
|
|
itemsSellTotalMoneyText.text = totalSellValue.ToString();
|
|
}
|
|
}
|
|
|
|
if (m_btn_sell != null)
|
|
{
|
|
m_btn_sell.interactable = stageCount > 0 && totalSellValue > 0;
|
|
}
|
|
}
|
|
}
|