📄 magic.cpp
字号:
return;
DWORD dwProf = m_pOwner->GetProfession();
for(int i = 0; i < m_setData->GetAmount(); i++)
{
IMagicData* pData = m_setData->GetObjByIndex(i);
if(pData && pData->GetInt(MAGICDATA_NEED_EXP) == AUTOLEVELUP_EXP
&& pData->GetInt(MAGICDATA_USE_XP) != TYPE_KONGFU
&& nOwnerLev >= pData->GetInt(MAGICDATA_NEED_LEVEL)
&& this->CheckProfession(dwProf, pData->GetInt(MAGICDATA_NEED_PROFMASK))
&& !IsWeaponMagic(pData->GetInt(MAGICDATA_TYPE))
)
{
int nNewLevel = pData->GetInt(MAGICDATA_LEVEL) + 1;
pData->SetInt(MAGICDATA_LEVEL, nNewLevel);
pData->Update();
// ASSERT(pData->FindType());
if ((pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_HIDDEN) == 0)
{
CMsgMagicInfo msg;
IF_OK(msg.Create(m_pOwner->GetID(), pData->GetInt(MAGICDATA_TYPE), nNewLevel, 0))
m_pOwner->SendMsg(&msg);
}
}
}
}
//////////////////////////////////////////////////////////////////////
void CMagic::UserWeaponSkillUpLevel(int nWeaponSkillType, int nWeaponSkillLevel)
{
if(m_setData->GetAmount() == 0)
return;
DWORD dwProf = m_pOwner->GetProfession();
for(int i = 0; i < m_setData->GetAmount(); i++)
{
IMagicData* pData = m_setData->GetObjByIndex(i);
if(pData && pData->GetInt(MAGICDATA_NEED_EXP) == AUTOLEVELUP_EXP
&& pData->GetInt(MAGICDATA_USE_XP) == TYPE_KONGFU
&& pData->GetInt(MAGICDATA_WEAPON_SUBTYPE) == nWeaponSkillType
&& nWeaponSkillLevel >= pData->GetInt(MAGICDATA_NEED_LEVEL)
&& this->CheckProfession(dwProf, pData->GetInt(MAGICDATA_NEED_PROFMASK))
&& !IsWeaponMagic(pData->GetInt(MAGICDATA_TYPE))
)
{
int nNewLevel = pData->GetInt(MAGICDATA_LEVEL) + 1;
pData->SetInt(MAGICDATA_LEVEL, nNewLevel);
pData->Update();
// ASSERT(pData->FindType());
if ((pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_HIDDEN) == 0)
{
CMsgMagicInfo msg;
IF_OK(msg.Create(m_pOwner->GetID(), pData->GetInt(MAGICDATA_TYPE), nNewLevel, 0))
m_pOwner->SendMsg(&msg);
}
}
}
}
//////////////////////////////////////////////////////////////////////
bool CMagic::AutoLearnWeaponSkill(int nWeaponSkillType, int nWeaponSkillLevel, int nWeaponSkillExp/*=0*/)
{
CMagicTypeData* pLearnMagic = NULL;
for(int i = 0; i < AutoMagicTypeSet()->GetAmount(); i++) //??? 可优化
{
CMagicTypeData* pData = AutoMagicTypeSet()->GetObjByIndex(i);
if(pData && pData->GetInt(MAGICTYPEDATA_AUTO_LEARN)
&& pData->GetInt(MAGICTYPEDATA_WEAPON_SUBTYPE) == nWeaponSkillType
&& nWeaponSkillLevel >= pData->GetInt(MAGICTYPEDATA_LEARN_LEVEL)%100 // %100: min level of need, 1208->max=12,min=8
&& FindMagic(pData->GetInt(MAGICTYPEDATA_TYPE)) == NULL )
{
int nMinLevel = pData->GetInt(MAGICTYPEDATA_LEARN_LEVEL) % 100;
int nMaxLevel = pData->GetInt(MAGICTYPEDATA_LEARN_LEVEL) / 100;
if(nMaxLevel == 0 || nWeaponSkillLevel >= nMaxLevel)
{
pLearnMagic = pData;
break;
}
else if(nWeaponSkillExp > 0)
{
ASSERT(nMinLevel < nMaxLevel);
int nExp = 0;
for(int i = nMinLevel; i < nMaxLevel; i++)
{
CHECKF(i >= 1 && i < MAX_WEAPONSKILLLEVEL);
nExp += nWeaponSkillLeveUpNeedExp[i];
}
const int nMaxRand = 30000;
int nRand = (nExp / nWeaponSkillExp) / 2;
if(nRand <= nMaxRand && ::RandGet(nRand) == 0 || nRand > nMaxRand && ::RandGet(nMaxRand) == 0 && ::RandGet(nRand/nMaxRand) == 0)
{
pLearnMagic = pData;
break;
}
}
}
}
if(pLearnMagic)
{
LearnMagic(pLearnMagic->GetInt(MAGICTYPEDATA_TYPE), pLearnMagic->GetInt(MAGICTYPEDATA_LEVEL));
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::UserKillTarget(IRole* pTarget)
{
for(int i = 0; i < m_setData->GetAmount(); i++)
{
IMagicData* pData = m_setData->GetObjByIndex(i);
if( pData && (pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_KILL)
&& !m_pOwner->QueryTransformation()
&& (!pData->GetInt(MAGICDATA_WEAPON_SUBTYPE) || m_pOwner->CheckWeaponSubType(pData->GetInt(MAGICDATA_WEAPON_SUBTYPE)))
&& ::RandGet(100) < pData->GetInt(MAGICDATA_PERCENT) )
{
// backup
IMagicData* pMagic = m_pMagic;
OBJID idTarget = m_idTarget;
POINT pos;
pos.x = m_pos.x;
pos.y = m_pos.y;
switch(pData->GetInt(MAGICDATA_SORT))
{
case MAGICSORT_RECRUIT:
{
m_pMagic = pData;
m_idTarget = m_pOwner->GetID();
m_pos.x = m_pOwner->GetPosX();
m_pos.y = m_pOwner->GetPosY();
ProcessRecruit();
}
break;
case MAGICSORT_SERIALCUT:
{
m_pMagic = pData;
m_idTarget = pTarget->GetID();
m_pos.x = pTarget->GetPosX();
m_pos.y = pTarget->GetPosY();
ProcessSerialCut();
}
break;
}
// restore
m_pMagic = pMagic;
m_idTarget = idTarget;
m_pos.x = pos.x;
m_pos.y = pos.y;
return true;
}
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::AutoAttackTarget(IRole* pTarget)
{
int nPercentAdjust = 100;
// 幻兽发动技能的概率调整
CMonster* pMonster = NULL;
if (m_pOwner->QueryObj(OBJ_MONSTER, IPP_OF(pMonster)) && pMonster->IsEudemon())
{
if (pMonster->GetFidelity() < 500)
nPercentAdjust = 0;
else
nPercentAdjust = 150 + 5*((pMonster->GetFidelity()-500)/50);
}
for(int i = 0; i < m_setData->GetAmount(); i++) //??? 可优化
{
IMagicData* pData = m_setData->GetObjByIndex(i);
if( pData && (pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_RANDOM)
&& !m_pOwner->QueryTransformation()
&& (!pData->GetInt(MAGICDATA_WEAPON_SUBTYPE)
|| m_pOwner->CheckWeaponSubType(pData->GetInt(MAGICDATA_WEAPON_SUBTYPE))
|| (pData->GetInt(MAGICDATA_SORT) == MAGICSORT_KO
&& pTarget->GetLife()*100/pTarget->GetMaxLife()<=MAGIC_KO_LIFE_PERCENT))
&& ::RandGet(100) < (nPercentAdjust*pData->GetInt(MAGICDATA_PERCENT)/100))
{
return MagicAttack(pData->GetInt(MAGICDATA_TYPE), pTarget->GetID(), pTarget->GetPosX(), pTarget->GetPosY(), AUTOACTIVE_RANDOM);
}
}
return false;
}
//////////////////////////////////////////////////////////////////////
// timer
//////////////////////////////////////////////////////////////////////
void CMagic::OnTimer(DWORD tCurr)
{
if (!m_pMagic)
return;
switch (m_nMagicState)
{
case MAGICSTATE_INTONE:
{
if (!m_tIntone.IsActive() || m_tIntone.TimeOver())
{
#ifdef ZLONG_DEBUG
m_pOwner->SendSysMsg("DEBUG: 魔法吟唱结束");
#endif
if (!Launch()) // 魔法执行失败就结束——这里包括目标死亡、目标消失等情况
{
LockTarget(false);
m_tApply.Clear();
ResetDelay();
break;
}
m_nMagicState = MAGICSTATE_LAUNCH;
// 魔法作用的次数由轨迹数来决定
// 为了允许没有轨迹的魔法执行,默认作用次数为1,无轨迹
m_nApplyTimes = __max(1, m_pMagic->GetSTrackAmount());
m_tApply.Startup(m_pMagic->GetApplyMS());
}
}
break;
case MAGICSTATE_LAUNCH:
{
if (!m_tApply.IsActive() || m_tApply.IsTimeOut())
{
#ifdef ZLONG_DEBUG
m_pOwner->SendSysMsg("Debug: 魔法施展结束");
#endif
// MAGICSORT_ATTACK类型的魔法留在攻击结束后Kill目标
if (m_pMagic->GetInt(MAGICDATA_SORT) == MAGICSORT_ATTACK
&& m_idTarget != ID_NONE)
{
IRole* pTarget = RoleManager()->QueryRole(m_idTarget);
if(pTarget && !pTarget->IsAlive())
{
m_pOwner->Kill(pTarget, GetDieMode());
}
}
// 怪物死亡需要查询是否处于锁定状态,因此这里必须在Kill怪物之后解锁
// 否则将不出现尸体消失状态
LockTarget(false);
ResetDelay();
// OnTimer的调用频率为0.5秒,
// 为了及时执行NextMagic,这里直接进入MAGICSTATE_DELAY
}
else
{
break;
}
}
// break;
case MAGICSTATE_DELAY:
{
if (!m_tDelay.IsActive())
{
m_nMagicState = MAGICSTATE_NONE;
break;
}
if(m_bAutoAttack
&& m_pMagic->GetInt(MAGICDATA_NEXT_MAGIC) != ID_NONE)
// && m_pMagic->GetInt(MAGICDATA_NEXT_MAGIC) != m_pMagic->GetInt(MAGICDATA_TYPE))
{
if (m_tDelay.IsActive() && !m_tDelay.TimeOver()) // 必须等到魔法延迟结束才可以执行下一个魔法
break;
#ifdef ZLONG_DEBUG
m_pOwner->SendSysMsg("Debug: 执行下一个魔法。");
#endif
// may be no next magic
if(!FindMagic(m_pMagic->GetInt(MAGICDATA_NEXT_MAGIC)))
{
ASSERT(EquipWeaponMagic(SpawnMagicID(), m_pMagic->GetInt(MAGICDATA_NEXT_MAGIC), 0));
m_tDelay.Clear();
break;
}
m_nMagicState = MAGICSTATE_NONE;
// m_pOwner->SetDelay(0);
MagicAttack(m_pMagic->GetInt(MAGICDATA_NEXT_MAGIC), m_idTarget, m_pos.x, m_pos.y);
break;
}
if (m_tDelay.IsActive() && m_tDelay.TimeOver())
{
#ifdef ZLONG_DEBUG
m_pOwner->SendSysMsg("Debug: 魔法延迟结束");
#endif
m_nMagicState = MAGICSTATE_NONE;
}
}
break;
case MAGICSTATE_NONE:
default:
break;
}
}
//////////////////////////////////////////////////////////////////////
// task
//////////////////////////////////////////////////////////////////////
bool CMagic::CheckType(int nType)
{
return FindMagic(nType) != NULL;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::CheckLevel(int nType, int nLevel)
{
IMagicData* pData = FindMagic(nType);
if(pData && pData->GetInt(MAGICDATA_LEVEL) == nLevel)
return true;
return false;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::UpLevelByTask(int nType)
{
IMagicData* pData = FindMagic(nType);
if(!pData)
return false;
CHECKF(!IsWeaponMagic(pData->GetInt(MAGICDATA_TYPE)));
int nNewLevel = pData->GetInt(MAGICDATA_LEVEL) + 1;
CHECKF(CMagic::FindMagicType(nType, nNewLevel));
pData->SetInt(MAGICDATA_EXP, 0);
pData->SetInt(MAGICDATA_LEVEL, nNewLevel);
pData->Update();
// if(bSynchro)
if ((pData->GetInt(MAGICDATA_AUTO_ACTIVE) & AUTOACTIVE_HIDDEN) == 0)
{
CMsgMagicInfo msg;
IF_OK(msg.Create(m_pOwner->GetID(), pData->GetInt(MAGICDATA_TYPE), nNewLevel, 0))
m_pOwner->SendMsg(&msg);
}
// CHECKF(pData->FindType());
return true;
}
//////////////////////////////////////////////////////////////////////
OBJID CMagic::LearnMagic(int nType, int nLevel/*=0*/, bool bSaveMagic/*=true*/)
{
CHECKF(CMagic::FindMagicType(nType, nLevel));
if(FindMagic(nType))
{
return ID_NONE;
}
DWORD dwExp = 0;
OBJID idMagic = ID_NONE;
IMagicData* pData = NULL;
if (bSaveMagic)
{
// check unlearn magic
SQLBUF szSQL;
sprintf(szSQL, "SELECT id FROM %s WHERE ownerid=%u && type=%d", _TBL_MAGIC, m_pOwner->GetID(), nType);
CAutoPtr<IRecordset> pRes = _Database(PID)->CreateNewRecordset(szSQL);
if(pRes)
idMagic = pRes->GetInt(0);
pData = CMagicData::CreateNew();
CHECKF(pData);
IF_NOT(pData->Create(GameDataDefault()->GetMagicData(), idMagic))
return ID_NONE;
}
else
{
// 临时学会魔法,仅仅保存在内存中
pData = CMagicTempData::CreateNew();
CHECKF (pData);
ST_MAGIC_DATA data;
memset(&data, 0L, sizeof(ST_MAGIC_DATA));
data.idMagic = CMagic::SpawnMagicID();
IF_NOT (pData->Create(&data))
return ID_NONE;
idMagic = data.idMagic;
}
pData->SetInt(MAGICDATA_OWNERID, m_pOwner->GetID());
pData->SetInt(MAGICDATA_TYPE, nType);
pData->SetInt(MAGICDATA_LEVEL, nLevel);
pData->SetInt(MAGICDATA_EXP, dwExp);
pData->SetInt(MAGICDATA_UNLEARN, false);
if(idMagic != ID_NONE)
{
pData->Update();
}
else
{
pData->SetInt(MAGICDATA_OLD_LEVEL, 0);
idMagic = pData->InsertRecord();
}
pData->FindType();
pData->SetDelay(); // 设置延迟
// synchro
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);
}
m_setData->AddObj(pData);
return idMagic;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::UnlearnMagic(int nType, bool bDrop)
{
IMagicData* pData = FindMagic(nType);
if(!pData)
return false;
if(bDrop)
{
ASSERT(pData->DeleteRecord());
}
else
{
pData->SetInt(MAGICDATA_OLD_LEVEL, pData->GetInt(MAGICDATA_LEVEL));
pData->SetInt(MAGICDATA_UNLEARN, true);
pData->Update();
}
if(m_pMagic && m_pMagic->GetID() == pData->GetID())
m_pMagic = NULL;
m_setData->DelObj(pData->GetID());
// synchro
CMsgAction msg;
IF_OK(msg.Create(m_pOwner->GetID(), m_pOwner->GetPosX(), m_pOwner->GetPosY(), m_pOwner->GetDir(), actionDropMagic, nType))
m_pOwner->SendMsg(&msg);
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::EquipWeaponMagic(OBJID idMagic, int nType, int nLevel)
{
// CHECKF(IsWeaponMagic(nType));
CMagicTypeData* pType = CMagic::FindMagicType(nType, nLevel);
CHECKF(pType);
DWORD dwExp = 0;
IMagicData* pData = CMagicData::CreateNew();
CHECKF(pData);
IF_NOT(pData->Create(GameDataDefault()->GetMagicData(), idMagic))
return false;
pData->SetInt(MAGICDATA_ID_, idMagic);
pData->SetInt(MAGICDATA_OWNERID, m_pOwner->GetID());
pData->SetInt(MAGICDATA_TYPE, nType);
pData->SetInt(MAGICDATA_LEVEL, nLevel);
pData->SetInt(MAGICDATA_EXP, dwExp);
pData->ClearUpdateFlags();
pData->FindType();
m_setData->DelObj(idMagic); // 冲掉
m_setData->AddObj(pData);
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMagic::UnequipWeaponMagic(OBJID idMagic)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -