using Animancer; using BrewMonster; using BrewMonster.Managers; using BrewMonster.Scripts.Managers; using CSNetwork.GPDataType; using ModelRenderer.Scripts.GameData; using PerfectWorld.Scripts.Managers; using PerfectWorld.Scripts.Player; using System; using System.Collections.Generic; using System.Xml.Linq; using TMPro; using Unity.VisualScripting; using UnityEngine; using UnityEngine.SceneManagement; public abstract class CECPlayer : CECObject { [SerializeField] protected Transform parentModel; [SerializeField] protected TextMeshProUGUI txtName; private static PLAYER_ACTION[] _default_actions; private static PLAYER_ACTION[] _turning_actions; PLAYER_ACTION[] m_PlayerActions; [SerializeField] internal INFO m_PlayerInfo; protected GameObject _pPlayerModel; protected float rotationSpeed = 5; internal int m_iMoveMode; // Player's move mode [SerializeField] internal int m_idSelTarget; protected int m_iShape; // Ñ¡ÖÐÄ¿±êµÄID protected uint m_dwStates; // Player's basic states protected uint m_uAttackType; protected int[] m_aEquips; protected ROLEEXTPROP m_ExtProps; // Extend properties protected int m_iFashionWeaponType; protected float m_fTouchRad = 0.3f; // Touch radius protected bool m_bWeaponAttached; protected bool m_bFight; protected int m_iBattleCamp = Player_camp_in_battle.GP_BATTLE_CAMP_NONE; // Battle this player belongs to byte m_factionPVPMask; // pvp mask protected uint m_dwResFlags; // 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 protected bool m_bFashionMode; public bool m_bShowWeapon; private QueueActionEvent queueActionEvent; protected static PLAYER_LEVELEXP_CONFIG _player_levelup_exp; protected int NUM_WEAPON_TYPE = 15; public static readonly int[] m_sciStateIDForStateAction = { 117 }; public MOVECONST m_MoveConst; // Const used when moving control public Move_Mode m_MoveMode; public MOVECONST[] aMoveConsts = new MOVECONST[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER] { // ÎäÏÀ // fStepHei fMinAirHei fMinWaterHei fShoreDepth fWaterSurf new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // ·¨Ê¦ new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // Î×ʦ new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // Ñý¾« new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // ÑýÊÞ new MOVECONST(0.8f, 1.6f, 0.3f, 1.8f, 0.7f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), // ´Ì¿Í new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // Óðâ new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // ÓðÁé new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // ½£Áé new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // ÷ÈÁé new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // Ò¹Ó° new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), // ÔÂÏÉ new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f), new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f), }; public A3DVECTOR3[] aExts = new A3DVECTOR3[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER] { new A3DVECTOR3(0.4f, 0.9f, 0.4f), // ÎäÏÀ new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ·¨Ê¦ new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Î×ʦ new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Ñý¾« new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.5f, 1.05f, 0.5f), // ÑýÊÞ new A3DVECTOR3(0.3f, 0.9f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ´Ì¿Í new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Óðâ new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÓðÁé new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ½£Áé new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÷ÈÁé new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Ò¹Ó° new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÔÂÏÉ new A3DVECTOR3(0.3f, 0.85f, 0.3f), }; protected void Awake() { m_PlayerActions = _default_actions; m_iShape = 0; m_aEquips = new int[(int)IndexOfIteminEquipmentInventory.SIZE_ALL_EQUIPIVTR]; queueActionEvent = new QueueActionEvent("", null, false, null); } public void SetModelHostPlayer() { parentModel = transform.GetChild(0); txtName = GetComponentInChildren(); _pPlayerModel = NPCManager.Instance.GetModelPlayer(); Scene scene = SceneManager.GetSceneByName("a61"); SceneManager.MoveGameObjectToScene(_pPlayerModel, scene); _pPlayerModel.transform.SetParent(parentModel); _pPlayerModel.transform.localPosition = Vector3.zero; _pPlayerModel.SetActive(true); } public virtual void SetUpPlayer() { m_dwResFlags = 0; m_iFashionWeaponType = -1; m_uAttackType = DEFAULT_ACTION_TYPE; AttachWeapon(); } 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(); DATA_TYPE dt = default; _player_levelup_exp = (PLAYER_LEVELEXP_CONFIG)ElementDataManProvider.GetElementDataMan() .get_data_ptr(202, ID_SPACE.ID_SPACE_CONFIG, ref dt); } 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; } public int GetCharacterID() { return m_PlayerInfo.cid; } private static void BuildActionList() { if (_default_actions == null) { // thay cho hashtab trong C++ Dictionary actionMap = new Dictionary(100); 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) { 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); _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)) { 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) { 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 INFO GetPlayerInfo() { return m_PlayerInfo; } 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 void PlayAttackEffect(int idTarget, int idSkill, int skillLevel, int nDamage, uint dwModifier, int nAttackSpeed, ref int piAttackTime, int nSection = 0) { if (!IsAllResReady()) return; if (idSkill == 0) { int idWeapon = IsShapeChanged() ? 0 : GetWeaponID(); int nTimeFly = 10; if (idWeapon != 0) { // ¿´¿´ÊDz»ÊÇÔ¶³ÌÎäÆ÷ DATA_TYPE dt = default; WEAPON_ESSENCE? pWeapon = (WEAPON_ESSENCE)ElementDataManProvider.GetElementDataMan() .get_data_ptr((uint)idWeapon, ID_SPACE.ID_SPACE_ESSENCE, ref dt); if (dt == DATA_TYPE.DT_WEAPON_ESSENCE && pWeapon != null && pWeapon.Value.require_projectile != 0) { nTimeFly = 700; if (m_aEquips[(int)IndexOfIteminEquipmentInventory.EQUIPIVTR_PROJECTILE] != 0) idWeapon = m_aEquips[(int)IndexOfIteminEquipmentInventory.EQUIPIVTR_PROJECTILE]; } } if (CECAttacksMan.Instance.FindAttackByAttacker(GetPlayerInfo().cid)) { BMLogger.LogError("CECAttacksMan::FindAttackByAttacker != NULL"); ClearComActFlagAllRankNodes(true); } // melee attack CECAttackEvent pAttack = CECAttacksMan.Instance.AddMeleeAttack( GetPlayerInfo().cid, idTarget, idWeapon, dwModifier, nDamage, nTimeFly); if (pAttack != null) { if (!IsDead() && (dwModifier & (uint)MOD.MOD_RETORT) == 0 && (dwModifier & (uint)MOD.MOD_ATTACK_AURA) == 0 && PlayAttackAction(nAttackSpeed, ref piAttackTime, pAttack) && (dwModifier & (uint)MOD.MOD_BEAT_BACK) == 0) { } else { pAttack.m_bSignaled = true; } } } //else //{ // if (skillLevel == 0) // { // if (m_pCurSkill) // skillLevel = m_pCurSkill.GetSkillLevel(); // else // skillLevel = 1; // } // CECAttackEvent pAttack1 = 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 pAttack1 = attackerEvents.Find(idSkill, nSection); // if (pAttack1 != null) // { // // Ãæ¹¥»÷µÄ·ÇµÚÒ»´ÎÉ˺¦ÏûÏ¢ // pAttack1.AddTarget(idTarget, dwModifier, nDamage); // goto EXIT; // } // else // { // attackerEvents.Signal(); // } // } // if (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; //} } private void ClearComActFlagAllRankNodes(bool v) { EventBus.PublishChannel(m_PlayerInfo.cid, new CleearComActFlagAllRankNodesEvent(v)); } public struct CleearComActFlagAllRankNodesEvent { public bool v; public CleearComActFlagAllRankNodesEvent(bool value) { v = value; } } public bool PlayAttackAction(int nAttackSpeed, ref int attackTime, CECAttackEvent attackEvent) { //attackTime = 0; //if (_pPlayerModel == null) // return false; int nRand = UnityEngine.Random.Range(0, 4); string szAct = string.Empty; int weapon_type = GetShowingWeaponType(); int nTime1 = 0, nTime2 = 0; int iAction = (int)PLAYER_ACTION_TYPE.ACT_ATTACK_1 + nRand; PLAYER_ACTION action = m_PlayerActions[iAction]; if (string.IsNullOrEmpty(action.data.ActionPrefix)) return false; ShowWeaponByConfig(action.data); /* var pRightHandWeapon = GetRightHandWeapon(); bool bHideFX = !CECOptimize.Instance.GFX.CanShowAttack(GetCharacterID(), GetClassID());*/ // ============================== // Ground Attack // ============================== if (GetMoveEnv() == (int)MoveEnvironment.MOVEENV_GROUND) { // “起” 动作(挥起) szAct = EC_Utility.BuildActionName(action, weapon_type, "Æð"); EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szAct)); szAct = EC_Utility.BuildActionName(action, weapon_type, "Âä"); queueActionEvent.SetData(szAct, SetApplyDamage, true, attackEvent); EventBus.PublishChannelClass(m_PlayerInfo.cid, queueActionEvent); //PlayNonSkillActionWithName(iAction, szAct, true, 200, true, ref pActFlag, COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX);gagága /* if (pRightHandWeapon != null && IsUsingMagicWeapon()) pRightHandWeapon.PlayActionByName(_GenWeaponActionName(szAct, m_iGender), 1.0f, true, 200, true, iAction, bHideFX); nTime1 = _pPlayerModel.GetComActTimeSpanByName(szAct); // “收” 动作(挥下) szAct = $"{action.data.action_prefix}_{action.data.action_weapon_suffix[weapon_type].suffix}Âä"; QueueNonSkillActionWithName(iAction, szAct, 0, false, bHideFX); if (pRightHandWeapon != null && IsUsingMagicWeapon()) pRightHandWeapon.QueueAction(_GenWeaponActionName(szAct, m_iGender), 0, iAction, false, false, bHideFX); nTime2 = _pPlayerModel.GetComActTimeSpanByName(szAct);*/ } // ============================== // Air Attack // ============================== else { /*string szActionMiddleName; if ((m_wingType == WINGTYPE_WING && IsFlying()) || GetProfession() == PROF_ANGEL || GetProfession() == PROF_ARCHOR || GetProfession() == PROF_MONK || GetProfession() == PROF_GHOST) { szActionMiddleName = "¿ÕÖгá°ò"; // tấn công trên không } else { szActionMiddleName = "¿ÕÖзɽ£"; // rơi xuống hoặc bay } szAct = $"{action.data.action_prefix}_{szActionMiddleName}_{action.data.action_weapon_suffix[weapon_type].suffix}Æð"; PlayNonSkillActionWithName(iAction, szAct, true, 200, bHideFX, ref pActFlag, COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX); if (pRightHandWeapon != null && IsUsingMagicWeapon()) pRightHandWeapon.PlayActionByName(_GenWeaponActionName(szAct, m_iGender), 1.0f, true, 200, true, iAction, bHideFX); nTime1 = m_pPlayerModel.GetComActTimeSpanByName(szAct); szAct = $"{action.data.action_prefix}_{szActionMiddleName}_{action.data.action_weapon_suffix[weapon_type].suffix}Âä"; QueueNonSkillActionWithName(iAction, szAct, 0, false, bHideFX); if (pRightHandWeapon != null && IsUsingMagicWeapon()) pRightHandWeapon.QueueAction(_GenWeaponActionName(szAct, m_iGender), 0, iAction, false, false, bHideFX); nTime2 = m_pPlayerModel.GetComActTimeSpanByName(szAct);*/ } // ============================== // Kết thúc bằng FightStand // ============================== PLAYER_ACTION stand_action = m_PlayerActions[(int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND]; szAct = EC_Utility.BuildActionName(stand_action, 0); queueActionEvent.SetData(szAct, SetApplyDamage, false, attackEvent); EventBus.PublishChannelClass(m_PlayerInfo.cid, queueActionEvent); /* QueueNonSkillActionWithName(ACT_FIGHTSTAND, szAct, 300, false, bHideFX, true); if (pRightHandWeapon != null && IsUsingMagicWeapon()) pRightHandWeapon.QueueAction(_GenWeaponActionName(szAct, m_iGender), 300, iAction, false, false, bHideFX, true);*/ // ============================== // Điều chỉnh tốc độ phát animation theo tốc độ tấn công // ============================== /* if (nAttackSpeed > 0) { float vScale = (nTime1 + nTime2) / (float)nAttackSpeed; if (vScale > 0f) { m_pPlayerModel.SetPlaySpeed(vScale); if (pRightHandWeapon != null && IsUsingMagicWeapon()) pRightHandWeapon.SetPlaySpeed(vScale); } } attackTime = nTime1 + nTime2;*/ // ============================== // Cập nhật vị trí weapon hanger (vũ khí) // ============================== //UpdateWeaponHangerPosByAction(iAction); return true; } public void SetApplyDamage(bool isApplyDamage, CECAttackEvent cECAttackEvent) { cECAttackEvent.m_bSignaled = isApplyDamage; } public void ShowWeaponByConfig(PLAYER_ACTION_INFO_CONFIG p) { m_bShowWeapon = p.hide_weapon != 0 ? false : true; //ShowWeapon(m_bShowWeapon); } public int GetShowingWeaponType() { //todo: mr Hoang should double check it return 10; int weapon_type = 0; if (CanShowFashionWeapon((int)m_uAttackType, m_iFashionWeaponType) && m_aEquips[(int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_WEAPON] != 0) { weapon_type = (EC_Utility.BinaryEquals(m_iFashionWeaponType, DEFAULT_ACTION_TYPE) || !IsWeaponAttached()) ? 10 : m_iFashionWeaponType; } else { weapon_type = (EC_Utility.BinaryEquals(m_uAttackType, DEFAULT_ACTION_TYPE) || !IsWeaponAttached()) ? 10 : (int)m_uAttackType; } return weapon_type; } public bool IsWeaponAttached() { return m_bWeaponAttached; } bool AttachWeapon(){ bool result = (false); /*while (GetPlayerModel() && (GetLeftHandWeapon() || GetRightHandWeapon())){ A3DSkinModel *pSkinModel = GetPlayerModel()->GetA3DSkinModel(); if (!pSkinModel || !pSkinModel->GetSkeleton()){ break; } if (!pSkinModel->GetSkeletonHook(GetLeftWeaponHookPos(m_weaponHangerPos),true) || !pSkinModel->GetSkeletonHook(GetRightWeaponHookPos(m_weaponHangerPos),true)){ break; } if (GetLeftHandWeapon()){ GetPlayerModel()->AddChildModel( _left_hand_weapon, false, GetLeftWeaponHookPos(m_weaponHangerPos), GetLeftHandWeapon(), GetLeftWeaponOwnHookPos(GetLeftHandWeapon())); } if (GetRightHandWeapon()){ GetPlayerModel()->AddChildModel( _right_hand_weapon, false, GetRightWeaponHookPos(m_weaponHangerPos), GetRightHandWeapon(), GetRightWeaponOwnHookPos(GetRightHandWeapon())); } ALog log; log.Init("EC.log", "My Application Log"); // Anywhere in your code where you want to see the call flow: log.Log("[HoangDev]Checking execution flow at this point:"); log.LogStackTrace(); log.Release(); m_bWeaponAttached = true; result = true; break; }*/ m_bWeaponAttached = true; result = true; return result; } public bool InFashionMode() { return m_bFashionMode; } public bool CanShowFashionWeapon(int weapon_type, int fashion_weapon_type) { return IsFashionWeaponTypeFit(weapon_type, fashion_weapon_type) && InFashionMode(); } public bool IsFashionWeaponTypeFit(int weapon_type, int fashion_weapon_type) { if (fashion_weapon_type < 0 || fashion_weapon_type >= NUM_WEAPON_TYPE) return false; FASHION_WEAPON_CONFIG? pConfig = GetFashionConfig(); if (null == pConfig) { BMLogger.LogError("CECPlayer::GetFashionConfig, Failed to load fashion weapon config"); return false; } int fashion_weapon_mask = (int)pConfig.Value.action_mask[fashion_weapon_type]; return (fashion_weapon_mask & (1 << GetWeaponType(weapon_type))) != 0; } public FASHION_WEAPON_CONFIG GetFashionConfig() { FASHION_WEAPON_CONFIG? pFashionConfig = null; if (null == pFashionConfig) { elementdataman pDataMan = ElementDataManProvider.GetElementDataMan(); DATA_TYPE DataType = DATA_TYPE.DT_FASHION_WEAPON_CONFIG; uint tid = pDataMan.get_id_with_data_type(ID_SPACE.ID_SPACE_CONFIG, DataType); if (tid != 0) { pFashionConfig = (FASHION_WEAPON_CONFIG)pDataMan.get_data_ptr(tid, ID_SPACE.ID_SPACE_CONFIG, ref DataType); BMLogger.LogError($"HoangDev : get_data_ptr {pFashionConfig.GetType()}"); } } return pFashionConfig == null ? default : pFashionConfig.Value; } public int GetSelectedTarget() { return m_idSelTarget; } 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 const uint DEFAULT_ACTION_TYPE = 0xFFFFFFFF; public static int GetWeaponType(int iWeaponType) { return iWeaponType == DEFAULT_ACTION_TYPE ? 10 : iWeaponType; } public bool IsInFactionPVP() => (m_factionPVPMask & 0x01) != 0; public bool CanAttackFactionPVPMineCar() => (m_factionPVPMask & 0x02) != 0; public bool CanAttackFactionPVPMineBase() => (m_factionPVPMask & 0x04) != 0; public int GetLevelUpExp(int iLevel) { return _player_levelup_exp.exp[iLevel - 1]; //return iLevel * iLevel * 500; } // Get basic properties public ROLEBASICPROP GetBasicProps() { return m_BasicProps; } public override void TurnFaceTo(int idTarget, float dwTime = 200) { if (idTarget != 0) { if (idTarget == GetCharacterID()) { return; } if (IsWorkMoveRunning() /*&& !IsPlayingCastingSkillAndMoveActions()*/) { // ÒÆ¶¯Ê±Ò»°ãÓ¦ÃæÏòÒÆ¶¯·½Ïò¡¢Ö»ÔÚÒÆ¶¯Ê©·¨ÖвÅתÏò return; } } var target = EC_ManMessageMono.Instance?.GetObject(idTarget, 0)?.gameObject.transform; if (target == null) { BMLogger.LogError("HoangDev: ko có transform "); return; } Vector3 direction = (target.position - transform.position).normalized; direction.y = 0f; int turnSpeed = 5; if (direction.sqrMagnitude > 0.001f) { // Tạo rotation mới hướng tới target Quaternion targetRotation = Quaternion.LookRotation(direction, Vector3.up); // Xoay mượt từ rotation hiện tại sang rotation mục tiêu //transform.rotation = Quaternion.Slerp( // transform.rotation, // targetRotation, // Time.deltaTime * turnSpeed //); transform.rotation = targetRotation; } } public virtual bool IsWorkMoveRunning() { return false; } /* public bool IsPlayingCastingSkillAndMoveActions() { return IsPlayingCastingSkillAction() && IsPlayingMoveAction(); } public bool IsPlayingCastingSkillAction() { return m_pActionController ? m_pActionController.IsPlayingCastingSkillAction() : false; } bool IsPlayingMoveAction() { return m_pActionController ? m_pActionController.IsPlayingMoveAction() : false; }*/ 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; } public void Damaged(int nDamage, uint dwModifier = 0, int skill = 0) { BMLogger.LogError($"HoangDev: Damaged nDamage={nDamage} "); if (nDamage == -2) { // this message is caused by a help skill, so don't use a wounded action here /* if (dwModifier & CECAttackEvent::MOD_IMMUNE) BubbleText(BUBBLE_IMMUNE, 0); else if (dwModifier & CECAttackEvent::MOD_NULLITY) BubbleText(BUBBLE_INVALIDHIT, 0); else if (dwModifier & CECAttackEvent::MOD_DODGE_DEBUFF) BubbleText(BUBBLE_DODGE_DEBUFF, 0);*/ } else if (nDamage == -1) { // when else player hit this player iDamage is -1, // Just play a wounded action if (!OnDamaged(skill)) { PlayAction((int)PLAYER_ACTION_TYPE.ACT_WOUNDED); } /*if (dwModifier & CECAttackEvent::MOD_IMMUNE) BubbleText(BUBBLE_IMMUNE, 0); else if (dwModifier & CECAttackEvent::MOD_NULLITY) BubbleText(BUBBLE_INVALIDHIT, 0); else if (dwModifier & CECAttackEvent::MOD_DODGE_DEBUFF) BubbleText(BUBBLE_DODGE_DEBUFF, 0);*/ } else { // Popup a damage decal if (nDamage > 0) { int p1 = 0; /*if (dwModifier & CECAttackEvent::MOD_CRITICAL_STRIKE) p1 |= 0x0001; if (dwModifier & CECAttackEvent::MOD_RETORT) p1 |= 0x0002;*/ if (!OnDamaged(skill)) PlayAction((int)PLAYER_ACTION_TYPE.ACT_WOUNDED); DamageTextManager.Instance.ShowDamageText( transform.position, nDamage, Color.yellow, 1.0f); /* if (dwModifier & CECAttackEvent::MOD_IMMUNE) BubbleText(BUBBLE_IMMUNE, 0); else if (dwModifier & CECAttackEvent::MOD_REBOUND) BubbleText(BUBBLE_REBOUND, nDamage); else if (dwModifier & CECAttackEvent::MOD_BEAT_BACK) BubbleText(BUBBLE_BEAT_BACK, nDamage); else BubbleText(BUBBLE_DAMAGE, nDamage, p1);*/ } /* else if (dwModifier & CECAttackEvent::MOD_IMMUNE) BubbleText(BUBBLE_IMMUNE, 0); else if (dwModifier & CECAttackEvent::MOD_NULLITY) BubbleText(BUBBLE_INVALIDHIT, 0); else BubbleText(BUBBLE_HITMISSED, 0);*/ } } public bool OnDamaged(int skill) { var atkMan = CECAttacksMan.Instance; if (atkMan == null) return false; string name1, name2; for (int i = 0; i < m_sciStateIDForStateAction.Length; i++) { /* if (atkMan.GetSkillStateActionName(skill, m_sciStateIDForStateAction[i], out name1, out name2)) { m_SkillIDForStateAction = skill; return true; }*/ } return false; } bool GetSkillStateActionName(int skill, int state, string name1, string name2) { /* for (int i = 0; i < (int)m_SkillStateActionVec.size(); i++) { if (m_SkillStateActionVec[i].skill == skill && m_SkillStateActionVec[i].state == state) { name1 = m_SkillStateActionVec[i].beHitAction; name2 = m_SkillStateActionVec[i].stayDownAction; return true; } }*/ return false; } public virtual bool IsFighting() { return m_bFight; } public float GetGroundSpeed() { // return m_bWalkRun ? g_pGame.GetConfigs().GetHostRunSpeed() : m_ExtProps.mv.walk_speed; return 5f; return m_bWalkRun ? m_ExtProps.mv.run_speed : m_ExtProps.mv.walk_speed; } // Get move environment public int GetMoveEnv() { return m_iMoveEnv; } public bool IsShapeChanged() { return m_iShape != 0; } public int GetWeaponID() { return m_aEquips[(int)IndexOfIteminEquipmentInventory.EQUIPIVTR_WEAPON] & 0xffff; } public bool IsAllResReady() { return (m_dwResFlags & (uint)PlayerResourcesReadyFlag.RESFG_ALL) == (uint)PlayerResourcesReadyFlag.RESFG_ALL; } // Get character ID } public struct PlayActionEvent { public string AnimationName; public PlayActionEvent(string animationName) { this.AnimationName = animationName; } } public class QueueActionEvent { public string AnimationName; public Action SetFlag; public CECAttackEvent AttackEvent; public bool IsHitAnim; public QueueActionEvent(string animationName, Action setFlag, bool isHitAnim, CECAttackEvent attackEvent) { this.AnimationName = animationName; SetFlag = setFlag; IsHitAnim = isHitAnim; AttackEvent = attackEvent; } public void SetData(string animationName, Action setFlag, bool isHitAnim, CECAttackEvent attackEvent) { this.AnimationName = animationName; SetFlag = setFlag; IsHitAnim = isHitAnim; AttackEvent = attackEvent; } } [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 enum PlayerResourcesReadyFlag { RESFG_SKELETON = 0x01, RESFG_SKIN = 0x02, RESFG_CUSTOM = 0x04, RESFG_ASSEMBLED = 0x08, RESFG_ALL = 0x0f, }; 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 class Move_Mode { public const int MOVE_STAND = 0, MOVE_MOVE = 1, // Normal move, walk, run, swim or fly MOVE_JUMP = 2, MOVE_FREEFALL = 3, MOVE_SLIDE = 4; }