server/game/src/mob_manager.cpp

383 lines
8.4 KiB
C++

#include "stdafx.h"
#include "char.h"
#include "char_manager.h"
#include "item_manager.h"
#include "mob_manager.h"
#include "regen.h"
#include "sectree.h"
#include "text_file_loader.h"
#include "questmanager.h"
#include "locale_service.h"
CMob::CMob()
{
memset( &m_table, 0, sizeof(m_table) );
for( size_t i=0 ; i < MOB_SKILL_MAX_NUM ; ++i )
{
m_mobSkillInfo[i].dwSkillVnum = 0;
m_mobSkillInfo[i].bSkillLevel = 0;
m_mobSkillInfo[i].vecSplashAttack.clear();
}
}
CMob::~CMob()
{
}
void CMob::AddSkillSplash(int iIndex, DWORD dwTiming, DWORD dwHitDistance)
{
if (iIndex >= MOB_SKILL_MAX_NUM || iIndex < 0)
return;
sys_log(0, "MOB_SPLASH %s idx %d timing %u hit_distance %u",
m_table.szLocaleName, iIndex, dwTiming, dwHitDistance);
m_mobSkillInfo[iIndex].vecSplashAttack.push_back(TMobSplashAttackInfo(dwTiming, dwHitDistance));
}
CMobInstance::CMobInstance()
: m_IsBerserk(false), m_IsGodSpeed(false), m_IsRevive(false)
{
m_dwLastAttackedTime = get_dword_time();
m_dwLastWarpTime = get_dword_time();
memset( &m_posLastAttacked, 0, sizeof(m_posLastAttacked) );
}
CMobManager::CMobManager()
{
}
CMobManager::~CMobManager()
{
}
bool CMobManager::Initialize(TMobTable * pTable, int iSize)
{
m_map_pkMobByVnum.clear();
m_map_pkMobByName.clear();
TMobTable * t = pTable;
for (int i = 0; i < iSize; ++i, ++t)
{
CMob * pkMob = M2_NEW CMob;
memcpy(&pkMob->m_table, t, sizeof(TMobTable));
m_map_pkMobByVnum.insert(std::map<DWORD, CMob *>::value_type(t->dwVnum, pkMob));
m_map_pkMobByName.insert(std::map<std::string, CMob *>::value_type(t->szLocaleName, pkMob));
int SkillCount = 0;
for (int j = 0; j < MOB_SKILL_MAX_NUM; ++j)
if (pkMob->m_table.Skills[j].dwVnum)
++SkillCount;
sys_log(0, "MOB: #%-5d %-30s LEVEL %u HP %u DEF %u EXP %u DROP_ITEM_VNUM %u SKILL_COUNT %d",
t->dwVnum, t->szLocaleName, t->bLevel, t->dwMaxHP, t->wDef, t->dwExp, t->dwDropItemVnum, SkillCount);
if (t->bType == CHAR_TYPE_NPC || t->bType == CHAR_TYPE_WARP || t->bType == CHAR_TYPE_GOTO)
CHARACTER_MANAGER::instance().RegisterRaceNum(t->dwVnum);
quest::CQuestManager::instance().RegisterNPCVnum(t->dwVnum);
}
// LOCALE_SERVICE
const int FILE_NAME_LEN = 256;
char szGroupFileName[FILE_NAME_LEN];
char szGroupGroupFileName[FILE_NAME_LEN];
snprintf(szGroupFileName, sizeof(szGroupGroupFileName),
"%s/group.txt", LocaleService_GetBasePath().c_str());
snprintf(szGroupGroupFileName, sizeof(szGroupGroupFileName),
"%s/group_group.txt", LocaleService_GetBasePath().c_str());
if (!LoadGroup(szGroupFileName))
{
sys_err("cannot load %s", szGroupFileName);
thecore_shutdown();
}
if (!LoadGroupGroup(szGroupGroupFileName))
{
sys_err("cannot load %s", szGroupGroupFileName);
thecore_shutdown();
}
// END_OF_LOCALE_SERVICE
//exit(1);
CHARACTER_MANAGER::instance().for_each_pc(std::bind1st(std::mem_fun(&CMobManager::RebindMobProto),this));
return true;
}
void CMobManager::RebindMobProto(LPCHARACTER ch)
{
if (ch->IsPC())
return;
const CMob * pMob = Get(ch->GetRaceNum());
if (pMob)
ch->SetProto(pMob);
}
const CMob * CMobManager::Get(DWORD dwVnum)
{
std::map<DWORD, CMob *>::iterator it = m_map_pkMobByVnum.find(dwVnum);
if (it == m_map_pkMobByVnum.end())
return NULL;
return it->second;
}
const CMob * CMobManager::Get(const char * c_pszName, bool bIsAbbrev)
{
std::map<std::string, CMob *>::iterator it;
if (!bIsAbbrev)
{
it = m_map_pkMobByName.find(c_pszName);
if (it == m_map_pkMobByName.end())
return NULL;
return it->second;
}
int len = strlen(c_pszName);
it = m_map_pkMobByName.begin();
while (it != m_map_pkMobByName.end())
{
if (!strncmp(it->first.c_str(), c_pszName, len))
return it->second;
++it;
}
return NULL;
}
void CMobManager::IncRegenCount(BYTE bRegenType, DWORD dwVnum, int iCount, int iTime)
{
switch (bRegenType)
{
case REGEN_TYPE_MOB:
m_mapRegenCount[dwVnum] += iCount * 86400. / iTime;
break;
case REGEN_TYPE_GROUP:
{
CMobGroup * pkGroup = CMobManager::Instance().GetGroup(dwVnum);
if (!pkGroup)
return;
const std::vector<DWORD> & c_rdwMembers = pkGroup->GetMemberVector();
for (DWORD i=0; i<c_rdwMembers.size(); i++)
m_mapRegenCount[c_rdwMembers[i]] += iCount * 86400. / iTime;
}
break;
case REGEN_TYPE_GROUP_GROUP:
{
std::map<DWORD, CMobGroupGroup *>::iterator it = m_map_pkMobGroupGroup.find(dwVnum);
if (it == m_map_pkMobGroupGroup.end())
return;
std::vector<DWORD>& v = it->second->m_vec_dwMemberVnum;
for (DWORD i=0; i<v.size(); i++)
{
//m_mapRegenCount[v[i]] += iCount * 86400. / iTime / v.size();
CMobGroup * pkGroup = CMobManager::Instance().GetGroup(v[i]);
if (!pkGroup)
return;
const std::vector<DWORD> & c_rdwMembers = pkGroup->GetMemberVector();
for (DWORD i=0; i<c_rdwMembers.size(); i++)
m_mapRegenCount[c_rdwMembers[i]] += iCount * 86400. / iTime / v.size();
}
}
break;
}
}
void CMobManager::DumpRegenCount(const char* c_szFilename)
{
FILE* fp = fopen(c_szFilename, "w");
if (fp)
{
std::map<DWORD, double>::iterator it;
fprintf(fp,"MOB_VNUM\tCOUNT\n");
for (it = m_mapRegenCount.begin(); it != m_mapRegenCount.end(); ++it)
{
fprintf(fp,"%u\t%g\n", it->first, it->second);
}
fclose(fp);
}
}
DWORD CMobManager::GetGroupFromGroupGroup(DWORD dwVnum)
{
std::map<DWORD, CMobGroupGroup *>::iterator it = m_map_pkMobGroupGroup.find(dwVnum);
if (it == m_map_pkMobGroupGroup.end())
return 0;
return it->second->GetMember();
}
CMobGroup * CMobManager::GetGroup(DWORD dwVnum)
{
std::map<DWORD, CMobGroup *>::iterator it = m_map_pkMobGroup.find(dwVnum);
if (it == m_map_pkMobGroup.end())
return NULL;
return it->second;
}
bool CMobManager::LoadGroupGroup(const char * c_pszFileName)
{
CTextFileLoader loader;
if (!loader.Load(c_pszFileName))
return false;
std::string stName;
for (DWORD i = 0; i < loader.GetChildNodeCount(); ++i)
{
loader.SetChildNode(i);
loader.GetCurrentNodeName(&stName);
int iVnum;
if (!loader.GetTokenInteger("vnum", &iVnum))
{
sys_err("LoadGroupGroup : Syntax error %s : no vnum, node %s", c_pszFileName, stName.c_str());
loader.SetParentNode();
continue;
}
TTokenVector * pTok;
CMobGroupGroup * pkGroup = M2_NEW CMobGroupGroup(iVnum);
for (int k = 1; k < 256; ++k)
{
char buf[4];
snprintf(buf, sizeof(buf), "%d", k);
if (loader.GetTokenVector(buf, &pTok))
{
DWORD dwMobVnum = 0;
str_to_number(dwMobVnum, pTok->at(0).c_str());
// ADD_MOB_GROUP_GROUP_PROB
int prob = 1;
if (pTok->size() > 1)
str_to_number(prob, pTok->at(1).c_str());
// END_OF_ADD_MOB_GROUP_GROUP_PROB
if (dwMobVnum)
pkGroup->AddMember(dwMobVnum);
continue;
}
break;
}
loader.SetParentNode();
m_map_pkMobGroupGroup.insert(std::make_pair((DWORD)iVnum, pkGroup));
}
return true;
}
bool CMobManager::LoadGroup(const char * c_pszFileName)
{
CTextFileLoader loader;
if (!loader.Load(c_pszFileName))
return false;
std::string stName;
for (DWORD i = 0; i < loader.GetChildNodeCount(); ++i)
{
loader.SetChildNode(i);
loader.GetCurrentNodeName(&stName);
int iVnum;
if (!loader.GetTokenInteger("vnum", &iVnum))
{
sys_err("LoadGroup : Syntax error %s : no vnum, node %s", c_pszFileName, stName.c_str());
loader.SetParentNode();
continue;
}
TTokenVector * pTok;
if (!loader.GetTokenVector("leader", &pTok))
{
sys_err("LoadGroup : Syntax error %s : no leader, node %s", c_pszFileName, stName.c_str());
loader.SetParentNode();
continue;
}
if (pTok->size() < 2)
{
sys_err("LoadGroup : Syntax error %s : no leader vnum, node %s", c_pszFileName, stName.c_str());
loader.SetParentNode();
continue;
}
CMobGroup * pkGroup = M2_NEW CMobGroup;
pkGroup->Create(iVnum, stName);
DWORD vnum = 0;
str_to_number(vnum, pTok->at(1).c_str());
pkGroup->AddMember(vnum);
sys_log(0, "GROUP: %-5d %s", iVnum, stName.c_str());
sys_log(0, " %s %s", pTok->at(0).c_str(), pTok->at(1).c_str());
for (int k = 1; k < 256; ++k)
{
char buf[4];
snprintf(buf, sizeof(buf), "%d", k);
if (loader.GetTokenVector(buf, &pTok))
{
sys_log(0, " %s %s", pTok->at(0).c_str(), pTok->at(1).c_str());
DWORD vnum = 0;
str_to_number(vnum, pTok->at(1).c_str());
pkGroup->AddMember(vnum);
continue;
}
break;
}
loader.SetParentNode();
m_map_pkMobGroup.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));
}
return true;
}