#include "stdafx.h" #include "PvPZombieMode.h" #include "DnActor.h" #include "DNUserSession.h" #include "DNPvPGameRoom.h" #include "DnPlayerActor.h" #include "DnStateBlow.h" #include "DNGameDataManager.h" #include "DNDBConnection.h" #include "DNMissionSystem.h" CPvPZombieMode::CPvPZombieMode( CDNGameRoom* pGameRoom, const TPvPGameModeTable* pPvPGameModeTable, const MAGAPVP_GAMEMODE* pPacket ) :CPvPRoundMode( pGameRoom, pPvPGameModeTable, pPacket ) { memset(&m_MutationGroup, 0, sizeof(TMonsterMutationGroup)); m_nGhoulCount = 0; m_bInitializeZombie = false; } CPvPZombieMode::~CPvPZombieMode() { } void CPvPZombieMode::OnInitializeActor( CDNUserSession* pSession ) { DnActorHandle hActor = pSession->GetActorHandle(); if( !hActor ) return; if( pSession->GetTeam() == PvPCommon::Team::Observer ) return; hActor->SetTeam( PvPCommon::Team::Human ); pSession->SetTeam( hActor->GetTeam() ); _AddHumanBlow( hActor ); } void CPvPZombieMode::Process( LOCAL_TIME LocalTime, float fDelta ) { _ProcessSelectZombie(); CPvPRoundMode::Process( LocalTime, fDelta ); // Playing ÁßÀÏ ¶§ »ó´ë¹æ ³ª°¬´ÂÁö °Ë»ç if( bIsPlaying() ) { OnCheckFinishRound( PvPCommon::FinishReason::OpponentTeamAllGone ); } } void CPvPZombieMode::OnFinishProcessDie( DnActorHandle hActor ) { if( !hActor ) return; if( bIsPlaying() != true ) return; if( bIsPlayingUser( hActor) == false ) return; // ¸®½ºÆùÀ§Ä¡ ¼³Á¤ if( bIsZombie( hActor ) ) _SetRespawnPosition( hActor ); // ºÎȰ½ÃÅ´ UINT uiRespawnHPPercent = GetPvPGameModeTable() ? GetPvPGameModeTable()->uiRespawnHPPercent : 100; UINT uiRespawnMPPercent = GetPvPGameModeTable() ? GetPvPGameModeTable()->uiRespawnMPPercent : 100; UINT uiImmortalTime = GetPvPGameModeTable() ? GetPvPGameModeTable()->uiRespawnNoDamageTimeSec : 5; char szParam[32]; sprintf_s( szParam, "Coin/%d/%d/%d", uiRespawnHPPercent, uiRespawnMPPercent, uiImmortalTime ); hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_057, uiImmortalTime*1000, szParam ); } void CPvPZombieMode::OnCheckFinishRound( PvPCommon::FinishReason::eCode Reason ) { UINT uiWinTeam = PvPCommon::Team::Max; switch( Reason ) { // Á»ºñ,À¯Àú ÇÑÂÊÀÌ ´Ù ³ª°¬À¸¸é Á¾·á ó¸® case PvPCommon::FinishReason::OpponentTeamAllGone: { if( m_bInitializeZombie == false ) return; int iPlayerCount = 0; int iZombieCount = 0; for( UINT i=0 ; iGetUserCount() ; ++i ) { CDNUserSession* pSession = GetGameRoom()->GetUserData(i); DnActorHandle hActor = pSession->GetActorHandle(); if( bIsPlayingUser( hActor ) == false ) continue; if( hActor->GetTeam() == PvPCommon::Team::A ) ++iPlayerCount; else if( hActor->GetTeam() == PvPCommon::Team::Zombie ) ++iZombieCount; } // À¯Àú,Á»ºñ µÑ ´Ù »ì¾ÆÀÖÀ½¿ä~! if( iPlayerCount > 0 && iZombieCount > 0 ) return; if( iPlayerCount == 0 && iZombieCount > 0 ) uiWinTeam = PvPCommon::Team::Zombie; else if( iZombieCount == 0 && iPlayerCount > 0 ) uiWinTeam = PvPCommon::Team::A; CPvPRoundMode::_ProcessFinishRound( uiWinTeam, Reason ); return; } // Á»ºñ¸ðµå¿¡¼­´Â TimeOver ½Ã À¯Àú°¡ ¹«Á¶°Ç ½Â¸®ÇÑ´Ù. case PvPCommon::FinishReason::TimeOver: { uiWinTeam = PvPCommon::Team::A; CPvPRoundMode::_ProcessFinishRound( uiWinTeam, Reason ); return; } // Á»ºñ¸ðµå¿¡¼­´Â Á»ºñ°¡ ´Ù Á×¾îÀÖ´Â »óÅÂÀΰ¡¸¸ °Ë»çÇÑ´Ù. case PvPCommon::FinishReason::OpponentTeamAllDead: { if( m_bInitializeZombie == false ) return; int iZombieCount = 0; int iZombieDeadCount = 0; for( UINT i=0 ; iGetUserCount() ; ++i ) { CDNUserSession* pSession = GetGameRoom()->GetUserData(i); DnActorHandle hActor = pSession->GetActorHandle(); if( bIsPlayingUser( hActor ) == false ) continue; if( hActor->GetTeam() == PvPCommon::Team::Zombie ) { ++iZombieCount; if( hActor->IsDie() ) ++iZombieDeadCount; } } if( iZombieCount <= 0 ) return; if( iZombieCount == iZombieDeadCount ) uiWinTeam = PvPCommon::Team::Human; else return; CPvPRoundMode::_ProcessFinishRound( uiWinTeam, Reason ); return; } } CPvPRoundMode::OnCheckFinishRound( Reason ); } void CPvPZombieMode::OnFinishRound() { } void CPvPZombieMode::OnDie( DnActorHandle hActor, DnActorHandle hHitter ) { CPvPGameMode::OnDie( hActor, hHitter ); // Àΰ£->Á»ºñ ÀÌ¸é ¹Ù·Î º¯½Å½ÃŲ´Ù if( hActor && hActor->IsPlayerActor() && static_cast(hActor.GetPointer())->IsTransformMode() == false ) hActor->SetDieDelta( 0.f ); } void CPvPZombieMode::OnLeaveUser( DnActorHandle hActor ) { if( hActor ) m_mZombieActor.erase( hActor->GetUniqueID() ); CPvPRoundMode::OnLeaveUser( hActor ); CDnPlayerActor *pPlayer = static_cast(hActor.GetPointer()); if( pPlayer ) { CDNUserSession* pSession = pPlayer->GetUserSession(); if( pSession->GetAddGhoulScore(GhoulMode::PointType::GhoulKill) || pSession->GetAddGhoulScore(GhoulMode::PointType::HumanKill) || pSession->GetAddGhoulScore(GhoulMode::PointType::HolyWaterUse) ) { pSession->GetDBConnection()->QueryAddPVPGhoulScores(pSession); pSession->ClearAddGhoulScore(); } } } void CPvPZombieMode::OnSuccessBreakInto( CDNUserSession* pGameSession ) { CPvPRoundMode::OnSuccessBreakInto( pGameSession ); // ³­ÀÔ À¯Àú¿¡°Ô Á»ºñ Á¤º¸ ¾Ë·ÁÁØ´Ù. pGameSession->SendPvPSelectZombie( m_mZombieActor ); } void CPvPZombieMode::OnRebirth( DnActorHandle hActor, bool bForce/*=false*/ ) { TMonsterMutationData Data; memset(&Data, 0, sizeof(TMonsterMutationData)); if( GetZombieActorData(Data) == false ) _ASSERT(0); if( bIsZombie(hActor) ) { _AddZombieBlow( hActor, Data ); } else { _ChangeZombie( hActor, Data ); } } void CPvPZombieMode::_ProcessSelectZombie() { if( m_bInitializeZombie ) return; if( bIsPlaying() == false ) return; // 10Ãʰ¡ Áö³­ÈĺÎÅÍ Zombie ¼³Á¤µÈ´Ù. if( GetElapsedTimeRound() < static_cast(PvPCommon::Common::RoundStartMutationTimeSec) ) return; // ÀÌ¹Ì Á»ºñ°¡ ¼³Á¤µÇ¾îÀÖÀ¸¸é ¼³Á¤ÇÒ Çʿ䰡 ¾ø´Ù. if( m_mZombieActor.empty() == false ) return; InitializeZombie(); m_bInitializeZombie = true; } void CPvPZombieMode::_OnStartRound() { CPvPRoundMode::_OnStartRound(); AllReturnHuman(); m_bInitializeZombie = false; m_mZombieActor.clear(); } void CPvPZombieMode::_ProcessFinishRoundMode( CDNUserSession* pSession, bool bIsWin, UINT uiWinTeam, PvPCommon::FinishReason::eCode Reason ) { if( bIsWin ) { switch(Reason) { case PvPCommon::FinishReason::TimeOver : // ŸÀÓ¿À¹ö { pSession->AddGhoulScore(GhoulMode::PointType::TimeOver); pSession->GetEventSystem()->OnEvent( EventSystem::OnRoundFinished, 4, EventSystem::PvPGameMode, PvPCommon::GameMode::PvP_Zombie_Survival, EventSystem::PvPTeam, PvPCommon::Team::Human, EventSystem::PvPWinCondition, PvPCommon::FinishReason::TimeOver, EventSystem::GhoulModeWin, pSession->GetTotalGhoulScore(GhoulMode::PointType::TimeOver)); break; } case PvPCommon::FinishReason::OpponentTeamAllDead : { if( uiWinTeam == PvPCommon::Team::Human ) // Á»ºñ°¡ ´Ù Á×¾îÀÖÀ½. { pSession->AddGhoulScore(GhoulMode::PointType::HumanWin); pSession->GetEventSystem()->OnEvent( EventSystem::OnRoundFinished, 4, EventSystem::PvPGameMode, PvPCommon::GameMode::PvP_Zombie_Survival, EventSystem::PvPTeam, PvPCommon::Team::Human, EventSystem::PvPWinCondition, PvPCommon::FinishReason::OpponentTeamAllDead, EventSystem::GhoulModeWin, pSession->GetTotalGhoulScore(GhoulMode::PointType::HumanWin)); } break; } case PvPCommon::FinishReason::OpponentTeamAllGone : { if( uiWinTeam == PvPCommon::Team::Human ) { pSession->AddGhoulScore(GhoulMode::PointType::HumanWin); pSession->GetEventSystem()->OnEvent( EventSystem::OnRoundFinished, 4, EventSystem::PvPGameMode, PvPCommon::GameMode::PvP_Zombie_Survival, EventSystem::PvPTeam, PvPCommon::Team::Human, EventSystem::PvPWinCondition, PvPCommon::FinishReason::OpponentTeamAllGone, EventSystem::GhoulModeWin, pSession->GetTotalGhoulScore(GhoulMode::PointType::HumanWin)); } else if( uiWinTeam == PvPCommon::Team::Zombie ) { pSession->AddGhoulScore(GhoulMode::PointType::GhoulWin); pSession->GetEventSystem()->OnEvent( EventSystem::OnRoundFinished, 4, EventSystem::PvPGameMode, PvPCommon::GameMode::PvP_Zombie_Survival, EventSystem::PvPTeam, PvPCommon::Team::Zombie, EventSystem::PvPWinCondition, PvPCommon::FinishReason::OpponentTeamAllGone, EventSystem::GhoulModeWin, pSession->GetTotalGhoulScore(GhoulMode::PointType::GhoulWin)); } break; } } pSession->AddGhoulScore(GhoulMode::PointType::PlayCount); // ¿©±â¼­ DB¿¡ ¶ó¿îµå ÆÇ ÀúÀå pSession->GetDBConnection()->QueryAddPVPGhoulScores( pSession ); pSession->ClearAddGhoulScore(); // ±¸¿ï ¸ðµå ¶ó¿îµå Ƚ¼ö pSession->GetEventSystem()->OnEvent( EventSystem::OnRoundFinished, 2, EventSystem::PvPGameMode, PvPCommon::GameMode::PvP_Zombie_Survival, EventSystem::PvPRoundCount, pSession->GetTotalGhoulScore(GhoulMode::PointType::PlayCount)); } } void CPvPZombieMode::_ChangeZombie( DnActorHandle hActor, const TMonsterMutationData &Data ) { if( bIsZombie(hActor) ) return; if( !hActor || !hActor->IsPlayerActor() ) return; // Á»ºñ Á¤º¸ ¼³Á¤ if (AddZombie(hActor, Data )) { _AddZombieBlow( hActor, Data ); _UpdateSelectZombieCount( hActor->GetSessionID() ); return; } _DANGER_POINT(); } void CPvPZombieMode::_AddHumanBlow( DnActorHandle hActor ) { if( !hActor ) return; // Àΰ£À¸·Î º¯°æµÉ ¶§ ½ºÅ³Á¦ÇÑ std::string strSkillVec; std::vector< std::pair > vData; bool bRet = g_pDataManager->GetPvPGameModeSkillSetting( GetPvPGameModeTable()->iSkillSetting, hActor->GetClassID(), vData ); if( bRet ) { hActor->CmdRemoveStateEffect(STATE_BLOW::BLOW_176); // ½ºÅ³Á¦ÇÑ ºí·Î¿ì¸¦ ÃʱâÈ­ ÇØÁØ´Ù. hActor->GetStateBlow()->Process( 0, 0.f ); for(DWORD i=0; iCmdAddStateEffect( NULL, STATE_BLOW::BLOW_176, -1, strSkillVec.c_str(), true ); // ¼³Á¤µÈ Àΰ£½ºÅ³À» Á¦¿ÜÇÑ ½ºÅ³µéÀº ºñȰ¼ºÈ­ ½ÃŲ´Ù. } if(!(hActor->GetStateBlow()->IsApplied(STATE_BLOW::BLOW_183))) hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_183, -1, NULL, true ); } void CPvPZombieMode::_AddZombieBlow( DnActorHandle hActor, const TMonsterMutationData &Data ) { { USES_CONVERSION; hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_058, -1, I2A(Data.nMutationHP), true ); // 58) ÃÖ´ë HP ºñÀ² hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_002, -1, I2A(Data.nMutationStrPMax), true ); // 2) ¹°¸® °ø°Ý·Â ºñÀ² hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_029, -1, I2A(Data.nMutationStrMMax), true ); // 29) ¸¶¹ý °ø°Ý ºñÀ² hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_004, -1, I2A(Data.nMutationDefP), true ); // 4) ¹°¸® ¹æ¾î·Â ºñÀ² hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_094, -1, I2A(Data.nMutationDefM), true ); // 94) ¸¶¹ý ¹æ¾î ºñÀ² hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_123, -1, I2A(Data.nMutationStiff), true ); // 123) °æÁ÷·Â ºñÀ² º¯°æ hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_124, -1, I2A(Data.nMutationStiffResis), true ); // 124) °æÁ÷·Â ÀúÇ× ºñÀ² º¯°æ hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_126, -1, I2A(Data.nMutationCriticalResis), true ); // 126) Å©¸®Æ¼Äà ÀúÇ× ºñÀ² º¯°æ hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_128, -1, I2A(Data.nMutationStunResis), true ); // 128) ½ºÅÏ ÀúÇ× ºñÀ² º¯°æ hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_061, -1, I2A(Data.nMutationSuperArmor), true ); // 61) ½´ÆÛ¾Æ¸Ó1 ºÎ¿© if(!(hActor->GetStateBlow()->IsApplied(STATE_BLOW::BLOW_183))) hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_183, -1, NULL, true ); // 183) ±¸¿ï¸ðµå¿¡¼­ Á¢µÎ¾î »óÅÂÈ¿°ú Àû¿ë µÇÁö ¾Êµµ·Ï ÇÏ´Â »óÅÂÈ¿°ú } hActor->GetStateBlow()->Process( 0, 0.f ); hActor->CmdRefreshHPSP( hActor->GetMaxHP(), hActor->GetMaxSP() ); } bool CPvPZombieMode::bIsZombie( DnActorHandle hActor ) { if( !hActor || !hActor->IsPlayerActor() ) return false; std::map::iterator itor = m_mZombieActor.find( hActor->GetUniqueID() ); if( itor == m_mZombieActor.end() ) return false; return true; } void CPvPZombieMode::_UpdateSelectZombieCount( UINT uiSessionID ) { std::map::iterator itor = m_mSelectZombieCount.find( uiSessionID ); if( itor != m_mSelectZombieCount.end() ) { ++(*itor).second; } else { m_mSelectZombieCount.insert( std::make_pair(uiSessionID,1) ); } } UINT CPvPZombieMode::_GetSelectZombieCount( UINT uiSessionID ) { std::map::iterator itor = m_mSelectZombieCount.find( uiSessionID ); if( itor != m_mSelectZombieCount.end() ) return (*itor).second; return 0; } void CPvPZombieMode::_GetZombieCandidate( std::vector& vResult ) { UINT uiMinValue = UINT_MAX; std::vector vCandidate; for( UINT i=0 ; iGetUserCount() ; ++i ) { CDNUserSession* pSession = GetGameRoom()->GetUserData(i); if( !pSession || !pSession->GetActorHandle() ) continue; if( !bIsPlayingUser( pSession->GetActorHandle() ) ) continue; UINT uiCount = _GetSelectZombieCount( pSession->GetSessionID() ); if( uiCount < uiMinValue ) uiMinValue = uiCount; vCandidate.push_back( pSession->GetActorHandle() ); } for( UINT i=0 ; iGetSessionID() ) == uiMinValue ) vResult.push_back( vCandidate[i] ); } } void CPvPZombieMode::InitZombieGroupData() { g_pDataManager->GetGhoulGroup(GetGameRoom()->GetUserCountWithoutGM(), m_MutationGroup, m_nGhoulCount); } bool CPvPZombieMode::GetZombieActorData(TMonsterMutationData &Data) { int nRandomOffset = _roomrand(GetGameRoom())%1000000000; int nTotalProb = 0; for (int i = 0; i < PvPCommon::Common::MonsterMutationColCount; i++) { if( nRandomOffset < m_MutationGroup.nProbability[i] + nTotalProb ) return g_pDataManager->GetMonsterMutationData(m_MutationGroup.nMonsterID[i], Data); nTotalProb += m_MutationGroup.nProbability[i]; } return false; } bool CPvPZombieMode::AddZombie(DnActorHandle hActor, const TMonsterMutationData &Data ) { if( !hActor || !hActor->IsPlayerActor() ) return false; std::map::iterator itor = m_mZombieActor.find( hActor->GetUniqueID() ); if( itor == m_mZombieActor.end() ) { m_mZombieActor.insert(std::make_pair(hActor->GetUniqueID(), hActor)); // Á»ºñ ÆÀÀ¸·Î º¯°æ hActor->CmdChangeTeam( PvPCommon::Team::Zombie ); static_cast(hActor.GetPointer())->GetUserSession()->SetTeam( PvPCommon::Team::Zombie ); static_cast(hActor.GetPointer())->ToggleTransformMode(true, Data.nMutationID ); // ¾×ÅÍ Á»ºñ¼³Á¤ // ·£´ý »çÀÌÁî _fpreset(); int nScale = 100; int nMin = Data.nSizeMin; int nMax = Data.nSizeMax; if( nMin <= nMax ) { nScale = ( nMin + ( _rand(hActor->GetRoom())%( ( nMax + 1 ) - nMin ) ) ); } float fScale = nScale/100.f; static_cast(hActor.GetPointer())->SetScale( EtVector3( fScale, fScale, fScale ) ); _ASSERT( GetGameRoom()->bIsPvPRoom() ); static_cast(GetGameRoom())->SendSelectZombie( hActor, Data.nMutationID, true, false, nScale ); return true; } return false; } bool CPvPZombieMode::DelZombie(DnActorHandle hActor, bool bRemoveStateBlow/*=false*/ ) { if( !hActor || !hActor->IsPlayerActor() ) return false; std::map::iterator itor = m_mZombieActor.find( hActor->GetUniqueID() ); if( itor != m_mZombieActor.end() ) { // Àΰ£ ÆÀÀ¸·Î º¯°æ hActor->CmdChangeTeam( PvPCommon::Team::Human ); static_cast(hActor.GetPointer())->GetUserSession()->SetTeam( PvPCommon::Team::Human ); static_cast(hActor.GetPointer())->ToggleTransformMode(false); // »çÀÌÁî º¹±¸ static_cast(hActor.GetPointer())->SetScale( EtVector3( 1.f, 1.f, 1.f ) ); _ASSERT( GetGameRoom()->bIsPvPRoom() ); static_cast(GetGameRoom())->SendSelectZombie( hActor, -1, false, bRemoveStateBlow ); m_mZombieActor.erase(itor); if( bRemoveStateBlow ) { // ³ª¸ÓÁö, ´Ù¸¥ Ç÷¹À̾ ¸÷¿¡ ÀÇÇØ °É·Á ÀÖ´Â »óÅÂÈ¿°ú ¸ðµÎ ¾ø¾Ø´Ù. hActor->RemoveAllBlowExpectPassiveSkill(); hActor->GetStateBlow()->Process( 0, 0.f ); hActor->CmdRefreshHPSP( hActor->GetMaxHP(), hActor->GetMaxSP() ); } // Àΰ£ »óÅÂÈ¿°ú _AddHumanBlow( hActor ); return true; } return false; } void CPvPZombieMode::InitializeZombie() { InitZombieGroupData(); if (GetZombieCount() >= m_nGhoulCount) return; _srand( GetGameRoom(), timeGetTime() ); for (int i = 0; i < m_nGhoulCount; i++) { TMonsterMutationData Data; memset(&Data, 0, sizeof(TMonsterMutationData)); if (GetZombieActorData(Data) == false) { _DANGER_POINT(); continue; } std::vector vResult; _GetZombieCandidate( vResult ); if( vResult.empty() ) return; DnActorHandle hZombie = vResult[_roomrand(GetGameRoom())%vResult.size()]; _ChangeZombie( hZombie, Data ); } } void CPvPZombieMode::AllReturnHuman() { CDNUserSession * pSession = NULL; for (int i = 0; i < (int)GetGameRoom()->GetUserCount(); i++) { pSession = GetGameRoom()->GetUserData(i); if (pSession ) { if( pSession->GetTeam() == PvPCommon::Team::Observer ) continue; if( DelZombie(pSession->GetActorHandle()) == false ) { _AddHumanBlow( pSession->GetActorHandle() ); } } else _DANGER_POINT(); } }