Add Suite ("Noi dung bo trang bi") to show with item in inventory. Rename some Variant that have confuse name in hostplayer.

This commit is contained in:
Chomper9981
2026-01-16 13:35:51 +07:00
parent 785bcbbc26
commit e37fbefad4
17 changed files with 2160 additions and 1424 deletions
@@ -42,6 +42,9 @@ namespace BrewMonster
else
{
BMLogger.Log("ElementDataManProvider: Successfully loaded element data");
// Build suite equip tab now that data is loaded
// 数据加载完成后构建套装装备表
BrewMonster.Network.EC_Game.BuildSuiteEquipTab();
}
}
catch (Exception ex)
@@ -204,3 +204,21 @@ public struct ROLEEXTPROP_DEF
armor = 0;
}
};
// Profession
public enum PROFESSION
{
PROF_WARRIOR = 0, // 0:
PROF_MAGE, // 1:ʦ
PROF_MONK, // 2:ʦ
PROF_HAG, // 3:
PROF_ORC, // 4:
PROF_GHOST, // 5:̿
PROF_ARCHOR, // 6:â
PROF_ANGEL, // 7:
PROF_JIANLING, // 8:
PROF_MEILING, // 9:
PROF_YEYING, // 10:ҹӰ
PROF_YUEXIAN, // 11:
NUM_PROFESSION,
};
@@ -30,6 +30,8 @@ namespace BrewMonster
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public ushort[] name; // Name
public string Name => ByteToStringUtils.UshortArrayToUnicodeString(name);
public int num_params; // Number of parameters
public int param1; // Parameter 1
public int param2; // Parameter 2
@@ -559,6 +561,8 @@ namespace BrewMonster
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public ushort[] name; // Suite name, max 15 characters
public string Name => ByteToStringUtils.UshortArrayToUnicodeString(name);
public int max_equips; // Maximum equipment in suite
[StructLayout(LayoutKind.Sequential, Pack = 1)]
@@ -25,6 +25,8 @@ namespace BrewMonster.Network
private static BrewMonster.CECStringTab m_ItemDesc; // Item desciption string table
private static BrewMonster.CECStringTab m_ItemExtDesc; // Item extend description string table
private static BrewMonster.CECStringTab m_ItemExtProp; // Item extend prop string table
private static BrewMonster.CECStringTab ItemColTab; // Item color string table
private static Dictionary<int, int> m_SuiteEquipTab; // Item suite string table
private static BrewMonster.CECStringTab m_SkillDesc = new CECStringTab(); // Skill description string table
private static BrewMonster.CECStringTab m_BuffDesc; // Buff description string table
@@ -76,7 +78,15 @@ namespace BrewMonster.Network
{
return m_ItemExtProp;
}
public static BrewMonster.CECStringTab GetItemColTab()
{
return ItemColTab;
}
public static Dictionary<int, int> GetSuiteEquipTab()
{
Debug.Log("[EC_Game] GetSuiteEquipTab: " + m_SuiteEquipTab.Count);
return m_SuiteEquipTab;
}
public static bool TryGetItemMsg(int templateId, out int messageId, out int displayMode)
{
messageId = 0;
@@ -140,6 +150,8 @@ namespace BrewMonster.Network
m_SkillDesc = new BrewMonster.CECStringTab();
m_BuffDesc = new BrewMonster.CECStringTab();
m_ItemExtProp = new BrewMonster.CECStringTab();
ItemColTab = new BrewMonster.CECStringTab();
m_SuiteEquipTab = new Dictionary<int, int>();
try
{
// Addressables-only loading (no StreamingAssets/configs file IO).
@@ -174,10 +186,17 @@ namespace BrewMonster.Network
{
Debug.LogWarning("[EC_Game] Failed to load item_ext_prop.txt");
}
var itemColTa = Addressables.LoadAssetAsync<TextAsset>("Assets/Addressable/item_col.txt").WaitForCompletion();
if (!ItemColTab.InitFromTextAsset(itemColTa, true))
{
Debug.LogWarning("[EC_Game] Failed to load item_col.txt");
}
// Note: There's no buff_desc.txt file in the configs folder
// You may need to create this file or use a different source for buff descriptions
// (If you add it to Addressables later, load it here.)
// BuildSuiteEquipTab() is now called from ElementDataManProvider after data is loaded
// BuildSuiteEquipTab() 现在在 ElementDataManProvider 数据加载完成后调用
// Load item message map (template -> message id)
LoadItemMsgMap();
@@ -433,6 +452,86 @@ namespace BrewMonster.Network
map = list[0].strMap;
return true;
}
/// <summary>
/// Build suite equip tab mapping. Must be called after m_pElementDataMan is initialized and data is loaded.
/// 构建套装装备表映射。必须在 m_pElementDataMan 初始化且数据加载完成后调用。
/// </summary>
public static void BuildSuiteEquipTab()
{
if (m_pElementDataMan == null)
{
return;
}
// Ensure m_SuiteEquipTab is initialized
// 确保 m_SuiteEquipTab 已初始化
if (m_SuiteEquipTab == null)
{
m_SuiteEquipTab = new Dictionary<int, int>();
}
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
elementdataman _edm = ElementDataManProvider.GetElementDataMan();
for (int i = 0; i < _edm.essence_id_data_type_map.Count; i++)
{
uint tid = _edm.get_data_id(ID_SPACE.ID_SPACE_ESSENCE, i, ref DataType);
object pData = _edm.get_data_ptr(tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
switch (DataType)
{
case DATA_TYPE.DT_SUITE_ESSENCE:
SUITE_ESSENCE pSuiteEss = (SUITE_ESSENCE)pData;
pSuiteEss.max_equips = 0;
for (int j=0; j<12; j++)
{
if( pSuiteEss.equipments[j].id != 0 )
{
pSuiteEss.max_equips ++;
int index = (int)pSuiteEss.equipments[j].id;
m_SuiteEquipTab[index] = (int)tid;
}
}
break;
case DATA_TYPE.DT_POKER_SUITE_ESSENCE:
POKER_SUITE_ESSENCE pPokerSuiteEss = (POKER_SUITE_ESSENCE)pData;
for (int j=0; j<6; j++)
{
if( pPokerSuiteEss.list[j] != 0 )
{
int index = (int)pPokerSuiteEss.list[j];
m_SuiteEquipTab[index] = (int)tid;
}
}
break;
case DATA_TYPE.DT_FASHION_SUITE_ESSENCE:
FASHION_SUITE_ESSENCE pFashionSuiteEss = (FASHION_SUITE_ESSENCE)pData;
for (int j=0; j<6; j++)
{
if( pFashionSuiteEss.list[j] != 0 )
{
int index = (int)pFashionSuiteEss.list[j];
m_SuiteEquipTab[index] = (int)tid;
}
}
break;
}
}
}
public static int GetItemNameColorIdx(int tid, int iDefIndex = 0)
{
int iIndex = iDefIndex;
string color = ItemColTab.GetWideString(tid);
if (!string.IsNullOrEmpty(color))
iIndex = color.GetHashCode();
if (iIndex < 0 || iIndex >= 10)
{
iIndex = 0;
}
return iIndex;
}
#endregion
}
}
@@ -15,6 +15,7 @@ using System.Reflection;
using BrewMonster.Scripts.Managers;
using BrewMonster.Scripts;
using UnityEngine.AddressableAssets;
using CSNetwork.Protocols;
namespace PerfectWorld.Scripts.Managers
{
@@ -30,8 +31,74 @@ namespace PerfectWorld.Scripts.Managers
public const int ICID_EQUIP = 1;
public const int ICID_WEAPON = 2;
public enum EQUIP_CLASS_ID
{
ICID_ITEM = -100,
ICID_EQUIP = -101,
ICID_ARMOR = 0,
ICID_ARMORRUNE,
ICID_ARROW,
ICID_DECORATION,
ICID_DMGRUNE,
ICID_ELEMENT,
ICID_FASHION,
ICID_FLYSWORD,
ICID_MATERIAL,
ICID_MEDICINE,
ICID_REVSCROLL,
ICID_SKILLTOME,
ICID_TOSSMAT,
ICID_TOWNSCROLL,
ICID_UNIONSCROLL,
ICID_WEAPON,
ICID_TASKITEM,
ICID_STONE,
ICID_WING,
ICID_TASKDICE,
ICID_TASKNMMATTER,
ICID_ERRORITEM,
ICID_FACETICKET,
ICID_FACEPILL,
ICID_GM_GENERATOR,
ICID_RECIPE,
ICID_PETEGG,
ICID_PETFOOD,
ICID_PETFACETICKET,
ICID_FIREWORK,
ICID_TANKCALLIN,
ICID_SKILLMATTER,
ICID_REFINETICKET,
ICID_DESTROYINGESSENCE,
ICID_BIBLE,
ICID_SPEAKER,
ICID_AUTOHP,
ICID_AUTOMP,
ICID_DOUBLEEXP,
ICID_TRANSMITSCROLL,
ICID_DYETICKET,
ICID_GOBLIN,
ICID_GOBLIN_EQUIP,
ICID_GOBLIN_EXPPILL,
ICID_CERTIFICATE,
ICID_TARGETITEM,
ICID_LOOKINFOITEM,
ICID_INCSKILLABILITY,
ICID_WEDDINGBOOKCARD,
ICID_WEDDINGINVITECARD,
ICID_SHARPENER,
ICID_FACTIONMATERIAL,
ICID_CONGREGATE,
ICID_FORCETOKEN,
ICID_DYNSKILLEQUIP,
ICID_MONEYCONVERTIBLE,
ICID_MONSTERSPIRIT,
ICID_GENERALCARD,
ICID_GENERALCARD_DICE,
ICID_SHOPTOKEN,
ICID_UNIVERSAL_TOKEN,
}
// Item Made From Types
public enum ITEM_MAKE_TAG
public enum ITEM_MAKE_TAG
{
IMT_NULL,
IMT_CREATE, // GM
@@ -109,6 +176,9 @@ namespace PerfectWorld.Scripts.Managers
// Basic Item Properties
public int TemplateId { get; set; }
public int ExpireDate { get; set; }
/// <summary>
/// class id
/// </summary>
public int CID { get; set; }
public int Price { get; set; }
public int Count { get; set; }
@@ -583,7 +653,6 @@ namespace PerfectWorld.Scripts.Managers
// [6 x short requirements][2 x int endurance][short essenceSize][maker info][essence bytes][short numHole][WORD stoneMask][numHole x int holes][int numProp][props]
if (TryParseEquipInfoNative(infoData, dataLen))
{
BMLogger.Log("CECIvtrEquip::SetItemInfo, native order success");
ParseProperties();
return true;
}
@@ -591,7 +660,6 @@ namespace PerfectWorld.Scripts.Managers
// Fallback to legacy/custom order if server payload differs
if (TryParseEquipInfoLegacy(infoData, dataLen))
{
BMLogger.Log("CECIvtrEquip::SetItemInfo, legacy order success");
ParseProperties();
return true;
}
@@ -1233,7 +1301,6 @@ namespace PerfectWorld.Scripts.Managers
}
}
Debug.Log($"[EC_IvtrEquip] Loaded {s_propIdToType.Count} property mappings from Addressables");
}
else
{
@@ -1304,7 +1371,7 @@ namespace PerfectWorld.Scripts.Managers
/// <summary>
/// Decide equipment name color
/// </summary>
public int DecideNameCol()
protected override int DecideNameCol()
{
int index = GetColorStrID(TemplateId);
if (index >= 0)
@@ -1329,10 +1396,16 @@ namespace PerfectWorld.Scripts.Managers
/// <summary>
/// Get color string ID for template
/// </summary>
private int GetColorStrID(int templateId)
public override int GetColorStrID(int templateId)
{
// This would normally query the game's color system
return -1;
int iIndex = EC_Game.GetItemNameColorIdx(templateId);
if (iIndex <= 0)
return -1;
else if (iIndex < 7)
return (int)DescriptipionMsg.ITEMDESC_COL_LIGHTBLUE + iIndex - 1;
else
return (int)DescriptipionMsg.ITEMDESC_COL2_START + iIndex - 7 + 1;
}
#endregion
@@ -2177,6 +2250,11 @@ namespace PerfectWorld.Scripts.Managers
public int GetSuiteID()
{
// This would normally query the game's suite equip table
Dictionary<int, int> suiteEquipTab = EC_Game.GetSuiteEquipTab();
if (suiteEquipTab.TryGetValue(GetTemplateID(), out int suiteId))
{
return suiteId;
}
return 0;
}
@@ -4134,6 +4212,19 @@ namespace PerfectWorld.Scripts.Managers
}
}
struct SUITEITEM
{
public bool bEnabled;
public int tid;
public char[] szName;
public string Name => new string(szName);
public SUITEITEM(bool bEnabled, int tid)
{
this.bEnabled = bEnabled;
this.tid = tid;
this.szName = new char[32];
}
}
/// <summary>
/// Add suite description
/// </summary>
@@ -4152,63 +4243,128 @@ namespace PerfectWorld.Scripts.Managers
// ASSERT in C++
return;
}
// In C#, we'd need to cast to SUITE_ESSENCE struct
// For now, use placeholder values
string suiteName = "Suite"; // TODO: Get from SUITE_ESSENCE.name
int maxEquips = 12; // TODO: Get from SUITE_ESSENCE.max_equips
// Get host player (would normally come from EC_Game.GetGameRun().GetHostPlayer())
// Check if this equipment is in host's equipment pack
bool showDetail = false; // TODO: Check if m_pDescIvtr == pHostPlayer->GetEquipment()
SUITE_ESSENCE pSuiteEss = (SUITE_ESSENCE)pData;
CECHostPlayer hostPlayer = EC_Game.GetGameRun().GetHostPlayer();
// Colors
int nameCol = DecideNameCol();
int iNameCol = DecideNameCol();
int lblue = (int)DescriptipionMsg.ITEMDESC_COL_LIGHTBLUE;
int green = (int)DescriptipionMsg.ITEMDESC_COL_GREEN;
int gray = (int)DescriptipionMsg.ITEMDESC_COL_GRAY;
int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE;
int yellow = (int)DescriptipionMsg.ITEMDESC_COL_YELLOW;
// Save current description
string strCurDesc = m_strDesc;
if (!showDetail)
bool bShowDetail = true;
if (hostPlayer.GetEquipment() != m_pDescIvtr)
bShowDetail = false;
else
{
// Isn't equipment inventory, only add total suite number info.
for(int i = 0; i < m_pDescIvtr.GetSize(); i++)
{
EC_IvtrItem pItem = m_pDescIvtr.GetItem(i);
if (pItem == null)
{
bShowDetail = false;
continue;
}
if (pItem.m_tid == this.m_tid)
{
bShowDetail = true;
break;
}
}
}
if (!bShowDetail)
{
m_strDesc = "\\r\\r";
AddDescText(nameCol, false, "{0} ({1})", suiteName, maxEquips);
AddDescText(iNameCol, true, "{0} {1}/{2}", pSuiteEss.Name, 0, pSuiteEss.max_equips);
m_strDesc = strCurDesc + m_strDesc;
return;
}
// Maximum number of suite items
// Maximum number of suite items
const int MAX_NUM = 12;
SUITEITEM[] aSuiteItems = new SUITEITEM[MAX_NUM];
// Get equipped suite item list
int[] aEquipped = new int[MAX_NUM];
int itemCnt = 0; // TODO: Get from pHostPlayer->GetEquippedSuiteItem(idSuite, aEquipped)
if (itemCnt == 0)
return;
m_strDesc = "\\r\\r";
// Build suite addon properties at first
if (itemCnt > 1)
int maxEquips = (pSuiteEss.max_equips > MAX_NUM) ? MAX_NUM : (int)pSuiteEss.max_equips;
for(int i = 0; i < maxEquips; i++)
{
// Change color
AddDescText(lblue, false, "");
// In C++, this loops through suite addons and displays them
// For now, skip detailed addon display
aSuiteItems[i].bEnabled = false;
aSuiteItems[i].tid = (int)pSuiteEss.equipments[i].id;
aSuiteItems[i].szName = new char[32];
aSuiteItems[i].szName[0] = '\0';
EC_IvtrItem pEquipItem = CreateItem((int)pSuiteEss.equipments[i].id, 0,1);
if (pEquipItem != null)
{
aSuiteItems[i].szName = pEquipItem.GetName().ToCharArray();
//delete pEquipItem;
}
else
{
aSuiteItems[i].tid = 0;
}
}
int iItemCnt;
int[] aEquipped = new int[MAX_NUM];
iItemCnt = hostPlayer.GetEquippedSuiteItem(idSuite,ref aEquipped);
if(iItemCnt == 0) return;
m_strDesc += "\\r\\r";
// Build suite addon properties at first
for (int i = 0; i < MAX_NUM; i++)
{
for(int j = 0; j < iItemCnt; j++)
{
if (aSuiteItems[i].tid == aEquipped[j])
{
aSuiteItems[i].bEnabled = true;
break;
}
}
}
// Add suite name
AddDescText(yellow, true, "{0} ({1} / {2})", suiteName, itemCnt, maxEquips);
// List suite item names would go here
// In C++, this creates SUITEITEM array and lists enabled/disabled items
// green, gray, white colors would be used here for enabled/disabled items
// For now, simplified version
if(iItemCnt > 1)
{
// Change color
AddDescText(lblue, false, "");
for (int i=1; i < iItemCnt; i++)
{
int idProp = (int)pSuiteEss.addons[i-1].id;
if (idProp == 0)
continue;
pData = dataMan.get_data_ptr((uint)idProp, ID_SPACE.ID_SPACE_ADDON, ref dataType);
if (dataType != DATA_TYPE.DT_EQUIPMENT_ADDON)
{
continue;
}
EQUIPMENT_ADDON pAddOn = (EQUIPMENT_ADDON)pData;
AddDescText(-1, false, "(%d) ", i+1);
AddDescText(-1, true, "%s", pAddOn.Name);
}
}
// Add suite name
AddDescText(yellow/*iNameCol*/, true, "{0} ({1} / {2})", pSuiteEss.Name, iItemCnt, pSuiteEss.max_equips);
for (int i=0; i < pSuiteEss.max_equips; i++)
{
SUITEITEM suiteItem = aSuiteItems[i];
if (suiteItem.tid == 0)
continue;
int col = suiteItem.bEnabled ? green : gray;
bool bRet = (i == pSuiteEss.max_equips-1) ? false : true;
// Add item name
AddDescText(col, bRet, " %s", suiteItem.Name);
}
}
/// <summary>
/// Add destroying description
/// </summary>
@@ -4493,27 +4649,22 @@ namespace PerfectWorld.Scripts.Managers
if (string.IsNullOrEmpty(Maker))
return;
BMLogger.Log("[THN]EC_IvtrEquip: AddMakerDesc: Maker: " + Maker);
m_strDesc += "\\r";
m_strDesc += "\\r";
// For signed marks (IMT_SIGN), Maker already contains color codes and formatted text.
if (MadeFrom == (byte)ITEM_MAKE_TAG.IMT_SIGN)
{
BMLogger.Log("[THN]EC_IvtrEquip: AddMakerDesc IF: Maker: " + Maker);
m_strDesc += Maker;
}
else
{
BMLogger.Log("[THN]EC_IvtrEquip: AddMakerDesc ELSE: Maker: " + Maker);
// Normal "made by" line using item-desc string if available
string fmt = GetItemDescString(DescriptipionMsg.ITEMDESC_MADEFROM);
if (string.IsNullOrEmpty(fmt))
{
fmt = "Made by {0}";
}
BMLogger.Log("[THN]EC_IvtrEquip: AddMakerDesc ELSE: fmt: " + fmt);
AddDescText((int)DescriptipionMsg.ITEMDESC_COL_GREEN, false, fmt, Maker);
BMLogger.Log("[THN]EC_IvtrEquip: AddMakerDesc ELSE: m_strDesc: " + m_strDesc);
}
}
}
/// <summary>
@@ -167,17 +167,14 @@ namespace BrewMonster.Scripts.Managers
}
}
Debug.Log($"[Inventory] Loaded multi-sprite atlas with {atlasSprites.Length} sprites");
}
else
{
Debug.LogWarning("[Inventory] Failed to load multi-sprite atlas: iconlist_ivtrm_multisprite");
_multiSpriteAtlas = new Sprite[0]; // Prevent repeated loading attempts
}
}
catch (Exception ex)
{
Debug.LogError($"[Inventory] Error loading multi-sprite atlas: {ex.Message}");
_multiSpriteAtlas = new Sprite[0]; // Prevent repeated loading attempts
}
}
@@ -332,7 +329,6 @@ namespace BrewMonster.Scripts.Managers
try
{
var val = getNameMethod.Invoke(data, null) as string;
Debug.Log($"[Inventory] GetName method result: '{val}' (length: {val?.Length ?? 0})");
if (!string.IsNullOrEmpty(val) && !string.IsNullOrWhiteSpace(val)) return val;
}
catch (Exception ex)
@@ -459,15 +455,12 @@ namespace BrewMonster.Scripts.Managers
ci += extraLen;
}
var item = new EC_IvtrItem(tid, expireDate)
{
Package = byPackage,
Slot = slotIndex,
State = state,
Crc = crc,
Content = extra
};
item.SetCount(amount);
var item = EC_IvtrItem.CreateItem(tid, expireDate, amount);
item.Package = byPackage;
item.Slot = slotIndex;
item.State = state;
item.Crc = crc;
item.Content = extra;
items.Add(item);
}
@@ -823,7 +816,8 @@ namespace BrewMonster.Scripts.Managers
pItem = new EC_IvtrArmor(tid, expire_date);
break;
default:
BMLogger.Log("[THN]EC_IvtrItem: CreateItem: Default Item: tid: " + tid + ", expire_date: " + expire_date + ", pItem: " + pItem.GetName());
BMLogger.Log("[THN]EC_IvtrItem: CreateItem: Default Item for tid: " + tid + " is: " + pItem.GetName());
BMLogger.Log("[THN]TODO: Add create item with DataType: " + DataType);
break;
}
pItem.SetCount(iCount);
@@ -1516,7 +1510,7 @@ namespace BrewMonster.Scripts.Managers
str = iPrice.ToString();
}
protected int GetColorStrID(int tid)
public virtual int GetColorStrID(int templateId)
{
// Placeholder: color index lookup; return -1 (white) by default.
return -1;
@@ -94,7 +94,7 @@ namespace BrewMonster
public MOVECONST m_MoveConst; // Const used when moving control
public Move_Mode m_MoveMode;
public MOVECONST[] aMoveConsts = new MOVECONST[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
public MOVECONST[] aMoveConsts = new MOVECONST[(int)PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
{
// ÎäÏÀ
// fStepHei fMinAirHei fMinWaterHei fShoreDepth fWaterSurf
@@ -135,7 +135,7 @@ namespace BrewMonster
new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f),
};
public A3DVECTOR3[] aExts = new A3DVECTOR3[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
public A3DVECTOR3[] aExts = new A3DVECTOR3[(int)PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
{
new A3DVECTOR3(0.4f, 0.9f, 0.4f), // ÎäÏÀ
new A3DVECTOR3(0.3f, 0.85f, 0.3f),
@@ -1207,10 +1207,10 @@ namespace BrewMonster
// 空中动作 / Air action
string szActionMiddleName = null;
if ((m_wingType == enumWingType.WINGTYPE_WING && IsFlying()) ||
(m_iProfession == PROFESSION.PROF_ANGEL) ||
(m_iProfession == PROFESSION.PROF_ARCHOR) ||
(m_iProfession == PROFESSION.PROF_MONK) ||
(m_iProfession == PROFESSION.PROF_GHOST))
(m_iProfession == (int)PROFESSION.PROF_ANGEL) ||
(m_iProfession == (int)PROFESSION.PROF_ARCHOR) ||
(m_iProfession == (int)PROFESSION.PROF_MONK) ||
(m_iProfession == (int)PROFESSION.PROF_GHOST))
{
szActionMiddleName = "_空中翅膀"; // Air with wings / 空中翅膀
}
@@ -1,14 +1,15 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System;
namespace BrewMonster.Scripts.UI
{
public class AwardItem : MonoBehaviour
{
[SerializeField] private Image img;
[SerializeField] private Button btn;
[SerializeField] private GameObject objHint;
[SerializeField] private TMP_Text txtHint;
[SerializeField] private string txtHint;
[SerializeField] private bool isOn;
private bool _bShowHint = false;
private Vector2Int _position;
@@ -21,7 +22,7 @@ namespace BrewMonster.Scripts.UI
this.gameObject.name = "Item_" + row + "_" + column;
}
public void SetImage(Sprite sprite)
{
img.sprite = sprite;
@@ -40,13 +41,7 @@ namespace BrewMonster.Scripts.UI
public void SetHint(string text)
{
// TODO : Implement hint functionality
btn.onClick.RemoveAllListeners();
txtHint.text = text;
btn.onClick.AddListener(() => {
HintBehaviour();
});
txtHint = text;
}
public void ClearCover()
@@ -61,8 +56,18 @@ namespace BrewMonster.Scripts.UI
private void HintBehaviour()
{
_bShowHint = !_bShowHint;
objHint.SetActive(_bShowHint);
}
public void SetOnClick(Action<string, bool, AwardItem> action)
{
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => {
action?.Invoke(txtHint, !isOn, this);
});
}
public void HideHint()
{
isOn = false;
}
}
}
@@ -7,7 +7,7 @@ using PerfectWorld.Scripts.Managers;
using PerfectWorld.Scripts.Task;
using UnityEngine;
using UnityEngine.UI;
using BrewMonster.Scripts.UI;
namespace BrewMonster.Scripts.UI
{
public class CDlgAward : AUIDialog
@@ -22,6 +22,11 @@ namespace BrewMonster.Scripts.UI
[SerializeField] private Transform _itemsParent;
[SerializeField] private Toggle[] _radioButtons;
[Header("ItemDetail")]
[SerializeField] GameObject itemInfoPanel;
[SerializeField] Vector2 itemInfoPanelOffset = new Vector2(20f, 0f);
[SerializeField] private TextOutlet descriptionOutlet;
[Header("DEBUG")]
[SerializeField] private AwardItem[] _awardItems;
@@ -39,7 +44,10 @@ namespace BrewMonster.Scripts.UI
{
SpawnItems();
InitRadioBtns();
// this is copy paste from InventoryUI.cs. so it have equip and drop button.
// temporary disable them
itemInfoPanel.SetActive(false);
itemInfoPanel.transform.GetChild(0).gameObject.SetActive(false);
m_pBtn_Confirm.onClick.AddListener(OnCommand_confirm);
}
@@ -141,6 +149,7 @@ namespace BrewMonster.Scripts.UI
pItem.GetDetailDataFromLocal();
string strDesc = pItem.GetDesc();
pImage.SetHint(strDesc); // TODO
pImage.SetOnClick(OnAwardItemClicked);
//Debug.Log("[THN]CDlgAward: pItem.GetDesc():" + pItem.GetDesc());
// af_GetFileTitle(pItem.GetIconFile(), strFile); // TODO
strFile.ToLower();
@@ -373,6 +382,114 @@ namespace BrewMonster.Scripts.UI
}
}
void OnAwardItemClicked(string hint, bool isOn, AwardItem awardItem)
{
if(isOn)
{
descriptionOutlet.Set(hint);
PositionDetailPanelNearButton(awardItem);
}
else
{
descriptionOutlet.Set("");
}
itemInfoPanel.SetActive(isOn);
RefreshLayout(itemInfoPanel);
}
private void PositionDetailPanelNearButton(AwardItem awardItem)
{
if (itemInfoPanel == null || awardItem == null)
{
return;
}
var panelRect = itemInfoPanel.transform as RectTransform;
if (panelRect == null)
{
return;
}
var buttonRect = awardItem.transform as RectTransform;
if (buttonRect == null)
{
return;
}
var canvas = panelRect.GetComponentInParent<Canvas>();
if (canvas == null)
{
return;
}
var parentRect = panelRect.parent as RectTransform;
if (parentRect == null)
{
return;
}
Camera eventCamera = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera;
Vector3 worldCenter = buttonRect.TransformPoint(buttonRect.rect.center);
Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(eventCamera, worldCenter);
Vector2 localPoint;
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRect, screenPoint, eventCamera, out localPoint))
{
return;
}
float btnHalfW = buttonRect.rect.width * 0.5f;
float panelW = panelRect.rect.width;
float panelH = panelRect.rect.height;
float pivotX = panelRect.pivot.x;
float pivotY = panelRect.pivot.y;
// Compute right-placement candidate (panel's left edge at button's right edge + offset)
// 计算右侧放置候选位置(面板左边缘在按钮右边缘 + 偏移量)
float leftEdgeRightPlacement = localPoint.x + btnHalfW + itemInfoPanelOffset.x;
float candidateXRight = leftEdgeRightPlacement + pivotX * panelW;
// Compute left-placement candidate (panel's right edge at button's left edge - offset)
// 计算左侧放置候选位置(面板右边缘在按钮左边缘 - 偏移量)
float rightEdgeLeftPlacement = localPoint.x - btnHalfW - itemInfoPanelOffset.x;
float candidateXLeft = rightEdgeLeftPlacement - (1f - pivotX) * panelW;
// Vertical clamping honoring pivot
// 垂直方向根据pivot进行限制
float minY = parentRect.rect.yMin + pivotY * panelH;
float maxY = parentRect.rect.yMax - (1f - pivotY) * panelH;
float candidateY = Mathf.Clamp(localPoint.y + itemInfoPanelOffset.y, minY, maxY);
// Choose side based on available space
// 根据可用空间选择放置侧
float rightEdgeOfRight = candidateXRight + (1f - pivotX) * panelW;
float canvasRight = parentRect.rect.xMax;
float canvasLeft = parentRect.rect.xMin;
float leftEdgeOfLeft = candidateXLeft - pivotX * panelW;
Vector2 finalPos;
if (rightEdgeOfRight <= canvasRight)
{
finalPos = new Vector2(candidateXRight, candidateY);
}
else if (leftEdgeOfLeft >= canvasLeft)
{
finalPos = new Vector2(candidateXLeft, candidateY);
}
else
{
// Fallback: clamp within canvas horizontally
// 回退:在画布内水平方向限制
float minX = canvasLeft + pivotX * panelW;
float maxX = canvasRight - (1f - pivotX) * panelW;
finalPos = new Vector2(Mathf.Clamp(candidateXRight, minX, maxX), candidateY);
}
panelRect.anchoredPosition = finalPos;
}
public void RefreshLayout(GameObject gameObject)
{
var parent = gameObject.GetComponent<RectTransform>();
// Force Unity to rebuild layout immediately
parent.ForceUpdateRectTransforms();
LayoutRebuilder.ForceRebuildLayoutImmediate(parent);
}
}
}
@@ -0,0 +1,51 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
namespace BrewMonster.Scripts.UI
{
/// <summary>
/// Helper class to set text on both legacy Text and TextMeshPro components
/// Supports automatic formatting for Perfect World text codes
/// </summary>
[System.Serializable]
public class TextOutlet
{
[SerializeField] public Text legacy;
[SerializeField] public TMPro.TextMeshProUGUI tmp;
public void Set(string value)
{
if (legacy != null)
{
legacy.text = EC_Utility.FormatForLegacyText(value ?? string.Empty);
}
if (tmp != null)
{
tmp.text = EC_Utility.FormatForTextMeshPro(value ?? string.Empty);
}
}
/// <summary>
/// Set text with explicit formatting preference
/// </summary>
/// <param name="value">Raw text with formatting codes</param>
/// <param name="preferTextMeshPro">Whether to prefer TextMeshPro formatting</param>
public void SetFormatted(string value, bool preferTextMeshPro = true)
{
string formattedText = preferTextMeshPro ?
EC_Utility.FormatForTextMeshPro(value ?? string.Empty) :
EC_Utility.FormatForLegacyText(value ?? string.Empty);
if (legacy != null)
{
legacy.text = formattedText;
}
if (tmp != null)
{
tmp.text = formattedText;
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a5c1c1cd1df1d4d7980499bf1ab6b179
+180 -217
View File
@@ -1,81 +1,5 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &165174036537021008
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3386269673238764405}
- component: {fileID: 5695467372271221829}
- component: {fileID: 8051377020245334668}
m_Layer: 5
m_Name: Panel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!224 &3386269673238764405
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 165174036537021008}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1815682412766530288}
m_Father: {fileID: 2175163742848198118}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 366.661, y: -167.5}
m_SizeDelta: {x: 531, y: 335}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5695467372271221829
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 165174036537021008}
m_CullTransparentMesh: 1
--- !u!114 &8051377020245334668
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 165174036537021008}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &227158560462075115
GameObject:
m_ObjectHideFlags: 0
@@ -477,6 +401,7 @@ RectTransform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2109723218317570040}
- {fileID: 7191187217159756027}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -507,6 +432,11 @@ MonoBehaviour:
- {fileID: 2166136893266299956}
- {fileID: 1707764266222510119}
- {fileID: 2876579923345408843}
itemInfoPanel: {fileID: 2914562378533747067}
itemInfoPanelOffset: {x: 20, y: 0}
descriptionOutlet:
legacy: {fileID: 0}
tmp: {fileID: 6034451007464405912}
_awardItems: []
--- !u!1 &1403327757381850957
GameObject:
@@ -1298,7 +1228,6 @@ RectTransform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 504415793170309261}
- {fileID: 3386269673238764405}
m_Father: {fileID: 1558872982091896349}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -1320,8 +1249,8 @@ MonoBehaviour:
m_EditorClassIdentifier:
img: {fileID: 5798109676702798723}
btn: {fileID: 5829300517807457460}
objHint: {fileID: 165174036537021008}
txtHint: {fileID: 7658705790532366309}
txtHint:
isOn: 0
--- !u!222 &1897581106405175503
CanvasRenderer:
m_ObjectHideFlags: 0
@@ -1561,7 +1490,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 2fafe2cfe61f6974895a912c3755e8f1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_AllowSwitchOff: 0
m_AllowSwitchOff: 1
--- !u!1 &5325640235670539457
GameObject:
m_ObjectHideFlags: 0
@@ -1637,142 +1566,6 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5403631556117558338
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1815682412766530288}
- component: {fileID: 8320041494551075808}
- component: {fileID: 7658705790532366309}
m_Layer: 5
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1815682412766530288
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5403631556117558338}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3386269673238764405}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -20, y: -20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8320041494551075808
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5403631556117558338}
m_CullTransparentMesh: 1
--- !u!114 &7658705790532366309
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5403631556117558338}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: New Text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 0, g: 0, b: 0, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 36
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &5498099694921818792
GameObject:
m_ObjectHideFlags: 0
@@ -1883,7 +1676,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: -0.53490067, y: 0.7298012}
m_AnchoredPosition: {x: -0.53490067, y: 0.72979736}
m_SizeDelta: {x: -17.4895, y: -18.3651}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &673608011296253043
@@ -2518,3 +2311,173 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1001 &8554979174101426034
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 2539478906271782923}
m_Modifications:
- target: {fileID: 636299721907915661, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 636299721907915661, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMin.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 636299721907915661, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchoredPosition.x
value: 20
objectReference: {fileID: 0}
- target: {fileID: 636299721907915661, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchoredPosition.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMax.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMax.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMin.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMin.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_SizeDelta.x
value: 450
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6830833846243993097, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_Name
value: item_info
objectReference: {fileID: 0}
- target: {fileID: 7209086543831860202, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7209086543831860202, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMin.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7209086543831860202, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchoredPosition.x
value: 20
objectReference: {fileID: 0}
- target: {fileID: 7209086543831860202, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchoredPosition.y
value: -805.53
objectReference: {fileID: 0}
- target: {fileID: 8894405194986632892, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 8894405194986632892, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchorMin.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 8894405194986632892, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8894405194986632892, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchoredPosition.x
value: 20
objectReference: {fileID: 0}
- target: {fileID: 8894405194986632892, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
propertyPath: m_AnchoredPosition.y
value: -402.765
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
--- !u!1 &2914562378533747067 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 6830833846243993097, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
m_PrefabInstance: {fileID: 8554979174101426034}
m_PrefabAsset: {fileID: 0}
--- !u!114 &6034451007464405912 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 2668322321768899818, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
m_PrefabInstance: {fileID: 8554979174101426034}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!224 &7191187217159756027 stripped
RectTransform:
m_CorrespondingSourceObject: {fileID: 1546246053547542409, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
m_PrefabInstance: {fileID: 8554979174101426034}
m_PrefabAsset: {fileID: 0}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c56ed80641ff74ce49f91401e3eb8367
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+132 -24
View File
@@ -18,6 +18,7 @@ using PerfectWorld.Scripts.Managers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
@@ -162,13 +163,16 @@ namespace BrewMonster
// ===== Inventory packs (instance-based) =====
// 0 = normal pack, 1 = equip pack, 2 = task pack (see InventoryConst.IVTRTYPE_*)
private readonly EC_Inventory m_packInventory = new EC_Inventory();
private readonly EC_Inventory m_equipInventory = new EC_Inventory();
private readonly EC_Inventory m_taskInventory = new EC_Inventory();
private readonly EC_Inventory m_pPack = new EC_Inventory();
/// <summary>
/// m_pEquipPack is changed to m_equipInventory
/// </summary>
private readonly EC_Inventory m_pEquipPack = new EC_Inventory();
private readonly EC_Inventory m_pTaskPack = new EC_Inventory();
public EC_Inventory PackInventory => m_packInventory;
public EC_Inventory EquipInventory => m_equipInventory;
public EC_Inventory TaskInventory => m_taskInventory;
public EC_Inventory IvtrPack => m_pPack;
public EC_Inventory IvtrEquipPack => m_pEquipPack;
public EC_Inventory IvtrTaskPack => m_pTaskPack;
public Transform PointCam { get => pointCam; }
@@ -187,10 +191,18 @@ namespace BrewMonster
{
return m_pAutoTeam;
}
public EC_Inventory GetPack()
{
return m_pPack;
}
public EC_Inventory GetTaskPack()
{
return m_taskInventory;
return m_pTaskPack;
}
public EC_Inventory GetEquipment()
{
return m_pEquipPack;
}
// Get work manager // 获取工作管理器
@@ -244,11 +256,11 @@ namespace BrewMonster
switch (byPackage)
{
case InventoryConst.IVTRTYPE_PACK:
return m_packInventory;
return m_pPack;
case InventoryConst.IVTRTYPE_EQUIPPACK:
return m_equipInventory;
return m_pEquipPack;
case InventoryConst.IVTRTYPE_TASKPACK:
return m_taskInventory;
return m_pTaskPack;
default:
return null;
}
@@ -3655,11 +3667,6 @@ namespace BrewMonster
}
}
public EC_Inventory GetPack()
{
return m_packInventory;
}
private void LogInventoryPacket(string tag, byte[] buffer, int hostId)
{
if (buffer == null)
@@ -4009,7 +4016,7 @@ namespace BrewMonster
{
// Use host player's equipment inventory (per-instance CECInventory)
var host = CECGameRun.Instance?.GetHostPlayer();
var equipInv = host?.EquipInventory;
var equipInv = host?.IvtrEquipPack;
pItem = equipInv?.GetItem(i, false);
if (pItem != null)
aNewEquips[i] = pItem.m_tid;
@@ -4176,7 +4183,7 @@ namespace BrewMonster
Info.mp = m_BasicProps.iCurMP;
Info.ap = m_BasicProps.iCurAP;
Info.form = m_iShape; // Different from PW, no need to mask
Info.freepackage = m_packInventory.GetEmptySlotNum();
Info.freepackage = m_pPack.GetEmptySlotNum();
Info.move_env = GetMoveEnv();
Info.is_combat = IsFighting();
Info.hp = m_BasicProps.iCurHP;
@@ -4191,7 +4198,7 @@ namespace BrewMonster
Info.weapon = 0;
Info.arrow = 0;
EC_IvtrItem pWeaponItem = m_equipInventory.GetItem(EQUIPIVTR_WEAPON);
EC_IvtrItem pWeaponItem = m_pEquipPack.GetItem(EQUIPIVTR_WEAPON);
if (pWeaponItem != null && pWeaponItem is EC_IvtrEquip pWeaponEquip)
{
// Check if weapon has endurance
@@ -4204,7 +4211,7 @@ namespace BrewMonster
}
// Get remaining arrow number
EC_IvtrItem pArrowItem = m_equipInventory.GetItem(EQUIPIVTR_PROJECTILE);
EC_IvtrItem pArrowItem = m_pEquipPack.GetItem(EQUIPIVTR_PROJECTILE);
if (pArrowItem != null)
{
// TODO: Implement CanUseProjectile method to check requirements
@@ -5964,7 +5971,7 @@ namespace BrewMonster
}
else
{
if (PackInventory.CanAddItem(idItem, iAmount, false) >= 0)
if (IvtrPack.CanAddItem(idItem, iAmount, false) >= 0)
bCanPick = true;
}
@@ -5992,14 +5999,14 @@ namespace BrewMonster
if (idTool != 0)
{
int iIndex = PackInventory.FindItem(idTool);
int iIndex = IvtrPack.FindItem(idTool);
if (iIndex >= 0)
{
piPack = EC_Inventory.Inventory_type.IVTRTYPE_PACK;
piIndex = iIndex;
pidTool = idTool;
}
else if ((iIndex = TaskInventory.FindItem(idTool)) >= 0)
else if ((iIndex = IvtrTaskPack.FindItem(idTool)) >= 0)
{
piPack = EC_Inventory.Inventory_type.IVTRTYPE_TASKPACK;
piIndex = iIndex;
@@ -6386,7 +6393,7 @@ namespace BrewMonster
if (!CanDo(ActionCanDo.CANDO_FLY))
return false;
EC_IvtrItem pItem = EquipInventory.GetItem(InventoryConst.EQUIPIVTR_FLYSWORD);
EC_IvtrItem pItem = IvtrEquipPack.GetItem(InventoryConst.EQUIPIVTR_FLYSWORD);
if (pItem == null)
return false;
@@ -6462,5 +6469,106 @@ namespace BrewMonster
m_bRushFly = pCmd.is_active != 0 ? true : false;
}
}
public int GetEquippedSuiteItem(int idSuite, ref int[] aItems)
{
int i, iItemCnt = 0;
for(i = 0; i < m_pEquipPack.GetSize(); i++)
{
Debug.Log("[THN] GetEquippedSuiteItem: pItem: " + m_pEquipPack.GetItem(i));
var pItem = m_pEquipPack.GetItem(i);
if(pItem == null || (pItem is not EC_IvtrWeapon && pItem is not EC_IvtrArmor))
{
continue;
}
EC_IvtrEquip pEquip = (EC_IvtrEquip)pItem;
if (pEquip == null)
{
Debug.Log("[THN] GetEquippedSuiteItem: pEquip == null");
continue;
}
if(pEquip.GetSuiteID() != idSuite)
{
Debug.Log("[THN] GetEquippedSuiteItem: pEquip.GetSuiteID() != idSuite " + " pEquip.GetTemplateID() " + pEquip.GetTemplateID() + " idSuite " + idSuite);
continue;
}
int iReason = 0;
if(!CanUseEquipment(pEquip, ref iReason))
{
Debug.Log("[THN] GetEquippedSuiteItem: CanUseEquipment(pEquip, ref iReason) == false");
Debug.Log("[THN] GetEquippedSuiteItem: iReason: " + iReason);
continue;
}
if(pEquip.CID == (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_GENERALCARD)
{
//TODO: Add general card Suite
}
if(aItems.Length > 0)
{
Debug.Log("[THN] GetEquippedSuiteItem: aItems.Length > 0");
aItems[iItemCnt] = pEquip.GetTemplateID();
}
iItemCnt++;
}
return iItemCnt;
}
bool CanUseEquipment(EC_IvtrEquip pEquip, ref int piReason)
{
int iReason = 0;
if(pEquip == null)
{
iReason = 1;
goto End;
}
if(GetMaxLevelSofar() < pEquip.LevelReq||
m_ExtProps.bs.strength < pEquip.StrengthReq||
m_ExtProps.bs.agility < pEquip.AgilityReq||
m_ExtProps.bs.vitality < pEquip.VitalityReq||
m_ExtProps.bs.energy < pEquip.EnergyReq/*||
Reputation < pEquip.ReputationReq*/)//todo Add reputation check
{
iReason = 2;
goto End;
}
switch(pEquip.CID)//class id
{
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_ARROW:
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_WING:
if (m_iProfession != (int)PROFESSION.PROF_ARCHOR && m_iProfession != (int)PROFESSION.PROF_ANGEL)
iReason = 3;
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_FLYSWORD:
//TODO: Add flysword check
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_FASHION:
//TODO: Add fashion check
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_ARMOR:
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_DECORATION:
if ((pEquip.ProfReq & (1 << m_iProfession)) == 0)
iReason = 3;
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_WEAPON:
if ((pEquip.ProfReq & (1 << m_iProfession)) == 0)
iReason = 3;
else
{
//TODO: check range weapon arrow
}
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_GENERALCARD:
// TODO: Add general card check
break;
default:
break;
}
End:
if(piReason > 0)
{
piReason = iReason;
}
return iReason == 0? true : false;
}
}
}
+1 -1
View File
@@ -147,7 +147,7 @@ namespace BrewMonster
{
// Use host player's equipment inventory (per-instance CECInventory)
var host = CECGameRun.Instance?.GetHostPlayer();
var equipInv = host?.EquipInventory;
var equipInv = host?.IvtrEquipPack;
pItem = equipInv?.GetItem(i, false);
if (pItem != null)
aNewEquips[i] = pItem.m_tid;