888 lines
25 KiB
C++
888 lines
25 KiB
C++
|
|
#include "StdAfx.h"
|
|
#include "MAAiChecker.h"
|
|
#include "DnActor.h"
|
|
#include "MAAiScript.h"
|
|
#include "DnBlow.h"
|
|
#include "DNAggroSystem.h"
|
|
#include "DnMonsterActor.h"
|
|
#include "DnStateBlow.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
|
#endif
|
|
|
|
/*#####################################################################################################################
|
|
ActorChecker
|
|
#####################################################################################################################*/
|
|
|
|
|
|
// 무기검사
|
|
// 무기가 있으면 return true, 무기가 없으면 return false;
|
|
|
|
bool CMAAiActorWeaponChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor )
|
|
return false;
|
|
|
|
return hActor->GetWeapon(m_uiWeaponIndex) ? true : false;
|
|
}
|
|
|
|
// 부위파괴검사
|
|
// 해당부위 파괴 되었으면 return true; 아니면 return false;
|
|
bool CMAAiActorPartsDestroyChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor )
|
|
return false;
|
|
|
|
for( UINT i=0 ; i<m_vPartsTableID.size() ; ++i )
|
|
{
|
|
if( !hActor->bIsDestroyParts(m_vPartsTableID[i]) )
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// 부위존재검사
|
|
// 해당부위 존재하면 return true; 아니면 return false;
|
|
bool CMAAiActorPartsExistChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor )
|
|
return false;
|
|
|
|
for( UINT i=0 ; i<m_vPartsTableID.size() ; ++i )
|
|
{
|
|
if( hActor->bIsDestroyParts(m_vPartsTableID[i]) )
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Fly상태검사
|
|
bool CMAAiActorFlyStateChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
return (hActor->IsFly()&&!hActor->IsFly2());
|
|
}
|
|
|
|
bool CMAAiActorFly2StateChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
return hActor->IsFly2();
|
|
}
|
|
|
|
// Ground상태검사
|
|
bool CMAAiActorGroundStateChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
return hActor->IsGround();
|
|
}
|
|
|
|
// UnderGround상태검사
|
|
bool CMAAiActorUnderGroundStateChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
return hActor->IsUnderGround();
|
|
}
|
|
|
|
// HPPercent 검사
|
|
bool CMAAiActorHPPercentChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
return m_iHPPercent >= hActor->GetHPPercent();
|
|
}
|
|
|
|
// HPPercent Range검사(Min이상~Max이하)
|
|
bool CMAAiActorHPPercentCheckerRange::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
int iHPPercent = hActor->GetHPPercent();
|
|
return (iHPPercent >= m_iHPMinPercent && iHPPercent <= m_iHPMaxPercent);
|
|
}
|
|
|
|
// SP검사
|
|
bool CMAAiActorSPChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
return m_iSP <= hActor->GetSP();
|
|
}
|
|
|
|
// 현재 사용중인 스킬 체크
|
|
bool CMAAiActorUsedSkillChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor->GetStateBlow() ) return false;
|
|
|
|
std::vector<UINT> vCheckTableID = m_vSkillTableID;
|
|
|
|
for( int i=0 ; i<hActor->GetStateBlow()->GetNumStateBlow() ; ++i )
|
|
{
|
|
DnBlowHandle hBlow = hActor->GetStateBlow()->GetStateBlow(i);
|
|
if( !hBlow ) continue;
|
|
|
|
const CDnSkill::SkillInfo* pSkillinfo = hBlow->GetParentSkillInfo();
|
|
if ( pSkillinfo )
|
|
{
|
|
vCheckTableID.erase( remove( vCheckTableID.begin(), vCheckTableID.end(), pSkillinfo->iSkillID), vCheckTableID.end() );
|
|
if( vCheckTableID.empty() )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// 현재 사용중이지 않은 스킬 체크
|
|
bool CMAAiActorNotUsedSkillChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor->GetStateBlow() ) return true;
|
|
for( int i=0 ; i<hActor->GetStateBlow()->GetNumStateBlow() ; ++i )
|
|
{
|
|
DnBlowHandle hBlow = hActor->GetStateBlow()->GetStateBlow(i);
|
|
if( !hBlow ) continue;
|
|
|
|
const CDnSkill::SkillInfo* pSkillinfo = hBlow->GetParentSkillInfo();
|
|
if ( pSkillinfo )
|
|
{
|
|
if( std::find( m_vSkillTableID.begin(), m_vSkillTableID.end(), pSkillinfo->iSkillID ) != m_vSkillTableID.end() )
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// rate
|
|
bool CMAAiActorSkillRateChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( m_iRate < (_rand(hActor->GetRoom())%100) )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// LimitCount
|
|
bool CMAAiActorSkillLimitCountChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( hActor->IsMonsterActor() )
|
|
{
|
|
CDnMonsterActor* pMonsterActor = static_cast<CDnMonsterActor*>(hActor.GetPointer());
|
|
if( pMonsterActor->GetUseSkillCount( iParam ) < m_iLimitCount )
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CMAAiActorEncounterTickChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor || !hActor->GetAggroSystem() )
|
|
return false;
|
|
|
|
bool bIsProvocationTarget;
|
|
DnActorHandle hTarget = hActor->GetAggroSystem()->OnGetAggroTarget( bIsProvocationTarget );
|
|
if( !hTarget )
|
|
return false;
|
|
|
|
if( static_cast<int>(timeGetTime()-hActor->GetGenTick()) >= m_iCheckTick )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CMAAiActorLimitTickChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor )
|
|
return false;
|
|
|
|
if( static_cast<int>(timeGetTime()-hActor->GetGenTick()) >= m_iCheckTick )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMAAiActorNotifyAnnounceChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor || !hActor->IsMonsterActor() )
|
|
return false;
|
|
|
|
CDnMonsterActor* pMonster = static_cast<CDnMonsterActor*>(hActor.GetPointer());
|
|
|
|
bool bNotify = pMonster->GetAIBase()->bIsNotifyDieAnnounce( m_iTickGap );
|
|
if( !bNotify )
|
|
return false;
|
|
|
|
pMonster->GetAIBase()->ResetNotifyDieAnnounce();
|
|
|
|
if( m_iRate > (_rand(hActor->GetRoom())%100) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CMAAiActorGlobalCoolTimeChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor || !hActor->IsMonsterActor() )
|
|
return false;
|
|
|
|
CDnMonsterActor* pMonster = static_cast<CDnMonsterActor*>(hActor.GetPointer());
|
|
|
|
MAAiScript* pScript = static_cast<MAAiScript*>(pMonster->GetAIBase());
|
|
if( m_iCoolTimeIndex >= static_cast<int>(pScript->GetScriptData().m_AIGlobalCoolTime.size()) )
|
|
{
|
|
_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
DWORD dwRet = pScript->m_GlobalCoolTime.Update( m_iCoolTimeIndex, timeGetTime() );
|
|
return ( dwRet == 0 );
|
|
}
|
|
|
|
bool CMAAiActorNoAggroChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor || !hActor->IsMonsterActor() )
|
|
return false;
|
|
|
|
CDnMonsterActor* pMonster = static_cast<CDnMonsterActor*>(hActor.GetPointer());
|
|
|
|
DnActorHandle hTarget = pMonster->GetAIBase()->GetTarget();
|
|
|
|
return hTarget ? false : true;
|
|
}
|
|
|
|
bool CMAAiActorWaitOrderChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( !hActor || !hActor->IsMonsterActor() )
|
|
return false;
|
|
|
|
CDnMonsterActor* pMonster = static_cast<CDnMonsterActor*>(hActor.GetPointer());
|
|
|
|
MAAiScript* pScript = static_cast<MAAiScript*>(pMonster->GetAIBase());
|
|
int iSkillIndex = pScript->GetMonsterSkillAI()->GetSkillIndexFromLuaSkillIndex( iParam );
|
|
|
|
return pMonster->GetWaitOrderCount( iSkillIndex ) > 0;
|
|
}
|
|
|
|
// SkillToggle
|
|
bool CMAAiActorSkillToggleChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
if( hActor->IsMonsterActor() == false )
|
|
return false;
|
|
|
|
CDnMonsterActor* pMonster = static_cast<CDnMonsterActor*>(hActor.GetPointer());
|
|
DnActorHandle hSummoner = pMonster->GetSummonerPlayerActor();
|
|
if( !hSummoner )
|
|
return false;
|
|
|
|
MAAiScript* pScript = static_cast<MAAiScript*>(pMonster->GetAIBase());
|
|
int iSkillIndex = pScript->GetMonsterSkillAI()->GetSkillIndexFromLuaSkillIndex( iParam );
|
|
DnSkillHandle hMonsterSkill = pMonster->FindSkill( iSkillIndex );
|
|
if( !hMonsterSkill )
|
|
return false;
|
|
|
|
DnSkillHandle hSkill = hSummoner->FindSkill( m_iSkillID );
|
|
if( !hSkill )
|
|
return false;
|
|
|
|
//RLKT FIX Alfredo
|
|
if( hSkill->GetDurationType() == CDnSkill::ActiveToggleForSummon && hSkill->IsToggleOn() == true && m_iSkillLevel == -1 )
|
|
{
|
|
if( hSummoner->GetSP() >= hSkill->GetDecreaseMP() )
|
|
{
|
|
#if defined( PRE_ADD_ACADEMIC )
|
|
hMonsterSkill->SetSummonerDecreaseSP( m_iSkillID, hSkill->GetDecreaseMP() );
|
|
#endif // #if defined( PRE_ADD_ACADEMIC )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if( hSkill->GetDurationType() == CDnSkill::ActiveToggleForSummon && hSkill->IsToggleOn() == true && hSkill->GetLevel() == m_iSkillLevel )
|
|
{
|
|
if( hSummoner->GetSP() >= hSkill->GetDecreaseMP() )
|
|
{
|
|
#if defined( PRE_ADD_ACADEMIC )
|
|
hMonsterSkill->SetSummonerDecreaseSP( m_iSkillID, hSkill->GetDecreaseMP() );
|
|
#endif // #if defined( PRE_ADD_ACADEMIC )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// PassiveSkill
|
|
bool CMAAiActorPassiveSkillChecker::bIsCheck( DnActorHandle hActor, int iParam )
|
|
{
|
|
CDnMonsterActor* pMonster = static_cast<CDnMonsterActor*>(hActor.GetPointer());
|
|
DnActorHandle hSummoner = pMonster->GetSummonerPlayerActor();
|
|
if( !hSummoner )
|
|
return false;
|
|
|
|
DnSkillHandle hSkill = hSummoner->FindSkill( m_iSkillID );
|
|
if( !hSkill )
|
|
return false;
|
|
|
|
//RLKT FIX
|
|
if( (hSkill->GetSkillType() == CDnSkill::Passive || hSkill->GetSkillType() == CDnSkill::EnchantPassive) && m_iSkillLevel == -1)
|
|
return true;
|
|
|
|
if( (hSkill->GetSkillType() == CDnSkill::Passive || hSkill->GetSkillType() == CDnSkill::EnchantPassive) && hSkill->GetLevel() == m_iSkillLevel )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/*#####################################################################################################################
|
|
TargetActorChecker
|
|
#####################################################################################################################*/
|
|
|
|
int CMAAiTargetActorChecker::GetTargetDegree( DnActorHandle hActor, DnActorHandle hTarget, const EtVector3& AxisVector )
|
|
{
|
|
EtVector3 vec = *hActor->GetPosition() - *hTarget->GetPosition();
|
|
vec.y = 0.f;
|
|
EtVec3Normalize( &vec, &vec );
|
|
|
|
float fDot = EtVec3Dot( &vec, &AxisVector );
|
|
|
|
return static_cast<int>(EtToDegree( acosf( min( fDot, 1.0f) ) ));
|
|
}
|
|
|
|
// LF
|
|
bool CMAAi_LF_DirectionChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
int iDegree = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vXAxis) );
|
|
int iDegree2 = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vZAxis) );
|
|
if( iDegree >= 135 && iDegree2 <= 90 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// LB
|
|
bool CMAAi_LB_DirectionChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
int iDegree = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vXAxis) );
|
|
int iDegree2 = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vZAxis) );
|
|
if( iDegree >= 135 && iDegree2 >= 90 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// FL
|
|
bool CMAAi_FL_DirectionChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
int iDegree = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vZAxis) );
|
|
int iDegree2 = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vXAxis) );
|
|
if( iDegree <= 45 && iDegree2 >= 90 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// FR
|
|
bool CMAAi_FR_DirectionChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
int iDegree = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vZAxis) );
|
|
int iDegree2 = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vXAxis) );
|
|
if( iDegree <= 45 && iDegree2 <= 90 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// RF
|
|
bool CMAAi_RF_DirectionChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
int iDegree = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vXAxis) );
|
|
int iDegree2 = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vZAxis) );
|
|
if( iDegree <= 45 && iDegree2 <= 90 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// RB
|
|
bool CMAAi_RB_DirectionChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
int iDegree = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vXAxis) );
|
|
int iDegree2 = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vZAxis) );
|
|
if( iDegree <= 45 && iDegree2 >= 90 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// BR
|
|
bool CMAAi_BR_DirectionChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
int iDegree = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vZAxis) );
|
|
int iDegree2 = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vXAxis) );
|
|
if( iDegree >= 135 && iDegree2 <= 90 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// BL
|
|
bool CMAAi_BL_DirectionChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
int iDegree = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vZAxis) );
|
|
int iDegree2 = GetTargetDegree( hActor, hTarget, -(hActor->GetMatEx()->m_vXAxis) );
|
|
if( iDegree >= 135 && iDegree2 >= 90 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// TargetHPPercent
|
|
bool CMAAiTargetActorHPPercentChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
return m_iHPPercent >= hTarget->GetHPPercent();
|
|
}
|
|
|
|
// TargetBuff
|
|
bool CMAAiTargetActorBuffChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
for( int i=0 ; i<hTarget->GetNumAppliedStateBlow() ; ++i )
|
|
{
|
|
DnBlowHandle hBlow = hTarget->GetAppliedStateBlow( i );
|
|
if( hBlow )
|
|
{
|
|
const CDnSkill::SkillInfo* pSkillInfo = hBlow->GetParentSkillInfo();
|
|
if( !pSkillInfo )
|
|
continue;
|
|
|
|
if( pSkillInfo->eDurationType == CDnSkill::DurationTypeEnum::Buff )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// TargetDeBuff
|
|
bool CMAAiTargetActorDeBuffChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
for( int i=0 ; i<hTarget->GetNumAppliedStateBlow() ; ++i )
|
|
{
|
|
DnBlowHandle hBlow = hTarget->GetAppliedStateBlow( i );
|
|
if( hBlow )
|
|
{
|
|
const CDnSkill::SkillInfo* pSkillInfo = hBlow->GetParentSkillInfo();
|
|
if( !pSkillInfo )
|
|
continue;
|
|
|
|
if( pSkillInfo->eDurationType == CDnSkill::DurationTypeEnum::Debuff )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Blow
|
|
bool CMAAiTargetActorBlowChecker::bIsCheck( DnActorHandle hActor, DnActorHandle hTarget )
|
|
{
|
|
for( UINT i=0 ; i<m_vTableID.size() ; ++i )
|
|
{
|
|
// m_bIsNoBlowCheck == true 인 경우 => 대상이 해당 상태효과에 걸려있으면 스킬을 사용하지 않는다.
|
|
// m_bIsNoBlowCheck == false 인 경우 => 대상이 해당 상태효과에 걸려있지 않으면 스킬을 사용하지 않는다.
|
|
if( hTarget->IsAppliedThisStateBlow( static_cast<STATE_BLOW::emBLOW_INDEX>(m_vTableID[i]) ) == m_bIsNoBlowCheck )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*#####################################################################################################################
|
|
CheckerManager
|
|
#####################################################################################################################*/
|
|
|
|
CMAAiCheckerManager::~CMAAiCheckerManager()
|
|
{
|
|
SAFE_DELETE_PVEC( m_vTargetActorChecker );
|
|
SAFE_DELETE_PVEC( m_vTargetActorDirectionChecker );
|
|
SAFE_DELETE_PVEC( m_vActorChecker );
|
|
}
|
|
|
|
bool CMAAiCheckerManager::bIsActorChecker( DnActorHandle hActor, int iParam/*=0*/ ) const
|
|
{
|
|
for( UINT i=0 ; i<m_vActorChecker.size() ; ++i )
|
|
{
|
|
if( m_bIgnoreRateChecker )
|
|
{
|
|
if( m_vActorChecker[i]->bIsRateChecker() )
|
|
continue;
|
|
}
|
|
|
|
if( !m_vActorChecker[i]->bIsCheck( hActor, iParam ) )
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CMAAiCheckerManager::bIsTargetActorChecker( DnActorHandle hActor, DnActorHandle hTarget ) const
|
|
{
|
|
if( !hTarget )
|
|
return false;
|
|
|
|
// TargetDirection 체크
|
|
if( !m_vTargetActorDirectionChecker.empty() )
|
|
{
|
|
bool bOK = false;
|
|
for( UINT i=0 ; i<m_vTargetActorDirectionChecker.size() ; ++i )
|
|
{
|
|
if( m_vTargetActorDirectionChecker[i]->bIsCheck( hActor, hTarget ) )
|
|
{
|
|
bOK = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !bOK )
|
|
return false;
|
|
}
|
|
|
|
// Target 체크
|
|
for( UINT i=0 ; i<m_vTargetActorChecker.size() ; ++i )
|
|
{
|
|
if( !m_vTargetActorChecker[i]->bIsCheck( hActor, hTarget ) )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMAAiCheckerManager::bLoadChecker( lua_tinker::table& t )
|
|
{
|
|
// 무기체크
|
|
switch( t.get<int>("checkweapon") )
|
|
{
|
|
case 1:
|
|
{
|
|
m_vActorChecker.push_back( new CMAAiActorWeaponChecker( 0 ) );
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
m_vActorChecker.push_back( new CMAAiActorWeaponChecker( 1 ) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 부위파괴
|
|
const char* pszDestroyParts = t.get<const char*>("destroyparts" );
|
|
if( pszDestroyParts )
|
|
{
|
|
std::string strString(pszDestroyParts);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<UINT> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( !vTableID.empty() )
|
|
m_vActorChecker.push_back( new CMAAiActorPartsDestroyChecker(vTableID) );
|
|
}
|
|
|
|
// 부위존재
|
|
const char* pszExistParts = t.get<const char*>("existparts" );
|
|
if( pszExistParts )
|
|
{
|
|
std::string strString(pszExistParts);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<UINT> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( !vTableID.empty() )
|
|
m_vActorChecker.push_back( new CMAAiActorPartsExistChecker(vTableID) );
|
|
}
|
|
|
|
// 타겟방향
|
|
const char* pszTD = t.get<const char*>("td");
|
|
if( pszTD )
|
|
{
|
|
std::string strString(pszTD);
|
|
std::vector<std::string> vSplit;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
{
|
|
if( strcmp( vSplit[i].c_str(), "LF" ) == 0 )
|
|
m_vTargetActorDirectionChecker.push_back( new CMAAi_LF_DirectionChecker() );
|
|
else if( strcmp( vSplit[i].c_str(), "FL" ) == 0 )
|
|
m_vTargetActorDirectionChecker.push_back( new CMAAi_FL_DirectionChecker() );
|
|
else if( strcmp( vSplit[i].c_str(), "FR" ) == 0 )
|
|
m_vTargetActorDirectionChecker.push_back( new CMAAi_FR_DirectionChecker() );
|
|
else if( strcmp( vSplit[i].c_str(), "RF" ) == 0 )
|
|
m_vTargetActorDirectionChecker.push_back( new CMAAi_RF_DirectionChecker() );
|
|
else if( strcmp( vSplit[i].c_str(), "RB" ) == 0 )
|
|
m_vTargetActorDirectionChecker.push_back( new CMAAi_RB_DirectionChecker() );
|
|
else if( strcmp( vSplit[i].c_str(), "BR" ) == 0 )
|
|
m_vTargetActorDirectionChecker.push_back( new CMAAi_BR_DirectionChecker() );
|
|
else if( strcmp( vSplit[i].c_str(), "BL" ) == 0 )
|
|
m_vTargetActorDirectionChecker.push_back( new CMAAi_BL_DirectionChecker() );
|
|
else if( strcmp( vSplit[i].c_str(), "LB" ) == 0 )
|
|
m_vTargetActorDirectionChecker.push_back( new CMAAi_LB_DirectionChecker() );
|
|
}
|
|
}
|
|
|
|
// 상태
|
|
for( int i=1 ; i<=3 ; ++i )
|
|
{
|
|
char szBuf[MAX_PATH];
|
|
sprintf_s( szBuf, "custom_state%d", i );
|
|
|
|
const char* pszState = t.get<const char*>(szBuf);
|
|
if( pszState )
|
|
{
|
|
if( stricmp( pszState, "custom_fly" ) == 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorFlyStateChecker() );
|
|
else if( stricmp( pszState, "custom_ground" ) == 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorGroundStateChecker() );
|
|
else if( stricmp( pszState, "custom_underground" ) == 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorUnderGroundStateChecker() );
|
|
else if( stricmp( pszState, "custom_fly2" ) == 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorFly2StateChecker() );
|
|
}
|
|
}
|
|
|
|
// selfhppercent
|
|
int iHPPercent = t.get<int>("selfhppercent");
|
|
if( iHPPercent > 0 ) // 입력되어 있으면 Checker 생성
|
|
m_vActorChecker.push_back( new CMAAiActorHPPercentChecker(iHPPercent) );
|
|
|
|
// selfhppercentrange
|
|
const char* pszHPPercentRange = t.get<const char*>("selfhppercentrange");
|
|
if( pszHPPercentRange )
|
|
{
|
|
std::string strString(pszHPPercentRange);
|
|
std::vector<std::string> vSplit;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
if( vSplit.size() != 2 )
|
|
return false;
|
|
|
|
boost::trim( vSplit[0]);
|
|
boost::trim( vSplit[1]);
|
|
|
|
int iMin = boost::lexical_cast<int>( vSplit[0] );
|
|
int iMax = boost::lexical_cast<int>( vSplit[1] );
|
|
|
|
if( iMin<0 || iMax<0 || iMin > iMax )
|
|
return false;
|
|
|
|
m_vActorChecker.push_back( new CMAAiActorHPPercentCheckerRange(iMin,iMax) );
|
|
}
|
|
|
|
// targethppercent
|
|
int iTargetHPPercent = t.get<int>("hppercent");
|
|
if( iTargetHPPercent > 0 )
|
|
m_vTargetActorChecker.push_back( new CMAAiTargetActorHPPercentChecker( iTargetHPPercent ) );
|
|
|
|
// SP
|
|
int iSP = t.get<int>("sp");
|
|
if( iSP > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorSPChecker(iSP) );
|
|
|
|
// Buff
|
|
int iBuffCheck = t.get<int>("buffcheck");
|
|
if( iBuffCheck > 0 )
|
|
m_vTargetActorChecker.push_back( new CMAAiTargetActorBuffChecker() );
|
|
|
|
// DeBuff
|
|
int iDeBuffCheck = t.get<int>("debuffcheck");
|
|
if( iDeBuffCheck > 0 )
|
|
m_vTargetActorChecker.push_back( new CMAAiTargetActorDeBuffChecker() );
|
|
|
|
// BlowCheck
|
|
const char* pszBlowCheck = t.get<const char*>("blowcheck");
|
|
if( pszBlowCheck )
|
|
{
|
|
std::string strString(pszBlowCheck);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<UINT> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( !vTableID.empty() )
|
|
m_vTargetActorChecker.push_back( new CMAAiTargetActorBlowChecker( vTableID ) );
|
|
}
|
|
|
|
// NoBlowCheck
|
|
const char* pszNoBlowCheck = t.get<const char*>("noblowcheck");
|
|
if( pszNoBlowCheck )
|
|
{
|
|
std::string strString(pszNoBlowCheck);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<UINT> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( !vTableID.empty() )
|
|
m_vTargetActorChecker.push_back( new CMAAiTargetActorBlowChecker( vTableID,true ) );
|
|
}
|
|
|
|
// usedskill
|
|
const char* pszUsedSkill = t.get<const char*>("usedskill");
|
|
if( pszUsedSkill )
|
|
{
|
|
std::string strString(pszUsedSkill);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<UINT> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( !vTableID.empty() )
|
|
m_vActorChecker.push_back( new CMAAiActorUsedSkillChecker( vTableID ) );
|
|
}
|
|
|
|
// notusedskill
|
|
const char* pszNotUsedSkill = t.get<const char*>("notusedskill");
|
|
if( pszNotUsedSkill )
|
|
{
|
|
std::string strString(pszNotUsedSkill);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<UINT> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( !vTableID.empty() )
|
|
m_vActorChecker.push_back( new CMAAiActorNotUsedSkillChecker( vTableID ) );
|
|
}
|
|
|
|
// encountertime
|
|
int iEnCounterTime = t.get<int>("encountertime");
|
|
if( iEnCounterTime > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorEncounterTickChecker( iEnCounterTime ) );
|
|
|
|
// limittime
|
|
int iLimitTime = t.get<int>("limittime");
|
|
if( iLimitTime > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorLimitTickChecker( iLimitTime ) );
|
|
|
|
// DieAnnounce
|
|
const char* pszAnnounce = t.get<const char*>("announce");
|
|
if( pszAnnounce )
|
|
{
|
|
std::string strString(pszAnnounce);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<int> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( vTableID.size() == 2 )
|
|
m_vActorChecker.push_back( new CMAAiActorNotifyAnnounceChecker( vTableID[0], vTableID[1] ) );
|
|
}
|
|
|
|
#if defined( PRE_FIX_68096 )
|
|
int iGlobalCoolTimeIndex = t.get<int>("globalcooltime");
|
|
if( iGlobalCoolTimeIndex > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorGlobalCoolTimeChecker(iGlobalCoolTimeIndex-1) );
|
|
|
|
for( int i=1 ; i<ActionTableCommon::eCommon::MaxGlobalCoolTime ; ++i )
|
|
{
|
|
char szBuf[MAX_PATH];
|
|
sprintf_s( szBuf, "globalcooltime%d", i+1 );
|
|
int nGlobalCoolTimeIndex = t.get<int>(szBuf);
|
|
if( nGlobalCoolTimeIndex > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorGlobalCoolTimeChecker(nGlobalCoolTimeIndex-1) );
|
|
else
|
|
break;
|
|
}
|
|
#else
|
|
int iGlobalCoolTimeIndex = t.get<int>("globalcooltime");
|
|
if( iGlobalCoolTimeIndex > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorGlobalCoolTimeChecker(iGlobalCoolTimeIndex-1) );
|
|
#endif
|
|
|
|
// noaggro
|
|
int iNoAggro = t.get<int>("noaggro");
|
|
if( iEnCounterTime > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorEncounterTickChecker( iEnCounterTime ) );
|
|
|
|
// checkpassiveskill
|
|
const char* pszCheckPassiveSkill = t.get<const char*>("checkpassiveskill");
|
|
if( pszCheckPassiveSkill )
|
|
{
|
|
std::string strString(pszCheckPassiveSkill);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<int> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( vTableID.size() == 2 )
|
|
m_vActorChecker.push_back( new CMAAiActorPassiveSkillChecker( vTableID[0], vTableID[1] ) );
|
|
}
|
|
|
|
return bOnAddLoadChecker( t );
|
|
}
|
|
|
|
// Action 쪽 Checker 추가 생성
|
|
bool CMAAiActionCheckerManager::bOnAddLoadChecker( lua_tinker::table& t )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Skill 쪽 Checker 추가 생성
|
|
bool CMAAiSkillCheckerManager::bOnAddLoadChecker( lua_tinker::table& t )
|
|
{
|
|
int iRate = t.get<int>("rate");
|
|
// 스킬쪽에서 rate 값을 입력하지 않았을 경우 DefaultValue 는 100% 이다.
|
|
if( iRate == 0 )
|
|
iRate = 100;
|
|
|
|
m_vActorChecker.push_back( new CMAAiActorSkillRateChecker( iRate ) );
|
|
|
|
int iLimitCount = t.get<int>("limitcount");
|
|
if( iLimitCount > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorSkillLimitCountChecker( iLimitCount ) );
|
|
|
|
int iWaitOrder = t.get<int>("waitorder");
|
|
if( iWaitOrder > 0 )
|
|
m_vActorChecker.push_back( new CMAAiActorWaitOrderChecker(iWaitOrder) );
|
|
|
|
// checkskilltoggle
|
|
const char* pszCheckSkillToggle = t.get<const char*>("checkskilltoggle");
|
|
if( pszCheckSkillToggle )
|
|
{
|
|
std::string strString(pszCheckSkillToggle);
|
|
std::vector<std::string> vSplit;
|
|
std::vector<int> vTableID;
|
|
|
|
boost::algorithm::split( vSplit, strString, boost::algorithm::is_any_of(",") );
|
|
|
|
for( UINT i=0 ; i<vSplit.size() ; ++i )
|
|
vTableID.push_back( atoi(vSplit[i].c_str()) );
|
|
|
|
if( vTableID.size() == 2 )
|
|
m_vActorChecker.push_back( new CMAAiActorSkillToggleChecker( vTableID[0], vTableID[1] ) );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMAAiCheckerManager::bIsAnnounceSkill()
|
|
{
|
|
for( UINT i=0 ; i<m_vActorChecker.size() ; ++i )
|
|
{
|
|
if( m_vActorChecker[i]->bIsAnnounceSkill() )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|