Files
test/Assets/PerfectWorld/Scripts/UI/NPCShopUIManager.cs
T
2025-12-04 14:39:46 +07:00

465 lines
15 KiB
C#

// Filename : NPCShopUIManager.cs
// Creator : Converted from C++ EC_Shop
// Date : 2024
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using PerfectWorld.Scripts.Shop;
using BrewMonster;
using static CSNetwork.Common.ExpTypes;
using ModelRenderer.Scripts.Common;
public class NPCShopUIManager : MonoBehaviour
{
[Header("UI Panels")]
public GameObject npcShopMainPanel;
public GameObject npcShopDetailPanel;
[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;
private List<GameObject> currentItemPanels = new List<GameObject>();
private List<GameObject> currentTabButtons = new List<GameObject>();
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 NPCShopDetailPanel detailPanelScript;
void Start()
{
if (closeShopButton != null)
closeShopButton.onClick.AddListener(CloseShop);
// Initialize detail panel reference
if (npcShopDetailPanel != null)
{
detailPanelScript = npcShopDetailPanel.GetComponent<NPCShopDetailPanel>();
if (detailPanelScript == null)
detailPanelScript = npcShopDetailPanel.GetComponentInChildren<NPCShopDetailPanel>();
// Initially hide the detail panel
if (npcShopDetailPanel.activeSelf)
npcShopDetailPanel.SetActive(false);
}
}
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;
foreach (var good in page.goods)
{
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
CreateItemPanel(shopItem);
}
}
}
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)
{
if (itemPanelPrefab == null || itemContainer == null)
return;
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);
}
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)
{
if (item.id == 0)
return;
if (npcShopDetailPanel == null)
{
Debug.LogWarning("[NPCShopUIManager] npcShopDetailPanel is not assigned!");
return;
}
// Ensure detail panel script is available
if (detailPanelScript == null)
{
detailPanelScript = npcShopDetailPanel.GetComponent<NPCShopDetailPanel>();
if (detailPanelScript == null)
detailPanelScript = npcShopDetailPanel.GetComponentInChildren<NPCShopDetailPanel>();
}
if (detailPanelScript != null)
{
npcShopDetailPanel.SetActive(true);
detailPanelScript.SetupDetailPanel(item, this);
}
else
{
Debug.LogError("[NPCShopUIManager] NPCShopDetailPanel component not found on npcShopDetailPanel GameObject!");
}
}
public void CloseDetailPanel()
{
if (npcShopDetailPanel != null)
npcShopDetailPanel.SetActive(false);
}
public void CloseShop()
{
if (npcShopMainPanel != null)
npcShopMainPanel.SetActive(false);
// Close detail panel when closing shop
CloseDetailPanel();
ClearTabs();
ClearItems();
cachedSellService = null;
currentNPCID = 0;
}
void OnDestroy()
{
ClearTabs();
ClearItems();
}
}