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

361 lines
9.8 KiB
C++

#include "StdAfx.h"
EntityVector* CAggressorAI::s_pVisibleEntityList = NULL;
bool CAggressorAI::CheckEnemy()
{
bool result = false;
Inherid::CheckEnemy();
//static CVector<int> sEmptyPriorAttackList;
INT_PTR nType = m_pSelf->GetType();
CScene * pScene = m_pSelf->GetScene();
if(pScene ==NULL) return false;
int nSelfX, nSelfY;
int nTargetX, nTargetY;
m_pSelf->GetPosition(nSelfX, nSelfY);
EntityHandle enemyHandle;
CEntity *pAttackTarget =NULL;
UINT64 nPriority = 0;
int nTargetDisSquare = 0;
if(pScene->GetPlayCount() <=0 ) return false; //场景里没有玩家的话就不执行了
CVector<EntityHandleTag> &entityList = m_pSelf->GetObserverSystem()->GetVisibleList();
INT_PTR nActorCount = entityList.count(); //玩家的数目
//获取这个场景里所有的宠物
CEntityList &petList = pScene->GetPetList();
CEntityList &heroList = pScene->GetHeroList();
INT_PTR nPetCount = petList.count(); //宠物的数目
INT_PTR nHeroCount = heroList.count();
INT_PTR nPetAndActorCount = nPetCount + nActorCount ; //宠物+玩家的数目
INT_PTR nPetActorHeroCount = nPetAndActorCount + nHeroCount; //英雄 + 宠物 + 玩家的数目
if(!m_pSelf->GetAttriFlag().CanAttackMonster && nPetActorHeroCount <=0) return false; //视野里没有玩家和宠物,则返回
int nVisibleList = __max(m_pAiConfig->watchDistance, 0);
int nDis = nVisibleList;
nVisibleList *= nVisibleList;
CLinkedNode<EntityHandle> *pNode =NULL;
CLinkedListIterator<EntityHandle> it(petList);
CLinkedListIterator<EntityHandle> itHero(heroList);
bool bDenyInitiativeAttackActor = m_pSelf->GetAttriFlag().DenyInitiativeAttackActor;
bool bOnlyAttackRedActorFlag = m_pSelf->GetAttriFlag().AttackKiller;
bool bAttackPetFlag = m_pSelf->GetAttriFlag().AttackPet;
PMONSTERCONFIG pMonConf = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(m_pSelf->GetId());
//若可攻击怪物
if(m_pSelf->GetAttriFlag().CanAttackMonster && m_pSelf->IsMonster())
{
EntityHandle selfHd = m_pSelf->GetHandle();
//需要检测是否攻击怪物的,也只有部分
if( m_checkMonsterTimer.CheckAndSet( GetLogicCurrTickCount(), true) && nDis>0 )
{
CObserverSystem::s_seqVisibleList->clear();
CFuBenManager* fm = GetGlobalLogicEngine()->GetFuBenMgr();
fm->GetVisibleList(m_pSelf, *CObserverSystem::s_seqVisibleList, -nDis, nDis, -nDis, nDis);
INT_PTR nCount = CObserverSystem::s_seqVisibleList->count();
if(nCount > 1)
{
for(INT_PTR i=0; i< nCount ; i++)
{
EntityHandle newHandle = (*CObserverSystem::s_seqVisibleList)[i];
if(newHandle.GetType() == enMonster && newHandle != selfHd)
{
CEntity *pEntity = GetEntityFromHandle(newHandle);
if (pEntity)
{
// 不主动攻击被动怪
if (((CAnimal*)pEntity)->GetAI()->m_btAiType == atAiTypePassive) continue;
if (!m_pSelf->CanSee(pEntity))
continue;
CAnimal *pAnimal = (CAnimal*) pEntity;
//不能攻击的不算
if(! m_pSelf->CanAttack( pAnimal) ) continue;
AttackStart(pAnimal);
return true;
}
}
}
}
}
}
//遍历玩家,宠物、英雄
for (INT_PTR i = 0; i < nPetActorHeroCount ; ++i)
{
//先遍历玩家再遍历宠物
EntityHandle handler ;
if(i < nActorCount )
{
handler = entityList[i].m_handle;
}
else if( i >= nActorCount && i < nPetAndActorCount )
{
if( i== nActorCount)
{
pNode = it.first();
}
if(pNode)
{
handler = pNode->m_Data;
pNode = it.next();
}
}
else if( i >= nPetAndActorCount && i < nPetActorHeroCount)
{
if( i== nPetAndActorCount )
{
pNode = itHero.first();
}
if(pNode)
{
handler = pNode->m_Data;
pNode = itHero.next();
}
}
//得到一个攻击对象
if (CEntity *pEntity = GetEntityFromHandle(handler))
{
CAnimal *pAnimal = (CAnimal*) pEntity;
if(pEntity->isAnimal() ==false) continue; //为动物
if(!m_pSelf->CanSee(pEntity)) continue; //可视this->GetTarget() == pEntity->GetHandle()
if (pAnimal->IsDeath()) continue; //非死亡
pEntity->GetPosition(nTargetX, nTargetY);
int nDisSquare = (nTargetX - nSelfX ) * (nTargetX - nSelfX ) + (nTargetY - nSelfY ) * (nTargetY - nSelfY );
if(nDisSquare > nVisibleList) continue; //距离过远的不选择
//主动怪配置DenyInitiativeAttackActor
if (bDenyInitiativeAttackActor && (enActor == handler.GetType() || enPet == handler.GetType() || enHero == handler.GetType()))
{
//主动怪只主动攻击红名玩家
if (pEntity->GetType() == enActor)
{
if(!m_pSelf->CanAttack( pAnimal))
continue;
if((bOnlyAttackRedActorFlag && ((CActor*)pEntity)->GetNameColorData()<3))
continue;
}
//主动怪不主动攻击宠物
if (pEntity->GetType() == enPet)
{
if (!bAttackPetFlag)
continue;
if(!m_pSelf->CanAttack( pAnimal))
continue;
}
//主动怪不主动攻击英雄
if (pEntity->GetType() == enHero)
{
if(!bAttackPetFlag)
{
if(!m_pSelf->CanAttack( pAnimal))
continue;
}
}
}
else
{
if (pEntity->GetType() == enActor)
{
if(!m_pSelf->CanAttack( pAnimal))
continue;
} else
{
if(!bAttackPetFlag && !m_pSelf->CanAttack( pAnimal))
{
continue;
}
}
}
UINT64 curPriority = 0;
//boss 用累计伤害计算仇恨值
if(m_pSelf->IsMonster() && pMonConf &&
(pMonConf->btMonsterType == MONSTERCONFIG::mtBoss ||
pMonConf->btMonsterType == MONSTERCONFIG::mtToumu ||
pMonConf->btMonsterType == MONSTERCONFIG::mtWorldBoss))
{
curPriority = ((CMonster*)m_pSelf)->GetMonsterHetred(pEntity);
if ((curPriority > nPriority) || (curPriority == nPriority && nDisSquare < nTargetDisSquare) || nPriority == 0)
{
nPriority = curPriority;
nTargetDisSquare = nDisSquare;
pAttackTarget = pEntity;
}
}
//其他的,同等仇恨条件下,距离越远的,攻击优先级低
else
{
UINT64 nAttackLevel = pAnimal->GetAttackLevel();
++nAttackLevel;
curPriority = (UINT64) (nAttackLevel << 32 );
curPriority -= nDisSquare;
if (curPriority >= nPriority)
{
nPriority = curPriority;
pAttackTarget = pEntity;
}
}
}
} // for
//怪物能够攻击怪物的话,再取下旁边的列表
if (pAttackTarget && pAttackTarget->isAnimal())
{
AttackStart((CAnimal *)pAttackTarget);
result = true;
}
return result;
}
void CAggressorAI::MoveInSight(CAnimal * pTarget,INT_PTR nPosX,INT_PTR nPosY)
{
unsigned int nSelfPosX= m_pSelf->GetProperty<unsigned int>(PROP_ENTITY_POSX);
unsigned int nSelfPosY= m_pSelf->GetProperty<unsigned int>(PROP_ENTITY_POSY);
INT_PTR nDis= CMovementSystem::GetDisSqare(nSelfPosX,nPosY,nPosX,nPosY);
if( nDis <= Inherid::m_pAiConfig->watchDistance * Inherid::m_pAiConfig->watchDistance) //进入了可视范围
{
if (m_pSelf->HasState( esStateBattle ) ==false)
{
AttackStart(pTarget); //开始攻击
}
}
}
bool CAggressorAI::CalcTargetPrior(CEntity *pTarget, const CVector<int> *priorTargetList, UINT64 &priority, int nSelfX, int nSelfY)
{
/*DECLARE_FUN_TIME_PROF()*/
priority = 0;
if (!m_pSelf->IsMonster()) return false;
if (!pTarget || ((CAnimal *)pTarget)->HasState(esStateDeath)) return false;
CMonster *pThisMonster = (CMonster *)m_pSelf;
if (!pThisMonster->CanAttack((CAnimal *)pTarget))
return false;
bool bIsOwnerTarget = false;
bool bIsValidTarget = false;
bool bIsPriorTarget = false;
INT_PTR targetType = pTarget->GetType();
int nAttackLevel = 0, nDistSqrt = 0;
bool bIsBabyMonster = false; // 自己是否是宝宝怪
CEntity *pMaster = GetEntityFromHandle(pThisMonster->GetOwner());
if (pMaster && pMaster->GetType() == enActor)
bIsBabyMonster = true;
if (bIsBabyMonster)
{
CEntity *pMasterTarget = GetEntityFromHandle(pMaster->GetTarget());
if (pMasterTarget && ((CAnimal *)pMaster)->CanAttack((CAnimal *)pMasterTarget) && pThisMonster->CanAttack((CAnimal *)pMasterTarget))
{
bIsOwnerTarget = true;
priority = ComposePriority(true, false, 0, 0); // 最高优先级
return true;
}
}
if (targetType == enMonster)
{
CMonster *pTargetMonster = (CMonster *)pTarget;
CEntity *pTargetOwner = GetEntityFromHandle(pTargetMonster->GetOwner());
bool bTargetIsBabay = false;
if (pTargetOwner && pTargetOwner->GetType() == enActor)
bTargetIsBabay = true;
int monsterId = pTargetMonster->GetId();
if (priorTargetList)
{
for (INT_PTR i = 0; i < priorTargetList->count(); ++i)
{
if (monsterId == (*priorTargetList)[i])
{
//bIsValidTarget = true;
bIsPriorTarget = true;
break;
}
}
}
if (bIsBabyMonster) // 自己是宝宝怪
{
if (bTargetIsBabay) // 宝宝怪不主动攻击宝宝怪
{
bIsValidTarget = false;
}
else // 目标是非宝宝怪,会主动攻击
{
// 是合法目标
bIsValidTarget = true;
}
}
else // 自己是非宝宝怪
{
if (bTargetIsBabay)
{
// 是合法目标
bIsValidTarget = true;
}
else // 目标不是宝宝怪,只有是优选攻击目标列表中的怪才会被攻击
{
if (bIsPriorTarget)
bIsValidTarget = true;
}
}
}
else if (targetType == enActor || targetType ==enPet || targetType == enHero)
{
if (bIsBabyMonster)
{
// 宝宝怪不主动攻击玩家
}
else
{
// 非宝宝怪, 主动攻击玩家
bIsValidTarget = true;
}
}
bool bIsDectDist = false;
if (bIsValidTarget)
{
int nX, nY;
pTarget->GetPosition(nX, nY);
nAttackLevel = ((CAnimal *)pTarget)->GetAttackLevel();
nDistSqrt = (int)CMovementSystem::GetDisSqare(nX, nY, nSelfX, nSelfY);
if (nDistSqrt <= Inherid::m_pAiConfig->watchDistance * Inherid::m_pAiConfig->watchDistance)
{
bIsDectDist = true;
priority = ComposePriority(bIsOwnerTarget, bIsPriorTarget, nAttackLevel, nDistSqrt);
}
}
return bIsValidTarget && bIsDectDist;
}