fix performent issual of using medicine
This commit is contained in:
@@ -81,6 +81,7 @@ namespace BrewMonster.Scripts
|
||||
|
||||
var old = m_aItems[iSlot];
|
||||
m_aItems[iSlot] = pItem;
|
||||
EventBus.Publish(new InventoryChangedEvent());
|
||||
return old;
|
||||
}
|
||||
|
||||
@@ -92,6 +93,7 @@ namespace BrewMonster.Scripts
|
||||
}
|
||||
|
||||
m_aItems[iSlot] = pItem;
|
||||
EventBus.Publish(new InventoryChangedEvent());
|
||||
}
|
||||
|
||||
public EC_IvtrItem GetItem(int iSlot, bool bRemove = false)
|
||||
@@ -144,6 +146,7 @@ namespace BrewMonster.Scripts
|
||||
m_aItems[iSlot] = newItem;
|
||||
piLastSlot = iSlot;
|
||||
piLastAmount = iAmount;
|
||||
EventBus.Publish(new InventoryChangedEvent());
|
||||
return true;
|
||||
}
|
||||
if (slotItem.GetTemplateID() != tid)
|
||||
@@ -156,6 +159,7 @@ namespace BrewMonster.Scripts
|
||||
slotItem.AddAmount(add);
|
||||
piLastSlot = iSlot;
|
||||
piLastAmount = slotItem.GetCount();
|
||||
EventBus.Publish(new InventoryChangedEvent());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -179,6 +183,7 @@ namespace BrewMonster.Scripts
|
||||
{
|
||||
piLastSlot = i;
|
||||
piLastAmount = slotItem.GetCount();
|
||||
EventBus.Publish(new InventoryChangedEvent());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -201,6 +206,7 @@ namespace BrewMonster.Scripts
|
||||
m_aItems[firstEmpty] = newItem;
|
||||
piLastSlot = firstEmpty;
|
||||
piLastAmount = iAmount;
|
||||
EventBus.Publish(new InventoryChangedEvent());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -240,6 +246,7 @@ namespace BrewMonster.Scripts
|
||||
}
|
||||
|
||||
RemoveItem(iSrc, iAmount);
|
||||
EventBus.Publish(new InventoryChangedEvent());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -258,6 +265,7 @@ namespace BrewMonster.Scripts
|
||||
if (newCount <= 0)
|
||||
m_aItems[iSlot] = null;
|
||||
|
||||
EventBus.Publish(new InventoryChangedEvent());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -352,4 +360,10 @@ namespace BrewMonster.Scripts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired when any client-side inventory pack mutates (add/remove/move/merge).
|
||||
/// Used by UI (quickbar HP/MP auto-pick) to re-evaluate best potions.
|
||||
/// </summary>
|
||||
public struct InventoryChangedEvent { }
|
||||
}
|
||||
|
||||
@@ -7,6 +7,30 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay
|
||||
public class AUIImageHPMPItem : AUIImagePicture
|
||||
{
|
||||
[SerializeField] TMP_Text m_TextAmount;
|
||||
private int _lastTemplateId = int.MinValue;
|
||||
private int _lastCount = int.MinValue;
|
||||
|
||||
public bool TrySetTemplateId(int templateId)
|
||||
{
|
||||
if (_lastTemplateId == templateId)
|
||||
return false;
|
||||
_lastTemplateId = templateId;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TrySetCount(int count)
|
||||
{
|
||||
if (_lastCount == count)
|
||||
return false;
|
||||
_lastCount = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ResetRenderCache()
|
||||
{
|
||||
_lastTemplateId = int.MinValue;
|
||||
_lastCount = int.MinValue;
|
||||
}
|
||||
public void SetText(string text)
|
||||
{
|
||||
if(m_TextAmount != null)
|
||||
|
||||
@@ -23,8 +23,34 @@ namespace BrewMonster
|
||||
[SerializeField] AUIImageHPMPItem HpItemButton = new AUIImageHPMPItem();
|
||||
[SerializeField] AUIImageHPMPItem MpItemButton = new AUIImageHPMPItem();
|
||||
|
||||
private bool _hpmpReselectDirty = true;
|
||||
|
||||
int currentListIndex = 0;
|
||||
CECSkill assignedSkill = null;
|
||||
public override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
EventBus.Subscribe<InventoryChangedEvent>(OnInventoryChanged);
|
||||
EventBus.Subscribe<CECHostPlayer.HostPlayerLevelUpUIEvent>(OnHostLevelUp);
|
||||
_hpmpReselectDirty = true;
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
EventBus.Unsubscribe<InventoryChangedEvent>(OnInventoryChanged);
|
||||
EventBus.Unsubscribe<CECHostPlayer.HostPlayerLevelUpUIEvent>(OnHostLevelUp);
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
private void OnInventoryChanged(InventoryChangedEvent _)
|
||||
{
|
||||
_hpmpReselectDirty = true;
|
||||
}
|
||||
|
||||
private void OnHostLevelUp(CECHostPlayer.HostPlayerLevelUpUIEvent _)
|
||||
{
|
||||
_hpmpReselectDirty = true;
|
||||
}
|
||||
/// <summary>
|
||||
/// Apply for a license remove later
|
||||
/// </summary>
|
||||
@@ -59,7 +85,7 @@ namespace BrewMonster
|
||||
AUIImagePicture pCell;
|
||||
CECSkill pSkill = new CECSkill(-1, -1);
|
||||
AUIClockIcon pClock;
|
||||
int iIconFile, nMax = 0;
|
||||
int iIconFile = 0, nMax = 0;
|
||||
|
||||
int nCurPanel9 = GetCurPanel1();
|
||||
int nCurPanel8 = GetCurPanel2();
|
||||
@@ -444,6 +470,9 @@ namespace BrewMonster
|
||||
if (pHost == null)
|
||||
return;
|
||||
|
||||
bool forceReselect = _hpmpReselectDirty;
|
||||
_hpmpReselectDirty = false;
|
||||
|
||||
// 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).
|
||||
@@ -519,6 +548,12 @@ namespace BrewMonster
|
||||
return item != null;
|
||||
}
|
||||
|
||||
static int GetHealScore(EC_IvtrMedicine med, int majorTypeId)
|
||||
{
|
||||
if (med == null) return 0;
|
||||
return majorTypeId == 1794 ? med.GetHpAddTotal() : med.GetMpAddTotal();
|
||||
}
|
||||
|
||||
void ApplyItemToButton(AUIImageHPMPItem button, CECShortcut sc, EC_IvtrItem item)
|
||||
{
|
||||
if (button == null)
|
||||
@@ -526,23 +561,39 @@ namespace BrewMonster
|
||||
|
||||
if (sc == null || item == null)
|
||||
{
|
||||
button.ResetRenderCache();
|
||||
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();
|
||||
// Skill-slot logic pattern: if the shortcut ptr hasn't changed and we're not forced to reselect,
|
||||
// avoid re-applying icon/text every frame.
|
||||
// 复用技能格的思路:快捷键指针没变且非强制刷新时,不要每帧重刷图标/数量。
|
||||
if (button.GetDataPtr() != sc)
|
||||
{
|
||||
button.SetDataPtr(sc);
|
||||
button.ResetRenderCache();
|
||||
}
|
||||
|
||||
int tid = item.GetTemplateID();
|
||||
if (button.TrySetTemplateId(tid))
|
||||
{
|
||||
// Inventory UI path is more reliable than icon-file string matching.
|
||||
// 背包UI的路径更稳定:按模板ID解析Sprite,而不是匹配图标文件名字符串
|
||||
var sp = EC_IvtrItemUtils.Instance.ResolveItemIconSprite(tid);
|
||||
if (sp != null)
|
||||
button.SetImage(sp);
|
||||
else
|
||||
button.Clear();
|
||||
}
|
||||
|
||||
// Amount text / 数量文本
|
||||
int count = Mathf.Max(0, item.GetCount());
|
||||
button.SetText(count > 0 ? count.ToString() : string.Empty);
|
||||
if (button.TrySetCount(count))
|
||||
{
|
||||
button.SetText(count > 0 ? count.ToString() : string.Empty);
|
||||
}
|
||||
|
||||
// Cooldown overlay / 冷却遮罩
|
||||
var clock = button.GetClockIcon();
|
||||
@@ -566,9 +617,13 @@ namespace BrewMonster
|
||||
|
||||
// Interactable state should reflect usability.
|
||||
// 可交互状态应该反映物品是否可使用
|
||||
bool usable = item.CheckUseCondition();
|
||||
// Mirror host-side restrictions like `UseItemInPack` uses (CANDO_USEITEM etc.)
|
||||
// 同步宿主侧限制(例如 CANDO_USEITEM),与 UseItemInPack 的限制保持一致
|
||||
bool hostCanUseItem = pHost.CanDo(CECHostPlayer.ActionCanDo.CANDO_USEITEM);
|
||||
bool usable = hostCanUseItem && item.CheckUseCondition() && !item.IsFrozen();
|
||||
bool cooling = (cool > 0 && max > 0);
|
||||
button.SetInteract(usable && !cooling);
|
||||
bool interact = usable && !cooling;
|
||||
button.SetInteract(interact);
|
||||
}
|
||||
|
||||
void EnsureAssignedAndRefresh(AUIImageHPMPItem button, int majorTypeId)
|
||||
@@ -578,15 +633,50 @@ namespace BrewMonster
|
||||
|
||||
CECShortcut sc = button.GetDataPtr();
|
||||
|
||||
// Resolve current shortcut item (if any).
|
||||
bool hasCurrent = TryGetShortcutItem(pHost, sc, out EC_IvtrItem item);
|
||||
|
||||
// Find best candidate (used both for initial assign and reselect-on-change).
|
||||
bool hasBest = TryFindBestMedicine(pHost, majorTypeId, out int bestPack, out int bestSlot, out EC_IvtrMedicine bestMed);
|
||||
|
||||
// If there is no valid shortcut item, auto assign the best available potion.
|
||||
if (!TryGetShortcutItem(pHost, sc, out EC_IvtrItem item))
|
||||
if (!hasCurrent)
|
||||
{
|
||||
if (TryFindBestMedicine(pHost, majorTypeId, out int pack, out int slot, out EC_IvtrMedicine med))
|
||||
if (hasBest)
|
||||
{
|
||||
var newSc = new CECSCItem();
|
||||
newSc.Init(pack, slot, med);
|
||||
newSc.Init(bestPack, bestSlot, bestMed);
|
||||
sc = newSc;
|
||||
item = med;
|
||||
item = bestMed;
|
||||
hasCurrent = true;
|
||||
}
|
||||
}
|
||||
else if (forceReselect && hasBest)
|
||||
{
|
||||
// Upgrade to best potion when inventory changes or level changes.
|
||||
// 背包变化或升级时,自动切换到“最优药品”
|
||||
var curMed = item as EC_IvtrMedicine;
|
||||
if (curMed == null || curMed.GetMajorTypeId() != majorTypeId || !curMed.CheckUseCondition())
|
||||
{
|
||||
var newSc = new CECSCItem();
|
||||
newSc.Init(bestPack, bestSlot, bestMed);
|
||||
sc = newSc;
|
||||
item = bestMed;
|
||||
}
|
||||
else
|
||||
{
|
||||
int curHeal = GetHealScore(curMed, majorTypeId);
|
||||
int bestHeal = GetHealScore(bestMed, majorTypeId);
|
||||
int curReq = curMed.GetLevelReq();
|
||||
int bestReq = bestMed.GetLevelReq();
|
||||
|
||||
if (bestHeal > curHeal || (bestHeal == curHeal && bestReq < curReq))
|
||||
{
|
||||
var newSc = new CECSCItem();
|
||||
newSc.Init(bestPack, bestSlot, bestMed);
|
||||
sc = newSc;
|
||||
item = bestMed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user