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

📄 magic.cpp

📁 网络游戏魔域的服务端与客户端完整源代码 包括详细的说明文档与开发日志
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		&& ((m_pMagic->GetInt(MAGICDATA_AUTO_ACTIVE)&AUTOACTIVE_EXPDISABLE) == 0)	// 可以得到经验
			|| bIgnoreFlag)
	{
		// ....
		int	nAllExp = m_pMagic->GetInt(MAGICDATA_EXP) + nExp;
		m_pMagic->SetInt(MAGICDATA_EXP, nAllExp);

		// inform client
		if ((m_pMagic->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_HIDDEN) == 0)
		{
			CMsgFlushExp	msg;
			IF_OK(msg.Create(MSGFLUSHEXP_MAGIC, m_pMagic->GetInt(MAGICDATA_TYPE), nAllExp))
				m_pOwner->SendMsg(&msg);
		}
		UpLevel(SYNCHRO_TRUE);
		return true;
	}
	return false;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::UpLevel(bool bSynchro)
{
	CHECKF(m_pMagic);
	CHECKF(!IsWeaponMagic(m_pMagic->GetInt(MAGICDATA_TYPE)));

	int	nNeedExp = m_pMagic->GetInt(MAGICDATA_NEED_EXP);

	if(!( nNeedExp > 0 		// nNeedExp > 0 : 可以升级
			&& ( m_pMagic->GetInt(MAGICDATA_EXP) >= nNeedExp
					|| m_pMagic->GetInt(MAGICDATA_OLD_LEVEL)			// 顿悟
						&& m_pMagic->GetInt(MAGICDATA_LEVEL) >= m_pMagic->GetInt(MAGICDATA_OLD_LEVEL)/2
						&& m_pMagic->GetInt(MAGICDATA_LEVEL) < m_pMagic->GetInt(MAGICDATA_OLD_LEVEL) ) ))
		return false;		// 不用检查职业,因为职业不符不会长EXP

	int	nNewLevel = m_pMagic->GetInt(MAGICDATA_LEVEL) + 1;
	m_pMagic->SetInt(MAGICDATA_EXP, 0);
	m_pMagic->SetInt(MAGICDATA_LEVEL, nNewLevel);
	m_pMagic->Update();

	if(bSynchro && (m_pMagic->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_HIDDEN) == 0)
	{
		CMsgMagicInfo msg;
		IF_OK(msg.Create(m_pOwner->GetID(), m_pMagic->GetInt(MAGICDATA_TYPE), nNewLevel, 0))
			m_pOwner->SendMsg(&msg);
	}

//	CHECKF(m_pMagic->FindType());
	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::MagicAttack(int nType, OBJID idTarget, int x, int y, UCHAR ucAutoActive /*= 0*/)
{
	switch (m_nMagicState)
	{
	case MAGICSTATE_INTONE:
		{
#ifdef ZLONG_DEBUG
			m_pOwner->SendSysMsg("Debug: 魔法吟唱中被打断!准备使用新魔法。");
#endif
			AbortMagic(true);		// true: send faild msg
		}
		break;
	case MAGICSTATE_LAUNCH:
		{
#ifdef ZLONG_DEBUG
			m_pOwner->SendSysMsg("Debug: 魔法施展中,不能施展其它魔法。");
#endif
			return false;
		}
		break;
	case MAGICSTATE_DELAY:
		{
#ifdef ZLONG_DEBUG
			m_pOwner->SendSysMsg("Debug: 魔法延迟尚未结束,不能施展其他魔法。");
#endif
//			AbortMagic(true);		// true: send faild msg
			return false;
		}
		break;
	}

	// 原来的被动技能是简单魔法攻击
	// 为了使修改后的被动技能在执行结束后继续自动攻击目标,这里不清除被攻击目标
	// 同时,CUser::ProcessAutoAttack中通过判断Magic的IsActive以避免魔法攻击的同时进行物理攻击
	// -- zlong 2005-01-04 注释说明
//	m_pOwner->SetAttackTarget(NULL);
	m_bTargetLocked	= false;

	IMagicData* pData = FindMagic(nType);
	if(!( pData && (0 == ucAutoActive || pData->GetInt(MAGICDATA_AUTO_ACTIVE) & ucAutoActive )))
	{
		LOGCHEAT("invalid magic type: %d, user[%s][%d]", nType, m_pOwner->GetName(), m_pOwner->GetID());
		AbortMagic(true);		// true: send faild msg
		return false;
	}

	if(!CheckCondition(pData, idTarget, x, y))				//??? don't return false above this line.
	{
		if(pData->GetInt(MAGICDATA_SORT) == MAGICSORT_COLLIDE)
		{
			ProcessCollideFail(x, y, idTarget);		// idTarget: dir
		}
		else if(pData->GetInt(MAGICDATA_SORT) == MAGICSORT_JUMPATTACK)
		{
			IF_NOT(m_pOwner->GetDistance(x, y) <= pData->GetInt(MAGICDATA_DISTANCE))
			{
				m_pOwner->SendSysMsg(STR_INVALID_MSG);
				CUser* pUser = NULL;
				if (m_pOwner->QueryObj(OBJ_USER, IPP_OF(pUser)))
					UserManager()->KickOutSocket(pUser->GetSocketID(), "JUMPATTACK 太远!");
				return false;
			}
			m_pMagic		= pData;
			ProcessJumpAttackFaild(x, y);
		}
		AbortMagic(true);		// true: send faild msg
		return false;
	}

	// set all member variable
	m_pMagic		= pData;
	m_idTarget		= idTarget;
	if(pData->GetInt(MAGICDATA_GROUND))
		m_idTarget	= ID_NONE;

	m_bAutoAttack	= true;

	if (MAGICSORT_COLLIDE == pData->GetInt(MAGICDATA_SORT))
		m_nData	= (int)idTarget;

	m_pos.x			= x;
	m_pos.y			= y;
	m_nMagicState	= MAGICSTATE_INTONE;
	m_tIntone.Startup(m_pMagic->GetInt(MAGICDATA_INTONE));
#ifdef ZLONG_DEBUG
	m_pOwner->SendSysMsg("Debug: 魔法吟唱开始……");
#endif

	// spend resource
	IRole* pRole = RoleManager()->QueryRole(m_idTarget);
	if(!m_pOwner->GetMap()->IsTrainMap())
	{
		if(m_pMagic->GetInt(MAGICDATA_USE_MP) > 0)
			m_pOwner->AddAttrib(_USERATTRIB_MANA, -1*m_pMagic->GetInt(MAGICDATA_USE_MP), SYNCHRO_TRUE);
		if(m_pMagic->GetInt(MAGICDATA_USE_EP) > 0)
			m_pOwner->AddAttrib(_USERATTRIB_ENERGY, -1*m_pMagic->GetInt(MAGICDATA_USE_EP), SYNCHRO_TRUE);
		if(pData->GetInt(MAGICDATA_USE_ITEM) && pData->GetInt(MAGICDATA_ITEM_NUM) > 0)
			m_pOwner->SpendEquipItem(pData->GetInt(MAGICDATA_USE_ITEM), pData->GetInt(MAGICDATA_ITEM_NUM), SYNCHRO_TRUE);
		if (m_pMagic->GetInt(MAGICDATA_USE_POTENTIAL) > 0)
			m_pOwner->AddAttrib(_USERATTRIB_POTENTIAL, -1*m_pMagic->GetInt(MAGICDATA_USE_POTENTIAL), SYNCHRO_TRUE);
	}

	if (pRole && pData->GetInt(MAGICDATA_NEXT_MAGIC) == pData->GetInt(MAGICDATA_TYPE))
	{
		CUser* pTargetUser = NULL;
		if (pRole->QueryObj(OBJ_USER, IPP_OF(pTargetUser)))
			m_bAutoAttack	= false;
	}

	// broadcast msg
	if(!IsWeaponMagic(m_pMagic->GetInt(MAGICDATA_TYPE)))
	{
		CMsgInteract	msg;
		IF_OK(msg.Create(INTERACT_MAGICATTACK, m_pOwner->GetID(), idTarget, x, y, m_pMagic->GetInt(MAGICDATA_TYPE), m_pMagic->GetInt(MAGICDATA_LEVEL)))
			m_pOwner->BroadcastRoomMsg(&msg, INCLUDE_SELF);
	}

	// equipment durability cost
	if (m_pMagic->GetInt(MAGICDATA_USE_MP) != 0)
	{
		if(!m_pOwner->GetMap()->IsTrainMap())
			m_pOwner->DecEquipmentDurability(ATTACK_TIME, HitByMagic(), m_pMagic->GetInt(MAGICDATA_DURABILITY));

		if (::RandGet(10) == 7)
			m_pOwner->SendGemEffect();
	}


	// launch immediately
	if(m_pMagic->GetInt(MAGICDATA_INTONE) <= 0)
	{
		m_tIntone.Clear();
#ifdef ZLONG_DEBUG
		m_pOwner->SendSysMsg("Debug: 魔法吟唱立刻结束,开始施展魔法……");
#endif
		m_nMagicState	= MAGICSTATE_LAUNCH;
		m_nApplyTimes	= __max(1, m_pMagic->GetSTrackAmount());

		if (!Launch())	// 魔法执行失败就结束——这里包括攻击前目标已经死亡、目标消失等情况
		{
			LockTarget(false);
			m_tApply.Clear();
			ResetDelay();
		}
		else
			m_tApply.Startup(m_pMagic->GetApplyMS());
		return true;
	}

	return true;	// 不会立即伤血
}

//////////////////////////////////////////////////////////////////////
void CMagic::BreakAutoAttack()
{
	m_bAutoAttack	= false;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::AbortMagic(bool bSynchro)
{
	// 魔法施展过程中禁止中止 —— 暂时这么设定
	if (m_nMagicState == MAGICSTATE_LAUNCH)
	{
#ifdef ZLONG_DEBUG
		m_pOwner->SendSysMsg("Debug: 魔法施放过程中,不能中止!");
#endif
//		m_tApply.Clear();
		return false;
	}

	BreakAutoAttack();
	if (m_nMagicState == MAGICSTATE_DELAY)
	{
#ifdef ZLONG_DEBUG
		m_pOwner->SendSysMsg("Debug: 魔法延迟中。");
#endif
//		m_tDelay.Clear();
		return false;
	}
	
	m_pMagic = NULL;
	if (m_nMagicState == MAGICSTATE_INTONE)
	{
		m_tIntone.Clear();

#ifdef ZLONG_DEBUG
		m_pOwner->SendSysMsg("Debug: 魔法吟唱被中止!");
#endif
	}

	m_nMagicState	= MAGICSTATE_NONE;
	if(bSynchro)
	{
		CMsgAction msg;
		if (msg.Create(m_pOwner->GetID(), 0, 0, 0, actionAbordMagic))
			m_pOwner->SendMsg(&msg);
	}

	return true;
}

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

	CMsgMagicEffect	msg;
	if(m_pMagic->GetInt(MAGICDATA_GROUND))
		msg.CreateByPos(m_pOwner->GetID(), m_pMagic->GetInt(MAGICDATA_TYPE), m_pMagic->GetInt(MAGICDATA_LEVEL), m_pos.x, m_pos.y, m_pOwner->GetDir());
	else
		msg.Create(m_pOwner->GetID(), m_pMagic->GetInt(MAGICDATA_TYPE), m_pMagic->GetInt(MAGICDATA_LEVEL), m_idTarget, 0, m_pOwner->GetDir());
	m_pOwner->BroadcastRoomMsg(&msg, true);
}

//////////////////////////////////////////////////////////////////////
bool CMagic::CheckCondition(IMagicData* pData, OBJID idTarget, int x, int y)
{
	// delay
	if(!m_tDelay.IsTimeOut(m_nDelay) && MAGICSORT_COLLIDE != pData->GetInt(MAGICDATA_SORT))
		return false;

	if (!pData->IsReady())		// 检查魔法的单独延迟时间
		return false;

	// 命中率判断 -- 满足下面条件的魔法不需要判断命中率
	if (!((pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_KILL)==AUTOACTIVE_KILL
		|| (pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_RANDOM)==AUTOACTIVE_RANDOM))
	{
		if (::RandGet(100) >= pData->GetInt(MAGICDATA_PERCENT))
			return false;
	}

	//---jinggy---装备镶嵌的宝石技能---begin
	//检验技能条件是否需要  宝石类型
	int nNeedGemType = pData->GetInt(MAGICDATA_NEED_GEMTYPE);
	if(nNeedGemType)
	{
		//判断是否是嵌入玩家装备的宝石类型
		IF_NOT(m_pOwner->IsEmbedGemType(nNeedGemType))
			return false;		
	}
	//---jinggy---装备镶嵌的宝石技能---end

	if(m_pOwner->GetMap()->IsInRegionType(REGION_PK_PROTECTED, m_pOwner->GetPosX(), m_pOwner->GetPosY()))
	{
		if(pData->GetInt(MAGICDATA_GROUND))
		{
			if(pData->GetInt(MAGICDATA_CRIME))
				return false;
		}
		else
		{
			IRole* pTarget = RoleManager()->QueryRole(idTarget);
			if(pTarget && pTarget->QueryOwnerUser() && pData->GetInt(MAGICDATA_CRIME))
				return false;
		}
	}

	// resource
	if(!m_pOwner->GetMap()->IsTrainMap())
	{
		if(m_pOwner->GetMana() < pData->GetInt(MAGICDATA_USE_MP))
			return false;
		if(m_pOwner->GetEnergy() < pData->GetInt(MAGICDATA_USE_EP))
			return false;
		// check use_item
		if(pData->GetInt(MAGICDATA_USE_ITEM))
		{
			if(!m_pOwner->CheckWeaponSubType(pData->GetInt(MAGICDATA_USE_ITEM), pData->GetInt(MAGICDATA_ITEM_NUM)))
				return false;
		}
		if (m_pOwner->GetPotential() < pData->GetInt(MAGICDATA_USE_POTENTIAL))
		{
			m_pOwner->SendSysMsg(STR_NOT_ENOUGH_POTENTIAL);
			return false;
		}
	}
	// 使用XP技能需要XPFULL状态
	if(pData->GetInt(MAGICDATA_USE_XP) == TYPE_XPSKILL)
	{
		IStatus* pStatus = m_pOwner->QueryStatus(STATUS_XPFULL);
		if (!pStatus)
			return false;
	}

	// with weapon
	if(pData->GetInt(MAGICDATA_WEAPON_SUBTYPE))
	{
		if(!m_pOwner->CheckWeaponSubType(pData->GetInt(MAGICDATA_WEAPON_SUBTYPE)))
		return false;
	}

	// check map
	int nSort = pData->GetInt(MAGICDATA_SORT);
	if((nSort == MAGICSORT_CALLTEAMMEMBER || nSort == MAGICSORT_RECORDTRANSSPELL) && m_pOwner->GetMap()->IsFlyToDisable())
	{
		return false;
	}
	if(nSort == MAGICSORT_RECORDTRANSSPELL && m_pOwner->GetMap()->QueryRegion(REGION_CITY, m_pOwner->GetPosX(), m_pOwner->GetPosY()))
	{
		return false;
	}
	if(m_pOwner->QueryTransformation() && nSort != MAGICSORT_TRANSFORM)
	{
		return false;
	}
	if(m_pOwner->IsWing() && nSort == MAGICSORT_TRANSFORM)
	{
		return false;
	}
//	if(!m_pOwner->GetMap()->IsWingEnable() && nSort == MAGICSORT_ATTACHSTATUS && pData->GetInt(MAGICDATA_STATUS) == STATUS_WING)
//	{
//		return false;
//	}

	// check distance
	IRole* pRole = NULL;
	if (!pData->GetInt(MAGICDATA_GROUND))
	{
		pRole = m_pOwner->FindAroundRole(idTarget);		// may be NULL
		if (!pRole)
			return false;			// not find target

		if (!pRole->IsAlive() && nSort != MAGICSORT_DETACHSTATUS && nSort != MAGICSORT_SORB_SOUL) 
			return false;

		if (nSort == MAGICSORT_ESCAPE)
		{
			if (pRole->GetLife()*100/pRole->GetMaxLife() >= MAGIC_ESCAPE_LIFE_PERCENT)
				return false;
		}

		if (nSort == MAGICSORT_SORB_SOUL)
		{
			CMonster* pMonster = NULL;
			if (!pRole->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)))
				return false;
			if ((pMonster->GetMaskData() & MASK_DISABLE_SORB_SOUL) == MASK_DISABLE_SORB_SOUL)
				return false;
		}
		if (nSort == MAGICSORT_STEAL_MONEY)
		{
			CMonster* pMonster = NULL;
			if (pRole->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)))
			{
				if ((pMonster->GetMaskData() & MASK_DISABLE_STEAL_MONEY) == MASK_DISABLE_STEAL_MONEY)
					return false;
			}
		}

		x = pRole->GetPosX();
		y = pRole->GetPosY();
	}
	if(m_pOwner->GetDistance(x, y) > pData->GetInt(MAGICDATA_DISTANCE))
		return false;

	// check goal
	CNpc* pNpc = NULL;
	if(pRole)
		pRole->QueryObj(OBJ_NPC, IPP_OF(pNpc));
	if(pNpc)
	{
		if(!pNpc->IsBeAtkable())
			return false;
		if (pNpc->IsGoal() && m_pOwner->GetLev() < pNpc->GetLev() 
				|| pNpc->GetType() != _MAGICGOAL_NPC)
			return false;
	}

	// check recruit
	if(pRole && pData->GetInt(MAGICDATA_SORT) == MAGICSORT_RECRUIT)
	{
		CMonster* pMonster=NULL;
		pRole->QueryObj(OBJ_MONSTER, IPP_OF(pMonster));
		if((pNpc && !pNpc->IsGoal()) || pMonster)			// && pMonster->IsSynPet()
			return false;
	}

	if(pRole && m_pOwner->IsBowman() && !m_pOwner->IsArrowPass(x, y))
		return false;

	// 结界魔法只有队长才可以发动
	if (pData->GetInt(MAGICDATA_SORT) == MAGICSORT_TEAM_MAGIC)
	{
		CTeam* pTeam = m_pOwner->GetTeam();
		if (!pTeam || pTeam->GetLeader() != m_pOwner->GetID() 
			|| pTeam->GetMemberAmount() < TEAM_STATUS_REQ_ROLES)	// 发动界结,队伍中必须至少有3人
		{
			return false;
		}
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::CheckCrime(IRole* pRole)
{
	CHECKF(m_pMagic);
	CHECKF(pRole);

	if(!m_pMagic->GetInt(MAGICDATA_CRIME))
		return false;

	return m_pOwner->CheckCrime(pRole);
}

//////////////////////////////////////////////////////////////////////
bool CMagic::CheckCrime(const vector<IRole*>* pSet)
{
	CHECKF(m_pMagic);

	if(!m_pMagic->GetInt(MAGICDATA_CRIME))
		return false;

	for(int i = 0; i < pSet->size(); i++)
	{
		if(m_pOwner->CheckCrime(pSet->at(i)))
			return true;
	}
	return false;
}

//////////////////////////////////////////////////////////////////////
void CMagic::OwnerUpLevel(int nOwnerLev)
{
	//m_nRawDelay = MAGIC_DELAY - MAGIC_DECDELAY_PER_LEVEL*m_pOwner->GetProfessionLevel();
	//ASSERT(m_nRawDelay >= 500);

	m_tDelay.SetInterval(m_nRawDelay);
	m_nDelay	= m_nRawDelay;//MulDiv(m_nRawDelay, AUTO_MAGIC_DELAY_PERCENT, 100);

	if (m_setData->GetAmount() == 0)

⌨️ 快捷键说明

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