Core/Player: Implemented account wide mounts

Closes #17369
This commit is contained in:
MitchesD
2016-10-01 13:48:16 +02:00
committed by Shauren
parent 20f0db0e47
commit ad3da9c971
15 changed files with 343 additions and 9 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
--
-- Table structure for table `battlenet_account_mounts`
--
DROP TABLE IF EXISTS `battlenet_account_mounts`;
CREATE TABLE `battlenet_account_mounts` (
`battlenetAccountId` int(10) unsigned NOT NULL,
`mountSpellId` int(10) unsigned NOT NULL,
`flags` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`battlenetAccountId`,`mountSpellId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@@ -0,0 +1,59 @@
DROP TABLE IF EXISTS `mount_definitions`;
CREATE TABLE `mount_definitions`(
`spellId` int(10) unsigned NOT NULL,
`otherFactionSpellId` int(10) unsigned NOT NULL,
PRIMARY KEY (`spellId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
DELETE FROM `mount_definitions`;
INSERT INTO `mount_definitions` (`spellId`,`otherFactionSpellId`) VALUES
(17229,64658),
(23509,23510),
(23510,23509),
(55531,60424),
(59785,59788),
(59788,59785),
(59797,59799),
(59799,59797),
(60114,60116),
(60116,60114),
(60118,60119),
(60119,60118),
(60424,55531),
(61229,61230),
(61230,61229),
(61425,61447),
(61447,61425),
(61465,61467),
(61467,61465),
(61469,61470),
(61470,61469),
(61996,61997),
(61997,61996),
(64658,17229),
(66087,66088),
(66088,66087),
(66090,66091),
(66091,66090),
(90621,93644),
(92231,92232),
(92232,92231),
(93644,90621),
(107516,107517),
(107517,107516),
(118737,130985),
(130985,118737),
(135416,135418),
(135418,135416),
(136163,136164),
(136164,136163),
(140249,140250),
(140250,140249),
(142266,142478),
(142478,142266),
(171625,171842),
(171626,171839),
(171839,171626),
(171842,171625),
(179244,179245),
(179245,179244);

View File

@@ -163,6 +163,10 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_ACCOUNT_HEIRLOOMS, "SELECT itemId, flags FROM battlenet_account_heirlooms WHERE accountId = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_REP_ACCOUNT_HEIRLOOMS, "REPLACE INTO battlenet_account_heirlooms (accountId, itemId, flags) VALUES (?, ?, ?)", CONNECTION_ASYNC);
// Account wide mounts
PrepareStatement(LOGIN_SEL_ACCOUNT_MOUNTS, "SELECT mountSpellId, flags FROM battlenet_account_mounts WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_REP_ACCOUNT_MOUNTS, "REPLACE INTO battlenet_account_mounts (battlenetAccountId, mountSpellId, flags) VALUES (?, ?, ?)", CONNECTION_ASYNC);
// Transmog collection
PrepareStatement(LOGIN_SEL_BNET_ITEM_APPEARANCES, "SELECT blobIndex, appearanceMask FROM battlenet_item_appearances WHERE battlenetAccountId = ? ORDER BY blobIndex DESC", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_BNET_ITEM_APPEARANCES, "INSERT INTO battlenet_item_appearances (battlenetAccountId, blobIndex, appearanceMask) VALUES (?, ?, ?) "

View File

@@ -152,6 +152,9 @@ enum LoginDatabaseStatements
LOGIN_SEL_ACCOUNT_HEIRLOOMS,
LOGIN_REP_ACCOUNT_HEIRLOOMS,
LOGIN_SEL_ACCOUNT_MOUNTS,
LOGIN_REP_ACCOUNT_MOUNTS,
LOGIN_SEL_BNET_ITEM_APPEARANCES,
LOGIN_INS_BNET_ITEM_APPEARANCES,
LOGIN_SEL_BNET_ITEM_FAVORITE_APPEARANCES,

View File

@@ -16,10 +16,53 @@
*/
#include "CollectionMgr.h"
#include "MiscPackets.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "TransmogrificationPackets.h"
namespace
{
MountDefinitionMap FactionSpecificMounts;
}
void CollectionMgr::LoadMountDefinitions()
{
uint32 oldMSTime = getMSTime();
QueryResult result = WorldDatabase.Query("SELECT spellId, otherFactionSpellId FROM mount_definitions");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 mount definitions. DB table `mount_definitions` is empty.");
return;
}
do
{
Field* fields = result->Fetch();
uint32 spellId = fields[0].GetUInt32();
uint32 otherFactionSpellId = fields[1].GetUInt32();
if (!sDB2Manager.GetMount(spellId))
{
TC_LOG_ERROR("sql.sql", "Mount spell %u defined in `mount_definitions` does not exist in Mount.db2, skipped", spellId);
continue;
}
if (otherFactionSpellId && !sDB2Manager.GetMount(otherFactionSpellId))
{
TC_LOG_ERROR("sql.sql", "otherFactionSpellId %u defined in `mount_definitions` for spell %u does not exist in Mount.db2, skipped", otherFactionSpellId, spellId);
continue;
}
FactionSpecificMounts[spellId] = otherFactionSpellId;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " mount definitions in %u ms", FactionSpecificMounts.size(), GetMSTimeDiffToNow(oldMSTime));
}
CollectionMgr::CollectionMgr(WorldSession* owner) : _owner(owner), _appearances()
{
}
@@ -195,7 +238,7 @@ void CollectionMgr::UpgradeHeirloom(uint32 itemId, uint32 castItem)
// Get heirloom offset to update only one part of dynamic field
std::vector<uint32> const& fields = player->GetDynamicValues(PLAYER_DYNAMIC_FIELD_HEIRLOOMS);
uint8 offset = std::find(fields.begin(), fields.end(), itemId) - fields.begin();
uint8 offset = uint8(std::find(fields.begin(), fields.end(), itemId) - fields.begin());
player->SetDynamicValue(PLAYER_DYNAMIC_FIELD_HEIRLOOM_FLAGS, offset, flags);
itr->second.flags = flags;
@@ -235,7 +278,7 @@ void CollectionMgr::CheckHeirloomUpgrades(Item* item)
if (newItemId)
{
std::vector<uint32> const& fields = player->GetDynamicValues(PLAYER_DYNAMIC_FIELD_HEIRLOOMS);
uint8 offset = std::find(fields.begin(), fields.end(), itr->first) - fields.begin();
uint8 offset = uint8(std::find(fields.begin(), fields.end(), itr->first) - fields.begin());
player->SetDynamicValue(PLAYER_DYNAMIC_FIELD_HEIRLOOMS, offset, newItemId);
player->SetDynamicValue(PLAYER_DYNAMIC_FIELD_HEIRLOOM_FLAGS, offset, 0);
@@ -274,6 +317,107 @@ bool CollectionMgr::CanApplyHeirloomXpBonus(uint32 itemId, uint32 level)
return level <= 60;
}
void CollectionMgr::LoadMounts()
{
for (auto const& m : _mounts)
AddMount(m.first, m.second, false, false);
}
void CollectionMgr::LoadAccountMounts(PreparedQueryResult result)
{
if (!result)
return;
do
{
Field* fields = result->Fetch();
uint32 mountSpellId = fields[0].GetUInt32();
MountStatusFlags flags = MountStatusFlags(fields[1].GetUInt8());
if (!sDB2Manager.GetMount(mountSpellId))
continue;
_mounts[mountSpellId] = flags;
} while (result->NextRow());
}
void CollectionMgr::SaveAccountMounts(SQLTransaction& trans)
{
for (auto const& mount : _mounts)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_REP_ACCOUNT_MOUNTS);
stmt->setUInt32(0, _owner->GetBattlenetAccountId());
stmt->setUInt32(1, mount.first);
stmt->setUInt8(2, mount.second);
trans->Append(stmt);
}
}
bool CollectionMgr::AddMount(uint32 spellId, MountStatusFlags flags, bool factionMount /*= false*/, bool learned /*= false*/)
{
Player* player = _owner->GetPlayer();
if (!player)
return false;
MountEntry const* mount = sDB2Manager.GetMount(spellId);
if (!mount)
return false;
MountDefinitionMap::const_iterator itr = FactionSpecificMounts.find(spellId);
if (itr != FactionSpecificMounts.end() && !factionMount)
AddMount(itr->second, flags, true, learned);
_mounts.insert(MountContainer::value_type(spellId, flags));
// Mount condition only applies to using it, should still learn it.
if (mount->PlayerConditionId)
{
PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(mount->PlayerConditionId);
if (!ConditionMgr::IsPlayerMeetingCondition(player, playerCondition))
return false;
}
if (!learned)
{
if (!factionMount)
SendSingleMountUpdate(std::make_pair(spellId, flags));
if (!player->HasSpell(spellId))
player->LearnSpell(spellId, true);
}
return true;
}
void CollectionMgr::MountSetFavorite(uint32 spellId, bool favorite)
{
auto itr = _mounts.find(spellId);
if (itr == _mounts.end())
return;
if (favorite)
itr->second = MountStatusFlags(itr->second | MOUNT_IS_FAVORITE);
else
itr->second = MountStatusFlags(itr->second & ~MOUNT_IS_FAVORITE);
SendSingleMountUpdate(*itr);
}
void CollectionMgr::SendSingleMountUpdate(std::pair<uint32, MountStatusFlags> mount)
{
Player* player = _owner->GetPlayer();
if (!player)
return;
// Temporary container, just need to store only selected mount
MountContainer tempMounts;
tempMounts.insert(mount);
WorldPackets::Misc::AccountMountUpdate mountUpdate;
mountUpdate.IsFullUpdate = false;
mountUpdate.Mounts = &tempMounts;
player->SendDirectMessage(mountUpdate.Write());
}
struct DynamicBitsetBlockOutputIterator : public std::iterator<std::output_iterator_tag, void, void, void, void>
{
explicit DynamicBitsetBlockOutputIterator(std::function<void(uint32)>&& action) : _action(std::forward<std::function<void(uint32)>>(action)) { }
@@ -351,7 +495,7 @@ void CollectionMgr::SaveAccountItemAppearances(SQLTransaction& trans)
if (blockValue) // this table is only appended/bits are set (never cleared) so don't save empty blocks
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ITEM_APPEARANCES);
stmt->setUInt32(0, GetOwner()->GetBattlenetAccountId());
stmt->setUInt32(0, _owner->GetBattlenetAccountId());
stmt->setUInt16(1, blockIndex);
stmt->setUInt32(2, blockValue);
trans->Append(stmt);
@@ -515,7 +659,7 @@ void CollectionMgr::AddItemAppearance(ItemModifiedAppearanceEntry const* itemMod
{
if (_appearances.size() <= itemModifiedAppearance->ID)
{
uint32 numBlocks = _appearances.num_blocks();
std::size_t numBlocks = _appearances.num_blocks();
_appearances.resize(itemModifiedAppearance->ID + 1);
numBlocks = _appearances.num_blocks() - numBlocks;
while (numBlocks--)
@@ -619,7 +763,7 @@ void CollectionMgr::SendFavoriteAppearances() const
transmogCollectionUpdate.FavoriteAppearances.reserve(_favoriteAppearances.size());
for (auto itr = _favoriteAppearances.begin(); itr != _favoriteAppearances.end(); ++itr)
if (itr->second != FavoriteAppearanceState::Removed)
transmogCollectionUpdate.FavoriteAppearances.push_back(itr->first);
transmogCollectionUpdate.FavoriteAppearances.push_back(itr->first);
_owner->SendPacket(transmogCollectionUpdate.Write());
}

View File

@@ -48,12 +48,22 @@ struct HeirloomData
typedef std::map<uint32, bool> ToyBoxContainer;
typedef std::map<uint32, HeirloomData> HeirloomContainer;
enum MountStatusFlags : uint8
{
MOUNT_STATUS_NONE = 0x00,
MOUNT_NEEDS_FANFARE = 0x01,
MOUNT_IS_FAVORITE = 0x02
};
typedef std::map<uint32, MountStatusFlags> MountContainer;
typedef std::unordered_map<uint32, uint32> MountDefinitionMap;
class TC_GAME_API CollectionMgr
{
public:
explicit CollectionMgr(WorldSession* owner);
WorldSession* GetOwner() const { return _owner; }
static void LoadMountDefinitions();
// Account-wide toys
void LoadToys();
@@ -83,6 +93,13 @@ public:
HeirloomContainer const& GetAccountHeirlooms() const { return _heirlooms; }
// Account-wide mounts
void LoadMounts();
void LoadAccountMounts(PreparedQueryResult result);
void SaveAccountMounts(SQLTransaction& trans);
bool AddMount(uint32 spellId, MountStatusFlags flags, bool factionMount = false, bool learned = false);
void MountSetFavorite(uint32 spellId, bool favorite);
void SendSingleMountUpdate(std::pair<uint32, MountStatusFlags> mount);
MountContainer const& GetAccountMounts() const { return _mounts; }
// Appearances
void LoadItemAppearances();
@@ -114,6 +131,7 @@ private:
ToyBoxContainer _toys;
HeirloomContainer _heirlooms;
MountContainer _mounts;
boost::dynamic_bitset<uint32> _appearances;
std::unordered_map<uint32, std::unordered_set<ObjectGuid>> _temporaryAppearances;
std::unordered_map<uint32, FavoriteAppearanceState> _favoriteAppearances;

View File

@@ -3149,6 +3149,10 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
UpdateCriteria(CRITERIA_TYPE_LEARN_SPELL, spellId);
}
// needs to be when spell is already learned, to prevent infinite recursion crashes
if (sDB2Manager.GetMount(spellId))
GetSession()->GetCollectionMgr()->AddMount(spellId, MOUNT_STATUS_NONE, false, IsInWorld() ? false : true);
// return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell
return active && !disabled && !superceded_old;
}
@@ -17551,6 +17555,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
_LoadSpells(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELLS));
GetSession()->GetCollectionMgr()->LoadToys();
GetSession()->GetCollectionMgr()->LoadHeirlooms();
GetSession()->GetCollectionMgr()->LoadMounts();
GetSession()->GetCollectionMgr()->LoadItemAppearances();
LearnSpecializationSpells();
@@ -19604,6 +19609,7 @@ void Player::SaveToDB(bool create /*=false*/)
GetSession()->GetCollectionMgr()->SaveAccountToys(trans);
GetSession()->GetBattlePetMgr()->SaveToDB(trans);
GetSession()->GetCollectionMgr()->SaveAccountHeirlooms(trans);
GetSession()->GetCollectionMgr()->SaveAccountMounts(trans);
GetSession()->GetCollectionMgr()->SaveAccountItemAppearances(trans);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_LAST_PLAYER_CHARACTERS);
@@ -23041,6 +23047,11 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendDirectMessage(worldServerInfo.Write());
// SMSG_ACCOUNT_MOUNT_UPDATE
WorldPackets::Misc::AccountMountUpdate mountUpdate;
mountUpdate.IsFullUpdate = true;
mountUpdate.Mounts = &GetSession()->GetCollectionMgr()->GetAccountMounts();
SendDirectMessage(mountUpdate.Write());
// SMSG_ACCOUNT_TOYS_UPDATE
WorldPackets::Toy::AccountToysUpdate toysUpdate;
toysUpdate.IsFullUpdate = true;

View File

@@ -1154,3 +1154,8 @@ void WorldSession::HandleMountSpecialAnimOpcode(WorldPackets::Misc::MountSpecial
specialMountAnim.UnitGUID = _player->GetGUID();
GetPlayer()->SendMessageToSet(specialMountAnim.Write(), false);
}
void WorldSession::HandleMountSetFavorite(WorldPackets::Misc::MountSetFavorite& mountSetFavorite)
{
_collectionMgr->MountSetFavorite(mountSetFavorite.MountSpellID, mountSetFavorite.IsFavorite);
}

View File

@@ -642,3 +642,25 @@ WorldPacket const* WorldPackets::Misc::DisplayGameError::Write()
return &_worldPacket;
}
WorldPacket const* WorldPackets::Misc::AccountMountUpdate::Write()
{
_worldPacket.WriteBit(IsFullUpdate);
_worldPacket << uint32(Mounts->size());
for (auto const& spell : *Mounts)
{
_worldPacket << int32(spell.first);
_worldPacket.WriteBits(spell.second, 2);
}
_worldPacket.FlushBits();
return &_worldPacket;
}
void WorldPackets::Misc::MountSetFavorite::Read()
{
_worldPacket >> MountSpellID;
IsFavorite = _worldPacket.ReadBit();
}

View File

@@ -838,6 +838,28 @@ namespace WorldPackets
Optional<int32> Arg;
Optional<int32> Arg2;
};
class AccountMountUpdate final : public ServerPacket
{
public:
AccountMountUpdate() : ServerPacket(SMSG_ACCOUNT_MOUNT_UPDATE) { }
WorldPacket const* Write() override;
bool IsFullUpdate = false;
MountContainer const* Mounts = nullptr;
};
class MountSetFavorite final : public ClientPacket
{
public:
MountSetFavorite(WorldPacket&& packet) : ClientPacket(CMSG_MOUNT_SET_FAVORITE, std::move(packet)) { }
void Read() override;
uint32 MountSpellID = 0;
bool IsFavorite = false;
};
}
}

View File

@@ -498,7 +498,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_MINIMAP_PING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMinimapPingOpcode);
DEFINE_HANDLER(CMSG_MISSILE_TRAJECTORY_COLLISION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMissileTrajectoryCollision);
DEFINE_HANDLER(CMSG_MOUNT_CLEAR_FANFARE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_MOUNT_SET_FAVORITE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_MOUNT_SET_FAVORITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSetFavorite);
DEFINE_HANDLER(CMSG_MOUNT_SPECIAL_ANIM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSpecialAnimOpcode);
DEFINE_HANDLER(CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_MOVE_CHANGE_TRANSPORT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes);
@@ -835,7 +835,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_CRITERIA_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_DATA_TIMES, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_HEIRLOOM_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_MOUNT_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_MOUNT_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_TOYS_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACHIEVEMENT_DELETED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACHIEVEMENT_EARNED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);

View File

@@ -1079,6 +1079,7 @@ public:
BATTLE_PET_SLOTS,
GLOBAL_ACCOUNT_HEIRLOOMS,
GLOBAL_REALM_CHARACTER_COUNTS,
MOUNTS,
ITEM_APPEARANCES,
ITEM_FAVORITE_APPEARANCES,
@@ -1107,6 +1108,10 @@ public:
stmt->setUInt32(0, battlenetAccountId);
ok = SetPreparedQuery(GLOBAL_ACCOUNT_HEIRLOOMS, stmt) && ok;
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_MOUNTS);
stmt->setUInt32(0, battlenetAccountId);
ok = SetPreparedQuery(MOUNTS, stmt) && ok;
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID);
stmt->setUInt32(0, accountId);
ok = SetPreparedQuery(GLOBAL_REALM_CHARACTER_COUNTS, stmt) && ok;
@@ -1152,6 +1157,7 @@ void WorldSession::InitializeSessionCallback(SQLQueryHolder* realmHolder, SQLQue
LoadTutorialsData(realmHolder->GetPreparedResult(AccountInfoQueryHolderPerRealm::TUTORIALS));
_collectionMgr->LoadAccountToys(holder->GetPreparedResult(AccountInfoQueryHolder::GLOBAL_ACCOUNT_TOYS));
_collectionMgr->LoadAccountHeirlooms(holder->GetPreparedResult(AccountInfoQueryHolder::GLOBAL_ACCOUNT_HEIRLOOMS));
_collectionMgr->LoadAccountMounts(holder->GetPreparedResult(AccountInfoQueryHolder::MOUNTS));
_collectionMgr->LoadAccountItemAppearances(holder->GetPreparedResult(AccountInfoQueryHolder::ITEM_APPEARANCES), holder->GetPreparedResult(AccountInfoQueryHolder::ITEM_FAVORITE_APPEARANCES));
if (!m_inQueue)

View File

@@ -432,6 +432,7 @@ namespace WorldPackets
class WorldTeleport;
class MountSpecial;
class SetTaxiBenchmarkMode;
class MountSetFavorite;
}
namespace Movement
@@ -1681,6 +1682,8 @@ class TC_GAME_API WorldSession
void HandleToySetFavorite(WorldPackets::Toy::ToySetFavorite& packet);
void HandleUseToy(WorldPackets::Toy::UseToy& packet);
void HandleMountSetFavorite(WorldPackets::Misc::MountSetFavorite& mountSetFavorite);
// Scenes
void HandleSceneTriggerEvent(WorldPackets::Scenes::SceneTriggerEvent& sceneTriggerEvent);
void HandleScenePlaybackComplete(WorldPackets::Scenes::ScenePlaybackComplete& scenePlaybackComplete);

View File

@@ -1938,6 +1938,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading faction change title pairs...");
sObjectMgr->LoadFactionChangeTitles();
TC_LOG_INFO("server.loading", "Loading mount definitions...");
CollectionMgr::LoadMountDefinitions();
TC_LOG_INFO("server.loading", "Loading GM bugs...");
sSupportMgr->LoadBugTickets();