Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions conf/playerbots.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,14 @@ AiPlayerbot.PvpProhibitedZoneIds = "2255,656,2361,2362,2363,976,35,2268,3425,392
# PvP Restricted Areas (bots don't pvp)
AiPlayerbot.PvpProhibitedAreaIds = "976,35,392,2268,4161,4010,4317,4312,3649,3887,3958,3724,4080,3938,3754,3786,3973"

# PvP restricted distance from innkeepers (in yards)
# Default: 0 (disabled)
AiPlayerbot.PvpProhibitedInnkeeperDistance = 0

# PvP restricted distance from flight masters (in yards)
# Default: 0 (disabled)
AiPlayerbot.PvpProhibitedFlightMasterDistance = 0

# Improve reaction speeds in battlegrounds and arenas (may cause lag)
AiPlayerbot.FastReactInBG = 1

Expand Down
52 changes: 50 additions & 2 deletions src/PlayerbotAIConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ bool PlayerbotAIConfig::Initialize()
sConfigMgr->GetOption<std::string>("AiPlayerbot.PvpProhibitedAreaIds",
"976,35,392,2268,4161,4010,4317,4312,3649,3887,3958,3724,4080,3938,3754,3786,3973"),
pvpProhibitedAreaIds);
pvpProhibitedFlightMasterDistance = sConfigMgr->GetOption<float>("AiPlayerbot.PvpProhibitedFlightMasterDistance", 0.0f);
pvpProhibitedInnkeeperDistance = sConfigMgr->GetOption<float>("AiPlayerbot.PvpProhibitedInnkeeperDistance", 0.0f);
fastReactInBG = sConfigMgr->GetOption<bool>("AiPlayerbot.FastReactInBG", true);
LoadList<std::vector<uint32>>(
sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestIds", "3802,5505,6502,7761,7848,10277,10285,11492,13188,13189,24499,24511,24710,24712"),
Expand Down Expand Up @@ -694,9 +696,15 @@ bool PlayerbotAIConfig::IsInRandomQuestItemList(uint32 id)
return find(randomBotQuestItems.begin(), randomBotQuestItems.end(), id) != randomBotQuestItems.end();
}

bool PlayerbotAIConfig::IsPvpProhibited(uint32 zoneId, uint32 areaId)
bool PlayerbotAIConfig::IsPvpProhibited(uint32 zoneId, uint32 areaId, Player* player)
{
return IsInPvpProhibitedZone(zoneId) || IsInPvpProhibitedArea(areaId) || IsInPvpProhibitedZone(areaId);
if (IsInPvpProhibitedZone(zoneId) || IsInPvpProhibitedArea(areaId) || IsInPvpProhibitedZone(areaId))
return true;

if (player && IsNearProtectedNPC(player))
return true;

return false;
}

bool PlayerbotAIConfig::IsInPvpProhibitedZone(uint32 id)
Expand All @@ -709,6 +717,46 @@ bool PlayerbotAIConfig::IsInPvpProhibitedArea(uint32 id)
return find(pvpProhibitedAreaIds.begin(), pvpProhibitedAreaIds.end(), id) != pvpProhibitedAreaIds.end();
}

bool PlayerbotAIConfig::IsNearProtectedNPC(Player* player)
{
if (!player)
return false;

if (pvpProhibitedInnkeeperDistance <= 0.0f && pvpProhibitedFlightMasterDistance <= 0.0f)
return false;

WorldPosition botPos(player);
uint32 mapId = player->GetMapId();

if (pvpProhibitedFlightMasterDistance > 0.0f)
{
auto it = sRandomPlayerbotMgr->flightMastersByMap.find(mapId);
if (it != sRandomPlayerbotMgr->flightMastersByMap.end())
{
for (const WorldPosition& fmPos : it->second)
{
if (botPos.distance(fmPos) <= pvpProhibitedFlightMasterDistance)
return true;
}
}
}

if (pvpProhibitedInnkeeperDistance > 0.0f)
{
auto it = sRandomPlayerbotMgr->innkeepersByMap.find(mapId);
if (it != sRandomPlayerbotMgr->innkeepersByMap.end())
{
for (const WorldPosition& innkeeperPos : it->second)
{
if (botPos.distance(innkeeperPos) <= pvpProhibitedInnkeeperDistance)
return true;
}
}
}

return false;
}

bool PlayerbotAIConfig::IsRestrictedHealerDPSMap(uint32 mapId) const
{
return restrictHealerDPS &&
Expand Down
5 changes: 4 additions & 1 deletion src/PlayerbotAIConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ class PlayerbotAIConfig
bool Initialize();
bool IsInRandomAccountList(uint32 id);
bool IsInRandomQuestItemList(uint32 id);
bool IsPvpProhibited(uint32 zoneId, uint32 areaId);
bool IsPvpProhibited(uint32 zoneId, uint32 areaId, Player* player = nullptr);
bool IsInPvpProhibitedZone(uint32 id);
bool IsInPvpProhibitedArea(uint32 id);
bool IsNearProtectedNPC(Player* player);

bool enabled;
bool disabledWithoutRealPlayer;
Expand Down Expand Up @@ -272,6 +273,8 @@ class PlayerbotAIConfig
std::vector<uint32> randomBotGuilds;
std::vector<uint32> pvpProhibitedZoneIds;
std::vector<uint32> pvpProhibitedAreaIds;
float pvpProhibitedFlightMasterDistance;
float pvpProhibitedInnkeeperDistance;
bool fastReactInBG;

bool randombotsWalkingRPG;
Expand Down
4 changes: 4 additions & 0 deletions src/RandomPlayerbotMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2007,7 +2007,11 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
{
allianceFlightMasterCache.push_back(guid);
}
flightMastersByMap[mapId].push_back(WorldPosition(mapId, x, y, z));
}
if (tNpcflag & UNIT_NPC_FLAG_INNKEEPER)
innkeepersByMap[mapId].push_back(WorldPosition(mapId, x, y, z));

const AreaTableEntry* area = sAreaTableStore.LookupEntry(map->GetAreaId(PHASEMASK_NORMAL, x, y, z));
uint32 zoneId = area->zone ? area->zone : area->ID;
if (zone2LevelBracket.find(zoneId) == zone2LevelBracket.end())
Expand Down
2 changes: 2 additions & 0 deletions src/RandomPlayerbotMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ class RandomPlayerbotMgr : public PlayerbotHolder
std::map<uint8, std::vector<WorldLocation>> hordeStarterPerLevelCache;
std::vector<uint32> allianceFlightMasterCache;
std::vector<uint32> hordeFlightMasterCache;
std::unordered_map<uint32, std::vector<WorldPosition>> flightMastersByMap;
std::unordered_map<uint32, std::vector<WorldPosition>> innkeepersByMap;
struct LevelBracket {
uint32 low;
uint32 high;
Expand Down
33 changes: 30 additions & 3 deletions src/strategy/actions/AttackAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,45 @@ bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/)
return false;
}

// Check if bot OR target is in prohibited zone/area (skip for duels)
// Check if bot is in prohibited zone/area (skip for duels)
if ((target->IsPlayer() || target->IsPet()) &&
(!bot->duel || bot->duel->Opponent != target) &&
(sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) ||
sPlayerbotAIConfig->IsPvpProhibited(target->GetZoneId(), target->GetAreaId())))
sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId(), bot))
{
if (verbose)
botAI->TellError("I cannot attack other players in PvP prohibited areas.");

return false;
}

// Check if target is in prohibited zone/area (skip for duels)
if (target->IsPlayer() || target->IsPet())
{
Player* targetPlayer = nullptr;

if (target->IsPlayer())
targetPlayer = target->ToPlayer();

else if (target->IsPet())
{
Pet* pet = target->ToPet();
if (pet)
{
Unit* owner = pet->GetOwner();
if (owner && owner->IsPlayer())
targetPlayer = owner->ToPlayer();
}
}

if (targetPlayer && (!bot->duel || bot->duel->Opponent != target) &&
sPlayerbotAIConfig->IsPvpProhibited(target->GetZoneId(), target->GetAreaId(), targetPlayer))
{
if (verbose)
botAI->TellError("I cannot attack players who are in PvP prohibited areas.");
return false;
}
}

if (bot->IsFriendlyTo(target))
{
if (verbose)
Expand Down
2 changes: 1 addition & 1 deletion src/strategy/actions/ChooseTargetActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ bool AttackEnemyPlayerAction::isUseful()
if (PlayerHasFlag::IsCapturingFlag(bot))
return false;

return !sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId());
return !sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId(), bot);
}

bool AttackEnemyFlagCarrierAction::isUseful()
Expand Down
2 changes: 1 addition & 1 deletion src/strategy/actions/PetsAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ bool PetsAction::Execute(Event event)
botAI->TellError(text);
return false;
}
if (sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) &&
if (sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId(), bot) &&
(targetUnit->IsPlayer() || targetUnit->IsPet()) &&
(!bot->duel || bot->duel->Opponent != targetUnit))
{
Expand Down
2 changes: 1 addition & 1 deletion src/strategy/values/AttackersValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float /*range
// PvP prohibition checks (skip for duels)
if ((attacker->GetGUID().IsPlayer() || attacker->GetGUID().IsPet()) &&
(!bot->duel || bot->duel->Opponent != attacker) &&
(sPlayerbotAIConfig->IsPvpProhibited(attacker->GetZoneId(), attacker->GetAreaId()) ||
(sPlayerbotAIConfig->IsPvpProhibited(attacker->GetZoneId(), attacker->GetAreaId(), bot) ||
sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId())))
{
// This will stop aggresive pets from starting an attack.
Expand Down
2 changes: 1 addition & 1 deletion src/strategy/values/EnemyPlayerValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ 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()) &&
!sPlayerbotAIConfig->IsPvpProhibited(enemy->GetZoneId(), enemy->GetAreaId(), enemy) &&
!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) &&
Expand Down