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

📄 ainpc.cpp

📁 网络游戏魔域的服务端与客户端完整源代码 包括详细的说明文档与开发日志
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	{
		if ((IsCallPet() || IsEudemon()) && m_pOwner)
			m_pOwner->SendMsg(pMsg);
		else
			MapGroup(PID)->QueryIntraMsg()->SendNpcMsg(ID_NONE, pMsg);
	}
}

//////////////////////////////////////////////////////////////////////
void CMonster::BroadcastMapMsg(LPCTSTR szMsg, bool bSendSelf /*= false*/)		
{
	CMsgTalk	msg;
	if(msg.Create(SYSTEM_NAME, ALLUSERS_NAME, szMsg, NULL, 0xff0000, _TXTATR_SYSTEM))
		this->BroadcastMapMsg(&msg, bSendSelf);
}

//////////////////////////////////////////////////////////////////////
bool CMonster::SendSelfToBlock()
{
	// brocast my info
	CMsgPlayer msg;
	if (msg.Create((IRole*)this))
		this->BroadcastRoomMsg(&msg);

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMonster::SendLeaveFromBlock()
{
	if(!m_bLeaveMap)
	{
		m_bLeaveMap = true;

		CMsgAction	msg;
		if(msg.Create(GetID(), 0, 0, 0, actionLeaveMap))
			this->BroadcastRoomMsg(&msg, INCLUDE_SELF);

		if (this->IsEudemon() && m_pOwner)
			m_pOwner->SendMsg(&msg);
	}

	return true;
}

/////////////////////////////////////////////////////////////////////////////
// role
/////////////////////////////////////////////////////////////////////////////
void CMonster::SendShow(IRole* pRole)
{
	CHECK(pRole);

	CMsgPlayer	msg;
	if(msg.Create((IRole*)this))
		pRole->SendMsg(&msg);
}

//////////////////////////////////////////////////////////////////////
bool CMonster::SendSysMsg(const char* fmt, ...)
{ 
	MSGBUF	szMsg;
    vsprintf( szMsg, fmt, (char*) ((&fmt)+1) );

	CMsgTalk msg;
	if (msg.Create(SYSTEM_NAME, GetName(), szMsg, NULL, 0xff0000, _TXTATR_SYSTEM))
		return this->SendMsg(&msg);

	return false;
}

//////////////////////////////////////////////////////////////////////
// modify attrib
//////////////////////////////////////////////////////////////////////
bool CMonster::AddAttrib(int idxAttr, __int64 i64Data, int nSynchro)
{
	CMsgUserAttrib	msg;
	if(!msg.Create(GetID(), _USERATTRIB_NONE, _USERATTRIB_NONE))			// _USERATTRIB_NONE : 不添加
		return false;

	if(i64Data)
	{
		switch(idxAttr)
		{
		case	_USERATTRIB_LIFE:
			{
				if (this->IsEudemon())
				{
					IF_OK (m_pEudemonItem)
					{
						int nCurrLife = ::CutTrail(0, m_pEudemonItem->GetInt(ITEMDATA_EUDEMON_LIFE)+(int)i64Data);
						int nMaxLife = GetMaxLife();
						nCurrLife = ::CutOverflow(nCurrLife, nMaxLife);
						m_pEudemonItem->SetInt(ITEMDATA_EUDEMON_LIFE, nCurrLife);

						CMsgItemAttrib	msgItemAttrib;
						if (msgItemAttrib.Create(m_pEudemonItem->GetID(), _ITEMATTRIB_EUDEMON_LIFE, m_pEudemonItem->GetInt(ITEMDATA_EUDEMON_LIFE)))
							m_pOwner->SendMsg(&msgItemAttrib);
					}
				}
				else
				{
					if ((int)this->GetLife() + i64Data <= 0)
					{
//						this->SetStatus(STATUS_DIE);
						m_nCurrLife	= 0;
					}
					else
						m_nCurrLife	= this->GetLife() + i64Data;
				}
				// 血超过70%的时候解除狂暴状态
				if (GetLife()*100/GetMaxLife() > MAX_FRENZY_LIFE_PERCENT)
				{
					CRole::DetachStatus(this->QueryRole(), STATUS_FRENZY);
				}

				IF_NOT (msg.Append(_USERATTRIB_LIFE, GetLife()))
					return false;
			}
			break;
		case	_USERATTRIB_POTENTIAL:
			{
				if (this->IsEudemon())
				{
					m_nPotential = __max(0, __min(m_nPotential + (int)i64Data, MAX_EUDEMON_POTENTIAL));
					IF_NOT (msg.Append(_USERATTRIB_POTENTIAL, m_nPotential))
						return false;
				}
			}
			break;
		case	_USERATTRIB_MANA:
			{
//				m_nCurrMana	= (__max(GetMana() + i64Data, 0));
//				IF_NOT (msg.Append(_USERATTRIB_MANA, GetMana()))
					return false;
			}
			break;
		case	_USERATTRIB_EXP:
			{
//				IF_NOT (msg.Append(_USERATTRIB_EXP, GetExp()))
					return false;
			}
			break;
		case	_USERATTRIB_MONEY:
			{
//				IF_NOT (msg.Append(_USERATTRIB_MONEY, GetMoney()))
					return false;
			}
			break;
		default:
			return false;
		}
	}

	if(nSynchro != SYNCHRO_FALSE)
	{
		switch(nSynchro)
		{
		case SYNCHRO_TRUE:
			this->SendMsg(&msg);
			break;

		case SYNCHRO_BROADCAST:
			this->BroadcastRoomMsg(&msg, INCLUDE_SELF);
			break;

		default:
			break;
		}
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
void CMonster::ProcessAfterMove()
{
	IThingSet* pSet = GetMap()->QueryBlock(GetPosX(), GetPosY()).QuerySet();
	for(int i = 0; i < pSet->GetAmount(); i++)
	{
		IMapThing* pTarget = pSet->GetObjByIndex(i);
		CMapTrap* pTrap;
		if(pTarget && pTarget->QueryObj(OBJ_TRAP, IPP_OF(pTrap))
				&& pTrap->IsTrapSort() && pTarget->GetPosX() == GetPosX() && pTarget->GetPosY() == GetPosY())
		{
			pTrap->TrapAttack(QueryRole());
		}
	}
}

//////////////////////////////////////////////////////////////////////
void CMonster::ProcessOnMove(int nMoveMode)
{
	SetPose(_ACTION_STANDBY);
	// stop fight
	if(nMoveMode != MOVEMODE_JUMPMAGICATTCK && nMoveMode != MOVEMODE_COLLIDE && nMoveMode != MOVEMODE_SYNCHRO)
		ClrAttackTarget();

	m_tFootPrint = ::TimeGet();
	m_posFootPrint.x = this->GetPosX();
	m_posFootPrint.y = this->GetPosY();
}

//////////////////////////////////////////////////////////////////////
void CMonster::GetFootPrint	(int& nPosX, int& nPosY)
{
	if (::TimeGet()-m_tFootPrint >= TIME_FOOTPRINT)
	{	// time out
		nPosX = this->GetPosX();
		nPosY = this->GetPosY();
	}
	else
	{
		nPosX = m_posFootPrint.x;
		nPosY = m_posFootPrint.y;
	}
}

//////////////////////////////////////////////////////////////////////
// interactive
//////////////////////////////////////////////////////////////////////
bool CMonster::Freeze(int nPower)								// return false: 解穴不成功
{
	if(IsAlive())
	{
		if(nPower > 0)
		{
			return false;								// 不显示被点状态
		}
		else
		{
			return true;
		}
	}

	return false;
}

//////////////////////////////////////////////////////////////////////
// fight
//////////////////////////////////////////////////////////////////////
bool CMonster::SetAttackTarget(IRole* pTarget /*= NULL*/)
{
	if(pTarget == NULL)
	{
		m_pBattleSystem->ResetBattle();
		return true;
	}

	if(pTarget->QueryOwnerUser() && GetMap()->IsInRegionType(REGION_PK_PROTECTED, GetPosX(), GetPosY()))
		return false;
	
	if(this->GetDistance(pTarget->QueryMapThing()) > GetAttackRange(pTarget->GetSizeAdd()))
		return false;

	m_pBattleSystem->CreateBattle(pTarget->GetID());
	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMonster::AutoSkillAttack(IRole* pTarget)
{
	CHECKF(pTarget);

	if (m_pMagic && m_pMagic->AutoAttackTarget(pTarget))
		return true;

	if(!IsMagicAtk())
		return false;

	CHECKF(m_pMagicType);
	switch(m_pMagicType->GetInt(MAGICTYPEDATA_SORT))
	{
	case	MAGICSORT_RECRUIT:
		{
			if(m_pOwner && m_tMagic.ToNextTime(m_pMagicType->GetInt(MAGICTYPEDATA_STEP)))
			{
				if(m_pOwner->GetLife() < m_pOwner->GetMaxLife())
				{
					int nAdd = m_pMagicType->GetInt(MAGICTYPEDATA_POWER);
					m_pOwner->AddAttrib(_USERATTRIB_LIFE, nAdd, SYNCHRO_TRUE);

					// effect
					CMsgMagicEffect	msg;
					IF_OK(msg.Create(GetID(), GetMagicType(), DEFAULT_MONSTER_MAGIC_LEVEL, m_pOwner->GetID(), nAdd, GetDir()))
						BroadcastRoomMsg(&msg, INCLUDE_SELF);
				}
			}
		}
		break;
	case	MAGICSORT_ADDMANA:
		{
			if(m_pOwner && m_tMagic.ToNextTime(m_pMagicType->GetInt(MAGICTYPEDATA_STEP)))
			{
				if(m_pOwner->GetMana() < m_pOwner->GetMaxMana())
				{
					int nAdd = m_pMagicType->GetInt(MAGICTYPEDATA_POWER);
					m_pOwner->AddAttrib(_USERATTRIB_MANA, nAdd, SYNCHRO_TRUE);

					// effect
					CMsgMagicEffect	msg;
					IF_OK(msg.Create(GetID(), GetMagicType(), DEFAULT_MONSTER_MAGIC_LEVEL, m_pOwner->GetID(), nAdd, GetDir()))
						BroadcastRoomMsg(&msg, INCLUDE_SELF);
				}
			}
		}
		break;
	case	MAGICSORT_BOMB:
		{
			DEBUG_TRY
			{
				if(!IsCallPet() && !IsEudemon())
					ProcessBomb();
				else
					return false;
			}
			DEBUG_CATCH("CMonster::ProcessBomb()")
		}
		break;
	case	MAGICSORT_VAMPIRE:
	case	MAGICSORT_INSTEAD:
		{
			return false;
		}
		break;
	default:
		ASSERT(!"Nonsupport monster magic sort!!!");
		return false;
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMonster::AdditionMagic(int nLifeLost, int nDamage)
{
	if(!IsMagicAtk())
		return false;

	CHECKF(m_pMagicType);
	switch(m_pMagicType->GetInt(MAGICTYPEDATA_SORT))
	{
	case	MAGICSORT_RECRUIT:
	case	MAGICSORT_ADDMANA:
	case	MAGICSORT_BOMB:
	case	MAGICSORT_INSTEAD:
		{
			return false;
		}
		break;
	case	MAGICSORT_VAMPIRE:
		{
			if(m_pOwner && nLifeLost)
			{
				if(m_pOwner->GetLife() < m_pOwner->GetMaxLife())
				{
					int nAdd = ::CutTrail(0, CRole::AdjustDataEx(nLifeLost, m_pMagicType->GetInt(MAGICTYPEDATA_POWER)));
					if(nAdd)
						m_pOwner->AddAttrib(_USERATTRIB_LIFE, nAdd, SYNCHRO_TRUE);
				}
			}
		}
		break;
	default:
		ASSERT(!"Nonsupport monster magic sort !!!");
		return false;
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
int CMonster::GetDieMode()
{
	CHECKF(m_pMagicType);

	if (m_pMagicType->GetInt(MAGICTYPEDATA_WEAPON_HIT) == CMagic::HIT_BY_MAGIC)
		return DIE_MAGIC;
	else if (IsBowman())
		return DIE_ARROWSHOOT;
	else
		return DIE_NORMAL;
}

//////////////////////////////////////////////////////////////////////
void CMonster::ProcessBomb()
{
	CHECK(IsMagicAtk());
	CHECK(m_pMagicType);
	CHECK(m_pOwner);

	int	nPower = m_pMagicType->GetInt(MAGICTYPEDATA_POWER);
	int	nRange = m_pMagicType->GetInt(MAGICTYPEDATA_RANGE);

	POINT	pos;
	pos.x			= GetPosX();
	pos.y			= GetPosY();
	int	nSize		= nRange*2 + 1;
	int	nBufSize	= nSize * nSize;
	MAPTHING_SET	setTarget;
	GetMap()->CollectMapThing(setTarget, pos, nRange, OBJ_USER|OBJ_MONSTER|OBJ_NPC);
	vector<IRole*>	setRole;
	vector<int>		setPower;

	for(int i = ::CutTrail(pos.x-nRange, 0); i <= pos.x+nRange && i < GetMap()->GetWidth(); i++)
	{
		for(int j = ::CutTrail(pos.y-nRange, 0); j <= pos.y+nRange && j < GetMap()->GetHeight(); j++)
		{
			POINT posThis;
			posThis.x	= i;
			posThis.y	= j;
			if(!CUser::IsInCircle(posThis, pos, nRange))
				continue;

			int idx = POS2INDEX(posThis.x - pos.x + nRange, posThis.y - pos.y + nRange, nSize, nSize);
			ASSERT(idx>=0 && idx<setTarget.size());
			if(setTarget[idx])
			{
				IRole* pRole = NULL;
				if(setTarget[idx]->QueryRole(IPP_OF(pRole)) && pRole->IsAlive() && !IsImmunity(pRole))
				{
					bool bByMagic = m_pMagicType->GetInt(MAGICTYPEDATA_WEAPON_HIT) == CMagic::HIT_BY_MAGIC;
					int	nPower	= CBattleSystem::CalcPower(bByMagic, QueryRole(), pRole, m_pMagicType->GetInt(MAGICTYPEDATA_POWER));

					{
						setRole.push_back(pRole);
						setPower.push_back(nPower);
					}
				}
			}
		}
	}

	// 广播法术效果
	CMsgMagicEffect	msg;
	IF_OK(msg.CreateByPos(GetID(), GetMagicType(), DEFAULT_MONSTER_MAGIC_LEVEL, pos.x, pos.y, GetDir()))
	{
		for(int i = 0; i < setRole.size(); i++)
			msg.AppendRole(setRole[i]->GetID(), setPower[i]);
		BroadcastRoomMsg(&msg, INCLUDE_SELF);
	}

	// set crime status
	for( i = 0; i < setRole.size(); i++)
	{
		if(m_pOwner->CheckCrime(setRole.at(i)))
			break;
	}

	int	nExp = 0;
	for (i = 0; i < setRole.size(); i++)
	{
		int nLifeLost = __min(setRole[i]->GetLife(), setPower[i]);
		setRole[i]->AddAttrib(_USERATTRIB_LIFE, -1*nLifeLost, SYNCHRO_TRUE);
		CNpc* pNpc;
		if(setRole[i]->QueryObj(OBJ_NPC, IPP_OF(pNpc)) && pNpc->IsAwardScore())
			m_pOwner->AwardSynWarScore(pNpc, nLifeLost);

		if (setRole[i]->IsMonster())			// || pNpc && pNpc->IsGoal() && GetLev() >= pNpc->GetLev()
		{
			nExp += m_pOwner->AdjustExp(setRole[i], nLifeLost);
			/*if (!setRole[i]->IsAlive())
			{
				// 有组队,并且队伍中有其他队员,则奖励其他队员经验
				int	nBonusExp	= setRole[i]->GetMaxLife()*KILLBONUS_PERCENT/100;
				OtherMemberAwardExp(setRole[i], nBonusExp);

				nExp += AdjustExp(setRole[i], nBonusExp, true);
			}*/
		}

		setRole[i]->BeAttack(BY_MAGIC, QueryRole(), setPower[i]);
		if(!setRole[i]->IsAlive())
			Kill(setRole[i], GetDieMode());
	}

	AwardBattleExp(nExp);
}

//////////////////////////////////////////////////////////////////////
// precondition is dodge failed
int CMonster::Attack(IRole* pTarget)		// return : lose life
{
	CHECKF(pTarget);

	int nTempAdjust = 0;
	int nDamage = CBattleSystem::CalcPower(IsSimpleMagicAtk(), QueryRole(), pTarget, nTempAdjust, true);

	//护盾转移伤害
	if (pTarget->TransferShield(BY_WEAPON, QueryRole(), nDamage))
	{
	}
	else
	{
		int nLoseLife = ::CutOverflow(nDamage, (int)pTarget->GetLife());
		if (nLoseLife > 0)
			pTarget->AddAttrib(_USERATTRIB_LIFE, -1*nLoseLife, SYNCHRO_TRUE);

		pTarget->BeAttack(BY_WEAPON, QueryRole(), nDamage);
	}

⌨️ 快捷键说明

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