Difficulte : traiter CMSG_TOGGLE_DIFFICULTY, le mode heroique des vieux raids

Signalement Discord : impossible de passer les Terres de feu en heroique, le
client repondait qu on ne remplissait pas les conditions. Aucun rapport avec un
deblocage par kill.

Les raids d avant Warlords n utilisent pas CMSG_SET_RAID_DIFFICULTY pour ce
bouton : le client envoie CMSG_TOGGLE_DIFFICULTY, sans preciser de difficulte,
et attend la bascule normal <-> heroique a taille de raid constante. L opcode
etait declare STATUS_UNHANDLED et jete a la reception, d ou le refus cote
client. C est aussi pourquoi le 10 <-> 25 fonctionnait : ce bouton passe par
l autre opcode.

Handler ecrit avec les memes garde-fous que le changement de difficulte
ordinaire. Reste a faire : la bascule depuis l interieur de l instance, le vrai
comportement de Cataclysm -- IsDynamicDifficultyMap existe dans les DB2 mais
n est utilise nulle part.
This commit is contained in:
BlaMacfly
2026-09-12 23:02:02 +02:00
parent 08426fa6d4
commit 0c87f040f6
4 changed files with 75 additions and 1 deletions
+62
View File
@@ -993,6 +993,68 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPackets::Misc::SetRaidDiff
}
}
// Les raids d'avant Warlords ne passent pas par CMSG_SET_RAID_DIFFICULTY pour le mode
// heroique : le client envoie CMSG_TOGGLE_DIFFICULTY, sans rien preciser, et attend que
// le serveur bascule entre normal et heroique en conservant la taille du raid. Cet
// opcode n'etait pas traite du tout, si bien que le client repondait « vous ne remplissez
// pas les conditions requises » -- impossible de monter les Terres de feu en heroique.
void WorldSession::HandleToggleDifficultyOpcode(WorldPackets::Misc::ToggleDifficulty& /*toggleDifficulty*/)
{
Difficulty difficultyID;
switch (_player->GetLegacyRaidDifficultyID())
{
case DIFFICULTY_10_N: difficultyID = DIFFICULTY_10_HC; break;
case DIFFICULTY_25_N: difficultyID = DIFFICULTY_25_HC; break;
case DIFFICULTY_10_HC: difficultyID = DIFFICULTY_10_N; break;
case DIFFICULTY_25_HC: difficultyID = DIFFICULTY_25_N; break;
default:
return;
}
// Memes garde-fous que le changement de difficulte ordinaire : on ne bascule pas
// depuis l'interieur d'une instance, et seul le chef decide pour le groupe.
Map* map = _player->FindMap();
if (map && map->IsDungeon())
{
TC_LOG_DEBUG("network", "WorldSession::HandleToggleDifficultyOpcode: player (Name: %s, %s) tried to toggle the difficulty while inside an instance!",
_player->GetName().c_str(), _player->GetGUID().ToString().c_str());
return;
}
Group* group = _player->GetGroup();
if (group)
{
if (!group->IsLeader(_player->GetGUID()))
return;
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* groupGuy = itr->GetSource();
if (!groupGuy)
continue;
if (!groupGuy->IsInMap(groupGuy))
return;
if (groupGuy->GetMap()->IsRaid())
{
TC_LOG_DEBUG("network", "WorldSession::HandleToggleDifficultyOpcode: %s tried to toggle the difficulty while group member (Name: %s, %s) is inside!",
_player->GetGUID().ToString().c_str(), groupGuy->GetName().c_str(), groupGuy->GetGUID().ToString().c_str());
return;
}
}
group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, true, _player);
group->SetLegacyRaidDifficultyID(difficultyID);
}
else
{
_player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, true);
_player->SetLegacyRaidDifficultyID(difficultyID);
_player->SendRaidDifficulty(true);
}
}
void WorldSession::HandleSetTaxiBenchmark(WorldPackets::Misc::SetTaxiBenchmarkMode& packet)
{
_player->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK, packet.Enable);
@@ -300,6 +300,16 @@ namespace WorldPackets
uint8 Legacy = 0;
};
// Le bouton « heroique » des raids d'avant Warlords : aucune difficulte n'est
// transmise, le client demande simplement la bascule normal <-> heroique.
class ToggleDifficulty final : public ClientPacket
{
public:
ToggleDifficulty(WorldPacket&& packet) : ClientPacket(CMSG_TOGGLE_DIFFICULTY, std::move(packet)) { }
void Read() override { }
};
class DungeonDifficultySet final : public ServerPacket
{
public:
+1 -1
View File
@@ -830,7 +830,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_TIME_SYNC_RESPONSE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleTimeSyncResponse);
DEFINE_HANDLER(CMSG_TIME_SYNC_RESPONSE_DROPPED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_TIME_SYNC_RESPONSE_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_TOGGLE_DIFFICULTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_TOGGLE_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleToggleDifficultyOpcode);
DEFINE_HANDLER(CMSG_TOGGLE_PVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTogglePvP);
DEFINE_HANDLER(CMSG_TOTEM_DESTROYED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTotemDestroyed);
DEFINE_HANDLER(CMSG_TRADE_SKILL_SET_FAVORITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
+2
View File
@@ -569,6 +569,7 @@ namespace WorldPackets
class TutorialSetFlag;
class SetDungeonDifficulty;
class SetRaidDifficulty;
class ToggleDifficulty;
class PortGraveyard;
class ReclaimCorpse;
class RepopRequest;
@@ -1727,6 +1728,7 @@ class TC_GAME_API WorldSession
void HandleFarSightOpcode(WorldPackets::Misc::FarSight& packet);
void HandleSetDungeonDifficultyOpcode(WorldPackets::Misc::SetDungeonDifficulty& setDungeonDifficulty);
void HandleSetRaidDifficultyOpcode(WorldPackets::Misc::SetRaidDifficulty& setRaidDifficulty);
void HandleToggleDifficultyOpcode(WorldPackets::Misc::ToggleDifficulty& toggleDifficulty);
void HandleSetTitleOpcode(WorldPackets::Character::SetTitle& packet);
void HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse& packet);
void HandleDiscardedTimeSyncAcks(WorldPackets::Misc::DiscardedTimeSyncAcks& packet);