use item but cooldown don't active
This commit is contained in:
@@ -601,7 +601,7 @@ namespace BrewMonster.Scripts
|
||||
case CECHPWork.Host_work_ID.WORK_TRACEOBJECT: pWork = new CECHPWorkTrace(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_HACKOBJECT: pWork = new CECHPWorkMelee(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_SPELLOBJECT: pWork = new CECHPWorkSpell(this); break;
|
||||
//case CECHPWork.Host_work_ID.WORK_USEITEM: pWork = new CECHPWorkUse(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_USEITEM: pWork = new CECHPWorkUse(this); break;
|
||||
//case CECHPWork.Host_work_ID.WORK_DEAD: pWork = new CECHPWorkDead(this); break;
|
||||
//case CECHPWork.Host_work_ID.WORK_FOLLOW: pWork = new CECHPWorkFollow(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_FLYOFF: pWork = new CECHPWorkFly(this); break;
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using CSNetwork.GPDataType;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster.Scripts
|
||||
{
|
||||
/// <summary>
|
||||
/// Host player work: Use item
|
||||
/// 主角玩家工作:使用物品
|
||||
/// </summary>
|
||||
public class CECHPWorkUse : CECHPWork
|
||||
{
|
||||
// Fields / 字段
|
||||
private int m_idItem; // Item template ID / 物品模板ID
|
||||
private int m_idTarget; // Target object ID / 目标对象ID
|
||||
private bool m_bWorkForMonsterSpirit; // Is this work for monster spirit gathering? / 是否为命轮采集工作
|
||||
private CECCounter m_UseTimeCnt; // Use time counter / 使用时间计数器
|
||||
|
||||
/// <summary>
|
||||
/// Constructor / 构造函数
|
||||
/// </summary>
|
||||
public CECHPWorkUse(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_USEITEM, pWorkMan)
|
||||
{
|
||||
m_dwMask = Work_mask.MASK_USEITEM;
|
||||
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS;
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset work / 重置工作
|
||||
/// </summary>
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
m_idItem = 0;
|
||||
m_idTarget = 0;
|
||||
m_bWorkForMonsterSpirit = false;
|
||||
|
||||
if (m_UseTimeCnt == null)
|
||||
m_UseTimeCnt = new CECCounter();
|
||||
|
||||
m_UseTimeCnt.SetPeriod(100);
|
||||
m_UseTimeCnt.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy work data / 复制工作数据
|
||||
/// </summary>
|
||||
public override bool CopyData(CECHPWork pWork)
|
||||
{
|
||||
if (!base.CopyData(pWork))
|
||||
return false;
|
||||
|
||||
CECHPWorkUse pSrc = pWork as CECHPWorkUse;
|
||||
if (pSrc == null)
|
||||
return false;
|
||||
|
||||
m_idItem = pSrc.m_idItem;
|
||||
m_idTarget = pSrc.m_idTarget;
|
||||
m_bWorkForMonsterSpirit = pSrc.m_bWorkForMonsterSpirit;
|
||||
|
||||
m_UseTimeCnt.SetPeriod(pSrc.m_UseTimeCnt.GetPeriod());
|
||||
m_UseTimeCnt.SetCounter(pSrc.m_UseTimeCnt.GetCounter());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On first tick / 第一帧执行
|
||||
/// </summary>
|
||||
protected override void OnFirstTick()
|
||||
{
|
||||
if (m_pHost == null)
|
||||
return;
|
||||
|
||||
m_pHost.m_iMoveMode = (int)MoveMode.MOVE_STAND;
|
||||
|
||||
EC_IvtrItem pItem = EC_IvtrItem.CreateItem(m_idItem, 0, 1);
|
||||
if (pItem == null)
|
||||
return;
|
||||
|
||||
if (m_bWorkForMonsterSpirit)
|
||||
{
|
||||
// Play gather monster spirit action / 播放采集命轮动作
|
||||
// TODO: Implement PlayGatherMonsterSpiritAction if needed
|
||||
// m_pHost.PlayGatherMonsterSpiritAction();
|
||||
Debug.Log($"[CECHPWorkUse] Playing gather monster spirit action for item {m_idItem}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play start use item action / 播放开始使用物品动作
|
||||
// TODO: Implement PlayStartUseItemAction if needed
|
||||
// m_pHost.PlayStartUseItemAction(m_idItem);
|
||||
Debug.Log($"[CECHPWorkUse] Playing start use item action for item {m_idItem}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Work is cancelled / 工作被取消
|
||||
/// </summary>
|
||||
public override void Cancel()
|
||||
{
|
||||
if (m_idTarget != 0 && m_pHost != null)
|
||||
{
|
||||
m_pHost.TurnFaceTo(0);
|
||||
}
|
||||
|
||||
base.Cancel();
|
||||
|
||||
// TODO: Implement AP_ActionEvent if needed
|
||||
// AP_ActionEvent(AP_EVENT_STOPUSEITEM);
|
||||
Debug.Log("[CECHPWorkUse] Work cancelled - STOPUSEITEM event");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set parameters / 设置参数
|
||||
/// </summary>
|
||||
/// <param name="idItem">Item template ID / 物品模板ID</param>
|
||||
/// <param name="dwUseTime">Use time in milliseconds / 使用时间(毫秒)</param>
|
||||
/// <param name="idTarget">Target object ID / 目标对象ID</param>
|
||||
/// <param name="bWorkForMonsterSpirit">Is for monster spirit gathering / 是否为命轮采集</param>
|
||||
public void SetParams(int idItem, float dwUseTime, int idTarget, bool bWorkForMonsterSpirit)
|
||||
{
|
||||
m_idItem = idItem;
|
||||
m_idTarget = idTarget;
|
||||
m_bWorkForMonsterSpirit = bWorkForMonsterSpirit;
|
||||
|
||||
m_UseTimeCnt.SetPeriod(dwUseTime);
|
||||
m_UseTimeCnt.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tick routine / 每帧更新
|
||||
/// </summary>
|
||||
public override bool Tick(float dwDeltaTime)
|
||||
{
|
||||
base.Tick(dwDeltaTime);
|
||||
|
||||
// Update use time counter / 更新使用时间计数器
|
||||
if (m_UseTimeCnt.IncCounter(dwDeltaTime))
|
||||
{
|
||||
m_UseTimeCnt.Reset(true);
|
||||
m_bFinished = true;
|
||||
}
|
||||
|
||||
// Turn face to target if needed / 如果有目标则面向目标
|
||||
if (m_idTarget != 0 && m_pHost != null)
|
||||
{
|
||||
m_pHost.TurnFaceTo(m_idTarget);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get item template ID / 获取物品模板ID
|
||||
/// </summary>
|
||||
public int GetItem()
|
||||
{
|
||||
return m_idItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get target object ID / 获取目标对象ID
|
||||
/// </summary>
|
||||
public int GetTarget()
|
||||
{
|
||||
return m_idTarget;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this work for monster spirit gathering? / 是否为命轮采集工作
|
||||
/// </summary>
|
||||
public bool IsWorkForMonsterSpirit()
|
||||
{
|
||||
return m_bWorkForMonsterSpirit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get use time counter / 获取使用时间计数器
|
||||
/// </summary>
|
||||
public CECCounter GetUseTimeCnt()
|
||||
{
|
||||
return m_UseTimeCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 965c8f617755486429a9f1bb88521065
|
||||
@@ -134,6 +134,71 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
UpdateCooldownOverlays();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update all cooldown overlays
|
||||
/// 更新所有冷却遮罩
|
||||
/// </summary>
|
||||
public void UpdateCooldownOverlays()
|
||||
{
|
||||
// Update inventory pack cooldowns
|
||||
// 更新背包冷却
|
||||
UpdatePackageCooldowns(inventoryPackButtons, PKG_INVENTORY);
|
||||
|
||||
// Equipment pack doesn't typically have cooldowns but update anyway
|
||||
// 装备栏通常没有冷却但也更新
|
||||
UpdatePackageCooldowns(equipmentPackButtons, PKG_EQUIPMENT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update cooldown overlays for a specific package
|
||||
/// 更新特定包裹的冷却遮罩
|
||||
/// </summary>
|
||||
private void UpdatePackageCooldowns(List<Button> buttons, byte package)
|
||||
{
|
||||
if (buttons == null)
|
||||
{
|
||||
Debug.LogWarning($"[UpdatePackageCooldowns] Buttons list is null for package {package}");
|
||||
return;
|
||||
}
|
||||
|
||||
var items = model.GetInventoryData(package);
|
||||
if (items == null)
|
||||
{
|
||||
Debug.LogWarning($"[UpdatePackageCooldowns] Items dictionary is null for package {package}");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[UpdatePackageCooldowns] Updating package {package} with {buttons.Count} buttons and {items.Count} items");
|
||||
|
||||
for (int slot = 0; slot < buttons.Count; slot++)
|
||||
{
|
||||
var button = buttons[slot];
|
||||
if (button == null)
|
||||
continue;
|
||||
|
||||
// Get item at this slot
|
||||
// 获取此槽位的物品
|
||||
EC_IvtrItem itemData = null;
|
||||
bool hasItem = items.TryGetValue(slot, out itemData) && itemData != null;
|
||||
|
||||
if (hasItem)
|
||||
{
|
||||
Debug.Log($"[UpdatePackageCooldowns] Package {package}, Slot {slot}: Found item {itemData.m_tid}");
|
||||
// Use InventoryView's method to update cooldown
|
||||
// 使用 InventoryView 的方法更新冷却
|
||||
view.UpdateCooldownOverlay(button, itemData);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide overlay for empty slots
|
||||
// 空槽位隐藏遮罩
|
||||
view.HideCooldownOverlay(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshAll()
|
||||
@@ -335,14 +400,23 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
if (currentSelectedItem == null)
|
||||
{
|
||||
Debug.LogWarning("[InventoryUI] No item selected for equip/unequip operation");
|
||||
Debug.LogWarning("[InventoryUI] No item selected for operation");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSelectedPackage == PKG_INVENTORY)
|
||||
{
|
||||
// Equipping from inventory
|
||||
EquipItem();
|
||||
// Check if item is equipment
|
||||
if (currentSelectedItem.IsEquipment())
|
||||
{
|
||||
// Equipping from inventory
|
||||
EquipItem();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use item from inventory
|
||||
UseItem();
|
||||
}
|
||||
}
|
||||
else if (currentSelectedPackage == PKG_EQUIPMENT)
|
||||
{
|
||||
@@ -351,7 +425,56 @@ namespace BrewMonster.Scripts.Managers
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[InventoryUI] Equip/Unequip not supported for package {currentSelectedPackage}");
|
||||
Debug.LogWarning($"[InventoryUI] Operation not supported for package {currentSelectedPackage}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use the currently selected item from inventory
|
||||
/// </summary>
|
||||
private void UseItem()
|
||||
{
|
||||
if (currentSelectedItem == null)
|
||||
{
|
||||
Debug.LogWarning("[InventoryUI] No item selected for use");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSelectedPackage != PKG_INVENTORY)
|
||||
{
|
||||
Debug.LogWarning("[InventoryUI] Can only use items from inventory package");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[UseItem] Attempting to use item {currentSelectedItem.m_tid} from slot {currentSelectedSlot}");
|
||||
|
||||
// Get host player to call UseItemInPack
|
||||
var host = CECGameRun.Instance?.GetHostPlayer();
|
||||
if (host == null)
|
||||
{
|
||||
Debug.LogError("[InventoryUI] Cannot get host player");
|
||||
return;
|
||||
}
|
||||
|
||||
// Call UseItemInPack with current package and slot
|
||||
bool success = host.UseItemInPack(currentSelectedPackage, currentSelectedSlot, true);
|
||||
|
||||
if (success)
|
||||
{
|
||||
Debug.Log($"[UseItem] Successfully used item {currentSelectedItem.m_tid} from slot {currentSelectedSlot}");
|
||||
|
||||
// Close detail panel after using item
|
||||
ShowDetailPanel(false);
|
||||
|
||||
// Refresh inventory to reflect changes
|
||||
RefreshAll();
|
||||
|
||||
Debug.Log($"[UseItem] Calling UpdateCooldownOverlays after item use");
|
||||
UpdateCooldownOverlays();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[UseItem] Failed to use item {currentSelectedItem.m_tid} from slot {currentSelectedSlot}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,6 +721,8 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
private static readonly Dictionary<Image, Sprite> _defaultSprites = new Dictionary<Image, Sprite>();
|
||||
|
||||
private static readonly Dictionary<Button, Image> _overlayImages = new Dictionary<Button, Image>();
|
||||
|
||||
public void RenderPackage(List<Button> buttons, Dictionary<int, EC_IvtrItem> items, byte package, System.Action<byte, int> onClick, System.Func<int, EC_IvtrItem, string> getDisplayText)
|
||||
{
|
||||
if (buttons == null)
|
||||
@@ -615,34 +740,41 @@ namespace BrewMonster.Scripts.Managers
|
||||
|
||||
EC_IvtrItem itemData = null;
|
||||
bool hasItem = items != null && items.TryGetValue(slot, out itemData);
|
||||
|
||||
button.onClick.RemoveAllListeners();
|
||||
int capturedSlot = slot;
|
||||
button.onClick.AddListener(() => onClick(package, capturedSlot));
|
||||
// Optional visual tweaks based on state/count
|
||||
|
||||
// Update icon and count
|
||||
var image = button.GetComponent<Image>();
|
||||
if (image != null)
|
||||
{
|
||||
// Store the default sprite if we haven't seen this image before
|
||||
// Store default sprite
|
||||
if (!_defaultSprites.ContainsKey(image))
|
||||
{
|
||||
_defaultSprites[image] = image.sprite;
|
||||
}
|
||||
|
||||
// Set icon sprite based on item TemplateId
|
||||
// Set icon sprite based on item
|
||||
if (hasItem && itemData != null && itemData.m_iCount > 0)
|
||||
{
|
||||
var sprite = EC_IvtrItemUtils.Instance.ResolveItemIconSprite(itemData.m_tid);
|
||||
image.sprite = sprite;
|
||||
image.enabled = true;
|
||||
|
||||
UpdateItemCountText(button, itemData.m_iCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore the default sprite instead of setting to null
|
||||
// Restore default sprite
|
||||
image.sprite = _defaultSprites[image];
|
||||
image.enabled = true;
|
||||
|
||||
UpdateItemCountText(button, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup drag-drop events
|
||||
var eventTrigger = button.GetComponent<EventTrigger>();
|
||||
if (eventTrigger == null)
|
||||
eventTrigger = button.gameObject.AddComponent<EventTrigger>();
|
||||
@@ -662,6 +794,175 @@ namespace BrewMonster.Scripts.Managers
|
||||
AddEvent(EventTriggerType.Drop, (data) => ((EC_InventoryUI)button.GetComponentInParent<EC_InventoryUI>()).OnDrop((PointerEventData)data));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update cooldown overlay for item
|
||||
/// 更新物品冷却遮罩
|
||||
/// </summary>
|
||||
public void UpdateCooldownOverlay(Button button, EC_IvtrItem itemData)
|
||||
{
|
||||
if (button == null || itemData == null)
|
||||
{
|
||||
Debug.LogWarning("[UpdateCooldownOverlay] Button or itemData is null");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[UpdateCooldownOverlay] Checking item {itemData.m_tid} in button {button.name}");
|
||||
|
||||
// Find or cache overlay image
|
||||
// 查找或缓存遮罩图片
|
||||
Image overlay = null;
|
||||
if (_overlayImages.TryGetValue(button, out overlay))
|
||||
{
|
||||
if (overlay == null)
|
||||
{
|
||||
// Cached but destroyed, remove and search again
|
||||
// 已缓存但被销毁,移除并重新查找
|
||||
Debug.LogWarning($"[UpdateCooldownOverlay] Cached overlay was destroyed for button {button.name}");
|
||||
_overlayImages.Remove(button);
|
||||
}
|
||||
}
|
||||
|
||||
if (overlay == null)
|
||||
{
|
||||
// Find image_overlay in button's children
|
||||
// 在按钮子物体中查找 image_overlay
|
||||
var overlayTransform = button.transform.Find("image_overlay");
|
||||
if (overlayTransform != null)
|
||||
{
|
||||
overlay = overlayTransform.GetComponent<Image>();
|
||||
if (overlay != null)
|
||||
{
|
||||
Debug.Log($"[UpdateCooldownOverlay] Found image_overlay for button {button.name}");
|
||||
_overlayImages[button] = overlay;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[UpdateCooldownOverlay] Found transform but no Image component on image_overlay for button {button.name}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[UpdateCooldownOverlay] Cannot find image_overlay child in button {button.name}");
|
||||
}
|
||||
}
|
||||
|
||||
if (overlay == null)
|
||||
{
|
||||
Debug.LogWarning($"[UpdateCooldownOverlay] Overlay is null after search for button {button.name}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get cooldown info from item
|
||||
// 从物品获取冷却信息
|
||||
int? maxCooldown = null;
|
||||
int currentCooldown = itemData.GetCoolTime(out maxCooldown);
|
||||
|
||||
Debug.Log($"[UpdateCooldownOverlay] Item {itemData.m_tid}: currentCooldown={currentCooldown}, maxCooldown={maxCooldown}");
|
||||
|
||||
if (currentCooldown > 0 && maxCooldown > 0)
|
||||
{
|
||||
// Show overlay and set fill amount
|
||||
// 显示遮罩并设置填充量
|
||||
overlay.gameObject.SetActive(true);
|
||||
|
||||
// Calculate fill amount (1 = full cooldown, 0 = ready)
|
||||
// 计算填充量(1=完全冷却,0=就绪)
|
||||
float fillAmount = (float)currentCooldown / maxCooldown.Value;
|
||||
overlay.fillAmount = fillAmount;
|
||||
|
||||
// Set semi-transparent black color like original code
|
||||
// 设置半透明黑色,与原始代码相同
|
||||
overlay.color = new Color(0, 0, 0, 0.5f); // A3DCOLORRGBA(0, 0, 0, 128)
|
||||
|
||||
Debug.Log($"[UpdateCooldownOverlay] Showing overlay for item {itemData.m_tid} with fillAmount={fillAmount}, overlay active={overlay.gameObject.activeSelf}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide overlay when not in cooldown
|
||||
// 不在冷却时隐藏遮罩
|
||||
overlay.gameObject.SetActive(false);
|
||||
Debug.Log($"[UpdateCooldownOverlay] Hiding overlay for item {itemData.m_tid} (no cooldown)");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hide cooldown overlay
|
||||
/// 隐藏冷却遮罩
|
||||
/// </summary>
|
||||
public void HideCooldownOverlay(Button button)
|
||||
{
|
||||
if (button == null)
|
||||
return;
|
||||
|
||||
Image overlay = null;
|
||||
if (_overlayImages.TryGetValue(button, out overlay) && overlay != null)
|
||||
{
|
||||
overlay.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update or create text component to show item count on the button
|
||||
/// </summary>
|
||||
/// <param name="button">The inventory button</param>
|
||||
/// <param name="count">Item count (0 to hide)</param>
|
||||
private void UpdateItemCountText(Button button, int count)
|
||||
{
|
||||
if (button == null) return;
|
||||
|
||||
TMPro.TextMeshProUGUI tmpText = null;
|
||||
Text legacyText = null;
|
||||
|
||||
// Find text component
|
||||
var textTransform = button.transform.Find("text_quality");
|
||||
|
||||
if (textTransform != null)
|
||||
{
|
||||
tmpText = textTransform.GetComponent<TMPro.TextMeshProUGUI>();
|
||||
legacyText = textTransform.GetComponent<Text>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: find any text in children
|
||||
tmpText = button.GetComponentInChildren<TMPro.TextMeshProUGUI>();
|
||||
if (tmpText == null)
|
||||
{
|
||||
legacyText = button.GetComponentInChildren<Text>();
|
||||
}
|
||||
}
|
||||
|
||||
// Update text
|
||||
if (count > 1)
|
||||
{
|
||||
string countText = count.ToString();
|
||||
|
||||
if (tmpText != null)
|
||||
{
|
||||
tmpText.text = countText;
|
||||
tmpText.gameObject.SetActive(true);
|
||||
}
|
||||
else if (legacyText != null)
|
||||
{
|
||||
legacyText.text = countText;
|
||||
legacyText.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide when count <= 1
|
||||
if (tmpText != null)
|
||||
{
|
||||
tmpText.text = "";
|
||||
tmpText.gameObject.SetActive(false);
|
||||
}
|
||||
else if (legacyText != null)
|
||||
{
|
||||
legacyText.text = "";
|
||||
legacyText.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === Detail Panel Helpers ===
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
namespace PerfectWorld.Scripts.Managers
|
||||
{
|
||||
public class EC_IvtrDoubleExp : EC_IvtrItem
|
||||
{
|
||||
private DOUBLE_EXP_ESSENCE m_pDBEssence;
|
||||
|
||||
/// <summary>
|
||||
/// Not create logic yet (add summary later)
|
||||
/// </summary>
|
||||
@@ -15,6 +18,11 @@ namespace PerfectWorld.Scripts.Managers
|
||||
public EC_IvtrDoubleExp(EC_IvtrDoubleExp other) : base(other)
|
||||
{
|
||||
}
|
||||
|
||||
public DOUBLE_EXP_ESSENCE GetDBEssence()
|
||||
{
|
||||
return m_pDBEssence;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
namespace PerfectWorld.Scripts.Managers
|
||||
{
|
||||
public class EC_IvtrTargetItem : EC_IvtrItem
|
||||
{
|
||||
private CECSkill m_pTargetSkill;
|
||||
|
||||
private TARGET_ITEM_ESSENCE m_pDBEssence;
|
||||
private bool m_bEssenceLoaded = false; // Flag to track if essence is loaded
|
||||
|
||||
/// <summary>
|
||||
/// Not create logic yet (add summary later)
|
||||
/// </summary>
|
||||
@@ -15,6 +21,33 @@ namespace PerfectWorld.Scripts.Managers
|
||||
public EC_IvtrTargetItem(EC_IvtrTargetItem other) : base(other)
|
||||
{
|
||||
}
|
||||
|
||||
public TARGET_ITEM_ESSENCE GetDBEssence()
|
||||
{
|
||||
if (!m_bEmbeddable)
|
||||
{
|
||||
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
|
||||
var pDataBuf = ElementDataManProvider.GetElementDataMan()
|
||||
.get_data_ptr((uint)m_tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
|
||||
|
||||
if (DataType == DATA_TYPE.DT_TARGET_ITEM_ESSENCE && pDataBuf != null)
|
||||
{
|
||||
m_pDBEssence = (TARGET_ITEM_ESSENCE)pDataBuf;
|
||||
m_bEssenceLoaded = true;
|
||||
}
|
||||
}
|
||||
return m_pDBEssence;
|
||||
}
|
||||
|
||||
public bool IsEssenceLoaded()
|
||||
{
|
||||
return m_bEssenceLoaded;
|
||||
}
|
||||
|
||||
public CECSkill GetTargetSkill()
|
||||
{
|
||||
return m_pTargetSkill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
namespace PerfectWorld.Scripts.Managers
|
||||
{
|
||||
@@ -15,6 +16,13 @@ namespace PerfectWorld.Scripts.Managers
|
||||
public EC_IvtrTossMat(EC_IvtrTossMat other) : base(other)
|
||||
{
|
||||
}
|
||||
|
||||
protected TOSSMATTER_ESSENCE m_pDBEssence;
|
||||
|
||||
public TOSSMATTER_ESSENCE GetDBEssence()
|
||||
{
|
||||
return m_pDBEssence;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace BrewMonster
|
||||
protected ROLEBASICPROP m_BasicProps;
|
||||
public int m_iMoveEnv = Move_environment.MOVEENV_GROUND; // Move environment
|
||||
public bool m_bWalkRun = true;
|
||||
public bool m_bInSanctuary = true;
|
||||
public A3DAABB m_aabbServer = new A3DAABB(); // Óë·þÎñÆ÷±£³ÖÒ»ÖµÄaabb£¬ ²»ÊÜËõ·ÅÓ°Ïì
|
||||
public A3DAABB m_aabb = new A3DAABB(); // Player's aabb£¬ÓÃÓÚÏÔʾµÄaabb£¬ÊÜËõ·ÅÓ°Ïì
|
||||
public int m_iProfession; // Profession
|
||||
@@ -261,6 +262,11 @@ namespace BrewMonster
|
||||
return (m_dwStates & PlayerNPCState.GP_STATE_INVISIBLE) != 0;
|
||||
}
|
||||
|
||||
public bool IsInSanctuary()
|
||||
{
|
||||
return m_bInSanctuary;
|
||||
}
|
||||
|
||||
public bool IsValidAction(int iIndex)
|
||||
{
|
||||
return (iIndex >= 0 && iIndex < (int)PLAYER_ACTION_TYPE.ACT_MAX) ? true : false;
|
||||
|
||||
@@ -2,6 +2,7 @@ using BrewMonster;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.S2CCommand;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -825,6 +826,25 @@ namespace CSNetwork.C2SCommand
|
||||
return SerializeCommand(CommandID.USE_ITEM, pCmd);
|
||||
}
|
||||
|
||||
public static Octets CreateUseItemWithTarget(byte byPackage, byte bySlot, int tid, byte byPVPMask)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
{
|
||||
// Write command header
|
||||
writer.Write((ushort)CommandID.USE_ITEM_T);
|
||||
|
||||
// Write cmd_use_item structure
|
||||
writer.Write(byPackage); // where
|
||||
writer.Write((byte)1); // byCount (always 1 for target items)
|
||||
writer.Write((ushort)bySlot); // index
|
||||
writer.Write(tid); // item_id
|
||||
writer.Write(byPVPMask); // pvp_mask
|
||||
|
||||
return new Octets(stream.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static Octets CreateGivePresentCmd(int roleid, int mail_id, int goods_id, int goods_index, int goods_slot)
|
||||
{
|
||||
cmd_player_give_present pCmd = new cmd_player_give_present();
|
||||
|
||||
@@ -872,6 +872,15 @@ namespace CSNetwork.GPDataType
|
||||
public int line;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_host_use_item
|
||||
{
|
||||
public byte byPackage;
|
||||
public byte bySlot;
|
||||
public int item_id;
|
||||
public ushort use_count;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_matter_pickup
|
||||
{
|
||||
|
||||
@@ -1040,6 +1040,9 @@ namespace CSNetwork
|
||||
case CommandID.EMBED_ITEM:
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_EMBEDITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
|
||||
break;
|
||||
case CommandID.HOST_USE_ITEM:
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_USEITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
|
||||
break;
|
||||
default:
|
||||
#if UNITY_EDITOR
|
||||
if (isDebug)
|
||||
@@ -1764,5 +1767,11 @@ namespace CSNetwork
|
||||
gamedatasend.Data = C2SCommandFactory.CreateGetItemInfoCmd(byPackage, bySlot);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
public void c2s_SendCmdUseItemWithTarget(byte byPackage, byte bySlot, int tid, byte byPVPMask)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
gamedatasend.Data = C2SCommandFactory.CreateUseItemWithTarget(byPackage, bySlot, tid, byPVPMask);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,6 +235,10 @@ namespace BrewMonster.Network
|
||||
{
|
||||
Instance._gameSession.RequestReviveByPlayer();
|
||||
}
|
||||
public static void c2s_SendCmdUseItemWithTarget(byte byPackage, byte bySlot, int tid, byte byPVPMask)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdUseItemWithTarget(byPackage, bySlot, tid, byPVPMask);
|
||||
}
|
||||
|
||||
public void RequestMallShopping(uint count, int good_id, int good_index, int good_pos)
|
||||
{
|
||||
|
||||
@@ -787,6 +787,17 @@ namespace BrewMonster
|
||||
return new CECShortcut();
|
||||
}
|
||||
public virtual bool Execute() { return true; }
|
||||
|
||||
public virtual int GetCoolTime(ref int piMax)
|
||||
{
|
||||
piMax = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual string GetIconFile()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public class CECSCCommand : CECShortcut
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace BrewMonster.UI
|
||||
protected AUIManager m_pAUIManager = null;
|
||||
string m_szName;
|
||||
|
||||
private bool m_bUpdateRenderTarget = false;
|
||||
|
||||
public virtual void Show(bool value)
|
||||
{
|
||||
gameObject.SetActive(value);
|
||||
@@ -129,5 +131,20 @@ namespace BrewMonster.UI
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void UpdateRenderTarget()
|
||||
{
|
||||
m_bUpdateRenderTarget = true;
|
||||
}
|
||||
|
||||
public bool NeedRenderTargetUpdate()
|
||||
{
|
||||
return m_bUpdateRenderTarget;
|
||||
}
|
||||
|
||||
public void ResetRenderTargetFlag()
|
||||
{
|
||||
m_bUpdateRenderTarget = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using BrewMonster.UI;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -20,6 +21,12 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay
|
||||
[SerializeField] int cooldownTime;
|
||||
[SerializeField] AUIClockIcon m_ClockCounter;
|
||||
|
||||
private Color m_color = Color.white;
|
||||
private bool m_bUpdateRenderTarget;
|
||||
private bool m_bForceDynamicRender;
|
||||
|
||||
private AUIDialog m_pParent;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (skillbutton == null)
|
||||
@@ -27,6 +34,7 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay
|
||||
Debug.LogError("Skill Button is not assigned in AUIImagePicture");
|
||||
}
|
||||
skillbutton.onClick.AddListener(Execute);
|
||||
m_pParent = GetComponentInParent<AUIDialog>();
|
||||
}
|
||||
public void SetDataPtr(CECShortcut pvData, string strName)
|
||||
{
|
||||
@@ -69,6 +77,24 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay
|
||||
skillbutton.interactable = true;
|
||||
}
|
||||
public AUIClockIcon GetClockIcon() => m_ClockCounter;
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
if (m_color != color)
|
||||
UpdateRenderTargert();
|
||||
m_color = color;
|
||||
}
|
||||
|
||||
private void UpdateRenderTargert()
|
||||
{
|
||||
if (!NeedDynamicRender())
|
||||
m_pParent.UpdateRenderTarget();
|
||||
}
|
||||
|
||||
private bool NeedDynamicRender()
|
||||
{
|
||||
return m_bUpdateRenderTarget || m_bForceDynamicRender;
|
||||
}
|
||||
}
|
||||
public struct OpenSkillUIEvent
|
||||
{
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using BrewMonster.UI;
|
||||
using CSNetwork.GPDataType;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
@@ -194,6 +196,128 @@ namespace BrewMonster
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
}
|
||||
}*/
|
||||
else if(pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_ITEM)
|
||||
{
|
||||
iIconFile = (int)EC_GAMEUI_ICONS.ICONS_INVENTORY;
|
||||
pCell.SetColor(new Color(1f, 1f, 1f));
|
||||
CECSCItem pSCItem = (CECSCItem)pSC;
|
||||
EC_Inventory pIvtr = pHost.GetPack(pSCItem.GetInventory());
|
||||
EC_IvtrItem pItem = pIvtr?.GetItem(pSCItem.GetIvtrSlot());
|
||||
|
||||
if (pItem != null)
|
||||
{
|
||||
int? maxNullable = null;
|
||||
int coolTime = pItem.GetCoolTime(out maxNullable);
|
||||
nMax = maxNullable ?? 0;
|
||||
|
||||
if (coolTime > 0)
|
||||
{
|
||||
pClock.SetProgressRange(0, nMax);
|
||||
pClock.SetProgressPos(nMax - coolTime);
|
||||
pClock.SetColor(new Color32(0, 0, 0, 128));
|
||||
}
|
||||
}
|
||||
|
||||
//if (pSCItem.GetInventory == InventoryConst.IVTRTYPE_EQUIPPACK)
|
||||
//{
|
||||
// pCell.SetColor(new Color(128, 128, 255, 128));
|
||||
//}
|
||||
|
||||
if (pItem != null)
|
||||
{
|
||||
slotIndex++;
|
||||
string itemIcon = pItem.GetIconFile();
|
||||
GetGameUIMan().SetCover(pCell, itemIcon, EC_GAMEUI_ICONS.ICONS_INVENTORY);
|
||||
}
|
||||
}
|
||||
//else if(pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_PET)
|
||||
//{
|
||||
// // Pet shortcut handling
|
||||
// CECSCPet pSCPet = (CECSCPet)pSC;
|
||||
// EC_PetCorral pPetCorral = pHost.GetPetCorral();
|
||||
// CECPetData pPet = pPetCorral?.GetPetData(pSCPet.GetPetIndex());
|
||||
|
||||
// iIconFile = (int)EC_GAMEUI_ICONS.ICONS_INVENTORY;
|
||||
// //pCell.SetColor(new Color(1f, 1f, 1f)); // RGB(255, 255, 255)
|
||||
|
||||
// if (pPet != null)
|
||||
// {
|
||||
// // Dead combat pet - grayscale
|
||||
// if ((pPet.GetClass() == (int)PetClass.GP_PET_CLASS_COMBAT ||
|
||||
// pPet.GetClass() == (int)PetClass.GP_PET_CLASS_EVOLUTION) &&
|
||||
// pPet.GetHPFactor() == 0.0f)
|
||||
// {
|
||||
// //pCell.SetColor(new Color32(128, 128, 128, 255));
|
||||
// }
|
||||
// // Current active pet - yellow highlight
|
||||
// else if (pSCPet.IsActivePet())
|
||||
// {
|
||||
// //pCell.SetColor(new Color32(255, 255, 0, 255));
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Set pet icon
|
||||
// if (pPet != null)
|
||||
// {
|
||||
// slotIndex++;
|
||||
// string petIcon = pSCPet.GetIconFile();
|
||||
// GetGameUIMan().SetCover(pCell, petIcon, EC_GAMEUI_ICONS.ICONS_INVENTORY);
|
||||
// }
|
||||
//}
|
||||
else if(pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_AUTOFASHION)
|
||||
{
|
||||
iIconFile = (int)EC_GAMEUI_ICONS.ICONS_SUITE;
|
||||
|
||||
int fashionCoolTimeMax = 0;
|
||||
int fashionCoolTime = pHost.GetCoolTime((int)CoolTimeIndex.GP_CT_EQUIP_FASHION_ITEM, ref fashionCoolTimeMax);
|
||||
pCell.SetColor(new Color(1f, 1f, 1f));
|
||||
|
||||
if (fashionCoolTimeMax > 0)
|
||||
{
|
||||
pClock.SetProgressRange(0, fashionCoolTimeMax);
|
||||
pClock.SetProgressPos(fashionCoolTimeMax - fashionCoolTime);
|
||||
pClock.SetColor(new Color32(0, 0, 0, 175));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iIconFile = (int)EC_GAMEUI_ICONS.ICONS_ACTION;
|
||||
if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_COMMAND)
|
||||
{
|
||||
CECSCCommand pCommandSC = (CECSCCommand)pSC;
|
||||
if (pHost.IsInvisible())
|
||||
{
|
||||
if (pCommandSC.GetCommandID() == (int)CECSCCommand.CommandID.CMD_STARTTRADE ||
|
||||
pCommandSC.GetCommandID() == (int)CECSCCommand.CommandID.CMD_SELLBOOTH ||
|
||||
pCommandSC.GetCommandID() == (int)CECSCCommand.CommandID.CMD_BINDBUDDY)
|
||||
{
|
||||
pCell.SetColor(new Color(128, 128, 128, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell.SetColor(new Color(1f, 1f, 1f));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell.SetColor(new Color(1f, 1f, 1f));
|
||||
}
|
||||
}
|
||||
nMax = 0;
|
||||
int cmdCoolTime = pSC.GetCoolTime(ref nMax);
|
||||
if (cmdCoolTime > 0)
|
||||
{
|
||||
pClock.SetProgressRange(0, nMax);
|
||||
pClock.SetProgressPos(nMax - cmdCoolTime);
|
||||
pClock.SetColor(new Color32(0, 0, 0, 128));
|
||||
}
|
||||
|
||||
slotIndex++;
|
||||
string cmdIcon = pSC.GetIconFile();
|
||||
GetGameUIMan().SetCover(pCell, cmdIcon, EC_GAMEUI_ICONS.ICONS_ACTION);
|
||||
}
|
||||
|
||||
|
||||
if (pSC != null)
|
||||
{
|
||||
pCell.SetDataPtr(pSC, "ptr_CECShortcut");
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace BrewMonster
|
||||
[SerializeField] private int m_iMax;
|
||||
[SerializeField] private int m_iPos;
|
||||
|
||||
private Color m_dwCol;
|
||||
|
||||
public Image GetClockIcon() => m_ClockIcon;
|
||||
public void SetProgressPos(int progress)
|
||||
{
|
||||
@@ -36,5 +38,9 @@ namespace BrewMonster
|
||||
m_ClockIcon.fillAmount = progress;
|
||||
}
|
||||
|
||||
public void SetColor(Color dwCol)
|
||||
{
|
||||
m_dwCol = dwCol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.VisualScripting;
|
||||
using static BrewMonster.SkillArrayWrapper;
|
||||
using UnityEngine;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using UnityEditorInternal.Profiling.Memory.Experimental;
|
||||
using BrewMonster.Scripts;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
// Item shortcut class - represents a shortcut to an inventory item
|
||||
public class CECSCItem : CECShortcut
|
||||
{
|
||||
private int m_iIvtr;
|
||||
private int m_iSlot;
|
||||
private int m_tidItem;
|
||||
private string m_strIconFile;
|
||||
private bool m_bAutoFind;
|
||||
|
||||
// Constructor
|
||||
public CECSCItem() : base()
|
||||
{
|
||||
m_iSCType = (int)ShortcutType.SCT_ITEM;
|
||||
m_iIvtr = 0;
|
||||
m_iSlot = 0;
|
||||
m_tidItem = 0;
|
||||
m_strIconFile = "";
|
||||
m_bAutoFind = false;
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
public CECSCItem(CECSCItem src) : base()
|
||||
{
|
||||
m_iSCType = (int)ShortcutType.SCT_ITEM;
|
||||
m_iIvtr = src.m_iIvtr;
|
||||
m_iSlot = src.m_iSlot;
|
||||
m_tidItem = src.m_tidItem;
|
||||
m_strIconFile = src.m_strIconFile;
|
||||
m_bAutoFind = src.m_bAutoFind;
|
||||
}
|
||||
|
||||
// Initialize object
|
||||
public bool Init(int iIvtr, int iSlot, EC_IvtrItem pItem)
|
||||
{
|
||||
m_iIvtr = iIvtr;
|
||||
m_iSlot = iSlot;
|
||||
|
||||
if (pItem != null)
|
||||
{
|
||||
m_tidItem = pItem.GetTemplateID();
|
||||
m_strIconFile = pItem.GetIconFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tidItem = 0;
|
||||
m_strIconFile = "";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clone this shortcut
|
||||
public override CECShortcut Clone()
|
||||
{
|
||||
return new CECSCItem(this);
|
||||
}
|
||||
|
||||
// Execute this shortcut - use the item
|
||||
public override bool Execute()
|
||||
{
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
if(pHost == null)
|
||||
return false;
|
||||
|
||||
EC_IvtrItem pItem = GetItem();
|
||||
if (pItem == null)
|
||||
{
|
||||
if (m_bAutoFind)
|
||||
{
|
||||
if(!AutoFindItem())
|
||||
return false;
|
||||
|
||||
pItem = GetItem();
|
||||
if(pItem == null)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return pHost.UseItemInPack(m_iIvtr, m_iSlot);
|
||||
}
|
||||
|
||||
public virtual string GetIconFile()
|
||||
{
|
||||
return m_strIconFile;
|
||||
}
|
||||
|
||||
public virtual string GetDesc()
|
||||
{
|
||||
EC_IvtrItem pItem = GetItem();
|
||||
if (pItem != null)
|
||||
{
|
||||
return pItem.GetDesc();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public virtual int GetCoolTime(ref int piMax)
|
||||
{
|
||||
EC_IvtrItem pItem = GetItem();
|
||||
if (pItem != null)
|
||||
{
|
||||
int? maxNullable = null;
|
||||
int result = pItem.GetCoolTime(out maxNullable);
|
||||
piMax = maxNullable ?? 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
piMax = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int GetInventory()
|
||||
{
|
||||
return m_iIvtr;
|
||||
}
|
||||
|
||||
public int GetIvtrSlot()
|
||||
{
|
||||
return m_iSlot;
|
||||
}
|
||||
|
||||
public int GetItemTID()
|
||||
{
|
||||
return m_tidItem;
|
||||
}
|
||||
|
||||
public void MoveItem(int iIvtr, int iSlot)
|
||||
{
|
||||
m_iIvtr = iIvtr;
|
||||
m_iSlot = iSlot;
|
||||
UpdateItemData();
|
||||
}
|
||||
|
||||
public bool GetAutoFindFlag()
|
||||
{
|
||||
return m_bAutoFind;
|
||||
}
|
||||
|
||||
public void SetAutoFindFlag(bool bAutoFind)
|
||||
{
|
||||
m_bAutoFind = bAutoFind;
|
||||
}
|
||||
|
||||
// Update item associated data after m_iIvtr or m_iSlot changed
|
||||
private void UpdateItemData()
|
||||
{
|
||||
EC_IvtrItem pItem = GetItem();
|
||||
if (pItem != null)
|
||||
{
|
||||
m_tidItem = pItem.GetTemplateID();
|
||||
m_strIconFile = pItem.GetIconFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tidItem = 0;
|
||||
m_strIconFile = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Auto find item in all inventory slots by template ID
|
||||
private bool AutoFindItem()
|
||||
{
|
||||
if(m_tidItem == 0)
|
||||
return false;
|
||||
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
if(pHost == null)
|
||||
return false;
|
||||
|
||||
EC_Inventory pPack = pHost.GetPack(EC_Inventory.Inventory_type.IVTRTYPE_PACK);
|
||||
if (pPack != null)
|
||||
{
|
||||
int iSlot = pPack.FindItem(m_tidItem);
|
||||
if (iSlot >= 0)
|
||||
{
|
||||
m_iIvtr = EC_Inventory.Inventory_type.IVTRTYPE_PACK;
|
||||
m_iSlot = iSlot;
|
||||
UpdateItemData();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
EC_Inventory pEquipPack = pHost.GetPack(EC_Inventory.Inventory_type.IVTRTYPE_EQUIPPACK);
|
||||
if (pEquipPack != null)
|
||||
{
|
||||
int iSlot = pPack.FindItem(m_tidItem);
|
||||
if (iSlot >= 0)
|
||||
{
|
||||
m_iIvtr = InventoryConst.IVTRTYPE_EQUIPPACK;
|
||||
m_iSlot = iSlot;
|
||||
UpdateItemData();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
EC_Inventory pTaskPack = pHost.GetPack(EC_Inventory.Inventory_type.IVTRTYPE_TASKPACK);
|
||||
if (pTaskPack != null)
|
||||
{
|
||||
int iSlot = pPack.FindItem(m_tidItem);
|
||||
if (iSlot >= 0)
|
||||
{
|
||||
m_iIvtr = InventoryConst.IVTRTYPE_TASKPACK;
|
||||
m_iSlot = iSlot;
|
||||
UpdateItemData();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private EC_IvtrItem GetItem()
|
||||
{
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
if(pHost == null)
|
||||
return null;
|
||||
|
||||
EC_Inventory pIvtr = pHost.GetPack(m_iIvtr);
|
||||
if (pIvtr == null)
|
||||
return null;
|
||||
|
||||
return pIvtr.GetItem(m_iSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05cde8ef04e79fd449fdb73d3f3fdc0f
|
||||
@@ -0,0 +1,197 @@
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.Players;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using ModelRenderer.Scripts.Common;
|
||||
using ModelRenderer.Scripts.GameData;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
/// <summary>
|
||||
/// Pet shortcut for quick summoning/recalling pets
|
||||
/// </summary>
|
||||
public class CECSCPet : CECShortcut
|
||||
{
|
||||
/*#region Fields
|
||||
|
||||
private int m_iPetIndex = -1; // Pet index in pet corral
|
||||
private PET_ESSENCE m_pPetEssence; // Pet essence data
|
||||
private bool m_bHasEssence = false; // Whether the pet essence has been loaded
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public CECSCPet()
|
||||
{
|
||||
m_iSCType = (int)ShortcutType.SCT_PET;
|
||||
m_iPetIndex = -1;
|
||||
m_bHasEssence = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="src">Source pet shortcut to copy from</param>
|
||||
public CECSCPet(CECSCPet src)
|
||||
{
|
||||
m_iSCType = src.m_iSCType;
|
||||
m_iPetIndex = src.m_iPetIndex;
|
||||
m_pPetEssence = src.m_pPetEssence;
|
||||
m_bHasEssence = src.m_bHasEssence;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the pet shortcut with a pet index
|
||||
/// </summary>
|
||||
/// <param name="iPetIndex">Index of the pet in the pet corral</param>
|
||||
/// <returns>True if initialization succeeded</returns>
|
||||
public bool Init(int iPetIndex)
|
||||
{
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
if (pHost == null)
|
||||
return false;
|
||||
|
||||
EC_PetCorral pPetCorral = pHost.GetPetCorral();
|
||||
if (pPetCorral == null)
|
||||
return false;
|
||||
|
||||
//CECPetData pPet = pPetCorral.GetPetData(iPetIndex);
|
||||
if (pPet == null)
|
||||
return false;
|
||||
|
||||
elementdataman pDB = ElementDataManProvider.GetElementDataMan();
|
||||
if (pDB == null)
|
||||
return false;
|
||||
|
||||
DATA_TYPE dataType = DATA_TYPE.DT_INVALID;
|
||||
object essenceObj = pDB.get_data_ptr((uint)pPet.GetTemplateID(), ID_SPACE.ID_SPACE_ESSENCE, ref dataType);
|
||||
|
||||
if (essenceObj == null || !(essenceObj is PET_ESSENCE))
|
||||
return false;
|
||||
|
||||
m_pPetEssence = (PET_ESSENCE)essenceObj;
|
||||
m_bHasEssence = true;
|
||||
m_iPetIndex = iPetIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CECShortcut Overrides
|
||||
|
||||
/// <summary>
|
||||
/// Clone this pet shortcut
|
||||
/// </summary>
|
||||
/// <returns>A new instance with the same data</returns>
|
||||
public override CECShortcut Clone()
|
||||
{
|
||||
return new CECSCPet(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the pet shortcut - summon or recall the pet
|
||||
/// </summary>
|
||||
/// <returns>True if execution succeeded</returns>
|
||||
public override bool Execute()
|
||||
{
|
||||
if (m_iPetIndex < 0)
|
||||
return false;
|
||||
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
if (pHost == null)
|
||||
return false;
|
||||
|
||||
EC_PetCorral pPetCorral = pHost.GetPetCorral();
|
||||
if (pPetCorral == null)
|
||||
return false;
|
||||
|
||||
//if (pPetCorral.GetActivePetIndex() == m_iPetIndex)
|
||||
//{
|
||||
// // If this pet is the active one, recall it
|
||||
// pHost.RecallPet();
|
||||
//}
|
||||
else
|
||||
{
|
||||
// Check action switcher for fly-to-ride transition
|
||||
CECActionSwitcherBase pSwitcher = pHost.GetActionSwitcher();
|
||||
//if (pSwitcher != null && pSwitcher.OnFlyToRideAction(m_iPetIndex))
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
|
||||
// Summon this pet
|
||||
//pHost.SummonPet(m_iPetIndex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the icon file path for this pet
|
||||
/// </summary>
|
||||
/// <returns>Icon file path</returns>
|
||||
//public override string GetIconFile()
|
||||
//{
|
||||
// return m_pPetEssence?.file_icon ?? string.Empty;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Get the description text for this pet
|
||||
/// </summary>
|
||||
/// <returns>Pet description</returns>
|
||||
//public override string GetDesc()
|
||||
//{
|
||||
// // TODO: Implement pet description retrieval
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Check if this pet is currently active
|
||||
/// </summary>
|
||||
/// <returns>True if this pet is the active pet</returns>
|
||||
//public bool IsActivePet()
|
||||
//{
|
||||
// EC_PetCorral pPetCorral = EC_Game.GetGameRun()?.GetHostPlayer()?.GetPetCorral();
|
||||
// if (pPetCorral == null)
|
||||
// return false;
|
||||
|
||||
// return pPetCorral.GetActivePetIndex() == m_iPetIndex;
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Get the pet index in pet corral
|
||||
/// </summary>
|
||||
/// <returns>Pet index</returns>
|
||||
public int GetPetIndex()
|
||||
{
|
||||
return m_iPetIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the pet essence data
|
||||
/// </summary>
|
||||
/// <returns>Pet essence</returns>
|
||||
public PET_ESSENCE GetPetEssence()
|
||||
{
|
||||
return m_pPetEssence;
|
||||
}
|
||||
|
||||
#endregion*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c1e98ce7d055204587eff3f6438ddc3
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,173 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b404da7f8f4b96f459d1c8caa65f7cf8
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 7482667652216324306
|
||||
second: Square
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 256
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: 0
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: iOS
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: Square
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 256
|
||||
height: 256
|
||||
alignment: 0
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: 0
|
||||
bones: []
|
||||
spriteID: 2d009a6b596c7d760800000000000000
|
||||
internalID: 7482667652216324306
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape:
|
||||
- - {x: -128, y: 128}
|
||||
- {x: -128, y: -128}
|
||||
- {x: 128, y: -128}
|
||||
- {x: 128, y: 128}
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
Square: 7482667652216324306
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+9620
-1948
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using BrewMonster.Scripts.World;
|
||||
using BrewMonster.UI;
|
||||
using CSNetwork;
|
||||
@@ -46,6 +47,8 @@ public partial class CECGameRun
|
||||
|
||||
static RoleInfo l_SelRoleInfo; // Selected character's role info.
|
||||
|
||||
private int m_iDExpEndTime = 0;
|
||||
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void AfterSceneLoad()
|
||||
@@ -525,4 +528,179 @@ public partial class CECGameRun
|
||||
}
|
||||
return szRet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a fixed message to chat system with optional formatting parameters
|
||||
/// 添加固定消息到聊天系统,支持可选的格式化参数
|
||||
/// </summary>
|
||||
/// <param name="iMsg">Fixed message ID / 固定消息ID</param>
|
||||
/// <param name="args">Optional formatting arguments / 可选的格式化参数</param>
|
||||
public void AddFixedMessage(int iMsg, params object[] args)
|
||||
{
|
||||
CECStringTab pStrTab = EC_Game.GetFixedMsgs();
|
||||
if (pStrTab == null)
|
||||
{
|
||||
Debug.LogWarning("[AddFixedMessage] Failed to get fixed message table");
|
||||
return;
|
||||
}
|
||||
|
||||
string szFixMsg = pStrTab.GetWideString(iMsg);
|
||||
if (string.IsNullOrEmpty(szFixMsg))
|
||||
{
|
||||
Debug.LogWarning($"[AddFixedMessage] Fixed message {iMsg} not found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Format the message with provided arguments
|
||||
string szFormattedMsg;
|
||||
try
|
||||
{
|
||||
if (args != null && args.Length > 0)
|
||||
{
|
||||
szFormattedMsg = string.Format(szFixMsg, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
szFormattedMsg = szFixMsg;
|
||||
}
|
||||
}
|
||||
catch (System.FormatException ex)
|
||||
{
|
||||
Debug.LogError($"[AddFixedMessage] Format error for message {iMsg}: {ex.Message}");
|
||||
szFormattedMsg = szFixMsg; // Use unformatted message as fallback
|
||||
}
|
||||
|
||||
// Try to add to in-game UI chat
|
||||
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan();
|
||||
if (pGameUI != null)
|
||||
{
|
||||
//pGameUI.AddChatMessage(szFormattedMsg, (int)GP_CHAT.GP_CHAT_SYSTEM);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to debug output if UI is not available
|
||||
Debug.Log($"[System] {szFormattedMsg}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a fixed message to specific chat channel with optional formatting
|
||||
/// 添加固定消息到指定聊天频道,支持可选的格式化
|
||||
/// </summary>
|
||||
/// <param name="iMsg">Fixed message ID / 固定消息ID</param>
|
||||
/// <param name="cChannel">Chat channel ID / 聊天频道ID</param>
|
||||
/// <param name="args">Optional formatting arguments / 可选的格式化参数</param>
|
||||
public void AddFixedChannelMsg(int iMsg, int cChannel, params object[] args)
|
||||
{
|
||||
CECStringTab pStrTab = EC_Game.GetFixedMsgs();
|
||||
if (pStrTab == null)
|
||||
{
|
||||
Debug.LogWarning("[AddFixedChannelMsg] Failed to get fixed message table");
|
||||
return;
|
||||
}
|
||||
|
||||
string szFixMsg = pStrTab.GetWideString(iMsg);
|
||||
if (string.IsNullOrEmpty(szFixMsg))
|
||||
{
|
||||
Debug.LogWarning($"[AddFixedChannelMsg] Fixed message {iMsg} not found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Format the message with provided arguments
|
||||
string szFormattedMsg;
|
||||
try
|
||||
{
|
||||
if (args != null && args.Length > 0)
|
||||
{
|
||||
szFormattedMsg = string.Format(szFixMsg, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
szFormattedMsg = szFixMsg;
|
||||
}
|
||||
}
|
||||
catch (System.FormatException ex)
|
||||
{
|
||||
Debug.LogError($"[AddFixedChannelMsg] Format error for message {iMsg}: {ex.Message}");
|
||||
szFormattedMsg = szFixMsg; // Use unformatted message as fallback
|
||||
}
|
||||
|
||||
// Try to add to in-game UI chat with specific channel
|
||||
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan();
|
||||
if (pGameUI != null)
|
||||
{
|
||||
//pGameUI.AddChatMessage(szFormattedMsg, cChannel);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to debug output if UI is not available
|
||||
Debug.Log($"[Channel {cChannel}] {szFormattedMsg}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a chat message with full parameters (matching C++ signature)
|
||||
/// 添加聊天消息(完整参数版本,匹配C++签名)
|
||||
/// </summary>
|
||||
/// <param name="pszMsg">Message text / 消息文本</param>
|
||||
/// <param name="cChannel">Chat channel / 聊天频道</param>
|
||||
/// <param name="idPlayer">Player ID (default -1) / 玩家ID</param>
|
||||
/// <param name="szName">Player name (optional) / 玩家名称</param>
|
||||
/// <param name="byFlag">Message flag (default 0) / 消息标志</param>
|
||||
/// <param name="cEmotion">Emotion ID (default 0) / 表情ID</param>
|
||||
/// <param name="pItem">Related item (optional) / 相关物品</param>
|
||||
/// <param name="pszMsgOrigion">Original message (optional) / 原始消息</param>
|
||||
public void AddChatMessage(string pszMsg, int cChannel, int idPlayer = -1,
|
||||
string szName = null, byte byFlag = 0, int cEmotion = 0,
|
||||
EC_IvtrItem pItem = null, string pszMsgOrigion = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pszMsg))
|
||||
return;
|
||||
|
||||
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan();
|
||||
if (pGameUI != null)
|
||||
{
|
||||
// Call UI manager's AddChatMessage with full parameters
|
||||
//pGameUI.AddChatMessage(pszMsg, cChannel, idPlayer, szName, byFlag, cEmotion, pItem, pszMsgOrigion);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to debug output if UI is not available
|
||||
Debug.Log($"[Channel {cChannel}] {pszMsg}");
|
||||
|
||||
// Note: In C++ original, pItem is deleted here if UI is not available
|
||||
// In C#, we don't need explicit deletion due to garbage collection
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get remaining double experience time in seconds
|
||||
/// 获取剩余双倍经验时间(秒)
|
||||
/// </summary>
|
||||
public int GetRemainDblExpTime()
|
||||
{
|
||||
int iRemainTime = m_iDExpEndTime - GetServerAbsTime();
|
||||
if (iRemainTime < 0) iRemainTime = 0;
|
||||
return iRemainTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get server absolute time
|
||||
/// 获取服务器绝对时间
|
||||
/// </summary>
|
||||
public int GetServerAbsTime()
|
||||
{
|
||||
// TODO: Implement server time synchronization
|
||||
// This should return the synchronized server timestamp
|
||||
return (int)(System.DateTime.UtcNow.Subtract(new System.DateTime(1970, 1, 1))).TotalSeconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set double experience end time
|
||||
/// 设置双倍经验结束时间
|
||||
/// </summary>
|
||||
public void SetDExpEndTime(int endTime)
|
||||
{
|
||||
m_iDExpEndTime = endTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace BrewMonster
|
||||
public bool m_bPrepareFight = false; // true, prepare to fight
|
||||
private int m_iJumpCount = 0;
|
||||
private bool m_bJumpInWater = false;
|
||||
private int m_iMoveEnv;
|
||||
|
||||
public A3DVECTOR3 m_vVelocity; // Velocity
|
||||
|
||||
@@ -562,6 +563,8 @@ namespace BrewMonster
|
||||
break;
|
||||
case int value when value == EC_MsgDef.MSG_HST_SELTARGET:
|
||||
OnMsgHstSelTarget(Msg); break;
|
||||
case int value when value == EC_MsgDef.MSG_HST_USEITEM:OnMsgHstUseItem(Msg);
|
||||
break;
|
||||
case int value when value == EC_MsgDef.MSG_HST_ATKRESULT: OnMsgHstAttackResult(Msg); break;
|
||||
case int value when value == EC_MsgDef.MSG_HST_ATTACKED: OnMsgHstAttacked(Msg); break;
|
||||
case int value when value == EC_MsgDef.MSG_HST_HURTRESULT: OnMsgHstHurtResult(Msg); break;
|
||||
@@ -3412,6 +3415,12 @@ namespace BrewMonster
|
||||
return m_iJumpCount > 0;
|
||||
}
|
||||
|
||||
public bool IsFalling()
|
||||
{
|
||||
return m_iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND
|
||||
&& m_GndInfo.bOnGround == false;
|
||||
}
|
||||
|
||||
public bool IsPlayingAction(int iAction)
|
||||
{
|
||||
if (iAction == (int)PLAYER_ACTION_TYPE.ACT_WALK) //&& _playerStateMachine.State is PlayerMoveState
|
||||
@@ -6978,7 +6987,7 @@ namespace BrewMonster
|
||||
}
|
||||
return iItemCnt;
|
||||
}
|
||||
bool CanUseEquipment(EC_IvtrEquip pEquip, ref int piReason)
|
||||
public bool CanUseEquipment(EC_IvtrEquip pEquip, ref int piReason)
|
||||
{
|
||||
int iReason = 0;
|
||||
if(pEquip == null)
|
||||
@@ -7059,5 +7068,533 @@ namespace BrewMonster
|
||||
{
|
||||
return m_pPetCorral;
|
||||
}
|
||||
|
||||
public bool UseItemInPack(int iPack, int iSlot, bool showMsg = true)
|
||||
{
|
||||
if(!CanDo(ActionCanDo.CANDO_USEITEM))
|
||||
return false;
|
||||
|
||||
EC_Inventory pPack = GetPack(iPack);
|
||||
if (pPack == null)
|
||||
return false;
|
||||
|
||||
EC_IvtrItem pItem = pPack.GetItem(iSlot);
|
||||
if (pItem == null || pItem.IsFrozen())
|
||||
return false;
|
||||
|
||||
if(pItem.Use_Persist() && (IsJumping() || IsFalling()))
|
||||
return false;
|
||||
|
||||
CECGameRun pGameRun = EC_Game.GetGameRun();
|
||||
//CECGameSession pSession = g_pGame.GetGameSession();
|
||||
|
||||
if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_TRANSMITSCROLL)
|
||||
{
|
||||
CECGameUIMan pGameUI = pGameRun.GetUIManager().GetInGameUIMan();
|
||||
if (pGameUI != null && !IsFighting())
|
||||
{
|
||||
// TODO: Implement travel map dialog
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_TARGETITEM)
|
||||
{
|
||||
EC_IvtrTargetItem pTargetItem = pItem as EC_IvtrTargetItem;
|
||||
if(pTargetItem == null)
|
||||
return false;
|
||||
|
||||
var essence = pTargetItem.GetDBEssence();
|
||||
|
||||
if(!pTargetItem.IsEssenceLoaded())
|
||||
return false;
|
||||
|
||||
if (IsFighting() && essence.use_in_combat == 0)
|
||||
{
|
||||
if (showMsg)
|
||||
if (showMsg) pGameRun.AddFixedMessage((int)FixedMsg.FIXMSG_CANNOT_USE_IN_BATTLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pTargetItem.GetDBEssence().use_in_sanctuary_only != 0 && !IsInSanctuary())
|
||||
{
|
||||
if (showMsg)
|
||||
pGameRun.AddFixedMessage((int)FixedMsg.FIXMSG_USE_IN_SANCTUARY_ONLY);
|
||||
return false;
|
||||
}
|
||||
|
||||
int iCurrMap = pGameRun.GetWorld().GetInstanceID();
|
||||
if (pTargetItem.GetDBEssence().num_area != 0)
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; i < pTargetItem.GetDBEssence().num_area; i++)
|
||||
{
|
||||
if (pTargetItem.GetDBEssence().area_id[i] == iCurrMap)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
if(showMsg)
|
||||
pGameRun.AddFixedMessage((int)FixedMsg.FIXMSG_CANNOT_USE_IN_CURR_MAP);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!CanDo(ActionCanDo.CANDO_SPELLMAGIC))
|
||||
return false;
|
||||
|
||||
if (InSlidingState())
|
||||
return false;
|
||||
|
||||
if (m_idSelTarget == 0)
|
||||
return false;
|
||||
|
||||
CECSkill pSkill = pTargetItem.GetTargetSkill();
|
||||
if (pSkill == null)
|
||||
return false;
|
||||
|
||||
if (IsSpellingMagic() && m_pCurSkill != null && m_pCurSkill.IsCharging() &&
|
||||
m_pCurSkill.GetSkillID() == pSkill.GetSkillID())
|
||||
{
|
||||
m_pCurSkill.EndCharging();
|
||||
UnityGameSession.c2s_SendCmdContinueAction();
|
||||
return true;
|
||||
}
|
||||
|
||||
int iCon = CheckSkillCastCondition(pSkill);
|
||||
if (iCon != 0)
|
||||
{
|
||||
if (showMsg)
|
||||
ProcessSkillCondition(iCon);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bForceAttack = glb_GetForceAttackFlag(0);
|
||||
if (pSkill.GetType() == (int)CECSkill.SkillType.TYPE_ATTACK ||
|
||||
pSkill.GetType() == (int)CECSkill.SkillType.TYPE_CURSE)
|
||||
{
|
||||
if (m_idSelTarget == m_PlayerInfo.cid)
|
||||
{
|
||||
if (showMsg)
|
||||
pGameRun.AddFixedChannelMsg((int)FixedMsg.FIXMSG_TARGETWRONG, (int)ChatChannel.GP_CHAT_FIGHT);
|
||||
return false;
|
||||
}
|
||||
else if (m_idSelTarget != 0)
|
||||
{
|
||||
if (AttackableJudge(m_idSelTarget, bForceAttack) != 1)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int idCastTarget = m_idSelTarget;
|
||||
int iTargetType = pSkill.GetTargetType();
|
||||
|
||||
if (pSkill.GetType() == (int)CECSkill.SkillType.TYPE_BLESS ||
|
||||
pSkill.GetType() == (int)CECSkill.SkillType.TYPE_NEUTRALBLESS)
|
||||
{
|
||||
if(iTargetType == 0 || !GPDataTypeHelper.ISPLAYERID(m_idSelTarget))
|
||||
idCastTarget = m_PlayerInfo.cid;
|
||||
|
||||
if (GPDataTypeHelper.ISPLAYERID(idCastTarget) && idCastTarget != m_PlayerInfo.cid)
|
||||
{
|
||||
byte byBLSMask = EC_Utility.glb_BuildBLSMask();
|
||||
|
||||
if (pSkill.GetRangeType() == (int)CECSkill.RangeType.RANGE_POINT)
|
||||
{
|
||||
if (!IsTeamMember(idCastTarget))
|
||||
{
|
||||
if ((byBLSMask & (byte)PVPMask.GP_BLSMASK_SELF) != 0)
|
||||
{
|
||||
idCastTarget = m_PlayerInfo.cid;
|
||||
}
|
||||
else
|
||||
{
|
||||
EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance.GetECManPlayer.GetElsePlayer(idCastTarget) as EC_ElsePlayer;
|
||||
if(pPlayer == null)
|
||||
return false;
|
||||
|
||||
if (pPlayer.IsInvader() || pPlayer.IsPariah())
|
||||
{
|
||||
if((byBLSMask & (byte)PVPMask.GP_BLSMASK_NORED) != 0)
|
||||
idCastTarget = m_PlayerInfo.cid;
|
||||
}
|
||||
|
||||
if (!IsFactionMember(pPlayer.GetFactionID()))
|
||||
{
|
||||
if ((byBLSMask & (byte)PVPMask.GP_BLSMASK_NOMAFIA) != 0)
|
||||
idCastTarget = m_PlayerInfo.cid;
|
||||
}
|
||||
|
||||
if (!IsFactionAllianceMember(pPlayer.GetFactionID()))
|
||||
{
|
||||
if((byBLSMask & (byte)PVPMask.GP_BLSMASK_NOALLIANCE) != 0)
|
||||
idCastTarget = m_PlayerInfo.cid;
|
||||
}
|
||||
|
||||
if (GetForce() != pPlayer.GetForce())
|
||||
{
|
||||
if((byBLSMask & (byte)PVPMask.GP_BLSMASK_NOFORCE) != 0)
|
||||
idCastTarget = m_PlayerInfo.cid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If host is in dule
|
||||
if(IsInDuel() && m_idSelTarget == m_pvp.idDuelOpp)
|
||||
idCastTarget = m_PlayerInfo.cid;
|
||||
|
||||
// If host is in battle
|
||||
if (IsInBattle())
|
||||
{
|
||||
EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance.GetECManPlayer.GetElsePlayer(idCastTarget);
|
||||
if (!InSameBattleCamp(pPlayer))
|
||||
idCastTarget = m_PlayerInfo.cid;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iTargetType != 0)
|
||||
{
|
||||
int iAliveFlag = 0;
|
||||
if (iTargetType == 1)
|
||||
iTargetType = 1;
|
||||
else if (iTargetType == 2)
|
||||
iTargetType = 2;
|
||||
|
||||
CECObject pObject = EC_ManMessageMono.Instance.GetObject(idCastTarget, iAliveFlag);
|
||||
if(pObject == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsMeleeing() && !IsSpellingMagic() &&
|
||||
(iTargetType == 0 || idCastTarget == m_PlayerInfo.cid))
|
||||
{
|
||||
if(!pSkill.ReadyToCast())
|
||||
return false;
|
||||
|
||||
if (!pSkill.IsInstant() && pSkill.GetType() != (int)CECSkill.SkillType.TYPE_FLASHMOVE)
|
||||
{
|
||||
// TODO: Implement NaturallyStopMoving
|
||||
//if (!NaturallyStopMoving())
|
||||
// return false;
|
||||
}
|
||||
else if (pSkill.GetType() == (int)CECSkill.SkillType.TYPE_FLASHMOVE)
|
||||
{
|
||||
if(!CanDo(ActionCanDo.CANDO_FLASHMOVE))
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pPrepSkill = pSkill;
|
||||
}
|
||||
else if (IsSpellingMagic() && m_pCurSkill == pSkill && !pSkill.ReadyToCast())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (pItem.IsEquipment())
|
||||
{
|
||||
if (iPack == Inventory_type.IVTRTYPE_EQUIPPACK)
|
||||
{
|
||||
// Take off equipment
|
||||
int iEmpty = m_pPack.SearchEmpty();
|
||||
if (iEmpty < 0)
|
||||
return false;
|
||||
|
||||
UnityGameSession.RequestEquipItemAsync((byte)iEmpty, (byte)iSlot, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
EC_IvtrEquip pEquip = pItem as EC_IvtrEquip;
|
||||
if(pEquip == null)
|
||||
return false;
|
||||
|
||||
int iReason = 0;
|
||||
if(!CanUseEquipment(pEquip, ref iReason))
|
||||
return false;
|
||||
|
||||
int iFirstFree = -1, iFirstCan = -1;
|
||||
for (int i = 0; i < InventoryConst.SIZE_ALL_EQUIPIVTR; i++)
|
||||
{
|
||||
if (pItem.CanEquippedTo(i))
|
||||
{
|
||||
if (iFirstCan < 0)
|
||||
iFirstCan = i;
|
||||
|
||||
if (m_pEquipPack.GetItem(i) == null && iFirstFree < 0)
|
||||
{
|
||||
iFirstFree = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int iDst;
|
||||
if (iFirstFree >= 0)
|
||||
iDst = iFirstFree;
|
||||
else if (iFirstCan >= 0)
|
||||
iDst = iFirstCan;
|
||||
else
|
||||
{
|
||||
Debug.Assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_ARROW ||
|
||||
pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_DYNSKILLEQUIP)
|
||||
{
|
||||
EC_IvtrItem pDstItem = m_pEquipPack.GetItem(iDst);
|
||||
if (pDstItem == null || pItem.GetTemplateID() != pDstItem.GetTemplateID())
|
||||
UnityGameSession.RequestEquipItemAsync((byte)iSlot, (byte)iDst, null);
|
||||
else
|
||||
{
|
||||
//UnityGameSession.c2s_CmdMoveItemToEquip((byte)iSlot, (byte)iDst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_GENERALCARD)
|
||||
{
|
||||
//TODO: Add general card equip request
|
||||
}
|
||||
UnityGameSession.RequestEquipItemAsync((byte)iSlot, (byte)iDst, null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(iPack != Inventory_type.IVTRTYPE_PACK)
|
||||
return false;
|
||||
|
||||
if (!pItem.CheckUseCondition())
|
||||
{
|
||||
if (showMsg)
|
||||
pGameRun.AddFixedMessage((int)FixedMsg.FIXMSG_ITEM_CANNOTUSE);
|
||||
return false;
|
||||
}
|
||||
|
||||
int? piMax = null;
|
||||
if (pItem.GetCoolTime(out piMax) > 0)
|
||||
{
|
||||
if (showMsg)
|
||||
pGameRun.AddFixedMessage((int)FixedMsg.FIXMSG_ITEM_INCOOLTIME);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pItem.Use_AtkTarget() || pItem.Use_Target())
|
||||
{
|
||||
if(pItem.Use_AtkTarget() && CannotAttack())
|
||||
return false;
|
||||
|
||||
if (m_idSelTarget == 0 || m_idSelTarget == m_PlayerInfo.cid)
|
||||
{
|
||||
if (showMsg)
|
||||
{
|
||||
CECStringTab pStrTab = EC_Game.GetFixedMsgs();
|
||||
pGameRun.AddChatMessage(pStrTab.GetWideString((int)FixedMsg.FIXMSG_NOTARGET), (int)ChatChannel.GP_CHAT_SYSTEM);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float fAattackRange = 10000.0f;
|
||||
if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_TOSSMAT)
|
||||
{
|
||||
EC_IvtrTossMat pTossMat = pItem as EC_IvtrTossMat;
|
||||
if (pTossMat != null)
|
||||
fAattackRange = pTossMat.GetDBEssence().attack_range;
|
||||
}
|
||||
else if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_TANKCALLIN)
|
||||
{
|
||||
fAattackRange = 5.0f;
|
||||
}
|
||||
else if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_TARGETITEM)
|
||||
{
|
||||
EC_IvtrTargetItem pTargetItem = pItem as EC_IvtrTargetItem;
|
||||
if (pTargetItem != null && pTargetItem.GetTargetSkill() != null)
|
||||
{
|
||||
fAattackRange = pTargetItem.GetTargetSkill().GetCastRange(m_ExtProps.ak.AttackRange, GetPrayDistancePlus());
|
||||
}
|
||||
}
|
||||
|
||||
float fDist = 0, fTargetRag = 0;
|
||||
CECObject pObject = null;
|
||||
//if (CalcDist(m_idSelTarget, ref fDist, ref pObject))
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
if (GPDataTypeHelper.ISNPCID(m_idSelTarget))
|
||||
{
|
||||
CECNPC pNPC = pObject as CECNPC;
|
||||
if (pNPC != null)
|
||||
fTargetRag = pNPC.GetTouchRadius();
|
||||
}
|
||||
else if (GPDataTypeHelper.ISPLAYERID(m_idSelTarget))
|
||||
{
|
||||
EC_ElsePlayer pPlayer = pObject as EC_ElsePlayer;
|
||||
if(pPlayer != null)
|
||||
fTargetRag = pPlayer.GetTouchRadius();
|
||||
}
|
||||
|
||||
if (fDist - fTargetRag > fAattackRange * 0.8f)
|
||||
{
|
||||
if (showMsg)
|
||||
{
|
||||
CECStringTab pStrTab = EC_Game.GetFixedMsgs();
|
||||
pGameRun.AddChatMessage(pStrTab.GetWideString((int)FixedMsg.FIXMSG_TARGETISFAR), (int)ChatChannel.GP_CHAT_SYSTEM);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
byte byPVPMask = glb_BuildPVPMask(glb_GetForceAttackFlag(0));
|
||||
UnityGameSession.c2s_SendCmdUseItemWithTarget((byte)iPack, (byte)iSlot, pItem.GetTemplateID(), byPVPMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_DOUBLEEXP)
|
||||
{
|
||||
EC_IvtrDoubleExp pDoubleExp = pItem as EC_IvtrDoubleExp;
|
||||
if (pDoubleExp != null)
|
||||
{
|
||||
if (pDoubleExp.GetDBEssence().double_exp_time + pGameRun.GetRemainDblExpTime() > 3600 * 4)
|
||||
{
|
||||
if (showMsg)
|
||||
{
|
||||
CECGameUIMan pGameUI = pGameRun.GetUIManager().GetInGameUIMan();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pItem.GetClassID() == (int)EC_IvtrItem.InventoryClassId.ICID_SHARPENER)
|
||||
{
|
||||
if (showMsg)
|
||||
pGameRun.AddFixedMessage((int)FixedMsg.FIXMSG_SHARPEN_ON_DRAG);
|
||||
return false;
|
||||
}
|
||||
UnityGameSession.c2s_SendCmdUseItem((byte)iPack, (byte)iSlot, pItem.GetTemplateID(), 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnMsgHstUseItem(ECMSG Msg)
|
||||
{
|
||||
cmd_host_use_item pCmd = GPDataTypeHelper.FromBytes<cmd_host_use_item>((byte[])Msg.dwParam1);
|
||||
EC_Inventory pPack = GetPack(pCmd.byPackage);
|
||||
if (pPack == null)
|
||||
{
|
||||
Debug.LogError("[OnMsgHstUseItem] Pack not found");
|
||||
return;
|
||||
}
|
||||
|
||||
EC_IvtrItem pItem = pPack.GetItem(pCmd.bySlot, false);
|
||||
if (pItem == null || pItem.GetTemplateID() != pCmd.item_id)
|
||||
{
|
||||
Debug.LogError($"[OnMsgHstUseItem] Item mismatch at slot {pCmd.bySlot}");
|
||||
return;
|
||||
}
|
||||
|
||||
pItem.Use();
|
||||
|
||||
if (pCmd.use_count > 0)
|
||||
{
|
||||
bool removed = pPack.RemoveItem(pCmd.bySlot, pCmd.use_count);
|
||||
if (removed)
|
||||
{
|
||||
if (pPack.GetItem(pCmd.bySlot, false) == null)
|
||||
{
|
||||
Debug.Log($"[OnMsgHstUseItem] Item {pCmd.item_id} removed from slot {pCmd.bySlot}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[OnMsgHstUseItem] Failed to remove item {pCmd.item_id} from slot {pCmd.bySlot}");
|
||||
}
|
||||
|
||||
var ui = GameObject.FindFirstObjectByType<EC_InventoryUI>();
|
||||
if (ui != null)
|
||||
{
|
||||
ui.RefreshAll();
|
||||
ui.UpdateCooldownOverlays();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[OnMsgHstUseItem] EC_InventoryUI not found, UI may not update");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pWorkMan != null)
|
||||
{
|
||||
CECHPWork pWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_USEITEM);
|
||||
if (pWork is CECHPWorkUse useWork)
|
||||
{
|
||||
if(useWork.GetItem() == pCmd.item_id)
|
||||
{
|
||||
m_pWorkMan.FinishRunningWork(Host_work_ID.WORK_USEITEM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate distance to an object and optionally retrieve the object reference
|
||||
/// 计算到对象的距离,并可选地获取对象引用
|
||||
/// </summary>
|
||||
/// <param name="idObject">Target object ID / 目标对象ID</param>
|
||||
/// <param name="pfDist">Output distance / 输出距离</param>
|
||||
/// <param name="ppObject">Output object reference (optional) / 输出对象引用(可选)</param>
|
||||
/// <returns>True if calculation succeeded / 计算成功返回true</returns>
|
||||
//public bool CalcDist(int idObject, ref float pfDist, out CECObject ppObject)
|
||||
//{
|
||||
// ppObject = null;
|
||||
|
||||
// if (idObject == 0 || idObject == m_PlayerInfo.cid)
|
||||
// return false;
|
||||
|
||||
// CECObject pObject = CECGameRun.Instance.GetWorld()?.GetObject(idObject, 1);
|
||||
// if (pObject == null)
|
||||
// return false;
|
||||
|
||||
// ppObject = pObject;
|
||||
// float fDist = 0.0f;
|
||||
|
||||
// if (ISNPCID(idObject))
|
||||
// {
|
||||
// CECNPC pNPC = (CECNPC)pObject;
|
||||
// fDist = pNPC.CalcDist(GetPos(), true);
|
||||
// }
|
||||
// else if (ISPLAYERID(idObject))
|
||||
// {
|
||||
// Debug.Assert(pObject.GetClassID() == CECObject.OCID_ELSEPLAYER);
|
||||
// EC_ElsePlayer pPlayer = (EC_ElsePlayer)pObject;
|
||||
// fDist = pPlayer.CalcDist(GetPos(), true);
|
||||
// }
|
||||
// else if (ISMATTERID(idObject))
|
||||
// {
|
||||
// Debug.Assert(pObject.GetClassID() == CECObject.OCID_MATTER);
|
||||
// CECMatter pMatter = (CECMatter)pObject;
|
||||
// fDist = (pMatter.GetPos() - GetPos()).magnitude;
|
||||
// }
|
||||
// else
|
||||
// return false;
|
||||
|
||||
// pfDist = fDist;
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//// Helper method overload without object output
|
||||
//public bool CalcDist(int idObject, ref float pfDist)
|
||||
//{
|
||||
// CECObject pObject;
|
||||
// return CalcDist(idObject, ref pfDist, out pObject);
|
||||
//}
|
||||
|
||||
//// ID checking helper methods
|
||||
//private bool ISNPCID(int id) => ((id & 0x80000000) != 0) && ((id & 0x40000000) == 0);
|
||||
//private bool ISPLAYERID(int id) => id != 0 && (id & 0x80000000) == 0;
|
||||
//private bool ISMATTERID(int id) => ((id) & 0xC0000000) == 0xC0000000;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user