#include "stdafx.h" #include #include //================================================================================================== // #include #include // for debugging control #undef WAVERIX_DEBUGGING_OUTPUTn #undef WAVERIX_DEBUGGING_OUTPUTnV #define WAVERIX_DEBUGGING_OUTPUTn(msg) \ SUNLOG(eCRITICAL_LOG, "[%s][%u][%u] %s\n", __FUNCTION__, __LINE__, \ (DWORD)((GetTickCount()-tickvalue)/(1000)), msg); \ tickvalue = GetTickCount() #define WAVERIX_DEBUGGING_OUTPUTnV(value) \ { CHAR _message[10]; \ WAVERIX_DEBUGGING_OUTPUTn(_itoa(value, _message, sizeof(_message))); } static DWORD tickvalue = GetTickCount(); #include "GameSSQControlInfos.hxx" #include "GameSSQPacketProcess.hxx" #include "GameSSQUpdateCtrl.hxx" #include "GameSSQControlManagerImpl.hxx" #include "SSQHandlerInGame.h" //_NA_001990_ACSYSTEM_ADD #include "AchievementManager.h" #ifdef _NA_002950_20110627_SSQ_NOTICE #include "GameGuildManager.h" #endif //================================================================================================== // // VOID GameSSQUpdateCtrl::MigrationDefault(const SSQCODE CodeOfSSQ, GameSSQControlManagerImpl* const pMgrImpl, SSQMsgRouterInGame* const pMsgParser, SSQInfo* const pSSQInfo) { m_CodeOfSSQ = CodeOfSSQ; m_CurType = GameSSQControlInfo::TT_MAX; m_Timer.Stop(); m_pManager = pMgrImpl; m_pMsgParser = pMsgParser; m_pSSQInfo = pSSQInfo; m_pSSQField = 0; if(m_pMsgParser) m_pMsgParser->SetUpdateCtrl(this); // SharedConstVariables }; //-------------------------------------------------------------------------------------------------- VOID GameSSQUpdateCtrl::RegisterUpdateCtrl(GameSSQUpdateCtrl* const pTarget) { GameSSQControlManagerImpl* const pImpl = pTarget->m_pManager; pImpl->_RegisterUpdateCtrl(pTarget->m_CodeOfSSQ, pTarget); } //-------------------------------------------------------------------------------------------------- GameSSQUpdateCtrl* GameSSQUpdateCtrl::ChangeToNextUpdateCtrl(GameSSQUpdateCtrl* const pCurUpdater, const GameSSQControlInfo::eTIME_TYPE nextType) { GameSSQControlManagerImpl* const pImpl = pCurUpdater->m_pManager; const eTIME_TYPE curType = pCurUpdater->m_CurType; // ´ÜÀÏ Interface·Î ÁøÇàÀÌ °¡´ÉÇÑÁö ¿©ºÎ ÆÇ´ÜÇÒ °Í. GameSSQUpdateCtrl* pNextUpdater = NULL; switch(nextType) { #undef SSQ_UPDATE_CTRL_NODE #define SSQ_UPDATE_CTRL_NODE(_type) \ case _type::value: pNextUpdater = TAllocNew(_type::value_type); break; SSQ_UPDATE_CTRL_LIST(); } if(!FlowControl::FCAssert(pNextUpdater)) { // ÀÌÈÄ ´ëÃ¥À» °­±¸ÇÒ °Í. return 0; } // Shared Logic pNextUpdater->Migration(pNextUpdater, pCurUpdater); pNextUpdater->Init(); pNextUpdater->RegisterUpdateCtrl(pNextUpdater); switch(curType) { #undef SSQ_UPDATE_CTRL_NODE #define SSQ_UPDATE_CTRL_NODE(_type) \ case _type::value: TAllocDelete(_type::value_type, pCurUpdater); break; SSQ_UPDATE_CTRL_LIST(); } //pImpl->_RegisterUpdateCtrl(pCurUpdater->m_ID, pTarget); return pNextUpdater; } //-------------------------------------------------------------------------------------------------- BOOL GameSSQUpdateCtrl::UpdateMsg(const curtime_info& tmInfo) { if(m_pMsgParser->GetUpdateCtrl()) m_pMsgParser->Update(m_CodeOfSSQ); return TRUE; } //-------------------------------------------------------------------------------------------------- VOID GameSSQUpdateCtrl::RecvedMsgProcess(const WAR_MSG_HDR* IN pStream) { if(m_pMsgParser->GetUpdateCtrl()) m_pMsgParser->OnRecv(pStream); } //-------------------------------------------------------------------------------------------------- VOID GameSSQUpdateCtrl::ConstVarsInit(GameSSQUpdateCtrl* const pUpdateCtrl) { const SSQInfo* const pSSQInfo = pUpdateCtrl->m_pSSQInfo; pUpdateCtrl->m_ConstVars.pCheckFilters = TAllocNew(MatchCheckCodeFilters); MatchCheckCodeFilters& rFilters = *pUpdateCtrl->m_ConstVars.pCheckFilters; new (&rFilters.SkillGroupFilter) MatchCheckCodeFilterArray(pSSQInfo->m_RestrictSkillGroupInfo.Count, pSSQInfo->m_RestrictSkillGroupInfo.SkillGroupCodes); new (&rFilters.ItemTypeFilter) MatchCheckCodeFilterArray(pSSQInfo->m_RestrictItemTypeInfo.Count, pSSQInfo->m_RestrictItemTypeInfo.ItemTypes); } //-------------------------------------------------------------------------------------------------- VOID GameSSQUpdateCtrl::ConstVarsRelease(GameSSQUpdateCtrl* const pUpdateCtrl) { if(pUpdateCtrl->m_ConstVars.pCheckFilters) { TAllocDelete(MatchCheckCodeFilters, pUpdateCtrl->m_ConstVars.pCheckFilters); pUpdateCtrl->m_ConstVars.pCheckFilters = 0; } } //================================================================================================== // VOID GameSSQUpdateCtrl_None::Init() { m_CurType = value; m_Timer.SetTimer(interval); ZeroMemory(&m_SharedVars, sizeof(m_SharedVars)); m_SharedVars.UpdaterState = SharedVariables::eBattle_NotStarted; } //-------------------------------------------------------------------------------------------------- BOOL GameSSQUpdateCtrl_None::Update(const curtime_info& tmInfo) { if(m_Timer.IsExpired()) { //WAVERIX_DEBUGGING_OUTPUTnV(m_CodeOfSSQ); } return TRUE; } //================================================================================================== // GameSSQReport::GameSSQReport() : m_pUpdater(0) //, m_LastUpdatedChrNum(0) { } VOID GameSSQReport::Init(GameSSQUpdateCtrl* const pUpdater) { m_pUpdater = pUpdater; m_ReportTimer.SetTimer(UPDATE_INTERVAL); } VOID GameSSQReport::Update(const curtime_info& tmInfo, const BOOLEAN bForced) { if(bForced || m_ReportTimer.IsExpired()) { // ÀÏ´Ü 5Ãʸ¶´Ù º¸³»´Â °É·Î ÇÏÀÚ. BROADCASTER_MSG_AG_ZONE_SSQ_ROOM_CTRL_CMD& rMsgCMD = m_pUpdater->GetMsgRouter()->GetCMD_AG(); WAR_MSG_HDR* const pHeader = &rMsgCMD.MSG_HEADER; { const SSQInfo::COUNT_T remained_num = m_pUpdater->SharedVars.RemainedTotal; MSGSUB_SSQ_PROTOCOL_INFORMATION_COUNT_OF_PLAYERS msg; msg.Remains = remained_num; msg.SerializeTo(pHeader); }; //const eTIME_TYPE updater_type = m_pUpdater->GetTimeType(); //if(updater_type == TT_BATTLE) //{ // const SSQInfo::MINUTE_T remained_playing_time = m_pUpdater->SharedVars.RemainedTime; // MSGSUB_SSQ_PROTOCOL_INFORMATION_REMAINED_TIME msg; // msg.Remains = remained_playing_time; // msg.SerializeTo(pHeader); //} } } //================================================================================================== // VOID GameSSQUpdateCtrl_Created::Init() { m_CurType = value; m_Timer.SetTimer(interval); m_Reporter.Init(this); typedef SSQTraps ST; m_Traps.Init(this, ST::eTrapFlag(ST::TRAP_ENABLED | ST::TRAP_ENABLED_THUNDERBOLT_SHOW)); } BOOL GameSSQUpdateCtrl_Created::Update(const curtime_info& tmInfo) { if(m_Timer.IsExpired()) { WAVERIX_DEBUGGING_OUTPUTnV(m_CodeOfSSQ); m_Reporter.Update(tmInfo); m_Traps.Update(tmInfo); } return TRUE; } //================================================================================================== // SSQTraps::SSQTraps() : pUpdateCtrl(0) { TrapUpdateTimer.Stop(); } VOID SSQTraps::Init(GameSSQUpdateCtrl* const pUpdater, const eTrapFlag control_flags) { pUpdateCtrl = pUpdater; TrapUpdateTimer.SetTimer(UPDATE_INTERVAL); SSQInfoParser* const pSSQInfoParser = SSQInfoParser::Instance(); const SSQInfo* const pSSQInfo = pUpdateCtrl->GetSSQInfo(); { sTIME_INFO timeInfo; sTIME_INFO::SetTimeValue(timeInfo); StartAcmTime = timeInfo.AcmTime; }; { // SSQDistributionChart Initialize TrapFlag = TRAP_NONE; GameInstanceDungeon* const pSSQField = pUpdateCtrl->GetSSQField(); GameField* const pField = DamageExecuter.SetAndGetSSQField(pSSQField); pGameField = pField; const SectorGrid& rGrid = pField->SectorGridRef; DamageExecuter.SetProjectionGrid(&rGrid); }; { TrapFlag |= TRAP_ENABLED; }; if(control_flags & TRAP_ENABLED_EARTHQUAKE) { // Earthquake Pattern Initialize typedef SSQInfoParser::SSQPATTERN_TABLE SSQPATTERN_TABLE; const SSQPATTERN_TABLE& rPatterns = pSSQInfoParser->GetRefSSQPattern(); const DWORD patterns_upperbound = (DWORD)rPatterns.size(); const DWORD selected_pattern = RandomNumberGenerator::GetRandomNumberRange(0, patterns_upperbound); SSQPATTERN_TABLE::const_iterator where = rPatterns.begin(); advance(where, selected_pattern); SSQPattern* const pPattern = where->second; EarthquakeInfo.pPattern = pPattern; EarthquakeInfo.Mode = EARTHQUAKE_NONE; EarthquakeInfo.PatternIndex = pPattern->m_Index; EarthquakeInfo.PatternArrayIndex = 0; EarthquakeInfo.LastUpdateCounter = 0; EarthquakeInfo.UpdateTimer.SetTimer(UPDATE_EARTHQUAKE_CHECK_INTERVAL); TrapFlag |= TRAP_ENABLED_EARTHQUAKE; }; if(control_flags & (TRAP_ENABLED_THUNDERBOLT|TRAP_ENABLED_THUNDERBOLT_SHOW)) { // Thunderbolt Initialize ThunderboltInfo.ThunderboltData = pSSQInfo->m_ThunderboltInfo; const DWORD interval = ThunderboltInfo.ThunderboltData.m_RaisePerXsec * second; SetVector(&ThunderboltInfo.SearchRangeWeight, SSQThunderbolt_DamageRadius, SSQThunderbolt_DamageRadius, 0.f); ThunderboltInfo.UpdateTimer.SetTimer(interval); TrapFlag |= TRAP_ENABLED_THUNDERBOLT; }; if(control_flags & TRAP_ENABLED_THUNDERBOLT_SHOW) TrapFlag |= TRAP_ENABLED_THUNDERBOLT_SHOW; if(control_flags & TRAP_ENABLED_CLOSEDSPACE) { // ClosedSpace ClosedSpaceInfo.ClosedSpaceData = pSSQInfo->m_ClosedSpaceInfo; const DWORD interval = ClosedSpaceInfo.ClosedSpaceData.m_RaisePerXsec * second; ClosedSpaceInfo.UpdateTimer.SetTimer(interval); TrapFlag |= TRAP_ENABLED_CLOSEDSPACE; }; } //-------------------------------------------------------------------------------------------------- #ifdef __WAVERIX_TEST_LOGIC_TASK_MACRO__ extern BOOLEAN Variation_SSQ_Trap_Art_R1(const GameSSQUpdateCtrl* const pUpdateCtrl); #endif VOID SSQTraps::Update(const curtime_info& tmInfo) { if(!TrapUpdateTimer.IsExpired()) return; const SSQInfo* const pSSQInfo = pUpdateCtrl->GetSSQInfo(); BROADCASTER_MSG_AG_ZONE_SSQ_ROOM_CTRL_CMD& rMsgCMD = pUpdateCtrl->GetMsgRouter()->GetCMD_AG(); WAR_MSG_HDR* const pHeader = &rMsgCMD.MSG_HEADER; if((TrapFlag & TRAP_ENABLED_EARTHQUAKE) && EarthquakeInfo.UpdateTimer.IsExpired()) { switch(EarthquakeInfo.Mode) { case EARTHQUAKE_NONE: if(EarthquakeInfo.LastUpdateCounter == EarthquakeInfo.PatternArrayIndex && EarthquakeInfo.LastUpdateCounter < EarthquakeInfo.pPattern->m_BanLiftStep) { GameSSQControlInfo::AcmTmFmt elapsedTm = tmInfo.AcmTime - StartAcmTime; // ASSERT(tmInfo.AcmTime>=StartAcmTime); const SSQInfo::COUNT_T characters_number = pUpdateCtrl->SharedVars.RemainedTotal; SSQInfo::EARTHQUAKE_NODE node = { (SSQInfo::MINUTE_T)elapsedTm, characters_number }; const BOOLEAN bOkEarthquakeCond = pSSQInfo->m_EarthquakeInfo[EarthquakeInfo.PatternArrayIndex].OnSatisfiedCondition(node); if(bOkEarthquakeCond) { EarthquakeInfo.Mode = EARTHQUAKE_INDICATION; EarthquakeInfo.UpdateTimer.SetTimer(UPDATE_EARTHQUAKE_CHANGE_TO_INDICATION); } } break; case EARTHQUAKE_INDICATION: { { MSGSUB_SSQ_PROTOCOL_TRAP_EARTHQUAKE_INDICATION msg; msg.PatternIndex = EarthquakeInfo.PatternIndex; msg.StepArrayIndex = EarthquakeInfo.PatternArrayIndex; msg.SerializeTo(pHeader); }; EarthquakeInfo.Mode = EARTHQUAKE_EXECUTE; EarthquakeInfo.UpdateTimer.SetTimer(UPDATE_EARTHQUAKE_INDICATION_INTERVAL); DamageExecuter.Earthquake_Indication(EarthquakeInfo.pPattern, EarthquakeInfo.PatternArrayIndex); if((EarthquakeInfo.LastUpdateCounter + 1) == EarthquakeInfo.pPattern->m_BanLiftStep) DamageExecuter.ClosedSpace_RemoveDanger(pSSQInfo); } break; case EARTHQUAKE_EXECUTE: { SSQMsgRouterInGame* const pMsgRouter = pUpdateCtrl->GetMsgRouter(); { const SSQCODE CodeOfSSQ = pUpdateCtrl->GetCodeOfSSQ(); pMsgRouter->Update(CodeOfSSQ); MSGSUB_SSQ_PROTOCOL_TRAP_EARTHQUAKE_EXECUTE msg; msg.SerializeTo(pHeader); MSGSUB_SSQ_PROTOCOL_CONTROL_FORCED_POSITION_CORRECTION msgFPC; DamageExecuter.Earthquake(EarthquakeInfo.pPattern, EarthquakeInfo.PatternArrayIndex, msgFPC); msgFPC.SerializeTo(pHeader); pMsgRouter->Update(CodeOfSSQ); }; ++EarthquakeInfo.PatternArrayIndex; ++EarthquakeInfo.LastUpdateCounter; EarthquakeInfo.Mode = EARTHQUAKE_NONE; EarthquakeInfo.UpdateTimer.SetTimer(UPDATE_EARTHQUAKE_CHECK_INTERVAL); if(EarthquakeInfo.LastUpdateCounter == EarthquakeInfo.pPattern->m_BanLiftStep) TrapFlag = TrapFlag & (~TRAP_ENABLED_EARTHQUAKE); } break; } } if((TrapFlag & (TRAP_ENABLED_THUNDERBOLT|TRAP_ENABLED_THUNDERBOLT_SHOW)) && ThunderboltInfo.UpdateTimer.IsExpired()) { { MSGSUB_SSQ_PROTOCOL_TRAP_THUNDERBOLT_EXECUTE msgTTE; MSGSUB_SSQ_PROTOCOL_CONTROL_DAMAGE_PROCESS msgCDP; const BOOLEAN bShowmanship = !!(TrapFlag&TRAP_ENABLED_THUNDERBOLT_SHOW); const BOOLEAN bProcOutRangeClosedSpace = bShowmanship ? TRUE : !!(TrapFlag & TRAP_ENABLED_EARTHQUAKE); DamageExecuter.Thunderbolt(pSSQInfo, bShowmanship, &ThunderboltInfo.SearchRangeWeight, bProcOutRangeClosedSpace, bProcOutRangeClosedSpace ? msgTTE.MAX_SIZE : (msgTTE.MAX_SIZE >> 1), msgTTE, msgCDP); if(msgTTE.Count) msgTTE.SerializeTo(pHeader); if(msgCDP.Count) msgCDP.SerializeTo(pHeader); }; } if((TrapFlag & TRAP_ENABLED_CLOSEDSPACE) && ClosedSpaceInfo.UpdateTimer.IsExpired()) { { MSGSUB_SSQ_PROTOCOL_TRAP_CLOSEDSPACE_EXECUTE msgTCE; DamageExecuter.ClosedSpace(pSSQInfo, EarthquakeInfo.LastUpdateCounter, msgTCE); if(msgTCE.Count) msgTCE.SerializeTo(pHeader); } if(!(TrapFlag&TRAP_ENABLED_EARTHQUAKE)) { MSGSUB_SSQ_PROTOCOL_TRAP_CLOSEDSPACE_DISABLED msgTCD; msgTCD.SerializeTo(pHeader); TrapFlag = TrapFlag & (~TRAP_ENABLED_CLOSEDSPACE); //DamageExecuter.ClosedSpace_Remove(pSSQInfo); } } #ifdef __WAVERIX_TEST_LOGIC_TASK_MACRO__ Variation_SSQ_Trap_Art_R1(pUpdateCtrl); #endif } //end SSQTraps::Update //================================================================================================== // GameSSQUpdateCtrl_Battle::~GameSSQUpdateCtrl_Battle() { } VOID GameSSQUpdateCtrl_Battle::Init() { m_CurType = value; m_Timer.SetTimer(interval); m_Reporter.Init(this); typedef SSQTraps ST; m_Traps.Init(this, ST::eTrapFlag(ST::TRAP_ENABLED | ST::TRAP_ENABLED_EARTHQUAKE | ST::TRAP_ENABLED_THUNDERBOLT | ST::TRAP_ENABLED_CLOSEDSPACE)); m_PlayersUpdateTimer.SetTimer(player_event_update_interval); m_SharedVars.BattleState = SharedVariables::eBattle_Init; m_SharedVars.UpdaterState = SharedVariables::eBattle_Init; m_SharedVars.RemainedTime = m_pSSQInfo->m_QuestPlayTime; // ÀÌ°Ç »ç½Ç»ó Agent¿¡¼­ ´ã´çÇÒ ¹®Á¦... GameField* const pGameField = m_pSSQField->GetEntryField(); typedef GameField GF; const GF::_PLAYER_HASH& rPlayers = pGameField->GetRefPlayerList(); new (&ItemDistributer) GameWarSSQItemDistribution(m_pSSQInfo, (DWORD)rPlayers.size()); //typedef GameField GF; //const GF::_PLAYER_HASH& rPlayers = pGameField->GetRefPlayerList(); //m_SharedVars.RemainedTotal = (SSQInfo::COUNT_T)SSQ_MAX_CHARACTERS; //rCharacters.size(); //m_SharedVars.RemainedPlayer = (SSQInfo::COUNT_T)rPlayers.size(); new (&ObserverControl) GameWarObserverMode(m_pSSQField); } BOOL GameSSQUpdateCtrl_Battle::Update(const curtime_info& tmInfo) { // (Á¾·áÁ¶°Ç) // - ÀüÅõ½Ã°£ ³¡³­ °æ¿ì (Ç÷¹ÀÌ¾î º¹¼ö¸íÀÏ ¼ö ÀÖÀ½) <- Agent¿¡¼­ ´ã´çÇÒ °Í. // - ÀüÅõ°¡ ¾ÆÁ÷ ³¡³ªÁö ¾ÊÀº »óÅ¿¡¼­ Ç÷¹À̾î 1¸í ³²´Â °æ¿ì // - ÀüÅõ°¡ ¾ÆÁ÷ ³¡³ªÁö ¾ÊÀº »óÅ¿¡¼­ Ç÷¹À̾î 0¸í µÇ´Â °æ¿ì if(m_Timer.IsExpired()) { //WAVERIX_DEBUGGING_OUTPUTnV(m_CodeOfSSQ); switch(m_SharedVars.BattleState) { case Ret::eBattle_Init: _Process_Init(tmInfo); break; case Ret::eBattle_Progress: _Process_Battle(tmInfo); break; case Ret::eBattle_Timeout: case Ret::eBattle_1_Remained: case Ret::eBattle_PlayerExtermination: case Ret::eBattle_AllDead: case Ret::eBattle_EndReserved: // Á¾·á ´ë±âÀÎ »óÅÂÀÏ È®·üÀÌ ³ô´Ù. break; } m_Reporter.Update(tmInfo); } return TRUE; } BOOLEAN GameSSQUpdateCtrl_Battle::RequestObserverModeCtrl(const MSGSUB_SSQ_S2S_OBSERVER_MODE_CTRL& rMsg) { using namespace Observer; Player* const pPlayer = PlayerManager::Instance()->FindPlayerByObjKey(rMsg.ObjectKey); if(!FlowControl::FCAssert(pPlayer)) return FALSE; //MSGSUB_SSQ_PROTOCOL_REQUEST_OBSERVER_CTRL* const pSub = // const_cast(&rMsg.C2GMsg); const Info::eRequest request = rMsg.Request; const Rules::eC2G_ReqRule rules = Rules::GetC2G_RequestRule(request); BROADCASTER_MSG_AG_ZONE_SSQ_ROOM_CTRL_CMD& rMsgCMD = m_pMsgParser->GetCMD_AG(); WAR_MSG_HDR* const pHeader = &rMsgCMD.MSG_HEADER; MSGSUB_SSQ_S2S_OBSERVER_MODE_RESULT msg; msg.C2GMsg.Init(); msg.ObjectKey = pPlayer->GetObjectKey(); ////////////////////////////////////////////////////////////////////////// // FlowControl flow; FLOWCONTROL_START() { IfFailThenBreak(!(rules & Rules::eC2G_ReqRule_BlockRequest), FALSE); if(rules & Rules::eC2G_ReqRule_CondInFieldServer) { // in FIELD_SERVER IfFailThenBreak(g_pGameServer->GetServerType() != FIELD_SERVER, FALSE); SetFailFc(!"not supported", FALSE); break; } ////////////////////////////////////////////////////////////////////////// // In SSQ Field StatusManager* const pStatusManager = pPlayer->GetStatusManager(); StatusField& rStatus = pStatusManager->Status; IfFailThenBreak(rules & Rules::eC2G_ReqRule_CondInSSQField, FALSE); const BOOLEAN isObserver = !!(rStatus.FIELD & rStatus.ENABLE_OBSERVER_MODE); SSQCharacterStatusInGame& rSSQStatus = pPlayer->SSQHandler->ControlStatus; const BOOLEAN isDead = !!(rSSQStatus.FIELD & rSSQStatus.CHECKED_DEAD); if(rules & Rules::eC2G_ReqRule_CondObserverModeOn) IfFailThenBreak(isObserver, FALSE); if(rules & Rules::eC2G_ReqRule_CondObserverModeOff) IfFailThenBreak(!isObserver, FALSE); if(rules & Rules::eC2G_ReqRule_CondDeadState) IfFailThenBreak(isDead, FALSE); switch(request) { case Info::eRequest_Observer : // not Observer IfFailThenBreak(ObserverControl.Enter(rules, pPlayer), FALSE); break; case Info::eRequest_Leave : // always { MSG_AG_ZONE_MISSION_LEAVE_CMD msgCMD; msgCMD.m_LeaveType = msgCMD.eLeaveType_Default; msgCMD.m_ReturnMapCode = 0; pPlayer->SendPacket(&msgCMD, sizeof(msgCMD)); } break; case Info::eRequest_ChangeCoord : // in ObserverMode IfFailThenBreak( ObserverControl.ChangeCoordinates(rules, pPlayer, rMsg.ObserverCmd.PressedKey), FALSE); break; default: SetFailFc(!"undefined", FALSE); break; } if(flow.IsErrorOccured()) break; MSGSUB_SSQ_PROTOCOL_REQUEST_OBSERVER_CTRL_RESULT& rCGMsg = msg.C2GMsg; rCGMsg.Result = MSGSUB_SSQ_PROTOCOL_REQUEST_OBSERVER_CTRL_RESULT::eNtfCmd_ResultByRequest_Success; ISSQHandlerInGame& rHandler = pPlayer->SSQHandler; rCGMsg.Coordinates = rHandler->GetObserverCoordinateIndex(); msg.SerializeTo(pHeader); return TRUE; } FLOWCONTROL_END; MSGSUB_SSQ_PROTOCOL_REQUEST_OBSERVER_CTRL_RESULT& rCGMsg = msg.C2GMsg; rCGMsg.Result = MSGSUB_SSQ_PROTOCOL_REQUEST_OBSERVER_CTRL_RESULT::eNtfCmd_ResultByRequest_Fail; rCGMsg.Coordinates = Observer::Info::eCoord_Slots; msg.SerializeTo(pHeader); return FALSE; } SharedVariables::eBattleState GameSSQUpdateCtrl_Battle::_CheckBattleEnd(const curtime_info& tmInfo) { // Ç÷¹À̾î, ¸ó½ºÅÍ ³²Àº ÀοøÃ³¸®´Â GameField¸®½ºÆ®¿¡¼­ ÂüÁ¶ÇÒ ¼ö ¾ø´Ù. ¼Òȯ¼ö ¹®Á¦µµ ÀÖ°í, Ç÷¹À̾î, Á×Àº »óÅ °ËÃâµµ ÇÊ¿äÇÏ´Ù. if(0 == m_SharedVars.RemainedTotal) return Ret::eBattle_AllDead; // Á¾·á Á¶°Ç if(1 == m_SharedVars.RemainedTotal) return Ret::eBattle_1_Remained; // Á¾·á Á¶°Ç if(0 == m_SharedVars.RemainedPlayer) // Ç÷¹À̾ Àü¸êÇÏ´Â »óȲµµ ÀÖÀ» °ÍÀÌ´Ù. return Ret::eBattle_PlayerExtermination; // ½Ã°£Àº °í·Á´ë»óÀÌ ¾Æ´Ï´Ù. Agent¿¡¼­ °ü¸®ÇØÁà¾ß ÇÑ´Ù. return Ret::eBattle_Progress; } VOID GameSSQUpdateCtrl_Battle::_Process_Init(const curtime_info& tmInfo) { m_SharedVars.BattleState = Ret::eBattle_Progress; } SharedVariables::eBattleState GameSSQUpdateCtrl_Battle::_Process_Battle(const curtime_info& tmInfo) { const Ret::eBattleState checked_state = _CheckBattleEnd(tmInfo); // ÀÌ »óÅ¿¡ µû¶ó Á¾·á 󸮵µ ¼öÇàÇØ¾ß ÇÑ´Ù. if(checked_state != Ret::eBattle_Progress) { if(m_SharedVars.bTransaction) return Ret::eBattle_EndReserved; _Process_EndReserve(tmInfo, checked_state); } if(Ret::eBattle_Progress == m_SharedVars.BattleState) { m_Traps.Update(tmInfo); _Process_Players(tmInfo); } return m_SharedVars.BattleState; } BOOLEAN GameSSQUpdateCtrl_Battle::_Process_EndReserve(const curtime_info& tmInfo, const Ret::eBattleState battle_state) { BROADCASTER_MSG_AG_ZONE_SSQ_ROOM_CTRL_CMD& rMsgCMD = m_pMsgParser->GetCMD_AG(); WAR_MSG_HDR* const pHeader = &rMsgCMD.MSG_HEADER; { MSGSUB_SSQ_S2S_BATTLE_END_REQUEST msg; msg.CodeOfSSQ = m_CodeOfSSQ; msg.SerializeTo(pHeader); m_SharedVars.bTransaction = TRUE; }; { // Last Update m_Reporter.Update(tmInfo, TRUE); }; m_SharedVars.BattleState = battle_state; return TRUE; } VOID GameSSQUpdateCtrl_Battle::_Process_Players(const curtime_info& tmInfo) { if(!m_PlayersUpdateTimer.IsExpired()) return; typedef GameField GF; typedef GF::_PLAYER_HASH _PLAYER_HASH; BROADCASTER_MSG_AG_ZONE_SSQ_ROOM_CTRL_CMD& rMsgCMD = m_pMsgParser->GetCMD_AG(); WAR_MSG_HDR* const pHeader = &rMsgCMD.MSG_HEADER; GF* const pGameField = m_pSSQField->GetEntryField(); const _PLAYER_HASH& rPlayers = pGameField->GetRefPlayerList(); FOREACH_CONTAINER(const _PLAYER_HASH::value_type& rPlayer, rPlayers, _PLAYER_HASH) { Player* const pPlayer = rPlayer.second; if (obj_util::IsValid(pPlayer, __FUNCTION__, __LINE__) == false) { continue; } ISSQHandlerInGame& rHandler = pPlayer->SSQHandler; SSQCharacterStatusInGame& rSSQStatus = rHandler->ControlStatus; if(rSSQStatus.FIELD & rSSQStatus.CHECKED_DEAD) { if(rHandler->QueryEvent_NeedLeaveProcess(pPlayer)) // Çѹø ó¸®µÇ¸é ´Ù½Ã ó¸®µÇÁö ¾Ê´Â´Ù. { MSGSUB_SSQ_S2S_OBSERVER_MODE_SELECT_WINDOW msg; msg.ObjectKey = pPlayer->GetObjectKey(); msg.SerializeTo(pHeader); } } } //m_SharedVars.RemainedTotal = (SSQInfo::COUNT_T)SSQ_MAX_CHARACTERS; //rCharacters.size(); //m_SharedVars.RemainedPlayer = (SSQInfo::COUNT_T)rPlayers.size(); } //==================================================================================================¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬ // VOID GameSSQUpdateCtrl_Clear::Init() { m_CurType = value; m_Timer.SetTimer(interval); m_ClearStep = STEP_INIT; } BOOL GameSSQUpdateCtrl_Clear::Update(const curtime_info& tmInfo) { if(!m_Timer.IsExpired()) return TRUE; WAVERIX_DEBUGGING_OUTPUTnV(m_CodeOfSSQ); switch(m_ClearStep) { case STEP_INIT: m_ClearStep = (eSTEP)(m_ClearStep+1); case STEP_WINNER_PROC: Winner_Process(tmInfo); break; case STEP_LEAVE_PROCESS: Leave_Process(tmInfo); break; case STEP_WAIT: m_Timer.SetTimer(interval_for_leave_wait); m_ClearStep = (eSTEP)(m_ClearStep+1); break; case STEP_MAX: { BROADCASTER_MSG_AG_ZONE_SSQ_ROOM_CTRL_CMD& rMsgCMD = m_pMsgParser->GetCMD_AG(); WAR_MSG_HDR* const pHeader = &rMsgCMD.MSG_HEADER; MSGSUB_SSQ_S2S_BATTLE_CLEARED msg; msg.CodeOfSSQ = m_CodeOfSSQ; msg.SerializeTo(pHeader); } break; } return TRUE; } //-------------------------------------------------------------------------------------------------- struct sPointNode { DWORD point; DWORD exp; //µ¿Á¡ÀÚ¿¡ ´ëÇÑ Ãß°¡ ºñ±³ ¸ñÀû Player* pPlayer; bool operator > (const sPointNode& rRight) const { if(point > rRight.point) return true; if(rRight.point > point) return false; return (exp > rRight.exp); } }; //-------------------------------------------------------------------------------------------------- VOID GameSSQUpdateCtrl_Clear::Winner_Process(const curtime_info& tmInfo) { typedef STLX_VECTOR< sPointNode > RankOrderList; DWORD proced_players = 0; // (CHANGES) (f100427.1L) change to more cheap routine static RankOrderList rankOrders; rankOrders.resize(0); // Äù½ºÆ® ¼º°øÇÑ ÀÌµé ¼³Á¤ typedef GameField::_PLAYER_HASH _PLAYER_HASH; const _PLAYER_HASH& rPlayers = m_pSSQField->GetEntryField()->GetRefPlayerList(); FOREACH_CONTAINER(const _PLAYER_HASH::value_type& rPlayer, rPlayers, _PLAYER_HASH) { Player* const pPlayer = rPlayer.second; if (obj_util::IsValid(pPlayer, __FUNCTION__, __LINE__) == false) { continue; } ISSQHandlerInGame& rRewarder = pPlayer->SSQHandler; const eEVENT_MODE_MULTIUSE reward_type = rRewarder->GetSSQEventID(); // »ç½Ç Å×½ºÆ® ¸ñÀûÀ¸·Î ÀüÅõÁß Áß°£ °³ÀԽà ȯºÒ Á¤º¸°¡ ±âÀçµÉ °ÍÀÌ´Ù. ÀÌ Á¡Àº °¨¾ÈÇϵµ·Ï ÇÏÀÚ. if(reward_type == eEVENT_MULTIUSE_SSQ_REFUND) continue; m_pManager->SettleAccounts(this, pPlayer); SSQ_RESERVED_REWARD_INFO info; if(!FlowControl::FCAssert(rRewarder->GetRewardInfo(info))) continue; ++proced_players; StatusField& rStatus = pPlayer->GetStatusManager()->Status; SSQCharacterStatusInGame& rSSQStatus = rRewarder->ControlStatus; const BOOLEAN bLoser = (rStatus.FIELD & rStatus.ENABLE_OBSERVER_MODE) || (rSSQStatus.FIELD & rSSQStatus.CHECKED_DEAD); // ó¸® ¿©ºÎ´Â È®ÀÎÇÒ °Í. //m_pManager->UpdateToRankingAndExtra(this, pPlayer); if(bLoser) continue; // Design Miss // - SettleAccounts´Â ½ÇÆÐ Á¤º¸¸¦ ±â¹ÝÀ¸·Î °è»êµÇ°Ô µÇ¾î ÀÖ´Ù. rRewarder->UpdateInfo_ChangeToWinner(); sPointNode node; node.point = info.m_WinnerReward.Point; node.exp = info.m_WinnerReward.Exp; node.pPlayer= pPlayer; rankOrders.push_back(node); } const BOOLEAN isExist = !rankOrders.empty(); Player* top_winner = 0; if(isExist) { std::sort(rankOrders.begin(), rankOrders.end(), std::greater< sPointNode >()); SSQHandlerInGame::eOrder order = SSQHandlerInGame::eOrder_1st; const DWORD upperbound = (DWORD)rankOrders.size(); // ´õ ÁÁÀº ¾Ë°í¸®ÁòÀ» »ý°¢Ç϶ó. FOREACH_CONTAINER(const RankOrderList::value_type& rOrder, rankOrders, RankOrderList) { Player* const pPlayer = rOrder.pPlayer; if(SSQHandlerInGame::eOrder_1st == order) top_winner = pPlayer; if(SSQHandlerInGame::eOrder_None != order) { m_pManager->SettleAccounts(this, pPlayer, order); m_pManager->RewardForWinner(this, pPlayer, order); order = (SSQHandlerInGame::eOrder)(order+1); } m_pManager->UpdateToRankingAndExtra(this, pPlayer); //_NA_001990_ACSYSTEM_ADD pPlayer->GetACManager()->IncConditionValue(ACHIEVEMENT_OBJECT_WIN, pPlayer->GetGameZonePtr()->GetMapCode()); } } m_ClearStep = (eSTEP)(m_ClearStep+1); m_Timer.SetTimer(interval_for_leave); BROADCASTER_MSG_AG_ZONE_SSQ_ROOM_CTRL_CMD& rMsgCMD = m_pMsgParser->GetCMD_AG(); WAR_MSG_HDR* const pHeader = &rMsgCMD.MSG_HEADER; if(isExist && top_winner) { MSGSUB_SSQ_PROTOCOL_INFORMATION_QUEST_SUCCESS_RESULT msg; msg.WinnerName.CopyFrom(top_winner->GetCharName()); #ifdef _NA_002950_20110627_SSQ_NOTICE const GameGuild* const guild = g_GameGuildManager.FindGuild(top_winner->GetGuildGuid()); if (guild != NULL) { typedef MSGSUB_SSQ_PROTOCOL_INFORMATION_QUEST_SUCCESS_RESULT::GuildNameBuffer GuildNameBuffer; BOOST_STATIC_ASSERT(GuildNameBuffer::SZ_STRING_LENGTH_WITH_NULL >= _countof(top_winner->GetCharInfo()->m_tszGuildName)); msg.guild_name.CopyFrom(top_winner->GetCharInfo()->m_tszGuildName); } #endif msg.SerializeTo(pHeader); } else { MSGSUB_SSQ_PROTOCOL_INFORMATION_QUEST_FAIL_RESULT msg; msg.bIsNotStarted = m_SharedVars.UpdaterState == SharedVariables::eBattle_NotStarted; msg.SerializeTo(pHeader); }; } //-------------------------------------------------------------------------------------------------- VOID GameSSQUpdateCtrl_Clear::Leave_Process(const curtime_info& tmInfo) { MSG_AG_ZONE_MISSION_LEAVE_CMD msgCMD; msgCMD.m_LeaveType = msgCMD.eLeaveType_Default; msgCMD.m_ReturnMapCode = 0; typedef GameField::_PLAYER_HASH _PLAYER_HASH; const _PLAYER_HASH& rPlayers = m_pSSQField->GetEntryField()->GetRefPlayerList(); FOREACH_CONTAINER(const _PLAYER_HASH::value_type& rPlayer, rPlayers, _PLAYER_HASH) { Player* const pPlayer = rPlayer.second; if (obj_util::IsValid(pPlayer, __FUNCTION__, __LINE__) == false) { continue; } pPlayer->SendPacket(&msgCMD, sizeof(msgCMD)); } m_ClearStep = (eSTEP)(m_ClearStep+1); }