📄 magic.cpp
字号:
// 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 + -