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