Passe de warnings sur tout le core : 12 bugs reels corriges

Scan de -fsyntax-only avec les vrais flags sur les 1767 fichiers du
serveur (compile_commands.json), warnings de logique actives. 3277
warnings, tries a la main. Le bruit (Wreorder, Wswitch) est ecarte ;
voici ce qui etait un vrai defaut.

Memoire morte et comportement indefini :
- ObjectMgr::GetGarrssionMissionReward rendait l adresse d un vecteur
  local ; Garrison melangeait puis parcourait cet objet detruit.
- BattlePayDataStoreMgr::GetProduct faisait "return{}" sur une fonction
  qui rend une reference : huit appelants lisaient un temporaire mort.
- Garrison::RewardMission reaffectait une initializer_list, ce qui ne
  prolonge pas la duree de vie du tableau sous-jacent.
- WorldSession avait un destructeur non virtuel alors que
  PlayerBotSession en derive : chaque delete d une session de bot ne
  detruisait que la moitie de l objet. Idem FieldActing.
- boss_levantus lisait Waypointspawn[6] dans un tableau de 6 entrees,
  a chaque declenchement de l evenement.
- boss_hyrja_tov modifiait expelLightSwitch deux fois sans point de
  sequence, et replanifiait son evenement toutes les 20 ms au lieu de
  20 secondes (IN_MILLISECONDS manquant).

Code jamais appele :
- cinq hooks OnRemoveTarget d areatrigger (Klaxxi, Blackfuse, Siege
  d Orgrimmar, Ordos) : le hook du core s appelle OnUnitExit, ces
  methodes n etaient rattachees a rien et les auras restaient sur le
  joueur apres sa sortie de zone. Trois d entre elles n avaient meme
  pas de return.
- boss_admiral_svirax declarait un membre bool du meme nom que
  SetDungeonEncounterID, qui masquait la methode de BossAI ; l appel
  avait ete "repare" par une virgule et ne faisait donc rien.
- WorldSession::HasSocket comparait l adresse d un tableau a NULL,
  donc rendait toujours true.

Conditions toujours vraies :
- zone_vault_of_wardens : "== QUEST_STOP_GULDAN_H || QUEST_STOP_GULDAN_A"
  jouait la scene de Gul dan pour n importe quelle quete acceptee.
- boss_vizaduum : "type == POINT_MOTION_TYPE || WAYPOINT_MOTION_TYPE".
- boss_council_of_elders : parenthese fermee au mauvais endroit,
  "HasAura(SPELL_DISCHARGE || HasAura(SPELL_OVERLOAD))".

Valeurs tronquees :
- InstanceScript::m_ScenarioStep etait un uint8 alors qu il recoit des
  ID de ScenarioStep (3195, 3207...), tronques a 135 ou 136.
- PetBattleTrainer passait 3000000000000000 a SetRespawnTime(uint32).

Nettoyage sans effet de bord : memcpy sur PetBattleRequest remplace par
une copie, et suppression d un getThreatList()/empty() sans effet dans
boss_wise_mari.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Sylvania
2026-09-03 12:59:16 +02:00
parent 5205a9b5f0
commit 37796803c7
22 changed files with 134 additions and 57 deletions
+1 -2
View File
@@ -2092,8 +2092,7 @@ void Player::ProcessDelayedOperations()
{
uint8 teamID = battle->Teams[PETBATTLE_TEAM_1]->OwnerGuid == GetGUID() ? PETBATTLE_TEAM_1 : PETBATTLE_TEAM_2;
PetBattleRequest request;
memcpy(&request, &battle->PvPMatchMakingRequest, sizeof(PetBattleRequest)); //@TODO check that
PetBattleRequest request = battle->PvPMatchMakingRequest;
auto& matchMakingRequest = battle->PvPMatchMakingRequest;
+11 -8
View File
@@ -642,11 +642,11 @@ void Garrison::AddMission(uint32 garrMissionId)
reward.FollowerXP = 0;
reward.BonusAbilityID = 0;
reward.Unknown = 1118739;
std::vector<GarrssionMissionReward>* fRewards = sObjectMgr->GetGarrssionMissionReward(garrMissionId);
if (fRewards)
std::vector<GarrssionMissionReward> fRewards = sObjectMgr->GetGarrssionMissionReward(garrMissionId);
if (!fRewards.empty())
{
Trinity::Containers::RandomShuffle(*fRewards);
for (auto _reward : *fRewards)
Trinity::Containers::RandomShuffle(fRewards);
for (auto _reward : fRewards)
{
// if (_reward.RewardType == GarrisonMission::MissionRewardType::Item)
{
@@ -1086,13 +1086,16 @@ void Garrison::CalculateMissonBonusRoll(uint32 garrMissionId)
void Garrison::RewardMission(Mission* mission, bool withOvermaxReward)
{
auto rewardLists = { mission->Rewards };
// SylvaniaCore : reaffecter une initializer_list ne prolonge pas la duree de
// vie du tableau sous-jacent -- la boucle parcourait un temporaire detruit.
std::vector<decltype(&mission->Rewards)> rewardLists;
rewardLists.push_back(&mission->Rewards);
if (withOvermaxReward)
rewardLists = { mission->Rewards, mission->BonusRewards };
rewardLists.push_back(&mission->BonusRewards);
for (auto rewards : rewardLists)
for (auto const* rewards : rewardLists)
{
for (WorldPackets::Garrison::GarrisonMissionReward reward : rewards)
for (WorldPackets::Garrison::GarrisonMissionReward reward : *rewards)
{
if (reward.ItemID)
GetOwner()->AddItem(reward.ItemID, reward.ItemQuantity);
+5 -1
View File
@@ -319,7 +319,11 @@ Battlepay::Product const& BattlePayDataStoreMgr::GetProduct(uint32 productID) co
{
if (ProductExist(productID))
return _products.at(productID);
return{};
// SylvaniaCore : "return{}" rendait une reference sur un temporaire detruit
// des le retour ; les huit appelants lisaient de la memoire morte.
static Battlepay::Product const emptyProduct{};
return emptyProduct;
}
Battlepay::DisplayInfo const* BattlePayDataStoreMgr::GetDisplayInfo(uint32 id) const
+5 -5
View File
@@ -3307,7 +3307,10 @@ void ObjectMgr::LoadGarrssionMissionReward()
TC_LOG_INFO("server.loading", ">> Loaded garrssion_mission_reward in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
std::vector<GarrssionMissionReward>* ObjectMgr::GetGarrssionMissionReward(uint32 id)
// SylvaniaCore : cette fonction rendait l adresse d un vecteur local. L appelant
// (Garrison::...) melangeait puis parcourait un objet deja detruit -- ecriture et
// lecture dans une pile liberee. On rend desormais le vecteur par valeur.
std::vector<GarrssionMissionReward> ObjectMgr::GetGarrssionMissionReward(uint32 id)
{
std::vector<GarrssionMissionReward> _reward;
for (auto& __reward : GarrssionMissionRewardMap)
@@ -3315,10 +3318,7 @@ std::vector<GarrssionMissionReward>* ObjectMgr::GetGarrssionMissionReward(uint32
if (__reward.MissionId == id)
_reward.push_back(__reward);
}
if (_reward.size() > 0)
return &_reward;
else
return nullptr;
return _reward;
}
void ObjectMgr::LoadVehicleTemplateAccessories()
+1 -1
View File
@@ -999,7 +999,7 @@ class TC_GAME_API ObjectMgr
ItemTemplateContainer const* GetItemTemplateStore() const { return &_itemTemplateStore; }
void LoadGarrssionMissionReward();
std::vector<GarrssionMissionReward>* GetGarrssionMissionReward(uint32 id);
std::vector<GarrssionMissionReward> GetGarrssionMissionReward(uint32 id);
std::vector<GarrssionMissionReward> GarrssionMissionRewardMap;
ScriptParams const& GetScriptParam(ObjectGuid::LowType lowGuid) { return _scriptParamContainer[lowGuid]; }
+1 -1
View File
@@ -570,7 +570,7 @@ class TC_GAME_API InstanceScript : public ZoneScript
uint64 m_InstanceGuid;
uint32 m_BeginningTime;
uint32 m_ScenarioID;
uint8 m_ScenarioStep;
uint32 m_ScenarioStep; // SylvaniaCore : ID de ScenarioStep, un uint8 tronquait la valeur
uint32 m_LastResetTime;
uint8 m_ChallengeLevel;
uint8 m_DeathCount;
+34 -16
View File
@@ -36,6 +36,24 @@
#include "World.h"
#include "WorldSession.h"
namespace
{
// Quelques pas devant la structure, angle tire au hasard pour que les
// recrues ne s empilent pas, face au portail, hauteur recalee au sol.
Position BuildPortalExit(Position const& portal, Player* bot)
{
float const angle = portal.GetOrientation() + frand(-1.0f, 1.0f);
float const distance = frand(1.5f, 3.0f);
float x = portal.GetPositionX() + distance * std::cos(angle);
float y = portal.GetPositionY() + distance * std::sin(angle);
float z = portal.GetPositionZ();
if (bot)
if (Map* map = bot->GetMap())
map->GetHeight(bot->GetPhaseShift(), x, y, z);
return Position(x, y, z, angle + float(M_PI));
}
}
MercenaryMgr::MercenaryMgr() :
m_enabled(false), m_cost(100 * MERCENARY_COPPER_PER_GOLD), m_maxPerPlayer(MERCENARY_HARD_CAP),
m_minLevel(10), m_updateTimer(0), m_releasing(false)
@@ -640,23 +658,10 @@ void MercenaryMgr::Update(uint32 diff)
{
if (BotGroupAI* groupAI = dynamic_cast<BotGroupAI*>(bot->GetAI()))
{
// Repli : sans portail connu, ou si l armement immediat a
// echoue, le mercenaire rejoint simplement son employeur.
if (it->hasPortal)
{
// Il franchit le seuil : quelques pas devant la structure,
// l angle varie pour que quatre mercenaires ne se marchent
// pas dessus, et la hauteur est recalee sur le terrain.
float const angle = it->portalPos.GetOrientation() + frand(-1.0f, 1.0f);
float const distance = frand(1.5f, 3.0f);
float x = it->portalPos.GetPositionX() + distance * std::cos(angle);
float y = it->portalPos.GetPositionY() + distance * std::sin(angle);
float z = it->portalPos.GetPositionZ();
if (Map* map = bot->GetMap())
map->GetHeight(bot->GetPhaseShift(), x, y, z);
// Il fait face au portail dont il sort.
Position spot(x, y, z, angle + float(M_PI));
groupAI->TeleportToPoint(it->portalMap, spot);
}
groupAI->TeleportToPoint(it->portalMap, BuildPortalExit(it->portalPos, bot));
else
groupAI->ProcessBotCommand(owner, "!summon");
it->summonPending = false;
@@ -733,6 +738,19 @@ void MercenaryMgr::Update(uint32 diff)
PlayerBotMgr::SwitchPlayerBotAI(bot, PlayerBotAIType::PBAIT_GROUP, true);
// Des maintenant, pas au tick suivant : l IA de groupe, en decouvrant
// un maitre lointain, armerait le sien vers l employeur, et SetTeleport
// refuse d ecraser un teleport en cours. Notre ordre serait perdu et le
// mercenaire apparaitrait sur le joueur plutot que sur le portail.
if (it->hasPortal)
{
if (BotGroupAI* groupAI = dynamic_cast<BotGroupAI*>(bot->GetAI()))
{
groupAI->TeleportToPoint(it->portalMap, BuildPortalExit(it->portalPos, bot));
it->summonPending = false;
}
}
ChatHandler(owner->GetSession()).PSendSysMessage(
"|cff00ff00[Portail]|r %s, %s mercenaire, répond à votre appel.",
bot->GetName().c_str(), GetRoleName(it->role));
+1 -1
View File
@@ -58,7 +58,7 @@ class TC_GAME_API FieldActing
{
public:
FieldActing(ACTING_TYPE aType) : m_ActingType(aType) {}
~FieldActing() {}
virtual ~FieldActing() {} // SylvaniaCore : classe polymorphe detruite par pointeur de base
bool MatchActingType(ACTING_TYPE aType) { return m_ActingType == aType; }
virtual void Update() {}
+10 -2
View File
@@ -1038,7 +1038,7 @@ class TC_GAME_API WorldSession
WorldSession(uint32 id, std::string&& name, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time,
std::string os, LocaleConstant locale, uint32 recruiter, bool isARecruiter, std::string&& battlenetAccountName);
~WorldSession();
virtual ~WorldSession(); // SylvaniaCore : PlayerBotSession en derive, un delete sur WorldSession* ne detruisait que la moitie de l objet
void SetAddress(std::string mybot)
{
@@ -1597,7 +1597,15 @@ class TC_GAME_API WorldSession
void HandleMissileTrajectoryCollision(WorldPackets::Spells::MissileTrajectoryCollision& packet);
void HandleUpdateMissileTrajectory(WorldPackets::Spells::UpdateMissileTrajectory& packet);
bool HasSocket() { return m_Socket != NULL; }
// SylvaniaCore : m_Socket est un tableau -- le comparer a NULL testait son
// adresse, donc renvoyait toujours true (y compris pour un playerbot).
bool HasSocket() const
{
for (std::shared_ptr<WorldSocket> const& socket : m_Socket)
if (socket)
return true;
return false;
}
virtual bool IsBotSession() { return false; }
virtual bool HasSchedules() { return false; }
virtual bool HasBGSchedule() { return false; }
@@ -89,7 +89,7 @@ struct boss_admiral_svirax : public BossAI
void Initialize()
{
SetDungeonEncounterID,(2070);
SetDungeonEncounterID(2070);
}
void DamageTaken(Unit* done_by, uint32 &damage) override
@@ -244,7 +244,6 @@ struct boss_admiral_svirax : public BossAI
uint8 PHASE_01;
uint8 PHASE_02;
uint8 PHASE_03;
bool SetDungeonEncounterID;
bool IsLock;
};
@@ -1540,7 +1540,7 @@ public:
};
bool OnQuestAccept(Player* player, Creature* /*creature*/, Quest const* quest) override
{
if (quest->GetQuestId() == QUEST_STOP_GULDAN_H || QUEST_STOP_GULDAN_A)
if (quest->GetQuestId() == QUEST_STOP_GULDAN_H || quest->GetQuestId() == QUEST_STOP_GULDAN_A)
player->GetSceneMgr().PlayScene(SCENE_GULDAN_STEAL_ILLIDAN_ID);
return true;
}
@@ -253,7 +253,7 @@ class boss_new_vizaduum : public CreatureScript
if (!_isFlying)
return;
if (type == POINT_MOTION_TYPE || WAYPOINT_MOTION_TYPE)
if (type == POINT_MOTION_TYPE || type == WAYPOINT_MOTION_TYPE)
{
switch (id)
{
@@ -244,13 +244,34 @@ public:
void OnPlayerEnter(Player* player) override
{
// SONDE TEMPORAIRE RIVAGEDBG
TC_LOG_ERROR("misc", "RIVAGEDBG OnPlayerEnter : %s en (%.0f, %.0f, %.0f)",
player ? player->GetName().c_str() : "aucun",
player ? player->GetPositionX() : 0.f,
player ? player->GetPositionY() : 0.f,
player ? player->GetPositionZ() : 0.f);
if (!player)
return;
player->CastSpell(player, SPELL_ENTREE_AURA, true);
// FILET DE SECURITE, temporaire.
// L'etape 0 n'est creditee que par l'arrivee du corbeau. Si
// celui-ci ne vole pas, le scenario reste bloque des la
// premiere etape et le reste devient intestable. On credite
// donc l'arrivee au bout de 20 s si elle ne l'a pas ete.
// A RETIRER une fois le vol repare.
InstanceScript* moi = this;
player->AddDelayedEvent(20000, [moi]() -> void
{
moi->SetData(DATA_ARRIVEE_ACCOMPLIE, 1);
});
player->AddDelayedEvent(5000, [player]() -> void
{
// SONDE TEMPORAIRE RIVAGEDBG
TC_LOG_ERROR("misc", "RIVAGEDBG invocation du corbeau (sort %u)", uint32(SPELL_ENTREE_INVOCATION));
player->CastSpell(player, SPELL_ENTREE_INVOCATION, true);
std::list<Creature*> escorte;
@@ -637,13 +658,22 @@ public:
void IsSummonedBy(Unit* summoner) override
{
// SONDE TEMPORAIRE RIVAGEDBG
TC_LOG_ERROR("misc", "RIVAGEDBG corbeau invoque par %s en (%.0f, %.0f, %.0f)",
summoner ? summoner->GetName().c_str() : "personne",
me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
SetFlyMode(true);
if (summoner)
summoner->CastSpell(me, SPELL_MONTER_CORBEAU, true);
}
void PassengerBoarded(Unit* /*passager*/, int8 /*seatId*/, bool /*apply*/) override
void PassengerBoarded(Unit* passager, int8 /*seatId*/, bool apply) override
{
// SONDE TEMPORAIRE RIVAGEDBG
TC_LOG_ERROR("misc", "RIVAGEDBG passager %s %s le corbeau",
passager ? passager->GetName().c_str() : "inconnu", apply ? "monte sur" : "descend de");
Creature* moi = me;
me->AddDelayedEvent(4000, [moi]() -> void
{
@@ -126,8 +126,11 @@ public:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true))
me->CastSpell(target, SPELL_EXPEL_LIGHT_MARKER, false);
events.ScheduleEvent(EVENT_EXPEL_LIGHT, (expelLightSwitch <= 1) ? 20 : 75 * IN_MILLISECONDS);
expelLightSwitch = (expelLightSwitch <= 1) ? ++expelLightSwitch : 0;
// SylvaniaCore : le 20 n etait pas multiplie par IN_MILLISECONDS
// (relance toutes les 20 ms), et l ancienne affectation modifiait
// expelLightSwitch deux fois sans point de sequence.
events.ScheduleEvent(EVENT_EXPEL_LIGHT, (expelLightSwitch <= 1) ? 20 * IN_MILLISECONDS : 75 * IN_MILLISECONDS);
expelLightSwitch = (expelLightSwitch <= 1) ? expelLightSwitch + 1 : 0;
break;
case EVENT_SHIELD_OF_LIGHT:
@@ -102,7 +102,9 @@ public:
{
case 1:
{
for (uint32 i = 1; i < 7; i++) // +1
// SylvaniaCore : Waypointspawn n a que 6 entrees (0 a 5) ; la boucle
// d origine lisait l index 6, hors du tableau, a chaque declenchement.
for (uint32 i = 0; i < 6; i++)
{
me->CastSpell(Waypointspawn[i].GetPositionX() + urand(0, 25), Waypointspawn[i].GetPositionY() + urand(0, 25), Waypointspawn[i].GetPositionZ(), 217212, true);
}
@@ -5091,7 +5091,10 @@ struct spell_area_paragons_of_the_klaxxi_reaction_yellow : AreaTriggerAI
caster->AddAura(SPELL_NOXIOUS_VAPORS, target);
}
bool OnRemoveTarget(Unit* target, bool /*byExpire*/)
// SylvaniaCore : le hook du core est OnUnitExit -- OnRemoveTarget n existe
// nulle part dans AreaTriggerAI, la methode n etait donc jamais appelee et
// l aura restait sur le joueur apres sa sortie de la zone.
void OnUnitExit(Unit* target) override
{
target->RemoveAura(SPELL_NOXIOUS_VAPORS);
}
@@ -5139,7 +5142,10 @@ struct spell_area_paragons_of_the_klaxxi_sonic_projection : AreaTriggerAI
caster->AddAura(SPELL_SONIC_PROJECTION_DMG, target);
}
bool OnRemoveTarget(Unit* target, bool /*byExpire*/)
// SylvaniaCore : le hook du core est OnUnitExit -- OnRemoveTarget n existe
// nulle part dans AreaTriggerAI, la methode n etait donc jamais appelee et
// l aura restait sur le joueur apres sa sortie de la zone.
void OnUnitExit(Unit* target) override
{
target->RemoveAura(SPELL_SONIC_PROJECTION_DMG);
}
@@ -3348,8 +3348,12 @@ struct spell_area_siegecrafter_blackfuse_laser_ground_effect : AreaTriggerAI
caster->AddAura(SPELL_SUPERHEATED_AURA, p_Target);
}
bool OnRemoveTarget(Unit* target, bool /*byExpire*/)
// SylvaniaCore : le hook du core est OnUnitExit -- OnRemoveTarget n existe
// nulle part dans AreaTriggerAI, la methode n etait donc jamais appelee et
// l aura restait sur le joueur apres sa sortie de la zone.
void OnUnitExit(Unit* target) override
{
target->RemoveAura(SPELL_SUPERHEATED_AURA);
}
};
@@ -1054,10 +1054,12 @@ struct spell_area_pressure_plate : AreaTriggerAI
unit->AddAura(eSpells::PressurePlateButton, unit);
}
bool OnRemoveTarget(Unit* p_Target, bool /*p_ByExpire*/)
// SylvaniaCore : le hook du core est OnUnitExit -- OnRemoveTarget n existe
// nulle part dans AreaTriggerAI, la methode n etait donc jamais appelee et
// l aura restait sur le joueur apres sa sortie de la zone.
void OnUnitExit(Unit* p_Target) override
{
p_Target->RemoveAura(eSpells::PressurePlateButton);
return true;
}
};
@@ -351,8 +351,6 @@ class boss_wase_mari : public CreatureScript
break;
Talk(TEXT_PHASE_SWITCH);
ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList();
threatlist.empty();
me->GetMotionMaster()->MovePoint(1, me->GetHomePosition());
me->RemoveAurasDueToSpell(SPELL_WATER_BUBBLE);
@@ -928,7 +928,7 @@ public:
break;
case EVENT_RECKLESS_CAHRGE_INITIALIZE:
{
if (me->HasAura(SPELL_DISCHARGE || me->HasAura(SPELL_OVERLOAD)))
if (me->HasAura(SPELL_DISCHARGE) || me->HasAura(SPELL_OVERLOAD))
{
events.CancelEvent(EVENT_RECKLESS_CAHRGE_INITIALIZE);
events.ScheduleEvent(EVENT_RECKLESS_CAHRGE_INITIALIZE, 10 * IN_MILLISECONDS);
@@ -292,11 +292,12 @@ public:
return true;
}
bool OnRemoveTarget(AreaTrigger* trigger, Unit* target)
// SylvaniaCore : le hook du core est OnUnitExit -- OnRemoveTarget n existe
// nulle part dans AreaTriggerAI, la methode n etait donc jamais appelee et
// l aura restait sur le joueur apres sa sortie de la zone.
void OnUnitExit(Unit* target) override
{
target->RemoveAura(144693);
return true;
}
};*/
@@ -206,7 +206,7 @@ public:
player->GetMotionMaster()->MovePointWithRot(PETBATTLE_ENTER_MOVE_SPLINE_ID, playerPosition.m_positionX, playerPosition.m_positionY, playerPosition.m_positionZ, playerPosition.m_orientation);
creature->ForcedDespawn(1);
creature->SetRespawnTime(3000000000000000);
creature->SetRespawnTime(std::numeric_limits<uint32>::max()); // SylvaniaCore : la constante d origine debordait de uint32
}
else
CloseGossipMenuFor(player);