Files
mod-playerbots/src/strategy/values/EnemyPlayerValue.cpp

169 lines
5.4 KiB
C++

/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "EnemyPlayerValue.h"
#include "Playerbots.h"
#include "ServerFacade.h"
#include "Vehicle.h"
bool NearestEnemyPlayersValue::AcceptUnit(Unit* unit)
{
bool inCannon = botAI->IsInVehicle(false, true);
Player* enemy = dynamic_cast<Player*>(unit);
if (enemy && botAI->IsOpposing(enemy) && enemy->IsPvP() &&
!sPlayerbotAIConfig->IsPvpProhibited(enemy->GetZoneId(), enemy->GetAreaId()) &&
!enemy->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NON_ATTACKABLE_2) &&
((inCannon || !enemy->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))) &&
/*!enemy->HasStealthAura() && !enemy->HasInvisibilityAura()*/ enemy->CanSeeOrDetect(bot) &&
!(enemy->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)))
return true;
return false;
}
Unit* EnemyPlayerValue::Calculate()
{
bool controllingCannon = false;
bool controllingVehicle = false;
if (Vehicle* vehicle = bot->GetVehicle())
{
VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot);
if (!seat || !seat->CanControl()) // not in control of vehicle so cant attack anyone
return nullptr;
VehicleEntry const* vi = vehicle->GetVehicleInfo();
if (vi && vi->m_flags & VEHICLE_FLAG_FIXED_POSITION)
controllingCannon = true;
else
controllingVehicle = true;
}
// 1. Check units we are currently in combat with.
std::vector<Unit*> targets;
Unit* pVictim = bot->GetVictim();
HostileReference* pReference = bot->getHostileRefMgr().getFirst();
while (pReference)
{
ThreatMgr* threatMgr = pReference->GetSource();
if (Unit* pTarget = threatMgr->GetOwner())
{
if (pTarget != pVictim && pTarget->IsPlayer() && pTarget->CanSeeOrDetect(bot) &&
bot->IsWithinDist(pTarget, VISIBILITY_DISTANCE_NORMAL))
{
if (bot->GetTeamId() == TEAM_HORDE)
{
if (pTarget->HasAura(23333))
return pTarget;
}
else
{
if (pTarget->HasAura(23335))
return pTarget;
}
targets.push_back(pTarget);
}
}
pReference = pReference->next();
}
if (!targets.empty())
{
std::sort(targets.begin(), targets.end(),
[&](Unit const* pUnit1, Unit const* pUnit2)
{ return bot->GetDistance(pUnit1) < bot->GetDistance(pUnit2); });
return *targets.begin();
}
// 2. Find enemy player in range.
GuidVector players = AI_VALUE(GuidVector, "nearest enemy players");
float const maxAggroDistance = GetMaxAttackDistance();
for (const auto& gTarget : players)
{
Unit* pUnit = botAI->GetUnit(gTarget);
if (!pUnit)
continue;
Player* pTarget = dynamic_cast<Player*>(pUnit);
if (!pTarget)
continue;
if (pTarget == pVictim)
continue;
if (bot->GetTeamId() == TEAM_HORDE)
{
if (pTarget->HasAura(23333))
return pTarget;
}
else
{
if (pTarget->HasAura(23335))
return pTarget;
}
// Aggro weak enemies from further away.
// If controlling mobile vehicle only agro close enemies (otherwise will never reach objective)
uint32 const aggroDistance = controllingVehicle ? 5.0f
: (controllingCannon || bot->GetHealth() > pTarget->GetHealth()) ? maxAggroDistance
: 20.0f;
if (!bot->IsWithinDist(pTarget, aggroDistance))
continue;
if (bot->IsWithinLOSInMap(pTarget) &&
(controllingCannon || (fabs(bot->GetPositionZ() - pTarget->GetPositionZ()) < 30.0f)))
return pTarget;
}
// 3. Check party attackers.
if (Group* pGroup = bot->GetGroup())
{
for (GroupReference* itr = pGroup->GetFirstMember(); itr != nullptr; itr = itr->next())
{
if (Unit* pMember = itr->GetSource())
{
if (pMember == bot)
continue;
if (sServerFacade->GetDistance2d(bot, pMember) > 30.0f)
continue;
if (Unit* pAttacker = pMember->getAttackerForHelper())
if (pAttacker->IsPlayer() && bot->IsWithinDist(pAttacker, maxAggroDistance * 2.0f) &&
bot->IsWithinLOSInMap(pAttacker) && pAttacker != pVictim && pAttacker->CanSeeOrDetect(bot))
return pAttacker;
}
}
}
return nullptr;
}
float EnemyPlayerValue::GetMaxAttackDistance()
{
if (!bot->GetBattleground())
return 60.0f;
Battleground* bg = bot->GetBattleground();
if (!bg)
return 40.0f;
BattlegroundTypeId bgType = bg->GetBgTypeID();
if (bgType == BATTLEGROUND_RB)
bgType = bg->GetBgTypeID(true);
if (bgType == BATTLEGROUND_IC)
{
if (botAI->IsInVehicle(false, true))
return 120.0f;
}
return 40.0f;
}