/* * Copyright (C) 2016+ AzerothCore , 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(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->HasSpiritOfRedemptionAura())) 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 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(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; }