From 4c51d6bf19604ea72268f50f87c09b01917b4f76 Mon Sep 17 00:00:00 2001 From: Tungdv Date: Tue, 27 Jan 2026 19:47:15 +0700 Subject: [PATCH] fix: update logic dlg pet. --- .../Scripts/Managers/EC_HPWork.cs | 5 + .../CSNetwork/C2SCommand/C2SCommand.cs | 6 + .../CSNetwork/C2SCommand/C2SCommandFactory.cs | 7 + .../Scripts/Network/CSNetwork/GPDataType.cs | 7 + .../Scripts/Network/CSNetwork/GameSession.cs | 37 ++ .../Scripts/Network/UnityGameSession.cs | 6 + .../Scripts/Players/CECActionContext.cs | 25 + .../Scripts/Players/CECActionSwitcherBase.cs | 183 +++++++ .../Scripts/UI/Dialogs/DlgPetList.cs | 2 +- Assets/Scripts/CECHostPlayer.cs | 452 +++++++++++++++++- 10 files changed, 723 insertions(+), 7 deletions(-) diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs index d96195517b..0f1d01b656 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs @@ -871,6 +871,11 @@ namespace BrewMonster.Scripts { return IsWorkRunning(Host_work_ID.WORK_FREEFALL); } + + public bool IsOperatingPet() + { + return IsWorkRunning(Host_work_ID.WORK_CONCENTRATE); + } } public abstract class CECHPWorkPostTickCommand { diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs index d44e949500..abc03226df 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs @@ -1570,6 +1570,12 @@ namespace CSNetwork.S2CCommand { public int faction_id; }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_summon_pet + { + public uint pet_index; + }; } // Player and NPC state \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs index 705cfde58e..1d89b265a1 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs @@ -874,5 +874,12 @@ namespace CSNetwork.C2SCommand pCmd.faction_id = faction_id; return SerializeCommand(CommandID.QUERY_MAFIA_PVP_INFO, pCmd); } + + public static Octets CreatePetSummon(int iPetIdx) + { + cmd_summon_pet pCmd = new cmd_summon_pet(); + pCmd.pet_index = (uint)iPetIdx; + return SerializeCommand(CommandID.SUMMON_PET, pCmd); + } } } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs index 45600ccafb..404a2efc5f 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs @@ -2304,5 +2304,12 @@ namespace CSNetwork.GPDataType public int plant_nid; public char reason; // 0 ËÀÍö£¬1 ÊÙÃüµ½£¬2 ³¬³ö·¶Î§£¬3 ×Ô±¬£¬4 ÊýÁ¿³¬³ö×éÉÏÏÞ }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_gain_pet + { + public int slot_index; // ´Ë³èÎï·ÅÓÚ³èÎïÀ¸ÄÚµÄλÖà + public info_pet data; // pet data + }; } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index 7a1c16de60..f777041aea 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -842,6 +842,36 @@ namespace CSNetwork BMLogger.LogError("### GameDataSend: LEARN_SKILL"); EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_LEARNSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); break; + case CommandID.GAIN_PET: + case CommandID.FREE_PET: + case CommandID.SUMMON_PET: + case CommandID.RECALL_PET: + case CommandID.PLAYER_START_PET_OP: + case CommandID.PLAYER_STOP_PET_OP: + case CommandID.PET_RECEIVE_EXP: + case CommandID.PET_LEVELUP: + case CommandID.PET_ROOM: + case CommandID.PET_ROOM_CAPACITY: + case CommandID.PET_HONOR_POINT: + case CommandID.PET_HUNGER_GAUGE: + case CommandID.PET_DEAD: + case CommandID.PET_REVIVE: + case CommandID.PET_HP_NOTIFY: + case CommandID.PET_AI_STATE: + case CommandID.PET_SET_COOLDOWN: + case CommandID.SUMMON_PLANT_PET: + case CommandID.PLANT_PET_DISAPPEAR: + case CommandID.PLANT_PET_HP_NOTIFY: + case CommandID.PET_PROPERTY: + case CommandID.PET_REBUILD_INHERIT_START: + case CommandID.PET_REBUILD_INHERIT_INFO: + case CommandID.PET_REBUILD_INHERIT_END: + case CommandID.PET_EVOLUTION_DONE: + case CommandID.PET_REBUILD_NATURE_START: + case CommandID.PET_REBUILD_NATURE_INFO: + case CommandID.PET_REBUILD_NATURE_END: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PETOPT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; default: #if UNITY_EDITOR if (isDebug) @@ -1522,5 +1552,12 @@ namespace CSNetwork { m_CmdCache.SendCmdPetCtrl(idTarget, cmd, (byte[])pParamBuf, iParamLen); } + + public void c2s_SendCmdPetSummon(int iPetIdx) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreatePetSummon(iPetIdx); + SendProtocol(gamedatasend); + } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs index 6d8600e7b6..a7b48a40b0 100644 --- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs @@ -446,5 +446,11 @@ namespace BrewMonster.Network { Instance._gameSession.SendCmdPetCtrl(idTarget, cmd, pParamBuf, iParamLen); } + + // Pet commands ... + public static void c2s_CmdPetSummon(int iPetIdx) + { + Instance._gameSession.c2s_SendCmdPetSummon(iPetIdx); + } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Players/CECActionContext.cs b/Assets/PerfectWorld/Scripts/Players/CECActionContext.cs index 7ea53badec..c85da656bb 100644 --- a/Assets/PerfectWorld/Scripts/Players/CECActionContext.cs +++ b/Assets/PerfectWorld/Scripts/Players/CECActionContext.cs @@ -1,3 +1,5 @@ +using BrewMonster.Assets.PerfectWorld.Scripts.Players; +using System.Collections.Generic; using UnityEngine; namespace BrewMonster @@ -14,10 +16,33 @@ namespace BrewMonster public class CECActionContext { public ActionContextType ContextType { get; set; } + public List m_actions; + CECHostPlayer m_pHostPlayer; + bool m_bForceRemove; + CECContextValidChecker m_ErrorCtr; public bool IsContext(ActionContextType contextType) { return ContextType == contextType; } + + public int GetActionCount() { return m_actions.Count; } + + public CECActionBase GetLastAction() + { + return GetAction(GetActionCount() - 1); + } + + public CECActionBase GetAction(int index) + { + if (index >= 0 && index < GetActionCount()) + return m_actions[index]; + else + return null; + } + + public virtual bool NeedCheckValid() { return false; } + public CECHostPlayer GetHostPlayer() { return m_pHostPlayer;} + public void SetForceRemove(bool v) { m_bForceRemove = v; } } } diff --git a/Assets/PerfectWorld/Scripts/Players/CECActionSwitcherBase.cs b/Assets/PerfectWorld/Scripts/Players/CECActionSwitcherBase.cs index 9c72e03750..1b270a0c84 100644 --- a/Assets/PerfectWorld/Scripts/Players/CECActionSwitcherBase.cs +++ b/Assets/PerfectWorld/Scripts/Players/CECActionSwitcherBase.cs @@ -6,6 +6,186 @@ using System.Threading.Tasks; namespace BrewMonster.Assets.PerfectWorld.Scripts.Players { + public abstract class CECActionBase + { + public enum ACTION_RESULT + { + FD_NONE = 0, + FD_SUCC, + FD_FAIL, + }; + + public CECHostPlayer m_pHostPlayer; + public ACTION_RESULT m_iFirstDoRes; + public CECActionSequencedRelationFilter m_ActionFilter; + + public CECActionBase(CECHostPlayer pHost) + { + m_pHostPlayer = pHost; + m_iFirstDoRes = (ACTION_RESULT.FD_NONE); + m_ActionFilter = null; + } + + public bool NeedBeRemoved() + { + return (m_iFirstDoRes != ACTION_RESULT.FD_NONE); + } + public CECActionSequencedRelationFilter GetActionFilter() { return m_ActionFilter; } + + public abstract bool CanDo(); + public abstract bool DoOnce(); + + public virtual bool Update(uint dt) + { + FlagKeeper keeper = new FlagKeeper(m_pHostPlayer.GetActionSwitcher()); + + // do once + if (CanDo() && m_iFirstDoRes == ACTION_RESULT.FD_NONE) + m_iFirstDoRes = DoOnce() ? ACTION_RESULT.FD_SUCC : ACTION_RESULT.FD_FAIL; + + return true; + } + public virtual bool CanAddTo(CECActionContext pContext) + { + return m_ActionFilter != null && m_ActionFilter.CanAddAction(pContext, this); + } + + }; + + public abstract class CECFitlerBase + { + public abstract bool CanAddAction(CECActionContext pContext, CECActionBase pAct); + } + + public abstract class CECActionSequencedRelationFilter : CECFitlerBase + { + public override bool CanAddAction(CECActionContext pContext, CECActionBase pAct) + { + // If the action queue is empty and the action can be executed, then add it. + if (pContext.GetActionCount() == 0 && pAct.CanDo()) + return true; + + // Determine the predecessor–successor order relationship of actions in the action queue. + CECActionBase pLastAct = pContext != null ? pContext.GetLastAction() : null; + CECActionSequencedRelationFilter filter = pLastAct != null ? pLastAct.GetActionFilter() : null; + if (filter != null && filter.IsPredecessorTo(pAct.GetActionFilter())) + return true; + + return false; + } + + public abstract bool IsPredecessorTo(CECActionSequencedRelationFilter cECActionSequencedRelationFilter); + + public virtual bool IsSuccessorTo(CECCancelRideActionFilter pFilter) { return false; } + public virtual bool IsSuccessorTo(CECRideActionFilter pFilter) { return false; } + public virtual bool IsSuccessorTo(CECLandingActionFilter pFilter) { return false; } + public virtual bool IsSuccessorTo(CECFlyActionFilter pFilter) { return false; } + public virtual bool IsSuccessorTo(CECSkillActionFilter pFilter) { return false; } + public virtual bool IsSuccessorTo(CECUseSkillItemActionFilter pFilter) { return false; } + }; + + public class FlagKeeper + { + public CECActionSwitcherBase m_pSwitcher; + public FlagKeeper(CECActionSwitcherBase pSwitcher) + { + m_pSwitcher = pSwitcher; + pSwitcher.SetPostMessageFlag(false); + } + }; + + public class CECCancelRideActionFilter : CECActionSequencedRelationFilter + { + public bool IsSuccessorTo(CECRideActionFilter filter ) { return true; } + + public override bool IsPredecessorTo(CECActionSequencedRelationFilter pFilter) + { + return pFilter.IsSuccessorTo(this); + } + }; + + public class CECRideActionFilter : CECActionSequencedRelationFilter + { + public virtual bool IsSuccessorTo(CECCancelRideActionFilter filter) { return true; } + public virtual bool IsSuccessorTo(CECLandingActionFilter filter ) { return true; } + + public override bool IsPredecessorTo(CECActionSequencedRelationFilter pFilter) + { + return pFilter.IsSuccessorTo(this); + } + }; + + public class CECLandingActionFilter : CECActionSequencedRelationFilter + { + public virtual bool IsSuccessorTo(CECFlyActionFilter filter) { return true; } + public override bool IsPredecessorTo(CECActionSequencedRelationFilter pFilter) + { + return pFilter.IsSuccessorTo(this); + } + }; + + public class CECFlyActionFilter : CECActionSequencedRelationFilter + { + public virtual bool IsSuccessorTo(CECCancelRideActionFilter pFilter) { return true; } + public virtual bool IsSuccessorTo(CECLandingActionFilter pFilter) { return true; } + public override bool IsPredecessorTo(CECActionSequencedRelationFilter pFilter) + { + return pFilter.IsSuccessorTo(this); + } + }; + + public class CECSkillActionFilter : CECActionSequencedRelationFilter + { + public virtual bool IsSuccessorTo(CECCancelRideActionFilter pFilter) { return true; } + public virtual bool IsSuccessorTo(CECLandingActionFilter pFilter) { return true; } + public virtual bool IsSuccessorTo(CECFlyActionFilter pFilter) { return true; } + public override bool IsPredecessorTo(CECActionSequencedRelationFilter pFilter) + { + return pFilter.IsSuccessorTo(this); + } + }; + + public class CECUseSkillItemActionFilter : CECActionSequencedRelationFilter + { + public virtual bool IsSuccessorTo(CECCancelRideActionFilter pFilter) { return true; } + public virtual bool IsSuccessorTo(CECLandingActionFilter pFilter) { return true; } + public virtual bool IsSuccessorTo(CECFlyActionFilter pFilter) { return true; } + public override bool IsPredecessorTo(CECActionSequencedRelationFilter pFilter) + { + return pFilter.IsSuccessorTo(this); + } + }; + + public class CECContextValidChecker + { + public CECContextValidChecker(CECActionContext context) + { + m_pActionContext = context; + error_correct = 0; + } + + public virtual void Update(uint dt) + { + //After the client sends mount or dismount commands, it immediately sends a movement message. + // As a result, the mount/ dismount operation on the server may fail, but the client is not notified. + // Therefore, a confirmation check is required here. + if (m_pActionContext.GetActionCount() != 0 && m_pActionContext.NeedCheckValid()) + { + error_correct += (int)dt; + + if (error_correct > MAX_ERRORTIME && !m_pActionContext.GetHostPlayer().GetWorkMan().IsOperatingPet()) + { + m_pActionContext.SetForceRemove(true); + error_correct = 0; + } + } + } + + public int error_correct; + public CECActionContext m_pActionContext; + public const int MAX_ERRORTIME = 3000; + }; + public class CECActionSwitcherBase { CECHostPlayer m_pHostPlayer; @@ -23,6 +203,9 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.Players if (CanAddMessage()) m_msgs.UniquelyAdd(msg); } + public void SetPostMessageFlag(bool bCan) { m_bCanAddMsg = bCan; } + + public virtual bool OnFlyToRideAction(int petIndex) { return false; } // fly -> ride } public enum EMsgActionSwitcher diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgPetList.cs b/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgPetList.cs index bcdbf7a9cd..eefa487128 100644 --- a/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgPetList.cs +++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgPetList.cs @@ -172,7 +172,7 @@ namespace BrewMonster.UI nSlot += m_nPageIndex* CDLGPETLIST_SLOT_MAX; // - - if (GetHostPlayer().GetActionSwitcher() && GetHostPlayer().GetActionSwitcher().OnFlyToRideAction(nSlot)) + if (GetHostPlayer().GetActionSwitcher() != null && GetHostPlayer().GetActionSwitcher().OnFlyToRideAction(nSlot)) return; GetHostPlayer().SummonPet(nSlot); diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index d0a4f406e0..c13f5c8a3b 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -22,7 +22,6 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; -using UnityEditor.Experimental.GraphView; using UnityEngine; using UnityEngine.UI; using static BrewMonster.Scripts.Managers.EC_Inventory; @@ -111,6 +110,8 @@ namespace BrewMonster Dictionary m_skillCoolTime = new Dictionary(); COOLTIME[] m_aCoolTimes = new COOLTIME[(int)CoolTimeIndex.GP_CT_MAX]; // Cool times CECPetCorral m_pPetCorral = null; + // תÉú´ÎÊý + byte m_ReincarnationCount = 0; // Host config data version const int HOSTCFG_VERSION = 11; @@ -587,6 +588,7 @@ namespace BrewMonster case int value when value == EC_MsgDef.MSG_HST_LEARNSKILL: OnMsgHstLearnSkill(Msg); break; case int value when value == EC_MsgDef.MSG_PM_PLAYERFLY: OnMsgPlayerFly(Msg); break; + case int value when value == EC_MsgDef.MSG_HST_PETOPT: OnMsgHstPetOpt(Msg); break; } @@ -4573,11 +4575,11 @@ namespace BrewMonster case ActionCanDo.CANDO_SUMMONPET: - 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()*/) + if (IsDead() || GPDataTypeHelper.ISMATTERID(m_idSelTarget) || IsAboutToDie() || IsSitting() || + IsJumping() || /*IsFlashMoving() ||*/ IsTrading() || IsUsingTrashBox() || IsTalkingWithNPC() || + IsChangingFace() || CannotAttack() || IsReviving() || GetBoothState() != 0 || + IsInvisible() /*|| IsGMInvisible()*/ || IsOperatingPet() != 0 || /*IsRebuildingPet() ||*/ IsUsingItem() || IsPassiveMove() + /*|| m_BattleInfo.IsChariotWar()*/) bRet = false; break; @@ -6911,5 +6913,443 @@ namespace BrewMonster } return 0; } + + bool IsPlayerMoving() + { + return m_pWorkMan.IsMoving(); + } + + // Stop host moving naturally, return true host stopped, otherwise return false + bool NaturallyStopMoving() + { + // if (!m_MoveCtrl.IsStop()) + if (!IsPlayerMoving()) + return true; // Host has been stopped + + if (m_iMoveMode == (int)Move_Mode.MOVE_FREEFALL || InSlidingState() || IsJumping()) + return false; // Host couldn't stop naturally + + if (!m_pWorkMan.IsStanding()) + { + m_pWorkMan.FinishAllWork(true); + } + + m_MoveCtrl.SendStopMoveCmd(); + + return true; + } + + // Summon pet + public bool SummonPet(int iPetIdx) + { + if (m_pActionSwitcher != null) + m_pActionSwitcher.PostMessge((int)EMsgActionSwitcher.MSG_MOUNTPET); + + CECGameRun pGameRun = EC_Game.GetGameRun(); + + CECPetData pPet = m_pPetCorral.GetPetData(iPetIdx); + if (pPet == null) + return false; + + if (!CanDo(ActionCanDo.CANDO_SUMMONPET)) + return false; + + // Couldn't summon daed pet + if (pPet.IsDead()) + { + //pGameRun.AddFixedMessage(FIXMSG_PET_DEAD); + Debug.LogError("FIXMSG_PET_DEAD"); + return false; + } + + // If host could't stop naturally, cancel summoning + if (!NaturallyStopMoving()) + return false; + + // ¼ì²éµ±Ç°ÊÇ·ñ½ûÖ¹ÕÙ»½Æï³è + if (pPet.IsMountPet() /*&& m_playerLimits.test(PLAYER_LIMIT_NOMOUNT)*/) + return false; + + if (m_ReincarnationCount != 0) + { + int iLevelRequired = pPet.GetLevel() - 35 - m_ReincarnationCount * 5; + if (m_BasicProps.iLevel < iLevelRequired) + { + CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); + if (pGameUI != null) + { + // TO DO: fix later + //string strText = ""; + //strText.Format(pGameUI.GetStringFromTable(10787), iLevelRequired); + //pGameUI.MessageBox("", strText, MB_OK, A3DCOLORRGBA(255, 255, 255, 160)); + } + return false; + } + } + + UnityGameSession.c2s_CmdPetSummon(iPetIdx); + + return true; + } + + void OnMsgHstPetOpt(ECMSG Msg) + { + + CECGameRun pGameRun = EC_Game.GetGameRun(); + + switch (Msg.dwParam2) + { + case CommandID.GAIN_PET: + { + cmd_gain_pet pCmd = (const cmd_gain_pet*)Msg.dwParam1; + m_pPetCorral.AddPet(pCmd.slot_index, pCmd.data); + + // Print a notify + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.slot_index); + if (pPet) + { + if (pPet.IsFollowPet() || pPet.IsCombatPet() || pPet.IsEvolutionPet()) + pGameRun.AddFixedMessage(FIXMSG_PET_HATCH, pPet.GetName()); + else if (pPet.IsSummonPet()) + pGameRun.AddFixedMessage(FIXMSG_SUMMON_PET_APPEAR, pPet.GetName()); + } + + break; + } + + case CommandID.FREE_PET: + { + const cmd_free_pet* pCmd = (const cmd_free_pet*)Msg.dwParam1; + + // Print a notify + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.slot_index); + if (pPet) + { + if (pPet.IsFollowPet() || pPet.IsCombatPet() || pPet.IsEvolutionPet()) + pGameRun.AddFixedMessage(FIXMSG_PET_FREE, pPet.GetName()); + else if (pPet.IsSummonPet()) + pGameRun.AddFixedMessage(FIXMSG_SUMMON_PET_DISAPPEAR, pPet.GetName()); + } + + // Remove pet from corral + m_pPetCorral.FreePet(pCmd.slot_index, pCmd.pet_id); + // Update pet shortcuts + UpdateFreedPetSC(pCmd.slot_index); + + break; + } + case CommandID.SUMMON_PET: + { + const cmd_summon_pet* pCmd = (const cmd_summon_pet*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.slot_index); + ASSERT(pPet && pPet.GetTemplateID() == pCmd.pet_tid); + m_pPetCorral.SetActivePetIndex(pCmd.slot_index); + m_pPetCorral.SetActivePetNPCID(pCmd.pet_pid); + m_pPetCorral.SetActivePetLifetime(pCmd.life_time); + + if (g_pGame.GetConfigs().GetGameSettings().bPetAutoSkill) + { + for (int i = 0; i < pPet.GetSkillNum(CECPetData::EM_SKILL_DEFAULT); i++) + { + const CECPetData::PETSKILL* pSkill = pPet.GetSkill(CECPetData::EM_SKILL_DEFAULT, i); + if (pSkill && g_pGame.IsPetAutoSkill(pSkill.idSkill)) + pPet.AddAutoSkill(pSkill.idSkill); + } + } + + OnPetSays(pCmd.pet_tid, pCmd.pet_pid, CECPetWords::TW_SUMMON); + if (pPet.IsCombatPet() || pPet.IsSummonPet() || pPet.IsEvolutionPet()) + CDlgQuickBarPet::ResetAutoCastSkill(); + break; + } + case CommandID.RECALL_PET: + { + const cmd_recall_pet* pCmd = (const cmd_recall_pet*)Msg.dwParam1; + ASSERT(pCmd.slot_index == m_pPetCorral.GetActivePetIndex()); + + int tid = pCmd.pet_id; + int nid = m_pPetCorral.GetActivePetNPCID(); + + // ³èÎïÓл°Ëµ + switch (pCmd.reason) + { + case PET_RECALL_DEFAULT: + OnPetSays(tid, nid, CECPetWords::TW_RECALL); + break; + + case PET_RECALL_DEATH: + OnPetSays(tid, nid, CECPetWords::TW_DEAD); + break; + + case PET_RECALL_LIFE_EXHAUST: + OnPetSays(tid, nid, CECPetWords::TW_DISAPPEAR); + break; + + case PET_RECALL_SACRIFICE: + OnPetSays(tid, nid, CECPetWords::TW_SACRIFICE); + break; + } + + CECPetData* pPet = m_pPetCorral.GetActivePet(); + if (pPet) + pPet.OnPetDead(); + + m_pPetCorral.SetActivePetIndex(-1); + m_pPetCorral.SetActivePetNPCID(0); + m_bPetInSanctuary = false; + break; + } + case CommandID.PLAYER_START_PET_OP: + { + const cmd_player_start_pet_op* pCmd = (const cmd_player_start_pet_op*)Msg.dwParam1; + int iDoWhat; + if (pCmd.op == 0) + iDoWhat = CECHPWorkConcentrate::DO_SUMMONPET; + else if (pCmd.op == 1) + iDoWhat = CECHPWorkConcentrate::DO_RECALLPET; + else if (pCmd.op == 2) + iDoWhat = CECHPWorkConcentrate::DO_BANISHPET; + else if (pCmd.op == 3) + iDoWhat = CECHPWorkConcentrate::DO_RESTOREPET; + else + iDoWhat = CECHPWorkConcentrate::DO_UNKNOWN; + + m_PetOptCnt.SetPeriod(pCmd.delay * 50); + m_PetOptCnt.Reset(); + + CECHPWorkConcentrate* pWork = (CECHPWorkConcentrate*)m_pWorkMan.CreateWork(CECHPWork::WORK_CONCENTRATE); + pWork.SetDoWhat(iDoWhat); + m_pWorkMan.StartWork_p1(pWork); + break; + } + case CommandID.PLAYER_STOP_PET_OP: + { + if (IsOperatingPet()) + m_pWorkMan.FinishRunningWork(CECHPWork::WORK_CONCENTRATE); + + break; + } + case CommandID.PET_RECEIVE_EXP: + { + const cmd_pet_receive_exp* pCmd = (const cmd_pet_receive_exp*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.slot_index); + if (pPet) + { + ASSERT(pPet.GetTemplateID() == pCmd.pet_id); + pPet.AddExp(pCmd.exp); + } + + break; + } + case CommandID.PET_LEVELUP: + { + const cmd_pet_levelup* pCmd = (const cmd_pet_levelup*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.slot_index); + if (pPet) + { + ASSERT(pPet.GetTemplateID() == pCmd.pet_id); + pPet.LevelUp(pCmd.level, pCmd.exp); + } + + pGameRun.AddFixedMessage(FIXMSG_PET_LEVELUP, pCmd.level); + break; + } + case CommandID.PET_ROOM: + { + const cmd_pet_room* pCmd = (const cmd_pet_room*)Msg.dwParam1; + m_pPetCorral.UpdatePets(*pCmd); + + CECGameUIMan* pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); + + if (pGameUI.GetDialog("Win_Teach").IsShow()) + pGameUI.UpdateTeach(); + + break; + } + case CommandID.PET_ROOM_CAPACITY: + { + const cmd_pet_room_capacity* pCmd = (const cmd_pet_room_capacity*)Msg.dwParam1; + m_pPetCorral.MagnifyPetSlots(pCmd.capacity); + + if (m_pPetCorral.HasInit()) + pGameRun.AddFixedMessage(FIXMSG_PET_ROOM_SIZE, pCmd.capacity); + else + m_pPetCorral.SetHasInit(true); + break; + } + case CommandID.PET_HONOR_POINT: + { + const cmd_pet_honor_point* pCmd = (const cmd_pet_honor_point*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.index); + if (pPet) + pPet.SetIntimacy(pCmd.cur_honor_point); + + break; + } + case CommandID.PET_HUNGER_GAUGE: + { + const cmd_pet_hunger_gauge* pCmd = (const cmd_pet_hunger_gauge*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.index); + if (pPet) + pPet.SetHunger(pCmd.cur_hunge_gauge); + + break; + } + case CommandID.PET_DEAD: + { + const cmd_pet_dead* pCmd = (const cmd_pet_dead*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.pet_index); + if (pPet) + { + pPet.SetHPFactor(0.0f); + pPet.SetHP(0); + pPet.OnPetDead(); + } + + pGameRun.AddFixedMessage(FIXMSG_PET_DEAD); + break; + } + case CommandID.PET_REVIVE: + { + const cmd_pet_revive* pCmd = (const cmd_pet_revive*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.pet_index); + if (pPet) + pPet.SetHPFactor(pCmd.hp_factor); + + break; + } + case CommandID.PET_HP_NOTIFY: + { + const cmd_pet_hp_notify* pCmd = (const cmd_pet_hp_notify*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.pet_index); + if (pPet) + { + int lastHP = pPet.GetHP(); + + pPet.SetHPFactor(pCmd.hp_factor); + pPet.SetHP(pCmd.cur_hp); + + pPet.SetMPFactor(pCmd.mp_factor); + pPet.SetMP(pCmd.cur_mp); + + // If HP is too low, popup a warning on pet's head + int iLimit = (int)(pPet.CalcMaxHP() * 0.3f); + if (pCmd.cur_hp < lastHP && lastHP && pCmd.cur_hp < iLimit) + { + CECNPC* pNPC = g_pGame.GetGameRun().GetWorld().GetNPCMan().GetNPC(m_pPetCorral.GetActivePetNPCID()); + if (pNPC && pNPC.GetMasterID() == GetCharacterID()) + pNPC.BubbleText(CECNPC::BUBBLE_HPWARN, 0); + } + } + + break; + } + case CommandID.PET_AI_STATE: + { + const cmd_pet_ai_state* pCmd = (const cmd_pet_ai_state*)Msg.dwParam1; + + // ³èÎïÓл°Ëµ + const CECPetData* pPetData = m_pPetCorral.GetActivePet(); + if (pPetData) + { + int tid = pPetData.GetTemplateID(); + int nid = m_pPetCorral.GetActivePetNPCID(); + if (m_pPetCorral.GetMoveMode() != pCmd.move) + { + switch (pCmd.move) + { + case CECPetCorral::MOVE_FOLLOW: + OnPetSays(tid, nid, CECPetWords::TW_FOLLOW); + break; + case CECPetCorral::MOVE_STAND: + OnPetSays(tid, nid, CECPetWords::TW_STOP); + break; + } + } + if (m_pPetCorral.GetAttackMode() != pCmd.attack) + { + switch (pCmd.attack) + { + case CECPetCorral::ATK_DEFENSE: + OnPetSays(tid, nid, CECPetWords::TW_DEFENSIVE); + break; + + case CECPetCorral::ATK_POSITIVE: + OnPetSays(tid, nid, CECPetWords::TW_OFFENSIVE); + break; + + case CECPetCorral::ATK_PASSIVE: + OnPetSays(tid, nid, CECPetWords::TW_PASSIVE); + break; + } + } + } + + m_pPetCorral.SetMoveMode(pCmd.move); + m_pPetCorral.SetAttackMode(pCmd.attack); + break; + } + case CommandID.PET_SET_COOLDOWN: + { + const cmd_pet_set_cooldown* pCmd = (const cmd_pet_set_cooldown*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.pet_index); + if (pPet) + pPet.SetSkillCoolTime(pCmd.cooldown_index, pCmd.cooldown_time); + + break; + } + + case CommandID.SUMMON_PLANT_PET: + { + const cmd_summon_plant_pet* pCmd = (const cmd_summon_plant_pet*)Msg.dwParam1; + if (pCmd) + m_pPetCorral.PlantPetEnter(*pCmd); + break; + } + + case CommandID.PLANT_PET_DISAPPEAR: + { + const cmd_plant_pet_disapper* pCmd = (const cmd_plant_pet_disapper*)Msg.dwParam1; + if (pCmd) + m_pPetCorral.PlantPetDisappear(*pCmd); + break; + } + + case CommandID.PLANT_PET_HP_NOTIFY: + { + const cmd_plant_pet_hp_notify* pCmd = (const cmd_plant_pet_hp_notify*)Msg.dwParam1; + if (pCmd) + m_pPetCorral.PlantPetInfo(*pCmd); + break; + } + + case CommandID.PET_PROPERTY: + { + const cmd_pet_property* pCmd = (const cmd_pet_property*)Msg.dwParam1; + CECPetData* pPet = m_pPetCorral.GetPetData(pCmd.pet_index); + if (pPet) + { + pPet.SetExtendProps(pCmd.prop); + } + break; + } + case CommandID.PET_REBUILD_INHERIT_START: + case CommandID.PET_REBUILD_INHERIT_INFO: + case CommandID.PET_REBUILD_INHERIT_END: + case CommandID.PET_EVOLUTION_DONE: + case CommandID.PET_REBUILD_NATURE_START: + case CommandID.PET_REBUILD_NATURE_INFO: + case CommandID.PET_REBUILD_NATURE_END: + { + CECGameUIMan* pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); + if (pGameUI) + ((CDlgPreviewPetRebuild*)pGameUI.GetDialog("Win_PreviewPet")).OnServerNotify(Msg.dwParam2, (void*)Msg.dwParam1); + break; + } + + default: + break; + } + } } }