#include "stdafx.h" #include "LuckyMonster.h" #include "CharacterFormula.h" #include "NPCStateManager.h" #include "AIParamParser.h" #include "AIMessageQueue.h" #include #include "PublicMath.h" LuckyMonster::LuckyMonster() { SetObjectType( LUCKYMON_OBJECT ); } BOOL LuckyMonster::Init() { m_dwRunAwayRegenTime = 0; m_ExpireTimer.Clear(); m_RetreatTimer.SetTimer( 5*1000 ); return NPC::Init(); } VOID LuckyMonster::InitMonster( WORD NPCCode, BYTE byMoveType, DWORD dwMoveAreaID ) { this->Init(); m_LinkedAction = AppliedNpcDependencyChain::Instance()->GetNpcLinkAction( NPCCode, MONSTER_OBJECT ); NPC::SetBaseInfo( NPCCode, byMoveType, dwMoveAreaID ); #ifdef __KR_0_20090519_EASY_GET_LUCKYMONSTER_ m_RegenHP = (DWORD)(GetHP() * 0.99f); //»ý¼º½ÃÀÇ HPÀÇ 99%¸¦ ÀúÀåÇÑ´Ù. //¼Ò¸ê½Ã°£ üũ¸¦ À§ÇØ, %´Â º¯°æ °¡´ÉÇÒ ºÎºÐÀ¸·Î ¿¹»ó #endif } BOOL LuckyMonster::Update( DWORD dwDeltaTick ) { // ½Ã°£ÀÌ ´ÙµÇ¸é ¼Ò¸êµÈ´Ù. if( m_ExpireTimer.IsExpired() && IsAlive() ) { AI_TYPE_INFO *pAITypeInfo = AIParamParser::Instance()->GetTypeInfo(GetBaseInfo()->m_wAICode); m_dwRunAwayRegenTime = pAITypeInfo->m_dwLUCKY_MONSTER_REGEN_TIME; // µµ¸Á»ç½ÇÀ» Ŭ¶ó¿¡ ¾Ë·ÁÁØ´Ù. MSG_CG_SYNC_LUCKY_MONSTER_RUNAWY_BRD brdMsg; brdMsg.m_dwObjectKey = GetObjectKey(); brdMsg.m_iRotateAngle = GetRunAwayAngle(); SendPacketAround( &brdMsg, sizeof(brdMsg) ); OnDead(); } // Çѹø¾¿ ÀÏÁ¤°Å¸® ¸¸Å­ µµ¸ÁÄ£´Ù. if( m_RetreatTimer.IsExpired() && (rand()%2) ) { AI_MSG_CHANGETORETREATSTATE AIMsg; AIMsg.fMaxDistance = 25.f; AIMsg.bIdleAfterRetreat = TRUE; SendAIMessage( &AIMsg, sizeof(AIMsg) ); } return NPC::Update( dwDeltaTick ); } VOID LuckyMonster::SetExpireTime( DWORD dwInterval ) { m_ExpireTimer.SetTimer( dwInterval ); if( !dwInterval ) m_ExpireTimer.DisableCheckTime(); } void LuckyMonster::_Damaged(DamageArgs* damage_arg) { #ifdef __KR_0_20090519_EASY_GET_LUCKYMONSTER_ if( !m_ExpireTimer.GetIntervalTime() && CheckExpireTimeStart() ) #else if( !m_ExpireTimer.GetIntervalTime() ) // ÃÖÃÊ·Î °ø°ÝÀ» ¹ÞÀ¸¸é ½Ã°£Á¦ÇÑÀÌ ¹ßµ¿µÈ´Ù. #endif { UnitRegenInfo* pUnitRegenInfo = GetUnitRegenInfo(); // ¸ðµç À¯´ÖÀº pUnitRegenInfo°¡ Á¸Àç ÇÑ´Ù. // ¿¹¿Ü gm¸í·É¾î·Î »ý¼º½Ã Á¸Àç ÇÏÁö ¾Ê´Â´Ù. if (!pUnitRegenInfo || pUnitRegenInfo->IsRegenTypeTrigger() == false) { const WORD wAICode = GetBaseInfo()->m_wAICode; const AI_TYPE_INFO *pAITypeInfo = AIParamParser::Instance()->GetTypeInfo(wAICode); const DWORD minTime = pAITypeInfo->m_dwLUCKY_MONSTER_RUNAWAY_TIME_MIN; const DWORD maxTime = pAITypeInfo->m_dwLUCKY_MONSTER_RUNAWAY_TIME_MAX; const DWORD dwInterval = (DWORD)dRandom( minTime, maxTime ); m_ExpireTimer.SetTimer( dwInterval ); } } if( GetRunAwayRegenTime() ) // ¸¶Áö¸·À¸·Î µµ¸Á°¡¼­ »ç¶óÁö´Â ÁßÀ̶ó¸é µ¥¹ÌÁö Miss ó¸®ÇÑ´Ù. return; Character* pAttacker = damage_arg->actor_; const Attributes& attributes = pAttacker->GetAttr(); damage_arg->damage_ = (damage_arg->option_.is_critical_ == false) ? 1 : 2; damage_arg->damage_ += attributes.GetLuckMonIncDamage(); // ´õºí µ¥¹ÌÁö: È®À²·Î µ¥¹ÌÁö°¡ µÎ¹è·Î Áõ°¡ÇÑ´Ù. damage_arg->damage_ += CalcDoubleDamage(pAttacker, damage_arg->damage_); return NPC::_Damaged(damage_arg); } VOID LuckyMonster::OnDead() { // ¸ó½ºÅͰ¡ µµ¸ÁÃļ­ »ç¶óÁö´Â°Å¶û, ¸Â¾Æ¼­ Á״°Ŷû 󸮰¡ ´Ù¸£´Ù. if( GetRunAwayRegenTime() ) { NPC::OnDead(); } else Monster::OnDead(); } int LuckyMonster::GetRunAwayAngle() { int iRotateAngle = 0; // ÇöÀç °ø°ÝÇϰí Àִ Ÿ°ÙÀÌ ÀÖÀ¸¸é Ÿ°ÙÀÇ ¹Ý´ë¹æÇâÀ¸·Î µµ¸ÁÄ£´Ù. if( GetTargetChar() ) { WzVector vCurPos, vTargetPos; GetPos( &vCurPos ); GetTargetChar()->GetPos( &vTargetPos ); iRotateAngle = Math_GetAngleFromVector2( &( vCurPos - vTargetPos ) ); } // Ÿ°ÙÀÌ ¾øÀ¸¸é ·£´ýÇÏ°Ô µµ¸Áħ else { iRotateAngle = rand() % 360; } return iRotateAngle; } #ifdef __KR_0_20090519_EASY_GET_LUCKYMONSTER_ //HP 99%¿¡¼Ò¸ê ŸÀ̸Ӹ¦ ÀÛµ¿ ½Ã۱â À§ÇÑ Ã¼Å© ÇÔ BOOL LuckyMonster::CheckExpireTimeStart() { DWORD currentHP = GetHP(); //ŸÀ̸Ӱ¡ ÀÛµ¿ÇÏÁö ¾Ê°í ¸ó½ºÅÍÀÇ HP°¡ 99% ÀÌÇÏÀÏ °æ¿ì if( m_RegenHP > currentHP ) return TRUE; return FALSE; } #endif