#include "StdAfx.h" #include ".\vitalsuctionstatus.h" #include "Ability.h" #include "VitalSuctionAbility.h" #include "NPCStateManager.h" #include "DeadState.h" #include "Skill.h" #include "SkillInfoParser.h" VitalSuctionStatus::VitalSuctionStatus(void) { m_pGameField = NULL; m_fSpeed = 0.0f; m_fAccelate = 0.0f; } VitalSuctionStatus::~VitalSuctionStatus(void) { } VOID VitalSuctionStatus::Init( Character *pOwner, Character *pAttacker, Ability *pAbility ) { // TODO: f101031.1L, targets of a 'eCHAR_STATE_VITAL_SUCTION' can include player by a script AbilityStatus::Init( pOwner, pAttacker, pAbility ); VitalSuctionAbility* vital_suction_ablity = (VitalSuctionAbility*)pAbility; suction_hp_ = vital_suction_ablity->GetSuctionHP(); m_pGameField = pAttacker->GetField(); m_dwAttackerObjectKey = pAttacker->GetObjectKey(); pOwner->GetPos( &m_vGhost ); m_fAccelate = 0.001f; m_fSpeed = 0.001f; m_dwFirstTick = GetTickCount(); m_dwPreTick = m_dwFirstTick; SetVector( &m_vGhostUnitDir, 0.f, 0.f, 1.f ); // Ÿ°ÙÀÇ Á׾ »ç¶óÁö´Â ½Ã°£À» »õ·Î ¼³Á¤ÇÑ´Ù. // ¼ÒÀ¯ÀÚ´Â ¸ó½ºÅÍ¿©¸¸ ÇÑ´Ù. NPC* pMonster = (NPC*)pOwner; State* pState = pMonster->GetStateManager()->GetCurState(); if( !pState ) { SUNLOG( eCRITICAL_LOG, "["__FUNCTION__"] ¸ó½ºÅͰ¡ Á×¾ú´Âµ¥ Á×Àº »óŰ¡ ¾ø´Ù." ); return; } if( pState->GetStateID() != STATE_ID_DEAD ) { SUNLOG( eCRITICAL_LOG, "["__FUNCTION__"] ¸ó½ºÅͰ¡ Á×¾ú´Âµ¥ Á×Àº »óŰ¡ ¾Æ´Ï´Ù. CurState = %d", pState->GetStateID() ); // (CHANGES) (100223) (WAVERIX) fix up missing return that post action assume dead state return; } // ¸ó½ºÅÍÀÇ DEAD»óŸ¦ Áõ°¡ ½ÃŲ´Ù. static_cast(pState)->SetNextTimeoutInterval(20 * 1000); } VOID VitalSuctionStatus::Execute() { Character* pAttacker = m_pGameField->FindCharacter( m_dwAttackerObjectKey ); // (WAVERIX) (090608) (WOPS:4077) VitalSuction ½ÇÇà Á¦¾à Á¶°Ç Ãß°¡ if(pAttacker == 0 || pAttacker->IsDead()) { // ±×¸®°í ÇöÀç »óÅ ¼ÒÀ¯ÀÚ´Â ¼Ò¸ê½ÃŲ´Ù. StopStatus(); return; } Character* const owner = GetOwner(); if (owner == NULL) { StopStatus(); return; } NPC* pMonster = (NPC*)owner; State* pState = pMonster->GetStateManager()->GetCurState(); if( !pState ) { SUNLOG( eCRITICAL_LOG, "["__FUNCTION__"] ¸ó½ºÅͰ¡ Á×¾ú´Âµ¥ Á×Àº »óŰ¡ ¾ø´Ù." ); StopStatus(); return; } if( pState->GetStateID() != STATE_ID_DEAD ) { SUNLOG( eCRITICAL_LOG, "["__FUNCTION__"] VitalSuctionStatusÀε¥ Á×Àº »óŰ¡ ¾Æ´Ï´Ù. CurState = %d", pState->GetStateID() ); StopStatus(); return; } DWORD dwCurTick = GetTickCount(); DWORD dwTick = dwCurTick - m_dwPreTick; WzVector vTemp, vAxis, vLen1, vLen2, vAttackerPos; //1ÃÊ µ¿¾ÈÀº À§·Î »ó½ÂÇÑ´Ù. if( ( m_dwFirstTick + 1000 ) >= dwCurTick ) { WzVector vUp; SetVector( &vUp, 0.f, 0.f, 1.f ); vTemp = vUp*(dwTick*m_fSpeed); //´ÜÀ§º¤ÅÍ.. m_vGhost = m_vGhost + vTemp; } else { pAttacker->GetPos( &vAttackerPos ); WzVector vLen = vAttackerPos - m_vGhost; float fLen = VectorLength( &vLen ); //¿ÜÀû ±¸ÇÏ´Â ÇÔ¼ö. VectorCrossProduct( &vAxis, &m_vGhostUnitDir, &vLen ); //ȸÀü°¢ float theta = 0.001f * dwTick; //ȸÀüº¯È¯¿ë Çà·Ä »ý¼º. WzMatrix matRotAxis; MatrixRotation( &matRotAxis, &vAxis, theta ); if( 0.5f < fLen ) { vTemp = m_vGhostUnitDir; VectorTransformCoord( &m_vGhostUnitDir, &vTemp, &matRotAxis ); } else { VectorNormalize( &m_vGhostUnitDir, &vLen ); } // Çѹø ExecuteÇÒ¶§ ¸¶´Ù( 1ÃÊ ) À̵¿ÇÏ´Â °Å¸®.. m_fSpeed += m_fAccelate; vTemp = m_vGhostUnitDir*( dwTick*m_fSpeed ); WzVector vLenCheck = m_vGhost + vTemp; vLen1 = vLenCheck - m_vGhost; vLen2 = vAttackerPos - m_vGhost; float fLen1 = VectorLength( &vLen1 ); //¹ß»çü°¡ À̹ø Tick µ¿¾È À̵¿ÇÑ °Å¸® float fLen2 = VectorLength( &vLen2 ); //¹ß»çü¿Í °ø°ÝÀÚ¿ÍÀÇ °Å¸®. if( fLen1 > fLen2 ) { m_vGhost = vAttackerPos; // ³Ñ¾î°¡¹Ç·Î... Ŭ¶óÇÑÅ× ÆÐŶÀ» º¸³½´Ù. DWORD dwAddHP = suction_hp_; pAttacker->IncreaseHP( dwAddHP ); // HPÁõ°¡.... ;{ MSGSUB_SKILL_VITAL_SUCTION_BRD msg_brd; msg_brd.Clear(); msg_brd.m_dwAttackerKey = pAttacker->GetObjectKey(); msg_brd.m_dwTargetKey = owner->GetObjectKey(); msg_brd.m_dwHP = pAttacker->GetHP(); owner->SendPacketAroundForSync(&msg_brd); }; SUNLOG( eDEV_LOG, "[VitalSuctionStatus::Execute()] AddHP = %d, MonsterObjectKey = %d", dwAddHP, owner->GetObjectKey() ); // 1. ¸ó½ºÅ͸¦ Á×Àº»óŸ¦ ¸¸·á½ÃŲ´Ù. static_cast(pState)->SetNextTimeoutInterval(0); // ½ÇÇàµÇ¾úÀ¸¹Ç·Î, ´Ù½Ã´Â Execute°¡ ½ÇÇàµÇÁö ¾Ê°ÔÇÑ´Ù. // ¿ø·¡´Â End°¡ ½ÇÇàµÇ°Ô ÇÏ·Á ÇßÀ¸³ª, DeadStateÀÇ ¸¸·á½Ã°£À» 0À¸·Î Ç߱⠶§¹®¿¡, Update½Ã¿¡ // FASLE¸¦ ¸®ÅÏÇØ, ÇØ´ç ¸ó½ºÅÍÀÇ °´Ã¼¸¦ Release ÇÒ °ÍÀÌ´Ù. ±×¶§ ÀÌ »óŵµ ¾ø¾îÁú °ÍÀÌ´Ù. StopStatus(); return; } else m_vGhost = m_vGhost + vTemp; } AbilityStatus::Execute(); } // ij¸¯ÅͰ¡ Á×À¸¸é ÇØ´ç Status¸¦ Á¦°ÅÇϱâ À§Çؼ­ Update½Ã ÇØ´ç Status¸¦ Á¦°ÅÇÑ´Ù. // Á¦°Å ÇÏÁö ¸»¾Æ¾ß ÇÒ °ÍÀº CanRemove·Î ÇÑ´Ù. BOOL VitalSuctionStatus::CanRemove() { Character* const owner = GetOwner(); if (owner == NULL) { return TRUE; } //¸¸ÀÏ ÇöÀç Á×Àº »óŰ¡ ÀÖÀ¸¸é Á¦°ÅÇÏÁö ¸»°í, Á×Àº »óŰ¡ ¾Æ´Ï¸é Á¦°ÅÇ϶ó. NPC* pMonster = (NPC*)owner; State* pState = pMonster->GetStateManager()->GetCurState(); if( !pState ) { SUNLOG( eCRITICAL_LOG, "[VitalSuctionStatus::Init] ¸ó½ºÅͰ¡ Á×¾ú´Âµ¥ Á×Àº »óŰ¡ ¾ø´Ù." ); return TRUE; } //ÇöÀç Á×Àº »óŸé.. if( pState->GetStateID() == STATE_ID_DEAD ) return FALSE; return TRUE; }