Files
mir_server/server/LogicServer/entity/Animal.cpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

1933 lines
54 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "Animal.h"
#include "../LogicServer.h"
#include "../skill/SkillSubSystem.h"
#include "config/HallowsConfig.h"
unsigned int * CAnimal::s_stateForbidMask =NULL;
#ifdef _DEBUG
extern std::string s_HurtValueMsg;
extern char s_HurtValueBuff[100];
#endif
bool CAnimal::Init(void * data, size_t size)
{
m_pAI =NULL;
if(Inherited::Init(data,size) ==false) return false;
if(m_observerSystem.Create(this,data,size) ==false)
{
OutputMsg(rmWaning,_T("Init fail for observer system "));
return false; //观察者子系统
}
if(m_moveSystem.Create(this,data,size) ==false)
{
OutputMsg(rmWaning,_T("Init fail for movement system "));
return false; //移动子系统
}
if(m_propertySystem.Create(this,data,size) ==false)
{
OutputMsg(rmWaning,_T("Init fail for property system "));
return false; // 属性子系统的初始化
}
if(m_buffSystem.Create(this,data,size) ==false)
{
OutputMsg(rmWaning,_T("Init fail for buff system "));
return false; // buff子系统的初始化
}
if(m_skillSystem.Create(this,data,size) ==false)
{
OutputMsg(rmWaning,_T("Init fail for skill system "));
return false; // 技能子系统的初始化
}
m_effectSystem.Create(this,data,size);
return true;
}
//等级提升
void CAnimal::OnLevelUp(int nUpdateVal)
{
//需要重新计算属性
CollectOperate(CEntityOPCollector::coRefAbility);
// 更新升级后的血、蓝
if(!IsDeath())
CollectOperate(CEntityOPCollector::coResetMaxHPMP);
}
VOID CAnimal::BeforeLogicRun(TICKCOUNT nCurrentTime)
{
Inherited::BeforeLogicRun(nCurrentTime);
//清空汇总操作标记
}
int CAnimal::GetAttackValue(INT_PTR nAttackType)
{
int nAttackMax,nAttackMin;
switch(nAttackType)
{
case TYPE_PHYSICAL_ATTACK: //物理攻击类型
nAttackMax= GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MAX);
nAttackMin= GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MIN);
break;
case TYPE_MAGIC_ATTACK://魔法攻击类型
nAttackMax= GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MAX);
nAttackMin= GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MIN);
break;
case TYPE_WIZARD_ATTACK://道士攻击类型
nAttackMax= GetProperty<int>(PROP_CREATURE_WIZARD_ATTACK_MAX);
nAttackMin= GetProperty<int>(PROP_CREATURE_WIZARD_ATTACK_MIN);
break;
case TYPE_HOLY_ATTACK: //神圣攻击
if (GetType() == enActor)
{
switch (((CActorProperty*)((CActor*)this)->GetPropertyPtr())->nVocation)
{
case enVocWarrior:
nAttackMax= GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MAX);
nAttackMin= GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MIN);
break;
case enVocMagician:
nAttackMax= GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MAX);
nAttackMin= GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MIN);
break;
case enVocWizard:
nAttackMax= GetProperty<int>(PROP_CREATURE_WIZARD_ATTACK_MAX);
nAttackMin= GetProperty<int>(PROP_CREATURE_WIZARD_ATTACK_MIN);
break;
default:
return 0;
}
}
else if (GetType() == enMonster)
{
nAttackMax= GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MAX);
nAttackMin= GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MIN);
}
break;
default:
return 0;
}
if (nAttackMin == 0) nAttackMin = 1;
if (nAttackMax == 0) nAttackMax = 1;
if(nAttackMin >= nAttackMax) return nAttackMax; //没什么算的
int nLuck = GetProperty<int>(PROP_CREATURE_LUCK); //幸运
//使用静态遍历,避免每次都去取一下
GLOBALCONFIG& globalConfig = GetLogicServer()->GetDataProvider()->GetGlobalConfig();
int nRandomVal = nAttackMax - nAttackMin + 1;
nRandomVal = wrand( nRandomVal );
int nAttackMaxRadom = 0;
if (nLuck == 0 )
{
return nAttackMin + nRandomVal;
}
else if (nLuck > 0)
{
int nRandVal = nLuck * 3;
// if (nLuck > 15)
// {
// nRandVal = 45;
// }
if (wrand(100) < (unsigned long)nRandVal)
{
return nAttackMax;
}
else
{
return nAttackMin + nRandomVal;
}
}
}
void CAnimal::OnEntityDeath()
{
Inherited::OnEntityDeath();
bool bHasDrop = 0; //声音的id
if(enMonster == GetType())
{
const PMONSTERCONFIG pMonster= GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(GetProperty<int>(PROP_ENTITY_ID));
if( pMonster !=NULL )
{
bHasDrop = ((CMonster*)this)->isHasDrop();
}
}
char buff[128];
CDataPacket data(buff,sizeof(buff));
data << (BYTE)enDefaultEntitySystemID << (BYTE) sEntityDeath << (Uint64)GetHandle() << (Uint64 )m_killHandler << bHasDrop;
m_observerSystem.BroadCast(data.getMemoryPtr(),data.getPosition(),true);
m_effectSystem.DelAllEffect(true); //死亡了需要删除所有的特效
m_buffSystem.OnDeadRemoveBuff();
}
VOID CAnimal::ChangeHP(int hpDrop, CEntity * pKiller,bool bIgnoreDamageRedure, bool bIgnoreMaxDropHp, bool boSkillResult,int btHitType)
{
//这里支持哪种每次只掉1滴血的情况
if(hpDrop == 0)
{
return ;
}
INT_PTR nKillType =-1;
bool hasKiller = false;
if(pKiller)
{
nKillType = pKiller->GetType();
hasKiller =true;
m_AttackerHandler = pKiller->GetHandle();
}
INT_PTR nSelfType = GetType();
if(nKillType == enActor)
{
if ( ((CActor*)pKiller)->OnGetIsTestSimulator() || ((CActor*)pKiller)->OnGetIsSimulator())
{
hpDrop = 0;
}
}
if(nSelfType == enActor)
{
if ( ((CActor*)this)->OnGetIsTestSimulator() || ((CActor*)this)->OnGetIsSimulator())
{
hpDrop = 0;
}
}
int nHpDrop = 0;
int absDrop = 0;
//伤害吸收
if(hpDrop < 0)
{
absDrop = -hpDrop; //掉了多少血
//最原始的掉血,这里要计算目标的最大的掉血
// int originalAbsDrop = absDrop;
// int nFinalDamageValue = 0;
int S7 = 10000;
//[BUFF] 伤害抵消的BUFF状态 ( value:池值, param:吸收万分比 )
CBuffSystem * bufSystem =GetBuffSystem();
CDynamicBuff *pBuff = bufSystem->GetFirstBuff(aDamageAbsorb);
if(pBuff && absDrop>0 && !bIgnoreDamageRedure)
{
INT_PTR nBuffGroup = pBuff->btGroup; //buff
if(pBuff->value.nValue > 0)
{
float fAbsorbRate = ((float)pBuff->pConfig->nParam / (float)10000);
S7 -= pBuff->pConfig->nParam;
int nBuffAbsorb = fAbsorbRate * absDrop;//吸收的伤害
nBuffAbsorb = __min(nBuffAbsorb, pBuff->value.nValue);
// nFinalDamageValue -= nBuffAbsorb;
pBuff->value.nValue -= nBuffAbsorb;//池值降低
#ifdef _DEBUG
// S8
SNPRINTFA(s_HurtValueBuff,100," //S7::%d",S7);
s_HurtValueMsg += s_HurtValueBuff;
#endif
}
if(pBuff->value.nValue <= 0)
{
bufSystem->Remove(aDamageAbsorb,nBuffGroup); //如果已经吸收完了就去掉这个buff
}
}
int S8 = 10000;
//伤害加成 --mhl
if(btHitType != htFire && pKiller && pKiller->isAnimal()) {
//伤害加成
S8 += ((CAnimal*)pKiller)->m_nDoubleAtkRate;
// int nDouAtkValue = absDrop * (((CAnimal*)pKiller)->m_nDoubleAtkRate / 10000.0);
// nFinalDamageValue += nDouAtkValue;
#ifdef _DEBUG
// S7
SNPRINTFA(s_HurtValueBuff,100," //S8:%d;",S8);
s_HurtValueMsg += s_HurtValueBuff;
#endif
}
int S9 = 10000;
//[NORMAL] 按比例吸收伤害,降低伤害的数值
if( S9 > 0.0f && !bIgnoreDamageRedure )
{
S9 -=(int)(m_fDamgeAbsorbRate*10000);
// int nDamgeAbsorb =(int) (absDrop * m_fDamgeAbsorbRate); //这里伤害减免了一定的数值
// nFinalDamageValue -= nDamgeAbsorb;
#ifdef _DEBUG
// S9伤害减免比例
SNPRINTFA(s_HurtValueBuff,100," //S9::%d",S9);
s_HurtValueMsg += s_HurtValueBuff;
#endif
}
//[NORMAL] 伤害转换为mp消耗
int S10 = 10000;
int fDamage2MpRate = GetHp2MpRate(); //获取血->蓝的转换比例
if(fDamage2MpRate >0)
{
S10 -= fDamage2MpRate;
int nMp = GetProperty<unsigned int >(PROP_CREATURE_MP) ; //获取玩家的蓝
if(nMp >0)
{
int nDropMp = (int)(((fDamage2MpRate * absDrop)/10000.0)/50);
int nAbsorb = __min( nDropMp , nMp); //吸收的点数
if(nAbsorb >0)
{
// nFinalDamageValue -= nAbsorb;
//static float fRate = GetLogicServer()->GetDataProvider()->GetGlobalConfig().fBodyDamageRate;
//nAbsorb = (int)(__min(nDropMp * fRate, nMp));
if (nMp - nAbsorb >= 500)
{
ChangeMP(-1 * nAbsorb); //降低蓝
}
}
#ifdef _DEBUG
// S10
SNPRINTFA(s_HurtValueBuff,100," //S10:%d;",S10);
s_HurtValueMsg += s_HurtValueBuff;
#endif
}
}
//守护 --mhl
bool bGuardEff = false;
int S11 = 10000;
int nGuardRand =wrand(10000); //取1万之间的随机数
if( m_nGuardRate > 0 && nGuardRand <= m_nGuardRate) {
S11 -= m_nGuardValue;
// int nAbsorb = absDrop * (10000 - m_nGuardValue)/10000.0;
// nFinalDamageValue -= nAbsorb;
bGuardEff = true;
#ifdef _DEBUG
// S10
SNPRINTFA(s_HurtValueBuff,100," //S11:%d;",S11);
s_HurtValueMsg += s_HurtValueBuff;
#endif
}
//切割--只对怪物生效 --mhl
int S12 = 10000;
if(nSelfType == enMonster && (pKiller && pKiller->isAnimal())) {
S12 += ((CAnimal*)pKiller)->m_nCuttingRate;
// int nCutDmage = absDrop * (((CAnimal*)pKiller)->m_nCuttingRate / 10000.0);
// nFinalDamageValue += nCutDmage;
#ifdef _DEBUG
// S12
SNPRINTFA(s_HurtValueBuff,100," //S12:%d;",S12);
s_HurtValueMsg += s_HurtValueBuff;
#endif
// static int nGuardEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nGuardEffId;
// CEntityMsg msg(CEntityMsg::emShowEntityEffect, pKiller->GetHandle());
// msg.nParam1 = nGuardEffId;
// this->PostEntityMsg(msg);
}
//pk伤害减免
int S13 = 10000;
if(nSelfType == enActor && nKillType == enActor)
{
S13 -= m_nPkDamageAbsorbRatio;
// int nAbsorb = absDrop * (m_nPkDamageAbsorbRatio / 10000.0);
// nFinalDamageValue -= nAbsorb;
#ifdef _DEBUG
// S12
SNPRINTFA(s_HurtValueBuff,100," //S13:%d;",S13);
s_HurtValueMsg += s_HurtValueBuff;
#endif
}
//伤害流程计算
//s6 = s6*s7*s8*s9*s11*s12*s13
absDrop = (int)(absDrop*(S7/10000.0)*(S8/10000.0)*(S9/10000.0)*(S10/10000.0)*(S11/10000.0)*(S12/10000.0)*(S13/10000.0));
// absDrop += nFinalDamageValue;
#ifdef _DEBUG
// Z1
SNPRINTFA(s_HurtValueBuff,100," //Z1:%d;",absDrop);
s_HurtValueMsg += s_HurtValueBuff;
#endif
if(absDrop <= 0)
absDrop = 1;
//剧毒绝对(绝对值)
if(m_nToxicAttckValue)
{
#ifdef _DEBUG
// J1
SNPRINTFA(s_HurtValueBuff,100," //J1:%d;",m_nToxicAttckValue);
s_HurtValueMsg += s_HurtValueBuff;
#endif
absDrop += m_nToxicAttckValue;
static int nTXJDCJ = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nTXJDCJ;
CEntityMsg msg2(CEntityMsg::emShowEntityEffect, GetHandle());
msg2.nParam1 = nTXJDCJ;
msg2.nParam3 = (int)m_nToxicAttckValue;
this->PostEntityMsg(msg2);
m_nToxicAttckValue = 0;
}
//冰冻伤害(绝对值)
if(m_nSZASAttckValue)
{
#ifdef _DEBUG
// J1
SNPRINTFA(s_HurtValueBuff,100," //J2:%d;",m_nSZASAttckValue);
s_HurtValueMsg += s_HurtValueBuff;
#endif
absDrop += m_nSZASAttckValue;
static int nTXSZAS = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nTXSZAS;
CEntityMsg msg2(CEntityMsg::emShowEntityEffect, GetHandle());
msg2.nParam1 = nTXSZAS;
msg2.nParam3 = (int)m_nSZASAttckValue;
this->PostEntityMsg(msg2);
m_nSZASAttckValue = 0;
}
//怪物收到攻击的时候需要计算一下声音
if ((nSelfType == enPet || nSelfType == enActor || nSelfType == enHero) && hasKiller && IsInited() && nKillType == enActor && this != pKiller)
{
CActor *pAttacked = ((CActor*)this);
if (nSelfType == enPet)
{
pAttacked = ((CPet *)this)->GetMaster();
}
else if(nSelfType == enHero)
{
pAttacked = ((CHero *)this)->GetMaster(); //主人
}
if (pAttacked)
{
CActorPacket pack ;
pAttacked->AllocPacket(pack);
pack << (BYTE) enSkillSystemID <<(BYTE)sAttackByActor;
pack << (Uint64)(pKiller->GetHandle()) ;
pack.flush();
//动攻击黄名、白名玩家后,变成褐名
((CActor*)this)->GetSkillSystem().SetInitiativeAttack(pKiller,pAttacked);
if(bGuardEff) {
static int nGuardEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nGuardEffId;
CEntityMsg msg(CEntityMsg::emShowEntityEffect, pKiller->GetHandle());
msg.nParam1 = nGuardEffId;
this->PostEntityMsg(msg);
}
}
}
//掉血判断
if(absDrop <=0)
{
OutputMsg(rmTip, _T("收到攻击,但无伤害!"));
return;
}
nHpDrop = - absDrop;
}
else
{
nHpDrop = hpDrop;
}
if(m_DieRefreshHpPro > 0 || m_MonsterDieHpPro > 0)
{
if (m_MonsterDieHpPro > 0)
{
m_DieRefreshHpPro = m_MonsterDieHpPro;
}
}
//兵魂-救主灵刃
if(pKiller)//&& btHitType != htFire)
{
if(nSelfType == enActor)
{
int nCurrentHP = GetProperty<unsigned int >(PROP_CREATURE_HP);
int nMaxHP = GetProperty<unsigned int >(PROP_CREATURE_MAXHP);
//救主灵刃CD时间为0不触发
if(m_nSaviorTime && (nCurrentHP - absDrop) < (nMaxHP * (float)GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nSaviorPercen / 10000) && m_nJZLRCDTime < GetGlobalLogicEngine()->getMiniDateTime())
{
bool bExitJZLRBuff = true;
std::vector<int>::iterator iter = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.vJZLRBuff.begin();
for (; iter != GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.vJZLRBuff.end(); ++iter)
{
CBuffProvider::BUFFCONFIG * pBUFFCONFIG = GetLogicServer()->GetDataProvider()->GetBuffProvider().GetBuff(*iter);
if(pBUFFCONFIG)
{
CDynamicBuff* pDynamicBuff = GetBuffSystem()->GetBuff((GAMEATTRTYPE)pBUFFCONFIG->nType, pBUFFCONFIG->nGroup);
if(!pDynamicBuff)
{
bExitJZLRBuff = false;
break;
}
}
}
if (bExitJZLRBuff)
{
//触发效果抵御本次伤害并回复最大HP的百分比 + 绝对值
nHpDrop = nMaxHP * (m_nSaviorRate / 10000.0) + m_nSaviorValue;
//设置救主灵刃CD时间
m_nJZLRCDTime = GetGlobalLogicEngine()->getMiniDateTime() + (m_nSaviorTime / 1000);
//设置救主Buff的CD时间
CBuffProvider::BUFFCONFIG * pBUFFCONFIG = GetLogicServer()->GetDataProvider()->GetBuffProvider().GetBuff(nJZBuffId);
if(pBUFFCONFIG)
{
CDynamicBuff* pDynamicBuff = GetBuffSystem()->GetBuff((GAMEATTRTYPE)pBUFFCONFIG->nType, pBUFFCONFIG->nGroup);
if( pDynamicBuff )
{
pDynamicBuff->m_nBuffCd = (m_nSaviorTime / 1000);
GetBuffSystem()->OnBuffChangeCdTime(pDynamicBuff);
}
}
//针对离线CD重置的处理
((CActor*)this)->SaveJZLRCDTime(szJZLRCDTime, m_nJZLRCDTime);
static int nTXJZLR = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nTXJZLR;
CEntityMsg msg(CEntityMsg::emShowEntityEffect, GetHandle());
msg.nParam1 = nTXJZLR;
PostEntityMsg(msg);
}
}
}
}
//OutputMsg(rmTip, _T("真实伤害 玩家name: , 伤害:%d, "), nHpDrop);
//Z2
if(hpDrop < 0)
{
if (!bIgnoreMaxDropHp) //是否忽略每次最大伤害限制
{
int nMaxDropHp = GetMaxDropHp();
if(nMaxDropHp > 0) //每次掉血的数量
{
if(-nHpDrop > nMaxDropHp ) //如果掉落的血超过了最大,就直接设置为掉落
{
nHpDrop = -nMaxDropHp;
}
}
}
}
if (nSelfType == enMonster)
{
if(((CMonster*)this)->GetMonsterType() == MONSTERCONFIG::mtKungfu)
{
if (nKillType == enActor)
{
char cBuff[30];
SNPRINTFA(cBuff,100,"伤害: %d",-nHpDrop);
std::string sFinalHurt;
sFinalHurt += cBuff;
((CActor*)pKiller)->SendTipmsg(sFinalHurt.c_str(),tstFigthing);
}
return;
}
}
Inherited::ChangeHP(nHpDrop,pKiller);
//H1
if(hpDrop < 0)
{
if(btHitType != htFire && pKiller && pKiller->isAnimal())
{
if( ((CAnimal*)pKiller)->m_nSuckBloodRatio > 0)
{
int nDamage = absDrop;
if (!bIgnoreMaxDropHp) //是否忽略每次最大伤害限制
{
int nMaxDropHp = GetMaxDropHp();
if(nMaxDropHp > 0) //每次掉血的数量
{
if(nDamage > nMaxDropHp ) //如果掉落的血超过了最大,就直接设置为掉落
{
nDamage = nMaxDropHp;
}
}
}
int nSuckBloodRatio = ((CAnimal*)pKiller)->m_nSuckBloodRatio;
LONG64 nSuck = (LONG64)(nDamage*( (double)nSuckBloodRatio/10000.0) );
int nSuckBloodRate = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nSuckBloodRate; //吸血属性(怪物)
int nSuckBloodRatePlayer = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nSuckBloodRatePlayer ; //吸血属性 (玩家)万分比
if(nSelfType == enActor && nKillType == enActor)//如果是玩家对玩家
{
nSuck = (LONG64)nSuck * ((double)nSuckBloodRatePlayer/10000.0);
}
else
{
nSuck = (LONG64)nSuck * ((double)nSuckBloodRate/10000.0);//* nSuckBloodRate/10000.0;
}
//OutputMsg(rmTip, _T("吸血伤害 玩家name: , 原始伤害:%d 吸血:%d 比例:%d "), (int)absDrop, (int)nSuck, ((CAnimal*)pKiller)->m_nSuckBloodRatio);
((CAnimal*)pKiller)->ChangeHP(nSuck);
#ifdef _DEBUG
// H1
SNPRINTFA(s_HurtValueBuff,100," //H1:%d;",nSuck);
s_HurtValueMsg += s_HurtValueBuff;
#endif
}
}
}
if (nHpDrop < 0)//2017-03-29修改掉血数据放在changehp后下发并实时下发当前血量,不用等属性变化再刷新,会有延迟
{
int absDrop = -nHpDrop; //掉了多少血
int nHp = GetProperty<unsigned int >(PROP_CREATURE_HP);
if(hasKiller && nKillType ==enActor && pKiller->IsInited() && this != pKiller)
{
if(absDrop >0 ) //有掉血的话,就需要给打出伤害这边的发一个消息包
{
if(GetType() != enGatherMonster)
{
int nMusicId=0;
if(nSelfType ==enMonster)
{
const PMONSTERCONFIG pMonster= GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(GetProperty<int>(PROP_ENTITY_ID));
if( pMonster !=NULL )
{
int nRate = pMonster->bDamageMusicRate;
int nId = pMonster->bDamageMusicId;
if(nRate >0 && nId >0)
{
if(nRate >=100 || nRate >= (int)(wrand(101)))
{
nMusicId = nId;
}
}
}
}
//自己对怪物造成的伤害要播放一个声音,宝宝的不要
unsigned int nCritDamage = 0;
if (boSkillResult)
{
nCritDamage = pKiller->GetProperty<unsigned int>(PROP_ACTOR_CRIT_DAMAGE);
}
char buff[1024];
CDataPacket outPack(buff, sizeof(buff)); //下发的数据包
outPack << (BYTE) enSkillSystemID <<(BYTE)sSelfDamageOther;
//GetHandle() 用于客户端查找 对应句柄的玩家
outPack <<GetHandle() << (int)absDrop << nMusicId << nCritDamage << nHp;
if (boSkillResult)
{
pKiller->SetProperty<unsigned int>(PROP_ACTOR_CRIT_DAMAGE,0);
}
((CActor*)pKiller)->SendData(outPack.getMemoryPtr(), outPack.getPosition());
if(nSelfType == enActor)
{
CActor *pAttacked = ((CActor*)this);
if(pAttacked && pAttacked->IsInited())
pAttacked->SendData(outPack.getMemoryPtr(), outPack.getPosition());
}
}
}
}
//宠物打出血了,要告诉宠物的主人,通知是自己打出来的
if(hasKiller && (nKillType ==enPet || nKillType == enHero))
{
if(absDrop >0 ) //有掉血的话,就需要给打出伤害这边的发一个消息包
{
if(GetType() != enGatherMonster)
{
CActor *pMaster = NULL;
if(nKillType == enPet)
{
pMaster=((CPet*)pKiller)->GetMaster(); //主人
}
else if(nKillType == enHero)
{
pMaster=((CHero*)pKiller)->GetMaster(); //主人
}
if(pMaster && pMaster->IsInited())
{
CActorPacket pack ;
pMaster->AllocPacket(pack);
pack << (BYTE) enSkillSystemID <<(BYTE)sSelfDamageOther;
pack << GetHandle() << (int)absDrop << (int)0 << (unsigned int)0<<nHp;
pack.flush();
}
}
}
}
}
}
void CAnimal::OnEntityRelive()
{
if(m_pAI == NULL) return;
CSkillSubSystem & skillSystem = m_pAI->m_pSelf->GetSkillSystem();
const CVector<CSkillSubSystem::SKILLDATA> & skills= skillSystem.GetSkills();
//这里加这个是为了一个技能
for(INT_PTR i=0; i< skills.count();i++)
{
if(skills[i].bEvent == mSkilleventAlive)
{
skillSystem.LaunchSkill(skills[i].nSkillID);
}
}
}
void CAnimal::ChangeName(const char* sName)
{
//OutputMsg(rmNormal, _T("CAnimal::ChangeName(), pShowsNameName=%s"), sName);
if(sName ==NULL) return;
if( strcmp(GetEntityName(), sName) ==0) return; //如果没有改变就不弄
//SetEntityName(sName);
char buff[148];
CDataPacket data(buff,sizeof(buff));
data << (BYTE)enDefaultEntitySystemID <<(BYTE) sChangeShowName ;
data << (Uint64) GetHandle(); //实体句柄
data.writeString(GetShowName()); //将这个字符串写入
if(GetType() ==enActor)
{
m_observerSystem.BroadCast(data.getMemoryPtr(), data.getPosition(),true);
}
else
{
m_observerSystem.BroadCast(data.getMemoryPtr(), data.getPosition(),false);
}
}
void CAnimal::ChangeShowName(int nRadius, LPCTSTR sName)
{
if (sName ==NULL) return;
if (strcmp(GetShowName(), sName) ==0) return; //如果没有改变就不弄
CScene * pScene = GetScene();
if (!pScene) return;
SetShowName(sName);
char sAllName[128];
if (GetType() == enNpc)
{
sprintf_s(sAllName,sizeof(sAllName),"%s\\%s",sName,GetTitle());
}
else
{
strncpy(sAllName, sName, strlen(sName));
}
EntityVector &vecPlys = *(CFuBenManager::m_pVisibleList);
vecPlys.clear();
pScene->GetVisibleList(this, vecPlys, -nRadius, nRadius, -nRadius, nRadius);
INT_PTR nEntityCount = vecPlys.count();
if (nEntityCount > 0)
{
Uint64 hEntityHandle = (Uint64)GetHandle();
CEntityManager * pMgr = GetGlobalLogicEngine()->GetEntityMgr();
for (int i = 0; i < nEntityCount; i++)
{
CEntity * pActor = pMgr->GetEntity(vecPlys[i]);
if (pActor && pActor->GetType() == enActor)
{
CActorPacket ap;
CDataPacket & outPack = ((CActor*)pActor)->AllocPacket(ap);
outPack << (BYTE)enDefaultEntitySystemID << (BYTE)sChangeShowName;
outPack << hEntityHandle;
outPack.writeString(sAllName); //名字=名字+'\'+称号,用\隔开
ap.flush();
}
}
}
}
void CAnimal::ChangeModel(int nRadius, int nModelId)
{
CScene * pScene = GetScene();
if (!pScene)
return;
if (GetProperty<unsigned int>(PROP_ENTITY_MODELID) == nModelId)
return;
SetProperty<unsigned int>(PROP_ENTITY_MODELID, nModelId);
EntityVector &vecPlys = *(CFuBenManager::m_pVisibleList);
vecPlys.clear();
pScene->GetVisibleList(this, vecPlys, -nRadius, nRadius, -nRadius, nRadius);
INT_PTR nEntityCount = vecPlys.count();
if (nEntityCount > 0)
{
Uint64 hEntityHandle = (Uint64)GetHandle();
CEntityManager * pMgr = GetGlobalLogicEngine()->GetEntityMgr();
for (int i = 0; i < nEntityCount; i++)
{
CEntity * pActor = pMgr->GetEntity(vecPlys[i]);
if (pActor && pActor->GetType() == enActor)
{
CActorPacket ap;
CDataPacket & outPack = ((CActor*)pActor)->AllocPacket(ap);
outPack << (BYTE)enDefaultEntitySystemID << (BYTE)sEntityPropertyChange;
outPack << hEntityHandle << (BYTE)1 << (BYTE)PROP_ENTITY_MODELID << nModelId;
ap.flush();
}
}
}
}
void CAnimal::SetAttackType(int nType,bool bNeedBroadCast )
{
m_nAttackType = nType;
if(bNeedBroadCast)
{
char buff[128];
CDataPacket data(buff,sizeof(buff));
data << (BYTE) enDefaultEntitySystemID << (BYTE) sChangeAttackType
<< (Uint64)GetHandle() << (BYTE) m_nAttackType;
CObserverSystem * pSystem = GetObserverSystem();
if(pSystem)
{
pSystem->BroadCast(data.getMemoryPtr(),data.getPosition(),false);
}
}
}
void CAnimal::SetCamp(int nCampId)
{
if(GetType() != enActor)
{
m_nCamp = nCampId;
}
else
{
SetProperty<int>(PROP_ACTOR_ZY, nCampId);
}
}
void CAnimal::OnAttacked(CAnimal * pEntity, bool bSetVest)
{
bool bUpdateAttackStatus = true;
INT_PTR nType = GetType();
CAnimalAI* pAI = GetAI();
if (pAI)
{
pAI->AttackedBy(pEntity);
bUpdateAttackStatus = false;
}
if (pEntity )
{
INT_PTR nAttackEntityType = ((CEntity*)pEntity)->GetType();
if ( nAttackEntityType == enActor || nAttackEntityType == enPet || nAttackEntityType == enHero || nAttackEntityType == enMonster )
{
if ( (nType == enMonster && GetAttriFlag().attackToScript) || nType != enMonster )
{
CFuBen* pFB = GetFuBen();
if (pFB && pFB->IsFb())
{
// 副本实体受伤事件
CScriptValueList paramList;
paramList << (int)CFubenSystem::enOnAttacked;
paramList << (int)pFB->GetConfig()->nFbConfType;
paramList << (int)pFB->GetFbId();
paramList << (int)pFB->GetConfig()->nFbEnterType;
paramList << pFB;
paramList << (int)GetSceneID();
paramList << this;
paramList << pEntity;
if(!GetGlobalLogicEngine()->GetGlobalNpc()->GetScript().CallModule("FubenDispatcher","OnEvent", paramList, paramList, 1))
{
OutputMsg(rmError,"[FubenSystem] OnEvent OnAttacked 错误副本ID=%d副本类型=%d !",pFB->GetFbId(),pFB->GetConfig()->nFbConfType);
}
}
if (pFB && !(pFB->IsFb()))
{
// 触发进入活动区域事件
int nPosX,nPosY;
this->GetPosition(nPosX,nPosY);
CScene* pScene = this->GetScene();
SCENEAREA* pArea = pScene->GetAreaAttri(nPosX, nPosY);
if (pScene && pArea && pScene->HasMapAttribute(nPosX,nPosY,aaActivity,pArea))
{
static CNpc* globalNpc = GetGlobalLogicEngine()->GetGlobalNpc();
CScriptValueList paramList;
AreaAttri * pAreaAttr = &pArea->attri[aaActivity];
for (size_t i = 0; i < pAreaAttr->nCount; i++)
{
int nAtvId = pAreaAttr->pValues[i];
// 个人活动
if((this->GetType() == enActor) && ((CActor*)this)->GetActivitySystem().IsActivityRunning(nAtvId))
{
if (PersonActivtyData* pActivty = ((CActor*)this)->GetActivitySystem().GetActivity(nAtvId))
{
paramList.clear();
paramList << (int)CActivitySystem::enOnAtvAreaAtk;
paramList << (int)pActivty->nActivityType;
paramList << (int)pActivty->nId;
paramList << this;
paramList << pEntity;
if (!globalNpc->GetScript().CallModule("ActivityDispatcher", "OnEvent", paramList, paramList))
{
OutputMsg(rmError,"[Personal Activity] OnEvent错误 enOnEnterArea活动Type=%d, 活动ID=%d !",pActivty->nActivityType,pActivty->nId);
}
}
}
// 全局活动
else if(GetGlobalLogicEngine()->GetActivityMgr().IsRunning(nAtvId))
{
if (GlobalActivityData* pActivty = GetGlobalLogicEngine()->GetActivityMgr().GetActivity(nAtvId))
{
paramList.clear();
paramList << (int)CActivitySystem::enOnAtvAreaAtk;
paramList << (int)pActivty->nActivityType;
paramList << (int)pActivty->nId;
paramList << this;
paramList << pEntity;
if (!globalNpc->GetScript().CallModule("ActivityDispatcher", "OnEvent", paramList, paramList))
{
OutputMsg(rmError,"[Global Activity] OnEvent错误 enOnEnterArea活动Type=%d, 活动ID=%d !",pActivty->nActivityType,pActivty->nId);
}
}
}
}
}
}
// CActor* pActor = NULL;
// if (nAttackEntityType == enPet)
// {
// pActor = ((CPet*)pEntity)->GetMaster();
// }
// else if ( nAttackEntityType == enHero )
// {
// pActor = ((CHero*)pEntity)->GetMaster();
// }
// else
// {
// pActor = (CActor*)pEntity;
// }
// CScriptValueList paramList, retList;
// CNpc* pNpc = GetGlobalLogicEngine()->GetGlobalNpc();
// paramList<< (CAnimal*)this << (CActor*)pActor;
// if (pNpc != NULL)
// {
// pNpc->GetScript().Call("OnMonsterAttackBy",paramList,retList );
// }
}
}
}
if(! HasState(esStateBattle) )
{
if (bUpdateAttackStatus)
{
AddState(esStateBattle);
}
}
else
{
// 玩家被非玩家攻击,不推迟离开战斗时间
bool bPostpone = true;
if (enActor == GetType() && pEntity->GetType() != enActor)
bPostpone = false;
if (bPostpone)
postponeLeaveCombatTimer();
}
}
void CAnimal::OnAttackOther(CAnimal * pEntity, bool bChgDura)
{
if(! HasState(esStateBattle) )
{
AddState(esStateBattle );
}
else
{
// 玩家攻击其他非玩家实体,不推迟离开战斗时间
bool bPostpone = true;
if (enActor == GetType() && pEntity->GetType() != enActor)
bPostpone = false;
if (bPostpone)
postponeLeaveCombatTimer();
}
}
void CAnimal::OnEnterBattle()
{
bool bPostpone = true;
if (enActor == GetType())
{
EntityHandle eh = GetTarget();
// 虽然enActor也是为0这里最好别去掉以防以后修改枚举类型 marked by wp 2011.9.15
if (!eh.IsNull() && eh.GetType() != enActor)
bPostpone = false;
}
if (bPostpone)
postponeLeaveCombatTimer();
}
void CAnimal::postponeLeaveCombatTimer()
{
m_battleLeftTime = GetGlobalLogicEngine()->getTickCount() + getLeaveCombatTime();
}
bool CAnimal::CheckCommonOpTickBefore(TICKCOUNT nTick)
{
if ((m_tOpsTimer.GetNextTime() - nTick) > 10000)
{
m_tOpsTimer.SetNextHitTime(nTick);
}
}
bool CAnimal::CheckCommonOpTick(TICKCOUNT nTick, bool bFailSendmsg, bool bMoveOp)
{
if (GetType() == enActor && bMoveOp)
{
return true;
}
if( m_tOpsTimer.Check(nTick) ) return true;
else
{
if(GetType() == enActor && bFailSendmsg)
{
/*OutputMsg(rmWaning,_T("Fail 下次的OP=%lld,current=%lld"),m_tOpsTimer.GetNextTime(), nTick );*/
((CActor*)this)->SendOperateResult(false);
}
return false;
}
}
void CAnimal::SetCommonOpNextTime(INT_PTR nNextTime,bool bSendResult2Client ,bool bResult, unsigned int nStep, unsigned int nSendPkgTick, bool bUseGateTime,bool bUseCheckCd,bool bNearAttackSuc)
{
if(GetType() == enActor)
{
CActor* pActor = (CActor *)this;
pActor->SetCommonOpNextTimeImpl(nNextTime, bSendResult2Client, bResult, nStep, nSendPkgTick, bUseGateTime,bUseCheckCd,bNearAttackSuc );
}
else
{
m_tOpsTimer.SetNextHitTimeFromNow(nNextTime);
}
}
VOID CAnimal::ChangeMP(int nValue)
{
Inherited::ChangeMP(nValue);
}
VOID CAnimal::LogicRun(TICKCOUNT nCurrentTime)
{
//DECLARE_FUN_TIME_PROF()
if(IsInited() ==false ) return;
Inherited::LogicRun(nCurrentTime);
//3秒钟回血回蓝
/************************************************************************
* 注意:为了提高程序运行效率。这里定时器不要并排执行,按照精度由高到低进行
层级嵌套。如果因为逻辑功能需要调整定时精度,需谨慎!!!必要时需要
修改层级关系。
/************************************************************************/
//怪物和宠物才执行移动的检测
INT_PTR nType = GetType();
switch(nType)
{
case enNpc:
return;
case enMonster:
case enPet:
case enHero:
case enActor:
{
m_moveSystem.OnTimeCheck(nCurrentTime);
break;
}
}
if (m_t500ms.CheckAndSet(nCurrentTime,true))
{
if (m_pAI)
m_pAI->UpdateAI(nCurrentTime);
if(m_nDizzyTime && m_nDizzyTime < nCurrentTime)
RemoveDizzyState();
}
// 更新观察者、技能子系统、技能AdornFlags
if (m_tRefViewTimer.CheckAndSet(nCurrentTime, true))
{
m_observerSystem.OnTimeCheck(nCurrentTime);
}
if(m_t1S.CheckAndSet(nCurrentTime, true))
{
m_skillSystem.OnTimeCheck(nCurrentTime); //技能的吟唱
//定时检测buff子系统
m_buffSystem.OnTimeCheck(nCurrentTime);
if (HasState(esStateBattle))
{
//只有玩家才去掉战斗状态
if (nCurrentTime >= m_battleLeftTime && nType ==enActor) //要脱离战斗了
{
RemoveState(esStateBattle); //脱离战斗
/*
if (m_pAI)
{
m_pAI->AttackStop(NULL);
}
*/
}
}
// 更新效果子系统
m_effectSystem.OnTimeCheck(nCurrentTime);
// 生物回血、回蓝处理
if( m_t2s.CheckAndSet(nCurrentTime, true))
{
/*if(!IsDeath() && nType == enHero) //英雄回血不需要战斗状态
{
if(!GetAttriFlag().DenyAutoAddHp)
{
static int s_nHpRenewAdd = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nHpRenewAdd;
static float s_fHpRenewRate =GetLogicServer()->GetDataProvider()->GetGlobalConfig().fHpRenewRate;
int nMaxHp = 0;
const CHeroSystem::HERODATA *pHero = ((CHero *)(this))->GetHeroPtr();
nMaxHp = pHero->nBaseMaxHp;
int nAddValue = (int) ( ( (int)(nMaxHp * s_fHpRenewRate) + s_nHpRenewAdd )*(1 + (float)GetProperty<unsigned int>(PROP_CREATURE_HP_RATE_RENEW)/10000 ));
nAddValue = nAddValue + GetProperty<int>( PROP_CREATURE_HP_RENEW );
ChangeHP(nAddValue);
}
if(!GetAttriFlag().DenyAutoAddMp)
{
static int s_nMpRenewAdd = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nMpRenewAdd;
static float s_nMpRenewRate =GetLogicServer()->GetDataProvider()->GetGlobalConfig().fMpRenewRate;
int nMaxMp = 0;
const CHeroSystem::HERODATA *pHero = ((CHero *)(this))->GetHeroPtr();
nMaxMp = pHero->nBaseMaxMp;
int nAddValue = (int) ( ( (int)(nMaxMp * s_nMpRenewRate) + s_nMpRenewAdd )*(1 + (float)GetProperty<unsigned int>(PROP_CREATURE_MP_RATE_RENEW)/10000 ));
nAddValue = nAddValue + GetProperty<int>( PROP_CREATURE_MP_RENEW );
ChangeMP(nAddValue);
}
}
else */if(!IsDeath() && !HasState(esStateBattle)) //死了不加血加蓝的
{
if (CDynamicBuff * pForbidHpRenewBuff = GetBuffSystem()->GetBuff(aForbidHpRenew, CDynamicBuff::AnyBuffGroup))
{
// 施毒术BUFF 禁止回血蓝
}
else
{
if(!GetAttriFlag().DenyAutoAddHp)
{
int nMaxHp = 0;
if (nType == enActor)
{
nMaxHp = ((CActor *)(this))->m_nBase_MaxHp;
}
else
{
nMaxHp = GetProperty< int>( PROP_CREATURE_MAXHP);
}
if (GetProperty<unsigned int>(PROP_CREATURE_HP) < nMaxHp)
{
int nAddValue = (int) (nMaxHp * ((float)GetProperty<unsigned int>(PROP_CREATURE_HP_RATE_RENEW)/10000));
nAddValue = nAddValue + GetProperty<int>( PROP_CREATURE_HP_RENEW );
ChangeHP(nAddValue);
}
}
if(!GetAttriFlag().DenyAutoAddMp)
{
int nMaxMp = 0;
if (nType == enActor)
{
nMaxMp = ((CActor *)(this))->m_nBase_MaxMp;
}
else
{
nMaxMp = GetProperty< int>( PROP_CREATURE_MAXMP);
}
if (GetProperty<unsigned int>(PROP_CREATURE_MP) < nMaxMp)
{
int nAddValue = (int) (nMaxMp*((float)GetProperty<unsigned int>(PROP_CREATURE_MP_RATE_RENEW)/10000));
nAddValue = nAddValue + GetProperty<int>( PROP_CREATURE_MP_RENEW );
ChangeMP(nAddValue);
}
}
}
}
}
if(m_nSaviorTime && m_nJZLRCDTime < GetGlobalLogicEngine()->getMiniDateTime())
{
UpdateJZLR();
}
}
}
VOID CAnimal::AfterLogicRun(TICKCOUNT nCurrentTime)
{
Inherited::AfterLogicRun(nCurrentTime);
INT_PTR i;
//处理集中的汇总操作
for (i=0; i<CEntityOPCollector::CollectedOperationCount; ++i)
{
if ( m_OPCollector.isCollected((CEntityOPCollector::CollecteOPType)i) )
{
DoCollectedOperation((CEntityOPCollector::CollecteOPType)i);
}
}
m_OPCollector.Reset();
}
bool CAnimal::_CanAttack(CAnimal *pTargetEntity, CAnimal *pPet, bool boAttackNotice)
{
if ( !pTargetEntity )
{
return false;
}
if(IsAttackImmune() || pTargetEntity->IsAttackImmune() ) return false;
INT_PTR nSrcType = GetType();
INT_PTR nTargetType = pTargetEntity->GetType();
if(this == pTargetEntity) return false; //自己不能攻击自己
if(nTargetType ==enNpc) return false;
if (!pTargetEntity->isAnimal()) return false;
if(nSrcType ==enPet )
{
CPet *pPet = (CPet*)this;
if(pPet->GetMaster() == NULL) return false;
if (GetAttriFlag().AttackPet)
{
return true;
}
return pPet->GetMaster()->CanAttack(pTargetEntity);
}
else if(nSrcType ==enHero)
{
CHero *pHero = (CHero*)this;
if(pHero->GetMaster() == NULL) return false;
return pHero->GetMaster()->CanAttack(pTargetEntity);
}
if( nTargetType ==enPet)
{
CPet *pPet = (CPet*)pTargetEntity;
if(pPet->GetMaster() == NULL) return false;
return CanAttack(pPet->GetMaster(), pPet); //能否攻击他的主人
}
else if(nTargetType ==enHero)
{
CHero *pHero = (CHero*)pTargetEntity;
if(pHero->GetMaster() == NULL) return false;
return CanAttack(pHero->GetMaster());
}
//不能被攻击
if(pTargetEntity->GetAttriFlag().DenyBeAttack)
{
return false;
}
//无敌buff不能攻击
if( nSrcType == enActor)
{
//如果玩家杀对方对方存在pk保护状态那么不能杀
if( pTargetEntity->GetBuffSystem()->Exists(aPkProtectState) ) return false;
//玩家不能功能本阵营的怪物
if( nTargetType ==enMonster)
{
if(pTargetEntity->GetCampId() )
{
if(pTargetEntity->GetCampId() == GetCampId()) return false;
}
}
if(nTargetType ==enActor)
{
return ((CActor *)this)->GetPkSystem().CanAttack((CActor*) pTargetEntity, pPet, boAttackNotice);
}
//怪物拒绝被玩家攻击
if(pTargetEntity->GetAttriFlag().DenyAttackedByActor)
{
return false;
}
if (pTargetEntity->IsMonster() )
{
CMonster *pMonster = (CMonster *)pTargetEntity;
if (pMonster->GetOwner() == GetHandle()) // 不能打归属于自己的怪
return false;
//如果配置了行会id
if(pTargetEntity->GetNpcGuildId() && GetProperty<unsigned int>(PROP_ACTOR_GUILD_ID) == pTargetEntity->GetNpcGuildId())
return false;
return true;
}
}
else if(nSrcType == enMonster)
{
// 怪物不能打NPC和采集怪
if (enGatherMonster == nTargetType)
{
return false;
}
// 怪物配置了阵营ID并且目标怪物或者玩家的阵营相同不能攻击
else if (enActor == nTargetType)
{
//如果配置了行会id
if(GetNpcGuildId() && pTargetEntity->GetProperty<unsigned int>(PROP_ACTOR_GUILD_ID) == GetNpcGuildId())
return false;
}
// 怪物不打同阵营的玩家
if( GetCampId() && nTargetType ==enActor &&pTargetEntity->GetCampId() == GetCampId())
{
return false;
}
}
//拒绝攻击玩家
if(nTargetType == enActor && GetAttriFlag().DenyAttackActor)
{
return false;
}
//如果目标是一个怪物,并且没有主人
if(nTargetType == enMonster && /*((CMonster*)pTargetEntity)->GetOwner().IsNull()) && */!GetAttriFlag().CanAttackMonster )
{
return false;
}
if(nSrcType ==enMonster) //如果释放者是一个怪物
{
return true;
}
return false;
}
bool CAnimal::CanAttack(CAnimal *pTargetEntity, CAnimal *, bool)
{
// 同阵营判断
if(pTargetEntity->GetCampId())
{
if(pTargetEntity->GetCampId() == GetCampId()) return false;
}
// 怪物的不能被攻击标志判断
if (pTargetEntity->IsMonster())
{
if (pTargetEntity->GetAttriFlag().DenyBeAttack)
{
return false;
}
return true;
}
else
{
// 如果A是宠物则看主人能否攻击目标
if (GetType() == enPet)
{
CPet *pSelf = (CPet*)this;
if(pSelf->GetMaster() == NULL) return false;
return pSelf->GetMaster()->CanAttack(pTargetEntity);
}
// 如果A是玩家
else if (GetType() == enActor)
{
CActor *pSelf = ((CActor *)this);
// 如果B是宠物
if (pTargetEntity->GetType() == enPet)
{
CPet *pTarPet = (CPet*)pTargetEntity;
if(pTarPet->GetMaster() == NULL) return false;
return pSelf->GetPkSystem().CanAttack(pTarPet->GetMaster(), pTarPet)
&& pSelf->GetPkSystem().IsUnLimited(pTargetEntity);
}
// 如果B是玩家
else// if (pTargetEntity->GetType() == enActor)
{
return pSelf->GetPkSystem().CanAttack((CActor*)pTargetEntity)
&& pSelf->GetPkSystem().IsUnLimited(pTargetEntity);
}
}else
{
return true;
}
}
}
bool CAnimal::IsFriend(CAnimal *pTargetEntity)
{
// 同阵营判断
if(pTargetEntity->GetCampId())
{
if(pTargetEntity->GetCampId() == GetCampId()) return false;
}
// 怪物的不能被攻击标志判断
if (pTargetEntity->IsMonster() && pTargetEntity->GetAttriFlag().DenyBeAttack)
{
return false;
}
// 如果A是宠物则看主人能否攻击目标
if (GetType() == enPet)
{
CPet *pSelf = (CPet*)this;
if(pSelf->GetMaster() == NULL) return false;
return pSelf->GetMaster()->CanAttack(pTargetEntity);
}
// 如果A是玩家
else if (GetType() == enActor)
{
CActor *pSelf = ((CActor *)this);
// 如果B是宠物
if (pTargetEntity->GetType() == enPet)
{
CPet *pTarPet = (CPet*)pTargetEntity;
if(pTarPet->GetMaster() == NULL) return false;
return pSelf->GetPkSystem().CanAttack(pTarPet->GetMaster());
}
// 如果B是玩家
else// if (pTargetEntity->GetType() == enActor)
{
return pSelf->GetPkSystem().CanAttack((CActor*)pTargetEntity);
}
}
return true;
}
VOID CAnimal::DoCollectedOperation(CEntityOPCollector::CollecteOPType eOPType)
{
INT_PTR nEntityType;
switch(eOPType)
{
case CEntityOPCollector::coRefAbility:
//TODO:实现刷新人物、被动技能、装备、经脉、BUFF等属性的全部属性刷新功能并向角色发送属性变更的消息
//#pragma __CPMSG__(TODO:实现刷新人物、被动技能、装备、经脉、BUFF等属性的全部属性刷新功能并向角色发送属性变更的消息)
GetPropertySystem().ResertProperty(); //重置属性
break;
case CEntityOPCollector::coRefFeature:
nEntityType =GetType();
if(nEntityType == enActor )
{
((CActor*)this)->GetEquipmentSystem().RefreshAppear(); //刷新外形
}
break;
case CEntityOPCollector::coTransport: //这个玩家是传送过来的,通知其他人,需要播放一个特效
//((CActor*)this)->NotifyNearbyTransport();
this->GetMoveSystem()->SetMoveFlag( CMovementSystem::mfTransport, false); //设置为传送标记
break;
case CEntityOPCollector::coResetMaxHPMP:
{
SetProperty(PROP_CREATURE_HP, GetProperty<unsigned int>(PROP_CREATURE_MAXHP));
SetProperty(PROP_CREATURE_MP, GetProperty<unsigned int>(PROP_CREATURE_MAXMP));
}
break;
case CEntityOPCollector::coRefMonsterDynProp:
{
GetPropertySystem().ResertProperty(); //重置属性
// 将怪物HP设置为满
//if (!HasState(esStateBattle))
//{
//SetProperty(PROP_CREATURE_HP, GetProperty<unsigned int>(PROP_CREATURE_MAXHP));
//}
break;
}
default:
break;
}
}
void CAnimal::ProcessEntityMsg(const CEntityMsg &msg)
{
char buff[256];
CEntity * pEntity;
int x,y,dis;
//如果消息已经被写坏了,则不执行
if(msg.bIsUsed ==false)
{
OutputMsg(rmError,"name=%s,msgid=%d,ProcessEntityMsg is invalid",GetEntityName(),(int)msg.nMsg);
return ;
}
switch(msg.nMsg)
{
case CEntityMsg::emRealLaunchSkill:
{
m_skillSystem.RealLaunchSkill((int)msg.nParam1,(CScene*)msg.pParam2,(int)msg.nParam3,
(int)msg.nParam4,(int)msg.nParam5,(CEntity *)msg.pParam6,
(int)msg.nParam7,(int)msg.nParam8);
}
break;
case CEntityMsg::emSkillApplyOneRange:
{
m_skillSystem.SkillApplyOneRange((int)msg.nParam1,
(CSkillSubSystem::PSKILLDATA)msg.pParam2,(PSKILLONERANGE)msg.pParam3,
(CEntity *)msg.pParam4,(CScene*)msg.pParam5,(int)msg.nParam6,(int)msg.nParam7,
(int)msg.nParam8,(int)msg.nParam9,(int)msg.nParam10);
}
break;
case CEntityMsg::emShowSceneEffect:
{
CDataPacket data(buff,sizeof(buff));
data << (BYTE)enDefaultEntitySystemID <<(BYTE) sAddSceneEffect ;
data << (Uint64)msg.nSender;
data << (WORD) msg.nParam1; //特效ID
data << (WORD) msg.nParam2 << (WORD) msg.nParam3; //x,y
m_observerSystem.BroadCast(data.getMemoryPtr(), data.getPosition(),true);
}
break;
case CEntityMsg::emShowEntityEffect:
{
CDataPacket data(buff,sizeof(buff));
data << (BYTE)enDefaultEntitySystemID <<(BYTE) sAddEffect;
data << (Uint64)msg.nSender << (Uint64)GetHandle();
data << (WORD) msg.nParam1; //特效ID
data <<(unsigned int)msg.nParam3;//
m_observerSystem.BroadCast(data.getMemoryPtr(), data.getPosition(),true);
//m_effectSystem.AddEffect( msg.nParam1,msg.nParam2,msg.nParam3); //添加特效
}
break;
case CEntityMsg::emSkillResult:
{
CAnimal* pSrc = (CAnimal*)GetEntityFromHandle(msg.nSender);
if (!pSrc) return;
CSkillResult * result=m_skillSystem.GetSkillResult();
SKILLRESULTPARAM skillParam; //技能的参数
skillParam.pTargetEntity = this;
skillParam.pSrcEntity = pSrc;
skillParam.nSkillID = msg.nParam1;
skillParam.nTargetPosX = (WORD)msg.nParam2;
skillParam.nTargetPosY = (WORD)msg.nParam3;
skillParam.btIgnoreDefence = (BYTE)msg.nParam4;
skillParam.btIgnoreMaxDropHp = (BYTE)msg.nParam5;
SKILLRESULT sresult; //技能的结果
sresult.nDelay = 0;
sresult.nValue = msg.nParam5;
sresult.nId = msg.nParam6;
sresult.nResultType = msg.nParam7;
skillParam.pSkillResult = &sresult;
result->DoResult(&skillParam,true); //无延迟立刻执行
}
break;
case CEntityMsg::emChangeHp:
if (msg.nParam1 > 0 || !IsDeath())
ChangeHP((int)msg.nParam1);
break;
case CEntityMsg::emReUseMonster:
{
Reuse();
break;
}
case CEntityMsg::emEntityTransfer:
{
int x,y;
GetPosition(x,y);
CObserverSystem* obs = GetObserverSystem();
TICKCOUNT tc = GetGlobalLogicEngine()->getTickCount();
obs->OnTimeCheck(tc);//先获取所有的可视玩家,因为在之前有可能被清空了
GetMoveSystem()->BroadcastMove(x,y,sActorTransport);
break;
}
case CEntityMsg::emEntityScriptDelay:
{
OnEntityScriptDelayMsgCallback((unsigned int)(msg.nParam1), (int)msg.nParam2, (int)msg.nParam3, (int)msg.nParam4, (int)msg.nParam5, (int)msg.nParam6);
break;
}
case CEntityMsg::emEntityDead:
{
if(GetProperty<unsigned int>(PROP_CREATURE_HP) == 0)
{
OnEntityDeath();
}
break;
}
case CEntityMsg::emRealTransfer:
{
GetGlobalLogicEngine()->GetFuBenMgr()->EnterFuBen(this,(CFuBen *)NULL,msg.nParam1,msg.nParam2,msg.nParam3);
break;
}
default:
Inherited::ProcessEntityMsg(msg);
break;
}
}
void CAnimal::DestroyAi()
{
if(m_pAI)
{
GetGlobalLogicEngine()->GetAiMgr().DestroyAi(m_pAI); //删除ai
m_pAI =NULL;
}
}
//初始化状态的禁止表,避免每次循环调用都去搞一下
void CAnimal::InitStateForbidMask()
{
if(s_stateForbidMask ) return ; //已经初始化好了
s_stateForbidMask = new unsigned int [esMaxStateCount];
//先都清0
memset(s_stateForbidMask,0,esMaxStateCount * sizeof(unsigned int));
//死亡状态
CAnimal::s_stateForbidMask[esStateDeath] = 0xFFFFFFFF; //死亡状态任何都禁止
unsigned int nMask=0;
//移动状态禁止摆摊,打坐,和吟唱
CAnimal::SetFlag<unsigned int>( nMask,esStateStall,true );
CAnimal::SetFlag<unsigned int>( nMask,esStateSing,true );
CAnimal::s_stateForbidMask[esStateMove] = nMask;
//禁止移动状态
nMask =0;
CAnimal::SetFlag<unsigned int>( nMask,esStateMove,true );
CAnimal::s_stateForbidMask[esStateMoveForbid] = nMask;
//摆摊状态的一些禁止状态
nMask =0;
CAnimal::SetFlag<unsigned int>( nMask,esStateMove,true );
CAnimal::SetFlag<unsigned int>( nMask,esStateSing,true );
CAnimal::s_stateForbidMask[esStateStall] = nMask;
//晕眩状态
nMask =0;
CAnimal::SetFlag<unsigned int>( nMask,esStateMove,true );
CAnimal::SetFlag<unsigned int>( nMask,esStateSing,true );
CAnimal::SetFlag<unsigned int>( nMask,esStateStall,true );
CAnimal::s_stateForbidMask[esStateDizzy] = nMask;
//吟唱状态
nMask = 0;
CAnimal::SetFlag<unsigned int>(nMask, esStateBattle, true);
CAnimal::SetFlag<unsigned int>(nMask, esStateSing, true);
CAnimal::s_stateForbidMask[esStateSing] = nMask;
}
void CAnimal::DestroyStateForbidMask()
{
//删除这个静态变量
if(s_stateForbidMask != NULL)
{
delete[] s_stateForbidMask;
}
};
void CAnimal::Reuse()
{
//清除所有buff
CBuffSystem* pBuff = GetBuffSystem();
if (pBuff)
{
pBuff->Clear(false);
}
//删除所有的消息
//ClearDelayDelEntityMsg();
//重置属性
GetPropertySystem().ResertProperty();
ClearDestoryTime();
}
void CAnimal::Say(MonsterSayBCType nStyle, const char *pMsg, int tipType, unsigned int nLimitLev)
{
if (!pMsg || strlen(pMsg) <= 0) return;
CVector<EntityHandle> vecNearEntityList, vecBCEntityList;
switch (nStyle)
{
case mssNear:
GetNearActorList(vecBCEntityList);
break;
case mssScene:
GetSceneActorList(GetScene(), vecBCEntityList);
break;
case mssFuben:
GetFubenActorList(vecBCEntityList);
break;
case mssWorld:
GetWorldActorList(vecBCEntityList);
break;
case mssCamp:
GetCampActorList(vecBCEntityList);
break;
case mssSelf:
vecNearEntityList.add(GetHandle());
break;
default:
break;
}
INT_PTR nCount = 0;
size_t nLen = 1024;
// 对于阵营广播,直接广播在中间
CEntityManager* em = GetGlobalLogicEngine()->GetEntityMgr();
if (mssCamp == nStyle)
{
nCount = vecBCEntityList.count();
for (INT_PTR i = 0; i < nCount; i++)
{
CEntity *pEntity = em->GetEntity(vecBCEntityList[i]);
if (pEntity && pEntity->GetType() == enActor
&& pEntity->GetProperty<unsigned int>(PROP_CREATURE_LEVEL) >= nLimitLev)
{
((CActor *)pEntity)->SendTipmsg(pMsg, tipType);
}
}
return;
}
// 附近频道不在系统频道显示(如果当前是频道类型广播,并且当前不是附近频道)
if(GetType() != enActor && (ttChatWindow & tipType) && nStyle != mssNear)
{
nCount = vecBCEntityList.count();
if (nCount <= 0) return;
char buff[1124]={0};
CDataPacket outPack(buff,sizeof(buff));
outPack << (BYTE)enChatSystemID << (BYTE)sSendChat <<(BYTE)ciChannelSystem;
outPack.writeString(GetEntityName());
if (strlen(pMsg) < nLen) nLen = strlen(pMsg);
outPack.writeString(pMsg, nLen);
outPack << (BYTE)0 << (BYTE)0 << (int)0 << (BYTE)0 << (BYTE)0 ;
for (INT_PTR i = 0; i < nCount; i++)
{
CEntity *pEntity = em->GetEntity(vecBCEntityList[i]);
if (pEntity && pEntity->GetType() == enActor
&& pEntity->GetProperty<unsigned int>(PROP_CREATURE_LEVEL) >= nLimitLev)
{
((CActor *)pEntity)->SendData(outPack.getMemoryPtr(), outPack.getPosition());
}
}
return;
}
// 附近头顶泡泡
CVector<EntityHandle> *pEntityList ;
/*
if(mssNear == nStyle)
{
GetNearActorList(vecNearEntityList);
pEntityList = &vecNearEntityList;
}
else
{
pEntityList = &vecBCEntityList;
}
*/
pEntityList = &vecBCEntityList;
nCount = pEntityList->count();
if (nCount > 0)
{
//如果是玩家的话,比如拾取的时候给玩家的广播
if( GetType() == enActor)
{
for (INT_PTR i = 0; i < pEntityList->count(); i++)
{
CEntity *pEntity = em->GetEntity( (*pEntityList)[i]);
if (pEntity && pEntity->GetType() == enActor
&& pEntity->GetProperty<unsigned int>(PROP_CREATURE_LEVEL) >= nLimitLev)
{
((CActor *)pEntity)->SendTipmsg(pMsg, tipType);
}
}
return;
}
char buff[1124]={0};
CDataPacket outPack(buff,sizeof(buff));
bool isMonsterNearSay = (mssNear == nStyle); //是怪物在附近广播
if( isMonsterNearSay )
{
outPack << (BYTE)enChatSystemID << (BYTE)sNonPlayerChatNear;
outPack << (INT64)GetHandle();
if (strlen(pMsg) < nLen) nLen = strlen(pMsg);
outPack.writeString(pMsg, nLen);
outPack << (BYTE)(tipType == ttChatWindow ? 0 : 1);
}
for (INT_PTR i = 0; i < pEntityList->count(); i++)
{
CEntity *pEntity = em->GetEntity( (*pEntityList)[i]);
if (pEntity && pEntity->GetType() == enActor &&pEntity->IsInited()
&& pEntity->GetProperty<unsigned int>(PROP_CREATURE_LEVEL) >= nLimitLev)
{
if (isMonsterNearSay)
{
((CActor *)pEntity)->SendData(outPack.getMemoryPtr(), outPack.getPosition());
}
else
{
((CActor *)pEntity)->SendTipmsg(pMsg, tipType);
}
}
}
}
}
void CAnimal::GetNearActorList(CVector<EntityHandle> &vecEntityList)
{
//GetGlobalLogicEngine()->GetFuBenMgr()->GetVisibleList(this,vecEntityList);
//CObserverEntityList &otherList = GetObserverSystem()->GetVisibleList();
CObserverEntityList otherList;
GetGlobalLogicEngine()->GetFuBenMgr()->GetVisibleList(this, otherList);
{
CLinkedListIterator<EntityHandleTag> iter(otherList);
CLinkedNode<EntityHandleTag> *pNode = 0;
for (pNode = iter.first(); pNode; pNode = iter.next())
{
CEntity *pEntity = GetEntityFromHandle(pNode->m_Data.m_handle);
if (pEntity && pEntity->GetType() == enActor)
{
vecEntityList.add(pEntity->GetHandle());
}
}
}
}
void CAnimal::GetSceneActorList(CScene *pScene, CVector<EntityHandle> &vecEntityList)
{
if (!pScene) return;
CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr();
CEntityList &list = pScene->GetPlayList();
CLinkedListIterator<EntityHandle> it(list);
CLinkedNode<EntityHandle> *pNode = NULL;
for (pNode = it.first(); pNode; pNode = it.next())
{
CEntity *pEntity = pEntityMgr->GetEntity(pNode->m_Data);
if (pEntity && enActor == pEntity->GetType())
vecEntityList.add(pEntity->GetHandle());
}
}
void CAnimal::GetFubenActorList(CVector<EntityHandle> &vecEntityList)
{
CScene *pScene = GetScene();
if (!pScene) return;
CFuBen *pFb = pScene->GetFuBen();
if (!pFb || !pFb->IsFb()) return;
CFuBen::SceneList& list = pFb->GetSceneList();
for (INT_PTR i = 0; i < list.count(); i++)
{
CScene *pScene = list[i];
GetSceneActorList(pScene, vecEntityList);
}
}
void CAnimal::GetWorldActorList(CVector<EntityHandle> &vecEntityList)
{
GetGlobalLogicEngine()->GetEntityMgr()->GetOnlineAcotrHandleList(vecEntityList);
}
void CAnimal::GetCampActorList(CVector<EntityHandle> &vecEntityList)
{
int nCampId = GetCampId();
if (nCampId == INVALID_CAMP_ID) return;
CVector<EntityHandle> vecList;
CEntityManager *pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr();
pEntityMgr->GetOnlineAcotrHandleList(vecList);
for (INT_PTR i = 0; i < vecList.count(); i++)
{
CActor *pActor = (CActor *)GetEntityFromHandle(vecList[i]);
if (pActor && pActor->IsInited() && pActor->GetCampId() == nCampId)
vecEntityList.push(vecList[i]);
}
}
//发送复活戒指的CD时间
void CAnimal::SendReliveRingCd()
{
if(GetType() == enActor ) //玩家
{
TICKCOUNT tickNow = GetLogicCurrTickCount();
if( m_nextHpReliveCd >= tickNow )
{
CActorPacket pack ;
((CActor*)this)->AllocPacket(pack);
pack << (BYTE) enEuipSystemID <<(BYTE)sSendReliveRingCd;
pack << (unsigned short)(m_nextHpReliveCd - tickNow );
pack.flush();
}
}
}
//设置麻痹
void CAnimal::SetDizzyTime(int nTime)
{
TICKCOUNT tickNow = GetLogicCurrTickCount();
m_nDizzyTime = tickNow + nTime;
SetDizzyState();
}
//更新救主灵刃特效以及当前CD时间
void CAnimal::UpdateJZLR()
{
std::vector<int>::iterator iter = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.vJZLRBuff.begin();
for (; iter != GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.vJZLRBuff.end(); ++iter)
{
CBuffProvider::BUFFCONFIG * pBUFFCONFIG = GetLogicServer()->GetDataProvider()->GetBuffProvider().GetBuff(*iter);
if(pBUFFCONFIG)
{
CDynamicBuff* pDynamicBuff = GetBuffSystem()->GetBuff((GAMEATTRTYPE)pBUFFCONFIG->nType, pBUFFCONFIG->nGroup);
if(!pDynamicBuff)
{
GetBuffSystem()->Append(*iter);
}
}
}
}