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

📄 user.cpp

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

	return nAddPercent;
}
//////////////////////////////////////////////////////////////////////
int	CUser::GetGemAtkEffect		(void)
{
	int nAddEffect = 0;
	for (int i = ITEMPOSITION_EQUIPBEGIN; i < ITEMPOSITION_EQUIPEND; i++)
	{
		CItem* pEquip = GetEquipItemByPos(i);
		if (pEquip)
			nAddEffect += pEquip->GetGemDmgEffect();
	}

	return nAddEffect;
}

//////////////////////////////////////////////////////////////////////
int CUser::GetGemMgcAtkEffect	(void)
{
	int nAddEffect = 0;
	for (int i = ITEMPOSITION_EQUIPBEGIN; i < ITEMPOSITION_EQUIPEND; i++)
	{
		CItem* pEquip = GetEquipItemByPos(i);
		if (pEquip)
			nAddEffect += pEquip->GetGemMgcAtkEffect();
	}

	return nAddEffect;
}

//////////////////////////////////////////////////////////////////////
void CUser::SendGemEffect(void)
{
	vector<int> setGem;

	int nGem = 0;
	for(int i = ITEMPOSITION_EQUIPBEGIN; i < ITEMPOSITION_EQUIPEND; i++)
	{
		CItem* pEquip = GetEquipItemByPos(i);
		if (pEquip)
		{
			nGem = pEquip->GetInt(ITEMDATA_GEM1);
			if (nGem != GEM_NONE && nGem != GEM_HOLE)
				setGem.push_back(nGem);

			nGem = pEquip->GetInt(ITEMDATA_GEM2);
			if (nGem != GEM_NONE && nGem != GEM_HOLE)
				setGem.push_back(nGem);
		}
	}	

	int nGems = setGem.size();
	if (nGems <= 0)
		return;

	string strEffect;
	switch(setGem[::RandGet(nGems)])
	{
	case 3:
		strEffect = "phoenix";
		break;
	case 13:
		strEffect = "goldendragon";
		break;
	case 23:
		strEffect = "fastflash";
		break;
	case 33:
		strEffect = "rainbow";
		break;
	case 43:
		strEffect = "goldenkylin";
		break;
	case 53:
		strEffect = "purpleray";
		break;
	case 63:
		strEffect = "moon";
		break;
	default:
		return;
	}

	CMsgName msg;
	IF_OK (msg.Create(NAMEACT_ROLEEFFECT, strEffect.c_str(), this->GetID()))
		this->BroadcastRoomMsg(&msg, true);
}

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

	CNpc* pNpc;
	pTarget->QueryObj(OBJ_NPC, IPP_OF(pNpc));

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

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

		// adjust synflag damage
		if(pNpc && pNpc->IsSynFlag() && pNpc->IsSynMoneyEmpty())
		{
			nDamage	*= SYNWAR_NOMONEY_DAMAGETIMES;
		} 

		if (nDamage > 0)
		{
			if (::RandGet(10) == 7)
				this->SendGemEffect();
		}
		
		pTarget->BeAttack(IsSimpleMagicAtk(), QueryRole(), nDamage);
	}		

	CGameMap* pMap = this->GetMap();
	if (pMap)
	{
		// crime
		if (!pTarget->IsEvil()				// 只有pk白名才闪蓝
				&& !pMap->IsDeadIsland())	// 死亡岛杀人不闪蓝
		{
			if (!QueryStatus(STATUS_CRIME))
				this->SetCrimeStatus();
		}

		// equipment durability cost
		if (!pMap->IsTrainMap())
			this->DecEquipmentDurability(ATTACK_TIME, IsSimpleMagicAtk(), (nDamage < nAtk/10) ? 10 : 1);
	}

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

	return nDamage;
}

//////////////////////////////////////////////////////////////////////
bool CUser::BeAttack(bool bMagic, IRole* pTarget, int nPower, bool bReflectEnable/*=true*/)
{
	CHECKF(pTarget);

	QueryStatusSet()->DelObj(STATUS_LURKER);
	CRole::DetachStatus(this->QueryRole(), STATUS_FREEZE);
	StopMine();

	// reflect, only use for weapon attack!!!
	IStatus* pStatus = QueryStatus(bMagic?STATUS_REFLECTMAGIC:STATUS_REFLECT);
	if(nPower>0 && pStatus && bReflectEnable)
	{
		int nPower2 = AdjustData(nPower, pStatus->GetPower());
		if(nPower2 > 0)
		{
			int nLoseLife = ::CutOverflow((int)pTarget->GetLife(), nPower2);
			pTarget->AddAttrib(_USERATTRIB_LIFE, -1*nLoseLife, SYNCHRO_TRUE);
			pTarget->BeAttack(bMagic, this, nPower2, false);

			// 传送结果消息
			CMsgInteract msg;
			if (msg.Create(bMagic?INTERACT_REFLECTMAGIC:INTERACT_REFLECTWEAPON, GetID(), pTarget->GetID(), GetPosX(), GetPosY(), nPower2))
				BroadcastRoomMsg(&msg, INCLUDE_SELF);

			// kill?
			if (!pTarget->IsAlive())
				pTarget->BeKill();
		}
	}

	// equipment durability cost
	if (!this->GetMap()->IsTrainMap())
	{
		this->DecEquipmentDurability(BEATTACK_TIME, bMagic, (nPower > this->GetMaxLife()/4) ? 10 : 1);
	}

	// self_defence     // add huang 2004.1.14
//	if(QueryStatus(STATUS_SELFDEFENCE))
//		this->SetSelfDefStatus();
	
	if(nPower > 0)
		BroadcastTeamLife();

	// abort magic
	if (QueryMagic() && QueryMagic()->IsIntone())
		QueryMagic()->AbortMagic(true);

	/*/ stamina lost
	if (_ACTION_SITDOWN ==  this->GetPose())
	{
		this->SetPose(_ACTION_STANDBY);
		this->SetAttrib(_USERATTRIB_ENERGY, this->GetEnergy()/2, SYNCHRO_TRUE);
	}*/

	return true;
}

//////////////////////////////////////////////////////////////////////
void CUser::SendDamageMsg(OBJID idTarget, int nDamage)
{
	OBJID idMagicType = ID_NONE;
	if(QueryTransformation())
		idMagicType = QueryTransformation()->GetMagicType();

	if(idMagicType != ID_NONE)
	{
		CMsgMagicEffect	msg;
		IF_OK(msg.Create(GetID(), idMagicType, 0, idTarget, nDamage, GetDir()))
			BroadcastRoomMsg(&msg, INCLUDE_SELF);
	}
	else if(IsBowman())
	{
		CMsgInteract msg;
		IF_OK(msg.Create(INTERACT_SHOOT, GetID(), idTarget, GetPosX(), GetPosY(), nDamage))
			BroadcastRoomMsg(&msg, INCLUDE_SELF);
	}
	else
	{
		CMsgInteract msg;
		IF_OK(msg.Create(INTERACT_ATTACK, GetID(), idTarget, GetPosX(), GetPosY(), nDamage))
			BroadcastRoomMsg(&msg, INCLUDE_SELF);
	}
}

//////////////////////////////////////////////////////////////////////
bool CUser::TransferShield(bool bMagic, IRole* pAtker, int nDamage)
{
	IStatus* pStatus = QueryStatus(STATUS_TRANSFER_SHIELD);
	if (!pStatus)
		return false;

	int nMagicType = pStatus->GetPower();
	vector<CMonster*>	setEudemon;

	// 寻找符合条件的已出征幻兽
	for (int i=0; i<this->GetEudemonAmount(); i++)
	{
		CMonster* pEudemon = this->QueryEudemonByIndex(i);
		if (pEudemon && pEudemon->QueryMagic() && pEudemon->QueryMagic()->FindMagic(nMagicType))
			setEudemon.push_back(pEudemon);
	}

	if (setEudemon.empty())
		return false;

	nDamage = nDamage/setEudemon.size();
	for (i=0; i<setEudemon.size(); i++)
	{
		int nLostLife = ::CutOverflow(nDamage, (int)setEudemon[i]->GetLife());
		if (nLostLife>0)
			setEudemon[i]->AddAttrib(_USERATTRIB_LIFE, -1*nLostLife, SYNCHRO_TRUE);
		setEudemon[i]->BeAttack(bMagic, pAtker, nDamage);

		// 这里这样处理在连招中应用会导致先杀死后出连招动作的bug
		// 等待确定解决方案
		if (!setEudemon[i]->IsAlive())
			pAtker->Kill(setEudemon[i], bMagic?DIE_MAGIC:DIE_NORMAL);
	}
	return true;
}

//////////////////////////////////////////////////////////////////////
bool CUser::BroadcastTeamLife(bool bMaxLife)
{
	// 2003.2.13 如果对方是玩家而且组队了。被攻击玩家去血值要在队内广播。
	CTeam* pTeam	= GetTeam();
	if (pTeam && pTeam->GetMemberAmount() > 1)
	{
		pTeam->BroadcastMemberLife(this, bMaxLife);
		return true;
	}
	return false;
}

//////////////////////////////////////////////////////////////////////
bool CUser::DecEquipmentDurability(bool bBeAttack, bool bMagic, int bDurValue/*=1*/)
{
	int nInc = -1 * bDurValue;
	for(int i = ITEMPOSITION_EQUIPBEGIN; i < ITEMPOSITION_EQUIPEND; i++)
	{
		if (!bMagic)
		{
			if (i == ITEMPOSITION_RINGR || 
					i == ITEMPOSITION_RINGL ||
						i == ITEMPOSITION_SHOES ||
							i == ITEMPOSITION_WEAPONR ||
								i == ITEMPOSITION_WEAPONL)
			{
				if(!bBeAttack)
					AddEquipmentDurability(i, nInc);
			}
			else
			{
				if(bBeAttack)
					AddEquipmentDurability(i, nInc);
			}
		}
		else
		{
			if (i == ITEMPOSITION_RINGR || 
					i == ITEMPOSITION_RINGL ||
						i == ITEMPOSITION_SHOES ||
							i == ITEMPOSITION_WEAPONR ||
								i == ITEMPOSITION_WEAPONL)
			{
				if(!bBeAttack)
					AddEquipmentDurability(i, -5);
			}
			else
			{
				if(bBeAttack)
					AddEquipmentDurability(i, nInc);
			}
		}
	}
	return true;
}

//////////////////////////////////////////////////////////////////////
bool CUser::MagicAttack(int nType, OBJID idTarget, int x, int y)
{
	if (QueryMagic())
		return QueryMagic()->MagicAttack(nType, idTarget, x, y);
	return false;
}

//////////////////////////////////////////////////////////////////////
int	CUser::CalcExpLostOfDeath (IRole* pKiller)
{
	CUser* pUserKiller = NULL;
	if (!pKiller->QueryObj(OBJ_USER, IPP_OF(pUserKiller)))
		return 0;

	// normal condition
	int nParam = 50;
	if (this->GetEffect()&KEEPEFFECT_RED)
		nParam = 10;
	else if (this->GetEffect()&KEEPEFFECT_DEEPRED)
		nParam = 5;
	else
		nParam = 50;

	int nExpLost = __max(0, this->GetExp()/nParam);

	//if (true)
	//	return nExpLost;

	// syndicate member && not the killer wanted guy
	if (this->GetSynID() != ID_NONE && !pUserKiller->IsMyWantedTarget(this))
	{
		int nDecPercent = 0;
		CSyndicate* pSyn = this->GetSyndicate();
		IF_OK (pSyn)
		{
			int nExpPayBySyn = 0;
			int nProffer = this->QuerySynProffer();
			if (nProffer > 0)
			{			
				int nRank = this->QuerySynRank();
//				switch(nRank)
//				{
//				case RANK_LEADER:
//					nDecPercent = 80;
//					break;
//
//				case RANK_SUBLEADER:
//					nDecPercent = 60;
//					break;
//				case RANK_TEAMLEADER:
//					nDecPercent = 40;
//					break;
//				default:
//					nDecPercent = 25;
//					break;
//				}
	

				CONST MONEYCOST_PEREXP = 100;
				int nFundSyn  = pSyn->GetInt(SYNDATA_MONEY);
				int nFundLost = ::MulDiv(nExpLost, nDecPercent, 100*MONEYCOST_PEREXP);	// 100点经验1两
				if (nFundLost > nFundSyn)
					nFundLost = nFundSyn;

				pSyn->QueryModify()->AddData(SYNDATA_MONEY, -1*nFundLost, true);

				if (nRank != RANK_LEADER)
					this->SetSynProffer(nProffer-nFundLost);

				nExpPayBySyn = nFundLost*MONEYCOST_PEREXP;
				nExpLost -= nExpPayBySyn;//nFundLost*MONEYCOST_PEREXP;
			}
			else
			{
				if (pSyn->IsWhiteSynMapOwner() || pSyn->IsBlackSynMapOwner())
				{
					nDecPercent = 20;
				}
				else
				{
					nDecPercent = 10;
				}

				CONST MONEYCOST_PEREXP = 100;
				int nFundSyn  = pSyn->GetInt(SYNDATA_MONEY);
				int nFundLost = ::MulDiv(nExpLost, nDecPercent, 100*MONEYCOST_PEREXP);	// 100点经验1两
				if (nFundLost > nFundSyn)
					nFundLost = nFundSyn;

				pSyn->QueryModify()->AddData(SYNDATA_MONEY, -1*nFundLost, true);

				if (this->QuerySynRank() != RANK_LEADER)
					this->SetSynProffer(nProffer-nFundLost);

				nExpPayBySyn = nFundLost*MONEYCOST_PEREXP;
				nExpLost -= nExpPayBySyn;//nFundLost*MONEYCOST_PEREXP;
			}

			this->SendSysMsg(_TXTATR_NORMAL, EXPLOST_PAYBY_SYNFUND, nExpPayBySyn);
		}
	}

	return __max(0, nExpLost);
}

//////////////////////////////////////////////////////////////////////
void CUser::Kill(IRole* pTarget, DWORD dwDieWay)
{
	CHECK(pTarget);

	// inc xp
	USHORT usRemainTime = 0;
//	IStatus* pStatus = QueryStatus(STATUS_XPFULL);
//	if (pStatus && pTarget->IsMonster())
//	{
//		pStatus->IncTime(ADD_XPFULL_SECS_KILLMONSTER*1000, MAX_XPFULL_SECS*1000);
//		m_nCurrSupermanKills++;
//		StatusInfoStruct	info;
//		if (pStatus->GetInfo(&info))
//			usRemainTime = info.nSecs;
//	}

	CMsgInteract msg;
	if(msg.Create(INTERACT_KILL, this->GetID(), pTarget->GetID(), pTarget->GetPosX(), pTarget->GetPosY(), dwDieWay, usRemainTime))
		pTarget->BroadcastRoomMsg(&msg, true);

	// earth magic
	//???

	if (QueryMagic())
		QueryMagic()->UserKillTarget(pTarget);

	CUser* pTargetUser	= NULL;
	if(!pTarget->QueryObj(OBJ_USER, IPP_OF(pTargetUser)))
	{
		pTarget->BeKill((IRole*)this);		// NPC return
		return;
	}

	ProcessPk(pTargetUser);

	// target...
	pTarget->BeKill((IRole*)this);
}

//////////////////////////////////////////////////////////////////////
void CUser::ProcessPk (CUser* pTargetUser)
{
	ASSERT(pTargetUser);

	// map...
	CGameMap* pMap = MapManager()->QueryMap(this->GetMapID());
	IF_OK (pMap) 
	{
		if (pMap->IsPkField())
		{
		}
		else if (pMap->IsPkGameMap())
		{
			pTargetUser->DelAllBadge();
			AddBadge();
		}
		else if (pMap->IsSynMap())
		{
		}
		else if (pMap->IsPrisonMap())
		{
		}
		else
		{
			// innocent kill      //change huang 2004.1.11
			if (!(pTargetUser->GetEffect()&KEEPEFFECT_RED) 
					&& !(pTargetUser->GetEffect()&KEEPEFFECT_DEEPRED))
			{
				if (this->G

⌨️ 快捷键说明

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