using Animancer; using BrewMonster; using BrewMonster.Managers; using BrewMonster.Network; using BrewMonster.PerfectWorld.Scripts.Vfx; using BrewMonster.Scripts; using BrewMonster.Scripts; using BrewMonster.Scripts.Managers; using BrewMonster.Scripts.Skills; using CSNetwork.GPDataType; using ModelRenderer.Scripts.GameData; using PerfectWorld.Scripts.Managers; using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Xml.Linq; using TMPro; using Unity.VisualScripting; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UIElements; using static BrewMonster.CECPlayer; using BrewMonster.Network; namespace BrewMonster { public abstract partial class CECPlayer : CECObject { [SerializeField] protected Transform parentModel; [SerializeField] protected TextMeshProUGUI txtName; [SerializeField] protected Transform pointCam; [ResetStatic] private static PLAYER_ACTION[] _default_actions; [ResetStatic] 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; [SerializeField] internal int m_idCurHover; // ID of object under cursor protected int m_iShape; // Ñ¡ÖÐÄ¿±êµÄID protected uint m_dwStates; // Player's basic states protected PVPINFO m_pvp; // pvp information // 当前攻击方式 // Action type for attack animation 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 = true; 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; private CECPlayerActionController m_pActionController; private enumWingType m_wingType = enumWingType.WINGTYPE_FLYSWORD; protected int m_idCurSkillTarget; protected CECSkill m_pCurSkill; protected int m_idFaction; // ID of player's faction protected int m_idForce; // id of the player's force protected int NUM_WEAPON_TYPE = 15; public static readonly int[] m_sciStateIDForStateAction = { 117 }; private static Dictionary _default_skill_actions = new Dictionary(); protected int m_iBoothState = 0; // Booth state. 0, none; 1, prepare; 2, open booth; 3, visite other's booth public int m_idFRole = GNETRoles._R_UNMEMBER; // ID of player's faction role protected int m_idCountry = 0; // ¹úÕ½ÕóÓª id public static int MAX_REINCARNATION = 2; protected List m_aCurEffects = new List(); // Current effects byte m_ReincarnationCount = 0; string m_strName; // Player name // 需要是可能 || Need is possible protected bool m_bHangerOn = false; protected int m_iCurAction; bool m_bAboutToDie = false; public bool m_bCandHangerOn = false; public MOVECONST m_MoveConst; // Const used when moving control public Move_Mode m_MoveMode; public MOVECONST[] aMoveConsts = new MOVECONST[(int)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[(int)PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER] { new A3DVECTOR3(0.4f, 0.9f, 0.4f), // ÎäÏÀ new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ·¨Ê¦ new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Î×ʦ new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Ñý¾« new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.5f, 1.05f, 0.5f), // ÑýÊÞ new A3DVECTOR3(0.3f, 0.9f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ´Ì¿Í new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Óðâ new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÓðÁé new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ½£Áé new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÷ÈÁé new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // Ò¹Ó° new A3DVECTOR3(0.3f, 0.85f, 0.3f), new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÔÂÏÉ new A3DVECTOR3(0.3f, 0.85f, 0.3f), }; public static class Effect_type { public const int EFF_FACEPILL = 1; } private BaseVfxObject _levelUpVfx; 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, 200); } /// This function will get the coressponding model player for the player based on the profession and gender public async Task SetPlayerModel(byte profession, byte gender) { parentModel = transform.GetChild(0); txtName = GetComponentInChildren(); if(transform.childCount >= 3) { pointCam = transform.GetChild(2); } _pPlayerModel = await NPCManager.Instance.GetModelPlayer(profession, gender); Scene scene = SceneManager.GetActiveScene(); 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 async Task LoadPlayerSkin(GameObject aSkins, int index, string szFile) { // these are LOD suffix string[] suffix1 = { "一�?", "二级", "三级" }; string[] suffix2 = { "", "二级", "三级" }; string szSkinFile = ""; if (index == EC_Player_Skin_Const.SKIN_BODY_INDEX || index == EC_Player_Skin_Const.SKIN_HEAD_INDEX) szSkinFile = $"{szFile}{suffix2[0]}"; else szSkinFile = $"{szFile}{suffix1[0]}"; aSkins = await AddressableManager.Instance.LoadPrefabAsync(szSkinFile); if (aSkins == null) return false; return true; } 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 IsInvisible() { return (m_dwStates & PlayerNPCState.GP_STATE_INVISIBLE) != 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) { 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)) { } } if (!string.IsNullOrEmpty(data.ActionName) && data.ActionName[0] != '0') { if (!skillActionMap.TryAdd(data.Name, 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; } } } if (_turning_actions != null) _turning_actions = new PLAYER_ACTION[(int)PLAYER_ACTION_TYPE.ACT_MAX]; _turning_actions = new PLAYER_ACTION[(int)PLAYER_ACTION_TYPE.ACT_MAX]; if (actionMap.TryGetValue("自身旋转", out PLAYER_ACTION_INFO_CONFIG turningData)) { for (int i = 0; i < (int)PLAYER_ACTION_TYPE.ACT_MAX; i++) { if (i < (int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE || i > (int)PLAYER_ACTION_TYPE.ACT_REVIVE) { // Dùng hành động xoay thay thế hành động thường _turning_actions[i].type = (PLAYER_ACTION_TYPE)i; _turning_actions[i].data = turningData; } else { // Dùng hành động mặc định _turning_actions[i] = _default_actions[i]; } } } uint idSkill = 0; while (true) { idSkill = ElementSkill.NextSkill(idSkill); if (idSkill == 0) break; string skillName = ElementSkill.GetName(idSkill); if (!string.IsNullOrEmpty(skillName)) { if (skillActionMap.TryGetValue(skillName, out PLAYER_ACTION_INFO_CONFIG data1)) { // ✅ Gán dữ liệu hành động cho skill tương ứng _default_skill_actions[idSkill] = data1; #if DEBUG_OUTPUT_ACTIONS for (int n = 0; n < PlayerSkillAction.NUM_WEAPON_TYPE; n++) { var suffix = data.action_weapon_suffix[n].suffix; if (!string.IsNullOrEmpty(suffix)) { Debug.Log($"{data.action_prefix}_Ò÷³ª_{suffix}"); Debug.Log($"{data.action_prefix}_Ê©·ÅÆð_{suffix}"); Debug.Log($"{data.action_prefix}_Ê©·ÅÂä_{suffix}"); } } #endif continue; } } // ❌ not found // Debug.LogWarning($"CECPlayer::BuildActionList() Failed to find skill action {idSkill}!"); } } } public bool PlayAction(int iAction, bool bRestart = true, int iTransTime = 200, bool bQueue = false) { return PlayActionWithConfig(iAction, 0, bRestart, iTransTime, bQueue); } public bool PlayAction(int iAction, int actionConfigID, bool bRestart = true, int iTransTime = 200, bool bQueue = false) { return PlayActionWithConfig(iAction, actionConfigID, bRestart, iTransTime, bQueue); } private 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); } private bool PlayActionWithConfig(int iAction, in PLAYER_ACTION actionConfig, bool bRestart = true, int iTransTime = 200, bool bQueue = false) { m_iCurAction = iAction; PLAYER_ACTION action = actionConfig; int weapon_type = GetShowingWeaponType(); var szAct = EC_Utility.BuildActionName(action, weapon_type); EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szAct, iTransTime)); return true; } public static void Dispose() { _default_actions = null; _turning_actions = null; } public INFO GetPlayerInfo() { return m_PlayerInfo; } // Get basic properties public ROLEBASICPROP GetBasicProps() { return m_BasicProps; } // Get extend properties public ROLEEXTPROP GetExtendProps() { return m_ExtProps; } protected override void Update() { base.Update(); } 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)) { ClearComActFlagAllRankNodes(true); } // melee attack CECAttackEvent pAttack1 = CECAttacksMan.Instance.AddMeleeAttack( GetPlayerInfo().cid, idTarget, idWeapon, dwModifier, nDamage, nTimeFly); if (pAttack1 != null) { if (!IsDead() && (dwModifier & (uint)MOD.MOD_RETORT) == 0 && (dwModifier & (uint)MOD.MOD_ATTACK_AURA) == 0 && PlayAttackAction(nAttackSpeed, ref piAttackTime, pAttack1) && (dwModifier & (uint)MOD.MOD_BEAT_BACK) == 0) { } else { pAttack1.m_bSignaled = true; } } } else { if (skillLevel == 0) { if (m_pCurSkill != null) 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 = CECAttacksMan.Instance.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((uint)idSkill) && ElementSkill.GetType((uint)idSkill) == 2) { pAttack = CECAttacksMan.Instance.AddSkillAttack( GetPlayerInfo().cid, GetPlayerInfo().cid, idTarget, GetWeaponID(), idSkill, skillLevel, dwModifier, nDamage); } else { // begin a skill attack pAttack = CECAttacksMan.Instance.AddSkillAttack( GetPlayerInfo().cid, m_idCurSkillTarget, idTarget, GetWeaponID(), idSkill, skillLevel, dwModifier, nDamage); } if (pAttack != null) { int unusedInt = 0; pAttack.SetSkillSection(nSection); if (!IsDead() && (dwModifier & (uint)MOD.MOD_RETORT) == 0 && (dwModifier & (uint)MOD.MOD_ATTACK_AURA) == 0 && PlaySkillAttackAction(idSkill, nAttackSpeed, ref unusedInt, nSection, pAttack) && (dwModifier & (uint)MOD.MOD_BEAT_BACK) == 0) { } else { pAttack.m_bSignaled = true; } } EXIT: // // For skill attacking, time is always set to 0 if (piAttackTime != 0) piAttackTime = 0; } } protected void ClearComActFlagAllRankNodes(bool v) { EventBus.PublishChannel(m_PlayerInfo.cid, new ClearComActFlagAllRankNodesEvent(v)); } 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, "起"); int iTransTime = 200; EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szAct, iTransTime)); szAct = EC_Utility.BuildActionName(action, weapon_type, "落"); queueActionEvent.SetData(szAct, SetApplyDamage, true, attackEvent, iTransTime); 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); int iTranstime = 200; queueActionEvent.SetData(szAct, SetApplyDamage, false, attackEvent, iTranstime); 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() { 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 int GetBattleCamp() { return m_iBattleCamp; } public bool InSameBattleCamp(CECPlayer pPlayer) { if (!pPlayer || m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_NONE || m_iBattleCamp != pPlayer.GetBattleCamp()) 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; } 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 == (int)MoveEnvironment.MOVEENV_AIR) { if (/*UsingWing()*/ m_wingType == enumWingType.WINGTYPE_WING) iAction = (int)PLAYER_ACTION_TYPE.ACT_FLY; else iAction = (int)PLAYER_ACTION_TYPE.ACT_FLY_SWORD; } else if (iMoveEnv == (int)MoveEnvironment.MOVEENV_WATER) { //if (CanCombineWithMoveForSkill()) //{ // iAction = (int)PLAYER_ACTION_TYPE.ACT_SWIM_FOR_MOVESKILL; //} //else { iAction = (int)PLAYER_ACTION_TYPE.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 == (int)MoveEnvironment.MOVEENV_AIR) { if (/*UsingWing()*/ m_wingType == enumWingType.WINGTYPE_WING) iAction = (int)PLAYER_ACTION_TYPE.ACT_HANGINAIR; else iAction = (int)PLAYER_ACTION_TYPE.ACT_HANGINAIR_SWORD; } else if (iMoveEnv == (int)MoveEnvironment.MOVEENV_WATER) iAction = (int)PLAYER_ACTION_TYPE.ACT_HANGINWATER; } return iAction; } public A3DVECTOR3 GetModelMoveDir() { // ÒÆ¶¯Ê±¡¢·µ»ØÒƶ¯³¯Ïò£¬¾²Ö¹Ê±¡¢·µ»ØÄ£Ðͳ¯Ïò return EC_Utility.ToA3DVECTOR3(transform.forward); } public void Damaged(int nDamage, uint dwModifier = 0, int skill = 0) { 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 void StopSkillAttackAction() { if (m_pActionController != null) { m_pActionController.StopSkillAttackAction(); } } public void StopSkillCastAction() { if (m_pActionController != null) { m_pActionController.StopSkillCastAction(); } } public bool PlaySkillCastAction(int idSkill) { string szAct = ""; int weapon_type = GetShowingWeaponType(); if (!_default_skill_actions.TryGetValue((uint)idSkill, out PLAYER_ACTION_INFO_CONFIG data) || data.action_prefix == null || data.action_prefix.Length == 0 || data.action_prefix[0] == 0) { // Check if it's a target item skill if (ElementSkill.GetCommonCoolDown((uint)idSkill) > 1 << 4) { data = m_PlayerActions[(int)PLAYER_ACTION_TYPE.ACT_USING_TARGET_ITEM].data; if (data.action_prefix == null || data.action_prefix.Length == 0 || data.action_prefix[0] == 0) return false; } else return false; } if (GetMoveEnv() == (int)MoveEnvironment.MOVEENV_GROUND) { szAct = EC_Utility.BuildActionName(data, weapon_type, "_Ò÷³ª_"); BMLogger.LogError($"HoangDev: PlaySkillCastAction szAct={szAct} "); } else { /* if ((*//*UsingWing()*//*m_wingType == enumWingType.WINGTYPE_WING && IsFlying()) || (GetProfession() == PROF_ANGEL) || (GetProfession() == PROF_ARCHOR) || (GetProfession() == PROF_MONK) || (GetProfession() == PROF_GHOST)) sprintf(szAct, "%s_¿ÕÖгá°ò_Ò÷³ª_%s", data->action_prefix, data->action_weapon_suffix[weapon_type].suffix); else sprintf(szAct, "%s_¿ÕÖзɽ£_Ò÷³ª_%s", data->action_prefix, data->action_weapon_suffix[weapon_type].suffix);*/ } bool bHideFX = false; /*!CECOptimize::Instance().GetGFX().CanShowCast(GetCharacterID(), GetClassID());*/ if (!PlaySkillCastActionWithName(idSkill, szAct, bHideFX)) { return false; } ShowWeaponByConfig(data); //UpdateWeaponHangerPosBySkillAction(idSkill);// ¸ù¾Ý¼¼Äܲ¥·ÅµÄ¶¯×÷£¬¸ü¸ÄÎäÆ÷Ðü¹ÒλÖã¨Ö»Äܼì²é²»ÅŶӶ¯×÷£© return true; } 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; } public CECSkill GetCurSkill() { return m_pCurSkill; } public bool IsHangerOn() { return m_bHangerOn; } public bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX/* =false */) { return m_pActionController != null && m_pActionController.PlaySkillCastActionWithName(idSkill, szActName, bNoFX); } public bool PlaySkillAttackAction(int idSkill, int nAttackSpeed, ref int piAttackTime, int nSection = 0, CECAttackEvent attackEvent = null) { if (_pPlayerModel == null) return false; string szAct = ""; int weapon_type = GetShowingWeaponType(); if (!_default_skill_actions.TryGetValue((uint)idSkill, out PLAYER_ACTION_INFO_CONFIG data) || data.action_prefix == null || data.action_prefix.Length == 0 || data.action_prefix[0] == 0) { // Check if it's a target item skill / 检查是否为目标道具技能 if (ElementSkill.GetCommonCoolDown((uint)idSkill) > 1 << 4) { PLAYER_ACTION_INFO_CONFIG? data2 = m_PlayerActions[(int)PLAYER_ACTION_TYPE.ACT_USING_TARGET_ITEM].data; if (data2 == null || data2.Value.action_prefix == null || data2.Value.action_prefix.Length == 0 || data2.Value.action_prefix[0] == 0) return false; } else return false; } int nTime1, nTime2; bool bInfinite = false; // CECModel pRightHandWeapon = GetRightHandWeapon(); // 获取右手武器 / Get right hand weapon bool bHideFX = false; // !CECOptimize::Instance().GetGFX().CanShowAttack(GetCharacterID(), GetClassID()); var atkMan = CECAttacksMan.Instance; if (GetMoveEnv() == (int)MoveEnvironment.MOVEENV_GROUND) { szAct = EC_Utility.BuildActionName(data, weapon_type, "_施放起_"); GetSkillSectionActionName(ref szAct, idSkill, nSection); if (!PlaySkillAttackActionWithName(idSkill, szAct, bHideFX, attackEvent)) { return false; } // nTime1 = m_pPlayerModel->GetComActTimeSpanByName(szAct); // 获取动作时长 / Get action time span // pAct = m_pPlayerModel->GetComActByName(szAct); // if (pAct) bInfinite |= pAct->IsInfinite(); nTime1 = 1000; // 临时值 / Temporary value szAct = EC_Utility.BuildActionName(data, weapon_type, "_施放落_"); GetSkillSectionActionName(ref szAct, idSkill, nSection); QueueSkillAttackActionWithName(idSkill, szAct, 0, bHideFX); // nTime2 = m_pPlayerModel->GetComActTimeSpanByName(szAct); // pAct = m_pPlayerModel->GetComActByName(szAct); // if (pAct) bInfinite |= pAct->IsInfinite(); nTime2 = 1000; // 临时值 / Temporary value } else { // 空中动作 / Air action string szActionMiddleName = null; if ((m_wingType == enumWingType.WINGTYPE_WING && IsFlying()) || (m_iProfession == (int)PROFESSION.PROF_ANGEL) || (m_iProfession == (int)PROFESSION.PROF_ARCHOR) || (m_iProfession == (int)PROFESSION.PROF_MONK) || (m_iProfession == (int)PROFESSION.PROF_GHOST)) { szActionMiddleName = "_空中翅膀"; // Air with wings / 空中翅膀 } else { szActionMiddleName = "_空中飞剑"; // Air with sword / 空中飞剑 } szActionMiddleName += "_施放起_"; szAct = EC_Utility.BuildActionName(data, weapon_type, szActionMiddleName); GetSkillSectionActionName(ref szAct, idSkill, nSection); if (!PlaySkillAttackActionWithName(idSkill, szAct, bHideFX, attackEvent)) { return false; } // if (pRightHandWeapon && IsUsingMagicWeapon()) // pRightHandWeapon->PlayActionByName(_GenWeaponActionName(szAct, m_iGender), 1.0f, true, 200, true, ACT_CASTSKILL, bHideFX); // nTime1 = m_pPlayerModel->GetComActTimeSpanByName(szAct); // pAct = m_pPlayerModel->GetComActByName(szAct); // if (pAct) bInfinite |= pAct->IsInfinite(); nTime1 = 1000; // 临时值 / Temporary value szAct = $"{data.action_prefix}_{szActionMiddleName}_施法行_{data.action_weapon_suffix[weapon_type].suffix}"; GetSkillSectionActionName(ref szAct, idSkill, nSection); QueueSkillAttackActionWithName(idSkill, szAct, 0, bHideFX); // if (pRightHandWeapon && IsUsingMagicWeapon()) // pRightHandWeapon->QueueAction(_GenWeaponActionName(szAct, m_iGender), 0, ACT_CASTSKILL, false, false, bHideFX); // nTime2 = m_pPlayerModel->GetComActTimeSpanByName(szAct); // pAct = m_pPlayerModel->GetComActByName(szAct); // if (pAct) bInfinite |= pAct->IsInfinite(); nTime2 = 1000; // 临时值 / Temporary value } // int nExecuteTime = GNET::ElementSkill::GetExecuteTime(idSkill, 0); // 获取技能执行时间 / Get skill execute time int nExecuteTime = 2000; // 临时值 / Temporary value // 调整动画速度以匹配攻击速度 / Adjust animation speed to match attack speed if (!bInfinite) { if (nExecuteTime > 0) { float vScale = (nTime1 + nTime2) / (float)nExecuteTime; // m_pPlayerModel->SetPlaySpeed(vScale * 1.2f); // if (pRightHandWeapon && IsUsingMagicWeapon()) // pRightHandWeapon->SetPlaySpeed(vScale * 1.2f); } piAttackTime = nTime1 + nTime2; } else { // 动作循环,返回技能决定的执行时间 / Action loops, return skill-determined execute time piAttackTime = nExecuteTime; } ShowWeaponByConfig(data); // UpdateWeaponHangerPosBySkillAction(idSkill); // 根据技能播放的动作,更改武器悬挂位置 / Update weapon hanger position based on skill action return true; } public bool IsTeamMember(int idPlayer) { //TODO: HoangDev implement later return false; /* if (!m_pTeam) return false; return m_pTeam->GetMemberByID(idPlayer) ? true : false;*/ } public bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX = false, CECAttackEvent attackEvent = null) { return m_pActionController != null && m_pActionController.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, attackEvent != null ? new bool[] { attackEvent.m_bSignaled } : null, 0); } public bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime = 200, bool bNoFX = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0) { return m_pActionController != null && m_pActionController.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode); } private void GetSkillSectionActionName(ref string szAct, int idSkill, int nSection) { if (nSection != 0) { var pAtkMan = CECAttacksMan.Instance; if (pAtkMan != null && pAtkMan.GetSkillSectionActionSuffix(idSkill, nSection, out string suffix)) { szAct += "_" + suffix; } } } // 判断是否在飞行 / Check if flying public bool IsFlying() { // 临时实现 / Temporary implementation return (m_dwStates & PlayerNPCState.GP_STATE_FLY) != 0 ? true : false; } public bool IsInvader() { return (m_dwStates & PlayerNPCState.GP_STATE_INVADER) != 0; } public int GetFactionID() { return m_idFaction; } public int GetForce() { return m_idForce; } public bool IsInDuel() { return m_pvp.iDuelState == (int)DuelState.DUEL_ST_INDUEL; } // Duel state public enum DuelState { DUEL_ST_NONE = 0, DUEL_ST_PREPARE, DUEL_ST_INDUEL, DUEL_ST_STOPPING, }; public bool IsPariah() { return (m_dwStates & PlayerNPCState.GP_STATE_PARIAH) != 0; } 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; } // 获取职业 // Get profession public int GetProfession() { return m_iProfession; } // 获取性别 // Get gender public int GetGender() { return m_iGender; } // 获取变身类型 // Get shape type // PLAYERMODEL_GETTYPE(iShape) = (iShape & 0xff) >> 6 public int GetShapeType() { return (m_iShape & 0xff) >> 6; } // 获取变身ID // Get shape ID // PLAYERMODEL_GETID(iShape) = iShape & 0x3f public int GetShapeID() { return m_iShape & 0x3f; } 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 // Play Gfx on Models protected bool PlayGfx(string szPath, string szHook, float fScale /*1.0f*/, uint iShapeTypeMask /*(1<PlayGfx(szPath, szHook, fScale); // bPlayed = true; // } // if(bSkipRecord) continue; // A3DGFXEx* pGfx = m_pModels[i]->GetGfx(szPath, szHook); // if (pGfx && pGfx->IsInfinite()){ // GFXRECORD rec; // rec.strPath = szPath; // rec.strHook = szHook; // rec.fScale = fScale; // AString key = rec.strPath + rec.strHook; // m_GfxRecords[key] = rec; // bSkipRecord = true; // } // } // } PlayLevelUpGfx(szPath); return false; } private async void PlayLevelUpGfx(string path) { // Usage: Load the prefab asynchronously using AddressableManager GameObject prefab = await AddressableManager.Instance.LoadPrefabAsync(path); if (prefab != null) { if (_levelUpVfx != null) { if (_levelUpVfx.IsPlaying()) return; _levelUpVfx.Play(); return; } // Instantiate at player's current position and rotation _levelUpVfx = Instantiate(prefab, transform).GetComponent(); _levelUpVfx.Play(); // vfx.transform.SetParent(transform); transform.position, prefab.transform.rotation _levelUpVfx.transform.localPosition = Vector3.zero; } else { BMLogger.LogError($"Failed to load level up effect prefab at: {path}"); } } // Get booth state public int GetBoothState() { return m_iBoothState; } // Check whether player has effect of specified type public bool HasEffectType(int iEffType) { int i; switch (iEffType) { case Effect_type.EFF_FACEPILL: { elementdataman pDataMan = EC_Game.GetElementDataMan(); // Get item data type for (i = 0; i < m_aCurEffects.Count; i++) { DATA_TYPE DataType = pDataMan.get_data_type((uint)m_aCurEffects[i], ID_SPACE.ID_SPACE_ESSENCE); if (DataType == DATA_TYPE.DT_FACEPILL_ESSENCE) return true; } break; } } return false; } public byte GetReincarnationCount() { return m_ReincarnationCount; } public string GetName() { return m_strName; } public enumWingType GetWingType() { return m_wingType; } // Set part extend properties public void SetPartExtendProps(int iPropIdx, object pData) { switch (iPropIdx) { case (int)ExtendPropertyClass.EXTPROPIDX_BASE: m_ExtProps.bs = (ROLEEXTPROP_BASE)pData; break; case (int)ExtendPropertyClass.EXTPROPIDX_MOVE: m_ExtProps.mv = (ROLEEXTPROP_MOVE)pData; break; case (int)ExtendPropertyClass.EXTPROPIDX_ATTACK: m_ExtProps.ak = (ROLEEXTPROP_ATK)pData; break; case (int)ExtendPropertyClass.EXTPROPIDX_DEF: m_ExtProps.df = (ROLEEXTPROP_DEF)pData; break; default: //ASSERT(0); return; } } #region Team // Get team to which this player belongs to // public CECTeam GetTeam() { return m_pTeam; } #endregion public static bool IsMoveStandAction(int action) { // tương đương: const static int s_MoveStandAction[] PLAYER_ACTION_TYPE[] s_MoveStandAction = { PLAYER_ACTION_TYPE.ACT_RUN, PLAYER_ACTION_TYPE.ACT_WALK, PLAYER_ACTION_TYPE.ACT_FLY, PLAYER_ACTION_TYPE.ACT_FLY_SWORD, PLAYER_ACTION_TYPE.ACT_SWIM, PLAYER_ACTION_TYPE.ACT_SWIM_FOR_MOVESKILL, PLAYER_ACTION_TYPE.ACT_STAND, PLAYER_ACTION_TYPE.ACT_FIGHTSTAND, PLAYER_ACTION_TYPE.ACT_HANGINAIR, PLAYER_ACTION_TYPE.ACT_HANGINAIR_SWORD, PLAYER_ACTION_TYPE.ACT_HANGINWATER, }; int begin = 0; int end = s_MoveStandAction.Length - 1; for (int i = begin; i < end; i++) { if ((int)s_MoveStandAction[i] == action) return true; } return false; } public int GetLowerBodyAction() { return m_pActionController?.GetLowerBodyAction() ?? -1; } // Check water moving environment public bool CheckWaterMoveEnv(A3DVECTOR3 vPos, float fWaterHei, float fGndHei) { bool bRet = false; /* if (vPos.y < fWaterHei - m_MoveConst.fShoreDepth) bRet = true; else if (vPos.y < fWaterHei && fWaterHei - fGndHei > m_MoveConst.fShoreDepth) bRet = true; */ // if (vPos.y < fWaterHei - m_MoveConst.fWaterSurf - m_aabb.Extents.y) // if (vPos.y < fWaterHei - m_MoveConst.fWaterSurf + 0.01f) /* if (vPos.y < fWaterHei - m_MoveConst.fShoreDepth) bRet = true; else if (vPos.y < fWaterHei - m_MoveConst.fWaterSurf + 0.01f && fWaterHei - fGndHei > m_MoveConst.fShoreDepth) bRet = true; */ //@note : modify the water test. By Kuiwu[12/10/2005] if (vPos.y + m_aabbServer.Extents.y < fWaterHei - m_MoveConst.fWaterSurf - 0.001f) { bRet = true; } //else if (vPos.y + m_aabb.Extents.y < fWaterHei- m_MoveConst.fWaterSurf + 1E-4f && vPos.y - fGndHei >= 0.2f ) else if (vPos.y + m_aabbServer.Extents.y < fWaterHei - m_MoveConst.fWaterSurf + 1E-4f && vPos.y - fGndHei >= 0.01f) { bRet = true; } return bRet; } public bool IsAboutToDie() { return m_bAboutToDie; } public void SetAboutToDie(bool bFlag) { m_bAboutToDie = bFlag; } // Show / hide wing public void ShowWing(bool bShow) { //if (m_pPlayerModel) //{ // CECModel* pWing = m_pPlayerModel->GetChildModel(_wing); // if (pWing) pWing->Show(bShow); // CECModel* pWing2 = m_pPlayerModel->GetChildModel(_wing2); // if (pWing2) pWing2->Show(bShow); //} } } public struct PlayActionEvent { public string AnimationName; public int ITransTime; public PlayActionEvent(string animationName, int iTransTime) { this.AnimationName = animationName; ITransTime = iTransTime; } } public struct PLAYER_ACTION { public PLAYER_ACTION_TYPE type; public PLAYER_ACTION_INFO_CONFIG data; }; public class QueueActionEvent { public string AnimationName; public int ITransTime; public Action SetFlag; public CECAttackEvent AttackEvent; public bool IsHitAnim; public QueueActionEvent(string animationName, Action setFlag, bool isHitAnim, CECAttackEvent attackEvent, int iTransTime) { this.AnimationName = animationName; SetFlag = setFlag; IsHitAnim = isHitAnim; AttackEvent = attackEvent; ITransTime = iTransTime; } public void SetData(string animationName, Action setFlag, bool isHitAnim, CECAttackEvent attackEvent, int iTransTime) { this.AnimationName = animationName; SetFlag = setFlag; IsHitAnim = isHitAnim; AttackEvent = attackEvent; ITransTime = iTransTime; } } 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 struct ClearComActFlagAllRankNodesEvent { public bool v; public ClearComActFlagAllRankNodesEvent(bool value) { v = value; } } [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 enumWingType { WINGTYPE_WING, // 飞行器类型:翅膀 WINGTYPE_FLYSWORD, // 飞行器类型:飞剑 WINGTYPE_DOUBLEWHEEL, // 飞行器类型:双脚飞行器 }; 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 }; 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; } public class EC_Player_Skin_Const { // Skin index public static byte SKIN_BODY_INDEX = 0; public static byte SKIN_UPPER_BODY_INDEX = 1; public static byte SKIN_WRIST_INDEX = 2; public static byte SKIN_LOWER_INDEX = 3; public static byte SKIN_FOOT_INDEX = 4; public static byte SKIN_HEAD_INDEX = 5; public static byte SKIN_FASHION_UPPER_BODY_INDEX = 6; public static byte SKIN_FASHION_WRIST_INDEX = 7; public static byte SKIN_FASHION_LOWER_INDEX = 8; public static byte SKIN_FASHION_FOOT_INDEX = 9; public static byte NUM_SKIN_INDEX = 10; } public enum enumSkinShow { enumSkinShowNone = 0, enumSkinShowUpperBody, enumSkinShowWrist, enumSkinShowLowerBody, enumSkinShowFoot, enumSkinShowUpperAndLower, enumSkinShowUpperAndWrist, enumSkinShowLowerAndFoot, enumSkinShowUpperLowerAndWrist, enumSkinShowArmet, enumSkinShowHand, }; }