📄 magic.cpp
字号:
if(m_pMagic && m_pMagic->GetID() == idMagic)
{
m_pMagic = NULL;
m_bAutoAttack = false;
}
return m_setData->DelObj(idMagic);
}
//////////////////////////////////////////////////////////////////////
// calc magic fight
//////////////////////////////////////////////////////////////////////
int CMagic::CalcMagicPower(IRole* pAtker, IRole* pTarget, int* pAdjustAtk/*=0*/)
{
// attack
int nMaxRand = 50 + pAtker->GetLuck();
int nAtk = 0;
if(::RandGet(100) < nMaxRand)
nAtk = pAtker->GetMgcMaxAtk() - ::RandGet((pAtker->GetMgcMaxAtk()-pAtker->GetMgcMinAtk()) / 2);
else
nAtk = pAtker->GetMgcMinAtk() + ::RandGet((pAtker->GetMgcMaxAtk()-pAtker->GetMgcMinAtk()) / 2);
nAtk = pAtker->AdjustMagicAtk(nAtk);
/*CUser* pUser;
if(pAtker->QueryObj(OBJ_USER, IPP_OF(pUser)))
{
nAtk = __max(0, nAtk + pUser->GetMagicAtk());
nAtk += nAtk*pUser->GetGemMgcAtkEffect()/100;
}*/
if(pAdjustAtk)
{
if(*pAdjustAtk)
nAtk = ::CutTrail(0, CRole::AdjustDataEx(nAtk, *pAdjustAtk));
*pAdjustAtk = nAtk;
}
int nDef = pTarget->GetMagicDef();
nDef = pTarget->AdjustMagicDef(nDef);
// damage
int nDamage = nAtk - nDef;
if (pAtker->QueryOwnerUser() && pTarget->IsMonster())
{
CMonster* pMonster;
if(pTarget->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)) && !pMonster->IsEquality())
nDamage = CBattleSystem::CalcDamageUser2Monster(nAtk, nDef, pAtker->GetLev(), pTarget->GetLev());
nDamage = pTarget->AdjustMagicDamage(nDamage);
nDamage = CBattleSystem::AdjustMinDamageUser2Monster(nDamage, pAtker, pTarget);
}
else if(pAtker->IsMonster() && pTarget->QueryOwnerUser())
{
CMonster* pMonster;
if(pAtker->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)) && !pMonster->IsEquality())
nDamage = CBattleSystem::CalcDamageMonster2User(nAtk, nDef, pAtker->GetLev(), pTarget->GetLev());
nDamage = pTarget->AdjustMagicDamage(nDamage);
nDamage = CBattleSystem::AdjustMinDamageMonster2User(nDamage, pAtker, pTarget);
}
else
{
// adjust magic damage
nDamage = pTarget->AdjustMagicDamage(nDamage);
}
// adjust synflag damage
CNpc* pNpc = NULL;
pTarget->QueryObj(OBJ_NPC, IPP_OF(pNpc));
if(pNpc && pNpc->IsSynFlag() && pNpc->IsSynMoneyEmpty())
nDamage *= SYNWAR_NOMONEY_DAMAGETIMES;
return ::CutTrail(1, nDamage);
}
//////////////////////////////////////////////////////////////////////
bool CMagic::CheckAwardExpEnable(DWORD dwProf)
{
CHECKF(m_pMagic);
return m_pOwner->GetLev() >= m_pMagic->GetInt(MAGICDATA_NEED_LEVEL)
&& m_pMagic->GetInt(MAGICDATA_NEED_EXP) != AUTOLEVELUP_EXP
&& m_pMagic->GetInt(MAGICDATA_NEED_EXP) != DISABLELEVELUP_EXP
&& this->CheckProfession(dwProf, m_pMagic->GetInt(MAGICDATA_NEED_PROFMASK))
// && m_pMagic->GetInt(MAGICDATA_USE_XP) != TYPE_KONGFU
;
}
//////////////////////////////////////////////////////////////////////
void CMagic::OtherMemberAwardExp(IRole* pTarget, int nRawExp)
{
if(m_pOwner->GetMap()->IsTrainMap())
return ;
CTeam* pTeam = m_pOwner->GetTeam();
if (pTeam)
{
pTeam->AwardMemberExp(m_pOwner->GetID(), pTarget, nRawExp);
}
CUser* pUser = NULL;
if (m_pOwner->QueryObj(OBJ_USER, IPP_OF(pUser)))
{
for (int i=0; i<pUser->GetEudemonAmount(); i++)
{
CMonster* pEudemon = pUser->QueryEudemonByIndex(i);
if (pEudemon && pEudemon->IsAlive() &&
(abs(pEudemon->GetPosX()-pTarget->GetPosX()) <= _RANGE_EXPSHARE
|| abs(pEudemon->GetPosY()-pTarget->GetPosY()) <= _RANGE_EXPSHARE))
{
int nBattleExp = pEudemon->AdjustExp(pTarget, nRawExp);
bool bIncludeOwner = false;
pEudemon->AwardBattleExp(nBattleExp, true, bIncludeOwner);
}
}
}
}
//////////////////////////////////////////////////////////////////////
int CMagic::GetExtendAtkRange (CItem* pWeaponR, CItem* pWeaponL)
{
CHECKF(m_pOwner);
int nRange = 0;
for(int i = 0; i < m_setData->GetAmount(); i++)
{
IMagicData* pData = m_setData->GetObjByIndex(i);
if (pData
&& (pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_FOREVER)
&& MAGICSORT_ATKRANGE == pData->GetInt(MAGICDATA_SORT))
{
int nWeaponRequired = pData->GetInt(MAGICDATA_WEAPON_SUBTYPE);
if (0 == nWeaponRequired
|| (pWeaponR && pWeaponR->GetItemSubType() == nWeaponRequired)
|| (pWeaponL && pWeaponL->GetItemSubType() == nWeaponRequired))
{
nRange += GetPower();
}
}
}
return nRange;
}
//////////////////////////////////////////////////////////////////////
int CMagic::HitByMagic()
{
CHECKF(m_pMagic);
if(m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) == HIT_BY_MAGIC)
{
if (m_pMagic->GetInt(MAGICDATA_USE_XP) == TYPE_XPSKILL)
return MAGICTYPE_XPSKILL;
else
return MAGICTYPE_NORMAL;
}
CItem* pItem = m_pOwner->GetEquipItemByPos(ITEMPOSITION_WEAPONL);
if(m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) == HIT_BY_ITEM && pItem && pItem->GetMgcMinAtk() > 0) // ->GetInt(ITEMDATA_MAGICATK_MIN) > 0)
{
if (m_pMagic->GetInt(MAGICDATA_USE_XP) == TYPE_XPSKILL)
return MAGICTYPE_XPSKILL;
else
return MAGICTYPE_NORMAL;
}
return MAGICTYPE_NONE;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::HitByWeapon()
{
CHECKF(m_pMagic);
if(m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) == HIT_BY_WEAPON)
return true;
CItem* pItem = m_pOwner->GetEquipItemByPos(ITEMPOSITION_WEAPONL);
if(m_pMagic->GetInt(MAGICDATA_WEAPON_HIT) == HIT_BY_ITEM && pItem && pItem->GetMgcMinAtk() <= 0) // ->GetInt(ITEMDATA_MAGICATK_MIN) <= 0)
return true;
return false;
}
//////////////////////////////////////////////////////////////////////
void CMagic::ResetDelay()
{
CHECK(m_pMagic);
m_nDelay = m_nRawDelay;
m_nMagicState = MAGICSTATE_DELAY;
m_tDelay.Update(); // 开始DELAY
// 启动 每个魔法单独的延迟计时器
if (m_pMagic)
m_pMagic->StartDelay();
}
//////////////////////////////////////////////////////////////////////
// bAtkerPenetrable: 攻击者移动轨迹是否可以穿人
// bTargetPenetrable: 被攻击者移动轨迹是否可以穿人
bool CMagic::AdjustPosByTrack(int nStepIndex, bool bAtkerPenetrable/*=false*/, bool bTargetPenetrable/*=false*/)
{
CHECKF(m_pOwner);
CHECKF(m_pMagic);
CMapPtr pMap = m_pOwner->GetMap();
if (!pMap)
return false;
// record target pos
int nTargetPosX = m_pOwner->GetPosX();
int nTargetPosY = m_pOwner->GetPosY();
IRole* pTarget = RoleManager()->QueryRole(m_idTarget);
if (pTarget)
{
nTargetPosX = pTarget->GetPosX();
nTargetPosY = pTarget->GetPosY();
}
if (nStepIndex >= 0 && nStepIndex < m_pMagic->GetTTrackAmount())
{
// 取轨迹
const ST_TRACK& track = m_pMagic->GetTTrackByIndex(nStepIndex);
for (int i=0; i<m_setTargetLocked.size(); i++)
{
DEBUG_TRY
OBJID idTarget = m_setTargetLocked[i];
if (idTarget == ID_NONE)
continue;
IRole* pTarget = m_pOwner->FindAroundRole(idTarget);
if (!pTarget)
continue;
int nNewX = pTarget->GetPosX();
int nNewY = pTarget->GetPosY();
// 取得攻击方向
UCHAR ucAtkDir = ::GetDirByPos(m_pOwner->GetPosX(), m_pOwner->GetPosY(), pTarget->GetPosX(), pTarget->GetPosY());
// 根据轨迹方向计算位移坐标
int nMoveDir = (ucAtkDir + track.ucDir) % 8;
for (int i=0; i<track.ucStep; i++)
{
int nTmpX = (nNewX + _DELTA_X[nMoveDir]);
int nTmpY = (nNewY + _DELTA_Y[nMoveDir]);
if (pMap->IsMoveEnable(nNewX, nNewY, nTmpX, nTmpY, track.ucAlt)
|| (bTargetPenetrable && pMap->IsStandEnable(nTmpX, nTmpY)))
{
nNewX = nTmpX;
nNewY = nTmpY;
}
}
// if (nNewX != pTarget->GetPosX() || nNewY != pTarget->GetPosY())
{
#ifdef _DEBUG
CUser* pTargetUser = NULL;
if (pTarget->QueryObj(OBJ_USER, IPP_OF(pTargetUser)))
{
// ::MyLogSave("syslog\\magic", "Debug: track step [%d], move from [%d, %d] to [%d, %d]",
// nStepIndex, pTargetUser->GetPosX(), pTargetUser->GetPosY(), nNewX, nNewY);
pTargetUser->SendSysMsg("Debug: track step [%d], move from [%d, %d] to [%d, %d]",
nStepIndex, pTargetUser->GetPosX(), pTargetUser->GetPosY(), nNewX, nNewY);
}
#endif
pTarget->ProcessOnMove(MOVEMODE_TRACK);
pTarget->SyncTrackTo(nNewX, nNewY, (nMoveDir+4)%8, track.idAction);
}
DEBUG_CATCH("Process adjust target track error.")
} // end of for
}
// attacker track
if (nStepIndex >= 0 && nStepIndex < m_pMagic->GetSTrackAmount())
{
int nNewX = m_pOwner->GetPosX();
int nNewY = m_pOwner->GetPosY();
// 取得攻击方向
UCHAR ucAtkDir = m_pOwner->GetDir();
if (pTarget)
ucAtkDir = ::GetDirByPos(m_pOwner->GetPosX(), m_pOwner->GetPosY(), nTargetPosX, nTargetPosY);
// 根据轨迹方向计算位移坐标
const ST_TRACK& track = m_pMagic->GetSTrackByIndex(nStepIndex);
int nMoveDir = (ucAtkDir + track.ucDir) % 8;
for (int i=0; i<track.ucStep; i++)
{
int nTmpX = (nNewX + _DELTA_X[nMoveDir]);
int nTmpY = (nNewY + _DELTA_Y[nMoveDir]);
if (pMap->IsMoveEnable(nNewX, nNewY, nTmpX, nTmpY, track.ucAlt)
|| (bAtkerPenetrable && pMap->IsStandEnable(nTmpX, nTmpY)))
{
nNewX = nTmpX;
nNewY = nTmpY;
}
}
// if (nNewX != m_pOwner->GetPosX() || nNewY != m_pOwner->GetPosY())
{
#ifdef _DEBUG
// ::MyLogSave("syslog\\magic", "Debug: track step [%d], move from [%d, %d] to [%d, %d]",
// nStepIndex, m_pOwner->GetPosX(), m_pOwner->GetPosY(), nNewX, nNewY);
m_pOwner->SendSysMsg("Debug: track step [%d], move from [%d, %d] to [%d, %d]",
nStepIndex, m_pOwner->GetPosX(), m_pOwner->GetPosY(), nNewX, nNewY);
#endif
m_pOwner->ProcessOnMove(MOVEMODE_TRACK);
m_pOwner->SyncTrackTo(nNewX, nNewY, nMoveDir, track.idAction);
}
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::LockTarget(bool bLock)
{
if (m_bTargetLocked == bLock)
return true;
int nAction = actionLockUser;
if (!bLock)
nAction = actionUnlockUser;
int nLockSecs = m_pMagic->GetLockSecs();
// lock atk user
if (bLock)
{
if (m_pOwner->IsAlive())
{
CMsgAction msg;
if (msg.Create(m_pOwner->GetID(), m_pOwner->GetPosX(), m_pOwner->GetPosY(), m_pOwner->GetDir(), nAction))
{
m_pOwner->BroadcastRoomMsg(&msg, true);
CRole::AttachStatus(m_pOwner, STATUS_LOCK, 0, nLockSecs);
}
}
}
else
CRole::DetachStatus(m_pOwner, STATUS_LOCK);
// lock target
vector<OBJID>::iterator it = m_setTargetLocked.begin();
for (; it!=m_setTargetLocked.end(); it++)
{
IRole* pRole = RoleManager()->QueryRole(*it);
if (pRole)
{
if (bLock)
{
if (pRole->IsAlive())
{
CMsgAction msg;
if (msg.Create(pRole->GetID(), pRole->GetPosX(), pRole->GetPosY(), pRole->GetDir(), nAction))
{
pRole->BroadcastRoomMsg(&msg, true);
}
CRole::AttachStatus(pRole, STATUS_LOCK, 0, nLockSecs);
}
}
else
CRole::DetachStatus(pRole, STATUS_LOCK);
}
}
m_bTargetLocked = bLock;
return true;
}
//////////////////////////////////////////////////////////////////////
int CMagic::GetPower(int nStepIndex /* = -1*/)
{
CHECKF(m_pMagic);
// if (nStepIndex != -1)
// nStepIndex = m_pMagic->GetSTrackAmount() - (m_nApplyTimes + 1);
if (nStepIndex >= 0 && nStepIndex < m_pMagic->GetSTrackAmount())
{
const ST_TRACK& track = m_pMagic->GetSTrackByIndex(nStepIndex);
return track.nPower;
}
return m_pMagic->GetInt(MAGICDATA_POWER);
}
//////////////////////////////////////////////////////////////////////
/*
int CMagic::GetApplyMS(int nStepIndex / *= -1* /)
{
CHECKF(m_pMagic);
// 缺省取当前步的延迟时间
// if (nStepIndex == -1)
// nStepIndex = m_pMagic->GetSTrackAmount() - (m_nApplyTimes + 1);
if (nStepIndex >= 0 && nStepIndex < m_pMagic->GetSTrackAmount())
{
const ST_TRACK& track = m_pMagic->GetSTrackByIndex(nStepIndex);
return track.nApplyMS;
}
return m_pMagic->GetInt(MAGICDATA_APPLY_MS);
}
*/
//////////////////////////////////////////////////////////////////////
BOOL CMagic::HaveXpMagic()
{
for(int i = 0; i < m_setData->GetAmount(); i++)
{
IMagicData* pData = m_setData->GetObjByIndex(i);
if(pData && pData->GetInt(MAGICDATA_USE_XP) == TYPE_XPSKILL)
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////
// 目前设计仅用于幻兽自动学习魔法
// 如需要用于其它用途可能要做相应修改
bool CMagic::AutoLearnMagic()
{
const int MAX_AUTO_LEARN_RAND = 10000;
bool bLearnMagic = false;
DWORD dwProf = m_pOwner->GetProfession();
for(int i = 0; i < AutoMagicTypeSet()->GetAmount(); i++) //??? 可优化
{
CMagicTypeData* pData = AutoMagicTypeSet()->GetObjByIndex(i);
if(pData && pData->GetInt(MAGICTYPEDATA_AUTO_LEARN)
&& m_pOwner->GetLev() >= pData->GetInt(MAGICTYPEDATA_LEARN_LEVEL)
&& CheckProfession(dwProf, pData->GetInt(MAGICTYPEDATA_NEED_PROFMASK))
&& ::RandGet(MAX_AUTO_LEARN_RAND) < pData->GetInt(MAGICTYPEDATA_AUTO_LEARN_PROB)
&& FindMagic(pData->GetInt(MAGICTYPEDATA_TYPE)) == NULL)
{
LearnMagic(pData->GetInt(MAGICTYPEDATA_TYPE), pData->GetInt(MAGICTYPEDATA_LEVEL));
bLearnMagic = true;
}
}
return bLearnMagic;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::CheckProfession(DWORD dwProf, DWORD dwNeedProf)
{
DWORD dwProfMask = Prof2Mask(dwProf);
if (dwProfMask != 0)
{
const DWORD PROF_MASK_USER = 0x0000003F;
if ((dwNeedProf&PROF_MASK_USER) == 0 || (dwProfMask & dwNeedProf) != 0)
return true;
}
else
{
// 幻兽职业
const DWORD PROF_MASK_EVOLVE0 = 0x00003FC0;
const DWORD PROF_MASK_EVOLVE1 = 0x0000C000;
const DWORD PROF_MASK_EVOLVE2 = 0x00FF0000;
dwProfMask = 0;
DWORD dwProf1 = dwProf/100;
if (dwProf1 > 0) // 0 次进化职业,1~8
dwProfMask = 1 << (dwProf1 - 1 + MAX_USER_PROFS);
if ((dwNeedProf & PROF_MASK_EVOLVE0)!= 0 && (dwNeedProf & dwProfMask) == 0)
return false;
dwProfMask = 0;
DWORD dwProf2 = dwProf/10 % 10;
if (dwProf2 > 0) // 1 次进化职业,1~2
dwProfMask = 1 << (dwProf2 - 1 + MAX_USER_PROFS+8);
if ((dwNeedProf & PROF_MASK_EVOLVE1)!= 0 && (dwNeedProf & dwProfMask) == 0)
return false;
dwProfMask = 0;
DWORD dwProf3 = dwProf%10;
if (dwProf3 > 0) // 2 次进化职业,1~8
dwProfMask = 1 << (dwProf3 - 1 + MAX_USER_PROFS+8+2);
if ((dwNeedProf & PROF_MASK_EVOLVE2)!= 0 && (dwNeedProf & dwProfMask) == 0)
return false;
return true;
}
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -