aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/Battlefield/BattlefieldHandler.cpp22
-rw-r--r--src/server/game/Entities/Player/Player.cpp85
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h105
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp4
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp6
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp194
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp4
-rwxr-xr-xsrc/server/game/Server/WorldSession.h4
9 files changed, 376 insertions, 50 deletions
diff --git a/src/server/game/Battlefield/BattlefieldHandler.cpp b/src/server/game/Battlefield/BattlefieldHandler.cpp
index f16237b6e31..66285fe1b04 100644
--- a/src/server/game/Battlefield/BattlefieldHandler.cpp
+++ b/src/server/game/Battlefield/BattlefieldHandler.cpp
@@ -112,7 +112,7 @@ void WorldSession::SendBfQueueInviteResponse(uint64 guid, uint32 ZoneId, bool Ca
ObjectGuid guidBytes = guid;
WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 16);
-
+
data.WriteBit(guidBytes[1]);
data.WriteBit(guidBytes[6]);
data.WriteBit(guidBytes[5]);
@@ -121,32 +121,32 @@ void WorldSession::SendBfQueueInviteResponse(uint64 guid, uint32 ZoneId, bool Ca
data.WriteBit(guidBytes[0]);
data.WriteBit(!hasSecondGuid);
data.WriteBit(guidBytes[4]);
-
- // if (hasSecondGuid) 7 3 0 4 2 6 1 5
-
+
+ // if (hasSecondGuid) 7 3 0 4 2 6 1 5
+
data.WriteBit(guidBytes[3]);
data.WriteBit(guidBytes[2]);
-
+
// if (hasSecondGuid) 2 5 3 0 4 6 1 7
data.FlushBits();
data << uint8(CanQueue); // Accepted
-
+
data.WriteByteSeq(guidBytes[1]);
data.WriteByteSeq(guidBytes[3]);
data.WriteByteSeq(guidBytes[6]);
data.WriteByteSeq(guidBytes[7]);
data.WriteByteSeq(guidBytes[0]);
-
+
data << uint8(warmup);
-
+
data.WriteByteSeq(guidBytes[2]);
data.WriteByteSeq(guidBytes[4]);
data.WriteByteSeq(guidBytes[5]);
-
+
data << uint32(ZoneId);
-
+
SendPacket(&data);
}
@@ -157,7 +157,7 @@ void WorldSession::SendBfEntered(uint64 guid)
ObjectGuid guidBytes = guid;
WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTERED, 11);
-
+
data.WriteBit(0); // unk
data.WriteBit(isAFK); // Clear AFK
data.WriteBit(guidBytes[1]);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index bef557e0b8f..8ac3ba358dd 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -849,7 +849,8 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep
_activeCheats = CHEAT_NONE;
- memset(_voidStorageItems, 0, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*));
+ memset(_voidStorageItems, NULL, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*));
+ memset(_CUFProfiles, NULL, MAX_CUF_PROFILES * sizeof(CUFProfile*));
}
Player::~Player()
@@ -884,6 +885,9 @@ Player::~Player()
for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
delete _voidStorageItems[i];
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ delete _CUFProfiles[i];
+
sWorld->DecreasePlayerCount();
}
@@ -17325,9 +17329,46 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
_LoadEquipmentSets(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS));
+ _LoadCUFProfiles(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES));
+
return true;
}
+void Player::_LoadCUFProfiles(PreparedQueryResult result)
+{
+ if (!result)
+ return;
+
+ do
+ {
+ // SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?
+ Field* fields = result->Fetch();
+
+ uint8 id = fields[0].GetUInt8();
+ std::string name = fields[1].GetString();
+ uint16 frameHeight = fields[2].GetUInt16();
+ uint16 frameWidth = fields[3].GetUInt16();
+ uint8 sortBy = fields[4].GetUInt8();
+ uint8 healthText = fields[5].GetUInt8();
+ uint32 boolOptions = fields[6].GetUInt32();
+ uint8 unk146 = fields[7].GetUInt8();
+ uint8 unk147 = fields[8].GetUInt8();
+ uint8 unk148 = fields[9].GetUInt8();
+ uint16 unk150 = fields[10].GetUInt16();
+ uint16 unk152 = fields[11].GetUInt16();
+ uint16 unk154 = fields[12].GetUInt16();
+
+ if (id > MAX_CUF_PROFILES)
+ {
+ sLog->outError(LOG_FILTER_PLAYER, "Player::_LoadCUFProfiles - Player (GUID: %u, name: %s) has an CUF profile with invalid id (id: %u), max is %i.", GetGUIDLow(), GetName(), id, MAX_CUF_PROFILES);
+ continue;
+ }
+
+ _CUFProfiles[id] = new CUFProfile(name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154);
+ }
+ while (result->NextRow());
+}
+
bool Player::isAllowedToLoot(const Creature* creature)
{
if (!creature->isDead() || !creature->IsDamageEnoughForLootingAndReward())
@@ -18941,6 +18982,7 @@ void Player::SaveToDB(bool create /*=false*/)
_SaveGlyphs(trans);
_SaveInstanceTimeRestrictions(trans);
_SaveCurrency(trans);
+ _SaveCUFProfiles(trans);
// check if stats should only be saved on logout
// save stats can be out of transaction
@@ -19226,6 +19268,45 @@ void Player::_SaveVoidStorage(SQLTransaction& trans)
}
}
+
+void Player::_SaveCUFProfiles(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = NULL;
+ uint32 lowGuid = GetGUIDLow();
+
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ {
+ if (!_CUFProfiles[i]) // unused profile
+ {
+ // DELETE FROM character_cuf_profiles WHERE guid = ? and id = ?
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ stmt->setUInt8(1, i);
+ }
+ else
+ {
+ // REPLACE INTO character_cuf_profiles (guid, id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ stmt->setUInt8(1, i);
+ stmt->setString(2, _CUFProfiles[i]->ProfileName);
+ stmt->setUInt16(3, _CUFProfiles[i]->FrameHeight);
+ stmt->setUInt16(4, _CUFProfiles[i]->FrameWidth);
+ stmt->setUInt8(5, _CUFProfiles[i]->SortBy);
+ stmt->setUInt8(6, _CUFProfiles[i]->HealthText);
+ stmt->setUInt32(7, _CUFProfiles[i]->BoolOptions.to_ulong()); // 24 of 31 fields used, fits in an int
+ stmt->setUInt8(8, _CUFProfiles[i]->Unk146);
+ stmt->setUInt8(9, _CUFProfiles[i]->Unk147);
+ stmt->setUInt8(10, _CUFProfiles[i]->Unk148);
+ stmt->setUInt16(11, _CUFProfiles[i]->Unk150);
+ stmt->setUInt16(12, _CUFProfiles[i]->Unk152);
+ stmt->setUInt16(13, _CUFProfiles[i]->Unk154);
+ }
+
+ trans->Append(stmt);
+ }
+}
+
void Player::_SaveMail(SQLTransaction& trans)
{
if (!m_mailsLoaded)
@@ -22358,6 +22439,8 @@ void Player::SendInitialPacketsAfterAddToMap()
ResetTimeSync();
SendTimeSync();
+ Player::GetSession()->SendLoadCUFProfiles();
+
CastSpell(this, 836, true); // LOGINEFFECT
// set some aura effects that send packet to player client after add player to map
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index bfa70e611e6..89c56165390 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -19,6 +19,7 @@
#ifndef _PLAYER_H
#define _PLAYER_H
+#include <bitset>
#include "AchievementMgr.h"
#include "Battleground.h"
#include "Bag.h"
@@ -147,6 +148,94 @@ typedef UNORDERED_MAP<uint32, PlayerCurrency> PlayerCurrenciesMap;
typedef std::list<uint64> WhisperListContainer;
+/// Maximum number of CompactUnitFrames profiles
+#define MAX_CUF_PROFILES 5
+
+/// Bit index used in the many bool options of CompactUnitFrames
+enum CUFBoolOptions
+{
+ CUF_KEEP_GROUPS_TOGETHER,
+ CUF_DISPLAY_PETS,
+ CUF_DISPLAY_MAIN_TANK_AND_ASSIST,
+ CUF_DISPLAY_HEAL_PREDICTION,
+ CUF_DISPLAY_AGGRO_HIGHLIGHT,
+ CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS,
+ CUF_DISPLAY_POWER_BAR,
+ CUF_DISPLAY_BORDER,
+ CUF_USE_CLASS_COLORS,
+ CUF_DISPLAY_NON_BOSS_DEBUFFS,
+ CUF_DISPLAY_HORIZONTAL_GROUPS,
+ CUF_LOCKED,
+ CUF_SHOWN,
+ CUF_AUTO_ACTIVATE_2_PLAYERS,
+ CUF_AUTO_ACTIVATE_3_PLAYERS,
+ CUF_AUTO_ACTIVATE_5_PLAYERS,
+ CUF_AUTO_ACTIVATE_10_PLAYERS,
+ CUF_AUTO_ACTIVATE_15_PLAYERS,
+ CUF_AUTO_ACTIVATE_25_PLAYERS,
+ CUF_AUTO_ACTIVATE_40_PLAYERS,
+ CUF_AUTO_ACTIVATE_SPEC_1,
+ CUF_AUTO_ACTIVATE_SPEC_2,
+ CUF_AUTO_ACTIVATE_PVP,
+ CUF_AUTO_ACTIVATE_PVE,
+ CUF_UNK_145,
+ CUF_UNK_156,
+ CUF_UNK_157,
+
+ CUF_BOOL_OPTIONS_COUNT,
+};
+
+/// Represents a CompactUnitFrame profile
+struct CUFProfile
+{
+ CUFProfile() : ProfileName(), BoolOptions() // might want to change default value for options
+ {
+ FrameHeight = 0;
+ FrameWidth = 0;
+ SortBy = 0;
+ HealthText = 0;
+ Unk146 = 0;
+ Unk147 = 0;
+ Unk148 = 0;
+ Unk150 = 0;
+ Unk152 = 0;
+ Unk154 = 0;
+ }
+
+ CUFProfile(const std::string& name, uint16 frameHeight, uint16 frameWidth, uint8 sortBy, uint8 healthText, uint32 boolOptions,
+ uint8 unk146, uint8 unk147, uint8 unk148, uint16 unk150, uint16 unk152, uint16 unk154)
+ : ProfileName(name), BoolOptions((int)boolOptions)
+ {
+ FrameHeight = frameHeight;
+ FrameWidth = frameWidth;
+ SortBy = sortBy;
+ HealthText = healthText;
+ Unk146 = unk146;
+ Unk147 = unk147;
+ Unk148 = unk148;
+ Unk150 = Unk150;
+ Unk152 = unk152;
+ Unk154 = unk154;
+ }
+
+ std::string ProfileName;
+ uint16 FrameHeight;
+ uint16 FrameWidth;
+ uint8 SortBy;
+ uint8 HealthText;
+
+ uint8 Unk146;
+ uint8 Unk147;
+ uint8 Unk148;
+ uint16 Unk150;
+ uint16 Unk152;
+ uint16 Unk154;
+
+ std::bitset<CUF_BOOL_OPTIONS_COUNT> BoolOptions;
+
+ // More fields can be added to BoolOptions without changing DB schema (up to 31, currently 24)
+};
+
struct SpellCooldown
{
time_t end;
@@ -793,6 +882,7 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOADSEASONALQUESTSTATUS = 31,
PLAYER_LOGIN_QUERY_LOADVOIDSTORAGE = 32,
PLAYER_LOGIN_QUERY_LOADCURRENCY = 33,
+ PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES = 34,
MAX_PLAYER_LOGIN_QUERY,
};
@@ -1577,6 +1667,17 @@ class Player : public Unit, public GridObject<Player>
void AddTimedQuest(uint32 quest_id) { m_timedquests.insert(quest_id); }
void RemoveTimedQuest(uint32 quest_id) { m_timedquests.erase(quest_id); }
+ void SaveCUFProfile(uint8 id, CUFProfile* profile) { delete _CUFProfiles[id]; _CUFProfiles[id] = profile; } ///> Replaces a CUF profile at position 0-4
+ CUFProfile* GetCUFProfile(uint8 id) const { return _CUFProfiles[id]; } ///> Retrieves a CUF profile at position 0-4
+ uint8 GetCUFProfilesCount() const
+ {
+ uint8 count = 0;
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ if (_CUFProfiles[i])
+ ++count;
+ return count;
+ }
+
/*********************************************************/
/*** LOAD SYSTEM ***/
/*********************************************************/
@@ -2712,6 +2813,7 @@ class Player : public Unit, public GridObject<Player>
void _LoadTalents(PreparedQueryResult result);
void _LoadInstanceTimeRestrictions(PreparedQueryResult result);
void _LoadCurrency(PreparedQueryResult result);
+ void _LoadCUFProfiles(PreparedQueryResult result);
/*********************************************************/
/*** SAVE SYSTEM ***/
@@ -2735,6 +2837,7 @@ class Player : public Unit, public GridObject<Player>
void _SaveStats(SQLTransaction& trans);
void _SaveInstanceTimeRestrictions(SQLTransaction& trans);
void _SaveCurrency(SQLTransaction& trans);
+ void _SaveCUFProfiles(SQLTransaction& trans);
/*********************************************************/
/*** ENVIRONMENTAL SYSTEM ***/
@@ -2898,6 +3001,8 @@ class Player : public Unit, public GridObject<Player>
uint8 m_grantableLevels;
+ CUFProfile* _CUFProfiles[MAX_CUF_PROFILES];
+
private:
// internal common parts for CanStore/StoreItem functions
InventoryResult CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemTemplate const* pProto, uint32& count, bool swap, Item* pSrcItem) const;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 7e1195463a2..6609ef55494 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -166,6 +166,10 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BGDATA);
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADBGDATA, stmt);
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 1d6cbf61c68..3549e56fb88 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -513,7 +513,7 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData)
void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SET_ROLES");
-
+
uint32 newRole;
ObjectGuid guid1; // Assigner GUID
ObjectGuid guid2; // Target GUID
@@ -539,7 +539,7 @@ void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData)
recvData.ReadByteSeq(guid2[5]);
recvData.ReadByteSeq(guid2[2]);
recvData.ReadByteSeq(guid2[7]);
-
+
WorldPacket data(SMSG_GROUP_SET_ROLE, 24);
data.WriteBit(guid1[1]);
@@ -558,7 +558,7 @@ void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData)
data.WriteBit(guid1[6]);
data.WriteBit(guid2[1]);
data.WriteBit(guid1[0]);
-
+
data.WriteByteSeq(guid1[7]);
data.WriteByteSeq(guid2[3]);
data.WriteByteSeq(guid1[6]);
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index 5b5f83719e3..e127a5ba658 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -775,7 +775,7 @@ void WorldSession::SendListInventory(uint64 vendorGuid)
}
int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
-
+
if (int32 priceMod = _player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES))
price -= CalculatePctN(price, priceMod);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index c6e0515a8ed..6499ead3685 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1940,35 +1940,165 @@ void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
HandleMovementOpcodes(recvPacket);
}
}
- void WorldSession::HandleViolenceLevel(WorldPacket& recvPacket)
- {
- uint8 violenceLevel;
- recvPacket >> violenceLevel;
-
- // do something?
- }
-
- void WorldSession::HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket)
- {
- ObjectGuid guid;
- guid[6] = recvPacket.ReadBit();
- guid[7] = recvPacket.ReadBit();
- guid[4] = recvPacket.ReadBit();
- guid[0] = recvPacket.ReadBit();
- guid[1] = recvPacket.ReadBit();
- guid[5] = recvPacket.ReadBit();
- guid[3] = recvPacket.ReadBit();
- guid[2] = recvPacket.ReadBit();
-
- recvPacket.ReadByteSeq(guid[6]);
- recvPacket.ReadByteSeq(guid[7]);
- recvPacket.ReadByteSeq(guid[2]);
- recvPacket.ReadByteSeq(guid[3]);
- recvPacket.ReadByteSeq(guid[1]);
- recvPacket.ReadByteSeq(guid[4]);
- recvPacket.ReadByteSeq(guid[0]);
- recvPacket.ReadByteSeq(guid[5]);
-
- WorldObject* obj = ObjectAccessor::GetWorldObject(*GetPlayer(), guid);
- sLog->outError(LOG_FILTER_NETWORKIO, "Object update failed for object "UI64FMTD" (%s) for player %s (%u)", uint64(guid), obj ? obj->GetName() : "object-not-found", GetPlayerName().c_str(), GetGuidLow());
- }
+
+void WorldSession::HandleViolenceLevel(WorldPacket& recvPacket)
+{
+ uint8 violenceLevel;
+ recvPacket >> violenceLevel;
+
+ // do something?
+}
+
+void WorldSession::HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket)
+{
+ ObjectGuid guid;
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[5]);
+
+ WorldObject* obj = ObjectAccessor::GetWorldObject(*GetPlayer(), guid);
+ sLog->outError(LOG_FILTER_NETWORKIO, "Object update failed for object "UI64FMTD" (%s) for player %s (%u)", uint64(guid), obj ? obj->GetName() : "object-not-found", GetPlayerName().c_str(), GetGuidLow());
+}
+
+void WorldSession::HandleSaveCUFProfiles(WorldPacket& recvPacket)
+{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SAVE_CUF_PROFILES");
+
+ uint8 count = (uint8)recvPacket.ReadBits(20);
+
+ if (count > MAX_CUF_PROFILES)
+ {
+ sLog->outError(LOG_FILTER_PLAYER, "HandleSaveCUFProfiles - %s tried to save more than %i CUF profiles. Hacking attempt?", GetPlayerName(), MAX_CUF_PROFILES);
+ recvPacket.rfinish();
+ return;
+ }
+
+ CUFProfile* profiles[MAX_CUF_PROFILES];
+ uint8 strlens[MAX_CUF_PROFILES];
+
+ for (uint8 i = 0; i < count; ++i)
+ {
+ profiles[i] = new CUFProfile;
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_2 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_10_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_157 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_HEAL_PREDICTION , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_1 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVP , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_POWER_BAR , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_15_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_40_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_PETS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_5_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS, recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_2_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_156 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_NON_BOSS_DEBUFFS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_MAIN_TANK_AND_ASSIST , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_AGGRO_HIGHLIGHT , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_3_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_BORDER , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_USE_CLASS_COLORS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_145 , recvPacket.ReadBit());
+ strlens[i] = (uint8)recvPacket.ReadBits(8);
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVE , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_HORIZONTAL_GROUPS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_25_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_KEEP_GROUPS_TOGETHER , recvPacket.ReadBit());
+ }
+
+ for (uint8 i = 0; i < count; ++i)
+ {
+ recvPacket >> profiles[i]->Unk146;
+ profiles[i]->ProfileName = recvPacket.ReadString(strlens[i]);
+ recvPacket >> profiles[i]->Unk152;
+ recvPacket >> profiles[i]->FrameHeight;
+ recvPacket >> profiles[i]->FrameWidth;
+ recvPacket >> profiles[i]->Unk150;
+ recvPacket >> profiles[i]->HealthText;
+ recvPacket >> profiles[i]->Unk147;
+ recvPacket >> profiles[i]->SortBy;
+ recvPacket >> profiles[i]->Unk154;
+ recvPacket >> profiles[i]->Unk148;
+
+ GetPlayer()->SaveCUFProfile(i, profiles[i]);
+ }
+
+ for (uint8 i = count; i < MAX_CUF_PROFILES; ++i)
+ GetPlayer()->SaveCUFProfile(i, NULL);
+}
+
+void WorldSession::SendLoadCUFProfiles()
+{
+ Player* player = GetPlayer();
+
+ uint8 count = player->GetCUFProfilesCount();
+
+ ByteBuffer byteBuffer(25 * count);
+ WorldPacket data(SMSG_LOAD_CUF_PROFILES, 5 * count + 25 * count);
+
+ data.WriteBits(count, 20);
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ {
+ CUFProfile* profile = player->GetCUFProfile(i);
+ if (!profile)
+ continue;
+
+ data.WriteBit(profile->BoolOptions[CUF_UNK_157]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_10_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_5_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_25_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HEAL_PREDICTION]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVE]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HORIZONTAL_GROUPS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_40_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_3_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_AGGRO_HIGHLIGHT]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_BORDER]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_2_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_NON_BOSS_DEBUFFS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_MAIN_TANK_AND_ASSIST]);
+ data.WriteBit(profile->BoolOptions[CUF_UNK_156]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_2]);
+ data.WriteBit(profile->BoolOptions[CUF_USE_CLASS_COLORS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_POWER_BAR]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_1]);
+ data.WriteBits(profile->ProfileName.size(), 8);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS]);
+ data.WriteBit(profile->BoolOptions[CUF_KEEP_GROUPS_TOGETHER]);
+ data.WriteBit(profile->BoolOptions[CUF_UNK_145]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_15_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_PETS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVP]);
+
+ byteBuffer << uint16(profile->Unk154);
+ byteBuffer << uint16(profile->FrameHeight);
+ byteBuffer << uint16(profile->Unk152);
+ byteBuffer << uint8(profile->Unk147);
+ byteBuffer << uint16(profile->Unk150);
+ byteBuffer << uint8(profile->Unk146);
+ byteBuffer << uint8(profile->HealthText);
+ byteBuffer << uint8(profile->SortBy);
+ byteBuffer << uint16(profile->FrameWidth);
+ byteBuffer << uint8(profile->Unk148);
+ byteBuffer.WriteString(profile->ProfileName);
+ }
+
+ data.FlushBits();
+ data.append(byteBuffer);
+ SendPacket(&data);
+}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 6eeb3661028..f25f8d18b0d 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -470,7 +470,7 @@ void InitOpcodes()
DEFINE_OPCODE_HANDLER(CMSG_RESURRECT_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResurrectResponseOpcode );
DEFINE_OPCODE_HANDLER(CMSG_RETURN_TO_GRAVEYARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReturnToGraveyard );
DEFINE_OPCODE_HANDLER(CMSG_ROLE_POLL_BEGIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
- DEFINE_OPCODE_HANDLER(CMSG_SAVE_CUF_PROFILES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SAVE_CUF_PROFILES, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSaveCUFProfiles );
DEFINE_OPCODE_HANDLER(CMSG_SELF_RES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSelfResOpcode );
DEFINE_OPCODE_HANDLER(CMSG_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSellItemOpcode );
DEFINE_OPCODE_HANDLER(CMSG_SEND_MAIL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSendMail );
@@ -948,7 +948,7 @@ void InitOpcodes()
DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_POST_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_LIST_INVENTORY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
- DEFINE_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_LOGIN_SETTIMESPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_LOGIN_VERIFY_WORLD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_LOGOUT_CANCEL_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 0ac7884efe2..6ff03b9c838 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -968,6 +968,10 @@ class WorldSession
void HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket);
int32 HandleEnableNagleAlgorithm();
+ // Compact Unit Frames (4.x)
+ void HandleSaveCUFProfiles(WorldPacket& recvPacket);
+ void SendLoadCUFProfiles();
+
private:
void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();