From 001a16cf32494c84020f2151a3c7a26668c515a3 Mon Sep 17 00:00:00 2001 From: Tungdv Date: Tue, 14 Oct 2025 18:34:16 +0700 Subject: [PATCH 1/6] fix: update namespace. feat: add new logic EC_World. --- .../Scripts/Managers/A3DTerrain2.cs | 6 + .../Scripts/Managers/A3DTerrain2.cs.meta | 2 + .../Scripts/Managers/CECNPCMan.cs | 476 ++-- .../Scripts/Managers/EC_HPWork.cs | 1142 ++++---- .../Scripts/Managers/EC_HPWorkMelee.cs | 258 +- .../Scripts/Managers/EC_HPWorkMove.cs | 681 ++--- .../Scripts/Managers/EC_HPWorkSpell.cs | 127 +- .../Scripts/Managers/EC_HPWorkTrace.cs | 1846 ++++++------ .../Scripts/Managers/EC_HostPlayer.cs | 2 +- .../Scripts/Managers/EC_Inventory.cs | 2 +- .../Scripts/Managers/EC_InventoryUI.cs | 2 +- .../Scripts/Managers/EC_IvtrItem.cs | 2 +- .../Scripts/Managers/EC_IvtrType.cs | 2 +- .../Scripts/Managers/EC_ManMatter.cs | 432 ++- .../Scripts/Managers/EC_ManPlayer.cs | 799 +++--- .../Scripts/Managers/EC_Object.cs | 414 +-- .../Scripts/Managers/EC_ObjectWork.cs | 115 +- .../PerfectWorld/Scripts/Managers/EC_World.cs | 6 + .../Scripts/Managers/EC_World.cs.meta | 2 + .../Scripts/Managers/HalfSpace.cs | 166 ++ .../Scripts/Managers/HalfSpace.cs.meta | 2 + .../Scripts/Managers/NPCManager.cs | 2 +- .../PerfectWorld/Scripts/Managers/aabbcd.cs | 66 + .../Scripts/Managers/aabbcd.cs.meta | 2 + Assets/PerfectWorld/Scripts/NPC/CECMonster.cs | 76 +- Assets/PerfectWorld/Scripts/NPC/CECNPC.cs | 1772 ++++++------ .../Scripts/NPC/CECNPCModelDefaultPolicy.cs | 186 +- .../Scripts/Network/CSNetwork/GameSession.cs | 2 + .../Scripts/Network/EC_ManMessageMono.cs | 6 +- .../Scripts/Network/UnityGameSession.cs | 2 + .../Scripts/Players/EC_ElsePlayer.cs | 5 +- Assets/PerfectWorld/Scripts/UI/pickupItem.cs | 769 ++--- Assets/PerfectWorld/Scripts/World/CECWorld.cs | 20 +- Assets/Scripts/CECHostPlayer.cs | 2485 ++++++++--------- Assets/Scripts/CanvasController.cs | 69 +- Assets/Scripts/EC_Utility.cs | 205 +- Assets/Scripts/GameController.cs | 138 +- Assets/Scripts/InitializePlayer.cs | 17 +- Assets/Scripts/MainFiles/EC_Game.cs | 2 +- Assets/Scripts/Move/CECHostMove.cs | 676 ++--- Assets/Scripts/Move/EC_CDR.cs | 607 ++-- Assets/Scripts/Move/EC_Player.cs | 772 ++--- Assets/Scripts/PlayerState/PlayerIdleState.cs | 29 +- Assets/Scripts/PlayerState/PlayerMoveState.cs | 35 +- Assets/Scripts/PlayerState/PlayerState.cs | 17 +- Assets/Scripts/PlayerStateMachine.cs | 71 +- Assets/Scripts/PlayerVisual.cs | 63 +- Assets/Scripts/ScreenLogin.cs | 53 +- Assets/Scripts/Task/ATaskTemplMan.cs | 2 +- Assets/Scripts/Task/CECTaskInterface.cs | 3 +- Assets/Scripts/Task/TaskExpAnalyser.cs | 2 +- Assets/Scripts/Task/TaskInterface.cs | 2 +- Assets/Scripts/Task/TaskProcess.cs | 2 +- Assets/Scripts/Task/TaskTempl.cs | 2 +- Assets/Scripts/Task/TaskTest.cs | 2 +- .../Scripts/ThirdPersonController.cs | 3 +- 56 files changed, 7574 insertions(+), 7075 deletions(-) create mode 100644 Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs.meta create mode 100644 Assets/PerfectWorld/Scripts/Managers/EC_World.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/EC_World.cs.meta create mode 100644 Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs.meta create mode 100644 Assets/PerfectWorld/Scripts/Managers/aabbcd.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/aabbcd.cs.meta diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs new file mode 100644 index 0000000000..a878a682e6 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public class A3DTerrain2 +{ + +} diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs.meta b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs.meta new file mode 100644 index 0000000000..1a18d55e91 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 828eeca29c5904541bdb0f5162832508 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs b/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs index 941257fdb8..88961d9c7b 100644 --- a/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs +++ b/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs @@ -1,4 +1,5 @@ using BrewMonster; +using BrewMonster.Managers; using CSNetwork; using CSNetwork.GPDataType; using DG.Tweening; @@ -8,267 +9,270 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; -public class CECNPCMan : CECObject, IMsgHandler +namespace BrewMonster.Scripts.Player { - private Dictionary m_NPCTab = new Dictionary(512); - private Dictionary m_UkNPCTab = new Dictionary(32); - Vector3 m_vServerPos; - public int HandlerId => (int)MANAGER_INDEX.MAN_NPC; + public class CECNPCMan : CECObject, IMsgHandler + { + private Dictionary m_NPCTab = new Dictionary(512); + private Dictionary m_UkNPCTab = new Dictionary(32); + Vector3 m_vServerPos; + public int HandlerId => (int)MANAGER_INDEX.MAN_NPC; - public CECNPCMan() - { - m_vServerPos = Vector3.zero; - m_iCID = (int)Class_ID.OCID_MONSTER; - } - public bool ProcessMessage(ECMSG Msg) - { - if (Msg.iSubID == 0) + public CECNPCMan() { - switch (Msg.dwMsg) - { - case long value when value == EC_MsgDef.MSG_NM_NPCINFO: OnMsgNPCInfo(Msg); break; - case long value when value == EC_MsgDef.MSG_NM_NPCMOVE: OnMsgNPCMove(Msg); break; - case long value when value == EC_MsgDef.MSG_NM_NPCSTOPMOVE: OnMsgNPCStopMove(Msg); break; - } + m_vServerPos = Vector3.zero; + m_iCID = (int)Class_ID.OCID_MONSTER; } - return true; - } - - private bool OnMsgNPCStopMove(ECMSG msg) - { - cmd_object_stop_move pCmd = EC_Utility.ByteArrayToStructure((byte[])msg.dwParam1); - - CECNPC pNPC = SeekOutNPC(pCmd.id); - if (pNPC) - pNPC.StopMoveTo(pCmd); - - return true; - } - - private bool OnMsgNPCMove(ECMSG msg) - { - var buffer = (byte[])msg.dwParam1; - cmd_object_move pCmd = MemoryMarshal.Read(buffer); - - if (pCmd.use_time == 0) + public bool ProcessMessage(ECMSG Msg) + { + if (Msg.iSubID == 0) + { + switch (Msg.dwMsg) + { + case long value when value == EC_MsgDef.MSG_NM_NPCINFO: OnMsgNPCInfo(Msg); break; + case long value when value == EC_MsgDef.MSG_NM_NPCMOVE: OnMsgNPCMove(Msg); break; + case long value when value == EC_MsgDef.MSG_NM_NPCSTOPMOVE: OnMsgNPCStopMove(Msg); break; + } + } return true; - - CECNPC pNPC = SeekOutNPC(pCmd.id); - - - if (pNPC) - pNPC.MoveTo(pCmd); - - return true; - } - public CECNPC SeekOutNPC(int nid) - { - if (!m_NPCTab.TryGetValue(nid, out var npc)) - { - // Couldn't find this NPC, put it into unknown NPC table - m_UkNPCTab[nid] = nid; - return null; } - return npc; - } - private bool OnMsgNPCInfo(ECMSG msg) - { - switch (Convert.ToInt32(msg.dwParam2)) + private bool OnMsgNPCStopMove(ECMSG msg) { - case CommandID.NPC_INFO_LIST: - { + cmd_object_stop_move pCmd = EC_Utility.ByteArrayToStructure((byte[])msg.dwParam1); - // msg.dwParam1 chính là buffer chứa placeholder data (không có header cmd_npc_info_list) - cmd_npc_info_list pCmd = MemoryMarshal.Read( - ((byte[])msg.dwParam1).AsSpan()); + CECNPC pNPC = SeekOutNPC(pCmd.id); + if (pNPC) + pNPC.StopMoveTo(pCmd); - int offset = Marshal.OffsetOf("placeholder").ToInt32(); - byte[] buffer = (byte[])msg.dwParam1; - Span pDataBuf = buffer.AsSpan(offset); - - for (int i = 0; i < pCmd.count; i++) - { - // giống const info_npc& Info = *(const info_npc*)pDataBuf; - info_npc info = MemoryMarshal.Read(pDataBuf); - - int iSize = info_npc.HEADER_SIZE; - if ((info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0) - iSize += sizeof(uint) * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT; - if ((info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0) - iSize += sizeof(int); - if ((info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0) - { - byte len = pDataBuf[iSize]; - iSize += 1 + len; - } - if ((info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0) - { - int countEff = BinaryPrimitives.ReadInt32LittleEndian( - pDataBuf.Slice(iSize, sizeof(int))); - iSize += sizeof(int) + countEff * (sizeof(int) + 1); - } - if ((info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0) - iSize += sizeof(int); - - NPCEnter(info, false, buffer, offset); - - // dịch pDataBuf về sau (giống pDataBuf += iSize) - pDataBuf = pDataBuf.Slice(iSize); - offset += iSize; - } - break; - } - - case CommandID.NPC_ENTER_SLICE: - { - var buffer = (byte[])msg.dwParam1; - info_npc info = MemoryMarshal.Read(buffer.AsSpan(0, info_npc.HEADER_SIZE)); - NPCEnter(info, false, buffer, info_npc.HEADER_SIZE); - break; - } - - case CommandID.NPC_ENTER_WORLD: - { - var buffer = (byte[])msg.dwParam1; - info_npc info = MemoryMarshal.Read(buffer.AsSpan(0, info_npc.HEADER_SIZE)); - NPCEnter(info, true, buffer, info_npc.HEADER_SIZE); - break; - } - case CommandID.NPC_INFO_00: - { - var buffer = (byte[])msg.dwParam1; - cmd_npc_info_00 pCmd = GPDataTypeHelper.FromBytes(buffer); - //cmd_npc_info_00 pCmd = MemoryMarshal.Read(buffer.AsSpan(0, cmd_npc_info_00.)); - CECNPC pNPC = SeekOutNPC(pCmd.idNPC); - if (pNPC) - { - ROLEBASICPROP bp = pNPC.GetBasicProps(); - ROLEEXTPROP ep = pNPC.GetExtendProps(); - - bp.iCurHP = pCmd.iHP; - ep.bs.max_hp = pCmd.iMaxHP; - pNPC.SetSelectedTarget(pCmd.iTargetID); - } - break; - } - case CommandID.NPC_VISIBLE_TID_NOTIFY: - { - cmd_npc_visible_tid_notify pCmd = (cmd_npc_visible_tid_notify)msg.dwParam1; - CECNPC pNPC = SeekOutNPC(pCmd.nid); - if (pNPC) - pNPC.TransformShape(pCmd.vis_tid); - break; - } - } - return true; - } - - public bool NPCEnter(in info_npc Info, bool bBornInSight, ReadOnlySpan packet, int infoOffset) - { - var npc = GetNPC(Info.nid); - if (npc != null) - { - m_NPCTab.Remove(Info.nid); + return true; } - // Nếu id này có trong bảng unknown thì xóa nó - if (m_UkNPCTab.ContainsKey(Info.nid)) + private bool OnMsgNPCMove(ECMSG msg) { - m_UkNPCTab.Remove(Info.nid); + var buffer = (byte[])msg.dwParam1; + cmd_object_move pCmd = MemoryMarshal.Read(buffer); + + if (pCmd.use_time == 0) + return true; + + CECNPC pNPC = SeekOutNPC(pCmd.id); + + + if (pNPC) + pNPC.MoveTo(pCmd); + + return true; } - - // Tạo NPC mới - npc = CreateNPC(Info, bBornInSight, packet, infoOffset); - if(npc != null) + public CECNPC SeekOutNPC(int nid) { - npc.SetUpCECNPC(this); - } - if (object.ReferenceEquals(npc, null)) - { - BrewMonster.BMLogger.LogError($"Failed to create NPC ({Info.tid})"); - return false; - } - - // Thêm NPC vào bảng - m_NPCTab[Info.nid] = npc; - - return true; - } - // Get NPC by id and optional bornStamp - public CECNPC GetNPC(int nid, uint bornStamp = 0) - { - if (!m_NPCTab.TryGetValue(nid, out var npc)) - return null; - - return npc; - } - public CECNPC CreateNPC(info_npc Info, bool bBornInSight, ReadOnlySpan packet, int infoOffset) - { - CECNPC pNPC = null; - - int tid = Info.tid; - bool bPet = (Info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0; - - // Get data type from database - var edm = ElementDataManProvider.GetElementDataMan(); // tương đương g_pGame->GetElementDataMan() - DATA_TYPE dataType = edm.get_data_type((uint)tid, ID_SPACE.ID_SPACE_ESSENCE); - - if (dataType != DATA_TYPE.DT_NPC_ESSENCE && - dataType != DATA_TYPE.DT_MONSTER_ESSENCE && - dataType != DATA_TYPE.DT_PET_ESSENCE) - { - // Try default npc - tid = 4249; - dataType = edm.get_data_type((uint)tid, ID_SPACE.ID_SPACE_ESSENCE); - } - if (bPet) - { - //pNPC = new CECPet(this); - } - else - { - switch (dataType) + if (!m_NPCTab.TryGetValue(nid, out var npc)) { - case DATA_TYPE.DT_NPC_ESSENCE: /*pNPC = new CECNPCServer(this);*/ break; - case DATA_TYPE.DT_MONSTER_ESSENCE: - - pNPC = GameController.Instance.GetMonster(); - - break; - case DATA_TYPE.DT_PET_ESSENCE:/* pNPC = new CECPet(this);*/ break; - default: - UnityEngine.Debug.Assert(false, "Invalid DATA_TYPE in CreateNPC"); - return null; + // Couldn't find this NPC, put it into unknown NPC table + m_UkNPCTab[nid] = nid; + return null; } + + return npc; } - - // Set born stamp & born-in-sight (giữ nguyên semantics) - uint bornStamp = CECWorld.Instance.GetBornStamp(); - - if (!object.ReferenceEquals(pNPC, null)) + private bool OnMsgNPCInfo(ECMSG msg) { - pNPC.SetBornStamp(bornStamp); - pNPC.SetBornInSight(bBornInSight); + switch (Convert.ToInt32(msg.dwParam2)) + { + case CommandID.NPC_INFO_LIST: + { + + // msg.dwParam1 chính là buffer chứa placeholder data (không có header cmd_npc_info_list) + cmd_npc_info_list pCmd = MemoryMarshal.Read( + ((byte[])msg.dwParam1).AsSpan()); + + int offset = Marshal.OffsetOf("placeholder").ToInt32(); + byte[] buffer = (byte[])msg.dwParam1; + Span pDataBuf = buffer.AsSpan(offset); + + for (int i = 0; i < pCmd.count; i++) + { + // giống const info_npc& Info = *(const info_npc*)pDataBuf; + info_npc info = MemoryMarshal.Read(pDataBuf); + + int iSize = info_npc.HEADER_SIZE; + if ((info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0) + iSize += sizeof(uint) * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT; + if ((info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0) + iSize += sizeof(int); + if ((info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0) + { + byte len = pDataBuf[iSize]; + iSize += 1 + len; + } + if ((info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0) + { + int countEff = BinaryPrimitives.ReadInt32LittleEndian( + pDataBuf.Slice(iSize, sizeof(int))); + iSize += sizeof(int) + countEff * (sizeof(int) + 1); + } + if ((info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0) + iSize += sizeof(int); + + NPCEnter(info, false, buffer, offset); + + // dịch pDataBuf về sau (giống pDataBuf += iSize) + pDataBuf = pDataBuf.Slice(iSize); + offset += iSize; + } + break; + } + + case CommandID.NPC_ENTER_SLICE: + { + var buffer = (byte[])msg.dwParam1; + info_npc info = MemoryMarshal.Read(buffer.AsSpan(0, info_npc.HEADER_SIZE)); + NPCEnter(info, false, buffer, info_npc.HEADER_SIZE); + break; + } + + case CommandID.NPC_ENTER_WORLD: + { + var buffer = (byte[])msg.dwParam1; + info_npc info = MemoryMarshal.Read(buffer.AsSpan(0, info_npc.HEADER_SIZE)); + NPCEnter(info, true, buffer, info_npc.HEADER_SIZE); + break; + } + case CommandID.NPC_INFO_00: + { + var buffer = (byte[])msg.dwParam1; + cmd_npc_info_00 pCmd = GPDataTypeHelper.FromBytes(buffer); + //cmd_npc_info_00 pCmd = MemoryMarshal.Read(buffer.AsSpan(0, cmd_npc_info_00.)); + CECNPC pNPC = SeekOutNPC(pCmd.idNPC); + if (pNPC) + { + ROLEBASICPROP bp = pNPC.GetBasicProps(); + ROLEEXTPROP ep = pNPC.GetExtendProps(); + + bp.iCurHP = pCmd.iHP; + ep.bs.max_hp = pCmd.iMaxHP; + pNPC.SetSelectedTarget(pCmd.iTargetID); + } + break; + } + case CommandID.NPC_VISIBLE_TID_NOTIFY: + { + cmd_npc_visible_tid_notify pCmd = (cmd_npc_visible_tid_notify)msg.dwParam1; + CECNPC pNPC = SeekOutNPC(pCmd.nid); + if (pNPC) + pNPC.TransformShape(pCmd.vis_tid); + break; + } + } + return true; } - else + + public bool NPCEnter(in info_npc Info, bool bBornInSight, ReadOnlySpan packet, int infoOffset) { - return null; - } + var npc = GetNPC(Info.nid); + if (npc != null) + { + m_NPCTab.Remove(Info.nid); + } - // Init với tid + Info như C++ - if (!pNPC.Init(tid, Info, packet, infoOffset)) + // Nếu id này có trong bảng unknown thì xóa nó + if (m_UkNPCTab.ContainsKey(Info.nid)) + { + m_UkNPCTab.Remove(Info.nid); + } + + // Tạo NPC mới + npc = CreateNPC(Info, bBornInSight, packet, infoOffset); + if (npc != null) + { + npc.SetUpCECNPC(this); + } + if (object.ReferenceEquals(npc, null)) + { + BrewMonster.BMLogger.LogError($"Failed to create NPC ({Info.tid})"); + return false; + } + + // Thêm NPC vào bảng + m_NPCTab[Info.nid] = npc; + + return true; + } + // Get NPC by id and optional bornStamp + public CECNPC GetNPC(int nid, uint bornStamp = 0) { + if (!m_NPCTab.TryGetValue(nid, out var npc)) + return null; - // đảm bảo giải phóng nếu bạn có tài nguyên kèm theo - //pNPC?.Release(); - pNPC = null; - - // log lỗi tương tự glb_ErrorOutput - UnityEngine.Debug.LogError($"CECNPCMan::CreateNPC failed, tid={tid}"); - return null; + return npc; } + public CECNPC CreateNPC(info_npc Info, bool bBornInSight, ReadOnlySpan packet, int infoOffset) + { + CECNPC pNPC = null; - return pNPC; + int tid = Info.tid; + bool bPet = (Info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0; + + // Get data type from database + var edm = ElementDataManProvider.GetElementDataMan(); // tương đương g_pGame->GetElementDataMan() + DATA_TYPE dataType = edm.get_data_type((uint)tid, ID_SPACE.ID_SPACE_ESSENCE); + + if (dataType != DATA_TYPE.DT_NPC_ESSENCE && + dataType != DATA_TYPE.DT_MONSTER_ESSENCE && + dataType != DATA_TYPE.DT_PET_ESSENCE) + { + // Try default npc + tid = 4249; + dataType = edm.get_data_type((uint)tid, ID_SPACE.ID_SPACE_ESSENCE); + } + if (bPet) + { + //pNPC = new CECPet(this); + } + else + { + switch (dataType) + { + case DATA_TYPE.DT_NPC_ESSENCE: /*pNPC = new CECNPCServer(this);*/ break; + case DATA_TYPE.DT_MONSTER_ESSENCE: + + pNPC = GameController.Instance.GetMonster(); + + break; + case DATA_TYPE.DT_PET_ESSENCE:/* pNPC = new CECPet(this);*/ break; + default: + UnityEngine.Debug.Assert(false, "Invalid DATA_TYPE in CreateNPC"); + return null; + } + } + + // Set born stamp & born-in-sight (giữ nguyên semantics) + uint bornStamp = CECWorld.Instance.GetBornStamp(); + + if (!object.ReferenceEquals(pNPC, null)) + { + pNPC.SetBornStamp(bornStamp); + pNPC.SetBornInSight(bBornInSight); + } + else + { + return null; + } + + // Init với tid + Info như C++ + if (!pNPC.Init(tid, Info, packet, infoOffset)) + { + + // đảm bảo giải phóng nếu bạn có tài nguyên kèm theo + //pNPC?.Release(); + pNPC = null; + + // log lỗi tương tự glb_ErrorOutput + UnityEngine.Debug.LogError($"CECNPCMan::CreateNPC failed, tid={tid}"); + return null; + } + + return pNPC; + } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs index 14f1895208..f8531917e2 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs @@ -1,100 +1,101 @@ +using BrewMonster.Scripts.Player; using System.Collections.Generic; -using System.Security.Cryptography; -using Unity.VisualScripting; -using WorkList = System.Collections.Generic.List; -public class CECHPWork : CECObjectWork +namespace BrewMonster.Scripts { - // Host work ID - public static class Host_work_ID + using WorkList = System.Collections.Generic.List; + public class CECHPWork : CECObjectWork { - public const int WORK_INVALID = -1, - WORK_STAND = 0, // Stand and do nothing - WORK_MOVETOPOS = 1, // Move to a destination terrain position - WORK_TRACEOBJECT = 2, // Trace specified object (NPC, player etc.) - WORK_HACKOBJECT = 3, // Hack specified object (NPC, player etc.) - WORK_SPELLOBJECT = 4, // Spell magic on specified object (NPC, player etc.) - WORK_USEITEM = 5, // Host use item - WORK_DEAD = 6, // Host is dead - WORK_FOLLOW = 7, // Follow some one else - WORK_FLYOFF = 8, // Fly off - WORK_FREEFALL = 9, // Free fall - WORK_SIT = 10, // Sit - WORK_PICKUP = 11, // Pickup item - WORK_CONCENTRATE = 12, // All concentrate work - WORK_REVIVE = 13, // Revive - WORK_FLASHMOVE = 14, // Flash move - WORK_BEBOUND = 15, // Be bound by buddy - WORK_PASSIVEMOVE = 16, // Passive movement (knock back / pull) - WORK_CONGREGATE = 17, // Congregate reply - WORK_SKILLSTATEACT = 18, // skill buff action - WORK_FORCENAVIGATEMOVE = 19, // force navigate move - NUM_WORK = 20; - } - - protected static class Work_mask - { - public const uint MASK_STAND = 0x0001, - MASK_MOVETOPOS = 0x0002, - MASK_TRACEOBJECT = 0x0004, - MASK_HACKOBJECT = 0x0008, - MASK_SPELLOBJECT = 0x0010, - MASK_USEITEM = 0x0020, - MASK_DEAD = 0x0040, - MASK_FOLLOW = 0x0080, - MASK_FLYOFF = 0x0100, - MASK_FREEFALL = 0x0200, - MASK_SIT = 0x0400, - MASK_PICKUP = 0x0800, - MASK_CONCENTRATE = 0x1000, - MASK_REVIVE = 0x2000, - MASK_FLASHMOVE = 0x4000, - MASK_BEBOUND = 0x8000, - MASK_CONGREGATE = 0x10000, - MASK_SKILLSTATEACT = 0x20000, - MASK_FORCENAVIGATE = 0x40000; - public const uint MASK_ALLWORK = 0xffffffff; - } - - protected CECHPWorkMan m_pWorkMan; // Work manager - protected CECHostPlayer m_pHost; // Host player object - - public CECHPWork(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID) - { - m_pWorkMan = pWorkMan; - m_pHost = pWorkMan.GetHostPlayer(); - } - - // Operations - // Override from CECObjectWork - public virtual void Cancel() - { - - } - // This work is do player moving ? - public virtual bool IsMoving() - { - return false; - } - // Copy work data - public virtual bool CopyData(CECHPWork pWork) - { - m_bFinished = pWork.m_bFinished; - m_bFirstTick = pWork.m_bFirstTick; - return true; - } - - public string GetWorkName() - { - return GetWorkName(GetWorkID()); - } - public static uint GetWorkMask(int iWorkID) - { - if (!Validate(iWorkID)) + // Host work ID + public static class Host_work_ID { - return 0; + public const int WORK_INVALID = -1, + WORK_STAND = 0, // Stand and do nothing + WORK_MOVETOPOS = 1, // Move to a destination terrain position + WORK_TRACEOBJECT = 2, // Trace specified object (NPC, player etc.) + WORK_HACKOBJECT = 3, // Hack specified object (NPC, player etc.) + WORK_SPELLOBJECT = 4, // Spell magic on specified object (NPC, player etc.) + WORK_USEITEM = 5, // Host use item + WORK_DEAD = 6, // Host is dead + WORK_FOLLOW = 7, // Follow some one else + WORK_FLYOFF = 8, // Fly off + WORK_FREEFALL = 9, // Free fall + WORK_SIT = 10, // Sit + WORK_PICKUP = 11, // Pickup item + WORK_CONCENTRATE = 12, // All concentrate work + WORK_REVIVE = 13, // Revive + WORK_FLASHMOVE = 14, // Flash move + WORK_BEBOUND = 15, // Be bound by buddy + WORK_PASSIVEMOVE = 16, // Passive movement (knock back / pull) + WORK_CONGREGATE = 17, // Congregate reply + WORK_SKILLSTATEACT = 18, // skill buff action + WORK_FORCENAVIGATEMOVE = 19, // force navigate move + NUM_WORK = 20; } - uint[] l_workMask = new uint[]{ + + protected static class Work_mask + { + public const uint MASK_STAND = 0x0001, + MASK_MOVETOPOS = 0x0002, + MASK_TRACEOBJECT = 0x0004, + MASK_HACKOBJECT = 0x0008, + MASK_SPELLOBJECT = 0x0010, + MASK_USEITEM = 0x0020, + MASK_DEAD = 0x0040, + MASK_FOLLOW = 0x0080, + MASK_FLYOFF = 0x0100, + MASK_FREEFALL = 0x0200, + MASK_SIT = 0x0400, + MASK_PICKUP = 0x0800, + MASK_CONCENTRATE = 0x1000, + MASK_REVIVE = 0x2000, + MASK_FLASHMOVE = 0x4000, + MASK_BEBOUND = 0x8000, + MASK_CONGREGATE = 0x10000, + MASK_SKILLSTATEACT = 0x20000, + MASK_FORCENAVIGATE = 0x40000; + public const uint MASK_ALLWORK = 0xffffffff; + } + + protected CECHPWorkMan m_pWorkMan; // Work manager + protected CECHostPlayer m_pHost; // Host player object + + public CECHPWork(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID) + { + m_pWorkMan = pWorkMan; + m_pHost = pWorkMan.GetHostPlayer(); + } + + // Operations + // Override from CECObjectWork + public override void Cancel() + { + + } + // This work is do player moving ? + public virtual bool IsMoving() + { + return false; + } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + m_bFinished = pWork.m_bFinished; + m_bFirstTick = pWork.m_bFirstTick; + return true; + } + + public string GetWorkName() + { + return GetWorkName(GetWorkID()); + } + public static uint GetWorkMask(int iWorkID) + { + if (!Validate(iWorkID)) + { + return 0; + } + uint[] l_workMask = new uint[]{ Work_mask.MASK_STAND, Work_mask.MASK_MOVETOPOS, Work_mask.MASK_TRACEOBJECT, @@ -115,17 +116,17 @@ public class CECHPWork : CECObjectWork Work_mask.MASK_SKILLSTATEACT, Work_mask.MASK_FORCENAVIGATE, }; - return l_workMask[iWorkID]; - } - public static bool Validate(int iWorkID) - { - return iWorkID >= 0 && iWorkID < Host_work_ID.NUM_WORK; - } - - public static string GetWorkName(int iWorkID) - { - string[] l_WorkName = new string[Host_work_ID.NUM_WORK] + return l_workMask[iWorkID]; + } + public static bool Validate(int iWorkID) { + return iWorkID >= 0 && iWorkID < Host_work_ID.NUM_WORK; + } + + public static string GetWorkName(int iWorkID) + { + string[] l_WorkName = new string[Host_work_ID.NUM_WORK] + { "WORK_STAND", "WORK_MOVETOPOS", "WORK_TRACEOBJECT", @@ -146,538 +147,539 @@ public class CECHPWork : CECObjectWork "WORK_CONGREGATE", "WORK_SKILLSTATEACT", "WORK_FORCENAVIGATEMOVE" - }; - if (Validate(iWorkID)) - { - return l_WorkName[iWorkID]; - } - else if (iWorkID == Host_work_ID.WORK_INVALID) - { - return "WORK_INVALID"; - } - else - { - return "Unknown"; - } - } -} - -/////////////////////////////////////////////////////////////////////////// -// -// Class CECHPWorkMan -// -/////////////////////////////////////////////////////////////////////////// -public class CECHPWorkMan -{ - // Work priority - public static class Work_priority - { - public const int PRIORITY_0 = 0, - PRIORITY_1 = 1, - PRIORITY_2 = 2, - NUM_PRIORITY = 3; - }; - - // Delayed work info. - public struct DELAYWORK - { - public int iPriority; - public CECHPWork pWork; - } - - private CECHostPlayer m_pHost; - private WorkList[] m_WorkStack = new WorkList[Work_priority.NUM_PRIORITY] { new List(), new List(), new List() }; - private int m_iCurPriority; - private DELAYWORK m_Delayed; - private CECHPWorkPostTickCommand m_pPostTickCommand; - - public CECHPWorkMan(CECHostPlayer pHost) - { - m_pHost = pHost; - m_iCurPriority = -1; - m_Delayed = new DELAYWORK - { - iPriority = 0, - pWork = null - }; - m_pPostTickCommand = null; - } - - public CECHPWork GetRunningWork(int iWorkID) - { - CECHPWork result = null; - if (ValidatePriority(m_iCurPriority)) - { - WorkList workList = m_WorkStack[m_iCurPriority]; - for (int i = 0; i < workList.Count; ++i) + }; + if (Validate(iWorkID)) { - if (iWorkID == workList[i].GetWorkID()) - { - result = workList[i]; - break; - } + return l_WorkName[iWorkID]; + } + else if (iWorkID == Host_work_ID.WORK_INVALID) + { + return "WORK_INVALID"; + } + else + { + return "Unknown"; } } - return result; } - public CECHPWork GetWork(int iWorkID, int iPriority = Work_priority.PRIORITY_1, bool bIncludeDelayedWork = false) + + /////////////////////////////////////////////////////////////////////////// + // + // Class CECHPWorkMan + // + /////////////////////////////////////////////////////////////////////////// + public class CECHPWorkMan { - CECHPWorkGeneralMatcher cECHPWork = new CECHPWorkGeneralMatcher(iWorkID, iPriority, bIncludeDelayedWork); - return GetWork(cECHPWork); - } - public CECHPWork GetWork(CECHPWorkMatcher matcher) - { - CECHPWork result = null; - for (int i = (Work_priority.NUM_PRIORITY - 1); i >= 0; --i) + // Work priority + public static class Work_priority { - WorkList workList = m_WorkStack[i]; - if (workList != null) + public const int PRIORITY_0 = 0, + PRIORITY_1 = 1, + PRIORITY_2 = 2, + NUM_PRIORITY = 3; + }; + + // Delayed work info. + public struct DELAYWORK + { + public int iPriority; + public CECHPWork pWork; + } + + private CECHostPlayer m_pHost; + private WorkList[] m_WorkStack = new WorkList[Work_priority.NUM_PRIORITY] { new List(), new List(), new List() }; + private int m_iCurPriority; + private DELAYWORK m_Delayed; + private CECHPWorkPostTickCommand m_pPostTickCommand; + + public CECHPWorkMan(CECHostPlayer pHost) + { + m_pHost = pHost; + m_iCurPriority = -1; + m_Delayed = new DELAYWORK { - for (int j = 0; j < workList.Count; ++j) + iPriority = 0, + pWork = null + }; + m_pPostTickCommand = null; + } + + public CECHPWork GetRunningWork(int iWorkID) + { + CECHPWork result = null; + if (ValidatePriority(m_iCurPriority)) + { + WorkList workList = m_WorkStack[m_iCurPriority]; + for (int i = 0; i < workList.Count; ++i) { - CECHPWork pWork = workList[j]; - if (matcher.Match(pWork, i, false)) + if (iWorkID == workList[i].GetWorkID()) { - result = pWork; + result = workList[i]; break; } } } + return result; } - if (result == null && GetDelayedWork() != null && matcher.Match(m_Delayed.pWork, m_Delayed.iPriority, true)) + public CECHPWork GetWork(int iWorkID, int iPriority = Work_priority.PRIORITY_1, bool bIncludeDelayedWork = false) { - result = GetDelayedWork(); + CECHPWorkGeneralMatcher cECHPWork = new CECHPWorkGeneralMatcher(iWorkID, iPriority, bIncludeDelayedWork); + return GetWork(cECHPWork); } - return result; - } - - bool InternallyStartWork(int iPriority, CECHPWork pWork) - { - bool bStarted = false; - if (CanRunSimultaneouslyWithCurrentWork(iPriority, pWork)) + public CECHPWork GetWork(CECHPWorkMatcher matcher) { - WorkList workList = m_WorkStack[iPriority]; - workList.Add(pWork); - bStarted = true; - //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started simultaneously, priority=%d", pWork->GetWorkName(), iPriority)); - } - else - { - if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_DEAD) + CECHPWork result = null; + for (int i = (Work_priority.NUM_PRIORITY - 1); i >= 0; --i) { - for (int i = iPriority; i < Work_priority.NUM_PRIORITY; i++) + WorkList workList = m_WorkStack[i]; + if (workList != null) { - FinishWorkAtPriority(i); + for (int j = 0; j < workList.Count; ++j) + { + CECHPWork pWork = workList[j]; + if (matcher.Match(pWork, i, false)) + { + result = pWork; + break; + } + } } - ClearDelayedWork(); + } + if (result == null && GetDelayedWork() != null && matcher.Match(m_Delayed.pWork, m_Delayed.iPriority, true)) + { + result = GetDelayedWork(); + } + return result; + } + + bool InternallyStartWork(int iPriority, CECHPWork pWork) + { + bool bStarted = false; + if (CanRunSimultaneouslyWithCurrentWork(iPriority, pWork)) + { WorkList workList = m_WorkStack[iPriority]; workList.Add(pWork); - m_iCurPriority = iPriority; bStarted = true; + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started simultaneously, priority=%d", pWork->GetWorkName(), iPriority)); } else { - bool shouldStart = (iPriority >= m_iCurPriority); - FinishWorkAtPriority(iPriority); - WorkList workList = m_WorkStack[iPriority]; - workList.Add(pWork); - if (shouldStart) + if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_DEAD) { - if (iPriority > m_iCurPriority) + for (int i = iPriority; i < Work_priority.NUM_PRIORITY; i++) { - CancelWorkAtPriority(m_iCurPriority); + FinishWorkAtPriority(i); } + ClearDelayedWork(); + WorkList workList = m_WorkStack[iPriority]; + workList.Add(pWork); m_iCurPriority = iPriority; bStarted = true; } + else + { + bool shouldStart = (iPriority >= m_iCurPriority); + FinishWorkAtPriority(iPriority); + WorkList workList = m_WorkStack[iPriority]; + workList.Add(pWork); + if (shouldStart) + { + if (iPriority > m_iCurPriority) + { + CancelWorkAtPriority(m_iCurPriority); + } + m_iCurPriority = iPriority; + bStarted = true; + } + } + //if (bStarted) + //{ + // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started, priority=%d", pWork->GetWorkName(), iPriority)); + //} + //else + //{ + // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s add to priority queue %d", pWork->GetWorkName(), iPriority)); + //} } - //if (bStarted) - //{ - // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started, priority=%d", pWork->GetWorkName(), iPriority)); - //} - //else - //{ - // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s add to priority queue %d", pWork->GetWorkName(), iPriority)); - //} + return bStarted; } - return bStarted; - } - bool CanRunSimultaneouslyWithCurrentWork(int iPriority, CECHPWork pWork) - { - if (!ValidatePriority(iPriority) || iPriority != m_iCurPriority) + bool CanRunSimultaneouslyWithCurrentWork(int iPriority, CECHPWork pWork) { - return false; - } - WorkList workList = m_WorkStack[iPriority]; - if (workList == null || workList.Count == 0) - { - return false; - } - - foreach (var work in workList) - { - if (!CanRunSimultaneously(work, pWork)) + if (!ValidatePriority(iPriority) || iPriority != m_iCurPriority) { return false; } - } - return true; - } - bool CanRunSimultaneously(CECHPWork pWork1, CECHPWork pWork2) - { - if (pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && - pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) - { - return CanSpellWhileMoving(pWork2 as CECHPWorkSpell); - } - if (pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && - pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) - { - return CanSpellWhileMoving(pWork1 as CECHPWorkSpell); - } - return false; - } - bool CanSpellWhileMoving(CECHPWorkSpell pWorkSpell) - { - //return pWorkSpell.GetSkill() - // && CECCastSkillWhenMove::Instance().IsSkillSupported(pWorkSpell->GetSkill()->GetSkillID(), m_pHost); - return false; - } - void StartAwaitingWorks() - { - if (ValidatePriority(m_iCurPriority)) - { - for (--m_iCurPriority; m_iCurPriority >= 0; --m_iCurPriority) + WorkList workList = m_WorkStack[iPriority]; + if (workList == null || workList.Count == 0) { - WorkList workList = m_WorkStack[m_iCurPriority]; - if (workList == null || workList.Count == 0) - { - continue; - } - foreach (var work in workList) - { - work.OnWorkShift(); - //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started by decrease priority, priority=%d", workList[j]->GetWorkName(), m_iCurPriority)); - } - break; + return false; } - } - StartDelayedWork(); - } - void FinishWorkAtPriority(int iPriority) - { - if (!ValidatePriority(iPriority)) - { - return; - } - WorkList workList = m_WorkStack[iPriority]; - while ((workList != null && workList.Count > 0)) - { - KillWork(iPriority, 0); - } - if (m_iCurPriority == iPriority) - { - m_iCurPriority = -1; - } - } - - void KillWork(int iPriority, int index) - { - if (!ValidatePriority(iPriority)) - { - return; - } - WorkList workList = m_WorkStack[iPriority]; - if (index < 0 || index >= workList.Count) - { - return; - } - CECHPWork pWork = workList[index]; - KillWork(pWork); - //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s priority=%d killed", pWork->GetWorkName(), iPriority)); - //delete pWork; - workList.RemoveAt(index); - } - void KillWork(CECHPWork pWork) - { - if (pWork == null) - { - return; - } - if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS) - { - CECHPWorkMove pWorkMove = pWork as CECHPWorkMove; - if (pWorkMove != null) + foreach (var work in workList) { - if (pWorkMove.GetAutoMove()) - { - //pWorkMove.Finish(); - } - else - { - pWorkMove.Cancel(); - } - } - } - else - { - pWork.Cancel(); - } - } - - public void CancelWork(CECHPWork pWork) - { - - } - public void CancelWorkAtPriority(int iPriority) - { - - } - - public bool DelayWork(int iPriority, CECHPWork pWork) - { - return false; - } - public void StartDelayedWork() - { - - } - public void ClearDelayedWork() - { - - } - public CECHPWork GetDelayedWork() - { - return m_Delayed.pWork; - } - - public bool ValidatePriority(int iPriority) - { - return iPriority >= 0 && iPriority < Work_priority.NUM_PRIORITY; - } - - public bool StartWork(int iPriority, CECHPWork pWork, bool bNoDelay = false) - { - if (pWork == null) - { - return false; - } - if (!ValidatePriority(iPriority)) - { - return false; - } - //if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_TRACEOBJECT) - //{ - // if (g_pGame->GetGameRun()->GetHostInputFilter()->IsMoveUsagePressed()) - // { - // CECHPWorkTrace pWorkTrace = pWork as CECHPWorkTrace; - // if (!pWorkTrace.CanTouch()) - // { // 2014-8-16 ̲ͨƶʱ CECHPWorkTrace, - // //delete pWorkTrace; // CECHPWorkTrace ʱתĿλáֱ̲ݵƶ·˲䶶 - // return false; // CECHPWorkTrace ĿӴʱ CECHPWorkTraceʵּ̿ƶСijӦüʱתʩż - // } - // } - //} - if (!bNoDelay && DelayWork(iPriority, pWork)) - { - return true; - } - return InternallyStartWork(iPriority, pWork); - } - public bool StartWork_p0(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_0, pWork, bNoDelay); } - public bool StartWork_p1(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_1, pWork, bNoDelay); } - public bool StartWork_p2(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_2, pWork, bNoDelay); } - public CECHostPlayer GetHostPlayer() { return m_pHost; } - - public CECHPWork CreateWork(int idWork) - { - CECHPWork pWork = null; - - switch (idWork) - { - //case CECHPWork.Host_work_ID.WORK_STAND: pWork = new CECHPWorkStand(this); break; - case CECHPWork.Host_work_ID.WORK_MOVETOPOS: pWork = new CECHPWorkMove(this); break; - 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_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; - //case CECHPWork.Host_work_ID.WORK_FREEFALL: pWork = new CECHPWorkFall(this); break; - //case CECHPWork.Host_work_ID.WORK_SIT: pWork = new CECHPWorkSit(this); break; - //case CECHPWork.Host_work_ID.WORK_PICKUP: pWork = new CECHPWorkPick(this); break; - //case CECHPWork.Host_work_ID.WORK_CONCENTRATE: pWork = new CECHPWorkConcentrate(this); break; - //case CECHPWork.Host_work_ID.WORK_REVIVE: pWork = new CECHPWorkRevive(this); break; - //case CECHPWork.Host_work_ID.WORK_FLASHMOVE: pWork = new CECHPWorkFMove(this); break; - //case CECHPWork.Host_work_ID.WORK_BEBOUND: pWork = new CECHPWorkBeBound(this); break; - //case CECHPWork.Host_work_ID.WORK_PASSIVEMOVE: pWork = new CECHPWorkPassiveMove(this); break; - //case CECHPWork.Host_work_ID.WORK_CONGREGATE: pWork = new CECHPWorkCongregate(this); break; - //case CECHPWork.Host_work_ID.WORK_SKILLSTATEACT: pWork = new CECHPWorkSkillStateAction(this); break; - //case CECHPWork.Host_work_ID.WORK_FORCENAVIGATEMOVE: pWork = new CECHPWorkNavigate(this); break; - default: - return null; - } - - return pWork; - } - - public bool CanStartWork(int iWorkID, int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1) - { - if (!ValidatePriority(iPriority)) - { - return false; - } - if (GetWork(iWorkID) != null) - { - return false; - } - if (!HasWorkOnPriority(iPriority)) - { - return true; - } - WorkList workList = m_WorkStack[iPriority]; - if (workList != null) - { - for (int i = 0; i < workList.Count; ++i) - { - if (!workList[i].CanTransferTo(CECHPWork.GetWorkMask(iWorkID))) + if (!CanRunSimultaneously(work, pWork)) { return false; } } + return true; } - return true; - } - - bool HasWorkOnPriority(int iPriority) - { - return ValidatePriority(iPriority) && m_WorkStack[iPriority] != null && m_WorkStack[iPriority].Count != 0; - } - - public void SetPostTickCommand(CECHPWorkPostTickCommand command) - { - m_pPostTickCommand = command; - } - - public bool HasWorkRunningOnPriority(int iPriority) - { - return HasWorkOnPriority(iPriority); - } - bool IsAnyWorkRunning() - { - return HasWorkRunningOnPriority(m_iCurPriority); - } - - public void Tick(float dwDeltaTime) - { - if (!IsAnyWorkRunning()) + bool CanRunSimultaneously(CECHPWork pWork1, CECHPWork pWork2) { - return; - } - WorkList workList = m_WorkStack[m_iCurPriority]; - for (int i = 0; i < workList.Count;) - { - CECHPWork pWork = workList[i]; - - SetPostTickCommand(null); - pWork.Tick(dwDeltaTime); - - if (m_pPostTickCommand == null) + if (pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && + pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) { - if (!pWork.IsFinished()) + return CanSpellWhileMoving(pWork2 as CECHPWorkSpell); + } + if (pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && + pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) + { + return CanSpellWhileMoving(pWork1 as CECHPWorkSpell); + } + return false; + } + bool CanSpellWhileMoving(CECHPWorkSpell pWorkSpell) + { + //return pWorkSpell.GetSkill() + // && CECCastSkillWhenMove::Instance().IsSkillSupported(pWorkSpell->GetSkill()->GetSkillID(), m_pHost); + return false; + } + void StartAwaitingWorks() + { + if (ValidatePriority(m_iCurPriority)) + { + for (--m_iCurPriority; m_iCurPriority >= 0; --m_iCurPriority) { - ++i; - continue; + WorkList workList = m_WorkStack[m_iCurPriority]; + if (workList == null || workList.Count == 0) + { + continue; + } + foreach (var work in workList) + { + work.OnWorkShift(); + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started by decrease priority, priority=%d", workList[j]->GetWorkName(), m_iCurPriority)); + } + break; + } + } + StartDelayedWork(); + } + + void FinishWorkAtPriority(int iPriority) + { + if (!ValidatePriority(iPriority)) + { + return; + } + WorkList workList = m_WorkStack[iPriority]; + while ((workList != null && workList.Count > 0)) + { + KillWork(iPriority, 0); + } + if (m_iCurPriority == iPriority) + { + m_iCurPriority = -1; + } + } + + void KillWork(int iPriority, int index) + { + if (!ValidatePriority(iPriority)) + { + return; + } + WorkList workList = m_WorkStack[iPriority]; + if (index < 0 || index >= workList.Count) + { + return; + } + CECHPWork pWork = workList[index]; + KillWork(pWork); + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s priority=%d killed", pWork->GetWorkName(), iPriority)); + //delete pWork; + workList.RemoveAt(index); + } + void KillWork(CECHPWork pWork) + { + if (pWork == null) + { + return; + } + if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS) + { + CECHPWorkMove pWorkMove = pWork as CECHPWorkMove; + if (pWorkMove != null) + { + if (pWorkMove.GetAutoMove()) + { + //pWorkMove.Finish(); + } + else + { + pWorkMove.Cancel(); + } } - KillWork(m_iCurPriority, i); } else { - m_pPostTickCommand.Run(this); - SetPostTickCommand(null); - break; // ȷ m_pPostTickCommand ִʲôݣ˴ + pWork.Cancel(); } } - if (workList.Count == 0) + + public void CancelWork(CECHPWork pWork) { - StartAwaitingWorks(); + } - } -} + public void CancelWorkAtPriority(int iPriority) + { -public abstract class CECHPWorkPostTickCommand -{ - public abstract bool Run(CECHPWorkMan pWorkMan); -}; + } -public abstract class CECHPWorkMatcher -{ - public abstract bool Match(CECHPWork pWork, int priority, bool isDelayWork); -}; - -public class CECHPWorkGeneralMatcher : CECHPWorkMatcher -{ - int m_workID; - int m_priority; - bool m_matchDelayedWork; - - public override bool Match(CECHPWork pWork, int priority, bool isDelayWork) - { - return pWork != null - && pWork.GetWorkID() == m_workID - && priority == m_priority - && isDelayWork == m_matchDelayedWork; - } - - public CECHPWorkGeneralMatcher(int workID, int priority, bool bIncludeDelayedWork) - { - m_workID = workID; - m_priority = priority; - m_matchDelayedWork = bIncludeDelayedWork; - } -} - -public class CECHPWorkPostTickRunWorkCommand : CECHPWorkPostTickCommand -{ - CECHPWork m_pWork; - int m_iPriority; - bool m_bNoDelay; - bool m_bShouldTick; - uint m_dwTickTime; - - // Constructor - public CECHPWorkPostTickRunWorkCommand( - CECHPWork pWork, - bool bNoDelay = false, - int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1, - bool bShouldTick = false, - uint dwTickTime = 0) - { - m_pWork = pWork; - m_bNoDelay = bNoDelay; - m_iPriority = iPriority; - m_bShouldTick = bShouldTick; - m_dwTickTime = dwTickTime; - } - - public override bool Run(CECHPWorkMan pWorkMan) - { - if (m_pWork == null || pWorkMan == null) + public bool DelayWork(int iPriority, CECHPWork pWork) { return false; } - if (!pWorkMan.StartWork(m_iPriority, m_pWork, m_bNoDelay)) + public void StartDelayedWork() { + + } + public void ClearDelayedWork() + { + + } + public CECHPWork GetDelayedWork() + { + return m_Delayed.pWork; + } + + public bool ValidatePriority(int iPriority) + { + return iPriority >= 0 && iPriority < Work_priority.NUM_PRIORITY; + } + + public bool StartWork(int iPriority, CECHPWork pWork, bool bNoDelay = false) + { + if (pWork == null) + { + return false; + } + if (!ValidatePriority(iPriority)) + { + return false; + } + //if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_TRACEOBJECT) + //{ + // if (g_pGame->GetGameRun()->GetHostInputFilter()->IsMoveUsagePressed()) + // { + // CECHPWorkTrace pWorkTrace = pWork as CECHPWorkTrace; + // if (!pWorkTrace.CanTouch()) + // { // 2014-8-16 ̲ͨƶʱ CECHPWorkTrace, + // //delete pWorkTrace; // CECHPWorkTrace ʱתĿλáֱ̲ݵƶ·˲䶶 + // return false; // CECHPWorkTrace ĿӴʱ CECHPWorkTraceʵּ̿ƶСijӦüʱתʩż + // } + // } + //} + if (!bNoDelay && DelayWork(iPriority, pWork)) + { + return true; + } + return InternallyStartWork(iPriority, pWork); + } + public bool StartWork_p0(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_0, pWork, bNoDelay); } + public bool StartWork_p1(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_1, pWork, bNoDelay); } + public bool StartWork_p2(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_2, pWork, bNoDelay); } + public CECHostPlayer GetHostPlayer() { return m_pHost; } + + public CECHPWork CreateWork(int idWork) + { + CECHPWork pWork = null; + + switch (idWork) + { + //case CECHPWork.Host_work_ID.WORK_STAND: pWork = new CECHPWorkStand(this); break; + case CECHPWork.Host_work_ID.WORK_MOVETOPOS: pWork = new CECHPWorkMove(this); break; + 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_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; + //case CECHPWork.Host_work_ID.WORK_FREEFALL: pWork = new CECHPWorkFall(this); break; + //case CECHPWork.Host_work_ID.WORK_SIT: pWork = new CECHPWorkSit(this); break; + //case CECHPWork.Host_work_ID.WORK_PICKUP: pWork = new CECHPWorkPick(this); break; + //case CECHPWork.Host_work_ID.WORK_CONCENTRATE: pWork = new CECHPWorkConcentrate(this); break; + //case CECHPWork.Host_work_ID.WORK_REVIVE: pWork = new CECHPWorkRevive(this); break; + //case CECHPWork.Host_work_ID.WORK_FLASHMOVE: pWork = new CECHPWorkFMove(this); break; + //case CECHPWork.Host_work_ID.WORK_BEBOUND: pWork = new CECHPWorkBeBound(this); break; + //case CECHPWork.Host_work_ID.WORK_PASSIVEMOVE: pWork = new CECHPWorkPassiveMove(this); break; + //case CECHPWork.Host_work_ID.WORK_CONGREGATE: pWork = new CECHPWorkCongregate(this); break; + //case CECHPWork.Host_work_ID.WORK_SKILLSTATEACT: pWork = new CECHPWorkSkillStateAction(this); break; + //case CECHPWork.Host_work_ID.WORK_FORCENAVIGATEMOVE: pWork = new CECHPWorkNavigate(this); break; + default: + return null; + } + + return pWork; + } + + public bool CanStartWork(int iWorkID, int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1) + { + if (!ValidatePriority(iPriority)) + { + return false; + } + if (GetWork(iWorkID) != null) + { + return false; + } + if (!HasWorkOnPriority(iPriority)) + { + return true; + } + WorkList workList = m_WorkStack[iPriority]; + if (workList != null) + { + for (int i = 0; i < workList.Count; ++i) + { + if (!workList[i].CanTransferTo(CECHPWork.GetWorkMask(iWorkID))) + { + return false; + } + } + } + return true; + } + + bool HasWorkOnPriority(int iPriority) + { + return ValidatePriority(iPriority) && m_WorkStack[iPriority] != null && m_WorkStack[iPriority].Count != 0; + } + + public void SetPostTickCommand(CECHPWorkPostTickCommand command) + { + m_pPostTickCommand = command; + } + + public bool HasWorkRunningOnPriority(int iPriority) + { + return HasWorkOnPriority(iPriority); + } + bool IsAnyWorkRunning() + { + return HasWorkRunningOnPriority(m_iCurPriority); + } + + public void Tick(float dwDeltaTime) + { + if (!IsAnyWorkRunning()) + { + return; + } + WorkList workList = m_WorkStack[m_iCurPriority]; + for (int i = 0; i < workList.Count;) + { + CECHPWork pWork = workList[i]; + + SetPostTickCommand(null); + pWork.Tick(dwDeltaTime); + + if (m_pPostTickCommand == null) + { + if (!pWork.IsFinished()) + { + ++i; + continue; + } + KillWork(m_iCurPriority, i); + } + else + { + m_pPostTickCommand.Run(this); + SetPostTickCommand(null); + break; // ȷ m_pPostTickCommand ִʲôݣ˴ + } + } + if (workList.Count == 0) + { + StartAwaitingWorks(); + } + } + } + + public abstract class CECHPWorkPostTickCommand + { + public abstract bool Run(CECHPWorkMan pWorkMan); + }; + + public abstract class CECHPWorkMatcher + { + public abstract bool Match(CECHPWork pWork, int priority, bool isDelayWork); + }; + + public class CECHPWorkGeneralMatcher : CECHPWorkMatcher + { + int m_workID; + int m_priority; + bool m_matchDelayedWork; + + public override bool Match(CECHPWork pWork, int priority, bool isDelayWork) + { + return pWork != null + && pWork.GetWorkID() == m_workID + && priority == m_priority + && isDelayWork == m_matchDelayedWork; + } + + public CECHPWorkGeneralMatcher(int workID, int priority, bool bIncludeDelayedWork) + { + m_workID = workID; + m_priority = priority; + m_matchDelayedWork = bIncludeDelayedWork; + } + } + + public class CECHPWorkPostTickRunWorkCommand : CECHPWorkPostTickCommand + { + CECHPWork m_pWork; + int m_iPriority; + bool m_bNoDelay; + bool m_bShouldTick; + uint m_dwTickTime; + + // Constructor + public CECHPWorkPostTickRunWorkCommand( + CECHPWork pWork, + bool bNoDelay = false, + int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1, + bool bShouldTick = false, + uint dwTickTime = 0) + { + m_pWork = pWork; + m_bNoDelay = bNoDelay; + m_iPriority = iPriority; + m_bShouldTick = bShouldTick; + m_dwTickTime = dwTickTime; + } + + public override bool Run(CECHPWorkMan pWorkMan) + { + if (m_pWork == null || pWorkMan == null) + { + return false; + } + if (!pWorkMan.StartWork(m_iPriority, m_pWork, m_bNoDelay)) + { + m_pWork = null; + return false; + } + if (m_bShouldTick) + { + m_pWork.Tick(m_dwTickTime); + } m_pWork = null; - return false; + return true; } - if (m_bShouldTick) - { - m_pWork.Tick(m_dwTickTime); - } - m_pWork = null; - return true; - } -}; + }; +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs index 126b9e1c93..7160354504 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs @@ -1,155 +1,157 @@ -using BrewMonster; +using BrewMonster.Managers; using BrewMonster.Network; +using BrewMonster.Scripts.Player; using CSNetwork.GPDataType; -using PerfectWorld.Scripts.Managers; -using PerfectWorld.Scripts.Player; using UnityEngine; -class CECHPWorkPostTickCommand1 : CECHPWorkPostTickRunWorkCommand +namespace BrewMonster.Scripts { - public CECHPWorkPostTickCommand1(CECHPWork pWork) : base(pWork, true) + class CECHPWorkPostTickCommand1 : CECHPWorkPostTickRunWorkCommand { - } - public virtual bool Run(CECHPWorkMan pWorkMan) - { - if (!base.Run(pWorkMan)) + public CECHPWorkPostTickCommand1(CECHPWork pWork) : base(pWork, true) { - return false; } - //AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE); - return true; - } -}; - -/////////////////////////////////////////////////////////////////////////// -// -// Class CECHPWorkMelee -// -/////////////////////////////////////////////////////////////////////////// - -class CECHPWorkMelee : CECHPWork -{ - protected int m_idTarget; // Target id - protected int m_iIdleTime; // Idle time - protected int m_iIdleTimeCnt; // Idle time counter - - // Constructor and Destructor - public CECHPWorkMelee(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_HACKOBJECT, pWorkMan) - { - m_dwMask = Work_mask.MASK_HACKOBJECT; - m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT; - Reset(); - } - - // Tick routine - public virtual bool Tick(float dwDeltaTime) - { - base.Tick(dwDeltaTime); - - if (m_idTarget != 0 || m_idTarget == m_pHost.m_PlayerInfo.cid) + public virtual bool Run(CECHPWorkMan pWorkMan) { - m_bFinished = true; + if (!base.Run(pWorkMan)) + { + return false; + } + //AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE); return true; } + }; - // If target turn to be un-attackable, cancel action - if (m_pHost.AttackableJudge(m_idTarget, true) == 0) + /////////////////////////////////////////////////////////////////////////// + // + // Class CECHPWorkMelee + // + /////////////////////////////////////////////////////////////////////////// + + class CECHPWorkMelee : CECHPWork + { + protected int m_idTarget; // Target id + protected int m_iIdleTime; // Idle time + protected int m_iIdleTimeCnt; // Idle time counter + + // Constructor and Destructor + public CECHPWorkMelee(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_HACKOBJECT, pWorkMan) { - UnityGameSession.c2s_CmdCancelAction(); - //g_pGame.GetGameSession().c2s_CmdCancelAction(); - m_bFinished = true; - return true; + m_dwMask = Work_mask.MASK_HACKOBJECT; + m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT; + Reset(); } - if (m_iIdleTimeCnt < m_iIdleTime) + // Tick routine + public virtual bool Tick(float dwDeltaTime) { - m_iIdleTimeCnt += (int)dwDeltaTime; + base.Tick(dwDeltaTime); + + if (m_idTarget != 0 || m_idTarget == m_pHost.m_PlayerInfo.cid) + { + m_bFinished = true; + return true; + } + + // If target turn to be un-attackable, cancel action + if (m_pHost.AttackableJudge(m_idTarget, true) == 0) + { + UnityGameSession.c2s_CmdCancelAction(); + //g_pGame.GetGameSession().c2s_CmdCancelAction(); + m_bFinished = true; + return true; + } + if (m_iIdleTimeCnt < m_iIdleTime) + { + m_iIdleTimeCnt += (int)dwDeltaTime; + if (m_iIdleTimeCnt < m_iIdleTime) + return true; + + m_iIdleTimeCnt = m_iIdleTime; + } + + // Face to target + //m_pHost.TurnFaceTo(m_idTarget); + + int idTraceTarget = 0; + + if (GPDataTypeHelper.ISPLAYERID(m_idTarget)) + { + EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance.GetECManPlayer.GetElsePlayer(m_idTarget); + if (!pPlayer || pPlayer.IsDead()) // Taget has missed ? + return true; + + // if (!m_pHost.CanTouchTarget(pPlayer.GetServerPos(), pPlayer.GetTouchRadius(), 1, 0.8f)) + if (!m_pHost.CanTouchTarget(pPlayer.GetPos(), pPlayer.GetTouchRadius(), 1)) + idTraceTarget = m_idTarget; + } + else if (GPDataTypeHelper.ISNPCID(m_idTarget)) + { + CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(m_idTarget); + if (!pNPC || pNPC.IsDead()) // Taget has missed ? + return true; + + if (!m_pHost.CanTouchTarget(pNPC.GetPos(), pNPC.GetTouchRadius(), 1)) + idTraceTarget = m_idTarget; + } + + if (idTraceTarget != 0 && !m_pHost.IsRooting()) + { + CECHPWorkTrace pWork = (CECHPWorkTrace)m_pWorkMan.CreateWork(Host_work_ID.WORK_TRACEOBJECT); + pWork.SetTraceTarget(pWork.CreatTraceTarget(idTraceTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK)); + m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickCommand1(pWork)); return true; - - m_iIdleTimeCnt = m_iIdleTime; - } - - // Face to target - //m_pHost.TurnFaceTo(m_idTarget); - - int idTraceTarget = 0; - - if (GPDataTypeHelper.ISPLAYERID(m_idTarget)) - { - EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance.GetECManPlayer.GetElsePlayer(m_idTarget); - if (!pPlayer || pPlayer.IsDead()) // Taget has missed ? - return true; - - // if (!m_pHost.CanTouchTarget(pPlayer.GetServerPos(), pPlayer.GetTouchRadius(), 1, 0.8f)) - if (!m_pHost.CanTouchTarget(pPlayer.GetPos(), pPlayer.GetTouchRadius(), 1)) - idTraceTarget = m_idTarget; - } - else if (GPDataTypeHelper.ISNPCID(m_idTarget)) - { - CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(m_idTarget); - if (!pNPC || pNPC.IsDead()) // Taget has missed ? - return true; - - if (!m_pHost.CanTouchTarget(pNPC.GetPos(), pNPC.GetTouchRadius(), 1)) - idTraceTarget = m_idTarget; - } - - if (idTraceTarget != 0 && !m_pHost.IsRooting()) - { - CECHPWorkTrace pWork = (CECHPWorkTrace)m_pWorkMan.CreateWork(Host_work_ID.WORK_TRACEOBJECT); - pWork.SetTraceTarget(pWork.CreatTraceTarget(idTraceTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK)); - m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickCommand1(pWork)); + } return true; } - return true; - } - // Reset work - public virtual void Reset() - { - base.Reset(); + // Reset work + public virtual void Reset() + { + base.Reset(); - m_idTarget = 0; - m_iIdleTime = 0; - m_iIdleTimeCnt = 0; - } - // Copy work data - public virtual bool CopyData(CECHPWork pWork) - { - if (!base.CopyData(pWork)) - return false; + m_idTarget = 0; + m_iIdleTime = 0; + m_iIdleTimeCnt = 0; + } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + if (!base.CopyData(pWork)) + return false; - CECHPWorkMelee pSrc = (CECHPWorkMelee)pWork; + CECHPWorkMelee pSrc = (CECHPWorkMelee)pWork; - m_idTarget = pSrc.m_idTarget; - m_iIdleTime = pSrc.m_iIdleTime; - m_iIdleTimeCnt = pSrc.m_iIdleTimeCnt; + m_idTarget = pSrc.m_idTarget; + m_iIdleTime = pSrc.m_iIdleTime; + m_iIdleTimeCnt = pSrc.m_iIdleTimeCnt; - return true; - } - public virtual void Cancel() - { - // TO DO: fix later - //m_pHost.TurnFaceTo(0); - } + return true; + } + public virtual void Cancel() + { + // TO DO: fix later + //m_pHost.TurnFaceTo(0); + } - // Get attack target - public int GetTarget() { return m_idTarget; } - // Set idle time - public void SetIdleTime(int iTime) - { - m_iIdleTime = iTime; - m_iIdleTimeCnt = 0; - } - // Get idle time - public int GetIdleTime() { return m_iIdleTime; } + // Get attack target + public int GetTarget() { return m_idTarget; } + // Set idle time + public void SetIdleTime(int iTime) + { + m_iIdleTime = iTime; + m_iIdleTimeCnt = 0; + } + // Get idle time + public int GetIdleTime() { return m_iIdleTime; } - // On first tick - protected virtual void OnFirstTick() - { - m_pHost.m_iMoveMode = (int)MoveMode.MOVE_STAND; - m_pHost.PlayAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + Random.Range(0, 3), true, 200, false); + // On first tick + protected virtual void OnFirstTick() + { + m_pHost.m_iMoveMode = (int)MoveMode.MOVE_STAND; + m_pHost.PlayAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + Random.Range(0, 3), true, 200, false); - m_idTarget = m_pHost.m_idSelTarget; - } -}; + m_idTarget = m_pHost.m_idSelTarget; + } + }; +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs index 318949b4b4..14ad942f18 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs @@ -1,367 +1,370 @@ using CSNetwork.GPDataType; using UnityEngine; -public class CECHPWorkMove : CECHPWork +namespace BrewMonster.Scripts { - public static class Types + public class CECHPWorkMove : CECHPWork { - public const int DEST_2D = 0, - DEST_3D = 1, - DEST_DIR = 2, - DEST_PUSH = 3, - DEST_STANDJUMP = 4, - DEST_AUTOPF = 5; // Movement type - } - - protected A3DVECTOR3 m_vMoveDest; // Move destination position or direction - protected int m_iDestType; // Destination type - protected bool m_bHaveDest; // true, have destination - protected bool m_bMeetSlide; // true, meet slide - protected A3DVECTOR3 m_vCurDir; // Current move direction - protected bool m_bReadyCancel; // true, ready to cancel - protected bool m_bGliding; // glide - protected float m_fGlideTime; - protected float m_fGlideSpan; - protected float m_fGlideAng; - protected float m_fGlideVel; // glide angular vel - protected float m_fGlidePitch; // glide pitch angle - protected float m_fCurPitch; - protected float m_fPushPitch; - protected float m_fPushLean; - - protected bool m_bUseAutoMoveDialog; // Auto move - protected float m_fAutoHeight; // Height of auto moving destination - protected bool m_bAutoLand; // Auto land when arrive at destination - protected bool m_bAutoFly; // Auto fly - protected bool m_bReachedHeight;// Player reached specified height - protected bool m_bAutoFlyPending; // Mark whether a fly command had been executed - - protected int m_iNPCTempleId; - protected int m_iTaskId; - protected bool m_bSwitchTo2D; - - protected bool m_bResetAutoPF; - - public CECHPWorkMove(CECHPWorkMan pWorkMan) : base (Host_work_ID.WORK_MOVETOPOS, pWorkMan) - { - m_dwMask = Work_mask.MASK_MOVETOPOS; - m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_TRACEOBJECT | Work_mask.MASK_FOLLOW; - Reset(); - } - - public CECHPWorkMove(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan) - { - } - - // Set destination position or direction - public void SetDestination(int iDestType, A3DVECTOR3 vMoveDest) - { - m_iDestType = iDestType; - m_vMoveDest = vMoveDest; - m_bHaveDest = true; - m_bGliding = false; - //m_pHost->SetAdjustOrient(false); // 2014-9-10 ı CECHPWorkMove ʱ򶼻ô˺ᵼʱͨ SetDestDirAndUp öijʧЧ - // ַΪɡӽͷźϰס'A''D'ƶסţʩƫĿƶγԣ - - //Ϣ - m_iTaskId = 0; - m_iNPCTempleId = 0; - ResetUseAutoPF(); - - if (iDestType == Types.DEST_DIR) + public static class Types { - m_vCurDir = vMoveDest; - if (m_bUseAutoMoveDialog) + public const int DEST_2D = 0, + DEST_3D = 1, + DEST_DIR = 2, + DEST_PUSH = 3, + DEST_STANDJUMP = 4, + DEST_AUTOPF = 5; // Movement type + } + + protected A3DVECTOR3 m_vMoveDest; // Move destination position or direction + protected int m_iDestType; // Destination type + protected bool m_bHaveDest; // true, have destination + protected bool m_bMeetSlide; // true, meet slide + protected A3DVECTOR3 m_vCurDir; // Current move direction + protected bool m_bReadyCancel; // true, ready to cancel + protected bool m_bGliding; // glide + protected float m_fGlideTime; + protected float m_fGlideSpan; + protected float m_fGlideAng; + protected float m_fGlideVel; // glide angular vel + protected float m_fGlidePitch; // glide pitch angle + protected float m_fCurPitch; + protected float m_fPushPitch; + protected float m_fPushLean; + + protected bool m_bUseAutoMoveDialog; // Auto move + protected float m_fAutoHeight; // Height of auto moving destination + protected bool m_bAutoLand; // Auto land when arrive at destination + protected bool m_bAutoFly; // Auto fly + protected bool m_bReachedHeight;// Player reached specified height + protected bool m_bAutoFlyPending; // Mark whether a fly command had been executed + + protected int m_iNPCTempleId; + protected int m_iTaskId; + protected bool m_bSwitchTo2D; + + protected bool m_bResetAutoPF; + + public CECHPWorkMove(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_MOVETOPOS, pWorkMan) + { + m_dwMask = Work_mask.MASK_MOVETOPOS; + m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_TRACEOBJECT | Work_mask.MASK_FOLLOW; + Reset(); + } + + public CECHPWorkMove(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan) + { + } + + // Set destination position or direction + public void SetDestination(int iDestType, A3DVECTOR3 vMoveDest) + { + m_iDestType = iDestType; + m_vMoveDest = vMoveDest; + m_bHaveDest = true; + m_bGliding = false; + //m_pHost->SetAdjustOrient(false); // 2014-9-10 ı CECHPWorkMove ʱ򶼻ô˺ᵼʱͨ SetDestDirAndUp öijʧЧ + // ַΪɡӽͷźϰס'A''D'ƶסţʩƫĿƶγԣ + + //Ϣ + m_iTaskId = 0; + m_iNPCTempleId = 0; + ResetUseAutoPF(); + + if (iDestType == Types.DEST_DIR) { - m_bUseAutoMoveDialog = false; - m_bAutoLand = false; - m_fAutoHeight = -1.0f; - m_bAutoFly = false; - m_bReachedHeight = true; - m_bAutoFlyPending = false; + m_vCurDir = vMoveDest; + if (m_bUseAutoMoveDialog) + { + m_bUseAutoMoveDialog = false; + m_bAutoLand = false; + m_fAutoHeight = -1.0f; + m_bAutoFly = false; + m_bReachedHeight = true; + m_bAutoFlyPending = false; + } } - } - else if (iDestType == Types.DEST_2D || iDestType == Types.DEST_3D) - { - m_vCurDir = vMoveDest - new A3DVECTOR3(m_pHost.transform.position.x, m_pHost.transform.position.y, m_pHost.transform.position.z); - m_vCurDir.y = 0.0f; - m_vCurDir.Normalize(); - } - else if (IsAutoPF()) - { + else if (iDestType == Types.DEST_2D || iDestType == Types.DEST_3D) + { + m_vCurDir = vMoveDest - new A3DVECTOR3(m_pHost.transform.position.x, m_pHost.transform.position.y, m_pHost.transform.position.z); + m_vCurDir.y = 0.0f; + m_vCurDir.Normalize(); + } + else if (IsAutoPF()) + { + // TO DO: fix later + //m_vCurDir = CECIntelligentRoute::Instance().GetCurDest() - m_pHost->GetPos(); + //m_vCurDir.y = 0.0f; + //m_vCurDir.Normalize(); + //if (m_bUseAutoMoveDialog) + //{ + // // ˴ m_bUseAutoMoveDialog SetUseAutoMoveDialog ˵ + // m_bUseAutoMoveDialog = false; + // m_bAutoLand = false; + // m_fAutoHeight = -1.0f; + // m_bAutoFly = false; + // m_bReachedHeight = true; + // m_bAutoFlyPending = false; + //} + } + // TO DO: fix later - //m_vCurDir = CECIntelligentRoute::Instance().GetCurDest() - m_pHost->GetPos(); - //m_vCurDir.y = 0.0f; - //m_vCurDir.Normalize(); - //if (m_bUseAutoMoveDialog) + //if (m_pHost.m_pMoveTargetGFX) //{ - // // ˴ m_bUseAutoMoveDialog SetUseAutoMoveDialog ˵ - // m_bUseAutoMoveDialog = false; - // m_bAutoLand = false; - // m_fAutoHeight = -1.0f; - // m_bAutoFly = false; - // m_bReachedHeight = true; - // m_bAutoFlyPending = false; + // if (iDestType != DEST_PUSH) + // m_pHost.m_pMoveTargetGFX.Stop(); //} } - // TO DO: fix later - //if (m_pHost.m_pMoveTargetGFX) - //{ - // if (iDestType != DEST_PUSH) - // m_pHost.m_pMoveTargetGFX.Stop(); - //} - } + void ResetUseAutoPF() + { + m_bResetAutoPF = true; + } - void ResetUseAutoPF() - { - m_bResetAutoPF = true; - } + // Tick routine + public virtual bool Tick(float dwDeltaTime) + { + //UpdateResetUseAutoPF(); + //if (m_bSwitchTo2D) + //{ + // SwitchToDest2D(); + // m_bSwitchTo2D = false; + // return true; + //} + //if (IsAutoPF()) + //{ + // if (CECIntelligentRoute::Instance().IsIdle()) + // { + // // Ѱ·ģʽδɹʱȴ¸ Tick л DEST_2D ģʽ + // return true; + // } + // if (m_pHost.IsFlying()) + // { + // // ;лģʽʱл DEST_2D ģʽ + // CECIntelligentRoute::Instance().ResetSearch(); + // m_bSwitchTo2D = true; + // return true; + // } + //} - // Tick routine - public virtual bool Tick(float dwDeltaTime) - { - //UpdateResetUseAutoPF(); - //if (m_bSwitchTo2D) - //{ - // SwitchToDest2D(); - // m_bSwitchTo2D = false; - // return true; - //} - //if (IsAutoPF()) - //{ - // if (CECIntelligentRoute::Instance().IsIdle()) - // { - // // Ѱ·ģʽδɹʱȴ¸ Tick л DEST_2D ģʽ - // return true; - // } - // if (m_pHost.IsFlying()) - // { - // // ;лģʽʱл DEST_2D ģʽ - // CECIntelligentRoute::Instance().ResetSearch(); - // m_bSwitchTo2D = true; - // return true; - // } - //} + //base.Tick(dwDeltaTime); - //base.Tick(dwDeltaTime); + //if (m_pHost.IsRooting()) + // return true; - //if (m_pHost.IsRooting()) - // return true; + //if (m_bUseAutoMoveDialog) + //{ + // if (m_pHost.IsFlying()) + // { + // m_bAutoFly = false; + // m_bAutoFlyPending = false; + // } - //if (m_bUseAutoMoveDialog) - //{ - // if (m_pHost.IsFlying()) - // { - // m_bAutoFly = false; - // m_bAutoFlyPending = false; - // } + // if (m_bAutoFly && !m_bAutoFlyPending && !m_pHost.IsFlying()) + // { + // if (m_pHost.CmdFly()) + // { + // m_bAutoFly = false; + // m_bAutoFlyPending = true; + // } + // } + //} + //else + //{ + // // Make sure 'Win_AutoPlay' dialog doesn't show up + // CECGameUIMan pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); + // pGameUI.AutoMoveShowDialog(false); + //} - // if (m_bAutoFly && !m_bAutoFlyPending && !m_pHost.IsFlying()) - // { - // if (m_pHost.CmdFly()) - // { - // m_bAutoFly = false; - // m_bAutoFlyPending = true; - // } - // } - //} - //else - //{ - // // Make sure 'Win_AutoPlay' dialog doesn't show up - // CECGameUIMan pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); - // pGameUI.AutoMoveShowDialog(false); - //} + ////Ѱ·ҵNPCתΪWorkTrace״̬ + //if ((m_vMoveDest - m_pHost.GetPos()).MagnitudeH() <= 5.0f) + //{ + // if (m_iNPCTempleId) + // { + // CECNPC pNPC = g_pGame.GetGameRun().GetWorld().GetNPCMan().FindNPCByTempleID(m_iNPCTempleId); + // if (pNPC && m_pHost.SelectTarget(pNPC->GetNPCID())) + // { + // CECHPWorkTrace pWork = m_pWorkMan.CreateNPCTraceWork(pNPC, m_iTaskId); + // if (pWork) + // { + // m_bAutoLand = false; //ֹ״̬Ѱ·תworktrace֮ǰԶ½workfall + // Finish(); + // m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickRunWorkCommand(pWork, true)); + // return true; + // } + // } + // } + //} - ////Ѱ·ҵNPCתΪWorkTrace״̬ - //if ((m_vMoveDest - m_pHost.GetPos()).MagnitudeH() <= 5.0f) - //{ - // if (m_iNPCTempleId) - // { - // CECNPC pNPC = g_pGame.GetGameRun().GetWorld().GetNPCMan().FindNPCByTempleID(m_iNPCTempleId); - // if (pNPC && m_pHost.SelectTarget(pNPC->GetNPCID())) - // { - // CECHPWorkTrace pWork = m_pWorkMan.CreateNPCTraceWork(pNPC, m_iTaskId); - // if (pWork) - // { - // m_bAutoLand = false; //ֹ״̬Ѱ·תworktrace֮ǰԶ½workfall - // Finish(); - // m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickRunWorkCommand(pWork, true)); - // return true; - // } - // } - // } - //} + //float fDeltaTime = dwDeltaTime; + //if (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_GROUND || + // m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER && m_pHost.IsJumping() && (m_pHost.m_CDRInfo.vAbsVelocity.y > 0 || m_pHost.m_CDRInfo.fYVel > 0)) + //{ + // // Play appropriate actions + // if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction(CECPlayer::ACT_TRICK_RUN) && + // m_pHost.m_iMoveMode != CECPlayer::MOVE_SLIDE && !m_bMeetSlide) + // { + // int iAction = m_pHost->GetMoveStandAction(true); + // m_pHost.PlayAction(iAction, false); + // } - //float fDeltaTime = dwDeltaTime; - //if (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_GROUND || - // m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER && m_pHost.IsJumping() && (m_pHost.m_CDRInfo.vAbsVelocity.y > 0 || m_pHost.m_CDRInfo.fYVel > 0)) - //{ - // // Play appropriate actions - // if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction(CECPlayer::ACT_TRICK_RUN) && - // m_pHost.m_iMoveMode != CECPlayer::MOVE_SLIDE && !m_bMeetSlide) - // { - // int iAction = m_pHost->GetMoveStandAction(true); - // m_pHost.PlayAction(iAction, false); - // } + // Tick_Walk(fDeltaTime); + //} + //else // (m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_WATER) + //{ + // m_pHost->ResetJump(); - // Tick_Walk(fDeltaTime); - //} - //else // (m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_WATER) - //{ - // m_pHost->ResetJump(); + // // Play appropriate actions + // if (!m_bGliding) + // { + // int iAction = m_pHost.GetMoveStandAction(true); + // m_pHost.PlayAction(iAction, false); + // } - // // Play appropriate actions - // if (!m_bGliding) - // { - // int iAction = m_pHost.GetMoveStandAction(true); - // m_pHost.PlayAction(iAction, false); - // } + // Tick_FlySwim(fDeltaTime); + //} - // Tick_FlySwim(fDeltaTime); - //} + return true; + } + // Reset work + public virtual void Reset() + { - return true; - } - // Reset work - public virtual void Reset() - { + } + // Work is cancel + public virtual void Cancel() + { + + } + + // This work is do player moving ? + public virtual bool IsMoving() { return true; } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + return true; + } + + // Play move target effect + public void PlayMoveTargetGFX(A3DVECTOR3 vPos, A3DVECTOR3 vNormal) + { + + } + + // User press cancel button + public void PressCancel() { m_bReadyCancel = true; } + + public void SetUseAutoMoveDialog(bool bUseAutoMoveDialog) + { + + } + public bool GetUseAutoMoveDialog() { return m_bUseAutoMoveDialog; } + public bool GetAutoMove() + { + return true; + } + + void SetAutoLand(bool bAutoLand) { m_bAutoLand = bAutoLand; } + bool GetAutoLand() { return m_bAutoLand; } + + void SetAutoHeight(float fHeight) { m_fAutoHeight = fHeight; m_bAutoFly = true; m_bReachedHeight = false; } + float GetAutoHeight() { return m_fAutoHeight; } + bool IsAutoFly() { return m_bAutoFly; } + + bool IsAutoPF() { return m_iDestType == Types.DEST_AUTOPF; } + + // Finish work + void Finish() + { + + } + + void SetTaskNPCInfo(int tid, int taskid) + { + + } + + void SwitchToDest2D() + { + //int tid, taskid; + //tid = m_iNPCTempleId; + //taskid = m_iTaskId; + //CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); + //pGameUI->SetAutoMoveShowDialogTarget((int)m_vMoveDest.x, (int)m_vMoveDest.z); + //SetDestination(CECHPWorkMove::DEST_2D, m_vMoveDest); + //SetTaskNPCInfo(tid, taskid); + //SetUseAutoMoveDialog(true); + } + // On first tick + protected virtual void OnFirstTick() + { + + } + + // Tick routine of walking on ground + protected bool Tick_Walk(float fDeltaTime) + { + return true; + } + // Tick routine of flying or swimming + protected bool Tick_FlySwim(float fDeltaTime) + { + return true; + } + // Start gliding + protected void Glide(float fMoveTime, A3DVECTOR3 vMoveDirH, float fDeltaTime, bool bFly) + { + + } + + // Calculate vertical speed when fly or swim + protected float CalcFlySwimVertSpeed(float fSpeed1, float fPushDir, float fPushAccel, float fDeltaTime) + { + return 0; + } + + protected void ClearResetUseAutoPF() + { + + } + protected void UpdateResetUseAutoPF() + { + // if (!m_bResetAutoPF) + // { + // return; + // } + // CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkMove); + // CECIntelligentRoute::Instance().ResetSearch(); + // if (m_iDestType == DEST_2D || m_iDestType == DEST_3D) + // { + //# ifdef SHOW_AUTOMOVE_FOOTPRINTS + // g_AutoPFFollowPoints.clear(); + // g_AutoPFPathPoints.clear(); + //#endif + // } + // else if (IsAutoPF()) + // { + // bool bSwitchTo2D(true); + // while (true) + // { + // if (m_pHost->IsFlying()) + // { + // break; + // } + // CECHostBrushTest brushTester(m_pHost->GetPos(), m_pHost->m_CDRInfo.vExtent, m_pHost->m_CDRInfo.fStepHeight); + // if (CECIntelligentRoute::Instance().Search(m_pHost->GetPos(), m_vMoveDest, &brushTester) != CECIntelligentRoute::enumSearchSuccess) + // { + // break; + // } + // bSwitchTo2D = false; + // break; + // } + // if (bSwitchTo2D) + // { + // m_bSwitchTo2D = true; + // } + // } + // ClearResetUseAutoPF(); + } } - // Work is cancel - public virtual void Cancel() - { - - } - - // This work is do player moving ? - public virtual bool IsMoving() { return true; } - // Copy work data - public virtual bool CopyData(CECHPWork pWork) - { - return true; - } - - // Play move target effect - public void PlayMoveTargetGFX(A3DVECTOR3 vPos, A3DVECTOR3 vNormal) - { - - } - - // User press cancel button - public void PressCancel() { m_bReadyCancel = true; } - - public void SetUseAutoMoveDialog(bool bUseAutoMoveDialog) - { - - } - public bool GetUseAutoMoveDialog() { return m_bUseAutoMoveDialog; } - public bool GetAutoMove() - { - return true; - } - - void SetAutoLand(bool bAutoLand) { m_bAutoLand = bAutoLand; } - bool GetAutoLand() { return m_bAutoLand; } - - void SetAutoHeight(float fHeight) { m_fAutoHeight = fHeight; m_bAutoFly = true; m_bReachedHeight = false; } - float GetAutoHeight() { return m_fAutoHeight; } - bool IsAutoFly() { return m_bAutoFly;} - - bool IsAutoPF(){ return m_iDestType == Types.DEST_AUTOPF; } - - // Finish work - void Finish() - { - - } - - void SetTaskNPCInfo(int tid, int taskid) - { - - } - - void SwitchToDest2D() - { - //int tid, taskid; - //tid = m_iNPCTempleId; - //taskid = m_iTaskId; - //CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); - //pGameUI->SetAutoMoveShowDialogTarget((int)m_vMoveDest.x, (int)m_vMoveDest.z); - //SetDestination(CECHPWorkMove::DEST_2D, m_vMoveDest); - //SetTaskNPCInfo(tid, taskid); - //SetUseAutoMoveDialog(true); - } - // On first tick - protected virtual void OnFirstTick() - { - - } - - // Tick routine of walking on ground - protected bool Tick_Walk(float fDeltaTime) - { - return true; - } - // Tick routine of flying or swimming - protected bool Tick_FlySwim(float fDeltaTime) - { - return true; - } - // Start gliding - protected void Glide(float fMoveTime, A3DVECTOR3 vMoveDirH, float fDeltaTime, bool bFly) - { - - } - - // Calculate vertical speed when fly or swim - protected float CalcFlySwimVertSpeed(float fSpeed1, float fPushDir, float fPushAccel, float fDeltaTime) - { - return 0; - } - - protected void ClearResetUseAutoPF() - { - - } - protected void UpdateResetUseAutoPF() - { -// if (!m_bResetAutoPF) -// { -// return; -// } -// CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkMove); -// CECIntelligentRoute::Instance().ResetSearch(); -// if (m_iDestType == DEST_2D || m_iDestType == DEST_3D) -// { -//# ifdef SHOW_AUTOMOVE_FOOTPRINTS -// g_AutoPFFollowPoints.clear(); -// g_AutoPFPathPoints.clear(); -//#endif -// } -// else if (IsAutoPF()) -// { -// bool bSwitchTo2D(true); -// while (true) -// { -// if (m_pHost->IsFlying()) -// { -// break; -// } -// CECHostBrushTest brushTester(m_pHost->GetPos(), m_pHost->m_CDRInfo.vExtent, m_pHost->m_CDRInfo.fStepHeight); -// if (CECIntelligentRoute::Instance().Search(m_pHost->GetPos(), m_vMoveDest, &brushTester) != CECIntelligentRoute::enumSearchSuccess) -// { -// break; -// } -// bSwitchTo2D = false; -// break; -// } -// if (bSwitchTo2D) -// { -// m_bSwitchTo2D = true; -// } -// } -// ClearResetUseAutoPF(); - } - } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs index 96368a98b4..6efffdd379 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs @@ -1,75 +1,78 @@ using UnityEngine; -/////////////////////////////////////////////////////////////////////////// -// -// Class CECHPWorkSpell -// -/////////////////////////////////////////////////////////////////////////// -public class CECHPWorkSpell : CECHPWork +namespace BrewMonster.Scripts { - public static class Spell_magic_state + /////////////////////////////////////////////////////////////////////////// + // + // Class CECHPWorkSpell + // + /////////////////////////////////////////////////////////////////////////// + public class CECHPWorkSpell : CECHPWork { - public const int ST_INCANT = 0, - ST_SPELL = 1; - } + public static class Spell_magic_state + { + public const int ST_INCANT = 0, + ST_SPELL = 1; + } - public CECHPWorkSpell(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_SPELLOBJECT, pWorkMan) - { - m_dwMask = Work_mask.MASK_SPELLOBJECT; - m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT; - Reset(); - } + public CECHPWorkSpell(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_SPELLOBJECT, pWorkMan) + { + m_dwMask = Work_mask.MASK_SPELLOBJECT; + m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT; + Reset(); + } - public CECHPWorkSpell(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan) - { - } + public CECHPWorkSpell(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan) + { + } - protected CECSkill m_pSkill; // Skill object - protected CECCounter m_OverTimeCnt; // Over time counter - protected int m_iState; - protected int m_idTarget; // Target id + protected CECSkill m_pSkill; // Skill object + protected CECCounter m_OverTimeCnt; // Over time counter + protected int m_iState; + protected int m_idTarget; // Target id - // On first tick - protected virtual void OnFirstTick() - { - //m_pHost.m_iMoveMode = CECHostPlayer::MOVE_STAND; - } - // Prepare cast - public void PrepareCast(int idTarget, CECSkill pSkill, int iIncantTime) - { + // On first tick + protected virtual void OnFirstTick() + { + //m_pHost.m_iMoveMode = CECHostPlayer::MOVE_STAND; + } + // Prepare cast + public void PrepareCast(int idTarget, CECSkill pSkill, int iIncantTime) + { - } - // Change state - public void ChangeState(int iState) - { + } + // Change state + public void ChangeState(int iState) + { - } - // Get state - public int GetState() - { - return m_iState; - } - public CECSkill GetSkill() - { - return m_pSkill; - } + } + // Get state + public int GetState() + { + return m_iState; + } + public CECSkill GetSkill() + { + return m_pSkill; + } - // Tick routine - public virtual bool Tick(uint dwDeltaTime) - { - return false; - } - // Reset work - public virtual void Reset() - { + // Tick routine + public virtual bool Tick(uint dwDeltaTime) + { + return false; + } + // Reset work + public virtual void Reset() + { - } - // Copy work data - public virtual bool CopyData(CECHPWork pWork) - { - return false; - } - // Cancel work - public virtual void Cancel() - { + } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + return false; + } + // Cancel work + public virtual void Cancel() + { + } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs index 1498b51fc3..a88ba96518 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs @@ -1,998 +1,1000 @@ -using BrewMonster; +using BrewMonster.Managers; using BrewMonster.Network; +using BrewMonster.Scripts.Player; using CSNetwork.GPDataType; -using PerfectWorld.Scripts.Player; using System; -using System.Runtime.ConstrainedExecution; using UnityEngine; -/////////////////////////////////////////////////////////////////////////// -// -// Class CECHPWorkTrace -// -/////////////////////////////////////////////////////////////////////////// - -public static class TraceObjectType +namespace BrewMonster.Scripts { - public const int TRACE_NONE = 0, - TRACE_PLAYER = 1, - TRACE_MATTER = 2, - TRACE_NPC = 3, - TRACE_TASKNPC = 4; -} + /////////////////////////////////////////////////////////////////////////// + // + // Class CECHPWorkTrace + // + /////////////////////////////////////////////////////////////////////////// -public abstract class CECTracedObject -{ - //friend CECHPWorkTrace; - protected int m_iTraceType; - protected int m_iObjectId; - protected int m_iReason; - protected bool m_bMoreClose; - protected CECHostPlayer m_pHost; - - public CECTracedObject(int type, int id, CECHostPlayer pHost, int ireason) + public static class TraceObjectType { - m_iTraceType = type; - m_iObjectId = id; - m_iReason = ireason; - m_pHost = pHost; - m_bMoreClose = false; - } - public CECTracedObject(CECTracedObject rhs) - { - m_iTraceType = rhs.m_iTraceType; - m_iObjectId = rhs.m_iObjectId; - m_iReason = rhs.m_iReason; - m_bMoreClose = rhs.m_bMoreClose; - m_pHost = rhs.m_pHost; + public const int TRACE_NONE = 0, + TRACE_PLAYER = 1, + TRACE_MATTER = 2, + TRACE_NPC = 3, + TRACE_TASKNPC = 4; } - public abstract bool OnTargetMissing(); - public abstract A3DVECTOR3 GetTargetPos(); - public abstract bool OnTouched(); - public abstract CECTracedObject Clone(); - - public virtual bool IsTargetMissing() + public abstract class CECTracedObject { - if (m_iObjectId != 0) + //friend CECHPWorkTrace; + protected int m_iTraceType; + protected int m_iObjectId; + protected int m_iReason; + protected bool m_bMoreClose; + protected CECHostPlayer m_pHost; + + public CECTracedObject(int type, int id, CECHostPlayer pHost, int ireason) { - CECObject pObj = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); - if (pObj) - { - return false; - } + m_iTraceType = type; + m_iObjectId = id; + m_iReason = ireason; + m_pHost = pHost; + m_bMoreClose = false; } - return true; - } - - public A3DVECTOR3? GetMovePos() - { - A3DVECTOR3 vMovePos; - CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); - if (pObject) + public CECTracedObject(CECTracedObject rhs) { - if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) + m_iTraceType = rhs.m_iTraceType; + m_iObjectId = rhs.m_iObjectId; + m_iReason = rhs.m_iReason; + m_bMoreClose = rhs.m_bMoreClose; + m_pHost = rhs.m_pHost; + } + + public abstract bool OnTargetMissing(); + public abstract A3DVECTOR3 GetTargetPos(); + public abstract bool OnTouched(); + public abstract CECTracedObject Clone(); + + public virtual bool IsTargetMissing() + { + if (m_iObjectId != 0) { - if (m_iObjectId == m_pHost.GetCharacterID()) + CECObject pObj = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + if (pObj) { - vMovePos = m_pHost.GetPos(); + return false; + } + } + return true; + } + + public A3DVECTOR3? GetMovePos() + { + A3DVECTOR3 vMovePos; + CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + if (pObject) + { + if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) + { + if (m_iObjectId == m_pHost.GetCharacterID()) + { + vMovePos = m_pHost.GetPos(); + } + else + { + vMovePos = (pObject as EC_ElsePlayer).GetServerPos(); + } + } + else if (GPDataTypeHelper.ISNPCID(m_iObjectId)) + { + vMovePos = (pObject as CECNPC).GetServerPos(); } else { - vMovePos = (pObject as EC_ElsePlayer).GetServerPos(); + vMovePos = pObject.GetPos(); } + return vMovePos; } - else if (GPDataTypeHelper.ISNPCID(m_iObjectId)) - { - vMovePos = (pObject as CECNPC).GetServerPos(); - } - else - { - vMovePos = pObject.GetPos(); - } - return vMovePos; + return null; } - return null; - } - public int GetObjectID() - { - return m_iObjectId; - } - public bool CanTouchMoreClose() - { - return m_bMoreClose; - } - public void SetMoveCloseFlag(bool bMoveClode) - { - m_bMoreClose = bMoveClode; - } - public int GetTraceReason() - { - return m_iReason; - } - public bool CanTouchFrom(A3DVECTOR3 vHostPos) - { - while (m_iObjectId != 0) + public int GetObjectID() { - A3DVECTOR3 vTargetPos = new A3DVECTOR3(0f, 0f, 0f); - vTargetPos = GetTargetPos(); - - int iTouchReason = 0; - if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) - iTouchReason = 1; - else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) - iTouchReason = 2; - else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) - iTouchReason = 3; - - float fMaxCut = m_bMoreClose ? -1.0f : 1.0f; - - CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); - - float fTouchRadius = 0.0f; - if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) + return m_iObjectId; + } + public bool CanTouchMoreClose() + { + return m_bMoreClose; + } + public void SetMoveCloseFlag(bool bMoveClode) + { + m_bMoreClose = bMoveClode; + } + public int GetTraceReason() + { + return m_iReason; + } + public bool CanTouchFrom(A3DVECTOR3 vHostPos) + { + while (m_iObjectId != 0) { + A3DVECTOR3 vTargetPos = new A3DVECTOR3(0f, 0f, 0f); + vTargetPos = GetTargetPos(); + + int iTouchReason = 0; + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + iTouchReason = 1; + else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + iTouchReason = 2; + else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) + iTouchReason = 3; + + float fMaxCut = m_bMoreClose ? -1.0f : 1.0f; + + CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + + float fTouchRadius = 0.0f; + if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) + { + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) + { + fTouchRadius = 0.0f; + } + else + { + EC_Player pPlayer = pObject.GetComponent(); + fTouchRadius = pPlayer.GetTouchRadius(); + } + return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut); + } + else if (GPDataTypeHelper.ISNPCID(m_iObjectId)) + { + CECNPC pNPC = pObject as CECNPC; + fTouchRadius = pNPC.GetTouchRadius(); + return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut); + } + //else if (GPDataTypeHelper.ISMATTERID(m_iObjectId)) + //{ + // CECMatter pMatter = (pObject) as CECMatter; + // return pMatter.CalcDist(vHostPos, true) < pMatter.GetGatherDist(); + //} + break; + } + return false; + } + public int GetTraceType() + { + return m_iTraceType; + } + public CECObject GetTargetObject() + { + return EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + } + }; + + public class CECTracedNPC : CECTracedObject + { + protected bool m_bForceAttack; + + public CECTracedNPC(int type, int id, CECHostPlayer pHost, int ireason, bool bForceAttack = false) : base(type, id, pHost, ireason) + { + m_bForceAttack = bForceAttack; + } + public CECTracedNPC(CECTracedNPC rhs) : base(rhs) + { + m_bForceAttack = rhs.m_bForceAttack; + } + + public override bool OnTargetMissing() + { + bool bRet = false; + + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + { + bRet = true; + } + //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // CECSkill pSkill = m_pHost.m_pPrepSkill; + // if (pSkill == null || pSkill.GetTargetType() != 2) + // { + // bRet = true; + // m_pHost.m_pPrepSkill = null; + // } + //} + return bRet; + } + + public override A3DVECTOR3 GetTargetPos() + { + return (GetTargetObject() as CECNPC).GetServerPos(); + } + + public override bool OnTouched() + { + bool bActionDone = false; + + if (GPDataTypeHelper.ISNPCID(m_iObjectId)) + { + CECNPC pNPC = (CECNPC)GetTargetObject(); + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) { - fTouchRadius = 0.0f; - } - else - { - EC_Player pPlayer = pObject.GetComponent(); - fTouchRadius = pPlayer.GetTouchRadius(); - } - return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut); - } - else if (GPDataTypeHelper.ISNPCID(m_iObjectId)) - { - CECNPC pNPC = pObject as CECNPC; - fTouchRadius = pNPC.GetTouchRadius(); - return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut); - } - //else if (GPDataTypeHelper.ISMATTERID(m_iObjectId)) - //{ - // CECMatter pMatter = (pObject) as CECMatter; - // return pMatter.CalcDist(vHostPos, true) < pMatter.GetGatherDist(); - //} - break; - } - return false; - } - public int GetTraceType() - { - return m_iTraceType; - } - public CECObject GetTargetObject() - { - return EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); - } -}; - -public class CECTracedNPC : CECTracedObject -{ - protected bool m_bForceAttack; - - public CECTracedNPC(int type, int id, CECHostPlayer pHost, int ireason, bool bForceAttack = false) : base(type, id, pHost, ireason) - { - m_bForceAttack = bForceAttack; - } - public CECTracedNPC(CECTracedNPC rhs) : base(rhs) - { - m_bForceAttack = rhs.m_bForceAttack; - } - - public override bool OnTargetMissing() - { - bool bRet = false; - - if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) - { - bRet = true; - } - //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) - //{ - // CECSkill pSkill = m_pHost.m_pPrepSkill; - // if (pSkill == null || pSkill.GetTargetType() != 2) - // { - // bRet = true; - // m_pHost.m_pPrepSkill = null; - // } - //} - return bRet; - } - - public override A3DVECTOR3 GetTargetPos() - { - return (GetTargetObject() as CECNPC).GetServerPos(); - } - - public override bool OnTouched() - { - bool bActionDone = false; - - if (GPDataTypeHelper.ISNPCID(m_iObjectId)) - { - CECNPC pNPC = (CECNPC)GetTargetObject(); - - if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) - { - if ((!m_pHost.IsInBattle() || m_pHost.InSameBattleCamp(pNPC)) /*&& + if ((!m_pHost.IsInBattle() || m_pHost.InSameBattleCamp(pNPC)) /*&& !g_pGame.GetGameRun().GetUIManager().GetInGameUIMan().GetDialog("Win_SkillAction").IsShow()*/) - { - UnityGameSession.c2s_CmdNPCSevHello(m_iObjectId); - bActionDone = true; - //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_TALK"); + { + UnityGameSession.c2s_CmdNPCSevHello(m_iObjectId); + bActionDone = true; + //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_TALK"); + } } - } - else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) - { - if (m_iObjectId == m_pHost.m_idSelTarget && - m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1) + else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) { - byte byPVPMask = EC_Utility.glb_BuildPVPMask(m_bForceAttack); - UnityGameSession.c2s_CmdNormalAttack(byPVPMask); - m_pHost.m_bPrepareFight = true; - bActionDone = true; - //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_ATTACK"); + if (m_iObjectId == m_pHost.m_idSelTarget && + m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1) + { + byte byPVPMask = EC_Utility.glb_BuildPVPMask(m_bForceAttack); + UnityGameSession.c2s_CmdNormalAttack(byPVPMask); + m_pHost.m_bPrepareFight = true; + bActionDone = true; + //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_ATTACK"); + } } + //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_SPELL"); + // if (!m_pHost.CannotAttack()) + // { + // if (m_pHost.CastSkill(m_iObjectId, m_bForceAttack)) + // bActionDone = true; + // } + // else + // m_pHost.m_pPrepSkill = null; + //} } - //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) - //{ - // //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_SPELL"); - // if (!m_pHost.CannotAttack()) - // { - // if (m_pHost.CastSkill(m_iObjectId, m_bForceAttack)) - // bActionDone = true; - // } - // else - // m_pHost.m_pPrepSkill = null; - //} + return bActionDone; } - return bActionDone; - } - public override CECTracedObject Clone() - { - return new CECTracedNPC(this); - } - - public override bool IsTargetMissing() - { - if (base.IsTargetMissing()) + public override CECTracedObject Clone() { - return true; + return new CECTracedNPC(this); } - CECNPC pNPC = GetTargetObject() as CECNPC; - if (pNPC.IsDead()) - { - return true; - } - return false; - } -} -public class CECTracedPlayer : CECTracedObject -{ - protected bool m_bForceAttack; - public CECTracedPlayer(int type, int id, CECHostPlayer pHost, int ireason, bool bForceAttack = false) : base(type, id, pHost, ireason) - { - m_bForceAttack = bForceAttack; - } - public CECTracedPlayer(CECTracedPlayer rhs) : base(rhs) - { - m_bForceAttack = rhs.m_bForceAttack; - } - - public override bool OnTargetMissing() - { - bool bRet = false; - - if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + public override bool IsTargetMissing() { - bRet = true; - } - //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) - //{ - // CECSkill pSkill = m_pHost.m_pPrepSkill; - // if (pSkill == null || pSkill.GetTargetType() != 2) - // { - // bRet = true; - // m_pHost.m_pPrepSkill = null; - // } - //} - return bRet; - } - - public override A3DVECTOR3 GetTargetPos() - { - CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); - if (m_iObjectId == m_pHost.GetCharacterID()) - { - return m_pHost.GetPos(); - } - else - { - return (pObject as EC_ElsePlayer).GetServerPos(); - } - } - - public override bool OnTouched() - { - bool bActionDone = false; - if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) - { - if (m_iObjectId == 0 || m_iObjectId == m_pHost.GetCharacterID()) + if (base.IsTargetMissing()) { - // Handle special case - //ASSERT(m_iReason == CECHPWorkTrace::TRACE_SPELL); - //if (!m_pHost.CannotAttack()) - //{ - // if (m_pHost.CastSkill(m_iObjectId, m_bForceAttack, null)) - // bActionDone = true; - //} - //else - //{ - // m_pHost.m_pPrepSkill = null; - //} - //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- special case- TRACE_SPELL"); - return bActionDone; + return true; } + CECNPC pNPC = GetTargetObject() as CECNPC; + if (pNPC.IsDead()) + { + return true; + } + return false; + } + } + + public class CECTracedPlayer : CECTracedObject + { + protected bool m_bForceAttack; + public CECTracedPlayer(int type, int id, CECHostPlayer pHost, int ireason, bool bForceAttack = false) : base(type, id, pHost, ireason) + { + m_bForceAttack = bForceAttack; + } + public CECTracedPlayer(CECTracedPlayer rhs) : base(rhs) + { + m_bForceAttack = rhs.m_bForceAttack; + } + + public override bool OnTargetMissing() + { + bool bRet = false; + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) { - if (m_iObjectId == m_pHost.m_idSelTarget && - m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1) - { - byte byPVPMask = EC_Utility.glb_BuildPVPMask(m_bForceAttack); - UnityGameSession.c2s_CmdNormalAttack(byPVPMask); - m_pHost.m_bPrepareFight = true; - bActionDone = true; - //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_ATTACK"); - } + bRet = true; } //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) //{ - // //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_SPELL"); - // if (!m_pHost.CastSkill(m_iObjectId, m_bForceAttack, GetTargetObject())) + // CECSkill pSkill = m_pHost.m_pPrepSkill; + // if (pSkill == null || pSkill.GetTargetType() != 2) // { + // bRet = true; // m_pHost.m_pPrepSkill = null; // } - // else - // { - // bActionDone = true; - // } //} - else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) + return bRet; + } + + public override A3DVECTOR3 GetTargetPos() + { + CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + if (m_iObjectId == m_pHost.GetCharacterID()) { - // Visite other's booth, send hello message to him - //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_TALK"); - UnityGameSession.c2s_CmdNPCSevHello(m_iObjectId); - bActionDone = true; - } - } - return bActionDone; - } - - public override CECTracedObject Clone() - { - return new CECTracedPlayer(this); - } - - public override bool IsTargetMissing() - { - if (base.IsTargetMissing()) - { - return true; - } - EC_Player pPlayer = GetTargetObject() as EC_Player; - if (pPlayer.IsElsePlayer()) - { - if (pPlayer.IsDead()) - { - //if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) - //{ - // CECSkill pSkill = m_pHost.m_pPrepSkill; - // if (pSkill && pSkill.GetTargetType() == 2) - // { - // return false; - // } - //} - return true; - } - } - return false; - } -}; - -public class CECTracedMatter : CECTracedObject -{ - - public CECTracedMatter(int type, int id, CECHostPlayer pHost, int ireason) : base(type, id, pHost, ireason) - { - - } - public CECTracedMatter(CECTracedMatter rhs) : base(rhs) - { - - } - - public override bool OnTargetMissing() - { - return false; - } - - public override A3DVECTOR3 GetTargetPos() - { - return GetTargetObject().GetPos(); - } - - public override bool OnTouched() - { - bool bActionDone = false; - //if (GPDataTypeHelper.ISMATTERID(m_iObjectId)) - //{ - // if (m_pHost.GetProfession() == PROF_GHOST && m_pHost.IsInvisible()) - // { - // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CANNOT_USE_WHEN_INVISIBLE); - // return bActionDone; - // } - // CECMatter* pMatter = (CECMatter*)GetTargetObject(); - - // if (m_iReason == CECHPWorkTrace::TRACE_PICKUP) - // { - // // Check whether we have enougth place to hold this item or money - // a_LogOutput(1, "[NormalATK]- CECTracedMatter- OnTouched- TRACE_PICKUP"); - // if (m_pHost.CanTakeItem(pMatter.GetTemplateID(), 1)) - // { - // // Send pickup asking and wait response command - // g_pGame.GetGameSession().c2s_CmdPickup(m_iObjectId, pMatter.GetTemplateID()); - // bActionDone = true; - // } - // else - // { - // // Print a notify message - // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_PACKISFULL); - // } - // } - // else - // { // m_iReason == TRACE_GATHER - // int tidMatter = pMatter.GetTemplateID(); - // a_LogOutput(1, "[NormalATK]- CECTracedMatter- OnTouched- TRACE_GATHER"); - // // Check mine level requirement - // if (m_pHost.GetBasicProps().iLevel < pMatter.GetLevelReq()) - // { - // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_LEVELTOOLOW); - // return bActionDone; - // } - - // // Check whether we have a mine tool - // int iPack, iIndex, idTool; - // if (m_pHost.FindMineTool(tidMatter, &iPack, &iIndex, &idTool)) - // { - // DATA_TYPE DataType; - // const MINE_ESSENCE* pData = (const MINE_ESSENCE*)g_pGame.GetElementDataMan().get_data_ptr(pMatter.GetTemplateID(), ID_SPACE_ESSENCE, DataType); - // if (DataType != DT_MINE_ESSENCE) - // { - // ASSERT(DataType == DT_MINE_ESSENCE); - // return bActionDone; - // } - - // if (m_pHost.GetCoolTime(GP_CT_PLAYER_GATHER)) - // { - // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CMD_INCOOLTIME); - // } - // else - // { - // // Send gather asking and wait response command - // g_pGame.GetGameSession().c2s_CmdGatherMaterial(m_iObjectId, iPack, iIndex, idTool, pData.task_in); - // } - // } - // else - // { - // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_NEEDTOOL); - // } - // } - //} - return bActionDone; - } - - public override CECTracedObject Clone() - { - return new CECTracedMatter(this); - } -}; -public class CECHPWorkTrace : CECHPWork -{ - // Trace reason - public static class Trace_reason - { - public const int TRACE_NONE = -1, - TRACE_ATTACK = 0, // Normal attack - TRACE_PICKUP = 1, // Pickup object - TRACE_TALK = 2, // Go to talk - TRACE_SPELL = 3, // Cast magic - TRACE_GATHER = 4; // Gather object - } - // Constructor and Destructor - public CECHPWorkTrace(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_TRACEOBJECT, pWorkMan) - { - m_dwMask = Work_mask.MASK_TRACEOBJECT; - m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_FLYOFF | Work_mask.MASK_FREEFALL | - Work_mask.MASK_FOLLOW | Work_mask.MASK_USEITEM; - - Reset(); - } - - // Change trace target - //void ChangeTarget(int idTarget, int iReason, bool bUseAutoPF=false); - // 趨traceobject - public void SetTraceTarget(CECTracedObject pTraceObj, bool bUseAutoPF = false) - { - ResetUseAutoPF(bUseAutoPF); - if (!pTraceObj.GetTargetObject() || pTraceObj.GetObjectID() == m_pHost.GetCharacterID()) - { - // This is special case - ReplaceTarget(pTraceObj); - return; - } - int idTarget = pTraceObj.GetObjectID(); - if (!GPDataTypeHelper.ISPLAYERID(idTarget) && !GPDataTypeHelper.ISNPCID(idTarget) && !GPDataTypeHelper.ISMATTERID(idTarget)) - { - return; - } - CECObject pObject = pTraceObj.GetTargetObject(); - if (!pObject) - { - //delete pTraceObj; - return; - } - ReplaceTarget(pTraceObj); - if (m_pTraceObject.GetTargetObject()) - { - A3DVECTOR3 vDirH = pTraceObj.GetTargetPos() - m_pHost.GetPos(); - vDirH.y = 0.0f; - vDirH.Normalize(); - m_vCurDirH = !vDirH.IsZero() ? vDirH : m_vCurDirH = GPDataTypeHelper.g_vAxisZ; - } - } - - public CECTracedObject CreatTraceTarget(int iTraceObjId, int iReason, bool bForceAttack = false) - { - if (GPDataTypeHelper.ISPLAYERID(iTraceObjId)) - { - return new CECTracedPlayer(TraceObjectType.TRACE_PLAYER, iTraceObjId, m_pHost, iReason, bForceAttack); - } - else if (GPDataTypeHelper.ISNPCID(iTraceObjId)) - { - return new CECTracedNPC(TraceObjectType.TRACE_NPC, iTraceObjId, m_pHost, iReason, bForceAttack); - } - //else if (GPDataTypeHelper.ISMATTERID(iTraceObjId)) - //{ - // return new CECTracedMatter(TraceObjectType.TRACE_MATTER, iTraceObjId, m_pHost, iReason); - //} - return null; - } - - // Tick routine - public override bool Tick(float dwDeltaTime) - { - base.Tick(dwDeltaTime); - - CheckPrepSkill(); - - UpdateResetUseAutoPF(); - UpdateUseAutoPF(); - - // m_bFinished flag may be set both in OnFirstTick() and CheckPrepSkill(), - // so check it here ! - if (m_bFinished) - { - return true; - } - if (m_pTraceObject.IsTargetMissing()) - { - OnTargetMissing(); - return true; - } - - if (m_bCheckTouch) - { - if (IsGoodTimeToTouch()) - { - OnTouchTarget(); - return true; - //if (m_pTraceObject.CanTouchFrom(m_pHost.GetPos())) - //{ - // OnTouchTarget(); - // return true; - //} - } - } - m_bCheckTouch = true; - - return true; // TO DO: remove later - if (!m_pHost.IsRooting()) - { - // Continue tracing object - float fDeltaTime = dwDeltaTime /** 0.001f*/; - if (m_pHost.m_iMoveEnv == EC_Player.Move_environment.MOVEENV_GROUND) - { - // Play appropriate actions - if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_TRICK_RUN) && - m_pHost.m_iMoveMode != (int)MoveMode.MOVE_SLIDE) - { - int iAction = m_pHost.GetMoveStandAction(true); - m_pHost.PlayAction(iAction, false, 200, false); - } - - Trace_Walk(fDeltaTime); - } - else // (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER) - { - m_pHost.ResetJump(); - - // Play appropriate actions - int iAction = m_pHost.GetMoveStandAction(true); - m_pHost.PlayAction(iAction, false, 200, false); - - Trace_FlySwim(fDeltaTime); - } - - m_bHaveMoved = true; - } - - return true; - } - // Reset work - public override void Reset() - { - base.Reset(); - - m_bHaveMoved = false; - m_bMeetSlide = false; - m_bCheckTouch = true; - m_bReadyCancel = false; - m_bMoreClose = false; - //m_pPrepSkill = null; - m_bForceAttack = false; - m_bActionDone = false; - ClearResetUseAutoPF(); - m_bUseAutoPF = false; - m_dwAutoPFNextCheckTime = 0; - m_pTraceObject = null; - } - // Work is cancel - public override void Cancel() - { - //if (m_pHost.m_pPrepSkill && m_pTraceObject.GetTraceReason() == Trace_reason.TRACE_SPELL) - // m_pHost.m_pPrepSkill = null; - - ClearResetUseAutoPF(); - if (GetUseAutoPF()) - { - SetUseAutoPF(false); - } - //m_pHost.StopModelMove(); - base.Cancel(); - - //AP_ActionEvent(m_bActionDone ? AP_EVENT_TRACEOK : AP_EVENT_MOVEFINISHED, m_pTraceObject.GetTraceReason()); - } - - // This work is do player moving ? - public override bool IsMoving() { return true; } - // Copy work data - public override bool CopyData(CECHPWork pWork) - { - if (!base.CopyData(pWork)) - return false; - - CECHPWorkTrace pSrc = (CECHPWorkTrace)pWork; - - m_bHaveMoved = pSrc.m_bHaveMoved; - m_bMeetSlide = pSrc.m_bMeetSlide; - m_bCheckTouch = pSrc.m_bCheckTouch; - m_bReadyCancel = pSrc.m_bReadyCancel; - m_bMoreClose = pSrc.m_bMoreClose; - m_vCurDirH = pSrc.m_vCurDirH; - //m_pPrepSkill = pSrc.m_pPrepSkill; - m_bForceAttack = pSrc.m_bForceAttack; - m_bActionDone = pSrc.m_bActionDone; - m_bShouldResetUseAutoPF = pSrc.m_bShouldResetUseAutoPF; - m_bUseAutoPFResetValue = pSrc.m_bUseAutoPFResetValue; - m_bUseAutoPF = pSrc.m_bUseAutoPF; - m_dwAutoPFNextCheckTime = pSrc.m_dwAutoPFNextCheckTime; - - //delete m_pTraceObject; - m_pTraceObject = pSrc.m_pTraceObject.Clone(); - - return true; - } - - // User press cancel button - public void PressCancel() - { - m_bReadyCancel = true; - //if (m_pTraceObject.GetTraceReason() == TRACE_SPELL) - // m_pHost.m_pPrepSkill = NULL; - } - // Set move close flag - public void SetMoveCloseFlag(bool bMoveClose) { m_pTraceObject.SetMoveCloseFlag(bMoveClose); } - - // Set / Get force attack flag - public void SetForceAttack(bool bTrue) { m_bForceAttack = bTrue; } - public bool GetForceAttack() { return m_bForceAttack; } - // Set / Get prepared skill - public void SetPrepSkill(CECSkill pSkill) { /*m_pPrepSkill = pSkill;*/ } - public CECSkill GetPrepSkill() { /*return m_pPrepSkill;*/ return null; } - // Get target ID - public int GetTarget() { return m_pTraceObject.GetObjectID(); } - // Get trace reason - public int GetTraceReason() { return m_pTraceObject.GetTraceReason(); } - // AutoPF - public void SetUseAutoPF(bool bUse) - { - m_bUseAutoPF = bUse; - //if (!m_bUseAutoPF && CECIntelligentRoute.Instance().IsUsageTrace()) - //{ - // CECIntelligentRoute.Instance().ResetSearch(); - //} - } - public bool GetUseAutoPF() - { - return m_bUseAutoPF; - } - public bool IsAutoPF() - { - return false; - } - - public void SetActionDone(bool bActionDone) { m_bActionDone = bActionDone; } - - public void OnTargetMissing() - { - StopMove(true); - if ((m_pTraceObject.GetTraceType() == TraceObjectType.TRACE_NPC) || (m_pTraceObject.GetTraceType() == TraceObjectType.TRACE_PLAYER)) - { - m_pTraceObject.OnTargetMissing(); - } - //else if (m_pTraceObject.GetTraceReason() == Trace_reason.TRACE_SPELL) - //{ - // m_pHost.m_pPrepSkill = null; - //} - } - - public void OnTouchTarget() - { - StopMove(true); - m_bActionDone = m_pTraceObject.OnTouched(); - } - public bool CanTouch() - { - //CECSkill pPrepSkill = m_pHost.m_pPrepSkill; - CheckPrepSkill(); - bool result = m_pTraceObject.CanTouchFrom(m_pHost.GetPos()); - //m_pHost.m_pPrepSkill = pPrepSkill; - return result; - } - // Attributes - - protected bool m_bHaveMoved; // Have moved flag - protected bool m_bMeetSlide; // true, meet slide - protected bool m_bCheckTouch; // Check whether touch target in this frame - protected A3DVECTOR3 m_vCurDirH; // Current move direction - protected bool m_bReadyCancel; // true, ready to cancel - protected bool m_bMoreClose; // Move close flag - protected bool m_bForceAttack; // Force attack flag - protected CECSkill m_pPrepSkill; // Skill prepared to be casted - protected bool m_bActionDone; // ĿΪɹ - protected bool m_bShouldResetUseAutoPF; - protected bool m_bUseAutoPFResetValue; - protected bool m_bUseAutoPF; // Use CECIntelligentRoute::Search - protected uint m_dwAutoPFNextCheckTime; // ´μʱ - - protected CECTracedObject m_pTraceObject; // traceĿ - - // Operations - - // On first tick - protected virtual void OnFirstTick() - { - m_pHost.m_iMoveMode = (int)MoveMode.MOVE_MOVE; - m_bHaveMoved = false; - } - - // Trace on ground - protected bool Trace_Walk(float fDeltaTime) - { - A3DVECTOR3 vCurPos = m_pHost.GetPos(); - A3DVECTOR3 vTargetPos = GetCurMovingDest(); - CDR_INFO cdr = m_pHost.m_CDRInfo; - - if (m_pHost.m_iMoveMode == (int)MoveMode.MOVE_SLIDE) - { - m_pHost.PlayAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false, 200, false); - - // This will cause stop moming after we slide down. - A3DVECTOR3 vDir = vTargetPos - vCurPos; - vDir.y = 0; - vDir.Normalize(); - - float fMaxSpeedV = 0f; - m_bMeetSlide = m_pHost.m_MoveCtrl.MeetSlope(vDir, fMaxSpeedV); - EC_Utility.a_ClampFloor(cdr.fYVel, -fMaxSpeedV); - - if (!vDir.IsZero()) - m_vCurDirH = vDir; - - vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDirH, m_pHost.GetGroundSpeed(), fDeltaTime); - if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3) - { - m_pHost.m_MoveCtrl.SetSlideLock(true); - m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_SLIDE); - m_bFinished = true; + return m_pHost.GetPos(); } else { + return (pObject as EC_ElsePlayer).GetServerPos(); + } + } + + public override bool OnTouched() + { + bool bActionDone = false; + if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) + { + if (m_iObjectId == 0 || m_iObjectId == m_pHost.GetCharacterID()) + { + // Handle special case + //ASSERT(m_iReason == CECHPWorkTrace::TRACE_SPELL); + //if (!m_pHost.CannotAttack()) + //{ + // if (m_pHost.CastSkill(m_iObjectId, m_bForceAttack, null)) + // bActionDone = true; + //} + //else + //{ + // m_pHost.m_pPrepSkill = null; + //} + //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- special case- TRACE_SPELL"); + return bActionDone; + } + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + { + if (m_iObjectId == m_pHost.m_idSelTarget && + m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1) + { + byte byPVPMask = EC_Utility.glb_BuildPVPMask(m_bForceAttack); + UnityGameSession.c2s_CmdNormalAttack(byPVPMask); + m_pHost.m_bPrepareFight = true; + bActionDone = true; + //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_ATTACK"); + } + } + //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_SPELL"); + // if (!m_pHost.CastSkill(m_iObjectId, m_bForceAttack, GetTargetObject())) + // { + // m_pHost.m_pPrepSkill = null; + // } + // else + // { + // bActionDone = true; + // } + //} + else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) + { + // Visite other's booth, send hello message to him + //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_TALK"); + UnityGameSession.c2s_CmdNPCSevHello(m_iObjectId); + bActionDone = true; + } + } + return bActionDone; + } + + public override CECTracedObject Clone() + { + return new CECTracedPlayer(this); + } + + public override bool IsTargetMissing() + { + if (base.IsTargetMissing()) + { + return true; + } + EC_Player pPlayer = GetTargetObject() as EC_Player; + if (pPlayer.IsElsePlayer()) + { + if (pPlayer.IsDead()) + { + //if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // CECSkill pSkill = m_pHost.m_pPrepSkill; + // if (pSkill && pSkill.GetTargetType() == 2) + // { + // return false; + // } + //} + return true; + } + } + return false; + } + }; + + public class CECTracedMatter : CECTracedObject + { + + public CECTracedMatter(int type, int id, CECHostPlayer pHost, int ireason) : base(type, id, pHost, ireason) + { + + } + public CECTracedMatter(CECTracedMatter rhs) : base(rhs) + { + + } + + public override bool OnTargetMissing() + { + return false; + } + + public override A3DVECTOR3 GetTargetPos() + { + return GetTargetObject().GetPos(); + } + + public override bool OnTouched() + { + bool bActionDone = false; + //if (GPDataTypeHelper.ISMATTERID(m_iObjectId)) + //{ + // if (m_pHost.GetProfession() == PROF_GHOST && m_pHost.IsInvisible()) + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CANNOT_USE_WHEN_INVISIBLE); + // return bActionDone; + // } + // CECMatter* pMatter = (CECMatter*)GetTargetObject(); + + // if (m_iReason == CECHPWorkTrace::TRACE_PICKUP) + // { + // // Check whether we have enougth place to hold this item or money + // a_LogOutput(1, "[NormalATK]- CECTracedMatter- OnTouched- TRACE_PICKUP"); + // if (m_pHost.CanTakeItem(pMatter.GetTemplateID(), 1)) + // { + // // Send pickup asking and wait response command + // g_pGame.GetGameSession().c2s_CmdPickup(m_iObjectId, pMatter.GetTemplateID()); + // bActionDone = true; + // } + // else + // { + // // Print a notify message + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_PACKISFULL); + // } + // } + // else + // { // m_iReason == TRACE_GATHER + // int tidMatter = pMatter.GetTemplateID(); + // a_LogOutput(1, "[NormalATK]- CECTracedMatter- OnTouched- TRACE_GATHER"); + // // Check mine level requirement + // if (m_pHost.GetBasicProps().iLevel < pMatter.GetLevelReq()) + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_LEVELTOOLOW); + // return bActionDone; + // } + + // // Check whether we have a mine tool + // int iPack, iIndex, idTool; + // if (m_pHost.FindMineTool(tidMatter, &iPack, &iIndex, &idTool)) + // { + // DATA_TYPE DataType; + // const MINE_ESSENCE* pData = (const MINE_ESSENCE*)g_pGame.GetElementDataMan().get_data_ptr(pMatter.GetTemplateID(), ID_SPACE_ESSENCE, DataType); + // if (DataType != DT_MINE_ESSENCE) + // { + // ASSERT(DataType == DT_MINE_ESSENCE); + // return bActionDone; + // } + + // if (m_pHost.GetCoolTime(GP_CT_PLAYER_GATHER)) + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CMD_INCOOLTIME); + // } + // else + // { + // // Send gather asking and wait response command + // g_pGame.GetGameSession().c2s_CmdGatherMaterial(m_iObjectId, iPack, iIndex, idTool, pData.task_in); + // } + // } + // else + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_NEEDTOOL); + // } + // } + //} + return bActionDone; + } + + public override CECTracedObject Clone() + { + return new CECTracedMatter(this); + } + }; + public class CECHPWorkTrace : CECHPWork + { + // Trace reason + public static class Trace_reason + { + public const int TRACE_NONE = -1, + TRACE_ATTACK = 0, // Normal attack + TRACE_PICKUP = 1, // Pickup object + TRACE_TALK = 2, // Go to talk + TRACE_SPELL = 3, // Cast magic + TRACE_GATHER = 4; // Gather object + } + // Constructor and Destructor + public CECHPWorkTrace(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_TRACEOBJECT, pWorkMan) + { + m_dwMask = Work_mask.MASK_TRACEOBJECT; + m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_FLYOFF | Work_mask.MASK_FREEFALL | + Work_mask.MASK_FOLLOW | Work_mask.MASK_USEITEM; + + Reset(); + } + + // Change trace target + //void ChangeTarget(int idTarget, int iReason, bool bUseAutoPF=false); + // 趨traceobject + public void SetTraceTarget(CECTracedObject pTraceObj, bool bUseAutoPF = false) + { + ResetUseAutoPF(bUseAutoPF); + if (!pTraceObj.GetTargetObject() || pTraceObj.GetObjectID() == m_pHost.GetCharacterID()) + { + // This is special case + ReplaceTarget(pTraceObj); + return; + } + int idTarget = pTraceObj.GetObjectID(); + if (!GPDataTypeHelper.ISPLAYERID(idTarget) && !GPDataTypeHelper.ISNPCID(idTarget) && !GPDataTypeHelper.ISMATTERID(idTarget)) + { + return; + } + CECObject pObject = pTraceObj.GetTargetObject(); + if (!pObject) + { + //delete pTraceObj; + return; + } + ReplaceTarget(pTraceObj); + if (m_pTraceObject.GetTargetObject()) + { + A3DVECTOR3 vDirH = pTraceObj.GetTargetPos() - m_pHost.GetPos(); + vDirH.y = 0.0f; + vDirH.Normalize(); + m_vCurDirH = !vDirH.IsZero() ? vDirH : m_vCurDirH = GPDataTypeHelper.g_vAxisZ; + } + } + + public CECTracedObject CreatTraceTarget(int iTraceObjId, int iReason, bool bForceAttack = false) + { + if (GPDataTypeHelper.ISPLAYERID(iTraceObjId)) + { + return new CECTracedPlayer(TraceObjectType.TRACE_PLAYER, iTraceObjId, m_pHost, iReason, bForceAttack); + } + else if (GPDataTypeHelper.ISNPCID(iTraceObjId)) + { + return new CECTracedNPC(TraceObjectType.TRACE_NPC, iTraceObjId, m_pHost, iReason, bForceAttack); + } + //else if (GPDataTypeHelper.ISMATTERID(iTraceObjId)) + //{ + // return new CECTracedMatter(TraceObjectType.TRACE_MATTER, iTraceObjId, m_pHost, iReason); + //} + return null; + } + + // Tick routine + public override bool Tick(float dwDeltaTime) + { + base.Tick(dwDeltaTime); + + CheckPrepSkill(); + + UpdateResetUseAutoPF(); + UpdateUseAutoPF(); + + // m_bFinished flag may be set both in OnFirstTick() and CheckPrepSkill(), + // so check it here ! + if (m_bFinished) + { + return true; + } + if (m_pTraceObject.IsTargetMissing()) + { + OnTargetMissing(); + return true; + } + + if (m_bCheckTouch) + { + if (IsGoodTimeToTouch()) + { + //OnTouchTarget(); + //return true; + if (m_pTraceObject.CanTouchFrom(m_pHost.GetPos())) + { + OnTouchTarget(); + return true; + } + } + } + m_bCheckTouch = true; + + //return true; // TO DO: remove later + if (!m_pHost.IsRooting()) + { + // Continue tracing object + float fDeltaTime = dwDeltaTime /** 0.001f*/; + if (m_pHost.m_iMoveEnv == EC_Player.Move_environment.MOVEENV_GROUND) + { + // Play appropriate actions + if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_TRICK_RUN) && + m_pHost.m_iMoveMode != (int)MoveMode.MOVE_SLIDE) + { + int iAction = m_pHost.GetMoveStandAction(true); + m_pHost.PlayAction(iAction, false, 200, false); + } + + Trace_Walk(fDeltaTime); + } + else // (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER) + { + m_pHost.ResetJump(); + + // Play appropriate actions + int iAction = m_pHost.GetMoveStandAction(true); + m_pHost.PlayAction(iAction, false, 200, false); + + Trace_FlySwim(fDeltaTime); + } + + m_bHaveMoved = true; + } + + return true; + } + // Reset work + public override void Reset() + { + base.Reset(); + + m_bHaveMoved = false; + m_bMeetSlide = false; + m_bCheckTouch = true; + m_bReadyCancel = false; + m_bMoreClose = false; + //m_pPrepSkill = null; + m_bForceAttack = false; + m_bActionDone = false; + ClearResetUseAutoPF(); + m_bUseAutoPF = false; + m_dwAutoPFNextCheckTime = 0; + m_pTraceObject = null; + } + // Work is cancel + public override void Cancel() + { + //if (m_pHost.m_pPrepSkill && m_pTraceObject.GetTraceReason() == Trace_reason.TRACE_SPELL) + // m_pHost.m_pPrepSkill = null; + + ClearResetUseAutoPF(); + if (GetUseAutoPF()) + { + SetUseAutoPF(false); + } + //m_pHost.StopModelMove(); + base.Cancel(); + + //AP_ActionEvent(m_bActionDone ? AP_EVENT_TRACEOK : AP_EVENT_MOVEFINISHED, m_pTraceObject.GetTraceReason()); + } + + // This work is do player moving ? + public override bool IsMoving() { return true; } + // Copy work data + public override bool CopyData(CECHPWork pWork) + { + if (!base.CopyData(pWork)) + return false; + + CECHPWorkTrace pSrc = (CECHPWorkTrace)pWork; + + m_bHaveMoved = pSrc.m_bHaveMoved; + m_bMeetSlide = pSrc.m_bMeetSlide; + m_bCheckTouch = pSrc.m_bCheckTouch; + m_bReadyCancel = pSrc.m_bReadyCancel; + m_bMoreClose = pSrc.m_bMoreClose; + m_vCurDirH = pSrc.m_vCurDirH; + //m_pPrepSkill = pSrc.m_pPrepSkill; + m_bForceAttack = pSrc.m_bForceAttack; + m_bActionDone = pSrc.m_bActionDone; + m_bShouldResetUseAutoPF = pSrc.m_bShouldResetUseAutoPF; + m_bUseAutoPFResetValue = pSrc.m_bUseAutoPFResetValue; + m_bUseAutoPF = pSrc.m_bUseAutoPF; + m_dwAutoPFNextCheckTime = pSrc.m_dwAutoPFNextCheckTime; + + //delete m_pTraceObject; + m_pTraceObject = pSrc.m_pTraceObject.Clone(); + + return true; + } + + // User press cancel button + public void PressCancel() + { + m_bReadyCancel = true; + //if (m_pTraceObject.GetTraceReason() == TRACE_SPELL) + // m_pHost.m_pPrepSkill = NULL; + } + // Set move close flag + public void SetMoveCloseFlag(bool bMoveClose) { m_pTraceObject.SetMoveCloseFlag(bMoveClose); } + + // Set / Get force attack flag + public void SetForceAttack(bool bTrue) { m_bForceAttack = bTrue; } + public bool GetForceAttack() { return m_bForceAttack; } + // Set / Get prepared skill + public void SetPrepSkill(CECSkill pSkill) { /*m_pPrepSkill = pSkill;*/ } + public CECSkill GetPrepSkill() { /*return m_pPrepSkill;*/ return null; } + // Get target ID + public int GetTarget() { return m_pTraceObject.GetObjectID(); } + // Get trace reason + public int GetTraceReason() { return m_pTraceObject.GetTraceReason(); } + // AutoPF + public void SetUseAutoPF(bool bUse) + { + m_bUseAutoPF = bUse; + //if (!m_bUseAutoPF && CECIntelligentRoute.Instance().IsUsageTrace()) + //{ + // CECIntelligentRoute.Instance().ResetSearch(); + //} + } + public bool GetUseAutoPF() + { + return m_bUseAutoPF; + } + public bool IsAutoPF() + { + return false; + } + + public void SetActionDone(bool bActionDone) { m_bActionDone = bActionDone; } + + public void OnTargetMissing() + { + StopMove(true); + if ((m_pTraceObject.GetTraceType() == TraceObjectType.TRACE_NPC) || (m_pTraceObject.GetTraceType() == TraceObjectType.TRACE_PLAYER)) + { + m_pTraceObject.OnTargetMissing(); + } + //else if (m_pTraceObject.GetTraceReason() == Trace_reason.TRACE_SPELL) + //{ + // m_pHost.m_pPrepSkill = null; + //} + } + + public void OnTouchTarget() + { + StopMove(true); + m_bActionDone = m_pTraceObject.OnTouched(); + } + public bool CanTouch() + { + //CECSkill pPrepSkill = m_pHost.m_pPrepSkill; + CheckPrepSkill(); + bool result = m_pTraceObject.CanTouchFrom(m_pHost.GetPos()); + //m_pHost.m_pPrepSkill = pPrepSkill; + return result; + } + // Attributes + + protected bool m_bHaveMoved; // Have moved flag + protected bool m_bMeetSlide; // true, meet slide + protected bool m_bCheckTouch; // Check whether touch target in this frame + protected A3DVECTOR3 m_vCurDirH; // Current move direction + protected bool m_bReadyCancel; // true, ready to cancel + protected bool m_bMoreClose; // Move close flag + protected bool m_bForceAttack; // Force attack flag + protected CECSkill m_pPrepSkill; // Skill prepared to be casted + protected bool m_bActionDone; // ĿΪɹ + protected bool m_bShouldResetUseAutoPF; + protected bool m_bUseAutoPFResetValue; + protected bool m_bUseAutoPF; // Use CECIntelligentRoute::Search + protected uint m_dwAutoPFNextCheckTime; // ´μʱ + + protected CECTracedObject m_pTraceObject; // traceĿ + + // Operations + + // On first tick + protected virtual void OnFirstTick() + { + m_pHost.m_iMoveMode = (int)MoveMode.MOVE_MOVE; + m_bHaveMoved = false; + } + + // Trace on ground + protected bool Trace_Walk(float fDeltaTime) + { + A3DVECTOR3 vCurPos = m_pHost.GetPos(); + A3DVECTOR3 vTargetPos = GetCurMovingDest(); + CDR_INFO cdr = m_pHost.m_CDRInfo; + + if (m_pHost.m_iMoveMode == (int)MoveMode.MOVE_SLIDE) + { + m_pHost.PlayAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false, 200, false); + + // This will cause stop moming after we slide down. + A3DVECTOR3 vDir = vTargetPos - vCurPos; + vDir.y = 0; + vDir.Normalize(); + + float fMaxSpeedV = 0f; + m_bMeetSlide = m_pHost.m_MoveCtrl.MeetSlope(vDir, fMaxSpeedV); + EC_Utility.a_ClampFloor(cdr.fYVel, -fMaxSpeedV); + + if (!vDir.IsZero()) + m_vCurDirH = vDir; + + vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDirH, m_pHost.GetGroundSpeed(), fDeltaTime); + if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3) + { + m_pHost.m_MoveCtrl.SetSlideLock(true); + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_SLIDE); + m_bFinished = true; + } + else + { + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + //if (GetUseAutoPF() && CECIntelligentRoute::Instance().IsMoveOn()) + //{ + // CECIntelligentRoute::Instance().OnPlayerPosChange(vCurPos); + //} + m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 2, GPDataTypeHelper.g_vOrigin, EC_Utility.ToA3DVECTOR3(cdr.vAbsVelocity), (int)GPMoveMode.GP_MOVE_SLIDE); + } + } + else if (!m_bMeetSlide) + { + int iMoveMode = m_pHost.m_bWalkRun ? (int)GPMoveMode.GP_MOVE_RUN : (int)GPMoveMode.GP_MOVE_WALK; + if (m_pHost.IsJumping()) + iMoveMode = (int)GPMoveMode.GP_MOVE_JUMP; + else if (!m_pHost.m_GndInfo.bOnGround) + iMoveMode = (int)GPMoveMode.GP_MOVE_FALL; + + if (m_pHost.m_GndInfo.bOnGround) + { + if (m_bReadyCancel) + { + StopMove(true); + return true; + } + + // Ajust direction only when player on ground + A3DVECTOR3 vDirH = vTargetPos - vCurPos; + A3DVECTOR3 v = A3DFuncs.a3d_Normalize(vDirH); + if (Math.Abs(v.y) > 0.9848f) + { + PressCancel(); + return true; + } + + vDirH.y = 0.0f; + vDirH.Normalize(); + if (!vDirH.IsZero()) + m_vCurDirH = vDirH; + } + + vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDirH, 1f/*m_pHost.GetGroundSpeed()*/, fDeltaTime, m_pHost.m_fVertSpeed); + Debug.LogError(vCurPos); m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); //if (GetUseAutoPF() && CECIntelligentRoute::Instance().IsMoveOn()) //{ // CECIntelligentRoute::Instance().OnPlayerPosChange(vCurPos); //} - m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 2, GPDataTypeHelper.g_vOrigin, EC_Utility.ToA3DVECTOR3(cdr.vAbsVelocity), (int)GPMoveMode.GP_MOVE_SLIDE); - } - } - else if (!m_bMeetSlide) - { - int iMoveMode = m_pHost.m_bWalkRun ? (int)GPMoveMode.GP_MOVE_RUN : (int)GPMoveMode.GP_MOVE_WALK; - if (m_pHost.IsJumping()) - iMoveMode = (int)GPMoveMode.GP_MOVE_JUMP; - else if (!m_pHost.m_GndInfo.bOnGround) - iMoveMode = (int)GPMoveMode.GP_MOVE_FALL; - if (m_pHost.m_GndInfo.bOnGround) - { - if (m_bReadyCancel) - { - StopMove(true); - return true; - } + if (cdr.vTPNormal == Vector3.zero) + m_bCheckTouch = false; - // Ajust direction only when player on ground - A3DVECTOR3 vDirH = vTargetPos - vCurPos; - A3DVECTOR3 v = A3DFuncs.a3d_Normalize(vDirH); - if (Math.Abs(v.y) > 0.9848f) + //if (!m_vCurDirH.IsZero()) + //{ + // m_pHost.StartModelMove(m_vCurDirH, g_vAxisY, 0); + //} + + if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3) { + // m_pHost.m_MoveCtrl.SendStopMoveCmd(vCurPos, m_pHost.GetGroundSpeed(), iMoveMode); PressCancel(); - return true; } - - vDirH.y = 0.0f; - vDirH.Normalize(); - if (!vDirH.IsZero()) - m_vCurDirH = vDirH; + else + m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 0, vTargetPos, EC_Utility.ToA3DVECTOR3(cdr.vAbsVelocity), iMoveMode); } - - vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDirH, m_pHost.GetGroundSpeed(), fDeltaTime, m_pHost.m_fVertSpeed); - Debug.LogError(vCurPos); - m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); - //if (GetUseAutoPF() && CECIntelligentRoute::Instance().IsMoveOn()) - //{ - // CECIntelligentRoute::Instance().OnPlayerPosChange(vCurPos); - //} - - if (cdr.vTPNormal == Vector3.zero) - m_bCheckTouch = false; - - //if (!m_vCurDirH.IsZero()) - //{ - // m_pHost.StartModelMove(m_vCurDirH, g_vAxisY, 0); - //} - - if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3) + else // m_bMeetSlide == true { - // m_pHost.m_MoveCtrl.SendStopMoveCmd(vCurPos, m_pHost.GetGroundSpeed(), iMoveMode); - PressCancel(); + if (m_bHaveMoved) + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_SLIDE); + + m_bFinished = true; } - else - m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 0, vTargetPos, EC_Utility.ToA3DVECTOR3(cdr.vAbsVelocity), iMoveMode); + return true; } - else // m_bMeetSlide == true + // Trace in air and water + public bool Trace_FlySwim(float fDeltaTime) { - if (m_bHaveMoved) - m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_SLIDE); - - m_bFinished = true; + return true; } - return true; - } - // Trace in air and water - public bool Trace_FlySwim(float fDeltaTime) - { - return true; - } - // Stop move when touch target - public void StopMove(bool bFinish) - { - // If 'trace' work was transfered from a work which - // needs moving (such as 'move to' work) and we touch the target - // immediately (m_bHaveMoved = false), we must need to send 'stop move' - // command - if (m_bHaveMoved || !m_pHost.m_MoveCtrl.IsStop()) - m_pHost.m_MoveCtrl.SendStopMoveCmd(); - - m_pHost.m_vVelocity.Clear(); - //m_pHost.StopModelMove(); - - if (bFinish) + // Stop move when touch target + public void StopMove(bool bFinish) { - m_bFinished = true; + // If 'trace' work was transfered from a work which + // needs moving (such as 'move to' work) and we touch the target + // immediately (m_bHaveMoved = false), we must need to send 'stop move' + // command + if (m_bHaveMoved || !m_pHost.m_MoveCtrl.IsStop()) + m_pHost.m_MoveCtrl.SendStopMoveCmd(); + + m_pHost.m_vVelocity.Clear(); + //m_pHost.StopModelMove(); + + if (bFinish) + { + m_bFinished = true; + } } - } - // Handle the case that target died when host is tracing it - public bool OnTargetDied(CECObject pTarget) - { - return true; - } - // Is valid time to touch target ? - public bool IsGoodTimeToTouch() - { - if (m_pHost.IsJumping()) + // Handle the case that target died when host is tracing it + public bool OnTargetDied(CECObject pTarget) { - return false; + return true; } - return true; - } - // Check prepare skill - public void CheckPrepSkill() - { - - } - public bool GetTargetCurPos(A3DVECTOR3 pos) - { - return true; - } - public A3DVECTOR3 GetCurMovingDest() - { - return m_pTraceObject.GetTargetPos(); - } - public void UpdateUseAutoPF() - { - - } - - public void ReplaceTarget(CECTracedObject ptraceobj) - { - //if (m_pTraceObject) - //{ - // delete m_pTraceObject; - //} - m_pTraceObject = ptraceobj; - } - - public void ResetUseAutoPF(bool bUseAutoPF) - { - m_bShouldResetUseAutoPF = true; - m_bUseAutoPFResetValue = bUseAutoPF; - } - public void UpdateResetUseAutoPF() - { - if (!m_bShouldResetUseAutoPF) + // Is valid time to touch target ? + public bool IsGoodTimeToTouch() { - return; + if (m_pHost.IsJumping()) + { + return false; + } + return true; } - //# ifdef SHOW_AUTOMOVE_FOOTPRINTS - // g_AutoPFFollowPoints.clear(); - // g_AutoPFPathPoints.clear(); - //#endif - //CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkTrace); - //CECIntelligentRoute::Instance().ResetSearch(); - SetUseAutoPF(m_bUseAutoPFResetValue); - ClearResetUseAutoPF(); - } - public void ClearResetUseAutoPF() - { - m_bShouldResetUseAutoPF = false; - m_bUseAutoPFResetValue = false; - } -}; \ No newline at end of file + // Check prepare skill + public void CheckPrepSkill() + { + + } + public bool GetTargetCurPos(A3DVECTOR3 pos) + { + return true; + } + public A3DVECTOR3 GetCurMovingDest() + { + return m_pTraceObject.GetTargetPos(); + } + public void UpdateUseAutoPF() + { + + } + + public void ReplaceTarget(CECTracedObject ptraceobj) + { + //if (m_pTraceObject) + //{ + // delete m_pTraceObject; + //} + m_pTraceObject = ptraceobj; + } + + public void ResetUseAutoPF(bool bUseAutoPF) + { + m_bShouldResetUseAutoPF = true; + m_bUseAutoPFResetValue = bUseAutoPF; + } + public void UpdateResetUseAutoPF() + { + if (!m_bShouldResetUseAutoPF) + { + return; + } + //# ifdef SHOW_AUTOMOVE_FOOTPRINTS + // g_AutoPFFollowPoints.clear(); + // g_AutoPFPathPoints.clear(); + //#endif + //CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkTrace); + //CECIntelligentRoute::Instance().ResetSearch(); + SetUseAutoPF(m_bUseAutoPFResetValue); + ClearResetUseAutoPF(); + } + public void ClearResetUseAutoPF() + { + m_bShouldResetUseAutoPF = false; + m_bUseAutoPFResetValue = false; + } + }; +} \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs index edf7b5a694..53324a201c 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs @@ -5,7 +5,7 @@ using System; using System.Runtime.InteropServices; using UnityEngine; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { namespace BrewMonster.Managers { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs index 4f8844f226..cd90feb0d1 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using UnityEngine; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public static class EC_Inventory diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs index 70ad7df4c7..4710a728c1 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs @@ -7,7 +7,7 @@ using BrewMonster.Network; using BrewMonster; using ModelRenderer.Scripts.GameData; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public class EC_InventoryUI : MonoBehaviour { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem.cs index 7b63d045a0..2c8487e8b1 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem.cs @@ -8,7 +8,7 @@ using ModelRenderer.Scripts.Common; using ModelRenderer.Scripts.GameData; using UnityEngine; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public class InventoryItemData { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrType.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrType.cs index d42c58746d..74ad3a5077 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrType.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrType.cs @@ -3,7 +3,7 @@ using UnityEngine; using ModelRenderer.Scripts.GameData; using BrewMonster; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public static class EC_IvtrType { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManMatter.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManMatter.cs index 863fb742f4..8263668a53 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManMatter.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManMatter.cs @@ -1,10 +1,6 @@ -using BrewMonster; -using BrewMonster.Network; +using BrewMonster.Scripts; using CSNetwork; using CSNetwork.GPDataType; -using CSNetwork.Protocols; -using CSNetwork.Protocols.RPCData; -using PerfectWorld.Scripts.Player; using System; using System.Collections; using System.Collections.Generic; @@ -12,250 +8,246 @@ using System.Linq; using System.Runtime.InteropServices; using TMPro; using UnityEngine; -using UnityEngine.SceneManagement; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Managers { - namespace BrewMonster.Managers + /// + /// Matter Manager - Handles matter data storage and provides access to other classes + /// + /// Usage Examples: + /// // Get matter manager instance + /// var matterManager = EC_ManMessageMono.Instance.GetECManMatter; + /// + /// // Get specific matter data + /// var matterData = matterManager.GetMatterData(12345); + /// + /// // Get individual fields + /// int? mid = matterManager.GetMatterId(12345); + /// int? tid = matterManager.GetMatterTid(12345); + /// A3DVECTOR3? pos = matterManager.GetMatterPosition(12345); + /// byte? state = matterManager.GetMatterState(12345); + /// + /// // Find matters by criteria + /// int[] mattersByTid = matterManager.FindMattersByTid(100); + /// int[] mattersByState = matterManager.FindMattersByState(1); + /// int[] nearbyMatters = matterManager.FindMattersNearPosition(new A3DVECTOR3(0,0,0), 10.0f); + /// + [Serializable] + public class EC_ManMatter : IMsgHandler { - /// - /// Matter Manager - Handles matter data storage and provides access to other classes - /// - /// Usage Examples: - /// // Get matter manager instance - /// var matterManager = EC_ManMessageMono.Instance.GetECManMatter; - /// - /// // Get specific matter data - /// var matterData = matterManager.GetMatterData(12345); - /// - /// // Get individual fields - /// int? mid = matterManager.GetMatterId(12345); - /// int? tid = matterManager.GetMatterTid(12345); - /// A3DVECTOR3? pos = matterManager.GetMatterPosition(12345); - /// byte? state = matterManager.GetMatterState(12345); - /// - /// // Find matters by criteria - /// int[] mattersByTid = matterManager.FindMattersByTid(100); - /// int[] mattersByState = matterManager.FindMattersByState(1); - /// int[] nearbyMatters = matterManager.FindMattersNearPosition(new A3DVECTOR3(0,0,0), 10.0f); - /// - [Serializable] - public class EC_ManMatter : IMsgHandler + public int HandlerId => (int)MANAGER_INDEX.MAN_MATTER; + + // Storage for matter data that players can access later + private Dictionary matterDataStorage = new Dictionary(); + public bool ProcessMessage(ECMSG Msg) { - public int HandlerId => (int)MANAGER_INDEX.MAN_MATTER; - - // Storage for matter data that players can access later - private Dictionary matterDataStorage = new Dictionary(); - public bool ProcessMessage(ECMSG Msg) + if (Msg.iSubID == 0) { - if (Msg.iSubID == 0) + switch ((int)Msg.dwMsg) { - switch ((int)Msg.dwMsg) - { - case int value when value == EC_MsgDef.MSG_MM_MATTERINFO: - { - Debug.Log("MATTERINFO"); - //ENABLE LATER: It fetch all matters in the game world, causing performance issues - //OnMsgMatterInfo(Msg); - break; - } - case int value when value == EC_MsgDef.MSG_MM_MATTERENTWORLD: - { - Debug.Log("MATTERENTWORLD"); - OnMsgMatterEnterWorld(Msg); - break; - } - } - } - else - { - - } - return true; - } - - public void OnMsgMatterInfo(ECMSG Msg) - { - byte[] data = (byte[])Msg.dwParam1; - - try - { - // Parse the data structure: count + info_matter array - int offset = 0; - - // Read count (int) - int count = BitConverter.ToInt32(data, offset); - offset += sizeof(int); - - Debug.Log($"MATTERINFO: Received {count} matter entries"); - - // Parse each info_matter entry - for (int i = 0; i < count; i++) - { - // Parse info_matter structure - info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes(data, offset); - offset += Marshal.SizeOf(typeof(info_matter)); - - // Store the matter data for later player access - matterDataStorage[matterInfo.mid] = matterInfo; - - Debug.Log($"Matter info - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}"); - - // Spawn cube for this matter since it has entered the world - SpawnMatterCube(matterInfo.mid); - } - } - catch (Exception ex) - { - Debug.LogError($"Failed to parse matter info data: {ex.Message}"); + case int value when value == EC_MsgDef.MSG_MM_MATTERINFO: + { + Debug.Log("MATTERINFO"); + //ENABLE LATER: It fetch all matters in the game world, causing performance issues + //OnMsgMatterInfo(Msg); + break; + } + case int value when value == EC_MsgDef.MSG_MM_MATTERENTWORLD: + { + Debug.Log("MATTERENTWORLD"); + OnMsgMatterEnterWorld(Msg); + break; + } } } - - public void OnMsgMatterEnterWorld(ECMSG Msg) + else { - byte[] data = (byte[])Msg.dwParam1; - - try + + } + return true; + } + + public void OnMsgMatterInfo(ECMSG Msg) + { + byte[] data = (byte[])Msg.dwParam1; + + try + { + // Parse the data structure: count + info_matter array + int offset = 0; + + // Read count (int) + int count = BitConverter.ToInt32(data, offset); + offset += sizeof(int); + + Debug.Log($"MATTERINFO: Received {count} matter entries"); + + // Parse each info_matter entry + for (int i = 0; i < count; i++) { - // Parse the byte array into info_matter structure - info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes(data); - + // Parse info_matter structure + info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes(data, offset); + offset += Marshal.SizeOf(typeof(info_matter)); + // Store the matter data for later player access matterDataStorage[matterInfo.mid] = matterInfo; - - Debug.Log($"Matter entered world - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}"); - - // Notify pickupItem to create cube for this matter - NotifyPickupItem(matterInfo.mid); - } - catch (Exception ex) - { - Debug.LogError($"Failed to parse matter data: {ex.Message}"); + + Debug.Log($"Matter info - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}"); + + // Spawn cube for this matter since it has entered the world + SpawnMatterCube(matterInfo.mid); } } - - private void SpawnMatterCube(int matterId) + catch (Exception ex) { - // Find the pickupItem component in the scene and create cube for this specific matter - pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType(); - if (pickupScript != null) - { - pickupScript.CreateMatterCube(matterId); - } - else - { - Debug.LogWarning("pickupItem component not found in scene - cannot spawn matter cube"); - } + Debug.LogError($"Failed to parse matter info data: {ex.Message}"); } - - private void NotifyPickupItem(int matterId) + } + + public void OnMsgMatterEnterWorld(ECMSG Msg) + { + byte[] data = (byte[])Msg.dwParam1; + + try { - // Find the pickupItem component in the scene and update cubes - pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType(); - if (pickupScript != null) - { - pickupScript.UpdateMatterCubes(); - } + // Parse the byte array into info_matter structure + info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes(data); + + // Store the matter data for later player access + matterDataStorage[matterInfo.mid] = matterInfo; + + Debug.Log($"Matter entered world - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}"); + + // Notify pickupItem to create cube for this matter + NotifyPickupItem(matterInfo.mid); } - - // Public methods for players to access matter data - public info_matter? GetMatterData(int matterId) + catch (Exception ex) { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data : null; + Debug.LogError($"Failed to parse matter data: {ex.Message}"); } - - public Dictionary GetAllMatterData() + } + + private void SpawnMatterCube(int matterId) + { + // Find the pickupItem component in the scene and create cube for this specific matter + pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType(); + if (pickupScript != null) { - return new Dictionary(matterDataStorage); + pickupScript.CreateMatterCube(matterId); } - - public bool HasMatterData(int matterId) + else { - return matterDataStorage.ContainsKey(matterId); + Debug.LogWarning("pickupItem component not found in scene - cannot spawn matter cube"); } - - public void RemoveMatterData(int matterId) + } + + private void NotifyPickupItem(int matterId) + { + // Find the pickupItem component in the scene and update cubes + pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType(); + if (pickupScript != null) { - if (matterDataStorage.ContainsKey(matterId)) - { - matterDataStorage.Remove(matterId); - Debug.Log($"Removed matter data for ID: {matterId}"); - } + pickupScript.UpdateMatterCubes(); } - - public int GetMatterCount() + } + + // Public methods for players to access matter data + public info_matter? GetMatterData(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data : null; + } + + public Dictionary GetAllMatterData() + { + return new Dictionary(matterDataStorage); + } + + public bool HasMatterData(int matterId) + { + return matterDataStorage.ContainsKey(matterId); + } + + public void RemoveMatterData(int matterId) + { + if (matterDataStorage.ContainsKey(matterId)) { - return matterDataStorage.Count; + matterDataStorage.Remove(matterId); + Debug.Log($"Removed matter data for ID: {matterId}"); } - - // Convenience methods to get specific fields from matter data - public int? GetMatterId(int matterId) + } + + public int GetMatterCount() + { + return matterDataStorage.Count; + } + + // Convenience methods to get specific fields from matter data + public int? GetMatterId(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.mid : null; + } + + public int? GetMatterTid(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.tid : null; + } + + public A3DVECTOR3? GetMatterPosition(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.pos : null; + } + + public byte? GetMatterDir0(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir0 : null; + } + + public byte? GetMatterDir1(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir1 : null; + } + + public byte? GetMatterRadius(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.rad : null; + } + + public byte? GetMatterState(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.state : null; + } + + public byte? GetMatterValue(int matterId) + { + return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.value : null; + } + + // Get all matter IDs + public int[] GetAllMatterIds() + { + return matterDataStorage.Keys.ToArray(); + } + + // Find matters by template ID (tid) + public int[] FindMattersByTid(int tid) + { + return matterDataStorage.Where(kvp => kvp.Value.tid == tid).Select(kvp => kvp.Key).ToArray(); + } + + // Find matters by state + public int[] FindMattersByState(byte state) + { + return matterDataStorage.Where(kvp => kvp.Value.state == state).Select(kvp => kvp.Key).ToArray(); + } + + // Get matters within a certain distance from a position + public int[] FindMattersNearPosition(A3DVECTOR3 position, float maxDistance) + { + return matterDataStorage.Where(kvp => { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.mid : null; - } - - public int? GetMatterTid(int matterId) - { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.tid : null; - } - - public A3DVECTOR3? GetMatterPosition(int matterId) - { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.pos : null; - } - - public byte? GetMatterDir0(int matterId) - { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir0 : null; - } - - public byte? GetMatterDir1(int matterId) - { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir1 : null; - } - - public byte? GetMatterRadius(int matterId) - { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.rad : null; - } - - public byte? GetMatterState(int matterId) - { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.state : null; - } - - public byte? GetMatterValue(int matterId) - { - return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.value : null; - } - - // Get all matter IDs - public int[] GetAllMatterIds() - { - return matterDataStorage.Keys.ToArray(); - } - - // Find matters by template ID (tid) - public int[] FindMattersByTid(int tid) - { - return matterDataStorage.Where(kvp => kvp.Value.tid == tid).Select(kvp => kvp.Key).ToArray(); - } - - // Find matters by state - public int[] FindMattersByState(byte state) - { - return matterDataStorage.Where(kvp => kvp.Value.state == state).Select(kvp => kvp.Key).ToArray(); - } - - // Get matters within a certain distance from a position - public int[] FindMattersNearPosition(A3DVECTOR3 position, float maxDistance) - { - return matterDataStorage.Where(kvp => - { - float distance = (kvp.Value.pos - position).Magnitude(); - return distance <= maxDistance; - }).Select(kvp => kvp.Key).ToArray(); - } + float distance = (kvp.Value.pos - position).Magnitude(); + return distance <= maxDistance; + }).Select(kvp => kvp.Key).ToArray(); } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs index 0db2223156..c6d322024b 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs @@ -1,10 +1,8 @@ -using BrewMonster; -using BrewMonster.Network; +using BrewMonster.Scripts.Player; using CSNetwork; using CSNetwork.GPDataType; using CSNetwork.Protocols; using CSNetwork.Protocols.RPCData; -using PerfectWorld.Scripts.Player; using System; using System.Collections; using System.Collections.Generic; @@ -13,476 +11,473 @@ using TMPro; using UnityEngine; using UnityEngine.SceneManagement; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Managers { - namespace BrewMonster.Managers + [Serializable] + public class EC_ManPlayer : IMsgHandler { - [Serializable] - public class EC_ManPlayer : IMsgHandler + Dictionary m_UkPlayerTab = new Dictionary(); + Dictionary m_PlayerTab = new Dictionary(); + private readonly object m_csPlayerTab = new object(); + CECHostPlayer m_pHostPlayer; + public int HandlerId => (int)MANAGER_INDEX.MAN_PLAYER; + public bool ProcessMessage(ECMSG Msg) { - Dictionary m_UkPlayerTab = new Dictionary(); - Dictionary m_PlayerTab = new Dictionary(); - private readonly object m_csPlayerTab = new object(); - CECHostPlayer m_pHostPlayer; - public int HandlerId => (int)MANAGER_INDEX.MAN_PLAYER; - public bool ProcessMessage(ECMSG Msg) + Debug.Log("HoangDev: ProcessMessageManPlayer :"); + if (Msg.iSubID == 0) { - Debug.Log("HoangDev: ProcessMessageManPlayer :"); - if (Msg.iSubID == 0) - { - if (GameController.Instance == null) return true; - GameController.Instance.GetHostPlayer().ProcessMessage(Msg); - } - else if (Msg.iSubID < 0) - { - switch ((int)Msg.dwMsg) - { - case int value when value == EC_MsgDef.MSG_PM_PLAYERINFO: - { - OnMsgPlayerInfo(Msg); - break; - } - case int value when value == EC_MsgDef.MSG_PM_PLAYERMOVE: - { - OnMsgPlayerMove(Msg); - break; - } - case int value when value == EC_MsgDef.MSG_PM_PLAYERSTOPMOVE: - { - OnMsgPlayerStopMove(Msg); - break; - } - case int value when value == EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY: - Debug.Log("EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY"); - TransmitMessage(Msg); - break; - } - } - else - { - - } - return true; + if (GameController.Instance == null) return true; + GameController.Instance.GetHostPlayer().ProcessMessage(Msg); } - - public void OnMsgPlayerInfo(ECMSG Msg) + else if (Msg.iSubID < 0) { - int iHostID = Convert.ToInt32(Msg.dwParam3); - int lenghtByte = Marshal.SizeOf(); - byte[] byteArray = new byte[lenghtByte]; - byte[] data = (byte[])Msg.dwParam1; - for (int i = 0; i < lenghtByte; i++) + switch ((int)Msg.dwMsg) { - byteArray[i] = data[i]; - } - int cid = BitConverter.ToInt32(byteArray); - int commandID = Convert.ToInt32(Msg.dwParam2); - switch (commandID) - { - case CommandID.PLAYER_INFO_1: - case CommandID.PLAYER_ENTER_WORLD: - case CommandID.PLAYER_ENTER_SLICE: + case int value when value == EC_MsgDef.MSG_PM_PLAYERINFO: { - if (cid != iHostID) - { - info_player_1 info_Player_1 = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - RoleInfo roleInfo = (RoleInfo)Msg.dwParam4; - ElsePlayerEnter(info_Player_1, commandID, roleInfo); - GameController.Instance.Log("ElsePlayer has join"); - } + OnMsgPlayerInfo(Msg); break; } - case CommandID.SELF_INFO_1: - Debug.Log("SELF_INFO_1"); - cmd_self_info_1 info = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - HostPlayerInfo1(info); + case int value when value == EC_MsgDef.MSG_PM_PLAYERMOVE: + { + OnMsgPlayerMove(Msg); + break; + } + case int value when value == EC_MsgDef.MSG_PM_PLAYERSTOPMOVE: + { + OnMsgPlayerStopMove(Msg); + break; + } + case int value when value == EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY: + Debug.Log("EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY"); + TransmitMessage(Msg); break; - case CommandID.PLAYER_INFO_2: break; - case CommandID.PLAYER_INFO_3: break; - case CommandID.PLAYER_INFO_4: break; + } + } + else + { - case CommandID.PLAYER_INFO_1_LIST: + } + return true; + } + + public void OnMsgPlayerInfo(ECMSG Msg) + { + int iHostID = Convert.ToInt32(Msg.dwParam3); + int lenghtByte = Marshal.SizeOf(); + byte[] byteArray = new byte[lenghtByte]; + byte[] data = (byte[])Msg.dwParam1; + for (int i = 0; i < lenghtByte; i++) + { + byteArray[i] = data[i]; + } + int cid = BitConverter.ToInt32(byteArray); + int commandID = Convert.ToInt32(Msg.dwParam2); + switch (commandID) + { + case CommandID.PLAYER_INFO_1: + case CommandID.PLAYER_ENTER_WORLD: + case CommandID.PLAYER_ENTER_SLICE: + { + if (cid != iHostID) { - byte[] bytes = (byte[])Msg.dwParam1; - cmd_player_info_1_list pCmd = GPDataTypeHelper.FromBytes(bytes); - if (pCmd.count == 0) - { - break; - } - int lenght = Marshal.SizeOf(); - int preSize = 0; - byte[] pDataBuf = null; - preSize += Marshal.SizeOf(); + info_player_1 info_Player_1 = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); RoleInfo roleInfo = (RoleInfo)Msg.dwParam4; - for (int i = 0; i < pCmd.count; i++) - { - pDataBuf = new byte[lenght]; - for (int j = 0; j < pDataBuf.Length; j++) - { - pDataBuf[j] = bytes[preSize + j]; - } - info_player_1 Info = GPDataTypeHelper.FromBytes(pDataBuf); - if (Info.cid != iHostID) - { - EC_ElsePlayer pPlayer = ElsePlayerEnter(Info, commandID, roleInfo); - } + ElsePlayerEnter(info_Player_1, commandID, roleInfo); + GameController.Instance.Log("ElsePlayer has join"); + } + break; + } + case CommandID.SELF_INFO_1: + Debug.Log("SELF_INFO_1"); + cmd_self_info_1 info = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + HostPlayerInfo1(info); + break; + case CommandID.PLAYER_INFO_2: break; + case CommandID.PLAYER_INFO_3: break; + case CommandID.PLAYER_INFO_4: break; - // Calculate player info data size and skip it - int iSize = Marshal.SizeOf(); - if ((Info.state & PlayerNPCState.GP_STATE_ADV_MODE) != 0) - iSize += Marshal.SizeOf() * 2; - - if ((Info.state & PlayerNPCState.GP_STATE_SHAPE) != 0) - iSize += Marshal.SizeOf(); - - if ((Info.state & PlayerNPCState.GP_STATE_EMOTE) != 0) - iSize += Marshal.SizeOf(); - - if ((Info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0) - iSize += Marshal.SizeOf() * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT; - - if ((Info.state & PlayerNPCState.GP_STATE_FACTION) != 0) - iSize += (Marshal.SizeOf() + Marshal.SizeOf()); - - if ((Info.state & PlayerNPCState.GP_STATE_BOOTH) != 0) - iSize += Marshal.SizeOf(); - - //// Parse effect data - if ((Info.state & PlayerNPCState.GP_STATE_EFFECT) != 0) - { - iSize += Marshal.SizeOf(); - byte byNum = bytes[preSize + iSize]; - - if (byNum > 0) - iSize += byNum * Marshal.SizeOf(); - } - - if ((Info.state & PlayerNPCState.GP_STATE_PARIAH) != 0) - iSize += Marshal.SizeOf(); - - if ((Info.state & PlayerNPCState.GP_STATE_IN_MOUNT) != 0) - iSize += Marshal.SizeOf() + Marshal.SizeOf(); - - // Parse bind data - if ((Info.state & PlayerNPCState.GP_STATE_IN_BIND) != 0) - iSize += Marshal.SizeOf() + Marshal.SizeOf(); - - // Parse spouse data - if ((Info.state & PlayerNPCState.GP_STATE_SPOUSE) != 0) - iSize += Marshal.SizeOf(); - - if ((Info.state & PlayerNPCState.GP_STATE_EQUIPDISABLED) != 0) - iSize += Marshal.SizeOf(); - - if ((Info.state & PlayerNPCState.GP_STATE_PLAYERFORCE) != 0) - iSize += Marshal.SizeOf(); - - if ((Info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0) - { - int effectNum = Marshal.ReadInt32(bytes, iSize);//*(int*)(pDataBuf + iSize); - iSize += Marshal.SizeOf(); - - if (effectNum > 0) - iSize += effectNum * (Marshal.SizeOf() + Marshal.SizeOf()); - } - - if ((Info.state & PlayerNPCState.GP_STATE_COUNTRY) != 0) - iSize += Marshal.SizeOf(); - if ((Info.state2 & PlayerNPCState2.GP_STATE2_TITLE) != 0) - iSize += Marshal.SizeOf(); - if ((Info.state2 & PlayerNPCState2.GP_STATE2_REINCARNATION) != 0) - iSize += Marshal.SizeOf(); - if ((Info.state2 & PlayerNPCState2.GP_STATE2_REALM) != 0) - iSize += Marshal.SizeOf(); - if ((Info.state2 & PlayerNPCState2.GP_STATE2_FACTION_PVP_MASK) != 0) - iSize += Marshal.SizeOf(); - - // Goblin refine data - if ((Info.state & PlayerNPCState.GP_STATE_GOBLINREFINE) != 0) - iSize += Marshal.SizeOf(); - - //pDataBuf += iSize; - - preSize += iSize; - } - Debug.LogError("PLAYER_INFO_1_LIST"); + case CommandID.PLAYER_INFO_1_LIST: + { + byte[] bytes = (byte[])Msg.dwParam1; + cmd_player_info_1_list pCmd = GPDataTypeHelper.FromBytes(bytes); + if (pCmd.count == 0) + { break; } - } - } + int lenght = Marshal.SizeOf(); + int preSize = 0; + byte[] pDataBuf = null; + preSize += Marshal.SizeOf(); + RoleInfo roleInfo = (RoleInfo)Msg.dwParam4; + for (int i = 0; i < pCmd.count; i++) + { + pDataBuf = new byte[lenght]; + for (int j = 0; j < pDataBuf.Length; j++) + { + pDataBuf[j] = bytes[preSize + j]; + } + info_player_1 Info = GPDataTypeHelper.FromBytes(pDataBuf); + if (Info.cid != iHostID) + { + EC_ElsePlayer pPlayer = ElsePlayerEnter(Info, commandID, roleInfo); + } - public void OnMsgPlayerMove(ECMSG Msg) - { - int iHostID = Convert.ToInt32(Msg.dwParam3); - cmd_object_move pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - if (pCmd.use_time == 0) - return; - if (pCmd.id != iHostID) - { - EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id); - if (pPlayer) - { - pPlayer.MoveTo(pCmd); + // Calculate player info data size and skip it + int iSize = Marshal.SizeOf(); + if ((Info.state & PlayerNPCState.GP_STATE_ADV_MODE) != 0) + iSize += Marshal.SizeOf() * 2; + + if ((Info.state & PlayerNPCState.GP_STATE_SHAPE) != 0) + iSize += Marshal.SizeOf(); + + if ((Info.state & PlayerNPCState.GP_STATE_EMOTE) != 0) + iSize += Marshal.SizeOf(); + + if ((Info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0) + iSize += Marshal.SizeOf() * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT; + + if ((Info.state & PlayerNPCState.GP_STATE_FACTION) != 0) + iSize += (Marshal.SizeOf() + Marshal.SizeOf()); + + if ((Info.state & PlayerNPCState.GP_STATE_BOOTH) != 0) + iSize += Marshal.SizeOf(); + + //// Parse effect data + if ((Info.state & PlayerNPCState.GP_STATE_EFFECT) != 0) + { + iSize += Marshal.SizeOf(); + byte byNum = bytes[preSize + iSize]; + + if (byNum > 0) + iSize += byNum * Marshal.SizeOf(); + } + + if ((Info.state & PlayerNPCState.GP_STATE_PARIAH) != 0) + iSize += Marshal.SizeOf(); + + if ((Info.state & PlayerNPCState.GP_STATE_IN_MOUNT) != 0) + iSize += Marshal.SizeOf() + Marshal.SizeOf(); + + // Parse bind data + if ((Info.state & PlayerNPCState.GP_STATE_IN_BIND) != 0) + iSize += Marshal.SizeOf() + Marshal.SizeOf(); + + // Parse spouse data + if ((Info.state & PlayerNPCState.GP_STATE_SPOUSE) != 0) + iSize += Marshal.SizeOf(); + + if ((Info.state & PlayerNPCState.GP_STATE_EQUIPDISABLED) != 0) + iSize += Marshal.SizeOf(); + + if ((Info.state & PlayerNPCState.GP_STATE_PLAYERFORCE) != 0) + iSize += Marshal.SizeOf(); + + if ((Info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0) + { + int effectNum = Marshal.ReadInt32(bytes, iSize);//*(int*)(pDataBuf + iSize); + iSize += Marshal.SizeOf(); + + if (effectNum > 0) + iSize += effectNum * (Marshal.SizeOf() + Marshal.SizeOf()); + } + + if ((Info.state & PlayerNPCState.GP_STATE_COUNTRY) != 0) + iSize += Marshal.SizeOf(); + if ((Info.state2 & PlayerNPCState2.GP_STATE2_TITLE) != 0) + iSize += Marshal.SizeOf(); + if ((Info.state2 & PlayerNPCState2.GP_STATE2_REINCARNATION) != 0) + iSize += Marshal.SizeOf(); + if ((Info.state2 & PlayerNPCState2.GP_STATE2_REALM) != 0) + iSize += Marshal.SizeOf(); + if ((Info.state2 & PlayerNPCState2.GP_STATE2_FACTION_PVP_MASK) != 0) + iSize += Marshal.SizeOf(); + + // Goblin refine data + if ((Info.state & PlayerNPCState.GP_STATE_GOBLINREFINE) != 0) + iSize += Marshal.SizeOf(); + + //pDataBuf += iSize; + + preSize += iSize; + } + Debug.LogError("PLAYER_INFO_1_LIST"); + break; } - } } + } - public bool HostPlayerInfo1(cmd_self_info_1 info) + public void OnMsgPlayerMove(ECMSG Msg) + { + int iHostID = Convert.ToInt32(Msg.dwParam3); + cmd_object_move pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + if (pCmd.use_time == 0) + return; + if (pCmd.id != iHostID) { - //bool isDoneWorldRender = false; - //bool isDoneNPCRender = false; - //Action actLoadChar = () => - //{ - // if (!isDoneNPCRender || !isDoneWorldRender) - // { - // return; - // } - // GameController.Instance.InitCharacter(info); - //}; - //string nameScene = "NPCRender"; - //UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) => - //{ - // isDoneNPCRender = value; - // actLoadChar?.Invoke(); - //}); - //nameScene = "WorldRender"; - //UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) => - //{ - // isDoneWorldRender = value; - // actLoadChar?.Invoke(); - //}); - //UnityGameSession.Instance.LoadScene("HoangTest", LoadSceneMode.Single, (value) => - //{ - // isDoneWorldRender = value; - // actLoadChar?.Invoke(); - //}); - GameController.Instance.InitCharacter(info); - return true; - } - - public EC_ElsePlayer ElsePlayerEnter(info_player_1 info, int iCmd, RoleInfo roleInfo) - { - // If this player's id is in unknown table, remove it because this player - // won't be unknown anymore - if (m_UkPlayerTab.TryGetValue(info.cid, out int value)) - { - if (value != 0) // Pair.second != 0 - { - m_UkPlayerTab.Remove(info.cid); - } - } - - int iAppearFlag = (iCmd == (int)CommandID.PLAYER_ENTER_WORLD) ? - (int)PlayerAppearFlag.APPEAR_ENTERWORLD : (int)PlayerAppearFlag.APPEAR_RUNINTOVIEW; - - // Has player been in active player table ? - EC_ElsePlayer pPlayer = GetElsePlayer(info.cid); + EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id); if (pPlayer) { - // This player has existed in player table, call special initial function - // TODO: fix after pPlayer init - pPlayer.Init(roleInfo, info); - return pPlayer; + pPlayer.MoveTo(pCmd); } + } + } - // Create a new player - if (!(pPlayer = CreateElsePlayer(roleInfo, info, iAppearFlag))) + public bool HostPlayerInfo1(cmd_self_info_1 info) + { + //bool isDoneWorldRender = false; + //bool isDoneNPCRender = false; + //Action actLoadChar = () => + //{ + // if (!isDoneNPCRender || !isDoneWorldRender) + // { + // return; + // } + // GameController.Instance.InitCharacter(info); + //}; + //string nameScene = "NPCRender"; + //UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) => + //{ + // isDoneNPCRender = value; + // actLoadChar?.Invoke(); + //}); + //nameScene = "WorldRender"; + //UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) => + //{ + // isDoneWorldRender = value; + // actLoadChar?.Invoke(); + //}); + //UnityGameSession.Instance.LoadScene("HoangTest", LoadSceneMode.Single, (value) => + //{ + // isDoneWorldRender = value; + // actLoadChar?.Invoke(); + //}); + GameController.Instance.InitCharacter(info); + return true; + } + + public EC_ElsePlayer ElsePlayerEnter(info_player_1 info, int iCmd, RoleInfo roleInfo) + { + // If this player's id is in unknown table, remove it because this player + // won't be unknown anymore + if (m_UkPlayerTab.TryGetValue(info.cid, out int value)) + { + if (value != 0) // Pair.second != 0 { - return null; - } - lock (m_csPlayerTab) - { - if (m_PlayerTab.ContainsKey(info.cid)) - { - m_PlayerTab[info.cid] = pPlayer; - } - else - { - m_PlayerTab.Add(info.cid, pPlayer); - } + m_UkPlayerTab.Remove(info.cid); } + } + + int iAppearFlag = (iCmd == (int)CommandID.PLAYER_ENTER_WORLD) ? + (int)PlayerAppearFlag.APPEAR_ENTERWORLD : (int)PlayerAppearFlag.APPEAR_RUNINTOVIEW; + + // Has player been in active player table ? + EC_ElsePlayer pPlayer = GetElsePlayer(info.cid); + if (pPlayer) + { + // This player has existed in player table, call special initial function + // TODO: fix after pPlayer init + pPlayer.Init(roleInfo, info); return pPlayer; } - private EC_ElsePlayer CreateElsePlayer(RoleInfo roleInfo, info_player_1 info, int iAppearFlag) + // Create a new player + if (!(pPlayer = CreateElsePlayer(roleInfo, info, iAppearFlag))) { - GameObject ob = GameController.Instance.InitCharacter(info); - EC_ElsePlayer elsePlayer = ob.AddComponent(); - elsePlayer.GetComponent().enabled = false; - //init - elsePlayer.Init(roleInfo, info); - return elsePlayer; + return null; } - - public EC_ElsePlayer GetElsePlayer(int cid, long dwBornStamp = 0) + lock (m_csPlayerTab) { - lock (m_csPlayerTab) + if (m_PlayerTab.ContainsKey(info.cid)) { - if (!m_PlayerTab.TryGetValue(cid, out var player)) - return null; - if (dwBornStamp != 0) - { - //TO DO: fix after GetBornStamp() is create in code - //if (player.GetBornStamp() != dwBornStamp) - return null; - } - - return player; + m_PlayerTab[info.cid] = pPlayer; + } + else + { + m_PlayerTab.Add(info.cid, pPlayer); } } + return pPlayer; + } - private EC_ElsePlayer SeekOutElsePlayer(int cid) + private EC_ElsePlayer CreateElsePlayer(RoleInfo roleInfo, info_player_1 info, int iAppearFlag) + { + GameObject ob = GameController.Instance.InitCharacter(info); + EC_ElsePlayer elsePlayer = ob.AddComponent(); + elsePlayer.GetComponent().enabled = false; + //init + elsePlayer.Init(roleInfo, info); + return elsePlayer; + } + + public EC_ElsePlayer GetElsePlayer(int cid, long dwBornStamp = 0) + { + lock (m_csPlayerTab) { if (!m_PlayerTab.TryGetValue(cid, out var player)) + return null; + if (dwBornStamp != 0) { - // Couldn't find this else player, put it into unknown player table - m_UkPlayerTab[cid] = cid; + //TO DO: fix after GetBornStamp() is create in code + //if (player.GetBornStamp() != dwBornStamp) return null; } return player; } + } - - public bool OnMsgPlayerStopMove(ECMSG Msg) + private EC_ElsePlayer SeekOutElsePlayer(int cid) + { + if (!m_PlayerTab.TryGetValue(cid, out var player)) { - cmd_object_stop_move pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id); - if (pPlayer) - pPlayer.StopMoveTo(pCmd); - return true; + // Couldn't find this else player, put it into unknown player table + m_UkPlayerTab[cid] = cid; + return null; } - //private cmd_object_move ConvertToStruct(byte[] bytes) - //{ - // if (bytes.Length < Marshal.SizeOf()) - // { - // return default; - // } + return player; + } - // cmd_object_move result = new cmd_object_move(); - // int preLenghtData = 0; - // int lenghtDataType = Marshal.SizeOf(); - // byte[] arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.id = BitConverter.ToInt32(arrByteData); - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.dest_X = BitConverter.ToSingle(arrByteData); + public bool OnMsgPlayerStopMove(ECMSG Msg) + { + cmd_object_stop_move pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id); + if (pPlayer) + pPlayer.StopMoveTo(pCmd); + return true; + } - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.dest_Y = BitConverter.ToSingle(arrByteData); + //private cmd_object_move ConvertToStruct(byte[] bytes) + //{ + // if (bytes.Length < Marshal.SizeOf()) + // { + // return default; + // } - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.dest_Z = BitConverter.ToSingle(arrByteData); + // cmd_object_move result = new cmd_object_move(); + // int preLenghtData = 0; + // int lenghtDataType = Marshal.SizeOf(); + // byte[] arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); + // result.id = BitConverter.ToInt32(arrByteData); - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.use_time = BitConverter.ToUInt16(arrByteData); + // preLenghtData += lenghtDataType; + // lenghtDataType = Marshal.SizeOf(); + // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); + // result.dest_X = BitConverter.ToSingle(arrByteData); - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.sSpeed = BitConverter.ToInt16(arrByteData); + // preLenghtData += lenghtDataType; + // lenghtDataType = Marshal.SizeOf(); + // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); + // result.dest_Y = BitConverter.ToSingle(arrByteData); - // preLenghtData += lenghtDataType; - // result.move_mode = bytes[preLenghtData + 1]; - // return result; - //} + // preLenghtData += lenghtDataType; + // lenghtDataType = Marshal.SizeOf(); + // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); + // result.dest_Z = BitConverter.ToSingle(arrByteData); - private byte[] GetBytes(byte[] bytes, int length, int index) + // preLenghtData += lenghtDataType; + // lenghtDataType = Marshal.SizeOf(); + // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); + // result.use_time = BitConverter.ToUInt16(arrByteData); + + // preLenghtData += lenghtDataType; + // lenghtDataType = Marshal.SizeOf(); + // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); + // result.sSpeed = BitConverter.ToInt16(arrByteData); + + // preLenghtData += lenghtDataType; + // result.move_mode = bytes[preLenghtData + 1]; + // return result; + //} + + private byte[] GetBytes(byte[] bytes, int length, int index) + { + byte[] arrByteData = new byte[length]; + for (int i = 0; i < length; i++) { - byte[] arrByteData = new byte[length]; - for (int i = 0; i < length; i++) - { - arrByteData[i] = bytes[i + index]; - } - return arrByteData; + arrByteData[i] = bytes[i + index]; } + return arrByteData; + } - public void Initialize() + public void Initialize() + { + + } + public bool TransmitMessage(ECMSG msg) + { + int cid = 0; + var host = GameController.Instance.GetHostPlayer(); + + switch (msg.dwMsg) { + /*case long value when value == EC_MsgDef.MSG_PM_PLAYEREQUIPDATA: + if (msg.dwParam2 == S2C.EQUIP_DATA) + cid = ((cmd_equip_data)msg.dwParam1).idPlayer; + else // EQUIP_DATA_CHANGED + cid = ((cmd_equip_data_changed)msg.dwParam1).idPlayer; + break;*/ - } - public bool TransmitMessage(ECMSG msg) - { - int cid = 0; - var host = GameController.Instance.GetHostPlayer(); + case long value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO: + cid = (int)((playerbaseinfo_re)msg.dwParam1).Player.id; + // Xoá khỏi cache + //g_pGame.GetGameSession().GetC2SCmdCache().RemovePlayerBaseInfo(cid); + break; - switch (msg.dwMsg) - { - /*case long value when value == EC_MsgDef.MSG_PM_PLAYEREQUIPDATA: - if (msg.dwParam2 == S2C.EQUIP_DATA) - cid = ((cmd_equip_data)msg.dwParam1).idPlayer; - else // EQUIP_DATA_CHANGED - cid = ((cmd_equip_data_changed)msg.dwParam1).idPlayer; - break;*/ + /*case long value when value == EC_MsgDef.MSG_PM_PLAYERCUSTOM: + cid = ((GetCustomData_Re)msg.dwParam1).cus_roleid; + break; - case long value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO: - cid = (int)((playerbaseinfo_re)msg.dwParam1).Player.id; - // Xoá khỏi cache - //g_pGame.GetGameSession().GetC2SCmdCache().RemovePlayerBaseInfo(cid); - break; + case long value when value == EC_MsgDef.MSG_PM_PLAYERFLY: + if (msg.dwParam2 == S2C.OBJECT_TAKEOFF) + cid = ((cmd_object_takeoff)msg.dwParam1).object_id; + else + cid = ((cmd_object_landing)msg.dwParam1).object_id; + break;*/ - /*case long value when value == EC_MsgDef.MSG_PM_PLAYERCUSTOM: - cid = ((GetCustomData_Re)msg.dwParam1).cus_roleid; - break; + // ⚠️ Các case khác cũng tương tự, chỉ việc lấy ra đúng trường id / caster / user ... + // Do quá dài nên bạn có thể copy dần từng case từ C++ sang. - case long value when value == EC_MsgDef.MSG_PM_PLAYERFLY: - if (msg.dwParam2 == S2C.OBJECT_TAKEOFF) - cid = ((cmd_object_takeoff)msg.dwParam1).object_id; - else - cid = ((cmd_object_landing)msg.dwParam1).object_id; - break;*/ - - // ⚠️ Các case khác cũng tương tự, chỉ việc lấy ra đúng trường id / caster / user ... - // Do quá dài nên bạn có thể copy dần từng case từ C++ sang. - - default: - System.Diagnostics.Debug.Assert(false, "Unknown message"); - return false; - } - - /* if (cid == 0) - { - System.Diagnostics.Debug.Assert(false, "cid = 0"); + default: + System.Diagnostics.Debug.Assert(false, "Unknown message"); return false; - } - - if (host != null && cid == host.GetCharacterID()) - { - host.ProcessMessage(msg); - } - else - { - var elsePlayer = SeekOutElsePlayer(cid); - if (elsePlayer != null) - elsePlayer.ProcessMessage(msg); - }*/ - - return true; } - // Get a player (may be host or else player) by id - public EC_Player GetPlayer(int cid, uint dwBornStamp = 0) - { - CECHostPlayer pHost = GetHostPlayer(); - if (pHost && pHost.GetCharacterID() == cid) - return pHost; - else - return GetElsePlayer(cid, dwBornStamp); - } + /* if (cid == 0) + { + System.Diagnostics.Debug.Assert(false, "cid = 0"); + return false; + } - public CECHostPlayer GetHostPlayer() - { - return GameController.Instance.GetHostPlayer(); - } + if (host != null && cid == host.GetCharacterID()) + { + host.ProcessMessage(msg); + } + else + { + var elsePlayer = SeekOutElsePlayer(cid); + if (elsePlayer != null) + elsePlayer.ProcessMessage(msg); + }*/ + + return true; + } + + // Get a player (may be host or else player) by id + public EC_Player GetPlayer(int cid, uint dwBornStamp = 0) + { + CECHostPlayer pHost = GetHostPlayer(); + if (pHost && pHost.GetCharacterID() == cid) + return pHost; + else + return GetElsePlayer(cid, dwBornStamp); + } + + public CECHostPlayer GetHostPlayer() + { + return GameController.Instance.GetHostPlayer(); } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs index 6ee388cece..7041efd290 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs @@ -1,245 +1,247 @@ using CSNetwork.GPDataType; -using CSNetwork.Protocols; using UnityEngine; -/////////////////////////////////////////////////////////////////////////// -// -// Class CECObject -// -/////////////////////////////////////////////////////////////////////////// - -public class CECObject : MonoBehaviour +namespace BrewMonster.Scripts.Player { - // Class ID - public static class Class_ID + /////////////////////////////////////////////////////////////////////////// + // + // Class CECObject + // + /////////////////////////////////////////////////////////////////////////// + + public class CECObject : MonoBehaviour { - public const int OCID_OBJECT = 0, - OCID_PLAYER = 1, - OCID_HOSTPLAYER = 2, - OCID_ELSEPLAYER = 3, - OCID_LOGINPLAYER = 4, - OCID_NPC = 5, - OCID_MONSTER = 6, - OCID_SERVER = 7, - OCID_MATTER = 8, - OCID_PET = 9, - OCID_CLONED_PLAYER = 10, // ƽɫģ - OCID_HOST_NAVIGATER = 11, // ͻplayer,ǿƶ - OCID_NPCCLONED_MASTER = 12; // NPC ƵĽɫģ - } + // Class ID + public static class Class_ID + { + public const int OCID_OBJECT = 0, + OCID_PLAYER = 1, + OCID_HOSTPLAYER = 2, + OCID_ELSEPLAYER = 3, + OCID_LOGINPLAYER = 4, + OCID_NPC = 5, + OCID_MONSTER = 6, + OCID_SERVER = 7, + OCID_MATTER = 8, + OCID_PET = 9, + OCID_CLONED_PLAYER = 10, // ƽɫģ + OCID_HOST_NAVIGATER = 11, // ͻplayer,ǿƶ + OCID_NPCCLONED_MASTER = 12; // NPC ƵĽɫģ + } - // Render flag - public static class Render_flag - { - public const int RD_NORMAL = 0, - RD_REFRACT = 1, - RD_REFLECT = 2; - } + // Render flag + public static class Render_flag + { + public const int RD_NORMAL = 0, + RD_REFRACT = 1, + RD_REFLECT = 2; + } - // Move environment - public static class Move_environment - { - public const int MOVEENV_GROUND = 0, // Move on ground - MOVEENV_WATER = 1, - MOVEENV_AIR = 2; - } + // Move environment + public static class Move_environment + { + public const int MOVEENV_GROUND = 0, // Move on ground + MOVEENV_WATER = 1, + MOVEENV_AIR = 2; + } - // Constructor and Destructor - public CECObject() - { - m_iCID = Class_ID.OCID_OBJECT; - m_bAdjustOrient = false; - m_bVisible = true; - m_bBornInSight = false; - m_dwBornStamp = 0; + // Constructor and Destructor + public CECObject() + { + m_iCID = Class_ID.OCID_OBJECT; + m_bAdjustOrient = false; + m_bVisible = true; + m_bBornInSight = false; + m_dwBornStamp = 0; - m_bUseGroundNormal = false; - m_vecGroundNormal = new A3DVECTOR3(0.0f, 1.0f, 0.0f); - m_vecGroundNormalSet = new A3DVECTOR3(0.0f, 1.0f, 0.0f); + m_bUseGroundNormal = false; + m_vecGroundNormal = new A3DVECTOR3(0.0f, 1.0f, 0.0f); + m_vecGroundNormalSet = new A3DVECTOR3(0.0f, 1.0f, 0.0f); - m_bSelectable = true; - } + m_bSelectable = true; + } - public virtual void SetUpCECObject() - { - m_dwBornStamp = 0; - m_bBornInSight = false; - //m_bSelectable = false; - m_iCID = (int)Class_ID.OCID_OBJECT; - } + public virtual void SetUpCECObject() + { + m_dwBornStamp = 0; + m_bBornInSight = false; + //m_bSelectable = false; + m_iCID = (int)Class_ID.OCID_OBJECT; + } - public void SetSelectable(bool bSelectable) { m_bSelectable = bSelectable; } + public void SetSelectable(bool bSelectable) { m_bSelectable = bSelectable; } - // Tick routine - public bool Tick(float dwDeltaTime) - { - if (m_bAdjustOrient) - AdjustOrientation(dwDeltaTime); + // Tick routine + public bool Tick(float dwDeltaTime) + { + if (m_bAdjustOrient) + AdjustOrientation(dwDeltaTime); - m_vecGroundNormal = Normalize(m_vecGroundNormal * 0.85f + m_vecGroundNormalSet * 0.15f); - return true; - } + m_vecGroundNormal = Normalize(m_vecGroundNormal * 0.85f + m_vecGroundNormalSet * 0.15f); + return true; + } - // Set absolute forward and up direction - public virtual void SetDirAndUp(A3DVECTOR3 vDir, A3DVECTOR3 vUp) - { - //if (m_bUseGroundNormal) - //{ - // A3DVECTOR3 vecRight = Normalize(CrossProduct(g_vAxisY, vDir)); - // A3DVECTOR3 vecNormal = m_vecGroundNormal - DotProduct(m_vecGroundNormal, vecRight) * vecRight; - // A3DVECTOR3 vecNewDir = Normalize(CrossProduct(vecRight, vecNormal)); - // A3DCoordinate::SetDirAndUp(vecNewDir, vecNormal); - //} - //else - // A3DCoordinate::SetDirAndUp(vDir, vUp); + // Set absolute forward and up direction + public virtual void SetDirAndUp(A3DVECTOR3 vDir, A3DVECTOR3 vUp) + { + //if (m_bUseGroundNormal) + //{ + // A3DVECTOR3 vecRight = Normalize(CrossProduct(g_vAxisY, vDir)); + // A3DVECTOR3 vecNormal = m_vecGroundNormal - DotProduct(m_vecGroundNormal, vecRight) * vecRight; + // A3DVECTOR3 vecNewDir = Normalize(CrossProduct(vecRight, vecNormal)); + // A3DCoordinate::SetDirAndUp(vecNewDir, vecNormal); + //} + //else + // A3DCoordinate::SetDirAndUp(vDir, vUp); - // Stop orientation adjusting - m_bAdjustOrient = false; - } - // Set destination orientation of model - public void SetDestDirAndUp(A3DVECTOR3 vDir, A3DVECTOR3 vUp, float dwTime) - { - m_bAdjustOrient = true; - m_dwOrientTime = dwTime; - m_dwOrientTimeCnt = 0; + // Stop orientation adjusting + m_bAdjustOrient = false; + } + // Set destination orientation of model + public void SetDestDirAndUp(A3DVECTOR3 vDir, A3DVECTOR3 vUp, float dwTime) + { + m_bAdjustOrient = true; + m_dwOrientTime = dwTime; + m_dwOrientTimeCnt = 0; - //// Calculate start orientation - //A3DMATRIX4 mat = a3d_TransformMatrix(GetDir(), GetUp(), g_vOrigin); - //m_quOrientStart.ConvertFromMatrix(mat); + //// Calculate start orientation + //A3DMATRIX4 mat = a3d_TransformMatrix(GetDir(), GetUp(), g_vOrigin); + //m_quOrientStart.ConvertFromMatrix(mat); - //// Calculate end orientation - //if (m_bUseGroundNormal) - //{ - // A3DVECTOR3 vecRight = Normalize(CrossProduct(g_vAxisY, vDir)); - // A3DVECTOR3 vecNormal = m_vecGroundNormal - DotProduct(m_vecGroundNormal, vecRight) * vecRight; - // A3DVECTOR3 vecNewDir = Normalize(CrossProduct(vecRight, vecNormal)); - // mat = a3d_TransformMatrix(vecNewDir, vecNormal, g_vOrigin); - //} - //else - //{ - // mat = a3d_TransformMatrix(vDir, vUp, g_vOrigin); - //} + //// Calculate end orientation + //if (m_bUseGroundNormal) + //{ + // A3DVECTOR3 vecRight = Normalize(CrossProduct(g_vAxisY, vDir)); + // A3DVECTOR3 vecNormal = m_vecGroundNormal - DotProduct(m_vecGroundNormal, vecRight) * vecRight; + // A3DVECTOR3 vecNewDir = Normalize(CrossProduct(vecRight, vecNormal)); + // mat = a3d_TransformMatrix(vecNewDir, vecNormal, g_vOrigin); + //} + //else + //{ + // mat = a3d_TransformMatrix(vDir, vUp, g_vOrigin); + //} - //m_quOrientEnd.ConvertFromMatrix(mat); - } + //m_quOrientEnd.ConvertFromMatrix(mat); + } - // Calculate distance between this object and specified position - public float CalcDist(A3DVECTOR3 vPos, bool b3D) - { - A3DVECTOR3 vDelta = GetPos() - vPos; - return b3D ? vDelta.Magnitude() : vDelta.MagnitudeH(); - } + // Calculate distance between this object and specified position + public float CalcDist(A3DVECTOR3 vPos, bool b3D) + { + A3DVECTOR3 vDelta = GetPos() - vPos; + return b3D ? vDelta.Magnitude() : vDelta.MagnitudeH(); + } - private A3DVECTOR3 Normalize(A3DVECTOR3 v) - { - float mag = v.Magnitude(); - if (mag < 1e-12 && mag > -1e-12) - return new A3DVECTOR3(0.0f); - else - return v / mag; - } + private A3DVECTOR3 Normalize(A3DVECTOR3 v) + { + float mag = v.Magnitude(); + if (mag < 1e-12 && mag > -1e-12) + return new A3DVECTOR3(0.0f); + else + return v / mag; + } - public A3DVECTOR3 GetPos() - { - return new A3DVECTOR3(transform.position.x, transform.position.y, transform.position.z); - } + public A3DVECTOR3 GetPos() + { + return new A3DVECTOR3(transform.position.x, transform.position.y, transform.position.z); + } - // Turn around object and face to specified object - public virtual void TurnFaceTo(int idTarget, float dwTime = 200) - { + // Turn around object and face to specified object + public virtual void TurnFaceTo(int idTarget, float dwTime = 200) + { - } + } - // Set / Get visible flag - public void SetVisible(bool bVisible) - { - m_bVisible = bVisible; - } - public bool GetVisible() - { - return m_bVisible; - } + // Set / Get visible flag + public void SetVisible(bool bVisible) + { + m_bVisible = bVisible; + } + public bool GetVisible() + { + return m_bVisible; + } - // Get object class ID - public int GetClassID() { return m_iCID; } - public bool IsPlayer() { return m_iCID == Class_ID.OCID_HOSTPLAYER || m_iCID == Class_ID.OCID_ELSEPLAYER || m_iCID == Class_ID.OCID_LOGINPLAYER; } - public bool IsHostPlayer() { return m_iCID == Class_ID.OCID_HOSTPLAYER; } - public bool IsElsePlayer() { return m_iCID == Class_ID.OCID_ELSEPLAYER; } - public bool IsLoginPlayer(){ return m_iCID == Class_ID.OCID_LOGINPLAYER; } - public bool IsNPC() { return m_iCID == Class_ID.OCID_MONSTER || m_iCID == Class_ID.OCID_SERVER; } - public bool IsMonsterNPC() { return m_iCID == Class_ID.OCID_MONSTER; } - public bool IsServerNPC() { return m_iCID == Class_ID.OCID_SERVER; } - public bool IsMatter() { return m_iCID == Class_ID.OCID_MATTER; } - public bool IsSelectable() { return m_bSelectable; } - // Set / Get object born stamp - public uint GetBornStamp() { return m_dwBornStamp; } - public void SetBornStamp(uint dwStamp) { m_dwBornStamp = dwStamp; } - // Set / Get born in sight flag - public bool GetBornInSight() { return m_bBornInSight; } - public void SetBornInSight(bool bFlag) { m_bBornInSight = bFlag; } + // Get object class ID + public int GetClassID() { return m_iCID; } + public bool IsPlayer() { return m_iCID == Class_ID.OCID_HOSTPLAYER || m_iCID == Class_ID.OCID_ELSEPLAYER || m_iCID == Class_ID.OCID_LOGINPLAYER; } + public bool IsHostPlayer() { return m_iCID == Class_ID.OCID_HOSTPLAYER; } + public bool IsElsePlayer() { return m_iCID == Class_ID.OCID_ELSEPLAYER; } + public bool IsLoginPlayer() { return m_iCID == Class_ID.OCID_LOGINPLAYER; } + public bool IsNPC() { return m_iCID == Class_ID.OCID_MONSTER || m_iCID == Class_ID.OCID_SERVER; } + public bool IsMonsterNPC() { return m_iCID == Class_ID.OCID_MONSTER; } + public bool IsServerNPC() { return m_iCID == Class_ID.OCID_SERVER; } + public bool IsMatter() { return m_iCID == Class_ID.OCID_MATTER; } + public bool IsSelectable() { return m_bSelectable; } + // Set / Get object born stamp + public uint GetBornStamp() { return m_dwBornStamp; } + public void SetBornStamp(uint dwStamp) { m_dwBornStamp = dwStamp; } + // Set / Get born in sight flag + public bool GetBornInSight() { return m_bBornInSight; } + public void SetBornInSight(bool bFlag) { m_bBornInSight = bFlag; } - // Get object id - public static int GetObjectID(CECObject pObject) - { - if (!pObject) - return 0; + // Get object id + public static int GetObjectID(CECObject pObject) + { + if (!pObject) + return 0; - if (pObject.IsPlayer()) - return ((EC_Player)pObject).GetCharacterID(); - else if (pObject.IsNPC()) - return ((CECNPC)pObject).GetNPCID(); - //else if (pObject.IsMatter()) - // return ((CECMatter*)pObject)->GetMatterID(); - else - return 0; - } + if (pObject.IsPlayer()) + return ((EC_Player)pObject).GetCharacterID(); + else if (pObject.IsNPC()) + return ((CECNPC)pObject).GetNPCID(); + //else if (pObject.IsMatter()) + // return ((CECMatter*)pObject)->GetMatterID(); + else + return 0; + } - protected int m_iCID; // Class ID - protected bool m_bAdjustOrient; // Is adjusting orientation - //protected A3DQUATERNION m_quOrientStart; // Orientation start - //protected A3DQUATERNION m_quOrientEnd; // Orientation end - protected float m_dwOrientTime; // Orientation adjusting time counter - protected uint m_dwOrientTimeCnt; // Orientation adjusting time counter + protected int m_iCID; // Class ID + protected bool m_bAdjustOrient; // Is adjusting orientation + //protected A3DQUATERNION m_quOrientStart; // Orientation start + //protected A3DQUATERNION m_quOrientEnd; // Orientation end + protected float m_dwOrientTime; // Orientation adjusting time counter + protected uint m_dwOrientTimeCnt; // Orientation adjusting time counter - protected bool m_bBornInSight; // Born in my sight - protected uint m_dwBornStamp; // Born time stamp - protected bool m_bVisible; // Render flag + protected bool m_bBornInSight; // Born in my sight + protected uint m_dwBornStamp; // Born time stamp + protected bool m_bVisible; // Render flag - protected bool m_bUseGroundNormal; // flag indicates whether we use a ground normal as up - protected A3DVECTOR3 m_vecGroundNormal; // current ground normal - protected A3DVECTOR3 m_vecGroundNormalSet; // ground normal set + protected bool m_bUseGroundNormal; // flag indicates whether we use a ground normal as up + protected A3DVECTOR3 m_vecGroundNormal; // current ground normal + protected A3DVECTOR3 m_vecGroundNormalSet; // ground normal set - protected bool m_bSelectable; // whether the object can be selected + protected bool m_bSelectable; // whether the object can be selected - public A3DVECTOR3 GetGroundNormal(){ return m_vecGroundNormal; } - public bool GetUseGroundNormal(){ return m_bUseGroundNormal; } + public A3DVECTOR3 GetGroundNormal() { return m_vecGroundNormal; } + public bool GetUseGroundNormal() { return m_bUseGroundNormal; } - public void SetUseGroundNormal(bool bFlag) - { - //if (m_bUseGroundNormal == bFlag) - // return; + public void SetUseGroundNormal(bool bFlag) + { + //if (m_bUseGroundNormal == bFlag) + // return; - //m_bUseGroundNormal = bFlag; - //if (m_bUseGroundNormal) - //{ - // // now reset dir and up to make the object show correct pose - // SetDirAndUp(GetDir(), GetUp()); - //} - //else - //{ - // // now reset dir and up to make the player show correct pose - // A3DVECTOR3 vLeft = CrossProduct(GetDir(), g_vAxisY); - // A3DVECTOR3 vDir = Normalize(CrossProduct(g_vAxisY, vLeft)); - // SetDirAndUp(vDir, g_vAxisY); - //} - } - public void SetGroundNormal(A3DVECTOR3 vecNormal) - { - m_vecGroundNormalSet = vecNormal; - } + //m_bUseGroundNormal = bFlag; + //if (m_bUseGroundNormal) + //{ + // // now reset dir and up to make the object show correct pose + // SetDirAndUp(GetDir(), GetUp()); + //} + //else + //{ + // // now reset dir and up to make the player show correct pose + // A3DVECTOR3 vLeft = CrossProduct(GetDir(), g_vAxisY); + // A3DVECTOR3 vDir = Normalize(CrossProduct(g_vAxisY, vLeft)); + // SetDirAndUp(vDir, g_vAxisY); + //} + } + public void SetGroundNormal(A3DVECTOR3 vecNormal) + { + m_vecGroundNormalSet = vecNormal; + } - protected void AdjustOrientation(float dwDeltaTime) - { + protected void AdjustOrientation(float dwDeltaTime) + { + } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs index 77a4e6cde8..0a899d2cf7 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs @@ -1,64 +1,67 @@ using UnityEngine; -public class CECObjectWork +namespace BrewMonster.Scripts { - // Attributes - protected int m_iWorkID; // Work ID - protected bool m_bFinished; // true, Work is finished - protected uint m_dwMask; // Mask of this work - protected uint m_dwTransMask; // Work transfer masks - protected bool m_bFirstTick; - // Constructor - public CECObjectWork(int iWorkID) + public class CECObjectWork { - m_iWorkID = iWorkID; - m_bFinished = false; - m_dwMask = 0; - m_dwTransMask = 0; - m_bFinished = true; - } - - public virtual bool Tick(float dwDeltaTime) - { - if (m_bFirstTick) + // Attributes + protected int m_iWorkID; // Work ID + protected bool m_bFinished; // true, Work is finished + protected uint m_dwMask; // Mask of this work + protected uint m_dwTransMask; // Work transfer masks + protected bool m_bFirstTick; + // Constructor + public CECObjectWork(int iWorkID) { - m_bFirstTick = false; - OnFirstTick(); + m_iWorkID = iWorkID; + m_bFinished = false; + m_dwMask = 0; + m_dwTransMask = 0; + m_bFinished = true; } - return true; + + public virtual bool Tick(float dwDeltaTime) + { + if (m_bFirstTick) + { + m_bFirstTick = false; + OnFirstTick(); + } + return true; + } + + // Reset work + public virtual void Reset() + { + m_bFinished = false; + m_bFirstTick = true; + } + + // Work is cancel + public virtual void Cancel() { } + + // Can work transfer to another work with specified mask + public virtual bool CanTransferTo(uint dwMask) + { + return (m_dwTransMask & dwMask) != 0; + } + + // On work shift to + public virtual void OnWorkShift() { } + + // Get work ID + public int GetWorkID() => m_iWorkID; + + // Is work finished? + public bool IsFinished() => m_bFinished; + + // Get work mask + public uint GetWorkMask() => m_dwMask; + + // Get work transfer works + public uint GetTransferMask() => m_dwTransMask; + + // On first tick + protected virtual void OnFirstTick() { } } - - // Reset work - public virtual void Reset() - { - m_bFinished = false; - m_bFirstTick = true; - } - - // Work is cancel - public virtual void Cancel() { } - - // Can work transfer to another work with specified mask - public virtual bool CanTransferTo(uint dwMask) - { - return (m_dwTransMask & dwMask) != 0; - } - - // On work shift to - public virtual void OnWorkShift() { } - - // Get work ID - public int GetWorkID() => m_iWorkID; - - // Is work finished? - public bool IsFinished() => m_bFinished; - - // Get work mask - public uint GetWorkMask() => m_dwMask; - - // Get work transfer works - public uint GetTransferMask() => m_dwTransMask; - - // On first tick - protected virtual void OnFirstTick() { } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_World.cs b/Assets/PerfectWorld/Scripts/Managers/EC_World.cs new file mode 100644 index 0000000000..91d9f27bb0 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_World.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +//public class CECWorld +//{ + +//} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_World.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_World.cs.meta new file mode 100644 index 0000000000..b08d5372e0 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_World.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4f8b18d59a72e044fbcf236fe5b2991c \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs b/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs new file mode 100644 index 0000000000..42933fa251 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs @@ -0,0 +1,166 @@ +using CSNetwork.GPDataType; +using System; +using UnityEngine; +using UnityEngine.UIElements; + +namespace BrewMonster.Scripts +{ + public class CHalfSpace + { + public static float DistThresh; //ռһ㵽halfspaceƽľֵΪжڰռڲⲿor ߽ + //ֵijһ˶Ϊ̬Ա + //㹹ƽ漰ռ + //Attributes + public const float HS_DEFAULT_DISTTHRESH = 0.000001f; //ֵΪжڰռڲor߽ + + protected A3DVECTOR3 m_vNormal; + protected float m_d; + + public void Set(A3DVECTOR3 v1, A3DVECTOR3 v2) + { + m_vNormal = A3DVECTOR3.CrossProduct(v2 - v1, new A3DVECTOR3(0.0f, 0.0f, 1.0f)); + m_vNormal.Normalize(); + m_d = A3DVECTOR3.DotProduct(v1, m_vNormal); + } + public void Set(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 v3) + { + m_vNormal = A3DVECTOR3.CrossProduct(v2 - v1, v3 - v1); + m_vNormal.Normalize(); + m_d = A3DVECTOR3.DotProduct(v1, m_vNormal); + } + + //ֱ÷ + public void SetNormal(A3DVECTOR3 n) { m_vNormal = n; m_vNormal.Normalize(); } + + public float GetDist() { return m_d; } + + //ֱþd + public void SetD(float d) { m_d = d; } + + public CHalfSpace(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 v3) + { + Set(v1, v2, v3); + + } + //㹹ƽZƽ漰ռ + public CHalfSpace(A3DVECTOR3 v1, A3DVECTOR3 v2) + { + Set(v1, v2); + } + public CHalfSpace() + { + + } + + public CHalfSpace(CHalfSpace hs) + { + m_vNormal = hs.m_vNormal; + m_d = hs.m_d; + } + + // ԾHalfspaceƽб任任ΪmtxTrans + public virtual void Transform(A3DMATRIX4 mtxTrans) + { + //mtxTransֽScale,Rotate,Translate + A3DVECTOR3 vTranslate = mtxTrans.GetRow(3); + float fScale = mtxTrans.GetCol(0).Magnitude(); + + // mtxTransһԶΪҳ˾ + A3DMATRIX3 mtx3Rotate = new A3DMATRIX3(); + mtx3Rotate.m = new float[3 * 3]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + mtx3Rotate.m[(i * 3) + j] = mtxTrans.m[(i * 4) + j] / fScale; + + //ƽ淽N.X=Dı任(s,R,t)£ + + // N'=NR + SetNormal(m_vNormal * mtx3Rotate); + + //D'=s*D+N'.t + SetD(fScale * m_d + A3DVECTOR3.DotProduct(m_vNormal, vTranslate)); + } + + public void Translate(float Delta) { m_d += Delta; } //ط߷һƽ + public void Inverse() { m_d = -m_d; m_vNormal = -m_vNormal; } //תռ + + //vռ䶨ƽľ룬˾ţ + public float DistV2Plane(A3DVECTOR3 v) + { + float d = A3DVECTOR3.DotProduct(v, m_vNormal); + return (d - m_d); + } + + //߶ + public int IntersectLineSeg(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 vIntersection) + { + vIntersection = new A3DVECTOR3(0.0f, 0.0f, 0.0f); + //ȴƽϵ + bool v1InPlane = OnPlane(v1); + bool v2InPlane = OnPlane(v2); + if (v1InPlane && v2InPlane) return 3; + if (v1InPlane) return 1; + if (v2InPlane) return 2; + + if (Outside(v1) ^ Outside(v2)) + { + //ֱ࣬㽻 + A3DVECTOR3 vd = v2 - v1; + float t = m_d - A3DVECTOR3.DotProduct(m_vNormal, v1); + t /= A3DVECTOR3.DotProduct(m_vNormal, vd); + //assert(t < 1.0f && t > 0.0f); + vIntersection = v1 + t * vd; + + return 4; + } + else + return 0; + } + + //////////////////////////////////////////////////////////// + // жһάǷڰռڲ˵ƽһ + // עhalfspaceOutSide,Inside巽ʽ + // /\ + // /||\ + // || + // || normal (Outside) + //------------------------------------------Plane + // (Inside) + // + public bool Inside(A3DVECTOR3 v) + { + float d = A3DVECTOR3.DotProduct(v, m_vNormal); + bool bInside = (m_d - d > DistThresh); + return (bInside); + } + public bool Outside(A3DVECTOR3 v) + { + float d = A3DVECTOR3.DotProduct(v, m_vNormal); + bool bOutside = (d - m_d > DistThresh); + return (bOutside); + } + public bool OnPlane(A3DVECTOR3 v) + { + float d = A3DVECTOR3.DotProduct(v, m_vNormal); + bool bOnPlane = (Math.Abs(m_d - d) <= DistThresh); + return bOnPlane; + } + + //set && get operations + public static void SetDistThresh(float DThresh = HS_DEFAULT_DISTTHRESH) //趨һȱʡֵ + { + DistThresh = DThresh; + } + + public A3DVECTOR3 GetNormal() { return m_vNormal; } + + //㷨ʽ + public void SetNV(A3DVECTOR3 n, A3DVECTOR3 v) + { + m_vNormal = n; + m_vNormal.Normalize(); + m_d = A3DVECTOR3.DotProduct(m_vNormal, v); + } + + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs.meta b/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs.meta new file mode 100644 index 0000000000..30fbbcd701 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 495f51cd9612ff441a012f1aea98974d \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/NPCManager.cs b/Assets/PerfectWorld/Scripts/Managers/NPCManager.cs index 3f80cd6492..25b591664a 100644 --- a/Assets/PerfectWorld/Scripts/Managers/NPCManager.cs +++ b/Assets/PerfectWorld/Scripts/Managers/NPCManager.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public class NPCManager : MonoBehaviour { diff --git a/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs b/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs new file mode 100644 index 0000000000..63e60b9b99 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs @@ -0,0 +1,66 @@ +using CSNetwork.GPDataType; +using BrewMonster.Scripts.Player; + +namespace BrewMonster.Scripts +{ + ////////////////////////////////////////////////////////////////////////// + // define a new compact Convex Hull data type which is used in ElementClient! + ////////////////////////////////////////////////////////////////////////// + public class BrushTraceInfo + { + ////////////////////////////////////////////////////////////////////////// + // In + ////////////////////////////////////////////////////////////////////////// + // aabb's info + public A3DVECTOR3 vStart; // Start point + public A3DVECTOR3 vDelta; // Move delta + public A3DVECTOR3 vExtents; + public A3DAABB BoundAABB; + // Dist Epsilon + public float fDistEpsilon; // Dist Epsilon + public bool bIsPoint; //raytrace + ////////////////////////////////////////////////////////////////////////// + // Out + ////////////////////////////////////////////////////////////////////////// + public bool bStartSolid; // Collide something at start point + public bool bAllSolid; // All in something + public CHalfSpace ClipPlane; // Clip plane + public int iClipPlane; // Clip plane's index + public float fFraction; // Fraction + public uint dwUser1; // User defined data 1 + public uint dwUser2; // User defined data 2 + + public void Init(A3DVECTOR3 start, A3DVECTOR3 delta, A3DVECTOR3 ext, bool bRay = false, float epsilon = 0.03125f) + { + + vStart = start; + vDelta = delta; + vExtents = ext; + fDistEpsilon = epsilon; + fFraction = 100.0f; + bIsPoint = bRay; + bStartSolid = false; + bAllSolid = false; + dwUser1 = 0; + dwUser2 = 0; + if (!bIsPoint) + { + BoundAABB.Clear(); + BoundAABB.AddVertex(vStart); + BoundAABB.AddVertex(vStart + vExtents); + BoundAABB.AddVertex(vStart - vExtents); + BoundAABB.AddVertex(vStart + vDelta); + BoundAABB.AddVertex(vStart + vDelta + vExtents); + BoundAABB.AddVertex(vStart + vDelta - vExtents); + BoundAABB.CompleteCenterExts(); + } + + else + { + //@note : it cheats the caller. By Kuiwu[25/8/2005] + //@todo : refine me. By Kuiwu[25/8/2005] + fDistEpsilon = 1E-5f; + } + } + }; +} diff --git a/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs.meta b/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs.meta new file mode 100644 index 0000000000..69fc874090 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2ac2c48a14ff7e1478eb76c24ead3cc3 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/NPC/CECMonster.cs b/Assets/PerfectWorld/Scripts/NPC/CECMonster.cs index e9e0b8b4cc..78ba45cb9c 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECMonster.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECMonster.cs @@ -1,51 +1,49 @@ -using BrewMonster; -using CSNetwork.GPDataType; -using ModelRenderer.Scripts.GameData; +using CSNetwork.GPDataType; using System; -using Unity.VisualScripting; -using UnityEngine; -using static CECNPC; -public class CECMonster : CECNPC +namespace BrewMonster.Scripts.Player { - MONSTER_ESSENCE m_pDBEssence; - - public override void SetUpCECNPC(CECNPCMan pNPCMan) + public class CECMonster : CECNPC { - base.SetUpCECNPC(pNPCMan); - m_iCID = (int)Class_ID.OCID_MONSTER; - m_pDBEssence = default; - } - public override bool Init(int tid, in info_npc info, ReadOnlySpan packet, int infoOffset) - { - base.Init(tid, info, packet, infoOffset); - BrewMonster.BMLogger.Log("HoangDev: MonsterInit"); - var pDB = ElementDataManProvider.GetElementDataMan(); - DATA_TYPE DataType = default; - m_pDBEssence = (MONSTER_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); - m_fTouchRad = m_pDBEssence.size; - m_BasicProps.iLevel = m_pDBEssence.level; + MONSTER_ESSENCE m_pDBEssence; - QueueLoadNPCModel(); - - /* float fExt = m_fTouchRad * 1.5f; - m_cdr.vExts.Set(fExt, fExt, fExt); - m_pNPCModelPolicy.SetDefaultPickAABBExt(m_cdr.vExts);*/ - - // If NPC doesn't have specific name, use the name in database - if ((info.state & (int)PlayerNPCState.GP_STATE_NPC_NAME) == 0) + public override void SetUpCECNPC(CECNPCMan pNPCMan) { - m_strName = m_pDBEssence.name.ToString(); - /* if (m_pPateName) - m_pPateName->SetText(m_strName, false);*/ + base.SetUpCECNPC(pNPCMan); + m_iCID = (int)Class_ID.OCID_MONSTER; + m_pDBEssence = default; } + public override bool Init(int tid, in info_npc info, ReadOnlySpan packet, int infoOffset) + { + base.Init(tid, info, packet, infoOffset); + BrewMonster.BMLogger.Log("HoangDev: MonsterInit"); + var pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = default; + m_pDBEssence = (MONSTER_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + m_fTouchRad = m_pDBEssence.size; + m_BasicProps.iLevel = m_pDBEssence.level; - if ((m_pDBEssence.combined_switch & (uint)MONSTER_COMBINED_SWITCH. MCS_FORBID_SELECTION) != 0) - SetSelectable(false); + QueueLoadNPCModel(); - transform.position = EC_Utility.ToVector3(info.pos); + /* float fExt = m_fTouchRad * 1.5f; + m_cdr.vExts.Set(fExt, fExt, fExt); + m_pNPCModelPolicy.SetDefaultPickAABBExt(m_cdr.vExts);*/ - StartWork((int)WorkType.WT_NOTHING, (int)WorkID.WORK_STAND); - return true; + // If NPC doesn't have specific name, use the name in database + if ((info.state & (int)PlayerNPCState.GP_STATE_NPC_NAME) == 0) + { + m_strName = m_pDBEssence.name.ToString(); + /* if (m_pPateName) + m_pPateName->SetText(m_strName, false);*/ + } + + if ((m_pDBEssence.combined_switch & (uint)MONSTER_COMBINED_SWITCH.MCS_FORBID_SELECTION) != 0) + SetSelectable(false); + + transform.position = EC_Utility.ToVector3(info.pos); + + StartWork((int)WorkType.WT_NOTHING, (int)WorkID.WORK_STAND); + return true; + } } } diff --git a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs index 4ec062951a..67d8aab39b 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs @@ -6,982 +6,986 @@ using BrewMonster; using CSNetwork; using ModelRenderer.Scripts.Common; using System.IO; +using BrewMonster.Managers; -public class CECNPC : CECObject +namespace BrewMonster.Scripts.Player { - protected INFO m_NPCInfo; - protected private uint m_dwStates; - protected private uint m_dwStates2; - protected private Vector3 m_vServerPos; - protected private int m_iRandomProp; - protected private int m_iMoveEnv; - protected int m_idMaster; - protected string m_strName; - protected int m_idOwnerFaction; - protected float m_fDistToHost; - protected float m_fDistToHostH; - protected OtherPlayer_Move_Info m_cdr; - protected float m_fTouchRad = 1f; - protected ROLEBASICPROP m_BasicProps; - protected Vector3 m_vMoveDir; - protected int m_iPassiveMove; - protected bool m_bStopMove; - protected bool m_bStartFight; - protected int[] m_aWorks = new int[4]; - protected int m_iAction; - protected int m_idSelTarget; - protected int m_iCurWorkType; - protected int m_iCurWork; - protected int m_DisappearCnt; - protected bool m_bAboutToDie; - protected Vector3 m_vStopDir; - protected ROLEEXTPROP m_ExtProps; - protected CECNPCModelPolicy m_pNPCModelPolicy; - - [SerializeField] protected float m_fMoveSpeed; - [SerializeField] protected CharacterController _characterController; - - protected static CECStringTab m_ActionNames; - - - - public virtual void SetUpCECNPC(CECNPCMan pNPCMan) + public class CECNPC : CECObject { - base.SetUpCECObject(); - m_vServerPos = new Vector3(); - m_iCID = (int)Class_ID.OCID_NPC; - } - public virtual bool Init(int tid, in info_npc info, ReadOnlySpan packet, int infoOffset) - { - m_NPCInfo.nid = info.nid; - m_NPCInfo.tid = tid; - m_NPCInfo.vis_tid = info.vis_tid; - m_dwStates = (uint)info.state; - m_dwStates2 = (uint)info.state2; - m_vServerPos = EC_Utility.ToVector3(info.pos); - m_iRandomProp = (info.state & 0x0f00) >> 8; - m_pNPCModelPolicy = new CECNPCModelDefaultPolicy(this); - m_idSelTarget = 0; - m_iCurWorkType = -1; - m_fMoveSpeed = 1.0f; - m_iCurWork = 0; - m_bStartFight = false; - m_bAboutToDie = false; - m_DisappearCnt = 5000; + protected INFO m_NPCInfo; + protected private uint m_dwStates; + protected private uint m_dwStates2; + protected private Vector3 m_vServerPos; + protected private int m_iRandomProp; + protected private int m_iMoveEnv; + protected int m_idMaster; + protected string m_strName; + protected int m_idOwnerFaction; + protected float m_fDistToHost; + protected float m_fDistToHostH; + protected OtherPlayer_Move_Info m_cdr; + protected float m_fTouchRad = 1f; + protected ROLEBASICPROP m_BasicProps; + protected Vector3 m_vMoveDir; + protected int m_iPassiveMove; + protected bool m_bStopMove; + protected bool m_bStartFight; + protected int[] m_aWorks = new int[4]; + protected int m_iAction; + protected int m_idSelTarget; + protected int m_iCurWorkType; + protected int m_iCurWork; + protected int m_DisappearCnt; + protected bool m_bAboutToDie; + protected Vector3 m_vStopDir; + protected ROLEEXTPROP m_ExtProps; + protected CECNPCModelPolicy m_pNPCModelPolicy; - m_BasicProps = new ROLEBASICPROP(true); // struct mặc định, các trường số = 0, mảng đã tạo - m_ExtProps = new ROLEEXTPROP(true); + [SerializeField] protected float m_fMoveSpeed; + [SerializeField] protected CharacterController _characterController; - _characterController = GetComponent(); + protected static CECStringTab m_ActionNames; - m_iMoveEnv = (int)((info.state & PlayerNPCState.GP_STATE_NPC_FLY) != 0 ? Move_environment.MOVEENV_AIR - : (info.state & PlayerNPCState.GP_STATE_NPC_SWIM) != 0 ? Move_environment.MOVEENV_WATER - : Move_environment.MOVEENV_GROUND); - var npcVisual = GetComponent(); - m_pNPCModelPolicy.SetNpcVisual(npcVisual); - // 2) Cắt “đuôi” ngay sau phần cố định info_npc - int fixedSize = System.Runtime.InteropServices.Marshal.SizeOf(); - var tail = packet.Slice(infoOffset); - - var r = new ByteReader(tail); - - // 3) Đọc theo cờ state, giống C++ (pData tăng dần) - // EXTEND_PROPERTY - var ojexitStateCount = (uint)OBJECT_EXT_STATE.OBJECT_EXT_STATE_COUNT; - - var ext = new uint[ojexitStateCount]; - if ((info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0) - r.ReadInto(ext); - //SetNewExtendStates(0, ext, ojexitStateCount ); - - // PET - m_idMaster = 0; - if ((info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0) - m_idMaster = r.ReadInt32(); - - // NAME - if ((info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0) + public virtual void SetUpCECNPC(CECNPCMan pNPCMan) { - byte len = r.ReadByte(); - if (len > 0) + base.SetUpCECObject(); + m_vServerPos = new Vector3(); + m_iCID = (int)Class_ID.OCID_NPC; + } + public virtual bool Init(int tid, in info_npc info, ReadOnlySpan packet, int infoOffset) + { + m_NPCInfo.nid = info.nid; + m_NPCInfo.tid = tid; + m_NPCInfo.vis_tid = info.vis_tid; + m_dwStates = (uint)info.state; + m_dwStates2 = (uint)info.state2; + m_vServerPos = EC_Utility.ToVector3(info.pos); + m_iRandomProp = (info.state & 0x0f00) >> 8; + m_pNPCModelPolicy = new CECNPCModelDefaultPolicy(this); + m_idSelTarget = 0; + m_iCurWorkType = -1; + m_fMoveSpeed = 1.0f; + m_iCurWork = 0; + m_bStartFight = false; + m_bAboutToDie = false; + m_DisappearCnt = 5000; + + m_BasicProps = new ROLEBASICPROP(true); // struct mặc định, các trường số = 0, mảng đã tạo + m_ExtProps = new ROLEEXTPROP(true); + + _characterController = GetComponent(); + + m_iMoveEnv = (int)((info.state & PlayerNPCState.GP_STATE_NPC_FLY) != 0 ? Move_environment.MOVEENV_AIR + : (info.state & PlayerNPCState.GP_STATE_NPC_SWIM) != 0 ? Move_environment.MOVEENV_WATER + : Move_environment.MOVEENV_GROUND); + + var npcVisual = GetComponent(); + m_pNPCModelPolicy.SetNpcVisual(npcVisual); + + // 2) Cắt “đuôi” ngay sau phần cố định info_npc + int fixedSize = System.Runtime.InteropServices.Marshal.SizeOf(); + var tail = packet.Slice(infoOffset); + + var r = new ByteReader(tail); + + // 3) Đọc theo cờ state, giống C++ (pData tăng dần) + // EXTEND_PROPERTY + var ojexitStateCount = (uint)OBJECT_EXT_STATE.OBJECT_EXT_STATE_COUNT; + + var ext = new uint[ojexitStateCount]; + if ((info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0) + r.ReadInto(ext); + //SetNewExtendStates(0, ext, ojexitStateCount ); + + // PET + m_idMaster = 0; + if ((info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0) + m_idMaster = r.ReadInt32(); + + // NAME + if ((info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0) { - // ACHAR thường là UTF-16LE → len là số byte - var nameBytes = r.ReadBytes(len); - m_strName = System.Text.Encoding.Unicode.GetString(nameBytes); - } - } - - SetSelectable((info.state & PlayerNPCState.GP_STATE_FORBIDBESELECTED) == 0); - - // MULTIOBJ_EFFECT - if ((info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0) - { - int n = r.ReadInt32(); - for (int i = 0; i < n; i++) - { - int idTarget = r.ReadInt32(); - char cType = (char)r.ReadByte(); - //AddMultiObjectEffect(idTarget, cType); - } - } - - // MAFIA - m_idOwnerFaction = 0; - if ((info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0) - m_idOwnerFaction = r.ReadInt32(); - - m_cdr.fStepHeight = 0.4f; - m_cdr.vVelocity.Clear(); - - var pHost = GameController.Instance.GetHostPlayer(); - if (pHost != null) - { - m_fDistToHost = Vector3.Distance(m_vServerPos, pHost.transform.position); - m_fDistToHostH = Vector2.Distance( - new Vector2(m_vServerPos.x, m_vServerPos.z), - new Vector2(pHost.transform.position.x, pHost.transform.position.z)); - } - - return true; - } - private void Update() - { - switch (m_iCurWork) - { - case (int)WorkID.WORK_MOVE: TickWork_Move(Time.deltaTime); break; - } - } - public void TickWork_Move(float dwDeltaTime) - { - if (m_bAboutToDie) - { - WorkFinished((int)WorkID.WORK_MOVE); - } - else if (MovingTo(dwDeltaTime)) - { - /* if (!IsDirFixed()) - { - SetDestDirAndUp(m_vStopDir, g_vAxisY, 150); - }*/ - - WorkFinished((int)WorkID.WORK_MOVE); - - // when stopped, we should rebuild the convex brushes for collision detection. - //RebuildTraceBrush(); - } - } - public bool MovingTo(float deltaTime) - { - bool reachedDestination = false; - Vector3 curPos = transform.position; - - if (m_bStopMove) - { - - // Tính hướng đến serverPos - Vector3 dir = (m_vServerPos - curPos); - float dist = dir.magnitude; - if (dist > 0.001f) - { - - dir.Normalize(); - - // Di chuyển một bước - Vector3 moveDelta = dir * m_fMoveSpeed * deltaTime; - if (moveDelta.magnitude >= dist) + byte len = r.ReadByte(); + if (len > 0) { - // Nếu vượt quá đích thì teleport + // ACHAR thường là UTF-16LE → len là số byte + var nameBytes = r.ReadBytes(len); + m_strName = System.Text.Encoding.Unicode.GetString(nameBytes); + } + } + + SetSelectable((info.state & PlayerNPCState.GP_STATE_FORBIDBESELECTED) == 0); + + // MULTIOBJ_EFFECT + if ((info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0) + { + int n = r.ReadInt32(); + for (int i = 0; i < n; i++) + { + int idTarget = r.ReadInt32(); + char cType = (char)r.ReadByte(); + //AddMultiObjectEffect(idTarget, cType); + } + } + + // MAFIA + m_idOwnerFaction = 0; + if ((info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0) + m_idOwnerFaction = r.ReadInt32(); + + m_cdr.fStepHeight = 0.4f; + m_cdr.vVelocity.Clear(); + + var pHost = GameController.Instance.GetHostPlayer(); + if (pHost != null) + { + m_fDistToHost = Vector3.Distance(m_vServerPos, pHost.transform.position); + m_fDistToHostH = Vector2.Distance( + new Vector2(m_vServerPos.x, m_vServerPos.z), + new Vector2(pHost.transform.position.x, pHost.transform.position.z)); + } + + return true; + } + private void Update() + { + switch (m_iCurWork) + { + case (int)WorkID.WORK_MOVE: TickWork_Move(Time.deltaTime); break; + } + } + public void TickWork_Move(float dwDeltaTime) + { + if (m_bAboutToDie) + { + WorkFinished((int)WorkID.WORK_MOVE); + } + else if (MovingTo(dwDeltaTime)) + { + /* if (!IsDirFixed()) + { + SetDestDirAndUp(m_vStopDir, g_vAxisY, 150); + }*/ + + WorkFinished((int)WorkID.WORK_MOVE); + + // when stopped, we should rebuild the convex brushes for collision detection. + //RebuildTraceBrush(); + } + } + public bool MovingTo(float deltaTime) + { + bool reachedDestination = false; + Vector3 curPos = transform.position; + + if (m_bStopMove) + { + + // Tính hướng đến serverPos + Vector3 dir = (m_vServerPos - curPos); + float dist = dir.magnitude; + if (dist > 0.001f) + { + + dir.Normalize(); + + // Di chuyển một bước + Vector3 moveDelta = dir * m_fMoveSpeed * deltaTime; + if (moveDelta.magnitude >= dist) + { + // Nếu vượt quá đích thì teleport + _characterController.enabled = false; + transform.position = m_vServerPos; + _characterController.enabled = true; + reachedDestination = true; + FaceDirectionImmediate(moveDelta); + + } + else + { + _characterController.Move(moveDelta); + FaceDirectionImmediate(moveDelta); + } + } + } + else // đang move bình thường + { + + float dist = (m_vServerPos - curPos).magnitude; + + if (IsLag(dist)) + { + // Teleport nếu lag xa _characterController.enabled = false; transform.position = m_vServerPos; _characterController.enabled = true; - reachedDestination = true; - FaceDirectionImmediate(moveDelta); + m_vStopDir = transform.forward; + return true; } - else + + Vector3 dir = m_vMoveDir.normalized; + Vector3 moveDelta = dir * m_fMoveSpeed * deltaTime; + _characterController.Move(moveDelta); + // Thêm xoay theo trục Y + FaceDirectionSmooth(dir, 10f, deltaTime); + } + + return reachedDestination; + } + /// + /// Xoay model NGAY LẬP TỨC theo hướng chỉ định (giữ nguyên trục Y đứng thẳng). + /// + public void FaceDirectionImmediate(Vector3 dir) + { + if (dir.sqrMagnitude > 0.0001f) + { + Vector3 flatDir = new Vector3(dir.x, 0, dir.z); + if (flatDir.sqrMagnitude > 0.0001f) { - _characterController.Move(moveDelta); - FaceDirectionImmediate(moveDelta); + transform.rotation = Quaternion.LookRotation(flatDir, Vector3.up); } } } - else // đang move bình thường + + /// + /// Xoay model TỪ TỪ (mượt) theo hướng chỉ định (giữ nguyên trục Y đứng thẳng). + /// rotateSpeed = tốc độ xoay (độ mượt), ví dụ 10f. + /// deltaTime = Time.deltaTime trong Update. + /// + public void FaceDirectionSmooth(Vector3 dir, float rotateSpeed, float deltaTime) { - - float dist = (m_vServerPos - curPos).magnitude; - - if (IsLag(dist)) + if (dir.sqrMagnitude > 0.0001f) { - // Teleport nếu lag xa - _characterController.enabled = false; - transform.position = m_vServerPos; - _characterController.enabled = true; - - m_vStopDir = transform.forward; - return true; - } - - Vector3 dir = m_vMoveDir.normalized; - Vector3 moveDelta = dir * m_fMoveSpeed * deltaTime; - _characterController.Move(moveDelta); - // Thêm xoay theo trục Y - FaceDirectionSmooth(dir, 10f, deltaTime); - } - - return reachedDestination; - } - /// - /// Xoay model NGAY LẬP TỨC theo hướng chỉ định (giữ nguyên trục Y đứng thẳng). - /// - public void FaceDirectionImmediate(Vector3 dir) - { - if (dir.sqrMagnitude > 0.0001f) - { - Vector3 flatDir = new Vector3(dir.x, 0, dir.z); - if (flatDir.sqrMagnitude > 0.0001f) - { - transform.rotation = Quaternion.LookRotation(flatDir, Vector3.up); - } - } - } - - /// - /// Xoay model TỪ TỪ (mượt) theo hướng chỉ định (giữ nguyên trục Y đứng thẳng). - /// rotateSpeed = tốc độ xoay (độ mượt), ví dụ 10f. - /// deltaTime = Time.deltaTime trong Update. - /// - public void FaceDirectionSmooth(Vector3 dir, float rotateSpeed, float deltaTime) - { - if (dir.sqrMagnitude > 0.0001f) - { - Vector3 flatDir = new Vector3(dir.x, 0, dir.z); - if (flatDir.sqrMagnitude > 0.0001f) - { - Quaternion targetRot = Quaternion.LookRotation(flatDir, Vector3.up); - transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, deltaTime * rotateSpeed); - } - } - } - - public void WorkFinished(int iWorkID) - { - // Note: below judge can prevent many problems when we attempt to - // finish a work but don't assure we are doing this work - BrewMonster.BMLogger.Log("HoangDev : WorkFinished :"+ iWorkID); - if (m_iCurWork != iWorkID) - return; - - // ASSERT equivalent - if (m_iCurWork <= 0 || m_iCurWorkType < 0) - { - throw new InvalidOperationException("Invalid work state in WorkFinished"); - } - - // Release current work - ReleaseWork(m_iCurWorkType); - - for (int i = m_iCurWorkType - 1; i >= 0; i--) - { - if (m_aWorks[i] != 0) // giả định m_aWorks là mảng int workIDs - { - m_iCurWorkType = i; - StartWorkByID(m_aWorks[i], 0); - break; - } - } - - // clear passive move flag - if (iWorkID == (int)WorkID.WORK_MOVE) - m_iPassiveMove = 0; - } - - public static bool InitStaticRes() - { - m_ActionNames = new CECStringTab(); - // Load action names from file - if (!m_ActionNames.IsInitialized()) - m_ActionNames.Init("actions_npc", false); - - return true; - } - - public void TransformShape(int vis_tid) - { - if (m_NPCInfo.vis_tid == vis_tid) - { - return; - } - m_NPCInfo.vis_tid = vis_tid; - - QueueLoadNPCModel(); - } - public void QueueLoadNPCModel() - { - /* if (ShouldUseMasterModel()) - { - if (GetMaster()) - { - return; // ÄÜ»ñÈ¡½ÇɫģÐÍʱ£¬µ½Ï¸ö Tick ¼ÓÔØÄ£ÐÍ - } // ÎÞ·¨»ñÈ¡½Çɫʱ¡¢ÔÝʱʹÓà NPC Ä£ÐÍ - }*/ - int tid = 0; - string szModelFile = ""; - if (!GetVisibleModel(out tid, out szModelFile)) - { - return; - } - - var nameMonster = Path.GetFileNameWithoutExtension(szModelFile); - var model = NPCBuilder.Instance.GetModelByName(nameMonster); - if (model == null) return; - - var monsterModel = Instantiate(model, transform); - monsterModel.SetActive(true); - var npcVisual = GetComponent(); - npcVisual.InitNPCEventDoneHandler(); - - //QueueECModelForLoad(MTL_ECM_NPC, GetNPCInfo().nid, GetBornStamp(), GetServerPos(), szModelFile, tid); - } - public ROLEBASICPROP GetBasicProps() { return m_BasicProps; } - public ROLEEXTPROP GetExtendProps() { return m_ExtProps; } - public void SetSelectedTarget(int id) { m_idSelTarget = id; } - public bool GetVisibleModel(out int tid, out string szModelFile) - { - tid = 0; - szModelFile = string.Empty; - - // nếu vis_tid có model file - if (GetModelFile(GetNPCInfo().vis_tid, out szModelFile)) - { - tid = GetNPCInfo().vis_tid; - } - // nếu không có thì thử lấy từ tid thường - else if (GetModelFile(GetNPCInfo().tid, out szModelFile)) - { - tid = GetNPCInfo().tid; - } - - return tid > 0; - } - public bool GetModelFile(int tid, out string szModelFile) - { - szModelFile = string.Empty; - - // Lấy database - var pDB = ElementDataManProvider.GetElementDataMan(); // g_pGame->GetElementDataMan() - DATA_TYPE dataType = default; - - // Giả định get_data_ptr trả về object (Essence) và out DataType - var pDBEssence = pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref dataType); - if (pDBEssence == null) - return false; - - bool ret = true; - - switch (dataType) - { - case DATA_TYPE.DT_MONSTER_ESSENCE: + Vector3 flatDir = new Vector3(dir.x, 0, dir.z); + if (flatDir.sqrMagnitude > 0.0001f) { - var ess = (MONSTER_ESSENCE)pDBEssence; - szModelFile = ByteToStringUtils.ByteArrayToCP936String(ess.file_model); + Quaternion targetRot = Quaternion.LookRotation(flatDir, Vector3.up); + transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, deltaTime * rotateSpeed); + } + } + } + + public void WorkFinished(int iWorkID) + { + // Note: below judge can prevent many problems when we attempt to + // finish a work but don't assure we are doing this work + BrewMonster.BMLogger.Log("HoangDev : WorkFinished :" + iWorkID); + if (m_iCurWork != iWorkID) + return; + + // ASSERT equivalent + if (m_iCurWork <= 0 || m_iCurWorkType < 0) + { + throw new InvalidOperationException("Invalid work state in WorkFinished"); + } + + // Release current work + ReleaseWork(m_iCurWorkType); + + for (int i = m_iCurWorkType - 1; i >= 0; i--) + { + if (m_aWorks[i] != 0) // giả định m_aWorks là mảng int workIDs + { + m_iCurWorkType = i; + StartWorkByID(m_aWorks[i], 0); break; } - case DATA_TYPE.DT_PET_ESSENCE: - { - var ess = (PET_ESSENCE)pDBEssence; - szModelFile = ByteToStringUtils.ByteArrayToCP936String(ess.file_model); - break; - } - case DATA_TYPE.DT_NPC_ESSENCE: - { - var ess = (NPC_ESSENCE)pDBEssence; - szModelFile = ByteToStringUtils.ByteArrayToCP936String(ess.file_model); - break; - } - default: - ret = false; - break; + } + + // clear passive move flag + if (iWorkID == (int)WorkID.WORK_MOVE) + m_iPassiveMove = 0; } - return ret; - } - public static void ReleaseStaticRes() - { - m_ActionNames.Release(); - } - public static string GetBaseActionName(int iAct) - { - return m_ActionNames.GetANSIString(iAct); - } - public static bool IsAttackAction(int iAct) - { - return iAct == (int)NPCActionIndex.ACT_ATTACK1 - || iAct == (int)NPCActionIndex.ACT_ATTACK2 - || iAct == (int)NPCActionIndex.ACT_NPC_ATTACK; - } - public void StopMoveTo(cmd_object_stop_move cmd) - { - /* if (IsDead()) - return;*/ - - int iMoveMode = cmd.move_mode & (int)GPMoveMode.GP_MOVE_MASK; - - m_vMoveDir = EC_Utility.ToVector3(cmd.dest) - transform.position; - m_bStopMove = true; - m_fMoveSpeed = EC_Utility.FIX8TOFLOAT(cmd.sSpeed); - m_vServerPos = EC_Utility.ToVector3(cmd.dest); - m_vStopDir = EC_Utility.glb_DecompressDirH(cmd.dir); - - // only store the passive move mode - m_iPassiveMove = (iMoveMode == (int)GPMoveMode.GP_MOVE_PUSH || - iMoveMode == (int)GPMoveMode.GP_MOVE_PULL || - iMoveMode == (int)GPMoveMode.GP_MOVE_BLINK) - ? iMoveMode : 0; - - if (IsDirFixed()) + public static bool InitStaticRes() { - // hướng cố định, set luôn - transform.forward = m_vStopDir; + m_ActionNames = new CECStringTab(); + // Load action names from file + if (!m_ActionNames.IsInitialized()) + m_ActionNames.Init("actions_npc", false); + + return true; } - float fDist = m_vMoveDir.normalized.magnitude; // Normalize() trả về float trong C++, ở đây cần xử lý lại - m_vMoveDir.Normalize(); - - // Trong các trường hợp dưới thì kéo NPC về đích - if (iMoveMode != (int)GPMoveMode.GP_MOVE_RETURN && - iMoveMode != (int)GPMoveMode.GP_MOVE_PUSH && - iMoveMode != (int)GPMoveMode.GP_MOVE_PULL) + public void TransformShape(int vis_tid) { - bool bPull = false; - - if (IsLag(fDist)) + if (m_NPCInfo.vis_tid == vis_tid) { - // case 1 - bPull = true; - } - else if (fDist < 1.0f) - { - // case 2 - Vector3 vDirH = m_vMoveDir; - vDirH.y = 0.0f; - vDirH.Normalize(); - if (Vector3.Dot(vDirH, m_vStopDir) < 0.7f) - bPull = true; - } - else if (iMoveMode == (int)GPMoveMode.GP_MOVE_BLINK) - { - // case 3 - bPull = true; - } - - if (bPull) - { - SetPos(EC_Utility.ToVector3(cmd.dest)); - WorkFinished((int)WorkID.WORK_MOVE); return; } - } + m_NPCInfo.vis_tid = vis_tid; - if (!IsDirFixed() && m_iPassiveMove == 0) + QueueLoadNPCModel(); + } + public void QueueLoadNPCModel() { - Vector3 vDir = m_vMoveDir; - vDir.y = 0.0f; - if (vDir != Vector3.zero) + /* if (ShouldUseMasterModel()) + { + if (GetMaster()) + { + return; // ÄÜ»ñÈ¡½ÇɫģÐÍʱ£¬µ½Ï¸ö Tick ¼ÓÔØÄ£ÐÍ + } // ÎÞ·¨»ñÈ¡½Çɫʱ¡¢ÔÝʱʹÓà NPC Ä£ÐÍ + }*/ + int tid = 0; + string szModelFile = ""; + if (!GetVisibleModel(out tid, out szModelFile)) { - vDir.Normalize(); + return; + } + + var nameMonster = Path.GetFileNameWithoutExtension(szModelFile); + var model = NPCBuilder.Instance.GetModelByName(nameMonster); + if (model == null) return; + + var monsterModel = Instantiate(model, transform); + monsterModel.SetActive(true); + var npcVisual = GetComponent(); + npcVisual.InitNPCEventDoneHandler(); + + //QueueECModelForLoad(MTL_ECM_NPC, GetNPCInfo().nid, GetBornStamp(), GetServerPos(), szModelFile, tid); + } + public ROLEBASICPROP GetBasicProps() { return m_BasicProps; } + public ROLEEXTPROP GetExtendProps() { return m_ExtProps; } + public void SetSelectedTarget(int id) { m_idSelTarget = id; } + public bool GetVisibleModel(out int tid, out string szModelFile) + { + tid = 0; + szModelFile = string.Empty; + + // nếu vis_tid có model file + if (GetModelFile(GetNPCInfo().vis_tid, out szModelFile)) + { + tid = GetNPCInfo().vis_tid; + } + // nếu không có thì thử lấy từ tid thường + else if (GetModelFile(GetNPCInfo().tid, out szModelFile)) + { + tid = GetNPCInfo().tid; + } + + return tid > 0; + } + public bool GetModelFile(int tid, out string szModelFile) + { + szModelFile = string.Empty; + + // Lấy database + var pDB = ElementDataManProvider.GetElementDataMan(); // g_pGame->GetElementDataMan() + DATA_TYPE dataType = default; + + // Giả định get_data_ptr trả về object (Essence) và out DataType + var pDBEssence = pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref dataType); + if (pDBEssence == null) + return false; + + bool ret = true; + + switch (dataType) + { + case DATA_TYPE.DT_MONSTER_ESSENCE: + { + var ess = (MONSTER_ESSENCE)pDBEssence; + szModelFile = ByteToStringUtils.ByteArrayToCP936String(ess.file_model); + break; + } + case DATA_TYPE.DT_PET_ESSENCE: + { + var ess = (PET_ESSENCE)pDBEssence; + szModelFile = ByteToStringUtils.ByteArrayToCP936String(ess.file_model); + break; + } + case DATA_TYPE.DT_NPC_ESSENCE: + { + var ess = (NPC_ESSENCE)pDBEssence; + szModelFile = ByteToStringUtils.ByteArrayToCP936String(ess.file_model); + break; + } + default: + ret = false; + break; + } + + return ret; + } + public static void ReleaseStaticRes() + { + m_ActionNames.Release(); + } + public static string GetBaseActionName(int iAct) + { + return m_ActionNames.GetANSIString(iAct); + } + public static bool IsAttackAction(int iAct) + { + return iAct == (int)NPCActionIndex.ACT_ATTACK1 + || iAct == (int)NPCActionIndex.ACT_ATTACK2 + || iAct == (int)NPCActionIndex.ACT_NPC_ATTACK; + } + public void StopMoveTo(cmd_object_stop_move cmd) + { + /* if (IsDead()) + return;*/ + + int iMoveMode = cmd.move_mode & (int)GPMoveMode.GP_MOVE_MASK; + + m_vMoveDir = EC_Utility.ToVector3(cmd.dest) - transform.position; + m_bStopMove = true; + m_fMoveSpeed = EC_Utility.FIX8TOFLOAT(cmd.sSpeed); + m_vServerPos = EC_Utility.ToVector3(cmd.dest); + m_vStopDir = EC_Utility.glb_DecompressDirH(cmd.dir); + + // only store the passive move mode + m_iPassiveMove = (iMoveMode == (int)GPMoveMode.GP_MOVE_PUSH || + iMoveMode == (int)GPMoveMode.GP_MOVE_PULL || + iMoveMode == (int)GPMoveMode.GP_MOVE_BLINK) + ? iMoveMode : 0; + + if (IsDirFixed()) + { + // hướng cố định, set luôn + transform.forward = m_vStopDir; + } + + float fDist = m_vMoveDir.normalized.magnitude; // Normalize() trả về float trong C++, ở đây cần xử lý lại + m_vMoveDir.Normalize(); + + // Trong các trường hợp dưới thì kéo NPC về đích + if (iMoveMode != (int)GPMoveMode.GP_MOVE_RETURN && + iMoveMode != (int)GPMoveMode.GP_MOVE_PUSH && + iMoveMode != (int)GPMoveMode.GP_MOVE_PULL) + { + bool bPull = false; + + if (IsLag(fDist)) + { + // case 1 + bPull = true; + } + else if (fDist < 1.0f) + { + // case 2 + Vector3 vDirH = m_vMoveDir; + vDirH.y = 0.0f; + vDirH.Normalize(); + if (Vector3.Dot(vDirH, m_vStopDir) < 0.7f) + bPull = true; + } + else if (iMoveMode == (int)GPMoveMode.GP_MOVE_BLINK) + { + // case 3 + bPull = true; + } + + if (bPull) + { + SetPos(EC_Utility.ToVector3(cmd.dest)); + WorkFinished((int)WorkID.WORK_MOVE); + return; + } + } + + if (!IsDirFixed() && m_iPassiveMove == 0) + { + Vector3 vDir = m_vMoveDir; + vDir.y = 0.0f; + if (vDir != Vector3.zero) + { + vDir.Normalize(); + } + } + + if (m_aWorks[(int)WorkType.WT_NORMAL] != (int)WorkID.WORK_MOVE) + { + StartWork((int)WorkType.WT_NORMAL, (int)WorkID.WORK_MOVE); + + if (m_iPassiveMove == 0) + { + PlayMoveAction(iMoveMode); + } } } - - if (m_aWorks[(int)WorkType.WT_NORMAL] != (int)WorkID.WORK_MOVE) + void SetPos(Vector3 pos) { - StartWork((int)WorkType.WT_NORMAL, (int)WorkID.WORK_MOVE); + transform.position = pos; + } + public void MoveTo(cmd_object_move Cmd) + { + if (Cmd.use_time == 0) + return; + var dest = EC_Utility.ToVector3(Cmd.dest); + m_vServerPos = dest; + m_vMoveDir = dest - transform.position; + float fDist = m_vMoveDir.magnitude; // lấy độ dài ban đầu + m_vMoveDir.Normalize(); // giả sử Normalize() trả về độ dài trước khi chuẩn hóa - if (m_iPassiveMove == 0) + // If destination position is too far, forcely pull player + if (IsLag(fDist)) { + transform.position = EC_Utility.ToVector3(Cmd.dest); + return; + } + + int iMoveMode = Cmd.move_mode & (int)GPMoveMode.GP_MOVE_MASK; + + m_bStopMove = false; + + if (iMoveMode == (int)GPMoveMode.GP_MOVE_PUSH || iMoveMode == (int)GPMoveMode.GP_MOVE_PULL) + { + // Push back or pull should occur in stop move command + UnityEngine.Debug.Assert(false, "Invalid move mode: push/pull inside MoveTo"); + return; + } + + m_cdr.bTraceGround = true; + + if ((Cmd.move_mode & (int)GPMoveMode.GP_MOVE_AIR) != 0) + { + m_iMoveEnv = (int)MoveEnvironment.MOVEENV_AIR; + m_cdr.bTraceGround = false; + } + else if ((Cmd.move_mode & (int)GPMoveMode.GP_MOVE_WATER) != 0) + { + m_iMoveEnv = (int)MoveEnvironment.MOVEENV_WATER; + m_cdr.bTraceGround = false; + } + else + { + m_iMoveEnv = (int)MoveEnvironment.MOVEENV_GROUND; + + int iTemp = iMoveMode & (int)GPMoveMode.GP_MOVE_MASK; + if (iTemp == (int)GPMoveMode.GP_MOVE_FALL || iTemp == (int)GPMoveMode.GP_MOVE_FLYFALL) + m_cdr.bTraceGround = false; + } + + m_fMoveSpeed = fDist / (Cmd.use_time * 0.001f); + // Adjust NPC's direction + /*if (!IsDirFixed()) + { + var vDir = m_vMoveDir; + vDir.y = 0.0f; + if (!vDir.IsZero()) + { + vDir.Normalize(); + SetDestDirAndUp(vDir, g_vAxisY, 150); + } + } + */ + + if (m_aWorks[(int)WorkType.WT_NORMAL] != (int)WorkID.WORK_MOVE || ShouldPlayNewActionFor(iMoveMode)) + { + StartWork((int)WorkType.WT_NORMAL, (int)WorkID.WORK_MOVE); + // Play run or walk action + PlayMoveAction(iMoveMode); } } - } - void SetPos(Vector3 pos) - { - transform.position = pos; - } - public void MoveTo(cmd_object_move Cmd) - { - if (Cmd.use_time == 0) - return; - var dest = EC_Utility.ToVector3(Cmd.dest); - m_vServerPos = dest; - m_vMoveDir = dest - transform.position; - float fDist = m_vMoveDir.magnitude; // lấy độ dài ban đầu - m_vMoveDir.Normalize(); // giả sử Normalize() trả về độ dài trước khi chuẩn hóa - - // If destination position is too far, forcely pull player - if (IsLag(fDist)) + public bool IsDirFixed() { return (m_dwStates & PlayerNPCState.GP_STATE_NPC_FIXDIR) != 0 ? true : false; } + public void ReleaseWork(int iWorkType) { - transform.position = EC_Utility.ToVector3(Cmd.dest); - return; - } + //BrewMonster.BMLogger.LogError("HoangDev : ReleaseWorkl :"+ iWorkType); + Debug.Assert(iWorkType >= 0 && iWorkType < (int)WorkType.NUM_WORKTYPE); - int iMoveMode = Cmd.move_mode & (int)GPMoveMode.GP_MOVE_MASK; - - m_bStopMove = false; - - if (iMoveMode == (int)GPMoveMode.GP_MOVE_PUSH || iMoveMode == (int)GPMoveMode.GP_MOVE_PULL) - { - // Push back or pull should occur in stop move command - UnityEngine.Debug.Assert(false, "Invalid move mode: push/pull inside MoveTo"); - return; - } - - m_cdr.bTraceGround = true; - - if ((Cmd.move_mode & (int)GPMoveMode.GP_MOVE_AIR) != 0) - { - m_iMoveEnv = (int)MoveEnvironment.MOVEENV_AIR; - m_cdr.bTraceGround = false; - } - else if ((Cmd.move_mode & (int)GPMoveMode.GP_MOVE_WATER) != 0) - { - m_iMoveEnv = (int)MoveEnvironment.MOVEENV_WATER; - m_cdr.bTraceGround = false; - } - else - { - m_iMoveEnv = (int)MoveEnvironment.MOVEENV_GROUND; - - int iTemp = iMoveMode & (int)GPMoveMode.GP_MOVE_MASK; - if (iTemp == (int)GPMoveMode.GP_MOVE_FALL || iTemp == (int)GPMoveMode.GP_MOVE_FLYFALL) - m_cdr.bTraceGround = false; - } - - m_fMoveSpeed = fDist / (Cmd.use_time * 0.001f); - // Adjust NPC's direction - /*if (!IsDirFixed()) - { - var vDir = m_vMoveDir; - vDir.y = 0.0f; - if (!vDir.IsZero()) + switch (m_aWorks[iWorkType]) { - vDir.Normalize(); - SetDestDirAndUp(vDir, g_vAxisY, 150); - } - } -*/ + case (int)WorkID.WORK_STAND: + break; - if (m_aWorks[(int)WorkType.WT_NORMAL] != (int)WorkID.WORK_MOVE || ShouldPlayNewActionFor(iMoveMode)) - { - StartWork((int)WorkType.WT_NORMAL, (int)WorkID.WORK_MOVE); - // Play run or walk action + case (int)WorkID.WORK_FIGHT: + break; - PlayMoveAction(iMoveMode); - } - } - public bool IsDirFixed() { return (m_dwStates & PlayerNPCState.GP_STATE_NPC_FIXDIR) != 0 ? true : false; } - public void ReleaseWork(int iWorkType) - { - //BrewMonster.BMLogger.LogError("HoangDev : ReleaseWorkl :"+ iWorkType); - Debug.Assert(iWorkType >= 0 && iWorkType < (int)WorkType.NUM_WORKTYPE); + case (int)WorkID.WORK_SPELL: + break; - switch (m_aWorks[iWorkType]) - { - case (int)WorkID.WORK_STAND: - break; + case (int)WorkID.WORK_DEAD: + break; - case (int)WorkID.WORK_FIGHT: - break; - - case (int)WorkID.WORK_SPELL: - break; - - case (int)WorkID.WORK_DEAD: - break; - - case (int)WorkID.WORK_MOVE: - { - // Để tránh trường hợp WORK_MOVE bị ghi đè bởi WORK_SPELL hoặc WORK khác - // dẫn đến NPC sai vị trí, ta sẽ kiểm tra và kéo NPC về đúng server position - var pos = m_vServerPos; - var vDelta = pos - transform.position; - float fDist = vDelta.magnitude; // Vector3.magnitude trong Unity - - if (fDist > 0.1f) + case (int)WorkID.WORK_MOVE: { - transform.position = (pos); - /* if (!IsDirFixed()) - { - SetDestDirAndUp(m_vStopDir, Vector3.up, 150); - }*/ - //RebuildTraceBrush(); + // Để tránh trường hợp WORK_MOVE bị ghi đè bởi WORK_SPELL hoặc WORK khác + // dẫn đến NPC sai vị trí, ta sẽ kiểm tra và kéo NPC về đúng server position + var pos = m_vServerPos; + var vDelta = pos - transform.position; + float fDist = vDelta.magnitude; // Vector3.magnitude trong Unity + + if (fDist > 0.1f) + { + transform.position = (pos); + /* if (!IsDirFixed()) + { + SetDestDirAndUp(m_vStopDir, Vector3.up, 150); + }*/ + //RebuildTraceBrush(); + } + break; } - break; - } - case (int)WorkID.WORK_POLICYACTION: - { - /* m_pNPCModelPolicy?.StopChannelAction(); - m_pPolicyAction = null; - m_nPolicyActionIntervalTimer = 0;*/ - break; - } + case (int)WorkID.WORK_POLICYACTION: + { + /* m_pNPCModelPolicy?.StopChannelAction(); + m_pPolicyAction = null; + m_nPolicyActionIntervalTimer = 0;*/ + break; + } + } + + m_aWorks[iWorkType] = 0; + + if (m_iCurWorkType == iWorkType) + m_iCurWork = 0; } - m_aWorks[iWorkType] = 0; - - if (m_iCurWorkType == iWorkType) - m_iCurWork = 0; - } - - public void StartWork(int iWorkType, int iNewWork, uint dwParam = 0) - { - Debug.Assert(iWorkType >= 0 && iWorkType < (int)WorkType.NUM_WORKTYPE); - - if (iNewWork == (int)WorkID.WORK_DEAD) + public void StartWork(int iWorkType, int iNewWork, uint dwParam = 0) { - // Dead is a special work - ReleaseWork((int)WorkType.WT_INTERRUPT); - ReleaseWork((int)WorkType.WT_NORMAL); + Debug.Assert(iWorkType >= 0 && iWorkType < (int)WorkType.NUM_WORKTYPE); - m_aWorks[(int)WorkType.WT_NORMAL] = iNewWork; - m_iCurWorkType = (int)WorkType.WT_NORMAL; - } - else if (iWorkType == (int)WorkType.WT_INTERRUPT) - { - // Release old work - ReleaseWork((int)WorkType.WT_INTERRUPT); - m_aWorks[(int)WorkType.WT_INTERRUPT] = iNewWork; - - if (m_iCurWorkType == (int)WorkType.WT_NORMAL || m_iCurWorkType == (int)WorkType.WT_NOTHING) - StopWork(m_iCurWorkType); - - m_aWorks[(int)WorkType.WT_INTERRUPT] = iNewWork; - m_iCurWorkType = (int)WorkType.WT_INTERRUPT; - } - else if (iWorkType == (int)WorkType.WT_NORMAL) - { - // Release old work - ReleaseWork((int)WorkType.WT_NORMAL); - m_aWorks[(int)WorkType.WT_NORMAL] = iNewWork; - - if (m_iCurWorkType < 0 || m_iCurWorkType == (int)WorkType.WT_NORMAL || m_iCurWorkType == (int)WorkType.WT_NOTHING) + if (iNewWork == (int)WorkID.WORK_DEAD) { - if (m_iCurWorkType == (int)WorkType.WT_NOTHING) - StopWork((int)WorkType.WT_NOTHING); + // Dead is a special work + ReleaseWork((int)WorkType.WT_INTERRUPT); + ReleaseWork((int)WorkType.WT_NORMAL); + m_aWorks[(int)WorkType.WT_NORMAL] = iNewWork; m_iCurWorkType = (int)WorkType.WT_NORMAL; } - else - return; - } - else // iWorkType == WT_NOTHING - { - // Release old work - ReleaseWork((int)WorkType.WT_NOTHING); - m_aWorks[(int)WorkType.WT_NOTHING] = iNewWork; + else if (iWorkType == (int)WorkType.WT_INTERRUPT) + { + // Release old work + ReleaseWork((int)WorkType.WT_INTERRUPT); + m_aWorks[(int)WorkType.WT_INTERRUPT] = iNewWork; - if (m_iCurWorkType < 0 || m_iCurWorkType == (int)WorkType.WT_NOTHING) - m_iCurWorkType = (int)WorkType.WT_NOTHING; - else - return; - } + if (m_iCurWorkType == (int)WorkType.WT_NORMAL || m_iCurWorkType == (int)WorkType.WT_NOTHING) + StopWork(m_iCurWorkType); - StartWorkByID(iNewWork, dwParam); - } + m_aWorks[(int)WorkType.WT_INTERRUPT] = iNewWork; + m_iCurWorkType = (int)WorkType.WT_INTERRUPT; + } + else if (iWorkType == (int)WorkType.WT_NORMAL) + { + // Release old work + ReleaseWork((int)WorkType.WT_NORMAL); + m_aWorks[(int)WorkType.WT_NORMAL] = iNewWork; - public void StopWork(int iWorkType) - { - } - public void StartWorkByID(int iWorkID, uint dwParam) - { - // Ignore all message if this NPC is dead. - // if (IsDead()) - // return; - - switch (iWorkID) - { - case (int)WorkID.WORK_STAND: StartWork_Stand(dwParam); break; - case (int)WorkID.WORK_FIGHT: StartWork_Fight(dwParam); break; - case (int)WorkID.WORK_SPELL: StartWork_Spell(dwParam); break; - case (int)WorkID.WORK_DEAD: StartWork_Dead(dwParam); break; - case (int)WorkID.WORK_MOVE: StartWork_Move(dwParam); break; - case (int)WorkID.WORK_POLICYACTION: StartWork_PolicyAction(dwParam); break; - } - - // if (iWorkID != WORK_MOVE) m_iPassiveMove = 0; - m_iCurWork = iWorkID; - } - public void StartWork_Stand(uint dwParam) - { - if (!m_bStartFight) - { - if (IsMonsterOrPet()) - PlayModelAction((int)NPCActionIndex.ACT_STAND); - else - PlayModelAction((int)NPCActionIndex.ACT_NPC_STAND); - } - } - - public void StartWork_Fight(uint dwParam) - { - // dwParam được dùng như “thời gian chiến đấu còn lại” - //m_nFightTimeLeft = (int)dwParam; - // Không play animation ở đây vì animation được điều khiển bởi message tấn công - } - - public void StartWork_Spell(uint dwParam) - { - // Trong C++ không có xử lý gì, giữ nguyên - } - - public void StartWork_Dead(uint dwParam) - { - if (IsMonsterOrPet()) - PlayModelAction((int)NPCActionIndex.ACT_DIE); - else - PlayModelAction((int)NPCActionIndex.ACT_NPC_DIE); - } - - public void StartWork_Move(uint dwParam) - { - m_bStartFight = false; - /* - if (m_pNPCModelPolicy != null && m_pNPCModelPolicy.IsModelLoaded()) + if (m_iCurWorkType < 0 || m_iCurWorkType == (int)WorkType.WT_NORMAL || m_iCurWorkType == (int)WorkType.WT_NOTHING) { - ClearComActFlag(true); + if (m_iCurWorkType == (int)WorkType.WT_NOTHING) + StopWork((int)WorkType.WT_NOTHING); - // Khi NPC đang di chuyển thì bỏ trace brush (không cần va chạm) - ReleaseTraceBrush(); - }*/ - } + m_iCurWorkType = (int)WorkType.WT_NORMAL; + } + else + return; + } + else // iWorkType == WT_NOTHING + { + // Release old work + ReleaseWork((int)WorkType.WT_NOTHING); + m_aWorks[(int)WorkType.WT_NOTHING] = iNewWork; - public void StartWork_PolicyAction(uint dwParam) - { - /* if (m_pPolicyAction == null) - m_pPolicyAction = new CECPolicyAction(); + if (m_iCurWorkType < 0 || m_iCurWorkType == (int)WorkType.WT_NOTHING) + m_iCurWorkType = (int)WorkType.WT_NOTHING; + else + return; + } - // Trong C++: m_pPolicyAction->Init((const S2C::cmd_object_start_play_action *)dwParam); - // Sang C#: dwParam không thể cast trực tiếp. Bạn sẽ cần truyền object phù hợp vào. - m_pPolicyAction.Init((S2C.cmd_object_start_play_action)dwParam); - m_pPolicyAction.Tick(0); - m_nPolicyActionIntervalTimer = 0; - - CheckStartPolicyAction();*/ - } - - public bool ShouldPlayNewActionFor(int iMoveMode) - { - if (m_pNPCModelPolicy.IsPlayingAction()) - { - int iAction = GetMoveAction(iMoveMode); - return !m_pNPCModelPolicy.IsPlayingAction(iAction) - && m_pNPCModelPolicy.HasAction(iAction); + StartWorkByID(iNewWork, dwParam); } - return false; - } - public int GetMoveAction(int iMoveMode) - { - if (iMoveMode == (int)GPMoveMode.GP_MOVE_RUN || iMoveMode == (int)GPMoveMode.GP_MOVE_RETURN) + + public void StopWork(int iWorkType) + { + } + public void StartWorkByID(int iWorkID, uint dwParam) + { + // Ignore all message if this NPC is dead. + // if (IsDead()) + // return; + + switch (iWorkID) + { + case (int)WorkID.WORK_STAND: StartWork_Stand(dwParam); break; + case (int)WorkID.WORK_FIGHT: StartWork_Fight(dwParam); break; + case (int)WorkID.WORK_SPELL: StartWork_Spell(dwParam); break; + case (int)WorkID.WORK_DEAD: StartWork_Dead(dwParam); break; + case (int)WorkID.WORK_MOVE: StartWork_Move(dwParam); break; + case (int)WorkID.WORK_POLICYACTION: StartWork_PolicyAction(dwParam); break; + } + + // if (iWorkID != WORK_MOVE) m_iPassiveMove = 0; + m_iCurWork = iWorkID; + } + public void StartWork_Stand(uint dwParam) + { + if (!m_bStartFight) + { + if (IsMonsterOrPet()) + PlayModelAction((int)NPCActionIndex.ACT_STAND); + else + PlayModelAction((int)NPCActionIndex.ACT_NPC_STAND); + } + } + + public void StartWork_Fight(uint dwParam) + { + // dwParam được dùng như “thời gian chiến đấu còn lại” + //m_nFightTimeLeft = (int)dwParam; + // Không play animation ở đây vì animation được điều khiển bởi message tấn công + } + + public void StartWork_Spell(uint dwParam) + { + // Trong C++ không có xử lý gì, giữ nguyên + } + + public void StartWork_Dead(uint dwParam) { if (IsMonsterOrPet()) - return (int)NPCActionIndex.ACT_RUN; + PlayModelAction((int)NPCActionIndex.ACT_DIE); else - return (int)NPCActionIndex.ACT_NPC_RUN; + PlayModelAction((int)NPCActionIndex.ACT_NPC_DIE); } - else - { - if (IsMonsterOrPet()) - return (int)NPCActionIndex.ACT_WALK; - else - return (int)NPCActionIndex.ACT_NPC_WALK; - } - } - bool IsMonsterOrPet() { return IsMonsterNPC() || IsPetNPC(); } - bool IsMonsterNPC() { return (int)Class_ID.OCID_MONSTER == m_iCID; } - bool IsPetNPC() { return (int)Class_ID.OCID_PET == m_iCID; } - public bool IsDead(){ return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; } - public void PlayMoveAction(int iMoveMode) - { - //BrewMonster.BMLogger.LogError($"HoangDev: PlayMoveAction {iMoveMode}"); - // Play run or walk aciton - if (iMoveMode == (int)GPMoveMode.GP_MOVE_RUN || iMoveMode == (int)GPMoveMode.GP_MOVE_RETURN) + public void StartWork_Move(uint dwParam) { - PlayModelAction((int)NPCActionIndex.ACT_WALK, false); - /*if (IsMonsterOrPet()) - PlayModelAction(ACT_RUN, false); + m_bStartFight = false; + /* + if (m_pNPCModelPolicy != null && m_pNPCModelPolicy.IsModelLoaded()) + { + ClearComActFlag(true); + + // Khi NPC đang di chuyển thì bỏ trace brush (không cần va chạm) + ReleaseTraceBrush(); + }*/ + } + + public void StartWork_PolicyAction(uint dwParam) + { + /* if (m_pPolicyAction == null) + m_pPolicyAction = new CECPolicyAction(); + + // Trong C++: m_pPolicyAction->Init((const S2C::cmd_object_start_play_action *)dwParam); + // Sang C#: dwParam không thể cast trực tiếp. Bạn sẽ cần truyền object phù hợp vào. + m_pPolicyAction.Init((S2C.cmd_object_start_play_action)dwParam); + m_pPolicyAction.Tick(0); + m_nPolicyActionIntervalTimer = 0; + + CheckStartPolicyAction();*/ + } + + public bool ShouldPlayNewActionFor(int iMoveMode) + { + if (m_pNPCModelPolicy.IsPlayingAction()) + { + int iAction = GetMoveAction(iMoveMode); + return !m_pNPCModelPolicy.IsPlayingAction(iAction) + && m_pNPCModelPolicy.HasAction(iAction); + } + return false; + } + public int GetMoveAction(int iMoveMode) + { + if (iMoveMode == (int)GPMoveMode.GP_MOVE_RUN || iMoveMode == (int)GPMoveMode.GP_MOVE_RETURN) + { + if (IsMonsterOrPet()) + return (int)NPCActionIndex.ACT_RUN; + else + return (int)NPCActionIndex.ACT_NPC_RUN; + } else - PlayModelAction(ACT_NPC_RUN, false);*/ + { + if (IsMonsterOrPet()) + return (int)NPCActionIndex.ACT_WALK; + else + return (int)NPCActionIndex.ACT_NPC_WALK; + } } - else + bool IsMonsterOrPet() { return IsMonsterNPC() || IsPetNPC(); } + bool IsMonsterNPC() { return (int)Class_ID.OCID_MONSTER == m_iCID; } + bool IsPetNPC() { return (int)Class_ID.OCID_PET == m_iCID; } + + public bool IsDead() { return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; } + public void PlayMoveAction(int iMoveMode) { - PlayModelAction((int)NPCActionIndex.ACT_WALK, false); - /* if (IsMonsterOrPet()) - PlayModelAction(ACT_WALK, false); - else - PlayModelAction(ACT_NPC_WALK, false);*/ + //BrewMonster.BMLogger.LogError($"HoangDev: PlayMoveAction {iMoveMode}"); + // Play run or walk aciton + if (iMoveMode == (int)GPMoveMode.GP_MOVE_RUN || iMoveMode == (int)GPMoveMode.GP_MOVE_RETURN) + { + PlayModelAction((int)NPCActionIndex.ACT_WALK, false); + /*if (IsMonsterOrPet()) + PlayModelAction(ACT_RUN, false); + else + PlayModelAction(ACT_NPC_RUN, false);*/ + } + else + { + PlayModelAction((int)NPCActionIndex.ACT_WALK, false); + /* if (IsMonsterOrPet()) + PlayModelAction(ACT_WALK, false); + else + PlayModelAction(ACT_NPC_WALK, false);*/ + } } - } - public void PlayModelAction(int iAction, bool bRestart = false) - { - m_iAction = iAction; - /* if (IsDead()) - { - // ¼ì²éËÀÍö״̬£¬ÒÔÆÁ±ÎÆäËü¶¯×÷ - // ËÀÍö״̬ÉèÖúó£¬Ö»ÔÊÐí²¥·ÅËÀÍö¶¯×÷ - // Íæ¼Ò¹¥»÷NPCʱ£¬»áÊ×ÏȲ¥·ÅÍæ¼ÒµÄ¹¥»÷¶¯×÷£¬Íê³Éºó²¥·Å¹ÖÎïµÄÊÜÉ˶¯×÷ - // µ«ÔÚÍæ¼Ò×ÔÉíµÄ¹¥»÷¶¯×÷δÍê³Éʱ£¬¿ÉÄܾÍÊÕµ½NPCËÀÍöµÄÏûÏ¢ - // Òò´Ë£¬¿ÉÄÜ»áÏȲ¥·ÅËÀÍö¶¯×÷£¬¶øºóÓÖ²¥·ÅÊÜÉ˶¯×÷£¬µ¼ÖÂËÀÍö¶¯×÷²»ÄÜÕý³£²¥·ÅµÄ±íÏÖ½á¹û - // ²»·ûºÏÆÚÍû - if (IsMonsterOrPet()) + public void PlayModelAction(int iAction, bool bRestart = false) + { + m_iAction = iAction; + /* if (IsDead()) { - if (iAction != CECNPC::ACT_DIE) + // ¼ì²éËÀÍö״̬£¬ÒÔÆÁ±ÎÆäËü¶¯×÷ + // ËÀÍö״̬ÉèÖúó£¬Ö»ÔÊÐí²¥·ÅËÀÍö¶¯×÷ + // Íæ¼Ò¹¥»÷NPCʱ£¬»áÊ×ÏȲ¥·ÅÍæ¼ÒµÄ¹¥»÷¶¯×÷£¬Íê³Éºó²¥·Å¹ÖÎïµÄÊÜÉ˶¯×÷ + // µ«ÔÚÍæ¼Ò×ÔÉíµÄ¹¥»÷¶¯×÷δÍê³Éʱ£¬¿ÉÄܾÍÊÕµ½NPCËÀÍöµÄÏûÏ¢ + // Òò´Ë£¬¿ÉÄÜ»áÏȲ¥·ÅËÀÍö¶¯×÷£¬¶øºóÓÖ²¥·ÅÊÜÉ˶¯×÷£¬µ¼ÖÂËÀÍö¶¯×÷²»ÄÜÕý³£²¥·ÅµÄ±íÏÖ½á¹û + // ²»·ûºÏÆÚÍû + if (IsMonsterOrPet()) { - return; + if (iAction != CECNPC::ACT_DIE) + { + return; + } } - } - else - { - if (iAction != CECNPC::ACT_NPC_DIE) + else { - return; + if (iAction != CECNPC::ACT_NPC_DIE) + { + return; + } } - } - }*/ - m_pNPCModelPolicy.PlayModelAction(iAction, bRestart); + }*/ + m_pNPCModelPolicy.PlayModelAction(iAction, bRestart); + } + bool IsDisappearing() { return m_DisappearCnt == 0 ? true : false; } + + public float GetTouchRadius() { return m_fTouchRad; } + + bool IsLag(float fDist) + { + return m_iPassiveMove == 0 && fDist > MAX_LAGDIST; + } + public INFO GetNPCInfo() { return m_NPCInfo; } + + public struct INFO + { + public int nid; // NPC id + public int tid; // Template id + public int vis_tid;// template id for shape + }; + public const float MAX_LAGDIST = 25.0f; + + // Get NPC's real position on server + public A3DVECTOR3 GetServerPos() + { + return EC_Utility.ToA3DVECTOR3(m_vServerPos); + } + + // Get master id + public int GetMasterID() { return m_idMaster; } + // Is monster in invader camp in battle ? + public virtual bool IsInBattleInvaderCamp() { return false; } + // Is monster in defender camp in battle ? + public virtual bool IsInBattleDefenderCamp() { return false; } + // Get role in battle + public virtual int GetRoleInBattle() { return 0; } + public int GetOwnerFaction() { return m_idOwnerFaction; } + + public bool IsFactionPVPMineCar() + { + //if (const MONSTER_ESSENCE* pMonsterEssence = GetMonsterEssence()){ + // return (pMonsterEssence.faction & (1 << 19)) != 0; + //} + return false; + } + + public bool IsFactionPVPMineBase() + { + //if (const MONSTER_ESSENCE *pMonsterEssence = GetMonsterEssence()){ + // return (pMonsterEssence->faction & (1 << 20)) != 0; + //} + return false; + } + + // 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; } } - bool IsDisappearing() { return m_DisappearCnt == 0 ? true : false; } - - public float GetTouchRadius() { return m_fTouchRad; } - - bool IsLag(float fDist) + public enum WorkType { - return m_iPassiveMove == 0 && fDist > MAX_LAGDIST; - } - public INFO GetNPCInfo() { return m_NPCInfo; } - - public struct INFO - { - public int nid; // NPC id - public int tid; // Template id - public int vis_tid;// template id for shape + WT_NOTHING = 0, // Do thing + WT_NORMAL, // Normal type work + WT_INTERRUPT, // Interrupt type work + NUM_WORKTYPE, }; - public const float MAX_LAGDIST = 25.0f; + // Work ID + public enum WorkID - // Get NPC's real position on server - public A3DVECTOR3 GetServerPos() - { - return EC_Utility.ToA3DVECTOR3(m_vServerPos); - } - - // Get master id - public int GetMasterID() { return m_idMaster; } - // Is monster in invader camp in battle ? - public virtual bool IsInBattleInvaderCamp() { return false; } - // Is monster in defender camp in battle ? - public virtual bool IsInBattleDefenderCamp() { return false; } - // Get role in battle - public virtual int GetRoleInBattle() { return 0; } - public int GetOwnerFaction(){ return m_idOwnerFaction; } - - public bool IsFactionPVPMineCar() - { - //if (const MONSTER_ESSENCE* pMonsterEssence = GetMonsterEssence()){ - // return (pMonsterEssence.faction & (1 << 19)) != 0; - //} - return false; - } - - public bool IsFactionPVPMineBase() - { - //if (const MONSTER_ESSENCE *pMonsterEssence = GetMonsterEssence()){ - // return (pMonsterEssence->faction & (1 << 20)) != 0; - //} - return false; - } - - // 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 -{ - WT_NOTHING = 0, // Do thing - WT_NORMAL, // Normal type work - WT_INTERRUPT, // Interrupt type work - NUM_WORKTYPE, -}; -// Work ID -public enum WorkID - -{ - WORK_STAND = 1, // Stand and do nothing - WORK_FIGHT, // Fighting - WORK_SPELL, // Monster is cast skill - WORK_DEAD, // Monster is dead - WORK_MOVE, // Move to a destination terrain position - WORK_POLICYACTION, // Is playing policy action£¬WT_INTERRUPT -}; -public enum NPCActionIndex - -{ - ACT_STAND = 0, - ACT_IDLE, - ACT_GUARD, - ACT_SKILL1, - ACT_WALK, - ACT_ATTACK1, - ACT_ATTACK2, - ACT_RUN, - ACT_DIE, - ACT_JUMP_START, - ACT_JUMP_LAND, - ACT_JUMP_LOOP, - ACT_MAGIC1, - ACT_WOUNDED, - ACT_NPC_CHAT1, - ACT_NPC_CHAT2, - ACT_NPC_CHATLOOP, - ACT_NPC_IDLE1, - ACT_NPC_IDLE2, - ACT_NPC_STAND, - ACT_NPC_WALK, - ACT_NPC_RUN, - ACT_NPC_ATTACK, - ACT_NPC_DIE, - ACT_COMMON_BORN, - ACT_NPC_DISAPPEAR, - ACT_WOUNDED2, - ACT_MAX, -}; -public ref struct ByteReader -{ - private ReadOnlySpan _span; - private int _offset; - public ByteReader(ReadOnlySpan span) { _span = span; _offset = 0; } - public bool Eof => _offset >= _span.Length; - public byte ReadByte() => _span[_offset++]; - public int ReadInt32() { - int v = BitConverter.ToInt32(_span.Slice(_offset, 4)); - _offset += 4; return v; - } - public void ReadInto(uint[] dst) + WORK_STAND = 1, // Stand and do nothing + WORK_FIGHT, // Fighting + WORK_SPELL, // Monster is cast skill + WORK_DEAD, // Monster is dead + WORK_MOVE, // Move to a destination terrain position + WORK_POLICYACTION, // Is playing policy action£¬WT_INTERRUPT + }; + public enum NPCActionIndex + { - // OBJECT_EXT_STATE_COUNT * sizeof(DWORD) - int bytes = dst.Length * 4; - var s = _span.Slice(_offset, bytes); - for (int i = 0; i < dst.Length; i++) - dst[i] = BitConverter.ToUInt32(s.Slice(i * 4, 4)); - _offset += bytes; - } - public byte[] ReadBytes(int len) + ACT_STAND = 0, + ACT_IDLE, + ACT_GUARD, + ACT_SKILL1, + ACT_WALK, + ACT_ATTACK1, + ACT_ATTACK2, + ACT_RUN, + ACT_DIE, + ACT_JUMP_START, + ACT_JUMP_LAND, + ACT_JUMP_LOOP, + ACT_MAGIC1, + ACT_WOUNDED, + ACT_NPC_CHAT1, + ACT_NPC_CHAT2, + ACT_NPC_CHATLOOP, + ACT_NPC_IDLE1, + ACT_NPC_IDLE2, + ACT_NPC_STAND, + ACT_NPC_WALK, + ACT_NPC_RUN, + ACT_NPC_ATTACK, + ACT_NPC_DIE, + ACT_COMMON_BORN, + ACT_NPC_DISAPPEAR, + ACT_WOUNDED2, + ACT_MAX, + }; + public ref struct ByteReader { - var s = _span.Slice(_offset, len).ToArray(); - _offset += len; return s; + private ReadOnlySpan _span; + private int _offset; + public ByteReader(ReadOnlySpan span) { _span = span; _offset = 0; } + public bool Eof => _offset >= _span.Length; + public byte ReadByte() => _span[_offset++]; + public int ReadInt32() + { + int v = BitConverter.ToInt32(_span.Slice(_offset, 4)); + _offset += 4; return v; + } + public void ReadInto(uint[] dst) + { + // OBJECT_EXT_STATE_COUNT * sizeof(DWORD) + int bytes = dst.Length * 4; + var s = _span.Slice(_offset, bytes); + for (int i = 0; i < dst.Length; i++) + dst[i] = BitConverter.ToUInt32(s.Slice(i * 4, 4)); + _offset += bytes; + } + public byte[] ReadBytes(int len) + { + var s = _span.Slice(_offset, len).ToArray(); + _offset += len; return s; + } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/NPC/CECNPCModelDefaultPolicy.cs b/Assets/PerfectWorld/Scripts/NPC/CECNPCModelDefaultPolicy.cs index 81e8d828fb..068dcc3928 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECNPCModelDefaultPolicy.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECNPCModelDefaultPolicy.cs @@ -1,120 +1,124 @@ -using CSNetwork.Protocols; +using BrewMonster.Scripts.Player; +using CSNetwork.Protocols; using UnityEngine; -public class CECNPCModelDefaultPolicy - : CECNPCModelPolicy +namespace BrewMonster.Scripts { - CECModel m_pNPCModel; - - public CECNPCModelDefaultPolicy(CECNPC pNPC) + public class CECNPCModelDefaultPolicy + : CECNPCModelPolicy { + CECModel m_pNPCModel; - } - - public string GetActionName(int iAct, bool bAttackStart = false) - { - // Tạo builder thay cho static char[128] - var sb = new System.Text.StringBuilder(); - - // Thêm tên base action - sb.Append(CECNPC.GetBaseActionName(iAct)); - - // Nếu là attack action thì thêm hậu tố - if (CECNPC.IsAttackAction(iAct)) + public CECNPCModelDefaultPolicy(CECNPC pNPC) { - sb.Append(bAttackStart ? "Æð" : "Âä"); + } - // Xử lý loại bỏ dấu nháy kép (nếu có) - string result = sb.ToString().Replace("\"", ""); - - // Trả về kết quả đã clean - return result; - } - - public override bool PlayModelAction(int iAction, bool bRestart) - { - - /* if (m_pNPCModel == null) + public string GetActionName(int iAct, bool bAttackStart = false) { - return false; - } -*/ - bool result = false; + // Tạo builder thay cho static char[128] + var sb = new System.Text.StringBuilder(); - if (iAction == (int)NPCActionIndex.ACT_WOUNDED) - { - string szAct = GetActionName(iAction); - if (!_npcVisual.IsAnimationExist(szAct)) + // Thêm tên base action + sb.Append(CECNPC.GetBaseActionName(iAct)); + + // Nếu là attack action thì thêm hậu tố + if (CECNPC.IsAttackAction(iAct)) { - szAct = GetActionName((int)NPCActionIndex.ACT_WOUNDED2); + sb.Append(bAttackStart ? "Æð" : "Âä"); } - result = _npcVisual.TryPlayAction(szAct); + + // Xử lý loại bỏ dấu nháy kép (nếu có) + string result = sb.ToString().Replace("\"", ""); + + // Trả về kết quả đã clean + return result; } - else if (iAction == (int)NPCActionIndex.ACT_ATTACK1 || iAction == (int)NPCActionIndex.ACT_ATTACK2) + + public override bool PlayModelAction(int iAction, bool bRestart) { - //bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID()); - result = _npcVisual.TryPlayAction(GetActionName(iAction, true)); - if (result) + + /* if (m_pNPCModel == null) + { + return false; + } + */ + bool result = false; + + if (iAction == (int)NPCActionIndex.ACT_WOUNDED) { - /* m_pNPCModel->QueueAction(GetActionName(iAction, false), 0, 0, false, false, bHideFX); - m_pNPCModel->QueueAction(GetActionName(CECNPC::ACT_GUARD), 300);*/ + string szAct = GetActionName(iAction); + if (!_npcVisual.IsAnimationExist(szAct)) + { + szAct = GetActionName((int)NPCActionIndex.ACT_WOUNDED2); + } + result = _npcVisual.TryPlayAction(szAct); } - } - else if (iAction == (int)NPCActionIndex.ACT_IDLE) - { - result = _npcVisual.TryPlayAction(GetActionName(iAction)); - if (result) + else if (iAction == (int)NPCActionIndex.ACT_ATTACK1 || iAction == (int)NPCActionIndex.ACT_ATTACK2) { - //m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_STAND)); + //bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID()); + result = _npcVisual.TryPlayAction(GetActionName(iAction, true)); + if (result) + { + /* m_pNPCModel->QueueAction(GetActionName(iAction, false), 0, 0, false, false, bHideFX); + m_pNPCModel->QueueAction(GetActionName(CECNPC::ACT_GUARD), 300);*/ + } } - } - else if (iAction == (int)NPCActionIndex.ACT_NPC_IDLE1 || iAction == (int)NPCActionIndex.ACT_NPC_IDLE2) - { - result = _npcVisual.TryPlayAction(GetActionName(iAction)); - if (result) + else if (iAction == (int)NPCActionIndex.ACT_IDLE) { - //m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_NPC_STAND)); + result = _npcVisual.TryPlayAction(GetActionName(iAction)); + if (result) + { + //m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_STAND)); + } } - } - else if (iAction == (int)NPCActionIndex.ACT_NPC_ATTACK) - { - //bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID()); - result = _npcVisual.TryPlayAction(GetActionName(iAction)); ; - if (result) + else if (iAction == (int)NPCActionIndex.ACT_NPC_IDLE1 || iAction == (int)NPCActionIndex.ACT_NPC_IDLE2) { - /*m_pNPCModel->QueueAction(GetActionName(iAction, false), 0, 0, false, false, bHideFX); - m_pNPCModel->QueueAction(GetActionName(CECNPC::ACT_NPC_STAND), 300);*/ + result = _npcVisual.TryPlayAction(GetActionName(iAction)); + if (result) + { + //m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_NPC_STAND)); + } } - } - else if (iAction == (int)NPCActionIndex.ACT_COMMON_BORN) - { - result = _npcVisual.TryPlayAction(GetActionName(iAction)); - if (result) + else if (iAction == (int)NPCActionIndex.ACT_NPC_ATTACK) { - //m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_STAND)); + //bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID()); + result = _npcVisual.TryPlayAction(GetActionName(iAction)); ; + if (result) + { + /*m_pNPCModel->QueueAction(GetActionName(iAction, false), 0, 0, false, false, bHideFX); + m_pNPCModel->QueueAction(GetActionName(CECNPC::ACT_NPC_STAND), 300);*/ + } } + else if (iAction == (int)NPCActionIndex.ACT_COMMON_BORN) + { + result = _npcVisual.TryPlayAction(GetActionName(iAction)); + if (result) + { + //m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_STAND)); + } + } + else + { + result = _npcVisual.TryPlayAction(GetActionName(iAction)); + } + return result; } - else + public override bool IsPlayingAction() { - result = _npcVisual.TryPlayAction(GetActionName(iAction)); + return _npcVisual.IsPlayAnimation(); + } + public override bool IsPlayingAction(int iAction) + { + return _npcVisual.IsPlayAnimation(GetActionName(iAction)); + } + public override bool HasAction(int iAction) + { + return _npcVisual.IsAnimationExist(GetActionName(iAction)); + } + public override void SetNpcVisual(NPCVisual npcVisual) + { + _npcVisual = npcVisual; } - return result; - } - public override bool IsPlayingAction() - { - return _npcVisual.IsPlayAnimation(); - } - public override bool IsPlayingAction(int iAction) - { - return _npcVisual.IsPlayAnimation(GetActionName(iAction)); - } - public override bool HasAction(int iAction) - { - return _npcVisual.IsAnimationExist(GetActionName(iAction)); - } - public override void SetNpcVisual(NPCVisual npcVisual) - { - _npcVisual = npcVisual; } } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index e406bbd7f3..4bc7474d8a 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -15,6 +15,8 @@ using System.Numerics; using CSNetwork.C2SCommand; using CSNetwork.GPDataType; using BrewMonster; +using BrewMonster.Managers; +using BrewMonster.Scripts.Player; namespace CSNetwork { diff --git a/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs b/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs index 57599c37b2..d5d8955545 100644 --- a/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs +++ b/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs @@ -1,12 +1,10 @@ using System; using UnityEngine; using CSNetwork; -using PerfectWorld.Scripts.Managers.BrewMonster.Managers; -using BrewMonster.Network; -using UnityEngine.SceneManagement; using CSNetwork.GPDataType; +using BrewMonster.Scripts.Player; -namespace BrewMonster +namespace BrewMonster.Managers { [Serializable] public class EC_ManMessageMono : MonoBehaviour diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs index 07f37b5c83..c0e283d323 100644 --- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs @@ -1,4 +1,6 @@ using BrewMonster; +using BrewMonster.Scripts; +using BrewMonster.Scripts.Player; using CSNetwork; using CSNetwork.Protocols; using CSNetwork.Protocols.RPCData; diff --git a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs index bc96829d14..233ba523b9 100644 --- a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs +++ b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs @@ -1,11 +1,10 @@ -using BrewMonster; -using CSNetwork; +using BrewMonster.Managers; using CSNetwork.GPDataType; using CSNetwork.Protocols.RPCData; using System; using UnityEngine; -namespace PerfectWorld.Scripts.Player +namespace BrewMonster.Scripts.Player { public class EC_ElsePlayer : EC_Player { diff --git a/Assets/PerfectWorld/Scripts/UI/pickupItem.cs b/Assets/PerfectWorld/Scripts/UI/pickupItem.cs index 6127acf62c..e0863bef19 100644 --- a/Assets/PerfectWorld/Scripts/UI/pickupItem.cs +++ b/Assets/PerfectWorld/Scripts/UI/pickupItem.cs @@ -1,442 +1,443 @@ using UnityEngine; using UnityEngine.UI; using BrewMonster.Network; -using PerfectWorld.Scripts.Managers.BrewMonster.Managers; -using PerfectWorld.Scripts.Managers; -using CSNetwork.GPDataType; +using BrewMonster.Scripts.Managers; using System.Collections.Generic; -using BrewMonster; using TMPro; +using BrewMonster.Managers; -public class pickupItem : MonoBehaviour +namespace BrewMonster.Scripts { - public InputField mid; - public InputField tid; - public Button send; - - // Dictionary to store created cubes with their matter IDs - private Dictionary matterCubes = new Dictionary(); - - // Dictionary to track pending pickups by TID - private Dictionary pendingPickups = new Dictionary(); // TID -> MatterID - - // Set to track items that have been picked up by the player (to prevent respawn) - private HashSet pickedUpItems = new HashSet(); // MID of picked up items - - // Reference to the matter manager - private EC_ManMatter matterManager; + public class pickupItem : MonoBehaviour + { + public InputField mid; + public InputField tid; + public Button send; - // Start is called once before the first execution of Update after the MonoBehaviour is created - void Start() - { - // Add button click listener - if (send != null) - { - send.onClick.AddListener(OnPickupButtonClicked); - } - - // Get reference to matter manager - if (EC_ManMessageMono.Instance != null) - { - matterManager = EC_ManMessageMono.Instance.GetECManMatter; - } - else - { - Debug.LogError("EC_ManMessageMono.Instance is null - matter manager not available"); - } - - // Subscribe to matter enter world events - SubscribeToMatterEvents(); - } + // Dictionary to store created cubes with their matter IDs + private Dictionary matterCubes = new Dictionary(); - // Update is called once per frame - void Update() - { - // Check for mouse clicks on cubes - if (Input.GetMouseButtonDown(0)) + // Dictionary to track pending pickups by TID + private Dictionary pendingPickups = new Dictionary(); // TID -> MatterID + + // Set to track items that have been picked up by the player (to prevent respawn) + private HashSet pickedUpItems = new HashSet(); // MID of picked up items + + // Reference to the matter manager + private EC_ManMatter matterManager; + + // Start is called once before the first execution of Update after the MonoBehaviour is created + void Start() { - HandleCubeClick(); - } - } - - private void SubscribeToMatterEvents() - { - // We'll need to hook into the matter manager's events - // For now, we'll check for new matters in Update - } - - private void HandleCubeClick() - { - // Find the main camera - Camera mainCamera = Camera.main; - if (mainCamera == null) - { - mainCamera = FindFirstObjectByType(); - } - - if (mainCamera == null) - { - Debug.LogWarning("No camera found for raycast"); - return; - } - - Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition); - RaycastHit hit; - - if (Physics.Raycast(ray, out hit)) - { - GameObject clickedObject = hit.collider.gameObject; - - // Check if the clicked object is one of our matter cubes - foreach (var kvp in matterCubes) + // Add button click listener + if (send != null) { - if (kvp.Value == clickedObject) - { - int matterId = kvp.Key; - SendPickupCommand(matterId); - break; - } + send.onClick.AddListener(OnPickupButtonClicked); } - } - } - - public void SendPickupCommand(int matterId) - { - if (matterManager != null) - { - var matterData = matterManager.GetMatterData(matterId); - if (matterData.HasValue) + + // Get reference to matter manager + if (EC_ManMessageMono.Instance != null) { - // Track this pickup request - pendingPickups[matterData.Value.tid] = matterId; - - UnityGameSession.RequestPickupItem(matterData.Value.mid, matterData.Value.tid); - Debug.Log($"Pickup request sent for matter - MID: {matterData.Value.mid}, TID: {matterData.Value.tid}"); + matterManager = EC_ManMessageMono.Instance.GetECManMatter; } else { - Debug.LogWarning($"No matter data found for matter ID: {matterId}"); + Debug.LogError("EC_ManMessageMono.Instance is null - matter manager not available"); + } + + // Subscribe to matter enter world events + SubscribeToMatterEvents(); + } + + // Update is called once per frame + void Update() + { + // Check for mouse clicks on cubes + if (Input.GetMouseButtonDown(0)) + { + HandleCubeClick(); } } - else + + private void SubscribeToMatterEvents() { - Debug.LogError("Matter manager is null - cannot send pickup command"); + // We'll need to hook into the matter manager's events + // For now, we'll check for new matters in Update } - } - - public void CreateMatterCube(int matterId) - { - if (matterManager == null) return; - - var matterData = matterManager.GetMatterData(matterId); - if (!matterData.HasValue) return; - - // Check if this item was previously picked up by the player - if (pickedUpItems.Contains(matterId)) + + private void HandleCubeClick() { - Debug.Log($"Skipping cube creation for matter {matterId} - item was previously picked up by player"); - return; + // Find the main camera + Camera mainCamera = Camera.main; + if (mainCamera == null) + { + mainCamera = FindFirstObjectByType(); + } + + if (mainCamera == null) + { + Debug.LogWarning("No camera found for raycast"); + return; + } + + Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition); + RaycastHit hit; + + if (Physics.Raycast(ray, out hit)) + { + GameObject clickedObject = hit.collider.gameObject; + + // Check if the clicked object is one of our matter cubes + foreach (var kvp in matterCubes) + { + if (kvp.Value == clickedObject) + { + int matterId = kvp.Key; + SendPickupCommand(matterId); + break; + } + } + } } - - // Check if cube already exists - if (matterCubes.ContainsKey(matterId)) + + public void SendPickupCommand(int matterId) { - Debug.Log($"Cube for matter {matterId} already exists"); - return; + if (matterManager != null) + { + var matterData = matterManager.GetMatterData(matterId); + if (matterData.HasValue) + { + // Track this pickup request + pendingPickups[matterData.Value.tid] = matterId; + + UnityGameSession.RequestPickupItem(matterData.Value.mid, matterData.Value.tid); + Debug.Log($"Pickup request sent for matter - MID: {matterData.Value.mid}, TID: {matterData.Value.tid}"); + } + else + { + Debug.LogWarning($"No matter data found for matter ID: {matterId}"); + } + } + else + { + Debug.LogError("Matter manager is null - cannot send pickup command"); + } } - - // Create cube GameObject - GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); - cube.name = $"Matter_{matterData.Value.mid}_TID_{matterData.Value.tid}"; - cube.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f); - // Position the cube based on matter position - Vector3 position = new Vector3( - matterData.Value.pos.x, - matterData.Value.pos.y, - matterData.Value.pos.z - ); - cube.transform.position = position; - - // Add a collider if it doesn't have one - if (cube.GetComponent() == null) + + public void CreateMatterCube(int matterId) { - cube.AddComponent(); + if (matterManager == null) return; + + var matterData = matterManager.GetMatterData(matterId); + if (!matterData.HasValue) return; + + // Check if this item was previously picked up by the player + if (pickedUpItems.Contains(matterId)) + { + Debug.Log($"Skipping cube creation for matter {matterId} - item was previously picked up by player"); + return; + } + + // Check if cube already exists + if (matterCubes.ContainsKey(matterId)) + { + Debug.Log($"Cube for matter {matterId} already exists"); + return; + } + + // Create cube GameObject + GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); + cube.name = $"Matter_{matterData.Value.mid}_TID_{matterData.Value.tid}"; + cube.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f); + // Position the cube based on matter position + Vector3 position = new Vector3( + matterData.Value.pos.x, + matterData.Value.pos.y, + matterData.Value.pos.z + ); + cube.transform.position = position; + + // Add a collider if it doesn't have one + if (cube.GetComponent() == null) + { + cube.AddComponent(); + } + + // Create text object to display item name above the cube + CreateItemNameText(cube, matterData.Value.tid); + + // Add a script to handle click events + MatterCubeClickHandler clickHandler = cube.AddComponent(); + clickHandler.Initialize(matterId, this); + + // Store reference to the cube + matterCubes[matterId] = cube; + + Debug.Log($"Created cube for matter {matterId} at position {position}"); } - - // Create text object to display item name above the cube - CreateItemNameText(cube, matterData.Value.tid); - - // Add a script to handle click events - MatterCubeClickHandler clickHandler = cube.AddComponent(); - clickHandler.Initialize(matterId, this); - - // Store reference to the cube - matterCubes[matterId] = cube; - - Debug.Log($"Created cube for matter {matterId} at position {position}"); - } - - private void CreateItemNameText(GameObject cube, int tid) - { - // Create a child GameObject for the text - GameObject textObject = new GameObject("ItemNameText"); - textObject.transform.SetParent(cube.transform); - - // Position the text above the cube - textObject.transform.localPosition = new Vector3(0, 1.2f, 0); // Above the cube - - // Add TextMeshPro component - TextMeshPro textMesh = textObject.AddComponent(); - - // Get the item name - string itemName = EC_IvtrItem.ResolveItemName(tid); - if (string.IsNullOrEmpty(itemName)) - { - itemName = $"Item {tid}"; - } - - // Configure the text - textMesh.text = itemName; - textMesh.fontSize = 10f; - textMesh.color = Color.white; - textMesh.alignment = TextAlignmentOptions.Center; - - // Make the text face the camera - textObject.AddComponent(); - - // Add a background for better visibility - GameObject background = new GameObject("TextBackground"); - background.transform.SetParent(textObject.transform); - background.transform.localPosition = Vector3.zero; - background.transform.localScale = new Vector3(2f, 0.8f, 0.1f); - - // Add a simple quad renderer for background - MeshRenderer bgRenderer = background.AddComponent(); - MeshFilter bgFilter = background.AddComponent(); - - // Create a simple quad mesh for the background - Mesh quadMesh = new Mesh(); - quadMesh.vertices = new Vector3[] + + private void CreateItemNameText(GameObject cube, int tid) { + // Create a child GameObject for the text + GameObject textObject = new GameObject("ItemNameText"); + textObject.transform.SetParent(cube.transform); + + // Position the text above the cube + textObject.transform.localPosition = new Vector3(0, 1.2f, 0); // Above the cube + + // Add TextMeshPro component + TextMeshPro textMesh = textObject.AddComponent(); + + // Get the item name + string itemName = EC_IvtrItem.ResolveItemName(tid); + if (string.IsNullOrEmpty(itemName)) + { + itemName = $"Item {tid}"; + } + + // Configure the text + textMesh.text = itemName; + textMesh.fontSize = 10f; + textMesh.color = Color.white; + textMesh.alignment = TextAlignmentOptions.Center; + + // Make the text face the camera + textObject.AddComponent(); + + // Add a background for better visibility + GameObject background = new GameObject("TextBackground"); + background.transform.SetParent(textObject.transform); + background.transform.localPosition = Vector3.zero; + background.transform.localScale = new Vector3(2f, 0.8f, 0.1f); + + // Add a simple quad renderer for background + MeshRenderer bgRenderer = background.AddComponent(); + MeshFilter bgFilter = background.AddComponent(); + + // Create a simple quad mesh for the background + Mesh quadMesh = new Mesh(); + quadMesh.vertices = new Vector3[] + { new Vector3(-0.5f, -0.5f, 0), new Vector3(0.5f, -0.5f, 0), new Vector3(0.5f, 0.5f, 0), new Vector3(-0.5f, 0.5f, 0) - }; - quadMesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 }; - quadMesh.uv = new Vector2[] - { + }; + quadMesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 }; + quadMesh.uv = new Vector2[] + { new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1) - }; - quadMesh.RecalculateNormals(); - - bgFilter.mesh = quadMesh; - - // Create a simple material for the background - Material bgMaterial = new Material(Shader.Find("Standard")); - bgMaterial.color = new Color(0, 0, 0, 0.7f); // Semi-transparent black - bgRenderer.material = bgMaterial; - - Debug.Log($"Created item name text for TID {tid}: {itemName}"); - } - - public void RemoveMatterCube(int matterId) - { - if (matterCubes.ContainsKey(matterId)) - { - GameObject cube = matterCubes[matterId]; - if (cube != null) - { - Destroy(cube); - } - matterCubes.Remove(matterId); - Debug.Log($"Removed cube for matter {matterId}"); - } - } - - public void UpdateMatterCubes() - { - if (matterManager == null) return; - - // Get all current matter IDs - int[] allMatterIds = matterManager.GetAllMatterIds(); - - // Create cubes for new matters (but skip items previously picked up by player) - foreach (int matterId in allMatterIds) - { - if (!matterCubes.ContainsKey(matterId) && !pickedUpItems.Contains(matterId)) - { - CreateMatterCube(matterId); - } - } - - // Remove cubes for matters that no longer exist - List cubesToRemove = new List(); - foreach (var kvp in matterCubes) - { - if (!matterManager.HasMatterData(kvp.Key)) - { - cubesToRemove.Add(kvp.Key); - } - } - - foreach (int matterId in cubesToRemove) - { - RemoveMatterCube(matterId); - } - } - - /// - /// Called when a pickup is successful. Removes the cube for the picked up item. - /// - /// Template ID of the picked up item - public void OnPickupSuccess(int tid) - { - if (pendingPickups.ContainsKey(tid)) - { - int matterId = pendingPickups[tid]; - - // Track this item as picked up by the player - pickedUpItems.Add(matterId); - - // Remove the cube - RemoveMatterCube(matterId); - - // Remove from pending pickups - pendingPickups.Remove(tid); - - Debug.Log($"Successfully picked up item with TID: {tid}, removed cube for matter ID: {matterId}"); - } - else - { - Debug.LogWarning($"Received pickup success for TID {tid} but no pending pickup found"); - } - } - - /// - /// Called when a pickup fails. Removes the pending pickup tracking. - /// - /// Template ID of the failed pickup - public void OnPickupFailed(int tid) - { - if (pendingPickups.ContainsKey(tid)) - { - pendingPickups.Remove(tid); - Debug.Log($"Pickup failed for TID: {tid}, removed from pending pickups"); - } - } - - /// - /// Clears the tracking of picked up items. Call this when player changes areas or logs out. - /// - public void ClearPickedUpItemsTracking() - { - pickedUpItems.Clear(); - Debug.Log("Cleared picked up items tracking"); - } - - /// - /// Gets the count of items that have been picked up by the player. - /// - /// Number of items picked up - public int GetPickedUpItemsCount() - { - return pickedUpItems.Count; - } + }; + quadMesh.RecalculateNormals(); - private void OnPickupButtonClicked() - { - // Validate input fields - if (mid == null || tid == null) - { - Debug.LogError("PickupItem: Mid or Tid InputField is not assigned!"); - return; + bgFilter.mesh = quadMesh; + + // Create a simple material for the background + Material bgMaterial = new Material(Shader.Find("Standard")); + bgMaterial.color = new Color(0, 0, 0, 0.7f); // Semi-transparent black + bgRenderer.material = bgMaterial; + + Debug.Log($"Created item name text for TID {tid}: {itemName}"); } - // Parse the input values - if (int.TryParse(mid.text, out int midValue) && int.TryParse(tid.text, out int tidValue)) + public void RemoveMatterCube(int matterId) { - // Call the pickup item request - UnityGameSession.RequestPickupItem(midValue, tidValue); - Debug.Log($"Pickup request sent - MID: {midValue}, TID: {tidValue}"); + if (matterCubes.ContainsKey(matterId)) + { + GameObject cube = matterCubes[matterId]; + if (cube != null) + { + Destroy(cube); + } + matterCubes.Remove(matterId); + Debug.Log($"Removed cube for matter {matterId}"); + } } - else + + public void UpdateMatterCubes() { - Debug.LogError("PickupItem: Invalid input values. Please enter valid integers for MID and TID."); + if (matterManager == null) return; + + // Get all current matter IDs + int[] allMatterIds = matterManager.GetAllMatterIds(); + + // Create cubes for new matters (but skip items previously picked up by player) + foreach (int matterId in allMatterIds) + { + if (!matterCubes.ContainsKey(matterId) && !pickedUpItems.Contains(matterId)) + { + CreateMatterCube(matterId); + } + } + + // Remove cubes for matters that no longer exist + List cubesToRemove = new List(); + foreach (var kvp in matterCubes) + { + if (!matterManager.HasMatterData(kvp.Key)) + { + cubesToRemove.Add(kvp.Key); + } + } + + foreach (int matterId in cubesToRemove) + { + RemoveMatterCube(matterId); + } + } + + /// + /// Called when a pickup is successful. Removes the cube for the picked up item. + /// + /// Template ID of the picked up item + public void OnPickupSuccess(int tid) + { + if (pendingPickups.ContainsKey(tid)) + { + int matterId = pendingPickups[tid]; + + // Track this item as picked up by the player + pickedUpItems.Add(matterId); + + // Remove the cube + RemoveMatterCube(matterId); + + // Remove from pending pickups + pendingPickups.Remove(tid); + + Debug.Log($"Successfully picked up item with TID: {tid}, removed cube for matter ID: {matterId}"); + } + else + { + Debug.LogWarning($"Received pickup success for TID {tid} but no pending pickup found"); + } + } + + /// + /// Called when a pickup fails. Removes the pending pickup tracking. + /// + /// Template ID of the failed pickup + public void OnPickupFailed(int tid) + { + if (pendingPickups.ContainsKey(tid)) + { + pendingPickups.Remove(tid); + Debug.Log($"Pickup failed for TID: {tid}, removed from pending pickups"); + } + } + + /// + /// Clears the tracking of picked up items. Call this when player changes areas or logs out. + /// + public void ClearPickedUpItemsTracking() + { + pickedUpItems.Clear(); + Debug.Log("Cleared picked up items tracking"); + } + + /// + /// Gets the count of items that have been picked up by the player. + /// + /// Number of items picked up + public int GetPickedUpItemsCount() + { + return pickedUpItems.Count; + } + + private void OnPickupButtonClicked() + { + // Validate input fields + if (mid == null || tid == null) + { + Debug.LogError("PickupItem: Mid or Tid InputField is not assigned!"); + return; + } + + // Parse the input values + if (int.TryParse(mid.text, out int midValue) && int.TryParse(tid.text, out int tidValue)) + { + // Call the pickup item request + UnityGameSession.RequestPickupItem(midValue, tidValue); + Debug.Log($"Pickup request sent - MID: {midValue}, TID: {tidValue}"); + } + else + { + Debug.LogError("PickupItem: Invalid input values. Please enter valid integers for MID and TID."); + } + } + + private void OnDestroy() + { + // Clean up button listener + if (send != null) + { + send.onClick.RemoveListener(OnPickupButtonClicked); + } + + // Clean up all matter cubes + foreach (var kvp in matterCubes) + { + if (kvp.Value != null) + { + Destroy(kvp.Value); + } + } + matterCubes.Clear(); + + // Clean up pending pickups + pendingPickups.Clear(); + + // Clean up picked up items tracking + pickedUpItems.Clear(); } } - private void OnDestroy() + // Helper class to handle click events on matter cubes + public class MatterCubeClickHandler : MonoBehaviour { - // Clean up button listener - if (send != null) + private int matterId; + private pickupItem pickupItemScript; + + public void Initialize(int id, pickupItem script) { - send.onClick.RemoveListener(OnPickupButtonClicked); + matterId = id; + pickupItemScript = script; } - - // Clean up all matter cubes - foreach (var kvp in matterCubes) + + private void OnMouseDown() { - if (kvp.Value != null) + if (pickupItemScript != null) { - Destroy(kvp.Value); + pickupItemScript.SendPickupCommand(matterId); } } - matterCubes.Clear(); - - // Clean up pending pickups - pendingPickups.Clear(); - - // Clean up picked up items tracking - pickedUpItems.Clear(); } -} -// Helper class to handle click events on matter cubes -public class MatterCubeClickHandler : MonoBehaviour -{ - private int matterId; - private pickupItem pickupItemScript; - - public void Initialize(int id, pickupItem script) + // Simple Billboard component to make text always face the camera + public class Billboard : MonoBehaviour { - matterId = id; - pickupItemScript = script; - } - - private void OnMouseDown() - { - if (pickupItemScript != null) + private Camera mainCamera; + + void Start() { - pickupItemScript.SendPickupCommand(matterId); - } - } -} - -// Simple Billboard component to make text always face the camera -public class Billboard : MonoBehaviour -{ - private Camera mainCamera; - - void Start() - { - mainCamera = Camera.main; - if (mainCamera == null) - { - mainCamera = FindFirstObjectByType(); - } - } - - void Update() - { - if (mainCamera != null) - { - // Make the text face the camera - transform.LookAt(mainCamera.transform); - transform.Rotate(0, 180, 0); // Flip to face the camera properly + mainCamera = Camera.main; + if (mainCamera == null) + { + mainCamera = FindFirstObjectByType(); + } + } + + void Update() + { + if (mainCamera != null) + { + // Make the text face the camera + transform.LookAt(mainCamera.transform); + transform.Rotate(0, 180, 0); // Flip to face the camera properly + } } } } diff --git a/Assets/PerfectWorld/Scripts/World/CECWorld.cs b/Assets/PerfectWorld/Scripts/World/CECWorld.cs index 779918373f..a4cc2e7679 100644 --- a/Assets/PerfectWorld/Scripts/World/CECWorld.cs +++ b/Assets/PerfectWorld/Scripts/World/CECWorld.cs @@ -1,9 +1,21 @@ using BrewMonster; using UnityEngine; -public class CECWorld : MonoSingleton -{ - uint m_dwBornStamp = 0; - public uint GetBornStamp() { return m_dwBornStamp++; } +namespace BrewMonster.Scripts.World +{ + public class CECWorld : MonoSingleton + { + protected A3DTerrain2 m_pA3DTerrain; // Terrain object + + uint m_dwBornStamp = 0; + + public uint GetBornStamp() { return m_dwBornStamp++; } + + // Get terrain object + public A3DTerrain2 GetTerrain() + { + return m_pA3DTerrain; + } + } } diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 967a427bec..d7370cf99e 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -1,1443 +1,1442 @@ -using BrewMonster; -using BrewMonster.Network; +using BrewMonster.Network; using CSNetwork; using CSNetwork.GPDataType; -using CSNetwork.Protocols; -using CSNetwork.Protocols.RPCData; -using PerfectWorld.Scripts.Managers; -using PerfectWorld.Scripts.Player; -using PerfectWorld.Scripts.Task; +using BrewMonster.Scripts.Managers; using System; -using System.IO; using System.Runtime.InteropServices; -using System.Text; using TMPro; using UnityEngine; -using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using UnityEngine.UI; using Scene = UnityEngine.SceneManagement.Scene; +using BrewMonster.Managers; -public class CECHostPlayer : EC_Player +namespace BrewMonster.Scripts.Player { - [SerializeField] private TextMeshPro txtName; - [SerializeField] private CharacterController controller; - - [SerializeField] private Joystick joystick; - [SerializeField] private Button btnJump; - [SerializeField] private Button btnRun; - [SerializeField] private Transform parentModel; - - PlayerStateMachine _playerStateMachine; - PlayerMoveState _moveState; - PlayerIdleState _idleState; - public CECHostMove m_MoveCtrl; - - CECHPWorkMan m_pWorkMan; // Host work manager - uint m_dwLIES; // Logic-influence extend states - FACTION_FORTRESS_ENTER m_fortressEnter; // ½øÈë»ùµØÐÅÏ¢ - PVPINFO m_pvp; // pvp information - bool m_bInSanctuary = false; // true, player is in sanctuary - int m_idFaction = 0; // ID of player's faction - public bool m_bPrepareFight = false; // true, prepare to fight - int m_iJumpCount = 0; - bool m_bJumpInWater = false; - public A3DVECTOR3 m_vVelocity; // Velocity - - float playerSpeed = 5.0f; - float jumpHeight = 1.5f; - float gravityValue = -9.81f; - StateAnim stateAnim = StateAnim.Idle; - Vector3 playerVelocity; - bool isGrounded = false; - bool isRun = false; - 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 ====== - [Header("Ground Cast")] - [Tooltip("Khoảng thêm ngoài skinWidth để SphereCast xuống (m ngắn)")] - [SerializeField] private float extraGroundDistance = 0.05f; - [Tooltip("Bớt bán kính một chút để tránh tự va vào capsule (epsilon)")] - [SerializeField] private float radiusEpsilon = 0.005f; - [Tooltip("Layer mặt đất")] - [SerializeField] private LayerMask groundMask; - [Tooltip("Layer mặt đất")] - [SerializeField] private float slopeToleranceDeg = 2f; - - // cache tùy chọn (không bắt buộc) - float ccRadius, ccSkin; - RaycastHit lastGroundHit; - Camera mainCam; - - private void Awake() + public class CECHostPlayer : EC_Player { - base.Awake(); - _moveState = new PlayerMoveState(this); - _idleState = new PlayerIdleState(this); - _playerStateMachine = new PlayerStateMachine(); - m_MoveCtrl = new CECHostMove(this); + [SerializeField] private TextMeshPro txtName; + [SerializeField] private CharacterController controller; - // Cache: không bắt buộc, nhưng gọn tay và ít gọi property lặp. - if (controller != null) + [SerializeField] private Joystick joystick; + [SerializeField] private Button btnJump; + [SerializeField] private Button btnRun; + [SerializeField] private Transform parentModel; + + PlayerStateMachine _playerStateMachine; + PlayerMoveState _moveState; + PlayerIdleState _idleState; + public CECHostMove m_MoveCtrl; + + CECHPWorkMan m_pWorkMan; // Host work manager + uint m_dwLIES; // Logic-influence extend states + FACTION_FORTRESS_ENTER m_fortressEnter; // ½øÈë»ùµØÐÅÏ¢ + PVPINFO m_pvp; // pvp information + bool m_bInSanctuary = false; // true, player is in sanctuary + int m_idFaction = 0; // ID of player's faction + public bool m_bPrepareFight = false; // true, prepare to fight + int m_iJumpCount = 0; + bool m_bJumpInWater = false; + public A3DVECTOR3 m_vVelocity; // Velocity + + float playerSpeed = 5.0f; + float jumpHeight = 1.5f; + float gravityValue = -9.81f; + StateAnim stateAnim = StateAnim.Idle; + Vector3 playerVelocity; + bool isGrounded = false; + bool isRun = false; + 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 ====== + [Header("Ground Cast")] + [Tooltip("Khoảng thêm ngoài skinWidth để SphereCast xuống (m ngắn)")] + [SerializeField] private float extraGroundDistance = 0.05f; + [Tooltip("Bớt bán kính một chút để tránh tự va vào capsule (epsilon)")] + [SerializeField] private float radiusEpsilon = 0.005f; + [Tooltip("Layer mặt đất")] + [SerializeField] private LayerMask groundMask; + [Tooltip("Layer mặt đất")] + [SerializeField] private float slopeToleranceDeg = 2f; + + // cache tùy chọn (không bắt buộc) + float ccRadius, ccSkin; + RaycastHit lastGroundHit; + Camera mainCam; + + private void Awake() { - ccRadius = controller.radius; - ccSkin = controller.skinWidth; - } - } + base.Awake(); + _moveState = new PlayerMoveState(this); + _idleState = new PlayerIdleState(this); + _playerStateMachine = new PlayerStateMachine(); + m_MoveCtrl = new CECHostMove(this); - - public void SetModelHostPlayer() - { - m_pPlayerModel = NPCManager.Instance.GetModelPlayer(); - Scene scene = SceneManager.GetSceneByName("WorldRender"); - SceneManager.MoveGameObjectToScene(m_pPlayerModel, scene); - m_pPlayerModel.transform.SetParent(parentModel); - m_pPlayerModel.transform.localPosition = Vector3.zero; - m_pPlayerModel.SetActive(true); - } - private void Start() - { - mainCam = Camera.main; - if (mainCam == null) - { - mainCam = FindFirstObjectByType(); - } - _playerStateMachine.InitState(_idleState); - // btnJump.onClick.AddListener(HandleJump); - } - - private void Update() - { - //Debug.Log($"(ulong)Time.deltaTime * 1000 {(ulong)(Time.deltaTime * 1000)}"); - m_MoveCtrl.Tick((ulong)(Time.deltaTime * 1000)); - // Nếu có thay đổi runtime, có thể lấy lại mỗi vài giây/Start nếu bạn thích: - // ccRadius = controller.radius; ccSkin = controller.skinWidth; - - _playerStateMachine.UpdateState(); - - if (Input.GetMouseButtonDown(1) && mainCam != null) - { - int idTraceTarget = 0, idSelTarget = 0; - bool bForceAttack = false; - int iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_NONE; - bool bWikiMonster = false; - - Ray ray = mainCam.ScreenPointToRay(Input.mousePosition); - RaycastHit hit; - - if (Physics.Raycast(ray, out hit)) + // Cache: không bắt buộc, nhưng gọn tay và ít gọi property lặp. + if (controller != null) { - CECObject clickedObject = hit.collider.gameObject.GetComponent(); + ccRadius = controller.radius; + ccSkin = controller.skinWidth; + } + } - if(clickedObject != null) + + public void SetModelHostPlayer() + { + m_pPlayerModel = NPCManager.Instance.GetModelPlayer(); + Scene scene = SceneManager.GetSceneByName("WorldRender"); + SceneManager.MoveGameObjectToScene(m_pPlayerModel, scene); + m_pPlayerModel.transform.SetParent(parentModel); + m_pPlayerModel.transform.localPosition = Vector3.zero; + m_pPlayerModel.SetActive(true); + } + private void Start() + { + mainCam = Camera.main; + if (mainCam == null) + { + mainCam = FindFirstObjectByType(); + } + _playerStateMachine.InitState(_idleState); + // btnJump.onClick.AddListener(HandleJump); + } + + private void Update() + { + //Debug.Log($"(ulong)Time.deltaTime * 1000 {(ulong)(Time.deltaTime * 1000)}"); + m_MoveCtrl.Tick((ulong)(Time.deltaTime * 1000)); + // Nếu có thay đổi runtime, có thể lấy lại mỗi vài giây/Start nếu bạn thích: + // ccRadius = controller.radius; ccSkin = controller.skinWidth; + + _playerStateMachine.UpdateState(); + + if (Input.GetMouseButtonDown(1) && mainCam != null) + { + int idTraceTarget = 0, idSelTarget = 0; + bool bForceAttack = false; + int iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_NONE; + bool bWikiMonster = false; + + Ray ray = mainCam.ScreenPointToRay(Input.mousePosition); + RaycastHit hit; + + if (Physics.Raycast(ray, out hit)) { - int idObject = CECObject.GetObjectID(clickedObject); - if (idObject != 0) + CECObject clickedObject = hit.collider.gameObject.GetComponent(); + + if (clickedObject != null) { - CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idObject); - if(pNPC != null) + int idObject = CECObject.GetObjectID(clickedObject); + if (idObject != 0) { - if (!pNPC.IsDead()/* && m_idSelTarget == idObject*/) + CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idObject); + if (pNPC != null) { - idTraceTarget = idObject; - idSelTarget = idObject; - } - if (idTraceTarget != 0) - { - if (AttackableJudge(idObject, bForceAttack) == 1) - iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_ATTACK; - else if (pNPC.IsServerNPC()) + if (!pNPC.IsDead()/* && m_idSelTarget == idObject*/) { - if (!IsInBattle() || InSameBattleCamp(pNPC)) - iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_TALK; + idTraceTarget = idObject; + idSelTarget = idObject; + } + if (idTraceTarget != 0) + { + if (AttackableJudge(idObject, bForceAttack) == 1) + iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_ATTACK; + else if (pNPC.IsServerNPC()) + { + if (!IsInBattle() || InSameBattleCamp(pNPC)) + iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_TALK; + } } } } } } - } - // 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()) - //{ - // g_pGame.GetGameSession().c2s_CmdStandUp(); - // return; - //} - // Trace a object - if (iTraceReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + // Tell server we select a target + if (idSelTarget != 0 && m_idSelTarget != idSelTarget) { - if (!CanDo(ActionCanDo.CANDO_MELEE)) - return; - Debug.LogError("Attack"); - NormalAttackObject(idTraceTarget, bForceAttack); + m_idUCSelTarget = idSelTarget; + SelectTarget(m_idUCSelTarget); } - //else - //{ - // if (!CanDo(CANDO_MOVETO)) - // return; - // if (iTraceReason == CECHPWorkTrace::TRACE_PICKUP) - // { - // PickupObject(idTraceTarget, false); - // } - // else if (iTraceReason == CECHPWorkTrace::TRACE_GATHER) - // { - // PickupObject(idTraceTarget, true); - // } - // else if (CECHPWork * pWork = m_pWorkMan.GetWork(CECHPWork::WORK_TRACEOBJECT)) - // { - // CECHPWorkTrace* pWorkTrace = dynamic_cast(pWork); - // pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idTraceTarget, iTraceReason, bForceAttack)); - // } - // else if (m_pWorkMan.CanStartWork(CECHPWork::WORK_TRACEOBJECT) && !bWikiMonster) - // { - // CECHPWorkTrace* pWork = (CECHPWorkTrace*)m_pWorkMan.CreateWork(CECHPWork::WORK_TRACEOBJECT); - // pWork.SetTraceTarget(pWork.CreatTraceTarget(idTraceTarget, iTraceReason, bForceAttack)); - // m_pWorkMan.StartWork_p1(pWork); - // } - //} - } - } - - m_pWorkMan?.Tick(Time.deltaTime); - } - public void StopMovement() - { - m_MoveCtrl.SendStopMoveCmd(transform.position, 5f, (int)GPMoveMode.GP_MOVE_WALK); - } - public void HandleMovement() - { - // 1) Kiểm tra grounded bằng SphereCast ngắn dựa trên radius + skinWidth - isGrounded = GroundCheck(out lastGroundHit); - - // 2) Input tạm thời: giữ nguyên như bạn - if (UnityEngine.Input.GetKeyDown(KeyCode.LeftShift)) SetStatusRun(true); - if (UnityEngine.Input.GetKeyUp(KeyCode.LeftShift)) SetStatusRun(false); - if (UnityEngine.Input.GetKeyDown(KeyCode.Space)) HandleJump(); - - // 3) Trọng lực / sticky - if (isGrounded && playerVelocity.y < 0f) - { - // Đè nhẹ để bám đất (tránh nhấp-nháy) - playerVelocity.y = -2f; - } - else - { - playerVelocity.y += gravityValue * Time.deltaTime; - } - - // 4) Chuyển động phẳng - float x = joystick.Horizontal; - float z = joystick.Vertical; - - Vector3 move = new Vector3(x, 0, z); - move = Vector3.ClampMagnitude(move, 1f); - - if (move != Vector3.zero) - { - transform.forward = move; - m_MoveCtrl.GroundMove(Time.deltaTime); - m_MoveCtrl.SendMoveCmd(transform.position, controller.velocity, (int)GPMoveMode.GP_MOVE_RUN); - } - else - { - - } - - Vector3 finalMove = (move * playerSpeed) + (playerVelocity.y * Vector3.up); - controller.Move(finalMove * Time.deltaTime); - } - private void JoystickRelease(JoystickRealeaseEvent joystickRealeaseEvent) - { - _playerStateMachine.ChangeState(_idleState); - } - - private bool GroundCheck(out RaycastHit hit) - { - float radius = controller.radius; - float skin = controller.skinWidth; - float height = controller.height; - - // Tâm capsule theo world - Vector3 cWorld = transform.TransformPoint(controller.center); - float hemi = Mathf.Max(0f, (height * 0.5f) - radius); - - // Hai điểm top/bottom của capsule nhân vật (đang đứng) - Vector3 pTop = cWorld + Vector3.up * hemi; - Vector3 pBottom = cWorld - Vector3.up * hemi; - - // Ta tạo một "đoạn capsule ngắn" gần đáy để sweep xuống - // Nhấc đoạn bắt đầu lên 1 chút để không bắt đầu trong trạng thái giao nhau - Vector3 startBottom = pBottom + Vector3.up * (skin + 0.01f); - Vector3 startTop = startBottom + Vector3.up * (radius * 2f - 0.02f); // chiều cao đoạn ngắn ~2*radius - - float castRadius = Mathf.Max(0f, radius - radiusEpsilon); - float castDistance = skin + extraGroundDistance; // quãng sweep ngắn - - bool hitSomething = Physics.CapsuleCast( - startTop, startBottom, castRadius, - Vector3.down, out hit, castDistance, - groundMask, QueryTriggerInteraction.Ignore - ); - - if (!hitSomething) return false; - - // Lọc theo slope limit - float maxSlope = controller.slopeLimit + slopeToleranceDeg; - float slope = Vector3.Angle(hit.normal, Vector3.up); - if (slope > maxSlope) return false; - - return true; - } - - private void HandleJump() - { - if (isGrounded) - { - playerVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravityValue); - } - } - public void ProcessMessage(in ECMSG Msg) - { - Debug.LogWarning("HoangDev : ProcessMessageProcessMessageProcessMessage"); - var msg = (int)Msg.dwMsg; - switch (msg) - { - case int value when value == EC_MsgDef.MSG_HST_CORRECTPOS: OnMsgHstCorrectPos(Msg); break; - case int value when value == EC_MsgDef.MSG_HST_GOTO: OnMsgHstGoto(Msg); break; - case int value when value == EC_MsgDef.MSG_HST_IVTRINFO: + if (idTraceTarget != 0) { - OnMsgHstIvtrInfo(Msg); - break; - } - case int value when value == EC_MsgDef.MSG_HST_OWNITEMINFO: - { - OnMsgHstOwnItemInfo(Msg); - break; - } - case int value when value == EC_MsgDef.MSG_HST_TASKDATA: - { - OnMsgHstTaskData(Msg); - //Debug.LogError("[Dat]- OnMsgHstTaskData"); - break; - } - case int value when value == EC_MsgDef.MSG_HST_ITEMOPERATION: - OnMsgHstItemOperation(Msg); - break; - 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; - } - } - - public void OnMsgHstPickupItem(in ECMSG Msg) - { - var data = Msg.dwParam1 as byte[]; - int cmd = Convert.ToInt32(Msg.dwParam2); - switch (cmd) - { - case CommandID.PICKUP_ITEM: - { - // Parse the pickup item data from the server response - if (data != null && data.Length >= 16) - { - int tid = BitConverter.ToInt32(data, 0); - int expire_date = BitConverter.ToInt32(data, 4); - uint iAmount = BitConverter.ToUInt32(data, 8); - uint iSlotAmount = BitConverter.ToUInt32(data, 12); - byte byPackage = data[16]; - byte bySlot = data[17]; - - Debug.Log($"[Inventory] PICKUP_ITEM: tid={tid}, expire_date={expire_date}, iAmount={iAmount}, iSlotAmount={iSlotAmount}, byPackage={byPackage}, bySlot={bySlot}"); - - // Notify pickupItem script about successful pickup - pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType(); - if (pickupScript != null) + //if (m_pWorkMan.IsSitting()) + //{ + // g_pGame.GetGameSession().c2s_CmdStandUp(); + // return; + //} + // Trace a object + if (iTraceReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) { - pickupScript.OnPickupSuccess(tid); - } - - // Create new inventory item data - var newItem = new InventoryItemData - { - Package = byPackage, - Slot = bySlot, - TemplateId = tid, - ExpireDate = expire_date, - State = 0, - Count = (int)iAmount, - Crc = 0, - Content = null - }; - - // Add item to inventory - EC_Inventory.SetItem(byPackage, bySlot, newItem); - - Debug.Log($"[Inventory] Successfully added item {tid} to package {byPackage}, slot {bySlot} with count {iAmount}"); - - // Trigger UI refresh if an EC_InventoryUI is present in scene - var ui = GameObject.FindFirstObjectByType(); - if (ui != null) - { - ui.RefreshAll(); + if (!CanDo(ActionCanDo.CANDO_MELEE)) + return; + Debug.LogError("Attack"); + NormalAttackObject(idTraceTarget, bForceAttack); } + //else + //{ + // if (!CanDo(CANDO_MOVETO)) + // return; + + // if (iTraceReason == CECHPWorkTrace::TRACE_PICKUP) + // { + // PickupObject(idTraceTarget, false); + // } + // else if (iTraceReason == CECHPWorkTrace::TRACE_GATHER) + // { + // PickupObject(idTraceTarget, true); + // } + // else if (CECHPWork * pWork = m_pWorkMan.GetWork(CECHPWork::WORK_TRACEOBJECT)) + // { + // CECHPWorkTrace* pWorkTrace = dynamic_cast(pWork); + // pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idTraceTarget, iTraceReason, bForceAttack)); + // } + // else if (m_pWorkMan.CanStartWork(CECHPWork::WORK_TRACEOBJECT) && !bWikiMonster) + // { + // CECHPWorkTrace* pWork = (CECHPWorkTrace*)m_pWorkMan.CreateWork(CECHPWork::WORK_TRACEOBJECT); + // pWork.SetTraceTarget(pWork.CreatTraceTarget(idTraceTarget, iTraceReason, bForceAttack)); + // m_pWorkMan.StartWork_p1(pWork); + // } + //} } - else - { - Debug.LogWarning("[Inventory] PICKUP_ITEM: Invalid data length"); - } - break; + } + + m_pWorkMan?.Tick(Time.deltaTime); + } + public void StopMovement() + { + m_MoveCtrl.SendStopMoveCmd(transform.position, 5f, (int)GPMoveMode.GP_MOVE_WALK); + } + public void HandleMovement() + { + // 1) Kiểm tra grounded bằng SphereCast ngắn dựa trên radius + skinWidth + isGrounded = GroundCheck(out lastGroundHit); + + // 2) Input tạm thời: giữ nguyên như bạn + if (UnityEngine.Input.GetKeyDown(KeyCode.LeftShift)) SetStatusRun(true); + if (UnityEngine.Input.GetKeyUp(KeyCode.LeftShift)) SetStatusRun(false); + if (UnityEngine.Input.GetKeyDown(KeyCode.Space)) HandleJump(); + + // 3) Trọng lực / sticky + if (isGrounded && playerVelocity.y < 0f) + { + // Đè nhẹ để bám đất (tránh nhấp-nháy) + playerVelocity.y = -2f; + } + else + { + playerVelocity.y += gravityValue * Time.deltaTime; + } + + // 4) Chuyển động phẳng + float x = joystick.Horizontal; + float z = joystick.Vertical; + + Vector3 move = new Vector3(x, 0, z); + move = Vector3.ClampMagnitude(move, 1f); + + if (move != Vector3.zero) + { + transform.forward = move; + m_MoveCtrl.GroundMove(Time.deltaTime); + m_MoveCtrl.SendMoveCmd(transform.position, controller.velocity, (int)GPMoveMode.GP_MOVE_RUN); + } + else + { + + } + + Vector3 finalMove = (move * playerSpeed) + (playerVelocity.y * Vector3.up); + controller.Move(finalMove * Time.deltaTime); + } + private void JoystickRelease(JoystickRealeaseEvent joystickRealeaseEvent) + { + _playerStateMachine.ChangeState(_idleState); + } + + private bool GroundCheck(out RaycastHit hit) + { + float radius = controller.radius; + float skin = controller.skinWidth; + float height = controller.height; + + // Tâm capsule theo world + Vector3 cWorld = transform.TransformPoint(controller.center); + float hemi = Mathf.Max(0f, (height * 0.5f) - radius); + + // Hai điểm top/bottom của capsule nhân vật (đang đứng) + Vector3 pTop = cWorld + Vector3.up * hemi; + Vector3 pBottom = cWorld - Vector3.up * hemi; + + // Ta tạo một "đoạn capsule ngắn" gần đáy để sweep xuống + // Nhấc đoạn bắt đầu lên 1 chút để không bắt đầu trong trạng thái giao nhau + Vector3 startBottom = pBottom + Vector3.up * (skin + 0.01f); + Vector3 startTop = startBottom + Vector3.up * (radius * 2f - 0.02f); // chiều cao đoạn ngắn ~2*radius + + float castRadius = Mathf.Max(0f, radius - radiusEpsilon); + float castDistance = skin + extraGroundDistance; // quãng sweep ngắn + + bool hitSomething = Physics.CapsuleCast( + startTop, startBottom, castRadius, + Vector3.down, out hit, castDistance, + groundMask, QueryTriggerInteraction.Ignore + ); + + if (!hitSomething) return false; + + // Lọc theo slope limit + float maxSlope = controller.slopeLimit + slopeToleranceDeg; + float slope = Vector3.Angle(hit.normal, Vector3.up); + if (slope > maxSlope) return false; + + return true; + } + + private void HandleJump() + { + if (isGrounded) + { + playerVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravityValue); } } - } - public void OnMsgHstItemOperation(ECMSG Msg) - { - var data = Msg.dwParam1 as byte[]; - int cmd = Convert.ToInt32(Msg.dwParam2); - switch (cmd) + public void ProcessMessage(in ECMSG Msg) { - case CommandID.PLAYER_DROP_ITEM: + Debug.LogWarning("HoangDev : ProcessMessageProcessMessageProcessMessage"); + var msg = (int)Msg.dwMsg; + switch (msg) { - // Parse the drop item data from the server response - if (data != null && data.Length >= 6) - { - byte byPackage = data[0]; - byte bySlot = data[1]; - int count = BitConverter.ToInt32(data, 2); - int tid = BitConverter.ToInt32(data, 6); - byte reason = data[10]; - - Debug.Log($"[Inventory] PLAYER_DROP_ITEM: package={byPackage}, slot={bySlot}, count={count}, tid={tid}, reason={reason}"); - - // Update the inventory by removing the item - bool success = EC_Inventory.RemoveItem(byPackage, bySlot, count); - - if (success) + case int value when value == EC_MsgDef.MSG_HST_CORRECTPOS: OnMsgHstCorrectPos(Msg); break; + case int value when value == EC_MsgDef.MSG_HST_GOTO: OnMsgHstGoto(Msg); break; + case int value when value == EC_MsgDef.MSG_HST_IVTRINFO: { - Debug.Log($"[Inventory] Successfully removed {count} items from package {byPackage}, slot {bySlot}"); - + OnMsgHstIvtrInfo(Msg); + break; + } + case int value when value == EC_MsgDef.MSG_HST_OWNITEMINFO: + { + OnMsgHstOwnItemInfo(Msg); + break; + } + case int value when value == EC_MsgDef.MSG_HST_TASKDATA: + { + OnMsgHstTaskData(Msg); + //Debug.LogError("[Dat]- OnMsgHstTaskData"); + break; + } + case int value when value == EC_MsgDef.MSG_HST_ITEMOPERATION: + OnMsgHstItemOperation(Msg); + break; + 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; + } + } + + public void OnMsgHstPickupItem(in ECMSG Msg) + { + var data = Msg.dwParam1 as byte[]; + int cmd = Convert.ToInt32(Msg.dwParam2); + switch (cmd) + { + case CommandID.PICKUP_ITEM: + { + // Parse the pickup item data from the server response + if (data != null && data.Length >= 16) + { + int tid = BitConverter.ToInt32(data, 0); + int expire_date = BitConverter.ToInt32(data, 4); + uint iAmount = BitConverter.ToUInt32(data, 8); + uint iSlotAmount = BitConverter.ToUInt32(data, 12); + byte byPackage = data[16]; + byte bySlot = data[17]; + + Debug.Log($"[Inventory] PICKUP_ITEM: tid={tid}, expire_date={expire_date}, iAmount={iAmount}, iSlotAmount={iSlotAmount}, byPackage={byPackage}, bySlot={bySlot}"); + + // Notify pickupItem script about successful pickup + pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType(); + if (pickupScript != null) + { + pickupScript.OnPickupSuccess(tid); + } + + // Create new inventory item data + var newItem = new InventoryItemData + { + Package = byPackage, + Slot = bySlot, + TemplateId = tid, + ExpireDate = expire_date, + State = 0, + Count = (int)iAmount, + Crc = 0, + Content = null + }; + + // Add item to inventory + EC_Inventory.SetItem(byPackage, bySlot, newItem); + + Debug.Log($"[Inventory] Successfully added item {tid} to package {byPackage}, slot {bySlot} with count {iAmount}"); + + // Trigger UI refresh if an EC_InventoryUI is present in scene + var ui = GameObject.FindFirstObjectByType(); + if (ui != null) + { + ui.RefreshAll(); + } + } + else + { + Debug.LogWarning("[Inventory] PICKUP_ITEM: Invalid data length"); + } + break; + } + } + } + public void OnMsgHstItemOperation(ECMSG Msg) + { + var data = Msg.dwParam1 as byte[]; + int cmd = Convert.ToInt32(Msg.dwParam2); + switch (cmd) + { + case CommandID.PLAYER_DROP_ITEM: + { + // Parse the drop item data from the server response + if (data != null && data.Length >= 6) + { + byte byPackage = data[0]; + byte bySlot = data[1]; + int count = BitConverter.ToInt32(data, 2); + int tid = BitConverter.ToInt32(data, 6); + byte reason = data[10]; + + Debug.Log($"[Inventory] PLAYER_DROP_ITEM: package={byPackage}, slot={bySlot}, count={count}, tid={tid}, reason={reason}"); + + // Update the inventory by removing the item + bool success = EC_Inventory.RemoveItem(byPackage, bySlot, count); + + if (success) + { + Debug.Log($"[Inventory] Successfully removed {count} items from package {byPackage}, slot {bySlot}"); + + // Trigger UI refresh if an EC_InventoryUI is present in scene + var ui = GameObject.FindFirstObjectByType(); + if (ui != null) + { + ui.RefreshAll(); + } + } + else + { + Debug.LogWarning($"[Inventory] Failed to remove items from package {byPackage}, slot {bySlot}"); + } + } + else + { + Debug.LogWarning("[Inventory] PLAYER_DROP_ITEM: Invalid data length"); + } + break; + } + case CommandID.EQUIP_ITEM: + { + byte index_inv = data[0]; + byte index_equip = data[1]; + // Update client-side data: move item between PACK_INVENTORY and PACK_EQUIPMENT + var invItem = EC_Inventory.GetItem(EC_Inventory.PACK_INVENTORY, index_inv, true); + var equipItem = EC_Inventory.GetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, true); + if (invItem != null) + { + invItem.Package = EC_Inventory.PACK_EQUIPMENT; + invItem.Slot = index_equip; + EC_Inventory.SetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, invItem); + } + if (equipItem != null) + { + equipItem.Package = EC_Inventory.PACK_INVENTORY; + equipItem.Slot = index_inv; + EC_Inventory.SetItem(EC_Inventory.PACK_INVENTORY, index_inv, equipItem); + } + // Trigger UI refresh if an EC_InventoryUI is present in scene - var ui = GameObject.FindFirstObjectByType(); + var ui = GameObject.FindObjectOfType(); if (ui != null) { ui.RefreshAll(); } + + break; } - else - { - Debug.LogWarning($"[Inventory] Failed to remove items from package {byPackage}, slot {bySlot}"); - } - } - else - { - Debug.LogWarning("[Inventory] PLAYER_DROP_ITEM: Invalid data length"); - } - break; } - case CommandID.EQUIP_ITEM: - { - byte index_inv = data[0]; - byte index_equip = data[1]; - // Update client-side data: move item between PACK_INVENTORY and PACK_EQUIPMENT - var invItem = EC_Inventory.GetItem(EC_Inventory.PACK_INVENTORY, index_inv, true); - var equipItem = EC_Inventory.GetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, true); - if (invItem != null) - { - invItem.Package = EC_Inventory.PACK_EQUIPMENT; - invItem.Slot = index_equip; - EC_Inventory.SetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, invItem); - } - if (equipItem != null) - { - equipItem.Package = EC_Inventory.PACK_INVENTORY; - equipItem.Slot = index_inv; - EC_Inventory.SetItem(EC_Inventory.PACK_INVENTORY, index_inv, equipItem); - } - - // Trigger UI refresh if an EC_InventoryUI is present in scene - var ui = GameObject.FindObjectOfType(); - if (ui != null) - { - ui.RefreshAll(); - } - - break; - } } - } - public void OnMsgHstOwnItemInfo(ECMSG Msg) - { - int cmd = Convert.ToInt32(Msg.dwParam2); - switch (cmd) + public void OnMsgHstOwnItemInfo(ECMSG Msg) { - case CommandID.OWN_ITEM_INFO: - { - Debug.Log("[Inventory] OWN_ITEM_INFO received"); - var data = Msg.dwParam1 as byte[]; - int hostId = Convert.ToInt32(Msg.dwParam3); - PerfectWorld.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_ITEM_INFO", data, hostId); - break; - } - - } - } - public void OnMsgHstIvtrInfo(ECMSG Msg) - { - var data = Msg.dwParam1 as byte[]; - int cmd = Convert.ToInt32(Msg.dwParam2); - int hostId = Convert.ToInt32(Msg.dwParam3); - - switch (cmd) - { - case CommandID.OWN_IVTR_DATA: - { - Debug.Log("[Inventory] OWN_IVTR_DATA received"); - PerfectWorld.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_IVTR_DATA", data, hostId); - break; - } - case CommandID.OWN_IVTR_DETAIL_DATA: - { - Debug.Log("[Inventory] OWN_IVTR_DETAIL_DATA received"); - PerfectWorld.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_IVTR_DETAIL_DATA", data, hostId); - // Parse and store - if (data != null && data.Length >= 6) + int cmd = Convert.ToInt32(Msg.dwParam2); + switch (cmd) + { + case CommandID.OWN_ITEM_INFO: { - byte byPackage = data[0]; - byte ivtrSize = data[1]; - if (PerfectWorld.Scripts.Managers.EC_IvtrItem.TryParseInventoryDetail(data, out var pkg, out var size, out var items)) + Debug.Log("[Inventory] OWN_ITEM_INFO received"); + var data = Msg.dwParam1 as byte[]; + int hostId = Convert.ToInt32(Msg.dwParam3); + BrewMonster.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_ITEM_INFO", data, hostId); + break; + } + + } + } + public void OnMsgHstIvtrInfo(ECMSG Msg) + { + var data = Msg.dwParam1 as byte[]; + int cmd = Convert.ToInt32(Msg.dwParam2); + int hostId = Convert.ToInt32(Msg.dwParam3); + + switch (cmd) + { + case CommandID.OWN_IVTR_DATA: + { + Debug.Log("[Inventory] OWN_IVTR_DATA received"); + BrewMonster.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_IVTR_DATA", data, hostId); + break; + } + case CommandID.OWN_IVTR_DETAIL_DATA: + { + Debug.Log("[Inventory] OWN_IVTR_DETAIL_DATA received"); + BrewMonster.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_IVTR_DETAIL_DATA", data, hostId); + // Parse and store + if (data != null && data.Length >= 6) { - PerfectWorld.Scripts.Managers.EC_Inventory.UpdatePack(pkg, size, items); + byte byPackage = data[0]; + byte ivtrSize = data[1]; + if (BrewMonster.Scripts.Managers.EC_IvtrItem.TryParseInventoryDetail(data, out var pkg, out var size, out var items)) + { + BrewMonster.Scripts.Managers.EC_Inventory.UpdatePack(pkg, size, items); + } } + break; } - break; - } + + } + } + public void OnMsgHstCorrectPos(in ECMSG Msg) + { + Debug.LogWarning("HoangDev : OnMsgHstCorrectPos"); + byte[] buf = (byte[])Msg.dwParam1; // chỗ bạn lưu pDataBuf + GCHandle handle = GCHandle.Alloc(buf, GCHandleType.Pinned); + cmd_host_correct_pos pCmd = (cmd_host_correct_pos)Marshal.PtrToStructure( + handle.AddrOfPinnedObject(), typeof(cmd_host_correct_pos)); + handle.Free(); + Debug.LogWarning("HoangDev :pCmd.pos " + pCmd.pos); + SetPos(pCmd.pos); + } + public void OnMsgHstGoto(in ECMSG Msg) + { + Debug.Log("HoangDev :OnMsgHstGoto"); + cmd_notify_hostpos pCmd = (cmd_notify_hostpos)Msg.dwParam1; } - } - public void OnMsgHstCorrectPos(in ECMSG Msg) - { - Debug.LogWarning("HoangDev : OnMsgHstCorrectPos"); - byte[] buf = (byte[])Msg.dwParam1; // chỗ bạn lưu pDataBuf - GCHandle handle = GCHandle.Alloc(buf, GCHandleType.Pinned); - cmd_host_correct_pos pCmd = (cmd_host_correct_pos)Marshal.PtrToStructure( - handle.AddrOfPinnedObject(), typeof(cmd_host_correct_pos)); - handle.Free(); - Debug.LogWarning("HoangDev :pCmd.pos " + pCmd.pos); - SetPos(pCmd.pos); - } - public void OnMsgHstGoto(in ECMSG Msg) - { - Debug.Log("HoangDev :OnMsgHstGoto"); - cmd_notify_hostpos pCmd = (cmd_notify_hostpos)Msg.dwParam1; - } - - // Message MSG_HST_SELTARGET handler - void OnMsgHstSelTarget(ECMSG Msg) - { - if (Convert.ToInt32(Msg.dwParam2) == CommandID.SELECT_TARGET) - { - var data = (byte[])Msg.dwParam1; - cmd_select_target pCmd = GPDataTypeHelper.FromBytes(data); - m_idSelTarget = pCmd.idTarget; - m_idUCSelTarget = 0; - } - else if (Convert.ToInt32(Msg.dwParam2) == CommandID.UNSELECT) + // Message MSG_HST_SELTARGET handler + void OnMsgHstSelTarget(ECMSG Msg) { - m_idSelTarget = 0; + if (Convert.ToInt32(Msg.dwParam2) == CommandID.SELECT_TARGET) + { + var data = (byte[])Msg.dwParam1; + cmd_select_target pCmd = GPDataTypeHelper.FromBytes(data); + m_idSelTarget = pCmd.idTarget; + m_idUCSelTarget = 0; + } + else if (Convert.ToInt32(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) - { - if (!isGrounded) + public void SetPos(Vector3 pos) { - Debug.LogError("Player not in ground"); - return; + 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(); } - isRun = value; - } - public void InitCharacter(cmd_self_info_1 role) - { - string roleName = "(Error decoding name)"; - //if (role.name != null && role.name.ByteArray != null) - //{ - // roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); - //} - SetPlayerInfor(new INFO(role.cid, role.crc_e, role.crc_c)); - Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); - if (txtName != null) txtName.text = roleName; - transform.position = pos; - SetModelHostPlayer(); - Debug.LogError("Pos Character = " + pos); - joystick = FindAnyObjectByType(); - EventBus.Subscribe(JoystickRelease); - EventBus.Subscribe(JoystickStartDrag); - if (TryGetComponent(out var visual)) + public void SetStatusRun(bool value) { - visual.InitHostPlayerEventDoneHandler(); + if (!isGrounded) + { + Debug.LogError("Player not in ground"); + return; + } + isRun = value; } - 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); - if (m_pWorkMan == null) + public void InitCharacter(cmd_self_info_1 role) { - return; - } - } - - private void JoystickStartDrag(JoystickPressEvent joystickPressEvent) - { - _playerStateMachine.ChangeState(_moveState); - } - private void OnDestroy() - { - EventBus.Unsubscribe(JoystickRelease); - EventBus.Unsubscribe(JoystickStartDrag); - } - public void InitCharacter(info_player_1 role) - { - string roleName = "(Error decoding name)"; - //if (role.name != null && role.name.ByteArray != null) - //{ - // roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); - //} - Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); - if (txtName != null) txtName.text = roleName; - transform.position = pos; - SetModelHostPlayer(); - Debug.LogError("Pos Character = " + pos); - } - - #region Task - public void OnMsgHstTaskData(ECMSG Msg) - { - int cmd = Convert.ToInt32(Msg.dwParam2); - if (cmd == CommandID.TASK_DATA) - { - Debug.Log("[Dat]- OnMsgHstTaskData- TASK_DATA"); - //a_LogOutput(1, "[Dat]- EC_HostMsg- OnMsgHstTaskData- TASK_DATA"); - //cmd_task_data* pCmd = (cmd_task_data*)Msg.dwParam1; - //ASSERT(pCmd); - - //int iActiveListSize = (int)pCmd.active_list_size; - //BYTE* pData = (BYTE*)pCmd + sizeof(size_t); - //void* pActiveListbuf = pData; - //pData += iActiveListSize; - - //int iFinishedListSize = *(int*)pData; - //pData += sizeof(int); - //void* pFinishedListBuf = pData; - //pData += iFinishedListSize; - - //int iFinishTimeListSize = *(int*)pData; - //pData += sizeof(int); - //void* pFinishTimeListBuf = pData; - //pData += iFinishTimeListSize; - - //int iFinishedCountListSize = *(int*)pData; - //pData += sizeof(int); - //void* pFinishedCountListBuf = pData; - //pData += iFinishedCountListSize; - - //int iStorageTasksListSize = *(int*)pData; - //pData += sizeof(int); - //void* pStorageTaskListBuf = pData; - //pData += iStorageTasksListSize; - - //A3DRELEASE(m_pTaskInterface); - - //todo - //var m_pTaskInterface = new CECTaskInterface(this); - - //if (!m_pTaskInterface.Init(null, 0, null, 0, - // null, 0, null, 0, null, 0)) + CalcPlayerAABB(); + m_aabb.Center = GPDataTypeHelper.g_vOrigin; + m_aabb.Extents.Set(0.3f, 0.9f, 0.3f); + m_aabbServer = m_aabb; + string roleName = "(Error decoding name)"; + //if (role.name != null && role.name.ByteArray != null) //{ - // //a_LogOutput(1, "CECHostPlayer::OnMsgHstTaskData, failed to initialize task interface"); - // return; + // roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); //} + SetPlayerInfor(new INFO(role.cid, role.crc_e, role.crc_c)); + Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); + if (txtName != null) txtName.text = roleName; + //SetPos(pos); + transform.position = pos; + SetModelHostPlayer(); + Debug.LogError("Pos Character = " + pos); + joystick = FindAnyObjectByType(); + EventBus.Subscribe(JoystickRelease); + EventBus.Subscribe(JoystickStartDrag); + if (TryGetComponent(out var visual)) + { + visual.InitHostPlayerEventDoneHandler(); + } - //m_pTaskInterface.CheckPQEnterWorldInit(); + // Create work manager + m_pWorkMan = new CECHPWorkMan(this); + if (m_pWorkMan == null) + { + return; + } + } - //// check if player has equipped goblin - //if (m_pEquipPack.GetItem(EQUIPIVTR_GOBLIN) != NULL) + private void JoystickStartDrag(JoystickPressEvent joystickPressEvent) + { + _playerStateMachine.ChangeState(_moveState); + } + private void OnDestroy() + { + EventBus.Unsubscribe(JoystickRelease); + EventBus.Unsubscribe(JoystickStartDrag); + } + public void InitCharacter(info_player_1 role) + { + string roleName = "(Error decoding name)"; + //if (role.name != null && role.name.ByteArray != null) //{ - // CECIvtrGoblin* pIvtrGoblin = (CECIvtrGoblin*)m_pEquipPack.GetItem(EQUIPIVTR_GOBLIN); - // m_pGoblin = new CECHostGoblin(); - // m_pGoblin.Init(pIvtrGoblin.GetTemplateID(), pIvtrGoblin, this); + // roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); //} - - //// Note: this command now is also used as the end flag of responding - //// for GET_ALL_DATA request - //g_pGame.GetGameSession().LoadConfigData(); - - //// ¸ù¾Ý×°±¸°ü¹ü¸üÐÂ×°±¸¼¼Äܵ½¼¼ÄÜÁбí - //if (UpdateEquipSkills()) - // UpdateEquipSkillCoolDown(); + Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); + if (txtName != null) txtName.text = roleName; + transform.position = pos; + SetModelHostPlayer(); + Debug.LogError("Pos Character = " + pos); } - else if (cmd == CommandID.TASK_VAR_DATA) - { - //cmd_task_var_data* pCmd = (cmd_task_var_data*)Msg.dwParam1; - //ASSERT(pCmd); - //if (m_pTaskInterface) - // OnServerNotify(m_pTaskInterface, pCmd.data, pCmd.size); - //else - // ASSERT(m_pTaskInterface); - } - } - #endregion - private bool NormalAttackObject(int idTarget, bool bForceAttack, bool bMoreClose = false) - { - if (idTarget == 0 || idTarget == m_PlayerInfo.cid) + #region Task + public void OnMsgHstTaskData(ECMSG Msg) { - // We should have check target isn't dead + int cmd = Convert.ToInt32(Msg.dwParam2); + if (cmd == CommandID.TASK_DATA) + { + Debug.Log("[Dat]- OnMsgHstTaskData- TASK_DATA"); + //a_LogOutput(1, "[Dat]- EC_HostMsg- OnMsgHstTaskData- TASK_DATA"); + //cmd_task_data* pCmd = (cmd_task_data*)Msg.dwParam1; + //ASSERT(pCmd); + + //int iActiveListSize = (int)pCmd.active_list_size; + //BYTE* pData = (BYTE*)pCmd + sizeof(size_t); + //void* pActiveListbuf = pData; + //pData += iActiveListSize; + + //int iFinishedListSize = *(int*)pData; + //pData += sizeof(int); + //void* pFinishedListBuf = pData; + //pData += iFinishedListSize; + + //int iFinishTimeListSize = *(int*)pData; + //pData += sizeof(int); + //void* pFinishTimeListBuf = pData; + //pData += iFinishTimeListSize; + + //int iFinishedCountListSize = *(int*)pData; + //pData += sizeof(int); + //void* pFinishedCountListBuf = pData; + //pData += iFinishedCountListSize; + + //int iStorageTasksListSize = *(int*)pData; + //pData += sizeof(int); + //void* pStorageTaskListBuf = pData; + //pData += iStorageTasksListSize; + + //A3DRELEASE(m_pTaskInterface); + + //todo + //var m_pTaskInterface = new CECTaskInterface(this); + + //if (!m_pTaskInterface.Init(null, 0, null, 0, + // null, 0, null, 0, null, 0)) + //{ + // //a_LogOutput(1, "CECHostPlayer::OnMsgHstTaskData, failed to initialize task interface"); + // return; + //} + + //m_pTaskInterface.CheckPQEnterWorldInit(); + + //// check if player has equipped goblin + //if (m_pEquipPack.GetItem(EQUIPIVTR_GOBLIN) != NULL) + //{ + // CECIvtrGoblin* pIvtrGoblin = (CECIvtrGoblin*)m_pEquipPack.GetItem(EQUIPIVTR_GOBLIN); + // m_pGoblin = new CECHostGoblin(); + // m_pGoblin.Init(pIvtrGoblin.GetTemplateID(), pIvtrGoblin, this); + //} + + //// Note: this command now is also used as the end flag of responding + //// for GET_ALL_DATA request + //g_pGame.GetGameSession().LoadConfigData(); + + //// ¸ù¾Ý×°±¸°ü¹ü¸üÐÂ×°±¸¼¼Äܵ½¼¼ÄÜÁбí + //if (UpdateEquipSkills()) + // UpdateEquipSkillCoolDown(); + } + else if (cmd == CommandID.TASK_VAR_DATA) + { + //cmd_task_var_data* pCmd = (cmd_task_var_data*)Msg.dwParam1; + //ASSERT(pCmd); + //if (m_pTaskInterface) + // OnServerNotify(m_pTaskInterface, pCmd.data, pCmd.size); + //else + // ASSERT(m_pTaskInterface); + } + } + #endregion + + private bool NormalAttackObject(int idTarget, bool bForceAttack, bool bMoreClose = false) + { + if (idTarget == 0 || idTarget == m_PlayerInfo.cid) + { + // We should have check target isn't dead + return false; + } + //if (!EC_Game.GetGameRun().GetWorld().GetObject(idTarget, 1)) + // return false; + bool bStartNewWork = false; + + bool bUseAutoPF = false; + //CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper(); + //if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper.GetAttackError() >= 2) + bUseAutoPF = true; + + CECHPWorkTrace pWorkTrace = null; + CECHPWork pWork = null; + if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) != null) + { + pWorkTrace = pWork as CECHPWorkTrace; + } + else if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT)) != null) + { + if ((pWork as CECHPWorkMelee).GetTarget() == idTarget) + return false; // Host is attacking the target + + pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); + bStartNewWork = true; + } + else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) + { + pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); + bStartNewWork = true; + } + + if (pWorkTrace != null) + { + pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK, bForceAttack), bUseAutoPF); + pWorkTrace.SetMoveCloseFlag(bMoreClose); + + if (bStartNewWork) + m_pWorkMan.StartWork_p1(pWorkTrace); + return true; + } return false; } - //if (!EC_Game.GetGameRun().GetWorld().GetObject(idTarget, 1)) - // return false; - bool bStartNewWork = false; - bool bUseAutoPF = false; - //CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper(); - //if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper.GetAttackError() >= 2) - bUseAutoPF = true; - - CECHPWorkTrace pWorkTrace = null; - CECHPWork pWork = null; - if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) != null) + public int AttackableJudge(int idTarget, bool bForceAttack) { - pWorkTrace = pWork as CECHPWorkTrace; - } - else if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT)) != null) - { - if ((pWork as CECHPWorkMelee).GetTarget() == idTarget) - return false; // Host is attacking the target + if (CannotAttack()) + return 0; - pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); - bStartNewWork = true; - } - else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) - { - pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); - bStartNewWork = true; - } + //if (CDlgAutoHelp::IsAutoHelp()) + // return 0; - if (pWorkTrace != null) - { - pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK, bForceAttack), bUseAutoPF); - pWorkTrace.SetMoveCloseFlag(bMoreClose); + if (idTarget == 0 || idTarget == m_PlayerInfo.cid) + return -1; - if (bStartNewWork) - m_pWorkMan.StartWork_p1(pWorkTrace); - return true; - } - return false; - } + CECObject pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); + if (!pObject) + return -1; - public int AttackableJudge(int idTarget, bool bForceAttack) - { - if (CannotAttack()) - return 0; - - //if (CDlgAutoHelp::IsAutoHelp()) - // return 0; - - if (idTarget == 0 || idTarget == m_PlayerInfo.cid) - return -1; - - CECObject pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); - if (!pObject) - return -1; - - // If target is pet, it's attacked possibility depends on it's monster - if (GPDataTypeHelper.ISNPCID(idTarget)) - { - CECNPC pNPC = (CECNPC)pObject; - int idMaster = pNPC.GetMasterID(); - if (idMaster != 0) + // If target is pet, it's attacked possibility depends on it's monster + if (GPDataTypeHelper.ISNPCID(idTarget)) { - // master¿ÉÄÜÊÇhostplayer - if (idMaster == m_PlayerInfo.cid) - return 0; + CECNPC pNPC = (CECNPC)pObject; + int idMaster = pNPC.GetMasterID(); + if (idMaster != 0) + { + // master¿ÉÄÜÊÇhostplayer + if (idMaster == m_PlayerInfo.cid) + return 0; - //// Follow pet cannot be attacked - //if (pNPC.IsPetNPC() && ((CECPet)pNPC).IsFollowPet()) + //// Follow pet cannot be attacked + //if (pNPC.IsPetNPC() && ((CECPet)pNPC).IsFollowPet()) + // return 0; + + idTarget = idMaster; + pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); + if (!pObject) + return -1; + } + } + + int iRet = 0; + + if (GPDataTypeHelper.ISNPCID(idTarget)) + { + CECNPC pNPC = (CECNPC)pObject; + + // If this npc is host's pet, cannot be attacked + //if (pNPC.GetMasterID() == m_PlayerInfo.cid) // return 0; - idTarget = idMaster; - pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); - if (!pObject) - return -1; - } - } + // If it's a pet and can not be attacked, pet can be attacked only if it's a fighting pet + //if (pNPC.IsPetNPC() && !((CECPet)pNPC).CanBeAttacked()) + // return 0; - int iRet = 0; - - if (GPDataTypeHelper.ISNPCID(idTarget)) - { - CECNPC pNPC = (CECNPC)pObject; - - // If this npc is host's pet, cannot be attacked - //if (pNPC.GetMasterID() == m_PlayerInfo.cid) - // return 0; - - // If it's a pet and can not be attacked, pet can be attacked only if it's a fighting pet - //if (pNPC.IsPetNPC() && !((CECPet)pNPC).CanBeAttacked()) - // return 0; - - if (IsInBattle()) // Host is in battle - { - if (InSameBattleCamp(pNPC)) - iRet = 0; - else + if (IsInBattle()) // Host is in battle { - if (pNPC.IsMonsterNPC()) - iRet = 1; - else if (pNPC.IsServerNPC() && (IsInFortress() || pNPC.GetRoleInBattle() == 8)) // ¶Ô·þÎñÐÍNPCµÄ¹¥»÷£¬°ïÅÉ»ùµØ»ò³Çսʱ¿ÉÓà - iRet = 1; - else + if (InSameBattleCamp(pNPC)) iRet = 0; - } - } - else if (pNPC.IsServerNPC()) - { - // In sanctuary we cannot attack NPCs - if (!IsPVPOpen() || m_bInSanctuary || !bForceAttack) - iRet = 0; - else - iRet = 1; - } - else // Is monster - { - iRet = 1; - } - if (iRet == 1 && pNPC.GetOwnerFaction() > 0) - { - // Õë¶Ô°ïÅÉ PVP Õ½ÕùÖнûÖ¹²¿·Ö¹¥»÷ - if (GetFactionID() == pNPC.GetOwnerFaction() || // ²»¹¥»÷ͬ°ï¹Ö - pNPC.IsFactionPVPMineCar() && !CanAttackFactionPVPMineCar() || // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï¿ó³µÇé¿ö - pNPC.IsFactionPVPMineBase() && !CanAttackFactionPVPMineBase()) - { // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï´æ¿óµãÇé¿ö - iRet = 0; - } - } - } - // TO DO: fix later - //else if (GPDataTypeHelper.ISPLAYERID(idTarget)) - //{ - // // Check duel at first - // if (m_pvp.iDuelState == Duel_state.DUEL_ST_INDUEL && m_pvp.idDuelOpp == idTarget) - // return 1; - // else if (m_pvp.iDuelState == Duel_state.DUEL_ST_STOPPING && m_pvp.idDuelOpp == idTarget) - // return 0; - - // // In sanctuary we cannot attack other players - // if (m_bInSanctuary) - // return 0; - - // //ASSERT(pObject.GetClassID() == CECObject::OCID_ELSEPLAYER); - // EC_ElsePlayer pPlayer = (EC_ElsePlayer)pObject; - // ROLEBASICPROP bp = pPlayer.GetBasicProps(); - // EC_GAME_SETTING gs = g_pGame.GetConfigs().GetGameSettings(); - - // if (m_pvp.bFreePVP) - // { - // if (IsTeamMember(idTarget)) - // return 0; - - // // In free pvp mode, for example, host is in arena. - // if (bForceAttack) - // iRet = 1; - // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) - // iRet = 0; - // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) - // iRet = 0; - // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) - // iRet = 0; - // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) - // iRet = 0; - // else - // iRet = 1; - // } - // else if (m_iBattleCamp != GP_BATTLE_CAMP_NONE) - // { - // // Host is in battle - // int iCamp = pPlayer.GetBattleCamp(); - // if (iCamp != GP_BATTLE_CAMP_NONE && iCamp != m_iBattleCamp) - // iRet = 1; - // else - // iRet = 0; - // } - // else // Normal mode - // { - // if (IsTeamMember(idTarget)) - // return 0; - - // if (!IsPVPOpen() || !pPlayer.IsPVPOpen() || m_BasicProps.iLevel < EC_MAXNOPKLEVEL || bp.iLevel < EC_MAXNOPKLEVEL) - // iRet = 0; - // else if (bForceAttack) - // iRet = 1; - // else if (!gs.bAtk_Player) - // iRet = 0; - // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) - // iRet = 0; - // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) - // iRet = 0; - // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) - // iRet = 0; - // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) - // iRet = 0; - // else - // iRet = 1; - // } - //} - else - { - return -1; - } - - return iRet; - } - - private float A3d_Magnitude(A3DVECTOR3 v) - { - return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - } - - public int GetCharacterID(){ return m_PlayerInfo.cid; } - - public bool CannotAttack() { return (m_dwLIES & (uint)Logic_Influence_Extned_states.LIES_DISABLEFIGHT) != 0; } - - public bool CanTouchTarget(A3DVECTOR3 vHostPos, A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f) - { - float fDist = A3d_Magnitude(vTargetPos - vHostPos); - switch (iReason) - { - case 1: // melee - { - float fRange; - if (fMaxCut >= 0.0f) - { - float fCutDist = m_ExtProps.ak.AttackRange * 0.3f; - if (fCutDist > fMaxCut) - fCutDist = fMaxCut; - - fRange = m_ExtProps.ak.AttackRange - fCutDist; - } - else - fRange = m_ExtProps.ak.AttackRange * 0.7f; - - if (fDist - fTargetRad <= fRange) - return true; - - break; + { + if (pNPC.IsMonsterNPC()) + iRet = 1; + else if (pNPC.IsServerNPC() && (IsInFortress() || pNPC.GetRoleInBattle() == 8)) // ¶Ô·þÎñÐÍNPCµÄ¹¥»÷£¬°ïÅÉ»ùµØ»ò³Çսʱ¿ÉÓà + iRet = 1; + else + iRet = 0; + } } - //case 2: // cast magic + else if (pNPC.IsServerNPC()) + { + // In sanctuary we cannot attack NPCs + if (!IsPVPOpen() || m_bInSanctuary || !bForceAttack) + iRet = 0; + else + iRet = 1; + } + else // Is monster + { + iRet = 1; + } + if (iRet == 1 && pNPC.GetOwnerFaction() > 0) + { + // Õë¶Ô°ïÅÉ PVP Õ½ÕùÖнûÖ¹²¿·Ö¹¥»÷ + if (GetFactionID() == pNPC.GetOwnerFaction() || // ²»¹¥»÷ͬ°ï¹Ö + pNPC.IsFactionPVPMineCar() && !CanAttackFactionPVPMineCar() || // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï¿ó³µÇé¿ö + pNPC.IsFactionPVPMineBase() && !CanAttackFactionPVPMineBase()) + { // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï´æ¿óµãÇé¿ö + iRet = 0; + } + } + } + // TO DO: fix later + //else if (GPDataTypeHelper.ISPLAYERID(idTarget)) //{ - // if (m_pPrepSkill) + // // Check duel at first + // if (m_pvp.iDuelState == Duel_state.DUEL_ST_INDUEL && m_pvp.idDuelOpp == idTarget) + // return 1; + // else if (m_pvp.iDuelState == Duel_state.DUEL_ST_STOPPING && m_pvp.idDuelOpp == idTarget) + // return 0; + + // // In sanctuary we cannot attack other players + // if (m_bInSanctuary) + // return 0; + + // //ASSERT(pObject.GetClassID() == CECObject::OCID_ELSEPLAYER); + // EC_ElsePlayer pPlayer = (EC_ElsePlayer)pObject; + // ROLEBASICPROP bp = pPlayer.GetBasicProps(); + // EC_GAME_SETTING gs = g_pGame.GetConfigs().GetGameSettings(); + + // if (m_pvp.bFreePVP) // { - // float fRange = m_pPrepSkill.GetCastRange(m_ExtProps.ak.AttackRange, GetPrayDistancePlus()); - // if (fRange > 0.0f) - // { - // if (fDist - fTargetRad <= fRange) - // return true; - // } + // if (IsTeamMember(idTarget)) + // return 0; + + // // In free pvp mode, for example, host is in arena. + // if (bForceAttack) + // iRet = 1; + // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) + // iRet = 0; + // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) + // iRet = 0; // else - // return true; + // iRet = 1; // } + // else if (m_iBattleCamp != GP_BATTLE_CAMP_NONE) + // { + // // Host is in battle + // int iCamp = pPlayer.GetBattleCamp(); + // if (iCamp != GP_BATTLE_CAMP_NONE && iCamp != m_iBattleCamp) + // iRet = 1; + // else + // iRet = 0; + // } + // else // Normal mode + // { + // if (IsTeamMember(idTarget)) + // return 0; - // break; + // if (!IsPVPOpen() || !pPlayer.IsPVPOpen() || m_BasicProps.iLevel < EC_MAXNOPKLEVEL || bp.iLevel < EC_MAXNOPKLEVEL) + // iRet = 0; + // else if (bForceAttack) + // iRet = 1; + // else if (!gs.bAtk_Player) + // iRet = 0; + // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) + // iRet = 0; + // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) + // iRet = 0; + // else + // iRet = 1; + // } //} - case 3: // talk - { - if (fDist - fTargetRad <= 5.0f) - return true; - - break; - } - default: // no special reason - { - if (fDist < (fTargetRad + m_fTouchRad) * 3.0f) - return true; - - break; - } - } - - return false; - } - - public bool CanTouchTarget(A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f) - { - A3DVECTOR3 vector = new A3DVECTOR3(gameObject.transform.position.x, gameObject.transform.position.y, gameObject.transform.position.z); - return CanTouchTarget(vector, vTargetPos, fTargetRad, iReason, fMaxCut); - } - public bool IsRooting() { - var mask = (uint)(Logic_Influence_Extned_states.LIES_ROOT - | Logic_Influence_Extned_states.LIES_SLEEP - | Logic_Influence_Extned_states.LIES_STUN); - return (m_dwLIES & mask) != 0; } - - bool IsInFortress() { return m_fortressEnter.role_in_war != 0; } - - bool IsPVPOpen() { return m_pvp.bEnable; } - // Get faction ID - int GetFactionID(){ return m_idFaction; } - - public bool IsJumping() { return m_iJumpCount > 0; } - - public bool IsPlayingAction(int iAction) - { - if (iAction == (int)PLAYER_ACTION_TYPE.ACT_WALK && _playerStateMachine.State is PlayerMoveState) - { - return true; - } - if (iAction == (int)PLAYER_ACTION_TYPE.ACT_STAND && _playerStateMachine.State is PlayerIdleState) - { - return true; - } - return false; - } - - public void ResetJump() { m_iJumpCount = 0; m_bJumpInWater = false; } - // Get move speed - 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 -1; } - } - return bRet; - } - bool CanSelectTarget(int idTarget) - { - if (idTarget == 0 || idTarget == this.GetCharacterID()) - { - // 0 means unselect - return true; + return iRet; } - CECObject pTarget = null; - if (GPDataTypeHelper.ISPLAYERID(idTarget)) + + private float A3d_Magnitude(A3DVECTOR3 v) { - EC_ElsePlayer pElsePlayer = (EC_ManMessageMono.Instance.GetECManPlayer.GetPlayer(idTarget)) as EC_ElsePlayer; - if (pElsePlayer != null) + return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + } + + public int GetCharacterID() { return m_PlayerInfo.cid; } + + public bool CannotAttack() { return (m_dwLIES & (uint)Logic_Influence_Extned_states.LIES_DISABLEFIGHT) != 0; } + + public bool CanTouchTarget(A3DVECTOR3 vHostPos, A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f) + { + float fDist = A3d_Magnitude(vTargetPos - vHostPos); + switch (iReason) { - if (CanSafelySelect(pElsePlayer)) + case 1: // melee + { + float fRange; + if (fMaxCut >= 0.0f) + { + float fCutDist = m_ExtProps.ak.AttackRange * 0.3f; + if (fCutDist > fMaxCut) + fCutDist = fMaxCut; + + fRange = m_ExtProps.ak.AttackRange - fCutDist; + } + + else + fRange = m_ExtProps.ak.AttackRange * 0.7f; + + if (fDist - fTargetRad <= fRange) + return true; + + break; + } + //case 2: // cast magic + //{ + // if (m_pPrepSkill) + // { + // float fRange = m_pPrepSkill.GetCastRange(m_ExtProps.ak.AttackRange, GetPrayDistancePlus()); + // if (fRange > 0.0f) + // { + // if (fDist - fTargetRad <= fRange) + // return true; + // } + // else + // return true; + // } + + // break; + //} + case 3: // talk + { + if (fDist - fTargetRad <= 5.0f) + return true; + + break; + } + default: // no special reason + { + if (fDist < (fTargetRad + m_fTouchRad) * 3.0f) + return true; + + break; + } + } + + return false; + } + + public bool CanTouchTarget(A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f) + { + A3DVECTOR3 vector = new A3DVECTOR3(gameObject.transform.position.x, gameObject.transform.position.y, gameObject.transform.position.z); + return CanTouchTarget(vector, vTargetPos, fTargetRad, iReason, fMaxCut); + } + public bool IsRooting() + { + var mask = (uint)(Logic_Influence_Extned_states.LIES_ROOT + | Logic_Influence_Extned_states.LIES_SLEEP + | Logic_Influence_Extned_states.LIES_STUN); + return (m_dwLIES & mask) != 0; + } + + bool IsInFortress() { return m_fortressEnter.role_in_war != 0; } + + bool IsPVPOpen() { return m_pvp.bEnable; } + // Get faction ID + int GetFactionID() { return m_idFaction; } + + public bool IsJumping() { return m_iJumpCount > 0; } + + public bool IsPlayingAction(int iAction) + { + if (iAction == (int)PLAYER_ACTION_TYPE.ACT_WALK && _playerStateMachine.State is PlayerMoveState) + { + return true; + } + if (iAction == (int)PLAYER_ACTION_TYPE.ACT_STAND && _playerStateMachine.State is PlayerIdleState) + { + return true; + } + return false; + } + + public void ResetJump() { m_iJumpCount = 0; m_bJumpInWater = false; } + // Get move speed + 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 { - pTarget = pElsePlayer; + UnityGameSession.c2s_CmdSelectTarget(idTarget); } } + return bRet; } - else if (GPDataTypeHelper.ISNPCID(idTarget)) + + bool CanSelectTarget(int idTarget) { - CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idTarget); - if (pNPC != null) + if (idTarget == 0 || idTarget == this.GetCharacterID()) { - if (CanSafelySelect(pNPC) && !pNPC.IsDead()) + // 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) { - pTarget = pNPC; + 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; } - 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) + float SafelySelectDistance() { - case ActionCanDo.CANDO_SITDOWN: + // ·þÎñÆ÷¶Ô SelectTarget ÓжîÍâ¾àÀëÏÞÖÆ£¬Èýά¾àÀë 150.0¡¢Ë®Æ½¾àÀë 125.0 ÒÔÉϵ쬶¼»áÎÞ·¨Ñ¡ÖÐ + // »ùÓÚÒÔÉÏÔ­Òò£¬¿Í»§¶ËÑ¡Ôñ¶ÔÏó¡¢»òÕß¶ÔÒѾ­Ñ¡ÔñµÄ¶ÔÏ󣬶¼È·±£ÆäÔÚ´ËÏÞÖÆ·¶Î§ÄÚ£¬¼´Ñ¡ÔñʱʹÓýÏС¾àÀë¼ì²â + return 100.0f; + } - if (IsDead() /*|| IsAboutToDie() */|| IsJumping() /*|| IsTrading() || IsUsingTrashBox()*/ || - IsRooting() || /*IsReviving() || IsTalkingWithNPC() || IsChangingFace() ||*/ - !m_GndInfo.bOnGround /*|| GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || + 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() || + 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; + bRet = false; - break; + break; - case ActionCanDo.CANDO_ASSISTSEL: + case ActionCanDo.CANDO_ASSISTSEL: - if (IsDead() || !GPDataTypeHelper.ISPLAYERID(m_idSelTarget) || m_idSelTarget == m_PlayerInfo.cid /*|| + 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; + bRet = false; - break; + break; - case ActionCanDo.CANDO_FLY: + case ActionCanDo.CANDO_FLY: - if (IsDead() || IsRooting() /*|| IsSitting() || IsTrading() || IsReviving() || + 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; + bRet = false; - break; + break; - case ActionCanDo.CANDO_PICKUP: - case ActionCanDo.CANDO_GATHER: + case ActionCanDo.CANDO_PICKUP: + case ActionCanDo.CANDO_GATHER: - if (IsDead() /*|| IsAboutToDie() || IsSitting() || IsTrading() || IsUsingTrashBox() || + if (IsDead() /*|| IsAboutToDie() || IsSitting() || IsTrading() || IsUsingTrashBox() || IsReviving() || IsTalkingWithNPC() || IsChangingFace() || GetBoothState() != 0 || GetBuddyState() == 1 || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()*/) - bRet = false; + bRet = false; - break; + break; - case ActionCanDo.CANDO_TRADE: + case ActionCanDo.CANDO_TRADE: - if (IsDead() /*|| IsAboutToDie() || IsSitting() */|| IsJumping() /*|| IsMeleeing() || + if (IsDead() /*|| IsAboutToDie() || IsSitting() */|| IsJumping() /*|| IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || IsSpellingMagic() || GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsInvisible() || IsPassiveMove()*/) - bRet = false; + bRet = false; - break; + break; - case ActionCanDo.CANDO_PLAYPOSE: + case ActionCanDo.CANDO_PLAYPOSE: - if (IsDead() /*|| IsAboutToDie() || IsSitting()*/ || IsJumping() ||/* IsMeleeing() || + 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; + bRet = false; - break; + 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; + //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; + // break; - case ActionCanDo.CANDO_SUMMONPET: + case ActionCanDo.CANDO_SUMMONPET: - if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) || /*IsAboutToDie() || IsSitting() ||*/ - IsJumping() || /*IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + 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; + bRet = false; - break; - case ActionCanDo.CANDO_REBUILDPET: + break; + case ActionCanDo.CANDO_REBUILDPET: - if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) /*|| IsAboutToDie() || IsSitting() */|| - IsJumping() /*|| IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + 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; + bRet = false; - break; + break; - //case ActionCanDo.CANDO_USEITEM: + //case ActionCanDo.CANDO_USEITEM: - // if (IsAboutToDie() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || - // IsChangingFace() || GetBoothState() != 0 || IsPassiveMove() || m_BattleInfo.IsChariotWar()) - // bRet = false; + // if (IsAboutToDie() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || GetBoothState() != 0 || IsPassiveMove() || m_BattleInfo.IsChariotWar()) + // bRet = false; - // break; + // 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; + //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_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: + // 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; + // 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; + // break; - //case ActionCanDo.CANDO_FLASHMOVE: + //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; + // 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; + // break; - //case ActionCanDo.CANDO_BINDBUDDY: + //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() || + // if (IsDead() || IsAboutToDie() || IsJumping() || IsSitting() || // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || // IsGathering() || IsRooting() || GetBoothState() != 0 || - // m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || - // GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove()) + // !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; } - return bRet; + public void SetSelectedTarget(int id) { m_idSelTarget = id; } + + //public float GetSwimSpeedSev() + //{ + // float fSpeedSev = GetSwimSpeed(); + // while (true) + // { + // if (!IsUnderWater()) break; + // //CECWorld* pWorld = g_pGame.GetGameRun().GetWorld(); + // //if (!pWorld) break; + + // const A3DVECTOR3 vPos = GetPos(); + // float fTerrainHeight = pWorld.GetTerrainHeight(vPos); + // float fWaterHeight = pWorld.GetWaterHeight(vPos); + // if (fWaterHeight <= fTerrainHeight) break; + + // float fBorderLine = fWaterHeight - 2.0f; + // if (vPos.y <= fBorderLine) break; + + // // ·þÎñÆ÷¶Ë½«Ë®ÃæÒÔÏÂ2Ã×ÒÔÉÏ´¦ÀíΪ run_speed£¨ÓÐÎÊÌ⣩ + // // µ«Î´Ê¹ÓüÓËÙ¼¼ÄÜʱ swim_speed СÓÚ run_speed£¬ + // // ¿ÉÒÔÔÚË®ÃæÒÔÏÂ2Ã×ÒÔÉÏ»ñÈ¡³¬¹ý swim_speed µÄËÙ¶È£¬Òò´Ë£¬´Ë´¦È¡Á½Õß½ÏСֵΪºÏÀí×ö·¨ + // fSpeedSev = min(m_ExtProps.mv.run_speed, fSpeedSev); + // break; + // } + // return fSpeedSev; + //} } - public void SetSelectedTarget(int id) { m_idSelTarget = id; } - - //public float GetSwimSpeedSev() - //{ - // float fSpeedSev = GetSwimSpeed(); - // while (true) - // { - // if (!IsUnderWater()) break; - // //CECWorld* pWorld = g_pGame.GetGameRun().GetWorld(); - // //if (!pWorld) break; - - // const A3DVECTOR3 vPos = GetPos(); - // float fTerrainHeight = pWorld.GetTerrainHeight(vPos); - // float fWaterHeight = pWorld.GetWaterHeight(vPos); - // if (fWaterHeight <= fTerrainHeight) break; - - // float fBorderLine = fWaterHeight - 2.0f; - // if (vPos.y <= fBorderLine) break; - - // // ·þÎñÆ÷¶Ë½«Ë®ÃæÒÔÏÂ2Ã×ÒÔÉÏ´¦ÀíΪ run_speed£¨ÓÐÎÊÌ⣩ - // // µ«Î´Ê¹ÓüÓËÙ¼¼ÄÜʱ swim_speed СÓÚ run_speed£¬ - // // ¿ÉÒÔÔÚË®ÃæÒÔÏÂ2Ã×ÒÔÉÏ»ñÈ¡³¬¹ý swim_speed µÄËÙ¶È£¬Òò´Ë£¬´Ë´¦È¡Á½Õß½ÏСֵΪºÏÀí×ö·¨ - // fSpeedSev = min(m_ExtProps.mv.run_speed, fSpeedSev); - // break; - // } - // return fSpeedSev; - //} -} - -public enum StateAnim -{ - Idle = 1, - Walk = 2, - Run = 3, - Jump = 4 -} - -// Mask of some special extend states which will influence host game logic. -// Logic Influence Extned states -[Flags] -public enum Logic_Influence_Extned_states -{ - LIES_SLEEP = 0x0001, - LIES_STUN = 0x0002, - LIES_ROOT = 0x0004, - LIES_NOFGIHT = 0x0008, - - LIES_DISABLEFIGHT = 0x000B, -} - -// ½øÈë»ùµØÐÅÏ¢ -public struct FACTION_FORTRESS_ENTER -{ - public int faction_id; - public int role_in_war; // 0 : ÖÐÁ¢»ò²»ÔÚ»ùµØ 1:¹¥·½ 2: ÊØ·½ - public int end_time; - - public FACTION_FORTRESS_ENTER(int faction_id, int role_in_war, int end_time) + public enum StateAnim { - this.faction_id = faction_id; - this.role_in_war = role_in_war; - this.end_time = end_time; + Idle = 1, + Walk = 2, + Run = 3, + Jump = 4 } -} -// PVP infomation -public struct PVPINFO -{ - public bool bEnable; // PVP switch - public uint dwCoolTime; - public uint dwMaxCoolTime; - public bool bFreePVP; // Free PVP flag, ignore bEnable flag - public bool bInPVPCombat; // true, in PVP combat - public int iDuelState; // Duel state - public int idDuelOpp; // Duel opponent - public int iDuelTimeCnt; // Duel time counter - public int iDuelRlt; // Duel result. 0, no defined; 1-win; 2-lose; 3-draw -}; + // Mask of some special extend states which will influence host game logic. + // Logic Influence Extned states + [Flags] + public enum Logic_Influence_Extned_states + { + LIES_SLEEP = 0x0001, + LIES_STUN = 0x0002, + LIES_ROOT = 0x0004, + LIES_NOFGIHT = 0x0008, -// Current ground information -public struct GNDINFO -{ - public float fGndHei; // Ground height - public float fWaterHei; // Water height - public A3DVECTOR3 vGndNormal; // Terrain normal - public bool bOnGround; // On ground flag -}; + LIES_DISABLEFIGHT = 0x000B, + } -// Behavior id used by CanDo() -public static class ActionCanDo + // ½øÈë»ùµØÐÅÏ¢ + public struct FACTION_FORTRESS_ENTER + { + public int faction_id; + public int role_in_war; // 0 : ÖÐÁ¢»ò²»ÔÚ»ùµØ 1:¹¥·½ 2: ÊØ·½ + public int end_time; + + public FACTION_FORTRESS_ENTER(int faction_id, int role_in_war, int end_time) + { + this.faction_id = faction_id; + this.role_in_war = role_in_war; + this.end_time = end_time; + } + } + + // PVP infomation + public struct PVPINFO + { + public bool bEnable; // PVP switch + public uint dwCoolTime; + public uint dwMaxCoolTime; + public bool bFreePVP; // Free PVP flag, ignore bEnable flag + public bool bInPVPCombat; // true, in PVP combat + public int iDuelState; // Duel state + public int idDuelOpp; // Duel opponent + public int iDuelTimeCnt; // Duel time counter + public int iDuelRlt; // Duel result. 0, no defined; 1-win; 2-lose; 3-draw + }; + + // Current ground information + public struct GNDINFO + { + public float fGndHei; // Ground height + public float fWaterHei; // Water height + public A3DVECTOR3 vGndNormal; // Terrain normal + public bool bOnGround; // On ground flag + }; + + // 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; + 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/CanvasController.cs b/Assets/Scripts/CanvasController.cs index ae5585106f..a63b381e24 100644 --- a/Assets/Scripts/CanvasController.cs +++ b/Assets/Scripts/CanvasController.cs @@ -1,47 +1,50 @@ using BrewMonster.UI; using CSNetwork.Protocols.RPCData; -using PerfectWorld.Scripts.Managers; +using BrewMonster.Scripts.Managers; using System.Collections.Generic; using System.Threading; using UnityEngine; -public class CanvasController : MonoBehaviour +namespace BrewMonster.Managers { - [SerializeField] private ScreenLogin screenLogin; - [SerializeField] private SelecScreenCharacter screenCharacter; - [SerializeField] private GameObject bgr; - [SerializeField] private GameController gameController; - - GameObject screenLoginOb; - GameObject screenCharacterOb; - private SynchronizationContext context; - - // Start is called once before the first execution of Update after the MonoBehaviour is created - void Start() + public class CanvasController : MonoBehaviour { - bgr.gameObject.SetActive(true); - screenLogin.gameObject.SetActive(true); - screenCharacter.gameObject.SetActive(false); - context = SynchronizationContext.Current; - } + [SerializeField] private ScreenLogin screenLogin; + [SerializeField] private SelecScreenCharacter screenCharacter; + [SerializeField] private GameObject bgr; + [SerializeField] private GameController gameController; - public void ShowScreenSelectCharacter(List roleInfos) - { - context.Post(_ => + GameObject screenLoginOb; + GameObject screenCharacterOb; + private SynchronizationContext context; + + // Start is called once before the first execution of Update after the MonoBehaviour is created + void Start() { - screenLogin.gameObject.SetActive(false); - screenCharacter.gameObject.SetActive(true); - screenCharacter.InitScreen(roleInfos, OnClickSelectChacter); - }, null); - } + bgr.gameObject.SetActive(true); + screenLogin.gameObject.SetActive(true); + screenCharacter.gameObject.SetActive(false); + context = SynchronizationContext.Current; + } - private void OnClickSelectChacter(RoleInfo roleInfo) - { - - } + public void ShowScreenSelectCharacter(List roleInfos) + { + context.Post(_ => + { + screenLogin.gameObject.SetActive(false); + screenCharacter.gameObject.SetActive(true); + screenCharacter.InitScreen(roleInfos, OnClickSelectChacter); + }, null); + } - private void OnDestroy() - { - + private void OnClickSelectChacter(RoleInfo roleInfo) + { + + } + + private void OnDestroy() + { + + } } } diff --git a/Assets/Scripts/EC_Utility.cs b/Assets/Scripts/EC_Utility.cs index d1ef9f4cfb..7813c25bc0 100644 --- a/Assets/Scripts/EC_Utility.cs +++ b/Assets/Scripts/EC_Utility.cs @@ -1,130 +1,131 @@ -using BrewMonster; -using CSNetwork.GPDataType; +using CSNetwork.GPDataType; using System; -using System.Collections; using System.Runtime.InteropServices; using UnityEngine; -using static EC_Player; +using static BrewMonster.Scripts.Player.EC_Player; -public static class EC_Utility +namespace BrewMonster.Scripts { - public static byte glb_CompressDirH(float x, float z) + public static class EC_Utility { - const float fInvInter = 256.0f / 360.0f; - - if (Math.Abs(x) < 0.00001f) + public static byte glb_CompressDirH(float x, float z) { - if (z > 0.0f) - return 64; + const float fInvInter = 256.0f / 360.0f; + + if (Math.Abs(x) < 0.00001f) + { + if (z > 0.0f) + return 64; + else + return 192; + } else - return 192; + { + // atan2 trong C# trả về radian, cần đổi sang độ + float fDeg = (float)(Math.Atan2(z, x) * (180.0 / Math.PI)); + + // đảm bảo góc nằm trong [0, 360) + if (fDeg < 0) + fDeg += 360.0f; + + return (byte)(fDeg * fInvInter); + } } - else + public static float FIX8TOFLOAT(int x) => x / 256.0f; + public static T ByteArrayToStructure(byte[] bytes) where T : struct { - // atan2 trong C# trả về radian, cần đổi sang độ - float fDeg = (float)(Math.Atan2(z, x) * (180.0 / Math.PI)); - - // đảm bảo góc nằm trong [0, 360) - if (fDeg < 0) - fDeg += 360.0f; - - return (byte)(fDeg * fInvInter); + GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); + try + { + return Marshal.PtrToStructure(handle.AddrOfPinnedObject()); + } + finally + { + handle.Free(); + } } - } - public static float FIX8TOFLOAT(int x) => x / 256.0f; - public static T ByteArrayToStructure(byte[] bytes) where T : struct - { - GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - try + public static Vector3 glb_DecompressDirH(byte byDir) { - return Marshal.PtrToStructure(handle.AddrOfPinnedObject()); + const float fInter = 360.0f / 256.0f; + float fRad = Mathf.Deg2Rad * (byDir * fInter); + + Vector3 v; + v.x = Mathf.Cos(fRad); + v.z = Mathf.Sin(fRad); + v.y = 0.0f; + + return v; } - finally + public static System.Numerics.Vector3 ToNumerics(this UnityEngine.Vector3 v) { - handle.Free(); + return new System.Numerics.Vector3(v.x, v.y, v.z); } - } - public static Vector3 glb_DecompressDirH(byte byDir) - { - const float fInter = 360.0f / 256.0f; - float fRad = Mathf.Deg2Rad * (byDir * fInter); - - Vector3 v; - v.x = Mathf.Cos(fRad); - v.z = Mathf.Sin(fRad); - v.y = 0.0f; - - return v; - } - public static System.Numerics.Vector3 ToNumerics(this UnityEngine.Vector3 v) - { - return new System.Numerics.Vector3(v.x, v.y, v.z); - } - public static A3DVECTOR3 ToA3DVECTOR3(this UnityEngine.Vector3 v) - { - return new A3DVECTOR3(v.x, v.y, v.z); - } - public static Vector3 ToVector3(A3DVECTOR3 a3DVECTOR3) - { - return new Vector3(a3DVECTOR3.x, a3DVECTOR3.y, a3DVECTOR3.z); - } - public static float MagnitudeH(this Vector3 v) - { - return Mathf.Sqrt(v.x * v.x + v.z * v.z); - } - public static string BuildActionName(PLAYER_ACTION action, int weaponType) - { - string prefix = action.data.ActionPrefix ?? string.Empty; - string suffix = string.Empty; - - if (action.data.action_weapon_suffix != null - && weaponType >= 0 - && weaponType < action.data.action_weapon_suffix.Length) + public static A3DVECTOR3 ToA3DVECTOR3(this UnityEngine.Vector3 v) { - suffix = action.data.action_weapon_suffix[weaponType].Suffix ?? string.Empty; + return new A3DVECTOR3(v.x, v.y, v.z); + } + public static Vector3 ToVector3(A3DVECTOR3 a3DVECTOR3) + { + return new Vector3(a3DVECTOR3.x, a3DVECTOR3.y, a3DVECTOR3.z); + } + public static float MagnitudeH(this Vector3 v) + { + return Mathf.Sqrt(v.x * v.x + v.z * v.z); + } + public static string BuildActionName(PLAYER_ACTION action, int weaponType) + { + string prefix = action.data.ActionPrefix ?? string.Empty; + string suffix = string.Empty; + + if (action.data.action_weapon_suffix != null + && weaponType >= 0 + && weaponType < action.data.action_weapon_suffix.Length) + { + suffix = action.data.action_weapon_suffix[weaponType].Suffix ?? string.Empty; + } + + return $"{prefix}_{suffix}"; } - return $"{prefix}_{suffix}"; - } + // Build pvp mask + public static byte glb_BuildPVPMask(bool bForceAttack) + { + byte byMask = 0; + if (bForceAttack) + byMask |= (byte)PVP_mask.GP_PVPMASK_FORCE; + //else + //{ + // CECConfigs* pConfigs = g_pGame->GetConfigs(); - // Build pvp mask - public static byte glb_BuildPVPMask(bool bForceAttack) - { - byte byMask = 0; - if (bForceAttack) - byMask |= (byte)PVP_mask.GP_PVPMASK_FORCE; - //else - //{ - // CECConfigs* pConfigs = g_pGame->GetConfigs(); + // if (pConfigs->GetGameSettings().bAtk_Player) + // { + // byMask |= GP_PVPMASK_FORCE; - // if (pConfigs->GetGameSettings().bAtk_Player) - // { - // byMask |= GP_PVPMASK_FORCE; + // if (pConfigs->GetGameSettings().bAtk_NoMafia) + // byMask |= GP_PVPMASK_NOMAFIA; - // if (pConfigs->GetGameSettings().bAtk_NoMafia) - // byMask |= GP_PVPMASK_NOMAFIA; + // if (pConfigs->GetGameSettings().bAtk_NoWhite) + // byMask |= GP_PVPMASK_NOWHITE; - // if (pConfigs->GetGameSettings().bAtk_NoWhite) - // byMask |= GP_PVPMASK_NOWHITE; + // if (pConfigs->GetGameSettings().bAtk_NoAlliance) + // byMask |= GP_PVPMASK_NOALLIANCE; - // if (pConfigs->GetGameSettings().bAtk_NoAlliance) - // byMask |= GP_PVPMASK_NOALLIANCE; + // if (pConfigs->GetGameSettings().bAtk_NoForce) + // byMask |= GP_PVPMASK_NOFORCE; + // } + //} - // if (pConfigs->GetGameSettings().bAtk_NoForce) - // byMask |= GP_PVPMASK_NOFORCE; - // } - //} + return byMask; + } - return byMask; - } + public static T a_ClampFloor(T x, T min) where T : IComparable + { + return (x.CompareTo(min) < 0) ? min : x; + } - public static T a_ClampFloor(T x, T min) where T : IComparable - { - return (x.CompareTo(min) < 0) ? min : x; - } - - public static T a_Min(T x, T y) where T : IComparable - { - return (y.CompareTo(x) < 0) ? y : x; + public static T a_Min(T x, T y) where T : IComparable + { + return (y.CompareTo(x) < 0) ? y : x; + } } } diff --git a/Assets/Scripts/GameController.cs b/Assets/Scripts/GameController.cs index bdd3c803f6..eac5e99ad2 100644 --- a/Assets/Scripts/GameController.cs +++ b/Assets/Scripts/GameController.cs @@ -1,89 +1,89 @@ +using BrewMonster.Scripts.Player; using CSNetwork.GPDataType; -using CSNetwork.Protocols.RPCData; -using System.Data; using Unity.Cinemachine; -using Unity.VisualScripting; using UnityEngine; -using UnityEngine.UIElements; -public class GameController : MonoBehaviour +namespace BrewMonster.Managers { - private static GameController instance; - - [SerializeField] private CECHostPlayer characterPrefab; - [SerializeField] private CECMonster monsterPrefab; - [SerializeField] private CinemachineCamera cinemachineCamera; - //[SerializeField] private Transform ground; - CECHostPlayer hostPlayer; - - public static GameController Instance + public class GameController : MonoBehaviour { - get + private static GameController instance; + + [SerializeField] private CECHostPlayer characterPrefab; + [SerializeField] private CECMonster monsterPrefab; + [SerializeField] private CinemachineCamera cinemachineCamera; + //[SerializeField] private Transform ground; + CECHostPlayer hostPlayer; + + public static GameController Instance + { + get + { + if (instance == null) + { + instance = FindAnyObjectByType(); + } + return instance; + } + } + private void Awake() { if (instance == null) { - instance = FindAnyObjectByType(); + instance = this; } - return instance; } - } - private void Awake() - { - if (instance == null) - { - instance = this; - } - } - public void Log(string s) - { - Debug.LogError(s); - } - public CECHostPlayer GetHostPlayer() - { - if (hostPlayer == null) + public void Log(string s) { - hostPlayer = FindAnyObjectByType(); + Debug.LogError(s); } - return hostPlayer; - } - public void InitCharacter(cmd_self_info_1 info) - { - if (characterPrefab == null) + public CECHostPlayer GetHostPlayer() { - Debug.LogError("null prefab"); - return; + if (hostPlayer == null) + { + hostPlayer = FindAnyObjectByType(); + } + return hostPlayer; } - EC_Player.InitStaticRes(); - hostPlayer = Instantiate(characterPrefab, transform); - hostPlayer.InitCharacter(info); - cinemachineCamera.Follow = hostPlayer.transform; - cinemachineCamera.ForceCameraPosition(hostPlayer.transform.position, Quaternion.identity); - //Vector3 pos = new Vector3(info.pos.x, info.pos.y, info.pos.z); - //Vector3 posCam = pos; - //posCam.z -= 10f; - //camera.transform.position = posCam; - //Vector3 posGround = pos; - //posGround.y -= 2f; - //ground.transform.position = posGround; - } - public CECMonster GetMonster() - { - return Instantiate(monsterPrefab, transform); - } - public GameObject InitCharacter(info_player_1 info) - { - if (characterPrefab == null) + public void InitCharacter(cmd_self_info_1 info) { - Debug.LogError("null prefab"); - return null; + if (characterPrefab == null) + { + Debug.LogError("null prefab"); + return; + } + EC_Player.InitStaticRes(); + hostPlayer = Instantiate(characterPrefab, transform); + hostPlayer.InitCharacter(info); + cinemachineCamera.Follow = hostPlayer.transform; + cinemachineCamera.ForceCameraPosition(hostPlayer.transform.position, Quaternion.identity); + //Vector3 pos = new Vector3(info.pos.x, info.pos.y, info.pos.z); + //Vector3 posCam = pos; + //posCam.z -= 10f; + //camera.transform.position = posCam; + //Vector3 posGround = pos; + //posGround.y -= 2f; + //ground.transform.position = posGround; + } + public CECMonster GetMonster() + { + return Instantiate(monsterPrefab, transform); + } + public GameObject InitCharacter(info_player_1 info) + { + if (characterPrefab == null) + { + Debug.LogError("null prefab"); + return null; + } + CECHostPlayer character = Instantiate(characterPrefab, transform); + character.InitCharacter(info); + return character.gameObject; + } + private void OnDestroy() + { + instance = null; } - CECHostPlayer character = Instantiate(characterPrefab, transform); - character.InitCharacter(info); - return character.gameObject; - } - private void OnDestroy() - { - instance = null; } } diff --git a/Assets/Scripts/InitializePlayer.cs b/Assets/Scripts/InitializePlayer.cs index 74f9de84a2..2aa133df85 100644 --- a/Assets/Scripts/InitializePlayer.cs +++ b/Assets/Scripts/InitializePlayer.cs @@ -1,15 +1,18 @@ using BrewMonster; using UnityEngine; -public class InitializePlayer /*: IAutoInitialize*/ +namespace BrewMonster.Scripts.Player { - public void Dispose() + public class InitializePlayer /*: IAutoInitialize*/ { - EC_Player.Dispose(); - } + public void Dispose() + { + EC_Player.Dispose(); + } - public void Initialize() - { - EC_Player.InitStaticRes(); + public void Initialize() + { + EC_Player.InitStaticRes(); + } } } diff --git a/Assets/Scripts/MainFiles/EC_Game.cs b/Assets/Scripts/MainFiles/EC_Game.cs index 615f715b06..c4477637c2 100644 --- a/Assets/Scripts/MainFiles/EC_Game.cs +++ b/Assets/Scripts/MainFiles/EC_Game.cs @@ -1,5 +1,5 @@ using ModelRenderer.Scripts.GameData; -using PerfectWorld.Scripts.Task; +using BrewMonster.Scripts.Task; using UnityEngine; namespace BrewMonster.Network { diff --git a/Assets/Scripts/Move/CECHostMove.cs b/Assets/Scripts/Move/CECHostMove.cs index dd3115dc98..7ced0c3cbd 100644 --- a/Assets/Scripts/Move/CECHostMove.cs +++ b/Assets/Scripts/Move/CECHostMove.cs @@ -1,4 +1,5 @@ using BrewMonster.Network; +using BrewMonster.Scripts.Player; using CSNetwork; using CSNetwork.C2SCommand; using CSNetwork.GPDataType; @@ -10,360 +11,363 @@ using System.Security.Cryptography; using System.Text; using UnityEngine; -public class CECHostMove +namespace BrewMonster.Scripts { - ushort m_wMoveStamp; - float m_fMoveTime; - CECHostPlayer m_pHost; - bool m_bStop; - const float MOVECMD_INTERVAL = .5f; - Vector3 m_vLastSevPos; - STOPMOVE m_DelayedStop; - ulong cmdstopdelayCounter = 500; - ulong cmdmovedelayCounter = 500; - ulong m_dwLastTime; - Vector3 m_vLastPos; - float m_fAverSpeedH; - int m_iBlockedCnt; // Move blocked counter - bool m_bSlideLock; // Locked when slide - float m_fBlockTime; // Block time counter - float m_fBlockMove; // Block move counter - A3DVECTOR3 m_vBlockMove; - bool m_bLocalMove; // true, Moving info isn't sent to server - - public CECHostMove(CECHostPlayer pHost) + public class CECHostMove { - m_wMoveStamp = 0; - m_fMoveTime = 0.0f; - m_pHost = pHost; - m_bStop = false; - } + ushort m_wMoveStamp; + float m_fMoveTime; + CECHostPlayer m_pHost; + bool m_bStop; + const float MOVECMD_INTERVAL = .5f; + Vector3 m_vLastSevPos; + STOPMOVE m_DelayedStop; + ulong cmdstopdelayCounter = 500; + ulong cmdmovedelayCounter = 500; + ulong m_dwLastTime; + Vector3 m_vLastPos; + float m_fAverSpeedH; + int m_iBlockedCnt; // Move blocked counter + bool m_bSlideLock; // Locked when slide + float m_fBlockTime; // Block time counter + float m_fBlockMove; // Block move counter + A3DVECTOR3 m_vBlockMove; + bool m_bLocalMove; // true, Moving info isn't sent to server - public void Tick(ulong dwDeltaTime) - { - cmdstopdelayCounter += dwDeltaTime; - cmdmovedelayCounter += dwDeltaTime; - if (cmdstopdelayCounter >= 500 && m_DelayedStop.bValid) + public CECHostMove(CECHostPlayer pHost) { - var m = m_DelayedStop; - - // a_GetTime() . Environment.TickCount (ms) - ulong dwCurrent = (ulong)Mathf.RoundToInt(Time.time * 1000); - - // iTime: thời gian tích lũy (ms) + delta từ timestamp đến hiện tại - int iTime = (int)((m.fTime * 1000f) - + ((dwCurrent > m.dwTimeStamp) ? (dwCurrent - m.dwTimeStamp) : 0)); - - // tính tốc độ trung bình (giây = iTime * 0.001f) - float fSpeed = l_CalcAverageSpeed(m_vLastSevPos, m.vPos, iTime * 0.001f, m.fSpeed); - - int iMoveMode = m.iMoveMode; - - // make a potential check with tuojigua - iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD; - - UnityGameSession.Instance.c2s_SendCmdStopMove( - m.vPos, fSpeed, iMoveMode, m.byDir, m_wMoveStamp++, iTime - ); - - // Record this position - m_vLastSevPos = m.vPos; - - Reset(); - } - - m_dwLastTime = Math.Max(m_dwLastTime, 1); - Vector3 vOffset = m_pHost.transform.position - m_vLastPos; - m_fAverSpeedH = EC_Utility.MagnitudeH(vOffset) * 1000.0f / m_dwLastTime; - m_vLastPos = m_pHost.transform.position; - m_dwLastTime = dwDeltaTime; - } - - public void SendStopMoveCmd() - { - int iMoveMode = (int)GPMoveMode.GP_MOVE_RUN; - float fSpeed = 0f; - switch (m_pHost.GetMoveEnv()) - { - case EC_Player.Move_environment.MOVEENV_AIR: - - iMoveMode |= (int)GPMoveMode.GP_MOVE_AIR; - fSpeed = m_pHost.GetFlySpeed(); - break; - - //case EC_Player.Move_environment.MOVEENV_WATER: - - // iMoveMode |= (int)GPMoveMode.GP_MOVE_WATER; - // fSpeed = m_pHost.GetSwimSpeedSev(); - // break; - - default: - - fSpeed = m_pHost.GetGroundSpeed(); - break; - } - SendStopMoveCmd(EC_Utility.ToVector3(m_pHost.GetPos()), fSpeed, iMoveMode); - } - - public void SendStopMoveCmd(in Vector3 vPos, float fSpeed, int iMoveMode) - { - Debug.LogWarning("HoangDev : SendStopMoveCmd"); - iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD; - - if (cmdstopdelayCounter == 500) - { - Vector3 vDir = m_pHost.transform.forward; - byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z); - fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vPos, m_fMoveTime, fSpeed); - int iTime = (int)(m_fMoveTime * 1000); - - UnityGameSession.Instance.c2s_SendCmdStopMove(vPos, fSpeed, iMoveMode, byDir, m_wMoveStamp++, iTime); - - m_vLastSevPos = vPos; - Reset(); - } - else - { - Vector3 vDir = m_pHost.transform.forward; - byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z); - - if (!m_DelayedStop.bValid) - { - m_DelayedStop.dwTimeStamp = (ulong)Mathf.RoundToInt(Time.time * 1000); - m_DelayedStop.fTime = m_fMoveTime; - } - - m_DelayedStop.bValid = true; - m_DelayedStop.byDir = byDir; - m_DelayedStop.vPos = vPos; - m_DelayedStop.iMoveMode = iMoveMode; - m_DelayedStop.fSpeed = fSpeed; - } - m_fMoveTime = 0.0f; - } - public void SendMoveCmd(in Vector3 vCurPos, in Vector3 vVel, int iMoveMode, bool bForceSend = false) - { - Vector3 vMoveDir = vVel; - float fSpeed = vMoveDir.magnitude; - SendMoveCmd(vCurPos, fSpeed, iMoveMode, bForceSend); - } - - public void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, A3DVECTOR3 vVel, int iMoveMode, bool bForceSend = false) - { - - A3DVECTOR3 vMoveDir = vVel; - float fSpeed = vMoveDir.Normalize(); - SendMoveCmd(vCurPos, iDestType, vDest, vMoveDir, fSpeed, iMoveMode, bForceSend); - } - - void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, - A3DVECTOR3 vMoveDir, float fSpeed, int iMoveMode, bool bForceSend) - - { - Vector3 pos = new Vector3(vCurPos.x, vCurPos.y, vCurPos.z); - SendMoveCmd(pos, fSpeed, iMoveMode, bForceSend); - } - - void SendMoveCmd(in Vector3 vCurPos, - float fSpeed, int iMoveMode, bool bForceSend) - { - - if (m_bStop) - { - // m_CmdTimeCnt.Reset(); - cmdmovedelayCounter = (ulong)(m_fMoveTime * 1000); + m_wMoveStamp = 0; + m_fMoveTime = 0.0f; + m_pHost = pHost; m_bStop = false; } - if (!bForceSend && cmdmovedelayCounter < 500) - return; - int iTime = (int)(m_fMoveTime * 1000); - - if (iTime < 200) + public void Tick(ulong dwDeltaTime) { - if (iTime == 0 || !bForceSend) + cmdstopdelayCounter += dwDeltaTime; + cmdmovedelayCounter += dwDeltaTime; + if (cmdstopdelayCounter >= 500 && m_DelayedStop.bValid) { - // if time is too little, wait again - cmdmovedelayCounter = (ulong)(iTime); + var m = m_DelayedStop; + + // a_GetTime() . Environment.TickCount (ms) + ulong dwCurrent = (ulong)Mathf.RoundToInt(Time.time * 1000); + + // iTime: thời gian tích lũy (ms) + delta từ timestamp đến hiện tại + int iTime = (int)((m.fTime * 1000f) + + ((dwCurrent > m.dwTimeStamp) ? (dwCurrent - m.dwTimeStamp) : 0)); + + // tính tốc độ trung bình (giây = iTime * 0.001f) + float fSpeed = l_CalcAverageSpeed(m_vLastSevPos, m.vPos, iTime * 0.001f, m.fSpeed); + + int iMoveMode = m.iMoveMode; + + // make a potential check with tuojigua + iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD; + + UnityGameSession.Instance.c2s_SendCmdStopMove( + m.vPos, fSpeed, iMoveMode, m.byDir, m_wMoveStamp++, iTime + ); + + // Record this position + m_vLastSevPos = m.vPos; + + Reset(); + } + + m_dwLastTime = Math.Max(m_dwLastTime, 1); + Vector3 vOffset = m_pHost.transform.position - m_vLastPos; + m_fAverSpeedH = EC_Utility.MagnitudeH(vOffset) * 1000.0f / m_dwLastTime; + m_vLastPos = m_pHost.transform.position; + m_dwLastTime = dwDeltaTime; + } + + public void SendStopMoveCmd() + { + int iMoveMode = (int)GPMoveMode.GP_MOVE_RUN; + float fSpeed = 0f; + switch (m_pHost.GetMoveEnv()) + { + case EC_Player.Move_environment.MOVEENV_AIR: + + iMoveMode |= (int)GPMoveMode.GP_MOVE_AIR; + fSpeed = m_pHost.GetFlySpeed(); + break; + + //case EC_Player.Move_environment.MOVEENV_WATER: + + // iMoveMode |= (int)GPMoveMode.GP_MOVE_WATER; + // fSpeed = m_pHost.GetSwimSpeedSev(); + // break; + + default: + + fSpeed = m_pHost.GetGroundSpeed(); + break; + } + SendStopMoveCmd(EC_Utility.ToVector3(m_pHost.GetPos()), fSpeed, iMoveMode); + } + + public void SendStopMoveCmd(in Vector3 vPos, float fSpeed, int iMoveMode) + { + Debug.LogWarning("HoangDev : SendStopMoveCmd"); + iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD; + + if (cmdstopdelayCounter == 500) + { + Vector3 vDir = m_pHost.transform.forward; + byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z); + fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vPos, m_fMoveTime, fSpeed); + int iTime = (int)(m_fMoveTime * 1000); + + UnityGameSession.Instance.c2s_SendCmdStopMove(vPos, fSpeed, iMoveMode, byDir, m_wMoveStamp++, iTime); + + m_vLastSevPos = vPos; + Reset(); + } + else + { + Vector3 vDir = m_pHost.transform.forward; + byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z); + + if (!m_DelayedStop.bValid) + { + m_DelayedStop.dwTimeStamp = (ulong)Mathf.RoundToInt(Time.time * 1000); + m_DelayedStop.fTime = m_fMoveTime; + } + + m_DelayedStop.bValid = true; + m_DelayedStop.byDir = byDir; + m_DelayedStop.vPos = vPos; + m_DelayedStop.iMoveMode = iMoveMode; + m_DelayedStop.fSpeed = fSpeed; + } + m_fMoveTime = 0.0f; + } + public void SendMoveCmd(in Vector3 vCurPos, in Vector3 vVel, int iMoveMode, bool bForceSend = false) + { + Vector3 vMoveDir = vVel; + float fSpeed = vMoveDir.magnitude; + SendMoveCmd(vCurPos, fSpeed, iMoveMode, bForceSend); + } + + public void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, A3DVECTOR3 vVel, int iMoveMode, bool bForceSend = false) + { + + A3DVECTOR3 vMoveDir = vVel; + float fSpeed = vMoveDir.Normalize(); + SendMoveCmd(vCurPos, iDestType, vDest, vMoveDir, fSpeed, iMoveMode, bForceSend); + } + + void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, + A3DVECTOR3 vMoveDir, float fSpeed, int iMoveMode, bool bForceSend) + + { + Vector3 pos = new Vector3(vCurPos.x, vCurPos.y, vCurPos.z); + SendMoveCmd(pos, fSpeed, iMoveMode, bForceSend); + } + + void SendMoveCmd(in Vector3 vCurPos, + float fSpeed, int iMoveMode, bool bForceSend) + { + + if (m_bStop) + { + // m_CmdTimeCnt.Reset(); + cmdmovedelayCounter = (ulong)(m_fMoveTime * 1000); + m_bStop = false; + } + if (!bForceSend && cmdmovedelayCounter < 500) return; - } - } - cmdmovedelayCounter = 0; - m_DelayedStop.bValid = false; + int iTime = (int)(m_fMoveTime * 1000); - fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vCurPos, m_fMoveTime, fSpeed); - m_fMoveTime = 0.0f; - - iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD; - UnityGameSession.Instance.c2s_CmdPlayerMove(vCurPos, vCurPos, iTime/* MOVECMD_INTERVAL */, fSpeed, iMoveMode, m_wMoveStamp++); - - m_vLastSevPos = vCurPos; - } - - float l_CalcAverageSpeed(in Vector3 p1, in Vector3 p2, float fTime, float fDefSpeed) - { - if (Mathf.Approximately(fTime, 0f)) - return fDefSpeed; - - Vector3 d = p2 - p1; - float fSpeed = d.magnitude / fTime; - - if (fTime < 0.05f || fSpeed > 50.0f) - { - // tương đương ASSERT(0) trong C++, ở đây có thể Debug.LogWarning - Debug.LogWarning("CalcAverageSpeed: invalid input, fallback to default speed."); - return fDefSpeed; - } - - return fSpeed; - } - private void Reset() - { - cmdstopdelayCounter = 0; - m_bStop = true; - m_DelayedStop.bValid = false; - } - - public void GroundMove(float ftime) - { - m_fMoveTime += ftime; - } - - struct STOPMOVE - { - public bool bValid; // Valid flag - public Vector3 vPos; - public float fSpeed; - public int iMoveMode; - public byte byDir; - public ulong dwTimeStamp; - public float fTime; - }; - - // Check whether host meet a slope - // vMoveDirH: normalized horizontal moving direction - // fMaxSpeed (out): maximum vertical speed - public bool MeetSlope(A3DVECTOR3 vMoveDirH, float fMaxSpeedV) - { - A3DVECTOR3 vTangent = m_pHost.m_GndInfo.vGndNormal; - - float d = vTangent.MagnitudeH(); - float tan = d / (float)Math.Abs(vTangent.y); - float max = m_pHost.GetGroundSpeed() * tan * 0.96f; - // Prevent max is too small, tan60 = 1.732 - EC_Utility.a_ClampFloor(max, m_pHost.GetGroundSpeed() * 1.732f); - fMaxSpeedV = EC_Utility.a_Min(max, 19.5f); - - // fMaxSpeedV = 100.0f; - - vTangent.y = 0.0f; - vTangent.Normalize(); - - if (A3DVECTOR3.DotProduct(vMoveDirH, vTangent) <= -0.85f) - return true; - - return false; - } - - public A3DVECTOR3 GroundMove(A3DVECTOR3 vDirH, float fSpeedH, float fTime, float fSpeedV = 0f, float fGravity = 9.8f) - { - A3DVECTOR3 vRealDirH = vDirH; - - if (Math.Abs(vRealDirH.y) > 0.0001) - { - vRealDirH.y = 0.0f; - vRealDirH.Normalize(); - } - - // OnGroundMove only accept positive speed value - if (fSpeedH < 0.0f) - { - vRealDirH = -vDirH; - fSpeedH = -fSpeedH; - } - - //int idInst = g_pGame.GetGameRun().GetWorld().GetInstanceID(); - //CECInstance pInstance = g_pGame.GetGameRun().GetInstance(idInst); - //if (pInstance.GetLimitJump()) - //fGravity *= 4.0f; - - CDR_INFO cdr = m_pHost.m_CDRInfo; - var pos = m_pHost.m_aabbServer.Center; - cdr.vCenter = new Vector3(pos.x, pos.y, pos.z); - cdr.vXOZVelDir = new Vector3(vRealDirH.x, vRealDirH.y, vRealDirH.z); - cdr.fSpeed = fSpeedH; - cdr.t = fTime; - cdr.fGravityAccel = fGravity; - cdr.fYVel += fSpeedV; - - EC_CDR.OnGroundMove(ref cdr); - - //if (g_pGame.GetGameRun().GetWorld().GetAssureMove()) - // g_pGame.GetGameRun().GetWorld().GetAssureMove().AssureMove(m_pHost.m_aabbServer.Center, cdr.vCenter); - - if (cdr.vTPNormal != Vector3.zero) - m_pHost.SetGroundNormal(new A3DVECTOR3(cdr.vTPNormal.x, cdr.vTPNormal.y, cdr.vTPNormal.z)); - else - m_pHost.SetGroundNormal(GPDataTypeHelper.g_vAxisY); - - A3DVECTOR3 vNewPos = new A3DVECTOR3(cdr.vCenter.x, cdr.vCenter.y, cdr.vCenter.z) - GPDataTypeHelper.g_vAxisY * m_pHost.m_aabbServer.Extents.y; - - m_iBlockedCnt = 0; - m_fBlockMove += (vNewPos - m_pHost.GetPos()).Magnitude(); - m_vBlockMove += vNewPos - m_pHost.GetPos(); - if ((m_fBlockTime += fTime) >= 1.0f) - { - if (m_fBlockMove < GPDataTypeHelper.MIN_MOVELEN_ON_GROUND || m_vBlockMove.Magnitude() < GPDataTypeHelper.MIN_MOVELEN_FOR_DETECT_VIBRATION) + if (iTime < 200) { - m_iBlockedCnt = 5; + if (iTime == 0 || !bForceSend) + { + // if time is too little, wait again + cmdmovedelayCounter = (ulong)(iTime); + return; + } } - m_fBlockTime = 0.0f; - m_fBlockMove = 0.0f; - m_vBlockMove.Clear(); + cmdmovedelayCounter = 0; + m_DelayedStop.bValid = false; + + fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vCurPos, m_fMoveTime, fSpeed); + m_fMoveTime = 0.0f; + + iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD; + UnityGameSession.Instance.c2s_CmdPlayerMove(vCurPos, vCurPos, iTime/* MOVECMD_INTERVAL */, fSpeed, iMoveMode, m_wMoveStamp++); + + m_vLastSevPos = vCurPos; } - m_fMoveTime += fTime; + float l_CalcAverageSpeed(in Vector3 p1, in Vector3 p2, float fTime, float fDefSpeed) + { + if (Mathf.Approximately(fTime, 0f)) + return fDefSpeed; - return vNewPos; + Vector3 d = p2 - p1; + float fSpeed = d.magnitude / fTime; + + if (fTime < 0.05f || fSpeed > 50.0f) + { + // tương đương ASSERT(0) trong C++, ở đây có thể Debug.LogWarning + Debug.LogWarning("CalcAverageSpeed: invalid input, fallback to default speed."); + return fDefSpeed; + } + + return fSpeed; + } + private void Reset() + { + cmdstopdelayCounter = 0; + m_bStop = true; + m_DelayedStop.bValid = false; + } + + public void GroundMove(float ftime) + { + m_fMoveTime += ftime; + } + + struct STOPMOVE + { + public bool bValid; // Valid flag + public Vector3 vPos; + public float fSpeed; + public int iMoveMode; + public byte byDir; + public ulong dwTimeStamp; + public float fTime; + }; + + // Check whether host meet a slope + // vMoveDirH: normalized horizontal moving direction + // fMaxSpeed (out): maximum vertical speed + public bool MeetSlope(A3DVECTOR3 vMoveDirH, float fMaxSpeedV) + { + A3DVECTOR3 vTangent = m_pHost.m_GndInfo.vGndNormal; + + float d = vTangent.MagnitudeH(); + float tan = d / (float)Math.Abs(vTangent.y); + float max = m_pHost.GetGroundSpeed() * tan * 0.96f; + // Prevent max is too small, tan60 = 1.732 + EC_Utility.a_ClampFloor(max, m_pHost.GetGroundSpeed() * 1.732f); + fMaxSpeedV = EC_Utility.a_Min(max, 19.5f); + + // fMaxSpeedV = 100.0f; + + vTangent.y = 0.0f; + vTangent.Normalize(); + + if (A3DVECTOR3.DotProduct(vMoveDirH, vTangent) <= -0.85f) + return true; + + return false; + } + + public A3DVECTOR3 GroundMove(A3DVECTOR3 vDirH, float fSpeedH, float fTime, float fSpeedV = 0f, float fGravity = 9.8f) + { + A3DVECTOR3 vRealDirH = vDirH; + + if (Math.Abs(vRealDirH.y) > 0.0001) + { + vRealDirH.y = 0.0f; + vRealDirH.Normalize(); + } + + // OnGroundMove only accept positive speed value + if (fSpeedH < 0.0f) + { + vRealDirH = -vDirH; + fSpeedH = -fSpeedH; + } + + //int idInst = g_pGame.GetGameRun().GetWorld().GetInstanceID(); + //CECInstance pInstance = g_pGame.GetGameRun().GetInstance(idInst); + //if (pInstance.GetLimitJump()) + //fGravity *= 4.0f; + + CDR_INFO cdr = m_pHost.m_CDRInfo; + var pos = m_pHost.m_aabbServer.Center; + cdr.vCenter = new Vector3(pos.x, pos.y, pos.z); + cdr.vXOZVelDir = new Vector3(vRealDirH.x, vRealDirH.y, vRealDirH.z); + cdr.fSpeed = fSpeedH; + cdr.t = fTime; + cdr.fGravityAccel = fGravity; + cdr.fYVel += fSpeedV; + + EC_CDR.OnGroundMove(ref cdr); + + //if (g_pGame.GetGameRun().GetWorld().GetAssureMove()) + // g_pGame.GetGameRun().GetWorld().GetAssureMove().AssureMove(m_pHost.m_aabbServer.Center, cdr.vCenter); + + if (cdr.vTPNormal != Vector3.zero) + m_pHost.SetGroundNormal(new A3DVECTOR3(cdr.vTPNormal.x, cdr.vTPNormal.y, cdr.vTPNormal.z)); + else + m_pHost.SetGroundNormal(GPDataTypeHelper.g_vAxisY); + + A3DVECTOR3 vNewPos = new A3DVECTOR3(cdr.vCenter.x, cdr.vCenter.y, cdr.vCenter.z) - GPDataTypeHelper.g_vAxisY * m_pHost.m_aabbServer.Extents.y; + + m_iBlockedCnt = 0; + m_fBlockMove += (vNewPos - m_pHost.GetPos()).Magnitude(); + m_vBlockMove += vNewPos - m_pHost.GetPos(); + if ((m_fBlockTime += fTime) >= 1.0f) + { + if (m_fBlockMove < GPDataTypeHelper.MIN_MOVELEN_ON_GROUND || m_vBlockMove.Magnitude() < GPDataTypeHelper.MIN_MOVELEN_FOR_DETECT_VIBRATION) + { + m_iBlockedCnt = 5; + } + + m_fBlockTime = 0.0f; + m_fBlockMove = 0.0f; + m_vBlockMove.Clear(); + } + + m_fMoveTime += fTime; + + return vNewPos; + } + + public int MoveBlocked() { return m_iBlockedCnt; } + public void SetSlideLock(bool bLock) { m_bSlideLock = bLock; } + // Is stoping ? + public bool IsStop() { return m_bStop; } } + public struct CDR_INFO + { + //the aabb + public Vector3 vCenter; + //@note : the caller should make sure ext(.x, .y, .z) > 0. By Kuiwu[22/9/2005] + public Vector3 vExtent; - public int MoveBlocked() { return m_iBlockedCnt; } - public void SetSlideLock(bool bLock) { m_bSlideLock = bLock; } - // Is stoping ? - public bool IsStop() { return m_bStop; } + public float fStepHeight; + + // Velocity Info + public Vector3 vXOZVelDir; + public float fYVel; + public float fSpeed; + + // time span ( sec ) + public float t; + + // Gravity acceleration + public float fGravityAccel; + + // the Climb Slope Thresh + public float fSlopeThresh; + + // Tangent plane Info + public Vector3 vTPNormal; + + // Absolute Velocity: output for forcast! + public Vector3 vAbsVelocity; + + + //the moving dist + public float fMoveDist; + }; } -public struct CDR_INFO -{ - //the aabb - public Vector3 vCenter; - //@note : the caller should make sure ext(.x, .y, .z) > 0. By Kuiwu[22/9/2005] - public Vector3 vExtent; - - public float fStepHeight; - - // Velocity Info - public Vector3 vXOZVelDir; - public float fYVel; - public float fSpeed; - - // time span ( sec ) - public float t; - - // Gravity acceleration - public float fGravityAccel; - - // the Climb Slope Thresh - public float fSlopeThresh; - - // Tangent plane Info - public Vector3 vTPNormal; - - // Absolute Velocity: output for forcast! - public Vector3 vAbsVelocity; - - - //the moving dist - public float fMoveDist; -}; diff --git a/Assets/Scripts/Move/EC_CDR.cs b/Assets/Scripts/Move/EC_CDR.cs index e6e29eb985..4b7b0506ca 100644 --- a/Assets/Scripts/Move/EC_CDR.cs +++ b/Assets/Scripts/Move/EC_CDR.cs @@ -1,251 +1,440 @@ using CSNetwork.GPDataType; -using System; -using TMPro; -using Unity.VisualScripting; +using UnityEditor.PackageManager; using UnityEngine; -public static class EC_CDR + +namespace BrewMonster.Scripts { - // Cho phép CECHostMove gán mask theo scene (giữ linh hoạt nhưng không phá cấu trúc) - public static LayerMask BrushMask { get; set; } = ~0; - public static LayerMask TerrainMask { get; set; } = ~0; - - static LayerMask UsedMask_Ground() => BrushMask | TerrainMask; - - // == Thay CollideWithEnv (C++) bằng BoxCast == - static bool CollideWithEnv_BoxCast(Vector3 vStart, Vector3 vDelta, Vector3 vExt, - LayerMask mask, - out RaycastHit hit, out float fFraction, out Vector3 vHitNormal, out bool bStartSolid, - float skin = 0.01f) + public static class EC_CDR { - hit = default; - vHitNormal = Vector3.up; - bStartSolid = false; - fFraction = 1.0f; + // Cho phép CECHostMove gán mask theo scene (giữ linh hoạt nhưng không phá cấu trúc) + public static LayerMask BrushMask { get; set; } = ~0; + public static LayerMask TerrainMask { get; set; } = ~0; - float dist = vDelta.magnitude; - if (dist <= 1e-6f) return false; - - // start-in-solid - var overlapped = Physics.OverlapBox(vStart, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); - if (overlapped != null && overlapped.Length > 0) + //[Flags] + public class CDR_EVN { - bStartSolid = true; - return true; + public const int CDR_BRUSH = 0x1, + CDR_TERRAIN = 0x2, + CDR_WATER = 0x4; } - // sweep AABB - Vector3 dir = vDelta / Mathf.Max(dist, 1e-6f); - if (Physics.BoxCast(vStart, vExt - Vector3.one * skin, dir, out hit, Quaternion.identity, dist, mask, QueryTriggerInteraction.Ignore)) + static LayerMask UsedMask_Ground() => BrushMask | TerrainMask; + + static bool CollideWithEnv(env_trace_t pEnvTrc) { - fFraction = Mathf.Clamp01(hit.distance / Mathf.Max(dist, 1e-6f)); - vHitNormal = hit.normal; - return true; - } - return false; - } - - // == Thay RetrieveSupportPlane (C++) bằng Raycast xuống == - static bool DoGroundProbe(Vector3 vStart, Vector3 vExt, float fDeltaY, LayerMask mask, - out Vector3 vEnd, out Vector3 vHitNormal, out bool bSupport, - float skin = 0.01f) - { - vEnd = vStart; - vHitNormal = Vector3.up; - bSupport = false; - - float dist = Mathf.Max(fDeltaY, 0f) + vExt.y + skin + 0.05f; - Vector3 origin = vStart + Vector3.up * 0.05f; - - if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, dist, mask, QueryTriggerInteraction.Ignore)) - { - vHitNormal = hit.normal; - vEnd = new Vector3(vStart.x, hit.point.y + vExt.y + skin, vStart.z); - bSupport = (vHitNormal.y >= 0f); - return true; - } - return true; // không thấy ground → bSupport=false - } - - // ======= STATIC OnGroundMove – GIỮ NGUYÊN VAI TRÒ TOÀN CỤC (C API) ======= - public static void OnGroundMove(ref CDR_INFO CDRInfo) - { - const float VEL_EPSILON = 1e-4f; - const float DIST_EPSILON = 1e-4f; - const float NORMAL_EPSILON = 1e-2f; - const float VEL_MAX_SPEED = 200f; - const float VEL_REFLECT = 0.3f; - - CDRInfo.fMoveDist = 0.0f; - - bool bFreeFall = (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh); - if (Mathf.Abs(CDRInfo.fYVel) < VEL_EPSILON && Mathf.Abs(CDRInfo.fSpeed) < VEL_EPSILON && !bFreeFall) - return; - - float fYVel = CDRInfo.fYVel; - bool bJump = (fYVel > 0.5f); - - Vector3 vVelocity = CDRInfo.fSpeed * new Vector3(CDRInfo.vXOZVelDir.x, 0f, CDRInfo.vXOZVelDir.z) + fYVel * Vector3.up; - if (bFreeFall) - { - vVelocity += -CDRInfo.fGravityAccel * CDRInfo.t * Vector3.up; - fYVel += -CDRInfo.fGravityAccel * CDRInfo.t; - } - - Vector3 vVelDir = vVelocity; - float fVelSpeed = vVelDir.magnitude; - if (fVelSpeed > 1e-6f) vVelDir /= fVelSpeed; else vVelDir = Vector3.zero; - if (!bFreeFall) fVelSpeed = Mathf.Min(fVelSpeed, VEL_MAX_SPEED); - vVelocity = vVelDir * fVelSpeed; - - float dtp = Vector3.Dot(vVelDir, CDRInfo.vTPNormal); - if (dtp < 0f || !bJump) - { - vVelocity = (vVelDir - CDRInfo.vTPNormal * dtp - CDRInfo.vTPNormal * dtp * 0.01f) * fVelSpeed; - } - - CDRInfo.vAbsVelocity = vVelocity; - - Vector3 vStart = CDRInfo.vCenter; - Vector3 vExt = CDRInfo.vExtent; - float fTime = CDRInfo.t; - - Vector3 vDelta, vNormal = Vector3.up, vFinalPos = vStart; - bool bPull = false; - bool bTryPull = false; - - int nTry = 0; - LayerMask mask = UsedMask_Ground(); - - while (nTry < 4) - { - vDelta = vVelocity * fTime; - float fDeltaDist = vDelta.magnitude; - if (fDeltaDist < DIST_EPSILON) break; - - bool hasHit = CollideWithEnv_BoxCast(vStart, vDelta, vExt, mask, - out RaycastHit hit, out float fFraction, out Vector3 hitNormal, out bool bStartSolid); - - nTry++; - - if (bStartSolid) + pEnvTrc.fFraction = 100.0f; + pEnvTrc.bStartSolid = false; + pEnvTrc.dwClsFlag = 0; + if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_BRUSH) == CDR_EVN.CDR_BRUSH) { - CDRInfo.fMoveDist = 0f; - if (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh) CDRInfo.vTPNormal = Vector3.up; + BrushTraceInfo bruInfo = new BrushTraceInfo(); + bruInfo.Init(pEnvTrc.vStart, pEnvTrc.vDelta, pEnvTrc.vExt); + if (AABBCollideWithBrush(ref bruInfo)) + { + pEnvTrc.fFraction = bruInfo.fFraction; + pEnvTrc.vHitNormal = bruInfo.ClipPlane.GetNormal(); + pEnvTrc.bStartSolid = bruInfo.bStartSolid; + pEnvTrc.dwClsFlag = CDR_EVN.CDR_BRUSH; + } + } + if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_TERRAIN) == CDR_EVN.CDR_TERRAIN) + { + float fFraction = 0f; + A3DVECTOR3 vTerNormal = new A3DVECTOR3(); + bool bStart = false; + if (CollideWithTerrain(pEnvTrc.vTerStart, pEnvTrc.vDelta, ref fFraction, ref vTerNormal, ref bStart) + && (fFraction < pEnvTrc.fFraction)) + { + //assert(fFraction >= 0.0f); + //pEnvTrc.fFraction = a_Max(0.0f, fFraction - 1E-4f); + pEnvTrc.fFraction = fFraction; + pEnvTrc.vHitNormal = vTerNormal; + pEnvTrc.bStartSolid = bStart; + pEnvTrc.dwClsFlag = CDR_EVN.CDR_TERRAIN; + } + + } + + if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_WATER) == CDR_EVN.CDR_WATER) + { + float fFraction = 0f; + A3DVECTOR3 vWatNormal = new A3DVECTOR3(); + bool bStart = false; + //@todo : TBD: use center or foot? By Kuiwu[10/10/2005] + if (CollideWithWater(pEnvTrc.vWatStart, pEnvTrc.vDelta, pEnvTrc.bWaterSolid, ref fFraction, ref vWatNormal, ref bStart) + && fFraction < pEnvTrc.fFraction) + { + pEnvTrc.fFraction = fFraction; + pEnvTrc.vHitNormal = vWatNormal; + pEnvTrc.bStartSolid = bStart; + pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER; + //# ifdef CDR_DEBUG + // A3DVECTOR3 vHitPos(pEnvTrc.vWatStart +pEnvTrc.vDelta * fFraction); + // sprintf(msg, "collide water, fraction %f pos %f %f %f \n", fFraction, vHitPos.x, vHitPos.y, vHitPos.z); + // OUTPUT_DEBUG_INFO(msg); + //#endif + + } + } + + return (pEnvTrc.fFraction < 1.0f + 1E-4f); + } + + // == Thay CollideWithEnv (C++) bằng BoxCast == + static bool CollideWithEnv_BoxCast(Vector3 vStart, Vector3 vDelta, Vector3 vExt, + LayerMask mask, + out RaycastHit hit, out float fFraction, out Vector3 vHitNormal, out bool bStartSolid, + float skin = 0.01f) + { + hit = default; + vHitNormal = Vector3.up; + bStartSolid = false; + fFraction = 1.0f; + + float dist = vDelta.magnitude; + if (dist <= 1e-6f) return false; + + // start-in-solid + var overlapped = Physics.OverlapBox(vStart, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); + if (overlapped != null && overlapped.Length > 0) + { + bStartSolid = true; + return true; + } + + // sweep AABB + Vector3 dir = vDelta / Mathf.Max(dist, 1e-6f); + if (Physics.BoxCast(vStart, vExt - Vector3.one * skin, dir, out hit, Quaternion.identity, dist, mask, QueryTriggerInteraction.Ignore)) + { + fFraction = Mathf.Clamp01(hit.distance / Mathf.Max(dist, 1e-6f)); + vHitNormal = hit.normal; + return true; + } + return false; + } + + // == Thay RetrieveSupportPlane (C++) bằng Raycast xuống == + static bool DoGroundProbe(Vector3 vStart, Vector3 vExt, float fDeltaY, LayerMask mask, + out Vector3 vEnd, out Vector3 vHitNormal, out bool bSupport, + float skin = 0.01f) + { + vEnd = vStart; + vHitNormal = Vector3.up; + bSupport = false; + + float dist = Mathf.Max(fDeltaY, 0f) + vExt.y + skin + 0.05f; + Vector3 origin = vStart + Vector3.up * 0.05f; + + if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, dist, mask, QueryTriggerInteraction.Ignore)) + { + vHitNormal = hit.normal; + vEnd = new Vector3(vStart.x, hit.point.y + vExt.y + skin, vStart.z); + bSupport = (vHitNormal.y >= 0f); + return true; + } + return true; // không thấy ground → bSupport=false + } + + // ======= STATIC OnGroundMove – GIỮ NGUYÊN VAI TRÒ TOÀN CỤC (C API) ======= + public static void OnGroundMove(ref CDR_INFO CDRInfo) + { + const float VEL_EPSILON = 1e-4f; + const float DIST_EPSILON = 1e-4f; + const float NORMAL_EPSILON = 1e-2f; + const float VEL_MAX_SPEED = 200f; + const float VEL_REFLECT = 0.3f; + + CDRInfo.fMoveDist = 0.0f; + + bool bFreeFall = (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh); + if (Mathf.Abs(CDRInfo.fYVel) < VEL_EPSILON && Mathf.Abs(CDRInfo.fSpeed) < VEL_EPSILON && !bFreeFall) return; + + float fYVel = CDRInfo.fYVel; + bool bJump = (fYVel > 0.5f); + + Vector3 vVelocity = CDRInfo.fSpeed * new Vector3(CDRInfo.vXOZVelDir.x, 0f, CDRInfo.vXOZVelDir.z) + fYVel * Vector3.up; + if (bFreeFall) + { + vVelocity += -CDRInfo.fGravityAccel * CDRInfo.t * Vector3.up; + fYVel += -CDRInfo.fGravityAccel * CDRInfo.t; } - if (!hasHit) + Vector3 vVelDir = vVelocity; + float fVelSpeed = vVelDir.magnitude; + if (fVelSpeed > 1e-6f) vVelDir /= fVelSpeed; else vVelDir = Vector3.zero; + if (!bFreeFall) fVelSpeed = Mathf.Min(fVelSpeed, VEL_MAX_SPEED); + vVelocity = vVelDir * fVelSpeed; + + float dtp = Vector3.Dot(vVelDir, CDRInfo.vTPNormal); + if (dtp < 0f || !bJump) { - vFinalPos = vStart + vDelta; - CDRInfo.fMoveDist += fDeltaDist; - break; + vVelocity = (vVelDir - CDRInfo.vTPNormal * dtp - CDRInfo.vTPNormal * dtp * 0.01f) * fVelSpeed; } - vStart += vDelta * fFraction; - CDRInfo.fMoveDist += (fDeltaDist * fFraction); - fTime -= fTime * fFraction; - vNormal = hitNormal; + CDRInfo.vAbsVelocity = vVelocity; - // Step-up (giữ tinh thần bản gốc) - if (!bFreeFall && !bTryPull && !bJump) + Vector3 vStart = CDRInfo.vCenter; + Vector3 vExt = CDRInfo.vExtent; + float fTime = CDRInfo.t; + + Vector3 vDelta, vNormal = Vector3.up, vFinalPos = vStart; + bool bPull = false; + bool bTryPull = false; + + int nTry = 0; + LayerMask mask = UsedMask_Ground(); + + while (nTry < 4) { - float skin = 0.01f; - Vector3 vStartUp = vStart + new Vector3(0f, CDRInfo.fStepHeight, 0f); - bool upBlocked = Physics.CheckBox(vStartUp, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); - if (!upBlocked) + vDelta = vVelocity * fTime; + float fDeltaDist = vDelta.magnitude; + if (fDeltaDist < DIST_EPSILON) break; + + // TO DO: fix later beacuse logic in CollideWithEnv_BoxCast is wrong + //bool hasHit = CollideWithEnv_BoxCast(vStart, vDelta, vExt, mask, + // out RaycastHit hit, out float fFraction, out Vector3 hitNormal, out bool bStartSolid); + bool hasHit = false, bStartSolid = false; + float fFraction = 0f; + Vector3 hitNormal = Vector3.zero; + nTry++; + + if (bStartSolid) { - Vector3 vDelta2 = vVelocity; - bool hasHit2 = CollideWithEnv_BoxCast(vStartUp, vDelta2, vExt, mask, - out RaycastHit hit2, out float frac2, out Vector3 hitNormal2, out bool bStartSolid2); - if (hasHit2) vDelta2 *= frac2; + CDRInfo.fMoveDist = 0f; + if (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh) CDRInfo.vTPNormal = Vector3.up; + return; + } - if (vDelta2.sqrMagnitude >= (vExt.x * vExt.x * 4f)) + if (!hasHit) + { + vFinalPos = vStart + vDelta; + CDRInfo.fMoveDist += fDeltaDist; + break; + } + + vStart += vDelta * fFraction; + CDRInfo.fMoveDist += (fDeltaDist * fFraction); + fTime -= fTime * fFraction; + vNormal = hitNormal; + + // Step-up (giữ tinh thần bản gốc) + if (!bFreeFall && !bTryPull && !bJump) + { + float skin = 0.01f; + Vector3 vStartUp = vStart + new Vector3(0f, CDRInfo.fStepHeight, 0f); + bool upBlocked = Physics.CheckBox(vStartUp, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); + if (!upBlocked) { - vStart = vStartUp; - vDelta = vDelta2; + Vector3 vDelta2 = vVelocity; + bool hasHit2 = CollideWithEnv_BoxCast(vStartUp, vDelta2, vExt, mask, + out RaycastHit hit2, out float frac2, out Vector3 hitNormal2, out bool bStartSolid2); + if (hasHit2) vDelta2 *= frac2; - float distAll = vVelocity.magnitude; - float distMoved = vDelta.magnitude; - if (distAll > 1e-6f) fTime *= Mathf.Clamp01(distMoved / Mathf.Max(distAll, 1e-6f)); + if (vDelta2.sqrMagnitude >= (vExt.x * vExt.x * 4f)) + { + vStart = vStartUp; + vDelta = vDelta2; - bPull = true; + float distAll = vVelocity.magnitude; + float distMoved = vDelta.magnitude; + if (distAll > 1e-6f) fTime *= Mathf.Clamp01(distMoved / Mathf.Max(distAll, 1e-6f)); + + bPull = true; + } + } + bTryPull = true; + } + + if (!bPull) + { + if (vVelocity.sqrMagnitude > 1e-12f) + { + vVelDir = vVelocity.normalized; + fVelSpeed = vVelocity.magnitude * (1f - nTry * 0.1f); + + dtp = Vector3.Dot(vNormal, vVelDir); + float fRelSpeed = Mathf.Min(fVelSpeed, 5.0f); + + if (dtp >= 0f && dtp < 1e-4f) + { + vVelocity += vNormal * VEL_REFLECT * fRelSpeed; + } + else + { + vVelocity = (vVelDir - vNormal * dtp) * fVelSpeed - vNormal * dtp * VEL_REFLECT * fRelSpeed; + } + } + + if (fYVel > VEL_EPSILON) + { + if (vNormal.y >= CDRInfo.fSlopeThresh || vNormal.y < -NORMAL_EPSILON) fYVel = 0f; + } + else if (fYVel < -VEL_EPSILON) + { + if (vNormal.y >= CDRInfo.fSlopeThresh) fYVel = 0f; } } - bTryPull = true; } - if (!bPull) + // “vertical ground trace” – thay RetrieveSupportPlane + Vector3 vTPNormal = Vector3.zero; + Vector3 vFinal = vFinalPos; + + float downDist = 0.3f; + if (bPull) downDist = CDRInfo.fStepHeight + 0.1f; + if (bJump) downDist = 0.0f; + + if (downDist > 0f) { - if (vVelocity.sqrMagnitude > 1e-12f) + if (!DoGroundProbe(vFinalPos, vExt, downDist, mask, out Vector3 vEnd, out Vector3 groundNormal, out bool bSupport)) { - vVelDir = vVelocity.normalized; - fVelSpeed = vVelocity.magnitude * (1f - nTry * 0.1f); - - dtp = Vector3.Dot(vNormal, vVelDir); - float fRelSpeed = Mathf.Min(fVelSpeed, 5.0f); - - if (dtp >= 0f && dtp < 1e-4f) - { - vVelocity += vNormal * VEL_REFLECT * fRelSpeed; - } - else - { - vVelocity = (vVelDir - vNormal * dtp) * fVelSpeed - vNormal * dtp * VEL_REFLECT * fRelSpeed; - } + CDRInfo.fMoveDist = 0f; + CDRInfo.vTPNormal = Vector3.up; + return; } - if (fYVel > VEL_EPSILON) + if (bSupport) { - if (vNormal.y >= CDRInfo.fSlopeThresh || vNormal.y < -NORMAL_EPSILON) fYVel = 0f; - } - else if (fYVel < -VEL_EPSILON) - { - if (vNormal.y >= CDRInfo.fSlopeThresh) fYVel = 0f; + vFinal = vEnd; + if (!bJump) vTPNormal = groundNormal; } } + + if ((vTPNormal.y >= CDRInfo.fSlopeThresh && fYVel < 0.0f) || (!bJump && fYVel > 0.0f)) + fYVel = 0.0f; + + CDRInfo.vCenter = vFinal; + CDRInfo.fYVel = fYVel; + if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal; } - // “vertical ground trace” – thay RetrieveSupportPlane - Vector3 vTPNormal = Vector3.zero; - Vector3 vFinal = vFinalPos; + bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart) +{ - float downDist = 0.3f; - if (bPull) downDist = CDRInfo.fStepHeight + 0.1f; - if (bJump) downDist = 0.0f; + CECWorld pWorld = g_pGame.GetGameRun().GetWorld(); + A3DTerrain2 pTerrain = pWorld.GetTerrain(); + bStart = false; + float h1 = pTerrain.GetPosHeight(vStart, &vHitNormal); + if (h1 > vStart.y + 1E-4f ) + {//start under terrain + bStart = true; + fFraction = 0.0f; + return true; + } - if (downDist > 0f) - { - if (!DoGroundProbe(vFinalPos, vExt, downDist, mask, out Vector3 vEnd, out Vector3 groundNormal, out bool bSupport)) - { - CDRInfo.fMoveDist = 0f; - CDRInfo.vTPNormal = Vector3.up; - return; - } - if (bSupport) - { - vFinal = vEnd; - if (!bJump) vTPNormal = groundNormal; - } - } + int nWid, nHei; // in grid, 2 meters + float fMag = vDelta.Magnitude(); - if ((vTPNormal.y >= CDRInfo.fSlopeThresh && fYVel < 0.0f) || (!bJump && fYVel > 0.0f)) - fYVel = 0.0f; + nWid = (int) ceil(fMag / 2.0f); + nWid = a_Max(3, nWid); + nHei = nWid; + int nTriangles = nWid * nHei * 2; + A3DVECTOR3* pVerts = (A3DVECTOR3*)a_malloctemp(sizeof(A3DVECTOR3) * ((nWid + 1) * (nHei + 1))); + assert(pVerts != NULL); + memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1)); + WORD* pIndices = (WORD*)a_malloctemp(sizeof(WORD) * (nTriangles * 3)); + assert(pIndices != NULL); + memset(pIndices, 0, sizeof(WORD)* nTriangles * 3); + if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, pVerts, pIndices)) + { + a_freetemp(pVerts); + a_freetemp(pIndices); + return false; + } +int i; +A3DVECTOR3* vert[3]; +//@note : Here init the fraction. By Kuiwu[9/10/2005] +fFraction = 100.0f; +float tmpFraction = fFraction; - CDRInfo.vCenter = vFinal; - CDRInfo.fYVel = fYVel; - if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal; - } +for (i = 0; i < nTriangles; i++) +{ + vert[0] = pVerts + pIndices[i * 3]; + vert[1] = pVerts + pIndices[i * 3 + 1]; + vert[2] = pVerts + pIndices[i * 3 + 2]; + A3DVECTOR3 vPt; + + //@note: Tomas Moller's JGT code : By Kuiwu[9/10/2005] + //@note: discard the engine version because it put back the hit point too much. By Kuiwu[13/10/2005] + // if(CLS_RayToTriangle(vStart, vDelta, *vert[0], *vert[1], *vert[2], vPt, true, &tmpFraction) + // && (tmpFraction <= 1.0f) && (tmpFraction < fFraction)) + if (SegmentTriangleIntersect(vStart, vDelta, vert, tmpFraction, true) && (tmpFraction < fFraction)) + { + //get the triangle normal + A3DVECTOR3 vEdge1((* vert[1]) -(*vert[0]) ); +A3DVECTOR3 vEdge2((* vert[2]) -(*vert[0]) ); +vHitNormal = CrossProduct(vEdge1, vEdge2); +vHitNormal.Normalize(); + +//@note : may be redundant, but to assure. By Kuiwu[17/10/2005] +A3DVECTOR3 vDir; +Normalize(vDelta, vDir); +if (DotProduct(vHitNormal, vDir) > 0.01f) +{//leave the hit plane + assert(0 && "hit a plane with same direction!"); + continue; +} + +fFraction = a_Max(0.0f, tmpFraction); + } + + } + a_freetemp(pVerts); +a_freetemp(pIndices); + +# ifdef CDR_DEBUG +// if (fFraction <= 1.0f) +// { +// A3DVECTOR3 vHitPos(vStart + vDelta * fFraction); +// A3DVECTOR3 vTerNormal; +// float fH2 = pTerrain.GetPosHeight(vHitPos, &vTerNormal); +// sprintf(msg, "terrain hit %f %f %f normal %f %f %f trcNormal %f %f %f fFraction %f\n", vHitPos.x, vHitPos.y, vHitPos.z, +// vHitNormal.x, vHitNormal.y, vHitNormal.z, vTerNormal.x, vTerNormal.y, vTerNormal.z, fFraction); +// OUTPUT_DEBUG_INFO(msg); +// +// //vHitNormal = vTerNormal; +// } +// else +// { +// A3DVECTOR3 vEnd(vStart + vDelta); +// float fH2 = pTerrain.GetPosHeight(vEnd); +// sprintf(msg, "terrain test clear %f %f %f height %f\n", vEnd.x, vEnd.y, vEnd.z,fH2); +// OUTPUT_DEBUG_INFO(msg); +// } +#endif +return (fFraction <= 1.0f); + +} + } + public struct OtherPlayer_Move_Info + { + // Bounding sphere of avator + public A3DVECTOR3 vCenter; + public A3DVECTOR3 vExts; + public float fStepHeight; + public A3DVECTOR3 vVelocity; + public float t; + public bool bTraceGround; // Whether trace the ground + public bool bTestTrnOnly; // Trace terrain only + public A3DVECTOR3 vecGroundNormal; // if bTraceGround is true, this will contain the ground normal when returned + }; + + //@desc :used to trace the environment, brush&terrain&water By Kuiwu[8/10/2005] + public struct env_trace_t + { + public A3DVECTOR3 vStart; // brush start + public A3DVECTOR3 vExt; + public A3DVECTOR3 vDelta; + public A3DVECTOR3 vTerStart; + public A3DVECTOR3 vWatStart; + public uint dwCheckFlag; + public bool bWaterSolid; + + public float fFraction; + public A3DVECTOR3 vHitNormal; + public bool bStartSolid; //start in solid + public uint dwClsFlag; //collision flag + }; } -public struct OtherPlayer_Move_Info -{ - // Bounding sphere of avator - public A3DVECTOR3 vCenter; - public A3DVECTOR3 vExts; - public float fStepHeight; - public A3DVECTOR3 vVelocity; - public float t; - public bool bTraceGround; // Whether trace the ground - public bool bTestTrnOnly; // Trace terrain only - public A3DVECTOR3 vecGroundNormal; // if bTraceGround is true, this will contain the ground normal when returned -}; \ No newline at end of file diff --git a/Assets/Scripts/Move/EC_Player.cs b/Assets/Scripts/Move/EC_Player.cs index 9ace0ed5ea..2c2485dcee 100644 --- a/Assets/Scripts/Move/EC_Player.cs +++ b/Assets/Scripts/Move/EC_Player.cs @@ -1,38 +1,38 @@ -using BrewMonster; -using CSNetwork.GPDataType; +using CSNetwork.GPDataType; using ModelRenderer.Scripts.GameData; -using PerfectWorld.Scripts.Player; using System; using System.Collections.Generic; using UnityEngine; -public abstract class EC_Player : CECObject +namespace BrewMonster.Scripts.Player { - private static PLAYER_ACTION[] _default_actions; - private static PLAYER_ACTION[] _turning_actions; - PLAYER_ACTION[] m_PlayerActions; - [SerializeField] internal INFO m_PlayerInfo; - protected GameObject m_pPlayerModel; - protected float rotationSpeed = 5; - internal int m_iMoveMode; // Player's move mode - internal int m_idSelTarget; // Ñ¡ÖÐÄ¿±êµÄID - uint m_dwStates; // Player's basic states - protected ROLEEXTPROP m_ExtProps; // Extend properties - protected float m_fTouchRad = 0.3f; // Touch radius - protected int m_iBattleCamp = Player_camp_in_battle.GP_BATTLE_CAMP_NONE; // Battle this player belongs to - byte m_factionPVPMask; // pvp mask - protected ROLEBASICPROP m_BasicProps; - public int m_iMoveEnv = Move_environment.MOVEENV_GROUND; // Move environment - public bool m_bWalkRun; - 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 abstract class EC_Player : CECObject + { + private static PLAYER_ACTION[] _default_actions; + private static PLAYER_ACTION[] _turning_actions; + PLAYER_ACTION[] m_PlayerActions; + [SerializeField] internal INFO m_PlayerInfo; + protected GameObject m_pPlayerModel; + protected float rotationSpeed = 5; + internal int m_iMoveMode; // Player's move mode + internal int m_idSelTarget; // Ñ¡ÖÐÄ¿±êµÄID + uint m_dwStates; // Player's basic states + protected ROLEEXTPROP m_ExtProps; // Extend properties + protected float m_fTouchRad = 0.3f; // Touch radius + protected int m_iBattleCamp = Player_camp_in_battle.GP_BATTLE_CAMP_NONE; // Battle this player belongs to + byte m_factionPVPMask; // pvp mask + protected ROLEBASICPROP m_BasicProps; + public int m_iMoveEnv = Move_environment.MOVEENV_GROUND; // Move environment + public bool m_bWalkRun; + 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] - { + 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), @@ -70,10 +70,10 @@ public abstract class EC_Player : CECObject // ÔÂÏÉ 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] - { + 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), // ·¨Ê¦ @@ -98,404 +98,404 @@ public abstract class EC_Player : CECObject 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; - } - public void SetPlayerInfor(INFO playinfo) - { - m_PlayerInfo = playinfo; - } - public INFO GetPlayInfo() - { - 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(); - } - - public bool IsDead(){ return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; } - - public bool IsValidAction(int iIndex) { return (iIndex >= 0 && iIndex < (int)PLAYER_ACTION_TYPE.ACT_MAX) ? true : false; } - private static void BuildActionList() - { - if (_default_actions == null) + protected void Awake() { - // thay cho hashtab trong C++ - Dictionary actionMap = - new Dictionary(100); + m_PlayerActions = _default_actions; + } + public void SetPlayerInfor(INFO playinfo) + { + m_PlayerInfo = playinfo; + } + public INFO GetPlayInfo() + { + return m_PlayerInfo; + } - Dictionary skillActionMap = - new Dictionary(100); + public void CalcPlayerAABB() + { + int iIndex = m_iProfession * GENDER.NUM_GENDER + m_iGender; - elementdataman dataman = ElementDataManProvider.GetElementDataMan(); - PLAYER_ACTION_INFO_CONFIG data; + m_aabb.Extents = aExts[iIndex] * m_fScaleBySkill; + m_aabbServer.Extents = aExts[iIndex]; + m_MoveConst = aMoveConsts[iIndex]; + } - int count = dataman.get_data_num(ID_SPACE.ID_SPACE_CONFIG); + public static void InitStaticRes() + { + BuildActionList(); + } - DATA_TYPE dt = default; - uint id = 0; + public bool IsDead() { return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; } - for (int i = 0; i < count; ++i) + public bool IsValidAction(int iIndex) { return (iIndex >= 0 && iIndex < (int)PLAYER_ACTION_TYPE.ACT_MAX) ? true : false; } + private static void BuildActionList() + { + if (_default_actions == null) { - id = dataman.get_data_id(ID_SPACE.ID_SPACE_CONFIG, i, ref dt); - if (dt != DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG) - continue; + // thay cho hashtab trong C++ + Dictionary actionMap = + new Dictionary(100); - data = (PLAYER_ACTION_INFO_CONFIG)dataman.get_data_ptr(id, ID_SPACE.ID_SPACE_CONFIG, ref dt); - if (!string.IsNullOrEmpty(data.ActionName) && data.ActionName[0] != '0') + Dictionary skillActionMap = + new Dictionary(100); + + elementdataman dataman = ElementDataManProvider.GetElementDataMan(); + PLAYER_ACTION_INFO_CONFIG data; + + int count = dataman.get_data_num(ID_SPACE.ID_SPACE_CONFIG); + + DATA_TYPE dt = default; + uint id = 0; + + for (int i = 0; i < count; ++i) { - if (!actionMap.TryAdd(data.ActionName, data)) - { + id = dataman.get_data_id(ID_SPACE.ID_SPACE_CONFIG, i, ref dt); + if (dt != DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG) + continue; + data = (PLAYER_ACTION_INFO_CONFIG)dataman.get_data_ptr(id, ID_SPACE.ID_SPACE_CONFIG, ref dt); + if (!string.IsNullOrEmpty(data.ActionName) && data.ActionName[0] != '0') + { + if (!actionMap.TryAdd(data.ActionName, data)) + { + + } } } - } - CECStringTab actionNames = new CECStringTab(); - actionNames.Init("actions_player", false); + CECStringTab actionNames = new CECStringTab(); + actionNames.Init("actions_player", false); - _default_actions = new PLAYER_ACTION[(int)PLAYER_ACTION_TYPE.ACT_MAX]; + _default_actions = new PLAYER_ACTION[(int)PLAYER_ACTION_TYPE.ACT_MAX]; - for (int i = 0; i < _default_actions.Length; i++) - { - _default_actions[i].type = (PLAYER_ACTION_TYPE)i; - - string szName = actionNames.GetANSIString(i); - - if (!string.IsNullOrEmpty(szName)) + for (int i = 0; i < _default_actions.Length; i++) { - if (actionMap.TryGetValue(szName, out var it)) + _default_actions[i].type = (PLAYER_ACTION_TYPE)i; + + string szName = actionNames.GetANSIString(i); + + if (!string.IsNullOrEmpty(szName)) { - _default_actions[i].data = it; + if (actionMap.TryGetValue(szName, out var it)) + { + _default_actions[i].data = it; + } } } } } - } - public bool PlayAction(int iAction, bool bRestart/* true */, int iTransTime/* 200 */, bool bQueue/* false */) - { - return PlayActionWithConfig(iAction, 0, bRestart, iTransTime, bQueue); - } - public bool PlayActionWithConfig(int iAction, int actionConfigID, bool bRestart/* =true */, int iTransTime/* =200 */, bool bQueue/* =false */) - { - if (iAction < 0 || iAction >= (int)PLAYER_ACTION_TYPE.ACT_MAX) + public bool PlayAction(int iAction, bool bRestart/* true */, int iTransTime/* 200 */, bool bQueue/* false */) { - return false; + return PlayActionWithConfig(iAction, 0, bRestart, iTransTime, bQueue); } - if (actionConfigID > 0) + public bool PlayActionWithConfig(int iAction, int actionConfigID, bool bRestart/* =true */, int iTransTime/* =200 */, bool bQueue/* =false */) { - DATA_TYPE dt = DATA_TYPE.DT_INVALID; - var p = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)actionConfigID, ID_SPACE.ID_SPACE_CONFIG, ref dt); - if (dt == DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG) + if (iAction < 0 || iAction >= (int)PLAYER_ACTION_TYPE.ACT_MAX) { - PLAYER_ACTION actionConfig; - actionConfig.type = (PLAYER_ACTION_TYPE)iAction; - actionConfig.data = (PLAYER_ACTION_INFO_CONFIG)p; - return PlayActionWithConfig(iAction, actionConfig, bRestart, iTransTime, bQueue); + return false; + } + if (actionConfigID > 0) + { + DATA_TYPE dt = DATA_TYPE.DT_INVALID; + var p = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)actionConfigID, ID_SPACE.ID_SPACE_CONFIG, ref dt); + if (dt == DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG) + { + PLAYER_ACTION actionConfig; + actionConfig.type = (PLAYER_ACTION_TYPE)iAction; + actionConfig.data = (PLAYER_ACTION_INFO_CONFIG)p; + return PlayActionWithConfig(iAction, actionConfig, bRestart, iTransTime, bQueue); + } + else + { + + } + } + return PlayActionWithConfig(iAction, m_PlayerActions[iAction], bRestart, iTransTime, bQueue); + } + public bool PlayActionWithConfig(int iAction, in PLAYER_ACTION actionConfig, + bool bRestart = true, int iTransTime = 200, bool bQueue = false) + { + PLAYER_ACTION action = actionConfig; + + var szAct = EC_Utility.BuildActionName(action, 0); + EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szAct)); + return true; + } + public static void Dispose() + { + _default_actions = null; + _turning_actions = null; + } + public struct PLAYER_ACTION + { + public PLAYER_ACTION_TYPE type; + public PLAYER_ACTION_INFO_CONFIG data; + }; + public enum PLAYER_ACTION_TYPE + { + // 0 + ACT_STAND = 0, // Đứng + ACT_FIGHTSTAND, // Đứng chiến đấu + ACT_WALK, // Đi bộ + ACT_RUN, // Chạy + ACT_JUMP_START, // Bắt đầu nhảy + + // 5 + ACT_JUMP_LOOP, // Nhảy trên không lặp lại + ACT_JUMP_LAND, // Nhảy tiếp đất + ACT_SWIM, // Bơi + ACT_HANGINWATER, // Lơ lửng trong nước + ACT_TAKEOFF, // Cất cánh (should be ACT_TAKEOFF_WING) + + // 10 + ACT_HANGINAIR, // Treo trên không (should be ACT_HANGINAIR_WING) + ACT_FLY, // Bay (should be ACT_FLY_WING) + ACT_FLYDOWN, // Bay xuống cao (should be ACT_FLYDOWN_WING_HIGH) + ACT_FLYDOWN_WING_LOW, // Bay xuống thấp (should be ACT_FLYDOWN_WING_LOW) + ACT_LANDON, // Hạ cánh (should be ACT_LAND_WING) + + // 15 + ACT_TAKEOFF_SWORD, // Kiếm bay - cất cánh + ACT_HANGINAIR_SWORD, // Kiếm bay - treo không trung + ACT_FLY_SWORD, // Kiếm bay - tiến tới + ACT_FLYDOWN_SWORD_HIGH, // Kiếm bay - rơi cao + ACT_FLYDOWN_SWORD_LOW, // Kiếm bay - rơi thấp + + // 20 + ACT_LANDON_SWORD, // Kiếm bay - hạ cánh + ACT_SITDOWN, // Ngồi + ACT_SITDOWN_LOOP, // Ngồi lặp lại + ACT_STANDUP, // Đứng dậy + ACT_WOUNDED, // Bị thương + + // 25 + ACT_GROUNDDIE, // Chết trên mặt đất + ACT_GROUNDDIE_LOOP, // Chết trên đất (loop) + ACT_WATERDIE, // Chết trong nước + ACT_WATERDIE_LOOP, // Chết trong nước (loop) + ACT_AIRDIE_ST, // Chết trên không (bắt đầu) + + // 30 + ACT_AIRDIE, // Chết trên không (loop rơi) + ACT_AIRDIE_ED, // Chết trên không (chạm đất) + ACT_AIRDIE_LAND_LOOP, // Chết rơi đất (loop) + ACT_REVIVE, // Hồi sinh + ACT_CUSTOMIZE, // Động tác tùy chỉnh + + // 35 + ACT_STRIKEBACK, // Bị đánh lùi + ACT_STRIKEDOWN, // Bị đánh ngã + ACT_STRIKEDOWN_LOOP, // Bị đánh ngã (loop) + ACT_STRIKEDOWN_STANDUP, // Bị đánh ngã rồi đứng dậy + ACT_PICKUP, // Nhặt đồ + + // 40 + ACT_PICKUP_LOOP, // Nhặt đồ (loop) + ACT_PICKUP_STANDUP, // Nhặt đồ đứng dậy + ACT_PICKUP_MATTER, // Nhặt vật thể + ACT_GAPE, // Há miệng + ACT_LOOKAROUND, // Nhìn quanh + + // 45 + ACT_PLAYWEAPON, // Vung vũ khí + ACT_EXP_WAVE, // Vẫy tay + ACT_EXP_NOD, // Gật đầu + ACT_EXP_SHAKEHEAD, // Lắc đầu + ACT_EXP_SHRUG, // Nhún vai + + // 50 + ACT_EXP_LAUGH, // Cười lớn + ACT_EXP_ANGRY, // Tức giận + ACT_EXP_STUN, // Choáng + ACT_EXP_DEPRESSED, // Buồn bã + ACT_EXP_KISSHAND, // Hôn tay + + // 55 + ACT_EXP_SHY, // Ngại ngùng + ACT_EXP_SALUTE, // Chào + ACT_EXP_SITDOWN, // Ngồi xuống + ACT_EXP_SITDOWN_LOOP, // Ngồi xuống (loop) + ACT_EXP_SITDOWN_STANDUP, // Ngồi xuống rồi đứng dậy + + // 60 + ACT_EXP_ASSAULT, // Tấn công + ACT_EXP_THINK, // Suy nghĩ + ACT_EXP_DEFIANCE, // Thách thức + ACT_EXP_VICTORY, // Chiến thắng + ACT_EXP_KISS, // Hôn + + // 65 + ACT_EXP_KISS_LOOP, // Hôn (loop) + ACT_EXP_KISS_END, // Kết thúc hôn + ACT_ATTACK_1, // Tấn công 1 + ACT_ATTACK_2, // Tấn công 2 + ACT_ATTACK_3, // Tấn công 3 + + // 70 + ACT_ATTACK_4, // Tấn công 4 + ACT_ATTACK_TOSS, // Ném vũ khí + ACT_TRICK_RUN, // Chiêu khi chạy + ACT_TRICK_JUMP, // Chiêu khi nhảy + ACT_FLY_GLIDE, // Lượn + + // 75 + ACT_FLY_GLIDE_SWORD, // Kiếm bay - lượn + ACT_EXP_FIGHT, // Tư thế chiến đấu + ACT_EXP_ATTACK1, // Tấn công diễn xuất 1 + ACT_EXP_ATTACK2, // Tấn công diễn xuất 2 + ACT_EXP_ATTACK3, // Tấn công diễn xuất 3 + + // 80 + ACT_EXP_ATTACK4, // Tấn công diễn xuất 4 + ACT_EXP_DEFENCE, // Phòng thủ + ACT_EXP_FALL, // Té ngã + ACT_EXP_FALLONGROUND, // Ngã xuống đất + ACT_EXP_LOOKAROUND, // Nhìn quanh + + // 85 + ACT_EXP_DANCE, // Nhảy múa + ACT_EXP_FASHIONWEAPON, // Động tác vũ khí thời trang + ACT_USEITEM, // Dùng item + ACT_USEITMELOOP, // Dùng item (loop) + ACT_TWO_KISS, // Hôn đôi + + // 90 + ACT_USING_TARGET_ITEM, // Dùng đạo cụ + ACT_SWIM_FOR_MOVESKILL, // Bơi trong lúc dùng skill di chuyển + + ACT_MAX, + ACT_CASTSKILL // Chỉ là placeholder cho skill actions + } + + public float GetTouchRadius() { return m_fTouchRad; } + // Is player in battle + public bool IsInBattle() { return m_iBattleCamp != Player_camp_in_battle.GP_BATTLE_CAMP_NONE; } + + // Check whether specified npc in a same battle camp + public bool InSameBattleCamp(CECNPC pNPC) + { + if (!pNPC || m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_NONE || + (m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_INVADER && !pNPC.IsInBattleInvaderCamp()) || + (m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_DEFENDER && !pNPC.IsInBattleDefenderCamp())) + return false; + + return true; + } + public bool IsInFactionPVP() => (m_factionPVPMask & 0x01) != 0; + public bool CanAttackFactionPVPMineCar() => (m_factionPVPMask & 0x02) != 0; + public bool CanAttackFactionPVPMineBase() => (m_factionPVPMask & 0x04) != 0; + + // Get basic properties + public ROLEBASICPROP GetBasicProps() { return m_BasicProps; } + + public int GetMoveStandAction(bool bMove, bool bFight = false) + { + int iMoveEnv = m_iMoveEnv; + //if (m_AttachMode != enumAttachNone) + //{ + // bFight = false; + // if (m_bHangerOn) + // iMoveEnv = MOVEENV_GROUND; + //} + + int iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND; + + if (bMove) + { + // Play appropriate actions + if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND) + { + if (m_bWalkRun) + iAction = (int)PLAYER_ACTION_TYPE.ACT_RUN; + else + iAction = (int)PLAYER_ACTION_TYPE.ACT_WALK; + } + //else if (iMoveEnv == MOVEENV_AIR) + //{ + // //if (/*UsingWing()*/ m_wingType == WINGTYPE_WING) + // // iAction = ACT_FLY; + // //else + // // iAction = ACT_FLY_SWORD; + //} + //else if (iMoveEnv == MOVEENV_WATER) + //{ + // //if (CanCombineWithMoveForSkill()) + // //{ + // // iAction = ACT_SWIM_FOR_MOVESKILL; + // //} + // //else + // //{ + // // iAction = ACT_SWIM; + // //} + //} } else { - + // Play appropriate actions + if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND) + { + if (bFight) + iAction = (int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND; + else + iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND; + } + //else if (iMoveEnv == MOVEENV_AIR) + //{ + // if (/*UsingWing()*/ m_wingType == WINGTYPE_WING) + // iAction = ACT_HANGINAIR; + // else + // iAction = ACT_HANGINAIR_SWORD; + //} + //else if (iMoveEnv == MOVEENV_WATER) + // iAction = ACT_HANGINWATER; } + + return iAction; } - return PlayActionWithConfig(iAction, m_PlayerActions[iAction], bRestart, iTransTime, bQueue); - } - public bool PlayActionWithConfig(int iAction, in PLAYER_ACTION actionConfig, - bool bRestart = true, int iTransTime = 200, bool bQueue = false) - { - PLAYER_ACTION action = actionConfig; - var szAct = EC_Utility.BuildActionName(action, 0); - EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szAct)); - return true; - } - public static void Dispose() - { - _default_actions = null; - _turning_actions = null; - } - public struct PLAYER_ACTION - { - public PLAYER_ACTION_TYPE type; - public PLAYER_ACTION_INFO_CONFIG data; - }; - public enum PLAYER_ACTION_TYPE - { - // 0 - ACT_STAND = 0, // Đứng - ACT_FIGHTSTAND, // Đứng chiến đấu - ACT_WALK, // Đi bộ - ACT_RUN, // Chạy - ACT_JUMP_START, // Bắt đầu nhảy - - // 5 - ACT_JUMP_LOOP, // Nhảy trên không lặp lại - ACT_JUMP_LAND, // Nhảy tiếp đất - ACT_SWIM, // Bơi - ACT_HANGINWATER, // Lơ lửng trong nước - ACT_TAKEOFF, // Cất cánh (should be ACT_TAKEOFF_WING) - - // 10 - ACT_HANGINAIR, // Treo trên không (should be ACT_HANGINAIR_WING) - ACT_FLY, // Bay (should be ACT_FLY_WING) - ACT_FLYDOWN, // Bay xuống cao (should be ACT_FLYDOWN_WING_HIGH) - ACT_FLYDOWN_WING_LOW, // Bay xuống thấp (should be ACT_FLYDOWN_WING_LOW) - ACT_LANDON, // Hạ cánh (should be ACT_LAND_WING) - - // 15 - ACT_TAKEOFF_SWORD, // Kiếm bay - cất cánh - ACT_HANGINAIR_SWORD, // Kiếm bay - treo không trung - ACT_FLY_SWORD, // Kiếm bay - tiến tới - ACT_FLYDOWN_SWORD_HIGH, // Kiếm bay - rơi cao - ACT_FLYDOWN_SWORD_LOW, // Kiếm bay - rơi thấp - - // 20 - ACT_LANDON_SWORD, // Kiếm bay - hạ cánh - ACT_SITDOWN, // Ngồi - ACT_SITDOWN_LOOP, // Ngồi lặp lại - ACT_STANDUP, // Đứng dậy - ACT_WOUNDED, // Bị thương - - // 25 - ACT_GROUNDDIE, // Chết trên mặt đất - ACT_GROUNDDIE_LOOP, // Chết trên đất (loop) - ACT_WATERDIE, // Chết trong nước - ACT_WATERDIE_LOOP, // Chết trong nước (loop) - ACT_AIRDIE_ST, // Chết trên không (bắt đầu) - - // 30 - ACT_AIRDIE, // Chết trên không (loop rơi) - ACT_AIRDIE_ED, // Chết trên không (chạm đất) - ACT_AIRDIE_LAND_LOOP, // Chết rơi đất (loop) - ACT_REVIVE, // Hồi sinh - ACT_CUSTOMIZE, // Động tác tùy chỉnh - - // 35 - ACT_STRIKEBACK, // Bị đánh lùi - ACT_STRIKEDOWN, // Bị đánh ngã - ACT_STRIKEDOWN_LOOP, // Bị đánh ngã (loop) - ACT_STRIKEDOWN_STANDUP, // Bị đánh ngã rồi đứng dậy - ACT_PICKUP, // Nhặt đồ - - // 40 - ACT_PICKUP_LOOP, // Nhặt đồ (loop) - ACT_PICKUP_STANDUP, // Nhặt đồ đứng dậy - ACT_PICKUP_MATTER, // Nhặt vật thể - ACT_GAPE, // Há miệng - ACT_LOOKAROUND, // Nhìn quanh - - // 45 - ACT_PLAYWEAPON, // Vung vũ khí - ACT_EXP_WAVE, // Vẫy tay - ACT_EXP_NOD, // Gật đầu - ACT_EXP_SHAKEHEAD, // Lắc đầu - ACT_EXP_SHRUG, // Nhún vai - - // 50 - ACT_EXP_LAUGH, // Cười lớn - ACT_EXP_ANGRY, // Tức giận - ACT_EXP_STUN, // Choáng - ACT_EXP_DEPRESSED, // Buồn bã - ACT_EXP_KISSHAND, // Hôn tay - - // 55 - ACT_EXP_SHY, // Ngại ngùng - ACT_EXP_SALUTE, // Chào - ACT_EXP_SITDOWN, // Ngồi xuống - ACT_EXP_SITDOWN_LOOP, // Ngồi xuống (loop) - ACT_EXP_SITDOWN_STANDUP, // Ngồi xuống rồi đứng dậy - - // 60 - ACT_EXP_ASSAULT, // Tấn công - ACT_EXP_THINK, // Suy nghĩ - ACT_EXP_DEFIANCE, // Thách thức - ACT_EXP_VICTORY, // Chiến thắng - ACT_EXP_KISS, // Hôn - - // 65 - ACT_EXP_KISS_LOOP, // Hôn (loop) - ACT_EXP_KISS_END, // Kết thúc hôn - ACT_ATTACK_1, // Tấn công 1 - ACT_ATTACK_2, // Tấn công 2 - ACT_ATTACK_3, // Tấn công 3 - - // 70 - ACT_ATTACK_4, // Tấn công 4 - ACT_ATTACK_TOSS, // Ném vũ khí - ACT_TRICK_RUN, // Chiêu khi chạy - ACT_TRICK_JUMP, // Chiêu khi nhảy - ACT_FLY_GLIDE, // Lượn - - // 75 - ACT_FLY_GLIDE_SWORD, // Kiếm bay - lượn - ACT_EXP_FIGHT, // Tư thế chiến đấu - ACT_EXP_ATTACK1, // Tấn công diễn xuất 1 - ACT_EXP_ATTACK2, // Tấn công diễn xuất 2 - ACT_EXP_ATTACK3, // Tấn công diễn xuất 3 - - // 80 - ACT_EXP_ATTACK4, // Tấn công diễn xuất 4 - ACT_EXP_DEFENCE, // Phòng thủ - ACT_EXP_FALL, // Té ngã - ACT_EXP_FALLONGROUND, // Ngã xuống đất - ACT_EXP_LOOKAROUND, // Nhìn quanh - - // 85 - ACT_EXP_DANCE, // Nhảy múa - ACT_EXP_FASHIONWEAPON, // Động tác vũ khí thời trang - ACT_USEITEM, // Dùng item - ACT_USEITMELOOP, // Dùng item (loop) - ACT_TWO_KISS, // Hôn đôi - - // 90 - ACT_USING_TARGET_ITEM, // Dùng đạo cụ - ACT_SWIM_FOR_MOVESKILL, // Bơi trong lúc dùng skill di chuyển - - ACT_MAX, - ACT_CASTSKILL // Chỉ là placeholder cho skill actions - } - - public float GetTouchRadius(){ return m_fTouchRad; } - // Is player in battle - public bool IsInBattle() { return m_iBattleCamp != Player_camp_in_battle.GP_BATTLE_CAMP_NONE; } - - // Check whether specified npc in a same battle camp - public bool InSameBattleCamp(CECNPC pNPC) - { - if (!pNPC || m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_NONE || - (m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_INVADER && !pNPC.IsInBattleInvaderCamp()) || - (m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_DEFENDER && !pNPC.IsInBattleDefenderCamp())) - return false; - - return true; - } - public bool IsInFactionPVP() => (m_factionPVPMask & 0x01) != 0; - public bool CanAttackFactionPVPMineCar() => (m_factionPVPMask & 0x02) != 0; - public bool CanAttackFactionPVPMineBase() => (m_factionPVPMask & 0x04) != 0; - - // Get basic properties - public ROLEBASICPROP GetBasicProps() { return m_BasicProps; } - - public int GetMoveStandAction(bool bMove, bool bFight = false) - { - int iMoveEnv = m_iMoveEnv; - //if (m_AttachMode != enumAttachNone) - //{ - // bFight = false; - // if (m_bHangerOn) - // iMoveEnv = MOVEENV_GROUND; - //} - - int iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND; - - if (bMove) + public float GetGroundSpeed() { - // Play appropriate actions - if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND) - { - if (m_bWalkRun) - iAction = (int)PLAYER_ACTION_TYPE.ACT_RUN; - else - iAction = (int)PLAYER_ACTION_TYPE.ACT_WALK; - } - //else if (iMoveEnv == MOVEENV_AIR) - //{ - // //if (/*UsingWing()*/ m_wingType == WINGTYPE_WING) - // // iAction = ACT_FLY; - // //else - // // iAction = ACT_FLY_SWORD; - //} - //else if (iMoveEnv == MOVEENV_WATER) - //{ - // //if (CanCombineWithMoveForSkill()) - // //{ - // // iAction = ACT_SWIM_FOR_MOVESKILL; - // //} - // //else - // //{ - // // iAction = ACT_SWIM; - // //} - //} + // return m_bWalkRun ? g_pGame->GetConfigs()->GetHostRunSpeed() : m_ExtProps.mv.walk_speed; + return m_bWalkRun ? m_ExtProps.mv.run_speed : m_ExtProps.mv.walk_speed; } - else + + // Get move environment + public int GetMoveEnv() { return m_iMoveEnv; } + // Get character ID + public int GetCharacterID() { return m_PlayerInfo.cid; } + } + public struct PlayActionEvent + { + public string AnimationName; + public PlayActionEvent(string animationName) { - // Play appropriate actions - if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND) - { - if (bFight) - iAction = (int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND; - else - iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND; - } - //else if (iMoveEnv == MOVEENV_AIR) - //{ - // if (/*UsingWing()*/ m_wingType == WINGTYPE_WING) - // iAction = ACT_HANGINAIR; - // else - // iAction = ACT_HANGINAIR_SWORD; - //} - //else if (iMoveEnv == MOVEENV_WATER) - // iAction = ACT_HANGINWATER; + this.AnimationName = animationName; } - - return iAction; } - - public float GetGroundSpeed() + [Serializable] + public struct INFO { - // return m_bWalkRun ? g_pGame->GetConfigs()->GetHostRunSpeed() : m_ExtProps.mv.walk_speed; - return m_bWalkRun ? m_ExtProps.mv.run_speed : m_ExtProps.mv.walk_speed; + public int cid; // Character ID + public int crc_c; // customized data crc + public int crc_e; // Equipment data crc + public INFO(int cid, int crc_c, int crc_) + { + this.cid = cid; + this.crc_c = crc_c; + this.crc_e = crc_; + } } - // Get move environment - public int GetMoveEnv(){ return m_iMoveEnv; } - // Get character ID - public int GetCharacterID(){ return m_PlayerInfo.cid; } -} -public struct PlayActionEvent -{ - public string AnimationName; - public PlayActionEvent(string animationName) + public static class Duel_state // Duel state { - this.AnimationName = animationName; + public const int DUEL_ST_NONE = 0, + DUEL_ST_PREPARE = 1, + DUEL_ST_INDUEL = 2, + DUEL_ST_STOPPING = 3; } } -[Serializable] -public struct INFO -{ - public int cid; // Character ID - public int crc_c; // customized data crc - public int crc_e; // Equipment data crc - public INFO(int cid, int crc_c, int crc_) - { - this.cid = cid; - this.crc_c = crc_c; - this.crc_e = crc_; - } -} - -public static class Duel_state // Duel state -{ - public const int DUEL_ST_NONE = 0, - DUEL_ST_PREPARE = 1, - DUEL_ST_INDUEL = 2, - DUEL_ST_STOPPING = 3; -} - //// Move mode //public static class Move_Mode //{ diff --git a/Assets/Scripts/PlayerState/PlayerIdleState.cs b/Assets/Scripts/PlayerState/PlayerIdleState.cs index dab799fc4a..c24f445b78 100644 --- a/Assets/Scripts/PlayerState/PlayerIdleState.cs +++ b/Assets/Scripts/PlayerState/PlayerIdleState.cs @@ -1,24 +1,27 @@ using UnityEngine; -using static EC_Player; +using static BrewMonster.Scripts.Player.EC_Player; -public class PlayerIdleState : PlayerState +namespace BrewMonster.Scripts.Player { - public PlayerIdleState(CECHostPlayer characterCtrl) : base(characterCtrl) + public class PlayerIdleState : PlayerState { - } + public PlayerIdleState(CECHostPlayer characterCtrl) : base(characterCtrl) + { + } - public override void Enter() - { - _characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_STAND, true, 1, false); - } + public override void Enter() + { + _characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_STAND, true, 1, false); + } - public override void Exit() - { + public override void Exit() + { - } + } - public override void Update() - { + public override void Update() + { + } } } diff --git a/Assets/Scripts/PlayerState/PlayerMoveState.cs b/Assets/Scripts/PlayerState/PlayerMoveState.cs index e82e7f53a4..b57c7db97b 100644 --- a/Assets/Scripts/PlayerState/PlayerMoveState.cs +++ b/Assets/Scripts/PlayerState/PlayerMoveState.cs @@ -1,25 +1,28 @@ using UnityEngine; -using static EC_Player; +using static BrewMonster.Scripts.Player.EC_Player; -public class PlayerMoveState : PlayerState +namespace BrewMonster.Scripts.Player { - public PlayerMoveState(CECHostPlayer characterCtrl) : base(characterCtrl) + public class PlayerMoveState : PlayerState { - } + public PlayerMoveState(CECHostPlayer characterCtrl) : base(characterCtrl) + { + } - public override void Enter() - { - _characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_WALK,true,1,false); - } + public override void Enter() + { + _characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_WALK, true, 1, false); + } - public override void Exit() - { - _characterCtrl.StopMovement(); - } + public override void Exit() + { + _characterCtrl.StopMovement(); + } - public override void Update() - { - _characterCtrl.HandleMovement(); - } + public override void Update() + { + _characterCtrl.HandleMovement(); + } + } } diff --git a/Assets/Scripts/PlayerState/PlayerState.cs b/Assets/Scripts/PlayerState/PlayerState.cs index 6ce5c03a59..e9fc80c320 100644 --- a/Assets/Scripts/PlayerState/PlayerState.cs +++ b/Assets/Scripts/PlayerState/PlayerState.cs @@ -1,13 +1,16 @@ using UnityEngine; -public abstract class PlayerState +namespace BrewMonster.Scripts.Player { - protected readonly CECHostPlayer _characterCtrl; - public PlayerState(CECHostPlayer characterCtrl) + public abstract class PlayerState { - _characterCtrl = characterCtrl; + protected readonly CECHostPlayer _characterCtrl; + public PlayerState(CECHostPlayer characterCtrl) + { + _characterCtrl = characterCtrl; + } + public abstract void Enter(); + public abstract void Exit(); + public abstract void Update(); } - public abstract void Enter(); - public abstract void Exit(); - public abstract void Update(); } diff --git a/Assets/Scripts/PlayerStateMachine.cs b/Assets/Scripts/PlayerStateMachine.cs index da9131e4e7..8d7528e566 100644 --- a/Assets/Scripts/PlayerStateMachine.cs +++ b/Assets/Scripts/PlayerStateMachine.cs @@ -1,41 +1,44 @@ using UnityEngine; -public class PlayerStateMachine +namespace BrewMonster.Scripts.Player { - PlayerState _state; - CECHostPlayer _characterCtrl; - - public PlayerState State { get => _state; } - - public void InitState(PlayerState state) + public class PlayerStateMachine { - if (_state != null) - { - Debug.LogWarning("_state is already inited"); - return; - } - _state = state; - _state.Enter(); - } + PlayerState _state; + CECHostPlayer _characterCtrl; - public void ChangeState(PlayerState state) - { - if (_state == null ) - { - Debug.LogError("you need to init state first "); - return; - } - if (_state == state) - { - Debug.LogWarning("Unchanged state"); - } - _state.Exit(); - _state = state; - _state.Enter(); - } - public void UpdateState() - { - _state.Update(); - } + public PlayerState State { get => _state; } + public void InitState(PlayerState state) + { + if (_state != null) + { + Debug.LogWarning("_state is already inited"); + return; + } + _state = state; + _state.Enter(); + } + + public void ChangeState(PlayerState state) + { + if (_state == null) + { + Debug.LogError("you need to init state first "); + return; + } + if (_state == state) + { + Debug.LogWarning("Unchanged state"); + } + _state.Exit(); + _state = state; + _state.Enter(); + } + public void UpdateState() + { + _state.Update(); + } + + } } diff --git a/Assets/Scripts/PlayerVisual.cs b/Assets/Scripts/PlayerVisual.cs index 08fab98c64..4810df7d5c 100644 --- a/Assets/Scripts/PlayerVisual.cs +++ b/Assets/Scripts/PlayerVisual.cs @@ -2,42 +2,45 @@ using Animancer; using System; using UnityEngine; -public class PlayerVisual : MonoBehaviour +namespace BrewMonster.Scripts.Player { - [SerializeField] NamedAnimancerComponent namedAnimancer; - - [SerializeField] private INFO _playerInfo; - - - private void PlayActionEventHandler(PlayActionEvent @event) + public class PlayerVisual : MonoBehaviour { - BrewMonster.BMLogger.Log("PlayActionEventHandler : "+@event.AnimationName); - namedAnimancer.TryPlay(@event.AnimationName); - } + [SerializeField] NamedAnimancerComponent namedAnimancer; - public void InitHostPlayerEventDoneHandler() - { - namedAnimancer = GetComponentInChildren(); - if(namedAnimancer == null) + [SerializeField] private INFO _playerInfo; + + + private void PlayActionEventHandler(PlayActionEvent @event) { - BrewMonster.BMLogger.LogError("animancer == null"); - return; + BrewMonster.BMLogger.Log("PlayActionEventHandler : " + @event.AnimationName); + namedAnimancer.TryPlay(@event.AnimationName); } - var player = GetComponentInParent(); - if(player == null) + + public void InitHostPlayerEventDoneHandler() { - BrewMonster.BMLogger.LogError("player == null"); - return; + namedAnimancer = GetComponentInChildren(); + if (namedAnimancer == null) + { + BrewMonster.BMLogger.LogError("animancer == null"); + return; + } + var player = GetComponentInParent(); + if (player == null) + { + BrewMonster.BMLogger.LogError("player == null"); + return; + } + _playerInfo = player.GetPlayInfo(); + EventBus.SubscribeChannel(_playerInfo.cid, PlayActionEventHandler); + } + private void OnDestroy() + { + EventBus.UnsubscribeAllInChannel(_playerInfo.cid); + } + public bool IsAnimationExist(string animationName) + { + return namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false; } - _playerInfo = player.GetPlayInfo(); - EventBus.SubscribeChannel(_playerInfo.cid, PlayActionEventHandler); - } - private void OnDestroy() - { - EventBus.UnsubscribeAllInChannel(_playerInfo.cid); - } - public bool IsAnimationExist(string animationName) - { - return namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false; } } diff --git a/Assets/Scripts/ScreenLogin.cs b/Assets/Scripts/ScreenLogin.cs index 06314e2205..1d05f569fe 100644 --- a/Assets/Scripts/ScreenLogin.cs +++ b/Assets/Scripts/ScreenLogin.cs @@ -4,35 +4,38 @@ using UnityEngine.UI; using System.Collections.Generic; using CSNetwork.Protocols.RPCData; -public class ScreenLogin : MonoBehaviour +namespace BrewMonster.Managers { - [SerializeField] private TMP_InputField ifUsername; - [SerializeField] private TMP_InputField ifPassword; - [SerializeField] private TMP_Dropdown ip; - [SerializeField] private Button btnLogin; - [SerializeField] private CanvasController canvasController; - - private void Start() + public class ScreenLogin : MonoBehaviour { - btnLogin.onClick.AddListener(OnClickBtnLogin); - } + [SerializeField] private TMP_InputField ifUsername; + [SerializeField] private TMP_InputField ifPassword; + [SerializeField] private TMP_Dropdown ip; + [SerializeField] private Button btnLogin; + [SerializeField] private CanvasController canvasController; - private void OnClickBtnLogin() - { - string _username = ifUsername.text; - string _password = ifPassword.text; - string _ip = ip.options[ip.value].text; - Debug.LogError("Login..."); - } + private void Start() + { + btnLogin.onClick.AddListener(OnClickBtnLogin); + } - private void HandleLoginComplete(List roleInfos) - { - Debug.LogError("Success"); - canvasController.ShowScreenSelectCharacter(roleInfos); - } + private void OnClickBtnLogin() + { + string _username = ifUsername.text; + string _password = ifPassword.text; + string _ip = ip.options[ip.value].text; + Debug.LogError("Login..."); + } - private void HandleLoginFaile(string reslut) - { - Debug.LogError(reslut); + private void HandleLoginComplete(List roleInfos) + { + Debug.LogError("Success"); + canvasController.ShowScreenSelectCharacter(roleInfos); + } + + private void HandleLoginFaile(string reslut) + { + Debug.LogError(reslut); + } } } diff --git a/Assets/Scripts/Task/ATaskTemplMan.cs b/Assets/Scripts/Task/ATaskTemplMan.cs index a7981b970f..c49991ccf9 100644 --- a/Assets/Scripts/Task/ATaskTemplMan.cs +++ b/Assets/Scripts/Task/ATaskTemplMan.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.IO; using UnityEngine; -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public class ATaskTemplMan { diff --git a/Assets/Scripts/Task/CECTaskInterface.cs b/Assets/Scripts/Task/CECTaskInterface.cs index 461bb9622a..38be64a5b1 100644 --- a/Assets/Scripts/Task/CECTaskInterface.cs +++ b/Assets/Scripts/Task/CECTaskInterface.cs @@ -1,8 +1,9 @@ using BrewMonster.Network; +using BrewMonster.Scripts.Player; using System.Collections.Generic; using UnityEngine; -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public class CECTaskInterface : TaskInterface { diff --git a/Assets/Scripts/Task/TaskExpAnalyser.cs b/Assets/Scripts/Task/TaskExpAnalyser.cs index fb05f704bf..e7101b9a2b 100644 --- a/Assets/Scripts/Task/TaskExpAnalyser.cs +++ b/Assets/Scripts/Task/TaskExpAnalyser.cs @@ -1,4 +1,4 @@ -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public struct TASK_EXPRESSION { diff --git a/Assets/Scripts/Task/TaskInterface.cs b/Assets/Scripts/Task/TaskInterface.cs index 242ccd320f..084574cd72 100644 --- a/Assets/Scripts/Task/TaskInterface.cs +++ b/Assets/Scripts/Task/TaskInterface.cs @@ -1,4 +1,4 @@ -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public interface TaskInterface { diff --git a/Assets/Scripts/Task/TaskProcess.cs b/Assets/Scripts/Task/TaskProcess.cs index 24230b2a9e..9491d3c884 100644 --- a/Assets/Scripts/Task/TaskProcess.cs +++ b/Assets/Scripts/Task/TaskProcess.cs @@ -1,6 +1,6 @@ using System; using System.Runtime.InteropServices; -using PerfectWorld.Scripts.Task; +using BrewMonster.Scripts.Task; using UnityEngine; public class TaskProcess diff --git a/Assets/Scripts/Task/TaskTempl.cs b/Assets/Scripts/Task/TaskTempl.cs index 9c28eae2d6..89bd3962b6 100644 --- a/Assets/Scripts/Task/TaskTempl.cs +++ b/Assets/Scripts/Task/TaskTempl.cs @@ -3,7 +3,7 @@ using System.IO; using System.Runtime.InteropServices; -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public sealed class TaskConstant { diff --git a/Assets/Scripts/Task/TaskTest.cs b/Assets/Scripts/Task/TaskTest.cs index 2fca9f1774..a8af4ffd46 100644 --- a/Assets/Scripts/Task/TaskTest.cs +++ b/Assets/Scripts/Task/TaskTest.cs @@ -2,7 +2,7 @@ using System.IO; using UnityEngine; -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public class TaskTest : MonoBehaviour { diff --git a/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs b/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs index 855dea1336..3068a8777f 100644 --- a/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs +++ b/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs @@ -1,4 +1,5 @@ - using UnityEngine; +using BrewMonster.Scripts.Player; +using UnityEngine; #if ENABLE_INPUT_SYSTEM using UnityEngine.InputSystem; #endif From 79a3450e9d1b2a71a156513145d998696235a81f Mon Sep 17 00:00:00 2001 From: Tungdv Date: Tue, 14 Oct 2025 18:46:20 +0700 Subject: [PATCH 2/6] feat: update logic Get Terrain. --- .../Scripts/Managers/A3DTerrain2.cs | 173 +++++++++++++++++- 1 file changed, 171 insertions(+), 2 deletions(-) diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs index a878a682e6..8ce44da6a3 100644 --- a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs @@ -1,6 +1,175 @@ +using CSNetwork.GPDataType; using UnityEngine; -public class A3DTerrain2 +namespace BrewMonster.Scripts.World { - + public class A3DTerrain2 + { + protected ACTBLOCKS[] m_pCurActBlocks; // Currently active block array + + // Active blocks + public struct ACTBLOCKS + { + public ARectI rcArea; // Active area represented in blocks + public BlockArray aBlocks; // Active block array + + public ACTBLOCKS() + { + aBlocks = new BlockArray[128]; + } + + ARectI rcArea; // Active area represented in blocks + BlockArray aBlocks; // Active block array + + // Get block object at specified row, column. + A3DTerrain2Block* GetBlock(int r, int c, bool bClear) + { + ASSERT(rcArea.PtInRect(c, r)); + + int iIndex = GetBlockIndex(r, c); + A3DTerrain2Block* pBlock = aBlocks[iIndex]; + + if (bClear) + aBlocks[iIndex] = NULL; + + return pBlock; + } + + // Set block object at specified row, column + void SetBlock(int r, int c, A3DTerrain2Block* pBlock) + { + ASSERT(rcArea.PtInRect(c, r)); + int iIndex = GetBlockIndex(r, c); + aBlocks[iIndex] = pBlock; + } + + // Get block index in aBlocks + int GetBlockIndex(int r, int c) + { + return (r - rcArea.top) * rcArea.Width() + c - rcArea.left; + } + }; + + + // Get height and normal of specified position + public float GetPosHeight(A3DVECTOR3 vPos, A3DVECTOR3? pvNormal = null) + { + // Give a default value to normal + if (pvNormal.HasValue) + pvNormal.Value.Clear(); + + if (m_pCurActBlocks.rcArea.IsEmpty()) + return 0.0f; + + // Currenly active area AABB + ARectF rcActive; + rcActive.left = m_rcTerrain.left + m_pCurActBlocks.rcArea.left * m_fBlockSize; + rcActive.top = m_rcTerrain.top - m_pCurActBlocks.rcArea.top * m_fBlockSize; + rcActive.right = rcActive.left + m_pCurActBlocks.rcArea.Width() * m_fBlockSize; + rcActive.bottom = rcActive.top - m_pCurActBlocks.rcArea.Height() * m_fBlockSize; + + if (vPos.x < rcActive.left || vPos.x > rcActive.right || + vPos.z > rcActive.top || vPos.z < rcActive.bottom) + return 0.0f; + + // Get block this position is in + float fInvBlockSize = 1.0f / m_fBlockSize; + int iCol = (int)((vPos.x - rcActive.left) * fInvBlockSize); + int iRow = (int)(-(vPos.z - rcActive.top) * fInvBlockSize); + a_Clamp(iCol, 0, m_pCurActBlocks.rcArea.Width() - 1); + a_Clamp(iRow, 0, m_pCurActBlocks.rcArea.Height() - 1); + + int iBlock = iRow * m_pCurActBlocks.rcArea.Width() + iCol; + A3DTerrain2Block* pBlock = m_pCurActBlocks.aBlocks[iBlock]; + if (!pBlock || !pBlock.IsDataLoaded()) + return 0.0f; + + // If whole block is a hole, return as if there is no block here + if (pBlock.IsNoPosHeight()) + return 0.0f; + + // Get block's AABB + const A3DAABB&aabb = pBlock.GetBlockAABB(); + + // Get grid this position is in + float fInvGridSize = 1.0f / m_fGridSize; + iCol = (int)((vPos.x - aabb.Mins.x) * fInvGridSize); + iRow = (int)(-(vPos.z - aabb.Maxs.z) * fInvGridSize); + a_Clamp(iCol, 0, m_iBlockGrid - 1); + a_Clamp(iRow, 0, m_iBlockGrid - 1); + + int iGrid = iRow * m_iBlockGrid + iCol; + const A3DTerrain2LOD::GRID&Grid = m_pLODMan.GetGrids()[iGrid]; + + A3DVECTOR3 v0 = pBlock.GetVertexPos(Grid.v0); + A3DVECTOR3 v1 = pBlock.GetVertexPos(Grid.v1); + A3DVECTOR3 v2 = pBlock.GetVertexPos(Grid.v2); + A3DVECTOR3 v3 = pBlock.GetVertexPos(Grid.v3); + A3DVECTOR3 v4 = pBlock.GetVertexPos(Grid.v4); + A3DVECTOR3 v5 = pBlock.GetVertexPos(Grid.v5); + + A3DVECTOR3 vDest; + float dx, dz; + + if (iGrid == m_iBlockGrid - 1 || iGrid == m_iBlockGrid * (m_iBlockGrid - 1)) + { + // The grid is on right-top corner or left-bottom corner + dx = vPos.x - v2.x; + dz = vPos.z - v2.z; + + if (dx > dz) + { + vDest = v5 + (v4 - v5) * (dx / (v4.x - v5.x)); + vDest += (v3 - v4) * (dz / (v3.z - v4.z)); + + if (pvNormal) + { + pvNormal.CrossProduct(v4 - v3, v5 - v3); + pvNormal.Normalize(); + } + } + else + { + vDest = v2 + (v0 - v2) * (dz / (v0.z - v2.z)); + vDest += (v1 - v0) * (dx / (v1.x - v0.x)); + + if (pvNormal) + { + pvNormal.CrossProduct(v1 - v0, v2 - v0); + pvNormal.Normalize(); + } + } + } + else + { + dx = vPos.x - v0.x; + dz = vPos.z - v0.z; + + if (dx > -dz) + { + vDest = v0 + (v1 - v0) * (dx / (v1.x - v0.x)); + vDest += (v2 - v1) * (dz / (v2.z - v1.z)); + + if (pvNormal) + { + pvNormal.CrossProduct(v1 - v0, v2 - v0); + pvNormal.Normalize(); + } + } + else + { + vDest = v3 + (v5 - v3) * (dz / (v5.z - v3.z)); + vDest += (v4 - v5) * (dx / (v4.x - v5.x)); + + if (pvNormal) + { + pvNormal.CrossProduct(v4 - v3, v5 - v3); + pvNormal.Normalize(); + } + } + } + + return vDest.y; + } + } } From de76d2dec0fc44d59290336678b2535c3d6b9fc4 Mon Sep 17 00:00:00 2001 From: Tungdv Date: Wed, 15 Oct 2025 18:14:53 +0700 Subject: [PATCH 3/6] fix: update struct in logic terrain. --- Assets/PerfectWorld/Scene/Boostrap.unity | 109 +++++++ .../Scripts/Managers/A3DTerrain2.cs | 301 ++++++++++++++---- .../Scripts/Managers/A3DTerrain2LOD.cs | 9 + .../Scripts/Managers/A3DTerrain2LOD.cs.meta | 2 + Assets/PerfectWorld/Scripts/Managers/ARect.cs | 280 ++++++++++++++++ .../Scripts/Managers/ARect.cs.meta | 2 + Assets/Scripts/Move/EC_CDR.cs | 85 ++--- 7 files changed, 673 insertions(+), 115 deletions(-) create mode 100644 Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta create mode 100644 Assets/PerfectWorld/Scripts/Managers/ARect.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta diff --git a/Assets/PerfectWorld/Scene/Boostrap.unity b/Assets/PerfectWorld/Scene/Boostrap.unity index 8fc81705c0..8af98d5485 100644 --- a/Assets/PerfectWorld/Scene/Boostrap.unity +++ b/Assets/PerfectWorld/Scene/Boostrap.unity @@ -164,6 +164,114 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: _nextSceneName: LoginScene +--- !u!1 &428240946 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 428240950} + - component: {fileID: 428240949} + - component: {fileID: 428240948} + - component: {fileID: 428240947} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &428240947 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &428240948 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &428240949 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &428240950 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &506356661 PrefabInstance: m_ObjectHideFlags: 0 @@ -586,3 +694,4 @@ SceneRoots: - {fileID: 591506937} - {fileID: 105404091} - {fileID: 506356661} + - {fileID: 428240950} diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs index 8ce44da6a3..f2d6deeda0 100644 --- a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs @@ -1,68 +1,185 @@ using CSNetwork.GPDataType; using UnityEngine; +using ARectI = BrewMonster.Scripts.ARect; +using ARectF = BrewMonster.Scripts.ARect; +using BlockArray = System.Collections.Generic.List; +using BrewMonster.Scripts.Player; +using WORD = System.UInt16; namespace BrewMonster.Scripts.World { - public class A3DTerrain2 + public class A3DTerrain2Block { - protected ACTBLOCKS[] m_pCurActBlocks; // Currently active block array - - // Active blocks - public struct ACTBLOCKS + // Trerrain2 vertex format when use lightmap + public struct A3DTRN2VERTEX1 { - public ARectI rcArea; // Active area represented in blocks - public BlockArray aBlocks; // Active block array - - public ACTBLOCKS() - { - aBlocks = new BlockArray[128]; - } - - ARectI rcArea; // Active area represented in blocks - BlockArray aBlocks; // Active block array - - // Get block object at specified row, column. - A3DTerrain2Block* GetBlock(int r, int c, bool bClear) - { - ASSERT(rcArea.PtInRect(c, r)); - - int iIndex = GetBlockIndex(r, c); - A3DTerrain2Block* pBlock = aBlocks[iIndex]; - - if (bClear) - aBlocks[iIndex] = NULL; - - return pBlock; - } - - // Set block object at specified row, column - void SetBlock(int r, int c, A3DTerrain2Block* pBlock) - { - ASSERT(rcArea.PtInRect(c, r)); - int iIndex = GetBlockIndex(r, c); - aBlocks[iIndex] = pBlock; - } - - // Get block index in aBlocks - int GetBlockIndex(int r, int c) - { - return (r - rcArea.top) * rcArea.Width() + c - rcArea.left; - } + public float vPosX; // PositionX + public float vPosY; // PositionY + public float vPosZ; // PositionZ + public float vNormalX; // NormalX + public float vNormalY; // NormalY + public float vNormalZ; // NormalZ + public float u1, v1; // Texture coordinates project on xz + public float u2, v2; // Texture coordinates project on xy + public float u3, v3; // Texture coordinates project on yz + public float u4, v4; // Texture coordinate of layer mask }; + // Terrain2 vertex format when use vertex-light (not lightmap) + struct A3DTRN2VERTEX2 + { + public float vPosX; // Position X + public float vPosY; // Position Y + public float vPosZ; // Position Z + public uint dwDiffuse; // Diffuse color + public uint dwSpecular; // Specular color + public float u1, v1; // Texture coordinates project on xz + public float u2, v2; // Texture coordinates project on xy + public float u3, v3; // Texture coordinates project on yz + public float u4, v4; // Texture coordinate of layer mask + }; + + public bool m_bDataLoaded = false; // Data loaded flag + public bool IsDataLoaded() { return m_bDataLoaded; } + public uint m_dwBlockFlags; // Block flags + public A3DAABB m_aabbBlock; // Block postion and size in whole world + A3DTRN2VERTEX1[] m_aVertices1; // Vertex buffer, ps version + A3DTRN2VERTEX2[] m_aVertices2; // Vertex buffer, non-ps version + + // Get block's position and size in whole world + public A3DAABB GetBlockAABB() { return m_aabbBlock; } + // Get flag for this whole block unable for GetPosHeight + public bool IsNoPosHeight() + { + return (m_dwBlockFlags & Block_flags_masks.T2BKFLAG_NOPOSHEIGHT) != 0; + } + + // Get vertex + public A3DVECTOR3 GetVertexPos(int n) + { + if (m_aVertices1 != null && m_aVertices1.Length > n) + return new A3DVECTOR3(m_aVertices1[n].vPosX, m_aVertices1[n].vPosY, m_aVertices1[n].vPosZ); + else + { + //ASSERT(m_aVertices2); + return new A3DVECTOR3(m_aVertices2[n].vPosX, m_aVertices2[n].vPosY, m_aVertices2[n].vPosZ); + } + } + } + + public class A3DTerrain2 + { + public ACTBLOCKS m_pCurActBlocks; // Currently active block array + public ARectF m_rcTerrain; // Whole terrain area in logic unit (metres) + public float m_fBlockSize = 0; // Block size (on x and z axis) in logic unit (metres) + public int m_iBlockGrid = 0; // Each block has m_iBlockGrid * m_iBlockGrid terrain grids + public float m_fGridSize; // Terrain grid size (on x and z axis) in logic unit (metres) + public A3DTerrain2LOD m_pLODMan; // LOD manager + + // Get grid faces of specified area + public bool GetFacesOfArea(A3DVECTOR3 vCenter, int iGridWid, int iGridLen, A3DVECTOR3 pVertBuf, WORD pIdxBuf) + { + if (m_pCurActBlocks.rcArea.IsEmpty()) + return false; + + float fInvGridSize = 1.0f / m_fGridSize; + + ARectI rcGrid = new ARectI(); + rcGrid.left = (int)((vCenter.x - m_rcTerrain.left) * fInvGridSize) - (iGridWid >> 1); + rcGrid.top = (int)((m_rcTerrain.top - vCenter.z) * fInvGridSize) - (iGridLen >> 1); + rcGrid.right = rcGrid.left + iGridWid; + rcGrid.bottom = rcGrid.top + iGridLen; + + return GetFacesOfArea(rcGrid, pVertBuf, pIdxBuf); + } + + public bool GetFacesOfArea(ARectI rcGridArea, A3DVECTOR3 pVertBuf, WORD pIdxBuf) + { + if (m_pCurActBlocks.rcArea.IsEmpty()) + return false; + + float fInvGridSize = 1.0f / m_fGridSize; + + ARectI rcGrid = rcGridArea; + + int iMaxGrid = m_iNumAllBlockCol * m_iBlockGrid; + AAssist.a_Clamp(ref rcGrid.left, 0, iMaxGrid); + AAssist.a_Clamp(ref rcGrid.right, 0, iMaxGrid); + iMaxGrid = m_iNumAllBlockRow * m_iBlockGrid; + AAssist.a_Clamp(ref rcGrid.top, 0, iMaxGrid); + AAssist.a_Clamp(ref rcGrid.bottom, 0, iMaxGrid); + + if (rcGrid.IsEmpty()) + return false; + + ARectI rcBlock = new ARectI(); + rcBlock.left = rcGrid.left / m_iBlockGrid; + rcBlock.top = rcGrid.top / m_iBlockGrid; + rcBlock.right = (rcGrid.right - 1) / m_iBlockGrid; + rcBlock.bottom = (rcGrid.bottom - 1) / m_iBlockGrid; + + int r, c; + + // Ensure all blocks in active area and have been loaded + for (r = rcBlock.top; r <= rcBlock.bottom; r++) + { + for (c = rcBlock.left; c <= rcBlock.right; c++) + { + if (!m_pCurActBlocks.rcArea.PtInRect(c, r) || + !m_pCurActBlocks.GetBlock(r, c, false)) + return false; + } + } + + WORD pDestIdx = pIdxBuf; + + for (r = rcBlock.top; r <= rcBlock.bottom; r++) + { + ARectI rect = new ARectI(); + rect.left = rcBlock.left * m_iBlockGrid; + rect.top = r * m_iBlockGrid; + rect.right = rect.left + m_iBlockGrid; + rect.bottom = rect.top + m_iBlockGrid; + + for (c = rcBlock.left; c <= rcBlock.right; c++) + { + A3DTerrain2Block pBlock = m_pCurActBlocks.GetBlock(r, c, false); + //ASSERT(pBlock); + + ARectI rc = rcGrid & rect; + //ASSERT(!rc.IsEmpty()); + + int dx = rc.left - rcGrid.left; + int dy = rc.top - rcGrid.top; + int iBaseVert = dy * (rcGrid.Width() + 1) + dx; + A3DVECTOR3 pVertDest = pVertBuf + iBaseVert; + + int sx = rc.left - rect.left; + int sy = rc.top - rect.top; + + pBlock.CopyFaces(pVertDest, pDestIdx, rc.Width(), rc.Height(), rcGrid.Width() + 1, iBaseVert, sx, sy); + + pDestIdx += rc.Width() * rc.Height() * 6; + rect.left += m_iBlockGrid; + rect.right += m_iBlockGrid; + } + } + + return true; + } // Get height and normal of specified position - public float GetPosHeight(A3DVECTOR3 vPos, A3DVECTOR3? pvNormal = null) + public float GetPosHeight(A3DVECTOR3 vPos, ref A3DVECTOR3 pvNormal) { // Give a default value to normal - if (pvNormal.HasValue) - pvNormal.Value.Clear(); + if (pvNormal != null) + pvNormal.Clear(); if (m_pCurActBlocks.rcArea.IsEmpty()) return 0.0f; // Currenly active area AABB - ARectF rcActive; + ARectF rcActive = new ARectF(); rcActive.left = m_rcTerrain.left + m_pCurActBlocks.rcArea.left * m_fBlockSize; rcActive.top = m_rcTerrain.top - m_pCurActBlocks.rcArea.top * m_fBlockSize; rcActive.right = rcActive.left + m_pCurActBlocks.rcArea.Width() * m_fBlockSize; @@ -76,12 +193,12 @@ namespace BrewMonster.Scripts.World float fInvBlockSize = 1.0f / m_fBlockSize; int iCol = (int)((vPos.x - rcActive.left) * fInvBlockSize); int iRow = (int)(-(vPos.z - rcActive.top) * fInvBlockSize); - a_Clamp(iCol, 0, m_pCurActBlocks.rcArea.Width() - 1); - a_Clamp(iRow, 0, m_pCurActBlocks.rcArea.Height() - 1); + AAssist.a_Clamp(ref iCol, 0, m_pCurActBlocks.rcArea.Width() - 1); + AAssist.a_Clamp(ref iRow, 0, m_pCurActBlocks.rcArea.Height() - 1); int iBlock = iRow * m_pCurActBlocks.rcArea.Width() + iCol; - A3DTerrain2Block* pBlock = m_pCurActBlocks.aBlocks[iBlock]; - if (!pBlock || !pBlock.IsDataLoaded()) + A3DTerrain2Block pBlock = m_pCurActBlocks.aBlocks[iBlock]; + if (pBlock == null || !pBlock.IsDataLoaded()) return 0.0f; // If whole block is a hole, return as if there is no block here @@ -89,17 +206,17 @@ namespace BrewMonster.Scripts.World return 0.0f; // Get block's AABB - const A3DAABB&aabb = pBlock.GetBlockAABB(); + A3DAABB aabb = pBlock.GetBlockAABB(); // Get grid this position is in float fInvGridSize = 1.0f / m_fGridSize; iCol = (int)((vPos.x - aabb.Mins.x) * fInvGridSize); iRow = (int)(-(vPos.z - aabb.Maxs.z) * fInvGridSize); - a_Clamp(iCol, 0, m_iBlockGrid - 1); - a_Clamp(iRow, 0, m_iBlockGrid - 1); + AAssist.a_Clamp(ref iCol, 0, m_iBlockGrid - 1); + AAssist.a_Clamp(ref iRow, 0, m_iBlockGrid - 1); int iGrid = iRow * m_iBlockGrid + iCol; - const A3DTerrain2LOD::GRID&Grid = m_pLODMan.GetGrids()[iGrid]; + GRID Grid = m_pLODMan.GetGrids()[iGrid]; A3DVECTOR3 v0 = pBlock.GetVertexPos(Grid.v0); A3DVECTOR3 v1 = pBlock.GetVertexPos(Grid.v1); @@ -122,9 +239,9 @@ namespace BrewMonster.Scripts.World vDest = v5 + (v4 - v5) * (dx / (v4.x - v5.x)); vDest += (v3 - v4) * (dz / (v3.z - v4.z)); - if (pvNormal) + if (pvNormal != null) { - pvNormal.CrossProduct(v4 - v3, v5 - v3); + pvNormal = A3DVECTOR3.CrossProduct(v4 - v3, v5 - v3); pvNormal.Normalize(); } } @@ -133,9 +250,9 @@ namespace BrewMonster.Scripts.World vDest = v2 + (v0 - v2) * (dz / (v0.z - v2.z)); vDest += (v1 - v0) * (dx / (v1.x - v0.x)); - if (pvNormal) + if (pvNormal != null) { - pvNormal.CrossProduct(v1 - v0, v2 - v0); + pvNormal= A3DVECTOR3.CrossProduct(v1 - v0, v2 - v0); pvNormal.Normalize(); } } @@ -150,9 +267,9 @@ namespace BrewMonster.Scripts.World vDest = v0 + (v1 - v0) * (dx / (v1.x - v0.x)); vDest += (v2 - v1) * (dz / (v2.z - v1.z)); - if (pvNormal) + if (pvNormal != null) { - pvNormal.CrossProduct(v1 - v0, v2 - v0); + pvNormal = A3DVECTOR3.CrossProduct(v1 - v0, v2 - v0); pvNormal.Normalize(); } } @@ -161,9 +278,9 @@ namespace BrewMonster.Scripts.World vDest = v3 + (v5 - v3) * (dz / (v5.z - v3.z)); vDest += (v4 - v5) * (dx / (v4.x - v5.x)); - if (pvNormal) + if (pvNormal != null) { - pvNormal.CrossProduct(v4 - v3, v5 - v3); + pvNormal = A3DVECTOR3.CrossProduct(v4 - v3, v5 - v3); pvNormal.Normalize(); } } @@ -172,4 +289,62 @@ namespace BrewMonster.Scripts.World return vDest.y; } } + + // Active blocks + public struct ACTBLOCKS + { + public ARectI rcArea; // Active area represented in blocks + public BlockArray aBlocks; // Active block array + + public ACTBLOCKS(ARectI rcArea, BlockArray aBlocks) + { + this.rcArea = rcArea; + this.aBlocks = aBlocks; + } + + // Get block object at specified row, column. + public A3DTerrain2Block GetBlock(int r, int c, bool bClear) + { + //ASSERT(rcArea.PtInRect(c, r)); + + int iIndex = GetBlockIndex(r, c); + A3DTerrain2Block pBlock = aBlocks[iIndex]; + + if (bClear) + aBlocks[iIndex] = null; + + return pBlock; + } + + // Set block object at specified row, column + void SetBlock(int r, int c, A3DTerrain2Block pBlock) + { + //ASSERT(rcArea.PtInRect(c, r)); + int iIndex = GetBlockIndex(r, c); + aBlocks[iIndex] = pBlock; + } + + // Get block index in aBlocks + int GetBlockIndex(int r, int c) + { + return (r - rcArea.top) * rcArea.Width() + c - rcArea.left; + } + }; + + // Block flags & masks + public class Block_flags_masks + { + public static uint T2BKFLAG_DEFAULT = 0x00, // The block flag default value + T2BKFLAG_NORENDER = 0x01, // The whole block is not rendered + T2BKFLAG_NOTRACE = 0x02, // The whole block is out of RayTrace + T2BKFLAG_NOPOSHEIGHT = 0x04, // The whole block is unable to GetPosHeight + T2BKFLAG_NORENDERWITHWATER = 0x08; // The whole block is not rendered with water + }; + + // Vertex indices in a terrain grid + public struct GRID + { + public int v0, v1, v2; // Face 1 + public int v3, v4, v5; // Face 2 + }; } diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs new file mode 100644 index 0000000000..6636b24e3b --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs @@ -0,0 +1,9 @@ +using BrewMonster.Scripts.World; +using UnityEngine; + +public class A3DTerrain2LOD +{ + public GRID[] m_aGrids; // Grid of a block + // Get grids + public GRID[] GetGrids() { return m_aGrids; } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta new file mode 100644 index 0000000000..adced35aa5 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ea4c2d97d77797548b9de5443e250290 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/ARect.cs b/Assets/PerfectWorld/Scripts/Managers/ARect.cs new file mode 100644 index 0000000000..4a13c814a9 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/ARect.cs @@ -0,0 +1,280 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace BrewMonster.Scripts +{ + public class ARect where T : IComparable + { + public T left, top, right, bottom; + + public ARect() + { + left = default(T); + top = default(T); + right = default(T); + bottom = default(T); + } + + public ARect(ARect rc) + { + left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; + } + + public ARect(T left, T top, T right, T bottom) + { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + // == and != operator + public static bool operator !=(ARect rc1, ARect rc2) + { + return !(rc1 == rc2); + } + public static bool operator ==(ARect rc1, ARect rc2) + { + return EqualityComparer.Default.Equals(rc1.left, rc2.left) && + EqualityComparer.Default.Equals(rc1.top, rc2.top) && + EqualityComparer.Default.Equals(rc1.right, rc2.right) && + EqualityComparer.Default.Equals(rc1.bottom, rc2.bottom); + } + + // + and - operator + public static ARect operator +(ARect rc1, ARect rc2) + { + dynamic l = rc1.left, t = rc1.top, r = rc1.right, b = rc1.bottom; + dynamic l2 = rc2.left, t2 = rc2.top, r2 = rc2.right, b2 = rc2.bottom; + return new ARect(l + l2, t + t2, r + r2, b + b2); + } + public static ARect operator -(ARect rc1, ARect rc2) + { + return new ARect((dynamic)rc1.left - (dynamic)rc2.left, + (dynamic)rc1.top - (dynamic)rc2.top, + (dynamic)rc1.right - (dynamic)rc2.right, + (dynamic)rc1.bottom - (dynamic)rc2.bottom); + } + //public static ARect operator +(ARect rc1, APoint pt) + //{ + // return new ARect((dynamic)rc1.left + (dynamic)pt.x, + // (dynamic)rc1.top + (dynamic)pt.y, + // (dynamic)rc1.right + (dynamic)pt.x, + // (dynamic)rc1.bottom + (dynamic)pt.y); + //} + //public static ARect operator -(ARect rc1, APoint pt) + //{ + // return new ARect((dynamic)rc1.left - (dynamic)pt.x, + // (dynamic)rc1.top - (dynamic)pt.y, + // (dynamic)rc1.right - (dynamic)pt.x, + // (dynamic)rc1.bottom - (dynamic)pt.y); + //} + + // &= and |= operator + public ARect AndAssign(ARect rc) => this & rc; + public ARect OrAssign(ARect rc) => this | rc; + + public static ARect operator &(ARect rc1, ARect rc2) + { + if (rc1.IsEmpty() || rc2.IsEmpty()) + return new ARect(default, default, default, default); + + dynamic l1 = rc1.left, r1 = rc1.right, t1 = rc1.top, b1 = rc1.bottom; + dynamic l2 = rc2.left, r2 = rc2.right, t2 = rc2.top, b2 = rc2.bottom; + + if (l1 >= r2 || l2 >= r1 || + t1 >= b2 || t2 >= b1) + return new ARect(default, default, default, default); + + return new ARect(l1 > l2 ? l1 : l2, + t1 > t2 ? t1 : t2, + r1 < r2 ? r1 : r2, + b1 < b2 ? b1 : b2); + } + + public static ARect operator |(ARect rc1, ARect rc2) + { + if (rc1.IsEmpty()) + return rc2; + + if (rc2.IsEmpty()) + return rc1; + + dynamic l1 = rc1.left, r1 = rc1.right, t1 = rc1.top, b1 = rc1.bottom; + dynamic l2 = rc2.left, r2 = rc2.right, t2 = rc2.top, b2 = rc2.bottom; + + return new ARect(l1 < l2 ? l1 : l2, + t1 < t2 ? t1 : t2, + r1 > r2 ? r1 : r2, + b1 > b2 ? b1 : b2); + } + + public static ARect operator +(ARect rc) { return rc; } + public static ARect operator -(ARect rc) + { + return new ARect(-(dynamic)rc.left, -(dynamic)rc.top, -(dynamic)rc.right, -(dynamic)rc.bottom); + } + + // = operator + //public static ARect operator = (ARect rc) { left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; return *this; } + + // += and -= operator + public ARect AdditionAssign(ARect rc) + { + left += (dynamic)rc.left; + top += (dynamic)rc.top; + right += (dynamic)rc.right; + bottom += (dynamic)rc.bottom; + return this; + } + public ARect SubtractionAssign(ARect rc) + { + left -= (dynamic)rc.left; + top -= (dynamic)rc.top; + right -= (dynamic)rc.right; + bottom -= (dynamic)rc.bottom; + return this; + } + //public ARect AdditionAssign(APoint pt) { left += pt.x; top += pt.y; right += pt.x; bottom += pt.y; return this; } + //public ARect SubtractionAssign(APoint pt) { left -= pt.x; top -= pt.y; right -= pt.x; bottom -= pt.y; return this; } + + // Get width of rectangle + public T Width() + { + return (dynamic)right - (dynamic)left; + } + // Get height of rectangle + public T Height() + { + return (dynamic)bottom - (dynamic)top; + } + // Get center point of rectangle + //public APoint CenterPoint() { return new APoint((left + right) / 2, (top + bottom) / 2); } + // Set rectangle value + public void SetRect(T _left, T _top, T _right, T _bottom) + { + left = _left; + top = _top; + right = _right; + bottom = _bottom; + } + + // Point in rectangle + public bool PtInRect(T x, T y) + { + dynamic valueX = x; + dynamic valueY = y; + return (valueX >= left && valueX < right && valueY >= top && valueY < bottom) ? true : false; + } + //public bool PtInRect(APoint pt) { return PtInRect(pt.x, pt.y); } + + // Normalize rectangle. Note: The following CRect member functions require + // normalized rectangles in order to work properly: Height, Width, Size, + // IsEmpty, PtInRect, SetUnion, SetIntersect, operator ==, operator !=, + // operator |, operator |=, operator &, and operator &= + void Normalize() + { + if ((dynamic)left > right) + a_Swap(left, right); + + if ((dynamic)top > bottom) + a_Swap(top, bottom); + } + + private void a_Swap(T lhs, T rhs) + { + T tmp; + tmp = lhs; + lhs = rhs; + rhs = tmp; + } + + // All members are 0 ? + public bool IsRectNull() + { + return ((dynamic)left == 0 && (dynamic)top == 0 && (dynamic)right == 0 && (dynamic)bottom == 0); + } + // Rectangle is empty ? + public bool IsEmpty() + { + return ((dynamic)Width() == 0 || (dynamic)Height() == 0); + } + // Set all members to 0 + public void Clear() + { + left = top = right = bottom = default(T); + } + // Deflate rectangle + public void Deflate(T x, T y) + { + left += (dynamic)x; + top += (dynamic)y; + right -= (dynamic)x; + bottom -= (dynamic)y; + } + public void Deflate(ARect rc) + { + left += (dynamic)rc.left; + top += (dynamic)rc.top; + right -= (dynamic)rc.right; + bottom -= (dynamic)rc.bottom; + } + public void Deflate(T l, T t, T r, T b) + { + left += (dynamic)l; + top += (dynamic)t; + right -= (dynamic)r; + bottom -= (dynamic)b; + } + // Inflate rectangle + public void Inflate(T x, T y) + { + left -= (dynamic)x; + top -= (dynamic)y; + right += (dynamic)x; + bottom += (dynamic)y; + } + public void Inflate(ARect rc) + { + left -= (dynamic)rc.left; + top -= (dynamic)rc.top; + right += (dynamic)rc.right; + bottom += (dynamic)rc.bottom; + } + public void Inflate(T l, T t, T r, T b) + { + left -= (dynamic)l; + top -= (dynamic)t; + right += (dynamic)r; + bottom += (dynamic)b; + } + // Offset rectangle + public void Offset(T x, T y) + { + left += (dynamic)x; + top += (dynamic)y; + right += (dynamic)x; + bottom += (dynamic)y; + } + //public void Offset(APoint pt) { this += pt; } + // Set rectangle as union result + public void SetUnion(ARect rc1, ARect rc2) + { + var result = rc1 | rc2; + left = result.left; + right = result.right; + bottom = result.bottom; + top = result.top; + } + // Set rectangle as intersect result + public void SetIntersect(ARect rc1, ARect rc2) + { + var result = rc1 & rc2; + left = result.left; + right = result.right; + bottom = result.bottom; + top = result.top; + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta b/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta new file mode 100644 index 0000000000..66c5766867 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 00eedf309b0008346a58412f4aad4dec \ No newline at end of file diff --git a/Assets/Scripts/Move/EC_CDR.cs b/Assets/Scripts/Move/EC_CDR.cs index 4b7b0506ca..5d91a37209 100644 --- a/Assets/Scripts/Move/EC_CDR.cs +++ b/Assets/Scripts/Move/EC_CDR.cs @@ -1,6 +1,8 @@ -using CSNetwork.GPDataType; -using UnityEditor.PackageManager; +using BrewMonster.Scripts.World; +using CSNetwork.GPDataType; +using System; using UnityEngine; +using WORD = System.UInt16; namespace BrewMonster.Scripts { @@ -312,38 +314,37 @@ namespace BrewMonster.Scripts bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart) { - CECWorld pWorld = g_pGame.GetGameRun().GetWorld(); - A3DTerrain2 pTerrain = pWorld.GetTerrain(); - bStart = false; - float h1 = pTerrain.GetPosHeight(vStart, &vHitNormal); - if (h1 > vStart.y + 1E-4f ) - {//start under terrain - bStart = true; - fFraction = 0.0f; - return true; - } + CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld(); + A3DTerrain2 pTerrain = pWorld.GetTerrain(); + bStart = false; + float h1 = pTerrain.GetPosHeight(vStart, ref vHitNormal); + if (h1 > vStart.y + 1E-4f ) + {//start under terrain + bStart = true; + fFraction = 0.0f; + return true; + } + int nWid, nHei; // in grid, 2 meters + float fMag = vDelta.Magnitude(); - int nWid, nHei; // in grid, 2 meters - float fMag = vDelta.Magnitude(); - - nWid = (int) ceil(fMag / 2.0f); - nWid = a_Max(3, nWid); - nHei = nWid; - int nTriangles = nWid * nHei * 2; - A3DVECTOR3* pVerts = (A3DVECTOR3*)a_malloctemp(sizeof(A3DVECTOR3) * ((nWid + 1) * (nHei + 1))); - assert(pVerts != NULL); - memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1)); - WORD* pIndices = (WORD*)a_malloctemp(sizeof(WORD) * (nTriangles * 3)); - assert(pIndices != NULL); - memset(pIndices, 0, sizeof(WORD)* nTriangles * 3); - if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, pVerts, pIndices)) - { - a_freetemp(pVerts); - a_freetemp(pIndices); - return false; - } -int i; + nWid = (int)Math.Ceiling(fMag / 2.0f); + nWid = Math.Max(3, nWid); + nHei = nWid; + int nTriangles = nWid * nHei * 2; + A3DVECTOR3[] pVerts = new A3DVECTOR3[(nWid + 1) * (nHei + 1)]; + //assert(pVerts != NULL); + //memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1)); + WORD[] pIndices = new WORD[nTriangles * 3]; + //assert(pIndices != NULL); + //memset(pIndices, 0, sizeof(WORD)* nTriangles * 3); + if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, pVerts, pIndices)) + { + //a_freetemp(pVerts); + // a_freetemp(pIndices); + return false; + } + int i; A3DVECTOR3* vert[3]; //@note : Here init the fraction. By Kuiwu[9/10/2005] fFraction = 100.0f; @@ -384,26 +385,6 @@ fFraction = a_Max(0.0f, tmpFraction); a_freetemp(pVerts); a_freetemp(pIndices); -# ifdef CDR_DEBUG -// if (fFraction <= 1.0f) -// { -// A3DVECTOR3 vHitPos(vStart + vDelta * fFraction); -// A3DVECTOR3 vTerNormal; -// float fH2 = pTerrain.GetPosHeight(vHitPos, &vTerNormal); -// sprintf(msg, "terrain hit %f %f %f normal %f %f %f trcNormal %f %f %f fFraction %f\n", vHitPos.x, vHitPos.y, vHitPos.z, -// vHitNormal.x, vHitNormal.y, vHitNormal.z, vTerNormal.x, vTerNormal.y, vTerNormal.z, fFraction); -// OUTPUT_DEBUG_INFO(msg); -// -// //vHitNormal = vTerNormal; -// } -// else -// { -// A3DVECTOR3 vEnd(vStart + vDelta); -// float fH2 = pTerrain.GetPosHeight(vEnd); -// sprintf(msg, "terrain test clear %f %f %f height %f\n", vEnd.x, vEnd.y, vEnd.z,fH2); -// OUTPUT_DEBUG_INFO(msg); -// } -#endif return (fFraction <= 1.0f); } From 8ea53ac651c24b08607c99fcfa8948be9986ccde Mon Sep 17 00:00:00 2001 From: Tungdv Date: Thu, 16 Oct 2025 18:35:15 +0700 Subject: [PATCH 4/6] fix: update logic check bush. --- .../Scripts/Managers/A3DTerrain2.cs | 214 ++++++++++++- .../Scripts/Managers/A3DTerrain2LOD.cs | 5 +- Assets/PerfectWorld/Scripts/Managers/ARect.cs | 3 +- .../Scripts/Managers/CECNPCMan.cs | 1 + .../Scripts/Managers/EC_BrushMan.cs | 55 ++++ .../Scripts/Managers/EC_BrushMan.cs.meta | 2 + .../Scripts/Managers/EC_OrnamentMan.cs | 98 ++++++ .../Scripts/Managers/EC_OrnamentMan.cs.meta | 2 + Assets/PerfectWorld/Scripts/World/CECWorld.cs | 8 +- Assets/Scripts/Move/EC_CDR.cs | 283 +++++++++++++----- 10 files changed, 579 insertions(+), 92 deletions(-) create mode 100644 Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs.meta create mode 100644 Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs.meta diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs index f2d6deeda0..f802c783da 100644 --- a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs @@ -1,9 +1,9 @@ -using CSNetwork.GPDataType; -using UnityEngine; -using ARectI = BrewMonster.Scripts.ARect; -using ARectF = BrewMonster.Scripts.ARect; -using BlockArray = System.Collections.Generic.List; using BrewMonster.Scripts.Player; +using CSNetwork.GPDataType; +using System.Linq; +using ARectF = BrewMonster.Scripts.ARect; +using ARectI = BrewMonster.Scripts.ARect; +using BlockArray = System.Collections.Generic.List; using WORD = System.UInt16; namespace BrewMonster.Scripts.World @@ -26,7 +26,7 @@ namespace BrewMonster.Scripts.World }; // Terrain2 vertex format when use vertex-light (not lightmap) - struct A3DTRN2VERTEX2 + public struct A3DTRN2VERTEX2 { public float vPosX; // Position X public float vPosY; // Position Y @@ -43,8 +43,10 @@ namespace BrewMonster.Scripts.World public bool IsDataLoaded() { return m_bDataLoaded; } public uint m_dwBlockFlags; // Block flags public A3DAABB m_aabbBlock; // Block postion and size in whole world - A3DTRN2VERTEX1[] m_aVertices1; // Vertex buffer, ps version - A3DTRN2VERTEX2[] m_aVertices2; // Vertex buffer, non-ps version + public A3DTRN2VERTEX1[] m_aVertices1; // Vertex buffer, ps version + public A3DTRN2VERTEX2[] m_aVertices2; // Vertex buffer, non-ps version + public A3DTerrain2 m_pTerrain; // Terrain object + public int m_iBlockGrid; // Each block has m_iBlockGrid * m_iBlockGrid terrain grids // Get block's position and size in whole world public A3DAABB GetBlockAABB() { return m_aabbBlock; } @@ -65,6 +67,165 @@ namespace BrewMonster.Scripts.World return new A3DVECTOR3(m_aVertices2[n].vPosX, m_aVertices2[n].vPosY, m_aVertices2[n].vPosZ); } } + + /* Copy block vertices to destination buffer. This function works like BitBlt. + Copy vertex positions in a rectangle grid area to destination buffer, every + vertex is like a pixel in BitBlt; + + pDestBuf: destination vertex buffer + iWid, iHei: vertex rectangle area's size + iDestPitch: destination vertex buffer pitch in A3DVECTOR3 + sx, sy: grid rectangle area's left-top corner in block +*/ + public bool CopyVertexPos(ref A3DVECTOR3[] pDestBuf, int iWid, int iHei, + int iDestPitch, int sx, int sy) + { + WORD[] aIndexMaps = m_pTerrain.GetLODManager().GetIndexMaps(); + int pDestLine = 0; + int iSrcLine = sy * (m_iBlockGrid + 1) + sx; + + if (m_pTerrain.UseLightmapTech()) + { + //ASSERT(m_aVertices1); + + for (int i = 0; i < iHei; i++) + { + int destIndex = pDestLine; + int iSrc = iSrcLine; + pDestLine += iDestPitch; + iSrcLine += m_iBlockGrid + 1; + + for (int j = 0; j < iWid; j++, destIndex++, iSrc++) + { + // Note: here we map index + A3DTRN2VERTEX1 pSrc = m_aVertices1[aIndexMaps[iSrc]]; + + pDestBuf[destIndex].x = pSrc.vPosX; + pDestBuf[destIndex].y = pSrc.vPosY; + pDestBuf[destIndex].z = pSrc.vPosZ; + } + } + } + else + { + for (int i = 0; i < iHei; i++) + { + int pDest = pDestLine; + int iSrc = iSrcLine; + pDestLine += iDestPitch; + iSrcLine += m_iBlockGrid + 1; + + for (int j = 0; j < iWid; j++, pDest++, iSrc++) + { + var pSrc = m_aVertices2[aIndexMaps[iSrc]]; + + pDestBuf[pDest].x = pSrc.vPosX; + pDestBuf[pDest].y = pSrc.vPosY; + pDestBuf[pDest].z = pSrc.vPosZ; + } + } + } + + return true; + } + + /* Copy grid faces to destination buffer. This function works like BitBlt. + Copy face in a rectangle grid area to destination buffer, every face is + like a pixel in BitBlt; + + pDestVert: destination vertex buffer + pDestIdx: destination index buffer + iWid, iHei: grid rectangle area's size + iDstVertPitch: destination vertex buffer pitch in A3DVECTOR3 + iBaseVert: Index of left-top corner vertex in vertex buffer + sx, sy: grid rectangle area's left-top corner in block +*/ + public bool CopyFaces(ref A3DVECTOR3[] pDestVert, ref WORD[] pDestIdx, int iWid, int iHei, + int iDstVertPitch, int iBaseVert, int sx, int sy) + { + // Copy vertices at first. Notice the difference of iWid and iHei in this + // function and in CopyVertexPos() + CopyVertexPos(ref pDestVert, iWid + 1, iHei + 1, iDstVertPitch, sx, sy); + + // Build indices + int pIndices = 0; + + for (int i = 0; i < iHei; i++) + { + WORD v0 = (WORD)iBaseVert; + iBaseVert += iDstVertPitch; + + for (int j = 0; j < iWid; j++, pIndices += 6, v0++) + { + // v3 v0----v1 + // | \ \ | + // | \ \ | + // | \ \ | + // | \ \ | + // v5---v4 v2 + pDestIdx[pIndices] = v0; + pDestIdx[pIndices + 1] = (WORD)(v0 + 1); + pDestIdx[pIndices + 2] = (WORD)(v0 + iDstVertPitch + 1); + + pDestIdx[pIndices + 3] = v0; + pDestIdx[pIndices + 4] = (WORD)(v0 + iDstVertPitch + 1); + pDestIdx[pIndices + 5] = (WORD)(v0 + iDstVertPitch); + } + } + + // If this area contain block's right-top corner grid or left-bottom + // corner grid, then we have to adjust index so that they are in + // rendering order + if (sx == 0 && sy + iHei == m_iBlockGrid) + { + // Contain left-bottom corner grid + // v0----v1 + // | / | + // | / | + // | / | + // | / | + // v2----v3 + int offer = (iHei - 1) * iWid * 6; + WORD v0 = pDestIdx[offer]; + WORD v1 = pDestIdx[offer + 1]; + WORD v2 = pDestIdx[offer + 5]; + WORD v3 = pDestIdx[offer + 2]; + + pDestIdx[offer] = v0; + pDestIdx[offer + 1] = v1; + pDestIdx[offer + 2] = v2; + + pDestIdx[offer + 3] = v1; + pDestIdx[offer + 4] = v3; + pDestIdx[offer + 5] = v2; + } + + if (sx + iWid == m_iBlockGrid && sy == 0) + { + // Contain right-top corner grid + // v0----v1 + // | / | + // | / | + // | / | + // | / | + // v2----v3 + int offer = (iWid - 1) * 6; + WORD v0 = pDestIdx[offer]; + WORD v1 = pDestIdx[offer + 1]; + WORD v2 = pDestIdx[offer + 5]; + WORD v3 = pDestIdx[offer + 2]; + + pDestIdx[offer + 0] = v0; + pDestIdx[offer + 1] = v1; + pDestIdx[offer + 2] = v2; + + pDestIdx[offer + 3] = v1; + pDestIdx[offer + 4] = v3; + pDestIdx[offer + 5] = v2; + } + + return true; + } } public class A3DTerrain2 @@ -75,9 +236,18 @@ namespace BrewMonster.Scripts.World public int m_iBlockGrid = 0; // Each block has m_iBlockGrid * m_iBlockGrid terrain grids public float m_fGridSize; // Terrain grid size (on x and z axis) in logic unit (metres) public A3DTerrain2LOD m_pLODMan; // LOD manager + public int m_iNumActBlockRow; // Row and column number of active blocks + public int m_iNumAllBlockRow = 0; // Row number of all blocks + public int m_iNumAllBlockCol = 0; // Column number of all blocks + public bool m_bVertexLight = false; // true, force to use vertex light rather than lightmap + + // Check lightmap or vertex-light is used + public bool UseLightmapTech() { return !m_bVertexLight; } + + public A3DTerrain2LOD GetLODManager() { return m_pLODMan; } // Get grid faces of specified area - public bool GetFacesOfArea(A3DVECTOR3 vCenter, int iGridWid, int iGridLen, A3DVECTOR3 pVertBuf, WORD pIdxBuf) + public bool GetFacesOfArea(A3DVECTOR3 vCenter, int iGridWid, int iGridLen, ref A3DVECTOR3[] pVertBuf, ref WORD[] pIdxBuf) { if (m_pCurActBlocks.rcArea.IsEmpty()) return false; @@ -90,10 +260,10 @@ namespace BrewMonster.Scripts.World rcGrid.right = rcGrid.left + iGridWid; rcGrid.bottom = rcGrid.top + iGridLen; - return GetFacesOfArea(rcGrid, pVertBuf, pIdxBuf); + return GetFacesOfArea(rcGrid, ref pVertBuf, ref pIdxBuf); } - public bool GetFacesOfArea(ARectI rcGridArea, A3DVECTOR3 pVertBuf, WORD pIdxBuf) + public bool GetFacesOfArea(ARectI rcGridArea, ref A3DVECTOR3[] pVertBuf, ref WORD[] pIdxBuf) { if (m_pCurActBlocks.rcArea.IsEmpty()) return false; @@ -126,12 +296,14 @@ namespace BrewMonster.Scripts.World for (c = rcBlock.left; c <= rcBlock.right; c++) { if (!m_pCurActBlocks.rcArea.PtInRect(c, r) || - !m_pCurActBlocks.GetBlock(r, c, false)) + m_pCurActBlocks.GetBlock(r, c, false) == null) return false; } } - WORD pDestIdx = pIdxBuf; + int pDestIdx = 0; + A3DVECTOR3[] pVertDest = new A3DVECTOR3[0]; + WORD[] pIdxTemp = new WORD[0]; for (r = rcBlock.top; r <= rcBlock.bottom; r++) { @@ -152,12 +324,22 @@ namespace BrewMonster.Scripts.World int dx = rc.left - rcGrid.left; int dy = rc.top - rcGrid.top; int iBaseVert = dy * (rcGrid.Width() + 1) + dx; - A3DVECTOR3 pVertDest = pVertBuf + iBaseVert; + pVertDest = pVertBuf.Skip(iBaseVert).ToArray(); + pIdxTemp = pIdxBuf.Skip(pDestIdx).ToArray(); int sx = rc.left - rect.left; int sy = rc.top - rect.top; - pBlock.CopyFaces(pVertDest, pDestIdx, rc.Width(), rc.Height(), rcGrid.Width() + 1, iBaseVert, sx, sy); + pBlock.CopyFaces(ref pVertDest, ref pIdxTemp, rc.Width(), rc.Height(), rcGrid.Width() + 1, iBaseVert, sx, sy); + + for (int i = iBaseVert; i < pVertBuf.Length; i++) + { + pVertBuf[i] = pVertDest[i - iBaseVert]; + } + for (int i = 0; i < pIdxBuf.Length; i++) + { + pIdxBuf[i] = pIdxTemp[i - pDestIdx]; + } pDestIdx += rc.Width() * rc.Height() * 6; rect.left += m_iBlockGrid; @@ -252,7 +434,7 @@ namespace BrewMonster.Scripts.World if (pvNormal != null) { - pvNormal= A3DVECTOR3.CrossProduct(v1 - v0, v2 - v0); + pvNormal = A3DVECTOR3.CrossProduct(v1 - v0, v2 - v0); pvNormal.Normalize(); } } diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs index 6636b24e3b..2098bb2af6 100644 --- a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs @@ -1,9 +1,12 @@ using BrewMonster.Scripts.World; -using UnityEngine; +using WORD = System.UInt16; public class A3DTerrain2LOD { public GRID[] m_aGrids; // Grid of a block + public WORD[] m_aIndexMaps; // Index map + // Get grids public GRID[] GetGrids() { return m_aGrids; } + public WORD[] GetIndexMaps() { return m_aIndexMaps; } } diff --git a/Assets/PerfectWorld/Scripts/Managers/ARect.cs b/Assets/PerfectWorld/Scripts/Managers/ARect.cs index 4a13c814a9..48dff7a51f 100644 --- a/Assets/PerfectWorld/Scripts/Managers/ARect.cs +++ b/Assets/PerfectWorld/Scripts/Managers/ARect.cs @@ -47,7 +47,8 @@ namespace BrewMonster.Scripts { dynamic l = rc1.left, t = rc1.top, r = rc1.right, b = rc1.bottom; dynamic l2 = rc2.left, t2 = rc2.top, r2 = rc2.right, b2 = rc2.bottom; - return new ARect(l + l2, t + t2, r + r2, b + b2); + ARect result = new ARect(l + l2, t + t2, r + r2, b + b2); + return result; } public static ARect operator -(ARect rc1, ARect rc2) { diff --git a/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs b/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs index 88961d9c7b..6e7f8cbfdc 100644 --- a/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs +++ b/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs @@ -1,5 +1,6 @@ using BrewMonster; using BrewMonster.Managers; +using BrewMonster.Scripts.World; using CSNetwork; using CSNetwork.GPDataType; using DG.Tweening; diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs b/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs new file mode 100644 index 0000000000..975631466f --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Numerics; +using UnityEngine; +namespace BrewMonster.Scripts +{ + //@desc : using grid to manage the brushes. By Kuiwu[2/11/2005] + public class CBrushGrid + { + //public CBrushGrid(int iCellSize = 80, int iW = 11, int iH = 11); + + // void AddProvider(CBrushProvider* pProvider); + // bool RemoveProvider(CBrushProvider* pProvider); + // void Build(const A3DVECTOR3& vCenter, bool bForce = false); + public bool Trace(BrushTraceInfo pInfo, bool bCheckFlag = true) + { + return false; + } + +#if BMAN_VERBOSE_STAT + CBManStat * GetStat() + { + return &m_Stat; + } +#endif + + + // private int m_iCellSize; + // private int m_iW, m_iH; //in cell + // private short m_iCenterX, m_iCenterZ; + // private float m_fTraceRange2; + + // private CBrushCell m_pBrushCell; //as a brush cell buffer + // //@note : use hash table to accelerate searching cell buffer. By Kuiwu[2/11/2005] + // private Dictionary CellTable; + // private CellTable m_CellTbl; + + // private vector m_UnOrganizedProvider; //to be built. + // private vector m_OutOfRangeBrush; + + // private void _GetCellIndex(const A3DVECTOR3& vPos, short& x, short& z); + //private CBrushCell * _FindCell(short x, short z); + + // private bool _UpdateCenter(const A3DVECTOR3& vCenter, bool bForce); + // private bool _AddBrush(CCDBrush pBrush); +#if BMAN_VERBOSE_STAT + CBManStat m_Stat; +#endif + + } + + public class CECBrushMan + { + public CBrushGrid m_pBrushGrid; + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs.meta new file mode 100644 index 0000000000..1cc88f8059 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: dbb7777494908644db0a9f59f533162d \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs new file mode 100644 index 0000000000..e1cc6580a4 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs @@ -0,0 +1,98 @@ +using CSNetwork.GPDataType; +using UnityEngine; + +namespace BrewMonster.Scripts.Ornament +{ + public class CECOrnamentMan + { + CECBrushMan m_pBrushMan; + // Trace for CD + public virtual bool TraceWithBrush(ref BrushTraceInfo pInfo) + { + bool bCollide = false; + //save original result + bool bStartSolid = pInfo.bStartSolid; // Collide something at start point + bool bAllSolid = pInfo.bAllSolid; // All in something + int iClipPlane = pInfo.iClipPlane; // Clip plane's index + float fFraction = 100.0f; // Fraction + A3DVECTOR3 vNormal = pInfo.ClipPlane.GetNormal(); //clip plane normal + float fDist = pInfo.ClipPlane.GetDist(); //clip plane dist + + if (m_pBrushMan != null && m_pBrushMan.Trace(pInfo) + && (pInfo.fFraction < fFraction)) + { + fFraction = pInfo.fFraction; + bAllSolid = pInfo.bAllSolid; + bStartSolid = pInfo.bStartSolid; + iClipPlane = pInfo.iClipPlane; + vNormal = pInfo.ClipPlane.GetNormal(); + fDist = pInfo.ClipPlane.GetDist(); + bCollide = true; + } + + HomeOnmtTable::iterator it1 = m_HomeOrnamentTab.begin(); + for (; it1 != m_HomeOrnamentTab.end(); ++it1) + { + CECHomeOrnament* pHomeOrnament = *it1.value(); + if (!pHomeOrnament.IsLoaded()) + continue; + + CELBuildingWithBrush* pBuildingWithBrush = pHomeOrnament.GetBuildingWithBrush(); + if (pBuildingWithBrush && pBuildingWithBrush.TraceWithBrush(pInfo) && (pInfo.fFraction < fFraction)) + { + fFraction = pInfo.fFraction; + bAllSolid = pInfo.bAllSolid; + bStartSolid = pInfo.bStartSolid; + iClipPlane = pInfo.iClipPlane; + vNormal = pInfo.ClipPlane.GetNormal(); + fDist = pInfo.ClipPlane.GetDist(); + bCollide = true; + } + } + + // now see if collide with forest + CELForest* pForest = g_pGame.GetGameRun().GetWorld().GetForest(); + if ((fFraction > 0.0f) && pForest + && pForest.TraceWithBrush(pInfo) + && (pInfo.fFraction < fFraction)) + { + fFraction = pInfo.fFraction; + bAllSolid = pInfo.bAllSolid; + bStartSolid = pInfo.bStartSolid; + iClipPlane = pInfo.iClipPlane; + vNormal = pInfo.ClipPlane.GetNormal(); + fDist = pInfo.ClipPlane.GetDist(); + bCollide = true; + } + + // now see if collide with dynamic scene building + ECModelTable::iterator it = m_ECModelTab.begin(); + for (; it != m_ECModelTab.end(); ++it) + { + ECMODELNODE* pNode = *it.value(); + if ((fFraction > 0.0f) && pNode + && pNode.TraceWithBrush(pInfo) + && (pInfo.fFraction < fFraction)) + { + fFraction = pInfo.fFraction; + bAllSolid = pInfo.bAllSolid; + bStartSolid = pInfo.bStartSolid; + iClipPlane = pInfo.iClipPlane; + vNormal = pInfo.ClipPlane.GetNormal(); + fDist = pInfo.ClipPlane.GetDist(); + bCollide = true; + } + } + + //set back + pInfo.fFraction = fFraction; + pInfo.bStartSolid = bStartSolid; + pInfo.bAllSolid = bAllSolid; + pInfo.iClipPlane = iClipPlane; + pInfo.ClipPlane.SetNormal(vNormal); + pInfo.ClipPlane.SetD(fDist); + return bCollide; + + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs.meta new file mode 100644 index 0000000000..4448024055 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 90848592c1c53d04e87291f2c1bfafdb \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/World/CECWorld.cs b/Assets/PerfectWorld/Scripts/World/CECWorld.cs index a4cc2e7679..fb4e33b65c 100644 --- a/Assets/PerfectWorld/Scripts/World/CECWorld.cs +++ b/Assets/PerfectWorld/Scripts/World/CECWorld.cs @@ -1,4 +1,5 @@ using BrewMonster; +using BrewMonster.Scripts.Ornament; using UnityEngine; @@ -7,7 +8,7 @@ namespace BrewMonster.Scripts.World public class CECWorld : MonoSingleton { protected A3DTerrain2 m_pA3DTerrain; // Terrain object - + CECOrnamentMan m_pOnmtMan; uint m_dwBornStamp = 0; public uint GetBornStamp() { return m_dwBornStamp++; } @@ -17,5 +18,10 @@ namespace BrewMonster.Scripts.World { return m_pA3DTerrain; } + + public CECOrnamentMan GetOrnamentMan() + { + return m_pOnmtMan; + } } } diff --git a/Assets/Scripts/Move/EC_CDR.cs b/Assets/Scripts/Move/EC_CDR.cs index 5d91a37209..898bc960bc 100644 --- a/Assets/Scripts/Move/EC_CDR.cs +++ b/Assets/Scripts/Move/EC_CDR.cs @@ -1,4 +1,6 @@ -using BrewMonster.Scripts.World; +using BrewMonster.Scripts.Ornament; +using BrewMonster.Scripts.Player; +using BrewMonster.Scripts.World; using CSNetwork.GPDataType; using System; using UnityEngine; @@ -12,6 +14,7 @@ namespace BrewMonster.Scripts public static LayerMask BrushMask { get; set; } = ~0; public static LayerMask TerrainMask { get; set; } = ~0; + const float LOCAL_EPSILON = 1e-5f; //[Flags] public class CDR_EVN { @@ -63,20 +66,20 @@ namespace BrewMonster.Scripts A3DVECTOR3 vWatNormal = new A3DVECTOR3(); bool bStart = false; //@todo : TBD: use center or foot? By Kuiwu[10/10/2005] - if (CollideWithWater(pEnvTrc.vWatStart, pEnvTrc.vDelta, pEnvTrc.bWaterSolid, ref fFraction, ref vWatNormal, ref bStart) - && fFraction < pEnvTrc.fFraction) - { - pEnvTrc.fFraction = fFraction; - pEnvTrc.vHitNormal = vWatNormal; - pEnvTrc.bStartSolid = bStart; - pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER; - //# ifdef CDR_DEBUG - // A3DVECTOR3 vHitPos(pEnvTrc.vWatStart +pEnvTrc.vDelta * fFraction); - // sprintf(msg, "collide water, fraction %f pos %f %f %f \n", fFraction, vHitPos.x, vHitPos.y, vHitPos.z); - // OUTPUT_DEBUG_INFO(msg); - //#endif + //if (CollideWithWater(pEnvTrc.vWatStart, pEnvTrc.vDelta, pEnvTrc.bWaterSolid, ref fFraction, ref vWatNormal, ref bStart) + // && fFraction < pEnvTrc.fFraction) + //{ + // pEnvTrc.fFraction = fFraction; + // pEnvTrc.vHitNormal = vWatNormal; + // pEnvTrc.bStartSolid = bStart; + // pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER; + // //# ifdef CDR_DEBUG + // // A3DVECTOR3 vHitPos(pEnvTrc.vWatStart +pEnvTrc.vDelta * fFraction); + // // sprintf(msg, "collide water, fraction %f pos %f %f %f \n", fFraction, vHitPos.x, vHitPos.y, vHitPos.z); + // // OUTPUT_DEBUG_INFO(msg); + // //#endif - } + //} } return (pEnvTrc.fFraction < 1.0f + 1E-4f); @@ -311,83 +314,217 @@ namespace BrewMonster.Scripts if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal; } - bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart) -{ + static bool SegmentTriangleIntersect(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, A3DVECTOR3[] vert, ref float fFraction, bool bCull) + { + float dist = 0f; + A3DVECTOR3 vDir = new A3DVECTOR3(vDelta); + + dist = vDir.Normalize(); + if (dist < 1E-5f) + { + //assert(0 && "too small dist!"); + fFraction = 0.0f; + return true; + } + + float t = 0f, u = 0f, v = 0f; + + if (RayTriangleIntersect(vStart, vDir, vert, ref t, ref u, ref v, bCull) && (t >= 0.0f) && (t <= dist)) + { + //fFraction = t/dist; + //fFraction = a_Max( 0.0f, fFraction -1E-4f); //put back + fFraction = (t - 5E-4f) / dist; + AAssist.a_ClampFloor(ref fFraction, 0.0f); + return true; + } + + return false; + } + + /* + * ray: origin + t* dir, triangle: p(u,v) = (1-u -v)vert[0] + u*vert[1] + v*vert[2] + * @desc : + * @param vDir: normalized direction + * @param bCull: cull back face if true + * @return : + * @note: + * @todo: + * @author: kuiwu [8/10/2005] + * @ref: Tomas Moller's JGT code + */ + static bool RayTriangleIntersect(A3DVECTOR3 vOrigin, A3DVECTOR3 vDir, A3DVECTOR3[] vert, ref float t, ref float u, ref float v, bool bCull) + { + // find vectors for two edges sharing vert0 + A3DVECTOR3 edge1 = vert[1] - vert[0]; + A3DVECTOR3 edge2 = vert[2] - vert[0]; + // begin calculating determinant - also used to calculate U parameter + A3DVECTOR3 pvec = A3DVECTOR3.CrossProduct(vDir, edge2); + // if determinant is near zero, ray lies in plane of triangle + float det = A3DVECTOR3.DotProduct(edge1, pvec); + if (bCull) + { + if (det < LOCAL_EPSILON) + return false; + // From here, det is > 0. + // Calculate distance from vert0 to ray origin + A3DVECTOR3 tvec = vOrigin - vert[0]; + // Calculate U parameter and test bounds + u = A3DVECTOR3.DotProduct(tvec, pvec); + if ((u < 0.0f) || (u > det)) + return false; + + // prepare to test V parameter + A3DVECTOR3 qvec = A3DVECTOR3.CrossProduct(tvec, edge1); + // calculate V parameter and test bounds + v = A3DVECTOR3.DotProduct(vDir, qvec); + if ((v < 0.0f) || (u + v > det)) + return false; + + // calculate t, ray intersects triangle + t = A3DVECTOR3.DotProduct(edge2, qvec); + // Det > 0 so we can early exit here + // Intersection point is valid if distance is positive + // (else it can just be a face behind the orig point) + if (t < 0.0f) + { + return false; + } + + float OneOverDet = 1.0f / det; + + + t *= OneOverDet; + u *= OneOverDet; + v *= OneOverDet; + } + + else + { + if (det > -LOCAL_EPSILON && det < LOCAL_EPSILON) + return false; + float OneOverDet = 1.0f / det; + // Calculate distance from vert0 to ray origin + A3DVECTOR3 tvec = vOrigin - vert[0]; + // calculate U parameter and test bounds + u = A3DVECTOR3.DotProduct(tvec, pvec) * OneOverDet; + if ((u < 0.0f) || (u > 1.0f)) + return false; + // prepare to test V parameter + A3DVECTOR3 qvec = A3DVECTOR3.CrossProduct(tvec, edge1); + // calculate V parameter and test bounds + v = A3DVECTOR3.DotProduct(vDir, qvec) * OneOverDet; + if ((v < 0.0f) || (u + v > 1.0f)) + return false; + // calculate t, ray intersects triangle + t = A3DVECTOR3.DotProduct(edge2, qvec) * OneOverDet; + } + + return true; + } + + public static bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart) + { CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld(); A3DTerrain2 pTerrain = pWorld.GetTerrain(); bStart = false; - float h1 = pTerrain.GetPosHeight(vStart, ref vHitNormal); - if (h1 > vStart.y + 1E-4f ) - {//start under terrain - bStart = true; - fFraction = 0.0f; - return true; - } + float h1 = pTerrain.GetPosHeight(vStart, ref vHitNormal); + if (h1 > vStart.y + 1E-4f) + {//start under terrain + bStart = true; + fFraction = 0.0f; + return true; + } - int nWid, nHei; // in grid, 2 meters + int nWid, nHei; // in grid, 2 meters float fMag = vDelta.Magnitude(); nWid = (int)Math.Ceiling(fMag / 2.0f); nWid = Math.Max(3, nWid); nHei = nWid; - int nTriangles = nWid * nHei * 2; + int nTriangles = nWid * nHei * 2; A3DVECTOR3[] pVerts = new A3DVECTOR3[(nWid + 1) * (nHei + 1)]; - //assert(pVerts != NULL); - //memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1)); - WORD[] pIndices = new WORD[nTriangles * 3]; - //assert(pIndices != NULL); - //memset(pIndices, 0, sizeof(WORD)* nTriangles * 3); - if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, pVerts, pIndices)) - { - //a_freetemp(pVerts); - // a_freetemp(pIndices); - return false; - } + //assert(pVerts != NULL); + //memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1)); + WORD[] pIndices = new WORD[nTriangles * 3]; + //assert(pIndices != NULL); + //memset(pIndices, 0, sizeof(WORD)* nTriangles * 3); + if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, ref pVerts, ref pIndices)) + { + //a_freetemp(pVerts); + // a_freetemp(pIndices); + return false; + } int i; -A3DVECTOR3* vert[3]; -//@note : Here init the fraction. By Kuiwu[9/10/2005] -fFraction = 100.0f; -float tmpFraction = fFraction; + A3DVECTOR3[] vert = new A3DVECTOR3[3]; + //@note : Here init the fraction. By Kuiwu[9/10/2005] + fFraction = 100.0f; + float tmpFraction = fFraction; -for (i = 0; i < nTriangles; i++) -{ - vert[0] = pVerts + pIndices[i * 3]; - vert[1] = pVerts + pIndices[i * 3 + 1]; - vert[2] = pVerts + pIndices[i * 3 + 2]; - A3DVECTOR3 vPt; + for (i = 0; i < nTriangles; i++) + { + vert[0] = pVerts[pIndices[i * 3]]; + vert[1] = pVerts[pIndices[i * 3 + 1]]; + vert[2] = pVerts[pIndices[i * 3 + 2]]; + //A3DVECTOR3 vPt; - //@note: Tomas Moller's JGT code : By Kuiwu[9/10/2005] - //@note: discard the engine version because it put back the hit point too much. By Kuiwu[13/10/2005] - // if(CLS_RayToTriangle(vStart, vDelta, *vert[0], *vert[1], *vert[2], vPt, true, &tmpFraction) - // && (tmpFraction <= 1.0f) && (tmpFraction < fFraction)) - if (SegmentTriangleIntersect(vStart, vDelta, vert, tmpFraction, true) && (tmpFraction < fFraction)) - { - //get the triangle normal - A3DVECTOR3 vEdge1((* vert[1]) -(*vert[0]) ); -A3DVECTOR3 vEdge2((* vert[2]) -(*vert[0]) ); -vHitNormal = CrossProduct(vEdge1, vEdge2); -vHitNormal.Normalize(); + //@note: Tomas Moller's JGT code : By Kuiwu[9/10/2005] + //@note: discard the engine version because it put back the hit point too much. By Kuiwu[13/10/2005] + // if(CLS_RayToTriangle(vStart, vDelta, *vert[0], *vert[1], *vert[2], vPt, true, &tmpFraction) + // && (tmpFraction <= 1.0f) && (tmpFraction < fFraction)) + if (SegmentTriangleIntersect(vStart, vDelta, vert, ref tmpFraction, true) && (tmpFraction < fFraction)) + { + //get the triangle normal + A3DVECTOR3 vEdge1 = vert[1] - vert[0]; + A3DVECTOR3 vEdge2 = vert[2] - vert[0]; + vHitNormal = A3DVECTOR3.CrossProduct(vEdge1, vEdge2); + vHitNormal.Normalize(); -//@note : may be redundant, but to assure. By Kuiwu[17/10/2005] -A3DVECTOR3 vDir; -Normalize(vDelta, vDir); -if (DotProduct(vHitNormal, vDir) > 0.01f) -{//leave the hit plane - assert(0 && "hit a plane with same direction!"); - continue; -} + //@note : may be redundant, but to assure. By Kuiwu[17/10/2005] + A3DVECTOR3 vDir = new A3DVECTOR3(); + A3DVECTOR3.Normalize(vDelta, out vDir); + if (A3DVECTOR3.DotProduct(vHitNormal, vDir) > 0.01f) + {//leave the hit plane + //assert(0 && "hit a plane with same direction!"); + continue; + } -fFraction = a_Max(0.0f, tmpFraction); - } - - } - a_freetemp(pVerts); -a_freetemp(pIndices); + fFraction = Math.Max(0.0f, tmpFraction); + } -return (fFraction <= 1.0f); + } + //a_freetemp(pVerts); + // a_freetemp(pIndices); -} + return (fFraction <= 1.0f); + + } + + public static bool AABBCollideWithBrush(ref BrushTraceInfo pInfo) + { + CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld(); + + CECOrnamentMan pOrnMan = pWorld.GetOrnamentMan(); + bool bBrush = pOrnMan.TraceWithBrush(ref pInfo); + + BrushTraceInfo info = pInfo; + CECMatterMan pMatterMan = pWorld.GetMatterMan(); + if (pMatterMan.TraceWithBrush(&info) && info.fFraction < pInfo.fFraction) + { + *pInfo = info; + bBrush = true; + } + + info = *pInfo; + CECNPCMan* pNPCMan = pWorld.GetNPCMan(); + if (pNPCMan.TraceWithBrush(&info) && info.fFraction < pInfo.fFraction) + { + *pInfo = info; + bBrush = true; + } + + return bBrush; + } } public struct OtherPlayer_Move_Info { From beb9d0f322e7f060afe168359c25065316fd67d8 Mon Sep 17 00:00:00 2001 From: Tungdv Date: Mon, 20 Oct 2025 16:37:08 +0700 Subject: [PATCH 5/6] fix: update logic worktrace --- .../Scripts/Managers/A3DTerrain2.cs | 14 +- .../Scripts/Managers/EC_OrnamentMan.cs | 149 +++++++++--------- Assets/Scripts/Move/EC_CDR.cs | 38 ++--- 3 files changed, 108 insertions(+), 93 deletions(-) diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs index f802c783da..745dcd8a0c 100644 --- a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs @@ -1,6 +1,9 @@ using BrewMonster.Scripts.Player; using CSNetwork.GPDataType; +using NUnit.Framework; +using System.Collections.Generic; using System.Linq; +using UnityEngine; using ARectF = BrewMonster.Scripts.ARect; using ARectI = BrewMonster.Scripts.ARect; using BlockArray = System.Collections.Generic.List; @@ -240,6 +243,7 @@ namespace BrewMonster.Scripts.World public int m_iNumAllBlockRow = 0; // Row number of all blocks public int m_iNumAllBlockCol = 0; // Column number of all blocks public bool m_bVertexLight = false; // true, force to use vertex light rather than lightmap + public List m_lstMesh; // Check lightmap or vertex-light is used public bool UseLightmapTech() { return !m_bVertexLight; } @@ -249,8 +253,16 @@ namespace BrewMonster.Scripts.World // Get grid faces of specified area public bool GetFacesOfArea(A3DVECTOR3 vCenter, int iGridWid, int iGridLen, ref A3DVECTOR3[] pVertBuf, ref WORD[] pIdxBuf) { - if (m_pCurActBlocks.rcArea.IsEmpty()) + //if (m_pCurActBlocks.rcArea.IsEmpty()) + // return false; + if(m_lstMesh == null || m_lstMesh.Count == 0) + { return false; + } + + float halfW = (iGridWid * m_fGridSize) / 2f; + float halfL = (iGridLen * m_fGridSize) / 2f; + Bounds area = new Bounds(EC_Utility.ToVector3(vCenter), new Vector3(halfW * 2, 1000f, halfL * 2)); float fInvGridSize = 1.0f / m_fGridSize; diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs index e1cc6580a4..8315be2ff5 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs @@ -10,87 +10,88 @@ namespace BrewMonster.Scripts.Ornament public virtual bool TraceWithBrush(ref BrushTraceInfo pInfo) { bool bCollide = false; + //TO DO: fix later //save original result - bool bStartSolid = pInfo.bStartSolid; // Collide something at start point - bool bAllSolid = pInfo.bAllSolid; // All in something - int iClipPlane = pInfo.iClipPlane; // Clip plane's index - float fFraction = 100.0f; // Fraction - A3DVECTOR3 vNormal = pInfo.ClipPlane.GetNormal(); //clip plane normal - float fDist = pInfo.ClipPlane.GetDist(); //clip plane dist + //bool bStartSolid = pInfo.bStartSolid; // Collide something at start point + //bool bAllSolid = pInfo.bAllSolid; // All in something + //int iClipPlane = pInfo.iClipPlane; // Clip plane's index + //float fFraction = 100.0f; // Fraction + //A3DVECTOR3 vNormal = pInfo.ClipPlane.GetNormal(); //clip plane normal + //float fDist = pInfo.ClipPlane.GetDist(); //clip plane dist - if (m_pBrushMan != null && m_pBrushMan.Trace(pInfo) - && (pInfo.fFraction < fFraction)) - { - fFraction = pInfo.fFraction; - bAllSolid = pInfo.bAllSolid; - bStartSolid = pInfo.bStartSolid; - iClipPlane = pInfo.iClipPlane; - vNormal = pInfo.ClipPlane.GetNormal(); - fDist = pInfo.ClipPlane.GetDist(); - bCollide = true; - } + //if (m_pBrushMan != null && m_pBrushMan.Trace(pInfo) + // && (pInfo.fFraction < fFraction)) + //{ + // fFraction = pInfo.fFraction; + // bAllSolid = pInfo.bAllSolid; + // bStartSolid = pInfo.bStartSolid; + // iClipPlane = pInfo.iClipPlane; + // vNormal = pInfo.ClipPlane.GetNormal(); + // fDist = pInfo.ClipPlane.GetDist(); + // bCollide = true; + //} - HomeOnmtTable::iterator it1 = m_HomeOrnamentTab.begin(); - for (; it1 != m_HomeOrnamentTab.end(); ++it1) - { - CECHomeOrnament* pHomeOrnament = *it1.value(); - if (!pHomeOrnament.IsLoaded()) - continue; + //HomeOnmtTable::iterator it1 = m_HomeOrnamentTab.begin(); + //for (; it1 != m_HomeOrnamentTab.end(); ++it1) + //{ + // CECHomeOrnament* pHomeOrnament = *it1.value(); + // if (!pHomeOrnament.IsLoaded()) + // continue; - CELBuildingWithBrush* pBuildingWithBrush = pHomeOrnament.GetBuildingWithBrush(); - if (pBuildingWithBrush && pBuildingWithBrush.TraceWithBrush(pInfo) && (pInfo.fFraction < fFraction)) - { - fFraction = pInfo.fFraction; - bAllSolid = pInfo.bAllSolid; - bStartSolid = pInfo.bStartSolid; - iClipPlane = pInfo.iClipPlane; - vNormal = pInfo.ClipPlane.GetNormal(); - fDist = pInfo.ClipPlane.GetDist(); - bCollide = true; - } - } + // CELBuildingWithBrush* pBuildingWithBrush = pHomeOrnament.GetBuildingWithBrush(); + // if (pBuildingWithBrush && pBuildingWithBrush.TraceWithBrush(pInfo) && (pInfo.fFraction < fFraction)) + // { + // fFraction = pInfo.fFraction; + // bAllSolid = pInfo.bAllSolid; + // bStartSolid = pInfo.bStartSolid; + // iClipPlane = pInfo.iClipPlane; + // vNormal = pInfo.ClipPlane.GetNormal(); + // fDist = pInfo.ClipPlane.GetDist(); + // bCollide = true; + // } + //} - // now see if collide with forest - CELForest* pForest = g_pGame.GetGameRun().GetWorld().GetForest(); - if ((fFraction > 0.0f) && pForest - && pForest.TraceWithBrush(pInfo) - && (pInfo.fFraction < fFraction)) - { - fFraction = pInfo.fFraction; - bAllSolid = pInfo.bAllSolid; - bStartSolid = pInfo.bStartSolid; - iClipPlane = pInfo.iClipPlane; - vNormal = pInfo.ClipPlane.GetNormal(); - fDist = pInfo.ClipPlane.GetDist(); - bCollide = true; - } + //// now see if collide with forest + //CELForest* pForest = g_pGame.GetGameRun().GetWorld().GetForest(); + //if ((fFraction > 0.0f) && pForest + // && pForest.TraceWithBrush(pInfo) + // && (pInfo.fFraction < fFraction)) + //{ + // fFraction = pInfo.fFraction; + // bAllSolid = pInfo.bAllSolid; + // bStartSolid = pInfo.bStartSolid; + // iClipPlane = pInfo.iClipPlane; + // vNormal = pInfo.ClipPlane.GetNormal(); + // fDist = pInfo.ClipPlane.GetDist(); + // bCollide = true; + //} - // now see if collide with dynamic scene building - ECModelTable::iterator it = m_ECModelTab.begin(); - for (; it != m_ECModelTab.end(); ++it) - { - ECMODELNODE* pNode = *it.value(); - if ((fFraction > 0.0f) && pNode - && pNode.TraceWithBrush(pInfo) - && (pInfo.fFraction < fFraction)) - { - fFraction = pInfo.fFraction; - bAllSolid = pInfo.bAllSolid; - bStartSolid = pInfo.bStartSolid; - iClipPlane = pInfo.iClipPlane; - vNormal = pInfo.ClipPlane.GetNormal(); - fDist = pInfo.ClipPlane.GetDist(); - bCollide = true; - } - } + //// now see if collide with dynamic scene building + //ECModelTable::iterator it = m_ECModelTab.begin(); + //for (; it != m_ECModelTab.end(); ++it) + //{ + // ECMODELNODE* pNode = *it.value(); + // if ((fFraction > 0.0f) && pNode + // && pNode.TraceWithBrush(pInfo) + // && (pInfo.fFraction < fFraction)) + // { + // fFraction = pInfo.fFraction; + // bAllSolid = pInfo.bAllSolid; + // bStartSolid = pInfo.bStartSolid; + // iClipPlane = pInfo.iClipPlane; + // vNormal = pInfo.ClipPlane.GetNormal(); + // fDist = pInfo.ClipPlane.GetDist(); + // bCollide = true; + // } + //} - //set back - pInfo.fFraction = fFraction; - pInfo.bStartSolid = bStartSolid; - pInfo.bAllSolid = bAllSolid; - pInfo.iClipPlane = iClipPlane; - pInfo.ClipPlane.SetNormal(vNormal); - pInfo.ClipPlane.SetD(fDist); + ////set back + //pInfo.fFraction = fFraction; + //pInfo.bStartSolid = bStartSolid; + //pInfo.bAllSolid = bAllSolid; + //pInfo.iClipPlane = iClipPlane; + //pInfo.ClipPlane.SetNormal(vNormal); + //pInfo.ClipPlane.SetD(fDist); return bCollide; } diff --git a/Assets/Scripts/Move/EC_CDR.cs b/Assets/Scripts/Move/EC_CDR.cs index 898bc960bc..b1991728a5 100644 --- a/Assets/Scripts/Move/EC_CDR.cs +++ b/Assets/Scripts/Move/EC_CDR.cs @@ -502,28 +502,30 @@ namespace BrewMonster.Scripts public static bool AABBCollideWithBrush(ref BrushTraceInfo pInfo) { - CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld(); + //TO DO: fix later + return false; + //CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld(); - CECOrnamentMan pOrnMan = pWorld.GetOrnamentMan(); - bool bBrush = pOrnMan.TraceWithBrush(ref pInfo); + //CECOrnamentMan pOrnMan = pWorld.GetOrnamentMan(); + //bool bBrush = pOrnMan.TraceWithBrush(ref pInfo); - BrushTraceInfo info = pInfo; - CECMatterMan pMatterMan = pWorld.GetMatterMan(); - if (pMatterMan.TraceWithBrush(&info) && info.fFraction < pInfo.fFraction) - { - *pInfo = info; - bBrush = true; - } + //BrushTraceInfo info = pInfo; + //CECMatterMan pMatterMan = pWorld.GetMatterMan(); + //if (pMatterMan.TraceWithBrush(ref info) && info.fFraction < pInfo.fFraction) + //{ + // pInfo = info; + // bBrush = true; + //} - info = *pInfo; - CECNPCMan* pNPCMan = pWorld.GetNPCMan(); - if (pNPCMan.TraceWithBrush(&info) && info.fFraction < pInfo.fFraction) - { - *pInfo = info; - bBrush = true; - } + //info = pInfo; + //CECNPCMan pNPCMan = pWorld.GetNPCMan(); + //if (pNPCMan.TraceWithBrush(ref info) && info.fFraction < pInfo.fFraction) + //{ + // pInfo = info; + // bBrush = true; + //} - return bBrush; + //return bBrush; } } public struct OtherPlayer_Move_Info From 776ac0fa5dbf462693a41582b01a832e1be36e59 Mon Sep 17 00:00:00 2001 From: Tungdv Date: Tue, 21 Oct 2025 19:12:23 +0700 Subject: [PATCH 6/6] feat: add logic else player action normal attack. --- .../Scripts/Managers/EC_EPWork.cs | 714 ++++++++++++++++++ .../Scripts/Managers/EC_EPWork.cs.meta | 2 + .../Scripts/Managers/EC_ManPlayer.cs | 10 +- Assets/PerfectWorld/Scripts/Move/CECPlayer.cs | 1 - .../Scripts/Network/CSNetwork/GameSession.cs | 9 +- .../Scripts/Players/EC_ElsePlayer.cs | 163 +++- 6 files changed, 885 insertions(+), 14 deletions(-) create mode 100644 Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs.meta diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs new file mode 100644 index 0000000000..fcc9d97884 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs @@ -0,0 +1,714 @@ +using CSNetwork.GPDataType; +using PerfectWorld.Scripts.Player; +using System; + +namespace BrewMonster.Scripts +{ + using WorkList = System.Collections.Generic.List; + + public abstract class CECEPWorkMatcher + { + public abstract bool Match(CECEPWork work, int workType); + } + + // class CECEPWorkMelee + public class CECEPWorkMelee : CECEPWork + { + int m_iAttackTarget; + + public CECEPWorkMelee(CECEPWorkMan pWorkMan, int attackTarget) : base(EP_work_ID.WORK_HACKOBJECT, pWorkMan) + { + m_iAttackTarget = attackTarget; + } + public override void Start() + { + GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + UnityEngine.Random.Range(0, 3)); + GetPlayer().EnterFightState(); + } + public override void Tick(float dwDeltaTime) + { + GetPlayer().TurnFaceTo(m_iAttackTarget); + + // Slide to server position + A3DVECTOR3 vDir = GetPlayer().m_vServerPos - GetPlayer().GetPos(); + float fDist = vDir.Normalize(); + if (fDist > 0.0001f) + { + float fMoveDist = 10.0f * dwDeltaTime * 0.001f; + if (fMoveDist > fDist) + fMoveDist = fDist; + + GetPlayer().SetPos(GetPlayer().GetPos() + vDir * fMoveDist); + } + if (GetPlayer().m_FightCnt.IncCounter(dwDeltaTime)) + { + Finish(); + } + } + public override void Cancel() + { + GetPlayer().TurnFaceTo(0); + } + }; + + public class CECEPWorkIDMatcher : CECEPWorkMatcher + { + int m_workID; + public CECEPWorkIDMatcher(int workID) + { + m_workID = workID; + } + public override bool Match(CECEPWork work, int workType) + { + return work != null && work.GetWorkID() == m_workID; + } + } + + // class CECEPWorkCongregate + public class CECEPWorkCongregate : CECEPWork + { + int m_iType; + public CECEPWorkCongregate(CECEPWorkMan pWorkMan, int iType) : base(EP_work_ID.WORK_CONGREGATE, pWorkMan) + { + m_iType = iType; + } + public override void Start() + { + + } + public int GetType() + { + return m_iType; + } + } + + public class CECEPCongregateWorkMatcher : CECEPWorkMatcher + { + int m_iType; + public CECEPCongregateWorkMatcher(int iType) + { + m_iType = iType; + } + + public override bool Match(CECEPWork work, int workType) + { + if (work != null && work.GetWorkID() == CECEPWork.EP_work_ID.WORK_CONGREGATE) + { + CECEPWorkCongregate pCongregateWork = work as CECEPWorkCongregate; + return pCongregateWork.GetType() == m_iType; + } + return false; + } + } + + // class CECEPWorkIdle + public class CECEPWorkIdle : CECEPWork + { + int m_iType; + bool m_bOTCheck; + CECCounter m_OTCnt; + uint m_dwParam; + public CECEPWorkIdle(CECEPWorkMan pWorkMan, int iType, int iOTTime, uint dwParam) : base(EP_work_ID.WORK_IDLE, pWorkMan) + { + m_dwParam = dwParam; + m_iType = iType; + m_bOTCheck = iOTTime > 0 ? true : false; + + if (m_bOTCheck) + { + m_OTCnt.SetPeriod(iOTTime); + m_OTCnt.Reset(); + } + + switch (iType) + { + case Idle_work_type.IDLE_SITDOWN: + GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; + + if (m_dwParam != 0) + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP); + else + { + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN); + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP, true, 200, true); + } + + break; + + case Idle_work_type.IDLE_REVIVE: + + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_REVIVE); + break; + + case Idle_work_type.IDLE_BOOTH: + + GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; + break; + } + } + public override void Tick(float dwDeltaTime) + { + base.Tick(dwDeltaTime); + } + public int GetType() + { + return m_iType; + } + } + + public class CECEPIdleWorkMatcher : CECEPWorkMatcher + { + int m_iType; + public CECEPIdleWorkMatcher(int iType) + { + m_iType = iType; + } + public override bool Match(CECEPWork work, int workType) + { + if (work != null && work.GetWorkID() == CECEPWork.EP_work_ID.WORK_IDLE) + { + CECEPWorkIdle pIdleWork = work as CECEPWorkIdle; + return pIdleWork.GetType() == m_iType; + } + return false; + } + } + + public class CECEPWork + { + public static class EP_work_ID + { + public const int WORK_INVALID = -1, + WORK_STAND = 0, // Stand and do nothing + WORK_MOVE = 1, // Move + WORK_HACKOBJECT = 2, // Hack specified object (NPC, player etc.) + WORK_SPELL = 3, // Spell magic + WORK_PICKUP = 4, // Pickup matter + WORK_DEAD = 5, // Dead + WORK_USEITEM = 6, // Use item + WORK_IDLE = 7, // Idle works + WORK_FLASHMOVE = 8, // Flash move + WORK_PASSIVEMOVE = 9, // Move controlled by server + WORK_CONGREGATE = 10, // Congregate reply + WORK_SKILLSTATEACT = 11, // skill buff action + NUM_WORK = 12; + } + + // Idle work type + public static class Idle_work_type + { + public const int IDLE_SITDOWN = 0, + IDLE_REVIVE = 1, + IDLE_BOOTH = 2; + } + + static string[] l_WorkName = new string[EP_work_ID.NUM_WORK] + { + "WORK_STAND", + "WORK_MOVE", + "WORK_HACKOBJECT", + "WORK_SPELL", + "WORK_PICKUP", + "WORK_DEAD", + "WORK_USEITEM", + "WORK_IDLE", + "WORK_FLASHMOVE", + "WORK_PASSIVEMOVE", + "WORK_CONGREGATE", + "WORK_SKILLSTATEACT", + }; + + + protected int m_iWorkID; + protected CECEPWorkMan m_pWorkMan; + protected bool m_bFinished; + protected EC_ElsePlayer GetPlayer() + { + return m_pWorkMan.GetPlayer(); + } + + + public CECEPWork(int iWorkID, CECEPWorkMan pWorkMan) + { + m_iWorkID = iWorkID; + m_pWorkMan = pWorkMan; + m_bFinished = false; + } + + + public static string GetWorkName(int iWork) + { + if (iWork >= EP_work_ID.WORK_STAND && iWork < l_WorkName.Length) + { + return l_WorkName[iWork]; + } + else + { + return "Invalid Work"; + } + } + + public string GetWorkName() + { + return GetWorkName(GetWorkID()); + } + public int GetWorkID() + { + return m_iWorkID; + } + public bool IsFinished() + { + return m_bFinished; + } + + public virtual void Start() { } + public virtual void Tick(float dwDeltaTime) { } + public virtual void Cancel() { } + public virtual void Finish() + { + m_bFinished = true; + } + static bool Validate(int iWork) + { + return iWork >= EP_work_ID.WORK_STAND && iWork < EP_work_ID.NUM_WORK; + } + } + + // class CECEPWorkSpell + public class CECEPWorkSpell : CECEPWork + { + CECCounter m_SkillCnt; + CECSkill m_pCurSkill; + int m_idCurSkillTarget; + + public CECEPWorkSpell(CECEPWorkMan pWorkMan, uint dwPeriod, CECSkill pSkill, int target) : base(CECEPWork.EP_work_ID.WORK_SPELL, pWorkMan) + { + m_pCurSkill = pSkill; + m_idCurSkillTarget = target; + m_SkillCnt.SetPeriod(dwPeriod); + m_SkillCnt.Reset(); + } + public override void Start() + { + GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; + } + public override void Tick(float dwDeltaTime) + { + //TO DO: fix later + //GetPlayer().m_FightCnt.IncCounter(dwDeltaTime); + //int iRealTime = g_pGame.GetRealTickTime(); + //if (m_SkillCnt.IncCounter(iRealTime)) + //{ + // Finish(); + //} + //else + //{ + // if (m_idCurSkillTarget != 0) + // { + // GetPlayer().TurnFaceTo(m_idCurSkillTarget); + // } + // if (GetPlayer().IsPlayingMoveAction() && !GetPlayer().IsWorkMoveRunning()) + // { // ƶʩֹͣƶһֱڳƶ˴ͣ + // GetPlayer().PlayAction(CECPlayer::ACT_FIGHTSTAND); + // } + // if (!GetPlayer().IsPlayingAction()) + // { + // GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_FIGHTSTAND); // ܶɺ󡢲սվ + // } + //} + } + public override void Cancel() + { + //TO DO: fix later + //if (m_pCurSkill != null) + //{ + // m_pCurSkill = null; + //} + //m_idCurSkillTarget = 0; + //GetPlayer().StopSkillAttackAction(); + //GetPlayer().TurnFaceTo(0); + } + public CECSkill GetSkill() + { + return m_pCurSkill; + } + } + + public class CECEPWorkMan + { + public static class Work_type + { + public const int WT_NOTHING = 0, // Do thing + WT_NORMAL = 1, // Normal type work + WT_INTERRUPT = 2, // Interrupt type work + NUM_WORKTYPE = 3; + } + + private EC_ElsePlayer m_pElsePlayer; + private WorkList[] m_WorkStack = new WorkList[Work_type.NUM_WORKTYPE]; + private int m_iCurWorkType; + + public CECEPWorkMan(EC_ElsePlayer pElsePlayer) + { + m_pElsePlayer = pElsePlayer; + m_iCurWorkType = -1; + } + + public EC_ElsePlayer GetPlayer() + { + return m_pElsePlayer; + } + + public bool ValidateWorkType(int iWorkType) + { + return iWorkType >= 0 && iWorkType < Work_type.NUM_WORKTYPE; + } + + public bool FindWork(int iWorkType, int iWorkID) + { + if (!ValidateWorkType(iWorkType)) + { + return false; + } + WorkList workList = m_WorkStack[iWorkType]; + if (workList != null) + { + for (int i = 0; i < workList.Count; ++i) + { + if (iWorkID == workList[i].GetWorkID()) + { + return true; + } + } + } + return false; + } + + public void StartNormalWork(CECEPWork pWork) + { + StartWork(Work_type.WT_NORMAL, ref pWork); + } + + private bool CanRunSimultaneously(CECEPWork pWork1, CECEPWork pWork2) + { + if (pWork1.GetWorkID() == CECEPWork.EP_work_ID.WORK_MOVE && + pWork2.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) + { + return CanSpellWhileMoving(pWork2 as CECEPWorkSpell); + } + if (pWork2.GetWorkID() == CECEPWork.EP_work_ID.WORK_MOVE && + pWork1.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) + { + return CanSpellWhileMoving(pWork1 as CECEPWorkSpell); + } + return false; + } + + private bool CanReplace(CECEPWork pNewWork, CECEPWork pExistWork) + { + if (pNewWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL && + pExistWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) + { + return CanSpellWhileMoving(pNewWork as CECEPWorkSpell) + && CanSpellWhileMoving(pExistWork as CECEPWorkSpell); + } + return false; + } + + private bool CanSpellWhileMoving(CECEPWorkSpell pWorkSpell) + { + return false; + // TO DO: fix later + // return pWorkSpell.GetSkill() + // && CECCastSkillWhenMove.Instance().IsSkillSupported(pWorkSpell.GetSkill().GetSkillID(), GetPlayer()); + } + + private bool CanMergeWithCurrentWork(int iWorkType, CECEPWork pWork) + { + if (!ValidateWorkType(iWorkType) || iWorkType != m_iCurWorkType) + { + return false; + } + WorkList workList = m_WorkStack[iWorkType]; + if (workList == null || workList.Count == 0) + { + return false; + } + for (int i = 0; i < workList.Count; ++i) + { + if (!CanRunSimultaneously(pWork, workList[i]) && // Ҫôͬʱ + !CanReplace(pWork, workList[i])) + { // Ҫô滻 + return false; + } + } + return true; + } + + private void KillWork(int iWorkType, int index) + { + if (!ValidateWorkType(iWorkType)) + { + //ASSERT(false); + return; + } + WorkList workList = m_WorkStack[iWorkType]; + if (index < 0 || index >= (int)workList.Count) + { + //ASSERT(false); + return; + } + CECEPWork pWork = workList[index]; + pWork.Cancel(); + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::%s(%s) killed", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); + //delete pWork; + pWork = null; + workList.RemoveAt(index); + } + + private void MergeWork(int iWorkType, CECEPWork pWork) + { + if (!CanMergeWithCurrentWork(iWorkType, pWork)) + { + //ASSERT(false); + return; + } + WorkList workList = m_WorkStack[iWorkType]; + for (int i = 0; i < workList.Count; ++i) + { + if (CanReplace(pWork, workList[i])) + { + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::MergeWork %s replacing %s at %s", pWork.GetWorkName(), workList[i].GetWorkName(), GetWorkTypeName(iWorkType))); + KillWork(iWorkType, i); + workList.Insert(i, pWork); + return; + } + } + workList.Add(pWork); + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::MergeWork %s appended to %s", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); + } + + private void FinishWorkAtWorkType(int iWorkType) + { + if (!ValidateWorkType(iWorkType)) + { + //ASSERT(false); + return; + } + WorkList workList = m_WorkStack[iWorkType]; + while (workList != null && workList.Count != 0) + { + KillWork(iWorkType, 0); + } + if (m_iCurWorkType == iWorkType) + { + m_iCurWorkType = -1; + } + } + + private void AppendWork(int iWorkType, CECEPWork pWork) + { + if (!ValidateWorkType(iWorkType) || pWork == null) + { + //ASSERT(false); + return; + } + m_WorkStack[iWorkType].Add(pWork); + } + + private void CancelWorkAtWorkType(int iWorkType) + { + if (!ValidateWorkType(iWorkType)) + { + return; + } + WorkList workList = m_WorkStack[iWorkType]; + for (int i = 0; i < workList.Count; ++i) + { + CancelWork(workList[i]); + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::%s(%s) cancelled", workList[i].GetWorkName(), GetWorkTypeName(iWorkType))); + } + } + + private void CancelWork(CECEPWork pWork) + { + if (pWork == null) + { + //ASSERT(false); + return; + } + pWork.Cancel(); + } + + public void StartWork(int iWorkType, ref CECEPWork pWork) + { + if (!ValidateWorkType(iWorkType)) + { + pWork = null; + return; + } + if (CanMergeWithCurrentWork(iWorkType, pWork)) + { + MergeWork(iWorkType, pWork); + } + else + { + if (pWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_DEAD) + { + for (int i = iWorkType; i < Work_type.NUM_WORKTYPE; i++) + { + FinishWorkAtWorkType(i); + } + AppendWork(iWorkType, pWork); + m_iCurWorkType = iWorkType; + } + else + { + bool shouldStart = (iWorkType >= m_iCurWorkType); + FinishWorkAtWorkType(iWorkType); + AppendWork(iWorkType, pWork); + if (!shouldStart) + { + //LOG_DEBUG_INFO(AString().Format("CECEPWork::StartWork %s flushed %s", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); + return; + } + if (iWorkType > m_iCurWorkType) + { + CancelWorkAtWorkType(m_iCurWorkType); + } + m_iCurWorkType = iWorkType; + } + } + pWork.Start(); + } + + private bool IsAnyWorkRunning() + { + return ValidateWorkType(m_iCurWorkType) && m_WorkStack != null && m_WorkStack[m_iCurWorkType] != null; + } + + private void StartAwaitingWorks() + { + if (ValidateWorkType(m_iCurWorkType)) + { + for (--m_iCurWorkType; m_iCurWorkType >= 0; --m_iCurWorkType) + { + WorkList workList = m_WorkStack[m_iCurWorkType]; + if (workList == null || workList.Count == 0) + { + continue; + } + for (int j = 0; j < workList.Count; ++j) + { + workList[j].Start(); + //LOG_DEBUG_INFO(AString().Format("CECElsePlayer::StartAwaitingWorks %s(%s) started by decrease priority", workList[j].GetWorkName(), GetWorkTypeName(m_iCurWorkType))); + } + break; + } + } + } + + public void Tick(float dwDeltaTime) + { + if (!IsAnyWorkRunning()) + { + return; + } + WorkList workList = m_WorkStack[m_iCurWorkType]; + if (workList != null) + { + for (int i = 0; i < workList.Count;) + { + CECEPWork pWork = workList[i]; + pWork.Tick(dwDeltaTime); + if (!pWork.IsFinished()) + { + ++i; + continue; + } + KillWork(m_iCurWorkType, i); + } + if (workList == null || workList.Count == 0) + { + StartAwaitingWorks(); + } + } + } + + public void FinishWork(CECEPWorkMatcher matcher) + { + bool bCurrentWorkFinished = false; + for (int i = Work_type.NUM_WORKTYPE - 1; i >= 0; --i) + { + WorkList workList = m_WorkStack[i]; + if (workList == null || workList.Count == 0) + { + continue; + } + for (int j = 0; j < workList.Count;) + { + if (!matcher.Match(workList[j], i)) + { + ++j; + continue; + } + KillWork(i, j); + if (i == m_iCurWorkType && (workList == null || workList.Count == 0)) + { + bCurrentWorkFinished = true; + } + } + } + if (bCurrentWorkFinished) + { + StartAwaitingWorks(); + } + } + public void FinishWork(int idWork) + { + FinishWork(new CECEPWorkIDMatcher(idWork)); + } + + public bool IsWorkRunning(int iWork) + { + return FindWork(m_iCurWorkType, iWork); + } + + public void FinishRunningWork(int idWork) + { + if (!IsWorkRunning(idWork)) + { + return; + } + WorkList workList = m_WorkStack[m_iCurWorkType]; + if (workList != null) + { + for (int i = 0; i < workList.Count;) + { + if (workList[i].GetWorkID() != idWork) + { + ++i; + continue; + } + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::FinishRunningWork %s(%s)", workList[i].GetWorkName(), GetWorkTypeName(m_iCurWorkType))); + KillWork(m_iCurWorkType, i); + } + if (workList == null) + { + StartAwaitingWorks(); + } + } + } + public bool FinishIdleWork(int iType) + { + FinishWork(new CECEPIdleWorkMatcher(iType)); + return true; + } + public bool FinishCongregateWork(int iType) + { + FinishWork(new CECEPCongregateWorkMatcher(iType)); + return true; + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs.meta new file mode 100644 index 0000000000..27becec87a --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9352b9911dad2d541b975297dcefa8d2 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs index 0648b0ed31..b2d1402019 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs @@ -52,6 +52,7 @@ namespace PerfectWorld.Scripts.Managers break; } case int value when value == EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY: + case int value1 when value1 == EC_MsgDef.MSG_PM_PLAYERATKRESULT: Debug.Log("EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY"); TransmitMessage(Msg); break; @@ -437,7 +438,10 @@ namespace PerfectWorld.Scripts.Managers else cid = ((cmd_object_landing)msg.dwParam1).object_id; break;*/ - + case long value when value == EC_MsgDef.MSG_PM_PLAYERATKRESULT: + cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes((byte[])msg.dwParam1); + cid = pCmdAtk.attacker_id; + break; // ⚠️ Các case khác cũng tương tự, chỉ việc lấy ra đúng trường id / caster / user ... // Do quá dài nên bạn có thể copy dần từng case từ C++ sang. @@ -446,7 +450,7 @@ namespace PerfectWorld.Scripts.Managers return false; } - /* if (cid == 0) + if (cid == 0) { System.Diagnostics.Debug.Assert(false, "cid = 0"); return false; @@ -461,7 +465,7 @@ namespace PerfectWorld.Scripts.Managers var elsePlayer = SeekOutElsePlayer(cid); if (elsePlayer != null) elsePlayer.ProcessMessage(msg); - }*/ + } return true; } diff --git a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs index e2db7b89b2..2f60537088 100644 --- a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs @@ -1,5 +1,4 @@ using Animancer; -using Animancer.Editor; using BrewMonster; using BrewMonster.Managers; using BrewMonster.Scripts.Managers; diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index f2ac064021..255b59ce30 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -417,12 +417,13 @@ namespace CSNetwork EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_HURTRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); break; case CommandID.OBJECT_ATTACK_RESULT: - int id = GPDataTypeHelper.FromBytes(pDataBuf); - BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id)); + //int id = GPDataTypeHelper.FromBytes(pDataBuf); + cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes(pDataBuf); + //BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id)); - if (ISPLAYERID(id)) + if (ISPLAYERID(pCmdAtk.attacker_id)) EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERATKRESULT, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(id)) + else if (ISNPCID(pCmdAtk.attacker_id)) EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); break; case CommandID.HOST_ATTACKRESULT: diff --git a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs index bc6299bed4..ed6c7af21d 100644 --- a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs +++ b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs @@ -1,5 +1,6 @@ using BrewMonster; using BrewMonster.Managers; +using BrewMonster.Scripts; using CSNetwork; using CSNetwork.GPDataType; using CSNetwork.Protocols.RPCData; @@ -11,7 +12,7 @@ namespace PerfectWorld.Scripts.Player public class EC_ElsePlayer : CECPlayer { A3DVECTOR3 m_vMoveDir; // Player's velocity - A3DVECTOR3 m_vServerPos; // Player's real position on server + public A3DVECTOR3 m_vServerPos; // Player's real position on server A3DVECTOR3 m_vStopDir; // The direction when player stop moving // 是否是依附者 = Is it a dependent/attacher? bool m_bHangerOn; @@ -25,10 +26,13 @@ namespace PerfectWorld.Scripts.Player 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 - CECCounter m_FightCnt; + public CECCounter m_FightCnt; + CECEPWorkMan m_pEPWorkMan; + CECHostPlayer pHost => EC_ManMessageMono.Instance?.GetECManPlayer?.GetHostPlayer(); public void Init(RoleInfo roleInfo, info_player_1 Info) { + m_pEPWorkMan = new CECEPWorkMan(this); m_iProfession = roleInfo.occupation; m_iGender = roleInfo.gender; @@ -70,7 +74,7 @@ namespace PerfectWorld.Scripts.Player { BrewMonster.BMLogger.Log("HoangDev : fDist >= MAX_LAGDIST"); SetPos(Cmd.dest); - //m_pEPWorkMan->FinishWork(CECEPWork::WORK_MOVE); + //m_pEPWorkMan.FinishWork(CECEPWork::WORK_MOVE); return; } @@ -349,15 +353,16 @@ namespace PerfectWorld.Scripts.Player private void Update() { MovingTo(Time.deltaTime); - CECHostPlayer pHost = EC_ManMessageMono.Instance.GetECManPlayer.GetHostPlayer(); - if (pHost != null /*&& pHost->IsSkeletonReady()*/) + + if (pHost != null /*&& pHost.IsSkeletonReady()*/) { m_fDistToHost = CalcDist(pHost.GetPos(), true); m_fDistToHostH = CalcDist(pHost.GetPos(), false); } + m_pEPWorkMan?.Tick(Time.deltaTime); } - private void SetPos(A3DVECTOR3 vPos) + public void SetPos(A3DVECTOR3 vPos) { Vector3 vector = new Vector3(); vector.x = vPos.x; @@ -383,6 +388,152 @@ namespace PerfectWorld.Scripts.Player // Get player's real position on server public A3DVECTOR3 GetServerPos() { return m_vServerPos; } + public bool ProcessMessage(ECMSG Msg) + { + switch (Msg.dwMsg) + { + case long value when value == EC_MsgDef.MSG_PM_PLAYERATKRESULT: + OnMsgPlayerAtkResult(Msg); + break; + } + return true; + } + + void OnMsgPlayerAtkResult(ECMSG Msg) + { + + cmd_object_atk_result pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + //ASSERT(pCmd && pCmd.attacker_id == m_PlayerInfo.cid); + + // Face to target + TurnFaceTo(pCmd.target_id); + + // TO DO: fix later + //PlayAttackEffect(pCmd.target_id, 0, 0, -1, pCmd.attack_flag, pCmd.speed* 50); + + if (!m_pEPWorkMan.FindWork(CECEPWorkMan.Work_type.WT_NORMAL, CECEPWork.EP_work_ID.WORK_HACKOBJECT)){ + m_pEPWorkMan.StartNormalWork(new CECEPWorkMelee(m_pEPWorkMan, pCmd.target_id)); + } + + // Enter fight state + EnterFightState(); + } + + // Play an attack effect + //void PlayAttackEffect(int idTarget, int idSkill, int skillLevel, int nDamage, + // uint dwModifier, int nAttackSpeed, int[] piAttackTime/* NULL */, int nSection) + //{ + // if (!IsAllResReady()) + // return; + + // if (idSkill == 0) + // { + // int idWeapon = IsShapeChanged() ? 0 : GetWeaponID(); + + // int nTimeFly = 10; + // if (idWeapon != 0) + // { + // // ¿´¿´ÊDz»ÊÇÔ¶³ÌÎäÆ÷ + // DATA_TYPE dt; + // WEAPON_ESSENCE pWeapon = (WEAPON_ESSENCE)g_pGame.GetElementDataMan().get_data_ptr(idWeapon, ID_SPACE_ESSENCE, dt); + // //ASSERT(dt == DT_WEAPON_ESSENCE); + + // if (dt == DT_WEAPON_ESSENCE && pWeapon && pWeapon.require_projectile) + // { + // nTimeFly = 700; + + // if (m_aEquips[EQUIPIVTR_PROJECTILE]) + // idWeapon = m_aEquips[EQUIPIVTR_PROJECTILE]; // set weapon to the projectile + // } + // } + + // if (g_pGame.GetGameRun().GetWorld().GetAttacksMan().FindAttackByAttacker(GetPlayerInfo().cid)) + // { + // // signal early attack event + // ClearComActFlagAllRankNodes(true); + // } + + // // melee attack + // CECAttackEvent pAttack = g_pGame.GetGameRun().GetWorld().GetAttacksMan().AddMeleeAttack( + // GetPlayerInfo().cid, idTarget, idWeapon, dwModifier, nDamage, nTimeFly); + + // if (pAttack != null) + // { + // if (!IsDead() && (dwModifier & CECAttackEvent::MOD_RETORT) == 0 + // && (dwModifier & CECAttackEvent::MOD_ATTACK_AURA) == 0 + // && PlayAttackAction(nAttackSpeed, piAttackTime, &pAttack.m_bSignaled) + // && (dwModifier & CECAttackEvent::MOD_BEAT_BACK) == 0) + // { + // } + // else + // { + // pAttack.m_bSignaled = true; + // } + // } + // } + // else + // { + // if (skillLevel == 0) + // { + // if (m_pCurSkill) + // skillLevel = m_pCurSkill.GetSkillLevel(); + // else + // skillLevel = 1; + // } + + // CECAttackEvent pAttack = null; + + // // first try to find if there is already a skill attack event in attackman + // CECAttackerEvents attackerEvents = g_pGame.GetGameRun().GetWorld().GetAttacksMan().FindAttackByAttacker(GetPlayerInfo().cid); + // if (attackerEvents) + // { + // CECAttackEvent pAttack = attackerEvents.Find(idSkill, nSection); + // if (() != null) + // { + // // Ãæ¹¥»÷µÄ·ÇµÚÒ»´ÎÉ˺¦ÏûÏ¢ + // pAttack.AddTarget(idTarget, dwModifier, nDamage); + // goto EXIT; + // } + // else + // { + // attackerEvents.Signal(); + // } + // } + // if (GNET::ElementSkill::IsGoblinSkill(idSkill) && + // GNET::ElementSkill::GetType(idSkill) == 2) + // { + // pAttack = g_pGame.GetGameRun().GetWorld().GetAttacksMan().AddSkillAttack( + // GetPlayerInfo().cid, GetPlayerInfo().cid, idTarget, GetWeaponID(), idSkill, skillLevel, dwModifier, nDamage); + // } + // else + // { + // // begin a skill attack + // pAttack = g_pGame.GetGameRun().GetWorld().GetAttacksMan().AddSkillAttack( + // GetPlayerInfo().cid, m_idCurSkillTarget, idTarget, GetWeaponID(), idSkill, skillLevel, dwModifier, nDamage); + // } + + // if (pAttack) + // { + // pAttack.SetSkillSection(nSection); + // if (!IsDead() && (dwModifier & CECAttackEvent::MOD_RETORT) == 0 + // && (dwModifier & CECAttackEvent::MOD_ATTACK_AURA) == 0 + // && PlaySkillAttackAction(idSkill, nAttackSpeed, NULL, nSection, &pAttack.m_bSignaled) + // && (dwModifier & CECAttackEvent::MOD_BEAT_BACK) == 0) + // { + // } + // else + // { + // pAttack.m_bSignaled = true; + // } + // } + + // EXIT: + // // For skill attacking, time is always set to 0 + // if (piAttackTime) + // *piAttackTime = 0; + // } + //} + //public A3DVECTOR3 GetPos() //{ // return new A3DVECTOR3(transform.position.x, transform.position.y, transform.position.z);