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

📄 magic_process.cpp

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

#include "AllMsg.h"
#include "GameObj.h"
#include "Magic.h"
#include "MapGroup.h"
#include "StatusOnce.h"
#include "StatusMore.h"
#include "MapTrap.h"

/*/ 4超级的特殊状态,及超级回复
3500	3500	0002	回复术
3501	3501	0006	钢铁皮肤
3502	3502	0006	魔法护盾
3503	3503	0006	神圣祈祷
3504	3504	0006	魔力加持
*/
const int	SUPER_MAGIC_RECRUIT			= 3500;
const int	SUPER_MAGIC_DEFENCE			= 3501;
const int	SUPER_MAGIC_MGC_DEFENCE		= 3502;
const int	SUPER_MAGIC_ATTACK			= 3503;
const int	SUPER_MAGIC_MGC_ATTACK		= 3504;

const int	THROW_WEAPON_DROP_RANGE		= 1;							// 扔武器攻击可掉物品的范围

//////////////////////////////////////////////////////////////////////
void	MovePos(POINT* pPos, int nDir)
{
	nDir %= 8;
	pPos->x	+= _DELTA_X[nDir];
	pPos->y	+= _DELTA_X[nDir];
}

//////////////////////////////////////////////////////////////////////
void	DDALine(int x0, int y0, int x1, int y1, int nRange, vector<POINT>& vctPoint)
{
	if (x0 == x1 && y0 == y1)
		return;

	float scale = 1.0f*nRange/sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0));
	x1 = int(0.5f+scale*(x1-x0)+x0);
	y1 = int(0.5f+scale*(y1-y0)+y0);

	::DDALineEx(x0, y0, x1, y1, vctPoint);
}

//////////////////////////////////////////////////////////////////////
// launch
//////////////////////////////////////////////////////////////////////
int CMagic::Launch()
{
	if(!m_pMagic)
		return 0;

	if(!m_pOwner->IsAlive())
	{
		ShowMiss();
		return 0;
	}

	int ret = 0;
	switch(m_pMagic->GetInt(MAGICDATA_SORT))
	{
	case	MAGICSORT_ATTACK:
		ret = ProcessAttack();
		break;
	case	MAGICSORT_RECRUIT:
		ret = ProcessRecruit();
		break;
	case	MAGICSORT_CROSS:
		ret = ProcessCross();
		break;
	case	MAGICSORT_LINE:
	case	MAGICSORT_LINE_PENETRABLE:
		ret = ProcessLine();
		break;
	case	MAGICSORT_FAN:
		ret = ProcessFan();
		break;
	case	MAGICSORT_BOMB:
		ret = ProcessBomb();
		break;
	case	MAGICSORT_BOMB_LOCKALL:
		ret = ProcessBombLockAll();
		break;
	case	MAGICSORT_ATTACHSTATUS:
	case	MAGICSORT_TEAM_MAGIC:
		ret = ProcessAttach();
		break;
	case	MAGICSORT_DETACHSTATUS:
		ret = ProcessDetach();
		break;
	case	MAGICSORT_SQUARE:
		ret = ProcessSquare();
		break;
	case	MAGICSORT_JUMPATTACK:
		ret = ProcessJumpAtk();
		break;
	case	MAGICSORT_RANDOMTRANS:
		ret = ProcessRandomTrans();
		break;
	case	MAGICSORT_DISPATCHXP:
		ret = ProcessDispatchXP();
		break;
	case	MAGICSORT_COLLIDE:
		ret = ProcessCollide();
		break;
	case	MAGICSORT_ATKSTATUS:
		ret = ProcessAtkStatus();
		break;
	case	MAGICSORT_CALLTEAMMEMBER:
		ret = ProcessCallTeamMember();
		break;
	case	MAGICSORT_RECORDTRANSSPELL:
		ret = ProcessRecordTransSpell();
		break;
	case	MAGICSORT_TRANSFORM:
		ret = ProcessTransform();
		break;
	case	MAGICSORT_ADDMANA:
		ret = ProcessAddMana();
		break;
	case	MAGICSORT_LAYTRAP:
		ret = ProcessLayTrap();
		break;
	case	MAGICSORT_CALLPET:
		ret = ProcessCallPet();
		break;
	case	MAGICSORT_DECLIFE:
		ret = ProcessDecLife();
		break;
	case	MAGICSORT_GROUNDSTING:
		ret = ProcessGroundSting();
		break;
	case	MAGICSORT_REBORN:
		ret = ProcessReborn();
		break;
	case	MAGICSORT_SORB_SOUL:
		ret = ProcessSorbSoul();
		break;
	case	MAGICSORT_STEAL:
		ret = ProcessSteal();
		break;
	/////////////////////////////////////////////////
	// 新增幻兽魔法类型	
	case	MAGICSORT_BLAST_THUNDER:
		ret = ProcessBlastThunder();
		break;
	case	MAGICSORT_MULTI_ATTACHSTATUS:
		ret = ProcessMultiAttach();
		break;
	case	MAGICSORT_MULTI_DETACHSTATUS:
		ret = ProcessMultiDetach();
		break;
	case	MAGICSORT_MULTI_CURE:
		ret = ProcessMultiCure();
		break;
	case	MAGICSORT_STEAL_MONEY:
		ret = ProcessStealMoney();
		break;
	case	MAGICSORT_KO:
		ret = ProcessKO();
		break;
	case	MAGICSORT_ESCAPE:
		ret = ProcessEscape();
		break;
	/////////////////////////////////////////////////
	default:
		ASSERT(!"switch magic sort");
	}

	return ret;
}

//////////////////////////////////////////////////////////////////////
// magic process
//////////////////////////////////////////////////////////////////////
bool CMagic::ProcessAttack()
{
	CHECKF(m_pMagic);
	CHECKF(m_pOwner);

	/*
	// check syn of user
	if (!m_pOwner->SynPosition(m_pos.x, m_pos.y))
	{
		UserManager()->KickOutSocket(m_pOwner->GetSocketID(), "SynPosition");
		return false;
	}
	*/

	m_setTargetLocked.clear();
	IRole* pTarget = m_pOwner->FindAroundRole(m_idTarget);
	if(!pTarget || !pTarget->IsAlive())
		return false;

//	if(m_pOwner->GetDistance(pTarget->GetPosX(), pTarget->GetPosY()) > m_pMagic->GetInt(MAGICDATA_DISTANCE))
//		return false;

	if (this->IsImmunity(pTarget))
		return false;

	if (m_pMagic->GetInt(MAGICDATA_FLOOR_ATTR))		// 0: need not check
	{
		int nAttr = m_pOwner->GetMap()->GetFloorAttr(pTarget->GetPosX(), pTarget->GetPosY());
		if(m_pMagic->GetInt(MAGICDATA_FLOOR_ATTR) != nAttr)
			return false;
	}

	m_setTargetLocked.push_back(pTarget->GetID());

	if (m_pMagic->GetSTrackAmount() > 0)
		LockTarget(true);

	int nTotalExp = 0;
	for (int k=0; k<m_nApplyTimes; k++)
	{
		int	nPower = CBattleSystem::CalcPower(HitByMagic(), m_pOwner, pTarget, GetPower(k));

		// 广播法术效果
		CMsgMagicEffect	msg;
		IF_OK(msg.Create(m_pOwner->GetID(), m_pMagic->GetInt(MAGICDATA_TYPE), m_pMagic->GetInt(MAGICDATA_LEVEL), m_idTarget, nPower, m_pOwner->GetDir()))
			m_pOwner->BroadcastRoomMsg(&msg, INCLUDE_SELF);

		// set crime status
		CheckCrime(pTarget);

		if (nPower)
		{
			int nLifeLost = nPower;
			if (pTarget->TransferShield(HitByMagic(), m_pOwner, nPower))
			{
			}
			else
			{
				nLifeLost = __min(pTarget->GetLife(), nPower);
				pTarget->AddAttrib(_USERATTRIB_LIFE, -1*nLifeLost, SYNCHRO_TRUE);

				pTarget->BeAttack(HitByMagic(), m_pOwner, nPower);
			}
			nTotalExp += nLifeLost;

			IStatus* pStatus = m_pOwner->QueryStatus(STATUS_DMG2LIFE);
			if (pStatus)
			{
				int nLifeGot = ::CutTrail(0, MulDiv(nPower, pStatus->GetPower(), 100));
				if (nLifeGot > 0)
					m_pOwner->AddAttrib(_USERATTRIB_LIFE, nLifeGot, SYNCHRO_TRUE);
			}
		}

		if (m_pMagic->GetSTrackAmount() > 0)
			AdjustPosByTrack(k);
	}
	if (nTotalExp > 0)
		AwardExpOfLife(pTarget, nTotalExp);

	m_pos.x	= pTarget->GetPosX();
	m_pos.y = pTarget->GetPosY();

//	if (!pTarget->IsAlive())
//		m_pOwner->Kill(pTarget, GetDieMode());

	//? 未增加武器熟练度,也未损耗双方装备。

	// drop weapon in weapon skill
	if(m_pMagic->GetInt(MAGICDATA_USE_XP) == TYPE_KONGFU && m_pMagic->GetInt(MAGICDATA_DROPWEAPON) == THROW_WERPONR_TARGET)
	{
		CItem* pWeapon = m_pOwner->GetWeaponR();
		IF_OK(pWeapon)
		{
			POINT	pos;
			pos.x	= pTarget->GetPosX();
			pos.y	= pTarget->GetPosY();
			m_pOwner->GetMap()->FindDropItemCell(THROW_WEAPON_DROP_RANGE, &pos);
			m_pOwner->DropItem(pWeapon->GetID(), pos.x, pos.y);					// 没找到CELL也扔,但会重叠。
		}
	}

	return true;
}

bool CMagic::ProcessAtkStatus()
{
	CHECKF(m_pMagic);

//	vector<OBJID>	setLastLocked;
//	if (!m_setTargetLocked.empty())
//		copy(m_setTargetLocked.begin(), m_setTargetLocked.end(), back_inserter(setLastLocked));

	m_setTargetLocked.clear();
	IRole* pTarget = m_pOwner->FindAroundRole(m_idTarget);
	if(!pTarget || !pTarget->IsAlive())
		return false;

//	if(m_pOwner->GetDistance(pTarget->GetPosX(), pTarget->GetPosY()) > m_pMagic->GetInt(MAGICDATA_DISTANCE))
//		return false;

	if (this->IsImmunity(pTarget))
		return false;

//	m_setTargetLocked.push_back(pTarget->GetID());
	int	nPower	= 0;
	bool bAttachStatus = false;
	int nStatusPower = 0;
	int nSecs = 0;
	int nTimes = 0;
	DWORD nStatus = 0;
	if(HitByWeapon())	// && !CBattleSystem::IsTargetDodged(m_pOwner, pTarget))
	{
		int	nAdjust = 0;
		switch(m_pMagic->GetInt(MAGICDATA_STATUS))
		{
		case	STATUS_ATTACK:
			{
				int	nAdjustAtk	= GetPower();
				nPower = CBattleSystem::CalcAttackPower(m_pOwner, pTarget, &nAdjustAtk, 0);
			}
			break;
		case	STATUS_DEFENCE1:
		case	STATUS_DEFENCE2:
		case	STATUS_DEFENCE3:
			{
				int	nAdjustDef	= GetPower();
				nPower = CBattleSystem::CalcAttackPower(m_pOwner, pTarget, 0, &nAdjustDef);
			}
			break;
//		case	STATUS_WEAPONDAMAGE:
//			{
//				int	nAdjustDmg	= GetPower();
//				nPower = CBattleSystem::CalcAttackPower(m_pOwner, pTarget);
//				nPower = ::CutRange(m_pOwner->AdjustData(nPower, nAdjustDmg, pTarget->GetLife()), 0, (int)pTarget->GetMaxLife()*9/10);
//			}
//			break;
		case	STATUS_ATKSPEED:
			{
				int	nPause	= GetPower();
				nPower = CBattleSystem::CalcAttackPower(m_pOwner, pTarget);
				pTarget->SetFightPause(nPause);
			}
			break;
// 根据策划要求,取消这个状态以避免MAGICDATA_PERCENT的使用冲突
//		case	STATUS_STOP:
//			{
//				int	nAdjustAtk	= GetPower();
//				int	nMilliSecs	= m_pMagic->GetInt(MAGICDATA_STEP);
//				nPower = CBattleSystem::CalcAttackPower(m_pOwner, pTarget, &nAdjustAtk);
//				if(pTarget->IsMonster() && ::RandGet(100) < m_pMagic->GetInt(MAGICDATA_PERCENT))
//				{
//					CMsgAction	msg;
//					IF_OK(msg.Create(pTarget->GetID(), pTarget->GetPosX(), pTarget->GetPosY(), pTarget->GetDir(), actionMoveStop, nMilliSecs))
//						pTarget->SendMsg(&msg);
//				}
//			}
//			break;
		case	STATUS_VAMPIRE:
			{
				int	nAdjustAtk		= GetPower();
				int	nAwardPercent	= m_pMagic->GetInt(MAGICDATA_WIDTH);
				CHECKF(nAwardPercent >= 0 && nAwardPercent <= 100);
				nPower = CBattleSystem::CalcAttackPower(m_pOwner, pTarget, &nAdjustAtk);
				int	nAddLife	= MulDiv(::CutTrail((int)pTarget->GetLife(), nPower), nAwardPercent, 100);
				if(nAddLife > 0 && m_pOwner->GetLife() < m_pOwner->GetMaxLife() && m_pOwner->IsAlive())
					m_pOwner->AddAttrib(_USERATTRIB_LIFE, nAddLife, UPDATE_TRUE);
			}
			break;
		case	STATUS_NORMAL:
			break;
		default:	// other status
			{
				if (::RandGet(100) < m_pMagic->GetInt(MAGICDATA_STATUS_CHANCE))
				{
					bAttachStatus = true;
					nStatusPower	= GetPower();
					nSecs	= m_pMagic->GetInt(MAGICDATA_STEP);
					nTimes	= m_pMagic->GetInt(MAGICDATA_TIMES);
					nStatus	= m_pMagic->GetInt(MAGICDATA_STATUS);
					ASSERT(nStatusPower > 0);
//					CRole::AttachStatus(pTarget, nStatus, nStatusPower, nSecs, nTimes);
				}

				nPower = CBattleSystem::CalcAttackPower(m_pOwner, pTarget);
			}
			break;
		}
	}

	// 广播法术效果
	CMsgMagicEffect	msg;
	IF_OK(msg.Create(m_pOwner->GetID(), m_pMagic->GetInt(MAGICDATA_TYPE), m_pMagic->GetInt(MAGICDATA_LEVEL), m_idTarget, nPower, m_pOwner->GetDir()))
		m_pOwner->BroadcastRoomMsg(&msg, INCLUDE_SELF);

	// set crime status
	CheckCrime(pTarget);

	if (nPower)
	{
		CNpc* pNpc = NULL;
		int nLifeLost = nPower;
		if (pTarget->TransferShield(HitByMagic(), m_pOwner, nPower))
		{
		}
		else
		{
			nLifeLost = __min(pTarget->GetLife(), nPower);
			pTarget->AddAttrib(_USERATTRIB_LIFE, -1*nLifeLost, SYNCHRO_TRUE);
			CUser* pTargetUser=NULL;
			if(pTarget->QueryObj(OBJ_USER, IPP_OF(pTargetUser)))
				pTargetUser->BroadcastTeamLife();

			if(pTarget->QueryObj(OBJ_NPC, IPP_OF(pNpc)) && pNpc->IsAwardScore())
				m_pOwner->AwardSynWarScore(pNpc, nLifeLost);

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

				nExp += m_pOwner->AdjustExp(pTarget, nBonusExp, true);
			}
		}
		// 必须在分配组队经验之后杀死
		if (!pTarget->IsAlive())
			m_pOwner->Kill(pTarget, GetDieMode());
		

		IStatus* pStatus = m_pOwner->QueryStatus(STATUS_DMG2LIFE);
		if (pStatus)
		{
			int nLifeGot = ::CutTrail(0, MulDiv(nPower, pStatus->GetPower(), 100));
			if (nLifeGot > 0)
				m_pOwner->AddAttrib(_USERATTRIB_LIFE, nLifeGot, SYNCHRO_TRUE);
		}

		this->AwardExp(nExp);
	}

	// 把原来的先加状态后算攻击修改为先算攻击后加状态
	// 原因是例如冰冻之类的魔法会在BeAttack的时候解除,因此必须在BeAttack之后调用加状态
	if (bAttachStatus)
	{
		if(pTarget->IsAlive())
			CRole::AttachStatus(pTarget, nStatus, nStatusPower, nSecs, nTimes);
	}

	//? 未增加武器熟练度,也未损耗双方装备。

	return true;
}

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

	m_setTargetLocked.clear();
	vector<IRole*>	setRole;
	vector<int>		setPower;
	CTeam* pTeam = m_pOwner->GetTeam();
	if(pTeam && m_pMagic->GetInt(MAGICDATA_MULTI))
	{
		for(int i = 0; i < pTeam->GetMemberAmount(); i++)
		{
			OBJID idTarget = pTeam->GetMemberByIndex(i);

⌨️ 快捷键说明

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