📄 npc.cpp
字号:
// TaskNpc.cpp: implementation of the CNpc class.
//
//////////////////////////////////////////////////////////////////////
#include "AllMsg.h"
#include "windows.h"
#include "Gameobj.h"
#include "MapGroup.h"
#include "define.h"
#include "Npc.h"
#include "NpcTask.h"
#include "NpcScene.h"
#include "NpcLink.h"
#include "NpcStorage.h"
#include "BetOutside.h"
//////////////////////////////////////////////////////////////////////
const int FIXSYNFLAG_SECS = 10;
const int MAX_FIXMONEY = 1000;
const int FIXLIFE_PER_MONEY = 1;
const int BROADCASTSCORE_SECS = 30; // 注意:太大可能错开战斗时间检查
const int TRANSNPC_FEE = 10000; // 每天每个传送门收费
//////////////////////////////////////////////////////////////////////
// static
char szNpcTable[] = _TBL_NPC;
char szDynTable[] = _TBL_DYNANPC;
MYHEAP_IMPLEMENTATION(CNpc,s_heap)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CNpc::CNpc()
{
SetObjType(OBJ_NPC);
m_id = ID_NONE;
m_pData = NULL;
m_bDynaNpc = false;
m_pShop = NULL;
m_pAuction = NULL;
m_pTask = NULL;
// m_pStorage = NULL;
m_pTrunk = NULL;
m_pScene = NULL;
m_pLinkMap = NULL;
m_pBet = NULL;
m_pEudemonBrooder = NULL;
m_pEudemonStorage = NULL;
m_i64Effect = 0;
}
//////////////////////////////////////////////////////////////////////
CNpc::~CNpc()
{
if(m_pMap)
{
//SendLeaveFromBlock();
ClrBroadcastSet();
if(m_pMap)
{
m_pMap->LeaveRoom(QueryMapThing(), WITH_BLOCK);
UpdateHoldFloor(false);
}
}
SAFE_RELEASE (m_setStatus);
if(m_pData)
{
if(IsDynaNpc())
{
if(IsAlive())
SaveInfo();
else
DeleteRecord();
}
m_pData->Release();
}
if(m_pShop)
{
m_pShop->Release();
}
if(m_pAuction)
{
m_pAuction->Release();
}
if(m_pTask)
{
m_pTask->Release();
}
/*if(m_pStorage)
{
m_pStorage->Release();
}*/
if(m_pLinkMap)
{
m_pLinkMap->Release();
}
if(m_pScene)
{
m_pScene->Release();
}
if(m_pTrunk)
{
m_pTrunk->Release();
}
if(m_pBet)
{
m_pBet->Release();
}
if (m_pEudemonBrooder)
SAFE_RELEASE (m_pEudemonBrooder);
if (m_pEudemonStorage)
SAFE_RELEASE (m_pEudemonStorage);
}
//////////////////////////////////////////////////////////////////////
bool CNpc::Create(PROCESS_ID idProcess, NPCINFO_ST* pInfo, OBJID idItemType, LPCTSTR szName)
{
m_idProcess = idProcess;
m_bDynaNpc = true;
/*
// 使用VALUES单独INSERT,防止SQL溢出
SQLBUF szSQL;
ASSERT(_MAX_NPCTASK == 8);
ASSERT(MAX_NPCDATA == 4);
sprintf(szSQL, "INSERT %s VALUES(%u,%u,%d,'%s',%d,%d,%d,%u,%d,%d"",%d,%d,%d,%d,%d,%d,%d,%d"",%d,%d,%d,%d,'%s'"",%u,%d,%d,%d,%u",
_TBL_DYNANPC,
ID_NONE, pInfo->idOwner, pInfo->nOwnerType, "无", pInfo->nType, pInfo->nLookFace, -1, pInfo->idMap, pInfo->nPosX, pInfo->nPosY,
pInfo->setTask[0], pInfo->setTask[1], pInfo->setTask[2], pInfo->setTask[3],
pInfo->setTask[4], pInfo->setTask[5], pInfo->setTask[6], pInfo->setTask[7],
pInfo->setData[0], pInfo->setData[1], pInfo->setData[2], pInfo->setData[3], pInfo->szData,
ID_NONE, pInfo->nLife, pInfo->nLife, pInfo->nDir, pInfo->idRegion);
CHECKFDatabase()->ExecuteSQL(szSQL));
OBJID idRecord = Database()->GetInsertId();
CHECKF(idRecord != ID_NONE);
*/
ASSERT(!m_pData);
CDynaNpcData* pData = CDynaNpcData::CreateNew();
if(pData)
m_pData = pData->QueryInterface();
IF_NOT(m_pData && m_pData->Create(GameDataDefault()->GetDynaNpc(), ID_NONE)) // idRecord))
return false;
m_pData->SetInt(NPCDATA_OWNERID, pInfo->idOwner);
m_pData->SetInt(NPCDATA_OWNERTYPE, pInfo->nOwnerType);
m_pData->SetInt(NPCDATA_TYPE, pInfo->nType);
m_pData->SetStr(NPCDATA_NAME, szName, _MAX_NAMESIZE);
m_pData->SetInt(NPCDATA_LOOKFACE, pInfo->nLookFace);
m_pData->SetInt(NPCDATA_LENGTH, pInfo->cLength);
m_pData->SetInt(NPCDATA_FAT, pInfo->cFat);
m_pData->SetInt(NPCDATA_IDXSERVER, -1);
m_pData->SetInt(NPCDATA_MAPID, pInfo->idMap);
m_pData->SetInt(NPCDATA_POSX_, pInfo->nPosX);
m_pData->SetInt(NPCDATA_POSY_, pInfo->nPosY);
m_pData->SetInt(NPCDATA_TASK0, pInfo->setTask[0]);
m_pData->SetInt(NPCDATA_TASK1, pInfo->setTask[1]);
m_pData->SetInt(NPCDATA_TASK2, pInfo->setTask[2]);
m_pData->SetInt(NPCDATA_TASK3, pInfo->setTask[3]);
m_pData->SetInt(NPCDATA_TASK4, pInfo->setTask[4]);
m_pData->SetInt(NPCDATA_TASK5, pInfo->setTask[5]);
m_pData->SetInt(NPCDATA_TASK6, pInfo->setTask[6]);
m_pData->SetInt(NPCDATA_TASK7, pInfo->setTask[7]);
m_pData->SetInt(NPCDATA_DATA0, pInfo->setData[0]);
m_pData->SetInt(NPCDATA_DATA1, pInfo->setData[1]);
m_pData->SetInt(NPCDATA_DATA2, pInfo->setData[2]);
m_pData->SetInt(NPCDATA_DATA3, pInfo->setData[3]);
m_pData->SetStr(NPCDATA_DATASTR, pInfo->szData, _MAX_NAMESIZE);
m_pData->SetInt(NPCDATA_LINKID, pInfo->idLink);
m_pData->SetInt(NPCDATA_LIFE, pInfo->nLife);
m_pData->SetInt(NPCDATA_MAXLIFE, pInfo->nLife);
m_pData->SetInt(NPCDATA_BASE, pInfo->idBase);
m_pData->SetInt(NPCDATA_SORT, pInfo->nSort);
if(pInfo->nSort & NPCSORT_RECYCLE)
m_pData->SetInt(NPCDATA_ITEMTYPE, idItemType);
m_pData->InsertRecord();
m_id = MapManager()->SpawnNewNpcID();
m_nPosX = m_pData->GetInt(NPCDATA_POSX_);
m_nPosY = m_pData->GetInt(NPCDATA_POSY_);
if (this->IsTrunkNpc()
|| this->IsShopNpc()
|| this->IsSceneNpc()
|| this->IsTaskNpc()
|| this->IsBetNpc())
{
IF_NOT(CreateFuncObj(idProcess))
return false;
}
IF_NOT(CheckSortMutex())
return false;
m_setStatus = CStatusSet::CreateNew(true);
CHECKF(m_setStatus);
m_pMap = MapManager()->QueryMap(m_pData->GetInt(NPCDATA_MAPID));
IF_NOT(m_pMap)
return false; //?? 非本进程组地图
// trans npc exclusive
MapGroup(PID)->QueryIntraMsg()->DelTransNpc(GetInt(NPCDATA_LINKID)); // del this mapgroup first
m_pMap->EnterRoom(QueryMapThing(), WITH_BLOCK);
UpdateHoldFloor(true);
//SendSelfToBlock();
UpdateBroadcastSet();
// set map syn id
if(IsSynFlag())
{
GetMap()->SetSynID(GetSynID(), true); // with all map npc
// CheckFightTime();
// temporary code
OBJID idMoreMap = GetData(SYNFLAGNPC_MOREMAPID);
if(idMoreMap != ID_NONE)
{
CGameMap* pMoreMap = MapManager()->QueryMap(idMoreMap);
if(pMoreMap)
pMoreMap->SetSynID(GetSynID(), true); // with all map npc
}
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CNpc::Create(PROCESS_ID idProcess, IRecordset* pRecordset, bool bDynaNpc)
{
m_idProcess = idProcess;
m_bDynaNpc = bDynaNpc;
ASSERT(!m_pData);
if(bDynaNpc)
{
CDynaNpcData* pData = CDynaNpcData::CreateNew();
if(pData)
m_pData = pData->QueryInterface();
}
else
{
CNpcData* pData = CNpcData::CreateNew();
if(pData)
m_pData = pData->QueryInterface();
}
IF_NOT(m_pData && m_pData->Create(pRecordset))
return false;
CGameMap* pMap = MapManager()->QueryMap(m_pData->GetInt(NPCDATA_MAPID), false); // false: not load dynamic map
if(!pMap)
return false; //?? 非本进程组地图,或者动态地图的NPC
if(bDynaNpc)
m_id = MapManager()->SpawnNewNpcID();
else
m_id = m_pData->GetID(); // fixed to database id
m_nPosX = m_pData->GetInt(NPCDATA_POSX_);
m_nPosY = m_pData->GetInt(NPCDATA_POSY_);
if (this->IsTrunkNpc()
|| this->IsShopNpc()
|| this->IsSceneNpc()
|| this->IsTaskNpc()
|| this->IsBetNpc()
|| this->IsAuctionNpc() )
{
IF_NOT(CreateFuncObj(idProcess))
return false;
}
IF_NOT(CheckSortMutex())
return false;
m_setStatus = CStatusSet::CreateNew(true);
CHECKF(m_setStatus);
m_pMap = pMap;
// 冗错非法NPC坐标
if(!GetMap()->IsValidPoint(GetPosX(), GetPosY()))
{
LOGERROR("NPC数据错[%u],坐标非法[%d,%d]", GetRecordID(), GetPosX(), GetPosY());
m_pMap = NULL;
return false;
}
m_pMap->EnterRoom(QueryMapThing(), WITH_BLOCK);
UpdateHoldFloor(true);
UpdateBroadcastSet();
// set map syn id
if(IsSynFlag())
{
GetMap()->SetSynID(GetSynID(), false); // false: no set npc in map
CheckFightTime();
// temporary code
OBJID idMoreMap = GetData(SYNFLAGNPC_MOREMAPID);
if(idMoreMap != ID_NONE)
{
CGameMap* pMoreMap = MapManager()->QueryMap(idMoreMap);
if(pMoreMap)
pMoreMap->SetSynID(GetSynID(), false); // false: no set npc in map
}
}
if(!IsDynaNpc() && GetMaxLife() > 0)
{
LOGERROR("静态NPC不能设置最大血为非0:[%d]", GetID());
}
return true;
}
/////////////////////////////////////////////////////////////////////
BOOL CNpc:: ChangePos (OBJID idMap, int nPosX, int nPosY)
{
if (!MapManager()->QueryMap(idMap))
return false;
this->SendLeaveFromBlock();
m_pMap->LeaveRoom(QueryMapThing(), WITH_BLOCK);
UpdateHoldFloor(false);
m_pMap = MapManager()->QueryMap(idMap);
m_nPosX = nPosX;
m_nPosY = nPosY;
m_pMap->EnterRoom(QueryMapThing(), WITH_BLOCK);
UpdateHoldFloor(true);
UpdateBroadcastSet();
return true;
}
//////////////////////////////////////////////////////////////////////
bool CNpc::CreateFuncTrunk(PROCESS_ID idProcess)
{
/*if(IsStorageNpc())
{
ASSERT(!m_pStorage);
CNpcStorage* m_pStorage = CNpcStorage::CreateNew();
IF_NOT(m_pStorage && m_pStorage->Create(idProcess, GetID())
return false;
}*/
if(IsTrunkNpc())
{
ASSERT(!m_pTrunk);
m_pTrunk = CNpcTrunk::CreateNew();
IF_NOT(m_pTrunk && m_pTrunk->Create(idProcess, GetRecordID(), GetData(TRUNKNPC_SIZE), ITEMPOSITION_TRUNK))
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CNpc::CreateFuncEudemonBrooder(PROCESS_ID idProcess)
{
if (IsEudemonBrooderNpc())
{
ASSERT(!m_pEudemonBrooder);
m_pEudemonBrooder = CNpcTrunk::CreateNew();
IF_NOT(m_pEudemonBrooder && m_pEudemonBrooder->Create(idProcess, GetRecordID(), GetData(EUDEMON_BROODER_NPC_SIZE), ITEMPOSITION_EUDEMON_BROODER))
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CNpc::CreateFuncEudemonStorage(PROCESS_ID idProcess)
{
if (IsEudemonStorageNpc())
{
ASSERT(!m_pEudemonStorage);
m_pEudemonStorage = CNpcTrunk::CreateNew();
IF_NOT(m_pEudemonStorage && m_pEudemonStorage->Create(idProcess, GetRecordID(), GetData(EUDEMON_STORAGE_NPC_SIZE), ITEMPOSITION_EUDEMON_STORAGE))
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CNpc::CreateFuncObj(PROCESS_ID idProcess)
{
// shop
if(IsShopNpc())
{
ASSERT(!m_pShop);
m_pShop = CNpcShop::CreateNew();
IF_NOT(m_pShop && m_pShop->Create(idProcess, this, GetRecordID()))
return false;
}
if(IsAuctionNpc())
{
ASSERT(!m_pAuction);
/* CAuction* temp = CAuction::CreateNew(idProcess);
CHECKF(temp);
m_pAuction = temp->QueryInterface();*/
m_pAuction = CAuction::CreateNew(idProcess);
IF_NOT(QueryAuction()->Create(idProcess,GetRecordID()))
return false;
// delete temp;
}
if(IsTaskNpc())
{
ASSERT(!m_pTask);
m_pTask = CNpcTask::CreateNew();
IF_NOT(m_pTask && m_pTask->Create(idProcess, this, m_pData))
return false;
}
if(IsSceneNpc())
{
CGameMap* pMap = MapManager()->QueryMap(m_pData->GetInt(NPCDATA_MAPID), false);
if(!pMap)
return false;
ASSERT(!m_pScene);
m_pScene = CNpcScene::CreateNew();
IF_NOT(m_pScene && m_pScene->Create(this, pMap))
return false;
}
if(IsLinkNpc())
{
ASSERT(!m_pLinkMap);
m_pLinkMap = CNpcLink::CreateNew(m_idProcess, this);
IF_NOT(m_pLinkMap)
return false;
}
if(IsBetNpc())
{
ASSERT(!m_pBet);
m_pBet = CNpcBet::CreateNew(m_idProcess, this);
IF_NOT(m_pBet)
return false;
}
if((m_pData->GetInt(NPCDATA_SORT) & NPCSORT_TABLE) != 0)
{
ASSERT(!m_pTable);
m_pTable = CNpcTable::CreateNew();
IF_NOT(m_pTable && m_pTable->Create(idProcess, this, GetRecordID()))
return false;
}
return true; //@
}
int CNpc::GetMountTypeID()
{ return IsShelfNpc() ? QueryTrunk()->QueryPackage()->GetItemType(0) : m_pData->GetInt(STATUARYDATA_HELMET); }
int CNpc::GetArmorTypeID()
{ return IsShelfNpc() ? QueryTrunk()->QueryPackage()->GetItemType(1) : m_pData->GetInt(STATUARYDATA_ARMOR); }
int CNpc::GetWeaponRTypeID()
{ return IsShelfNpc() ? QueryTrunk()->QueryPackage()->GetItemType(2) : m_pData->GetInt(STATUARYDATA_WEAPONR); }
int CNpc::GetWeaponLTypeID()
{ return IsShelfNpc() ? QueryTrunk()->QueryPackage()->GetItemType(3) : m_pData->GetInt(STATUARYDATA_WEAPONL); }
//////////////////////////////////////////////////////////////////////
void CNpc::SendShow(IRole* pRole)
{
if(IsStatuary() || IsShelfNpc())
{
CMsgPlayer msg;
IF_OK(msg.Create(QueryRole()))
pRole->SendMsg(&msg);
}
else if(IsDynaNpc() && GetMaxLife() > 0)
{
CMsgNpcInfoEx msg;
IF_OK(msg.Create(this))
pRole->SendMsg(&msg);
}
else
{
CMsgNpcInfo msg;
IF_OK(msg.Create(this))
pRole->SendMsg(&msg);
}
}
//////////////////////////////////////////////////////////////////////
// application
//////////////////////////////////////////////////////////////////////
bool CNpc::SendSelfToBlock()
{
CHECKF(GetMap());
if(IsStatuary() || IsShelfNpc())
{
CMsgPlayer msg;
IF_OK(msg.Create(QueryRole()))
GetMap()->BroadcastBlockMsg(QueryMapThing(), &msg);
}
else if(IsDynaNpc() && GetMaxLife() > 0)
{
CMsgNpcInfoEx msg;
IF_OK(msg.Create(this))
GetMap()->BroadcastBlockMsg(QueryMapThing(), &msg);
}
else
{
CMsgNpcInfo msg;
IF_OK(msg.Create(this))
GetMap()->BroadcastBlockMsg(QueryMapThing(), &msg);
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CNpc::SendLeaveFromBlock()
{
CHECKF(GetMap());
CMsgNpc msg;
CHECKF(msg.Create(EVENT_LEAVEMAP, GetID()));
GetMap()->BroadcastBlockMsg(QueryMapThing(), &msg);
return true;
}
bool CNpc::ActivateNpc(IRole* pRole, int nAction)
{
CUser* pUser = NULL;
if(IsTaskNpc() && IsAlive() && pRole->QueryObj(OBJ_USER, IPP_OF(pUser)))
return QueryTask()->ActivateTask(pUser);
return false;
}
//////////////////////////////////////////////////////////////////////
OBJID CNpc::GetMapID()
{
CHECKF(m_pMap);
return m_pMap->GetID();
}
//////////////////////////////////////////////////////////////////////
void CNpc::OnTimer(time_t tCurr)
{
if(IsAuctionNpc())
QueryAuction()->OnTimer(tCurr);
// auto recruit life
//---jinggy---进行帮派每占领一周,军团声望增加50万的处理---begin
if(this->IsSynWarLetter()) //判断是否是接收战书的NPC
{
if(!m_tSynWarLetter.IsActive())
m_tSynWarLetter.Startup(SYNWARLETTERNPC_CHECKINTERVAL);
if(m_tSynWarLetter.ToNextTime())
{
int nOccupyTime = this->GetData(SYNWARLETTER_OCCUPYTIME);
time_t tTmp = nOccupyTime;
tm * pTm = localtime(&tTmp);
if(!pTm)
return;
tm tmOccupy;
memset(&tmOccupy, 0, sizeof(tm));
tmOccupy =*pTm;
tmOccupy.tm_mday += 7;
time_t tAfterOccupy7 = mktime(&tmOccupy);
time_t tCur;
tCur = time(NULL);
if(tCur>=tAfterOccupy7)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -