aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNay <dnpd.dd@gmail.com>2012-09-05 19:01:28 +0100
committerNay <dnpd.dd@gmail.com>2012-09-05 19:01:28 +0100
commitdb819bbdbe091e97a8451bf9dc9d74b4c5899a41 (patch)
treeffc50c9d11361b4a5dc3c66e36dd6f3472d262bc
parent38dbea7583e1b6b7d666eaa53fbd753162f30697 (diff)
Core/Player: Implement server-side loading/saving of CUF profiles
CompactUnitFrames / RaidProfiles / GroupUI There are unknown fields added to DB, received and sent in packets that should be renamed
-rw-r--r--sql/base/characters_database.sql38
-rw-r--r--sql/updates/characters/2012_09_04_00_characters_character_cuf_profiles_434.sql19
-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
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.cpp6
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.h4
13 files changed, 442 insertions, 51 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 6656fe7d48c..5396b23857c 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -508,6 +508,42 @@ LOCK TABLES `character_battleground_random` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `character_cuf_profiles`
+--
+
+DROP TABLE IF EXISTS `character_cuf_profiles`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `character_cuf_profiles` (
+ `guid` int(10) unsigned NOT NULL COMMENT 'Character Guid',
+ `id` tinyint(3) unsigned NOT NULL COMMENT 'Profile Id (0-5)',
+ `name` varchar(12) NOT NULL COMMENT 'Profile Name',
+ `frameHeight` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Frame Height',
+ `frameWidth` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Frame Width',
+ `sortBy` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Frame Sort By',
+ `healthText` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Frame Health Text',
+ `boolOptions` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Many Configurable Bool Options',
+ `unk146` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk147` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk148` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk150` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ `unk152` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ `unk154` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ PRIMARY KEY (`guid`,`id`),
+ KEY `index` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `character_cuf_profiles`
+--
+
+LOCK TABLES `character_cuf_profiles` WRITE;
+/*!40000 ALTER TABLE `character_cuf_profiles` DISABLE KEYS */;
+/*!40000 ALTER TABLE `character_cuf_profiles` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `character_currency`
--
@@ -2380,4 +2416,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2012-08-08 18:51:30
+-- Dump completed on 2012-09-05 18:59:26
diff --git a/sql/updates/characters/2012_09_04_00_characters_character_cuf_profiles_434.sql b/sql/updates/characters/2012_09_04_00_characters_character_cuf_profiles_434.sql
new file mode 100644
index 00000000000..df0c825e67a
--- /dev/null
+++ b/sql/updates/characters/2012_09_04_00_characters_character_cuf_profiles_434.sql
@@ -0,0 +1,19 @@
+DROP TABLE IF EXISTS `character_cuf_profiles`;
+CREATE TABLE IF NOT EXISTS `character_cuf_profiles` (
+ `guid` int(10) unsigned NOT NULL COMMENT 'Character Guid',
+ `id` tinyint(3) unsigned NOT NULL COMMENT 'Profile Id (0-5)',
+ `name` varchar(12) NOT NULL COMMENT 'Profile Name',
+ `frameHeight` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Frame Height',
+ `frameWidth` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Frame Width',
+ `sortBy` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Frame Sort By',
+ `healthText` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Frame Health Text',
+ `boolOptions` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Many Configurable Bool Options',
+ `unk146` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk147` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk148` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk150` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ `unk152` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ `unk154` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ PRIMARY KEY (`guid`,`id`),
+ KEY `index` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
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();
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index aff2083ca5f..286f2c20811 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -567,7 +567,13 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND slot = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_UPD_CHAR_LIST_SLOT, "UPDATE characters SET slot = ? WHERE guid = ?", CONNECTION_ASYNC);
+ // Void Storage
PREPARE_STATEMENT(CHAR_SEL_CHAR_VOID_STORAGE, "SELECT itemId, itemEntry, slot, creatorGuid, randomProperty, suffixFactor FROM character_void_storage WHERE playerGuid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_REP_CHAR_VOID_STORAGE_ITEM, "REPLACE INTO character_void_storage (itemId, playerGuid, itemEntry, slot, creatorGuid, randomProperty, suffixFactor) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT, "DELETE FROM character_void_storage WHERE slot = ? AND playerGuid = ?", CONNECTION_ASYNC);
+
+ // CompactUnitFrame profiles
+ PREPARE_STATEMENT(CHAR_SEL_CHAR_CUF_PROFILES, "SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_REP_CHAR_CUF_PROFILES, "REPLACE INTO character_cuf_profiles (guid, id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_DEL_CHAR_CUF_PROFILES, "DELETE FROM character_cuf_profiles WHERE guid = ? and id = ?", CONNECTION_ASYNC);
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index 0634e226d5e..c134856a74f 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -533,6 +533,10 @@ enum CharacterDatabaseStatements
CHAR_REP_CHAR_VOID_STORAGE_ITEM,
CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT,
+ CHAR_SEL_CHAR_CUF_PROFILES,
+ CHAR_REP_CHAR_CUF_PROFILES,
+ CHAR_DEL_CHAR_CUF_PROFILES,
+
MAX_CHARACTERDATABASE_STATEMENTS,
};