PlayerBot : octroi des sorts de niveau et de specialisation au re-level

PlayerBotSetting::LearnSpells() n apprenait les sorts que depuis les donnees de
dresseur de classe (GetNpcTrainerSpells). En 7.3.5 les dresseurs n enseignent
plus le kit moderne : il s octroie a la montee de niveau et via la
specialisation. Les bots re-leveles arrivaient donc avec stuff et talents mais
un livre de sorts incomplet.

LearnDefaultSkills(), LearnSpecializationSpells() et
UpdateSkillsToMaxSkillsForLevel() sont desormais appeles avant le passage par
les dresseurs. Mesure avant / apres sur les bots 110 du siege, nombre moyen de
sorts connus :

  guerrier 43 -> 56    paladin 43 -> 51    chasseur 44 -> 55
  voleur   44 -> 63    pretre  44 -> 56    chaman   44 -> 56
  mage     44 -> 54    druide  44 -> 56

Concerne aussi le remplissage des champs de bataille, qui re-level par le meme
chemin.

Deuxieme correction : BotBGAIMovement::IsNearToPosition() repondait toujours
 pas encore arrive  hors champ de bataille. Les appelants ne coupaient donc
jamais court et relancaient un calcul de chemin a chaque tick, d ou le flot de
messages de pathfinding en echec pendant le siege. Le mode siege passe
desormais cette garde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-08-15 19:36:51 +02:00
parent 330f614a71
commit 03d5a97582
4 changed files with 67 additions and 7 deletions
+48 -5
View File
@@ -1766,12 +1766,49 @@ void BotBGAI::UpdateBotAI(uint32 diff)
// mais passent leur temps sur sa garde rapprochee.
if (m_SiegeMode && !m_SiegeTarget.IsEmpty())
{
if (Unit* siegeBoss = ObjectAccessor::GetUnit(*me, m_SiegeTarget))
Unit* siegeBoss = ObjectAccessor::GetUnit(*me, m_SiegeTarget);
if (siegeBoss)
{
if (siegeBoss->IsAlive() && me->IsValidAttackTarget(siegeBoss)
&& me->GetDistance(siegeBoss) < sCapitalSiegeMgr->GetBossEngageRange())
float const bossDistance = me->GetDistance(siegeBoss);
bool const bossAttackable = me->IsValidAttackTarget(siegeBoss);
bool const bossInRange = bossDistance < sCapitalSiegeMgr->GetBossEngageRange();
// Instrumentation temporaire du blocage sur le dirigeant : il ne
// perd aucun point de vie alors que des bots meurent a trois
// yards de lui, et ni sa faction, ni ses drapeaux, ni son
// creature_template ne l expliquent.
// Sonde declenchee des que le dirigeant est designe (60 yards),
// et non seulement au contact : IsValidAttackTarget ne depend pas
// de la distance, et la horde n arrive pas toujours jusqu a lui.
{
static uint32 s_siegeBossLog = 0;
if (++s_siegeBossLog % 25 == 1)
{
Unit* victim = me->GetVictim();
TC_LOG_ERROR("server.worldserver",
"SIEGE-DBG: %s dist=%.1f attaquable=%u cible=%s victime=%s flags=0x%X | evade=%u visible=%u memephase=%u react=%d pv=%s",
me->GetName().c_str(), bossDistance, uint32(bossAttackable),
(me->GetTarget() == m_SiegeTarget) ? "dirigeant" : "autre",
victim ? victim->GetName().c_str() : "aucune",
siegeBoss->GetUInt32Value(UNIT_FIELD_FLAGS),
uint32(siegeBoss->ToCreature() ? siegeBoss->ToCreature()->IsInEvadeMode() : 0),
uint32(siegeBoss->IsVisible()),
uint32(me->InSamePhase(siegeBoss->GetPhaseShift())),
int32(siegeBoss->ToCreature() ? siegeBoss->ToCreature()->GetReactState() : -1),
std::to_string(siegeBoss->GetHealth()).c_str());
}
}
(void)bossInRange;
if (siegeBoss->IsAlive() && bossAttackable && bossInRange)
me->SetSelection(m_SiegeTarget);
}
else
{
static uint32 s_siegeBossMissing = 0;
if (++s_siegeBossMissing % 50 == 1)
TC_LOG_ERROR("server.worldserver", "SIEGE-DBG: %s ne trouve pas le dirigeant en memoire.", me->GetName().c_str());
}
}
Unit* pSelect = GetBotAIValidSelectedUnit();
@@ -1784,7 +1821,13 @@ void BotBGAI::UpdateBotAI(uint32 diff)
else if (pSelect && !IsInvincible(pSelect) && !HasAuraMechanic(pSelect, Mechanics::MECHANIC_POLYMORPH))
{
float distance = me->GetDistance(pSelect->GetPosition());
if (distance < searchRange || inArena)
// Module Siege des Capitales : le dirigeant echappe au seuil
// d abandon de cible. Avec une portee d engagement courte, l IA le
// lachait des 17 yards ( distance > searchRange * 1.7 ) et la
// selection ne tenait pas une seule tick, meme a 28 yards de lui.
float const engageDistance = (m_SiegeMode && !m_SiegeTarget.IsEmpty() && pSelect->GetGUID() == m_SiegeTarget)
? sCapitalSiegeMgr->GetBossEngageRange() : searchRange;
if (distance < engageDistance || inArena)
{
if (m_CurrentTargetTick < BOTAI_MAXTARGET_TICKTIME || inArena)
{
@@ -1805,7 +1848,7 @@ void BotBGAI::UpdateBotAI(uint32 diff)
me->SetSelection(ObjectGuid::Empty);
}
}
else if (distance > searchRange * 1.7f || me->GetMap() != pSelect->GetMap())
else if (distance > engageDistance * 1.7f || me->GetMap() != pSelect->GetMap())
{
me->SetSelection(ObjectGuid::Empty);
}
@@ -691,7 +691,12 @@ void BotBGAIMovement::SyncPosition(Position& pos, bool immed)
bool BotBGAIMovement::IsNearToPosition(float x, float y, float z, float range)
{
if (!m_Player->InBattleground())
// Hors champ de bataille ce test repondait toujours pas encore arrive : les
// appelants ne coupaient donc jamais court et relancaient un calcul de chemin
// a chaque tick, d ou le flot de messages de pathfinding en echec pendant le
// siege. Le mode siege doit passer.
bool const siegeMode = m_BGAI && m_BGAI->IsSiegeMode();
if (!siegeMode && !m_Player->InBattleground())
return false;
if (Unit* pVehicle = m_Player->GetVehicleBase())
{
@@ -1903,6 +1903,18 @@ void PlayerBotSetting::RemoveSpells()
void PlayerBotSetting::LearnSpells()
{
uint8 level = m_Player->getLevel();
// SylvaniaCore : en 7.3.5 le gros du kit de classe ne s apprend plus chez un
// dresseur mais s octroie a la montee de niveau et via la specialisation. Se
// limiter aux donnees de dresseur laissait les bots re-leveles sans sorts
// d attaque : constate en jeu sur les demonistes 110 du siege, deux sorts de
// degats sur la duree sur cinq et aucun sort de degats directs sur quatre.
// Concerne aussi le remplissage des champs de bataille, qui re-level de la
// meme facon.
m_Player->LearnDefaultSkills();
m_Player->LearnSpecializationSpells();
m_Player->UpdateSkillsToMaxSkillsForLevel();
const TrainerSpellData* spellData = sObjectMgr->GetNpcTrainerSpells(classesTrainersGUID[m_Player->getClass()][(m_Player->GetTeamId() == TeamId::TEAM_ALLIANCE) ? 0 : 1]);
if (!spellData)
return;
+1 -1
View File
@@ -4751,7 +4751,7 @@ siege_engage_range = 10
# Default: 40
#
siege_boss_engage_range = 40
siege_boss_engage_range = 60
#
# siege_stall_timeout