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

📄 ainpc.cpp

📁 网络游戏魔域的服务端与客户端完整源代码 包括详细的说明文档与开发日志
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		{
			fprintf(fp, "monster: %u drop item: %u\n", 
					this->GetID(), idItemType);
		}
		fclose(fp);
#endif

	return false;
}

////////////////////////////////////////////////////////////////////////////////////
bool CMonster::DropEquipment (DWORD dwValue, OBJID idOwner, DWORD dwQuality/*=0*/)
{
	// drop money if value less than 100
	if (dwValue < 100)
		return this->DropMoney(dwValue, idOwner);
		
	// create equipment
	ItemInfoStruct info;
	if (CItem::CreateItemInfo(info, dwValue, m_pType, dwQuality))
	{
#ifdef _DEBUG
		// temp code
		FILE* fp = fopen("equipment.ini", "a+");
		if (fp)
		{
			fprintf(fp, "monster:%03u type:%06u amount:%05u amount_limit:%05u Gem1:%03u Gem2:%03u, Value:%06u\n", 
					this->GetID(), info.idType, info.nAmount, info.nAmountLimit, info.nGem1, info.nGem2, dwValue);
		}
		fclose(fp);
#endif

		// drop item
		POINT	pos;
		pos.x	= GetPosX();
		pos.y	= GetPosY();
		if(GetMap()->FindDropItemCell(MONSTERDROPITEM_RANGE, &pos))
		{
			CMapItem* pMapItem = CMapItem::CreateNew();
			if(pMapItem)
			{
				info.id = ID_NONE;
				if(pMapItem->Create(MapManager()->SpawnMapItemID(), GetMap(), pos, &info, idOwner))
				{
					MapManager()->QueryMapItemSet()->AddObj(pMapItem);
					return true;
				}
				else
				{
					pMapItem->ReleaseByOwner();
					return false;
				}
			}
		}

		return false;
	}

	return this->DropMoney(dwValue, idOwner);
}

////////////////////////////////////////////////////////////////////////////////////
bool CMonster::DropMedicine(OBJID idOwner)
{
	//rem by zlong 2003-11-15
	//修改了monstertype表以后已经没有drop_hp和drop_mp两个字段了

/*
	int nAmount = 0;
	int nRate = ::RandGet(100);
	if (nRate < 2)
		nAmount = 8;
	else if (nRate < 3)
		nAmount = 6;
	else if (nRate < 5)
		nAmount = 5;
	else if (nRate < 8)
		nAmount = 4;
	else if (nRate < 10)
		nAmount = 3;
	else if (nRate < 25)
		nAmount = 2;
	else
		nAmount = 1;


	for (int i=0; i<nAmount; i++)
	{
		DWORD dwType = 0;
		if (1 == ::RandGet(2))
			dwType = m_pType->GetInt(NPCTYPEDATA_DROP_HP);
		else
			dwType = m_pType->GetInt(NPCTYPEDATA_DROP_MP);

		this->DropItem(dwType, idOwner);

#ifdef _DEBUG
		// temp code
		FILE* fp = fopen("medicine.ini", "a+");
		if (fp)
		{
			fprintf(fp, "monster:%03u medicine:%06u\n", 
					this->GetID(), dwType);
		}
		fclose(fp);
#endif
	}
*/
	return true;
}

////////////////////////////////////////////////////////////////////////////////////
bool CMonster::ProcessAction(CUser* pUser, OBJID idAction, LPCTSTR pszAccept)
{
	if (idAction == ID_NONE)
		return false;

	try {
		// process action...
		const _MAX_ACTIONPRC	=32;
		DWORD dwActionCount	=0;
		while (idAction != ID_NONE)
		{
			CActionData* pAction	= ActionSet()->GetObj(idAction);
			if (!pAction)
			{
				::LogSave("Error: game action %u not found.", idAction);
				break;
			}

			// process action now!
			idAction = pAction->GetInt(ACTIONDATA_IDNEXTFAIL);

			int nActionType = pAction->GetInt(ACTIONDATA_TYPE);
			switch(nActionType)
			{
			case ACTION_RAND:
				{
					// 检测随机率。"data1 data2"。"10 100"表示有1/10的机会是true。
					DWORD dwChance = 0, dwMax = 0;
					if (2 == sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%u %u", &dwChance, &dwMax))
					{
						if (::RandGet(dwMax) < dwChance)
							idAction	= pAction->GetInt(ACTIONDATA_IDNEXT);
					}
					else
						LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
				}
				break;

			case ACTION_RANDACTION:
				{
					// 检测随机率。"action0 .... action7"
					OBJID idRndAction[8];
					if (8 == sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%u %u %u %u %u %u %u %u", 
						&idRndAction[0], &idRndAction[1], &idRndAction[2], &idRndAction[3],
						&idRndAction[4], &idRndAction[5], &idRndAction[6], &idRndAction[7]))
					{
						idAction	= idRndAction[::RandGet(8)];
					}
					else
						LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
				}
				break;

			case ACTION_MST_DROPITEM:
				{
					// monster被杀死后掉物品或者钱, param "dropitem itemtype"或者"dropmoney money [LowPercent]"
					char szCmd[MAX_PARAMSIZE] = "";					
					if (1 != sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%s", szCmd))
					{
						LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
						break;
					}

					if (0 == stricmp(szCmd, "dropitem"))
					{
						DWORD dwData = 0;
						if (2 == sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%s %u", szCmd, &dwData))
						{
							if (0 == stricmp(szCmd, "dropitem"))
							{
								OBJID idUser = ID_NONE;
								if (pUser)
									idUser = pUser->GetID();

								if (this->DropItem(dwData, idUser))
									idAction = pAction->GetInt(ACTIONDATA_IDNEXT);
							}
						}
						else
						{
							LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
							break;
						}
					}
					else if (0 == stricmp(szCmd, "dropmoney"))
					{
						DWORD dwData=0, dwLowPercent=0;
						int rval = sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%s %u %u", szCmd, &dwData, &dwLowPercent);
						if (rval == 2)
							dwLowPercent = 100;
						else if (rval == 3)
							dwLowPercent %= 100;
						else
						{
							LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
							break;
						}
						
						DWORD dwMoneyDrop = dwData*(dwLowPercent+::RandGet(100-dwLowPercent))/100;
						if (dwMoneyDrop <= 0)
							return true;

						OBJID idUser = ID_NONE;
						if (pUser)
							idUser = pUser->GetID();

						if (this->DropMoney(dwMoneyDrop, idUser))
							idAction	= pAction->GetInt(ACTIONDATA_IDNEXT);
					}
				}
				break;

			default:
				break;
			}

			if (dwActionCount++ >= _MAX_ACTIONPRC)
			{
				::LogSave("Error: too many game action, last action:%u.", idAction);
				break;
			}
		} // while
	}
	catch(...)
	{
		ASSERT(!"catch");
		::LogSave("Error: exception catched in CUser::ProcessAction(%u)", idAction);
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMonster::IsAtkable(IRole* pTarget, bool bSendHint)
{
	if (!pTarget)
		return false;

	if (!this->IsAlive())
	{
		if (bSendHint)
			this->SendSysMsg(STR_DIE_FORGIVE);
		return false;
	}

	if (!pTarget->IsAlive())
	{
		//if (bSendHint)
		//	this->SendSysMsg(STR_DIE_STOP_ATTACK);
		return false;
	}

	/*
	if (pTarget->IsGM())
	{
		if (bSendHint)
			this->SendSysMsg(STR_ATTACK_POLICE);
		return false;
	}
	*/

	if(GetID() == pTarget->GetID())
		return false;

	if(!pTarget->IsBeAtkable())
		return false;

	// 召唤兽不能攻击自己的主人
	if (this->QueryOwnerUser() && this->QueryOwnerUser()->GetID() == pTarget->GetID())
		return false;

	// map check
	if (!(this->GetMap() && pTarget->GetMap() && this->GetMap() == pTarget->GetMap()))
		return false;

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMonster::IsBeAtkable()
{
	return !(QueryStatus(STATUS_LOCK));
}

//////////////////////////////////////////////////////////////////////
bool CMonster::EnterMapGroup()
{
	CMapPtr pMap = this->GetMap();
	CHECKF(pMap);

	UpdateBroadcastSet();
	
	MapGroup(PID)->QueryIntraMsg()->SetNpcProcessID(GetID(), true);			// 同步SOCKET_KERNEL

	pMap->EnterRoom(this->QueryMapThing(), WITH_BLOCK);
//	if(IsSendBlockInfo())
//		pMap->SendBlockInfo((IRole*)this);
//	SendSelfToBlock();

	/*{
		CMsgAction	msg;
		IF_OK(msg.Create(GetID(), GetPosX(), GetPosY(), GetDir(), actionEmotion, _ACTION_EXCITEMENT))
			this->BroadcastRoomMsg(&msg);
	}*/

//	if(IsMapRoar())
	{
		CMsgAction	msg;
		IF_OK(msg.Create(GetID(), GetPosX(), GetPosY(), GetDir(), actionSoundEffect, GetType()))
			_UserManager(PID)->BroadcastMapMsg(pMap->GetID(), &msg);
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMonster::LeaveMapGroup()
{
	CMapPtr pMap = this->GetMap();
	CHECKF(pMap);


	MapGroup(PID)->QueryIntraMsg()->SetNpcProcessID(GetID(), false);			// 同步SOCKET_KERNEL

	// BeKill的时候调用了DecRole,因此这里需要判断,以免LeaveRoom的时候多减一次角色数
	bool bWithBlock = !m_bDecRole;
	
	SendLeaveFromBlock();	// NPC服务器需要这个通知来删除怪物
	ClrBroadcastSet();
	
	pMap->LeaveRoom(this->QueryMapThing(), bWithBlock);
	m_bDecRole	= true;
	return true;
}

//////////////////////////////////////////////////////////////////////
LPCTSTR	CMonster::GetName()
{
	if (this->IsEudemon() && m_pEudemonItem)
		return m_pEudemonItem->GetStr(ITEMDATA_NAME);

	return m_pType->GetStr(NPCTYPEDATA_NAME);
}

//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetLife()
{
	int nMaxLife = this->GetMaxLife();
	if (this->IsEudemon() && m_pEudemonItem)
	{
		m_nCurrLife = m_pEudemonItem->GetInt(ITEMDATA_EUDEMON_LIFE);
		if (m_nCurrLife > nMaxLife)
		{
			m_nCurrLife = nMaxLife;
			m_pEudemonItem->SetInt(ITEMDATA_EUDEMON_LIFE, nMaxLife, true);
		}
		return m_nCurrLife;
	}
	if (m_nCurrLife > nMaxLife)
		m_nCurrLife = nMaxLife;

	return m_nCurrLife;
}

//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMaxLife()
{
	int nLife = m_pType->GetInt(NPCTYPEDATA_LIFE);

	if (this->IsEudemon() && m_pEudemonItem)
	{
		int nMaxLife = __max(1, m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_LIFE) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_LIFE)*100) / 10000);
		nLife = nMaxLife;
	}

	IStatus* pStatus = QueryStatus(STATUS_MAXLIFE);
	if (pStatus)
	{
		nLife	= ::CutTrail(0, AdjustData(nLife, pStatus->GetPower(), 100));
	}
	return nLife;
}

//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMinAtk()
{
	DWORD dwAtk	= m_pType->GetInt(NPCTYPEDATA_ATTACKMIN);

	// 算幻兽的等级加成
	if (this->IsEudemon() && m_pEudemonItem)
	{
		int nMinAtk = m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_ATTACK_MIN_) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_ATTACK_MIN)*100) / 10000;
		dwAtk	= nMinAtk;
	}
	// 算装备的coding here...

	return dwAtk;
}

//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMaxAtk()
{
	DWORD dwAtk	= m_pType->GetInt(NPCTYPEDATA_ATTACKMAX);

	// 算装备的coding here...

	dwAtk	= dwAtk;

	// 算幻兽的等级加成
	if (this->IsEudemon() && m_pEudemonItem)
	{
		int nMaxAtk	= m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_ATTACK_MAX_) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_ATTACK_MAX)*100) / 10000;
		dwAtk	= nMaxAtk;
	}

	return dwAtk;
}

//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMgcMinAtk()
{
	DWORD dwAtk	= m_pType->GetInt(NPCTYPEDATA_ATTACKMIN);

	// 算装备的coding here...

	dwAtk	= dwAtk;

	// 算幻兽的等级加成
	if (this->IsEudemon() && m_pEudemonItem)
	{
		int nMinMgcAtk	= m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_MAGICATK_MIN_) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_MGCATK_MIN)*100) / 10000;
		dwAtk	= nMinMgcAtk;
	}

	return dwAtk;
}

//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMgcMaxAtk()
{
	DWORD dwAtk	= m_pType->GetInt(NPCTYPEDATA_ATTACKMAX);

	// 算装备的coding here...

	dwAtk	= dwAtk;

	// 算幻兽的等级加成
	if (this->IsEudemon() && m_pEudemonItem)
	{
		int nMaxMgcAtk	= m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_MAGICATK_MAX_) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_MGCATK_MAX)*100) / 10000;
		dwAtk	= nMaxMgcAtk;
	}

	return dwAtk;
}

//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetDdg()
{
	DWORD dwDodge	= this->GetDodge();

	// 算幻兽的加成
	if (this->IsEudemon() && m_pEudemonItem)
	{
		int nDodge	= m_pEudemonItem->GetInt(ITEMDATA_DODGE) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) / 10000 + m_pEudemonItem->GetEudemonLevel() * m_pEudemonItem->GetAddition(ITEMADDITIONDATA_DODGE)/100;
		dwDodge	= nDodge;
	}

//	IStatus* pStatus = QueryStatus(STATUS_DODGE);
//	if(pStatus)
//		dwDodge = AdjustData(dwDodge, pStatus->GetPower());

	// 算装备的coding here...
	
//	dwDodge	= dwDodge;

	return __max(0, dwDodge);
}

//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetDef()
{
	DWORD dwDef	= 0;

	// 算装备的coding here...
	
	dwDef	= dwDef + this->GetDefence();

⌨️ 快捷键说明

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