📄 ainpc.cpp
字号:
{
if ((IsCallPet() || IsEudemon()) && m_pOwner)
m_pOwner->SendMsg(pMsg);
else
MapGroup(PID)->QueryIntraMsg()->SendNpcMsg(ID_NONE, pMsg);
}
}
//////////////////////////////////////////////////////////////////////
void CMonster::BroadcastMapMsg(LPCTSTR szMsg, bool bSendSelf /*= false*/)
{
CMsgTalk msg;
if(msg.Create(SYSTEM_NAME, ALLUSERS_NAME, szMsg, NULL, 0xff0000, _TXTATR_SYSTEM))
this->BroadcastMapMsg(&msg, bSendSelf);
}
//////////////////////////////////////////////////////////////////////
bool CMonster::SendSelfToBlock()
{
// brocast my info
CMsgPlayer msg;
if (msg.Create((IRole*)this))
this->BroadcastRoomMsg(&msg);
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMonster::SendLeaveFromBlock()
{
if(!m_bLeaveMap)
{
m_bLeaveMap = true;
CMsgAction msg;
if(msg.Create(GetID(), 0, 0, 0, actionLeaveMap))
this->BroadcastRoomMsg(&msg, INCLUDE_SELF);
if (this->IsEudemon() && m_pOwner)
m_pOwner->SendMsg(&msg);
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
// role
/////////////////////////////////////////////////////////////////////////////
void CMonster::SendShow(IRole* pRole)
{
CHECK(pRole);
CMsgPlayer msg;
if(msg.Create((IRole*)this))
pRole->SendMsg(&msg);
}
//////////////////////////////////////////////////////////////////////
bool CMonster::SendSysMsg(const char* fmt, ...)
{
MSGBUF szMsg;
vsprintf( szMsg, fmt, (char*) ((&fmt)+1) );
CMsgTalk msg;
if (msg.Create(SYSTEM_NAME, GetName(), szMsg, NULL, 0xff0000, _TXTATR_SYSTEM))
return this->SendMsg(&msg);
return false;
}
//////////////////////////////////////////////////////////////////////
// modify attrib
//////////////////////////////////////////////////////////////////////
bool CMonster::AddAttrib(int idxAttr, __int64 i64Data, int nSynchro)
{
CMsgUserAttrib msg;
if(!msg.Create(GetID(), _USERATTRIB_NONE, _USERATTRIB_NONE)) // _USERATTRIB_NONE : 不添加
return false;
if(i64Data)
{
switch(idxAttr)
{
case _USERATTRIB_LIFE:
{
if (this->IsEudemon())
{
IF_OK (m_pEudemonItem)
{
int nCurrLife = ::CutTrail(0, m_pEudemonItem->GetInt(ITEMDATA_EUDEMON_LIFE)+(int)i64Data);
int nMaxLife = GetMaxLife();
nCurrLife = ::CutOverflow(nCurrLife, nMaxLife);
m_pEudemonItem->SetInt(ITEMDATA_EUDEMON_LIFE, nCurrLife);
CMsgItemAttrib msgItemAttrib;
if (msgItemAttrib.Create(m_pEudemonItem->GetID(), _ITEMATTRIB_EUDEMON_LIFE, m_pEudemonItem->GetInt(ITEMDATA_EUDEMON_LIFE)))
m_pOwner->SendMsg(&msgItemAttrib);
}
}
else
{
if ((int)this->GetLife() + i64Data <= 0)
{
// this->SetStatus(STATUS_DIE);
m_nCurrLife = 0;
}
else
m_nCurrLife = this->GetLife() + i64Data;
}
// 血超过70%的时候解除狂暴状态
if (GetLife()*100/GetMaxLife() > MAX_FRENZY_LIFE_PERCENT)
{
CRole::DetachStatus(this->QueryRole(), STATUS_FRENZY);
}
IF_NOT (msg.Append(_USERATTRIB_LIFE, GetLife()))
return false;
}
break;
case _USERATTRIB_POTENTIAL:
{
if (this->IsEudemon())
{
m_nPotential = __max(0, __min(m_nPotential + (int)i64Data, MAX_EUDEMON_POTENTIAL));
IF_NOT (msg.Append(_USERATTRIB_POTENTIAL, m_nPotential))
return false;
}
}
break;
case _USERATTRIB_MANA:
{
// m_nCurrMana = (__max(GetMana() + i64Data, 0));
// IF_NOT (msg.Append(_USERATTRIB_MANA, GetMana()))
return false;
}
break;
case _USERATTRIB_EXP:
{
// IF_NOT (msg.Append(_USERATTRIB_EXP, GetExp()))
return false;
}
break;
case _USERATTRIB_MONEY:
{
// IF_NOT (msg.Append(_USERATTRIB_MONEY, GetMoney()))
return false;
}
break;
default:
return false;
}
}
if(nSynchro != SYNCHRO_FALSE)
{
switch(nSynchro)
{
case SYNCHRO_TRUE:
this->SendMsg(&msg);
break;
case SYNCHRO_BROADCAST:
this->BroadcastRoomMsg(&msg, INCLUDE_SELF);
break;
default:
break;
}
}
return true;
}
//////////////////////////////////////////////////////////////////////
void CMonster::ProcessAfterMove()
{
IThingSet* pSet = GetMap()->QueryBlock(GetPosX(), GetPosY()).QuerySet();
for(int i = 0; i < pSet->GetAmount(); i++)
{
IMapThing* pTarget = pSet->GetObjByIndex(i);
CMapTrap* pTrap;
if(pTarget && pTarget->QueryObj(OBJ_TRAP, IPP_OF(pTrap))
&& pTrap->IsTrapSort() && pTarget->GetPosX() == GetPosX() && pTarget->GetPosY() == GetPosY())
{
pTrap->TrapAttack(QueryRole());
}
}
}
//////////////////////////////////////////////////////////////////////
void CMonster::ProcessOnMove(int nMoveMode)
{
SetPose(_ACTION_STANDBY);
// stop fight
if(nMoveMode != MOVEMODE_JUMPMAGICATTCK && nMoveMode != MOVEMODE_COLLIDE && nMoveMode != MOVEMODE_SYNCHRO)
ClrAttackTarget();
m_tFootPrint = ::TimeGet();
m_posFootPrint.x = this->GetPosX();
m_posFootPrint.y = this->GetPosY();
}
//////////////////////////////////////////////////////////////////////
void CMonster::GetFootPrint (int& nPosX, int& nPosY)
{
if (::TimeGet()-m_tFootPrint >= TIME_FOOTPRINT)
{ // time out
nPosX = this->GetPosX();
nPosY = this->GetPosY();
}
else
{
nPosX = m_posFootPrint.x;
nPosY = m_posFootPrint.y;
}
}
//////////////////////////////////////////////////////////////////////
// interactive
//////////////////////////////////////////////////////////////////////
bool CMonster::Freeze(int nPower) // return false: 解穴不成功
{
if(IsAlive())
{
if(nPower > 0)
{
return false; // 不显示被点状态
}
else
{
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////
// fight
//////////////////////////////////////////////////////////////////////
bool CMonster::SetAttackTarget(IRole* pTarget /*= NULL*/)
{
if(pTarget == NULL)
{
m_pBattleSystem->ResetBattle();
return true;
}
if(pTarget->QueryOwnerUser() && GetMap()->IsInRegionType(REGION_PK_PROTECTED, GetPosX(), GetPosY()))
return false;
if(this->GetDistance(pTarget->QueryMapThing()) > GetAttackRange(pTarget->GetSizeAdd()))
return false;
m_pBattleSystem->CreateBattle(pTarget->GetID());
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMonster::AutoSkillAttack(IRole* pTarget)
{
CHECKF(pTarget);
if (m_pMagic && m_pMagic->AutoAttackTarget(pTarget))
return true;
if(!IsMagicAtk())
return false;
CHECKF(m_pMagicType);
switch(m_pMagicType->GetInt(MAGICTYPEDATA_SORT))
{
case MAGICSORT_RECRUIT:
{
if(m_pOwner && m_tMagic.ToNextTime(m_pMagicType->GetInt(MAGICTYPEDATA_STEP)))
{
if(m_pOwner->GetLife() < m_pOwner->GetMaxLife())
{
int nAdd = m_pMagicType->GetInt(MAGICTYPEDATA_POWER);
m_pOwner->AddAttrib(_USERATTRIB_LIFE, nAdd, SYNCHRO_TRUE);
// effect
CMsgMagicEffect msg;
IF_OK(msg.Create(GetID(), GetMagicType(), DEFAULT_MONSTER_MAGIC_LEVEL, m_pOwner->GetID(), nAdd, GetDir()))
BroadcastRoomMsg(&msg, INCLUDE_SELF);
}
}
}
break;
case MAGICSORT_ADDMANA:
{
if(m_pOwner && m_tMagic.ToNextTime(m_pMagicType->GetInt(MAGICTYPEDATA_STEP)))
{
if(m_pOwner->GetMana() < m_pOwner->GetMaxMana())
{
int nAdd = m_pMagicType->GetInt(MAGICTYPEDATA_POWER);
m_pOwner->AddAttrib(_USERATTRIB_MANA, nAdd, SYNCHRO_TRUE);
// effect
CMsgMagicEffect msg;
IF_OK(msg.Create(GetID(), GetMagicType(), DEFAULT_MONSTER_MAGIC_LEVEL, m_pOwner->GetID(), nAdd, GetDir()))
BroadcastRoomMsg(&msg, INCLUDE_SELF);
}
}
}
break;
case MAGICSORT_BOMB:
{
DEBUG_TRY
{
if(!IsCallPet() && !IsEudemon())
ProcessBomb();
else
return false;
}
DEBUG_CATCH("CMonster::ProcessBomb()")
}
break;
case MAGICSORT_VAMPIRE:
case MAGICSORT_INSTEAD:
{
return false;
}
break;
default:
ASSERT(!"Nonsupport monster magic sort!!!");
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMonster::AdditionMagic(int nLifeLost, int nDamage)
{
if(!IsMagicAtk())
return false;
CHECKF(m_pMagicType);
switch(m_pMagicType->GetInt(MAGICTYPEDATA_SORT))
{
case MAGICSORT_RECRUIT:
case MAGICSORT_ADDMANA:
case MAGICSORT_BOMB:
case MAGICSORT_INSTEAD:
{
return false;
}
break;
case MAGICSORT_VAMPIRE:
{
if(m_pOwner && nLifeLost)
{
if(m_pOwner->GetLife() < m_pOwner->GetMaxLife())
{
int nAdd = ::CutTrail(0, CRole::AdjustDataEx(nLifeLost, m_pMagicType->GetInt(MAGICTYPEDATA_POWER)));
if(nAdd)
m_pOwner->AddAttrib(_USERATTRIB_LIFE, nAdd, SYNCHRO_TRUE);
}
}
}
break;
default:
ASSERT(!"Nonsupport monster magic sort !!!");
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////
int CMonster::GetDieMode()
{
CHECKF(m_pMagicType);
if (m_pMagicType->GetInt(MAGICTYPEDATA_WEAPON_HIT) == CMagic::HIT_BY_MAGIC)
return DIE_MAGIC;
else if (IsBowman())
return DIE_ARROWSHOOT;
else
return DIE_NORMAL;
}
//////////////////////////////////////////////////////////////////////
void CMonster::ProcessBomb()
{
CHECK(IsMagicAtk());
CHECK(m_pMagicType);
CHECK(m_pOwner);
int nPower = m_pMagicType->GetInt(MAGICTYPEDATA_POWER);
int nRange = m_pMagicType->GetInt(MAGICTYPEDATA_RANGE);
POINT pos;
pos.x = GetPosX();
pos.y = GetPosY();
int nSize = nRange*2 + 1;
int nBufSize = nSize * nSize;
MAPTHING_SET setTarget;
GetMap()->CollectMapThing(setTarget, pos, nRange, OBJ_USER|OBJ_MONSTER|OBJ_NPC);
vector<IRole*> setRole;
vector<int> setPower;
for(int i = ::CutTrail(pos.x-nRange, 0); i <= pos.x+nRange && i < GetMap()->GetWidth(); i++)
{
for(int j = ::CutTrail(pos.y-nRange, 0); j <= pos.y+nRange && j < GetMap()->GetHeight(); j++)
{
POINT posThis;
posThis.x = i;
posThis.y = j;
if(!CUser::IsInCircle(posThis, pos, nRange))
continue;
int idx = POS2INDEX(posThis.x - pos.x + nRange, posThis.y - pos.y + nRange, nSize, nSize);
ASSERT(idx>=0 && idx<setTarget.size());
if(setTarget[idx])
{
IRole* pRole = NULL;
if(setTarget[idx]->QueryRole(IPP_OF(pRole)) && pRole->IsAlive() && !IsImmunity(pRole))
{
bool bByMagic = m_pMagicType->GetInt(MAGICTYPEDATA_WEAPON_HIT) == CMagic::HIT_BY_MAGIC;
int nPower = CBattleSystem::CalcPower(bByMagic, QueryRole(), pRole, m_pMagicType->GetInt(MAGICTYPEDATA_POWER));
{
setRole.push_back(pRole);
setPower.push_back(nPower);
}
}
}
}
}
// 广播法术效果
CMsgMagicEffect msg;
IF_OK(msg.CreateByPos(GetID(), GetMagicType(), DEFAULT_MONSTER_MAGIC_LEVEL, pos.x, pos.y, GetDir()))
{
for(int i = 0; i < setRole.size(); i++)
msg.AppendRole(setRole[i]->GetID(), setPower[i]);
BroadcastRoomMsg(&msg, INCLUDE_SELF);
}
// set crime status
for( i = 0; i < setRole.size(); i++)
{
if(m_pOwner->CheckCrime(setRole.at(i)))
break;
}
int nExp = 0;
for (i = 0; i < setRole.size(); i++)
{
int nLifeLost = __min(setRole[i]->GetLife(), setPower[i]);
setRole[i]->AddAttrib(_USERATTRIB_LIFE, -1*nLifeLost, SYNCHRO_TRUE);
CNpc* pNpc;
if(setRole[i]->QueryObj(OBJ_NPC, IPP_OF(pNpc)) && pNpc->IsAwardScore())
m_pOwner->AwardSynWarScore(pNpc, nLifeLost);
if (setRole[i]->IsMonster()) // || pNpc && pNpc->IsGoal() && GetLev() >= pNpc->GetLev()
{
nExp += m_pOwner->AdjustExp(setRole[i], nLifeLost);
/*if (!setRole[i]->IsAlive())
{
// 有组队,并且队伍中有其他队员,则奖励其他队员经验
int nBonusExp = setRole[i]->GetMaxLife()*KILLBONUS_PERCENT/100;
OtherMemberAwardExp(setRole[i], nBonusExp);
nExp += AdjustExp(setRole[i], nBonusExp, true);
}*/
}
setRole[i]->BeAttack(BY_MAGIC, QueryRole(), setPower[i]);
if(!setRole[i]->IsAlive())
Kill(setRole[i], GetDieMode());
}
AwardBattleExp(nExp);
}
//////////////////////////////////////////////////////////////////////
// precondition is dodge failed
int CMonster::Attack(IRole* pTarget) // return : lose life
{
CHECKF(pTarget);
int nTempAdjust = 0;
int nDamage = CBattleSystem::CalcPower(IsSimpleMagicAtk(), QueryRole(), pTarget, nTempAdjust, true);
//护盾转移伤害
if (pTarget->TransferShield(BY_WEAPON, QueryRole(), nDamage))
{
}
else
{
int nLoseLife = ::CutOverflow(nDamage, (int)pTarget->GetLife());
if (nLoseLife > 0)
pTarget->AddAttrib(_USERATTRIB_LIFE, -1*nLoseLife, SYNCHRO_TRUE);
pTarget->BeAttack(BY_WEAPON, QueryRole(), nDamage);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -