#pragma once #include "MAAiBase.h" #include "DnActor.h" #include "MAAiSkill.h" #include "MAAiChecker.h" #include "MAAiMultipleTarget.h" class MAAiCommand; class CMAAiProcessorManager; struct ActionTableCommon { ActionTableCommon():Type(Max) { } enum eType { Action = 0, Skill, Max, }; enum eCommon { MaxGlobalCoolTime = 5, }; eType Type; }; struct ActionTable : public ActionTableCommon { ActionTable() :nDistanceState(0),nIdx(0),nRate(0),nLoop(0),nCoolTime(0),nLastTime(0),nCancelLook(0),fApproach(100.0f),nMinAttackMissRadian(0),nMaxAttackMissRadian(0) ,fRandomTarget(0.f) #if defined (PRE_MOD_AIMULTITARGET) ,nMultipleTarget(0) ,nSummonerTarget(0) #else ,bMultipleTarget(false) #endif ,pMAAiCheckerManager(NULL) ,nLuaSkillIndex(-1) ,nBeHitSkillIndex(-1) ,iMaxMultipleTargetCount(0) ,bIsAnyMultipleTarget(false) ,bIsExceptCannonPlayer(false) #if !defined( PRE_FIX_68096 ) ,iGlobalCoolTimeIndex(-1) #endif #ifdef PRE_ADD_MONSTER_NORMAL_ACTION_PRIORITY ,nActionPriority(0) #endif { #if defined( PRE_FIX_68096 ) memset(iGlobalCoolTimeIndex, -1, sizeof(iGlobalCoolTimeIndex)); #endif } std::string szActionName; int nDistanceState; // DistanceState int nIdx; int nRate; int nLoop; int nCoolTime; int nCancelLook; // À̾׼ÇÀ» ÃëÇÒ¶§ Look À» Ç®°ÍÀÎÁö ¾Æ´ÑÁö 1À̸é Ǭ´Ù. LOCAL_TIME nLastTime; float fApproach; std::string szTargetCondition; // Ÿ°ÙÀÇ ÄÁµð¼Ç Å×À̺í int nMinAttackMissRadian; // °ø°Ý½Ã ¹Ì½ºTarget °¢µµ int nMaxAttackMissRadian; float fRandomTarget; #if defined (PRE_MOD_AIMULTITARGET) int nMultipleTarget; int nSummonerTarget; #else bool bMultipleTarget; #endif int iMaxMultipleTargetCount; bool bIsAnyMultipleTarget; bool bIsExceptCannonPlayer; CMAAiCheckerManager* pMAAiCheckerManager; int nLuaSkillIndex; int nBeHitSkillIndex; #if defined( PRE_FIX_68096 ) int iGlobalCoolTimeIndex[ActionTableCommon::eCommon::MaxGlobalCoolTime]; #else int iGlobalCoolTimeIndex; #endif #ifdef PRE_ADD_MONSTER_NORMAL_ACTION_PRIORITY int nActionPriority; #endif }; struct AISkillProcessor { int nSkillIndex; bool bActive; CMAAiProcessorManager* pMAAiProcessorManager; }; #if defined( PRE_ADD_LOTUSGOLEM ) struct AIPartsProcessor { int iMinHP,iMaxHP; int iCheckSkillIndex; int iCheckBlowIndex; std::string strCheckActionName; std::vector vIgnorePartsIndex; std::vector vNoDamagePartsIndex; std::vector vActivePartsIndex; }; #endif // #if defined( PRE_ADD_LOTUSGOLEM ) struct AIAggroRange { int iSelfHPPercent; int iThreatRange; int iCognizanceGentleRange; int iCognizanceThreatRange; }; struct AIGlobalCoolTime { DWORD dwCoolTime; }; struct CustomAction { std::string szActionName; union { int nLoop; int nLuaSkillIndex; }; }; struct CustomActionTable { std::string szCustomActionName; std::vector m_ActionList; }; struct StateOperation { CDnActorState::ActorStateEnum nState; std::string szString; // for debug bool bNOT; bool Check(DnActorHandle hTarget) { switch( nState ) { case CDnActorState::Stay: { if ( bNOT ) return !(hTarget->IsStay()); else return (hTarget->IsStay()); } break; case CDnActorState::Move: { if ( bNOT ) return !(hTarget->IsMove()); else return (hTarget->IsMove()); } break; case CDnActorState::Attack: { if ( bNOT ) return !(hTarget->IsAttack()); else return (hTarget->IsAttack()); } break; case CDnActorState::Hit: { if ( bNOT ) return !(hTarget->IsHit()); else return (hTarget->IsHit()); } break; case CDnActorState::Air: { if ( bNOT ) return !(hTarget->IsAir()); else return (hTarget->IsAir()); } break; case CDnActorState::Down: { if ( bNOT ) return !(hTarget->IsDown()); else return (hTarget->IsDown()); } break; case CDnActorState::Stun: { if ( bNOT ) return !(hTarget->IsStun()); else return (hTarget->IsStun()); } break; case CDnActorState::Stiff: { if ( bNOT ) return !(hTarget->IsStiff()); else return (hTarget->IsStiff()); } break; } return false; } }; struct OrOperator { // ¿©±â¼± or ¿¬»êÇØ¼­ true ¸é true std::vector OrOperatorArray; bool Check(DnActorHandle hTarget) { for ( size_t i = 0 ; i < OrOperatorArray.size() ; i++ ) { if ( OrOperatorArray[i].Check(hTarget) ) return true; } return false; } }; struct StateCondition { // À̰ÍÀº and ¿¬»êÀϰæ¿ì ¸¸ true std::vector AndOperatorArray; bool Check(DnActorHandle hTarget) { for ( size_t i = 0 ; i < AndOperatorArray.size() ; i++ ) { if ( AndOperatorArray[i].Check(hTarget) == false ) return false; } return true; } }; struct AI_TABLE { std::vector VecActionTable; float fNearValue; float fNearValueSq; int nRateSum; }; struct AI_SETPARTSREBIRTH_TABLE { std::vector vPartsTableID; UINT uiRebirthTick; }; struct ScriptData { public: ScriptData() { m_Type = 0; m_nNearTableCnt = 0; m_nPatrolBaseTime = 0; m_nPatrolRandTime = 0; m_fApproachValue = 0; m_nAssaultTime = 0; m_nCurrentCustomActionPlayIndex = 0; m_nMinAttackMissRadian = 0; m_nMaxAttackMissRadian = 0; #if defined( PRE_ADD_LOTUSGOLEM ) m_iOnlyPartsDamage = 0; #endif // #if defined( PRE_ADD_LOTUSGOLEM ) } enum eTypeBit { None = 0, NoAggroOwnerFollow = 1, // ¾î±×·Î ¾øÀ»¶§ ÁÖÀÎ(?) µû¶ó´ó±â´Â ŸÀÔ NoAggroStand = 2, // ¾î±×·Î ¾øÀ» ¶§ ÀÚ¸®¿¡ ¼­ÀÖÀ½ }; int m_Type; int m_nNearTableCnt; int m_nPatrolBaseTime; int m_nPatrolRandTime; float m_fApproachValue; int m_nAssaultTime; std::string m_szSettingFile; // ±âº» AI Å×À̺í std::vector m_AITable; // ÆÄÃ÷¸ó½ºÅÍ °ø¿ë ºÎȰ Å×À̺í std::vector m_vSetPartsRebirthTable; std::map m_CustomActionMap; CustomActionTable m_CurrentCustomActionTable; int m_nCurrentCustomActionPlayIndex; // Miss Radian int m_nMinAttackMissRadian; int m_nMaxAttackMissRadian; // ´Ù¿î¾ÈµÇ´Â µ¥¹ÌÁö¸¦ ÀÔ¾úÀ»¶§ »ç¿ëµÉ Å×À̺í std::vector m_NonDownMeleeDamageActionTable; std::vector m_NonDownRangeDamageActionTable; // ¹æ¾î½Ã »ç¿ëµÉ Å×À̺í std::vector m_MeleeDefenseActionTable; std::vector m_RangeDefenseActionTable; // Hit½Ã »ç¿ëµÉ Å×À̺í std::vector m_BeHitSkillActionTable; // µ¹ÁøÈÄ »ç¿ëµÉ Å×À̺í std::vector m_AssaultActionTable; // ½ºÅ³ Å×À̺í #if defined(PRE_ADD_64990) std::vector m_SkillTable[2]; #else std::vector m_SkillTable; #endif // PRE_ADD_64990 // »ó´ëŸÄÏ »óÅ üũ std::map m_StateContidionMap; // ½ºÅ³ Processor std::vector m_AISkillProcessorTable; std::vector m_AIAggroRange; std::vector m_AIGlobalCoolTime; #if defined( PRE_ADD_LOTUSGOLEM ) int m_iOnlyPartsDamage; std::vector m_AIPartsProcessor; #endif // #if defined( PRE_ADD_LOTUSGOLEM ) }; class AiScriptLoader { public: AiScriptLoader(); virtual ~AiScriptLoader(); bool AllLoadScript(); bool GetScript(const char* szFileName, OUT ScriptData& data); bool LoadScript(const char* szFileName); bool LoadActionTable(lua_tinker::table& t, int nIdx, OUT ActionTable& at); bool LoadTable( lua_State* pLua, const char* pTableName, std::vector& vActionTable ); bool LoadSkillProcessor( lua_State* pLua, std::vector& vSkillProcessor ); #if defined( PRE_ADD_LOTUSGOLEM ) bool LoadPartsProcessor( lua_State* pLua, ScriptData& data ); #endif // #if defined( PRE_ADD_LOTUSGOLEM ) bool LoadAggroRange( lua_State* pLua, std::vector& vAggroRange ); bool LoadGlobalCoolTime( lua_State* pLua, std::vector& vGlobalCoolTime ); bool LoadSetPartsRebirthTable( lua_State* pLua, ScriptData& data ); std::map m_ScriptMap; }; extern AiScriptLoader g_AiScriptLoader; class MAAiScript : public MAAiBase, public TBoostMemoryPool< MAAiScript > { public: enum ActionType { AT_Normal = 0, AT_Assault, AT_Defense, AT_Damage, AT_CustomAction, AT_UseSkill, AT_Patrol, }; enum TargetDirection { TD_LF = 0, TD_FL, TD_FR, TD_RF, TD_RB, TD_BR, TD_BL, TD_LB, TD_MAX, }; private: ActionType m_nState; LOCAL_TIME m_ChangeStateTime; ScriptData m_Data; MonsterSkillAI m_SkillAI; int m_nSeletedAssaultActionIndex; bool m_bValidAI; // Trigger °ü·Ã SOBB* m_pDestinationOBB; UINT m_uiMoveFrontRate; DWORD m_dwDestinationOBB; // Command °ü·Ã MAAiCommand* m_pAICommand; std::string m_strAILookAction; bool _FindCustomAction(const char* szCustomActionName, OUT CustomActionTable& table); void _CmdAction(const char* szAction, float fLength, int nLoop); void _CmdActionTable( const ActionTable* pTable, float fLength, int iLoop, ActionType State=AT_Normal ); void _CmdFinishProcessSkill( LOCAL_TIME time ); bool _bIsActorChecker( const ActionTable& AT ); bool _bIsTargetActorChecker( const ActionTable& AT ); bool _bDestinationProcess(); void _SelectRandomTarget( const int state, const float fRandomTarget ); #if defined( PRE_ADD_LOTUSGOLEM ) void _ProcessParts(); #endif // #if defined( PRE_ADD_LOTUSGOLEM ) public: CMAAiMultipleTarget m_cMultipleTarget; CDNCoolTime m_GlobalCoolTime; protected: virtual void _OnSetProjectileTarget(); public: MAAiScript( DnActorHandle hActor, MAAiReceiver *pReceiver ); virtual ~MAAiScript(); MonsterSkillAI* GetMonsterSkillAI(){ return &m_SkillAI; } void SetAIState( ActionType State ){ m_nState = State; } ActionType GetAIState(){ return m_nState; } virtual bool IsScript(){ return true; }; virtual void Process( LOCAL_TIME LocalTime, float fDelta ); virtual void OnChangeAction(const char* szPrevAction); virtual void OnFinishAction(const char* szPrevAction, LOCAL_TIME time); virtual void OnDie(); // Trigger °ü·Ã virtual void OnInitNaviDestination( SOBB* pOBB, UINT uiMoveFrontRate ); void OnAI(const char* szPrevAction, LOCAL_TIME time); int GetTargetDistanceState( DnActorHandle hTarget ); void GetTargetDistance( const int state, DNVector(DnActorHandle)& vTarget, bool bExceptAggroTarget=true ); void GetTargetDistance( const int iMin, const int iMax, DNVector(DnActorHandle)& vTarget, bool bExceptAggroTarget=true ); static bool bIsTargetDistance( DnActorHandle hActor, DnActorHandle hTarget, const int iMin, const int iMax ); void OnDistanceState(int state, float fLength, LOCAL_TIME time); int SelectAction_Random(std::vector& AtArray, LOCAL_TIME time); int SelectAction(std::vector& AtArray, LOCAL_TIME time); bool IsPassedCoolTime(ActionTable& at, LOCAL_TIME time); bool IsCheckedTargetCondition(ActionTable& at, DnActorHandle hTarget); void OnAssault(int state, float fLength, LOCAL_TIME time); void OnNormal(int state, float fLength, LOCAL_TIME time); void OnCustomAction(int state, float fLength, LOCAL_TIME time); void OnDefense(int state, float fLength, LOCAL_TIME time); void OnDamage(int state, float fLength, LOCAL_TIME time); void OnHitFinish( LOCAL_TIME LocalTime, HitStruct *pStruct ); void OnUseSkill(int state, float fLength, LOCAL_TIME time); void OnBeginNaviMode( const char* szPrevAction, const bool bPrevIsMove ); void AICmdMsgProc( const UINT uiMsg, void* pParam ); bool LoadScript(const char* szFilename); static void ReloadAllScript(); const ScriptData& GetScriptData(){ return m_Data; } #ifndef _FINAL_BUILD private: void OnTestNaviAI( LOCAL_TIME time ); void OnTestAttackAI( LOCAL_TIME time ); #endif };