/////////////////////////////////////////////////////////////////////////////////// // File : "CreatureManager.cpp" // // Related Header File : "CreatureManager.h" // // Original Author : ÀåÁø¿µ // // Creation Date : 2002-09-06 // // Specification Document : None // // Purpose : CreatureÀÇ ¸®½ºÆ®¸¦ °ü¸®Çϴ Ŭ·¡½º /////////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "CreatureManager.h" #include "Creature.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction CCreatureManager::CCreatureManager() : m_CharacterPool(sizeof(CCharacter)), m_dwLastUpdateTime(0), m_bAutoBalance(true), m_bRest(false) { m_RespawnPoint[POINT_HUMAN1] = Position(1133, 57, 1429); m_RespawnPoint[POINT_HUMAN2] = Position(1217, 48, 1827); m_RespawnPoint[POINT_HUMAN3] = Position(1526, 33, 1685); m_RespawnPoint[POINT_AKHAN1] = Position(1310, 28, 1168); m_RespawnPoint[POINT_AKHAN2] = Position(1619, 49, 998); m_RespawnPoint[POINT_AKHAN3] = Position(1724, 53, 1444); std::fill_n(m_wCharacterNum, int(CClass::MAX_RACE), 0); } CCreatureManager::~CCreatureManager() { DestroyAll(); } int isize; int icur; struct FnDeleteSecond { template bool operator() (PairType& pair) { if(NULL != pair.second) { delete pair.second; } return true; } }; struct FnLeaveParty { template bool operator() (PairType& pair) { if(NULL != pair.second) { CParty* lpParty = (pair.second)->GetParty(); if (lpParty) { lpParty->Leave((pair.second)->GetCID(), 0, (pair.second)->GetMapIndex()); } ++icur; } return true; } }; CCreatureManager& CCreatureManager::GetInstance() { static CCreatureManager creatureManager; return creatureManager; } void CCreatureManager::DestoryCharacterList() { CharacterMap::iterator pos = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); for(; pos != end; ++pos) { DeleteCharacter(pos->second); } m_CharacterMap.clear(); m_CharacterNameMap.clear(); m_LogoutWaitList.clear(); } void CCreatureManager::DestoryMonsterList() { isize = m_MonsterMap.size(); icur = 0; std::for_each(m_MonsterMap.begin(), m_MonsterMap.end(), FnLeaveParty()); std::for_each(m_MonsterMap.begin(), m_MonsterMap.end(), FnDeleteSecond()); m_MonsterMap.clear(); m_AdminMonsterUIDMap.clear(); } void CCreatureManager::DestorySiegeObjectList() { m_SiegeObjectMap.clear(); } void CCreatureManager::DestoryNPCList() { std::for_each(m_NPCMap.begin(), m_NPCMap.end(), FnDeleteSecond()); m_NPCMap.clear(); } void CCreatureManager::DestroyAll() { DestoryCharacterList(); DestoryMonsterList(); DestorySiegeObjectList(); DestoryNPCList(); } bool CCreatureManager::AddCreature(CCreature* lpCreature) { unsigned long dwCID = lpCreature->GetCID(); bool bResult = false; switch (Creature::GetCreatureType(dwCID)) { case Creature::CT_PC: { CCharacter* lpCharacter = reinterpret_cast(lpCreature); bResult = m_CharacterMap.insert(std::make_pair(dwCID, lpCharacter)).second; if (true == bResult) { unsigned long nHashedKey = Math::HashFunc::sdbmHash( reinterpret_cast(lpCharacter->GetCharacterName())); m_CharacterNameMap.insert(std::make_pair(nHashedKey, lpCharacter)); CClass::RaceType eRace = lpCharacter->GetRace(); if(eRace < CClass::MAX_RACE) { ++m_wCharacterNum[eRace]; } } // CharSphereTree ¿¡ ³ëµå Ãß°¡ if (NULL != lpCharacter) { CCharSphereTree::GetInstance().AddCharacter(dwCID, lpCharacter, lpCharacter->GetCurrentPos() ); } } break; case Creature::CT_MONSTER: case Creature::CT_SUMMON: case Creature::CT_STRUCT: { bResult = m_MonsterMap.insert(std::make_pair(dwCID, reinterpret_cast(lpCreature))).second; unsigned short wKindID = static_cast( (dwCID & Creature::MONSTER_KIND_BIT) ); if ( bResult && m_AdminMonsterUIDMap.end() == m_AdminMonsterUIDMap.find(wKindID) ) { m_AdminMonsterUIDMap.insert(std::make_pair(wKindID, INIT_UID)).second; } } break; case Creature::CT_NPC: { bResult = m_NPCMap.insert(std::make_pair(dwCID, reinterpret_cast(lpCreature))).second; } break; case Creature::CT_SIEGE_OBJECT: { bResult = m_SiegeObjectMap.insert(std::make_pair(dwCID, reinterpret_cast(lpCreature))).second; } break; } return bResult; } bool CCreatureManager::DeleteCreature(unsigned long dwCID) { switch (Creature::GetCreatureType(dwCID)) { case Creature::CT_PC: { CharacterMap::iterator pos = m_CharacterMap.find(dwCID); if (pos == m_CharacterMap.end()) { ERRLOG1(g_Log, "CID:0x%08x ij¸¯Å͸¦ Áö¿ï ¼ö ¾ø½À´Ï´Ù. ¸Ê¿¡ ¾ø½À´Ï´Ù.", dwCID); return false; } else { CCharacter* lpDeleteCharacter = pos->second; const char* szCharacterName = lpDeleteCharacter->GetCharacterName(); unsigned long nHashedKey = Math::HashFunc::sdbmHash( reinterpret_cast(szCharacterName)); std::pair findpair = m_CharacterNameMap.equal_range(nHashedKey); for (;findpair.first != findpair.second;) { if(0 == strncmp(findpair.first->second->GetCharacterName(), szCharacterName, CHAR_INFOST::MAX_NAME_LEN)) { m_CharacterNameMap.erase(findpair.first); break; } else { ++findpair.first; } } CClass::RaceType eRace = lpDeleteCharacter->GetRace(); if(eRace < CClass::MAX_RACE) { --m_wCharacterNum[eRace]; } DeleteCharacter(lpDeleteCharacter); m_CharacterMap.erase(pos); } } break; case Creature::CT_MONSTER: case Creature::CT_SUMMON: case Creature::CT_STRUCT: { MonsterMap::iterator pos = m_MonsterMap.find(dwCID); if (pos == m_MonsterMap.end()) { return false; } delete pos->second; m_MonsterMap.erase(pos); } break; case Creature::CT_NPC: { NPCMap::iterator pos = m_NPCMap.find(dwCID); if (pos == m_NPCMap.end()) { return false; } delete pos->second; m_NPCMap.erase(dwCID); } break; case Creature::CT_SIEGE_OBJECT: { SiegeObjectMap::iterator pos = m_SiegeObjectMap.find(dwCID); if (pos == m_SiegeObjectMap.end()) { return false; } // ¸Þ¸ð¸® ÇØÁ¦´Â ÇÏÁö ¾Ê´Â´Ù. // °ø¼º ¿ÀºêÁ§Æ® °ü¸®´Â CSiegeObjectMgr ¿¡¼­ ÇÑ´Ù!! CSiegeObject* lpSiegeObject = pos->second; if (lpSiegeObject && lpSiegeObject->GetCellPos().m_lpCell) { // ¼¿¿¡¼­ »èÁ¦ lpSiegeObject->GetCellPos().m_lpCell->DeleteCreature(lpSiegeObject->GetCID()); } m_SiegeObjectMap.erase(pos); } break; } return true; } CCreature* CCreatureManager::GetCreature(unsigned long dwCID) { return (Creature::CT_NPC == Creature::GetCreatureType(dwCID)) ? reinterpret_cast(GetNPC(dwCID)) : reinterpret_cast(GetAggresiveCreature(dwCID)); } CAggresiveCreature* CCreatureManager::GetAggresiveCreature(unsigned long dwCID) { switch (Creature::GetCreatureType(dwCID)) { case Creature::CT_PC: return reinterpret_cast(GetCharacter(dwCID)); case Creature::CT_SIEGE_OBJECT: return reinterpret_cast(GetSiegeObject(dwCID)); case Creature::CT_MONSTER: case Creature::CT_SUMMON: case Creature::CT_STRUCT: return reinterpret_cast(GetMonster(dwCID)); } return NULL; } CCharacter* CCreatureManager::GetCharacter(unsigned long dwCID) { CharacterMap::iterator pos = m_CharacterMap.find(dwCID); return (pos != m_CharacterMap.end()) ? pos->second : NULL; } CCharacter* CCreatureManager::GetCharacter(const char* szCharacterName) { unsigned long nHashedKey = Math::HashFunc::sdbmHash( reinterpret_cast(szCharacterName)); std::pair findpair = m_CharacterNameMap.equal_range(nHashedKey); CCharacter* lpCharacter = 0; for(;findpair.first != findpair.second;) { lpCharacter = findpair.first->second; if(0 == strncmp(lpCharacter->GetCharacterName(), szCharacterName, CHAR_INFOST::MAX_NAME_LEN)) { return lpCharacter; } else { ++findpair.first; } } return NULL; } CMonster* CCreatureManager::GetMonster(unsigned long dwCID) { MonsterMap::iterator pos = m_MonsterMap.find(dwCID); return (pos != m_MonsterMap.end()) ? pos->second : NULL; } CSiegeObject* CCreatureManager::GetSiegeObject(unsigned long dwCID) { SiegeObjectMap::iterator pos = m_SiegeObjectMap.find(dwCID); return (pos != m_SiegeObjectMap.end()) ? pos->second : NULL; } CNPC* CCreatureManager::GetNPC(unsigned long dwCID) { NPCMap::iterator pos = m_NPCMap.find(dwCID); return (pos != m_NPCMap.end()) ? pos->second : NULL; } void CCreatureManager::EnqueueLogout(CCharacter* lpCharacter) { m_LogoutWaitList.push_back(lpCharacter); } bool CCreatureManager::CancelLogout(CCharacter* lpCharacter) { CharacterList::iterator end = m_LogoutWaitList.end(); CharacterList::iterator pos = std::find(m_LogoutWaitList.begin(), end, lpCharacter); if(pos != end) { (*pos)->ResetLogoutCount(); m_LogoutWaitList.erase(pos); return true; } return false; } bool CCreatureManager::ProcessCharacterLogout(void) { if(!m_LogoutWaitList.empty()) { CharacterList::iterator LogoutItr = std::partition(m_LogoutWaitList.begin(), m_LogoutWaitList.end(), std::mem_fun(&CCharacter::StillAlive)); std::for_each(LogoutItr, m_LogoutWaitList.end(), std::bind2nd(std::mem_fun1(&CCharacter::Logout), DBUpdateData::LOGOUT)); m_LogoutWaitList.erase(LogoutItr, m_LogoutWaitList.end()); return true; } return false; } void CCreatureManager::ProcessSummonMonsterDead(void) { MonsterMap::iterator pos = m_MonsterMap.begin(); MonsterMap::iterator end = m_MonsterMap.end(); for (; pos != end; ) { CMonster* lpMonster = pos->second; if (true == lpMonster->IsDeadSummonMonster()) { pos = m_MonsterMap.erase(pos); delete lpMonster; } else { ++pos; } } } void CCreatureManager::SetNationToCastleNPC(unsigned long dwCastleID, unsigned char cNation) { if (m_NPCMap.empty()) { return; } Castle::CCastle* lpCastle = Castle::CCastleMgr::GetInstance().GetCastle(dwCastleID); if (NULL == lpCastle) { return; } NPCMap::iterator pos = m_NPCMap.begin(); NPCMap::iterator end = m_NPCMap.end(); while ( pos != end ) { CNPC* lpNPC = pos->second; if (lpNPC && lpNPC->GetCastleNameID() == lpCastle->GetNameID() && lpNPC->IsBelongToCastle()) { lpNPC->SetNation(cNation); } ++pos; } } CCharacter* CCreatureManager::CreateCharacter(unsigned long dwCID, unsigned long dwSessionID) { void* lpMemory = m_CharacterPool.malloc(); return (NULL != lpMemory) ? new (lpMemory) CCharacter(dwCID, dwSessionID) : NULL; } void CCreatureManager::DeleteCharacter(CCharacter* lpCharacter) { // CharSphereTree ¿¡¼­ ³ëµå Á¦°Å CCharSphereTree::GetInstance().DeleteCharacter(lpCharacter->GetCID()); lpCharacter->~CCharacter(); m_CharacterPool.free(lpCharacter); } bool CCreatureManager::IsSummonee(unsigned long dwCID) { return Creature::IsSummonMonster(dwCID); } Item::CShopContainer* CCreatureManager::GetShopContainer(unsigned long dwCID) { if (Creature::CT_PC == Creature::GetCreatureType(dwCID)) { CCharacter* lpOwner = GetCharacter(dwCID); if (NULL != lpOwner) { return &(lpOwner->GetStall()); } } else if (Creature::CT_SIEGE_OBJECT == Creature::GetCreatureType(dwCID)) { CSiegeObject* lpSiegeObject = GetSiegeObject(dwCID); if (Siege::CAMP_SHOP == lpSiegeObject->GetObjectType() && Siege::CHANGING != lpSiegeObject->GetState()) { CCampShop* lpCampShop = reinterpret_cast(lpSiegeObject); if (NULL != lpCampShop) { return &(lpCampShop->GetContainer()); } } } return NULL; } void CCreatureManager::SendAllCharacter(const char* szBuffer, unsigned long dwLength, unsigned char cCMD_In, bool bSendAllMap) { CharacterMap::iterator pos = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = 0; CGameClientDispatch* lpDispatch = 0; for (; pos != end; ++pos) { CCharacter* lpCharacter = pos->second; if (0 != lpCharacter && (bSendAllMap || 0 == lpCharacter->GetMapIndex()) && 0 != (lpDispatch = lpCharacter->GetDispatcher())) { lpDispatch->GetSendStream().PutBuffer(szBuffer, dwLength, cCMD_In); } } } void CCreatureManager::SendFindPartyMsg(unsigned long dwSenderCID, const char* szCompressedPacket, unsigned long dwPacketSize) { CharacterMap::iterator pos = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpSender = GetCharacter(dwSenderCID); if (NULL != lpSender) { for (; pos != end; ++pos) { CCharacter* lpCharacter = pos->second; if (NULL != lpCharacter) { if (0 != lpCharacter->GetMapIndex()) continue; if (lpCharacter == lpSender || EnemyCheck::EC_ENEMY == lpSender->IsEnemy(lpCharacter)) continue; CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { lpDispatch->GetSendStream().PutBuffer(szCompressedPacket, dwPacketSize, CmdCharChat); } } } } } void CCreatureManager::CalculateEliteBonus(unsigned short *usPeopleNum) { // ¿ÀÅä ¹ë·±½º°¡ ²¨Áö¸é ¿¤¸®Æ® º¸³Ê½º°¡ ¹Ù²îÁö ¾Ê´Â´Ù. if (false == m_bAutoBalance) { return; } EliteBonus::EliteBonusData NewEliteBonus; unsigned short wMin = 0; unsigned short wMax = 0; if (usPeopleNum[CClass::HUMAN] < usPeopleNum[CClass::AKHAN]) { wMin = usPeopleNum[CClass::HUMAN] - 1; wMax = usPeopleNum[CClass::AKHAN] - 1; NewEliteBonus.m_cNation = CClass::HUMAN; } else { wMin = usPeopleNum[CClass::AKHAN] - 1; wMax = usPeopleNum[CClass::HUMAN] - 1; NewEliteBonus.m_cNation = CClass::AKHAN; } if (0 == wMin) { NewEliteBonus.m_cLevel = EliteBonus::MAX_BONUS_LEVEL; } else { float fRate = static_cast(wMax) / static_cast(wMin); if (1.5f <= fRate && fRate < 2.0f) { NewEliteBonus.m_cLevel = 1; } else if (2.0f <= fRate && fRate < 2.5f) { NewEliteBonus.m_cLevel = 2; } else if (2.5f <= fRate && fRate < 3.0f) { NewEliteBonus.m_cLevel = 3; } else if (3.0f <= fRate && fRate < 3.5f) { NewEliteBonus.m_cLevel = 4; } else if (3.5f <= fRate) { NewEliteBonus.m_cLevel = 5; } } if (0 == NewEliteBonus.m_cLevel) { NewEliteBonus.m_cNation = CClass::MAX_RACE; } SetEliteBonus(NewEliteBonus); } class CSendEliteBonus { public: bool operator () (CCharacter* lpCharacter) { if (NULL != lpCharacter) { CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { GameClientSendPacket::SendCharEliteBonus( lpDispatch->GetSendStream(), lpCharacter->GetEliteBonus()); } } return false; } }; void CCreatureManager::SetEliteBonus(EliteBonus::EliteBonusData eliteBonus) { if (m_EliteBonus.m_cNation != eliteBonus.m_cNation || m_EliteBonus.m_cLevel != eliteBonus.m_cLevel) { m_EliteBonus.m_cNation = eliteBonus.m_cNation; m_EliteBonus.m_cLevel = eliteBonus.m_cLevel; ProcessAllCharacter(CSendEliteBonus()); } } float CCreatureManager::GetFameBonus(CClass::RaceType eRace, FightResult eResult) { if (eRace == m_EliteBonus.m_cNation) { switch (eResult) { case WIN: { switch (m_EliteBonus.m_cLevel) { case 1: return 1.2f; case 2: return 1.4f; case 3: return 1.6f; case 4: return 1.8f; case 5: return 2.0f; } break; } case LOSE: { switch (m_EliteBonus.m_cLevel) { case 1: return 0.9f; case 2: return 0.8f; case 3: return 0.7f; case 4: return 0.6f; case 5: return 0.5f; } break; } } } return 1.0f; } void CCreatureManager::PushRespawnQueue(CCharacter* lpCharacter, unsigned char cPointNumber) { unsigned short wError = PktBase::NO_SERVER_ERR; long lTime = 0; if (m_wCharacterNum[CClass::HUMAN] + m_wCharacterNum[CClass::AKHAN] > CServerSetup::GetInstance().GetBattleLimit()) { if (m_wCharacterNum[CClass::HUMAN] > m_wCharacterNum[CClass::AKHAN] * 1.5 && CClass::HUMAN == lpCharacter->GetRace()) { wError = PktBGRsAck::FAIL_PERSONNEL_OVER; } if (m_wCharacterNum[CClass::AKHAN] > m_wCharacterNum[CClass::HUMAN] * 1.5 && CClass::AKHAN == lpCharacter->GetRace()) { wError = PktBGRsAck::FAIL_PERSONNEL_OVER; } } if (PktBase::NO_SERVER_ERR == wError) { int nIndex = 0; for (; nIndex < MAX_POINT_NUM; ++nIndex) { if (false == m_lstRespawn[nIndex].empty()) { break; } } if (nIndex == MAX_POINT_NUM) { m_dwLastUpdateTime = CPulse::GetInstance().GetLastTick(); } PopRespawnQueue(lpCharacter); if (0 != m_wCharacterNum[CClass::HUMAN] && 0 != m_wCharacterNum[CClass::AKHAN]) { switch (lpCharacter->GetRace()) { case CClass::HUMAN: lTime = m_wCharacterNum[CClass::HUMAN] / m_wCharacterNum[CClass::AKHAN] * 5000; break; case CClass::AKHAN: lTime = m_wCharacterNum[CClass::AKHAN] / m_wCharacterNum[CClass::HUMAN] * 5000; break; } } BattleGroundRespawnInfo tempInfo(lpCharacter, m_RespawnPoint[cPointNumber], lTime); m_lstRespawn[cPointNumber].push_back(tempInfo); } CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { GameClientSendPacket::SendCharBattleGroundRespawn(lpDispatch->GetSendStream(), lpCharacter->GetCID(), static_cast(m_lstRespawn[cPointNumber].size()), static_cast(m_lstRespawn[cPointNumber].size()), static_cast(lTime / 1000), m_wCharacterNum[CClass::HUMAN], m_wCharacterNum[CClass::AKHAN], wError); } } void CCreatureManager::PopRespawnQueue(CCharacter* lpCharacter) { for (int nIndex = 0; nIndex < MAX_POINT_NUM; ++nIndex) { if (true == m_lstRespawn[nIndex].empty()) { continue; } for (RespawnQueue::iterator it = m_lstRespawn[nIndex].begin(); it != m_lstRespawn[nIndex].end(); ) { BattleGroundRespawnInfo tempInfo = *it; if (tempInfo.m_lpCharacter == lpCharacter) { it = m_lstRespawn[nIndex].erase(it); } else { ++it; } } } } void CCreatureManager::ProcessRespawnQueue(void) { for (int nIndex = 0; nIndex < MAX_POINT_NUM; ++nIndex) { if (true == m_lstRespawn[nIndex].empty()) { continue; } unsigned short wTurn = 0; for (RespawnQueue::iterator it = m_lstRespawn[nIndex].begin(); it != m_lstRespawn[nIndex].end();) { BattleGroundRespawnInfo tempInfo = *it; tempInfo.m_lLeftTime -= (CPulse::GetInstance().GetLastTick() - m_dwLastUpdateTime); if (0 >= tempInfo.m_lLeftTime) { tempInfo.m_lpCharacter->Respawn(CCharRespawnMgr::RST_BATTLE, tempInfo.m_RespawnPos); if (0 != tempInfo.m_lpCharacter->GetPID()) { // ÆÄƼ¿ø ¸®½ºÆùÀ» ¾Ë¸°´Ù. GameClientSendPacket::SendCharDeadToParty(tempInfo.m_lpCharacter, 0, PktDeadInfo::RESPAWN); } it = m_lstRespawn[nIndex].erase(it); } else { ++wTurn; CGameClientDispatch* lpDispatch = tempInfo.m_lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { GameClientSendPacket::SendCharBattleGroundRespawn(lpDispatch->GetSendStream(), tempInfo.m_lpCharacter->GetCID(), wTurn, static_cast(m_lstRespawn[nIndex].size()), static_cast(tempInfo.m_lLeftTime / 1000), m_wCharacterNum[CClass::HUMAN], m_wCharacterNum[CClass::AKHAN], 0); } ++it; } } } } bool CCreatureManager::SendRespawnQueue(unsigned long dwCID) { CCharacter* lpCharacter = GetCharacter(dwCID); if (NULL == lpCharacter) { return false; } PopRespawnQueue(lpCharacter); CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL == lpDispatch) { return false; } CSendStream& SendStream = lpDispatch->GetSendStream(); char* lpBuffer = SendStream.GetBuffer(sizeof(PktRsWaitQueueAck)); if (NULL == lpBuffer) { return false; } PktRsWaitQueueAck* lpPktRsWQAck = reinterpret_cast(lpBuffer); lpPktRsWQAck->m_dwCharID = dwCID; switch (lpCharacter->GetRace()) { case CClass::HUMAN: lpPktRsWQAck->m_wWaitNum[0] = static_cast(m_lstRespawn[POINT_HUMAN1].size()); lpPktRsWQAck->m_wWaitNum[1] = static_cast(m_lstRespawn[POINT_HUMAN2].size()); lpPktRsWQAck->m_wWaitNum[2] = static_cast(m_lstRespawn[POINT_HUMAN3].size()); break; case CClass::AKHAN: lpPktRsWQAck->m_wWaitNum[0] = static_cast(m_lstRespawn[POINT_AKHAN1].size()); lpPktRsWQAck->m_wWaitNum[1] = static_cast(m_lstRespawn[POINT_AKHAN2].size()); lpPktRsWQAck->m_wWaitNum[2] = static_cast(m_lstRespawn[POINT_AKHAN3].size()); break; default: return false; } return SendStream.WrapCrypt(sizeof(PktRsWaitQueueAck), CmdCharRespawnWaitQueue, 0, 0); } unsigned char CCreatureManager::GetBonusTurn(const unsigned short wMapIndex) { const static unsigned char INIT_DEFAULT_VALUE = 0x80; unsigned char cResult = INIT_DEFAULT_VALUE; MonsterMap::iterator pos = m_MonsterMap.begin(); MonsterMap::iterator end = m_MonsterMap.end(); for (; pos != end; ++pos) { CMonster* lpMonster = pos->second; if (NULL == lpMonster) { continue; } if (lpMonster->GetMapIndex() != wMapIndex) { continue; } // BG_TODO : ¹èƲ ±×¶ó¿îµå ¼­¹ö±ºÀÇ ¼®»ó¿¡¼­ ¸¶Àϸ®Áö¸¦ ÁÙ °æ¿ì ¼öÁ¤ÀÌ ÇÊ¿äÇÏ´Ù!! CStatue* lpStatue = lpMonster->DowncastToStatue(); if (NULL != lpStatue && lpStatue->GetStatus().m_nNowHP > 0) { // 1·¹º§ if (MonsterInfo::STATUE_HUMAN_COMPLETE1 != lpStatue->GetKID() && MonsterInfo::STATUE_AKHAN_COMPLETE1 != lpStatue->GetKID()) { return CClass::MAX_RACE; } // 2·¹º§ else if (MonsterInfo::STATUE_HUMAN_COMPLETE2 != lpStatue->GetKID() && MonsterInfo::STATUE_AKHAN_COMPLETE2 != lpStatue->GetKID()) { return CClass::MAX_RACE; } if (INIT_DEFAULT_VALUE == cResult) { cResult = lpStatue->GetNation(); } else { // ¸ðµç ¼®»óÀÌ ÇÑ Á¾Á·ÀÇ °ÍÀÏ ¶§¸¸ º¸³Ê½º¸¦ ¹ÞÀ» ¼ö ÀÖ´Ù. if (cResult != lpStatue->GetNation()) { return CClass::MAX_RACE; } } } } if (Creature::KARTERANT == cResult) { return CClass::HUMAN; } if (Creature::MERKADIA == cResult) { return CClass::AKHAN; } return CClass::MAX_RACE; } void CCreatureManager::ProcessBattleGround() { // Zone ÀÌ Stron WarÀϰæ¿ì¸¸ if (SERVER_ID::STONE_WAR1 <= CServerSetup::GetInstance().GetServerZone() && CServerSetup::GetInstance().GetServerZone() <= SERVER_ID::STONE_WAR3) { if(CGameTimeMgr::GetInstance().IsRealmWarTime()) { // edith 2010.01.16 ¸ðµç ¼®»óÁ¸¿¡¼­ 1ºÐ¿¡ Çѹø¾¿ ¸Þ´ÞÀ» ºÎ¿©ÇÑ´Ù. ProcessAllCharacter(CBlessMileageInfo(0)); // 1ºÐ¿¡ 1¹ø¾¿ °øÇå ¸Þ´ÞÀ» ³ª´²ÁØ´Ù. MonsterMap::iterator mon_pos = m_MonsterMap.begin(); MonsterMap::iterator mon_end = m_MonsterMap.end(); for (; mon_pos != mon_end; ++mon_pos) { // ¼®»ó¸¸ °øÇå ¸Þ´ÞÀ» ³ª´²ÁØ´Ù. CStatue* lpStatue = (mon_pos->second)->DowncastToStatue(); if (NULL != lpStatue && lpStatue->GetStatus().m_nNowHP > 0) { lpStatue->GiveMileage(1); } } } // Á×Àº »óÅ·Π1ºÐ ÀÌ»ó ¸®½ºÆù ÇÏÁö ¾Ê°í ÀÖ´Â ½Ãü ó¸® CharacterMap::iterator char_pos = m_CharacterMap.begin(); CharacterMap::iterator char_end = m_CharacterMap.end(); CPulse& pulse = CPulse::GetInstance(); unsigned long dwLastTick = pulse.GetLastTick(); unsigned long dwRespawnTick = CCharacter::BATTLE_GROUND_PULSE * pulse.GetTicksPerPulse(); for (; char_pos != char_end; ++char_pos) { CCharacter* lpCharacter = char_pos->second; if (0 != lpCharacter && 0 == lpCharacter->GetStatus().m_nNowHP) { if (lpCharacter->GetLastTime() + dwRespawnTick < dwLastTick) { lpCharacter->AutoRespawn(); } } } } /* // Zone ÀÌ 3¹ø BattleGround ÀÏ °æ¿ìÀÇ Ã³¸®¸¸ ´ã´ç.. if (SERVER_ID::ZONE3 == CServerSetup::GetInstance().GetServerZone()) { // 1ºÐ¿¡ 1¹ø¾¿ °øÇå ¸Þ´ÞÀ» ³ª´²ÁØ´Ù. MonsterMap::iterator mon_pos = m_MonsterMap.begin(); MonsterMap::iterator mon_end = m_MonsterMap.end(); for (; mon_pos != mon_end; ++mon_pos) { // ¼®»ó¸¸ °øÇå ¸Þ´ÞÀ» ³ª´²ÁØ´Ù. CStatue* lpStatue = (mon_pos->second)->DowncastToStatue(); if (NULL != lpStatue && lpStatue->GetStatus().m_nNowHP > 0) { lpStatue->GiveMileage(0); } } // Á×Àº »óÅ·Π1ºÐ ÀÌ»ó ¸®½ºÆù ÇÏÁö ¾Ê°í ÀÖ´Â ½Ãü ó¸® CharacterMap::iterator char_pos = m_CharacterMap.begin(); CharacterMap::iterator char_end = m_CharacterMap.end(); CPulse& pulse = CPulse::GetInstance(); unsigned long dwLastTick = pulse.GetLastTick(); unsigned long dwRespawnTick = CCharacter::BATTLE_GROUND_PULSE * pulse.GetTicksPerPulse(); for (; char_pos != char_end; ++char_pos) { CCharacter* lpCharacter = char_pos->second; if (0 != lpCharacter && 0 == lpCharacter->GetStatus().m_nNowHP) { if (lpCharacter->GetLastTime() + dwRespawnTick < dwLastTick) { lpCharacter->AutoRespawn(); } } } } */ /* // ¼­¹ö°¡ ¹èƲ ±×¶ó¿îµå ÀÏ °æ¿ì¿¡¸¸ if (SERVER_ID::ZONE3 == CServerSetup::GetInstance().GetServerZone()) { SYSTEMTIME systemTime; GetSystemTime(&systemTime); if ((systemTime.wMinute >= CCreatureManager::STATUE_REST_TIME_1ST_START && systemTime.wMinute <= CCreatureManager::STATUE_REST_TIME_1ST_END) || (systemTime.wMinute >= CCreatureManager::STATUE_REST_TIME_2ND_START && systemTime.wMinute <= CCreatureManager::STATUE_REST_TIME_2ND_END)) { if (true == m_bRest) return; else { // ¹èƲ ±×¶ó¿îµå¿¡ ÀÖ´Â ¸ðµç À¯ÀúµéÀ» À̵¿ ½ÃŲ´Ù. for (CharacterMap::iterator it = m_CharacterMap.begin(); it != m_CharacterMap.end(); ++it) { CCharacter* lpCharacter = it->second; if (NULL != lpCharacter) { lpCharacter->AutoRespawn(); } } // ¸ðµç ¼®»óÀ» ´Ù Á×À̰í, ¾Æ¹«°Íµµ ¼ÒȯÇÏÁö ¾Ê´Â´Ù. for (MonsterMap::iterator it = m_MonsterMap.begin(); it != m_MonsterMap.end(); ++it) { CStatue* lpStatue = (it->second)->DowncastToStatue(); if (NULL != lpStatue) { lpStatue->Rest(); } } m_bRest = true; } } else if (systemTime.wMinute >= CCreatureManager::STATUE_RESPAWN_TIME_1ST || systemTime.wMinute >= CCreatureManager::STATUE_RESPAWN_TIME_2ND) { // Á×Àº »óÅ·Π1ºÐ ÀÌ»ó ¸®½ºÆù ÇÏÁö ¾Ê°í ÀÖ´Â ½Ãü ó¸® for (CharacterMap::iterator it = m_CharacterMap.begin(); it != m_CharacterMap.end(); ++it) { CCharacter* lpCharacter = it->second; if (NULL != lpCharacter && 0 == lpCharacter->GetStatus().m_nNowHP) { // TODO : ¹èƲ ±×¶ó¿îµå ¼öÁ¤ // Tick °ú Pluse °¡ ½â¿©ÀÖ´Ù. CPulse ¸¦ Base Library ÀÇ ¾÷µ¥ÀÌÆ®·Î Àâ°í ÀÖ´Â »óȲÀÌ¶ó¼­ // DEFAULT_TICKS_PER_PULSE ¸¦ »ç¿ëÇÏ¿´´Ù. if (CPulse::GetInstance().GetLastTick() > lpCharacter->GetLastTime() + CCharacter::BATTLE_GROUND_PULSE * CPulse::DEFAULT_TICKS_PER_PULSE) { lpCharacter->AutoRespawn(); } } } // ¼®»ó ÃʱâÈ­ »óÅ·Πº¯È­ ó¸® if (false == m_bRest) return; else { // TODO : ¼ø¼­°¡ Áß¿äÇÏ´Ù. Arrangement Script ÆÄÀÏ¿¡ µé¾î°£ ¼ø¼­´ë·Î ÇØ¾ßÇÑ´Ù. // ÈÞ¸Õ, Á߸³, ¾ÆÄ­ ¼®»óÀ» ¼ø¼­´ë·Î Çϳª¾¿ ¼ÒȯÇÑ´Ù. enum { HUMAN_STATUE = 0, NUETRALITY_STATUE = 1, AKHAN_STATUE = 2, NONE = 100 }; DWORD dwKind, dwOldKind = NONE; for (MonsterMap::iterator it = m_MonsterMap.begin(); it != m_MonsterMap.end(); ++it) { CStatue* lpStatue = (it->second)->DowncastToStatue(); if (NULL != lpStatue) { // Á¾·ù¸¦ ¾ò¾î¿Â´Ù. (HUMAN = 0, NUETRALITY = 1, AKHAN = 2) dwKind = (lpStatue->GetCID() & ~(Creature::MONSTER_BIT | Creature::MONSTER_KIND_BIT)) >> 16; if (dwOldKind != dwKind) { switch (dwKind) { case HUMAN_STATUE: lpStatue = lpStatue->GetLinkStatue(MonsterInfo::STATUE_HUMAN_COMPLETE); lpStatue->InitMonster(lpStatue->GetOriginalPos(), CCell::CellMoveType::LOGINOUT); break; case NUETRALITY_STATUE: lpStatue = lpStatue->GetLinkStatue(MonsterInfo::STATUE_NEUTRALITY); lpStatue->InitMonster(lpStatue->GetOriginalPos(), CCell::CellMoveType::LOGINOUT); break; case AKHAN_STATUE: lpStatue = lpStatue->GetLinkStatue(MonsterInfo::STATUE_AKHAN_COMPLETE); lpStatue->InitMonster(lpStatue->GetOriginalPos(), CCell::CellMoveType::LOGINOUT); break; } dwOldKind = dwKind; } } } m_bRest = false; } } } */ } // ¸ó½ºÅ͸¦ »ý¼ºÇÒ¶§ CID°¡ °ãÄ¡Áö ¾Ê°Ô Çϱâ À§Çؼ­ È£ÃâÇÏ´Â ÇÔ¼ö unsigned short CCreatureManager::GetAvailableMonsterUID(unsigned short wKindID) { if (m_AdminMonsterUIDMap.end() == m_AdminMonsterUIDMap.find(wKindID)) { m_AdminMonsterUIDMap.insert(std::make_pair(wKindID, INIT_UID)).second; } unsigned long nUID = ((m_AdminMonsterUIDMap[wKindID] << 16) | wKindID); if (NULL != GetMonster(nUID)) { if (m_AdminMonsterUIDMap[wKindID] == INIT_UID) { // ¿©À¯ °ø°£ÀÌ ¾ø´Ù¸é... return NO_BLANK_UID; } m_AdminMonsterUIDMap[wKindID] = INIT_UID - 1; return INIT_UID; } return m_AdminMonsterUIDMap[wKindID]--; } bool CCreatureManager::ChangeCharacterName(unsigned long dwCID, const char* szChangedName) { CCharacter* lpCharacter = GetCharacter(dwCID); if(0 != lpCharacter) { const char* szCurrentName = lpCharacter->GetCharacterName(); unsigned long dwOriginalHashedKey = Math::HashFunc::sdbmHash( reinterpret_cast(szCurrentName)); unsigned long dwChangeHashKey = Math::HashFunc::sdbmHash( reinterpret_cast(szChangedName)); std::pair findpair = m_CharacterNameMap.equal_range(dwOriginalHashedKey); for (;findpair.first != findpair.second;) { if(0 == strncmp(findpair.first->second->GetCharacterName(), szCurrentName, CHAR_INFOST::MAX_NAME_LEN)) { m_CharacterNameMap.erase(findpair.first); break; } else { ++findpair.first; } } lpCharacter->SetCharacterName(szChangedName); m_CharacterNameMap.insert(std::make_pair(dwChangeHashKey, lpCharacter)); return true; } return false; } // ±æµåÀü°ú ±¹°¡Àü ÀüÀï ½Ã°£½Ã¿¡ Á¸À̵¿ ó¸® ÇÔ¼ö void CCreatureManager::MoveCharacterToGuildWarZone(unsigned char cType, bool bOn) { CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = NULL; unsigned char cFlag = 0; while (itr != end) { lpCharacter = itr->second; if (lpCharacter) { switch (cType) { case GameTime::GUILD: cFlag = lpCharacter->GetGuildWarFlag(); break; case GameTime::REALM: cFlag = lpCharacter->GetRealmWarFlag(); break; default: { ++itr; continue; } } if (bOn && (Creature::WAR_ON == cFlag || Creature::WAR_INSTANCE == cFlag)) { lpCharacter->MoveToGuildWarZone(); } else if (!bOn && Creature::WAR_OFF == cFlag) { lpCharacter->MoveToGuildWarZone(); } } ++itr; } } void CCreatureManager::MoveCharacterToRealmWarZone(unsigned char cType, bool bOn) { CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = NULL; unsigned char cFlag = 0; GET_SINGLE_DISPATCH(lpDBAgentDispatch, CDBAgentDispatch, CDBAgentDispatch::GetDispatchTable()); while (itr != end) { lpCharacter = itr->second; if (lpCharacter) { switch (cType) { case GameTime::GUILD: cFlag = lpCharacter->GetGuildWarFlag(); break; case GameTime::REALM: cFlag = lpCharacter->GetRealmWarFlag(); break; default: { ++itr; continue; } } if (bOn && (Creature::WAR_ON == cFlag || Creature::WAR_INSTANCE == cFlag)) { lpCharacter->MoveToRealmWarZone(); } else if (!bOn && Creature::WAR_OFF == cFlag) { // °­Á¦Âü°¡. if (0 != lpDBAgentDispatch) GameClientSendPacket::SendWarOnOff(lpDBAgentDispatch->GetSendStream(), lpCharacter->GetCID(), GameTime::REALM, Creature::WAR_INSTANCE, 0); // lpCharacter->MoveToRealmWarZone(); } } ++itr; } } void CCreatureManager::ClearGuildWarInstanceFlag() { CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = NULL; while (itr != end) { lpCharacter = itr->second; if (lpCharacter && Creature::WAR_INSTANCE == lpCharacter->GetGuildWarFlag()) { lpCharacter->SetGuildWarFlag(Creature::WAR_OFF); // ÆÐŶ Àü¼Û CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { GameClientSendPacket::SendWarOnOff(lpDispatch->GetSendStream(), lpCharacter->GetCID(), GameTime::GUILD, Creature::WAR_OFF, 0); } } ++itr; } } void CCreatureManager::ClearRealmWarInstanceFlag() { CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = NULL; while (itr != end) { lpCharacter = itr->second; if (lpCharacter && Creature::WAR_INSTANCE == lpCharacter->GetRealmWarFlag()) { lpCharacter->SetRealmWarFlag(Creature::WAR_OFF); // ÆÐŶ Àü¼Û CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { GameClientSendPacket::SendWarOnOff(lpDispatch->GetSendStream(), lpCharacter->GetCID(), GameTime::REALM, Creature::WAR_OFF, 0); } } ++itr; } } void CCreatureManager::SetRealmStatueInfo(unsigned long dwIndex, unsigned short wKID, unsigned long dwLostHP) { MonsterMap::iterator itr = m_MonsterMap.begin(); MonsterMap::iterator end = m_MonsterMap.end(); CMonster* lpMonsetr = NULL; CStatue* lpStatue = NULL; while (itr != end) { lpMonsetr = itr->second; if (NULL == lpMonsetr) { ++itr; continue; } lpStatue = lpMonsetr->DowncastToStatue(); if (NULL == lpStatue) { ++itr; continue; } if (0 == lpStatue->GetStatus().m_nNowHP) { ++itr; continue; } unsigned long dwStatueIndex = (lpStatue->GetCID() & ~Creature::MONSTER_BIT) >> 16; if (dwStatueIndex == dwIndex) { lpStatue->Rest(); lpStatue = lpStatue->GetLinkStatue(wKID); lpStatue->InitMonster(lpStatue->GetOriginalPos()); lpStatue->GetStatus().m_nNowHP = static_cast(lpStatue->GetStatus().m_StatusInfo.m_nMaxHP - dwLostHP); // ¼®»ó ¸®½ºÆù Æ÷ÀÎÆ® Ãß°¡ if (lpStatue->EnableRespawn() && MonsterInfo::IsRaceCompleteStatueKID(lpStatue->GetKID())) { CCharRespawnMgr::GetInstance().AddRealmStatueRespawnPoint(dwStatueIndex, lpStatue->GetNation(), lpStatue->GetCurrentPos()); } return; } ++itr; } } void CCreatureManager::InitRealmStatue() { MonsterMap::iterator itr = m_MonsterMap.begin(); MonsterMap::iterator end = m_MonsterMap.end(); CMonster* lpMonsetr = NULL; CStatue* lpStatue = NULL; SERLOG0(g_Log, "¼®»ó Á¤º¸ ÃʱâÈ­¸¦ ½ÃÀÛÇÕ´Ï´Ù."); while (itr != end) { lpMonsetr = itr->second; if (NULL == lpMonsetr) { ++itr; continue; } lpStatue = lpMonsetr->DowncastToStatue(); if (NULL == lpStatue) { ++itr; continue; } if (0 == lpStatue->GetStatus().m_nNowHP) { ++itr; continue; } unsigned short wKID = lpStatue->GetKID(); if (wKID != MonsterInfo::GetDefaultStatueKID(wKID)) { lpStatue->Rest(); lpStatue = lpStatue->GetLinkStatue(MonsterInfo::GetDefaultStatueKID(wKID)); lpStatue->InitMonster(lpStatue->GetOriginalPos()); // Áß°è¼­¹ö¿¡ Á߸³ KID ·Î º¯°æ Á¤º¸ Àü¼Û lpStatue->SendKIDUpdate(); // ¼®»ó ¸®½ºÆù Æ÷ÀÎÆ® »èÁ¦ unsigned long dwStatueIndex = (lpStatue->GetCID() & ~Creature::MONSTER_BIT) >> 16; CCharRespawnMgr::GetInstance().DeleteRealmStatueRespawnPoint(dwStatueIndex); } lpStatue->GetStatus().m_nNowHP = lpStatue->GetStatus().m_StatusInfo.m_nMaxHP; // Áß°è¼­¹ö¿¡ HP ¸¸¶¥ Á¤º¸ Àü¼Û lpStatue->SendHPUpdate(true); ++itr; } } void CCreatureManager::InitRealmLoadingStatue() { MonsterMap::iterator itr = m_MonsterMap.begin(); MonsterMap::iterator end = m_MonsterMap.end(); CMonster* lpMonsetr = NULL; CStatue* lpStatue = NULL; SERLOG0(g_Log, "¼®»ó Á¤º¸ Á߸³È­¸¦ ½ÃÀÛÇÕ´Ï´Ù."); while (itr != end) { lpMonsetr = itr->second; if (NULL == lpMonsetr) { ++itr; continue; } lpStatue = lpMonsetr->DowncastToStatue(); if (NULL == lpStatue) { ++itr; continue; } if (0 == lpStatue->GetStatus().m_nNowHP) { ++itr; continue; } unsigned short wKID = lpStatue->GetKID(); if (MonsterInfo::IsLoadingStatueKID(wKID)) { lpStatue->Rest(); lpStatue = lpStatue->GetLinkStatue(MonsterInfo::GetDefaultStatueKID(wKID)); lpStatue->InitMonster(lpStatue->GetOriginalPos()); // Áß°è¼­¹ö¿¡ Á߸³ KID ·Î º¯°æ Á¤º¸ Àü¼Û lpStatue->SendKIDUpdate(); } lpStatue->GetStatus().m_nNowHP = lpStatue->GetStatus().m_StatusInfo.m_nMaxHP; // Áß°è¼­¹ö¿¡ HP ¸¸¶¥ Á¤º¸ Àü¼Û lpStatue->SendHPUpdate(true); ++itr; } } int CCreatureManager::GetRealmStatueNum() { int nCount = 0; MonsterMap::const_iterator itr = m_MonsterMap.begin(); MonsterMap::const_iterator end = m_MonsterMap.end(); CMonster* lpMonsetr = NULL; CStatue* lpStatue = NULL; while (itr != end) { lpMonsetr = itr->second; if (NULL == lpMonsetr) { ++itr; continue; } lpStatue = lpMonsetr->DowncastToStatue(); if (NULL == lpStatue) { ++itr; continue; } if (0 == lpStatue->GetStatus().m_nNowHP) { ++itr; continue; } ++nCount; ++itr; } return nCount; } bool CCreatureManager::SendRealmStatueDisplayInfo(CSendStream& SendStream) { int nRealmStatueNum = GetRealmStatueNum(); const int BUFFER_SIZE = sizeof(PktStatueCmd) + sizeof(StatueDisplayInfo) * nRealmStatueNum; char* lpBuffer = SendStream.GetBuffer(BUFFER_SIZE); if (NULL == lpBuffer) { return false; } PktStatueCmd* lpPktStatueCmd = reinterpret_cast(lpBuffer); StatueDisplayInfo* lpDisplayInfo = reinterpret_cast(lpPktStatueCmd + 1); lpPktStatueCmd->m_wSubCmd = PktStatueCmd::CMD_DISPLAY_INFO; lpPktStatueCmd->m_wSize = static_cast(BUFFER_SIZE - sizeof(PktStatueCmd)); lpPktStatueCmd->m_dwValue = nRealmStatueNum; MonsterMap::iterator itr = m_MonsterMap.begin(); MonsterMap::iterator end = m_MonsterMap.end(); CMonster* lpMonsetr = NULL; CStatue* lpStatue = NULL; while (itr != end) { lpMonsetr = itr->second; if (NULL == lpMonsetr) { ++itr; continue; } lpStatue = lpMonsetr->DowncastToStatue(); if (NULL == lpStatue) { ++itr; continue; } if (0 == lpStatue->GetStatus().m_nNowHP) { ++itr; continue; } lpDisplayInfo->m_dwIndex = (lpStatue->GetCID() & ~Creature::MONSTER_BIT) >> 16; lpDisplayInfo->m_dwKID = lpStatue->GetKID(); lpDisplayInfo->m_cNation = lpStatue->GetNation(); lpDisplayInfo->m_bSummoning = MonsterInfo::IsLoadingStatueKID(lpStatue->GetKID()); lpDisplayInfo->m_bAttacked = false; lpDisplayInfo->m_Pos.fPointX = lpStatue->GetCurrentPos().m_fPointX; lpDisplayInfo->m_Pos.fPointY = lpStatue->GetCurrentPos().m_fPointY; lpDisplayInfo->m_Pos.fPointZ = lpStatue->GetCurrentPos().m_fPointZ; ++lpDisplayInfo; ++itr; } return SendStream.WrapCrypt(BUFFER_SIZE, CmdStatueCmd, 0, 0); } bool CCreatureManager::SendRealmStatueDisplayInfo(unsigned long dwIndex, bool bAttacked) { const int BUFFER_SIZE = sizeof(PktStatueCmd) + sizeof(StatueDisplayInfo) * PktStatueCmd::MAX_STATUE_NUM; char szBuffer[BUFFER_SIZE] = {0, }; PktStatueCmd* lpPktStatueCmd = reinterpret_cast(szBuffer); StatueDisplayInfo* lpDisplayInfo = reinterpret_cast(lpPktStatueCmd + 1); MonsterMap::iterator itr = m_MonsterMap.begin(); MonsterMap::iterator end = m_MonsterMap.end(); CMonster* lpMonsetr = NULL; CStatue* lpStatue = NULL; unsigned short wSize = 0; unsigned long dwCount = 0; while (itr != end) { lpMonsetr = itr->second; if (NULL == lpMonsetr) { ++itr; continue; } lpStatue = lpMonsetr->DowncastToStatue(); if (NULL == lpStatue) { ++itr; continue; } if (0 == lpStatue->GetStatus().m_nNowHP) { ++itr; continue; } unsigned long dwStatueIndex = (lpStatue->GetCID() & ~Creature::MONSTER_BIT) >> 16; if (0 == dwIndex || dwIndex == dwStatueIndex) { lpDisplayInfo->m_dwIndex = dwStatueIndex; lpDisplayInfo->m_dwKID = lpStatue->GetKID(); lpDisplayInfo->m_cNation = lpStatue->GetNation(); lpDisplayInfo->m_bSummoning = MonsterInfo::IsLoadingStatueKID(lpStatue->GetKID()); lpDisplayInfo->m_bAttacked = bAttacked; lpDisplayInfo->m_Pos.fPointX = lpStatue->GetCurrentPos().m_fPointX; lpDisplayInfo->m_Pos.fPointY = lpStatue->GetCurrentPos().m_fPointY; lpDisplayInfo->m_Pos.fPointZ = lpStatue->GetCurrentPos().m_fPointZ; wSize += sizeof(StatueDisplayInfo); ++lpDisplayInfo; ++dwCount; } ++itr; } lpPktStatueCmd->m_wSubCmd = PktStatueCmd::CMD_DISPLAY_INFO; lpPktStatueCmd->m_wSize = wSize; lpPktStatueCmd->m_dwValue = dwCount; if (PacketWrap::WrapCrypt(szBuffer, sizeof(PktStatueCmd) + wSize, CmdStatueCmd, 0, 0)) { SendAllCharacter(szBuffer, sizeof(PktStatueCmd) + wSize, CmdStatueCmd); return true; } return false; } void CCreatureManager::CalculateRealmStatueEnchantInfo() { memset(m_RealmEnchantInfo, 0, sizeof(sRealmEnchant) * 2); MonsterMap::iterator itr = m_MonsterMap.begin(); MonsterMap::iterator end = m_MonsterMap.end(); CMonster* lpMonsetr = NULL; CStatue* lpStatue = NULL; while (itr != end) { lpMonsetr = itr->second; if (NULL == lpMonsetr) { ++itr; continue; } lpStatue = lpMonsetr->DowncastToStatue(); if (NULL == lpStatue) { ++itr; continue; } if (0 == lpStatue->GetStatus().m_nNowHP) { ++itr; continue; } if (MonsterInfo::IsRaceCompleteStatueKID(lpStatue->GetKID())) { switch (lpStatue->GetNation()) { case Creature::KARTERANT: { switch (lpStatue->GetRealmStatueEnchantType()) { case MonsterInfo::SE_HP: m_RealmEnchantInfo[CClass::HUMAN].m_cHPPercent += lpStatue->GetRealmStatueEnchantPercent(); break; case MonsterInfo::SE_MP: m_RealmEnchantInfo[CClass::HUMAN].m_cMPPercent += lpStatue->GetRealmStatueEnchantPercent(); break; case MonsterInfo::SE_EXP: m_RealmEnchantInfo[CClass::HUMAN].m_cExpPercent += lpStatue->GetRealmStatueEnchantPercent(); break; case MonsterInfo::SE_DROPRATE: m_RealmEnchantInfo[CClass::HUMAN].m_cDropRate += lpStatue->GetRealmStatueEnchantPercent(); break; case MonsterInfo::SE_NONE: default: break; } } break; case Creature::MERKADIA: { switch (lpStatue->GetRealmStatueEnchantType()) { case MonsterInfo::SE_HP: m_RealmEnchantInfo[CClass::AKHAN].m_cHPPercent += lpStatue->GetRealmStatueEnchantPercent(); break; case MonsterInfo::SE_MP: m_RealmEnchantInfo[CClass::AKHAN].m_cMPPercent += lpStatue->GetRealmStatueEnchantPercent(); break; case MonsterInfo::SE_EXP: m_RealmEnchantInfo[CClass::AKHAN].m_cExpPercent += lpStatue->GetRealmStatueEnchantPercent(); break; case MonsterInfo::SE_DROPRATE: m_RealmEnchantInfo[CClass::AKHAN].m_cDropRate += lpStatue->GetRealmStatueEnchantPercent(); break; case MonsterInfo::SE_NONE: default: break; } } break; } } ++itr; } // ROW¿¡¼­´Â °ø¼±ÀüÀ» 16¹ø¿¡¼­ ÇÏÁö ¾Ê±â ¶§¹®¿¡ ÇØ´ç º¸³Ê½º¸¦ Á¦°ÅÇÑ´Ù. // °ø¼±ÀüÀ» ÇÒ Á¸À» µû·Î ÁöÁ¤Çؼ­ ÃßÈÄ¿¡ Ãß°¡ÇÑ´Ù. // ÄÁÅÙÃ÷ : °ø¼ºÀü if (true == CServerSetup::GetInstance().UseContents(GameRYL::SIEGE)) { AddCastleBonus(); } } void CCreatureManager::AddRealmStatueEnchant(CCharacter* lpCharacter) { // CalculateRealmStatueEnchantInfo() ÇÔ¼ö°¡ È£ÃâµÇ¾î ÀÖ¾î¾ßÇÑ´Ù.!! unsigned char cRace = lpCharacter->GetRace(); // Á×¾îÀÖ´Â ³à¼®Àº ºÎȰÈÄ¿¡ ¹öÇÁ¸¦ °É¾îÁØ´Ù. if(lpCharacter->IsDead()) { lpCharacter->SetRealmWarBuffer(TRUE); return; } lpCharacter->SetRealmWarBuffer(FALSE); if (m_RealmEnchantInfo[cRace].m_cHPPercent > 0) { Skill::CAddSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCharacter, Skill::SpellType::STATUE_SPELL, Skill::SpellID::PowerStatue, m_RealmEnchantInfo[cRace].m_cHPPercent, CSpell::REALM_TIME))(lpCharacter); } if (m_RealmEnchantInfo[cRace].m_cMPPercent > 0) { Skill::CAddSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCharacter, Skill::SpellType::STATUE_SPELL, Skill::SpellID::IntStatue, m_RealmEnchantInfo[cRace].m_cMPPercent, CSpell::REALM_TIME))(lpCharacter); } if (m_RealmEnchantInfo[cRace].m_cExpPercent > 0) { Skill::CAddSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCharacter, Skill::SpellType::STATUE_SPELL, Skill::SpellID::ExpStatue, m_RealmEnchantInfo[cRace].m_cExpPercent, CSpell::REALM_TIME))(lpCharacter); } if (m_RealmEnchantInfo[cRace].m_cDropRate > 0) { Skill::CAddSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCharacter, Skill::SpellType::STATUE_SPELL, Skill::SpellID::WealthStatue, m_RealmEnchantInfo[cRace].m_cDropRate, CSpell::REALM_TIME))(lpCharacter); } } void CCreatureManager::AddRealmStatueEnchant() { // CalculateRealmStatueEnchantInfo() ÇÔ¼ö°¡ È£ÃâµÇ¾î ÀÖ¾î¾ßÇÑ´Ù.!! CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = NULL; while (itr != end) { lpCharacter = itr->second; if (NULL == lpCharacter) { ++itr; continue; } AddRealmStatueEnchant(lpCharacter); ++itr; } } void CCreatureManager::ClearRealmStatueEnchant() { CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = NULL; while (itr != end) { lpCharacter = itr->second; if (NULL == lpCharacter) { ++itr; continue; } lpCharacter->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::PowerStatue); lpCharacter->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::IntStatue); lpCharacter->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::ExpStatue); lpCharacter->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::WealthStatue); ++itr; } } void CCreatureManager::AddCastleBonus() { int iHumanCastleNum = Castle::CCastleMgr::GetInstance().GetCastleNum(Creature::KARTERANT, SERVER_ID::CAPITAL); int iAkhanCastleNum = Castle::CCastleMgr::GetInstance().GetCastleNum(Creature::MERKADIA, SERVER_ID::CAPITAL); if (iHumanCastleNum > 0) { m_RealmEnchantInfo[CClass::HUMAN].m_cHPPercent += static_cast( m_RealmEnchantInfo[CClass::HUMAN].m_cHPPercent * 0.3f * iHumanCastleNum ); m_RealmEnchantInfo[CClass::HUMAN].m_cMPPercent += static_cast( m_RealmEnchantInfo[CClass::HUMAN].m_cMPPercent * 0.3f * iHumanCastleNum ); m_RealmEnchantInfo[CClass::HUMAN].m_cExpPercent += static_cast( m_RealmEnchantInfo[CClass::HUMAN].m_cExpPercent * 0.3f * iHumanCastleNum ); m_RealmEnchantInfo[CClass::HUMAN].m_cDropRate += static_cast( m_RealmEnchantInfo[CClass::HUMAN].m_cDropRate * 0.3f * iHumanCastleNum ); } if (iAkhanCastleNum > 0) { m_RealmEnchantInfo[CClass::AKHAN].m_cHPPercent += static_cast( m_RealmEnchantInfo[CClass::AKHAN].m_cHPPercent * 0.3f * iAkhanCastleNum ); m_RealmEnchantInfo[CClass::AKHAN].m_cMPPercent += static_cast( m_RealmEnchantInfo[CClass::AKHAN].m_cMPPercent * 0.3f * iAkhanCastleNum ); m_RealmEnchantInfo[CClass::AKHAN].m_cExpPercent += static_cast( m_RealmEnchantInfo[CClass::AKHAN].m_cExpPercent * 0.3f * iAkhanCastleNum ); m_RealmEnchantInfo[CClass::AKHAN].m_cDropRate += static_cast( m_RealmEnchantInfo[CClass::AKHAN].m_cDropRate * 0.3f * iAkhanCastleNum ); } } void CCreatureManager::AddWorldWeaponEnchant(CAggresiveCreature* lpWeapon, unsigned char cNation) { if (Creature::KARTERANT != cNation && Creature::MERKADIA != cNation) return; if (NULL == lpWeapon) return; CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = NULL; while (itr != end) { lpCharacter = itr->second; if (lpCharacter) { lpCharacter->AddWorldWeaponEnchant(lpWeapon, cNation); } ++itr; } } void CCreatureManager::ClearWorldWeaponEnchant() { CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); CCharacter* lpCharacter = NULL; while (itr != end) { lpCharacter = itr->second; if (lpCharacter) { lpCharacter->ClearWorldWeaponEnchant(); } ++itr; } } void CCreatureManager::ProcessWorldWeaponDamage(int iX, int iZ, unsigned char cUpgradeStep) { CAggresiveCreature* pOffencer = reinterpret_cast( CSiegeObjectMgr::GetInstance().GetWorldWeapon() ); if (NULL == pOffencer) { return; } CSiegeObject* lpSiegeObject = NULL; CCharacter* lpCharacter = NULL; float fDX, fDZ, fDist; int nDamage = 0; int nPreviousHP = 0; // ---------------------------------------------------------------------------------------------- // // °ø¼º ¿ÀºêÁ§Æ®µé µ¥¹ÌÁö ó¸® SiegeObjectMap::iterator SiegeItr = m_SiegeObjectMap.begin(); SiegeObjectMap::iterator SiegeEnd = m_SiegeObjectMap.end(); while (SiegeItr != SiegeEnd) { lpSiegeObject = SiegeItr->second; if (NULL != lpSiegeObject) { fDX = lpSiegeObject->GetCurrentPos().m_fPointX - iX; fDZ = lpSiegeObject->GetCurrentPos().m_fPointZ - iZ; fDist = sqrtf(fDX*fDX + fDZ*fDZ); // ¹üÀ§ ¾È¿¡ µé¾î ÀÖ´Ù¸é... if (Siege::WEAPON_DAMAGE_RANGE >= fDist) { // Damage ÀÇ 1/4 ¿¡ ÇØ´çÇÏ´Â µ¥¹ÌÁö Àû¿ë nDamage = static_cast(((cUpgradeStep > 0 ) ? Siege::WEAPON_DAMAGE * cUpgradeStep : Siege::WEAPON_DAMAGE) * 0.25f); nPreviousHP = lpSiegeObject->GetStatus().m_nNowHP; // ¼º¹®Àº ¼º¹® ¸·±â¸¦ ÅëÇØ¼­ ºí·°·üÀ» ³ôÀ̰í, ¸·°í Àִ ij¸¯ÅÍ¿¡°Ô µ¥¹ÌÁö°¡ ³ª´²Á®°£´Ù. if (lpSiegeObject->IsGate()) { reinterpret_cast( lpSiegeObject )->DivideDamage(pOffencer, nDamage); reinterpret_cast( lpSiegeObject )->SendProtectGateInfo(); } const unsigned short nThreatAmount = (lpSiegeObject->GetStatus().m_nNowHP < nDamage) ? lpSiegeObject->GetStatus().m_nNowHP : nDamage; lpSiegeObject->GetThreat().AddToThreatList(pOffencer, nThreatAmount); lpSiegeObject->GetStatus().m_nNowHP = (lpSiegeObject->GetStatus().m_nNowHP > nDamage) ? lpSiegeObject->GetStatus().m_nNowHP - nDamage : 0; // °ø¼º ¿ÀºêÁ§Æ®¶ó¸é HP Á¤º¸¸¦ DBÁß°è ¼­¹ö¿¡ ¾÷µ¥ÀÌÆ®ÇÑ´Ù. lpSiegeObject->SendHPUpdateToDBAgent(); if (lpSiegeObject->IsCamp()) { // °ø°Ý ´çÇϰí ÀÖ´Ù´Â ¸Þ¼¼Áö¸¦ º¸³»ÁØ´Ù. reinterpret_cast(lpSiegeObject)->SendAttackedMessage(); } else if (lpSiegeObject->IsEmblem()) { // °ø°Ý ´çÇϰí ÀÖ´Ù´Â ¸Þ¼¼Áö¸¦ º¸³»ÁØ´Ù. reinterpret_cast(lpSiegeObject)->SendAttackedMessage(); } // Á×¾úÀ» °æ¿ì (ÀÚ»ì ½ºÅ³Àº ¹«È¿) // ÀÌ¹Ì Á×¾îÀÖ´Â °æ¿ì¿¡ ·¹Á®·º¼Ç ½ºÅ³À» ¹Þ¾ÒÀ»¶§´Â Dead() ÇÔ¼ö¸¦ ´Ù½Ã È£ÃâÇÏÁö ¾Ê´Â´Ù. if (0 != nPreviousHP && 0 == lpSiegeObject->GetStatus().m_nNowHP && pOffencer != lpSiegeObject) { lpSiegeObject->Dead(pOffencer); lpSiegeObject->GetThreat().ClearAll(); } // Attacked ÆÐŶÀ» º¸³»ÁØ´Ù. (Ÿ°í ÀÖ´Â »ç¶÷¿¡°Ô °ø¼º ¿ÀºêÁ§Æ®ÀÇ CID ·Î...) CCharacter* lpRider = GetCharacter( lpSiegeObject->GetRiderCID() ); if (NULL != lpRider) { CGameClientDispatch* lpDispatch = lpRider->GetDispatcher(); if (NULL != lpRider) { AtType Type = {0,}; Type.m_wType = 1; GameClientSendPacket::SendCharAttacked(lpDispatch->GetSendStream(), pOffencer, lpSiegeObject, Type, 0, nDamage, 0, 0, PktBase::NO_SERVER_ERR); } } } } ++SiegeItr; } // ---------------------------------------------------------------------------------------------- // // ---------------------------------------------------------------------------------------------- // // ij¸¯ÅÍµé µ¥¹ÌÁö ó¸® CharacterMap::iterator itr = m_CharacterMap.begin(); CharacterMap::iterator end = m_CharacterMap.end(); while (itr != end) { lpCharacter = itr->second; if (lpCharacter) { fDX = lpCharacter->GetCurrentPos().m_fPointX - iX; fDZ = lpCharacter->GetCurrentPos().m_fPointZ - iZ; fDist = sqrtf(fDX*fDX + fDZ*fDZ); // ¹üÀ§ ¾È¿¡ µé¾î ÀÖ´Ù¸é... if (Siege::WEAPON_DAMAGE_RANGE >= fDist) { if (false == lpCharacter->IsRideArms()) { // Àý´ë µ¥¹ÌÁö nDamage = (cUpgradeStep > 0 ) ? Siege::WEAPON_DAMAGE * cUpgradeStep : Siege::WEAPON_DAMAGE; nPreviousHP = lpCharacter->GetStatus().m_nNowHP; const unsigned short nThreatAmount = (lpCharacter->GetStatus().m_nNowHP < nDamage) ? lpCharacter->GetStatus().m_nNowHP : nDamage; lpCharacter->GetThreat().AddToThreatList(pOffencer, nThreatAmount); lpCharacter->GetStatus().m_nNowHP = (lpCharacter->GetStatus().m_nNowHP > nDamage) ? lpCharacter->GetStatus().m_nNowHP - nDamage : 0; // Á×¾úÀ» °æ¿ì (ÀÚ»ì ½ºÅ³Àº ¹«È¿) // ÀÌ¹Ì Á×¾îÀÖ´Â °æ¿ì¿¡ ·¹Á®·º¼Ç ½ºÅ³À» ¹Þ¾ÒÀ»¶§´Â Dead() ÇÔ¼ö¸¦ ´Ù½Ã È£ÃâÇÏÁö ¾Ê´Â´Ù. if (0 != nPreviousHP && 0 == lpCharacter->GetStatus().m_nNowHP && pOffencer != lpCharacter) { lpCharacter->Dead(pOffencer); lpCharacter->GetThreat().ClearAll(); } // Attacked ÆÐŶÀ» º¸³»ÁØ´Ù. CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { AtType Type = {0,}; Type.m_wType = 1; GameClientSendPacket::SendCharAttacked(lpDispatch->GetSendStream(), pOffencer, lpCharacter, Type, 0, nDamage, 0, 0, PktBase::NO_SERVER_ERR); } } } } ++itr; } // ---------------------------------------------------------------------------------------------- // }