📄 ainpc.cpp
字号:
{
fprintf(fp, "monster: %u drop item: %u\n",
this->GetID(), idItemType);
}
fclose(fp);
#endif
return false;
}
////////////////////////////////////////////////////////////////////////////////////
bool CMonster::DropEquipment (DWORD dwValue, OBJID idOwner, DWORD dwQuality/*=0*/)
{
// drop money if value less than 100
if (dwValue < 100)
return this->DropMoney(dwValue, idOwner);
// create equipment
ItemInfoStruct info;
if (CItem::CreateItemInfo(info, dwValue, m_pType, dwQuality))
{
#ifdef _DEBUG
// temp code
FILE* fp = fopen("equipment.ini", "a+");
if (fp)
{
fprintf(fp, "monster:%03u type:%06u amount:%05u amount_limit:%05u Gem1:%03u Gem2:%03u, Value:%06u\n",
this->GetID(), info.idType, info.nAmount, info.nAmountLimit, info.nGem1, info.nGem2, dwValue);
}
fclose(fp);
#endif
// drop item
POINT pos;
pos.x = GetPosX();
pos.y = GetPosY();
if(GetMap()->FindDropItemCell(MONSTERDROPITEM_RANGE, &pos))
{
CMapItem* pMapItem = CMapItem::CreateNew();
if(pMapItem)
{
info.id = ID_NONE;
if(pMapItem->Create(MapManager()->SpawnMapItemID(), GetMap(), pos, &info, idOwner))
{
MapManager()->QueryMapItemSet()->AddObj(pMapItem);
return true;
}
else
{
pMapItem->ReleaseByOwner();
return false;
}
}
}
return false;
}
return this->DropMoney(dwValue, idOwner);
}
////////////////////////////////////////////////////////////////////////////////////
bool CMonster::DropMedicine(OBJID idOwner)
{
//rem by zlong 2003-11-15
//修改了monstertype表以后已经没有drop_hp和drop_mp两个字段了
/*
int nAmount = 0;
int nRate = ::RandGet(100);
if (nRate < 2)
nAmount = 8;
else if (nRate < 3)
nAmount = 6;
else if (nRate < 5)
nAmount = 5;
else if (nRate < 8)
nAmount = 4;
else if (nRate < 10)
nAmount = 3;
else if (nRate < 25)
nAmount = 2;
else
nAmount = 1;
for (int i=0; i<nAmount; i++)
{
DWORD dwType = 0;
if (1 == ::RandGet(2))
dwType = m_pType->GetInt(NPCTYPEDATA_DROP_HP);
else
dwType = m_pType->GetInt(NPCTYPEDATA_DROP_MP);
this->DropItem(dwType, idOwner);
#ifdef _DEBUG
// temp code
FILE* fp = fopen("medicine.ini", "a+");
if (fp)
{
fprintf(fp, "monster:%03u medicine:%06u\n",
this->GetID(), dwType);
}
fclose(fp);
#endif
}
*/
return true;
}
////////////////////////////////////////////////////////////////////////////////////
bool CMonster::ProcessAction(CUser* pUser, OBJID idAction, LPCTSTR pszAccept)
{
if (idAction == ID_NONE)
return false;
try {
// process action...
const _MAX_ACTIONPRC =32;
DWORD dwActionCount =0;
while (idAction != ID_NONE)
{
CActionData* pAction = ActionSet()->GetObj(idAction);
if (!pAction)
{
::LogSave("Error: game action %u not found.", idAction);
break;
}
// process action now!
idAction = pAction->GetInt(ACTIONDATA_IDNEXTFAIL);
int nActionType = pAction->GetInt(ACTIONDATA_TYPE);
switch(nActionType)
{
case ACTION_RAND:
{
// 检测随机率。"data1 data2"。"10 100"表示有1/10的机会是true。
DWORD dwChance = 0, dwMax = 0;
if (2 == sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%u %u", &dwChance, &dwMax))
{
if (::RandGet(dwMax) < dwChance)
idAction = pAction->GetInt(ACTIONDATA_IDNEXT);
}
else
LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
}
break;
case ACTION_RANDACTION:
{
// 检测随机率。"action0 .... action7"
OBJID idRndAction[8];
if (8 == sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%u %u %u %u %u %u %u %u",
&idRndAction[0], &idRndAction[1], &idRndAction[2], &idRndAction[3],
&idRndAction[4], &idRndAction[5], &idRndAction[6], &idRndAction[7]))
{
idAction = idRndAction[::RandGet(8)];
}
else
LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
}
break;
case ACTION_MST_DROPITEM:
{
// monster被杀死后掉物品或者钱, param "dropitem itemtype"或者"dropmoney money [LowPercent]"
char szCmd[MAX_PARAMSIZE] = "";
if (1 != sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%s", szCmd))
{
LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
break;
}
if (0 == stricmp(szCmd, "dropitem"))
{
DWORD dwData = 0;
if (2 == sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%s %u", szCmd, &dwData))
{
if (0 == stricmp(szCmd, "dropitem"))
{
OBJID idUser = ID_NONE;
if (pUser)
idUser = pUser->GetID();
if (this->DropItem(dwData, idUser))
idAction = pAction->GetInt(ACTIONDATA_IDNEXT);
}
}
else
{
LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
break;
}
}
else if (0 == stricmp(szCmd, "dropmoney"))
{
DWORD dwData=0, dwLowPercent=0;
int rval = sscanf(pAction->GetStr(ACTIONDATA_PARAM), "%s %u %u", szCmd, &dwData, &dwLowPercent);
if (rval == 2)
dwLowPercent = 100;
else if (rval == 3)
dwLowPercent %= 100;
else
{
LOGERROR("ACTION %u: 错误的参数数量", pAction->GetID());
break;
}
DWORD dwMoneyDrop = dwData*(dwLowPercent+::RandGet(100-dwLowPercent))/100;
if (dwMoneyDrop <= 0)
return true;
OBJID idUser = ID_NONE;
if (pUser)
idUser = pUser->GetID();
if (this->DropMoney(dwMoneyDrop, idUser))
idAction = pAction->GetInt(ACTIONDATA_IDNEXT);
}
}
break;
default:
break;
}
if (dwActionCount++ >= _MAX_ACTIONPRC)
{
::LogSave("Error: too many game action, last action:%u.", idAction);
break;
}
} // while
}
catch(...)
{
ASSERT(!"catch");
::LogSave("Error: exception catched in CUser::ProcessAction(%u)", idAction);
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMonster::IsAtkable(IRole* pTarget, bool bSendHint)
{
if (!pTarget)
return false;
if (!this->IsAlive())
{
if (bSendHint)
this->SendSysMsg(STR_DIE_FORGIVE);
return false;
}
if (!pTarget->IsAlive())
{
//if (bSendHint)
// this->SendSysMsg(STR_DIE_STOP_ATTACK);
return false;
}
/*
if (pTarget->IsGM())
{
if (bSendHint)
this->SendSysMsg(STR_ATTACK_POLICE);
return false;
}
*/
if(GetID() == pTarget->GetID())
return false;
if(!pTarget->IsBeAtkable())
return false;
// 召唤兽不能攻击自己的主人
if (this->QueryOwnerUser() && this->QueryOwnerUser()->GetID() == pTarget->GetID())
return false;
// map check
if (!(this->GetMap() && pTarget->GetMap() && this->GetMap() == pTarget->GetMap()))
return false;
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMonster::IsBeAtkable()
{
return !(QueryStatus(STATUS_LOCK));
}
//////////////////////////////////////////////////////////////////////
bool CMonster::EnterMapGroup()
{
CMapPtr pMap = this->GetMap();
CHECKF(pMap);
UpdateBroadcastSet();
MapGroup(PID)->QueryIntraMsg()->SetNpcProcessID(GetID(), true); // 同步SOCKET_KERNEL
pMap->EnterRoom(this->QueryMapThing(), WITH_BLOCK);
// if(IsSendBlockInfo())
// pMap->SendBlockInfo((IRole*)this);
// SendSelfToBlock();
/*{
CMsgAction msg;
IF_OK(msg.Create(GetID(), GetPosX(), GetPosY(), GetDir(), actionEmotion, _ACTION_EXCITEMENT))
this->BroadcastRoomMsg(&msg);
}*/
// if(IsMapRoar())
{
CMsgAction msg;
IF_OK(msg.Create(GetID(), GetPosX(), GetPosY(), GetDir(), actionSoundEffect, GetType()))
_UserManager(PID)->BroadcastMapMsg(pMap->GetID(), &msg);
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CMonster::LeaveMapGroup()
{
CMapPtr pMap = this->GetMap();
CHECKF(pMap);
MapGroup(PID)->QueryIntraMsg()->SetNpcProcessID(GetID(), false); // 同步SOCKET_KERNEL
// BeKill的时候调用了DecRole,因此这里需要判断,以免LeaveRoom的时候多减一次角色数
bool bWithBlock = !m_bDecRole;
SendLeaveFromBlock(); // NPC服务器需要这个通知来删除怪物
ClrBroadcastSet();
pMap->LeaveRoom(this->QueryMapThing(), bWithBlock);
m_bDecRole = true;
return true;
}
//////////////////////////////////////////////////////////////////////
LPCTSTR CMonster::GetName()
{
if (this->IsEudemon() && m_pEudemonItem)
return m_pEudemonItem->GetStr(ITEMDATA_NAME);
return m_pType->GetStr(NPCTYPEDATA_NAME);
}
//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetLife()
{
int nMaxLife = this->GetMaxLife();
if (this->IsEudemon() && m_pEudemonItem)
{
m_nCurrLife = m_pEudemonItem->GetInt(ITEMDATA_EUDEMON_LIFE);
if (m_nCurrLife > nMaxLife)
{
m_nCurrLife = nMaxLife;
m_pEudemonItem->SetInt(ITEMDATA_EUDEMON_LIFE, nMaxLife, true);
}
return m_nCurrLife;
}
if (m_nCurrLife > nMaxLife)
m_nCurrLife = nMaxLife;
return m_nCurrLife;
}
//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMaxLife()
{
int nLife = m_pType->GetInt(NPCTYPEDATA_LIFE);
if (this->IsEudemon() && m_pEudemonItem)
{
int nMaxLife = __max(1, m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_LIFE) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_LIFE)*100) / 10000);
nLife = nMaxLife;
}
IStatus* pStatus = QueryStatus(STATUS_MAXLIFE);
if (pStatus)
{
nLife = ::CutTrail(0, AdjustData(nLife, pStatus->GetPower(), 100));
}
return nLife;
}
//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMinAtk()
{
DWORD dwAtk = m_pType->GetInt(NPCTYPEDATA_ATTACKMIN);
// 算幻兽的等级加成
if (this->IsEudemon() && m_pEudemonItem)
{
int nMinAtk = m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_ATTACK_MIN_) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_ATTACK_MIN)*100) / 10000;
dwAtk = nMinAtk;
}
// 算装备的coding here...
return dwAtk;
}
//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMaxAtk()
{
DWORD dwAtk = m_pType->GetInt(NPCTYPEDATA_ATTACKMAX);
// 算装备的coding here...
dwAtk = dwAtk;
// 算幻兽的等级加成
if (this->IsEudemon() && m_pEudemonItem)
{
int nMaxAtk = m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_ATTACK_MAX_) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_ATTACK_MAX)*100) / 10000;
dwAtk = nMaxAtk;
}
return dwAtk;
}
//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMgcMinAtk()
{
DWORD dwAtk = m_pType->GetInt(NPCTYPEDATA_ATTACKMIN);
// 算装备的coding here...
dwAtk = dwAtk;
// 算幻兽的等级加成
if (this->IsEudemon() && m_pEudemonItem)
{
int nMinMgcAtk = m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_MAGICATK_MIN_) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_MGCATK_MIN)*100) / 10000;
dwAtk = nMinMgcAtk;
}
return dwAtk;
}
//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetMgcMaxAtk()
{
DWORD dwAtk = m_pType->GetInt(NPCTYPEDATA_ATTACKMAX);
// 算装备的coding here...
dwAtk = dwAtk;
// 算幻兽的等级加成
if (this->IsEudemon() && m_pEudemonItem)
{
int nMaxMgcAtk = m_pEudemonItem->GetEudemonLevel() * (m_pEudemonItem->GetInt(ITEMDATA_MAGICATK_MAX_) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) + m_pEudemonItem->GetAddition(ITEMADDITIONDATA_MGCATK_MAX)*100) / 10000;
dwAtk = nMaxMgcAtk;
}
return dwAtk;
}
//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetDdg()
{
DWORD dwDodge = this->GetDodge();
// 算幻兽的加成
if (this->IsEudemon() && m_pEudemonItem)
{
int nDodge = m_pEudemonItem->GetInt(ITEMDATA_DODGE) * m_pEudemonItem->GetInt(ITEMDATA_GROWTH) / 10000 + m_pEudemonItem->GetEudemonLevel() * m_pEudemonItem->GetAddition(ITEMADDITIONDATA_DODGE)/100;
dwDodge = nDodge;
}
// IStatus* pStatus = QueryStatus(STATUS_DODGE);
// if(pStatus)
// dwDodge = AdjustData(dwDodge, pStatus->GetPower());
// 算装备的coding here...
// dwDodge = dwDodge;
return __max(0, dwDodge);
}
//////////////////////////////////////////////////////////////////////
DWORD CMonster::GetDef()
{
DWORD dwDef = 0;
// 算装备的coding here...
dwDef = dwDef + this->GetDefence();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -