aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/auth_database.sql28
-rw-r--r--sql/updates/auth/master/2022_06_09_00_auth.sql8
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.cpp3
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.h2
-rw-r--r--src/server/game/Entities/Player/CollectionMgr.cpp88
-rw-r--r--src/server/game/Entities/Player/CollectionMgr.h7
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Server/WorldSession.cpp6
-rw-r--r--src/server/game/Spells/Spell.h1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp16
11 files changed, 162 insertions, 3 deletions
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql
index bc8b79c6218..6b7c60380c8 100644
--- a/sql/base/auth_database.sql
+++ b/sql/base/auth_database.sql
@@ -384,6 +384,31 @@ LOCK TABLES `battlenet_account_toys` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `battlenet_account_transmog_illusions`
+--
+
+DROP TABLE IF EXISTS `battlenet_account_transmog_illusions`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `battlenet_account_transmog_illusions` (
+ `battlenetAccountId` int unsigned NOT NULL,
+ `blobIndex` smallint unsigned NOT NULL,
+ `illusionMask` int unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`battlenetAccountId`,`blobIndex`),
+ CONSTRAINT `battlenet_account_transmog_illusions_ibfk_1` FOREIGN KEY (`battlenetAccountId`) REFERENCES `battlenet_accounts` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `battlenet_account_transmog_illusions`
+--
+
+LOCK TABLES `battlenet_account_transmog_illusions` WRITE;
+/*!40000 ALTER TABLE `battlenet_account_transmog_illusions` DISABLE KEYS */;
+/*!40000 ALTER TABLE `battlenet_account_transmog_illusions` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `battlenet_accounts`
--
@@ -2572,7 +2597,8 @@ INSERT INTO `updates` VALUES
('2022_06_01_00_auth.sql','DCFC7EC6C52993769B568EAF87CA2DAA10359AEB','RELEASED','2022-06-02 00:52:17',0),
('2022_06_06_00_auth.sql','68D73F068598D37FD6FBC84362F1BA7BA4EC2709','RELEASED','2022-06-06 21:35:16',0),
('2022_06_07_00_auth.sql','76B4D21F13B0024445E5C0B48C630C1DF7E80966','RELEASED','2022-06-07 16:09:58',0),
-('2022_06_08_00_auth.sql','250081465C76AC9668E3F66D386CE2AAC05379E9','RELEASED','2022-06-08 10:45:01',0);
+('2022_06_08_00_auth.sql','250081465C76AC9668E3F66D386CE2AAC05379E9','RELEASED','2022-06-08 10:45:01',0),
+('2022_06_09_00_auth.sql','29C2A4209FB977373440666F00B2E04F0E095247','RELEASED','2022-06-09 18:31:38',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/auth/master/2022_06_09_00_auth.sql b/sql/updates/auth/master/2022_06_09_00_auth.sql
new file mode 100644
index 00000000000..da9ddd605af
--- /dev/null
+++ b/sql/updates/auth/master/2022_06_09_00_auth.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS `battlenet_account_transmog_illusions`;
+CREATE TABLE `battlenet_account_transmog_illusions` (
+ `battlenetAccountId` int unsigned NOT NULL,
+ `blobIndex` smallint unsigned NOT NULL,
+ `illusionMask` int unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`battlenetAccountId`,`blobIndex`),
+ CONSTRAINT `battlenet_account_transmog_illusions_ibfk_1` FOREIGN KEY (`battlenetAccountId`) REFERENCES `battlenet_accounts` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index f02ad1a4e68..95997a54d44 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -186,6 +186,9 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_BNET_ITEM_FAVORITE_APPEARANCES, "SELECT itemModifiedAppearanceId FROM battlenet_item_favorite_appearances WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_BNET_ITEM_FAVORITE_APPEARANCE, "INSERT INTO battlenet_item_favorite_appearances (battlenetAccountId, itemModifiedAppearanceId) VALUES (?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_BNET_ITEM_FAVORITE_APPEARANCE, "DELETE FROM battlenet_item_favorite_appearances WHERE battlenetAccountId = ? AND itemModifiedAppearanceId = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_SEL_BNET_TRANSMOG_ILLUSIONS, "SELECT blobIndex, illusionMask FROM battlenet_account_transmog_illusions WHERE battlenetAccountId = ? ORDER BY blobIndex DESC", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_INS_BNET_TRANSMOG_ILLUSIONS, "INSERT INTO battlenet_account_transmog_illusions (battlenetAccountId, blobIndex, illusionMask) VALUES (?, ?, ?) "
+ "ON DUPLICATE KEY UPDATE illusionMask = illusionMask | VALUES(illusionMask)", CONNECTION_ASYNC);
}
LoginDatabaseConnection::LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo)
diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h
index d46e441d961..7d3c44f1f91 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.h
+++ b/src/server/database/Database/Implementation/LoginDatabase.h
@@ -172,6 +172,8 @@ enum LoginDatabaseStatements : uint32
LOGIN_SEL_BNET_ITEM_FAVORITE_APPEARANCES,
LOGIN_INS_BNET_ITEM_FAVORITE_APPEARANCE,
LOGIN_DEL_BNET_ITEM_FAVORITE_APPEARANCE,
+ LOGIN_SEL_BNET_TRANSMOG_ILLUSIONS,
+ LOGIN_INS_BNET_TRANSMOG_ILLUSIONS,
MAX_LOGINDATABASE_STATEMENTS
};
diff --git a/src/server/game/Entities/Player/CollectionMgr.cpp b/src/server/game/Entities/Player/CollectionMgr.cpp
index c7d2966ea0f..ff77b19e6f7 100644
--- a/src/server/game/Entities/Player/CollectionMgr.cpp
+++ b/src/server/game/Entities/Player/CollectionMgr.cpp
@@ -85,7 +85,7 @@ namespace
}
}
-CollectionMgr::CollectionMgr(WorldSession* owner) : _owner(owner), _appearances(std::make_unique<boost::dynamic_bitset<uint32>>())
+CollectionMgr::CollectionMgr(WorldSession* owner) : _owner(owner), _appearances(std::make_unique<boost::dynamic_bitset<uint32>>()), _transmogIllusions(std::make_unique<boost::dynamic_bitset<uint32>>())
{
}
@@ -882,3 +882,89 @@ void CollectionMgr::SendFavoriteAppearances() const
_owner->SendPacket(accountTransmogUpdate.Write());
}
+
+void CollectionMgr::LoadTransmogIllusions()
+{
+ Player* owner = _owner->GetPlayer();
+ boost::to_block_range(*_transmogIllusions, DynamicBitsetBlockOutputIterator([owner](uint32 blockValue)
+ {
+ owner->AddIllusionBlock(blockValue);
+ }));
+}
+
+void CollectionMgr::LoadAccountTransmogIllusions(PreparedQueryResult knownTransmogIllusions)
+{
+ if (knownTransmogIllusions)
+ {
+ std::vector<uint32> blocks;
+ do
+ {
+ Field* fields = knownTransmogIllusions->Fetch();
+ uint16 blobIndex = fields[0].GetUInt16();
+ if (blobIndex >= blocks.size())
+ blocks.resize(blobIndex + 1);
+
+ blocks[blobIndex] = fields[1].GetUInt32();
+
+ } while (knownTransmogIllusions->NextRow());
+
+ _transmogIllusions->init_from_block_range(blocks.begin(), blocks.end());
+ }
+
+ // Static illusions known by every player
+ static uint16 constexpr defaultIllusions[] =
+ {
+ 3, // Lifestealing
+ 13, // Crusader
+ 22, // Striking
+ 23, // Agility
+ 34, // Hide Weapon Enchant
+ 43, // Beastslayer
+ 44, // Titanguard
+ };
+
+ for (uint16 illusionId : defaultIllusions)
+ {
+ if (_transmogIllusions->size() <= illusionId)
+ _transmogIllusions->resize(illusionId + 1);
+
+ _transmogIllusions->set(illusionId);
+ }
+}
+
+void CollectionMgr::SaveAccountTransmogIllusions(LoginDatabaseTransaction trans)
+{
+ uint16 blockIndex = 0;
+
+ boost::to_block_range(*_transmogIllusions, DynamicBitsetBlockOutputIterator([this, &blockIndex, trans](uint32 blockValue)
+ {
+ if (blockValue) // this table is only appended/bits are set (never cleared) so don't save empty blocks
+ {
+ LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_TRANSMOG_ILLUSIONS);
+ stmt->setUInt32(0, _owner->GetBattlenetAccountId());
+ stmt->setUInt16(1, blockIndex);
+ stmt->setUInt32(2, blockValue);
+ trans->Append(stmt);
+ }
+ ++blockIndex;
+ }));
+}
+
+void CollectionMgr::AddTransmogIllusion(uint16 illusionId)
+{
+ Player* owner = _owner->GetPlayer();
+ if (_transmogIllusions->size() <= illusionId)
+ {
+ std::size_t numBlocks = _transmogIllusions->num_blocks();
+ _transmogIllusions->resize(illusionId + 1);
+ numBlocks = _transmogIllusions->num_blocks() - numBlocks;
+ while (numBlocks--)
+ owner->AddIllusionBlock(0);
+ }
+
+ _transmogIllusions->set(illusionId);
+ uint32 blockIndex = illusionId / 32;
+ uint32 bitIndex = illusionId % 32;
+
+ owner->AddIllusionFlag(blockIndex, 1 << bitIndex);
+}
diff --git a/src/server/game/Entities/Player/CollectionMgr.h b/src/server/game/Entities/Player/CollectionMgr.h
index 7c3c5d9c014..7c757f0d64e 100644
--- a/src/server/game/Entities/Player/CollectionMgr.h
+++ b/src/server/game/Entities/Player/CollectionMgr.h
@@ -138,6 +138,12 @@ public:
// returns ItemAppearance::ID, not ItemModifiedAppearance::ID
std::unordered_set<uint32> GetAppearanceIds() const;
+ // Illusions
+ void LoadTransmogIllusions();
+ void LoadAccountTransmogIllusions(PreparedQueryResult knownIllusions);
+ void SaveAccountTransmogIllusions(LoginDatabaseTransaction trans);
+ void AddTransmogIllusion(uint16 illusionId);
+
enum class FavoriteAppearanceState
{
New,
@@ -161,6 +167,7 @@ private:
std::unique_ptr<boost::dynamic_bitset<uint32>> _appearances;
std::unordered_map<uint32, std::unordered_set<ObjectGuid>> _temporaryAppearances;
std::unordered_map<uint32, FavoriteAppearanceState> _favoriteAppearances;
+ std::unique_ptr<boost::dynamic_bitset<uint32>> _transmogIllusions;
};
#endif // CollectionMgr_h__
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index e35a3a80aa4..cf02d2e5e6b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -18500,6 +18500,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
GetSession()->GetCollectionMgr()->LoadHeirlooms();
GetSession()->GetCollectionMgr()->LoadMounts();
GetSession()->GetCollectionMgr()->LoadItemAppearances();
+ GetSession()->GetCollectionMgr()->LoadTransmogIllusions();
LearnSpecializationSpells();
@@ -20784,6 +20785,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
GetSession()->GetCollectionMgr()->SaveAccountHeirlooms(loginTransaction);
GetSession()->GetCollectionMgr()->SaveAccountMounts(loginTransaction);
GetSession()->GetCollectionMgr()->SaveAccountItemAppearances(loginTransaction);
+ GetSession()->GetCollectionMgr()->SaveAccountTransmogIllusions(loginTransaction);
LoginDatabasePreparedStatement* loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_LAST_PLAYER_CHARACTERS);
loginStmt->setUInt32(0, GetSession()->GetAccountId());
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index b9936e39af2..3f366b41c72 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2761,6 +2761,10 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
if (index >= 0)
RemoveDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ConditionalTransmog), uint32(index));
}
+
+ void AddIllusionBlock(uint32 blockValue) { AddDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::TransmogIllusions)) = blockValue; }
+ void AddIllusionFlag(uint32 slot, uint32 flag) { SetUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::TransmogIllusions, slot), flag); }
+
void AddSelfResSpell(int32 spellId) { AddDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::SelfResSpells)) = spellId; }
void RemoveSelfResSpell(int32 spellId)
{
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index fa92d25dc13..e3be227df53 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -1075,6 +1075,7 @@ public:
MOUNTS,
ITEM_APPEARANCES,
ITEM_FAVORITE_APPEARANCES,
+ TRANSMOG_ILLUSIONS,
MAX_QUERIES
};
@@ -1118,6 +1119,10 @@ public:
stmt->setUInt32(0, battlenetAccountId);
ok = SetPreparedQuery(ITEM_FAVORITE_APPEARANCES, stmt) && ok;
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_TRANSMOG_ILLUSIONS);
+ stmt->setUInt32(0, battlenetAccountId);
+ ok = SetPreparedQuery(TRANSMOG_ILLUSIONS, stmt) && ok;
+
return ok;
}
};
@@ -1169,6 +1174,7 @@ void WorldSession::InitializeSessionCallback(LoginDatabaseQueryHolder const& hol
_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));
+ _collectionMgr->LoadAccountTransmogIllusions(holder.GetPreparedResult(AccountInfoQueryHolder::TRANSMOG_ILLUSIONS));
if (!m_inQueue)
SendAuthResponse(ERROR_OK, false);
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 86a6404fd6d..58e39fc634b 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -402,6 +402,7 @@ class TC_GAME_API Spell
void EffectCreatePrivateConversation();
void EffectSendChatMessage();
void EffectGrantBattlePetExperience();
+ void EffectLearnTransmogIllusion();
typedef std::unordered_set<Aura*> UsedSpellMods;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 1f06b884942..dadff88a498 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -358,7 +358,7 @@ NonDefaultConstructible<SpellEffectHandlerFn> SpellEffectHandlers[TOTAL_SPELL_EF
&Spell::EffectNULL, //273 SPELL_EFFECT_CRAFT_RUNEFORGE_LEGENDARY
&Spell::EffectUnused, //274 SPELL_EFFECT_274
&Spell::EffectUnused, //275 SPELL_EFFECT_275
- &Spell::EffectNULL, //276 SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION
+ &Spell::EffectLearnTransmogIllusion, //276 SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION
&Spell::EffectNULL, //277 SPELL_EFFECT_SET_CHROMIE_TIME
&Spell::EffectNULL, //278 SPELL_EFFECT_278
&Spell::EffectNULL, //279 SPELL_EFFECT_LEARN_GARR_TALENT
@@ -5843,3 +5843,17 @@ void Spell::EffectGrantBattlePetExperience()
playerCaster->GetSession()->GetBattlePetMgr()->GrantBattlePetExperience(unitTarget->GetBattlePetCompanionGUID(), damage, BattlePets::BattlePetXpSource::SpellEffect);
}
+
+void Spell::EffectLearnTransmogIllusion()
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ Player* player = Object::ToPlayer(unitTarget);
+ if (!player)
+ return;
+
+ uint16 illusionId = effectInfo->MiscValue;
+
+ player->GetSession()->GetCollectionMgr()->AddTransmogIllusion(illusionId);
+}