Merge branch 'develop' of https://git.brew.monster/Unity/perfect-world-unity into update-in-game

This commit is contained in:
Chomper9981
2026-01-29 17:49:03 +07:00
84 changed files with 49622 additions and 6947 deletions
+178
View File
@@ -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;
}
}
+543 -7
View File
@@ -49,6 +49,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
@@ -565,6 +566,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;
@@ -678,8 +681,9 @@ namespace BrewMonster
COOLTIME ct = m_aCoolTimes[pCmd.cooldown_index];
ct.iCurTime = pCmd.cooldown_time;
ct.iMaxTime = pCmd.cooldown_time;
Debug.Log("New Max cool time forIvtrMedicine: it be: " + pCmd.cooldown_time);
Math.Min(ct.iCurTime, ct.iMaxTime);
m_aCoolTimes[pCmd.cooldown_index] = ct;
if (pCmd.cooldown_index == (int)CoolTimeIndex.GP_CT_CAST_ELF_SKILL)
{
int i;
@@ -707,7 +711,7 @@ namespace BrewMonster
CECSkill pSkill = GetPositiveSkillByIndex(i);
int fakeRef = 0;
if (pSkill != null && (pSkill.GetCommonCoolDown() & mask) != 0)
pSkill.StartCooling(GetCoolTime(pCmd.cooldown_index, ref fakeRef), GetCoolTime(pCmd.cooldown_index, ref fakeRef));
pSkill.StartCooling(GetCoolTime(pCmd.cooldown_index, out fakeRef), GetCoolTime(pCmd.cooldown_index, out fakeRef));
}
/*const std::map<unsigned int, CECSkill*>&inherentSkillMap = CECComboSkillState::Instance().GetInherentSkillMap();
std::map < unsigned int, CECSkill*>::const_iterator it;
@@ -3415,6 +3419,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
@@ -6092,13 +6102,13 @@ namespace BrewMonster
}
// Get cool time
public int GetCoolTime(int iIndex, ref int piMax /* NULL */)
public virtual int GetCoolTime(int iIndex, out int piMax /* NULL */)
{
piMax = 1;
if (iIndex >= 0 && iIndex < (int)CoolTimeIndex.GP_CT_MAX)
{
if (piMax > 0)
piMax = m_aCoolTimes[iIndex].iMaxTime;
return m_aCoolTimes[iIndex].iCurTime;
}
@@ -6981,7 +6991,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)
@@ -7063,8 +7073,6 @@ namespace BrewMonster
return m_pPetCorral;
}
// Get key object(NPC..) coordinates
public A3DVECTOR3 GetObjectCoordinates(int idTarget,ref ObjectCoords TargetCoord, ref bool bInTable)
{
@@ -7152,6 +7160,534 @@ namespace BrewMonster
}
return false;
}
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 = -1;
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;
}
}