From eed08c2b1391a15b7e579586d58cf9122283a201 Mon Sep 17 00:00:00 2001 From: VDH Date: Sat, 8 Nov 2025 16:41:19 +0700 Subject: [PATCH] bug skill data not received --- .../Scripts/MainFiles/CECGameRun.cs | 25 --- .../Scripts/MainFiles/CECGameRun.cs.meta | 2 - .../Scripts/Network/CSNetwork/GPDataType.cs | 18 ++- .../Scripts/Network/CSNetwork/GameSession.cs | 4 + .../PerfectWorld/Scripts/Skills/CECSCSkill.cs | 39 ++--- .../Scripts/Skills/EC_HostSkillModel.cs | 7 +- .../Scripts/Skills/ElementSkill.cs | 7 +- .../Scripts/Skills/SkillWrapper.cs | 35 +++++ .../Scripts/Skills/SkillWrapper.cs.meta | 2 + Assets/Scenes/a61.unity | 4 +- Assets/Scripts/CECGameRun.cs | 19 ++- Assets/Scripts/CECHostPlayer.cs | 143 +++++++++++++++--- 12 files changed, 233 insertions(+), 72 deletions(-) delete mode 100644 Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs delete mode 100644 Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs.meta create mode 100644 Assets/PerfectWorld/Scripts/Skills/SkillWrapper.cs create mode 100644 Assets/PerfectWorld/Scripts/Skills/SkillWrapper.cs.meta diff --git a/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs b/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs deleted file mode 100644 index 6eb2ace1d7..0000000000 --- a/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs +++ /dev/null @@ -1,25 +0,0 @@ -using BrewMonster; -using BrewMonster.Scripts.World; -using CSNetwork.GPDataType; -using System; -using UnityEngine; - -public partial class CECGameRun -{ - private CECWorld m_pWorld; - public CECWorld GetWorld() { return m_pWorld; } - public bool StartGame(int idInst, Vector3 vHostPos) - { - if (!JumpToInstance(idInst, vHostPos)) - { - BMLogger.LogError ( "CECGameRun::StartGame, Failed to create game world."); - return false; - } - return true; - } - - private bool JumpToInstance(int idInst, Vector3 vHostPos, int iParallelWorldID = 0) - { - return true; - } -} diff --git a/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs.meta b/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs.meta deleted file mode 100644 index 7cf0ff7a64..0000000000 --- a/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 923b4102fc6857a4e94d7a662b2e6e1a \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs index 1092c9f747..cf749f28b1 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs @@ -1197,15 +1197,31 @@ namespace CSNetwork.GPDataType public const float MIN_MOVELEN_FOR_DETECT_VIBRATION = 0.05f; } [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_skill_data + { + public uint skill_count; + + public struct SKILL + { + public short id_skill; + public byte level; + public short ability; + + } + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + public SKILL[] skill_list; + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct cmd_scene_service_npc_list { public uint count; - [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct NpcEntry { public int tid; // npc template id public int nid; // npc id } + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public NpcEntry[] list; } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index 743b7fcd7b..0d2e68e06b 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -613,6 +613,10 @@ namespace CSNetwork CECHostSkillModel.Instance.RecvNPCServiceList(protocol.Data); break; } + case CommandID.SKILL_DATA: + BMLogger.LogError("HoangDev: SKILL_DATASKILL_DATA"); + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; } } diff --git a/Assets/PerfectWorld/Scripts/Skills/CECSCSkill.cs b/Assets/PerfectWorld/Scripts/Skills/CECSCSkill.cs index 9888af4f3d..4db3a876e2 100644 --- a/Assets/PerfectWorld/Scripts/Skills/CECSCSkill.cs +++ b/Assets/PerfectWorld/Scripts/Skills/CECSCSkill.cs @@ -13,7 +13,12 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.Skills public class CECSCSkill { CECSkill m_pSkill; - public bool Excute() + public bool Init(CECSkill pSkill) + { + m_pSkill = pSkill; + return true; + } + public bool Execute() { if (m_pSkill == null) return false; @@ -22,23 +27,23 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.Skills if (ElementSkill.IsGoblinSkill((uint)m_pSkill.GetSkillID())) { - /* int idSelected = pHost->GetSelectedTarget(); - bool bForctAttack = glb_GetForceAttackFlag(NULL); - CECHostGoblin* pHostGoblin = (CECHostGoblin*)pHost->GetGoblinModel(); - int i; - for (i = 0; i < pHostGoblin->GetSkillNum(); i++) - { - if (m_pSkill == pHostGoblin->GetSkill(i)) - { - break; - } - } - if (i < pHostGoblin->GetSkillNum()) - { - a_LogOutput(1, "HoangDev: Shortcut: pHostGoblin->GetSkillNum()"); + /* int idSelected = pHost->GetSelectedTarget(); + bool bForctAttack = glb_GetForceAttackFlag(NULL); + CECHostGoblin* pHostGoblin = (CECHostGoblin*)pHost->GetGoblinModel(); + int i; + for (i = 0; i < pHostGoblin->GetSkillNum(); i++) + { + if (m_pSkill == pHostGoblin->GetSkill(i)) + { + break; + } + } + if (i < pHostGoblin->GetSkillNum()) + { + a_LogOutput(1, "HoangDev: Shortcut: pHostGoblin->GetSkillNum()"); - pHostGoblin->CastSkill(i, idSelected, bForctAttack); - }*/ + pHostGoblin->CastSkill(i, idSelected, bForctAttack); + }*/ } else { diff --git a/Assets/PerfectWorld/Scripts/Skills/EC_HostSkillModel.cs b/Assets/PerfectWorld/Scripts/Skills/EC_HostSkillModel.cs index dd7b165925..60a5cb83a0 100644 --- a/Assets/PerfectWorld/Scripts/Skills/EC_HostSkillModel.cs +++ b/Assets/PerfectWorld/Scripts/Skills/EC_HostSkillModel.cs @@ -52,6 +52,11 @@ namespace BrewMonster.Scripts.Skills } public void ProcessServiceList() { + if (m_npcListData== null) + { + BMLogger.LogWarning("CECHostSkillModel::ProcessServiceList, m_npcListData is null."); + return; + } if (m_npcListData.Size > 0) { byte[] data = m_npcListData.RawBuffer; @@ -111,7 +116,7 @@ namespace BrewMonster.Scripts.Skills var npcEssence = (NPC_ESSENCE)dataprt; // Get skill service block from id_skill_service - var dataprt2 = pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref dt); + var dataprt2 = pDB.get_data_ptr(npcEssence.id_skill_service, ID_SPACE.ID_SPACE_ESSENCE, ref dt); if (dataprt2 == null) return; diff --git a/Assets/PerfectWorld/Scripts/Skills/ElementSkill.cs b/Assets/PerfectWorld/Scripts/Skills/ElementSkill.cs index 321c42d2ed..04e213d5e4 100644 --- a/Assets/PerfectWorld/Scripts/Skills/ElementSkill.cs +++ b/Assets/PerfectWorld/Scripts/Skills/ElementSkill.cs @@ -1,3 +1,5 @@ +using BrewMonster.Assets.PerfectWorld.Scripts.Skills; +using CSNetwork.GPDataType; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -171,7 +173,10 @@ namespace BrewMonster.Scripts.Skills SkillStub s = SkillStub.GetStub(id); return s != null && (s.GetCls() == 258); } - // �������漶�� + public static void LoadSkillData(cmd_skill_data data) + { + SkillWrapper.Instance.LoadData(data); + } public virtual int GetRank() { return 0; } // ѧϰn������Ҫ�����Ҽ��� public virtual int GetRequiredLevel() { return 0; } diff --git a/Assets/PerfectWorld/Scripts/Skills/SkillWrapper.cs b/Assets/PerfectWorld/Scripts/Skills/SkillWrapper.cs new file mode 100644 index 0000000000..3627c4268f --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Skills/SkillWrapper.cs @@ -0,0 +1,35 @@ +using BrewMonster.Assets.PerfectWorld.Scripts.Common; +using CSNetwork.GPDataType; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BrewMonster.Assets.PerfectWorld.Scripts.Skills +{ + public struct PersistentData + { + public int ability; // ÊìÁ·¶È + public int level; // ¼¶±ð + + public PersistentData(int _t = 0, int _l = 1) { ability = (_t); level = (_l); } + }; + + public class SkillWrapper : Singleton + { + Dictionary map = new Dictionary(); + public void LoadData(cmd_skill_data pdata) + { + map.Clear(); + PersistentData skill; + for (int i = 0; i < (int)pdata.skill_count; i++) + { + cmd_skill_data.SKILL item = pdata.skill_list[i]; + skill.level = item.level; + skill.ability = item.ability; + map[(uint)item.id_skill] = skill; + } + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Skills/SkillWrapper.cs.meta b/Assets/PerfectWorld/Scripts/Skills/SkillWrapper.cs.meta new file mode 100644 index 0000000000..de34dd48ba --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Skills/SkillWrapper.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9475bf4d7aee23340a1a7444cafb502e \ No newline at end of file diff --git a/Assets/Scenes/a61.unity b/Assets/Scenes/a61.unity index d4bd652b8a..2cc0422482 100644 --- a/Assets/Scenes/a61.unity +++ b/Assets/Scenes/a61.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3df77e654f3a5255269e6a12859be0c185eef6bba1246f1f593148e2112d50c5 -size 533674545 +oid sha256:f976127e7fdcfdfeb7255c5da4baebb416fc3f37d1697952519189cf3c9712fb +size 533675813 diff --git a/Assets/Scripts/CECGameRun.cs b/Assets/Scripts/CECGameRun.cs index 13487ec84e..8bb02cdc7e 100644 --- a/Assets/Scripts/CECGameRun.cs +++ b/Assets/Scripts/CECGameRun.cs @@ -1,4 +1,6 @@ -using CSNetwork.GPDataType; +using BrewMonster; +using BrewMonster.Scripts.World; +using CSNetwork.GPDataType; using CSNetwork.Protocols.RPCData; using System.Data; using Unity.Cinemachine; @@ -21,7 +23,22 @@ public partial class CECGameRun : MonoBehaviour public CinemachineFreeLook freeLookCam; public float rotateSpeedX = 300f; // tốc độ xoay ngang public float rotateSpeedY = 2f; // tốc độ xoay dọc + private CECWorld m_pWorld; + public CECWorld GetWorld() { return m_pWorld; } + public bool StartGame(int idInst, Vector3 vHostPos) + { + if (!JumpToInstance(idInst, vHostPos)) + { + BMLogger.LogError("CECGameRun::StartGame, Failed to create game world."); + return false; + } + return true; + } + private bool JumpToInstance(int idInst, Vector3 vHostPos, int iParallelWorldID = 0) + { + return true; + } public static CECGameRun Instance { diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 09fd259c4c..f1745da743 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -28,6 +28,7 @@ using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using UnityEngine.UI; +using static Unity.Burst.Intrinsics.X86.Avx; using static UnityEditor.PlayerSettings; using Scene = UnityEngine.SceneManagement.Scene; @@ -60,9 +61,11 @@ public class CECHostPlayer : CECPlayer private List m_aTabSels = new List(); private List m_aPtSkills = new List(); + private List m_aPsSkills = new List(); private List m_aEquipSkills = new List(); private List m_aGoblinSkills = new List(); + private bool m_bEnterGame; private CECSkill m_pPrepSkill; private float playerSpeed = 5.0f; private float jumpHeight = 1.5f; @@ -183,6 +186,13 @@ public class CECHostPlayer : CECPlayer private void Update() { +#if UNITY_EDITOR + if (Input.GetKeyDown(KeyCode.C)) + { + ApplySkillShortcut(1); + } +#endif + //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: @@ -239,15 +249,15 @@ public class CECHostPlayer : CECPlayer SelectTarget(m_idUCSelTarget); } - if (idTraceTarget != 0) - { - if (iTraceReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) - { - if (!CanDo(ActionCanDo.CANDO_MELEE)) - return; - NormalAttackObject(idTraceTarget, bForceAttack); - } - } + /* if (idTraceTarget != 0) + { + if (iTraceReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + { + if (!CanDo(ActionCanDo.CANDO_MELEE)) + return; + NormalAttackObject(idTraceTarget, bForceAttack); + } + }*/ } m_pWorkMan?.Tick(Time.deltaTime); } @@ -388,9 +398,98 @@ public class CECHostPlayer : CECPlayer case int value when value == EC_MsgDef.MSG_HST_ATTACKED: OnMsgHstAttacked(Msg); break; case int value when value == EC_MsgDef.MSG_HST_HURTRESULT: OnMsgHstHurtResult(Msg); break; case int value when value == EC_MsgDef.MSG_HST_INFO00: OnMsgHstInfo00(Msg); break; + case int value when value == EC_MsgDef.MSG_HST_SKILLDATA: OnMsgHstSkillData(Msg); break; } } + private void OnMsgHstSkillData(ECMSG Msg) + { + cmd_skill_data pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + + if (pCmd.skill_list == null) + { + BMLogger.LogError("OnMsgHstSkillData: cmd is null"); + return; + } + + /* List skillSCConfigArray1 = new List(); + List skillSCConfigArray2 = new List(); + List skillGrpSCConfigArray1 = new List(); + List skillGrpSCConfigArray2 = new List();*/ + + if (HostIsReady()) + { +/* + for (int i = 0; i < HostConstants.NUM_HOSTSCSETS1; i++) + { + if (hostPlayer.m_aSCSets1[i] != null) + { + hostPlayer.m_aSCSets1[i].RemoveSkillShortcuts(); + } + } + + for (int i = 0; i < HostConstants.NUM_HOSTSCSETS2; i++) + { + if (hostPlayer.m_aSCSets2[i] != null) + { + hostPlayer.m_aSCSets2[i].RemoveSkillShortcuts(); + } + }*/ + + m_aPtSkills.Clear(); + + // Release passive skills + m_aPsSkills.Clear(); + } + + // Load skill data from command + // C++: GNET::ElementSkill::LoadSkillData(pCmd); + ElementSkill.LoadSkillData(pCmd); + + // Create skill objects from command data + for (int i = 0; i < pCmd.skill_count; i++) + { + cmd_skill_data.SKILL data = pCmd.skill_list[i]; + CECSkill skill = new CECSkill(data.id_skill, data.level); + + // Categorize skills into positive and passive + int skillType = skill.GetType(); + if (skillType != (int)CECSkill.SkillType.TYPE_PASSIVE && + skillType != (int)CECSkill.SkillType.TYPE_PRODUCE && + skillType != (int)CECSkill.SkillType.TYPE_LIVE) + { + m_aPtSkills.Add(skill); + } + else + { + m_aPsSkills.Add(skill); + } + } + + // Restore and convert shortcuts after loading new skills + /* if (hostPlayer.HostIsReady()) + { + hostPlayer.ConvertSkillShortcut(skillSCConfigArray1); + hostPlayer.AssignSkillShortcut(skillSCConfigArray1, hostPlayer.m_aSCSets1); + hostPlayer.ConvertSkillShortcut(skillSCConfigArray2); + hostPlayer.AssignSkillShortcut(skillSCConfigArray2, hostPlayer.m_aSCSets2); + hostPlayer.ConvertComboSkill(); + hostPlayer.ValidateSkillGrpShortcut(skillGrpSCConfigArray1); + hostPlayer.AssignSkillGrpShortcut(skillGrpSCConfigArray1, hostPlayer.m_aSCSets1); + hostPlayer.ValidateSkillGrpShortcut(skillGrpSCConfigArray2); + hostPlayer.AssignSkillGrpShortcut(skillGrpSCConfigArray2, hostPlayer.m_aSCSets2); + } + + if (hostPlayer.HostIsReady()) + { + // Update UI when profession changes, save all shortcut configurations + // to remove effects from intermediate skills (invalid pointers) + // C++: CECGameUIMan *pGameUIMan = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); + // pGameUIMan->UpdateSkillRelatedUI(); + hostPlayer.UpdateSkillRelatedUI(); + }*/ + } + public bool HostIsReady() { return true /*m_bEnterGame*/; } private void OnMsgHstInfo00(in ECMSG Msg) { cmd_self_info_00 pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); @@ -1740,24 +1839,24 @@ public class CECHostPlayer : CECPlayer byMask |= (byte)PVPMask.GP_PVPMASK_FORCE; else { - /* CECConfigs pConfigs = EC_Game.GetConfigs(); + /* CECConfigs pConfigs = EC_Game.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;