#pragma once #include #include "Character.h" #include "AIParamParser.h" #include "MovingPlanner.h" // È­ÀÏÀ̸§ ¹Ù²ã¾ß ÇÑ´Ù. -_-; //================================================================================================== // // TargetFinder // //================================================================================================== // @history // - ~~~~~ // - 09/12/13|waverix|add skip tile filter for _NA001415_091123_CHANGE_MOB_AI_IN_SAFETY_AREA_ //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // // - ƯÁ¤ »óÅÂÀÇ Ä³¸¯Å͸¦ ã´Â´Ù. //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER struct TargetFinderArg { Character* owner_; eTARGET_SEARCH_TYPE search_type_; eSKILL_TARGET_TYPE target_type_; REGENID unitID_; DWORD mapobjectID_; MONSTERCODE npc_code_; }; class TargetFinder { public: TargetFinder() : m_pOwner( 0 ) , m_pTarget( 0 ) , m_eTargetType( SKILL_TARGET_NONE ) , m_SkipTileAttr(0) , m_fOwnerSight( .0f ) , m_fOwnerSightX2( .0f ) , m_fBetweenOwnerWithTargetX2( .0f ) {} virtual ~TargetFinder() { } public: //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER TargetFinder(const TargetFinderArg& arg) : m_pOwner( 0 ) , m_pTarget( 0 ) , m_eTargetType( SKILL_TARGET_NONE ) , m_SkipTileAttr(0) , m_fOwnerSight( .0f ) , m_fOwnerSightX2( .0f ) , m_fBetweenOwnerWithTargetX2( .0f ) { SetFinder(arg); } virtual void SetFinder(const TargetFinderArg& finder_arg ) { ASSERT(finder_arg.owner_); m_pOwner = finder_arg.owner_; m_fOwnerSight = m_pOwner->GetSightRange(); m_fOwnerSightX2 = m_fOwnerSight*m_fOwnerSight; m_vOwnerPos = *m_pOwner->GetPosPtr(); m_eTargetType = finder_arg.target_type_; switch(m_eTargetType) { case SKILL_TARGET_ENEMY: case SKILL_TARGET_REACHABLE_ENEMY: case SKILL_TARGET_ENEMY_PLAYER: case SKILL_TARGET_ENEMY_CORPSE: case SKILL_TARGET_AREA_ENEMY_CORPSE: m_SkipTileAttr = PTA_SAFETY_ZONE; break; default: break; } } // Result inline Character* GetTarget() { return m_pTarget; } public: // virtual bool operator () ( Character* const pCharacter ) = 0; protected: bool CheckTarget( Character* const pTarget ) { if( !( pTarget && (m_pOwner != m_pTarget) ) ) return false; m_vTargetPos = *pTarget->GetPosPtr(); WzVector diff = m_vTargetPos; ; diff -= m_vOwnerPos; m_fBetweenOwnerWithTargetX2 = Math_Vector2DLength2(&diff); WORD skip_check_tile_attr_for_target = 0; if (pTarget->IsEqualObjectKind(MAPNPC_OBJECT)) { skip_check_tile_attr_for_target = PTA_NO_WALK; } if( !nsAI::PlanEventObject::AcceptableTarget(pTarget, m_SkipTileAttr, skip_check_tile_attr_for_target)) { return false; } if( !m_pOwner->IsCoincidentWithTargetType( pTarget, m_eTargetType ) ) return false; return true; } bool IsCheckTargetCasebyAlive( Character* const pTarget ) { if( !CheckTarget( pTarget ) ) return false; if( pTarget->IsDead() || (!pTarget->CanBeAttacked()) ) return false; return true; } protected: Character* m_pOwner; Character* m_pTarget; eSKILL_TARGET_TYPE m_eTargetType; // ã¾Æ¾ßÇÒ Å¸°Ù ŸÀÔ WORD m_SkipTileAttr;//_NA001415_091123_CHANGE_MOB_AI_IN_SAFETY_AREA_ #pragma warning(push) #pragma warning(disable : 4201) struct { // SetOwner È£Ãâ ÀÌÈÄ °è»êµÇ´Â °ª FLOAT m_fOwnerSight; // FLOAT m_fOwnerSightX2; // (OwnerSight*OwnerSight) }; struct { // CheckTarget È£Ãâ ÀÌÈÄ °è»êµÇ´Â °ª FLOAT m_fBetweenOwnerWithTargetX2; // µÑ »çÀÌÀÇ °Å¸® WzVector m_vOwnerPos; WzVector m_vTargetPos; }; #pragma warning(pop) }; //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // // class NearestTargetFinder : public TargetFinder { public: NearestTargetFinder() : m_TargetDistX2(999999.f) { } //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER NearestTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg), m_TargetDistX2(999999.f) {} public: virtual bool operator () ( Character* const pCharacter ) { if( !IsCheckTargetCasebyAlive( pCharacter ) ) return false; if( m_fBetweenOwnerWithTargetX2 >= m_TargetDistX2 ) return false; m_pTarget = pCharacter; m_TargetDistX2 = m_fBetweenOwnerWithTargetX2; return false; // continue À¯Áö ¸ñÀû? } protected: FLOAT m_TargetDistX2; }; //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // // class LowHPRatioTargetFinder : public TargetFinder { public: LowHPRatioTargetFinder() : m_LowHPRatio(ULONG_MAX) {} //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER LowHPRatioTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg), m_LowHPRatio(ULONG_MAX) {} public: virtual bool operator () ( Character* const pCharacter ) { if( !IsCheckTargetCasebyAlive( pCharacter ) ) return false; DWORD targetHP = pCharacter->GetMaxHP(); targetHP = targetHP ? targetHP : 1; const DWORD targetHPRatio = (DWORD)( pCharacter->GetHP() * 100 / targetHP ); if( targetHPRatio >= m_LowHPRatio ) return false; m_pTarget = pCharacter; m_LowHPRatio = targetHPRatio; // not found --> continue return false; // continue À¯Áö ¸ñÀû? } private : DWORD m_LowHPRatio; }; //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // // class LowHPTargetFinder : public TargetFinder { public: LowHPTargetFinder() : m_LowHP(ULONG_MAX) {} //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER LowHPTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg), m_LowHP(ULONG_MAX) {} public: virtual bool operator () ( Character* const pCharacter ) { if( !IsCheckTargetCasebyAlive( pCharacter ) ) return false; const DWORD targetHP = pCharacter->GetHP(); if( targetHP >= m_LowHP ) return false; m_pTarget = pCharacter; m_LowHP = targetHP; // not found --> continue return false; // continue À¯Áö ¸ñÀû? } private : DWORD m_LowHP; }; //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // // class LowLevelTargetFinder : public TargetFinder { public: LowLevelTargetFinder() : m_LowLevel(USHRT_MAX) {} //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER LowLevelTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg), m_LowLevel(USHRT_MAX) {} public : virtual bool operator () ( Character* const pCharacter ) { if( !IsCheckTargetCasebyAlive( pCharacter ) ) return false; const LEVELTYPE targetLevel = pCharacter->GetLevel(); if( targetLevel >= m_LowLevel ) return false; m_pTarget = pCharacter; m_LowLevel = targetLevel; // not found --> continue return false; // continue À¯Áö ¸ñÀû? } private : LEVELTYPE m_LowLevel; }; //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // // class HighMPTargetFinder : public TargetFinder { public: HighMPTargetFinder() : m_HighMP(0) {} //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER HighMPTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg), m_HighMP(0) {} public: virtual bool operator () ( Character* const pCharacter ) { if( !IsCheckTargetCasebyAlive( pCharacter ) ) return false; const DWORD targetMP = pCharacter->GetMP(); if( targetMP <= m_HighMP ) return false; m_pTarget = pCharacter; m_HighMP = targetMP; // not found --> continue return false; // continue À¯Áö ¸ñÀû? } private : DWORD m_HighMP; }; //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // // class DeadTargetFinder : public TargetFinder { public: DeadTargetFinder() {} //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER DeadTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg) {} public: virtual bool operator () ( Character* const pCharacter ) { if( !CheckTarget( pCharacter ) ) return false; if( pCharacter->IsAlive() ) return false; m_pTarget = pCharacter; return true; // °¡Àå Á×Àº...À̶ó´Â Àǹ̴ ¾øÀ¸¹Ç·Î ¹Ù·Î true } }; //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // ÇØ´ç regenID(¸ó½ºÅÍ) //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER class UnitIDTargetFinder : public TargetFinder { public: UnitIDTargetFinder() {} UnitIDTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg), unitID_(arg.unitID_) {} virtual bool operator () (Character* const pCharacter) { if (!IsCheckTargetCasebyAlive(pCharacter)) return false; if (pCharacter->IsEqualObjectKind(NPC_OBJECT) == FALSE) return false; NPC* const npc = static_cast(pCharacter); const REGENID unitID = npc->GetRegenID(); if (unitID == unitID_) { m_pTarget = pCharacter; return true; } return false; } protected: REGENID unitID_; }; class MapNpcObjectTargetFinder : public TargetFinder { public: MapNpcObjectTargetFinder() {} MapNpcObjectTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg), mapobjectID_(arg.mapobjectID_) {} virtual bool operator () (Character* const pCharacter) { if (!IsCheckTargetCasebyAlive(pCharacter)) return false; if (pCharacter->IsEqualObjectKind(MAPNPC_OBJECT) == FALSE) return false; MapNpc* const npc = static_cast(pCharacter); const DWORD mapobjectID = npc->GetMapObjectID(); if (mapobjectID == mapobjectID_) { m_pTarget = pCharacter; return true; } return false; } protected: DWORD mapobjectID_; }; class NearestMonsterCodeTargetFinder : public TargetFinder { public: NearestMonsterCodeTargetFinder() : target_distX2_(999999.f) {} NearestMonsterCodeTargetFinder(const TargetFinderArg& arg) : TargetFinder(arg), target_distX2_(999999.f), monster_code_(arg.npc_code_) {} virtual bool operator () (Character* const pCharacter) { if (!IsCheckTargetCasebyAlive(pCharacter)) return false; if (pCharacter->IsEqualObjectKind(NPC_OBJECT) == FALSE) return false; const NPC* const npc = static_cast(pCharacter); const BASE_NPCINFO* const base_info = npc->GetBaseInfo(); const MONSTERCODE monster_code = base_info->m_MonsterCode; if (monster_code == monster_code_) { if( m_fBetweenOwnerWithTargetX2 >= target_distX2_ ) return false; target_distX2_ = m_fBetweenOwnerWithTargetX2; m_pTarget = pCharacter; } return false; } protected: FLOAT target_distX2_; MONSTERCODE monster_code_; };