diff --git a/Assets/PerfectWorld/Config.meta b/Assets/PerfectWorld/Config.meta index 817ef66171..6b5288c3cd 100644 --- a/Assets/PerfectWorld/Config.meta +++ b/Assets/PerfectWorld/Config.meta @@ -1,6 +1,6 @@ fileFormatVersion: 2 <<<<<<<< HEAD:Assets/PerfectWorld/Editor.meta -guid: 75a0cc0fd8902794a883916febf9855b +guid: 7b6ba20c81b136a4aac2dfea2b936886 ======== guid: f0e041e8264a83545bf6e555757c9851 >>>>>>>> develop:Assets/PerfectWorld/Config.meta diff --git a/Assets/Scripts/CECHostPlayer.Task.cs b/Assets/Scripts/CECHostPlayer.Task.cs index 5e7b518ad7..e1fe530fc4 100644 --- a/Assets/Scripts/CECHostPlayer.Task.cs +++ b/Assets/Scripts/CECHostPlayer.Task.cs @@ -98,8 +98,6 @@ namespace BrewMonster m_pTaskInterface.CheckPQEnterWorldInit(); -#endif - // check if player has equipped goblin (not yet implemented in C#) // TODO: implement goblin initialization when equipment system is ready diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index a350e14310..65487041ad 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -370,15 +370,15 @@ namespace BrewMonster } }*/ } + + m_pWorkMan?.Tick(Time.deltaTime); + + // Update cursor based on what's under mouse + EstimateCursor(); + + // Update GFXs + UpdateGFXs(Time.deltaTime); } - m_pWorkMan?.Tick(Time.deltaTime); - - // Update cursor based on what's under mouse - EstimateCursor(); - - // Update GFXs - UpdateGFXs(Time.deltaTime); - } public void StopMovement() { @@ -524,414 +524,322 @@ namespace BrewMonster case int value when value == EC_MsgDef.MSG_HST_STARTATTACK: OnMsgHstStartAttack(Msg); break; case int value when value == EC_MsgDef.MSG_HST_STOPATTACK: OnMsgHstStopAttack(Msg); break; } - } - /* if (bActionStartSkill) - AP_ActionEvent(AP_EVENT_STARTSKILL, iActionTime); - if (bDoOtherThing) - { - if (m_pComboSkill != null && !m_pComboSkill.IsStop()) + /* if (bActionStartSkill) + AP_ActionEvent(AP_EVENT_STARTSKILL, iActionTime); + + if (bDoOtherThing) { - if (CECAutoPolicy.GetInstance().IsAutoPolicyEnabled()) - g_pGame.GetGameRun().PostMessage(MSG_HST_CONTINUECOMBOSKILL, MAN_PLAYER, 0, 0, m_pComboSkill.GetGroupIndex()); + if (m_pComboSkill != null && !m_pComboSkill.IsStop()) + { + if (CECAutoPolicy.GetInstance().IsAutoPolicyEnabled()) + g_pGame.GetGameRun().PostMessage(MSG_HST_CONTINUECOMBOSKILL, MAN_PLAYER, 0, 0, m_pComboSkill.GetGroupIndex()); + else + m_pComboSkill.Continue(false); + } else - m_pComboSkill.Continue(false); - } - else - { - if (idTarget != 0 && idTarget != m_PlayerInfo.cid) - NormalAttackObject(idTarget, true); - } - }*/ - } + { + if (idTarget != 0 && idTarget != m_PlayerInfo.cid) + NormalAttackObject(idTarget, true); + } + }*/ + } private void OnMsgHstSkillData(ECMSG Msg) -{ - cmd_skill_data pCmd = default; - pCmd.skill_count = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - int offset = sizeof(uint); - int skillSize = Marshal.SizeOf(); - pCmd.skill_list = new cmd_skill_data.SKILL[pCmd.skill_count]; - for (int i = 0; i < pCmd.skill_count; i++) - { - pCmd.skill_list[i] = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1, offset); - offset += skillSize; - } - 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(); - } - }*/ - - // 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 OnMsgHstDied(in ECMSG msg) -{ - EventBus.PublishChannel(GetCharacterID(), new CECPlayer.ClearComActFlagAllRankNodesEvent(true)); - PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE); - if (PopupManager.Instance != null) - { - PopupManager.Instance.OnPlayerDied(); - } -} -private void OnMsgHstInfo00(in ECMSG Msg) -{ - cmd_self_info_00 pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - - bool bFirstTime = m_BasicProps.iLevel == 0 ? true : false; - if (!bFirstTime) - { - int iLimit = (int)(pCmd.iMaxHP * 0.3f); - if (pCmd.iHP < m_BasicProps.iCurHP && m_BasicProps.iCurHP >= iLimit && pCmd.iHP < iLimit) - { - - /*if (CECUIHelper::GetGameUIMan()->IsShowLowHP()) { - // ѪÁ¿µÍÓÚÁÙ½çÖµÔò²¥·ÅÌØÐ§ - const int GfxLastTime = 10000; // ³ÖÐøÊ±¼ä10Ãë - CECUIHelper::GetGameUIMan()->GetScreenEffectMan()->StartEffect(CECScreenEffect::EFFECT_REDSPARK, GfxLastTime); - }*/ - } - - /*if (pCmd.iHP >= iLimit || pCmd.iHP <= 0) { - // ѪÁ¿¸ßÓÚÁÙ½çÖµ»òËÀÍö£¬ÔòÍ£Ö¹²¥·ÅÌØÐ§ - CECUIHelper::GetGameUIMan()->GetScreenEffectMan()->FinishEffect(CECScreenEffect::EFFECT_REDSPARK); - }*/ - - /*iLimit = (int)(pCmd.iMaxMP * 0.2f); - if (pCmd.iMP < m_BasicProps.iCurMP && m_BasicProps.iCurMP >= iLimit && pCmd.iMP < iLimit) - BubbleText(BUBBLE_MPWARN, 0);*/ - - /*if (m_ExtProps.max_ap != pCmd->iMaxAP) - g_pGame->GetGameRun()->AddFixedMessage(FIXMSG_ADDMAXAP, pCmd->iMaxAP - m_ExtProps.max_ap);*/ - } - - m_BasicProps.iLevel = pCmd.sLevel; - SetLevel2(pCmd.Level2, bFirstTime); - m_BasicProps.iExp = pCmd.iExp; - m_BasicProps.iSP = pCmd.iSP; - m_BasicProps.iCurHP = pCmd.iHP; - m_BasicProps.iCurMP = pCmd.iMP; - m_BasicProps.iCurAP = pCmd.iAP; - m_ExtProps.bs.max_hp = pCmd.iMaxHP; - m_ExtProps.bs.max_mp = pCmd.iMaxMP; - m_ExtProps.max_ap = pCmd.iMaxAP; - - EventBus.Publish(new EXPToUpLevel(GetLevelUpExp(pCmd.sLevel))); - EventBus.Publish(pCmd); - // if (pCmd.State != 0 && m_bFight == false) PlayEnterBattleGfx(); - m_bFight = pCmd.State != 0 ? true : false; - - // UpdateGodEvilSprite(); - - /*CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); - CDlgAutoHelp *pDlgHelp = dynamic_cast(pGameUI->GetDialog("Win_WikiPop"));*/ - /*if(pDlgHelp && m_bFight) - pDlgHelp->SetAutoHelpState(false);*/ -} -void SetLevel2(int level2, bool bFirstTime) -{ - int lastLevel2 = m_BasicProps.iLevel2; - m_BasicProps.iLevel2 = level2; - /*if (CanPlayTaoistEffect(lastLevel2, level2, bFirstTime)){ - PlayTaoistEffect(); - }*/ -} -void OnMsgHstAttacked(ECMSG Msg) -{ - var m_pPlayerMan = EC_ManMessageMono.Instance.EC_ManPlayer; - cmd_host_attacked pCmd = GPDataTypeHelper.FromBytes(Msg.dwParam1 as byte[]); - - if (pCmd.iDamage != 0 && (pCmd.cEquipment & 0x7f) != 0x7f) - { - /* char cEquip = (char)(pCmd.cEquipment & 0x7f); - CECIvtrEquip pEquip = (CECIvtrEquip)m_pEquipPack->GetItem(cEquip); - if (pEquip) - pEquip->AddCurEndurance(ARMOR_RUIN_SPEED);*/ - } - - // The host player is attacked, we should make an effect here - if (GPDataTypeHelper.ISPLAYERID(pCmd.idAttacker)) - { - EC_ElsePlayer pAttacker = m_pPlayerMan.GetElsePlayer(pCmd.idAttacker); - if (pAttacker) - { - if (!pAttacker.IsDead()) + cmd_skill_data pCmd = default; + pCmd.skill_count = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + int offset = sizeof(uint); + int skillSize = Marshal.SizeOf(); + pCmd.skill_list = new cmd_skill_data.SKILL[pCmd.skill_count]; + for (int i = 0; i < pCmd.skill_count; i++) { - // Face to target - pAttacker.TurnFaceTo(GetPlayerInfo().cid); + pCmd.skill_list[i] = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1, offset); + offset += skillSize; + } + if (pCmd.skill_list == null) + { + BMLogger.LogError("OnMsgHstSkillData: cmd is null"); + return; } - int useless_attacktime = 0; - pAttacker.PlayAttackEffect(GetCharacterID(), 0, 0, pCmd.iDamage, (uint)pCmd.attack_flag, - pCmd.speed * 50, ref useless_attacktime); - pAttacker.EnterFightState(); - } - } - else if (GPDataTypeHelper.ISNPCID(pCmd.idAttacker)) - { - CECNPC pAttacker = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.idAttacker); - if (pAttacker) - { - pAttacker.OnMsgAttackHostResult(GetCharacterID(), pCmd.iDamage, pCmd.attack_flag, pCmd.speed); - } - } + /* List skillSCConfigArray1 = new List(); + List skillSCConfigArray2 = new List(); + List skillGrpSCConfigArray1 = new List(); + List skillGrpSCConfigArray2 = new List();*/ - //CECAutoPolicy::GetInstance().SendEvent_BeHurt(pCmd.idAttacker); -} - -public void OnMsgHstAttackResult(ECMSG Msg) -{ - byte[] data = Msg.dwParam1 as byte[]; - cmd_host_attack_result pCmd = EC_Utility.ByteArrayToStructure(data); - - int iAttackTime = 0; - TurnFaceTo(pCmd.idTarget); - - PlayAttackEffect(pCmd.idTarget, 0, 0, pCmd.iDamage, (uint)pCmd.attack_flag, pCmd.attack_speed * 50, - ref iAttackTime); - - if (iAttackTime != 0) - { - if (m_pWorkMan.GetRunningWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT) is CECHPWorkMelee pCurWork) - { - pCurWork.SetIdleTime(iAttackTime); - } - } -} - -/* public override bool IsWorkMoveRunning() - { - return m_pWorkMan.IsMovingToPosition(); - }*/ -private void OnMsgHstHurtResult(ECMSG Msg) -{ - //BMLogger.LogError("HoangDev : OnMsgHstHurtResult"); - /* int cmd = Convert.ToInt32(Msg.dwParam2); - if (cmd == CommandID.BE_HURT) - { - cmd_be_hurt pCmd = (cmd_be_hurt)Msg.dwParam1; - if (pCmd.damage != 0) - Damaged(pCmd->damage); - } - else if (cmd == CommandID.HURT_RESULT) - { - cmd_hurt_result pCmd = (cmd_hurt_result)Msg.dwParam1; - if (pCmd.target_id == m_PlayerInfo.cid) - return; // Host himself will receive BE_HURT, so ignore this. - - if (UnityGameSession.Instance.GameSession.ISPLAYERID(pCmd.target_id)) - { - CECElsePlayer pTarget = m_pPlayerMan.GetElsePlayer(pCmd.target_id); - if (pTarget) - pTarget->Damaged(pCmd->damage); - } - else if (UnityGameSession.Instance.GameSession.ISNPCID(pCmd.target_id)) - { - CECNPC pTarget = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.target_id); - if (pTarget) - pTarget.Damaged(pCmd.damage); - } - }*/ -} - -public void OnMsgHstPickupItem(in ECMSG Msg) -{ - var data = Msg.dwParam1 as byte[]; - int cmd = Convert.ToInt32(Msg.dwParam2); - switch (cmd) - { - case CommandID.HOST_OBTAIN_ITEM: + if (HostIsReady()) { - // Parse cmd_host_obtain_item struct data - int type = BitConverter.ToInt32(data, 0); - int expire_date = BitConverter.ToInt32(data, 4); - uint amount = BitConverter.ToUInt32(data, 8); - uint slot_amount = BitConverter.ToUInt32(data, 12); - byte where = data[16]; // Package index - byte index = data[17]; // Slot index in that package - // Create new inventory item data - var newItem = new EC_IvtrItem - { - Package = where, - Slot = index, - m_tid = type, - m_expire_date = expire_date, - State = 0, - m_iCount = (int)amount, - Crc = 0, - Content = null - }; + /* + for (int i = 0; i < HostConstants.NUM_HOSTSCSETS1; i++) + { + if (hostPlayer.m_aSCSets1[i] != null) + { + hostPlayer.m_aSCSets1[i].RemoveSkillShortcuts(); + } + } - // Add item to inventory - EC_Inventory.SetItem(where, index, newItem); + for (int i = 0; i < HostConstants.NUM_HOSTSCSETS2; i++) + { + if (hostPlayer.m_aSCSets2[i] != null) + { + hostPlayer.m_aSCSets2[i].RemoveSkillShortcuts(); + } + }*/ - Debug.Log( - $"[HOST_OBTAIN_ITEM] Successfully added item {type} to package {where}, slot {index} with count {amount}"); - - // Trigger UI refresh if an EC_InventoryUI is present in scene - var ui = GameObject.FindFirstObjectByType(); - if (ui != null) - { - ui.RefreshAll(); - } + // Release passive skills + m_aPsSkills.Clear(); } - break; - case CommandID.PICKUP_ITEM: + + // 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++) { - int tid = BitConverter.ToInt32(data, 0); - int expire_date = BitConverter.ToInt32(data, 4); - uint iAmount = BitConverter.ToUInt32(data, 8); - uint iSlotAmount = BitConverter.ToUInt32(data, 12); - byte byPackage = data[16]; - byte bySlot = data[17]; + cmd_skill_data.SKILL data = pCmd.skill_list[i]; + CECSkill skill = new CECSkill(data.id_skill, data.level); - //Debug.Log($"[Inventory] PICKUP_ITEM: tid={tid}, expire_date={expire_date}, iAmount={iAmount}, iSlotAmount={iSlotAmount}, byPackage={byPackage}, bySlot={bySlot}"); - - // Notify pickupItem script about successful pickup - pickupItem pickupScript = pickupItem.Instance; - if (pickupScript != null) + // 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) { - //Debug.Log($"[Inventory] PICKUP_ITEM: tid={tid}, expire_date={expire_date}, iAmount={iAmount}, iSlotAmount={iSlotAmount}, byPackage={byPackage}, bySlot={bySlot}"); - - // Notify pickupItem script about successful pickup - pickupScript = UnityEngine.Object.FindFirstObjectByType(); - if (pickupScript != null) - { - pickupScript.OnPickupSuccess(tid); - } - - // Create new inventory item data - var newItem = new EC_IvtrItem - { - Package = byPackage, - Slot = bySlot, - m_tid = tid, - m_expire_date = expire_date, - State = 0, - m_iCount = (int)iAmount, - Crc = 0, - Content = null - }; - - // Add item to inventory - EC_Inventory.SetItem(byPackage, bySlot, newItem); - - //Debug.Log($"[Inventory] Successfully added item {tid} to package {byPackage}, slot {bySlot} with count {iAmount}"); - - // Trigger UI refresh if an EC_InventoryUI is present in scene - var ui = GameObject.FindFirstObjectByType(); - if (ui != null) - { - ui.RefreshAll(); - } + m_aPtSkills.Add(skill); } else { - Debug.LogWarning("[Inventory] PICKUP_ITEM: Invalid data length"); + m_aPsSkills.Add(skill); } - break; } - } -} -public void OnMsgHstItemOperation(ECMSG Msg) -{ - var data = Msg.dwParam1 as byte[]; - int cmd = Convert.ToInt32(Msg.dwParam2); - switch (cmd) - { - case CommandID.PLAYER_DROP_ITEM: + // 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 OnMsgHstDied(in ECMSG msg) + { + EventBus.PublishChannel(GetCharacterID(), new CECPlayer.ClearComActFlagAllRankNodesEvent(true)); + PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE); + if (PopupManager.Instance != null) { - // Parse the drop item data from the server response - if (data != null && data.Length >= 6) + PopupManager.Instance.OnPlayerDied(); + } + } + private void OnMsgHstInfo00(in ECMSG Msg) + { + cmd_self_info_00 pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + + bool bFirstTime = m_BasicProps.iLevel == 0 ? true : false; + if (!bFirstTime) + { + int iLimit = (int)(pCmd.iMaxHP * 0.3f); + if (pCmd.iHP < m_BasicProps.iCurHP && m_BasicProps.iCurHP >= iLimit && pCmd.iHP < iLimit) { - byte byPackage = data[0]; - byte bySlot = data[1]; - int count = BitConverter.ToInt32(data, 2); - int tid = BitConverter.ToInt32(data, 6); - byte reason = data[10]; - Debug.Log( - $"[Inventory] PLAYER_DROP_ITEM: package={byPackage}, slot={bySlot}, count={count}, tid={tid}, reason={reason}"); + /*if (CECUIHelper::GetGameUIMan()->IsShowLowHP()) { + // ѪÁ¿µÍÓÚÁÙ½çÖµÔò²¥·ÅÌØÐ§ + const int GfxLastTime = 10000; // ³ÖÐøÊ±¼ä10Ãë + CECUIHelper::GetGameUIMan()->GetScreenEffectMan()->StartEffect(CECScreenEffect::EFFECT_REDSPARK, GfxLastTime); + }*/ + } - // Update the inventory by removing the item - bool success = EC_Inventory.RemoveItem(byPackage, bySlot, count); + /*if (pCmd.iHP >= iLimit || pCmd.iHP <= 0) { + // ѪÁ¿¸ßÓÚÁÙ½çÖµ»òËÀÍö£¬ÔòÍ£Ö¹²¥·ÅÌØÐ§ + CECUIHelper::GetGameUIMan()->GetScreenEffectMan()->FinishEffect(CECScreenEffect::EFFECT_REDSPARK); + }*/ - if (success) + /*iLimit = (int)(pCmd.iMaxMP * 0.2f); + if (pCmd.iMP < m_BasicProps.iCurMP && m_BasicProps.iCurMP >= iLimit && pCmd.iMP < iLimit) + BubbleText(BUBBLE_MPWARN, 0);*/ + + /*if (m_ExtProps.max_ap != pCmd->iMaxAP) + g_pGame->GetGameRun()->AddFixedMessage(FIXMSG_ADDMAXAP, pCmd->iMaxAP - m_ExtProps.max_ap);*/ + } + + m_BasicProps.iLevel = pCmd.sLevel; + SetLevel2(pCmd.Level2, bFirstTime); + m_BasicProps.iExp = pCmd.iExp; + m_BasicProps.iSP = pCmd.iSP; + m_BasicProps.iCurHP = pCmd.iHP; + m_BasicProps.iCurMP = pCmd.iMP; + m_BasicProps.iCurAP = pCmd.iAP; + m_ExtProps.bs.max_hp = pCmd.iMaxHP; + m_ExtProps.bs.max_mp = pCmd.iMaxMP; + m_ExtProps.max_ap = pCmd.iMaxAP; + + EventBus.Publish(new EXPToUpLevel(GetLevelUpExp(pCmd.sLevel))); + EventBus.Publish(pCmd); + // if (pCmd.State != 0 && m_bFight == false) PlayEnterBattleGfx(); + m_bFight = pCmd.State != 0 ? true : false; + + // UpdateGodEvilSprite(); + + /*CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); + CDlgAutoHelp *pDlgHelp = dynamic_cast(pGameUI->GetDialog("Win_WikiPop"));*/ + /*if(pDlgHelp && m_bFight) + pDlgHelp->SetAutoHelpState(false);*/ + } + void SetLevel2(int level2, bool bFirstTime) + { + int lastLevel2 = m_BasicProps.iLevel2; + m_BasicProps.iLevel2 = level2; + /*if (CanPlayTaoistEffect(lastLevel2, level2, bFirstTime)){ + PlayTaoistEffect(); + }*/ + } + void OnMsgHstAttacked(ECMSG Msg) + { + var m_pPlayerMan = EC_ManMessageMono.Instance.EC_ManPlayer; + cmd_host_attacked pCmd = GPDataTypeHelper.FromBytes(Msg.dwParam1 as byte[]); + + if (pCmd.iDamage != 0 && (pCmd.cEquipment & 0x7f) != 0x7f) + { + /* char cEquip = (char)(pCmd.cEquipment & 0x7f); + CECIvtrEquip pEquip = (CECIvtrEquip)m_pEquipPack->GetItem(cEquip); + if (pEquip) + pEquip->AddCurEndurance(ARMOR_RUIN_SPEED);*/ + } + + // The host player is attacked, we should make an effect here + if (GPDataTypeHelper.ISPLAYERID(pCmd.idAttacker)) + { + EC_ElsePlayer pAttacker = m_pPlayerMan.GetElsePlayer(pCmd.idAttacker); + if (pAttacker) + { + if (!pAttacker.IsDead()) { + // Face to target + pAttacker.TurnFaceTo(GetPlayerInfo().cid); + } + + int useless_attacktime = 0; + pAttacker.PlayAttackEffect(GetCharacterID(), 0, 0, pCmd.iDamage, (uint)pCmd.attack_flag, + pCmd.speed * 50, ref useless_attacktime); + pAttacker.EnterFightState(); + } + } + else if (GPDataTypeHelper.ISNPCID(pCmd.idAttacker)) + { + CECNPC pAttacker = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.idAttacker); + if (pAttacker) + { + pAttacker.OnMsgAttackHostResult(GetCharacterID(), pCmd.iDamage, pCmd.attack_flag, pCmd.speed); + } + } + + //CECAutoPolicy::GetInstance().SendEvent_BeHurt(pCmd.idAttacker); + } + + public void OnMsgHstAttackResult(ECMSG Msg) + { + byte[] data = Msg.dwParam1 as byte[]; + cmd_host_attack_result pCmd = EC_Utility.ByteArrayToStructure(data); + + int iAttackTime = 0; + TurnFaceTo(pCmd.idTarget); + + PlayAttackEffect(pCmd.idTarget, 0, 0, pCmd.iDamage, (uint)pCmd.attack_flag, pCmd.attack_speed * 50, + ref iAttackTime); + + if (iAttackTime != 0) + { + if (m_pWorkMan.GetRunningWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT) is CECHPWorkMelee pCurWork) + { + pCurWork.SetIdleTime(iAttackTime); + } + } + } + + /* public override bool IsWorkMoveRunning() + { + return m_pWorkMan.IsMovingToPosition(); + }*/ + private void OnMsgHstHurtResult(ECMSG Msg) + { + //BMLogger.LogError("HoangDev : OnMsgHstHurtResult"); + /* int cmd = Convert.ToInt32(Msg.dwParam2); + if (cmd == CommandID.BE_HURT) + { + cmd_be_hurt pCmd = (cmd_be_hurt)Msg.dwParam1; + if (pCmd.damage != 0) + Damaged(pCmd->damage); + } + else if (cmd == CommandID.HURT_RESULT) + { + cmd_hurt_result pCmd = (cmd_hurt_result)Msg.dwParam1; + if (pCmd.target_id == m_PlayerInfo.cid) + return; // Host himself will receive BE_HURT, so ignore this. + + if (UnityGameSession.Instance.GameSession.ISPLAYERID(pCmd.target_id)) + { + CECElsePlayer pTarget = m_pPlayerMan.GetElsePlayer(pCmd.target_id); + if (pTarget) + pTarget->Damaged(pCmd->damage); + } + else if (UnityGameSession.Instance.GameSession.ISNPCID(pCmd.target_id)) + { + CECNPC pTarget = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.target_id); + if (pTarget) + pTarget.Damaged(pCmd.damage); + } + }*/ + } + + public void OnMsgHstPickupItem(in ECMSG Msg) + { + var data = Msg.dwParam1 as byte[]; + int cmd = Convert.ToInt32(Msg.dwParam2); + switch (cmd) + { + case CommandID.HOST_OBTAIN_ITEM: + { + // Parse cmd_host_obtain_item struct data + int type = BitConverter.ToInt32(data, 0); + int expire_date = BitConverter.ToInt32(data, 4); + uint amount = BitConverter.ToUInt32(data, 8); + uint slot_amount = BitConverter.ToUInt32(data, 12); + byte where = data[16]; // Package index + byte index = data[17]; // Slot index in that package + // Create new inventory item data + var newItem = new EC_IvtrItem + { + Package = where, + Slot = index, + m_tid = type, + m_expire_date = expire_date, + State = 0, + m_iCount = (int)amount, + Crc = 0, + Content = null + }; + + // Add item to inventory + var ivt = GetInventory(where); + ivt.SetItem(index, newItem); + Debug.Log( - $"[Inventory] Successfully removed {count} items from package {byPackage}, slot {bySlot}"); + $"[HOST_OBTAIN_ITEM] Successfully added item {type} to package {where}, slot {index} with count {amount}"); // Trigger UI refresh if an EC_InventoryUI is present in scene var ui = GameObject.FindFirstObjectByType(); @@ -940,2173 +848,2338 @@ public void OnMsgHstItemOperation(ECMSG Msg) ui.RefreshAll(); } } + break; + case CommandID.PICKUP_ITEM: + { + int tid = BitConverter.ToInt32(data, 0); + int expire_date = BitConverter.ToInt32(data, 4); + uint iAmount = BitConverter.ToUInt32(data, 8); + uint iSlotAmount = BitConverter.ToUInt32(data, 12); + byte byPackage = data[16]; + byte bySlot = data[17]; + + //Debug.Log($"[Inventory] PICKUP_ITEM: tid={tid}, expire_date={expire_date}, iAmount={iAmount}, iSlotAmount={iSlotAmount}, byPackage={byPackage}, bySlot={bySlot}"); + + // Notify pickupItem script about successful pickup + pickupItem pickupScript = pickupItem.Instance; + if (pickupScript != null) + { + //Debug.Log($"[Inventory] PICKUP_ITEM: tid={tid}, expire_date={expire_date}, iAmount={iAmount}, iSlotAmount={iSlotAmount}, byPackage={byPackage}, bySlot={bySlot}"); + + // Notify pickupItem script about successful pickup + pickupScript = UnityEngine.Object.FindFirstObjectByType(); + if (pickupScript != null) + { + pickupScript.OnPickupSuccess(tid); + } + + // Create new inventory item data + var newItem = new EC_IvtrItem + { + Package = byPackage, + Slot = bySlot, + m_tid = tid, + m_expire_date = expire_date, + State = 0, + m_iCount = (int)iAmount, + Crc = 0, + Content = null + }; + + // Add item to inventory + var ivt = GetInventory(byPackage); + ivt.SetItem(bySlot, newItem); + + //Debug.Log($"[Inventory] Successfully added item {tid} to package {byPackage}, slot {bySlot} with count {iAmount}"); + + // Trigger UI refresh if an EC_InventoryUI is present in scene + var ui = GameObject.FindFirstObjectByType(); + if (ui != null) + { + ui.RefreshAll(); + } + } + else + { + Debug.LogWarning("[Inventory] PICKUP_ITEM: Invalid data length"); + } + break; + } + } + } + public void OnMsgHstItemOperation(ECMSG Msg) + { + var data = Msg.dwParam1 as byte[]; + int cmd = Convert.ToInt32(Msg.dwParam2); + switch (cmd) + { + case CommandID.PLAYER_DROP_ITEM: + { + // Parse the drop item data from the server response + if (data != null && data.Length >= 6) + { + byte byPackage = data[0]; + byte bySlot = data[1]; + int count = BitConverter.ToInt32(data, 2); + int tid = BitConverter.ToInt32(data, 6); + byte reason = data[10]; + + Debug.Log( + $"[Inventory] PLAYER_DROP_ITEM: package={byPackage}, slot={bySlot}, count={count}, tid={tid}, reason={reason}"); + + // Update the inventory by removing the item + var inv = GetInventory(byPackage); + bool success = inv != null && inv.RemoveItem(bySlot, count); + + if (success) + { + Debug.Log( + $"[Inventory] Successfully removed {count} items from package {byPackage}, slot {bySlot}"); + + // Trigger UI refresh if an EC_InventoryUI is present in scene + var ui = GameObject.FindFirstObjectByType(); + if (ui != null) + { + ui.RefreshAll(); + } + } + else + { + Debug.LogWarning($"[Inventory] Failed to remove items from package {byPackage}, slot {bySlot}"); + } + } + else + { + Debug.LogWarning("[Inventory] PLAYER_DROP_ITEM: Invalid data length"); + } + + break; + } + + case CommandID.EQUIP_ITEM: + { + byte index_inv = data[0]; + byte index_equip = data[1]; + // Update client-side data: move item between PACK_INVENTORY and PACK_EQUIPMENT + var packInv = GetInventory(InventoryConst.IVTRTYPE_PACK); + var equipInv = GetInventory(InventoryConst.IVTRTYPE_EQUIPPACK); + var invItem = packInv?.GetItem(index_inv, true); + var equipItem = equipInv?.GetItem(index_equip, true); + if (invItem != null) + { + invItem.Package = InventoryConst.IVTRTYPE_EQUIPPACK; + invItem.Slot = index_equip; + equipInv?.SetItem(index_equip, invItem); + } + + if (equipItem != null) + { + equipItem.Package = InventoryConst.IVTRTYPE_PACK; + equipItem.Slot = index_inv; + packInv?.SetItem(index_inv, equipItem); + } + + // Trigger UI refresh if an EC_InventoryUI is present in scene + var ui = GameObject.FindObjectOfType(); + if (ui != null) + { + ui.RefreshAll(); + } + + break; + } + } + } + + public void OnMsgHstOwnItemInfo(ECMSG Msg) + { + int cmd = Convert.ToInt32(Msg.dwParam2); + switch (cmd) + { + case CommandID.OWN_ITEM_INFO: + { + Debug.Log("[Inventory] OWN_ITEM_INFO received"); + var data = Msg.dwParam1 as byte[]; + int hostId = Convert.ToInt32(Msg.dwParam3); + LogInventoryPacket("OWN_ITEM_INFO", data, hostId); + break; + } + } + } + + public void OnMsgHstIvtrInfo(ECMSG Msg) + { + var data = Msg.dwParam1 as byte[]; + int cmd = Convert.ToInt32(Msg.dwParam2); + int hostId = Convert.ToInt32(Msg.dwParam3); + + switch (cmd) + { + case CommandID.OWN_IVTR_DATA: + { + LogInventoryPacket("OWN_IVTR_DATA", data, hostId); + break; + } + case CommandID.OWN_IVTR_DETAIL_DATA: + { + // EC_Inventory.LogInventoryPacket("OWN_IVTR_DETAIL_DATA", data, hostId); + // Parse and store + if (data != null && data.Length >= 6) + { + byte byPackage = data[0]; + byte ivtrSize = data[1]; + if (EC_IvtrItemUtils.Instance.TryParseInventoryDetail(data, out var pkg, + out var size, out var items)) + { + var inv = GetInventory(pkg); + if (inv != null) + { + inv.Resize(size); + inv.RemoveAllItems(); + + if (items != null) + { + foreach (var it in items) + { + if (it != null && it.Slot >= 0 && it.Slot < size) + inv.SetItem(it.Slot, it); + } + } + } + } + + // check if we got the item from the Equipment Pack. If so, we have to load the equipment items + if (byPackage == InventoryConst.IVTRTYPE_EQUIPPACK) + { + UpdateEquipSkins(); + } + } + + break; + } + case CommandID.GET_OWN_MONEY: + { + if (data != null) + { + try + { + var money = GPDataTypeHelper.FromBytes(data); + var ui = GameObject.FindFirstObjectByType(); + if (ui == null) + { + var all = Resources.FindObjectsOfTypeAll(); + if (all != null) + { + for (int i = 0; i < all.Length; i++) + { + var candidate = all[i]; + if (candidate != null && candidate.gameObject.scene.IsValid()) + { + ui = candidate; + break; + } + } + } + } + + if (ui != null) + { + ui.UpdateMoney(money.amount, money.max_amount); + } + else + { + BrewMonster.Scripts.Managers.EC_InventoryUI.CacheMoney(money.amount, money.max_amount); + } + } + catch (Exception ex) + { + Debug.LogWarning($"[Inventory] Failed to parse GET_OWN_MONEY: {ex.Message}"); + } + } + + break; + } + case CommandID.PLAYER_CASH: + { + if (data != null) + { + try + { + var cash = GPDataTypeHelper.FromBytes(data); + var ui = GameObject.FindFirstObjectByType(); + if (ui == null) + { + var all = Resources.FindObjectsOfTypeAll(); + if (all != null) + { + for (int i = 0; i < all.Length; i++) + { + var candidate = all[i]; + if (candidate != null && candidate.gameObject.scene.IsValid()) + { + ui = candidate; + break; + } + } + } + } + + if (ui != null) + { + ui.UpdateCash(cash.cash_amount); + } + else + { + BrewMonster.Scripts.Managers.EC_InventoryUI.CacheCash(cash.cash_amount); + } + } + catch (Exception ex) + { + Debug.LogWarning($"[Inventory] Failed to parse PLAYER_CASH: {ex.Message}"); + } + } + + break; + } + } + } + + public void OnMsgHstCorrectPos(in ECMSG Msg) + { + Debug.LogWarning("HoangDev : OnMsgHstCorrectPos"); + byte[] buf = (byte[])Msg.dwParam1; // chỗ bạn lưu pDataBuf + GCHandle handle = GCHandle.Alloc(buf, GCHandleType.Pinned); + cmd_host_correct_pos pCmd = (cmd_host_correct_pos)Marshal.PtrToStructure( + handle.AddrOfPinnedObject(), typeof(cmd_host_correct_pos)); + handle.Free(); + Debug.LogWarning("HoangDev :pCmd.pos " + pCmd.pos); + SetPos(pCmd.pos); + } + + public void HandleRevive(short sReviveType, A3DVECTOR3 pos) + { + // Move to revive position and play revive animation + PlayAction((int)PLAYER_ACTION_TYPE.ACT_REVIVE); + // Clear any running dead work if exists + m_pWorkMan?.FinishRunningWork(CECHPWork.Host_work_ID.WORK_DEAD); + // Clear corpse state so player is alive again + m_dwStates &= ~(uint)PlayerNPCState.GP_STATE_CORPSE; + } + + public void OnMsgHstGoto(in ECMSG Msg) + { + Debug.Log("HoangDev :OnMsgHstGoto"); + PopupManager.Instance.OnPlayerRevived(); + // p1 is a byte[] buffer; parse into cmd_notify_hostpos then set position + byte[] buf = (byte[])Msg.dwParam1; + cmd_notify_hostpos pCmd = GPDataTypeHelper.FromBytes(buf); + SetPos(new Vector3(pCmd.vPos.x, pCmd.vPos.y, pCmd.vPos.z)); + + } + + private void OnMsgHstStartAttack(in ECMSG Msg) + { + // cmd_host_start_attack pCmd = (cmd_host_start_attack*)Msg.dwParam1; + // ASSERT(pCmd); + // + // // test code... + // // g_pGame->GetRTDebug()->OutputNotifyMessage(RTDCOL_WARNING, _AL("start attack !")); + // + // // Check whether target is the one that we have selected + // if (m_idSelTarget != pCmd->idTarget) + // g_pGame->RuntimeDebugInfo(RTDCOL_WARNING, _AL("Target has changed !")); + // + // // If target turn to be un-attackable, cancel action + // if (!AttackableJudge(pCmd->idTarget, true)) + // { + // g_pGame->GetGameSession()->c2s_CmdCancelAction(); + // g_pGame->RuntimeDebugInfo(RTDCOL_WARNING, _AL("Cannel attacking !")); + // return; + // } + // + // // Synchronize ammo amount + // CECIvtrItem* pItem = m_pEquipPack->GetItem(EQUIPIVTR_PROJECTILE); + // if (pItem) + // { + // if (!pCmd->ammo_remain) + // m_pEquipPack->SetItem(EQUIPIVTR_PROJECTILE, NULL); + // else + // pItem->SetAmount(pCmd->ammo_remain); + // } + // + // CECHPWorkMelee* pWork = (CECHPWorkMelee*)m_pWorkMan->CreateWork(CECHPWork::WORK_HACKOBJECT); + // m_pWorkMan->StartWork_p1(pWork); + // + // m_bMelee = true; + // AP_ActionEvent(AP_EVENT_STARTMELEE); + } + + private void OnMsgHstStopAttack(in ECMSG Msg) + { + // using namespace S2C; + // + // m_bMelee = false; + // + // // if there is an attack event currently, we should let it fire now. + ClearComActFlagAllRankNodes(true); + + cmd_host_stop_attack pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + // ASSERT(pCmd); + + /* If attack stopped for target is leave too far, trace it and continue + attacking. Stop reason defined as below: + + 0x00: attack is canceled or host want to do some other things. + 0x01: unable to attack anymore (no ammo, weapon is broken etc.) + 0x02: invalid target (target missed or died) + 0x04: target is out of range + */ + if ((pCmd.iReason & 0x04) != 0) + { + if (!m_pWorkMan.IsMovingToPosition() && + !m_pWorkMan.IsTracing()) + { + if (CmdNormalAttack(false, false, 0, -1)) //m_pComboSkill != NULL + { + // AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE, 1); + } else { - Debug.LogWarning($"[Inventory] Failed to remove items from package {byPackage}, slot {bySlot}"); + m_pWorkMan.FinishRunningWork(Host_work_ID.WORK_HACKOBJECT); + // AP_ActionEvent(AP_EVENT_STOPMELEE); } } else { - Debug.LogWarning("[Inventory] PLAYER_DROP_ITEM: Invalid data length"); + // AP_ActionEvent(AP_EVENT_STOPMELEE); } - - break; - } - case CommandID.EQUIP_ITEM: - { - byte index_inv = data[0]; - byte index_equip = data[1]; - // Update client-side data: move item between PACK_INVENTORY and PACK_EQUIPMENT - var invItem = EC_Inventory.GetItem(EC_Inventory.IVTRTYPE_PACK, index_inv, true); - var equipItem = EC_Inventory.GetItem(EC_Inventory.IVTRTYPE_EQUIPPACK, index_equip, true); - if (invItem != null) - { - invItem.Package = EC_Inventory.IVTRTYPE_EQUIPPACK; - invItem.Slot = index_equip; - EC_Inventory.SetItem(EC_Inventory.IVTRTYPE_EQUIPPACK, index_equip, invItem); - } - - if (equipItem != null) - { - equipItem.Package = EC_Inventory.IVTRTYPE_PACK; - equipItem.Slot = index_inv; - EC_Inventory.SetItem(EC_Inventory.IVTRTYPE_PACK, index_inv, equipItem); - } - - // Trigger UI refresh if an EC_InventoryUI is present in scene - var ui = GameObject.FindObjectOfType(); - if (ui != null) - { - ui.RefreshAll(); - } - - break; - } - } -} - -public void OnMsgHstOwnItemInfo(ECMSG Msg) -{ - int cmd = Convert.ToInt32(Msg.dwParam2); - switch (cmd) - { - case CommandID.OWN_ITEM_INFO: - { - Debug.Log("[Inventory] OWN_ITEM_INFO received"); - var data = Msg.dwParam1 as byte[]; - int hostId = Convert.ToInt32(Msg.dwParam3); - EC_Inventory.LogInventoryPacket("OWN_ITEM_INFO", data, hostId); - break; - } - } -} - -public void OnMsgHstIvtrInfo(ECMSG Msg) -{ - var data = Msg.dwParam1 as byte[]; - int cmd = Convert.ToInt32(Msg.dwParam2); - int hostId = Convert.ToInt32(Msg.dwParam3); - - switch (cmd) - { - case CommandID.OWN_IVTR_DATA: - { - EC_Inventory.LogInventoryPacket("OWN_IVTR_DATA", data, hostId); - break; - } - case CommandID.OWN_IVTR_DETAIL_DATA: - { - // EC_Inventory.LogInventoryPacket("OWN_IVTR_DETAIL_DATA", data, hostId); - // Parse and store - if (data != null && data.Length >= 6) - { - byte byPackage = data[0]; - byte ivtrSize = data[1]; - if (EC_IvtrItemUtils.TryParseInventoryDetail(data, out var pkg, - out var size, out var items)) - { - EC_Inventory.UpdatePack(pkg, size, items); - } - - // check if we got the item from the Equipment Pack. If so, we have to load the equipment items - if (byPackage == EC_Inventory.IVTRTYPE_EQUIPPACK) - { - UpdateEquipSkins(); - } - } - - break; - } - case CommandID.GET_OWN_MONEY: - { - if (data != null) - { - try - { - var money = GPDataTypeHelper.FromBytes(data); - var ui = GameObject.FindFirstObjectByType(); - if (ui == null) - { - var all = Resources.FindObjectsOfTypeAll(); - if (all != null) - { - for (int i = 0; i < all.Length; i++) - { - var candidate = all[i]; - if (candidate != null && candidate.gameObject.scene.IsValid()) - { - ui = candidate; - break; - } - } - } - } - - if (ui != null) - { - ui.UpdateMoney(money.amount, money.max_amount); - } - else - { - BrewMonster.Scripts.Managers.EC_InventoryUI.CacheMoney(money.amount, money.max_amount); - } - } - catch (Exception ex) - { - Debug.LogWarning($"[Inventory] Failed to parse GET_OWN_MONEY: {ex.Message}"); - } - } - - break; - } - case CommandID.PLAYER_CASH: - { - if (data != null) - { - try - { - var cash = GPDataTypeHelper.FromBytes(data); - var ui = GameObject.FindFirstObjectByType(); - if (ui == null) - { - var all = Resources.FindObjectsOfTypeAll(); - if (all != null) - { - for (int i = 0; i < all.Length; i++) - { - var candidate = all[i]; - if (candidate != null && candidate.gameObject.scene.IsValid()) - { - ui = candidate; - break; - } - } - } - } - - if (ui != null) - { - ui.UpdateCash(cash.cash_amount); - } - else - { - BrewMonster.Scripts.Managers.EC_InventoryUI.CacheCash(cash.cash_amount); - } - } - catch (Exception ex) - { - Debug.LogWarning($"[Inventory] Failed to parse PLAYER_CASH: {ex.Message}"); - } - } - - break; - } - } -} - -public void OnMsgHstCorrectPos(in ECMSG Msg) -{ - Debug.LogWarning("HoangDev : OnMsgHstCorrectPos"); - byte[] buf = (byte[])Msg.dwParam1; // chỗ bạn lưu pDataBuf - GCHandle handle = GCHandle.Alloc(buf, GCHandleType.Pinned); - cmd_host_correct_pos pCmd = (cmd_host_correct_pos)Marshal.PtrToStructure( - handle.AddrOfPinnedObject(), typeof(cmd_host_correct_pos)); - handle.Free(); - Debug.LogWarning("HoangDev :pCmd.pos " + pCmd.pos); - SetPos(pCmd.pos); -} - -public void HandleRevive(short sReviveType, A3DVECTOR3 pos) -{ - // Move to revive position and play revive animation - PlayAction((int)PLAYER_ACTION_TYPE.ACT_REVIVE); - // Clear any running dead work if exists - m_pWorkMan?.FinishRunningWork(CECHPWork.Host_work_ID.WORK_DEAD); - // Clear corpse state so player is alive again - m_dwStates &= ~(uint)PlayerNPCState.GP_STATE_CORPSE; -} - -public void OnMsgHstGoto(in ECMSG Msg) -{ - Debug.Log("HoangDev :OnMsgHstGoto"); - PopupManager.Instance.OnPlayerRevived(); - // p1 is a byte[] buffer; parse into cmd_notify_hostpos then set position - byte[] buf = (byte[])Msg.dwParam1; - cmd_notify_hostpos pCmd = GPDataTypeHelper.FromBytes(buf); - SetPos(new Vector3(pCmd.vPos.x, pCmd.vPos.y, pCmd.vPos.z)); - -} - -private void OnMsgHstStartAttack(in ECMSG Msg) -{ - // cmd_host_start_attack pCmd = (cmd_host_start_attack*)Msg.dwParam1; - // ASSERT(pCmd); - // - // // test code... - // // g_pGame->GetRTDebug()->OutputNotifyMessage(RTDCOL_WARNING, _AL("start attack !")); - // - // // Check whether target is the one that we have selected - // if (m_idSelTarget != pCmd->idTarget) - // g_pGame->RuntimeDebugInfo(RTDCOL_WARNING, _AL("Target has changed !")); - // - // // If target turn to be un-attackable, cancel action - // if (!AttackableJudge(pCmd->idTarget, true)) - // { - // g_pGame->GetGameSession()->c2s_CmdCancelAction(); - // g_pGame->RuntimeDebugInfo(RTDCOL_WARNING, _AL("Cannel attacking !")); - // return; - // } - // - // // Synchronize ammo amount - // CECIvtrItem* pItem = m_pEquipPack->GetItem(EQUIPIVTR_PROJECTILE); - // if (pItem) - // { - // if (!pCmd->ammo_remain) - // m_pEquipPack->SetItem(EQUIPIVTR_PROJECTILE, NULL); - // else - // pItem->SetAmount(pCmd->ammo_remain); - // } - // - // CECHPWorkMelee* pWork = (CECHPWorkMelee*)m_pWorkMan->CreateWork(CECHPWork::WORK_HACKOBJECT); - // m_pWorkMan->StartWork_p1(pWork); - // - // m_bMelee = true; - // AP_ActionEvent(AP_EVENT_STARTMELEE); -} - -private void OnMsgHstStopAttack(in ECMSG Msg) -{ - // using namespace S2C; - // - // m_bMelee = false; - // - // // if there is an attack event currently, we should let it fire now. - ClearComActFlagAllRankNodes(true); - - cmd_host_stop_attack pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - // ASSERT(pCmd); - - /* If attack stopped for target is leave too far, trace it and continue - attacking. Stop reason defined as below: - - 0x00: attack is canceled or host want to do some other things. - 0x01: unable to attack anymore (no ammo, weapon is broken etc.) - 0x02: invalid target (target missed or died) - 0x04: target is out of range - */ - if ((pCmd.iReason & 0x04) != 0) - { - if (!m_pWorkMan.IsMovingToPosition() && - !m_pWorkMan.IsTracing()) - { - if (CmdNormalAttack(false, false, 0, -1)) //m_pComboSkill != NULL - { - // AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE, 1); } else { m_pWorkMan.FinishRunningWork(Host_work_ID.WORK_HACKOBJECT); // AP_ActionEvent(AP_EVENT_STOPMELEE); } + + // #ifdef _SHOW_AUTOPOLICY_DEBUG + // a_LogOutput(1, "Stop Attack, Reason = %d", pCmd->iReason); + // #endif } - else + + // Message MSG_HST_SELTARGET handler + void OnMsgHstSelTarget(ECMSG Msg) { - // AP_ActionEvent(AP_EVENT_STOPMELEE); + //BMLogger.LogError("HoangDev: OnMsgHstSelTarget"); + if (Convert.ToInt32(Msg.dwParam2) == CommandID.SELECT_TARGET) + { + var data = (byte[])Msg.dwParam1; + cmd_select_target pCmd = GPDataTypeHelper.FromBytes(data); + m_idSelTarget = pCmd.idTarget; + m_idUCSelTarget = 0; + } + else if (Convert.ToInt32(Msg.dwParam2) == CommandID.UNSELECT) + { + m_idSelTarget = 0; + } } - } - else - { - m_pWorkMan.FinishRunningWork(Host_work_ID.WORK_HACKOBJECT); - // AP_ActionEvent(AP_EVENT_STOPMELEE); - } - // #ifdef _SHOW_AUTOPOLICY_DEBUG - // a_LogOutput(1, "Stop Attack, Reason = %d", pCmd->iReason); - // #endif -} - -// Message MSG_HST_SELTARGET handler -void OnMsgHstSelTarget(ECMSG Msg) -{ - //BMLogger.LogError("HoangDev: OnMsgHstSelTarget"); - if (Convert.ToInt32(Msg.dwParam2) == CommandID.SELECT_TARGET) - { - var data = (byte[])Msg.dwParam1; - cmd_select_target pCmd = GPDataTypeHelper.FromBytes(data); - m_idSelTarget = pCmd.idTarget; - m_idUCSelTarget = 0; - } - else if (Convert.ToInt32(Msg.dwParam2) == CommandID.UNSELECT) - { - m_idSelTarget = 0; - } -} - -public void SetPos(Vector3 pos) -{ - transform.position = pos; - - m_aabb.Center = EC_Utility.ToA3DVECTOR3(pos) + new A3DVECTOR3(0.0f, m_aabb.Extents.y, 0.0f); - m_aabb.CompleteMinsMaxs(); - m_aabbServer.Center = EC_Utility.ToA3DVECTOR3(pos) + new A3DVECTOR3(0.0f, m_aabbServer.Extents.y, 0.0f); - m_aabbServer.CompleteMinsMaxs(); -} - -public void SetStatusRun(bool value) -{ - if (!isGrounded) - { - Debug.LogError("Player not in ground"); - return; - } - - isRun = value; -} -public override void SetUpPlayer() -{ - base.SetUpPlayer(); - - m_IncantCnt = new CECCounter(); - m_IncantCnt.SetPeriod(1000); - m_IncantCnt.Reset(true); -} - -public async void InitCharacter(cmd_self_info_1 role) -{ - SetUpPlayer(); - controller = GetComponent(); - if (!controller) - { - BMLogger.LogError("HostPlayer InitCharacter no CharacterController"); - } - - //if (role.name != null && role.name.ByteArray != null) - //{ - // roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); - //} - SetPlayerInfor(new INFO(role.cid, role.crc_e, role.crc_c)); - await SetPlayerModel(UnityGameSession.Instance.GetRoleInfo().occupation, UnityGameSession.Instance.GetRoleInfo().gender); - - Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); - string roleName = Encoding.Unicode.GetString(UnityGameSession.Instance.GetRoleInfo().name.ByteArray); - if (txtName != null) txtName.text = roleName; - EventBus.Publish(new InfoHostPlayer(roleName)); - transform.position = pos; - m_dwResFlags = (uint)PlayerResourcesReadyFlag.RESFG_ALL; - joystick = FindAnyObjectByType(); - EventBus.Subscribe(JoystickRelease); - EventBus.Subscribe(JoystickStartDrag); - if (TryGetComponent(out var visual)) - { - visual.InitPlayerEventDoneHandler(); - } - - m_aabb.Center = GPDataTypeHelper.g_vOrigin; - m_aabb.Extents.Set(0.3f, 0.9f, 0.3f); - m_aabbServer = m_aabb; - CalcPlayerAABB(); - SetPos(pos); - m_CDRInfo.fStepHeight = 0.8f; - //m_CDRInfo.vTPNormal = GroundCheck(out RaycastHit hit) ? hit.normal : Vector3.zero; - m_CDRInfo.vExtent = EC_Utility.ToVector3(m_aabbServer.Extents); - // Create work manager - m_pWorkMan = new CECHPWorkMan(this); - m_pWorkMan.StartWork_p0(m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_STAND)); - /*if (IsDead()) - { - CECHPWorkDead pWork = (CECHPWorkDead*)m_pWorkMan->CreateWork(CECHPWork.Host_work_ID.WORK_DEAD); - pWork->SetBeDeadFlag(true); - m_pWorkMan->StartWork_p0(pWork); - } - else if (IsSitting()) - { - CECHPWorkSit* pWork = (CECHPWorkSit*)m_pWorkMan->CreateWork(CECHPWork.Host_work_ID.WORK_SIT); - pWork->SetBeSittingFlag(true); - m_pWorkMan->StartWork_p1(pWork); - }*/ - - LoadResources(); - if (m_pWorkMan == null) - { - return; - } - - LoadGfx(); -} - -public async void LoadGfx() -{ - // Load GFX - var gfxCaster = EC_Game.GetGFXCaster(); - // m_pMoveTargetGFX = g_pGame->GetGFXCaster()->LoadGFXEx(res_GFXFile(RES_GFX_MOVETARGET)); - m_pSelectedGFX = await gfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_SELECTED)); - m_pHoverGFX = await gfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_CURSORHOVER)); - // m_pFloatDust = g_pGame->GetGFXCaster()->LoadGFXEx(res_GFXFile(RES_GFX_FLOATING_DUST)); - - if (true /*CECUIConfig::Instance().GetGameUI().bEnableActionSwitch*/) - { - m_pActionSwitcher = new CECActionSwitcher(this); - } - else - m_pActionSwitcher = new CECActionSwitcherBase(this); - - UnityGameSession.c2s_CmdGetAllData(true, true, false); - // TODO: Move this to right flow later , it's just for test now - UnityGameSession.c2s_CmdSendEnterPKPrecinct(); -} - -private void JoystickStartDrag(JoystickPressEvent joystickPressEvent) -{ - _playerStateMachine.ChangeState(_moveState); -} - -private void OnDestroy() -{ - EventBus.Unsubscribe(JoystickRelease); - EventBus.Unsubscribe(JoystickStartDrag); -} - - -//TODO: Remove this function. Since it has been deprecated. -public void InitCharacter(info_player_1 role) -{ - string roleName = "(Error decoding name)"; - //if (role.name != null && role.name.ByteArray != null) - //{ - // roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); - //} - Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); - if (txtName != null) txtName.text = roleName; - transform.position = pos; - // SetPlayerModel(); - //Debug.LogError("Pos Character = " + pos); -} - -private bool NormalAttackObject(int idTarget, bool bForceAttack, bool bMoreClose = false) -{ - if (idTarget == 0 || idTarget == m_PlayerInfo.cid) - { - // We should have check target isn't dead - return false; - } - - //if (!EC_Game.GetGameRun().GetWorld().GetObject(idTarget, 1)) - // return false; - bool bStartNewWork = false; - - bool bUseAutoPF = false; - //CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper(); - //if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper.GetAttackError() >= 2) - //bUseAutoPF = true; - - CECHPWorkTrace pWorkTrace = null; - CECHPWork pWork = null; - if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) != null) - { - pWorkTrace = pWork as CECHPWorkTrace; - } - else if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT)) != null) - { - if ((pWork as CECHPWorkMelee).GetTarget() == idTarget) - return false; // Host is attacking the target - - pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); - bStartNewWork = true; - } - else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) - { - pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); - bStartNewWork = true; - } - - if (pWorkTrace != null) - { - pWorkTrace.SetTraceTarget( - pWorkTrace.CreatTraceTarget(idTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK, bForceAttack), - bUseAutoPF); - pWorkTrace.SetMoveCloseFlag(bMoreClose); - - if (bStartNewWork) - m_pWorkMan.StartWork_p1(pWorkTrace); - return true; - } - - return false; -} - -public int AttackableJudge(int idTarget, bool bForceAttack) -{ - if (CannotAttack()) - return 0; - - //if (CDlgAutoHelp::IsAutoHelp()) - // return 0; - - if (idTarget == 0 || idTarget == m_PlayerInfo.cid) - return -1; - - CECObject pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); - if (!pObject) - return -1; - - // If target is pet, it's attacked possibility depends on it's monster - if (GPDataTypeHelper.ISNPCID(idTarget)) - { - CECNPC pNPC = (CECNPC)pObject; - int idMaster = pNPC.GetMasterID(); - if (idMaster != 0) + public void SetPos(Vector3 pos) { - // master¿ÉÄÜÊÇhostplayer - if (idMaster == m_PlayerInfo.cid) + transform.position = pos; + + m_aabb.Center = EC_Utility.ToA3DVECTOR3(pos) + new A3DVECTOR3(0.0f, m_aabb.Extents.y, 0.0f); + m_aabb.CompleteMinsMaxs(); + m_aabbServer.Center = EC_Utility.ToA3DVECTOR3(pos) + new A3DVECTOR3(0.0f, m_aabbServer.Extents.y, 0.0f); + m_aabbServer.CompleteMinsMaxs(); + } + + public void SetStatusRun(bool value) + { + if (!isGrounded) + { + Debug.LogError("Player not in ground"); + return; + } + + isRun = value; + } + public override void SetUpPlayer() + { + base.SetUpPlayer(); + + m_IncantCnt = new CECCounter(); + m_IncantCnt.SetPeriod(1000); + m_IncantCnt.Reset(true); + } + + public async void InitCharacter(cmd_self_info_1 role) + { + SetUpPlayer(); + controller = GetComponent(); + if (!controller) + { + BMLogger.LogError("HostPlayer InitCharacter no CharacterController"); + } + + //if (role.name != null && role.name.ByteArray != null) + //{ + // roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); + //} + SetPlayerInfor(new INFO(role.cid, role.crc_e, role.crc_c)); + await SetPlayerModel(UnityGameSession.Instance.GetRoleInfo().occupation, UnityGameSession.Instance.GetRoleInfo().gender); + + Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); + string roleName = Encoding.Unicode.GetString(UnityGameSession.Instance.GetRoleInfo().name.ByteArray); + if (txtName != null) txtName.text = roleName; + EventBus.Publish(new InfoHostPlayer(roleName)); + transform.position = pos; + m_dwResFlags = (uint)PlayerResourcesReadyFlag.RESFG_ALL; + joystick = FindAnyObjectByType(); + EventBus.Subscribe(JoystickRelease); + EventBus.Subscribe(JoystickStartDrag); + if (TryGetComponent(out var visual)) + { + visual.InitPlayerEventDoneHandler(); + } + + m_aabb.Center = GPDataTypeHelper.g_vOrigin; + m_aabb.Extents.Set(0.3f, 0.9f, 0.3f); + m_aabbServer = m_aabb; + CalcPlayerAABB(); + SetPos(pos); + m_CDRInfo.fStepHeight = 0.8f; + //m_CDRInfo.vTPNormal = GroundCheck(out RaycastHit hit) ? hit.normal : Vector3.zero; + m_CDRInfo.vExtent = EC_Utility.ToVector3(m_aabbServer.Extents); + // Create work manager + m_pWorkMan = new CECHPWorkMan(this); + m_pWorkMan.StartWork_p0(m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_STAND)); + /*if (IsDead()) + { + CECHPWorkDead pWork = (CECHPWorkDead*)m_pWorkMan->CreateWork(CECHPWork.Host_work_ID.WORK_DEAD); + pWork->SetBeDeadFlag(true); + m_pWorkMan->StartWork_p0(pWork); + } + else if (IsSitting()) + { + CECHPWorkSit* pWork = (CECHPWorkSit*)m_pWorkMan->CreateWork(CECHPWork.Host_work_ID.WORK_SIT); + pWork->SetBeSittingFlag(true); + m_pWorkMan->StartWork_p1(pWork); + }*/ + + LoadResources(); + if (m_pWorkMan == null) + { + return; + } + + LoadGfx(); + } + + public async void LoadGfx() + { + // Load GFX + var gfxCaster = EC_Game.GetGFXCaster(); + // m_pMoveTargetGFX = g_pGame->GetGFXCaster()->LoadGFXEx(res_GFXFile(RES_GFX_MOVETARGET)); + m_pSelectedGFX = await gfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_SELECTED)); + m_pHoverGFX = await gfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_CURSORHOVER)); + // m_pFloatDust = g_pGame->GetGFXCaster()->LoadGFXEx(res_GFXFile(RES_GFX_FLOATING_DUST)); + + if (true /*CECUIConfig::Instance().GetGameUI().bEnableActionSwitch*/) + { + m_pActionSwitcher = new CECActionSwitcher(this); + } + else + m_pActionSwitcher = new CECActionSwitcherBase(this); + + UnityGameSession.c2s_CmdGetAllData(true, true, false); + // TODO: Move this to right flow later , it's just for test now + UnityGameSession.c2s_CmdSendEnterPKPrecinct(); + } + + private void JoystickStartDrag(JoystickPressEvent joystickPressEvent) + { + _playerStateMachine.ChangeState(_moveState); + } + + private void OnDestroy() + { + EventBus.Unsubscribe(JoystickRelease); + EventBus.Unsubscribe(JoystickStartDrag); + } + + + //TODO: Remove this function. Since it has been deprecated. + public void InitCharacter(info_player_1 role) + { + string roleName = "(Error decoding name)"; + //if (role.name != null && role.name.ByteArray != null) + //{ + // roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); + //} + Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); + if (txtName != null) txtName.text = roleName; + transform.position = pos; + // SetPlayerModel(); + //Debug.LogError("Pos Character = " + pos); + } + + private bool NormalAttackObject(int idTarget, bool bForceAttack, bool bMoreClose = false) + { + if (idTarget == 0 || idTarget == m_PlayerInfo.cid) + { + // We should have check target isn't dead + return false; + } + + //if (!EC_Game.GetGameRun().GetWorld().GetObject(idTarget, 1)) + // return false; + bool bStartNewWork = false; + + bool bUseAutoPF = false; + //CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper(); + //if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper.GetAttackError() >= 2) + //bUseAutoPF = true; + + CECHPWorkTrace pWorkTrace = null; + CECHPWork pWork = null; + if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) != null) + { + pWorkTrace = pWork as CECHPWorkTrace; + } + else if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT)) != null) + { + if ((pWork as CECHPWorkMelee).GetTarget() == idTarget) + return false; // Host is attacking the target + + pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); + bStartNewWork = true; + } + else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) + { + pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); + bStartNewWork = true; + } + + if (pWorkTrace != null) + { + pWorkTrace.SetTraceTarget( + pWorkTrace.CreatTraceTarget(idTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK, bForceAttack), + bUseAutoPF); + pWorkTrace.SetMoveCloseFlag(bMoreClose); + + if (bStartNewWork) + m_pWorkMan.StartWork_p1(pWorkTrace); + return true; + } + + return false; + } + + public int AttackableJudge(int idTarget, bool bForceAttack) + { + if (CannotAttack()) return 0; - //// Follow pet cannot be attacked - //if (pNPC.IsPetNPC() && ((CECPet)pNPC).IsFollowPet()) + //if (CDlgAutoHelp::IsAutoHelp()) // return 0; - idTarget = idMaster; - pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); + if (idTarget == 0 || idTarget == m_PlayerInfo.cid) + return -1; + + CECObject pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); if (!pObject) return -1; - } - } - int iRet = 0; - - if (GPDataTypeHelper.ISNPCID(idTarget)) - { - CECNPC pNPC = (CECNPC)pObject; - - // If this npc is host's pet, cannot be attacked - if (pNPC.GetMasterID() == m_PlayerInfo.cid) - return 0; - - // If it's a pet and can not be attacked, pet can be attacked only if it's a fighting pet - //if (pNPC.IsPetNPC() && !((CECPet)pNPC).CanBeAttacked()) - // return 0; - - if (IsInBattle()) // Host is in battle - { - if (InSameBattleCamp(pNPC)) - iRet = 0; - else + // If target is pet, it's attacked possibility depends on it's monster + if (GPDataTypeHelper.ISNPCID(idTarget)) { - if (pNPC.IsMonsterNPC()) - iRet = 1; - else if (pNPC.IsServerNPC() && - (IsInFortress() || pNPC.GetRoleInBattle() == 8)) // ¶Ô·þÎñÐÍNPCµÄ¹¥»÷£¬°ïÅÉ»ùµØ»ò³Çսʱ¿ÉÓà - iRet = 1; - else - iRet = 0; - } - } - else if (pNPC.IsServerNPC()) - { - // In sanctuary we cannot attack NPCs - if (!IsPVPOpen() || m_bInSanctuary || !bForceAttack) - iRet = 0; - else - iRet = 1; - } - else // Is monster - { - iRet = 1; - } - - if (iRet == 1 && pNPC.GetOwnerFaction() > 0) - { - // Õë¶Ô°ïÅÉ PVP Õ½ÕùÖнûÖ¹²¿·Ö¹¥»÷ - if (GetFactionID() == pNPC.GetOwnerFaction() || // ²»¹¥»÷ͬ°ï¹Ö - pNPC.IsFactionPVPMineCar() && !CanAttackFactionPVPMineCar() || // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï¿ó³µÇé¿ö - pNPC.IsFactionPVPMineBase() && !CanAttackFactionPVPMineBase()) - { - // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï´æ¿óµãÇé¿ö - iRet = 0; - } - } - } - // TO DO: fix later - //else if (GPDataTypeHelper.ISPLAYERID(idTarget)) - //{ - // // Check duel at first - // if (m_pvp.iDuelState == Duel_state.DUEL_ST_INDUEL && m_pvp.idDuelOpp == idTarget) - // return 1; - // else if (m_pvp.iDuelState == Duel_state.DUEL_ST_STOPPING && m_pvp.idDuelOpp == idTarget) - // return 0; - - // // In sanctuary we cannot attack other players - // if (m_bInSanctuary) - // return 0; - - // //ASSERT(pObject.GetClassID() == CECObject::OCID_ELSEPLAYER); - // EC_ElsePlayer pPlayer = (EC_ElsePlayer)pObject; - // ROLEBASICPROP bp = pPlayer.GetBasicProps(); - // EC_GAME_SETTING gs = g_pGame.GetConfigs().GetGameSettings(); - - // if (m_pvp.bFreePVP) - // { - // if (IsTeamMember(idTarget)) - // return 0; - - // // In free pvp mode, for example, host is in arena. - // if (bForceAttack) - // iRet = 1; - // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) - // iRet = 0; - // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) - // iRet = 0; - // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) - // iRet = 0; - // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) - // iRet = 0; - // else - // iRet = 1; - // } - // else if (m_iBattleCamp != GP_BATTLE_CAMP_NONE) - // { - // // Host is in battle - // int iCamp = pPlayer.GetBattleCamp(); - // if (iCamp != GP_BATTLE_CAMP_NONE && iCamp != m_iBattleCamp) - // iRet = 1; - // else - // iRet = 0; - // } - // else // Normal mode - // { - // if (IsTeamMember(idTarget)) - // return 0; - - // if (!IsPVPOpen() || !pPlayer.IsPVPOpen() || m_BasicProps.iLevel < EC_MAXNOPKLEVEL || bp.iLevel < EC_MAXNOPKLEVEL) - // iRet = 0; - // else if (bForceAttack) - // iRet = 1; - // else if (!gs.bAtk_Player) - // iRet = 0; - // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) - // iRet = 0; - // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) - // iRet = 0; - // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) - // iRet = 0; - // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) - // iRet = 0; - // else - // iRet = 1; - // } - //} - else - { - return -1; - } - - return iRet; -} -public CECActionSwitcherBase GetActionSwitcher() { return m_pActionSwitcher; } -private float A3d_Magnitude(A3DVECTOR3 v) -{ - return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); -} - -// Load configs data (shortcut, etc.) from specified buffer -// Converted from: bool CECHostPlayer::LoadConfigData(const void* pDataBuf) -public bool LoadConfigData(byte[] dataBuf) -{ - if (dataBuf == null || dataBuf.Length < sizeof(uint)) - return false; - - int offset = 0; - - // Version number - uint dwVer = GPDataTypeHelper.FromBytes(dataBuf, offset); - offset += sizeof(uint); - if (dwVer > HostCfgConstants.HOSTCFG_VERSION) - { - return false; - } - - // Load shortcut configs... - int iHostSCSets1 = (dwVer <= 4) ? 3 : HostCfgConstants.NUM_HOSTSCSETS1; - - for (int i = 0; i < iHostSCSets1; i++) - { - if (offset >= dataBuf.Length) - return false; - - if (m_aSCSets1[i] == null) - { - m_aSCSets1[i] = new CECShortcutSet(); - m_aSCSets1[i].Init(HostCfgConstants.SIZE_HOSTSCSET1); - } - - if (!m_aSCSets1[i].LoadConfigData(dataBuf, dwVer, ref offset)) - return false; - } - - for (int i = 0; i < HostCfgConstants.NUM_HOSTSCSETS2; i++) - { - if (offset >= dataBuf.Length) - break; // No more data; tolerate truncated optional parts - - if (m_aSCSets2[i] == null) - { - m_aSCSets2[i] = new CECShortcutSet(); - m_aSCSets2[i].Init(HostCfgConstants.SIZE_HOSTSCSET2); - } - - if (!m_aSCSets2[i].LoadConfigData(dataBuf, dwVer, ref offset)) - return false; - } - - // Notes: - // - Auto fashion sets, system module shortcut sets, booth packs, and AutoYinpiao - // sections from native are not loaded here in this Unity port yet. - // The native format appends these after the two shortcut-set groups. - // We intentionally ignore them safely for now. - - return true; -} - -public int GetCharacterID() -{ - return m_PlayerInfo.cid; -} - -public bool CannotAttack() -{ - return (m_dwLIES & (uint)Logic_Influence_Extned_states.LIES_DISABLEFIGHT) != 0; -} - -public bool CanTouchTarget(A3DVECTOR3 vHostPos, A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, - float fMaxCut = 1.0f) -{ - float fDist = A3d_Magnitude(vTargetPos - vHostPos); - switch (iReason) - { - case 1: // melee - { - float fRange; - if (fMaxCut >= 0.0f) + CECNPC pNPC = (CECNPC)pObject; + int idMaster = pNPC.GetMasterID(); + if (idMaster != 0) { - float fCutDist = m_ExtProps.ak.AttackRange * 0.3f; - if (fCutDist > fMaxCut) - fCutDist = fMaxCut; + // master¿ÉÄÜÊÇhostplayer + if (idMaster == m_PlayerInfo.cid) + return 0; - fRange = m_ExtProps.ak.AttackRange - fCutDist; + //// Follow pet cannot be attacked + //if (pNPC.IsPetNPC() && ((CECPet)pNPC).IsFollowPet()) + // return 0; + + idTarget = idMaster; + pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); + if (!pObject) + return -1; + } + } + + int iRet = 0; + + if (GPDataTypeHelper.ISNPCID(idTarget)) + { + CECNPC pNPC = (CECNPC)pObject; + + // If this npc is host's pet, cannot be attacked + if (pNPC.GetMasterID() == m_PlayerInfo.cid) + return 0; + + // If it's a pet and can not be attacked, pet can be attacked only if it's a fighting pet + //if (pNPC.IsPetNPC() && !((CECPet)pNPC).CanBeAttacked()) + // return 0; + + if (IsInBattle()) // Host is in battle + { + if (InSameBattleCamp(pNPC)) + iRet = 0; + else + { + if (pNPC.IsMonsterNPC()) + iRet = 1; + else if (pNPC.IsServerNPC() && + (IsInFortress() || pNPC.GetRoleInBattle() == 8)) // ¶Ô·þÎñÐÍNPCµÄ¹¥»÷£¬°ïÅÉ»ùµØ»ò³Çսʱ¿ÉÓà + iRet = 1; + else + iRet = 0; + } + } + else if (pNPC.IsServerNPC()) + { + // In sanctuary we cannot attack NPCs + if (!IsPVPOpen() || m_bInSanctuary || !bForceAttack) + iRet = 0; + else + iRet = 1; + } + else // Is monster + { + iRet = 1; + } + + if (iRet == 1 && pNPC.GetOwnerFaction() > 0) + { + // Õë¶Ô°ïÅÉ PVP Õ½ÕùÖнûÖ¹²¿·Ö¹¥»÷ + if (GetFactionID() == pNPC.GetOwnerFaction() || // ²»¹¥»÷ͬ°ï¹Ö + pNPC.IsFactionPVPMineCar() && !CanAttackFactionPVPMineCar() || // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï¿ó³µÇé¿ö + pNPC.IsFactionPVPMineBase() && !CanAttackFactionPVPMineBase()) + { + // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï´æ¿óµãÇé¿ö + iRet = 0; + } + } + } + // TO DO: fix later + //else if (GPDataTypeHelper.ISPLAYERID(idTarget)) + //{ + // // Check duel at first + // if (m_pvp.iDuelState == Duel_state.DUEL_ST_INDUEL && m_pvp.idDuelOpp == idTarget) + // return 1; + // else if (m_pvp.iDuelState == Duel_state.DUEL_ST_STOPPING && m_pvp.idDuelOpp == idTarget) + // return 0; + + // // In sanctuary we cannot attack other players + // if (m_bInSanctuary) + // return 0; + + // //ASSERT(pObject.GetClassID() == CECObject::OCID_ELSEPLAYER); + // EC_ElsePlayer pPlayer = (EC_ElsePlayer)pObject; + // ROLEBASICPROP bp = pPlayer.GetBasicProps(); + // EC_GAME_SETTING gs = g_pGame.GetConfigs().GetGameSettings(); + + // if (m_pvp.bFreePVP) + // { + // if (IsTeamMember(idTarget)) + // return 0; + + // // In free pvp mode, for example, host is in arena. + // if (bForceAttack) + // iRet = 1; + // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) + // iRet = 0; + // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) + // iRet = 0; + // else + // iRet = 1; + // } + // else if (m_iBattleCamp != GP_BATTLE_CAMP_NONE) + // { + // // Host is in battle + // int iCamp = pPlayer.GetBattleCamp(); + // if (iCamp != GP_BATTLE_CAMP_NONE && iCamp != m_iBattleCamp) + // iRet = 1; + // else + // iRet = 0; + // } + // else // Normal mode + // { + // if (IsTeamMember(idTarget)) + // return 0; + + // if (!IsPVPOpen() || !pPlayer.IsPVPOpen() || m_BasicProps.iLevel < EC_MAXNOPKLEVEL || bp.iLevel < EC_MAXNOPKLEVEL) + // iRet = 0; + // else if (bForceAttack) + // iRet = 1; + // else if (!gs.bAtk_Player) + // iRet = 0; + // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) + // iRet = 0; + // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) + // iRet = 0; + // else + // iRet = 1; + // } + //} + else + { + return -1; + } + + return iRet; + } + public CECActionSwitcherBase GetActionSwitcher() { return m_pActionSwitcher; } + private float A3d_Magnitude(A3DVECTOR3 v) + { + return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + } + + // Load configs data (shortcut, etc.) from specified buffer + // Converted from: bool CECHostPlayer::LoadConfigData(const void* pDataBuf) + public bool LoadConfigData(byte[] dataBuf) + { + if (dataBuf == null || dataBuf.Length < sizeof(uint)) + return false; + + int offset = 0; + + // Version number + uint dwVer = GPDataTypeHelper.FromBytes(dataBuf, offset); + offset += sizeof(uint); + if (dwVer > HostCfgConstants.HOSTCFG_VERSION) + { + return false; + } + + // Load shortcut configs... + int iHostSCSets1 = (dwVer <= 4) ? 3 : HostCfgConstants.NUM_HOSTSCSETS1; + + for (int i = 0; i < iHostSCSets1; i++) + { + if (offset >= dataBuf.Length) + return false; + + if (m_aSCSets1[i] == null) + { + m_aSCSets1[i] = new CECShortcutSet(); + m_aSCSets1[i].Init(HostCfgConstants.SIZE_HOSTSCSET1); + } + + if (!m_aSCSets1[i].LoadConfigData(dataBuf, dwVer, ref offset)) + return false; + } + + for (int i = 0; i < HostCfgConstants.NUM_HOSTSCSETS2; i++) + { + if (offset >= dataBuf.Length) + break; // No more data; tolerate truncated optional parts + + if (m_aSCSets2[i] == null) + { + m_aSCSets2[i] = new CECShortcutSet(); + m_aSCSets2[i].Init(HostCfgConstants.SIZE_HOSTSCSET2); + } + + if (!m_aSCSets2[i].LoadConfigData(dataBuf, dwVer, ref offset)) + return false; + } + + // Notes: + // - Auto fashion sets, system module shortcut sets, booth packs, and AutoYinpiao + // sections from native are not loaded here in this Unity port yet. + // The native format appends these after the two shortcut-set groups. + // We intentionally ignore them safely for now. + + return true; + } + + public int GetCharacterID() + { + return m_PlayerInfo.cid; + } + + public bool CannotAttack() + { + return (m_dwLIES & (uint)Logic_Influence_Extned_states.LIES_DISABLEFIGHT) != 0; + } + + public bool CanTouchTarget(A3DVECTOR3 vHostPos, A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, + float fMaxCut = 1.0f) + { + float fDist = A3d_Magnitude(vTargetPos - vHostPos); + switch (iReason) + { + case 1: // melee + { + float fRange; + if (fMaxCut >= 0.0f) + { + float fCutDist = m_ExtProps.ak.AttackRange * 0.3f; + if (fCutDist > fMaxCut) + fCutDist = fMaxCut; + + fRange = m_ExtProps.ak.AttackRange - fCutDist; + } + else + { + fRange = m_ExtProps.ak.AttackRange * 0.7f; + } + // TO DO: fix later + fRange = 1f; + if (fDist - fTargetRad <= fRange) + return true; + + break; + } + //case 2: // cast magic + //{ + // if (m_pPrepSkill) + // { + // float fRange = m_pPrepSkill.GetCastRange(m_ExtProps.ak.AttackRange, GetPrayDistancePlus()); + // if (fRange > 0.0f) + // { + // if (fDist - fTargetRad <= fRange) + // return true; + // } + // else + // return true; + // } + + // break; + //} + case 3: // talk + { + if (fDist - fTargetRad <= 5.0f) + return true; + + break; + } + default: // no special reason + { + if (fDist < (fTargetRad + m_fTouchRad) * 3.0f) + return true; + + break; + } + } + + return false; + } + + public void RemoveObjectFromTabSels(CECObject pObject) + { + for (int i = 0; i < m_aTabSels.Count; i++) + { + if (m_aTabSels[i] == pObject) + { + m_aTabSels.RemoveAt(i); + break; + } + } + } + + public bool CanTouchTarget(A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f) + { + A3DVECTOR3 vector = new A3DVECTOR3(gameObject.transform.position.x, gameObject.transform.position.y, + gameObject.transform.position.z); + return CanTouchTarget(vector, vTargetPos, fTargetRad, iReason, fMaxCut); + } + + public bool IsRooting() + { + var mask = (uint)(Logic_Influence_Extned_states.LIES_ROOT + | Logic_Influence_Extned_states.LIES_SLEEP + | Logic_Influence_Extned_states.LIES_STUN); + return (m_dwLIES & mask) != 0; + } + + public bool IsInFortress() + { + return m_fortressEnter.role_in_war != 0; + } + + bool IsPVPOpen() + { + return m_pvp.bEnable; + } + + // Get faction ID + public int GetFactionID() + { + return m_idFaction; + } + + public bool IsJumping() + { + return m_iJumpCount > 0; + } + + public bool IsPlayingAction(int iAction) + { + if (iAction == (int)PLAYER_ACTION_TYPE.ACT_WALK && _playerStateMachine.State is PlayerMoveState) + { + return true; + } + + if (iAction == (int)PLAYER_ACTION_TYPE.ACT_STAND && _playerStateMachine.State is PlayerIdleState) + { + return true; + } + + return false; + } + + public void ResetJump() + { + m_iJumpCount = 0; + m_bJumpInWater = false; + } + + // Get move speed + public float GetFlySpeed() + { + return m_ExtProps.mv.flight_speed; + } + + public float GetSwimSpeed() + { + return m_ExtProps.mv.swim_speed; + } + public bool ApplySkillShortcut(int idSkill, bool bCombo = false /* false */, + int idSelTarget = 0/* 0 */, int iForceAtk = -1/* -1 */) + { + //StackChecker::ACTrace(4); + + if (m_pActionSwitcher != null) + m_pActionSwitcher.PostMessge((int)EMsgActionSwitcher.MSG_CASTSKILL); + + // Return-town skill is very special, handle it separately + //if (idSkill == ID_RETURNTOWN_SKILL) + // return ReturnToTargetTown(0, bCombo); + + //if (idSkill == ID_SUMMONPLAYER_SKILL) + // return SummonPlayer(idSelTarget, bCombo); + + //if (!CanDo(CANDO_SPELLMAGIC)) + // return false; + + //if (InSlidingState()) + // return false; + + if (!bCombo) + //ClearComboSkill(); + + if (idSelTarget == 0) + idSelTarget = m_idSelTarget; + + CECSkill pSkill = GetPositiveSkillByID(idSkill); + if (pSkill == null) pSkill = GetEquipSkillByID(idSkill); + if (pSkill == null) pSkill = CECComboSkillState.Instance.GetInherentSkillByID((uint)idSkill); + if (pSkill == null) + { + return false; + } + + //// If we press a chargeable skill again when it's being charged, + //// we cast it out at once + //if (IsSpellingMagic() && m_pCurSkill && m_pCurSkill->IsCharging() && + // m_pCurSkill->GetSkillID() == pSkill->GetSkillID()) + //{ + // m_pCurSkill->EndCharging(); + // g_pGame->GetGameSession()->c2s_CmdContinueAction(); + // return true; + //} + + //int iCon = CheckSkillCastCondition(pSkill); + //if (iCon) + //{ + // ProcessSkillCondition(iCon); + // return false; + //} + + //// Get force attack flag + bool bForceAttack = false; + //if (iForceAtk < 0) + // bForceAttack = glb_GetForceAttackFlag(0); + //else + // bForceAttack = iForceAtk > 0 ? true : false; + + //// Check negative effect skill + //if (pSkill->GetType() == CECSkill::TYPE_ATTACK || pSkill->GetType() == CECSkill::TYPE_CURSE) + //{ + // if (idSelTarget == m_PlayerInfo.cid) + // { + // // Host cannot spell negative effect magic to himself. + // g_pGame->GetGameRun()->AddFixedChannelMsg(FIXMSG_TARGETWRONG, GP_CHAT_FIGHT); + // return false; + // } + // else if (idSelTarget) + // { + // if (AttackableJudge(idSelTarget, bForceAttack) != 1) + // return false; + // } + //} + + //// Check whether target type match + int idCastTarget = idSelTarget; + int iTargetType = pSkill.GetTargetType(); + + //if (pSkill->GetType() == CECSkill::TYPE_BLESS || + // pSkill->GetType() == CECSkill::TYPE_NEUTRALBLESS) + //{ + // if (!iTargetType || !ISPLAYERID(idSelTarget)) + // idCastTarget = m_PlayerInfo.cid; + + // // In some case, we shouldn't add bless effect to other players + // if (ISPLAYERID(idCastTarget) && idCastTarget != m_PlayerInfo.cid) + // { + // // If host has set bless skill filter only to himself, bless skill couldn't add to other players + // BYTE byBLSMask = glb_BuildBLSMask(); + + // if (pSkill->GetRangeType() == CECSkill::RANGE_POINT) + // { + // if (!IsTeamMember(idCastTarget)) + // { + // if (byBLSMask & GP_BLSMASK_SELF) + // idCastTarget = m_PlayerInfo.cid; + // else + // { + // CECElsePlayer* pPlayer = (CECElsePlayer*)g_pGame->GetGameRun()->GetWorld()->GetPlayerMan()->GetPlayer(idCastTarget); + // if (!pPlayer) + // { + // // Ä¿±êÏûʧ + // return false; + // } + + // if (pPlayer->IsInvader() || pPlayer->IsPariah()) + // { + // if (byBLSMask & GP_BLSMASK_NORED) + // idCastTarget = m_PlayerInfo.cid; + // } + + // if (!IsFactionMember(pPlayer->GetFactionID())) + // { + // if (byBLSMask & GP_BLSMASK_NOMAFIA) + // idCastTarget = m_PlayerInfo.cid; + // } + + // if (!IsFactionAllianceMember(pPlayer->GetFactionID())) + // { + // if (byBLSMask & GP_BLSMASK_NOALLIANCE) + // idCastTarget = m_PlayerInfo.cid; + // } + // if (GetForce() != pPlayer->GetForce()) + // { + // if (byBLSMask & GP_BLSMASK_NOFORCE) + // idCastTarget = m_PlayerInfo.cid; + // } + // } + // } + // } + + // // If host is in duel, bless skill couldn't add to opponent + // if (IsInDuel() && idSelTarget == m_pvp.idDuelOpp) + // idCastTarget = m_PlayerInfo.cid; + + // // If host is in battle, bless skill couldn't add to enemies + // if (IsInBattle()) + // { + // CECElsePlayer* pPlayer = m_pPlayerMan->GetElsePlayer(idCastTarget); + // if (!InSameBattleCamp(pPlayer)) + // idCastTarget = m_PlayerInfo.cid; + // } + // } + //} + //else if (pSkill->GetType() == CECSkill::TYPE_BLESSPET) + //{ + // CECPet* pPet = g_pGame->GetGameRun()->GetWorld()->GetNPCMan()->GetPetByID(idSelTarget); + // if (!pPet || pPet->GetMasterID() == GetCharacterID()) + // { + // // Spell skill on host's pet + // CECPetData* pPetData = m_pPetCorral->GetActivePet(); + // if (!pPetData || + // pPetData->GetClass() != GP_PET_CLASS_COMBAT && + // pPetData->GetClass() != GP_PET_CLASS_SUMMON && + // pPetData->GetClass() != GP_PET_CLASS_EVOLUTION) + // return false; + + // idCastTarget = m_pPetCorral->GetActivePetNPCID(); + // } + // // Only fighting pet can be blessed. + // if (pPet && !pPet->CanBeAttacked()) + // return false; + //} + //else + //{ + // if (iTargetType != 0 && !idCastTarget) + // return false; + //} + + //// iTargetType == 4 means target must be pet. The problem is that pet will + //// disappear from world after it died, so GetWorld()->GetObject() will return + //// NULL when host spells revive-pet skill on his dead pet. So, the target + //// type of revive-pet skill should be 0 + //if (iTargetType) + //{ + // // Target shoundn't be a corpse ? + // int iAliveFlag = 0; + // if (iTargetType == 1) + // iAliveFlag = 1; + // else if (iTargetType == 2) + // iAliveFlag = 2; + + // CECObject* pObject = g_pGame->GetGameRun()->GetWorld()->GetObject(idCastTarget, iAliveFlag); + // if (!pObject) + // return false; + //} + + //if (!IsMeleeing() && !IsSpellingMagic() && + // (!iTargetType || idCastTarget == m_PlayerInfo.cid)) + //{ + // // Cast this skill need't checking cast distance + // if (!pSkill->ReadyToCast()) + // return false; + + // // Prepare to cast skill, if skill isn't INSTANT and FLASHMOVE, + // // we must stop moving and stand + // if (!pSkill->IsInstant() && pSkill->GetType() != CECSkill::TYPE_FLASHMOVE) + // { + // if (!NaturallyStopMoving()) + // return false; // Couldn't stop naturally, so cancel casting skill + // } + // else if (pSkill->GetType() == CECSkill::TYPE_FLASHMOVE) + // { + // if (!CanDo(CANDO_FLASHMOVE)) + // return false; + // } + + m_pPrepSkill = pSkill; + //CastSkill(m_idSelTarget, bForceAttack); + //} + //else if (IsSpellingMagic() && m_pCurSkill == pSkill) + //{ + // // If we are casting the same skill and it's in cooling time + // return false; + //} + //else // Have to trace selected object before cast skill + //{ + // if (!pSkill->ReadyToCast()) + // return false; + + // if (CECCastSkillWhenMove::Instance().IsSkillSupported(pSkill->GetSkillID(), this) && + // m_pWorkMan->IsMovingToPosition() && + // m_pWorkMan->CanCastSkillImmediately(pSkill->GetSkillID())) + // { + // m_pPrepSkill = pSkill; + // return CastSkill(idCastTarget, bForceAttack); + // } + // else + // { + bool bTraceOK = false; + bool bUseAutoPF = false; + /* CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper(); + if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper->GetAttackError() >= 2) + bUseAutoPF = true;*/ + + if (idCastTarget == 0) + { + idCastTarget = GetCharacterID(); // ±ÜÃâË²ÒÆµÈ¼¼ÄÜʱ idCastTarget Ϊ0µ¼Ö CECWorkTrace::CreateTraceTarget ·µ»Ø¿Õ + } + CECHPWork pWork = m_pWorkMan.GetWork(Host_work_ID.WORK_TRACEOBJECT); + if (pWork != null) + { + CECHPWorkTrace pWorkTrace = (CECHPWorkTrace)(pWork); + if (pWorkTrace.GetTraceReason() == Trace_reason.TRACE_SPELL && + pWorkTrace.GetTarget() == idCastTarget && + pWorkTrace.GetPrepSkill() == pSkill) + return false; // We are just doing the same thing + + pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idCastTarget, Trace_reason.TRACE_SPELL, bForceAttack), bUseAutoPF); + pWorkTrace.SetPrepSkill(pSkill); + bTraceOK = true; + } + else if (m_pWorkMan.CanStartWork(Host_work_ID.WORK_TRACEOBJECT)) + { + CECHPWorkTrace pWork2 = (CECHPWorkTrace)m_pWorkMan.CreateWork(Host_work_ID.WORK_TRACEOBJECT); + pWork2.SetTraceTarget(pWork2.CreatTraceTarget(idCastTarget, Trace_reason.TRACE_SPELL, bForceAttack), bUseAutoPF); + pWork2.SetPrepSkill(pSkill); + m_pWorkMan.StartWork_p1(pWork2); + bTraceOK = true; + } + + if (!bTraceOK) return false; + // } + //} + + return true; + } + private void LogInventoryPacket(string tag, byte[] buffer, int hostId) + { + if (buffer == null) + return; + + int index = 0; + if (buffer.Length < 6) + { + //LogInventoryRaw(tag, buffer); + return; + } + + byte byPackage = buffer[index++]; + byte ivtrSize = buffer[index++]; + uint contentLength = BitConverter.ToUInt32(buffer, index); index += 4; + + int remaining = buffer.Length - index; + int contentBytes = remaining; + if (contentLength < (uint)remaining) + { + contentBytes = (int)contentLength; + } + + if (contentBytes > 0) + { + byte[] content = new byte[contentBytes]; + Buffer.BlockCopy(buffer, index, content, 0, contentBytes); + } + + int trailing = buffer.Length - (index + contentBytes); + if (trailing > 0) + { + byte[] tail = new byte[trailing]; + Buffer.BlockCopy(buffer, index + contentBytes, tail, 0, trailing); + } + } + public bool CastSkill(int idTarget, bool bForceAttack, CECObject pTarget = null) + { + byte byPVPMask = glb_BuildPVPMask(bForceAttack); + UnityGameSession.c2s_CmdCastSkill(m_pPrepSkill.GetSkillID(), byPVPMask, 1, idTarget); + return true; + } + public bool UpdateEquipSkins() + { + int[] aNewEquips = new int[InventoryConst.IVTRSIZE_EQUIPPACK]; + EC_IvtrItem pItem = null; + for (int i = 0; i < InventoryConst.IVTRSIZE_EQUIPPACK; i++) + { + // Use host player's equipment inventory (per-instance CECInventory) + var host = CECGameRun.Instance?.GetHostPlayer(); + var equipInv = host?.EquipInventory; + pItem = equipInv?.GetItem(i, false); + if (pItem != null) + aNewEquips[i] = pItem.m_tid; + } + + ShowEquipments(aNewEquips, true, true); + + return true; + } + public byte glb_BuildPVPMask(bool bForceAttack) + { + byte byMask = 0; + if (bForceAttack) + byMask |= (byte)PVPMask.GP_PVPMASK_FORCE; + else + { + /* CECConfigs pConfigs = EC_Game.GetConfigs(); + + if (pConfigs->GetGameSettings().bAtk_Player) + { + byMask |= GP_PVPMASK_FORCE; + + if (pConfigs->GetGameSettings().bAtk_NoMafia) + byMask |= GP_PVPMASK_NOMAFIA; + + if (pConfigs->GetGameSettings().bAtk_NoWhite) + byMask |= GP_PVPMASK_NOWHITE; + + if (pConfigs->GetGameSettings().bAtk_NoAlliance) + byMask |= GP_PVPMASK_NOALLIANCE; + + if (pConfigs->GetGameSettings().bAtk_NoForce) + byMask |= GP_PVPMASK_NOFORCE; + }*/ + } + + return byMask; + } + public bool SelectTarget(int idTarget) + { + //BMLogger.LogError("HoangDev: HostPlayer SelectTarget"); + bool bRet = false; + bool canDo = CanDo(ActionCanDo.CANDO_CHANGESELECT); + bool canselect = CanSelectTarget(idTarget); + if (canDo && canselect) + { + bRet = true; + if (idTarget == 0) + { + //BMLogger.LogError("HoangDev: HostPlayer Unsetlect npc"); + UnityGameSession.c2s_CmdUnselect(); } else { - fRange = m_ExtProps.ak.AttackRange * 0.7f; + //BMLogger.LogError("HoangDev: HostPlayer setlect npc"); + UnityGameSession.c2s_CmdSelectTarget(idTarget); } - // TO DO: fix later - fRange = 1f; - if (fDist - fTargetRad <= fRange) - return true; - - break; } - //case 2: // cast magic - //{ - // if (m_pPrepSkill) - // { - // float fRange = m_pPrepSkill.GetCastRange(m_ExtProps.ak.AttackRange, GetPrayDistancePlus()); - // if (fRange > 0.0f) - // { - // if (fDist - fTargetRad <= fRange) - // return true; - // } - // else - // return true; - // } - // break; - //} - case 3: // talk + return bRet; + } + public CECSkill GetPositiveSkillByID(int id, bool bSenior = false) + { + CECSkill pSenior = null; + + for (int i = 0; i < m_aPtSkills.Count; i++) { - if (fDist - fTargetRad <= 5.0f) - return true; - - break; + if (m_aPtSkills[i].GetSkillID() == id) + return m_aPtSkills[i]; + else if (m_aPtSkills[i].GetJunior().Find((uint)id)) + pSenior = m_aPtSkills[i]; } - default: // no special reason + + if (bSenior && pSenior != null) + return pSenior; + + return null; + } + + // C# conversion of CECHostPlayer::GetEquipSkillByID + // Assumes: GetEquipSkillNum() returns the count of equipment skills + // GetEquipSkillByIndex(int) returns a CECSkill at the given index + public CECSkill GetEquipSkillByID(int id) + { + CECSkill pRet = null; + + for (int i = 0; i < GetEquipSkillNum(); i++) { - if (fDist < (fTargetRad + m_fTouchRad) * 3.0f) - return true; - - break; + CECSkill pSkill = GetEquipSkillByIndex(i); + if (pSkill != null && pSkill.GetSkillID() == id) + { + pRet = pSkill; + break; + } } - } - return false; -} - -public void RemoveObjectFromTabSels(CECObject pObject) -{ - for (int i = 0; i < m_aTabSels.Count; i++) - { - if (m_aTabSels[i] == pObject) - { - m_aTabSels.RemoveAt(i); - break; + return pRet; } - } -} - -public bool CanTouchTarget(A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f) -{ - A3DVECTOR3 vector = new A3DVECTOR3(gameObject.transform.position.x, gameObject.transform.position.y, - gameObject.transform.position.z); - return CanTouchTarget(vector, vTargetPos, fTargetRad, iReason, fMaxCut); -} - -public bool IsRooting() -{ - var mask = (uint)(Logic_Influence_Extned_states.LIES_ROOT - | Logic_Influence_Extned_states.LIES_SLEEP - | Logic_Influence_Extned_states.LIES_STUN); - return (m_dwLIES & mask) != 0; -} - -public bool IsInFortress() -{ - return m_fortressEnter.role_in_war != 0; -} - -bool IsPVPOpen() -{ - return m_pvp.bEnable; -} - -// Get faction ID -public int GetFactionID() -{ - return m_idFaction; -} - -public bool IsJumping() -{ - return m_iJumpCount > 0; -} - -public bool IsPlayingAction(int iAction) -{ - if (iAction == (int)PLAYER_ACTION_TYPE.ACT_WALK && _playerStateMachine.State is PlayerMoveState) - { - return true; - } - - if (iAction == (int)PLAYER_ACTION_TYPE.ACT_STAND && _playerStateMachine.State is PlayerIdleState) - { - return true; - } - - return false; -} - -public void ResetJump() -{ - m_iJumpCount = 0; - m_bJumpInWater = false; -} - -// Get move speed -public float GetFlySpeed() -{ - return m_ExtProps.mv.flight_speed; -} - -public float GetSwimSpeed() -{ - return m_ExtProps.mv.swim_speed; -} -public bool ApplySkillShortcut(int idSkill, bool bCombo = false /* false */, - int idSelTarget = 0/* 0 */, int iForceAtk = -1/* -1 */) -{ - //StackChecker::ACTrace(4); - - if (m_pActionSwitcher != null) - m_pActionSwitcher.PostMessge((int)EMsgActionSwitcher.MSG_CASTSKILL); - - // Return-town skill is very special, handle it separately - //if (idSkill == ID_RETURNTOWN_SKILL) - // return ReturnToTargetTown(0, bCombo); - - //if (idSkill == ID_SUMMONPLAYER_SKILL) - // return SummonPlayer(idSelTarget, bCombo); - - //if (!CanDo(CANDO_SPELLMAGIC)) - // return false; - - //if (InSlidingState()) - // return false; - - if (!bCombo) - //ClearComboSkill(); - - if (idSelTarget == 0) - idSelTarget = m_idSelTarget; - - CECSkill pSkill = GetPositiveSkillByID(idSkill); - if (pSkill == null) pSkill = GetEquipSkillByID(idSkill); - if (pSkill == null) pSkill = CECComboSkillState.Instance.GetInherentSkillByID((uint)idSkill); - if (pSkill == null) - { - return false; - } - - //// If we press a chargeable skill again when it's being charged, - //// we cast it out at once - //if (IsSpellingMagic() && m_pCurSkill && m_pCurSkill->IsCharging() && - // m_pCurSkill->GetSkillID() == pSkill->GetSkillID()) - //{ - // m_pCurSkill->EndCharging(); - // g_pGame->GetGameSession()->c2s_CmdContinueAction(); - // return true; - //} - - //int iCon = CheckSkillCastCondition(pSkill); - //if (iCon) - //{ - // ProcessSkillCondition(iCon); - // return false; - //} - - //// Get force attack flag - bool bForceAttack = false; - //if (iForceAtk < 0) - // bForceAttack = glb_GetForceAttackFlag(0); - //else - // bForceAttack = iForceAtk > 0 ? true : false; - - //// Check negative effect skill - //if (pSkill->GetType() == CECSkill::TYPE_ATTACK || pSkill->GetType() == CECSkill::TYPE_CURSE) - //{ - // if (idSelTarget == m_PlayerInfo.cid) - // { - // // Host cannot spell negative effect magic to himself. - // g_pGame->GetGameRun()->AddFixedChannelMsg(FIXMSG_TARGETWRONG, GP_CHAT_FIGHT); - // return false; - // } - // else if (idSelTarget) - // { - // if (AttackableJudge(idSelTarget, bForceAttack) != 1) - // return false; - // } - //} - - //// Check whether target type match - int idCastTarget = idSelTarget; - int iTargetType = pSkill.GetTargetType(); - - //if (pSkill->GetType() == CECSkill::TYPE_BLESS || - // pSkill->GetType() == CECSkill::TYPE_NEUTRALBLESS) - //{ - // if (!iTargetType || !ISPLAYERID(idSelTarget)) - // idCastTarget = m_PlayerInfo.cid; - - // // In some case, we shouldn't add bless effect to other players - // if (ISPLAYERID(idCastTarget) && idCastTarget != m_PlayerInfo.cid) - // { - // // If host has set bless skill filter only to himself, bless skill couldn't add to other players - // BYTE byBLSMask = glb_BuildBLSMask(); - - // if (pSkill->GetRangeType() == CECSkill::RANGE_POINT) - // { - // if (!IsTeamMember(idCastTarget)) - // { - // if (byBLSMask & GP_BLSMASK_SELF) - // idCastTarget = m_PlayerInfo.cid; - // else - // { - // CECElsePlayer* pPlayer = (CECElsePlayer*)g_pGame->GetGameRun()->GetWorld()->GetPlayerMan()->GetPlayer(idCastTarget); - // if (!pPlayer) - // { - // // Ä¿±êÏûʧ - // return false; - // } - - // if (pPlayer->IsInvader() || pPlayer->IsPariah()) - // { - // if (byBLSMask & GP_BLSMASK_NORED) - // idCastTarget = m_PlayerInfo.cid; - // } - - // if (!IsFactionMember(pPlayer->GetFactionID())) - // { - // if (byBLSMask & GP_BLSMASK_NOMAFIA) - // idCastTarget = m_PlayerInfo.cid; - // } - - // if (!IsFactionAllianceMember(pPlayer->GetFactionID())) - // { - // if (byBLSMask & GP_BLSMASK_NOALLIANCE) - // idCastTarget = m_PlayerInfo.cid; - // } - // if (GetForce() != pPlayer->GetForce()) - // { - // if (byBLSMask & GP_BLSMASK_NOFORCE) - // idCastTarget = m_PlayerInfo.cid; - // } - // } - // } - // } - - // // If host is in duel, bless skill couldn't add to opponent - // if (IsInDuel() && idSelTarget == m_pvp.idDuelOpp) - // idCastTarget = m_PlayerInfo.cid; - - // // If host is in battle, bless skill couldn't add to enemies - // if (IsInBattle()) - // { - // CECElsePlayer* pPlayer = m_pPlayerMan->GetElsePlayer(idCastTarget); - // if (!InSameBattleCamp(pPlayer)) - // idCastTarget = m_PlayerInfo.cid; - // } - // } - //} - //else if (pSkill->GetType() == CECSkill::TYPE_BLESSPET) - //{ - // CECPet* pPet = g_pGame->GetGameRun()->GetWorld()->GetNPCMan()->GetPetByID(idSelTarget); - // if (!pPet || pPet->GetMasterID() == GetCharacterID()) - // { - // // Spell skill on host's pet - // CECPetData* pPetData = m_pPetCorral->GetActivePet(); - // if (!pPetData || - // pPetData->GetClass() != GP_PET_CLASS_COMBAT && - // pPetData->GetClass() != GP_PET_CLASS_SUMMON && - // pPetData->GetClass() != GP_PET_CLASS_EVOLUTION) - // return false; - - // idCastTarget = m_pPetCorral->GetActivePetNPCID(); - // } - // // Only fighting pet can be blessed. - // if (pPet && !pPet->CanBeAttacked()) - // return false; - //} - //else - //{ - // if (iTargetType != 0 && !idCastTarget) - // return false; - //} - - //// iTargetType == 4 means target must be pet. The problem is that pet will - //// disappear from world after it died, so GetWorld()->GetObject() will return - //// NULL when host spells revive-pet skill on his dead pet. So, the target - //// type of revive-pet skill should be 0 - //if (iTargetType) - //{ - // // Target shoundn't be a corpse ? - // int iAliveFlag = 0; - // if (iTargetType == 1) - // iAliveFlag = 1; - // else if (iTargetType == 2) - // iAliveFlag = 2; - - // CECObject* pObject = g_pGame->GetGameRun()->GetWorld()->GetObject(idCastTarget, iAliveFlag); - // if (!pObject) - // return false; - //} - - //if (!IsMeleeing() && !IsSpellingMagic() && - // (!iTargetType || idCastTarget == m_PlayerInfo.cid)) - //{ - // // Cast this skill need't checking cast distance - // if (!pSkill->ReadyToCast()) - // return false; - - // // Prepare to cast skill, if skill isn't INSTANT and FLASHMOVE, - // // we must stop moving and stand - // if (!pSkill->IsInstant() && pSkill->GetType() != CECSkill::TYPE_FLASHMOVE) - // { - // if (!NaturallyStopMoving()) - // return false; // Couldn't stop naturally, so cancel casting skill - // } - // else if (pSkill->GetType() == CECSkill::TYPE_FLASHMOVE) - // { - // if (!CanDo(CANDO_FLASHMOVE)) - // return false; - // } - - m_pPrepSkill = pSkill; - //CastSkill(m_idSelTarget, bForceAttack); - //} - //else if (IsSpellingMagic() && m_pCurSkill == pSkill) - //{ - // // If we are casting the same skill and it's in cooling time - // return false; - //} - //else // Have to trace selected object before cast skill - //{ - // if (!pSkill->ReadyToCast()) - // return false; - - // if (CECCastSkillWhenMove::Instance().IsSkillSupported(pSkill->GetSkillID(), this) && - // m_pWorkMan->IsMovingToPosition() && - // m_pWorkMan->CanCastSkillImmediately(pSkill->GetSkillID())) - // { - // m_pPrepSkill = pSkill; - // return CastSkill(idCastTarget, bForceAttack); - // } - // else - // { - bool bTraceOK = false; - bool bUseAutoPF = false; - /* CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper(); - if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper->GetAttackError() >= 2) - bUseAutoPF = true;*/ - - if (idCastTarget == 0) - { - idCastTarget = GetCharacterID(); // ±ÜÃâË²ÒÆµÈ¼¼ÄÜʱ idCastTarget Ϊ0µ¼Ö CECWorkTrace::CreateTraceTarget ·µ»Ø¿Õ - } - CECHPWork pWork = m_pWorkMan.GetWork(Host_work_ID.WORK_TRACEOBJECT); - if (pWork != null) - { - CECHPWorkTrace pWorkTrace = (CECHPWorkTrace)(pWork); - if (pWorkTrace.GetTraceReason() == Trace_reason.TRACE_SPELL && - pWorkTrace.GetTarget() == idCastTarget && - pWorkTrace.GetPrepSkill() == pSkill) - return false; // We are just doing the same thing - - pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idCastTarget, Trace_reason.TRACE_SPELL, bForceAttack), bUseAutoPF); - pWorkTrace.SetPrepSkill(pSkill); - bTraceOK = true; - } - else if (m_pWorkMan.CanStartWork(Host_work_ID.WORK_TRACEOBJECT)) - { - CECHPWorkTrace pWork2 = (CECHPWorkTrace)m_pWorkMan.CreateWork(Host_work_ID.WORK_TRACEOBJECT); - pWork2.SetTraceTarget(pWork2.CreatTraceTarget(idCastTarget, Trace_reason.TRACE_SPELL, bForceAttack), bUseAutoPF); - pWork2.SetPrepSkill(pSkill); - m_pWorkMan.StartWork_p1(pWork2); - bTraceOK = true; - } - - if (!bTraceOK) return false; - // } - //} - - return true; -} - -public bool CastSkill(int idTarget, bool bForceAttack, CECObject pTarget = null) -{ - byte byPVPMask = glb_BuildPVPMask(bForceAttack); - UnityGameSession.c2s_CmdCastSkill(m_pPrepSkill.GetSkillID(), byPVPMask, 1, idTarget); - return true; -} -public byte glb_BuildPVPMask(bool bForceAttack) -{ - byte byMask = 0; - if (bForceAttack) - byMask |= (byte)PVPMask.GP_PVPMASK_FORCE; - else - { - /* CECConfigs pConfigs = EC_Game.GetConfigs(); - - if (pConfigs->GetGameSettings().bAtk_Player) - { - byMask |= GP_PVPMASK_FORCE; - - if (pConfigs->GetGameSettings().bAtk_NoMafia) - byMask |= GP_PVPMASK_NOMAFIA; - - if (pConfigs->GetGameSettings().bAtk_NoWhite) - byMask |= GP_PVPMASK_NOWHITE; - - if (pConfigs->GetGameSettings().bAtk_NoAlliance) - byMask |= GP_PVPMASK_NOALLIANCE; - - if (pConfigs->GetGameSettings().bAtk_NoForce) - byMask |= GP_PVPMASK_NOFORCE; - }*/ - } - - return byMask; -} -public bool SelectTarget(int idTarget) -{ - //BMLogger.LogError("HoangDev: HostPlayer SelectTarget"); - bool bRet = false; - bool canDo = CanDo(ActionCanDo.CANDO_CHANGESELECT); - bool canselect = CanSelectTarget(idTarget); - if (canDo && canselect) - { - bRet = true; - if (idTarget == 0) + public int GetEquipSkillNum() { return m_aEquipSkills.Count; } + public CECSkill GetEquipSkillByIndex(int n) { return m_aEquipSkills[n]; } + bool CanSelectTarget(int idTarget) { - //BMLogger.LogError("HoangDev: HostPlayer Unsetlect npc"); - UnityGameSession.c2s_CmdUnselect(); - } - else - { - //BMLogger.LogError("HoangDev: HostPlayer setlect npc"); - UnityGameSession.c2s_CmdSelectTarget(idTarget); - } - } - - return bRet; -} -public CECSkill GetPositiveSkillByID(int id, bool bSenior = false) -{ - CECSkill pSenior = null; - - for (int i = 0; i < m_aPtSkills.Count; i++) - { - if (m_aPtSkills[i].GetSkillID() == id) - return m_aPtSkills[i]; - else if (m_aPtSkills[i].GetJunior().Find((uint)id)) - pSenior = m_aPtSkills[i]; - } - - if (bSenior && pSenior != null) - return pSenior; - - return null; -} - -// C# conversion of CECHostPlayer::GetEquipSkillByID -// Assumes: GetEquipSkillNum() returns the count of equipment skills -// GetEquipSkillByIndex(int) returns a CECSkill at the given index -public CECSkill GetEquipSkillByID(int id) -{ - CECSkill pRet = null; - - for (int i = 0; i < GetEquipSkillNum(); i++) - { - CECSkill pSkill = GetEquipSkillByIndex(i); - if (pSkill != null && pSkill.GetSkillID() == id) - { - pRet = pSkill; - break; - } - } - - return pRet; -} -public int GetEquipSkillNum() { return m_aEquipSkills.Count; } -public CECSkill GetEquipSkillByIndex(int n) { return m_aEquipSkills[n]; } -bool CanSelectTarget(int idTarget) -{ - if (idTarget == 0 || idTarget == this.GetCharacterID()) - { - // 0 means unselect - return true; - } - - CECObject pTarget = null; - if (GPDataTypeHelper.ISPLAYERID(idTarget)) - { - EC_ElsePlayer pElsePlayer = - (EC_ManMessageMono.Instance.GetECManPlayer.GetPlayer(idTarget)) as EC_ElsePlayer; - if (pElsePlayer != null) - { - if (CanSafelySelect(pElsePlayer)) + if (idTarget == 0 || idTarget == this.GetCharacterID()) { - pTarget = pElsePlayer; + // 0 means unselect + return true; } - } - } - else if (GPDataTypeHelper.ISNPCID(idTarget)) - { - CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idTarget); - if (pNPC != null) - { - if (CanSafelySelect(pNPC) && !pNPC.IsDead()) + + CECObject pTarget = null; + if (GPDataTypeHelper.ISPLAYERID(idTarget)) { - pTarget = pNPC; + EC_ElsePlayer pElsePlayer = + (EC_ManMessageMono.Instance.GetECManPlayer.GetPlayer(idTarget)) as EC_ElsePlayer; + if (pElsePlayer != null) + { + if (CanSafelySelect(pElsePlayer)) + { + pTarget = pElsePlayer; + } + } } + else if (GPDataTypeHelper.ISNPCID(idTarget)) + { + CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idTarget); + if (pNPC != null) + { + if (CanSafelySelect(pNPC) && !pNPC.IsDead()) + { + pTarget = pNPC; + } + } + } + + return pTarget ? pTarget.IsSelectable() : false; } - } - - return pTarget ? pTarget.IsSelectable() : false; -} -float SafelySelectDistance() -{ - // ·þÎñÆ÷¶Ô SelectTarget ÓжîÍâ¾àÀëÏÞÖÆ£¬Èýά¾àÀë 150.0¡¢Ë®Æ½¾àÀë 125.0 ÒÔÉϵ쬶¼»áÎÞ·¨Ñ¡ÖÐ - // »ùÓÚÒÔÉÏÔ­Òò£¬¿Í»§¶ËÑ¡Ôñ¶ÔÏó¡¢»òÕß¶ÔÒѾ­Ñ¡ÔñµÄ¶ÔÏ󣬶¼È·±£ÆäÔÚ´ËÏÞÖÆ·¶Î§ÄÚ£¬¼´Ñ¡ÔñʱʹÓýÏС¾àÀë¼ì²â - return 100.0f; -} + float SafelySelectDistance() + { + // ·þÎñÆ÷¶Ô SelectTarget ÓжîÍâ¾àÀëÏÞÖÆ£¬Èýά¾àÀë 150.0¡¢Ë®Æ½¾àÀë 125.0 ÒÔÉϵ쬶¼»áÎÞ·¨Ñ¡ÖÐ + // »ùÓÚÒÔÉÏÔ­Òò£¬¿Í»§¶ËÑ¡Ôñ¶ÔÏó¡¢»òÕß¶ÔÒѾ­Ñ¡ÔñµÄ¶ÔÏ󣬶¼È·±£ÆäÔÚ´ËÏÞÖÆ·¶Î§ÄÚ£¬¼´Ñ¡ÔñʱʹÓýÏС¾àÀë¼ì²â + return 100.0f; + } -bool CanSafelySelectWith(float fDistanceToHostPlayer) -{ - return fDistanceToHostPlayer <= SafelySelectDistance(); -} + bool CanSafelySelectWith(float fDistanceToHostPlayer) + { + return fDistanceToHostPlayer <= SafelySelectDistance(); + } -bool CanSafelySelect(EC_ElsePlayer pElsePlayer) -{ - // IsSkeletonReady() Ϊ true ʱ, GetDistToHost() ²ÅΪÓÐЧÊý¾Ý - // !IsSkeletonReady() ʱ£¬Ò²ÔÊÐíʹÓã¬Ä¿µÄÊDZÜÃâδ¿¼Âǵ½µÄÒâÍâÇé¿ö - // ÏÂͬ - return pElsePlayer && ( /*!IsSkeletonReady() || */CanSafelySelectWith(pElsePlayer.GetDistToHost())); -} + bool CanSafelySelect(EC_ElsePlayer pElsePlayer) + { + // IsSkeletonReady() Ϊ true ʱ, GetDistToHost() ²ÅΪÓÐЧÊý¾Ý + // !IsSkeletonReady() ʱ£¬Ò²ÔÊÐíʹÓã¬Ä¿µÄÊDZÜÃâδ¿¼Âǵ½µÄÒâÍâÇé¿ö + // ÏÂͬ + return pElsePlayer && ( /*!IsSkeletonReady() || */CanSafelySelectWith(pElsePlayer.GetDistToHost())); + } -bool CanSafelySelect(CECNPC pNPC) -{ - return pNPC && ( /*!IsSkeletonReady() ||*/ CanSafelySelectWith(pNPC.GetDistToHost())); -} + bool CanSafelySelect(CECNPC pNPC) + { + return pNPC && ( /*!IsSkeletonReady() ||*/ CanSafelySelectWith(pNPC.GetDistToHost())); + } -// Check whether host can do a behavior -bool CanDo(int iThing) -{ - bool bRet = true; + // Check whether host can do a behavior + bool CanDo(int iThing) + { + bool bRet = true; - switch (iThing) - { - case ActionCanDo.CANDO_SITDOWN: + switch (iThing) + { + case ActionCanDo.CANDO_SITDOWN: - if (IsDead() /*|| IsAboutToDie() */ || IsJumping() /*|| IsTrading() || IsUsingTrashBox()*/ || - IsRooting() || /*IsReviving() || IsTalkingWithNPC() || IsChangingFace() ||*/ - !m_GndInfo - .bOnGround /*|| GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || + if (IsDead() /*|| IsAboutToDie() */ || IsJumping() /*|| IsTrading() || IsUsingTrashBox()*/ || + IsRooting() || /*IsReviving() || IsTalkingWithNPC() || IsChangingFace() ||*/ + !m_GndInfo + .bOnGround /*|| GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsRidingOnPet() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove()*/ - ) - bRet = false; + ) + bRet = false; - break; + break; - case ActionCanDo.CANDO_MOVETO: - { - if (IsDead() /*|| IsSitting() || IsTrading() || IsUsingTrashBox()*/ || IsRooting() /*|| + case ActionCanDo.CANDO_MOVETO: + { + if (IsDead() /*|| IsSitting() || IsTrading() || IsUsingTrashBox()*/ || IsRooting() /*|| IsReviving() || IsTalkingWithNPC() || IsChangingFace() || IsUsingItem() || GetBoothState() != 0 || m_bHangerOn || IsOperatingPet() || IsRebuildingPet() || IsPassiveMove()*/) - bRet = false; + bRet = false; - break; - } - case ActionCanDo.CANDO_MELEE: + break; + } + case ActionCanDo.CANDO_MELEE: - if (IsDead() /*|| IsSitting() */ || m_idSelTarget == 0 || m_idSelTarget == m_PlayerInfo.cid || - IsJumping() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) /*|| IsTrading() || IsReviving() || + if (IsDead() /*|| IsSitting() */ || m_idSelTarget == 0 || m_idSelTarget == m_PlayerInfo.cid || + IsJumping() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) /*|| IsTrading() || IsReviving() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace()*/ || CannotAttack() /*|| GetBoothState() != 0 || m_iBuddyId || IsRidingOnPet() || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()*/) - bRet = false; + bRet = false; - break; + break; - case ActionCanDo.CANDO_ASSISTSEL: + case ActionCanDo.CANDO_ASSISTSEL: - if (IsDead() || !GPDataTypeHelper.ISPLAYERID(m_idSelTarget) || m_idSelTarget == m_PlayerInfo.cid /*|| + if (IsDead() || !GPDataTypeHelper.ISPLAYERID(m_idSelTarget) || m_idSelTarget == m_PlayerInfo.cid /*|| !m_pTeam || !m_pTeam->GetMemberByID(m_idSelTarget) || m_iBuddyId || IsPassiveMove() || m_playerLimits.test(PLAYER_LIMIT_NOCHANGESELECT)*/) - bRet = false; + bRet = false; - break; + break; - case ActionCanDo.CANDO_FLY: + case ActionCanDo.CANDO_FLY: - if (IsDead() || IsRooting() /*|| IsSitting() || IsTrading() || IsReviving() || + if (IsDead() || IsRooting() /*|| IsSitting() || IsTrading() || IsReviving() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || GetBoothState() != 0 || IsFlashMoving() */ || - m_pWorkMan.HasWorkRunningOnPriority(CECHPWorkMan.Work_priority.PRIORITY_2) /*|| + m_pWorkMan.HasWorkRunningOnPriority(CECHPWorkMan.Work_priority.PRIORITY_2) /*|| m_bHangerOn || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsRidingOnPet() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove() || m_playerLimits.test(PLAYER_LIMIT_NOFLY) || m_BattleInfo.IsChariotWar()*/) - bRet = false; + bRet = false; - break; + break; - case ActionCanDo.CANDO_PICKUP: - case ActionCanDo.CANDO_GATHER: + case ActionCanDo.CANDO_PICKUP: + case ActionCanDo.CANDO_GATHER: - if (IsDead() /*|| IsAboutToDie() || IsSitting() || IsTrading() || IsUsingTrashBox() || + if (IsDead() /*|| IsAboutToDie() || IsSitting() || IsTrading() || IsUsingTrashBox() || IsReviving() || IsTalkingWithNPC() || IsChangingFace() || GetBoothState() != 0 || GetBuddyState() == 1 || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()*/) - bRet = false; + bRet = false; - break; + break; - case ActionCanDo.CANDO_TRADE: + case ActionCanDo.CANDO_TRADE: - if (IsDead() /*|| IsAboutToDie() || IsSitting() */ || IsJumping() /*|| IsMeleeing() || + if (IsDead() /*|| IsAboutToDie() || IsSitting() */ || IsJumping() /*|| IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || IsSpellingMagic() || GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsInvisible() || IsPassiveMove()*/) - bRet = false; + bRet = false; - break; + break; - case ActionCanDo.CANDO_PLAYPOSE: + case ActionCanDo.CANDO_PLAYPOSE: - if (IsDead() /*|| IsAboutToDie() || IsSitting()*/ || IsJumping() || /* IsMeleeing() || + if (IsDead() /*|| IsAboutToDie() || IsSitting()*/ || IsJumping() || /* IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || IsSpellingMagic() || IsShapeChanged() || IsReviving() ||*/ - m_iMoveEnv != (int)MoveEnvironment.MOVEENV_GROUND /*|| + m_iMoveEnv != (int)MoveEnvironment.MOVEENV_GROUND /*|| GetBoothState() != 0 || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsRidingOnPet() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove() || m_BattleInfo.IsChariotWar()*/ - ) - bRet = false; + ) + bRet = false; - break; + break; - //case ActionCanDo.CANDO_SPELLMAGIC: - // if (IsDead() || ISMATTERID(m_idSelTarget) || IsAboutToDie() || IsSitting() || - // IsJumping() || IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || - // IsChangingFace() || CannotAttack() || IsReviving() || GetBoothState() != 0 || - // m_iBuddyId || IsRidingOnPet() || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) - // bRet = false; + //case ActionCanDo.CANDO_SPELLMAGIC: + // if (IsDead() || ISMATTERID(m_idSelTarget) || IsAboutToDie() || IsSitting() || + // IsJumping() || IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || CannotAttack() || IsReviving() || GetBoothState() != 0 || + // m_iBuddyId || IsRidingOnPet() || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) + // bRet = false; - // break; + // break; - case ActionCanDo.CANDO_SUMMONPET: + case ActionCanDo.CANDO_SUMMONPET: - if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) || /*IsAboutToDie() || IsSitting() ||*/ - IsJumping() || /*IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) || /*IsAboutToDie() || IsSitting() ||*/ + IsJumping() || /*IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() ||*/ CannotAttack() /*|| IsReviving() || GetBoothState() != 0 || IsInvisible() || IsGMInvisible() || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove() || m_BattleInfo.IsChariotWar()*/) - bRet = false; + bRet = false; - break; - case ActionCanDo.CANDO_REBUILDPET: + break; + case ActionCanDo.CANDO_REBUILDPET: - if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) /*|| IsAboutToDie() || IsSitting() */ || - IsJumping() /*|| IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) /*|| IsAboutToDie() || IsSitting() */ || + IsJumping() /*|| IsFlashMoving() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace()*/ || CannotAttack() /*|| IsReviving() || GetBoothState() != 0 || m_iBuddyId || IsInvisible() || IsGMInvisible() || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove() || IsPlayerMoving() || m_BattleInfo.IsChariotWar()*/) - bRet = false; + bRet = false; - break; + break; - //case ActionCanDo.CANDO_USEITEM: + //case ActionCanDo.CANDO_USEITEM: - // if (IsAboutToDie() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || - // IsChangingFace() || GetBoothState() != 0 || IsPassiveMove() || m_BattleInfo.IsChariotWar()) - // bRet = false; + // if (IsAboutToDie() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || GetBoothState() != 0 || IsPassiveMove() || m_BattleInfo.IsChariotWar()) + // bRet = false; - // break; + // break; - //case ActionCanDo.CANDO_JUMP: - // { - // if (IsDead() || - // m_iJumpCount >= MAX_JUMP_COUNT || - // // cannot jump more than one time if shape mode is type2 - // (IsJumping() && (GetShapeType() == PLAYERMODEL_DUMMYTYPE2)) || - // IsJumpInWater() || m_iMoveEnv == MOVEENV_AIR || IsSitting() || - // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || - // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || - // IsGathering() || IsRooting() || GetBoothState() != 0 || m_bHangerOn || (IsJumping() && IsRidingOnPet()) || - // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove() || m_BattleInfo.IsChariotWar()) - // bRet = false; + //case ActionCanDo.CANDO_JUMP: + // { + // if (IsDead() || + // m_iJumpCount >= MAX_JUMP_COUNT || + // // cannot jump more than one time if shape mode is type2 + // (IsJumping() && (GetShapeType() == PLAYERMODEL_DUMMYTYPE2)) || + // IsJumpInWater() || m_iMoveEnv == MOVEENV_AIR || IsSitting() || + // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || + // IsGathering() || IsRooting() || GetBoothState() != 0 || m_bHangerOn || (IsJumping() && IsRidingOnPet()) || + // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove() || m_BattleInfo.IsChariotWar()) + // bRet = false; - // break; - // } - //case ActionCanDo.CANDO_FOLLOW: - // { - // if (IsDead() || IsAboutToDie() || IsSitting() || IsMeleeing() || IsReviving() || - // IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || - // IsSpellingMagic() || GetBoothState() != 0 || m_bHangerOn || IsOperatingPet() || IsRebuildingPet() || - // IsUsingItem() || IsPassiveMove()) - // bRet = false; + // break; + // } + //case ActionCanDo.CANDO_FOLLOW: + // { + // if (IsDead() || IsAboutToDie() || IsSitting() || IsMeleeing() || IsReviving() || + // IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || + // IsSpellingMagic() || GetBoothState() != 0 || m_bHangerOn || IsOperatingPet() || IsRebuildingPet() || + // IsUsingItem() || IsPassiveMove()) + // bRet = false; - // break; - // } - //case ActionCanDo.CANDO_BOOTH: + // break; + // } + //case ActionCanDo.CANDO_BOOTH: - // if (IsDead() || IsAboutToDie() || IsPlayerMoving() || IsSitting() || IsReviving() || - // IsMeleeing() || IsJumping() || IsTrading() || IsUsingTrashBox() || - // IsTalkingWithNPC() || IsChangingFace() || IsSpellingMagic() || IsFlying() || - // IsUnderWater() || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsRidingOnPet() || IsInvisible() || - // IsPassiveMove()) - // bRet = false; + // if (IsDead() || IsAboutToDie() || IsPlayerMoving() || IsSitting() || IsReviving() || + // IsMeleeing() || IsJumping() || IsTrading() || IsUsingTrashBox() || + // IsTalkingWithNPC() || IsChangingFace() || IsSpellingMagic() || IsFlying() || + // IsUnderWater() || m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsRidingOnPet() || IsInvisible() || + // IsPassiveMove()) + // bRet = false; - // break; + // break; - //case ActionCanDo.CANDO_FLASHMOVE: + //case ActionCanDo.CANDO_FLASHMOVE: - // if (IsDead() || IsAboutToDie() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || - // IsJumping() || IsFlashMoving() || IsFalling() || IsChangingFace() || GetBoothState() != 0 || IsTakingOff() || - // m_pWorkMan.HasWorkRunningOnPriority(CECHPWorkMan::PRIORITY_2) || - // m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) - // bRet = false; + // if (IsDead() || IsAboutToDie() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsJumping() || IsFlashMoving() || IsFalling() || IsChangingFace() || GetBoothState() != 0 || IsTakingOff() || + // m_pWorkMan.HasWorkRunningOnPriority(CECHPWorkMan::PRIORITY_2) || + // m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) + // bRet = false; - // break; + // break; - //case ActionCanDo.CANDO_BINDBUDDY: + //case ActionCanDo.CANDO_BINDBUDDY: - // if (IsDead() || IsAboutToDie() || IsJumping() || IsSitting() || - // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || - // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || - // IsGathering() || IsRooting() || GetBoothState() != 0 || - // !m_pWorkMan->IsStanding() || m_iBuddyId || - // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove() || - // m_playerLimits.test(PLAYER_LIMIT_NOBIND)) - // bRet = false; + // if (IsDead() || IsAboutToDie() || IsJumping() || IsSitting() || + // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || + // IsGathering() || IsRooting() || GetBoothState() != 0 || + // !m_pWorkMan->IsStanding() || m_iBuddyId || + // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove() || + // m_playerLimits.test(PLAYER_LIMIT_NOBIND)) + // bRet = false; - // break; + // break; - //case ActionCanDo.CANDO_DUEL: + //case ActionCanDo.CANDO_DUEL: - // if (IsDead() || IsAboutToDie() || IsSitting() || IsFighting() || IsTrading() || - // IsReviving() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || - // GetBoothState() != 0 || m_iBuddyId || m_pvp.iDuelState != DUEL_ST_NONE || - // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) - // bRet = false; + // if (IsDead() || IsAboutToDie() || IsSitting() || IsFighting() || IsTrading() || + // IsReviving() || IsUsingTrashBox() || IsTalkingWithNPC() || IsChangingFace() || + // GetBoothState() != 0 || m_iBuddyId || m_pvp.iDuelState != DUEL_ST_NONE || + // IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || IsPassiveMove()) + // bRet = false; - // break; + // break; - case ActionCanDo.CANDO_CHANGESELECT: + case ActionCanDo.CANDO_CHANGESELECT: - //if (m_playerLimits.test(PLAYER_LIMIT_NOCHANGESELECT)) - // bRet = false; + //if (m_playerLimits.test(PLAYER_LIMIT_NOCHANGESELECT)) + // bRet = false; - break; + break; - //case ActionCanDo.CANDO_SWITCH_PARALLEL_WORLD: - // if (IsDead() || IsAboutToDie() || IsJumping() || IsFighting() || - // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || - // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || - // IsGathering() || IsRooting() || GetBoothState() != 0 || - // m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || - // GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove()) - // bRet = false; - // break; - } + //case ActionCanDo.CANDO_SWITCH_PARALLEL_WORLD: + // if (IsDead() || IsAboutToDie() || IsJumping() || IsFighting() || + // IsMeleeing() || IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + // IsChangingFace() || IsReviving() || IsSpellingMagic() || IsPicking() || + // IsGathering() || IsRooting() || GetBoothState() != 0 || + // m_iBuddyId || IsOperatingPet() || IsRebuildingPet() || IsUsingItem() || + // GetShapeType() == PLAYERMODEL_DUMMYTYPE2 || IsPassiveMove()) + // bRet = false; + // break; + } - return bRet; -} -public int GetProfession() -{ - return m_iProfession; -} -public void SetSelectedTarget(int id) -{ - m_idSelTarget = id; -} -public bool glb_GetForceAttackFlag(uint pdwParam) -{ + return bRet; + } + public int GetProfession() + { + return m_iProfession; + } + public void SetSelectedTarget(int id) + { + m_idSelTarget = id; + } + public bool glb_GetForceAttackFlag(uint pdwParam) + { - /*bool bForceAttack = false; - CECInputCtrl* pInputCtrl = g_pGame->GetGameRun()->GetInputCtrl(); + /*bool bForceAttack = false; + CECInputCtrl* pInputCtrl = g_pGame->GetGameRun()->GetInputCtrl(); - if (pdwParam) - bForceAttack = pInputCtrl->IsCtrlPressed(*pdwParam); - else - bForceAttack = pInputCtrl->KeyIsBeingPressed(VK_CONTROL); + if (pdwParam) + bForceAttack = pInputCtrl->IsCtrlPressed(*pdwParam); + else + bForceAttack = pInputCtrl->KeyIsBeingPressed(VK_CONTROL); - return bForceAttack;*/ - return true; -} -//public float GetSwimSpeedSev() -//{ -// float fSpeedSev = GetSwimSpeed(); -// while (true) -// { -// if (!IsUnderWater()) break; -// //CECWorld* pWorld = g_pGame.GetGameRun().GetWorld(); -// //if (!pWorld) break; - -// const A3DVECTOR3 vPos = GetPos(); -// float fTerrainHeight = pWorld.GetTerrainHeight(vPos); -// float fWaterHeight = pWorld.GetWaterHeight(vPos); -// if (fWaterHeight <= fTerrainHeight) break; - -// float fBorderLine = fWaterHeight - 2.0f; -// if (vPos.y <= fBorderLine) break; - -// // ·þÎñÆ÷¶Ë½«Ë®ÃæÒÔÏÂ2Ã×ÒÔÉÏ´¦ÀíΪ run_speed£¨ÓÐÎÊÌ⣩ -// // µ«Î´Ê¹ÓüÓËÙ¼¼ÄÜʱ swim_speed СÓÚ run_speed£¬ -// // ¿ÉÒÔÔÚË®ÃæÒÔÏÂ2Ã×ÒÔÉÏ»ñÈ¡³¬¹ý swim_speed µÄËÙ¶È£¬Òò´Ë£¬´Ë´¦È¡Á½Õß½ÏСֵΪºÏÀí×ö·¨ -// fSpeedSev = min(m_ExtProps.mv.run_speed, fSpeedSev); -// break; -// } -// return fSpeedSev; -//} - -private void OnMsgHstNPCGreeting(ECMSG Msg) -{ - cmd_npc_greeting pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - - if (GPDataTypeHelper.ISNPCID(pCmd.idObject)) - { - // רÃÅ´¦Àíѧϰ¼¼ÄܵÄÒþ²ØNPC - //if (CECHostSkillModel::Instance().IsSkillLearnNPC(pCmd.idObject)) + return bForceAttack;*/ + return true; + } + //public float GetSwimSpeedSev() //{ - // CECGameUIMan* pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); - // //m_idSevNPC = pCmd.idObject; - // //m_bTalkWithNPC = true; - // //pGameUI.GetDialog("Win_SkillAction").Show(true); - // //CDlgSkillAction* dlg = dynamic_cast(pGameUI.GetDialog("Win_SkillAction")); - // //dlg.ForceShowDialog(); - // CDlgSkillAction* dlg = dynamic_cast(pGameUI.GetDialog("Win_SkillAction")); - // dlg.SetReceivedNPCGreeting(true); - // return; + // float fSpeedSev = GetSwimSpeed(); + // while (true) + // { + // if (!IsUnderWater()) break; + // //CECWorld* pWorld = g_pGame.GetGameRun().GetWorld(); + // //if (!pWorld) break; + + // const A3DVECTOR3 vPos = GetPos(); + // float fTerrainHeight = pWorld.GetTerrainHeight(vPos); + // float fWaterHeight = pWorld.GetWaterHeight(vPos); + // if (fWaterHeight <= fTerrainHeight) break; + + // float fBorderLine = fWaterHeight - 2.0f; + // if (vPos.y <= fBorderLine) break; + + // // ·þÎñÆ÷¶Ë½«Ë®ÃæÒÔÏÂ2Ã×ÒÔÉÏ´¦ÀíΪ run_speed£¨ÓÐÎÊÌ⣩ + // // µ«Î´Ê¹ÓüÓËÙ¼¼ÄÜʱ swim_speed СÓÚ run_speed£¬ + // // ¿ÉÒÔÔÚË®ÃæÒÔÏÂ2Ã×ÒÔÉÏ»ñÈ¡³¬¹ý swim_speed µÄËÙ¶È£¬Òò´Ë£¬´Ë´¦È¡Á½Õß½ÏСֵΪºÏÀí×ö·¨ + // fSpeedSev = min(m_ExtProps.mv.run_speed, fSpeedSev); + // break; + // } + // return fSpeedSev; //} - CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.idObject); - if (!pNPC || !pNPC.IsServerNPC()) + private void OnMsgHstNPCGreeting(ECMSG Msg) { - return; - } + cmd_npc_greeting pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - // Check distance again - if (!CanTouchTarget(pNPC.GetPos(), pNPC.GetTouchRadius(), 3)) - return; - - m_idSevNPC = pCmd.idObject; - m_bTalkWithNPC = true; - - // Check way point service on NPC - var dwID = (pNPC as CECNPCServer).GetWayPointID(); - if (dwID != null && !HasWayPoint(dwID)) - UnityGameSession.c2s_CmdNPCSevWaypoint(); - //g_pGame.GetGameSession().c2s_CmdNPCSevWaypoint(); - - var pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); - NPC_ESSENCE? result = (pNPC as CECNPCServer).GetDBEssence(); - if (result != null) - { - pGameUI.PopupNPCDialog(result.Value); - } - } - //else if (GPDataTypeHelper.ISPLAYERID(pCmd.idObject)) - //{ - // EC_ElsePlayer pPlayer = m_pPlayerMan.GetElsePlayer(pCmd.idObject); - - // // Check distance again - // if (!pPlayer || !CanTouchTarget(pPlayer.GetPos(), 0.0f, 3)) - // return; - - // m_idSevNPC = pCmd.idObject; - // m_bTalkWithNPC = true; - // m_iBoothState = 3; - - // g_pGame.GetGameSession().c2s_CmdNPCSevGetContent(GP_NPCSEV_BOOTHSELL); - - // m_pBuyPack.RemoveAllItems(); - // m_pSellPack.RemoveAllItems(); - // m_pEPBoothBPack.RemoveAllItems(); - // m_pEPBoothSPack.RemoveAllItems(); - - // CECGameUIMan* pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); - // pGameUI.PopupBoothDialog(true, false, pCmd.idObject); - //} - else - { - return; - } -} - -// Does host player have specified way point ? -bool HasWayPoint(uint? wID) -{ - if (wID == null) - { - return false; - } - for (int i = 0; i < m_aWayPoints.Count; i++) - { - if (m_aWayPoints[i] == wID) - return true; - } - - return false; -} - -void OnMsgHstWayPoint(ECMSG Msg) -{ - //CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); - - //if (Convert.ToInt32(Msg.dwParam2) == CommandID.ACTIVATE_WAYPOINT) - //{ - // cmd_activate_waypoint pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); - // m_aWayPoints.Add(pCmd.waypoint); - - // // add to waypoints array - // pGameUI.GetMapDlgsMgr().UpdateWayPoints(&pCmd.waypoint, 1, false); - - // // Print a notify message - // const CECMapDlgsMgr::PointMap& aWayPoints = pGameUI.GetMapDlgsMgr().GetTransPoint(); - // CECMapDlgsMgr::PointMap::const_iterator itr = aWayPoints.find(pCmd.waypoint); - // if(itr != aWayPoints.end()) - // { - // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_NEWWAYPOINT, (itr.second).strName); - - // bool bCanPopUITips = true; - // int count = CECUIConfig::Instance().GetGameUI().GetTaskIDDisableWayPointsUITipsCount(); - // // ¼ì²éÉíÉÏÊÇ·ñÓнûÖ¹µ¯³ötipsµÄÈÎÎñ - // for (int i=0;i serverTime) - bInWar = true; - } - return bInWar; -} - -public int GetCountry() { return m_idCountry; } - -// Get battle info. -//public BATTLEINFO GetBattleInfo() { return m_BattleInfo; } - -//public bool IsInCountryWar() { return IsInBattle() && GetBattleInfo().IsCountryWar(); } - -// End NPC service -public void EndNPCService() -{ - m_idSevNPC = 0; - m_bTalkWithNPC = false; - m_iBoothState = 0; - m_bIsInKingService = false; - //m_pOffShopCtrl.SetNPCSevFlag(COfflineShopCtrl::NPCSEV_NULL); -} - -void UpdateGFXs(float dwDeltaTime) -{ - // if (m_pLevelUpGFX) - // m_pLevelUpGFX->SetParentTM(GetAbsoluteTM()); - - if (m_pHoverGFX)// && m_idCurHover != m_idSelTarget) - { - if (!IsChangingFace() && (GPDataTypeHelper.ISPLAYERID(m_idCurHover) || GPDataTypeHelper.ISNPCID(m_idCurHover))) - { - CECObject pObject = EC_ManMessageMono.Instance?.GetObject(m_idCurHover, 1); - if (pObject) + if (GPDataTypeHelper.ISNPCID(pCmd.idObject)) { - if (m_pHoverGFX.GetState() == GFX_STATE.ST_STOP) + // רÃÅ´¦Àíѧϰ¼¼ÄܵÄÒþ²ØNPC + //if (CECHostSkillModel::Instance().IsSkillLearnNPC(pCmd.idObject)) + //{ + // CECGameUIMan* pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); + // //m_idSevNPC = pCmd.idObject; + // //m_bTalkWithNPC = true; + // //pGameUI.GetDialog("Win_SkillAction").Show(true); + // //CDlgSkillAction* dlg = dynamic_cast(pGameUI.GetDialog("Win_SkillAction")); + // //dlg.ForceShowDialog(); + // CDlgSkillAction* dlg = dynamic_cast(pGameUI.GetDialog("Win_SkillAction")); + // dlg.SetReceivedNPCGreeting(true); + // return; + //} + + CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.idObject); + if (!pNPC || !pNPC.IsServerNPC()) { - m_pHoverGFX.Play(); - m_pHoverGFX.transform.parent = pObject.transform; - m_pHoverGFX.transform.localPosition = Vector3.zero; + return; + } + + // Check distance again + if (!CanTouchTarget(pNPC.GetPos(), pNPC.GetTouchRadius(), 3)) + return; + + m_idSevNPC = pCmd.idObject; + m_bTalkWithNPC = true; + + // Check way point service on NPC + var dwID = (pNPC as CECNPCServer).GetWayPointID(); + if (dwID != null && !HasWayPoint(dwID)) + UnityGameSession.c2s_CmdNPCSevWaypoint(); + //g_pGame.GetGameSession().c2s_CmdNPCSevWaypoint(); + + var pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); + NPC_ESSENCE? result = (pNPC as CECNPCServer).GetDBEssence(); + if (result != null) + { + pGameUI.PopupNPCDialog(result.Value); } } - else - m_pHoverGFX.Stop(true); - } - else - m_pHoverGFX.Stop(true); - } + //else if (GPDataTypeHelper.ISPLAYERID(pCmd.idObject)) + //{ + // EC_ElsePlayer pPlayer = m_pPlayerMan.GetElsePlayer(pCmd.idObject); - if (m_pSelectedGFX) - { - if (!IsChangingFace() && (GPDataTypeHelper.ISPLAYERID(m_idSelTarget) || GPDataTypeHelper.ISNPCID(m_idSelTarget))) - { - var pObject = EC_ManMessageMono.Instance?.GetObject(m_idSelTarget, 1); - if (pObject) + // // Check distance again + // if (!pPlayer || !CanTouchTarget(pPlayer.GetPos(), 0.0f, 3)) + // return; + + // m_idSevNPC = pCmd.idObject; + // m_bTalkWithNPC = true; + // m_iBoothState = 3; + + // g_pGame.GetGameSession().c2s_CmdNPCSevGetContent(GP_NPCSEV_BOOTHSELL); + + // m_pBuyPack.RemoveAllItems(); + // m_pSellPack.RemoveAllItems(); + // m_pEPBoothBPack.RemoveAllItems(); + // m_pEPBoothSPack.RemoveAllItems(); + + // CECGameUIMan* pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); + // pGameUI.PopupBoothDialog(true, false, pCmd.idObject); + //} + else { - if (m_pSelectedGFX.GetState() == GFX_STATE.ST_STOP) - { - m_pSelectedGFX.Play(); - m_pSelectedGFX.transform.parent = pObject.transform; - m_pSelectedGFX.transform.localPosition = Vector3.zero; - } + return; + } + } + + // Does host player have specified way point ? + bool HasWayPoint(uint? wID) + { + if (wID == null) + { + return false; + } + for (int i = 0; i < m_aWayPoints.Count; i++) + { + if (m_aWayPoints[i] == wID) + return true; + } + + return false; + } + + void OnMsgHstWayPoint(ECMSG Msg) + { + //CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); + + //if (Convert.ToInt32(Msg.dwParam2) == CommandID.ACTIVATE_WAYPOINT) + //{ + // cmd_activate_waypoint pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + // m_aWayPoints.Add(pCmd.waypoint); + + // // add to waypoints array + // pGameUI.GetMapDlgsMgr().UpdateWayPoints(&pCmd.waypoint, 1, false); + + // // Print a notify message + // const CECMapDlgsMgr::PointMap& aWayPoints = pGameUI.GetMapDlgsMgr().GetTransPoint(); + // CECMapDlgsMgr::PointMap::const_iterator itr = aWayPoints.find(pCmd.waypoint); + // if(itr != aWayPoints.end()) + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_NEWWAYPOINT, (itr.second).strName); + + // bool bCanPopUITips = true; + // int count = CECUIConfig::Instance().GetGameUI().GetTaskIDDisableWayPointsUITipsCount(); + // // ¼ì²éÉíÉÏÊÇ·ñÓнûÖ¹µ¯³ötipsµÄÈÎÎñ + // for (int i=0;iGetGameRun()->GetWorld()->GetTerrainWater(); - // - // if (pWater->IsUnderWater(m_CameraCoord.GetPos())) - // { - // if (m_pFloatDust->GetState() == ST_STOP) - // { - // m_pFloatDust->Start(true); - // m_pFloatDust->TickAnimation(2000); - // } - // - // m_pFloatDust->SetParentTM(GetAbsoluteTM()); - // } - // else if (m_pFloatDust->GetState() != ST_STOP) - // m_pFloatDust->Stop(); - // } - // UpdateMonsterSpiritGfx(dwDeltaTime); -} - -// Level up -public void LevelUp() -{ - // CECGameSession *pSession = g_pGame->GetGameSession(); - // - // m_BasicProps.iLevel++; - // g_pGame->GetGameRun()->AddFixedMessage(FIXMSG_LEVELUP, m_BasicProps.iLevel); - // - // // Get all extend properties - // pSession->c2s_CmdGetExtProps(); - - // if (m_pLevelUpGFX) - // m_pLevelUpGFX->Start(true); - PlayGfx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_LEVELUP), null, 1f, 1);//PLAYERMODEL_TYPEALL - - // // Popup notify bubble text - // BubbleText(BUBBLE_LEVELUP, 0); - // - // // Notify my friends that my level changed - // ACHAR szInfo[40]; - // a_sprintf(szInfo, _AL("L%d"), m_BasicProps.iLevel); - // - // for (int i=0; i < m_pFriendMan->GetGroupNum(); i++) - // { - // CECFriendMan::GROUP* pGroup = m_pFriendMan->GetGroupByIndex(i); - // for (int j=0; j < pGroup->aFriends.GetSize(); j++) - // { - // CECFriendMan::FRIEND* pFriend = pGroup->aFriends[j]; - // if (pFriend->IsGameOnline()) - // { - // pSession->SendPrivateChatData(pFriend->GetName(), - // szInfo, GNET::CHANNEL_USERINFO, pFriend->id); - // } - // } - // } - // - // if (GetBasicProps().iLevel==30) - // { - // CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); - // pGameUI->AddChatMessage(pGameUI->GetStringFromTable(9638), GP_CHAT_SYSTEM); - // } - // if (GetBasicProps().iLevel>31) - // { - // CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); - // ((CDlgOnlineAward*)pGameUI->GetDialog("Win_AddExp2"))->RestartWhenLevelup(); - // } -} - -// Estimate mouse cursor -private void EstimateCursor() -{ - m_cursorUpdateTimer += Time.deltaTime; - if (m_cursorUpdateTimer < CURSOR_UPDATE_INTERVAL) - return; - m_cursorUpdateTimer = 0f; - - // Early exit checks - if (IsChangingFace() || mainCam == null || m_cachedMouse == null) - { - m_idCurHover = 0; - return; - } - - // Get mouse position using cached device - Vector2 mousePosition = m_cachedMouse.position.ReadValue(); - - // Early exit if mouse hasn't moved significantly (2 pixel threshold) - if (Vector2.Distance(mousePosition, m_lastMousePosition) < 2f) - return; - - m_lastMousePosition = mousePosition; - m_idCurHover = 0; - - CursorType cursorType = CursorType.RES_CUR_NORMAL; - - // Check modifier keys using cached keyboard - bool isShiftPressed = m_cachedKeyboard != null && - (m_cachedKeyboard.leftShiftKey.isPressed || m_cachedKeyboard.rightShiftKey.isPressed); - - Ray ray = mainCam.ScreenPointToRay(mousePosition); - RaycastHit hit; - - // You can add a layer mask here to only raycast against specific layers - // LayerMask interactableMask = LayerMask.GetMask("NPC", "Player", "Item"); - // if (Physics.Raycast(ray, out hit, 100f, interactableMask)) - - if (Physics.Raycast(ray, out hit, 1000f)) // Reduced from 1000f to 100f for better performance - { - // Try to get CECObject component (cached lookup) - CECObject hitObject = hit.collider.GetComponent(); - - if (hitObject != null) - { - int idHitObject = CECObject.GetObjectID(hitObject); - - if (idHitObject != 0) { - bool bForceAttack = isShiftPressed; + pConfig = (FACTION_FORTRESS_CONFIG)ob; + } + return pConfig; + } - // Check object type and set appropriate cursor - if (GPDataTypeHelper.ISNPCID(idHitObject)) + public bool IsInFortressWar() + { + bool bInWar = false; + if (IsInFortress()) + { + int serverTime = EC_Game.GetServerGMTTime(); + if (m_fortressEnter.end_time > serverTime) + bInWar = true; + } + return bInWar; + } + + public int GetCountry() { return m_idCountry; } + + // Get battle info. + //public BATTLEINFO GetBattleInfo() { return m_BattleInfo; } + + //public bool IsInCountryWar() { return IsInBattle() && GetBattleInfo().IsCountryWar(); } + + // End NPC service + public void EndNPCService() + { + m_idSevNPC = 0; + m_bTalkWithNPC = false; + m_iBoothState = 0; + m_bIsInKingService = false; + //m_pOffShopCtrl.SetNPCSevFlag(COfflineShopCtrl::NPCSEV_NULL); + } + + void UpdateGFXs(float dwDeltaTime) + { + // if (m_pLevelUpGFX) + // m_pLevelUpGFX->SetParentTM(GetAbsoluteTM()); + + if (m_pHoverGFX)// && m_idCurHover != m_idSelTarget) + { + if (!IsChangingFace() && (GPDataTypeHelper.ISPLAYERID(m_idCurHover) || GPDataTypeHelper.ISNPCID(m_idCurHover))) { - // NPC handling - CECNPC pNPC = EC_ManMessageMono.Instance?._CECNPCMan?.GetNPC(idHitObject); - if (pNPC != null && !pNPC.IsDead()) + CECObject pObject = EC_ManMessageMono.Instance?.GetObject(m_idCurHover, 1); + if (pObject) { - m_idCurHover = idHitObject; - - if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1) + if (m_pHoverGFX.GetState() == GFX_STATE.ST_STOP) { - cursorType = CursorType.RES_CUR_ATTACK; + m_pHoverGFX.Play(); + m_pHoverGFX.transform.parent = pObject.transform; + m_pHoverGFX.transform.localPosition = Vector3.zero; } - else if (pNPC.IsServerNPC()) + } + else + m_pHoverGFX.Stop(true); + } + else + m_pHoverGFX.Stop(true); + } + + if (m_pSelectedGFX) + { + if (!IsChangingFace() && (GPDataTypeHelper.ISPLAYERID(m_idSelTarget) || GPDataTypeHelper.ISNPCID(m_idSelTarget))) + { + var pObject = EC_ManMessageMono.Instance?.GetObject(m_idSelTarget, 1); + if (pObject) + { + if (m_pSelectedGFX.GetState() == GFX_STATE.ST_STOP) { - if (!IsInBattle() || InSameBattleCamp(pNPC)) + m_pSelectedGFX.Play(); + m_pSelectedGFX.transform.parent = pObject.transform; + m_pSelectedGFX.transform.localPosition = Vector3.zero; + } + } + else + m_pSelectedGFX.Stop(true); + } + else + m_pSelectedGFX.Stop(true); + } + + // if (m_pFloatDust) + // { + // A3DTerrainWater* pWater = g_pGame->GetGameRun()->GetWorld()->GetTerrainWater(); + // + // if (pWater->IsUnderWater(m_CameraCoord.GetPos())) + // { + // if (m_pFloatDust->GetState() == ST_STOP) + // { + // m_pFloatDust->Start(true); + // m_pFloatDust->TickAnimation(2000); + // } + // + // m_pFloatDust->SetParentTM(GetAbsoluteTM()); + // } + // else if (m_pFloatDust->GetState() != ST_STOP) + // m_pFloatDust->Stop(); + // } + // UpdateMonsterSpiritGfx(dwDeltaTime); + } + + // Level up + public void LevelUp() + { + // CECGameSession *pSession = g_pGame->GetGameSession(); + // + // m_BasicProps.iLevel++; + // g_pGame->GetGameRun()->AddFixedMessage(FIXMSG_LEVELUP, m_BasicProps.iLevel); + // + // // Get all extend properties + // pSession->c2s_CmdGetExtProps(); + + // if (m_pLevelUpGFX) + // m_pLevelUpGFX->Start(true); + PlayGfx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_LEVELUP), null, 1f, 1);//PLAYERMODEL_TYPEALL + + // // Popup notify bubble text + // BubbleText(BUBBLE_LEVELUP, 0); + // + // // Notify my friends that my level changed + // ACHAR szInfo[40]; + // a_sprintf(szInfo, _AL("L%d"), m_BasicProps.iLevel); + // + // for (int i=0; i < m_pFriendMan->GetGroupNum(); i++) + // { + // CECFriendMan::GROUP* pGroup = m_pFriendMan->GetGroupByIndex(i); + // for (int j=0; j < pGroup->aFriends.GetSize(); j++) + // { + // CECFriendMan::FRIEND* pFriend = pGroup->aFriends[j]; + // if (pFriend->IsGameOnline()) + // { + // pSession->SendPrivateChatData(pFriend->GetName(), + // szInfo, GNET::CHANNEL_USERINFO, pFriend->id); + // } + // } + // } + // + // if (GetBasicProps().iLevel==30) + // { + // CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); + // pGameUI->AddChatMessage(pGameUI->GetStringFromTable(9638), GP_CHAT_SYSTEM); + // } + // if (GetBasicProps().iLevel>31) + // { + // CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); + // ((CDlgOnlineAward*)pGameUI->GetDialog("Win_AddExp2"))->RestartWhenLevelup(); + // } + } + + // Estimate mouse cursor + private void EstimateCursor() + { + m_cursorUpdateTimer += Time.deltaTime; + if (m_cursorUpdateTimer < CURSOR_UPDATE_INTERVAL) + return; + m_cursorUpdateTimer = 0f; + + // Early exit checks + if (IsChangingFace() || mainCam == null || m_cachedMouse == null) + { + m_idCurHover = 0; + return; + } + + // Get mouse position using cached device + Vector2 mousePosition = m_cachedMouse.position.ReadValue(); + + // Early exit if mouse hasn't moved significantly (2 pixel threshold) + if (Vector2.Distance(mousePosition, m_lastMousePosition) < 2f) + return; + + m_lastMousePosition = mousePosition; + m_idCurHover = 0; + + CursorType cursorType = CursorType.RES_CUR_NORMAL; + + // Check modifier keys using cached keyboard + bool isShiftPressed = m_cachedKeyboard != null && + (m_cachedKeyboard.leftShiftKey.isPressed || m_cachedKeyboard.rightShiftKey.isPressed); + + Ray ray = mainCam.ScreenPointToRay(mousePosition); + RaycastHit hit; + + // You can add a layer mask here to only raycast against specific layers + // LayerMask interactableMask = LayerMask.GetMask("NPC", "Player", "Item"); + // if (Physics.Raycast(ray, out hit, 100f, interactableMask)) + + if (Physics.Raycast(ray, out hit, 1000f)) // Reduced from 1000f to 100f for better performance + { + // Try to get CECObject component (cached lookup) + CECObject hitObject = hit.collider.GetComponent(); + + if (hitObject != null) + { + int idHitObject = CECObject.GetObjectID(hitObject); + + if (idHitObject != 0) + { + bool bForceAttack = isShiftPressed; + + // Check object type and set appropriate cursor + if (GPDataTypeHelper.ISNPCID(idHitObject)) + { + // NPC handling + CECNPC pNPC = EC_ManMessageMono.Instance?._CECNPCMan?.GetNPC(idHitObject); + if (pNPC != null && !pNPC.IsDead()) { - cursorType = CursorType.RES_CUR_TALK; + m_idCurHover = idHitObject; + + if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1) + { + cursorType = CursorType.RES_CUR_ATTACK; + } + else if (pNPC.IsServerNPC()) + { + if (!IsInBattle() || InSameBattleCamp(pNPC)) + { + cursorType = CursorType.RES_CUR_TALK; + } + } } } - } - } - else if (GPDataTypeHelper.ISPLAYERID(idHitObject)) - { - // Player handling - EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance?.GetECManPlayer?.GetPlayer(idHitObject) as EC_ElsePlayer; - if (pPlayer != null) - { - m_idCurHover = idHitObject; - - if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1) + else if (GPDataTypeHelper.ISPLAYERID(idHitObject)) { - cursorType = CursorType.RES_CUR_ATTACK; + // Player handling + EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance?.GetECManPlayer?.GetPlayer(idHitObject) as EC_ElsePlayer; + if (pPlayer != null) + { + m_idCurHover = idHitObject; + + if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1) + { + cursorType = CursorType.RES_CUR_ATTACK; + } + } + } + else if (GPDataTypeHelper.ISMATTERID(idHitObject)) + { + //todo + // BMLogger.LogError($"[EstimateCursor]- GPDataTypeHelper.ISMATTERID: {idHitObject}"); + // Matter/item handling (uncomment when CECMatter is implemented) + // CECMatter pMatter = GetMatterManager()?.GetMatter(idHitObject); + // if (pMatter != null) + // { + // if (!pMatter.IsMine()) + // cursorType = CursorType.Pickup; + // else if (CanGatherMatter(pMatter)) + // cursorType = pMatter.IsMonsterSpiritMine() ? CursorType.Swallow : CursorType.Dig; + // + // if (cursorType != CursorType.Normal) + // m_idCurHover = idHitObject; + // } } } } - else if (GPDataTypeHelper.ISMATTERID(idHitObject)) - { - //todo - // BMLogger.LogError($"[EstimateCursor]- GPDataTypeHelper.ISMATTERID: {idHitObject}"); - // Matter/item handling (uncomment when CECMatter is implemented) - // CECMatter pMatter = GetMatterManager()?.GetMatter(idHitObject); - // if (pMatter != null) - // { - // if (!pMatter.IsMine()) - // cursorType = CursorType.Pickup; - // else if (CanGatherMatter(pMatter)) - // cursorType = pMatter.IsMonsterSpiritMine() ? CursorType.Swallow : CursorType.Dig; - // - // if (cursorType != CursorType.Normal) - // m_idCurHover = idHitObject; - // } - } } + + // Apply cursor change + EC_Game.ChangeCursor((int)cursorType); + } + + // Start normal attacking to selected target + private bool CmdNormalAttack(bool bMoreClose/* false */, bool bCombo/* false */, + int idTarget/* 0 */, int iForceAtk/* -1 */) + { + // StackChecker::ACTrace(2); + + // first of all see if we need to cancel sitdown work. + // if (m_pWorkMan.IsSitting()) + // { + // g_pGame->GetGameSession()->c2s_CmdStandUp(); + // return false; + // } + + if (!CanDo(ActionCanDo.CANDO_MELEE)) + return false; + + // if (InSlidingState()) + // return false; + + // if (!bCombo) + // ClearComboSkill(); + + if (idTarget <= 0) + idTarget = m_idSelTarget; + + bool bForceAttack; + if (iForceAtk < 0) + bForceAttack = glb_GetForceAttackFlag(0); + else + bForceAttack = iForceAtk > 0 ? true : false; + + if (AttackableJudge(idTarget, bForceAttack) != 1) + return false; + + return NormalAttackObject(idTarget, bForceAttack, bMoreClose); } } - // Apply cursor change - EC_Game.ChangeCursor((int)cursorType); -} - -// Start normal attacking to selected target -private bool CmdNormalAttack(bool bMoreClose/* false */, bool bCombo/* false */, - int idTarget/* 0 */, int iForceAtk/* -1 */) -{ - // StackChecker::ACTrace(2); - - // first of all see if we need to cancel sitdown work. - // if (m_pWorkMan.IsSitting()) - // { - // g_pGame->GetGameSession()->c2s_CmdStandUp(); - // return false; - // } - - if (!CanDo(ActionCanDo.CANDO_MELEE)) - return false; - - // if (InSlidingState()) - // return false; - - // if (!bCombo) - // ClearComboSkill(); - - if (idTarget <= 0) - idTarget = m_idSelTarget; - - bool bForceAttack; - if (iForceAtk < 0) - bForceAttack = glb_GetForceAttackFlag(0); - else - bForceAttack = iForceAtk > 0 ? true : false; - - if (AttackableJudge(idTarget, bForceAttack) != 1) - return false; - - return NormalAttackObject(idTarget, bForceAttack, bMoreClose); -} -} - public enum StateAnim -{ - Idle = 1, - Walk = 2, - Run = 3, - Jump = 4 -} - -// Mask of some special extend states which will influence host game logic. -// Logic Influence Extned states -[Flags] -public enum Logic_Influence_Extned_states -{ - LIES_SLEEP = 0x0001, - LIES_STUN = 0x0002, - LIES_ROOT = 0x0004, - LIES_NOFGIHT = 0x0008, - - LIES_DISABLEFIGHT = 0x000B, -} - -// ½øÈë»ùµØÐÅÏ¢ -public struct FACTION_FORTRESS_ENTER -{ - public int faction_id; - public int role_in_war; // 0 : ÖÐÁ¢»ò²»ÔÚ»ùµØ 1:¹¥·½ 2: ÊØ·½ - public int end_time; - - public FACTION_FORTRESS_ENTER(int faction_id, int role_in_war, int end_time) { - this.faction_id = faction_id; - this.role_in_war = role_in_war; - this.end_time = end_time; + Idle = 1, + Walk = 2, + Run = 3, + Jump = 4 } -} -public struct EXPToUpLevel -{ - public int NeededExp; - public EXPToUpLevel(int neededExp) + // Mask of some special extend states which will influence host game logic. + // Logic Influence Extned states + [Flags] + public enum Logic_Influence_Extned_states { - NeededExp = neededExp; - } -} -public struct NPCINFO -{ - public string Name; // Movement properties - public int CurrentHealth; - public int MaxHealth; // Attacking properties - public int IDNPC; // Attacking properties + LIES_SLEEP = 0x0001, + LIES_STUN = 0x0002, + LIES_ROOT = 0x0004, + LIES_NOFGIHT = 0x0008, - public NPCINFO(string name, int currentHealth, int maxHealth, int idnpc) + LIES_DISABLEFIGHT = 0x000B, + } + + // ½øÈë»ùµØÐÅÏ¢ + public struct FACTION_FORTRESS_ENTER { - Name = name; - CurrentHealth = currentHealth; - MaxHealth = maxHealth; - IDNPC = idnpc; + public int faction_id; + public int role_in_war; // 0 : ÖÐÁ¢»ò²»ÔÚ»ùµØ 1:¹¥·½ 2: ÊØ·½ + public int end_time; + + public FACTION_FORTRESS_ENTER(int faction_id, int role_in_war, int end_time) + { + this.faction_id = faction_id; + this.role_in_war = role_in_war; + this.end_time = end_time; + } } -}; -// PVP infomation -public struct PVPINFO -{ - public bool bEnable; // PVP switch - public uint dwCoolTime; - public uint dwMaxCoolTime; - public bool bFreePVP; // Free PVP flag, ignore bEnable flag - public bool bInPVPCombat; // true, in PVP combat - public int iDuelState; // Duel state - public int idDuelOpp; // Duel opponent - public int iDuelTimeCnt; // Duel time counter - public int iDuelRlt; // Duel result. 0, no defined; 1-win; 2-lose; 3-draw -}; - -// Current ground information -public struct GNDINFO -{ - public float fGndHei; // Ground height - public float fWaterHei; // Water height - public A3DVECTOR3 vGndNormal; // Terrain normal - public bool bOnGround; // On ground flag -}; -public struct InfoHostPlayer -{ - public string NameHostPlayer; - - public InfoHostPlayer(string name) + public struct EXPToUpLevel { - NameHostPlayer = name; + public int NeededExp; + public EXPToUpLevel(int neededExp) + { + NeededExp = neededExp; + } } -} -// Behavior id used by CanDo() -public static class ActionCanDo + public struct NPCINFO + { + public string Name; // Movement properties + public int CurrentHealth; + public int MaxHealth; // Attacking properties + public int IDNPC; // Attacking properties -{ - public const int CANDO_SITDOWN = 0, - CANDO_MOVETO = 1, - CANDO_MELEE = 2, - CANDO_ASSISTSEL = 3, - CANDO_FLY = 4, - CANDO_PICKUP = 5, - CANDO_TRADE = 6, - CANDO_PLAYPOSE = 7, - CANDO_SPELLMAGIC = 8, - CANDO_USEITEM = 9, - CANDO_JUMP = 10, - CANDO_FOLLOW = 11, - CANDO_GATHER = 12, - CANDO_BOOTH = 13, - CANDO_FLASHMOVE = 14, - CANDO_BINDBUDDY = 15, - CANDO_DUEL = 16, - CANDO_SUMMONPET = 17, - CANDO_CHANGESELECT = 18, - CANDO_REBUILDPET = 19, - CANDO_SWITCH_PARALLEL_WORLD = 20; -} + public NPCINFO(string name, int currentHealth, int maxHealth, int idnpc) + { + Name = name; + CurrentHealth = currentHealth; + MaxHealth = maxHealth; + IDNPC = idnpc; + } + }; + + // PVP infomation + public struct PVPINFO + { + public bool bEnable; // PVP switch + public uint dwCoolTime; + public uint dwMaxCoolTime; + public bool bFreePVP; // Free PVP flag, ignore bEnable flag + public bool bInPVPCombat; // true, in PVP combat + public int iDuelState; // Duel state + public int idDuelOpp; // Duel opponent + public int iDuelTimeCnt; // Duel time counter + public int iDuelRlt; // Duel result. 0, no defined; 1-win; 2-lose; 3-draw + }; + + // Current ground information + public struct GNDINFO + { + public float fGndHei; // Ground height + public float fWaterHei; // Water height + public A3DVECTOR3 vGndNormal; // Terrain normal + public bool bOnGround; // On ground flag + }; + public struct InfoHostPlayer + { + public string NameHostPlayer; + + public InfoHostPlayer(string name) + { + NameHostPlayer = name; + } + } + // Behavior id used by CanDo() + public static class ActionCanDo + + { + public const int CANDO_SITDOWN = 0, + CANDO_MOVETO = 1, + CANDO_MELEE = 2, + CANDO_ASSISTSEL = 3, + CANDO_FLY = 4, + CANDO_PICKUP = 5, + CANDO_TRADE = 6, + CANDO_PLAYPOSE = 7, + CANDO_SPELLMAGIC = 8, + CANDO_USEITEM = 9, + CANDO_JUMP = 10, + CANDO_FOLLOW = 11, + CANDO_GATHER = 12, + CANDO_BOOTH = 13, + CANDO_FLASHMOVE = 14, + CANDO_BINDBUDDY = 15, + CANDO_DUEL = 16, + CANDO_SUMMONPET = 17, + CANDO_CHANGESELECT = 18, + CANDO_REBUILDPET = 19, + CANDO_SWITCH_PARALLEL_WORLD = 20; + } } \ No newline at end of file