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

📄 magic.cpp

📁 网络游戏魔域的服务端与客户端完整源代码 包括详细的说明文档与开发日志
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// 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 "RoleManager.h"
//#include "UserTable.h"
#include "AiNpc.h"

char			szMagicTable[] = _TBL_MAGIC;
const OBJID		MIN_TEMPORARY_MAGICID	= (DWORD)40*10000*10000 + 1;
long			CMagic::m_lockNextID	= (long)MIN_TEMPORARY_MAGICID;		// temporary magic id, use for "next magic" id.
//////////////////////////////////////////////////////////////////////
unsigned char	Prof2MaskTable[] = {
	10,			// 魔法师
	11,			// 魔法师转职
	20,			// 战士
	21,			// 战士转职
	30,			// 异能者
	31,			// 异能者转职
};

const int	MAX_USER_PROFS = sizeof(Prof2MaskTable)/sizeof(Prof2MaskTable[0]);

//////////////////////////////////////////////////////////////////////
const DWORD MASK_ALLPROF	= 0;
DWORD	Prof2Mask(int nProf)		// return ERROR_MASK : error
{
	for(int i = 0; i < MAX_USER_PROFS; i++)
		if(Prof2MaskTable[i] == nProf)
			return 1 << i;
	return 0;				// 其它职业
}

MYHEAP_IMPLEMENTATION(CMagicData,s_heap)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMagicData::~CMagicData()
{
	SAFE_RELEASE (m_pData);
}

//////////////////////////////////////////////////////////////////////
IMagicData* IMagicData::CreateNew()
{
	// 缺省是创建CMagicData
	return CMagicData::CreateNew();
}

//////////////////////////////////////////////////////////////////////
bool CMagicData::Create(IRecordset* pDefaultRecord, OBJID idNewKey)
{
	m_pData	= CMagicDataBase::CreateNew();
	if (m_pData && m_pData->Create(pDefaultRecord, idNewKey))
	{
		return true;
	}

	SAFE_RELEASE (m_pData);
	return false;
}

//////////////////////////////////////////////////////////////////////
bool CMagicData::Create(IRecordset* pRecordset)
{
	m_pData	= CMagicDataBase::CreateNew();
	if (m_pData && m_pData->Create(pRecordset))
	{
		SetDelay();
		return true;
	}
	
	SAFE_RELEASE (m_pData);
	return false;
}

//////////////////////////////////////////////////////////////////////
bool CMagicData::Create(ST_MAGIC_DATA* pMagicData)
{
	ASSERT(!"CMagicData::Create(ST_MAGIC_DATA* pMagicData)");
	return false;
}

//////////////////////////////////////////////////////////////////////
int CMagicData::GetInt(MAGICDATA nDataName)
{
//	CHECKF(m_pType);
	CHECKF (m_pData);

	if(m_pType == NULL)
	{
		IF_NOT(FindType())
		{
			LOGERROR("魔法找不到类型。type[%d],level[%d]", m_pData->GetInt(MAGICDATA_TYPE), m_pData->GetInt(MAGICDATA_LEVEL));
			return false;
		}
	}
	
	if(nDataName < MAGICTYPEDATA_OFFSET)
		return m_pData->GetInt(nDataName);

	return m_pType->GetInt((MAGICTYPEDATA)(nDataName - MAGICTYPEDATA_OFFSET));
}

//////////////////////////////////////////////////////////////////////
void CMagicData::SetInt(MAGICDATA idx, int nData)
{
	ASSERT(idx < MAGICTYPEDATA_OFFSET);

	m_pData->SetInt(idx, nData);

	if(idx == MAGICDATA_LEVEL)
	{
		CHECK(FindType());
	}
}

//////////////////////////////////////////////////////////////////////
bool CMagicData::FindType()
{
	m_pType = CMagic::FindMagicType(m_pData->GetInt(MAGICDATA_TYPE), m_pData->GetInt(MAGICDATA_LEVEL));
	return (m_pType != NULL);
}

//////////////////////////////////////////////////////////////////////
// 本来因该在MagicData.cpp中实现的
// 由于旧有代码的头文件包含比较复杂,暂时简单处理写在这里
bool CMagicTempData::FindType()
{
	m_pType = CMagic::FindMagicType(m_data.usType, m_data.usLevel);
	return (m_pType != NULL);
}

//////////////////////////////////////////////////////////////////////
//int CMagicData::GetApplyMS()
//{
//	int nApplyMS = 0;
//	if (this->GetSTrackAmount() > 0)
//	{
//		for (int i=0; i<this->GetSTrackAmount(); i++)
//		{
//			const ST_TRACK&	track = this->GetSTrackByIndex(i);
//			nApplyMS += track.nApplyMS;
//		}
//	}
//	else
//		nApplyMS = GetInt(MAGICDATA_APPLY_MS);
//
//	return nApplyMS;
//}

//////////////////////////////////////////////////////////////////////
//int CMagicData::GetLockSecs()
//{
//	return (GetApplyMS()/1000+1);
//}

MYHEAP_IMPLEMENTATION(CMagic,s_heap)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMagic::CMagic(PROCESS_ID idProcess, IRole* pRole)
	: m_nMagicState(MAGICSTATE_NONE), m_nApplyTimes(0), m_bTargetLocked(false)
{
	ASSERT (pRole);

	m_idProcess = idProcess;
	m_pOwner		= pRole;

	m_setData	= CMagicSet::CreateNew(true);
	m_pMagic	= NULL;

	//m_nRawDelay = MAGIC_DELAY - MAGIC_DECDELAY_PER_LEVEL*m_pOwner->GetProfessionLevel();
	//ASSERT(m_nRawDelay >= 500);

	m_nRawDelay = 800;

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

	m_tIntone.Clear();
	m_tApply.Clear();
}

//////////////////////////////////////////////////////////////////////
CMagic::~CMagic()
{
	if(m_setData)
		m_setData->Release();
}

//////////////////////////////////////////////////////////////////////
int CMagic::GetDieMode()
{
	return HitByMagic()?DIE_MAGIC:(m_pOwner->IsBowman()?DIE_ARROWSHOOT:DIE_NORMAL);
}

//////////////////////////////////////////////////////////////////////
CMagic* CMagic::CreateNew(PROCESS_ID idProcess, IRole* pRole)
{
	CHECKF (pRole);
	
	CMagic* pMagic = new CMagic(idProcess, pRole);
	CHECKF(pMagic);

	pMagic->m_idProcess = idProcess;
	pMagic->m_pOwner		= pRole;

	return pMagic;
}

//////////////////////////////////////////////////////////////////////
// login
//////////////////////////////////////////////////////////////////////
bool CMagic::CreateAll()
{
	CHECKF(CMapGroup::IsValidMapGroupProcessID(m_idProcess));
	CHECKF(m_setData);
	CHECKF(m_pOwner);

	SQLBUF	szSQL;
#ifdef	PALED_DEBUG_X
	sprintf(szSQL, "SELECT * FROM %s WHERE ownerid=%u && unlearn=0 XXXXXXXX", _TBL_MAGIC, m_pOwner->GetID());
#else
	sprintf(szSQL, "SELECT * FROM %s WHERE ownerid=%u && unlearn=0", _TBL_MAGIC, m_pOwner->GetID());
#endif
	CHECKF(m_setData->Create(szSQL, Database()));

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::SendInfoToClient()
{
	for(int i = m_setData->GetAmount()-1; i >= 0; i--)
	{
		IMagicData* pData = m_setData->GetObjByIndex(i);
		if(pData && pData->GetInt(MAGICDATA_TYPE))
		{
			if(!IsWeaponMagic(pData->GetInt(MAGICDATA_TYPE)))
			{
				if(CMagic::FindMagicType(pData->GetInt(MAGICDATA_TYPE), pData->GetInt(MAGICDATA_LEVEL)))
				{
					// 含AUTOACTIVE_HIDDEN掩码的魔法隐藏不显示
					if ((pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_HIDDEN) == 0)
					{
						CMsgMagicInfo msg;
						IF_OK(msg.Create(m_pOwner->GetID(),
										pData->GetInt(MAGICDATA_TYPE),
										pData->GetInt(MAGICDATA_LEVEL),
										pData->GetInt(MAGICDATA_EXP)))
							m_pOwner->SendMsg(&msg);
					}
				}
				else
				{
					LOGWARNING("角色学习了非法魔法: [%s][%d].", m_pOwner->GetName(), m_pOwner->GetID());
					m_setData->DelObj(pData->GetID());
				}
			}
		}
		else
		{
			LOGWARNING("角色学习了非法魔法: [%s][%d]", m_pOwner->GetName(), m_pOwner->GetID());
		}
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
// MapGroup
//////////////////////////////////////////////////////////////////////
bool CMagic::SaveInfo()
{
	for(int i = 0; i < m_setData->GetAmount(); i++)
	{
		IMagicData* pData = m_setData->GetObjByIndex(i);
		IF_OK(pData)
		{
			if(!IsWeaponMagic(pData->GetInt(MAGICDATA_TYPE)))
				pData->Update();
		}
	}
	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::GetInfoByIndex(MagicInfoStruct* pInfo, int idx)
{
	CHECKF(pInfo);
	CHECKF(idx >= 0 && idx < m_setData->GetAmount());

	IMagicData* pData = m_setData->GetObjByIndex(idx);
	IF_OK(pData)
	{
		pInfo->id		= pData->GetID();
		pInfo->idOwner	= m_pOwner->GetID();
		pInfo->nType	= pData->GetInt(MAGICDATA_TYPE);
		pInfo->nLevel	= pData->GetInt(MAGICDATA_LEVEL);
		pInfo->dwExp	= pData->GetInt(MAGICDATA_EXP);
		return true;
	}
	return false;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::AppendMagic(const MagicInfoStruct* pInfo)
{
	IMagicData* pData = NULL;
	if (pInfo->id >= MIN_TEMPORARY_MAGICID)
	{
		pData = CMagicTempData::CreateNew();
		CHECKF (pData);
		ST_MAGIC_DATA	data;
		memset(&data, 0L, sizeof(ST_MAGIC_DATA));
		data.idMagic	= pInfo->id;
		IF_NOT (pData->Create(&data))
			return false;
	}
	else
	{
		pData = CMagicData::CreateNew();
		CHECKF(pData);
		IF_NOT(pData->Create(GameDataDefault()->GetMagicData(), pInfo->id))
			return false;
	}

	pData->SetInt(MAGICDATA_OWNERID, pInfo->idOwner);
	pData->SetInt(MAGICDATA_TYPE, pInfo->nType);
	pData->SetInt(MAGICDATA_LEVEL, pInfo->nLevel);
	pData->SetInt(MAGICDATA_EXP, pInfo->dwExp);
	pData->ClearUpdateFlags();
	pData->FindType();

	m_setData->AddObj(pData);
	return true;
}

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

	if(!m_pOwner->IsAtkable(pRole))
		return true;

	if(pRole->IsWing() && !m_pOwner->IsWing() && m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) && m_pMagic->GetInt(MAGICDATA_WEAPON_SUBTYPE) != BOW_SUBTYPE)
		return true;

	return m_pOwner->IsImmunity(pRole);
}

//////////////////////////////////////////////////////////////////////
// application
//////////////////////////////////////////////////////////////////////
IMagicData* CMagic::FindMagic(int nType)
{
	for(int i = 0; i < m_setData->GetAmount(); i++)
	{
		IMagicData* pData = m_setData->GetObjByIndex(i);
		if(pData && pData->GetInt(MAGICDATA_TYPE) == nType)
			return pData;
	}
	return NULL;
}

//////////////////////////////////////////////////////////////////////
CMagicTypeData* CMagic::FindMagicType(int nType, int nLevel)
{
	for(int i = 0; i < MagicTypeSet()->GetAmount(); i++)
	{
		CMagicTypeData* pType = MagicTypeSet()->GetObjByIndex(i);
		if(pType && pType->GetInt(MAGICTYPEDATA_TYPE) == nType && pType->GetInt(MAGICTYPEDATA_LEVEL) == nLevel)
			return pType;
	}
	return NULL;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::AwardExpOfLife(IRole* pTarget, int nLifeLost, BOOL bMagicRecruit/*=false*/)
{
	CNpc* pNpc;
	pTarget->QueryObj(OBJ_NPC, IPP_OF(pNpc));
	if(pNpc && pNpc->IsAwardScore() && !bMagicRecruit)
	{
		m_pOwner->AwardSynWarScore(pNpc, nLifeLost);
	}
	if(pTarget->IsMonster() || pNpc && pNpc->IsGoal())
	{
		// correct exp here
		int nExp = m_pOwner->AdjustExp(pTarget, nLifeLost);

		// kill bonus
		if (!pTarget->IsAlive() && !bMagicRecruit) // target was killed
		{
			int	nBonusExp	= pTarget->GetMaxLife()*KILLBONUS_PERCENT/100;
			nExp += nBonusExp;
			
			// 有组队,并且队伍中有其他队员,则奖励其他队员经验
			OtherMemberAwardExp(pTarget, nBonusExp);

			if (!m_pOwner->GetMap()->IsTrainMap() && nBonusExp > 0)
			{
				m_pOwner->SendSysMsg(STR_KILLING_EXPERIENCE, nBonusExp);
			}
		}

		this->AwardExp(nExp);
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::AwardExp(int nType, int nBattleExp, int nExp)
{
	IMagicData* pData = FindMagic(nType);
	if (!pData)
		return false;

	IMagicData* pMagic = m_pMagic;
	m_pMagic	= pData;

	bool bRet = false;
	DEBUG_TRY
	bRet = AwardExp(nBattleExp, nExp, true);
	DEBUG_CATCH("CMagic::AwardExp(nBattleExp, nExp)")
	m_pMagic	= pMagic;
	return bRet;
}

//////////////////////////////////////////////////////////////////////
bool CMagic::AwardExp(int nBattleExp, int nExp, bool bIgnoreFlag)
{
	CHECKF(m_pMagic);

	if(nExp <= 0)
		return false;
	
	if(m_pOwner->GetMap()->IsTrainMap())
	{
//		if(nExp == AWARDEXP_BY_TIMES && 
//			(m_pMagic->GetInt(MAGICDATA_SORT) == MAGICSORT_ATTACHSTATUS
//				|| m_pMagic->GetInt(MAGICDATA_SORT)	== MAGICSORT_TEAM_MAGIC
//				|| m_pMagic->GetInt(MAGICDATA_SORT) == MAGICSORT_TRANSFORM
//				|| m_pMagic->GetInt(MAGICDATA_SORT) == MAGICSORT_ATKSTATUS
//				))
//		{
//			if(::RandGet(20) == 0)
//				nExp = AWARDEXP_BY_TIMES;
//			else
//				nExp = 0;
//		}
//		else
//		{
//			if(m_pOwner->IsBowman())
//				nExp	/= 2;
//			nExp = ::CutTrail(1, MulDiv(nExp, GOAL_EXP_PERCENT, 100));
//		}

		if(nBattleExp)
		{
			if(m_pOwner->IsBowman())
				nBattleExp	/= 2;
			nBattleExp = ::CutTrail(1, MulDiv(nBattleExp, GOAL_EXP_PERCENT, 100));
		}
	}

	// 战斗经验值
	if(nBattleExp)
		m_pOwner->AwardBattleExp(nBattleExp);

	if(!CheckAwardExpEnable(m_pOwner->GetProfession()))
		return false;

	if(m_pMagic->GetInt(MAGICDATA_NEED_EXP) >= 0									// >=0 : 可以升级

⌨️ 快捷键说明

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