Merge branch 'develop' of https://git.brew.monster/Unity/perfect-world-unity into update-in-game
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user