Merge pull request 'feature/hp-mp-button' (#312) from feature/hp-mp-button into develop
Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/312
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -341,5 +341,15 @@ namespace BrewMonster.Scripts
|
||||
m_aItems[i].Freeze(false);
|
||||
}
|
||||
}
|
||||
public void GetAllItemsOfType<T>(out List<T> items) where T : EC_IvtrItem
|
||||
{
|
||||
items = new List<T>();
|
||||
for (int i = 0; i < m_aItems.Length; i++)
|
||||
{
|
||||
if (m_aItems[i] != null)
|
||||
if (m_aItems[i] is T item)
|
||||
items.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,13 @@ namespace BrewMonster.Scripts
|
||||
protected MEDICINE_ESSENCE m_pDBEssence;
|
||||
|
||||
protected int m_iLevelReq;
|
||||
|
||||
// Expose data needed by UI/shortcut logic.
|
||||
// 暴露给UI/快捷栏需要的数据 (Expose data needed by UI/quickbar).
|
||||
public int GetMajorTypeId() => (int)m_pDBMajorType.id;
|
||||
public int GetLevelReq() => m_iLevelReq;
|
||||
public int GetHpAddTotal() => m_pDBEssence.hp_add_total;
|
||||
public int GetMpAddTotal() => m_pDBEssence.mp_add_total;
|
||||
/// <summary>
|
||||
/// Create medicine item (cac loai thuoc)
|
||||
/// </summary>
|
||||
@@ -171,14 +178,16 @@ namespace BrewMonster.Scripts
|
||||
}
|
||||
|
||||
// Check item use condition
|
||||
protected bool CheckUseCondition()
|
||||
public override bool CheckUseCondition()
|
||||
{
|
||||
CECHostPlayer pHost = CECGameRun.Instance.GetHostPlayer();
|
||||
if (pHost == null)
|
||||
return false;
|
||||
|
||||
if (pHost.GetMaxLevelSofar() < m_iLevelReq)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return IsUseable() && GetCount() > 0;
|
||||
}
|
||||
|
||||
// Get drop model for shown
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
namespace BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay
|
||||
{
|
||||
public class AUIImageHPMPItem : AUIImagePicture
|
||||
{
|
||||
[SerializeField] TMP_Text m_TextAmount;
|
||||
public void SetText(string text)
|
||||
{
|
||||
if(m_TextAmount != null)
|
||||
m_TextAmount.text = text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HP/MP item button should only execute its assigned shortcut.
|
||||
/// It must NOT open the assign-skill UI when empty.
|
||||
/// </summary>
|
||||
public override void Execute()
|
||||
{
|
||||
if (pSC != null)
|
||||
{
|
||||
pSC.Execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b2df34c4410f46b5865b5178bfe3058
|
||||
@@ -52,7 +52,7 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay
|
||||
}
|
||||
}
|
||||
|
||||
public void Execute()
|
||||
public virtual void Execute()
|
||||
{
|
||||
if (pSC != null )
|
||||
{
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace BrewMonster
|
||||
//[SerializeField] List<Image> m_aSkillImage = new List<Image>();
|
||||
//[SerializeField] List<Button> m_aSkillButton = new List<Button>();
|
||||
[SerializeField] List<AUIImagePicture> AUIImagePictureList = new List<AUIImagePicture>();
|
||||
public int m_nCurPanel1 = 1;
|
||||
public int m_nCurPanel2 = 1;
|
||||
[SerializeField] AUIImageHPMPItem HpItemButton = new AUIImageHPMPItem();
|
||||
[SerializeField] AUIImageHPMPItem MpItemButton = new AUIImageHPMPItem();
|
||||
|
||||
int currentListIndex = 0;
|
||||
CECSkill assignedSkill = null;
|
||||
@@ -30,8 +30,8 @@ namespace BrewMonster
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
// public int m_nCurPanel1 = 1;
|
||||
// public int m_nCurPanel2 = 1;
|
||||
public int m_nCurPanel1 = 1;
|
||||
public int m_nCurPanel2 = 1;
|
||||
public bool m_bShowAll1 = false;
|
||||
public bool m_bShowAll2 = false;
|
||||
public int m_nDisplayPanels1 = 0;
|
||||
@@ -432,9 +432,170 @@ namespace BrewMonster
|
||||
pCell.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
UpdateHpMpItem();
|
||||
return true;
|
||||
}
|
||||
public void UpdateHpMpItem()
|
||||
{
|
||||
const int HP_MAJOR_TYPE_ID = 1794;
|
||||
const int MP_MAJOR_TYPE_ID = 1802;
|
||||
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
if (pHost == null)
|
||||
return;
|
||||
|
||||
// Pick the first level-usable medicine with the lowest required level.
|
||||
// Prefer highest heal amount first, then lowest required level.
|
||||
// 优先选择“回复量最高”的药品,其次选择需求等级最低的 (Prefer max heal, tie-break by level).
|
||||
static bool TryFindBestMedicine(CECHostPlayer host, int majorTypeId, out int pack, out int slot, out EC_IvtrMedicine med)
|
||||
{
|
||||
pack = -1;
|
||||
slot = -1;
|
||||
med = null;
|
||||
|
||||
int bestHeal = int.MinValue;
|
||||
int bestReqLevel = int.MaxValue;
|
||||
|
||||
int[] packsToSearch = new int[]
|
||||
{
|
||||
InventoryConst.IVTRTYPE_PACK,
|
||||
InventoryConst.IVTRTYPE_TASKPACK,
|
||||
};
|
||||
|
||||
for (int p = 0; p < packsToSearch.Length; p++)
|
||||
{
|
||||
int curPack = packsToSearch[p];
|
||||
EC_Inventory inv = host.GetPack(curPack);
|
||||
if (inv == null)
|
||||
continue;
|
||||
|
||||
int size = inv.GetSize();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
EC_IvtrItem item = inv.GetItem(i);
|
||||
if (item is not EC_IvtrMedicine m)
|
||||
continue;
|
||||
|
||||
if (m.GetMajorTypeId() != majorTypeId)
|
||||
continue;
|
||||
|
||||
if (!m.CheckUseCondition())
|
||||
continue;
|
||||
|
||||
int heal = 0;
|
||||
// HP potion: use hp_add_total; MP potion: use mp_add_total.
|
||||
// 回血药用 hp_add_total;回蓝药用 mp_add_total。
|
||||
if (majorTypeId == 1794)
|
||||
heal = m.GetHpAddTotal();
|
||||
else if (majorTypeId == 1802)
|
||||
heal = m.GetMpAddTotal();
|
||||
|
||||
int req = m.GetLevelReq();
|
||||
if (heal > bestHeal || (heal == bestHeal && req < bestReqLevel))
|
||||
{
|
||||
bestHeal = heal;
|
||||
bestReqLevel = req;
|
||||
pack = curPack;
|
||||
slot = i;
|
||||
med = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return med != null && pack >= 0 && slot >= 0;
|
||||
}
|
||||
|
||||
static bool TryGetShortcutItem(CECHostPlayer host, CECShortcut sc, out EC_IvtrItem item)
|
||||
{
|
||||
item = null;
|
||||
if (host == null || sc is not CECSCItem scItem)
|
||||
return false;
|
||||
|
||||
EC_Inventory inv = host.GetPack(scItem.GetInventory());
|
||||
if (inv == null)
|
||||
return false;
|
||||
|
||||
item = inv.GetItem(scItem.GetIvtrSlot());
|
||||
return item != null;
|
||||
}
|
||||
|
||||
void ApplyItemToButton(AUIImageHPMPItem button, CECShortcut sc, EC_IvtrItem item)
|
||||
{
|
||||
if (button == null)
|
||||
return;
|
||||
|
||||
if (sc == null || item == null)
|
||||
{
|
||||
button.Clear();
|
||||
button.SetText(string.Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
button.SetDataPtr(sc);
|
||||
// Inventory UI uses templateId -> ResolveItemIconSprite, which is more reliable than string icon keys here.
|
||||
// 背包UI使用 templateId -> ResolveItemIconSprite,这里也用同一套更稳定 (use same path as Inventory UI).
|
||||
var sprite = EC_IvtrItemUtils.Instance.ResolveItemIconSprite(item.GetTemplateID());
|
||||
if (sprite != null)
|
||||
button.SetImage(sprite);
|
||||
else
|
||||
button.Clear();
|
||||
|
||||
// Amount text / 数量文本
|
||||
int count = Mathf.Max(0, item.GetCount());
|
||||
button.SetText(count > 0 ? count.ToString() : string.Empty);
|
||||
|
||||
// Cooldown overlay / 冷却遮罩
|
||||
var clock = button.GetClockIcon();
|
||||
int max = -1;
|
||||
int cool = 0;
|
||||
if (clock != null)
|
||||
{
|
||||
cool = item.GetCoolTime(out max);
|
||||
if (cool > 0 && max > 0)
|
||||
{
|
||||
clock.SetProgressRange(0, max);
|
||||
clock.SetProgressPos(max - cool);
|
||||
clock.SetColor(new Color32(0, 0, 0, 128));
|
||||
}
|
||||
else
|
||||
{
|
||||
clock.SetProgressRange(0, 1);
|
||||
clock.SetProgressPos(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Interactable state should reflect usability.
|
||||
// 可交互状态应该反映物品是否可使用
|
||||
bool usable = item.CheckUseCondition();
|
||||
bool cooling = (cool > 0 && max > 0);
|
||||
button.SetInteract(usable && !cooling);
|
||||
}
|
||||
|
||||
void EnsureAssignedAndRefresh(AUIImageHPMPItem button, int majorTypeId)
|
||||
{
|
||||
if (button == null)
|
||||
return;
|
||||
|
||||
CECShortcut sc = button.GetDataPtr();
|
||||
|
||||
// If there is no valid shortcut item, auto assign the best available potion.
|
||||
if (!TryGetShortcutItem(pHost, sc, out EC_IvtrItem item))
|
||||
{
|
||||
if (TryFindBestMedicine(pHost, majorTypeId, out int pack, out int slot, out EC_IvtrMedicine med))
|
||||
{
|
||||
var newSc = new CECSCItem();
|
||||
newSc.Init(pack, slot, med);
|
||||
sc = newSc;
|
||||
item = med;
|
||||
}
|
||||
}
|
||||
|
||||
ApplyItemToButton(button, sc, item);
|
||||
}
|
||||
|
||||
EnsureAssignedAndRefresh(HpItemButton, HP_MAJOR_TYPE_ID);
|
||||
EnsureAssignedAndRefresh(MpItemButton, MP_MAJOR_TYPE_ID);
|
||||
}
|
||||
private void GetQuickBarNameAndSC(CECHostPlayer pHost, List<string> pszPanel, List<CECShortcutSet> pSCS, int panel9, int panel8)
|
||||
{
|
||||
string dlgName;
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace BrewMonster.UI
|
||||
|
||||
private const string SKILL_ICONLIST_NAME = "iconlist_skill_multisprite";
|
||||
private const string ACTION_ICONLIST_NAME = "ActionIcon/iconlist_action_multisprite";
|
||||
private const string INVENTORY_ICONLIST_NAME = "UI/IconSprites/iconlist_ivtrm_multisprite";
|
||||
private const string STATE_ICONLIST_NAME = "iconlist_state";
|
||||
|
||||
public CDlgMiniMap m_pDlgMiniMap;
|
||||
@@ -375,11 +376,25 @@ namespace BrewMonster.UI
|
||||
|
||||
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_SKILL] = (SKILL_ICONLIST_NAME, Resources.LoadAll<Sprite>(SKILL_ICONLIST_NAME));
|
||||
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_ACTION] = (ACTION_ICONLIST_NAME, Resources.LoadAll<Sprite>(ACTION_ICONLIST_NAME));
|
||||
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_INVENTORY] = (INVENTORY_ICONLIST_NAME, Resources.LoadAll<Sprite>(INVENTORY_ICONLIST_NAME));
|
||||
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_STATE] = (STATE_ICONLIST_NAME, Resources.LoadAll<Sprite>(STATE_ICONLIST_NAME));
|
||||
}
|
||||
public void SetCover(AUIImagePictureBase pImgPic, string nameImage, EC_GAMEUI_ICONS iCONS_TYPE)
|
||||
{
|
||||
pImgPic.SetImage(m_IconMap[(byte)iCONS_TYPE].Item2.FirstOrDefault(s => s.name == nameImage));
|
||||
if (pImgPic == null)
|
||||
return;
|
||||
|
||||
if (m_IconMap == null || !m_IconMap.TryGetValue((byte)iCONS_TYPE, out var tuple) || tuple.Item2 == null)
|
||||
{
|
||||
pImgPic.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
var sprite = tuple.Item2.FirstOrDefault(s => s != null && s.name == nameImage);
|
||||
if (sprite != null)
|
||||
pImgPic.SetImage(sprite);
|
||||
else
|
||||
pImgPic.Clear();
|
||||
}
|
||||
|
||||
/// <summary>Refresh team UI (Arrange Team dialog). Called after team join/leave/member data.</summary>
|
||||
|
||||
@@ -2752,9 +2752,9 @@ RectTransform:
|
||||
- {fileID: 4504331075840543341}
|
||||
m_Father: {fileID: 1361524257611413148}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 469.781, y: -34.01085}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 179.9124, y: 68.0217}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8804506040386004496
|
||||
@@ -5515,9 +5515,9 @@ RectTransform:
|
||||
- {fileID: 2027606699309904338}
|
||||
m_Father: {fileID: 1361524257611413148}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 109.9562, y: -34.01085}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 179.9124, y: 68.0217}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &6741821173640675138
|
||||
@@ -17685,6 +17685,7 @@ MonoBehaviour:
|
||||
m_contentRootSkill: {fileID: 0}
|
||||
m_scrollRect: {fileID: 0}
|
||||
m_windowScale: 1
|
||||
totalSPText: {fileID: 0}
|
||||
m_isEvil: 0
|
||||
--- !u!1 &7758409605357852732
|
||||
GameObject:
|
||||
@@ -19226,9 +19227,9 @@ RectTransform:
|
||||
- {fileID: 911293677621153352}
|
||||
m_Father: {fileID: 1361524257611413148}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 289.8686, y: -34.01085}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 179.9124, y: 68.0217}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &5623009994815814977
|
||||
|
||||
Reference in New Issue
Block a user