BG BotFill : doctrine de ciblage PvP en champ de bataille

Le bot prenait l ennemi le plus bas en vie sous 80 %, sinon un ennemi AU
HASARD : aucun feu concentre, soigneurs ennemis jamais inquietes, porteur de
drapeau ignore. Les cibles sont desormais notees selon la doctrine PvP de
champ de bataille (Vanilla -> Legion) :
  porteur de drapeau  +1000  (objectif du match)
  soigneur ennemi     +400   (un soigneur libre rend le combat ingagnable)
  cible blessee       +3 par point de vie manquant (achever plutot qu etaler)
  allie deja au contact +60 chacun (feu concentre)
  distance            -1 par metre
  hors ligne de vue   -250
Detection du soigneur par classe ET specialisation (un paladin protection
n est plus traite comme un soigneur) ; le feu concentre se lit sur la liste
des attaquants de la cible, sans recherche couteuse.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-08-17 11:17:30 +02:00
parent beaf2ff164
commit 0bb8fb7d90
2 changed files with 74 additions and 5 deletions
+70 -5
View File
@@ -754,12 +754,62 @@ void BotBGAI::SearchCreatureListFromRange(Unit* center, NearCreatureVec& nearCre
}
}
// SylvaniaCore (module BG BotFill): un soigneur ennemi prolonge indefiniment un combat ;
// la doctrine PvP le designe comme cible prioritaire apres le porteur de drapeau.
// Meme regle que Arena::IsHealerBot : classe + specialisation.
bool BotBGAI::TargetIsHealer(Player* pTarget)
{
if (!pTarget)
return false;
switch (pTarget->getClass())
{
case CLASS_PALADIN:
return (pTarget->FindTalentType() == 0);
case CLASS_PRIEST:
return (pTarget->FindTalentType() != 2);
case CLASS_SHAMAN:
case CLASS_DRUID:
return (pTarget->FindTalentType() == 2);
default:
return false;
}
}
// Porteur d un drapeau de champ de bataille (Chanteguerres ou Oeil du cyclone).
bool BotBGAI::TargetIsFlagCarrier(Player* pTarget)
{
if (!pTarget)
return false;
return pTarget->HasAura(23333) // etendard de Chanteguerre (Horde)
|| pTarget->HasAura(23335) // etendard d Aile-argent (Alliance)
|| pTarget->HasAura(34976); // drapeau du Nethertempete (Oeil du cyclone)
}
// Nombre d allies deja au corps a corps sur cette cible : base du feu concentre.
uint32 BotBGAI::CountFriendlyAttackers(Unit* pTarget)
{
if (!pTarget)
return 0;
uint32 count = 0;
Unit::AttackerSet const& attackers = pTarget->getAttackers();
for (Unit::AttackerSet::const_iterator itAtk = attackers.begin(); itAtk != attackers.end(); ++itAtk)
{
Unit* attacker = *itAtk;
if (!attacker || attacker == me)
continue;
if (attacker->IsPlayer() && attacker->ToPlayer()->GetTeamId() == me->GetTeamId())
++count;
}
return count;
}
Unit* BotBGAI::SearchEnemy(float range)
{
NearPlayerList playersNearby;
QueryNearPlayerList(range, playersNearby);
NearPlayerVec enemyPlayers, invinciblePlayers;
Player* minHealthPlayer = NULL;
float bestScore = 0.0f;
for (Player* pVisionPlayer : playersNearby)
{
#ifdef EXCLUDE_PLAYER
@@ -776,13 +826,26 @@ Unit* BotBGAI::SearchEnemy(float range)
}
else
{
// SylvaniaCore (module BG BotFill): notation tactique de la cible.
// Bareme issu de la doctrine PvP de champ de bataille : le porteur de
// drapeau passe avant tout, puis le soigneur, puis l ennemi a achever,
// puis la cible que les allies frappent deja (feu concentre).
float hp = pVisionPlayer->GetHealthPct();
if (hp < 80.0f)
float score = 0.0f;
if (TargetIsFlagCarrier(pVisionPlayer))
score += 1000.0f;
if (TargetIsHealer(pVisionPlayer))
score += 400.0f;
score += (100.0f - hp) * 3.0f;
score += float(CountFriendlyAttackers(pVisionPlayer)) * 60.0f;
score -= me->GetDistance(pVisionPlayer);
if (!me->IsWithinLOSInMap(pVisionPlayer))
score -= 250.0f;
if (!minHealthPlayer || score > bestScore)
{
if (!minHealthPlayer)
minHealthPlayer = pVisionPlayer;
else if (hp < minHealthPlayer->GetHealthPct())
minHealthPlayer = pVisionPlayer;
bestScore = score;
minHealthPlayer = pVisionPlayer;
}
if (m_NeedFindpathSearch)
{
@@ -809,6 +872,8 @@ Unit* BotBGAI::SearchEnemy(float range)
Player* pVisionPlayer = invinciblePlayers[index];
return pVisionPlayer;
}
// SylvaniaCore (module BG BotFill): la cible la mieux notee est retenue ; le tirage
// au hasard ne subsiste que si la notation n a rien pu departager.
if (!minHealthPlayer)
{
uint32 index = urand(0, enemyPlayers.size() - 1);
+4
View File
@@ -161,6 +161,10 @@ protected:
virtual bool IsMeleeBotAI();
virtual bool IsRangeBotAI();
virtual bool IsHealerBotAI();
// SylvaniaCore (module BG BotFill): doctrine de ciblage en champ de bataille
static bool TargetIsHealer(Player* pTarget);
static bool TargetIsFlagCarrier(Player* pTarget);
uint32 CountFriendlyAttackers(Unit* pTarget);
virtual bool IsAttacker() { return true; }
virtual bool TryStartControlCommand() { ClearCruxControlCommand(); return false; }