#include "StdAfx.h" #include "DnMonsterActor.h" #include "DnWorld.h" #include "DnWeapon.h" #include "MAAiBase.h" #include "DnTableDB.h" #include "DnDropItem.h" #include "DnPartyTask.h" #include "DnGameTask.h" #include "TaskManager.h" #include "DnItemTask.h" #include "DnBlow.h" #include "DNGameRoom.h" #include "DNUserSession.h" #include "DnWorldTrapProp.h" #include "DnStateBlow.h" #include "navigationcell.h" #include "navigationmesh.h" #include "navigationpath.h" #include "DnPlayerActor.h" #include "DNLogConnection.h" #include "MAWalkMovementNav.h" #include "DNMissionSystem.h" #include "DnProjectile.h" #include "MAAiScript.h" #include "DNMonsterAggroSystem.h" #include "GameSendPacket.h" #include "MAScanner.h" #include "MasterRewardSystem.h" #include "DnBlockBlow.h" #include "DnParryBlow.h" #include "DnCannonMonsterActor.h" #if defined(PRE_ADD_WEEKLYEVENT) #include "DNGameDataManager.h" #endif int CDnMonsterActor::s_nPositionRevisionTime = 3000; CDnMonsterActor::CDnMonsterActor( CMultiRoom *pRoom, int nClassID ) :CDnActor( pRoom, nClassID ) ,m_nMonsterClassID(0) ,m_AIDifficult( Dungeon::Difficulty::Easy ) ,m_pszCanBumpActionName(NULL) { CDnActionBase::Initialize( this ); m_nDestroyTime = 0; m_bTimeMonster = false; m_fScale = 1.f; m_nMonsterWeightTableID = -1; m_eElementType = ElementEnum_Amount; m_bNoDamage = false; m_LastSendMoveMsg = 0; m_fRotateResistance = 1.f; m_nPartyComboCount = 0; m_nPartyComboDelay = 0; m_bIsTriggerMonster = false; m_iTriggerRandomSeed = 0; m_hProp = CDnWorldProp::Identity(); m_uiForcePositionRevisionTick = 0; m_uiPrevForcePositionRevisionTick = 0; m_bEnableDropItem = true; m_nBirthAreaHandle = -1; m_dwSummonerActorID = 0; m_bSuicideWhenSummonerDie = false; m_bFollowSummonerStage = false; m_iSummonGroupID = 0; m_fLimitSummonerDistanceSQ = 0.0f; m_bSummoned = false; m_bReCreatedFollowStageMonster = false; #ifdef PRE_ADD_MONSTER_CATCH m_iCatchedActorActionIndex = 0; #endif // #ifdef PRE_ADD_MONSTER_CATCH #if defined( PRE_FIX_MOVEBACK ) m_bNearMoveBack = false; m_bPrevMoveBack = false; #endif m_nAutoRecallRange = 0; #if defined(PRE_FIX_51048) m_EnablePassiveStateEffect = false; #endif // PRE_FIX_51048 m_bChangeAxisOnFinishAction = false; m_isPuppetSummonMonster = false; #ifdef PRE_MOD_DARKLAIR_RECONNECT m_nEventAreaUniqueID = -1; #endif // PRE_MOD_DARKLAIR_RECONNECT #ifdef PRE_ADD_TRANSFORM_MONSTER_ACTOR m_nSwapActorID = -1; #endif } CDnMonsterActor::~CDnMonsterActor() { //¸ó½ºÅÍ ¿À¶ó ½ºÅ³ Ãë¼Ò. if( IsEnabledAuraSkill() ) OnSkillAura( m_hAuraSkill, false ); SAFE_DELETE_VEC( m_VecDropItemList ); } bool CDnMonsterActor::Initialize() { CalcMonsterWeightIndex(); CDnMonsterState::Initialize( m_nClassID ); MAAiReceiver::Initialize( m_nMonsterClassID, GetAIFileName().c_str() ); CDnActor::Initialize(); if( m_fWeight == 0.f ) m_fRevisionWeight = 0.f; else m_fRevisionWeight = m_fWeight + ( ( m_fScale - 1.f ) * CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ScaleWeightValue ) ); GenerationDropItem(); if( m_hObject ) { m_hObject->SetCollisionGroup( COLLISION_GROUP_DYNAMIC( 1 ) ); m_hObject->SetTargetCollisionGroup( COLLISION_GROUP_STATIC( 1 ) | COLLISION_GROUP_DYNAMIC( 2 ) ); } DNTableFileFormat* pSox = GetDNTable( CDnTableDB::TMONSTER ); int nStrElementType = pSox->GetFieldFromLablePtr( m_nMonsterClassID, "_Element_Str_Type" )->GetInteger(); if( nStrElementType != -1 ) m_eElementType = (ElementEnum)nStrElementType; _ASSERT( m_pAggroSystem == NULL ); m_pAggroSystem = new CDNMonsterAggroSystem( GetActorHandle() ); _ASSERT( m_pAggroSystem != NULL ); return true; } void CDnMonsterActor::ProcessLook( LOCAL_TIME LocalTime, float fDelta ) { if( bIsAILook() && bIsTurnOnAILook() ) { Look( *m_pAi->GetAILook() ); } else { bool bNaviMode = IsNaviMode(); // bool bLockTarget = IsSignalRange( STE_LockTargetLook ); #if defined( PRE_MOD_LOCK_TARGET_LOOK ) if( false == bNaviMode && 0 != m_nLockLookEventArea && true == m_bLockLookTarget ) { if( GetLookTarget() ) ResetLook(); if( NULL != GetGameRoom() && NULL != GetGameRoom()->GetWorld() ) { std::vector vecArea; GetGameRoom()->GetWorld()->FindEventAreaFromCreateUniqueID( m_nLockLookEventArea, &vecArea ); if( false == vecArea.empty() ) { EtVector3 vAreaPosition = vecArea[0]->GetOBB()->Center; EtVector3 * vMonsterPosition = GetPosition(); EtVector2 vDir; vDir.x = vAreaPosition.x - vMonsterPosition->x; vDir.y = vAreaPosition.z - vMonsterPosition->z; EtVec2Normalize( &vDir, &vDir ); CmdLook( vDir ); } } } else #endif // #if defined( PRE_MOD_LOCK_TARGET_LOOK ) if( !bNaviMode && m_bLockLookTarget && GetAggroTarget() ) { if( !GetLookTarget() && GetLookTarget() != GetAggroTarget() ) LookTarget( GetAggroTarget() ); } else { if( GetLookTarget() ) ResetLook(); } } if( !IsSignalRange( STE_RotateResistance ) ) m_fRotateResistance = 1.f; } void CDnMonsterActor::Process( LOCAL_TIME LocalTime, float fDelta ) { m_bLockLookTarget = false; m_pszCanBumpActionName = NULL; m_uiPrevForcePositionRevisionTick = m_uiForcePositionRevisionTick; m_uiForcePositionRevisionTick = 0; #if defined( PRE_MOD_LOCK_TARGET_LOOK ) m_nLockLookEventArea = 0; #endif // #if defined( PRE_MOD_LOCK_TARGET_LOOK ) CDnActor::Process( LocalTime, fDelta ); PROFILE_TIME_TEST_BLOCK_START( "CDnMonsterActor::Process" ); ProcessLook( LocalTime, fDelta ); SetMoveVectorX( m_Cross.m_vXAxis ); SetMoveVectorZ( m_Cross.m_vZAxis ); if ( m_bTimeMonster && !IsDie() ) { m_nDestroyTime -= (LOCAL_TIME)(fDelta*1000.0f); if( m_nDestroyTime <= 0 ) CmdSuicide( false, false ); } // ¼ÒȯÀÚ°¡ Á×¾úÀ» ¶§ °°ÀÌ Á×µµ·Ï µÇ¾îÀÖ´Ù¸é Ã¼Å©ÇØ¼­ °°ÀÌ Á״´Ù. if( m_bSuicideWhenSummonerDie ) { // ¼ÒȯÀÚÀÇ ¾×ÅÍ °´Ã¼°¡ »ç¶óÁ³°Å³ª Á×¾úÀ» ¶§.. if( !m_hSummonerPlayerActor || m_hSummonerPlayerActor->IsDie() ) { CmdSuicide( false, false ); } } // ÀÏÁ¤ °Å¸® ÀÌ»ó ¹ú¾îÁö¸é Á×°Ô µÇ¾îÀÖ´Ù¸é ±×·¸°Ô ó¸®ÇÑ´Ù. if( 0.0f < m_fLimitSummonerDistanceSQ ) { if( m_hSummonerPlayerActor && false == m_hSummonerPlayerActor->IsDie() ) { EtVector3 vSummonerPos = *m_hSummonerPlayerActor->GetPosition(); float fNowDistanceSQ = EtVec3LengthSq( &(vSummonerPos - *GetPosition()) ); if( m_fLimitSummonerDistanceSQ < fNowDistanceSQ ) { CmdSuicide( false, false ); } } } ProcessPositionRevision( fDelta ); ProcessPartyCombo( LocalTime, fDelta ); #ifdef PRE_ADD_MONSTER_CATCH ProcessCatchActor( LocalTime, fDelta ); #endif // #ifdef PRE_ADD_MONSTER_CATCH Process_AutoRecallRange(); PROFILE_TIME_TEST_BLOCK_END(); } void CDnMonsterActor::ProcessAI(LOCAL_TIME LocalTime, float fDelta) { if( MATransAction::GetGameRoom() ) { MAAiReceiver::Process( LocalTime, fDelta ); } } void CDnMonsterActor::OnDamage( CDnDamageBase *pHitter, SHitParam &HitParam, HitStruct *pHitStruct ) { int nSeed = CRandom::Seed(GetRoom()); _srand( GetRoom(), nSeed ); INT64 nTemp = GetHP(); CDnActor::OnDamage( pHitter, HitParam, pHitStruct ); INT64 nDamage = nTemp - GetHP(); switch( pHitter->GetDamageObjectType() ) { case DamageObjectTypeEnum::Actor: { // Aggro Process //DnActorHandle hActor = dynamic_cast(pHitter)->GetMySmartPtr(); DnActorHandle hActor = pHitter->GetActorHandle(); if( m_pAggroSystem ) m_pAggroSystem->OnDamageAggro( hActor, HitParam, (int)nDamage ); ResetCustomAction(); // È­»ì°°Àº°æ¿ì ¹«±â°¡ Çÿ¡À̵Ǹ鼭 ¹ß»çµÇ±â ¶§¹®¿¡ Hit ½Ã Idle ¸¦ ÇØÁØ´Ù. if( GetWeapon() ) { if( GetWeapon()->GetElementIndex( "Idle" ) != -1 ) GetWeapon()->SetActionQueue( "Idle" ); } if( HitParam.HitType != CDnWeapon::Defense ) OnPartyCombo( hActor, pHitStruct->nPartyComboDelay ); } break; case DamageObjectTypeEnum::Prop: break; } RequestDamage( pHitter, nSeed, nDamage ); } void CDnMonsterActor::OnDie( DnActorHandle hHitter ) { CDnActor::OnDie( hHitter ); CDnPartyTask *pTask = (CDnPartyTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "PartyTask" ); if( !pTask ) return; #ifdef PRE_FIX_REMOVE_AURA_ONDIE if (IsEnabledAuraSkill()) OnSkillAura(m_hAuraSkill, false); #endif if( m_hSummonerPlayerActor ) { _ASSERT( m_hSummonerPlayerActor->IsPlayerActor() ); if( m_hSummonerPlayerActor->IsPlayerActor() ) { CDnPlayerActor* pPlayerActor = static_cast(m_hSummonerPlayerActor.GetPointer()); pPlayerActor->OnDieSummonedMonster( GetMySmartPtr() ); } } CDnPlayerActor* pMasterPlayerActor = NULL; if (hHitter) { if (hHitter->IsPlayerActor()) pMasterPlayerActor = static_cast(hHitter.GetPointer()); else if (hHitter->IsMonsterActor()) { CDnMonsterActor* pMonster = static_cast(hHitter.GetPointer()); if (pMonster && pMonster->IsCannonMonsterActor()) { CDnCannonMonsterActor* pCannonMonster = static_cast(hHitter.GetPointer()); if (pCannonMonster && pCannonMonster->GetMasterPlayerActor() && pCannonMonster->GetMasterPlayerActor()->IsPlayerActor()) pMasterPlayerActor = static_cast(pCannonMonster->GetMasterPlayerActor().GetPointer()); } } } int nPartyCount = pTask->GetRoom()->GetUserCount() - pTask->GetRoom()->GetGMCount(); // °æÇèÄ¡ ºÐ¹èÇØÁֽðí. µ·µµ Add ÇØÁֽðí.. // float fValue = ( ( 1.f + ( 0.9f * ( nPartyCount - 1 ) ) ) / nPartyCount ); float fExpPenalty; float fExp; int nValue; float fCompleteExp; float fItemExp = 0.f; float fGuildRewardExp = 0.f; float fDeadDurabilityRevision = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::MonsterDeadDurabilityRevision ); int nDeadDurability = (int)( ( GetDeadDurability() * ( 1.f + ( fDeadDurabilityRevision * ( nPartyCount - 1 ) ) ) ) / nPartyCount ); int nFinalDeadDurability = nDeadDurability; for( int i=0; iGetRoom()->GetUserData(i); if( !pSession ) continue; // ¿î¿µÀÚ³­ÀÔÀº °æÇèÄ¡¸¦ ¸ÔÁö ¾Ê°Ô ÇØÁØ´Ù. if( pSession->bIsGMTrace() ) continue; DnActorHandle hActor = pSession->GetActorHandle(); if( !hActor ) continue; pSession->GetEventSystem()->OnEvent( EventSystem::OnKillMonster2, 1, EventSystem::MonsterID, GetMonsterClassID() ); // »ç¸Á½Ã °æÇèÄ¡ nValue = hActor->GetLevel() - GetLevel(); fExpPenalty = 1.f - ( ( pow( max( nValue - 1, 0.f ), CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ExpPenaltyValue1 ) ) ) * CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ExpPenaltyValue2 ) ); fExpPenalty = max( fExpPenalty, CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ExpPenaltyMin ) ); float fExpPartyBonus = CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ExpPartyBonus ); fExp = GetDeadExperience() * ( 1.f + ( fExpPartyBonus * ( nPartyCount - 1 ) ) ) / nPartyCount * fExpPenalty; float fEventBonusExp = pTask->GetRoom()->GetEventExpWhenMonsterDie(fExp, pSession->GetFriendBonus(), pSession->GetClassID(), pSession->GetUserJob()); #ifdef PRE_ADD_BEGINNERGUILD fEventBonusExp += (pTask->GetRoom()->GetPartyStructData().bPartyBeginnerGuild == true && pSession->CheckBegginerGuild()) ? (float)((fExp * (float)((float)(BeginnerGuild::Common::PartyBonusRate)/100)) + 0.5f) : 0; #endif //#ifdef PRE_ADD_BEGINNERGUILD #if defined(PRE_ADD_TOTAL_LEVEL_SKILL) float fIncExpRate = 0.0f; if (hActor && hActor->IsAppliedThisStateBlow(STATE_BLOW::BLOW_255)) { DNVector(DnBlowHandle) vlBlows; hActor->GatherAppliedStateBlowByBlowIndex(STATE_BLOW::BLOW_255, vlBlows); { int nCount = (int)vlBlows.size(); for (int i = 0; i < nCount; ++i) { DnBlowHandle hBlow = vlBlows[i]; if (hBlow && hBlow->IsEnd() == false) { fIncExpRate += hBlow->GetFloatValue(); } } } } float fAddBlowExp = fExp * fIncExpRate; fEventBonusExp += fAddBlowExp; #endif // PRE_ADD_TOTAL_LEVEL_SKILL #if defined(PRE_ADD_WEEKLYEVENT) if (CDnWorld::GetInstance(GetRoom()).GetMapSubType() != EWorldEnum::MapSubTypeNest){ int nThreadID = GetGameRoom()->GetServerID(); if (pTask->GetRoom()->GetPartyUpkeepCount() > 0){ float fEventValue = g_pDataManager->GetWeeklyEventValuef(WeeklyEvent::Player, pSession->GetClassID(), WeeklyEvent::Event_6, nThreadID); if (fEventValue != 0) fEventBonusExp += fEventValue; } if (pSession->GetFriendBonus()){ float fEventValue = g_pDataManager->GetWeeklyEventValuef(WeeklyEvent::Player, pSession->GetClassID(), WeeklyEvent::Event_7, nThreadID); if (fEventValue != 0) fEventBonusExp += fEventValue; } } #endif // #if defined(PRE_ADD_WEEKLYEVENT) // ¿Ï·á½Ã °æÇèÄ¡ ó¸®ÈÄ »ç¸Á ÆÇÁ¤À» ÁøÇàÇÑ´Ù. fCompleteExp = GetCompleteExperience() * ( 1.f + ( fExpPartyBonus * ( nPartyCount - 1 ) ) ) / nPartyCount * fExpPenalty; CDnPlayerActor *pPlayer = static_cast(hActor.GetPointer()); if( pPlayer->GetAddExp() > 0.f ) fItemExp = GetDeadExperience()*pPlayer->GetAddExp(); float fGuildCompleteExp = 0.f; int nGuildRewardValue = pSession->GetGuildRewardItemValue(GUILDREWARDEFFECT_TYPE_EXTRAEXP); if( nGuildRewardValue > 0 ) { fGuildRewardExp = (float)(GetDeadExperience() * (nGuildRewardValue * 0.01)); fGuildCompleteExp = (float)(fCompleteExp * (nGuildRewardValue * 0.01)); } else fGuildRewardExp = 0; fCompleteExp += ( (fCompleteExp*pPlayer->GetAddExp()) + fGuildCompleteExp ); pPlayer->AddCompleteExperience((int)fCompleteExp); if (hActor->IsDie()) continue; MasterSystem::CRewardSystem* pMasterRewardSystem = pSession->GetGameRoom()->GetMasterRewardSystem(); if( pMasterRewardSystem ) { float fBonusRate = pMasterRewardSystem->GetExpRewardRate( pSession ); if( fBonusRate > 0.f ) { fEventBonusExp += (fExp*fBonusRate); int iMasterAddExp = 0; iMasterAddExp = pMasterRewardSystem->GetMasterSystemAddExp(pSession, fExp, false); fEventBonusExp += iMasterAddExp; #if defined( _WORK ) WCHAR wszBuf[MAX_PATH]; wsprintf( wszBuf, L"[»çÁ¦½Ã½ºÅÛ] Ãß°¡ °æÇèÄ¡ %d, ½º½Â:%d", static_cast(fExp*fBonusRate), iMasterAddExp ); pSession->SendDebugChat( wszBuf ); #endif // #if defined( _WORK ) } } if( pSession->GetPeriodExpItemRate() > 0 ) { fEventBonusExp += (fExp* (float)(pSession->GetPeriodExpItemRate()/100.0f)); #if defined( _WORK ) WCHAR wszBuf[MAX_PATH]; wsprintf( wszBuf, L"[°æÇèÄ¡Ãß°¡¾ÆÀÌÅÛ] Ãß°¡ °æÇèÄ¡ %d", static_cast(fExp* (float)(pSession->GetPeriodExpItemRate()/100.0f)) ); pSession->SendDebugChat( wszBuf ); #endif // #if defined( _WORK ) } float fPcBangExp = 0.0f; if (pSession->IsPCBang() && pSession->GetPcBangBonusExp() > 0 && fExp > 0.f ) fPcBangExp = (float)((fExp * (float)((float)(pSession->GetPcBangBonusExp())/100)) + 0.5f); float fPromotionBonusExp = 0.0f; if( fExp > 0.f ) fPromotionBonusExp = (float)((fExp * (float)((float)(pSession->GetPromotionValue(PROMOTIONTYPE_MONSTERKILL))/100)) + 0.5f); float fVIPExp = 0.0f; #if defined(PRE_ADD_VIP) if (pSession->IsVIP() && pSession->GetVIPBonusExp() > 0 && fExp > 0.f ) fVIPExp = (float)((fExp * (float)((float)(pSession->GetVIPBonusExp())/100)) + 0.5f); #endif // #if defined(PRE_ADD_VIP) TExpData ExpData; ExpData.set( fExp, fEventBonusExp, fPcBangExp, fVIPExp, fPromotionBonusExp, fItemExp, fGuildRewardExp ); #if defined( PRE_USA_FATIGUE ) pPlayer->CmdAddExperience( ExpData, DBDNWorldDef::CharacterExpChangeCode::DungeonMonster, pPlayer->GetUserSession()->GetPartyID() ); #else pPlayer->CmdAddExperience( ExpData, DBDNWorldDef::CharacterExpChangeCode::Dungeon, pPlayer->GetUserSession()->GetPartyID() ); #endif // #if defined( PRE_USA_FATIGUE ) // ¸¸·¦ º¸³Ê½º °æÇèÄ¡ÀÔ´Ï´Ù. ¹Ýµå½Ã À§¿¡ Ãß°¡µÇ¸é ¿©±âµµ ´õÇØ¼­ ÇØÁÖ¼¼¿ä. pPlayer->UpdateMaxLevelGainExperience( (int)( fExp + fEventBonusExp + fPcBangExp ) ); int nGuildRewardItemValue = pSession->GetGuildRewardItemValue(GUILDREWARDEFFECT_TYPE_REDUCEDURABILITYRATIO); if( nGuildRewardItemValue > 0 ) nFinalDeadDurability -= (int)(nFinalDeadDurability * nGuildRewardItemValue * 0.01); // ÆÄƼ¿ø ³»±¸µµ °¨¼Ò pPlayer->OnDecreaseEquipDurability( nFinalDeadDurability, false ); if (pMasterPlayerActor) { pSession->GetEventSystem()->OnEvent( EventSystem::OnKillMonster, 3, EventSystem::MonsterID, GetMonsterClassID(), EventSystem::MonsterGrade, GetGrade(), EventSystem::MonsterRaceID, GetRaceID()); } } // pTask->GetRoom()->AddCompleteExperience( GetCompleteExperience() ); if( m_bEnableDropItem ) DropItems(); if( IsSlowByDie() ) { CDnGameTask *pGameTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" ); if( pGameTask ) pGameTask->RequestChangeGameSpeed( 0.2f, 3000 ); } if (m_pAggroSystem) { int wholeAggro = m_pAggroSystem->GetAggroSum(); std::list& aggroList = m_pAggroSystem->GetAggroList(); std::list::iterator iter = aggroList.begin(); for( ; iter!=aggroList.end() ; ++iter) { CDNAggroSystem::AggroStruct& curAggro = *iter; if (curAggro.hActor && curAggro.hActor->IsPlayerActor()) { CDnPlayerActor* pActor = static_cast(curAggro.hActor.GetPointer()); pActor->UpdateAssistScore(curAggro.iAggro, wholeAggro); } } } if (GetGameRoom()) { GetGameRoom()->OnDie(GetActorHandle(), hHitter); } #ifdef PRE_ADD_MONSTER_CATCH if( false == m_vlCatchedActors.empty() ) { ReleaseAllActor(); } #endif // #ifdef PRE_ADD_MONSTER_CATCH } void CDnMonsterActor::ProcessDie( LOCAL_TIME LocalTime, float fDelta ) { CDnActor::ProcessDie( LocalTime, fDelta ); } void CDnMonsterActor::DropItems() { DNVector(CDnItem::RealDropItemStruct) vRealDropItemList; vRealDropItemList.reserve( m_VecDropItemList.size() ); int iPercent = HackPenanty::Common::MaxRate - GetGameRoom()->GetHackPenalty(); for( DWORD i=0; inSeed % 360 ) / (float)m_VecDropItemList.size() ) * i ); if( _rand(GetRoom())%HackPenanty::Common::MaxRate < iPercent ) { vRealDropItemList.push_back( CDnItem::RealDropItemStruct(*pStruct, nRotate) ); } else { g_Log.Log(LogType::_DROPITEMPENALTY, L"[%d] RoomID=%d HackPenalty=%d ItemID=%d Miss!!!\n", g_Config.nManagedID, GetGameRoom()->GetRoomID(), GetGameRoom()->GetHackPenalty(), pStruct->nItemID ); } } #if defined( PRE_FATIGUE_DROPITEM_PENALTY ) if( CDnWorld::GetInstance(GetRoom()).GetMapSubType() == EWorldEnum::MapSubTypeNone) { int iFatigueDropPercent = GetGameRoom()->GetFatigueDropRate(); if( iFatigueDropPercent < 100 ) { for( UINT i=0 ; i= iFatigueDropPercent ) { vRealDropItemList.erase( vRealDropItemList.begin()+i ); --i; } } } } #endif // #if defined( PRE_FATIGUE_DROPITEM_PENALTY ) EtVector3 vPos = *GetPosition(); for( DWORD i=0 ; idwUniqueID, pStruct->nItemID, pStruct->nSeed, pStruct->cOption, pStruct->nCount, pStruct->nRotate, -1, pStruct->nEnchantID ); #else // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD) CDnDropItem::DropItem( GetRoom(), vPos, pStruct->dwUniqueID, pStruct->nItemID, pStruct->nSeed, pStruct->cOption, pStruct->nCount, pStruct->nRotate ); #endif // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD) } if( !vRealDropItemList.empty() ) { for( DWORD i=0; iGetUserCount(); i++ ) { CDNUserSession* pGameSession = GetGameRoom()->GetUserData(i); if( pGameSession && pGameSession->GetState() == SESSION_STATE_GAME_PLAY ) SendGameDropItemList( pGameSession, vPos, vRealDropItemList ); } } SAFE_DELETE_VEC( m_VecDropItemList ); } void CDnMonsterActor::OnDrop( float fCurVelocity ) { if( IsAir() ) { if( !IsHit() ) { char szStr[64]; sprintf_s( szStr, "%s_Landing", GetCurrentAction() ); if( IsExistAction( szStr ) ) { SetActionQueue( szStr, 0, 2.f, 0.f, true, false ); // ½ºÅ³ »ç¿ëÁßÀ϶© üÀÎ¾×¼Ç ¼ÂÆÃÇØÁØ´Ù. if( m_hProcessSkill ) { m_hProcessSkill->AddUseActionName( szStr ); m_hProcessSkill->OnChainInput( szStr ); } } SetMovable( false ); } else if( !IsDie() ) { std::string szAction; float fBlendFrame = 2.f; // ¶³¾îÁö´Â ¼Óµµ°¡ 10ÀÌ»óÀ̸é bigBounce·Î Çѹø ´õ ¶ç¾îÁØ´Ù. if( fCurVelocity < -6.f && m_HitParam.vVelocity.y != 0.f && abs(m_HitParam.vVelocity.y) > 0.1f ) { if( m_HitParam.vVelocity.y > 0.f ) { m_HitParam.vVelocity.y *= 0.6f; SetVelocityY( m_HitParam.vVelocity.y ); } else { // °¡¼Óµµ°¡ óÀ½ºÎÅÍ ¹Ù´ÚÀ¸·Î ÇâÇØÀÖ´Â °æ¿ì¿¡´Â µÚÁý¾îÁà¾ßÇÑ´Ù. m_HitParam.vVelocity.y *= -0.6f; if( m_HitParam.vResistance.y > 0.f ) m_HitParam.vResistance.y *= -1.f; SetVelocityY( m_HitParam.vVelocity.y ); if( m_HitParam.vVelocity.y > 0 && m_HitParam.vResistance.y <= 0 ) SetResistanceY( -15.0f ); else SetResistanceY( m_HitParam.vResistance.y ); } szAction = "Hit_AirBounce"; } else { szAction = "Down_SmallBounce"; fBlendFrame = 0.f; } SetActionQueue( szAction.c_str(), 0, fBlendFrame, 0.f, true, false ); } } } void CDnMonsterActor::OnStop( EtVector3 &vPosition ) { if( IsDie() ) return; if( IsMove() ) CmdStop( "Stand" ); if( m_pAi ) m_pAi->OnStop(vPosition); } void CDnMonsterActor::OnBeginNaviMode() { if( IsDie() ) return; std::string strPrevAction = m_hActor->GetCurrentAction(); bool bPrevIsMove = false; if( IsMove() && !IsNaviMode() ) { bPrevIsMove = true; CmdStop( "Stand" ); } if( m_pAi ) m_pAi->OnBeginNaviMode( strPrevAction.c_str(), bPrevIsMove ); } void CDnMonsterActor::CmdMove( EtVector3 &vPos, const char *szActionName, int nLoopCount, float fBlendFrame ) { if( !IsMovable() ) return; MovePos( vPos, true ); if( SetActionQueue( szActionName, nLoopCount, fBlendFrame, 0.f, true ) == false ) return; BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); int nActionIndex = GetElementIndex( szActionName ); Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &EtVec3toVec2( *GetMoveVectorZ() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Send( eActor::SC_CMDMOVE, &Stream ); ResetPositionRevision(); } void CDnMonsterActor::CmdMove( DnActorHandle hActor, float fMinDistance, const char *szActionName, int nLoopCount, float fBlendFrame ) { if( !IsMovable() ) return; bool bIsNaviMode = m_hActor->IsNaviMode(); MoveTarget( hActor, fMinDistance ); if( SetActionQueue( szActionName, nLoopCount, fBlendFrame, 0.f, !bIsNaviMode ) == false ) return; BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); int nActionIndex = GetElementIndex( szActionName ); DWORD dwUniqueID = hActor->GetUniqueID(); Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Write( &dwUniqueID, sizeof(DWORD) ); Stream.Write( &fMinDistance, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 1.f ); Stream.Write( &EtVec3toVec2( *GetMoveVectorZ() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Send( eActor::SC_CMDMOVETARGET, &Stream ); ResetPositionRevision(); } bool CDnMonsterActor::_bIsCheckVaildPosition( EtVector3& vTargetPos ) { // Ÿ°Ù ³×ºñ°ÔÀÌ¼Ç ¹üÀ§ °Ë»ç CEtWorldGrid* pGrid = INSTANCE(CDnWorld).GetGrid(); if( IsMovable() && pGrid ) { NavigationMesh* pNavMesh = pGrid->GetNavMesh( vTargetPos ); if( pNavMesh ) { NavigationCell* pCurCell = pNavMesh->FindClosestCell( vTargetPos ); if( pCurCell && pCurCell->IsPointInCellCollumn( vTargetPos ) ) return true; } } if( !IsDie() ) CmdStop( "Stand" ); return false; } void CDnMonsterActor::_SendCmdMoveNavi( EtVector3& vTargetPos, float fMinDistance, const char* szActionName, int nLoopCount ) { BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); int nActionIndex = GetElementIndex( szActionName ); Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Write( &vTargetPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &fMinDistance, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 1.f ); Stream.Write( &EtVec3toVec2( *GetMoveVectorZ() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Send( eActor::SC_CMDMOVETARGET_NAVI, &Stream ); } void CDnMonsterActor::CmdMoveNavi( DnActorHandle hActor, float fMinDistance, const char *szActionName, int nLoopCount, float fBlendFrame ) { // Ÿ°ÙÀÌ ³×ºñ°ÔÀÌ¼Ç ¹Û¿¡ ÀÖ´ÂÁö °Ë»ç if( !_bIsCheckVaildPosition( *hActor->GetPosition() ) ) return; // bool bAlreadyNaviMode = m_hActor->IsNaviMode(); MoveTargetNavi( hActor, fMinDistance, szActionName ); if( !m_hActor->IsNaviMode() ) return CmdStop( "Stand" ); if( (bAlreadyNaviMode && GetWayPointSize() <= 2) ) return CmdStop( "Stand" ); if( SetActionQueue( szActionName, -1, fBlendFrame, 0.f, !bAlreadyNaviMode ) == false ) return; // ÆÐŶ _SendCmdMoveNavi( *hActor->GetPosition(), fMinDistance, szActionName, nLoopCount ); ResetPositionRevision(); } void CDnMonsterActor::CmdMoveNavi( EtVector3& vTargetPos, float fMinDistance, const char *szActionName, int nLoopCount, float fBlendFrame ) { // Ÿ°ÙÀÌ ³×ºñ°ÔÀÌ¼Ç ¹Û¿¡ ÀÖ´ÂÁö °Ë»ç if( !_bIsCheckVaildPosition( vTargetPos ) ) return; // bool bAlreadyNaviMode = m_hActor->IsNaviMode(); MoveTargetNavi( vTargetPos, fMinDistance, szActionName ); if( !m_hActor->IsNaviMode() ) return CmdStop( "Stand" ); if( SetActionQueue( szActionName, -1, fBlendFrame, 0.f, !bAlreadyNaviMode ) == false ) return; // ÆÐŶ _SendCmdMoveNavi( vTargetPos, fMinDistance, szActionName, nLoopCount ); ResetPositionRevision(); } void CDnMonsterActor::CmdStop( const char *szActionName, int nLoopCount, float fBlendFrame, float fStartFrame ) { if( SetActionQueue( szActionName, nLoopCount, fBlendFrame, fStartFrame, true ) == false ) return; ResetMove(); ResetLook(); BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); int nActionIndex = GetElementIndex( szActionName ); Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Send( eActor::SC_CMDSTOP, &Stream ); ResetPositionRevision(); } void CDnMonsterActor::CmdAction( const char *szActionName, int nLoopCount /*= 0*/, float fBlendFrame /*= 3.f*/, bool bCheckOverlapAction /*= true*/, bool bFromStateBlow /*= false */, bool bSkillChain/* = false*/ ) { // mp ¼Ò¸ð ½ºÅ³ »ç¿ë ºÒ°¡ »óÅÂÈ¿°ú°¡ ¸ó½ºÅÍ¿¡°Ô´Â attack state ÀÖ´Â ¾×¼ÇÀ» »ç¿ëÄ¡ ¸øÇϵµ·Ï 󸮵Ê. (#13032) if( m_pStateBlow->IsApplied( STATE_BLOW::BLOW_078 ) ) { if( IsAttack( szActionName ) ) return; } if( SetActionQueue( szActionName, nLoopCount, fBlendFrame, 0.f, bCheckOverlapAction ) == false ) return; int nActionIndex = GetElementIndex( szActionName ); bool bAILook = bIsAILook(); BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Write( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Stream.Write( &fBlendFrame, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 1.f ); Stream.Write( &bAILook, sizeof(bool) ); if( bAILook ) Stream.Write( m_pAi->GetAILook(), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); else Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &bFromStateBlow, sizeof(bool) ); #if defined( PRE_FIX_MOVEBACK ) bool bNearMoveBack = IsPrevMoveBack(); Stream.Write( &bNearMoveBack, sizeof(bool)); #endif Send( eActor::SC_CMDACTION, &Stream ); ResetPositionRevision(); } void CDnMonsterActor::CmdLook( EtVector2 &vVec, bool bForce ) { Look( vVec, bForce ); BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); Stream.Write( &vVec, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( &bForce, sizeof(bool) ); Send( eActor::SC_CMDLOOK, &Stream ); } void CDnMonsterActor::CmdLook( DnActorHandle hActor, bool bLock ) { if( bLock ) LookTarget( hActor ); else { if( !hActor ) ResetLook(); else { EtVector2 vVec; vVec.x = hActor->GetPosition()->x - GetPosition()->x; vVec.y = hActor->GetPosition()->z - GetPosition()->z; EtVec2Normalize( &vVec, &vVec ); Look( vVec ); } } BYTE pBuffer[128]; CMemoryStream Stream( pBuffer, 128 ); DWORD dwUniqueID = ( hActor ) ? hActor->GetUniqueID() : -1; Stream.Write( &dwUniqueID, sizeof(DWORD) ); Stream.Write( &bLock, sizeof(bool) ); Send( eActor::SC_CMDLOOKTARGET, &Stream ); } int CDnMonsterActor::CmdAddStateEffect( const CDnSkill::SkillInfo* pParentSkill, STATE_BLOW::emBLOW_INDEX emBlowIndex, int nDurationTime, const char *szParam, bool bOnPlayerInit/* = false*/, bool bCheckCanBegin/* = true*/ , bool bEternity /* = false */ ) { int iID = CDnActor::CmdAddStateEffect( pParentSkill, emBlowIndex, nDurationTime, szParam, bOnPlayerInit, bCheckCanBegin , bEternity ); if( -1 == iID ) return -1; DnBlowHandle hAddedBlow = m_pStateBlow->GetStateBlowFromID( iID ); const CPacketCompressStream* pPacketStream = hAddedBlow->GetPacketStream( szParam, false ); Send( eActor::SC_CMDADDSTATEEFFECT, const_cast(pPacketStream) ); return iID; } void CDnMonsterActor::CmdRemoveStateEffect( STATE_BLOW::emBLOW_INDEX emBlowIndex, bool bRemoveFromServerToo/* = true*/ ) { if( m_pStateBlow->IsApplied( emBlowIndex ) ) { if( bRemoveFromServerToo ) CDnActor::CmdRemoveStateEffect( emBlowIndex ); SendRemoveStateEffect( emBlowIndex ); } } void CDnMonsterActor::SendRemoveStateEffect( STATE_BLOW::emBLOW_INDEX emBlowIndex ) { BYTE pBuffer[32]; CPacketCompressStream Stream( pBuffer, 32 ); Stream.Write( &emBlowIndex, sizeof(STATE_BLOW::emBLOW_INDEX) ); Send( eActor::SC_CMDREMOVESTATEEFFECT, &Stream ); } void CDnMonsterActor::CmdSuicide( bool bDropItem, bool bDropExp ) { if( IsDie() ) return; SetDestroy(); if( m_hSummonerPlayerActor ) { _ASSERT( m_hSummonerPlayerActor->IsPlayerActor() ); if( m_hSummonerPlayerActor->IsPlayerActor() ) { CDnPlayerActor* pPlayerActor = static_cast(m_hSummonerPlayerActor.GetPointer()); pPlayerActor->OnDieSummonedMonster( GetMySmartPtr() ); } } if( bDropExp ) { EnableDropItem( bDropItem ); OnDie( DnActorHandle() ); } else { if( bDropItem ) DropItems(); } BYTE pBuffer[32]; CPacketCompressStream Stream( pBuffer, 32 ); Stream.Write( &bDropItem, sizeof(bool) ); Stream.Write( &bDropExp, sizeof(bool) ); Send( eActor::SC_CMDSUICIDE, &Stream ); } void CDnMonsterActor::CmdMixedAction( const char *szActionBone, const char *szMaintenanceBone, const char *szActionName, float fFrame, float fBlendFrame ) { int nActionIndex = GetElementIndex( szActionName ); int nMaintenanceBoneIndex = GetBoneIndex( szMaintenanceBone ); int nActionBoneIndex = GetBoneIndex( szActionBone ); int nBlendAniIndex = m_nAniIndex; if( nActionIndex == -1 ) { assert(0); } if( nActionBoneIndex == -1 || nMaintenanceBoneIndex == -1 ) return; BYTE pBuffer[128] = {0,}; CPacketCompressStream Stream( pBuffer, 128 ); Stream.Write( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Write( &nActionBoneIndex, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Stream.Write( &nMaintenanceBoneIndex, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Stream.Write( &fFrame, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 10.f ); Stream.Write( &fBlendFrame, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 10.f ); Send( eActor::SC_CMDMIXEDACTION, &Stream ); } void CDnMonsterActor::CmdWarp( EtVector3 &vPos, EtVector2 &vLook, CDNUserSession* pGameSession, bool bCheckPlayerFollowSummonedMonster/*=false*/ ) { CDnActor::CmdWarp( vPos, vLook, pGameSession, bCheckPlayerFollowSummonedMonster ); MAWalkMovementNav *pMovement = dynamic_cast(GetMovement()); if( pMovement ) pMovement->ValidateCurCell(); } void CDnMonsterActor::GenerationDropItem() { m_VecDropItemList.clear(); if( m_nItemDropGroupTableID < 1 ) return; int nExtendDropRate = 0; GetGameRoom()->GetExtendDropRateIgnoreTime(nExtendDropRate); #if defined(PRE_ADD_WORLD_EVENT) #else #if defined(PRE_ADD_WEEKLYEVENT) if (CDnWorld::GetInstance(GetRoom()).GetMapSubType() != EWorldEnum::MapSubTypeNest){ int nThreadID = GetGameRoom()->GetServerID(); int nEventValue = g_pDataManager->GetWeeklyEventValue(0, 0, WeeklyEvent::Event_10, nThreadID); if (nEventValue != 0) nExtendDropRate += nEventValue; } #endif // #if defined(PRE_ADD_WEEKLYEVENT) #endif //#if defined(PRE_ADD_WORLD_EVENT) #if defined( PRE_ADD_NEWCOMEBACK ) if( GetGameRoom() ) { if( GetGameRoom()->GetTaskMng() ) { CDnPartyTask* pPartyTask = (CDnPartyTask*)(GetGameRoom()->GetTaskMng()->GetTask("PartyTask")); if( pPartyTask ) { float fBlowValue = pPartyTask->GetPlayerDropUpBlowValue(); if( fBlowValue > 0 ) { fBlowValue = fBlowValue * 100; nExtendDropRate += (int)fBlowValue; } } } } #endif #if defined( PRE_ADD_STAGE_WEIGHT ) if( GetGameRoom() && GetGameRoom()->GetTaskMng() ) { CDnGameTask* pGameTask = static_cast(GetGameRoom()->GetTaskMng()->GetTask("GameTask")); if( pGameTask ) { const TStageWeightData * pStageWeightData = pGameTask->GetStageWeightData(); if( pStageWeightData ) { float fStageWeightBonus = pStageWeightData->fItemDropRate; fStageWeightBonus = fStageWeightBonus * 100; nExtendDropRate += (int)fStageWeightBonus; } } } #endif // #if defined( PRE_ADD_STAGE_WEIGHT ) float fCalcDropCount = ((float)((float)nExtendDropRate/100) + 1.0f); for (int h = 0; 0 < fCalcDropCount; h++) { CDnDropItem::CalcDropItemList( GetRoom(), m_AIDifficult, m_nItemDropGroupTableID, m_VecDropItemList ); for( DWORD i=0; i= 4 || (fCalcDropCount < 1.0f && ((float)(_rand(GetRoom())%100)/100) > fCalcDropCount)) break; //4°³ÀÌ»ó(À̺¥Æ®3°³)Àº ºÒ°¡ÇÏ°Ô Á¶Àý, 1º¸´Ù ÀÛÀº °ªÀÌ ³²Àº°æ¿ì È®À²°è»êÇÏ¿© ÇÑ´ø ´õµ¹Áö ÆÇ´Ü } } void CDnMonsterActor::SetGenerationArea( SOBB &Box ) { m_GenerationArea = Box; } SOBB *CDnMonsterActor::GetGenerationArea() { return &m_GenerationArea; } void CDnMonsterActor::SyncClassTime( LOCAL_TIME LocalTime ) { MAActorRenderBase::m_LocalTime = LocalTime; CDnActor::SyncClassTime( LocalTime ); } void CDnMonsterActor::OnChangeAction( const char *szPrevAction ) { if( m_pAi ) m_pAi->OnChangeAction( szPrevAction ); #ifdef PRE_ADD_AURA_FOR_MONSTER _CheckActionWithProcessPassiveActionSkill(szPrevAction); #endif } void CDnMonsterActor::_CheckActionWithProcessPassiveActionSkill( const char* szPrevAction ) { // °°Àº ¾×¼Ç ¹Ýº¹ÁßÀÌ¸é ÆÐ½º if( szPrevAction && m_nPrevActionIndex == m_nActionIndex ) return; // if instantly passive skill, then cancel skill. ( ex) archer's spinkick) // because state effect must deactivate when change to another attack action. if( m_hProcessSkill ) { m_setUseActionName.clear(); m_setUseActionName.insert( szPrevAction ); // ÇöÀç ¾×¼ÇÀÌ prev ¾×¼ÇÀÇ next ¾×¼ÇÀ̶ó¸é ½ºÅ³ÀÌ À̾îÁö´Â °ÍÀ¸·Î º»´Ù. // ÀÌÀü ¾×¼ÇÀÌ ÇöÀç ÁøÇàÁßÀÎ ½ºÅ³¿¡¼­ »ç¿ëÇÏ´Â ¾×¼ÇÀ̾ú°í ÇöÀç ¾×¼ÇÀÌ ÀÌÀü ¾×¼ÇÀÇ next ¾×¼ÇÀÌ ¾Æ´Ï¶ó¸é // ÆÐ½Ãºê ½ºÅ³ÀÌ ³¡³­ °ÍÀ¸·Î ÆÇ´ÜÇÑ´Ù. ActionElementStruct* pElement = GetElement( szPrevAction ); bool bIsNextAction = false; if( pElement ) { // #25154 ±âº» ½ºÅÄµå ¾×¼ÇÀº ½ºÅ³¿¡¼­ ÁöÁ¤µÈ next ¾×¼ÇÀÌ À̾îÁö´Â °ÍÀ¸·Î º¸Áö ¾Ê´Â´Ù. // ¿À¶ó ½ºÅ³ ¾×¼ÇÀÌ ³¡³ª°í ÀÌ ÇÔ¼ö°¡ È£ÃâµÇ¾úÀ» ¶§ ÇöÀç ¾×¼ÇÀÌ Stand ·Î µÇ¾îÀִµ¥ ÇØ´ç ½ÃÁ¡¿¡¼­ // m_hProcessSkill ÀÌ ½ºÅ³ÀÌ ³¡³­ °ÍÀ¸·Î ÆÇ´ÜµÇ¾î¼­ NULL ·Î µÇ¾î¾ß ÇÑ´Ù. // m_hProcessSkill ÀÌ ³²¾ÆÀÖÀ¸¸é ´Ù¸¥ ½ºÅ³ ½èÀ» ¶§ °­Á¦·Î onend µÉ ¼ö Àֱ⠶§¹®¿¡ ¾ÈµÊ. // µû¶ó¼­ bIsNextAction ÀÌ false °¡ µÇ°í m_hProcessSkill->IsUseSkillActionNames() ÇÔ¼ö ³»ºÎ¿¡¼­ // ½ºÅ³ ¾×¼ÇÀÌ Á¾·áµÈ °ÍÀ¸·Î ÆÇ´ÜµÇ¾î¾ß ÇÑ´Ù. bIsNextAction = ((pElement->szNextActionName != "Stand") && (pElement->szNextActionName == GetCurrentAction())); } if( false == bIsNextAction && m_hProcessSkill->IsUseActionNames( m_setUseActionName ) ) { if( (m_hProcessSkill->GetSkillType() == CDnSkill::Passive || m_hProcessSkill->GetSkillType() == CDnSkill::AutoPassive) && m_hProcessSkill->GetDurationType() == CDnSkill::Instantly ) { // ÆÐ½Ãºê ½ºÅ³ÀÌ Ã¼ÀÎ ÀÔ·ÂÀÌ µé¾î¿ÔÀ» ¶§¸¦ üũÇÑ´Ù. Çѹø üũµÇ´Â ¼ø°£ üÀÎ ÀÔ·Â Ç÷¡±×´Â ÃʱâÈ­µÈ´Ù. // üÀÎÀԷµǴ ¼ø°£ ¾×¼ÇÀÇ ±æÀ̸¸Å­ ÆÐ½Ãºê ½ºÅ³ »ç¿ë ±æÀ̰¡ ´Ã¾î³­´Ù. // ÀÌ·¸°Ô Ç÷¡±×¿Í ½Ã°£ µÑ ´Ù °°ÀÌ »ç¿ëÇØ¾ß ÆÐ½Ãºê ½ºÅ³ÀÇ ¿¬¼Ó üÀÎÀÌ °¡´ÉÇØÁø´Ù. if( false == m_hProcessSkill->CheckChainingPassiveSkill() ) { m_hProcessSkill->OnEnd( MAActorRenderBase::m_LocalTime, 0.0f ); m_hProcessSkill.Identity(); } } else // Note Çѱâ: m_hProcessSkill ½º¸¶Æ® Æ÷ÀÎÅÍ´Â ¿À¶ó ½ºÅ³ »ç¿ëÇÏ´Â ¾×¼ÇÀÌ Àç»ýµÇ´Â µ¿¾ÈÀº À¯È¿ÇØ¾ß // °ÔÀÓ ¼­¹ö¿¡¼­ CDnPlayerActor::CmdStop() ÂÊ¿¡¼­ °É·¯Áö±â ¶§¹®¿¡ °× ¼­¹ö¿¡¼­ ÇØ´ç ¾×¼Ç ½Ã±×³ÎÀÌ ³¡±îÁö // 󸮵Ê. µû¶ó¼­ CDnActor::OnChangeAction ÂÊ¿¡¼­ ProcessAction À» Identity ½ÃÅ´. if( IsEnabledAuraSkill() && m_hProcessSkill->IsAuraOn() ) { m_hProcessSkill.Identity(); ClearSelfStateSignalBlowQueue(); // ¿À¶ó ½ºÅ³ÀÇ ÀÚ±â Àڽſ¡°Ô Àû¿ëÇÏ´Â »óÅÂÈ¿°ú ŸÀÌ¹Ö ½Ã±×³Î¿¡ º¸³»Áִ ť ÃʱâÈ­ ½ÃÅ´. ¾È±×·³ ´Ù¸¥ ½ºÅ³¿¡ ¿µÇâÀ» ÁØ´Ù. } } } } void CDnMonsterActor::OnFinishAction(const char* szPrevAction, LOCAL_TIME time) { if( m_bChangeAxisOnFinishAction ) { EtVector2 vView = EtVec3toVec2( *GetLookDir() ); vView *= -1.f; Look( vView, true ); m_bChangeAxisOnFinishAction = false; } if( m_pAi ) m_pAi->OnFinishAction(szPrevAction, time); } void CDnMonsterActor::ResetActor() { if( m_pAi ) m_pAi->ResetDelay(); } void CDnMonsterActor::OnBeginStateBlow( DnBlowHandle hBlow ) { CDnActor::OnBeginStateBlow( hBlow ); if( m_pAggroSystem ) m_pAggroSystem->OnStateBlowAggro( hBlow ); } // MASkillUser #ifdef PRE_FIX_GAMESERVER_OPTIMIZE void CDnMonsterActor::OnAddSkill( DnSkillHandle hSkill, bool isInitialize/* = false*/ ) { // ÆÐ½Ãºê À̸鼭 ¹öÇÁ°í »óÅÂÈ¿°ú Self ·Î ºÙ¾îÀÖ´Â ½ºÅ³Àº °ð¹Ù·Î Àû¿ë½ÃÄÑ ÁÜ.. bool bPassiveBuff = false; bPassiveBuff = ApplyPassiveSkill( hSkill, isInitialize ); if( bPassiveBuff ) m_vlhSelfPassiveBlowSkill.push_back( hSkill ); } bool CDnMonsterActor::AddSkill( int nSkillTableID, int nLevel/* = 1*/, int iSkillLevelApplyType/* = CDnSkill::PVE*/ ) { if( IsExistSkill( nSkillTableID, nLevel ) ) return false; if( !MASkillUser::IsValidActor() ) return false; if( GetRoom() == NULL ) return false; DnSkillHandle hSkill = CDnSkill::CreateMonsterSkill( GetMySmartPtr(), nSkillTableID, nLevel ); if( !hSkill ) return false; #ifdef PRE_ADD_AURA_FOR_MONSTER CDnSkill::DurationTypeEnum eDurationType = hSkill->GetDurationType(); switch(eDurationType) { case CDnSkill::Aura: m_vlhAuraSkills.push_back(hSkill); } #endif #ifndef PRE_FIX_SKILLLIST m_vlhSkillList.push_back( hSkill ); m_vbSelfAllocList.push_back( true ); #else AddSkillObject( S_SKILL_OBJECT(hSkill, true) ); #endif // #ifndef PRE_FIX_SKILLLIST if( hSkill->GetActor() ) hSkill->SetHasActor( GetMySmartPtr() ); OnAddSkill( hSkill ); return true; } #endif // #ifdef PRE_FIX_GAMESERVER_OPTIMIZE bool CDnMonsterActor::ExecuteSkill( DnSkillHandle hSkill, LOCAL_TIME LocalTime, float fDelta ) { if ( CDnActor::ExecuteSkill(hSkill, LocalTime, fDelta) == false ) return false; BYTE pBuffer[128] = {0,}; CPacketCompressStream Stream( pBuffer, 128 ); int nSkillID = hSkill->GetClassID(); char cLevel = hSkill->GetLevel(); Stream.Write( &nSkillID, sizeof(int) ); Stream.Write( &cLevel, sizeof(char) ); Stream.Write( &EtVec3toVec2( *GetLookDir() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); #if defined( PRE_ADD_ACADEMIC ) int iSummonerSkillID = 0; DnSkillHandle hSummonerSkill = FindSkill( nSkillID ); if( hSummonerSkill ) iSummonerSkillID = hSummonerSkill->GetSummonerDecreaseSPSkillID(); Stream.Write( &iSummonerSkillID, sizeof(int) ); #endif // #if defined( PRE_ADD_ACADEMIC ) Send( eActor::SC_USESKILL, &Stream ); ResetPositionRevision(); return true; } CDnSkill::UsingResult CDnMonsterActor::UseSkill( int nSkillTableID, bool bCheckValid/* = true*/, bool bAutoUseFromServer/* = false*/, int nLuaSkillIndex/*=-1*/ ) { CDnSkill::UsingResult Result = MASkillUser::UseSkill( nSkillTableID, bCheckValid, bAutoUseFromServer ); if( Result == CDnSkill::UsingResult::Success && nLuaSkillIndex >= 0 ) { std::map::iterator itor = m_mUseSkillCount.find( nLuaSkillIndex ); if( itor == m_mUseSkillCount.end() ) { m_mUseSkillCount.insert( std::make_pair(nLuaSkillIndex,1) ); } else { ++(*itor).second; } } return Result; } int CDnMonsterActor::GetUseSkillCount( int iLuaSkillIndex ) { std::map::iterator itor = m_mUseSkillCount.find( iLuaSkillIndex ); if( itor != m_mUseSkillCount.end() ) return (*itor).second; return 0; } void CDnMonsterActor::SetScale( float fValue ) { m_fScale = fValue; if( m_hObject ) { m_hObject->SetCollisionScale( m_fScale ); } MAActorRenderBase::SetScale( EtVector3( m_fScale, m_fScale, m_fScale ) ); if( m_fWeight == 0.f ) m_fRevisionWeight = 0.f; else m_fRevisionWeight = m_fWeight + ( ( m_fScale - 1.f ) * CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::ScaleWeightValue ) ); } float CDnMonsterActor::GetWeight() { return m_fRevisionWeight; } float CDnMonsterActor::GetThreatRange() { _ASSERT( dynamic_cast(m_pAggroSystem) ); return m_pAggroSystem ? static_cast(m_pAggroSystem)->GetThreatRange() : 0.f; } float CDnMonsterActor::GetCognizanceThreatRange() { _ASSERT( dynamic_cast(m_pAggroSystem) ); return m_pAggroSystem ? static_cast(m_pAggroSystem)->GetCognizanceThreatRange() : 0.f; } float CDnMonsterActor::GetCognizanceThreatRangeSq() { _ASSERT( dynamic_cast(m_pAggroSystem) ); return m_pAggroSystem ? static_cast(m_pAggroSystem)->GetCognizanceThreatRangeSq() : 0.f; } std::string CDnMonsterActor::GetAIFileName() { DNTableFileFormat* pSox = NULL; int nItemID = 0; if( m_nMonsterWeightTableID == -1 ) { pSox = GetDNTable( CDnTableDB::TMONSTER ); nItemID = m_nMonsterClassID; } else { pSox = GetDNTable( CDnTableDB::TMONSTERWEIGHT ); nItemID = m_nMonsterWeightTableID; } if( !pSox || !pSox->IsExistItem( nItemID ) ) return std::string(""); std::string szName = pSox->GetFieldFromLablePtr( nItemID, "_CustomAI" )->GetString(); return szName; } void CDnMonsterActor::CalcMonsterWeightIndex() { if( m_nMonsterClassID == 0 ) return; DNTableFileFormat* pSox = GetDNTable( CDnTableDB::TMONSTERWEIGHT ); if( !pSox ) { g_Log.Log( LogType::_FILELOG, L"MonsterWeightTable.ext failed\r\n"); return; } std::vector nVecList; pSox->GetItemIDListFromField( "_MonsterTableIndex", m_nMonsterClassID, nVecList ); int nDifficulty; for( DWORD i=0; iGetFieldFromLablePtr( nVecList[i], "_Difficulty" )->GetInteger(); if( nDifficulty == m_AIDifficult ) { m_nMonsterWeightTableID = nVecList[i]; break; } } } void CDnMonsterActor::SetNaviDestination( SOBB* pOBB, UINT uiMoveFrontRate ) { if( m_pAi ) m_pAi->OnInitNaviDestination( pOBB, uiMoveFrontRate ); else _DANGER_POINT(); } int CDnMonsterActor::GetWaitOrderCount( int iSkillID ) { std::map::iterator itor = m_mOrderCount.find( iSkillID ); if( itor == m_mOrderCount.end() ) return 0; return (*itor).second; } void CDnMonsterActor::AddWaitOrderCount( int iSkillID ) { std::map::iterator itor = m_mOrderCount.find( iSkillID ); if( itor == m_mOrderCount.end() ) { m_mOrderCount.insert( std::make_pair(iSkillID,1) ); return; } ++(*itor).second; } void CDnMonsterActor::DelWaitOrderCount( int iSkillID ) { std::map::iterator itor = m_mOrderCount.find( iSkillID ); if( itor == m_mOrderCount.end() ) return; if( (*itor).second > 0 ) --(*itor).second; } bool CDnMonsterActor::OnAINonTarget() { // Walk_Font ¾×¼Ç °Ë»ç if( !IsExistAction( "Walk_Front") ) return true; if ( !IsHit() && IsMove() ) CmdStop( "Stand", 0, g_fBendFrame ); if ( !IsMovable() ) return false; // ¾î½½·· °Å¸°´Ù. EtVector3 *pvPos = m_hActor->GetPosition(); EtVector3 vTemp; vTemp = *pvPos; vTemp.y = 0.f; vTemp.x += cos( EtToRadian( _rand(m_hActor->GetRoom())%360 ) ) * ( 300 + _rand(m_hActor->GetRoom())%200 ); vTemp.z += sin( EtToRadian( _rand(m_hActor->GetRoom())%360 ) ) * ( 300 + _rand(m_hActor->GetRoom())%200 ); SOBB Box = *GetGenerationArea(); Box.Extent[1] = 1000000.f; if( !Box.IsInside( vTemp ) ) { vTemp = Box.Center; vTemp -= Box.Axis[0] * Box.Extent[0]; vTemp -= Box.Axis[2] * Box.Extent[2]; int iModValue = static_cast(Box.Extent[0] * 2.f); if( iModValue > 0 ) vTemp += Box.Axis[0] * (float)( _rand(m_hActor->GetRoom())%iModValue ); else vTemp += Box.Axis[0]; iModValue = static_cast(Box.Extent[2] * 2.f); if( iModValue ) vTemp += Box.Axis[2] * (float)( _rand(m_hActor->GetRoom())%iModValue ); else vTemp += Box.Axis[2]; vTemp.y = CDnWorld::GetInstance(m_hActor->GetRoom()).GetHeight( vTemp ); vTemp += Box.Axis[1] * Box.Extent[1]; } CmdMove( vTemp, "Walk_Front", -1, g_fBendFrame ); return true; } void CDnMonsterActor::OnBumpWall() { if( !m_pszCanBumpActionName ) return; CmdAction( m_pszCanBumpActionName, 0, g_fBendFrame ); } // ÆÐŶ º¸³»±â // ÀÌ ºÎºÐÀº CDnProjectile::GetPacketStream() À» ¾²Áö ¾Ê°í ¾×¼Ç À妽º¿Í ½Ã±×³Î À妽º ±âÁØÀ¸·Î ÆÐŶÀ» º¸³»¼­ // Ŭ¶óÀÌ¾ðÆ®°¡ ¹ß»çü ½Ã±×³Î Á¤º¸¸¦ ã¾Æ »ý¼ºÇÏ°Ô µÇ¾îÀִµ¥ ÀÏ´Ü ±×´ë·Î µÓ´Ï´Ù. // ÇöÀç´Â ¹®Á¦µÉ °ÍÀÌ ¾øÁö¸¸ ÃßÈÄ¿¡ ¼­¹ö¿¡¼­ °áÁ¤Çؼ­ º¸³»Áà¾ßÇÒ µ¥ÀÌÅͰ¡ »ý±ä´ÙµçÁö ÇÒ¶§ ¼öÁ¤ÇØ¾ß ÇÕ´Ï´Ù. - Çѱâ. void CDnMonsterActor::SendProjectile( CDnProjectile *pProjectile, ProjectileStruct* pStruct, MatrixEx& LocalCross, int iSignalIndex ) { BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); DWORD dwVal = pProjectile->GetUniqueID(); Stream.Write( &dwVal, sizeof(DWORD) ); Stream.Write( &LocalCross.m_vPosition, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &LocalCross.m_vXAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); Stream.Write( &LocalCross.m_vYAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); Stream.Write( &LocalCross.m_vZAxis, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); #if defined(PRE_FIX_55378) int nActionIndex = m_nActionIndex; std::string szChargerAction = GetChargerAction(); if (szChargerAction.empty() == false) nActionIndex = GetElementIndex(szChargerAction.c_str()); Stream.Write( &nActionIndex, sizeof(int) ); #else Stream.Write( &m_nActionIndex, sizeof(int) ); #endif // PRE_FIX_55378 Stream.Write( &iSignalIndex, sizeof(int) ); bool bUsedForceDir = pProjectile->IsUsedForceDir(); Stream.Write( &bUsedForceDir, sizeof(bool) ); if( bUsedForceDir ) { const EtVector3& vForceDir = pProjectile->GetForceDir(); Stream.Write( &vForceDir, sizeof(EtVector3), CPacketCompressStream::VECTOR3_SHORT ); } switch( pStruct->nTargetType ) { case 2: // TargetPosition { Stream.Write( pProjectile->GetTargetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); break; } case 3: // Target { DnActorHandle hTarget = pProjectile->GetTargetActor(); if( !hTarget ) hTarget = GetActorHandle(); dwVal = hTarget->GetUniqueID(); Stream.Write( &dwVal, sizeof(DWORD) ); break; } } Send( eActor::SC_PROJECTILE, &Stream ); } // #15557 À̽´ °ü·Ã. ¸ó½ºÅͰ¡ ¹ß»çü¿¡¼­ ¹ß»çü¸¦ ½î´Â °æ¿ì. // ±âº»ÀûÀ¸·Î Ŭ¶óÀ̾ðÆ®ÀÇ LocalPlayerActor °¡ º¸³»´Â ³»¿ë°ú °°´Ù. // Ŭ¶óÀÌ¾ðÆ® Ãø¿¡¼± ÆÄƼ¿øÀÌ ½ð ¹ß»çü¿Í ¿ª½Ã µ¿ÀÏÇÏ°Ô ÆÐŶÀ» ó¸®ÇÑ´Ù. // µû¶ó¼­ ¹Ýµå½Ã CDnLocalPlayerActor::OnProjectile() Âʵµ °°ÀÌ ¼öÁ¤ÇØ¾ß ÇÔ. void CDnMonsterActor::SendProjectileFromProjectile( CDnProjectile* pProjectile, int nSignalIndex ) { CPacketCompressStream* pPacketStream = pProjectile->GetPacketStream(); _ASSERT( pPacketStream ); if( pPacketStream ) Send( eActor::SC_MONSTER_PROJECTILE_FROM_PROJECTILE, pPacketStream ); } void CDnMonsterActor::OnSignal( SignalTypeEnum Type, void *pPtr, LOCAL_TIME LocalTime, LOCAL_TIME SignalStartTime, LOCAL_TIME SignalEndTime, int nSignalIndex ) { switch( Type ) { case STE_LockTargetLook: { #if defined( PRE_MOD_LOCK_TARGET_LOOK ) LockTargetLookStruct * pStruct = static_cast(pPtr); m_nLockLookEventArea = pStruct->LookEeventAreaID; #endif // PRE_MOD_LOCK_TARGET_LOOK #if defined( PRE_FIX_MOVEBACK ) if( !IsNearMoveBack() ) m_bLockLookTarget = true; #else m_bLockLookTarget = true; #endif break; } case STE_CanBumpWall: { CanBumpWallStruct* pStruct = static_cast(pPtr); m_pszCanBumpActionName = pStruct->szActionName; break; } case STE_Projectile: { ProjectileStruct* pStruct = (ProjectileStruct *)pPtr; // MultipleŸ°ÙÀ̸é Ãß°¡·Î ¼­¹ö¿¡¼­ Projectile »ý¼ºÇÏ¿© ¹ß»ç #if defined (PRE_MOD_AIMULTITARGET) if( static_cast(GetAIBase())->m_cMultipleTarget.GetMultipleTarget() > 0 ) #else if( static_cast(GetAIBase())->m_cMultipleTarget.bIsMultipleTarget() ) #endif { static_cast(GetAIBase())->m_cMultipleTarget.CreateProjectile( this, static_cast(pPtr), nSignalIndex ); } else { DNVector(DnActorHandle) StigmaActorList; if (pStruct->nTargetStateIndex != 0) { ScanActorByStateIndex(StigmaActorList, STATE_BLOW::BLOW_246); } //³«ÀÎ ´ë»óÀÌ ÀÖ´Â °æ¿ì¸¸ ó¸® if (StigmaActorList.empty() == false) { int nStigmaActorCount = (int)StigmaActorList.size(); for (int i = 0; i < nStigmaActorCount; ++i) { //Ÿ°Ù ¾×ÅÍ.. DnActorHandle hTargetActor = StigmaActorList[i]; CDnProjectile* pProjectile = CDnProjectile::CreateProjectile( GetRoom(), GetMySmartPtr(), m_Cross, pStruct, NULL, hTargetActor ); if( pProjectile == NULL ) return; pProjectile->SetShooterType( GetMySmartPtr(), m_nActionIndex, nSignalIndex ); SendProjectile( pProjectile, pStruct, m_Cross, nSignalIndex ); OnProjectile( pProjectile, pStruct, m_Cross, nSignalIndex ); OnSkillProjectile( pProjectile ); } } else { //#52808 - Ãß°¡ ¿äû (³«ÀÎ¿ë ¹ß»çü ¼³Á¤ÀÌ 2ÀÎ °æ¿ì ³«ÀÎ ´ë»óÀÌ ¾øÀ¸¸é ¹ß»çü »ý¼º ¾ÈµÊ. if (pStruct->nTargetStateIndex == 2) return; CDnProjectile* pProjectile = CDnProjectile::CreateProjectile( GetRoom(), GetMySmartPtr(), m_Cross, pStruct ); if( pProjectile == NULL ) return; pProjectile->SetShooterType( GetMySmartPtr(), m_nActionIndex, nSignalIndex ); SendProjectile( pProjectile, pStruct, m_Cross, nSignalIndex ); OnProjectile( pProjectile, pStruct, m_Cross, nSignalIndex ); OnSkillProjectile( pProjectile ); } } return; } case STE_ProjectileTargetPosition: { if( m_pAi ) m_pAi->SetProjectileTarget(); break; } case STE_ReserveProjectileTarget: { if( m_pAi ) m_pAi->ReservedProjectileTarget(); break; } case STE_RotateResistance: { RotateResistanceStruct *pStruct = (RotateResistanceStruct *)pPtr; m_fRotateResistance = pStruct->fResistanceRatio; break; } case STE_PositionRevision: { PositionRevisionStruct* pStruct = reinterpret_cast(pPtr); m_uiForcePositionRevisionTick = pStruct->nRevisionTick; return; } case STE_SuicideMonster: { SuicideMonsterStruct* pStruct = (SuicideMonsterStruct*)pPtr; // ¾ÆÀÌÅÛÀ» µå·ÓÇϴ°¡. ¿©±â¼­ Ŭ¶ó·Î ÆÐŶµµ º¸³¿. CmdSuicide( pStruct->bDropItem ? true : false, pStruct->bGetExp ? true : false ); } break; case STE_TriggerEvent: { TriggerEventStruct *pStruct = (TriggerEventStruct *)pPtr; CDnWorld::GetInstance(GetRoom()).InsertTriggerEventStore( "EventArea", GetBirthAreaHandle() ); CDnWorld::GetInstance(GetRoom()).InsertTriggerEventStore( "ActorHandle", GetUniqueID() ); CDnWorld::GetInstance(GetRoom()).InsertTriggerEventStore( "EventID", pStruct->nEventID ); CDnWorld::GetInstance(GetRoom()).OnTriggerEventCallback( "CDnActor::TriggerEvent", LocalTime, 0.f ); } break; case STE_Announce: { AnnounceStruct* pStruct = reinterpret_cast(pPtr); DNVector(DnActorHandle) hScanList; GetMAScanner().Scan( MAScanner::eType::MonsterSkillSameTeamExpectMe, m_hActor, 0.f, static_cast(pStruct->nRange), hScanList ); for( UINT i=0 ; iIsMonsterActor() ) { CDnMonsterActor* pMonster = static_cast(hActor.GetPointer()); if( pMonster->GetMonsterClassID() == pStruct->nTargetMonsterID ) { pMonster->GetAIBase()->NotifyDieAnnounce(); } } } break; } case STE_NextCustomAction: { if( !GetAIBase() ) return; int state = 0; float fLength = 0.0f; EtVector3* pvPos = GetPosition(); MAAiScript* pScript = static_cast(GetAIBase()); if( pScript->GetTarget() ) { state = pScript->GetTargetDistanceState( pScript->GetTarget() ); fLength = EtVec3Length( &( *pvPos - *pScript->GetTarget()->GetPosition() ) ); } if( static_cast(GetAIBase())->GetAIState() == MAAiScript::AT_CustomAction ) static_cast(GetAIBase())->OnCustomAction( state, fLength, 0 ); if( static_cast(GetAIBase())->GetAIState() == MAAiScript::AT_UseSkill ) { CancelUsingSkill(); static_cast(GetAIBase())->OnUseSkill( state, fLength, 0 ); } return; } #ifdef PRE_ADD_MONSTER_CATCH case STE_CatchActor: { CatchActor( reinterpret_cast(pPtr), nSignalIndex ); } break; case STE_ReleaseActor: { ReleaseAllActor( /*reinterpret_cast(pPtr)*/ ); } break; #endif // #ifdef PRE_ADD_MONSTER_CATCH case STE_ChangeAxis: { m_bChangeAxisOnFinishAction = true; } break; } CDnActor::OnSignal( Type, pPtr, LocalTime, SignalStartTime, SignalEndTime, nSignalIndex ); } bool CDnMonsterActor::IsHittable( DnActorHandle hHitter, LOCAL_TIME LocalTime, HitStruct *pHitSignal, int iHitUniqueID ) { #if defined(PRE_FIX_61382) #else //#59347 //²ÀµÎ°¢½Ã ¼Òȯ ¸ó½ºÅÍÀΰæ¿ì È÷Æ® °¡´É ¿©ºÎ¸¦ ²ÀµÎ°¢½Ã¸¦ ¼ÒȯÇÑ ÁÖÀÎ ¾×ÅÍÀÇ Hittable¿©ºÎ¸¦ üũ Çϵµ·Ï ÇÑ´Ù. if ( IsPuppetSummonMonster() && m_hSummonerPlayerActor ) { bool bSummonerPlayerActorHittable = m_hSummonerPlayerActor->IsHittable(hHitter, LocalTime, pHitSignal, iHitUniqueID); if (bSummonerPlayerActorHittable == false) return false; } #endif // PRE_FIX_61382 if( m_bNoDamage ) return false; return CDnActor::IsHittable( hHitter, LocalTime, pHitSignal, iHitUniqueID ); } void CDnMonsterActor::ProcessPositionRevision( float fDelta ) { if( CheckSignalPositionRevision( fDelta ) || CheckPositionRevision() ) { BYTE pBuffer[128] = { 0, }; CPacketCompressStream Stream( pBuffer, 128 ); Stream.Write( GetPosition(), sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT ); Stream.Write( &EtVec3toVec2( *GetMoveVectorZ() ), sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT ); Send( eActor::SC_POSREV, &Stream ); ResetPositionRevision(); } } bool CDnMonsterActor::CheckPositionRevision() { if( m_LastSendMoveMsg == 0 ) return false; if( !IsMove() ) { m_LastSendMoveMsg = CDnActionBase::m_LocalTime; return false; } if( CDnActionBase::m_LocalTime - m_LastSendMoveMsg > s_nPositionRevisionTime ) return true; return false; } bool CDnMonsterActor::CheckSignalPositionRevision( float fDelta ) { if( m_uiForcePositionRevisionTick == 0 ) return false; if( m_uiPrevForcePositionRevisionTick == 0 ) { //std::cout << GetTickCount() << ":ù¹øÂ° °­Á¦À§Ä¡ º¸Á¤" << std::endl; m_fForcePositionRevisionDelta = m_uiForcePositionRevisionTick/1000.f; return true; } m_fForcePositionRevisionDelta -= fDelta; if( m_fForcePositionRevisionDelta <= 0.f ) { m_fForcePositionRevisionDelta = m_uiForcePositionRevisionTick/1000.f; //std::cout << GetTickCount() << ":°­Á¦À§Ä¡ º¸Á¤" << std::endl; return true; } return false; } void CDnMonsterActor::ResetPositionRevision() { m_LastSendMoveMsg = CDnActionBase::m_LocalTime; } float CDnMonsterActor::GetRotateAngleSpeed() { return CDnMonsterState::GetRotateAngleSpeed() * m_fRotateResistance; } void CDnMonsterActor::AttachWeapon( DnWeaponHandle hWeapon, int nEquipIndex, bool bDelete ) { CDnActor::AttachWeapon( hWeapon, nEquipIndex, bDelete ); // ¹«±â ³»±¸µµ Á¦¼³Á¤ if( m_nMonsterWeightTableID == -1 ) return; if( hWeapon->IsInfinityDurability() || hWeapon->GetDurability() <= 0 ) return; DNTableFileFormat* pWeight = GetDNTable( CDnTableDB::TMONSTERWEIGHT ); int nDurability = (int)( hWeapon->GetDurability() * pWeight->GetFieldFromLablePtr( m_nMonsterWeightTableID, "_DurabilityWeight" )->GetFloat() ); hWeapon->SetDurability( nDurability ); } void CDnMonsterActor::SetTeam( int nValue ) { if( GetTeam() != nValue ) { if( m_pAi ) m_pAi->ResetAggro(); } CDnActor::SetTeam( nValue ); } void CDnMonsterActor::ProcessPartyCombo( LOCAL_TIME LocalTime, float fDelta ) { if( m_nPartyComboDelay > 0 ) m_nPartyComboDelay -= (int)( fDelta * 1000 ); if( m_nPartyComboDelay < 0 ) { m_nPartyComboCount = 0; m_nPartyComboDelay = 0; m_hPartyHitActor.Identity(); } } void CDnMonsterActor::OnPartyCombo( DnActorHandle hHitter, int nComboDelay ) { // #12170 ÄÞº¸ µô·¹ÀÌ °ªÀÌ 0ÀÎ hit ´Â ÄÞº¸ ÆÇÁ¤¿¡ ¾Æ¹«·± ¿µÇâÀ» ÁÖÁö ¾Êµµ·Ï ó¸®. if( 0 == nComboDelay ) return; if( m_hPartyHitActor == hHitter ) { m_nPartyComboDelay = nComboDelay; return; } m_hPartyHitActor = hHitter; if( m_nPartyComboDelay > 0 ) { m_nPartyComboCount++; if( hHitter && hHitter->IsPlayerActor() ) { CDnPlayerActor *pPlayer = static_cast(hHitter.GetPointer()); pPlayer->UpdatePartyCombo( m_nPartyComboCount ); } } else { m_nPartyComboCount = 0; } m_nPartyComboDelay = nComboDelay; } void CDnMonsterActor::Process_AutoRecallRange() { if( NULL == m_hSummonerPlayerActor ) return; if( 0 == m_nAutoRecallRange ) return; //#55707 ÇöÀç °ø°Ý »óÅÂÀÎ °æ¿ì °­Á¦ ¼Òȯ ¾ÈµÊ bool isAttackState = IsAttack(); if (isAttackState == true) return; EtVector2 vVec; vVec.x = m_hSummonerPlayerActor->GetPosition()->x - m_Cross.m_vPosition.x; vVec.y = m_hSummonerPlayerActor->GetPosition()->z - m_Cross.m_vPosition.z; float fLength = EtVec2Length(&vVec); if( m_nAutoRecallRange < fLength ) { //#55707 °­Á¦ ¼Òȯ½Ã ¾î±×·Î ¸®¼Â ½ÃÅ´. ResetAggro(); CmdWarp( *m_hSummonerPlayerActor->GetPosition(), EtVec3toVec2( *m_hSummonerPlayerActor->GetLookDir() ) ); } } void CDnMonsterActor::ReTransmitSlaveMsg(CDNUserSession* pBreakIntoSession) // µ¿±â¸ÂÃß±âÀ§ÇØ ³­ÀÔ À¯Àú¿¡°Ô º¸³»ÁÙ¶§ »ç¿ë. { BYTE pBuffer[32]; CPacketCompressStream Stream( pBuffer, 32 ); Stream.Write( &m_dwSummonerActorID, sizeof(DWORD) ); Stream.Write( &m_bSummoned , sizeof(bool) ); Stream.Write( &m_nMaxHP, sizeof(INT64) ); Stream.Write( &m_nHP, sizeof(INT64) ); Stream.Write( &m_bFollowSummonerStage, sizeof(bool) ); Stream.Write( &m_bReCreatedFollowStageMonster, sizeof(bool) ); #if defined(PRE_FIX_55618) //BaseStateÀÇ MaxHP/HP/À̵¿ ¼Óµµ °ü·Ã Á¤º¸¸¦ Ŭ¶óÀÌ¾ðÆ®·Î º¸³»ÁÖ°í, ÀÌ ÆÐŶÀ» ¹ÞÀº Ŭ¶óÀÌ¾ðÆ®´Â Á¤º¸ ÀúÀå ÇØ³õ°í //´õÀÌ»ó °»½Å µÇÁö ¾Êµµ·Ï m_bCopiedFromSummoner ¼³Á¤ ÇØÁØ´Ù.. INT64 nBaseMaxHP = m_BaseState.GetMaxHP(); float nBaseMaxHPRate = m_BaseState.GetMaxHPRatio(); Stream.Write( &nBaseMaxHP, sizeof(INT64) ); Stream.Write( &nBaseMaxHPRate, sizeof(float) ); Stream.Write( &m_nMoveSpeed, sizeof(int) ); #endif // PRE_FIX_55618 Send( pBreakIntoSession , eActor::SC_SLAVE_OF, GetUniqueID() , &Stream ); } void CDnMonsterActor::SlaveOf( DWORD dwSummonerActorUniqueID, bool bSummoned/* = false*/, bool bSuicideWhenSummonerDie/* = false*/, bool bFollowSummonerStage/* = false*/, bool bReCreateFollowStageMonster/* = false*/ ) { BYTE pBuffer[32]; CPacketCompressStream Stream( pBuffer, 32 ); Stream.Write( &dwSummonerActorUniqueID, sizeof(DWORD) ); Stream.Write( &bSummoned, sizeof(bool) ); if( bSummoned ) { Stream.Write( &m_nMaxHP, sizeof(INT64) ); Stream.Write( &m_nHP, sizeof(INT64) ); Stream.Write( &bFollowSummonerStage, sizeof(bool) ); Stream.Write( &bReCreateFollowStageMonster, sizeof(bool) ); #if defined(PRE_FIX_55618) //BaseStateÀÇ MaxHP/HP/À̵¿ ¼Óµµ °ü·Ã Á¤º¸¸¦ Ŭ¶óÀÌ¾ðÆ®·Î º¸³»ÁÖ°í, ÀÌ ÆÐŶÀ» ¹ÞÀº Ŭ¶óÀÌ¾ðÆ®´Â Á¤º¸ ÀúÀå ÇØ³õ°í //´õÀÌ»ó °»½Å µÇÁö ¾Êµµ·Ï m_bCopiedFromSummoner ¼³Á¤ ÇØÁØ´Ù.. INT64 nBaseMaxHP = m_BaseState.GetMaxHP(); float nBaseMaxHPRate = m_BaseState.GetMaxHPRatio(); Stream.Write( &nBaseMaxHP, sizeof(INT64) ); Stream.Write( &nBaseMaxHPRate, sizeof(float) ); Stream.Write( &m_nMoveSpeed, sizeof(int) ); #endif // PRE_FIX_55618 #if defined(PRE_FIX_61382) Stream.Write(&m_isPuppetSummonMonster, sizeof(bool)); #endif // PRE_FIX_61382 } Send( eActor::SC_SLAVE_OF, &Stream ); m_dwSummonerActorID = dwSummonerActorUniqueID; if( bSummoned ) { DnActorHandle hActor = CDnActor::FindActorFromUniqueID( GetRoom(), dwSummonerActorUniqueID ); //#53454 ²ÀµÎ°¢½Ã °ü·Ã ¼Òȯ ÁÖü°¡ PlayerActor°¡ ¾Æ´Ñ °æ¿ì°¡ »ý±è. if( hActor/* && hActor->IsPlayerActor()*/ ) { m_hSummonerPlayerActor = hActor; m_bSuicideWhenSummonerDie = bSuicideWhenSummonerDie; m_bFollowSummonerStage = bFollowSummonerStage; // Ç÷¹À̾ ¼ÒȯÇÏ´Â ¸ó½ºÅÍ ¾×ÅÍ´Â pvp/pve ½ºÅ³·¹º§Å×ÀÌºí ³ª´¶°ÍÀ» Àû¿ëÇÑ´Ù. SelectSkillLevelDataType( hActor->GetSelectedSkillLevelDataType(), true ); } } m_bSummoned = bSummoned; m_bReCreatedFollowStageMonster = bReCreateFollowStageMonster; } // ÇöÀç ´ëÆ÷¿¡¼­¸¸ ¾²ÀÓ. void CDnMonsterActor::SlaveRelease( void ) { if( 0 == m_dwSummonerActorID ) return; BYTE pBuffer[32]; CPacketCompressStream Stream( pBuffer, 32 ); Stream.Write( &m_dwSummonerActorID, sizeof(DWORD) ); Send( eActor::SC_SLAVE_RELEASE, &Stream ); if( m_hSummonerPlayerActor ) { m_hSummonerPlayerActor.Identity(); } } void CDnMonsterActor::OnHitSuccess( LOCAL_TIME LocalTime, DnActorHandle hActor, HitStruct *pStruct ) { // ÀϹÝÀûÀÎ »óȲ¿¡¼­ÀÇ ¸÷Àº ¿©±â¼­ ÇÒ ÀÏÀÌ ¾øÀ¸³ª ·¼¸¯À¸·Î ¼ÒȯµÈ ¸÷Àº ¼ÒȯÇÑ Ç÷¹À̾îÀÇ ÄÞº¸ Ä«¿îÆ®·Î ó¸®ÇØ Áà¾ß ÇÔ. if( m_hSummonerPlayerActor && m_hSummonerPlayerActor->IsPlayerActor() ) m_hSummonerPlayerActor->OnHitSuccess( LocalTime, hActor, pStruct ); } void CDnMonsterActor::OnHitFinish( LOCAL_TIME LocalTime, HitStruct *pStruct ) { CDnActor::OnHitFinish( LocalTime, pStruct ); if (IsSummonedMonster()) { DnActorHandle hMasterActor = GetSummonerPlayerActor(); if (hMasterActor) { int nDieCount = 0; for( DWORD i=0; iIsDie() ) nDieCount++; } hMasterActor->UpdateMissionByMonsterKillCount(nDieCount); } } if( GetAIBase() ) GetAIBase()->OnHitFinish( LocalTime, pStruct ); } void CDnMonsterActor::ResetAggro( void ) { if( m_pAggroSystem ) m_pAggroSystem->ResetAggro(); } void CDnMonsterActor::ResetAggro( DnActorHandle hActor ) { if( m_pAggroSystem ) m_pAggroSystem->ResetAggro( hActor ); } void CDnMonsterActor::RequestDamageFromStateBlow( DnBlowHandle hFromBlow, int iDamage ) { if( m_bNoDamage ) return; CDnActor::RequestDamageFromStateBlow( hFromBlow, iDamage ); } #ifdef PRE_ADD_MONSTER_CATCH void CDnMonsterActor::_CatchThisActor( DnActorHandle hResultActor, int nSignalIndex ) { S_CATCH_ACTOR_INFO CatchActorInfo; CatchActorInfo.hCatchedActor = hResultActor; CatchActorInfo.hCatchedActor->SetActionQueue( m_strCatchedActorAction.c_str() ); m_iCatchedActorActionIndex = CatchActorInfo.hCatchedActor->GetElementIndex( m_strCatchedActorAction.c_str() ); // À̵¿/ÇൿºÒ°¡ »óÅÂÈ¿°ú Ãß°¡. CatchActorInfo.iCatchCantMoveBlowID = CatchActorInfo.hCatchedActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_070, -1, "", false, false ); CatchActorInfo.iCatchCantActionBlowID = CatchActorInfo.hCatchedActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_071, -1, "", false, false ); if( CatchActorInfo.hCatchedActor->IsPlayerActor() ) { static_cast(CatchActorInfo.hCatchedActor.GetPointer())->SetCatcherMonsterActor( GetMySmartPtr() ); } m_vlCatchedActors.push_back( CatchActorInfo ); // Ŭ¶óÀÌ¾ðÆ®·Î Àâ¾Ò´Ù°í ÆÐŶ º¸³¿. BYTE pBuffer[ 128 ] = { 0 }; CPacketCompressStream Stream( pBuffer, 128 ); DWORD dwCatchedActorID = CatchActorInfo.hCatchedActor->GetUniqueID(); int nCatchActionIndex = GetCurrentActionIndex(); int nCatchSignalArrayIndex = nSignalIndex; Stream.Write( &dwCatchedActorID, sizeof(DWORD) ); Stream.Write( &nCatchActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Write( &nCatchSignalArrayIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Send( eActor::SC_CATCH_ACTOR, &Stream ); } void CDnMonsterActor::CatchActor( CatchActorStruct* pCatchActor, int nSignalIndex ) { // ¿©·¯¸í Àâ´Â °ÍÀÌ ÄÑÁ® ÀÖÁö ¾Ê´Ù¸é Çѳ𸸠Àâ°í À־ ó¸®ÇÏÁö ¾Ê°í ³Ñ±ä´Ù. if( FALSE == pCatchActor->bMultiCatch ) if( false == m_vlCatchedActors.empty() ) return; m_strCatchBoneName = pCatchActor->szCatchBoneName; m_strTargetActorCatchBoneName = pCatchActor->szTargetActorCatchBoneName; if( pCatchActor->szCatchedActorAction != NULL && 0 < strlen(pCatchActor->szCatchedActorAction) ) { m_strCatchedActorAction.assign( pCatchActor->szCatchedActorAction ); } else m_strCatchedActorAction.assign( "Hold" ); EtVector3 vCatchBonePos( 0.0f, 0.0f, 0.0f ); GetObjectHandle()->SetCalcAni( true ); EtMatrix matBoneWorld = GetBoneMatrix( m_strCatchBoneName.c_str() ); GetObjectHandle()->SetCalcAni( false ); memcpy_s( &vCatchBonePos, sizeof(EtVector3), &matBoneWorld._41, sizeof(EtVector3) ); // »ç¿ëÇÏ´Â º» À̸§À¸·Î º»ÀÇ À§Ä¡¸¦ ¾ò¾î¿À°í ÇöÀç º» À§Ä¡ ±Ùó¿¡¼­ ½Ã±×³Î¿¡¼­ ¼³Á¤ÇÑ ¹üÀ§º¸´Ù // °Å¸®°¡ ªÀº ¾Ö°¡ ÀÖ´ÂÁö È®ÀÎ. DNVector( DnActorHandle ) vlhActors; ScanActor( GetGameRoom(), vCatchBonePos, pCatchActor->fCatchDistance, vlhActors ); // ¹üÀ§¿¡ ³ôÀ̰ª¸¸ °®°í üũ. float fMinDistanceSQ = FLT_MAX; DnActorHandle hResultActor; for( int i = 0; i < (int)vlhActors.size(); ++i ) { DnActorHandle hActor = vlhActors.at( i ); // °°Àº ½Ã±×³Î¿¡¼­ Çѹø üũ°¡ µÈ ¾×ÅÍ´Â Á¦¿Ü. if( m_setCatchCheckedActorIDs.end() != m_setCatchCheckedActorIDs.find( hActor->GetUniqueID() ) ) continue; // ÀÚ±â ÀÚ½ÅÀº ÆÐ½º if( GetMySmartPtr() == hActor ) continue; // üũ°¡ µÈ ¾ÖµéÀº set ¿¡ °ð¹Ù·Î ³Ö¾îµÒ. m_setCatchCheckedActorIDs.insert( hActor->GetUniqueID() ); // Ç÷¹ÀÌ¾î ¾×Å͸¸. if( false == hActor->IsPlayerActor() ) continue; // °°Àº ÆÀ Á¦¿Ü. if( GetTeam() == hActor->GetTeam() ) continue; // CanHit ¿©ºÎ È®ÀÎ. if( FALSE == pCatchActor->bIgnoreCanHit ) { if( false == hActor->CDnActorState::IsHittable() ) continue; // ¹«Àû »óÅÂÈ¿°ú°¡ ÄÑÁ® ÀÖ´Ù¸é ÀâÈ÷Áö ¾Ê´Â´Ù. if( hActor->IsAppliedThisStateBlow( STATE_BLOW::BLOW_099 ) ) continue; } // bMultiCatch Ç÷¡±×°¡ ²¨Á®ÀÖ´Ù¸é °¡Àå °¡±î¿î ³à¼®À» Àâ±â ó¸®./ // ÄÑÁ® ÀÖ´Ù¸é ¹üÀ§¿¡¸¸ ¸ÂÀ¸¸é ¸ðµÎ Àâ±â ó¸®. EtVector3 vTargetActorPos = *hActor->GetPosition(); EtVector3 vDist = vCatchBonePos - vTargetActorPos; float fDistanceSQ = EtVec3LengthSq( &vDist ); if( TRUE == pCatchActor->bMultiCatch || fDistanceSQ < fMinDistanceSQ ) { // ³ôÀ̵µ ¸Â´ÂÁö È®ÀÎ. bool bHeightMax = vTargetActorPos.y < (pCatchActor->fHeightMax + vCatchBonePos.y); bool bHeightMin = (vCatchBonePos.y + pCatchActor->fHeightMin) < vTargetActorPos.y; // HeightMin °ªÀº À½¼öÀÓ. if( bHeightMax && bHeightMin ) { bool bCatchFailed = true; // Àâ±â ½ÇÆÐÇßÀ» °æ¿ì Ŭ¶ó·Î º¸³»ÁÙ Á¤º¸µé. // ½ÇÆÐÇÑ ÀÌÀ¯, 0: ÆÐ¸µ, 1: ºí·Ï, 2: ½´ÆÛ¾Æ¸Ó·Î °ßµõ. int iFailedType = -1; int iBlowID = 0; string strBlockOrParringAction; ////////////////////////////////////////////////////////////////////////// // ÆÐ¸µ »óÅÂÈ¿°ú ¹«½Ã ¿©ºÎ. ¿©±â¼± È÷Æ®°¡ ¾Æ´Ï¹Ç·Î °­Á¦·Î °ü·Ã »óÅÂÈ¿°úµéÀ» È®·ü üũ. bool bPassParring = true; if( FALSE == pCatchActor->bIgnoreParring ) { bool bAppliedBlockBlow = hActor->IsAppliedThisStateBlow( STATE_BLOW::BLOW_030 ); bool bAppliedParringBlow = hActor->IsAppliedThisStateBlow( STATE_BLOW::BLOW_031 ); if( bAppliedBlockBlow || bAppliedParringBlow ) { // ÆÐ¸µÀÌ µÈ °æ¿ì¿£ ÆÐ¸µ ¾×¼ÇÀ» ½ÇÇà½ÃÄÑÁà¾ß ÇÑ´Ù.. // »óÅÂÈ¿°úÂÊ¿¡¼­ HitParam À» ¾²±â ¶§¹®¿¡ °¡»óÀ¸·Î ¸¸µé¾î¼­ ³Ñ°ÜÁØ´Ù. SHitParam HitParam; HitParam.szActionName = m_strCatchedActorAction; HitParam.fDamage = 1.0f;// ¾îÂ÷ÇÇ ¿©±â¼­ µ¥¹ÌÁö ÁÖ´Â °ÍÀº ¾Æ´Ï¹Ç·Î ¾Æ¹«°ªÀ̳ª ³ÖÀ¸¸é µÊ. 0 ÀÌ¸é ºí·Ï »óÅÂÈ¿°úüũ¿¡¼­ ÆÐ½ºµÊ. HitParam.bIgnoreParring = false; CDnActorState* pState = static_cast(this); bool bSuccess = false; if( bAppliedParringBlow ) { DNVector(DnBlowHandle) vlhBlows; hActor->GatherAppliedStateBlowByBlowIndex( STATE_BLOW::BLOW_031, vlhBlows ); if( false == vlhBlows.empty() ) { DnBlowHandle hParringBlow = vlhBlows.front(); bSuccess = hParringBlow->OnDefenseAttack( GetMySmartPtr(), pState, HitParam, true ); if( bSuccess ) { iFailedType = 0; iBlowID = hParringBlow->GetBlowID(); } } } if( (false == bSuccess) && bAppliedBlockBlow ) { DNVector(DnBlowHandle) vlhBlows; hActor->GatherAppliedStateBlowByBlowIndex( STATE_BLOW::BLOW_030, vlhBlows ); if( false == vlhBlows.empty() ) { DnBlowHandle hBlockBlow = vlhBlows.front(); bSuccess = hBlockBlow->OnDefenseAttack( GetMySmartPtr(), pState, HitParam, true ); if( bSuccess ) { iFailedType = 1; iBlowID = hBlockBlow->GetBlowID(); } } } if( bSuccess ) { bPassParring = false; // ÆÐ¸µ »óÅÂÈ¿°ú³ª ºí·Ï »óÅÂÈ¿°ú¿¡ ÀÇÇØ ÇÇ°Ý ¾×¼ÇÀÌ º¯°æµÈ °æ¿ì ½ÇÇàÇÏ°í ³Ñ±ä´Ù. if( HitParam.szActionName != m_strCatchedActorAction ) { m_hActor->SetActionQueue( HitParam.szActionName.c_str() ); strBlockOrParringAction = HitParam.szActionName; } } } } // ÆÐ¸µÀÌ µÇÁö ¾Ê¾ÒÀ¸¸é ½ÇÁ¦·Î Àâ±â ó¸®. ¸¶Áö¸·À¸·Î ½´ÆÛ¾Æ¸Ó·Î °ßµ®³»´ÂÁö üũ. if( bPassParring ) { if( hActor->CatchCalcSuperArmor( GetMySmartPtr(), pCatchActor->nApplySuperArmorDamage ) ) { // ½ÇÁ¦·Î ½´ÆÛ¾Æ¸Ó ´ÙµÇ¾î ÀâÈù ¾Ö. // ¿©·¯¸í Àâ±â Ç÷¡±×°¡ ÄÑÁ³´À³ÄÀÇ ¿©ºÎ¿¡ µû¶ó ¿©·¯¸í Àâ±â ó¸®. if( TRUE == pCatchActor->bMultiCatch ) { _CatchThisActor( hActor, nSignalIndex ); } else { hResultActor = hActor; fMinDistanceSQ = fDistanceSQ; } bCatchFailed = false; } else { iFailedType = 2; } } // ÃÖÁ¾ÀûÀ¸·Î ¹üÀ§ ¾È¿¡ Àִµ¥µµ ¸ó½ºÅͰ¡ ij¸¯ÅÍ Àâ±â¿¡ ½ÇÆÐÇßÀ» °æ¿ì Ŭ¶óÀÌ¾ðÆ®·Î ¾Ë·ÁÁà¾ß ÇÑ´Ù. // ÆÐ¸µÀ̳ª ºí·Ï, ½´ÆÛ¾Æ¸Ó°¡ ±× ÀÌÀ¯°¡ µÉ ¼ö ÀÖÀ½. // ºí·ÏÀÎ °æ¿ì¿¡´Â Ŭ¶ó¿¡¼­ Ƚ¼ö¸¦ ±ï¾ÆÁÖ°í, ÆÐ¸µ ºí·Ï ¸ðµÎ ¸·´Â ¾×¼Ç ½ÇÇàŰ¼ÅÁà¾ß ÇÔ. if( bCatchFailed ) { BYTE pBuffer[ 128 ] = { 0 }; CPacketCompressStream Stream( pBuffer, 128 ); // ½ÇÆÐÇÑ ÀÌÀ¯, 0: ÆÐ¸µ, 1: ºí·Ï, 2: ½´ÆÛ¾Æ¸Ó·Î °ßµõ. int iFailedType = 0; DWORD dwCatchFailedActorID = hActor->GetUniqueID(); int iParringOrBlockActionIndex = hActor->GetElementIndex( strBlockOrParringAction.c_str() ); Stream.Write( &iFailedType, sizeof(int), CPacketCompressStream::INTEGER_CHAR ); Stream.Write( &iBlowID, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Stream.Write( &dwCatchFailedActorID, sizeof(DWORD) ); Stream.Write( &iParringOrBlockActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT ); Send( eActor::SC_CATCH_ACTOR_FAILED, &Stream ); } } } } if( hResultActor ) { _CatchThisActor( hResultActor, nSignalIndex ); } } void CDnMonsterActor::ReleaseThisActor( DnActorHandle hActor ) { vector::iterator iter = m_vlCatchedActors.begin(); for( iter; iter != m_vlCatchedActors.end(); ++iter ) { S_CATCH_ACTOR_INFO& CatchActorInfo = *iter; if( CatchActorInfo.hCatchedActor == hActor ) { ReleaseThisActor( CatchActorInfo ); m_vlCatchedActors.erase( iter ); break; } } } void CDnMonsterActor::ReleaseThisActor( S_CATCH_ACTOR_INFO &CatchActorInfo ) { if( CatchActorInfo.hCatchedActor ) { m_setCatchCheckedActorIDs.erase( CatchActorInfo.hCatchedActor->GetUniqueID() ); CatchActorInfo.hCatchedActor->CmdRemoveStateEffectFromID( CatchActorInfo.iCatchCantMoveBlowID ); CatchActorInfo.hCatchedActor->CmdRemoveStateEffectFromID( CatchActorInfo.iCatchCantActionBlowID ); // Ŭ¶ó·Î ³õ´Â´Ù°í ÆÐŶ º¸³½´Ù. BYTE pBuffer[ 128 ] = { 0 }; CPacketCompressStream Stream( pBuffer, 128 ); DWORD dwCatchActorID = CatchActorInfo.hCatchedActor->GetUniqueID(); Stream.Write( &dwCatchActorID, sizeof(DWORD) ); Send( eActor::SC_RELEASE_ACTOR, &Stream ); // TODO: ³õ¾ÆÁö´Â ¼ø°£À» ¾Ë¸± Çʿ䰡 ÀÖ´Ù¸é.. µû·Î ¶Ç ó¸®Çϰí. if( CatchActorInfo.hCatchedActor->IsPlayerActor() ) { static_cast( CatchActorInfo.hCatchedActor.GetPointer() )->ReleaseCatcherMonsterActor(); } } } void CDnMonsterActor::ReleaseAllActor( void ) { // üũ ¼Â ºñ¿ò. m_setCatchCheckedActorIDs.clear(); // °É¾îÁá´ø »óÅÂÈ¿°ú ÇØÁ¦ for( int i = 0; i < (int)m_vlCatchedActors.size(); ++i ) { S_CATCH_ACTOR_INFO& CatchActorInfo = m_vlCatchedActors.at( i ); if( CatchActorInfo.hCatchedActor ) { ReleaseThisActor( CatchActorInfo ); } } m_vlCatchedActors.clear(); } void CDnMonsterActor::ProcessCatchActor( LOCAL_TIME LocalTime, float fDelta ) { vector::iterator iter = m_vlCatchedActors.begin(); for( iter; iter != m_vlCatchedActors.end(); ) { S_CATCH_ACTOR_INFO& CatchActorInfo = *iter; // Àâ°í ÀÖ´Â Ç÷¹À̾ Á×¾úÀ» ¶§. ³öÁØ´Ù. // TODO: Àâ°í ÀÖ´Â ÀÌ ¸ó½ºÅͰ¡ Á×¾úÀ» ¶§µµ ³öÁà¾ß ÇÑ´Ù. if( CatchActorInfo.hCatchedActor && false == CatchActorInfo.hCatchedActor->IsDie() && false == IsDie() ) { EtVector3 vCatchBonePos( 0.0f, 0.0f, 0.0f ); EtMatrix matBoneWorld = GetBoneMatrix( m_strCatchBoneName.c_str() ); memcpy_s( &vCatchBonePos, sizeof(EtVector3), &matBoneWorld._41, sizeof(EtVector3) ); // vCatchBonePos ¿¡ ij¸¯ÅÍ Bip01 À» ¹èÄ¡½ÃÄÑ¾ß ÇÑ´Ù. // ÇöÀç ÀÌ ¸÷ÀÇ vCatchBonePos ¿Í ÀâÈú ij¸¯ÅÍÀÇ Bip01 ÀÇ °Å¸®¸¦ °è»êÇØ¼­ // ±×¸¸Å­ À§Ä¡¿¡ Àû¿ë½ÃÄÑÁØ´Ù. EtVector3 vPlayerCatchedPointPos( 0.0f, 0.0f, 0.0f ); CatchActorInfo.hCatchedActor->GetObjectHandle()->SetCalcAni( true ); matBoneWorld = CatchActorInfo.hCatchedActor->GetBoneMatrix( m_strTargetActorCatchBoneName.c_str() ); CatchActorInfo.hCatchedActor->GetObjectHandle()->SetCalcAni( false ); memcpy_s( &vPlayerCatchedPointPos, sizeof(EtVector3), &matBoneWorld._41, sizeof(EtVector3) ); EtVector3 vDelta = vCatchBonePos - vPlayerCatchedPointPos; EtVector3 vNowCatchedActorPos = *CatchActorInfo.hCatchedActor->GetPosition(); EtVector3 vCatchedActorPos = vNowCatchedActorPos + vDelta; CatchActorInfo.hCatchedActor->SetPosition( vCatchedActorPos ); //CatchActorInfo.hCatchedActor->SetActionQueue( m_strCatchedActorAction.c_str() ); // ´Ù¸¥ ¾×¼ÇÀ» ÃëÇϰí ÀÖÀ¸¸é Àâ±â ¾×¼ÇÀ¸·Î °íÃÄÁØ´Ù. int iCurrentActionIndex = CatchActorInfo.hCatchedActor->GetCurrentActionIndex(); if( iCurrentActionIndex != m_iCatchedActorActionIndex ) CatchActorInfo.hCatchedActor->SetActionQueue( m_strCatchedActorAction.c_str() ); ++iter; } else { ReleaseThisActor( CatchActorInfo ); iter = m_vlCatchedActors.erase( iter ); } } if( false == IsSignalRange( STE_CatchActor ) ) { if( false == m_setCatchCheckedActorIDs.empty() ) m_setCatchCheckedActorIDs.clear(); } } #endif // #ifdef PRE_ADD_MONSTER_CATCH #if defined(PRE_FIX_51048) void CDnMonsterActor::AddPassiveStateEffectInfo(PassiveStateEffectInfo& stateEffectInfo) { m_PassiveStateEffectInfoList.push_back(stateEffectInfo); } void CDnMonsterActor::InitPassiveStateEffectInfo() { m_PassiveStateEffectInfoList.clear(); } void CDnMonsterActor::ApplyPassiveStateEffect() { if (m_PassiveStateEffectInfoList.empty()) return; std::list::iterator iter = m_PassiveStateEffectInfoList.begin(); std::list::iterator endIter = m_PassiveStateEffectInfoList.end(); for (; iter != endIter; ++iter) { PassiveStateEffectInfo& passiveStateEffect = (*iter); DnSkillHandle hSkill = FindSkill(passiveStateEffect.pParentSkill->iSkillID); if (hSkill) { // ¼­¹ö -> Ŭ¶óÀÌ¾ðÆ®·Î ÆÐŶ Àü¼ÛÀ» À§ÇØ ¼öÁ¤µÊ int iBlowID = CmdAddStateEffect( passiveStateEffect.pParentSkill, passiveStateEffect.emBlowIndex, -1, passiveStateEffect.szParam.c_str(), true ); // Duration TimeÀÌ -1 ÀÌ¸é ¹«ÇÑ Àû¿ëÀÓ OnApplyPassiveSkillBlow( iBlowID ); hSkill->SetAppliedPassiveBlows( true ); } } } bool CDnMonsterActor::ApplyPassiveSkill( DnSkillHandle hSkill, bool isInitialize/* = false*/ ) { bool bPassiveBuf = false; if( CDnSkill::Passive == hSkill->GetSkillType() ) { int iNumStateEffect = hSkill->GetStateEffectCount(); for( int i = 0; i < iNumStateEffect; ++i ) { CDnSkill::StateEffectStruct* pSE = hSkill->GetStateEffectFromIndex( i ); if( CDnSkill::StateEffectApplyType::ApplySelf == pSE->ApplyType ) { if( CDnSkill::DurationTypeEnum::Buff == hSkill->GetDurationType() ) { bPassiveBuf = true; if( hSkill->IsSatisfyWeapon() ) { //ÆÐŶ ¼ø¼­¶§¹®¿¡ »óÅÂÈ¿°ú Á¤º¸¸¦ ¸®½ºÆ®¿¡ ´ã¾Æ ³õ´À´Ù. if (GetEnablePassiveStateEffectList() == true) { PassiveStateEffectInfo passiveStateEffectInfo; passiveStateEffectInfo.pParentSkill = hSkill->GetInfo(); passiveStateEffectInfo.emBlowIndex = (STATE_BLOW::emBLOW_INDEX)pSE->nID; passiveStateEffectInfo.nDurationTime = -1; passiveStateEffectInfo.szParam = pSE->szValue; AddPassiveStateEffectInfo(passiveStateEffectInfo); } else { // ¼­¹ö -> Ŭ¶óÀÌ¾ðÆ®·Î ÆÐŶ Àü¼ÛÀ» À§ÇØ ¼öÁ¤µÊ int iBlowID = CmdAddStateEffect( hSkill->GetInfo(), (STATE_BLOW::emBLOW_INDEX)pSE->nID, -1, pSE->szValue.c_str(), true ); // Duration TimeÀÌ -1 ÀÌ¸é ¹«ÇÑ Àû¿ëÀÓ OnApplyPassiveSkillBlow( iBlowID ); hSkill->SetAppliedPassiveBlows( true ); } #ifndef _FINAL_BUILD char szTemp[256] = { 0, }; WideCharToMultiByte( CP_ACP, 0, hSkill->GetName(), -1, szTemp, _countof(szTemp), NULL, NULL ); OutputDebug( "[ÆÐ½Ãºê ¹öÇÁ ½ºÅ³ Àû¿ëµÊ: %d] \"%s\" »óÅÂÈ¿°úIndex: %d, Value:%s\n", hSkill->GetClassID(), szTemp, pSE->nID, pSE->szValue.c_str() ); #endif // #ifndef _FINAL_BUILD } #ifndef _FINAL_BUILD else { char szTemp[256] = { 0, }; WideCharToMultiByte( CP_ACP, 0, hSkill->GetName(), -1, szTemp, _countof(szTemp), NULL, NULL ); OutputDebug( "[ÆÐ½Ãºê ¹öÇÁ ½ºÅ³ Àû¿ë¾ÈµÊ: %d] \"%s\" ½ºÅ³¿¡ ÁöÁ¤µÈ ÇÊ¿ä ¹«±â ŸÀÔÀÌ ¸ÂÁö ¾Ê½À´Ï´Ù.\n", hSkill->GetClassID(), szTemp ); } #endif // #ifndef _FINAL_BUILD } #ifndef _FINAL_BUILD else { char szTemp[256] = { 0, }; WideCharToMultiByte( CP_ACP, 0, hSkill->GetName(), -1, szTemp, _countof(szTemp), NULL, NULL ); OutputDebug( "[½ºÅ³ µ¥ÀÌÅÍ È®ÀÎ ¿ä¸Á: %d] \"%s\" ÆÐ½Ãºê ¹öÇÁ ½ºÅ³·Î »ý°¢µÇ³ª Buff ·Î ¼³Á¤µÇ¾îÀÖÁö ¾Ê¾Æ¼­ Àû¿ë ¾ÈµÊ\n", hSkill->GetClassID(), szTemp ); } #endif // #ifndef _FINAL_BUILD } } } return bPassiveBuf; } #endif // PRE_FIX_51048 #if defined(PRE_FIX_61382) void CDnMonsterActor::RequestDamageFromStateBlow( DnBlowHandle hFromBlow, int iDamage, CDnDamageBase::SHitParam* pHitParam/* = NULL*/ ) { if (IsPuppetSummonMonster() == true) { DnActorHandle hOwnerActor = GetSummonerPlayerActor(); //µ¥¹ÌÁö Àü´Þ »óÅÂÈ¿°ú°¡ ¼³Á¤ µÇ¾î ÀÖ´Â °æ¿ì¸¸? µ¥¹ÌÁö Àü´Þ ÇÑ´Ù. if (IsAppliedThisStateBlow(STATE_BLOW::BLOW_051) && hOwnerActor) { #if defined(PRE_FIX_59347) && !defined(PRE_FIX_67656) hOwnerActor->SetApplyPartsDamage(true); #endif // PRE_FIX_59347 hOwnerActor->RequestDamageFromStateBlow(hFromBlow, iDamage, pHitParam); #if defined(PRE_FIX_59347) && !defined(PRE_FIX_67656) hOwnerActor->SetApplyPartsDamage(false); #endif // PRE_FIX_59347 } } else { CDnActor::RequestDamageFromStateBlow(hFromBlow, iDamage, pHitParam); } } #endif // PRE_FIX_61382 #if defined(PRE_FIX_64312) void CDnMonsterActor::SendApplySummonMonsterExSkill(int nBaseSkillID, int nLevel, int nSelectedType, DWORD dwMasterUniqueID, int nMasterExSkillID) { BYTE pBuffer[128]; CPacketCompressStream Stream( pBuffer, 128 ); Stream.Write(&nBaseSkillID, sizeof(int)); Stream.Write(&nLevel, sizeof(int)); Stream.Write(&nSelectedType, sizeof(int)); Stream.Write(&dwMasterUniqueID, sizeof(DWORD)); Stream.Write(&nMasterExSkillID, sizeof(int)); Send( eActor::SC_APPLY_SUMMON_MONSTER_EX_SKILL, &Stream ); } #endif // PRE_FIX_64312