911 lines
29 KiB
C#
911 lines
29 KiB
C#
using BrewMonster.Network;
|
|
using BrewMonster.Scripts;
|
|
using BrewMonster.Scripts.Task;
|
|
using BrewMonster.UI;
|
|
using ModelRenderer.Scripts.Common;
|
|
using PerfectWorld.Scripts.Managers;
|
|
using PerfectWorld.Scripts.Task;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using CSNetwork;
|
|
using System.Text;
|
|
using TMPro;
|
|
|
|
namespace BrewMonster
|
|
{
|
|
public class DlgProduce : AUIDialog
|
|
{
|
|
[Header("Produce Tabs")]
|
|
[SerializeField] private Transform tabBtnContainer;
|
|
[SerializeField] private GameObject tabBtnPb;
|
|
[SerializeField] private string tabButtonTextComponentName = "Text";
|
|
|
|
[Header("Produce Detail")]
|
|
[SerializeField] private ScrollRect m_scrollRect;
|
|
[SerializeField] private Transform itemContainer;
|
|
[SerializeField] private GameObject itemPb;
|
|
|
|
[Header("Quantity")]
|
|
[SerializeField] private TextMeshProUGUI quantityText;
|
|
[SerializeField] private Button quantityIncreaseBtn;
|
|
[SerializeField] private Button quantityDecreaseBtn;
|
|
[SerializeField] private Button quantityMaxBtn;
|
|
|
|
private int currentQuantity = 1;
|
|
|
|
private int produceRemainCount = 0;
|
|
private bool isProducing = false;
|
|
|
|
[Header("Material Slots")]
|
|
[SerializeField] private List<Transform> materialSlots = new List<Transform>();
|
|
|
|
[Header("Result Slot")]
|
|
[SerializeField] private Image itemResult;
|
|
|
|
[Header("Item Info Panel")]
|
|
public Transform itemInfoRoot;
|
|
public TextMeshProUGUI infoNameText;
|
|
public TextMeshProUGUI infoDescText;
|
|
public TextMeshProUGUI infoExtraText;
|
|
|
|
[Header("Wepon Info Equippment Panel")]
|
|
[SerializeField] private Transform weponInfoRoot;
|
|
[SerializeField] private TextMeshProUGUI weponNameInfoText;
|
|
[SerializeField] private TextMeshProUGUI weponDescInfoText;
|
|
[SerializeField] private TextMeshProUGUI weponExtraInfoText;
|
|
|
|
[Header("Default")]
|
|
[SerializeField] private Sprite khung_item;
|
|
|
|
private NPC_MAKE_SERVICE? cachedMakeService = null;
|
|
private int currentTabIndex = 0;
|
|
private uint selectedRecipeId = 0; // Track the currently selected recipe
|
|
|
|
static readonly Color COLOR_NOT_ENOUGH = new Color32(145, 145, 145, 255);
|
|
static readonly Color COLOR_ENOUGH = Color.white;
|
|
|
|
[SerializeField] private Button startProduceBtn;
|
|
[SerializeField] private Button cancelProduceBtn;
|
|
[SerializeField] private Button clickCatcherPanel;
|
|
|
|
enum ItemInfoMode
|
|
{
|
|
None,
|
|
ResultItem,
|
|
MaterialItem
|
|
}
|
|
|
|
private ItemInfoMode currentInfoMode = ItemInfoMode.None;
|
|
|
|
|
|
public override void Start()
|
|
{
|
|
quantityText.text = currentQuantity.ToString();
|
|
quantityDecreaseBtn.onClick.AddListener(OnClickDecreaseBtn);
|
|
quantityIncreaseBtn.onClick.AddListener(OnClickIncreaseBtn);
|
|
quantityMaxBtn.onClick.AddListener(OnClickMaxBtn);
|
|
clickCatcherPanel.onClick.AddListener(HideItemInfo);
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
#if UNITY_EDITOR || UNITY_STANDALONE
|
|
if (Input.GetMouseButtonDown(0))
|
|
{
|
|
CheckHidePanel(Input.mousePosition);
|
|
}
|
|
#else
|
|
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
|
|
{
|
|
CheckHidePanel(Input.GetTouch(0).position);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CheckHidePanel(Vector2 screenPos)
|
|
{
|
|
if (!RectTransformUtility.RectangleContainsScreenPoint(
|
|
itemInfoRoot as RectTransform,
|
|
screenPos,
|
|
Camera.main))
|
|
{
|
|
HideItemInfo();
|
|
}
|
|
}
|
|
|
|
public void OpenProduce(uint npcId)
|
|
{
|
|
if (!LoadMakeService(npcId))
|
|
{
|
|
Debug.LogError("[DlgProduce] LoadMakeService failed");
|
|
return;
|
|
}
|
|
|
|
selectedRecipeId = 0; // Reset selected recipe
|
|
SetupButtonHandlers();
|
|
CreateTabs();
|
|
OnTabSelected(0);
|
|
}
|
|
|
|
void SetupButtonHandlers()
|
|
{
|
|
if (startProduceBtn != null)
|
|
{
|
|
startProduceBtn.onClick.RemoveAllListeners();
|
|
startProduceBtn.onClick.AddListener(OnStartProduceClicked);
|
|
}
|
|
|
|
if (cancelProduceBtn != null)
|
|
{
|
|
cancelProduceBtn.onClick.RemoveAllListeners();
|
|
cancelProduceBtn.onClick.AddListener(OnCancelProduceClicked);
|
|
}
|
|
}
|
|
|
|
bool LoadMakeService(uint npcId)
|
|
{
|
|
var edm = ElementDataManProvider.GetElementDataMan();
|
|
if (edm == null)
|
|
return false;
|
|
|
|
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
|
|
object npcData = edm.get_data_ptr(npcId, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
|
|
|
|
if (dt != DATA_TYPE.DT_NPC_ESSENCE || npcData == null)
|
|
return false;
|
|
|
|
NPC_ESSENCE npc = (NPC_ESSENCE)npcData;
|
|
if (npc.id_make_service == 0)
|
|
return false;
|
|
|
|
DATA_TYPE serviceDt = DATA_TYPE.DT_INVALID;
|
|
object serviceData = edm.get_data_ptr(
|
|
npc.id_make_service,
|
|
ID_SPACE.ID_SPACE_ESSENCE,
|
|
ref serviceDt
|
|
);
|
|
|
|
if (serviceDt != DATA_TYPE.DT_NPC_MAKE_SERVICE || serviceData == null)
|
|
return false;
|
|
|
|
cachedMakeService = (NPC_MAKE_SERVICE)serviceData;
|
|
return true;
|
|
}
|
|
|
|
void CreateTabs()
|
|
{
|
|
ClearContainer(tabBtnContainer);
|
|
|
|
if (!cachedMakeService.HasValue || cachedMakeService.Value.pages == null)
|
|
return;
|
|
|
|
var makeService = cachedMakeService.Value;
|
|
|
|
for (int pageIndex = 0; pageIndex < makeService.pages.Length; pageIndex++)
|
|
{
|
|
var page = makeService.pages[pageIndex];
|
|
bool hasRecipes = false;
|
|
if (page.id_goods != null)
|
|
{
|
|
foreach (uint recipeId in page.id_goods)
|
|
{
|
|
if (recipeId != 0)
|
|
{
|
|
hasRecipes = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!hasRecipes)
|
|
continue;
|
|
|
|
GameObject tabObj = Instantiate(tabBtnPb, tabBtnContainer);
|
|
tabObj.name = $"ProduceTab_Page_{pageIndex}";
|
|
tabObj.SetActive(true);
|
|
|
|
string pageTitle = ByteToStringUtils.UshortArrayToUnicodeString(page.page_title);
|
|
if (string.IsNullOrWhiteSpace(pageTitle))
|
|
pageTitle = $"Page {pageIndex + 1}";
|
|
|
|
TMPro.TextMeshProUGUI tabTMP = null;
|
|
TextMeshProUGUI tabText = null;
|
|
|
|
Transform textTf = tabObj.transform.Find(tabButtonTextComponentName);
|
|
if (textTf != null)
|
|
{
|
|
tabTMP = textTf.GetComponent<TMPro.TextMeshProUGUI>();
|
|
if (tabTMP == null)
|
|
{
|
|
tabText = textTf.GetComponent<TextMeshProUGUI>();
|
|
}
|
|
}
|
|
|
|
if (tabTMP == null && tabText == null)
|
|
{
|
|
tabTMP = tabObj.GetComponentInChildren<TMPro.TextMeshProUGUI>();
|
|
if(tabTMP == null)
|
|
{
|
|
tabText = tabObj.GetComponentInChildren<TextMeshProUGUI>();
|
|
}
|
|
}
|
|
|
|
if(tabTMP != null)
|
|
tabTMP.text = pageTitle;
|
|
else if(tabText != null)
|
|
tabText.text = pageTitle;
|
|
|
|
Button btn = tabObj.GetComponent<Button>();
|
|
if(btn == null)
|
|
btn = tabObj.GetComponentInChildren<Button>();
|
|
|
|
if(btn != null)
|
|
{
|
|
int capturedIndex = pageIndex;
|
|
btn.onClick.AddListener(() =>
|
|
{
|
|
OnTabSelected(capturedIndex);
|
|
ResetOnTop();
|
|
});
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnTabSelected(int index)
|
|
{
|
|
currentTabIndex = index;
|
|
RefreshSubItemList();
|
|
}
|
|
|
|
void RefreshSubItemList()
|
|
{
|
|
ClearContainer(itemContainer);
|
|
|
|
if (!cachedMakeService.HasValue)
|
|
return;
|
|
|
|
var service = cachedMakeService.Value;
|
|
if (service.pages == null || currentTabIndex >= service.pages.Length)
|
|
return;
|
|
|
|
var page = service.pages[currentTabIndex];
|
|
if (page.id_goods == null)
|
|
return;
|
|
|
|
foreach (uint recipeId in page.id_goods)
|
|
{
|
|
if (recipeId == 0)
|
|
continue;
|
|
|
|
CreateSubItem(recipeId);
|
|
}
|
|
}
|
|
|
|
void CreateSubItem(uint recipeId)
|
|
{
|
|
if (itemPb == null || itemContainer == null)
|
|
return;
|
|
|
|
GameObject item = Instantiate(itemPb, itemContainer);
|
|
item.name = $"Recipe_{recipeId}";
|
|
item.SetActive(true);
|
|
Debug.Log("[DlgProduce] Creating produce item for recipe ID: " + item.name);
|
|
|
|
ProduceItemPanel panel = item.GetComponent<ProduceItemPanel>();
|
|
if(panel != null)
|
|
{
|
|
panel.Setup(recipeId,this);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("[DlgProduce] ProduceItemPanel component not found on item prefab");
|
|
}
|
|
|
|
Button btn = item.GetComponent<Button>();
|
|
if (btn == null)
|
|
btn = item.AddComponent<Button>();
|
|
|
|
btn.onClick.RemoveAllListeners();
|
|
btn.onClick.AddListener(() =>
|
|
{
|
|
bool isNewRecipe = selectedRecipeId != recipeId;
|
|
selectedRecipeId = recipeId;
|
|
if (isNewRecipe)
|
|
{
|
|
currentQuantity = 1;
|
|
UpdateQuantityText(currentQuantity);
|
|
}
|
|
ShowRecipeMaterials(recipeId);
|
|
ShowItemInfoByRecipe(recipeId);
|
|
});
|
|
}
|
|
|
|
void ClearContainer(Transform container)
|
|
{
|
|
if (container == null)
|
|
return;
|
|
|
|
for (int i = container.childCount - 1; i >= 0; i--)
|
|
{
|
|
Destroy(container.GetChild(i).gameObject);
|
|
}
|
|
}
|
|
|
|
void ClearMaterialSlots()
|
|
{
|
|
foreach (var slot in materialSlots)
|
|
{
|
|
if (slot == null) continue;
|
|
|
|
Transform iconTf = slot.Find("item");
|
|
if (iconTf != null)
|
|
{
|
|
Image img = iconTf.GetComponent<Image>();
|
|
if (img != null)
|
|
img.sprite = khung_item;
|
|
}
|
|
|
|
Transform qtyTf = slot.Find("text_quantity");
|
|
if (qtyTf != null)
|
|
{
|
|
TextMeshProUGUI txt = qtyTf.GetComponent<TextMeshProUGUI>();
|
|
if (txt != null)
|
|
txt.text = "";
|
|
}
|
|
}
|
|
|
|
if (itemResult != null)
|
|
{
|
|
itemResult.sprite = khung_item;
|
|
}
|
|
}
|
|
|
|
|
|
public void ShowRecipeMaterials(uint recipeId)
|
|
{
|
|
selectedRecipeId = recipeId;
|
|
ClearMaterialSlots();
|
|
|
|
var edm = ElementDataManProvider.GetElementDataMan();
|
|
if (edm == null)
|
|
return;
|
|
|
|
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
|
|
object data = edm.get_data_ptr(recipeId, ID_SPACE.ID_SPACE_RECIPE, ref dt);
|
|
|
|
if (data is not RECIPE_ESSENCE recipe)
|
|
return;
|
|
|
|
if (itemResult != null &&
|
|
recipe.targets != null &&
|
|
recipe.targets.Length > 0 &&
|
|
recipe.targets[0].id_to_make != 0)
|
|
{
|
|
uint outputItemId = recipe.targets[0].id_to_make;
|
|
|
|
if (itemResult != null)
|
|
{
|
|
if (itemResult != null)
|
|
{
|
|
Sprite sp = EC_IvtrItemUtils.Instance.ResolveItemIconSprite((int)outputItemId);
|
|
if (sp != null)
|
|
{
|
|
itemResult.sprite = sp;
|
|
itemResult.enabled = true;
|
|
itemResult.preserveAspect = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
Button resultBtn = itemResult.GetComponent<Button>();
|
|
if (resultBtn == null)
|
|
{
|
|
resultBtn = itemResult.gameObject.AddComponent<Button>();
|
|
}
|
|
|
|
resultBtn.onClick.RemoveAllListeners();
|
|
uint capturedOutputId = outputItemId;
|
|
resultBtn.onClick.AddListener(() =>
|
|
{
|
|
EC_IvtrItem outputItem = EC_IvtrItem.CreateItem((int)capturedOutputId, 0, 1);
|
|
outputItem?.GetDetailDataFromLocal();
|
|
ShowResultItemInfo(outputItem, capturedOutputId);
|
|
});
|
|
}
|
|
|
|
if (recipe.materials == null)
|
|
return;
|
|
|
|
bool allEnough = true;
|
|
int slotIndex = 0;
|
|
foreach (var mat in recipe.materials)
|
|
{
|
|
if (slotIndex >= materialSlots.Count)
|
|
break;
|
|
|
|
if (mat.id == 0 || mat.num <= 0)
|
|
continue;
|
|
|
|
// compute required amount for the currently selected quantity
|
|
int requiredAmount = mat.num * Mathf.Max(1, currentQuantity);
|
|
|
|
int owned = GetInventoryItemCount(mat.id);
|
|
bool enough = owned >= requiredAmount;
|
|
|
|
if (!enough)
|
|
allEnough = false;
|
|
|
|
Transform slot = materialSlots[slotIndex];
|
|
slot.gameObject.SetActive(true);
|
|
|
|
Button btn = slot.GetComponent<Button>();
|
|
if (btn == null)
|
|
btn = slot.gameObject.AddComponent<Button>();
|
|
|
|
uint capturedMatId = mat.id;
|
|
|
|
btn.onClick.RemoveAllListeners();
|
|
btn.onClick.AddListener(() =>
|
|
{
|
|
EC_IvtrItem matItem = EC_IvtrItem.CreateItem((int)capturedMatId, 0, 1);
|
|
matItem?.GetDetailDataFromLocal();
|
|
ShowMaterialItemInfo(matItem, capturedMatId);
|
|
});
|
|
|
|
Transform iconTf = slot.Find("item");
|
|
if (iconTf != null)
|
|
{
|
|
Image img = iconTf.GetComponent<Image>();
|
|
if (img != null)
|
|
{
|
|
Sprite sp = EC_IvtrItemUtils.Instance.ResolveItemIconSprite((int)mat.id);
|
|
img.sprite = sp;
|
|
img.enabled = true;
|
|
img.preserveAspect = true;
|
|
img.color = enough ? COLOR_ENOUGH : COLOR_NOT_ENOUGH;
|
|
}
|
|
}
|
|
|
|
Transform qtyTf = slot.Find("text_quantity");
|
|
if (qtyTf != null)
|
|
{
|
|
var tmp = qtyTf.GetComponent<TMPro.TextMeshProUGUI>();
|
|
if (tmp != null)
|
|
tmp.text = $"{requiredAmount}/{owned}";
|
|
else
|
|
{
|
|
TextMeshProUGUI txt = qtyTf.GetComponent<TextMeshProUGUI>();
|
|
if (txt != null)
|
|
txt.text = $"{requiredAmount}/{owned}";
|
|
}
|
|
}
|
|
|
|
slotIndex++;
|
|
}
|
|
|
|
if (itemResult != null)
|
|
{
|
|
itemResult.color = allEnough ? COLOR_ENOUGH : COLOR_NOT_ENOUGH;
|
|
}
|
|
|
|
if (startProduceBtn != null)
|
|
{
|
|
startProduceBtn.interactable = allEnough;
|
|
}
|
|
}
|
|
|
|
void OnStartProduceClicked()
|
|
{
|
|
if (selectedRecipeId == 0)
|
|
{
|
|
Debug.LogWarning("[DlgProduce] No recipe selected");
|
|
return;
|
|
}
|
|
|
|
if (!cachedMakeService.HasValue)
|
|
{
|
|
Debug.LogError("[DlgProduce] No make service cached");
|
|
return;
|
|
}
|
|
|
|
produceRemainCount = currentQuantity;
|
|
isProducing = true;
|
|
|
|
SendProduceOnce();
|
|
}
|
|
|
|
void SendProduceOnce()
|
|
{
|
|
if(!isProducing || produceRemainCount <= 0)
|
|
{
|
|
Debug.Log("[DlgProduce] No production needed or already completed");
|
|
return;
|
|
}
|
|
|
|
// Get skill ID from the service (not from recipe)
|
|
// The second parameter is the recipe ID (not the item ID)
|
|
int idSkill = (int)cachedMakeService.Value.id_make_skill;
|
|
int idRecipe = (int)selectedRecipeId;
|
|
uint dwCount = 1; // Default count is 1 (matching C++ code for Win_Produce1)
|
|
|
|
// Send the command to the server
|
|
// Parameters: idSkill (from service), idRecipe (recipe ID), dwCount
|
|
UnityGameSession.c2s_CmdNPCSevMakeItem(idSkill, idRecipe, dwCount);
|
|
Debug.Log($"[DlgProduce] Sent make item command: skill={idSkill}, recipe={idRecipe}, count={dwCount}");
|
|
}
|
|
|
|
void OnCancelProduceClicked()
|
|
{
|
|
CloseProduce();
|
|
ResetItemInfoPanel();
|
|
}
|
|
|
|
public void CloseProduce()
|
|
{
|
|
EC_Game.GetGameRun().GetUIManager().GetInGameUIMan().EndNPCService();
|
|
isProducing = false;
|
|
produceRemainCount = 0;
|
|
|
|
CloseDialogue();
|
|
ClearContainer(tabBtnContainer);
|
|
ClearContainer(itemContainer);
|
|
ClearMaterialSlots();
|
|
cachedMakeService = null;
|
|
currentTabIndex = 0;
|
|
selectedRecipeId = 0;
|
|
ResetItemInfoPanel();
|
|
HideItemInfo();
|
|
currentQuantity = 1;
|
|
}
|
|
|
|
// Called when production starts (NOTIFY_PRODUCE_START)
|
|
public void OnProduceStart(CSNetwork.GPDataType.cmd_produce_start cmd)
|
|
{
|
|
Debug.Log($"[DlgProduce] OnProduceStart: type={cmd.type}, use_time={cmd.use_time}, count={cmd.count}");
|
|
// TODO: Update progress bar, disable start button, etc.
|
|
// This would typically start a progress bar showing production time
|
|
if (startProduceBtn != null)
|
|
{
|
|
startProduceBtn.interactable = false;
|
|
}
|
|
}
|
|
|
|
// Called when one item is produced (NOTIFY_PRODUCE_END_ONE)
|
|
public void OnProduceOnce(CSNetwork.GPDataType.cmd_produce_once cmd)
|
|
{
|
|
Debug.Log($"[DlgProduce] OnProduceOnce: type={cmd.type}, amount={cmd.amount}, where={cmd.where}, index={cmd.index}");
|
|
// TODO: Update UI counters, progress, skill ability, etc.
|
|
// This would typically update the remaining count and progress
|
|
|
|
produceRemainCount--;
|
|
if (produceRemainCount > 0)
|
|
{
|
|
SendProduceOnce();
|
|
}
|
|
else
|
|
{
|
|
isProducing = false;
|
|
Debug.Log("[DlgProduce] Production completed for all items");
|
|
}
|
|
}
|
|
|
|
// Called when production ends (NOTIFY_PRODUCE_END)
|
|
public void OnProduceEnd()
|
|
{
|
|
Debug.Log("[DlgProduce] OnProduceEnd: Production completed");
|
|
// TODO: Re-enable start button, reset progress, etc.
|
|
if (startProduceBtn != null)
|
|
{
|
|
startProduceBtn.interactable = true;
|
|
}
|
|
}
|
|
|
|
// Called when production fails (NOTIFY_PRODUCE_NULL)
|
|
public void OnProduceNull(CSNetwork.GPDataType.cmd_produce_null cmd)
|
|
{
|
|
Debug.Log($"[DlgProduce] OnProduceNull: type={cmd.type} - Production failed");
|
|
// TODO: Show error message, re-enable start button, etc.
|
|
if (startProduceBtn != null)
|
|
{
|
|
startProduceBtn.interactable = true;
|
|
}
|
|
isProducing = false;
|
|
produceRemainCount = 0;
|
|
}
|
|
|
|
public void ShowItemInfoByRecipe(uint recipeId)
|
|
{
|
|
if (itemInfoRoot == null)
|
|
return;
|
|
|
|
var edm = ElementDataManProvider.GetElementDataMan();
|
|
if (edm == null)
|
|
return;
|
|
|
|
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
|
|
object data = edm.get_data_ptr(recipeId, ID_SPACE.ID_SPACE_RECIPE, ref dt);
|
|
|
|
if (data is not RECIPE_ESSENCE recipe ||
|
|
recipe.targets == null ||
|
|
recipe.targets.Length == 0)
|
|
return;
|
|
|
|
uint itemId = recipe.targets[0].id_to_make;
|
|
if (itemId == 0)
|
|
return;
|
|
|
|
EC_IvtrItem item = null;
|
|
try
|
|
{
|
|
item = EC_IvtrItem.CreateItem((int)itemId, 0, 1);
|
|
item?.GetDetailDataFromLocal();
|
|
}
|
|
catch { }
|
|
|
|
if (item == null)
|
|
return;
|
|
|
|
itemInfoRoot.gameObject.SetActive(true);
|
|
|
|
//if (infoNameText != null)
|
|
// infoNameText.text = EC_Utility.ProcessColorCodes(new StringBuilder (item.GetName()));
|
|
|
|
if (infoDescText != null)
|
|
infoDescText.text = EC_Utility.ProcessColorCodes(new StringBuilder (item.GetDesc()?.Replace("\\r", "\n") ?? ""));
|
|
|
|
if (infoExtraText != null)
|
|
{
|
|
infoExtraText.text = $"Item ID: {itemId}";
|
|
}
|
|
|
|
ShowResultItemInfo(item, itemId);
|
|
}
|
|
|
|
public void HideItemInfo()
|
|
{
|
|
if (itemInfoRoot != null)
|
|
itemInfoRoot.gameObject.SetActive(false);
|
|
|
|
if(weponInfoRoot != null)
|
|
weponInfoRoot.gameObject.SetActive(false);
|
|
}
|
|
|
|
private void UpdateQuantityText(int quantity)
|
|
{
|
|
if (quantityText != null)
|
|
{
|
|
quantityText.text = quantity.ToString();
|
|
}
|
|
}
|
|
|
|
private void OnClickIncreaseBtn()
|
|
{
|
|
currentQuantity++;
|
|
|
|
if (selectedRecipeId != 0)
|
|
{
|
|
int max = CalculateMaxProduceCount(selectedRecipeId);
|
|
if (max > 0 && currentQuantity > max)
|
|
currentQuantity = max;
|
|
}
|
|
|
|
UpdateQuantityText(currentQuantity);
|
|
if (selectedRecipeId != 0)
|
|
ShowRecipeMaterials(selectedRecipeId);
|
|
}
|
|
|
|
private void OnClickDecreaseBtn()
|
|
{
|
|
if (currentQuantity > 1)
|
|
{
|
|
currentQuantity--;
|
|
UpdateQuantityText(currentQuantity);
|
|
|
|
if(selectedRecipeId != 0)
|
|
ShowRecipeMaterials(selectedRecipeId);
|
|
}
|
|
}
|
|
|
|
// Helper to get total count of an item in player's inventory
|
|
int GetInventoryItemCount(uint itemId)
|
|
{
|
|
var host = CECGameRun.Instance?.GetHostPlayer();
|
|
if (host == null)
|
|
return 0;
|
|
|
|
var inv = host.GetInventory(0); // 0 = inventory bag
|
|
if (inv == null)
|
|
return 0;
|
|
|
|
int total = 0;
|
|
int size = inv.GetSize();
|
|
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
var item = inv.GetItem(i, false);
|
|
if (item != null && item.m_tid == itemId)
|
|
{
|
|
total += item.m_iCount;
|
|
}
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
int CalculateMaxProduceCount(uint recipeId)
|
|
{
|
|
var edm = ElementDataManProvider.GetElementDataMan();
|
|
if (edm == null)
|
|
return 0;
|
|
|
|
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
|
|
object data = edm.get_data_ptr(recipeId, ID_SPACE.ID_SPACE_RECIPE, ref dt);
|
|
|
|
if (data is not RECIPE_ESSENCE recipe || recipe.materials == null)
|
|
return 0;
|
|
|
|
int maxCount = int.MaxValue;
|
|
|
|
foreach (var mat in recipe.materials)
|
|
{
|
|
if (mat.id == 0 || mat.num <= 0)
|
|
continue;
|
|
|
|
int owned = GetInventoryItemCount(mat.id);
|
|
int canMake = owned / mat.num;
|
|
|
|
if (canMake < maxCount)
|
|
maxCount = canMake;
|
|
}
|
|
|
|
if (maxCount == int.MaxValue)
|
|
return 0;
|
|
|
|
return Mathf.Max(0, maxCount);
|
|
}
|
|
|
|
void OnClickMaxBtn()
|
|
{
|
|
if (selectedRecipeId == 0)
|
|
return;
|
|
|
|
int max = CalculateMaxProduceCount(selectedRecipeId);
|
|
|
|
if (max <= 0)
|
|
{
|
|
currentQuantity = 1;
|
|
}
|
|
else
|
|
{
|
|
currentQuantity = max;
|
|
}
|
|
|
|
UpdateQuantityText(currentQuantity);
|
|
ShowRecipeMaterials(selectedRecipeId);
|
|
|
|
Debug.Log($"[DlgProduce] Max produce quantity = {currentQuantity}");
|
|
}
|
|
|
|
void ResetItemInfoPanel()
|
|
{
|
|
currentInfoMode = ItemInfoMode.None;
|
|
|
|
if (infoNameText != null)
|
|
infoNameText.text = string.Empty;
|
|
|
|
if (infoDescText != null)
|
|
infoDescText.text = string.Empty;
|
|
|
|
if (infoExtraText != null)
|
|
infoExtraText.text = string.Empty;
|
|
|
|
HideItemInfo();
|
|
}
|
|
|
|
void ForceRefreshItemInfoLayout()
|
|
{
|
|
infoNameText?.ForceMeshUpdate();
|
|
infoDescText?.ForceMeshUpdate();
|
|
infoExtraText?.ForceMeshUpdate();
|
|
|
|
var rt = itemInfoRoot.GetComponent<RectTransform>();
|
|
if (rt != null)
|
|
LayoutRebuilder.ForceRebuildLayoutImmediate(rt);
|
|
}
|
|
|
|
void ShowResultItemInfo(EC_IvtrItem item, uint itemId)
|
|
{
|
|
ResetItemInfoPanel();
|
|
currentInfoMode = ItemInfoMode.ResultItem;
|
|
|
|
itemInfoRoot.gameObject.SetActive(true);
|
|
|
|
//infoNameText.text = EC_Utility.ProcessColorCodes(new StringBuilder(item.GetName()));
|
|
infoDescText.text = EC_Utility.ProcessColorCodes(
|
|
new StringBuilder(item.GetDesc()?.Replace("\\r", "\n") ?? "")
|
|
);
|
|
|
|
infoExtraText.text = $"Item ID: {itemId}";
|
|
|
|
ForceRefreshItemInfoLayout();
|
|
ShowEquippmentWeponInfo();
|
|
}
|
|
|
|
void ShowMaterialItemInfo(EC_IvtrItem item, uint itemId)
|
|
{
|
|
ResetItemInfoPanel();
|
|
currentInfoMode = ItemInfoMode.MaterialItem;
|
|
|
|
itemInfoRoot.gameObject.SetActive(true);
|
|
|
|
infoNameText.text = item.GetName();
|
|
|
|
infoDescText.text = item.GetDesc();
|
|
|
|
infoExtraText.text = $"Material ID: {itemId}";
|
|
|
|
ForceRefreshItemInfoLayout();
|
|
}
|
|
|
|
private EC_IvtrItem GetquippedWepon()
|
|
{
|
|
var host = CECGameRun.Instance?.GetHostPlayer();
|
|
if (host == null)
|
|
return null;
|
|
|
|
var currentEquipment = host.GetEquipment();
|
|
if (currentEquipment == null)
|
|
return null;
|
|
|
|
var srcItem = currentEquipment.GetItem(0);
|
|
if (srcItem != null && srcItem.m_iCID == (int)EC_IvtrItem.InventoryClassId.ICID_WEAPON)
|
|
{
|
|
var item = EC_IvtrItem.CreateItem(srcItem.m_tid, srcItem.m_expire_date, 1);
|
|
if (srcItem.Content != null && srcItem.Content.Length > 0)
|
|
item.SetItemInfo(srcItem.Content, srcItem.Content.Length);
|
|
return item;
|
|
}
|
|
return null;
|
|
}
|
|
private void ShowEquippmentWeponInfo()
|
|
{
|
|
if (weponInfoRoot == null)
|
|
return;
|
|
var weponItem = GetquippedWepon();
|
|
|
|
if (weponItem != null)
|
|
{
|
|
weponInfoRoot.gameObject.SetActive(true);
|
|
//weponNameInfoText.text = weponItem.GetName();
|
|
Debug.Log("[DlgProduce] Showing weapon info: " + weponItem);
|
|
|
|
weponDescInfoText.text = "<color=#00FF00>[Được trang bị]</color> \n" + EC_Utility.ProcessColorCodes(new StringBuilder(weponItem.GetDesc().Replace("\\r", "\n")));
|
|
//weponExtraInfoText.text = $"Item ID: {weponItem.m_tid}";
|
|
|
|
var rt = weponInfoRoot.GetComponent<RectTransform>();
|
|
if (rt != null)
|
|
LayoutRebuilder.ForceRebuildLayoutImmediate(rt);
|
|
}
|
|
else
|
|
{
|
|
weponInfoRoot.gameObject.SetActive(false);
|
|
}
|
|
|
|
}
|
|
|
|
private void ResetOnTop()
|
|
{
|
|
m_scrollRect.verticalNormalizedPosition = 1f;
|
|
}
|
|
|
|
public void OnDestroy()
|
|
{
|
|
ClearContainer(tabBtnContainer);
|
|
ClearContainer(itemContainer);
|
|
}
|
|
}
|
|
}
|