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

📄 magic.cpp

📁 网络游戏魔域的服务端与客户端完整源代码 包括详细的说明文档与开发日志
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	if(m_pMagic && m_pMagic->GetID() == idMagic)
	{
		m_pMagic		= NULL;
		m_bAutoAttack	= false;
	}
	return m_setData->DelObj(idMagic);
}

//////////////////////////////////////////////////////////////////////
// calc magic fight
//////////////////////////////////////////////////////////////////////
int CMagic::CalcMagicPower(IRole* pAtker, IRole* pTarget, int* pAdjustAtk/*=0*/)
{
	// attack
	int nMaxRand = 50 + pAtker->GetLuck();
	int nAtk = 0;
	if(::RandGet(100) < nMaxRand)
		nAtk = pAtker->GetMgcMaxAtk() - ::RandGet((pAtker->GetMgcMaxAtk()-pAtker->GetMgcMinAtk()) / 2);
	else
		nAtk = pAtker->GetMgcMinAtk() + ::RandGet((pAtker->GetMgcMaxAtk()-pAtker->GetMgcMinAtk()) / 2);

	nAtk = pAtker->AdjustMagicAtk(nAtk);
	/*CUser* pUser;
	if(pAtker->QueryObj(OBJ_USER, IPP_OF(pUser)))
	{
		nAtk = __max(0, nAtk + pUser->GetMagicAtk());
		nAtk += nAtk*pUser->GetGemMgcAtkEffect()/100;
	}*/
	if(pAdjustAtk)
	{
		if(*pAdjustAtk)
			nAtk = ::CutTrail(0, CRole::AdjustDataEx(nAtk, *pAdjustAtk));

		*pAdjustAtk = nAtk;
	}

	int nDef = pTarget->GetMagicDef();

	nDef	= pTarget->AdjustMagicDef(nDef);

	// damage
	int	nDamage	= nAtk - nDef;
	if (pAtker->QueryOwnerUser() && pTarget->IsMonster())
	{
		CMonster* pMonster;
		if(pTarget->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)) && !pMonster->IsEquality())
			nDamage	= CBattleSystem::CalcDamageUser2Monster(nAtk, nDef, pAtker->GetLev(), pTarget->GetLev());
		nDamage = pTarget->AdjustMagicDamage(nDamage);
		nDamage	= CBattleSystem::AdjustMinDamageUser2Monster(nDamage, pAtker, pTarget);
	}
	else if(pAtker->IsMonster() && pTarget->QueryOwnerUser())
	{
		CMonster* pMonster;
		if(pAtker->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)) && !pMonster->IsEquality())
			nDamage	= CBattleSystem::CalcDamageMonster2User(nAtk, nDef, pAtker->GetLev(), pTarget->GetLev());
		nDamage = pTarget->AdjustMagicDamage(nDamage);
		nDamage	= CBattleSystem::AdjustMinDamageMonster2User(nDamage, pAtker, pTarget);
	}
	else
	{
		// adjust magic damage
		nDamage = pTarget->AdjustMagicDamage(nDamage);
	}

	// adjust synflag damage
	CNpc* pNpc = NULL;
	pTarget->QueryObj(OBJ_NPC, IPP_OF(pNpc));
	if(pNpc && pNpc->IsSynFlag() && pNpc->IsSynMoneyEmpty())
		nDamage	*= SYNWAR_NOMONEY_DAMAGETIMES;
	
	return ::CutTrail(1, nDamage);
}

//////////////////////////////////////////////////////////////////////
bool CMagic::CheckAwardExpEnable(DWORD dwProf)
{
	CHECKF(m_pMagic);
	return m_pOwner->GetLev() >= m_pMagic->GetInt(MAGICDATA_NEED_LEVEL)
								&& m_pMagic->GetInt(MAGICDATA_NEED_EXP) != AUTOLEVELUP_EXP 
								&& m_pMagic->GetInt(MAGICDATA_NEED_EXP) != DISABLELEVELUP_EXP 
								&& this->CheckProfession(dwProf, m_pMagic->GetInt(MAGICDATA_NEED_PROFMASK))
//								&& m_pMagic->GetInt(MAGICDATA_USE_XP) != TYPE_KONGFU
								;
}

//////////////////////////////////////////////////////////////////////
void CMagic::OtherMemberAwardExp(IRole* pTarget, int nRawExp)
{
	if(m_pOwner->GetMap()->IsTrainMap())
		return ;

	CTeam* pTeam	= m_pOwner->GetTeam();
	if (pTeam)
	{
		pTeam->AwardMemberExp(m_pOwner->GetID(), pTarget, nRawExp);
	}

	CUser* pUser = NULL;
	if (m_pOwner->QueryObj(OBJ_USER, IPP_OF(pUser)))
	{
		for (int i=0; i<pUser->GetEudemonAmount(); i++)
		{
			CMonster* pEudemon = pUser->QueryEudemonByIndex(i);
			if (pEudemon && pEudemon->IsAlive() && 
				(abs(pEudemon->GetPosX()-pTarget->GetPosX()) <= _RANGE_EXPSHARE
				|| abs(pEudemon->GetPosY()-pTarget->GetPosY()) <= _RANGE_EXPSHARE))
			{
				int nBattleExp = pEudemon->AdjustExp(pTarget, nRawExp);
				bool bIncludeOwner = false;
				pEudemon->AwardBattleExp(nBattleExp, true, bIncludeOwner);
			}
		}		
	}
}

//////////////////////////////////////////////////////////////////////
int	CMagic::GetExtendAtkRange	(CItem* pWeaponR, CItem* pWeaponL)
{
	CHECKF(m_pOwner);

	int nRange = 0;
	for(int i = 0; i < m_setData->GetAmount(); i++)
	{
		IMagicData* pData = m_setData->GetObjByIndex(i);
		if (pData
				&& (pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_FOREVER)
				&& MAGICSORT_ATKRANGE == pData->GetInt(MAGICDATA_SORT))
		{
			int nWeaponRequired = pData->GetInt(MAGICDATA_WEAPON_SUBTYPE);
			if (0 == nWeaponRequired		
					|| (pWeaponR && pWeaponR->GetItemSubType() == nWeaponRequired)
					|| (pWeaponL && pWeaponL->GetItemSubType() == nWeaponRequired))
			{
				nRange += GetPower();
			}			
		}
	}

	return nRange;
}

//////////////////////////////////////////////////////////////////////
int CMagic::HitByMagic()
{
	CHECKF(m_pMagic);

	if(m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) == HIT_BY_MAGIC)
	{
		if (m_pMagic->GetInt(MAGICDATA_USE_XP) == TYPE_XPSKILL)
			return MAGICTYPE_XPSKILL;
		else
			return MAGICTYPE_NORMAL;
	}

	CItem* pItem = m_pOwner->GetEquipItemByPos(ITEMPOSITION_WEAPONL);
	if(m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) == HIT_BY_ITEM && pItem && pItem->GetMgcMinAtk() > 0) // ->GetInt(ITEMDATA_MAGICATK_MIN) > 0)
	{
		if (m_pMagic->GetInt(MAGICDATA_USE_XP) == TYPE_XPSKILL)
			return MAGICTYPE_XPSKILL;
		else
			return MAGICTYPE_NORMAL;
	}
	
	return MAGICTYPE_NONE;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::HitByWeapon()
{
	CHECKF(m_pMagic);

	if(m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) == HIT_BY_WEAPON)
		return true;

	CItem* pItem = m_pOwner->GetEquipItemByPos(ITEMPOSITION_WEAPONL);
	if(m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) == HIT_BY_ITEM && pItem && pItem->GetMgcMinAtk() <= 0) // ->GetInt(ITEMDATA_MAGICATK_MIN) <= 0)
		return true;

	return false;
}

//////////////////////////////////////////////////////////////////////
void CMagic::ResetDelay()
{
	CHECK(m_pMagic);

	m_nDelay	= m_nRawDelay;
	m_nMagicState	= MAGICSTATE_DELAY;
	m_tDelay.Update();			// 开始DELAY
	// 启动 每个魔法单独的延迟计时器
	if (m_pMagic)
		m_pMagic->StartDelay();
}

//////////////////////////////////////////////////////////////////////
// bAtkerPenetrable:  攻击者移动轨迹是否可以穿人
// bTargetPenetrable: 被攻击者移动轨迹是否可以穿人
bool CMagic::AdjustPosByTrack(int nStepIndex, bool bAtkerPenetrable/*=false*/, bool bTargetPenetrable/*=false*/)
{
	CHECKF(m_pOwner);
	CHECKF(m_pMagic);

	CMapPtr pMap = m_pOwner->GetMap();
	if (!pMap)
		return false;

	// record target pos
	int	nTargetPosX = m_pOwner->GetPosX();
	int nTargetPosY = m_pOwner->GetPosY();
	IRole*	pTarget	= RoleManager()->QueryRole(m_idTarget);
	if (pTarget)
	{
		nTargetPosX	= pTarget->GetPosX();
		nTargetPosY	= pTarget->GetPosY();
	}

	if (nStepIndex >= 0 && nStepIndex < m_pMagic->GetTTrackAmount())
	{
		// 取轨迹
		const ST_TRACK& track = m_pMagic->GetTTrackByIndex(nStepIndex);
		for (int i=0; i<m_setTargetLocked.size(); i++)
		{
			DEBUG_TRY
			OBJID idTarget	= m_setTargetLocked[i];
			if (idTarget == ID_NONE)
				continue;

			IRole*	pTarget	= m_pOwner->FindAroundRole(idTarget);
			if (!pTarget)
				continue;

			int nNewX	= pTarget->GetPosX();
			int nNewY	= pTarget->GetPosY();

			// 取得攻击方向
			UCHAR ucAtkDir = ::GetDirByPos(m_pOwner->GetPosX(), m_pOwner->GetPosY(), pTarget->GetPosX(), pTarget->GetPosY());

			// 根据轨迹方向计算位移坐标
			int nMoveDir = (ucAtkDir + track.ucDir) % 8;

			for (int i=0; i<track.ucStep; i++)
			{
				int nTmpX = (nNewX + _DELTA_X[nMoveDir]);
				int nTmpY = (nNewY + _DELTA_Y[nMoveDir]);
				if (pMap->IsMoveEnable(nNewX, nNewY, nTmpX, nTmpY, track.ucAlt)
					|| (bTargetPenetrable && pMap->IsStandEnable(nTmpX, nTmpY)))
				{
					nNewX	= nTmpX;
					nNewY	= nTmpY;
				}
			}
			
//			if (nNewX != pTarget->GetPosX() || nNewY != pTarget->GetPosY())
			{
#ifdef _DEBUG
				CUser* pTargetUser = NULL;
				if (pTarget->QueryObj(OBJ_USER, IPP_OF(pTargetUser)))
				{
//					::MyLogSave("syslog\\magic", "Debug: track step [%d], move from [%d, %d] to [%d, %d]", 
//						nStepIndex, pTargetUser->GetPosX(), pTargetUser->GetPosY(), nNewX, nNewY);

					pTargetUser->SendSysMsg("Debug: track step [%d], move from [%d, %d] to [%d, %d]", 
						nStepIndex, pTargetUser->GetPosX(), pTargetUser->GetPosY(), nNewX, nNewY);
				}
#endif
				pTarget->ProcessOnMove(MOVEMODE_TRACK);
				pTarget->SyncTrackTo(nNewX, nNewY, (nMoveDir+4)%8, track.idAction);

			}
			DEBUG_CATCH("Process adjust target track error.")
		}	// end of for
	}

	// attacker track
	if (nStepIndex >= 0 && nStepIndex < m_pMagic->GetSTrackAmount())
	{
		int nNewX	= m_pOwner->GetPosX();
		int nNewY	= m_pOwner->GetPosY();

		// 取得攻击方向
		UCHAR ucAtkDir = m_pOwner->GetDir();
		if (pTarget)
			ucAtkDir = ::GetDirByPos(m_pOwner->GetPosX(), m_pOwner->GetPosY(), nTargetPosX, nTargetPosY);

		// 根据轨迹方向计算位移坐标
		const ST_TRACK& track	= m_pMagic->GetSTrackByIndex(nStepIndex);
		int nMoveDir = (ucAtkDir + track.ucDir) % 8;

		for (int i=0; i<track.ucStep; i++)
		{
			int nTmpX = (nNewX + _DELTA_X[nMoveDir]);
			int nTmpY = (nNewY + _DELTA_Y[nMoveDir]);
			if (pMap->IsMoveEnable(nNewX, nNewY, nTmpX, nTmpY, track.ucAlt)
				|| (bAtkerPenetrable && pMap->IsStandEnable(nTmpX, nTmpY)))
			{
				nNewX	= nTmpX;
				nNewY	= nTmpY;
			}
		}

//		if (nNewX != m_pOwner->GetPosX() || nNewY != m_pOwner->GetPosY())
		{
#ifdef _DEBUG
//			::MyLogSave("syslog\\magic", "Debug: track step [%d], move from [%d, %d] to [%d, %d]", 
//				nStepIndex, m_pOwner->GetPosX(), m_pOwner->GetPosY(), nNewX, nNewY);
			
			m_pOwner->SendSysMsg("Debug: track step [%d], move from [%d, %d] to [%d, %d]", 
				nStepIndex, m_pOwner->GetPosX(), m_pOwner->GetPosY(), nNewX, nNewY);
#endif
			m_pOwner->ProcessOnMove(MOVEMODE_TRACK);
			m_pOwner->SyncTrackTo(nNewX, nNewY, nMoveDir, track.idAction);
		}
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::LockTarget(bool bLock)
{
	if (m_bTargetLocked == bLock)
		return true;
	
	int nAction = actionLockUser;
	if (!bLock)
		nAction	= actionUnlockUser;

	int nLockSecs	= m_pMagic->GetLockSecs();
	// lock atk user
	if (bLock)
	{
		if (m_pOwner->IsAlive())
		{
			CMsgAction	msg;
			if (msg.Create(m_pOwner->GetID(), m_pOwner->GetPosX(), m_pOwner->GetPosY(), m_pOwner->GetDir(), nAction))
			{
				m_pOwner->BroadcastRoomMsg(&msg, true);
				CRole::AttachStatus(m_pOwner, STATUS_LOCK, 0, nLockSecs);
			}
		}
	}
	else
		CRole::DetachStatus(m_pOwner, STATUS_LOCK);

	// lock target
	vector<OBJID>::iterator	it = m_setTargetLocked.begin();
	for (; it!=m_setTargetLocked.end(); it++)
	{
		IRole* pRole = RoleManager()->QueryRole(*it);
		if (pRole)
		{
			if (bLock)
			{
				if (pRole->IsAlive())
				{
					CMsgAction msg;
					if (msg.Create(pRole->GetID(), pRole->GetPosX(), pRole->GetPosY(), pRole->GetDir(), nAction))
					{
						pRole->BroadcastRoomMsg(&msg, true);
					}
					CRole::AttachStatus(pRole, STATUS_LOCK, 0, nLockSecs);
				}
			}
			else
				CRole::DetachStatus(pRole, STATUS_LOCK);
		}
	}
	m_bTargetLocked	= bLock;
	return true;
}

//////////////////////////////////////////////////////////////////////
int CMagic::GetPower(int nStepIndex /* = -1*/)
{
	CHECKF(m_pMagic);

//	if (nStepIndex != -1)
//		nStepIndex	= m_pMagic->GetSTrackAmount() - (m_nApplyTimes + 1);
	if (nStepIndex >= 0 && nStepIndex < m_pMagic->GetSTrackAmount())
	{
		const ST_TRACK&	track = m_pMagic->GetSTrackByIndex(nStepIndex);
		return track.nPower;
	}

	return m_pMagic->GetInt(MAGICDATA_POWER);
}

//////////////////////////////////////////////////////////////////////
/*
int CMagic::GetApplyMS(int nStepIndex / *= -1* /)
{
	CHECKF(m_pMagic);

	// 缺省取当前步的延迟时间
//	if (nStepIndex == -1)
//		nStepIndex	= m_pMagic->GetSTrackAmount() - (m_nApplyTimes + 1);

	if (nStepIndex >= 0 && nStepIndex < m_pMagic->GetSTrackAmount())
	{
		const ST_TRACK&	track = m_pMagic->GetSTrackByIndex(nStepIndex);
		return track.nApplyMS;
	}

	return m_pMagic->GetInt(MAGICDATA_APPLY_MS);
}
*/
//////////////////////////////////////////////////////////////////////
BOOL CMagic::HaveXpMagic()
{
	for(int i = 0; i < m_setData->GetAmount(); i++)
	{
		IMagicData* pData = m_setData->GetObjByIndex(i);
		if(pData && pData->GetInt(MAGICDATA_USE_XP) == TYPE_XPSKILL)
			return true;
	}
	return false;
}

//////////////////////////////////////////////////////////////////////
// 目前设计仅用于幻兽自动学习魔法
// 如需要用于其它用途可能要做相应修改
bool CMagic::AutoLearnMagic()
{
	const int	MAX_AUTO_LEARN_RAND = 10000;
	bool bLearnMagic = false;
	DWORD	dwProf = m_pOwner->GetProfession();
	for(int i = 0; i < AutoMagicTypeSet()->GetAmount(); i++)		//??? 可优化
	{
		CMagicTypeData* pData = AutoMagicTypeSet()->GetObjByIndex(i);
		if(pData && pData->GetInt(MAGICTYPEDATA_AUTO_LEARN)
			&& m_pOwner->GetLev() >= pData->GetInt(MAGICTYPEDATA_LEARN_LEVEL)
			&& CheckProfession(dwProf, pData->GetInt(MAGICTYPEDATA_NEED_PROFMASK))
			&& ::RandGet(MAX_AUTO_LEARN_RAND) < pData->GetInt(MAGICTYPEDATA_AUTO_LEARN_PROB)
			&& FindMagic(pData->GetInt(MAGICTYPEDATA_TYPE)) == NULL)
		{
			LearnMagic(pData->GetInt(MAGICTYPEDATA_TYPE), pData->GetInt(MAGICTYPEDATA_LEVEL));
			bLearnMagic = true;
		}
	}
	
	return bLearnMagic;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::CheckProfession(DWORD dwProf, DWORD dwNeedProf)
{
	DWORD dwProfMask = Prof2Mask(dwProf);
	if (dwProfMask != 0)
	{
		const DWORD		PROF_MASK_USER		= 0x0000003F;
		if ((dwNeedProf&PROF_MASK_USER) == 0 || (dwProfMask & dwNeedProf) != 0)
			return true;
	}
	else
	{
		// 幻兽职业
		const DWORD		PROF_MASK_EVOLVE0	= 0x00003FC0;
		const DWORD		PROF_MASK_EVOLVE1	= 0x0000C000;
		const DWORD		PROF_MASK_EVOLVE2	= 0x00FF0000;

		dwProfMask = 0;
		DWORD dwProf1 = dwProf/100;
		if (dwProf1 > 0)		// 0 次进化职业,1~8
			dwProfMask = 1 << (dwProf1 - 1 + MAX_USER_PROFS);
		if ((dwNeedProf & PROF_MASK_EVOLVE0)!= 0 && (dwNeedProf & dwProfMask) == 0)
			return false;

		dwProfMask = 0;
		DWORD dwProf2 = dwProf/10 % 10;
		if (dwProf2 > 0)		// 1 次进化职业,1~2
			dwProfMask = 1 << (dwProf2 - 1 + MAX_USER_PROFS+8);
		if ((dwNeedProf & PROF_MASK_EVOLVE1)!= 0 && (dwNeedProf & dwProfMask) == 0)
			return false;
		
		dwProfMask = 0;
		DWORD dwProf3 = dwProf%10;
		if (dwProf3 > 0)		// 2 次进化职业,1~8
			dwProfMask = 1 << (dwProf3 - 1 + MAX_USER_PROFS+8+2);
		if ((dwNeedProf & PROF_MASK_EVOLVE2)!= 0 && (dwNeedProf & dwProfMask) == 0)
			return false;

		return true;
	}

	return false;
}

⌨️ 快捷键说明

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