Fix: Allow bots to duel in PVP prohibited areas (#1906)

Noticed that if you ask a bot to duel in a PVP prohibited area, it will
accept, and do nothing. I thought about making the bot reject the
request, but if you (the real player) want to duel with it, the duel
should happen. This is just a minor fix to allow bots to duel if you ask
them to in such areas.

Tested with bots in party, random bots of the same faction, and random
bots of the opposite faction. All behaved the same before and after fix.
An example place to test is Zim'Torga in Zul'Drak which is by default is
a PVP prohibited area.

- Before fix, you challenge a bot, they accept and turn red, then they
either just stay where they are or wander off.

- After fix, bot attacks you within the PVP prohibited area when the
duel starts.
This commit is contained in:
NoxMax
2025-12-16 10:38:50 -07:00
committed by GitHub
parent 5f697e806e
commit 00cb177c86
3 changed files with 19 additions and 24 deletions

View File

@@ -15,20 +15,19 @@
#include "SharedDefines.h"
#include "Unit.h"
bool AttackAction::Execute(Event event)
bool AttackAction::Execute(Event /*event*/)
{
Unit* target = GetTarget();
if (!target)
return false;
if (!target->IsInWorld())
{
return false;
}
return Attack(target);
}
bool AttackMyTargetAction::Execute(Event event)
bool AttackMyTargetAction::Execute(Event /*event*/)
{
Player* master = GetMaster();
if (!master)
@@ -51,7 +50,7 @@ bool AttackMyTargetAction::Execute(Event event)
return result;
}
bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/)
{
Unit* oldTarget = context->GetValue<Unit*>("current target")->Get();
bool shouldMelee = bot->IsWithinMeleeRange(target) || botAI->IsMelee(bot);
@@ -81,11 +80,13 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
{
if (verbose)
botAI->TellError(std::string(target->GetName()) + " is no longer in the world.");
return false;
}
// Check if bot OR target is in prohibited zone/area
// Check if bot OR target 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())))
{
@@ -99,6 +100,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
{
if (verbose)
botAI->TellError(std::string(target->GetName()) + " is friendly to me.");
return false;
}
@@ -106,6 +108,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
{
if (verbose)
botAI->TellError(std::string(target->GetName()) + " is dead.");
return false;
}
@@ -113,6 +116,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
{
if (verbose)
botAI->TellError(std::string(target->GetName()) + " is not in my sight.");
return false;
}
@@ -120,6 +124,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
{
if (verbose)
botAI->TellError("I am already attacking " + std::string(target->GetName()) + ".");
return false;
}
@@ -155,9 +160,8 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
}
if (IsMovingAllowed() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target))
{
sServerFacade->SetFacingTo(bot, target);
}
botAI->ChangeEngine(BOT_STATE_COMBAT);
bot->Attack(target, shouldMelee);
@@ -187,4 +191,4 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
bool AttackDuelOpponentAction::isUseful() { return AI_VALUE(Unit*, "duel target"); }
bool AttackDuelOpponentAction::Execute(Event event) { return Attack(AI_VALUE(Unit*, "duel target")); }
bool AttackDuelOpponentAction::Execute(Event /*event*/) { return Attack(AI_VALUE(Unit*, "duel target")); }

View File

@@ -18,9 +18,7 @@ bool PetsAction::Execute(Event event)
// Extract the command parameter from the event (e.g., "aggressive", "defensive", "attack", etc.)
std::string param = event.getParam();
if (param.empty() && !defaultCmd.empty())
{
param = defaultCmd;
}
if (param.empty())
{
@@ -129,10 +127,8 @@ bool PetsAction::Execute(Event event)
{
ObjectGuid masterTargetGuid = master->GetTarget();
if (!masterTargetGuid.IsEmpty())
{
targetUnit = botAI->GetUnit(masterTargetGuid);
}
}
// If no valid target is selected, show an error and return.
if (!targetUnit)
@@ -156,8 +152,9 @@ bool PetsAction::Execute(Event event)
botAI->TellError(text);
return false;
}
if (sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId())
&& (targetUnit->IsPlayer() || targetUnit->IsPet()))
if (sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) &&
(targetUnit->IsPlayer() || targetUnit->IsPet()) &&
(!bot->duel || bot->duel->Opponent != targetUnit))
{
std::string text = sPlayerbotTextMgr->GetBotTextOrDefault(
"pet_pvp_prohibited_error", "I cannot command my pet to attack players in PvP prohibited areas.", {});

View File

@@ -33,19 +33,15 @@ GuidVector AttackersValue::Calculate()
{
Unit* unit = botAI->GetUnit(target);
if (unit && IsValidTarget(unit, bot))
{
targets.insert(unit);
}
}
if (Group* group = bot->GetGroup())
{
ObjectGuid skullGuid = group->GetTargetIcon(7);
Unit* skullTarget = botAI->GetUnit(skullGuid);
if (skullTarget && IsValidTarget(skullTarget, bot))
{
targets.insert(skullTarget);
}
}
for (Unit* unit : targets)
result.push_back(unit->GetGUID());
@@ -61,11 +57,9 @@ GuidVector AttackersValue::Calculate()
{
Unit* unit = botAI->GetUnit(guid);
if (unit && unit->IsPlayer() && IsValidTarget(unit, bot))
{
result.push_back(unit->GetGUID());
}
}
}
return result;
}
@@ -110,9 +104,8 @@ void AttackersValue::AddAttackersOf(Player* player, std::unordered_set<Unit*>& t
if (player->IsValidAttackTarget(attacker) &&
player->GetDistance2d(attacker) < sPlayerbotAIConfig->sightDistance)
{
targets.insert(attacker);
}
ref = ref->next();
}
}
@@ -180,8 +173,9 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float /*range
if (!bot->CanSeeOrDetect(attacker))
return false;
// PvP prohibition checks
// 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(bot->GetZoneId(), bot->GetAreaId())))
{