neutral faction ui
This commit is contained in:
@@ -33875,3 +33875,9 @@ void Player::SendCtrOptions() const
|
||||
ctrOptions.ChromieTimeExpansionMask = m_playerData->CtrOptions->ChromieTimeExpansionMask;
|
||||
SendDirectMessage(ctrOptions.Write());
|
||||
}
|
||||
|
||||
void Player::ShowNeutralPlayerFactionSelectUI()
|
||||
{
|
||||
WorldPackets::Misc::FactionSelectUI packet;
|
||||
GetSession()->SendPacket(packet.Write());
|
||||
}
|
||||
|
||||
@@ -2140,6 +2140,9 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
void ApplyTraitEntryChanges(int32 editedConfigId, WorldPackets::Traits::TraitConfig const& newConfig, bool applyTraits, bool consumeCurrencies);
|
||||
void RenameTraitConfig(int32 editedConfigId, std::string&& newName);
|
||||
void DeleteTraitConfig(int32 deletedConfigId);
|
||||
|
||||
void ShowNeutralPlayerFactionSelectUI();
|
||||
|
||||
void ApplyTraitConfig(int32 configId, bool apply);
|
||||
void ApplyTraitEntry(int32 traitNodeEntryId, int32 rank, int32 grantedRanks, bool apply);
|
||||
void SetActiveCombatTraitConfigID(int32 traitConfigId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ActiveCombatTraitConfigID), traitConfigId); }
|
||||
|
||||
@@ -1285,3 +1285,138 @@ void WorldSession::HandleCovenantRenownRequestCatchupState(WorldPackets::MajorFa
|
||||
|
||||
SendPacket(response.Write());
|
||||
}
|
||||
|
||||
void WorldSession::HandleSelectFactionOpcode(WorldPackets::Misc::FactionSelect& selectFaction)
|
||||
{
|
||||
if (!_player)
|
||||
return;
|
||||
|
||||
enum FactionSelection
|
||||
{
|
||||
JOIN_HORDE = 0,
|
||||
JOIN_ALLIANCE = 1,
|
||||
|
||||
SPELL_TRIGGER_FACTION_CHOICE_ALLIANCE = 113244,
|
||||
SPELL_TRIGGER_FACTION_CHOICE_HORDE = 113245
|
||||
};
|
||||
|
||||
TC_LOG_INFO("entities.player", "HandleSelectFactionOpcode: Player {} (GUID: {}) attempting to select faction: {}",
|
||||
_player ? _player->GetName() : "<null>",
|
||||
_player ? _player->GetGUID().ToString() : "<null>",
|
||||
selectFaction.FactionChoice);
|
||||
|
||||
if (_player->GetRace() != RACE_PANDAREN_NEUTRAL)
|
||||
{
|
||||
TC_LOG_WARN("entities.player", "HandleSelectFactionOpcode: Player {} (GUID: {}) is not neutral pandaren (race: {}), rejecting faction selection",
|
||||
_player ? _player->GetName() : "<null>",
|
||||
_player ? _player->GetGUID().ToString() : "<null>",
|
||||
_player ? _player->GetRace() : 0);
|
||||
|
||||
// Send error result to client
|
||||
WorldPackets::Character::NeutralPlayerFactionSelectResult result;
|
||||
result.Success = false;
|
||||
result.NewRaceID = _player ? _player->GetRace() : 0;
|
||||
_player->GetSession()->SendPacket(result.Write());
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectFaction.FactionChoice > JOIN_ALLIANCE)
|
||||
{
|
||||
TC_LOG_WARN("entities.player", "HandleSelectFactionOpcode: Player {} (GUID: {}) sent invalid faction choice: {}",
|
||||
_player->GetName(), _player->GetGUID().ToString(), selectFaction.FactionChoice);
|
||||
|
||||
// Send error result to client
|
||||
WorldPackets::Character::NeutralPlayerFactionSelectResult result;
|
||||
result.Success = false;
|
||||
result.NewRaceID = _player->GetRace();
|
||||
_player->GetSession()->SendPacket(result.Write());
|
||||
return;
|
||||
}
|
||||
|
||||
// Additional validation: check if player already has a faction (shouldn't happen but safety check)
|
||||
if (_player->GetRace() == RACE_PANDAREN_ALLIANCE || _player->GetRace() == RACE_PANDAREN_HORDE)
|
||||
{
|
||||
TC_LOG_WARN("entities.player", "HandleSelectFactionOpcode: Player {} (GUID: {}) already has faction (race: {}), rejecting faction selection",
|
||||
_player->GetName(), _player->GetGUID().ToString(), _player->GetRace());
|
||||
|
||||
// Send error result to client
|
||||
WorldPackets::Character::NeutralPlayerFactionSelectResult result;
|
||||
result.Success = false;
|
||||
result.NewRaceID = _player->GetRace();
|
||||
_player->GetSession()->SendPacket(result.Write());
|
||||
return;
|
||||
}
|
||||
|
||||
Races newRace = RACE_NONE;
|
||||
uint32 languageSpell1 = 0;
|
||||
uint32 languageSpell2 = 0;
|
||||
uint32 triggerSpell = 0;
|
||||
|
||||
switch (selectFaction.FactionChoice)
|
||||
{
|
||||
case JOIN_ALLIANCE:
|
||||
newRace = RACE_PANDAREN_ALLIANCE;
|
||||
languageSpell1 = SPELL_LEARN_LANGUAGE_COMMON;
|
||||
languageSpell2 = SPELL_LEARN_LANGUAGE_PANDAREN_ALLIANCE;
|
||||
triggerSpell = SPELL_TRIGGER_FACTION_CHOICE_ALLIANCE;
|
||||
break;
|
||||
case JOIN_HORDE:
|
||||
newRace = RACE_PANDAREN_HORDE;
|
||||
languageSpell1 = SPELL_LEARN_LANGUAGE_ORCISH;
|
||||
languageSpell2 = SPELL_LEARN_LANGUAGE_PANDAREN_HORDE;
|
||||
triggerSpell = SPELL_TRIGGER_FACTION_CHOICE_HORDE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_player->SetRace(newRace);
|
||||
_player->SetFactionForRace(newRace);
|
||||
_player->SaveToDB();
|
||||
_player->LearnSpell(languageSpell1, false);
|
||||
_player->LearnSpell(languageSpell2, false);
|
||||
_player->CastSpell(_player, triggerSpell, true);
|
||||
|
||||
// Force client to refresh all reputation factions or sides
|
||||
uint32 headerFactionId = (newRace == RACE_PANDAREN_ALLIANCE) ? 469 : 67;
|
||||
|
||||
for (FactionEntry const* fe : sFactionStore)
|
||||
{
|
||||
if (!fe->CanHaveReputation())
|
||||
continue;
|
||||
|
||||
if (fe->ParentFactionID != headerFactionId)
|
||||
continue;
|
||||
|
||||
_player->GetReputationMgr().SetVisible(fe);
|
||||
|
||||
int32 base = fe->ReputationBase[0];
|
||||
|
||||
// Apply the base reputation
|
||||
_player->GetReputationMgr().SetOneFactionReputation(fe, base, false);
|
||||
|
||||
// Get the updated state
|
||||
FactionState* fs = const_cast<FactionState*>(_player->GetReputationMgr().GetState(fe));
|
||||
if (!fs)
|
||||
continue;
|
||||
|
||||
// Mark for sending
|
||||
fs->needSend = true;
|
||||
|
||||
// Trigger the system messages
|
||||
fs->VisualStandingIncrease = base;
|
||||
|
||||
// Send the update
|
||||
_player->GetReputationMgr().SendState(fs);
|
||||
}
|
||||
|
||||
const char* sideName = (selectFaction.FactionChoice == 0) ? "Horde" : "Alliance";
|
||||
TC_LOG_INFO("entities.player", "HandleSelectFactionOpcode: Player {} (GUID: {}) successfully joined {}",
|
||||
_player->GetName(), _player->GetGUID().ToString(), sideName);
|
||||
|
||||
// Send success result to client
|
||||
WorldPackets::Character::NeutralPlayerFactionSelectResult result;
|
||||
result.Success = true;
|
||||
result.NewRaceID = newRace;
|
||||
_player->GetSession()->SendPacket(result.Write());
|
||||
}
|
||||
|
||||
@@ -923,5 +923,14 @@ namespace WorldPackets::Character
|
||||
_worldPacket >> SizedString::Data(group.Name);
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket const* NeutralPlayerFactionSelectResult::Write()
|
||||
{
|
||||
_worldPacket << NewRaceID;
|
||||
_worldPacket >> Bits<1>(Success);
|
||||
_worldPacket.FlushBits();
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
//WowCommunity
|
||||
}
|
||||
|
||||
@@ -933,6 +933,17 @@ namespace WorldPackets
|
||||
|
||||
std::vector<WarbandGroupSetup> Groups;
|
||||
};
|
||||
|
||||
class NeutralPlayerFactionSelectResult final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
NeutralPlayerFactionSelectResult() : ServerPacket(SMSG_NEUTRAL_PLAYER_FACTION_SELECT_RESULT, 4 + 1) {}
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint32 NewRaceID = 0;
|
||||
bool Success = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -924,4 +924,9 @@ WorldPacket const* SetCtrOptions::Write()
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
void WorldPackets::Misc::FactionSelect::Read()
|
||||
{
|
||||
_worldPacket >> FactionChoice;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1149,6 +1149,23 @@ namespace WorldPackets
|
||||
uint32 ChromieTimeExpansionMask = 0;
|
||||
};
|
||||
|
||||
class FactionSelect final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
FactionSelect(WorldPacket&& packet) : ClientPacket(CMSG_NEUTRAL_PLAYER_SELECT_FACTION, std::move(packet)) {}
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint8 FactionChoice = 0;
|
||||
};
|
||||
|
||||
class FactionSelectUI final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
FactionSelectUI() : ServerPacket(SMSG_SHOW_NEUTRAL_PLAYER_FACTION_SELECT_UI, 0) {}
|
||||
|
||||
WorldPacket const* Write() override { return &_worldPacket; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -857,7 +857,7 @@ void OpcodeTable::InitializeClientOpcodes()
|
||||
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_REMOVE_SECONDARY_OWNER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodRemoveSecondaryOwner);
|
||||
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_SET_PUBLIC_FLAG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodSetPublicFlag);
|
||||
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_UPDATE_NAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodUpdateName);
|
||||
DEFINE_HANDLER(CMSG_NEUTRAL_PLAYER_SELECT_FACTION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_NEUTRAL_PLAYER_SELECT_FACTION, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSelectFactionOpcode);
|
||||
DEFINE_HANDLER(CMSG_NEXT_CINEMATIC_CAMERA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNextCinematicCamera);
|
||||
DEFINE_HANDLER(CMSG_NPC_CRAFTING_ORDER_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_OBJECT_UPDATE_FAILED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleObjectUpdateFailedOpcode);
|
||||
@@ -2132,7 +2132,7 @@ void OpcodeTable::InitializeServerOpcodes()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_REMOVE_SECONDARY_OWNER_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_ROSTER_RESIDENT_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_UPDATE_NAME_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEUTRAL_PLAYER_FACTION_SELECT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEUTRAL_PLAYER_FACTION_SELECT_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_DATA_BUILD, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_TAXI_PATH, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_WORLD, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
@@ -2426,7 +2426,7 @@ void OpcodeTable::InitializeServerOpcodes()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHIPMENT_FACTION_UPDATE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_DELVES_COMPANION_CONFIGURATION_UI, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_DELVES_DISPLAY_UI, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_NEUTRAL_PLAYER_FACTION_SELECT_UI, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_NEUTRAL_PLAYER_FACTION_SELECT_UI, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_QUEST_COMPLETION_TEXT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_TAXI_NODES, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_TRADE_SKILL_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
|
||||
@@ -743,6 +743,7 @@ namespace WorldPackets
|
||||
class RequestLatestSplashScreen;
|
||||
class QueryCountdownTimer;
|
||||
class SetCurrencyFlags;
|
||||
class FactionSelect;
|
||||
class RequestCurrencyDataForAccountCharacters;
|
||||
class TransferCurrencyFromAccountCharacter;
|
||||
class GetCharacterCurrencyTransferLog;
|
||||
@@ -2241,6 +2242,7 @@ class TC_GAME_API WorldSession
|
||||
void HandleKeyboundOverride(WorldPackets::Spells::KeyboundOverride& keyboundOverride);
|
||||
void HandleQueryCountdownTimer(WorldPackets::Misc::QueryCountdownTimer& queryCountdownTimer);
|
||||
void HandleSetCurrencyFlags(WorldPackets::Misc::SetCurrencyFlags const& setCurrenctFlags);
|
||||
void HandleSelectFactionOpcode(WorldPackets::Misc::FactionSelect& selectFaction);
|
||||
|
||||
// Adventure Journal
|
||||
void HandleAdventureJournalOpenQuest(WorldPackets::AdventureJournal::AdventureJournalOpenQuest& openQuest);
|
||||
|
||||
@@ -268,6 +268,14 @@ enum SpellFacingFlags
|
||||
SPELL_FACING_FLAG_INFRONT = 0x0001
|
||||
};
|
||||
|
||||
enum SpellLearnLanguage
|
||||
{
|
||||
SPELL_LEARN_LANGUAGE_COMMON = 668,
|
||||
SPELL_LEARN_LANGUAGE_ORCISH = 669,
|
||||
SPELL_LEARN_LANGUAGE_PANDAREN_ALLIANCE = 108130,
|
||||
SPELL_LEARN_LANGUAGE_PANDAREN_HORDE = 108131
|
||||
};
|
||||
|
||||
enum TriggerCastFlags : uint32
|
||||
{
|
||||
TRIGGERED_NONE = 0x00000000, //!< Not triggered
|
||||
|
||||
@@ -1669,6 +1669,22 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
// 108897 - Pandaren Faction Choice
|
||||
class spell_pandaren_faction_choice : public SpellScript
|
||||
{
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (caster->IsPlayer())
|
||||
caster->ToPlayer()->ShowNeutralPlayerFactionSelectUI();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_pandaren_faction_choice::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_zone_the_wandering_isle()
|
||||
{
|
||||
using namespace Scripts::Pandaria::TheWanderingIsle;
|
||||
@@ -1708,4 +1724,5 @@ void AddSC_zone_the_wandering_isle()
|
||||
RegisterSpellScript(spell_flying_shadow_kick);
|
||||
|
||||
RegisterCreatureAI(npc_delivery_cart);
|
||||
RegisterSpellScript(spell_pandaren_faction_choice);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user