⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamemap.cpp

📁 网络游戏魔域的服务端与客户端完整源代码 包括详细的说明文档与开发日志
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// GameMap.cpp: implementation of the CGameMap class.
//
//////////////////////////////////////////////////////////////////////

#pragma warning(disable: 4786)

#include "GameObj.h"
#include "GameMap.h"
#include <algorithm>
#include "AllMsg.h"
#include "GameData.h"
#include "I_MapData.h"
#include "MapGroup.h"
#include "BaseFunc.h"
#include "WeatherRegion.h"
#include "RoleManager.h"
#include "Array.h"

//////////////////////////////////////////////////////////////////////
#define		MAPDATA_VERSION		((LPCTSTR)true)					// DDVersion
const DWORD	DEFAULT_LIGHTRGB		= 0xFFFFFFFF;

//////////////////////////////////////////////////////////////////////
MYHEAP_IMPLEMENTATION(CGameMap,s_heap)
char	szMapTable[]		= _TBL_MAP;
char	szRegionTable[]		= _TBL_REGION;
char	szPortalTable[]		= _TBL_PORTAL;
char	szPasswayTable[]	= _TBL_PASSWAY;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGameMap::CGameMap()
{
	SetObjType(OBJ_MAP);

	m_idProcess = PROCESS_NONE;

	m_pData		= NULL;
	m_pMapData	= NULL;
	m_setRegion	= NULL;
	m_setWeather	= NULL;
	m_dwLightRGB	= DEFAULT_LIGHTRGB;
	m_nStatus	= STATUS_NONE;
}

//////////////////////////////////////////////////////////////////////
CGameMap::~CGameMap()
{
	if(m_pData)
	{
		if(IsDynaMap())
			m_pData->Update();
		m_pData->Release();
	}
	if(m_pMapData)
		m_pMapData->Release();
	if(m_setRegion)
		m_setRegion->Release();
	if(m_setWeather)
		m_setWeather->Release();
}

//////////////////////////////////////////////////////////////////////
bool CGameMap::Create(PROCESS_ID idProcess, IRecordset* pRes)
{
	m_idProcess = idProcess;

	m_pData	= CGameMapData::CreateNew();
	if(!m_pData || !m_pData->Create(pRes))
		return false;
//*
	LOGMSG("加载地图文件[%d]...", m_pData->GetInt(GAMEMAPDATA_MAPDOC));
	m_pMapData	= IMapData::CreateNew(m_pData->GetInt(GAMEMAPDATA_MAPDOC), MAPDATA_VERSION);
	if(!m_pMapData)
	{
		LOGERROR("地图文件[%d]加载失败!", m_pData->GetInt(GAMEMAPDATA_MAPDOC));
		return false;
	}

	// 装载地图
	m_setBlock.resize(GetWidthOfBlock());
	for(int i = 0; i < m_setBlock.size(); i++)
	{
		m_setBlock[i].resize(GetHeightOfBlock());
		for(int j = 0; j < m_setBlock[i].size(); j++)
			m_setBlock[i][j].Create();
	}
//*/
	m_setRegion = CRegionSet::CreateNew(true);
	CHECKF(m_setRegion);
	SQLBUF	szSQL;
	sprintf(szSQL, "SELECT * FROM %s WHERE mapid=%u", szRegionTable, m_pData->GetID());
	if(!m_setRegion->Create(szSQL, Database()))
		return false;

	m_setWeather	= CWeatherSet::CreateNew(true);
	CHECKF(m_setWeather);
	for( i = 0; i < m_setRegion->GetAmount(); i++)
	{
		CRegionData*	pData = m_setRegion->GetObjByIndex(i);
		if(pData && pData->GetInt(REGIONDATA_TYPE) == REGION_WEATHER)
		{
			CWeatherRegion* pWeather = CWeatherRegion::CreateNew();
			CHECKF(pWeather);
			IF_OK(pWeather->Create(pData, idProcess))
				m_setWeather->AddObj(pWeather);
			else
				pWeather->ReleaseByOwner();
		}
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
void CGameMap::OnTimer(DWORD tCurr)
{
	for(int i = 0; i < m_setWeather->GetAmount(); i++)
	{
		CWeatherRegion* pWeather = m_setWeather->GetObjByIndex(i);
		if(pWeather)
			pWeather->QueryWeather()->OnTimer();
	}
}

//////////////////////////////////////////////////////////////////////
bool CGameMap::QueryObjInPos(int nPosX, int nPosY, OBJID idObjType, void** ppObj)
{
	*ppObj = NULL;
	CHECKF(idObjType != ID_NONE);

	IThingSet* pSet = QueryBlock(nPosX, nPosY).QuerySet();
	for(int i = 0; i < pSet->GetAmount(); i++)
	{
		IMapThing* pTarget = pSet->GetObjByIndex(i);
		void* pTemp;
		if(pTarget && pTarget->QueryObj(idObjType, &pTemp) && pTarget->GetPosX() == nPosX && pTarget->GetPosY() == nPosY)
		{
			*ppObj = pTemp;
			return true;
		}
	}
	return false;
}

//////////////////////////////////////////////////////////////////////
bool CGameMap::QueryObj(int nCenterX, int nCenterY, OBJID idObjType, OBJID idObj, void** ppObj)
{
	*ppObj = NULL;
	CHECKF(idObjType != ID_NONE);

	void* pTemp = NULL;
	int x,y,z;
	FOR_9_BLOCKTHINGS(this, nCenterX, nCenterY)
	{
		IMapThing* pTarget = QueryThingByIndex(x,y,z);
		if(pTarget && pTarget->QueryObj(idObjType, &pTemp))
		{
			if (idObj != ID_NONE)
			{
				if (pTarget->GetID() == idObj)
				{
					*ppObj = pTemp;
					return true;
				}
			}
			else
			{
				*ppObj = pTemp;
				return true;
			}
		}
	}
	return false;
}

//////////////////////////////////////////////////////////////////////
IRole* CGameMap::QueryRole(int nCenterX, int nCenterY, OBJID idObj)
{
	//CHECKF(idObj != ID_NONE);

	IRole*	pRole	= NULL;
	int x,y,z;
	FOR_9_BLOCKTHINGS(this, nCenterX, nCenterY)
	{
		IMapThing* pTarget = QueryThingByIndex(x,y,z);
		if (pTarget && pTarget->QueryRole(IPP_OF(pRole)))
		{
			if (idObj == ID_NONE
					&& pTarget->GetPosX() == nCenterX
					&& pTarget->GetPosY() == nCenterY)
			{
				return pRole;
			}

			if (pTarget->GetID() == idObj)
				return pRole;
		}
	}
	return NULL;
}

//////////////////////////////////////////////////////////////////////
IRole* CGameMap::QueryRoleByPos(int nPosX, int nPosY)
{
	if(!IsValidPoint(nPosX, nPosY))
		return NULL;

	IRole*	pRole	= NULL;
	IThingSet* pSet = QueryBlock(nPosX, nPosY).QuerySet();
	for(int i = 0; i < pSet->GetAmount(); i++)
	{
		IMapThing* pTarget = pSet->GetObjByIndex(i);
		if (pTarget && pTarget->QueryRole(IPP_OF(pRole))
					&& pTarget->GetPosX() == nPosX && pTarget->GetPosY() == nPosY)
		{
			return pRole;
		}
	}
	return NULL;
}

//////////////////////////////////////////////////////////////////////
void CGameMap::SendBlockInfo(IRole* pRole)
{
	CHECK(pRole);

	// 优化
	void* pTemp = NULL;
	if(pRole->QueryObj(OBJ_USER, IPP_OF(pTemp)))
	{
		int x,y;
		FOR_9_BLOCKS(this, pRole->GetPosX(), pRole->GetPosY())
		{
			IThingSet* pSet = BlockByIndex(x,y).QuerySet();
			for(int i = 0; i < pSet->GetAmount(); i++)
			{
				IMapThing* pMapThing = pSet->GetObjByIndex(i);
				if(pMapThing && !(pMapThing->GetObjType() == OBJ_USER && pMapThing->GetID() == pRole->GetID()) )
				{
					if(!( IsNewbieMap() && pMapThing->GetObjType() == OBJ_USER ))
						pMapThing->SendShow(pRole);
				}
			}
		}
	}
	else // if(pRole->QueryObj(OBJ_MONSTER, IPP_OF(pTemp)))
	{
		CUser* pUser = NULL;
		int x,y;
		FOR_9_BLOCKS(this, pRole->GetPosX(), pRole->GetPosY())
		{
			IThingSet* pSet = BlockByIndex(x,y).QuerySet();
			for(int i = 0; i < pSet->GetAmount(); i++)
			{
				IMapThing* pMapThing = pSet->GetObjByIndex(i);
				if(pMapThing && pMapThing->GetObjType() == OBJ_USER)		//@ 只发USER的信息给NPC服务器
				{
					pMapThing->SendShow(pRole);
				}
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////
void CGameMap::BroadcastBlockMsg(IMapThing* pThing, CNetMsg* pMsg, bool bSendSelf /*= false*/)
{
	ASSERT(pMsg);

	//? 这个函数的逻辑有点乱:(
	void*	pObj	= NULL;
	IRole*	pRole	= NULL;
	CMonster* pMonster = NULL;
//@不发非玩家消息到NPC服务器	bool	bSendToNpc = (!pThing->QueryObj(OBJ_MONSTER, IPP_OF(pObj)) || bSendSelf);
	bool	bSendToNpc = (pThing->QueryObj(OBJ_USER, IPP_OF(pObj)) 
							|| (pThing->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)) && (pMonster->IsCallPet() || pMonster->IsEudemon()))
							|| bSendSelf);
	// newbie map
	if (IsNewbieMap() && bSendSelf)
	{
		if(pThing->QueryRole(IPP_OF(pRole)))
			pRole->SendMsg(pMsg);
		return ;
	}

	int x,y,z;
	FOR_9_BLOCKTHINGS(this, pThing->GetPosX(), pThing->GetPosY())
	{
		DEBUG_TRY	// VVVVVVVVVVVVVVVVVVVV
		IMapThing* pTarget = QueryThingByIndex(x,y,z);
		if(pTarget && pTarget->QueryRole(IPP_OF(pRole)) && pRole->GetDistance(pThing) <= CELLS_PER_VIEW)
		{
			if(bSendSelf || !(pTarget->GetObjType() == pThing->GetObjType() && pTarget->GetID() == pThing->GetID()))
			{
				// monster
				if (pTarget->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)) && bSendToNpc)
				{
					if (pMonster->IsCallPet() || pMonster->IsEudemon())
					{
					}
					else
					{
						pRole->SendMsg(pMsg);
						bSendToNpc = false;
					}
				}
				
				// user
				CUser* pUser;
				if (pTarget->QueryObj(OBJ_USER, IPP_OF(pUser)))
				{
					if(!pUser->IsAgent())
					{
						// player
						pRole->SendMsg(pMsg);
					}
					else if(bSendToNpc)
					{
						// agent
						pRole->SendMsg(pMsg);
						bSendToNpc = false;
					}
				}				
			}
		}
		DEBUG_CATCH("BroadcastBlockMsg")		// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	}
}

//////////////////////////////////////////////////////////////////////
void CGameMap::BroadcastBlockMsg(int nPosX, int nPosY, CNetMsg* pMsg)
{
	ASSERT(pMsg);

	bool bSendNpcAlready = false;
	void*	pObj	= NULL;
	IRole*	pRole	= NULL;

	int x,y,z;
	FOR_9_BLOCKTHINGS(this, nPosX, nPosY)
	{
		DEBUG_TRY	// VVVVVVVVVVVVVVVVVVVV
		IMapThing* pTarget = QueryThingByIndex(x,y,z);
		if(pTarget && pTarget->QueryRole(IPP_OF(pRole)) && pRole->GetDistance(nPosX, nPosY) <= CELLS_PER_VIEW)
		{
			// monster
			CMonster* pMonster = NULL;			
			if (pTarget->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)) && !bSendNpcAlready)
			{
				if (pMonster->IsCallPet() || pMonster->IsEudemon())
				{
				}
				else
				{
					pRole->SendMsg(pMsg);
					bSendNpcAlready = true;
				}
			}
			
			// user
			CUser* pUser;
			if (pTarget->QueryObj(OBJ_USER, IPP_OF(pUser)))
			{
				if(!pUser->IsAgent())
				{
					// player
					pRole->SendMsg(pMsg);
				}
				else if(!bSendNpcAlready)
				{
					// agent
					pRole->SendMsg(pMsg);
					bSendNpcAlready = true;
				}
			}
		}
		DEBUG_CATCH("BroadcastBlockMsg")		// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	}
}

//////////////////////////////////////////////////////////////////////
// role
//////////////////////////////////////////////////////////////////////
void CGameMap::EnterRoom(IMapThing* pThing, BOOL bWithBlock/*=false*/)
{
	CHECK(pThing);

	QueryBlock(pThing->GetPosX(), pThing->GetPosY()).QuerySet()->AddObj(pThing);
	if(bWithBlock)
		m_pMapData->IncRole(pThing->GetPosX(), pThing->GetPosY());
}

//////////////////////////////////////////////////////////////////////
void CGameMap::LeaveRoom(IMapThing* pThing, BOOL bWithBlock/*=false*/)
{
	CHECK(pThing);

	QueryBlock(pThing->GetPosX(), pThing->GetPosY()).QuerySet()->DelObj(pThing->GetID(), pThing->GetObjType());
	if(bWithBlock)
		m_pMapData->DecRole(pThing->GetPosX(), pThing->GetPosY());
}

//////////////////////////////////////////////////////////////////////
void CGameMap::MoveTo(IRole* pRole, int nNewPosX, int nNewPosY, BOOL bLeaveBlock/*=false*/, BOOL bEnterBlock/*=false*/)		// 移动到相邻的BLOCK
{
	CHECK(pRole);

	if(bLeaveBlock)
		m_pMapData->DecRole(pRole->GetPosX(), pRole->GetPosY());
	if(bEnterBlock)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -