#include "stdafx.h" #include "actionmove.h" #include "gamesrv.h" #include "../Common/Protocol.h" #include "Monster_Common.h" #include "MonsterScript.h" #include "Monster.h" #include "Player.h" #include "AIManager.h" #include "GridManager.h" #include "ObjectManager.h" cActionMove::cActionMove(void): cAction( eACT_MOVE ) { } cActionMove::~cActionMove(void) { } void cActionMove::ActionInit( cMonster* pMonster, unsigned long accumTime ) { if( pMonster == NULL ) return; cAction::ActionInit( pMonster, accumTime ); if( pMonster->IsFirstMove() == true ) { /// ¸®Á¨ ÈÄ ÀÏÁ¤ ½Ã°£µ¿¾È ¼±°ø ¾ÈÇÏ´Â ½Ã°£ mRegenCantMoveEndTime = accumTime + FIRSTMOVE_WAIT_TIME; /// À̵¿ Á¤Áö & ¸®Á¨ Á¤Áö ½Ã°£ÀÌ Áߺ¹ µÇ¹Ç·Î Å«°ªÀÌ Àû¿ë µÇ°Ô °è»ê if( accumTime + MOVE_WAIT_TIME > accumTime + FIRSTMOVE_WAIT_TIME ) mWaitEndTime = accumTime + MOVE_WAIT_TIME; else mWaitEndTime = accumTime + FIRSTMOVE_WAIT_TIME; /// óÀ½À̵¿ Ç÷¡±× »ç¿ë ³¡ - À̵¿,¼±°ø ÀÏÁ¤ ½Ã°£µ¿¾È ¾ÈÇÔ pMonster->FirstMoveEnd(); } else mWaitEndTime = accumTime + MOVE_WAIT_TIME; mDelayTime = accumTime; mDelayTime2 = accumTime; mSetPathErrCnd = 0; mIsIdle2Send = false; mIdle2SendTime = 0; mFirstMoveEndCheck = false; mFirstWaitEndCheck = false; } eACTION_CHANGE cActionMove::Action( cMonster* pMonster, unsigned long deltaTime, unsigned long accumTime ) { if( pMonster == NULL ) return eACTCH_ERROR; const sMonsterScript* pMonsterScript = pMonster->GetMonsterInfo(); if( pMonsterScript == NULL ) { assert(NULL); NETWORK2->PostServerEvent("cActionRegen::Action pRegenGroupScript == NULL"); return eACTCH_ERROR; } /// ½ºÅ³ »ç¿ëÀÌ ³¡³¯¶§ ±îÁö Åë°ú if( pMonster->IsSkillWaitEnd() == false ) return eACTCH_CONTINUE; pMonster->CheckComback(); if( pMonster->IsAutoDummy() == false ) { /// ¸ó½ºÅͰ¡ ¼±°ø¸÷Àΰæ¿ì Ÿ°Ù °Ë»ç if( pMonsterScript->mIsPrecedeAttack == true && pMonster->GetFollowEndMove() == false ) { /// 0.5ÃÊÈÄ¿¡ Àç°Ë»ç - ºÎÇϹæÁö if( mDelayTime <= accumTime ) { mDelayTime = accumTime + 500; /// ¸®Á¨ ÈÄ ÀÏÁ¤½Ã°£ µ¿¾È ¼±°ø ¾ÈÇÔ if( mRegenCantMoveEndTime < accumTime ) { /// ¹üÀ§¾È¿¡ µé¾î¿Â Ç÷¹ÀÌ¾î ¼±Åà cPlayer* pPlayer = TargetSelect( pMonster, pMonsterScript->mSeekRange ); if( pPlayer != NULL) { const sRegenScript* pRegen = pMonster->GetRegenMonsterInfo(); if( pRegen != NULL && pRegen->mFamilyNum != 0 ) AIMANAGER->FamilyAttack( pMonster->GetObjectID(), pRegen->mFamilyNum, pPlayer->GetObject() ); pMonster->AddTakeDamage( pPlayer->GetObject(), 0, 0, eTAKEDAMAGETYPE_ADDPLAYER ); return eACTCH_MOVE_END; } } } } } /// ¸ó½ºÅÍ À̵¿ if( pMonster->MoveUpdate( deltaTime ) == true ) { mFirstMoveEndCheck = false; /// ¸¶Áö¸· À̵¿±îÁö ´ë±â½Ã°£ 3ÃÊ ¼³Á¤ mWaitEndTime = accumTime + MOVE_WAIT_TIME; return eACTCH_CONTINUE; } /// À̵¿ ³¡³ªÀÚ¸¶ÀÚ Çѹø üũ if( mFirstMoveEndCheck == false ) { mFirstMoveEndCheck = true; pMonster->SendSpeech( eMONSTERTALK_MAX ); /// À̵¿ ÆÐÅÏÀÌ Àִ°æ¿ì °æÀ¯Áö¿¡¼­¸¸ ´ë±âÇÔ const sMonsterPattern* pPattern = pMonster->GetMovePattern(); if( pPattern != NULL ) { unsigned long waitTime = pMonster->GetPatternWait(); mWaitEndTime = accumTime + waitTime; pMonster->SetGroupMoveReady( 1 ); } } /// À̵¿ÀÌ ³¡³ª¸é ÃßÀûÀ̵¿ ȸ±Í´Â ¿Ï·á pMonster->SetFollowEndMove( false ); /// ´ë±âµ¿ÀÛ2 ¹ß¼Û üũ if( mIsIdle2Send == true && accumTime < mIdle2SendTime ) { /// ¸Þ¼¼Áö ¹ß¼Û MSG_SYN_MONSTER_IDLE2ANI synMsg; synMsg.Category = NM_MONSTER; synMsg.Protocol = NM_MONSTER_IDLE2_ANI_SYN; synMsg.mMonsterIdx = pMonster->GetObjectID(); NETWORK2->QuickSend( (cBaseObject*)pMonster, (char*)&synMsg, sizeof(MSG_SYN_MONSTER_IDLE2ANI) ); mIdle2SendTime = false; mIdle2SendTime = 0; } /// ´ë±â½Ã°£ ºñ±³ if( mWaitEndTime > accumTime ) return eACTCH_CONTINUE; /// ´ÙÀ½ À̵¿ °æ·Î ¼±Á¤ float targetPosX = pMonster->GetXPos(); float targetPosY = pMonster->GetYPos(); unsigned long familyNum = 0; if( pMonster->GetRegenMonsterInfo() != NULL ) familyNum = pMonster->GetRegenMonsterInfo()->mFamilyNum; if( mFirstWaitEndCheck == true ) { mFirstWaitEndCheck = false; const sMonsterPattern* pPattern = pMonster->GetMovePattern(); if( pPattern != NULL && familyNum != 0 ) pMonster->SetGroupMoveReady( 2 ); } if( pMonster->GetGroupMoveReady() == 2 ) return eACTCH_CONTINUE; pMonster->ClearPatternWait(); /// À̵¿¼Óµµ°¡ ¾øÀ¸¸é ´ÙÀ½ °æ·Î ¼±Á¤ ¾ÈÇÔ if( pMonsterScript->mActionRunSpd == 0 && pMonsterScript->mActionWalkSpd == 0 ) return eACTCH_CONTINUE; /// ´ÙÀ½ À̵¿ °æ·Î ¼±Á¤ if( pMonster->SelectNextPath( &targetPosX, &targetPosY ) == false ) return eACTCH_CONTINUE; if( familyNum != 0 ) { if( AIMANAGER->FamilyFar( pMonster->GetMapNumber(), familyNum, pMonster->GetPos() ) == true ) pMonster->SetMoveSpeed( pMonsterScript->mActionRunSpd, eMOVESPEED_RUN ); else pMonster->SetMoveSpeed( pMonsterScript->mActionWalkSpd, eMOVESPEED_WALK ); } /// °æ·Î ¼³Á¤½Ã ½ÇÆÐ ÇѰæ¿ì¸é ´Ù¸¥ À̵¿¹æ½Ä ¼±Á¤ ¾ÈÇÏ°í ±âÁ¸ À̵¿¹æ¹ýÀ¸·Î ¼±Á¤ if( mSetPathErrCnd == 0 ) { /// À̵¿ÀÌ ³¡³­°æ¿ì ÀÚÀ¯À̵¿ ¹æ½Ä ¼±Á¤ unsigned long moveSpeed = 0; eMOVE_SPEED_TYPE moveSpeedType = RandMoveSpeed( pMonster, &moveSpeed ); /// Çൿ Á¤Áö ¼±Åà if( moveSpeed == 0 ) { /// ´ë±â½Ã°£ Ãß°¡ mWaitEndTime = accumTime + pMonsterScript->mActionStopTime; /// ´ë±â½Ã°£ Áß ÀÏÁ¤½Ã°£¿¡ ´ë±âµ¿ÀÛ2 ¸Þ¼¼Áö ¹ß¼Û °áÁ¤ mIsIdle2Send = (rand() % 100) + 1 <= IDLE2_ANI_SEND_PER; if( mIsIdle2Send == true ) mIdle2SendTime = accumTime + ( pMonsterScript->mActionStopTime / 3 ); pMonster->SendSpeech( eMONSTERTALK_STAND ); return eACTCH_CONTINUE; } /// ¸ó½ºÅÍÀÇ À̵¿ ¼Óµµ °áÁ¤ pMonster->SetMoveSpeed( moveSpeed, moveSpeedType ); if( moveSpeedType == eMOVESPEED_WALK ) pMonster->SendSpeech( eMONSTERTALK_WORK ); else if( moveSpeedType == eMOVESPEED_RUN ) pMonster->SendSpeech( eMONSTERTALK_RUN ); } /// ¸ó½ºÅͰ¡ À̵¿ÇÒ °æ·Î ¼ÂÆÃ if( pMonster->SetPath( targetPosX, targetPosY ) == 0 ) ++mSetPathErrCnd; else mSetPathErrCnd = 0; /// °¥¼ö¾ø´Â °æ·Î ¿¬¼Ó½ÇÆÐ Ƚ¼ö°¡ ³Ê¹« ¸¹Àº °æ¿ì ¸ó½ºÅͰ¡ ±æÃ£±â Çã¿ë ¹üÀ§±îÁö ³ª°¬À» °¡´É¼ºÀÌ Å©´Ù. if( mSetPathErrCnd > 100 ) { /// °­Á¦ À̵¿ pMonster->SetPos( targetPosX, targetPosY ); mSetPathErrCnd = 0; } /// Ưº°ÇÑ À̺¥Æ®¿¡ °É¸®Áö ¾Ê´Â ÇÑ °è¼Ó À̵¿ return eACTCH_CONTINUE; } eMOVE_SPEED_TYPE cActionMove::RandMoveSpeed( cMonster* pMonster, unsigned long *moveSpeed ) { const sMonsterScript* pMonsterScript = pMonster->GetMonsterInfo(); if( pMonsterScript == NULL ) { assert(NULL); *moveSpeed = 0; return eMOVESPEED_RUN; } *moveSpeed = pMonsterScript->mActionWalkSpd; return eMOVESPEED_WALK; /* if( pMonster == NULL ) return eMOVESPEED_RUN; const sMonsterScript* pMonsterScript = pMonster->GetMonsterInfo(); if( pMonsterScript == NULL ) { assert(NULL); *moveSpeed = 0; return eMOVESPEED_RUN; } /// ºñÀ² ÇÕ°è unsigned short totalRatio = pMonsterScript->mActionStopRatio + pMonsterScript->mActionWalkRatio + pMonsterScript->mActionRunRatio; /// ·£´ý ¼±Åðª if( totalRatio == 0 ) totalRatio = 1; unsigned short randSelect = (unsigned short)( rand() % totalRatio ) + 1; if( randSelect <= pMonsterScript->mActionStopRatio ) { *moveSpeed = 0; /// Á¤Áö ¼±Åà return eMOVESPEED_STOP; } else if( randSelect <= pMonsterScript->mActionStopRatio + pMonsterScript->mActionWalkRatio ) { *moveSpeed = pMonsterScript->mActionWalkSpd; /// °È±â ¼±Åà return eMOVESPEED_WALK; } else { *moveSpeed = pMonsterScript->mActionRunSpd; /// ¶Ù±â ¼±Åà return eMOVESPEED_RUN; } */ } cPlayer* cActionMove::TargetSelect( cMonster* pMonster, unsigned long seekRange ) { if( pMonster == NULL ) return NULL; float tempRange; /// ÁÖº¯ ±×¸®µå¿¡ Ç÷¹À̾ ÀÖ´ÂÁö ¸ÕÀú üũ - ºÎÇϹæÁö if( GRIDMANAGER->IsPlayer( pMonster ) == 0 ) return NULL; /// °¢°¢ÀÇ Ç÷¹À̾ °Ë»öÇÔ cPlayer* pPlayer = GRIDMANAGER->FindFirstPlayer( pMonster ); while( pPlayer != NULL ) { /// Ÿ°Ù ¼±Á¤Àü ºñÁß È®ÀÎ if( pPlayer->GetMonsterImportance() + pMonster->GetFollowImportance() > 100 ) { pPlayer = GRIDMANAGER->FindNextPlayer(); continue; } /// ¸ó½ºÅÍ·Î º¯½ÅÇÑ Äɸ¯ÅÍÀÎ °æ¿ì if( pPlayer->GetChgMonsterIdx() != 0 || pPlayer->GetStateOddity( eODDITYTYPE_AVOID_MON_LOOK ) != 0 ) { /// ÇØ´ç ¸ó½ºÅͰ¡ º¯½ÅÇÑ Ç÷¹À̾ ÀνÄÇÏ´ÂÁö ¾ÈÇÏ´ÂÁö Á¤º¸¸¦ ¾òÀ½ sMonsterScript* pScript = MONSTERSCRIPT->GetMonsterListInfo( pMonster->GetRaceGender() ); if( pScript == NULL ) { pPlayer = GRIDMANAGER->FindNextPlayer(); continue; } /// º¯½Å ÀνÄÀ» ¾ÈÇÏ´Â °æ¿ì º¯½ÅÇ÷¹À̾î Åë°ú if( pScript->mIsChgMonCheck == false ) { pPlayer = GRIDMANAGER->FindNextPlayer(); continue; } } /// Ç÷¹À̾ Àִµ¥ Á×Àº°æ¿ì´Â Åë°ú if( pPlayer->GetStateDie() != true ) { tempRange = OBJECTMANAGER->ObjectSizeRange( pMonster, pPlayer, (float)seekRange ); /// ¸ó½ºÅÍ ¹üÀ§ ¼³Á¤ mRangechk.SetRadius( tempRange ); /// ¸ó½ºÅÍ À§Ä¡ NiPoint3 monsterpoint( pMonster->GetXPos(), pMonster->GetYPos(), pMonster->Height() ); /// Ç÷¹À̾î À§Ä¡ NiPoint3 playerpoint( pPlayer->GetXPos(), pPlayer->GetYPos(), pPlayer->Height() ); /// ¸ø°¡´Â Áö¿ªÀΰæ¿ì Åë°ú if( AIMANAGER->IsPossible( pPlayer->GetMapNumber(), playerpoint.x, playerpoint.y, pPlayer->GetObject() ) == false ) { pPlayer = GRIDMANAGER->FindNextPlayer(); continue; } /// ¸ó½ºÅÍ¿Í Ç÷¹À̾î Ãæµ¹ üũ if( mRangechk.IsRange( monsterpoint, playerpoint ) ) { return pPlayer; } } pPlayer = GRIDMANAGER->FindNextPlayer(); } return NULL; }