From 3af8d968f19d90c67f83a3b3fb5e9f8872539cf1 Mon Sep 17 00:00:00 2001 From: Tungdv Date: Fri, 10 Oct 2025 19:02:57 +0700 Subject: [PATCH] fix: Update atk normal. --- .../Scripts/Managers/EC_HPWork.cs | 42 +- .../Scripts/Managers/EC_HPWorkTrace.cs | 5 +- .../Scripts/Managers/EC_Object.cs | 2 +- Assets/PerfectWorld/Scripts/NPC/CECNPC.cs | 5 + .../CSNetwork/C2SCommand/C2SCommand.cs | 5 + .../Scripts/Network/CSNetwork/GPDataType.cs | 5 + .../Scripts/Network/CSNetwork/GameSession.cs | 29 ++ .../Scripts/Network/UnityGameSession.cs | 10 + .../Scripts/Players/EC_ElsePlayer.cs | 102 +---- Assets/Scripts/CECHostPlayer.cs | 365 +++++++++++++++++- Assets/Scripts/Move/EC_Player.cs | 86 ++++- 11 files changed, 545 insertions(+), 111 deletions(-) diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs index b603c779c4..14f1895208 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs @@ -5,8 +5,8 @@ using WorkList = System.Collections.Generic.List; public class CECHPWork : CECObjectWork { - // Host work ID - public static class Host_work_ID + // Host work ID + public static class Host_work_ID { public const int WORK_INVALID = -1, WORK_STAND = 0, // Stand and do nothing @@ -67,14 +67,14 @@ public class CECHPWork : CECObjectWork // Operations // Override from CECObjectWork - public virtual void Cancel() + public virtual void Cancel() { } // This work is do player moving ? - public virtual bool IsMoving() - { - return false; + public virtual bool IsMoving() + { + return false; } // Copy work data public virtual bool CopyData(CECHPWork pWork) @@ -231,7 +231,7 @@ public class CECHPWorkMan for (int i = (Work_priority.NUM_PRIORITY - 1); i >= 0; --i) { WorkList workList = m_WorkStack[i]; - if(workList != null) + if (workList != null) { for (int j = 0; j < workList.Count; ++j) { @@ -251,7 +251,7 @@ public class CECHPWorkMan return result; } - bool InternallyStartWork(int iPriority, CECHPWork pWork) + bool InternallyStartWork(int iPriority, CECHPWork pWork) { bool bStarted = false; if (CanRunSimultaneouslyWithCurrentWork(iPriority, pWork)) @@ -448,13 +448,13 @@ public class CECHPWorkMan } public CECHPWork GetDelayedWork() - { - return m_Delayed.pWork; + { + return m_Delayed.pWork; } public bool ValidatePriority(int iPriority) { - return iPriority >= 0 && iPriority < Work_priority.NUM_PRIORITY; + return iPriority >= 0 && iPriority < Work_priority.NUM_PRIORITY; } public bool StartWork(int iPriority, CECHPWork pWork, bool bNoDelay = false) @@ -538,7 +538,7 @@ public class CECHPWorkMan return true; } WorkList workList = m_WorkStack[iPriority]; - if(workList != null) + if (workList != null) { for (int i = 0; i < workList.Count; ++i) { @@ -553,7 +553,7 @@ public class CECHPWorkMan bool HasWorkOnPriority(int iPriority) { - return ValidatePriority(iPriority) && m_WorkStack[iPriority] != null && m_WorkStack[iPriority].Count != 0; + return ValidatePriority(iPriority) && m_WorkStack[iPriority] != null && m_WorkStack[iPriority].Count != 0; } public void SetPostTickCommand(CECHPWorkPostTickCommand command) @@ -561,14 +561,16 @@ public class CECHPWorkMan m_pPostTickCommand = command; } - bool HasWorkRunningOnPriority(int iPriority){ - return HasWorkOnPriority(iPriority); -} -bool IsAnyWorkRunning(){ - return HasWorkRunningOnPriority(m_iCurPriority); -} + public bool HasWorkRunningOnPriority(int iPriority) + { + return HasWorkOnPriority(iPriority); + } + bool IsAnyWorkRunning() + { + return HasWorkRunningOnPriority(m_iCurPriority); + } -public void Tick(float dwDeltaTime) + public void Tick(float dwDeltaTime) { if (!IsAnyWorkRunning()) { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs index d4a70c39fb..18f35737a3 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs @@ -574,7 +574,7 @@ public class CECHPWorkTrace : CECHPWork } // Tick routine - public virtual bool Tick(float dwDeltaTime) + public override bool Tick(float dwDeltaTime) { base.Tick(dwDeltaTime); @@ -599,6 +599,8 @@ public class CECHPWorkTrace : CECHPWork { if (IsGoodTimeToTouch()) { + OnTouchTarget(); + return true; if (m_pTraceObject.CanTouchFrom(m_pHost.GetPos())) { OnTouchTarget(); @@ -608,6 +610,7 @@ public class CECHPWorkTrace : CECHPWork } m_bCheckTouch = true; + return true; // TO DO: remove later if (!m_pHost.IsRooting()) { // Continue tracing object diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs index f6f58bbfb4..6ee388cece 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs @@ -64,7 +64,7 @@ public class CECObject : MonoBehaviour { m_dwBornStamp = 0; m_bBornInSight = false; - m_bSelectable = false; + //m_bSelectable = false; m_iCID = (int)Class_ID.OCID_OBJECT; } diff --git a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs index 5b57c77e9c..4ec062951a 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs @@ -37,6 +37,7 @@ public class CECNPC : CECObject protected Vector3 m_vStopDir; protected ROLEEXTPROP m_ExtProps; protected CECNPCModelPolicy m_pNPCModelPolicy; + [SerializeField] protected float m_fMoveSpeed; [SerializeField] protected CharacterController _characterController; @@ -902,6 +903,10 @@ public class CECNPC : CECObject // Get NPC ID public int GetNPCID() { return m_NPCInfo.nid; } + + // Get distance to host player + public float GetDistToHost() { return m_fDistToHost; } + public float GetDistToHostH() { return m_fDistToHostH; } } public enum WorkType { diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs index 1c95c8594f..d5443fdb14 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs @@ -1333,6 +1333,11 @@ namespace CSNetwork.S2CCommand { public byte pvp_mask; }; + + public struct cmd_select_target + { + public int id; + }; } // Player and NPC state \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs index 90ea6ed814..68f9330312 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs @@ -1265,5 +1265,10 @@ namespace CSNetwork.GPDataType GP_BLSMASK_NOALLIANCE = 0x0040, GP_BLSMASK_NOFORCE = 0x0080 // ÊÆÁ¦ÆÁ±Î }; + + public struct cmd_select_target + { + public int idTarget; + }; } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index 8be0d9d698..e406bbd7f3 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -29,6 +29,7 @@ namespace CSNetwork private string _password; private int _currentUserId = -1; // To store the UserID after successful login private int m_iCharID; + private int m_idLastSelTarget = 0; // ID of selected item last time // State management for async operations and callbacks private Action _loginCallback; @@ -439,6 +440,12 @@ namespace CSNetwork case CommandID.ERROR_MESSAGE: _logger.Info($"### GameDataSend: ERROR_MESSAGE: {BitConverter.ToInt32(pDataBuf, 0)}"); break; + case CommandID.SELECT_TARGET: + case CommandID.UNSELECT: + + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SELTARGET, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + } } @@ -770,5 +777,27 @@ namespace CSNetwork gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.CANCEL_ACTION); SendProtocol(gamedatasend); } + + public void c2s_CmdUnselect() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.UNSELECT); + SendProtocol(gamedatasend); + } + + public void c2s_CmdSelectTarget(int idTarget) + { + // Set selection first before server returns, so as to reduce the player waiting time. + CECHostPlayer pHost = EC_ManMessageMono.Instance.GetECManPlayer.GetHostPlayer(); + pHost.SetSelectedTarget(idTarget); + + if (m_idLastSelTarget != idTarget) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateSelectTarget(idTarget); + SendProtocol(gamedatasend); + m_idLastSelTarget = idTarget; + } + } } } diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs index 8a6928689e..07f37b5c83 100644 --- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs @@ -194,6 +194,16 @@ namespace BrewMonster.Network Instance._gameSession.c2s_CmdCancelAction(); } + public static void c2s_CmdUnselect() + { + Instance._gameSession.c2s_CmdUnselect(); + } + + public static void c2s_CmdSelectTarget(int idTarget) + { + Instance._gameSession.c2s_CmdSelectTarget(idTarget); + } + #region Task public static void c2s_CmdGetAllData(bool byPack, bool byEquip, bool byTask) { diff --git a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs index 58c64ecb0d..bc96829d14 100644 --- a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs +++ b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs @@ -22,87 +22,20 @@ namespace PerfectWorld.Scripts.Player long m_dwLastMoveTime = 0; // Last move command arrived time float m_fMoveSpeed; // Move speed OtherPlayer_Move_Info m_cdr = new OtherPlayer_Move_Info(); + float m_fDistToHost = 0f; // Distance to host player + float m_fDistToHostH = 0f; // Horizontal distance to host player // 和服务器提供的 aabb,无法影响朝向 = The AABB provided by the server cannot affect the facing/orientation - A3DAABB m_aabbServer = new A3DAABB(); - A3DAABB m_aabb = new A3DAABB(); // Player's aabb£¬ÓÃÓÚÏÔʾµÄaabb£¬ÊÜËõ·ÅÓ°Ïì - string m_strName; // Player name - int m_iProfession; // Profession - int m_iGender; // Gender - float m_fScaleBySkill = 1f; - MOVECONST m_MoveConst; // Const used when moving control + //A3DAABB m_aabbServer = new A3DAABB(); + //A3DAABB m_aabb = new A3DAABB(); // Player's aabb£¬ÓÃÓÚÏÔʾµÄaabb£¬ÊÜËõ·ÅÓ°Ïì + //string m_strName; // Player name + //int m_iProfession; // Profession + //int m_iGender; // Gender + //float m_fScaleBySkill = 1f; + //MOVECONST m_MoveConst; // Const used when moving control //int m_iMoveEnv; // Move environment //bool m_bWalkRun; // Walk-run switch, 0-walk, 1-run //int m_iMoveMode; // Player's move mode - public MOVECONST[] aMoveConsts = new MOVECONST[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER] - { - // ÎäÏÀ - // fStepHei fMinAirHei fMinWaterHei fShoreDepth fWaterSurf - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // ·¨Ê¦ - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // Î×ʦ - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // Ñý¾« - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // ÑýÊÞ - new MOVECONST(0.8f, 1.6f, 0.3f, 1.8f, 0.7f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - // ´Ì¿Í - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // Óðâ - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // ÓðÁé - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // ½£Áé - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // ÷ÈÁé - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // Ò¹Ó° - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - // ÔÂÏÉ - new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), - new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), - }; - - public A3DVECTOR3[] aExts = new A3DVECTOR3[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER] - { - new A3DVECTOR3(0.4f, 0.9f, 0.4f), // ÎäÏÀ - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ·¨Ê¦ - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Î×ʦ - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Ñý¾« - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.5f, 1.05f, 0.5f), // ÑýÊÞ - new A3DVECTOR3(0.3f, 0.9f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ´Ì¿Í - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Óðâ - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÓðÁé - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ½£Áé - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÷ÈÁé - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Ò¹Ó° - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÔÂÏÉ - new A3DVECTOR3(0.3f, 0.85f, 0.3f), - }; - public void Init(RoleInfo roleInfo, info_player_1 Info) { m_iProfession = roleInfo.occupation; @@ -129,15 +62,6 @@ namespace PerfectWorld.Scripts.Player } } - void CalcPlayerAABB() - { - int iIndex = m_iProfession * GENDER.NUM_GENDER + m_iGender; - - m_aabb.Extents = aExts[iIndex] * m_fScaleBySkill; - m_aabbServer.Extents = aExts[iIndex]; - m_MoveConst = aMoveConsts[iIndex]; - } - public void MoveTo(cmd_object_move Cmd) { BrewMonster.BMLogger.Log("HoangDev : MoveToMoveTo"); @@ -329,6 +253,8 @@ namespace PerfectWorld.Scripts.Player PlayAction(GetMoveStandAction(true), true, 1, false); } + public float GetDistToHost() { return m_fDistToHost; } + // Decompress horizontal direction A3DVECTOR3 glb_DecompressDirH(byte byDir) { @@ -429,6 +355,12 @@ namespace PerfectWorld.Scripts.Player private void Update() { MovingTo(Time.deltaTime); + CECHostPlayer pHost = EC_ManMessageMono.Instance.GetECManPlayer.GetHostPlayer(); + if (pHost != null /*&& pHost->IsSkeletonReady()*/) + { + m_fDistToHost = CalcDist(pHost.GetPos(), true); + m_fDistToHostH = CalcDist(pHost.GetPos(), false); + } } private void SetPos(A3DVECTOR3 vPos) diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 36d8e4e249..f67a54c3e6 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -12,7 +12,6 @@ using System.IO; using System.Runtime.InteropServices; using System.Text; using TMPro; -using UnityEditor.Experimental.GraphView; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; @@ -55,6 +54,7 @@ public class CECHostPlayer : EC_Player Vector3 m_vLastSevPos; public CDR_INFO m_CDRInfo; public GNDINFO m_GndInfo; + int m_idUCSelTarget; // Uncertificately selected object's ID public float m_fVertSpeed = 0f; // ====== Ground cast config ====== @@ -141,9 +141,10 @@ public class CECHostPlayer : EC_Player CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idObject); if(pNPC != null) { - if (!pNPC.IsDead()) + if (!pNPC.IsDead()/* && m_idSelTarget == idObject*/) { idTraceTarget = idObject; + idSelTarget = idObject; } if (idTraceTarget != 0) { @@ -160,6 +161,13 @@ public class CECHostPlayer : EC_Player } } + // Tell server we select a target + if (idSelTarget != 0 && m_idSelTarget != idSelTarget) + { + m_idUCSelTarget = idSelTarget; + SelectTarget(m_idUCSelTarget); + } + if (idTraceTarget != 0) { //if (m_pWorkMan.IsSitting()) @@ -202,6 +210,8 @@ public class CECHostPlayer : EC_Player //} } } + + m_pWorkMan?.Tick(Time.deltaTime); } public void StopMovement() { @@ -329,6 +339,8 @@ public class CECHostPlayer : EC_Player case int value when value == EC_MsgDef.MSG_HST_PICKUPITEM: OnMsgHstPickupItem(Msg); break; + case int value when value == EC_MsgDef.MSG_HST_SELTARGET: + OnMsgHstSelTarget(Msg); break; } } @@ -534,9 +546,29 @@ public class CECHostPlayer : EC_Player } + // Message MSG_HST_SELTARGET handler + void OnMsgHstSelTarget(ECMSG Msg) + { + if ((int)Msg.dwParam2 == CommandID.SELECT_TARGET) + { + cmd_select_target pCmd = (cmd_select_target)Msg.dwParam1; + m_idSelTarget = pCmd.idTarget; + m_idUCSelTarget = 0; + } + else if ((int)Msg.dwParam2 == CommandID.UNSELECT) + { + m_idSelTarget = 0; + } + } + public void SetPos(Vector3 pos) { transform.position = pos; + + m_aabb.Center = EC_Utility.ToA3DVECTOR3(pos) + new A3DVECTOR3(0.0f, m_aabb.Extents.y, 0.0f); + m_aabb.CompleteMinsMaxs(); + m_aabbServer.Center = EC_Utility.ToA3DVECTOR3(pos) + new A3DVECTOR3(0.0f, m_aabbServer.Extents.y, 0.0f); + m_aabbServer.CompleteMinsMaxs(); } public void SetStatusRun(bool value) { @@ -567,6 +599,10 @@ public class CECHostPlayer : EC_Player { visual.InitHostPlayerEventDoneHandler(); } + m_aabb.Center = GPDataTypeHelper.g_vOrigin; + m_aabb.Extents.Set(0.3f, 0.9f, 0.3f); + m_aabbServer = m_aabb; + CalcPlayerAABB(); // Create work manager m_pWorkMan = new CECHPWorkMan(this); @@ -996,6 +1032,302 @@ public class CECHostPlayer : EC_Player public float GetFlySpeed() { return m_ExtProps.mv.flight_speed; } public float GetSwimSpeed() { return m_ExtProps.mv.swim_speed; } + bool SelectTarget(int idTarget) + { + bool bRet = false; + bool canDo = CanDo(ActionCanDo.CANDO_CHANGESELECT); + bool canselect = CanSelectTarget(idTarget); + if (canDo && canselect) + { + bRet = true; + if (idTarget == 0) + UnityGameSession.c2s_CmdUnselect(); + else + { + UnityGameSession.c2s_CmdSelectTarget(idTarget); + } + } + return bRet; + } + + bool CanSelectTarget(int idTarget) + { + if (idTarget == 0 || idTarget == this.GetCharacterID()) + { + // 0 means unselect + return true; + } + CECObject pTarget = null; + if (GPDataTypeHelper.ISPLAYERID(idTarget)) + { + EC_ElsePlayer pElsePlayer = (EC_ManMessageMono.Instance.GetECManPlayer.GetPlayer(idTarget)) as EC_ElsePlayer; + if (pElsePlayer != null) + { + if (CanSafelySelect(pElsePlayer)) + { + pTarget = pElsePlayer; + } + } + } + else if (GPDataTypeHelper.ISNPCID(idTarget)) + { + CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idTarget); + if (pNPC != null) + { + if (CanSafelySelect(pNPC) && !pNPC.IsDead()) + { + pTarget = pNPC; + } + } + } + return pTarget ? pTarget.IsSelectable() : false; + } + + + float SafelySelectDistance() + { + // ·þÎñÆ÷¶Ô SelectTarget ÓжîÍâ¾àÀëÏÞÖÆ£¬Èýά¾àÀë 150.0¡¢Ë®Æ½¾àÀë 125.0 ÒÔÉϵ쬶¼»áÎÞ·¨Ñ¡ÖÐ + // »ùÓÚÒÔÉÏÔ­Òò£¬¿Í»§¶ËÑ¡Ôñ¶ÔÏó¡¢»òÕß¶ÔÒѾ­Ñ¡ÔñµÄ¶ÔÏ󣬶¼È·±£ÆäÔÚ´ËÏÞÖÆ·¶Î§ÄÚ£¬¼´Ñ¡ÔñʱʹÓýÏС¾àÀë¼ì²â + return 100.0f; + } + + bool CanSafelySelectWith(float fDistanceToHostPlayer) + { + return fDistanceToHostPlayer <= SafelySelectDistance(); + } + + bool CanSafelySelect(EC_ElsePlayer pElsePlayer) + { + // IsSkeletonReady() Ϊ true ʱ, GetDistToHost() ²ÅΪÓÐЧÊý¾Ý + // !IsSkeletonReady() ʱ£¬Ò²ÔÊÐíʹÓã¬Ä¿µÄÊDZÜÃâδ¿¼Âǵ½µÄÒâÍâÇé¿ö + // ÏÂͬ + return pElsePlayer && (/*!IsSkeletonReady() || */CanSafelySelectWith(pElsePlayer.GetDistToHost())); + } + + bool CanSafelySelect(CECNPC pNPC) + { + return pNPC && (/*!IsSkeletonReady() ||*/ CanSafelySelectWith(pNPC.GetDistToHost())); + } + + // Check whether host can do a behavior + bool CanDo(int iThing) + { + bool bRet = true; + + switch (iThing) + { + case ActionCanDo.CANDO_SITDOWN: + + if (IsDead() /*|| IsAboutToDie() */|| IsJumping() /*|| IsTrading() || IsUsingTrashBox()*/ || + IsRooting() || /*IsReviving() || IsTalkingWithNPC() || IsChangingFace() ||*/ + !m_GndInfo.bOnGround /*|| GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || + IsUsingItem() || IsRidingOnPet() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove()*/) + bRet = false; + + break; + + case ActionCanDo.CANDO_MOVETO: + { + if (IsDead() /*|| IsSitting() || IsTrading() || IsUsingTrashBox()*/ || IsRooting() /*|| + IsReviving() || IsTalkingWithNPC() || IsChangingFace() || IsUsingItem() || + GetBoothState() != 0 || m_bHangerOn || IsOperatingPet() || IsRebuildingPet() || IsPassiveMove()*/) + bRet = false; + + break; + } + case ActionCanDo.CANDO_MELEE: + + if (IsDead() /*|| IsSitting() */|| m_idSelTarget == 0 || m_idSelTarget == m_PlayerInfo.cid || + IsJumping() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) /*|| IsTrading() || IsReviving() || + IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace()*/ || CannotAttack() /*|| + GetBoothState() != 0 || m_iBuddyId || IsRidingOnPet() || IsOperatingPet() || IsRebuildingPet() || + IsUsingItem() || IsPassiveMove()*/) + bRet = false; + + break; + + case ActionCanDo.CANDO_ASSISTSEL: + + if (IsDead() || !GPDataTypeHelper.ISPLAYERID(m_idSelTarget) || m_idSelTarget == m_PlayerInfo.cid /*|| + !m_pTeam || !m_pTeam->GetMemberByID(m_idSelTarget) || m_iBuddyId || IsPassiveMove() || + m_playerLimits.test(PLAYER_LIMIT_NOCHANGESELECT)*/) + bRet = false; + + break; + + case ActionCanDo.CANDO_FLY: + + if (IsDead() || IsRooting() /*|| IsSitting() || IsTrading() || IsReviving() || + IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || GetBoothState() != 0 || + IsFlashMoving() */|| m_pWorkMan.HasWorkRunningOnPriority(CECHPWorkMan.Work_priority.PRIORITY_2) /*|| + m_bHangerOn || IsOperatingPet() || IsRebuildingPet() || + IsUsingItem() || IsRidingOnPet() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove() || + m_playerLimits.test(PLAYER_LIMIT_NOFLY) || m_BattleInfo.IsChariotWar()*/) + bRet = false; + + break; + + case ActionCanDo.CANDO_PICKUP: + case ActionCanDo.CANDO_GATHER: + + if (IsDead() /*|| IsAboutToDie() || IsSitting() || IsTrading() || IsUsingTrashBox() || + IsReviving() || IsTalkingWithNPC() || IsChangingFace() || GetBoothState() != 0 || + GetBuddyState() == 1 || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()*/) + bRet = false; + + break; + + case ActionCanDo.CANDO_TRADE: + + if (IsDead() /*|| IsAboutToDie() || IsSitting() */|| IsJumping() /*|| IsMeleeing() || + IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || + IsSpellingMagic() || GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || + IsUsingItem() || IsInvisible() || IsPassiveMove()*/) + bRet = false; + + break; + + case ActionCanDo.CANDO_PLAYPOSE: + + if (IsDead() /*|| IsAboutToDie() || IsSitting()*/ || IsJumping() ||/* IsMeleeing() || + IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || + IsSpellingMagic() || IsShapeChanged() || IsReviving() ||*/ m_iMoveEnv != (int)MoveEnvironment.MOVEENV_GROUND /*|| + GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || + IsRidingOnPet() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove() || m_BattleInfo.IsChariotWar()*/) + bRet = false; + + break; + + //case ActionCanDo.CANDO_SPELLMAGIC: + // if (IsDead() || ISMATTERID(m_idSelTarget) || IsAboutToDie() || IsSitting() || + // IsJumping() || IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || CannotAttack() || IsReviving() || GetBoothState() != 0 || + // m_iBuddyId || IsRidingOnPet() || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) + // bRet = false; + + // break; + + case ActionCanDo.CANDO_SUMMONPET: + + if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) || /*IsAboutToDie() || IsSitting() ||*/ + IsJumping() || /*IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + IsChangingFace() ||*/ CannotAttack() /*|| IsReviving() || GetBoothState() != 0 || + IsInvisible() || IsGMInvisible() || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove() + || m_BattleInfo.IsChariotWar()*/) + bRet = false; + + break; + case ActionCanDo.CANDO_REBUILDPET: + + if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) /*|| IsAboutToDie() || IsSitting() */|| + IsJumping() /*|| IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + IsChangingFace()*/ || CannotAttack() /*|| IsReviving() || GetBoothState() != 0 || + m_iBuddyId || IsInvisible() || IsGMInvisible() || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove() || + IsPlayerMoving() || m_BattleInfo.IsChariotWar()*/) + bRet = false; + + break; + + //case ActionCanDo.CANDO_USEITEM: + + // if (IsAboutToDie() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || GetBoothState() != 0 || IsPassiveMove() || m_BattleInfo.IsChariotWar()) + // bRet = false; + + // break; + + //case ActionCanDo.CANDO_JUMP: + // { + // if (IsDead() || + // m_iJumpCount >= MAX_JUMP_COUNT || + // // cannot jump more than one time if shape mode is type2 + // (IsJumping() && (GetShapeType() == PLAYERMODEL_DUMMYTYPE2)) || + // IsJumpInWater() || m_iMoveEnv == MOVEENV_AIR || IsSitting() || + // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || + // IsGathering() || IsRooting() || GetBoothState() != 0 || m_bHangerOn || (IsJumping() && IsRidingOnPet()) || + // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove() || m_BattleInfo.IsChariotWar()) + // bRet = false; + + // break; + // } + //case ActionCanDo.CANDO_FOLLOW: + // { + // if (IsDead() || IsAboutToDie() || IsSitting() || IsMeleeing() || IsReviving() || + // IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || + // IsSpellingMagic() || GetBoothState() != 0 || m_bHangerOn || IsOperatingPet() || IsRebuildingPet() || + // IsUsingItem() || IsPassiveMove()) + // bRet = false; + + // break; + // } + //case ActionCanDo.CANDO_BOOTH: + + // if (IsDead() || IsAboutToDie() || IsPlayerMoving() || IsSitting() || IsReviving() || + // IsMeleeing() || IsJumping() || IsTrading() || IsUsingTrashBox() || + // IsTalkingWithNPC() || IsChangingFace() || IsSpellingMagic() || IsFlying() || + // IsUnderWater() || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsRidingOnPet() || IsInvisible() || + // IsPassiveMove()) + // bRet = false; + + // break; + + //case ActionCanDo.CANDO_FLASHMOVE: + + // if (IsDead() || IsAboutToDie() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsJumping() || IsFlashMoving() || IsFalling() || IsChangingFace() || GetBoothState() != 0 || IsTakingOff() || + // m_pWorkMan->HasWorkRunningOnPriority(CECHPWorkMan::PRIORITY_2) || + // m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) + // bRet = false; + + // break; + + //case ActionCanDo.CANDO_BINDBUDDY: + + // if (IsDead() || IsAboutToDie() || IsJumping() || IsSitting() || + // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || + // IsGathering() || IsRooting() || GetBoothState() != 0 || + // !m_pWorkMan->IsStanding() || m_iBuddyId || + // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove() || + // m_playerLimits.test(PLAYER_LIMIT_NOBIND)) + // bRet = false; + + // break; + + //case ActionCanDo.CANDO_DUEL: + + // if (IsDead() || IsAboutToDie() || IsSitting() || IsFighting() || IsTrading() || + // IsReviving() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || + // GetBoothState() != 0 || m_iBuddyId || m_pvp.iDuelState != DUEL_ST_NONE || + // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) + // bRet = false; + + // break; + + case ActionCanDo.CANDO_CHANGESELECT: + + //if (m_playerLimits.test(PLAYER_LIMIT_NOCHANGESELECT)) + // bRet = false; + + break; + + //case ActionCanDo.CANDO_SWITCH_PARALLEL_WORLD: + // if (IsDead() || IsAboutToDie() || IsJumping() || IsFighting() || + // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || + // IsGathering() || IsRooting() || GetBoothState() != 0 || + // m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || + // GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove()) + // bRet = false; + // break; + } + + return bRet; + } + + public void SetSelectedTarget(int id) { m_idSelTarget = id; } + //public float GetSwimSpeedSev() //{ // float fSpeedSev = GetSwimSpeed(); @@ -1080,4 +1412,31 @@ public struct GNDINFO public float fWaterHei; // Water height public A3DVECTOR3 vGndNormal; // Terrain normal public bool bOnGround; // On ground flag -}; \ No newline at end of file +}; + +// Behavior id used by CanDo() +public static class ActionCanDo + + { + public const int CANDO_SITDOWN = 0, + CANDO_MOVETO = 1, + CANDO_MELEE = 2, + CANDO_ASSISTSEL = 3, + CANDO_FLY = 4, + CANDO_PICKUP = 5, + CANDO_TRADE = 6, + CANDO_PLAYPOSE = 7, + CANDO_SPELLMAGIC = 8, + CANDO_USEITEM = 9, + CANDO_JUMP = 10, + CANDO_FOLLOW = 11, + CANDO_GATHER = 12, + CANDO_BOOTH = 13, + CANDO_FLASHMOVE = 14, + CANDO_BINDBUDDY = 15, + CANDO_DUEL = 16, + CANDO_SUMMONPET = 17, + CANDO_CHANGESELECT = 18, + CANDO_REBUILDPET = 19, + CANDO_SWITCH_PARALLEL_WORLD = 20; +} \ No newline at end of file diff --git a/Assets/Scripts/Move/EC_Player.cs b/Assets/Scripts/Move/EC_Player.cs index 16b479fba9..9ace0ed5ea 100644 --- a/Assets/Scripts/Move/EC_Player.cs +++ b/Assets/Scripts/Move/EC_Player.cs @@ -24,7 +24,82 @@ public abstract class EC_Player : CECObject protected ROLEBASICPROP m_BasicProps; public int m_iMoveEnv = Move_environment.MOVEENV_GROUND; // Move environment public bool m_bWalkRun; - public A3DAABB m_aabbServer; // Óë·þÎñÆ÷±£³ÖÒ»ÖµÄaabb£¬ ²»ÊÜËõ·ÅÓ°Ïì + public A3DAABB m_aabbServer = new A3DAABB(); // Óë·þÎñÆ÷±£³ÖÒ»ÖµÄaabb£¬ ²»ÊÜËõ·ÅÓ°Ïì + public A3DAABB m_aabb = new A3DAABB(); // Player's aabb£¬ÓÃÓÚÏÔʾµÄaabb£¬ÊÜËõ·ÅÓ°Ïì + public int m_iProfession; // Profession + public float m_fScaleBySkill; + public int m_iGender; // Gender + public MOVECONST m_MoveConst; // Const used when moving control + + public MOVECONST[] aMoveConsts = new MOVECONST[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER] + { + // ÎäÏÀ + // fStepHei fMinAirHei fMinWaterHei fShoreDepth fWaterSurf + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // ·¨Ê¦ + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // Î×ʦ + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // Ñý¾« + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // ÑýÊÞ + new MOVECONST(0.8f, 1.6f, 0.3f, 1.8f, 0.7f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + // ´Ì¿Í + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // Óðâ + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // ÓðÁé + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // ½£Áé + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // ÷ÈÁé + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // Ò¹Ó° + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + // ÔÂÏÉ + new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), + new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), + }; + + public A3DVECTOR3[] aExts = new A3DVECTOR3[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER] + { + new A3DVECTOR3(0.4f, 0.9f, 0.4f), // ÎäÏÀ + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ·¨Ê¦ + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Î×ʦ + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Ñý¾« + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.5f, 1.05f, 0.5f), // ÑýÊÞ + new A3DVECTOR3(0.3f, 0.9f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ´Ì¿Í + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Óðâ + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÓðÁé + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ½£Áé + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÷ÈÁé + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Ò¹Ó° + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÔÂÏÉ + new A3DVECTOR3(0.3f, 0.85f, 0.3f), + }; + protected void Awake() { m_PlayerActions = _default_actions; @@ -38,6 +113,15 @@ public abstract class EC_Player : CECObject return m_PlayerInfo; } + public void CalcPlayerAABB() + { + int iIndex = m_iProfession * GENDER.NUM_GENDER + m_iGender; + + m_aabb.Extents = aExts[iIndex] * m_fScaleBySkill; + m_aabbServer.Extents = aExts[iIndex]; + m_MoveConst = aMoveConsts[iIndex]; + } + public static void InitStaticRes() { BuildActionList();