Files
Client/Server/RylServerProject/RylGameLibrary/Creature/Monster/VirtualMonsterMgr.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

352 lines
8.0 KiB
C++

#include "stdafx.h"
#include "VirtualMonsterMgr.h"
#include <Creature/Creature.h>
#include <Creature/Monster/Monster.h>
#include <Creature/Monster/PatternMonster.h>
#include <Network/Dispatch/GameClient/SendCharAttack.h>
CVirtualMonsterMgr::CVirtualMonsterMgr()
: m_usSummonCount(0)
{
}
CVirtualMonsterMgr::~CVirtualMonsterMgr()
{
DestroyMonsterList();
}
struct FnDeleteSecond
{
template<typename PairType>
bool operator() (PairType& pair) { if(NULL != pair.second) { delete pair.second; } return true; }
};
struct FnLeaveParty
{
template<typename PairType>
bool operator() (PairType& pair)
{
if(NULL != pair.second)
{
CParty* lpParty = (pair.second)->GetParty();
if (lpParty)
{
lpParty->Leave((pair.second)->GetCID(), 0, (pair.second)->GetMapIndex());
}
}
return true;
}
};
void CVirtualMonsterMgr::DestroyMonsterList()
{
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();
}
bool CVirtualMonsterMgr::AddMonster(CMonster* lpMonster)
{
if (NULL == lpMonster) return false;
unsigned long dwCID = lpMonster->GetCID();
bool bResult = false;
Creature::CreatureType eCreatureType = Creature::GetCreatureType(dwCID);
if (Creature::CT_MONSTER == eCreatureType ||
Creature::CT_SUMMON == eCreatureType ||
Creature::CT_STRUCT == eCreatureType)
{
bResult = m_MonsterMap.insert(std::make_pair(dwCID, reinterpret_cast<CMonster *>(lpMonster))).second;
unsigned short wKindID = static_cast<unsigned short>( (dwCID & Creature::MONSTER_KIND_BIT) );
if ( bResult && m_AdminMonsterUIDMap.end() == m_AdminMonsterUIDMap.find(wKindID) )
{
m_AdminMonsterUIDMap.insert(std::make_pair(wKindID, INIT_UID)).second;
}
}
return bResult;
}
CCreature* CVirtualMonsterMgr::GetCreature(unsigned long dwCID)
{
Creature::CreatureType eCreatureType = Creature::GetCreatureType(dwCID);
if (Creature::CT_MONSTER == eCreatureType || Creature::CT_SUMMON == eCreatureType || Creature::CT_STRUCT == eCreatureType)
return (CCreature *)GetMonster(dwCID);
return (CCreature *)NULL;
}
CAggresiveCreature* CVirtualMonsterMgr::GetAggresiveCreature(unsigned long dwCID)
{
Creature::CreatureType eCreatureType = Creature::GetCreatureType(dwCID);
if (Creature::CT_MONSTER == eCreatureType || Creature::CT_SUMMON == eCreatureType || Creature::CT_STRUCT == eCreatureType)
return (CAggresiveCreature *)GetMonster(dwCID);
return (CAggresiveCreature *)NULL;
}
CMonster* CVirtualMonsterMgr::GetMonster(unsigned long dwCID)
{
MonsterMap::iterator pos = m_MonsterMap.find(dwCID);
return (pos != m_MonsterMap.end()) ? pos->second : NULL;
}
void CVirtualMonsterMgr::ProcessAllMonster()
{
MonsterMap::iterator pos = m_MonsterMap.begin();
MonsterMap::iterator end = m_MonsterMap.end();
for (; pos != end; )
{
CMonster* lpMonster = pos->second;
if (lpMonster)
{
lpMonster->Process();
}
++pos;
}
}
void CVirtualMonsterMgr::ProcessMonsterRegenHPAndMP()
{
MonsterMap::iterator pos = m_MonsterMap.begin();
MonsterMap::iterator end = m_MonsterMap.end();
for (; pos != end; )
{
CMonster* lpMonster = pos->second;
if (lpMonster)
{
lpMonster->RegenHPAndMP(0, 0, true);
}
++pos;
}
}
void CVirtualMonsterMgr::ProcessSummonMonsterDead(void)
{
MonsterMap::iterator pos = m_MonsterMap.begin();
MonsterMap::iterator end = m_MonsterMap.end();
for (; pos != end; )
{
CMonster* lpMonster = pos->second;
if (lpMonster && true == lpMonster->IsDeadSummonMonster())
{
pos = m_MonsterMap.erase(pos);
delete lpMonster;
}
++pos;
}
}
bool CVirtualMonsterMgr::IsSummonee(unsigned long dwCID)
{
return Creature::IsSummonMonster(dwCID);
}
bool CVirtualMonsterMgr::SummonMonster(int nKID, Position Pos, CCharacter* lpMaster)
{
CMonster::MonsterCreateInfo tempInfo;
tempInfo.m_dwCID = Creature::SUMMON_MONSTER_BIT + (m_usSummonCount << 16) + nKID;
if (0 != GetMonster(tempInfo.m_dwCID))
{
ERRLOG0(g_Log, "몬스터 소환에 실패하였습니다.");
return false;
}
tempInfo.m_nKID = nKID;
tempInfo.m_Pos = Pos;
CMonster* lpSummonMonster = 0;
if (0 != lpMaster)
{
CAggresiveCreature* lpSummonee = lpMaster->GetSummonee();
if (0 != lpSummonee)
{
lpSummonee->Dead(0);
}
}
lpSummonMonster = new CSummonMonster(tempInfo, lpMaster);
if (0 == lpSummonMonster)
{
ERRLOG0(g_Log, "몬스터 소환에 실패하였습니다.");
return false;
}
lpSummonMonster->SetMapIndex(lpMaster->GetMapIndex());
if (false == lpSummonMonster->InitMonster(tempInfo.m_Pos))
{
ERRLOG0(g_Log, "소환 몬스터 초기화에 실패하였습니다.");
return false;
}
AddMonster(lpSummonMonster);
m_usSummonCount++;
if (CMonster::MAX_MONSTER_UID == m_usSummonCount) { m_usSummonCount = 0; }
if (0 != lpMaster)
{
lpMaster->SetSummonee(lpSummonMonster);
GameClientSendPacket::SendCharSummon(lpMaster->GetCID(), lpSummonMonster);
}
else
{
lpSummonMonster->SendMove(CMonster::RUN_ANI_LIMIT_MIN);
}
return true;
}
bool CVirtualMonsterMgr::AdminSummonMonster(int nKID, Position Pos, unsigned short wMapIndex)
{
CMonster::MonsterCreateInfo tempInfo;
CMonster* lpNewMonster = 0;
// nKID 가 정상인지 체크
const CMonsterMgr::MonsterProtoType* lpProtoType = CMonsterMgr::GetInstance().GetMonsterProtoType(nKID);
if (0 == lpProtoType)
{
ERRLOG1(g_Log, "KID : %d 몬스터를 소환하는데 실패하였습니다.", nKID);
return false;
}
// 존당 최대 몬스터 수를 초과하는지 체크
if (GetMonsterNum() >= CMonster::MAX_MONSTER_UID)
{
ERRLOG0(g_Log, "현재 존에 몬스터 수가 최대입니다. 더이상 몬스터를 생성할 수 없습니다.");
return false;
}
// 몬스터 맵에서 적당한 숫자를 넘겨준다. (CID 를 유니크하게 하기 위해서)
unsigned long dwUID = GetAvailableMonsterUID(static_cast<unsigned short>(nKID));
if (dwUID == NO_BLANK_UID)
{
ERRLOG1(g_Log, "KindID:%d 해당 종류의 몬스터 수가 최대입니다. 더이상 몬스터를 생성할 수 없습니다.", nKID);
return false;
}
tempInfo.m_dwCID = (dwUID << 16) + nKID;
tempInfo.m_nKID = nKID;
tempInfo.m_dwPID = 0;
tempInfo.m_Pos = Pos;
tempInfo.m_bScout = false;
tempInfo.m_nMovingPattern = 0;
tempInfo.m_wRespawnArea = CCell::CELL_DISTANCE;
// MON_TODO : 몬스터 타입에 맞게 생성
switch (lpProtoType->m_MonsterInfo.m_cSkillPattern)
{
case MonsterInfo::PATTERN_DEFENDER:
lpNewMonster = new CDefenderMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_WARRIOR:
lpNewMonster = new CWarriorMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_ACOLYTE:
lpNewMonster = new CAcolyteMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_MAGE:
lpNewMonster = new CMageMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_BOSS:
lpNewMonster = new CBossMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_NAMED:
lpNewMonster = new CNamedMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_CHIEF:
lpNewMonster = new CChiefMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_OBJECT:
lpNewMonster = new CObjectMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_GUARD:
lpNewMonster = new CGuardMonster(tempInfo, true);
break;
case MonsterInfo::PATTERN_GATHER:
lpNewMonster = new CGatherMonster(tempInfo, true);
break;
default:
lpNewMonster = new CMonster(tempInfo, true);
break;
};
if (0 == lpNewMonster)
{
ERRLOG0(g_Log, "몬스터 생성에 실패하였습니다.");
return false;
}
lpNewMonster->SetMapIndex(wMapIndex);
if (false == lpNewMonster->InitMonster(tempInfo.m_Pos))
{
ERRLOG0(g_Log, "몬스터 초기화에 실패하였습니다.");
return false;
}
return AddMonster(lpNewMonster);
}
unsigned short CVirtualMonsterMgr::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]--;
}