Core/Transmog: Update transmog system to 12.0
This commit is contained in:
@@ -459,6 +459,30 @@ LOCK TABLES `battlenet_account_transmog_illusions` WRITE;
|
||||
/*!40000 ALTER TABLE `battlenet_account_transmog_illusions` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `battlenet_account_transmog_outfits`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_account_transmog_outfits`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `battlenet_account_transmog_outfits` (
|
||||
`battlenetAccountId` int unsigned NOT NULL,
|
||||
`transmogOutfitId` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`battlenetAccountId`,`blobIndex`),
|
||||
CONSTRAINT `fk_battlenet_account_transmog_outfits` 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_outfits`
|
||||
--
|
||||
|
||||
LOCK TABLES `battlenet_account_transmog_outfits` WRITE;
|
||||
/*!40000 ALTER TABLE `battlenet_account_transmog_outfits` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `battlenet_account_transmog_outfits` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `battlenet_account_warband_scenes`
|
||||
--
|
||||
@@ -4147,7 +4171,8 @@ INSERT INTO `updates` VALUES
|
||||
('2026_03_10_00_auth.sql','4BB4EBC719F80F7BEA667E6DA49815B358956FEA','RELEASED','2026-03-10 20:42:13',0),
|
||||
('2026_03_14_00_auth.sql','4CE4AF3D9E1BF173832B25F4D1A730A93ED016FA','RELEASED','2026-03-14 12:03:14',0),
|
||||
('2026_03_18_00_auth.sql','7A755DADF9AAC9016FD01B26ACEC714FAB5E3269','RELEASED','2026-03-18 12:36:48',0),
|
||||
('2026_03_20_00_auth.sql','9083386953291DA3D0634E90D40863F7625FF37E','RELEASED','2026-03-20 01:11:00',0);
|
||||
('2026_03_20_00_auth.sql','9083386953291DA3D0634E90D40863F7625FF37E','RELEASED','2026-03-20 01:11:00',0),
|
||||
('2026_03_21_00_auth.sql','6D47EFD7FBCD159F5BC5B5A6020E61824280E92A','RELEASED','2026-03-21 00:08:26',0);
|
||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -1891,6 +1891,89 @@ LOCK TABLES `character_trait_entry` WRITE;
|
||||
/*!40000 ALTER TABLE `character_trait_entry` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_transmog_outfit`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `character_transmog_outfit`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `character_transmog_outfit` (
|
||||
`guid` bigint NOT NULL,
|
||||
`transmogOutfitId` int NOT NULL,
|
||||
`name` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`icon` int NOT NULL,
|
||||
`situationsEnabled` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`guid`,`transmogOutfitId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `character_transmog_outfit`
|
||||
--
|
||||
|
||||
LOCK TABLES `character_transmog_outfit` WRITE;
|
||||
/*!40000 ALTER TABLE `character_transmog_outfit` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `character_transmog_outfit` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_transmog_outfit_situation`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `character_transmog_outfit_situation`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `character_transmog_outfit_situation` (
|
||||
`guid` bigint NOT NULL,
|
||||
`transmogOutfitId` int NOT NULL,
|
||||
`situationID` int NOT NULL,
|
||||
`specID` int NOT NULL,
|
||||
`loadoutID` int NOT NULL,
|
||||
`equipmentSetID` int NOT NULL,
|
||||
PRIMARY KEY (`guid`,`transmogOutfitId`,`situationID`,`specID`,`loadoutID`,`equipmentSetID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `character_transmog_outfit_situation`
|
||||
--
|
||||
|
||||
LOCK TABLES `character_transmog_outfit_situation` WRITE;
|
||||
/*!40000 ALTER TABLE `character_transmog_outfit_situation` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `character_transmog_outfit_situation` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_transmog_outfit_slot`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `character_transmog_outfit_slot`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `character_transmog_outfit_slot` (
|
||||
`guid` bigint NOT NULL,
|
||||
`transmogOutfitId` int NOT NULL,
|
||||
`slot` tinyint NOT NULL,
|
||||
`slotOption` tinyint NOT NULL,
|
||||
`itemModifiedAppearanceID` int NOT NULL,
|
||||
`appearanceDisplayType` tinyint NOT NULL,
|
||||
`spellItemEnchantmentID` int NOT NULL,
|
||||
`illusionDisplayType` tinyint NOT NULL,
|
||||
`flags` int NOT NULL,
|
||||
PRIMARY KEY (`guid`,`transmogOutfitId`,`slot`,`slotOption`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `character_transmog_outfit_slot`
|
||||
--
|
||||
|
||||
LOCK TABLES `character_transmog_outfit_slot` WRITE;
|
||||
/*!40000 ALTER TABLE `character_transmog_outfit_slot` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `character_transmog_outfit_slot` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_transmog_outfits`
|
||||
--
|
||||
@@ -2043,6 +2126,8 @@ CREATE TABLE `characters` (
|
||||
`personalTabardBorderStyle` int NOT NULL DEFAULT '-1',
|
||||
`personalTabardBorderColor` int NOT NULL DEFAULT '-1',
|
||||
`personalTabardBackgroundColor` int NOT NULL DEFAULT '-1',
|
||||
`transmogOutfitEquippedId` int NOT NULL DEFAULT '2',
|
||||
`transmogOutfitLocked` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`guid`),
|
||||
UNIQUE KEY `idx_name` (`name`),
|
||||
KEY `idx_account` (`account`),
|
||||
@@ -3832,7 +3917,8 @@ INSERT INTO `updates` VALUES
|
||||
('2025_11_25_00_characters.sql','A0C04B2404B1832421402F78436DDC4AA18EBAD8','ARCHIVED','2025-11-25 22:28:32',0),
|
||||
('2026_01_14_00_characters.sql','FF5D889A41BBD9F9827489DEC08BCA9DB457933E','ARCHIVED','2026-01-14 23:40:33',0),
|
||||
('2026_01_28_00_characters.sql','807B6622970E81089806C3B45C6C7A32EF531BCA','ARCHIVED','2026-01-25 21:53:51',0),
|
||||
('2026_02_06_00_characters.sql','90735F4481A137E79B8371F291008CF6051657AC','ARCHIVED','2026-02-06 12:45:48',0);
|
||||
('2026_02_06_00_characters.sql','90735F4481A137E79B8371F291008CF6051657AC','ARCHIVED','2026-02-06 12:45:48',0),
|
||||
('2026_03_21_00_characters.sql','87963F4E341B195D4B4C4514A3119092DF127431','RELEASED','2026-03-21 00:42:13',0);
|
||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--
|
||||
-- Table structure for table `battlenet_account_transmog_outfits`
|
||||
--
|
||||
DROP TABLE IF EXISTS `battlenet_account_transmog_outfits`;
|
||||
CREATE TABLE `battlenet_account_transmog_outfits` (
|
||||
`battlenetAccountId` int unsigned NOT NULL,
|
||||
`transmogOutfitId` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`battlenetAccountId`,`transmogOutfitId`),
|
||||
CONSTRAINT `fk_battlenet_account_transmog_outfits` FOREIGN KEY (`battlenetAccountId`) REFERENCES `battlenet_accounts` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -0,0 +1,47 @@
|
||||
ALTER TABLE `characters`
|
||||
ADD `transmogOutfitEquippedId` int NOT NULL DEFAULT 2 AFTER `personalTabardBackgroundColor`,
|
||||
ADD `transmogOutfitLocked` tinyint(1) NOT NULL DEFAULT 0 AFTER `transmogOutfitEquippedId`;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_transmog_outfit`
|
||||
--
|
||||
DROP TABLE IF EXISTS `character_transmog_outfit`;
|
||||
CREATE TABLE `character_transmog_outfit` (
|
||||
`guid` bigint NOT NULL,
|
||||
`transmogOutfitId` int NOT NULL,
|
||||
`name` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`icon` int NOT NULL,
|
||||
`situationsEnabled` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`guid`,`transmogOutfitId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_transmog_outfit_situation`
|
||||
--
|
||||
DROP TABLE IF EXISTS `character_transmog_outfit_situation`;
|
||||
CREATE TABLE `character_transmog_outfit_situation` (
|
||||
`guid` bigint NOT NULL,
|
||||
`transmogOutfitId` int NOT NULL,
|
||||
`situationID` int NOT NULL,
|
||||
`specID` int NOT NULL,
|
||||
`loadoutID` int NOT NULL,
|
||||
`equipmentSetID` int NOT NULL,
|
||||
PRIMARY KEY (`guid`,`transmogOutfitId`,`situationID`,`specID`,`loadoutID`,`equipmentSetID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_transmog_outfit_slot`
|
||||
--
|
||||
DROP TABLE IF EXISTS `character_transmog_outfit_slot`;
|
||||
CREATE TABLE `character_transmog_outfit_slot` (
|
||||
`guid` bigint NOT NULL,
|
||||
`transmogOutfitId` int NOT NULL,
|
||||
`slot` tinyint NOT NULL,
|
||||
`slotOption` tinyint NOT NULL,
|
||||
`itemModifiedAppearanceID` int NOT NULL,
|
||||
`appearanceDisplayType` tinyint NOT NULL,
|
||||
`spellItemEnchantmentID` int NOT NULL,
|
||||
`illusionDisplayType` tinyint NOT NULL,
|
||||
`flags` int NOT NULL,
|
||||
PRIMARY KEY (`guid`,`transmogOutfitId`,`slot`,`slotOption`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -0,0 +1,190 @@
|
||||
--
|
||||
-- Table structure for table `transmog_outfit_entry`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_outfit_entry`;
|
||||
CREATE TABLE `transmog_outfit_entry` (
|
||||
`Cost` bigint unsigned NOT NULL DEFAULT '0',
|
||||
`Name` text,
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`OrderIndex` int NOT NULL DEFAULT '0',
|
||||
`Source` tinyint unsigned NOT NULL DEFAULT '0',
|
||||
`Flags` int NOT NULL DEFAULT '0',
|
||||
`SetType` tinyint unsigned NOT NULL DEFAULT '0',
|
||||
`OverrideCostModifier` float NOT NULL DEFAULT '0',
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_outfit_entry_locale`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_outfit_entry_locale`;
|
||||
CREATE TABLE `transmog_outfit_entry_locale` (
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`locale` varchar(4) NOT NULL,
|
||||
`Name_lang` text,
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`locale`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST COLUMNS(locale)
|
||||
(PARTITION deDE VALUES IN ('deDE') ENGINE = InnoDB,
|
||||
PARTITION esES VALUES IN ('esES') ENGINE = InnoDB,
|
||||
PARTITION esMX VALUES IN ('esMX') ENGINE = InnoDB,
|
||||
PARTITION frFR VALUES IN ('frFR') ENGINE = InnoDB,
|
||||
PARTITION itIT VALUES IN ('itIT') ENGINE = InnoDB,
|
||||
PARTITION koKR VALUES IN ('koKR') ENGINE = InnoDB,
|
||||
PARTITION ptBR VALUES IN ('ptBR') ENGINE = InnoDB,
|
||||
PARTITION ruRU VALUES IN ('ruRU') ENGINE = InnoDB,
|
||||
PARTITION zhCN VALUES IN ('zhCN') ENGINE = InnoDB,
|
||||
PARTITION zhTW VALUES IN ('zhTW') ENGINE = InnoDB);
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_outfit_slot_info`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_outfit_slot_info`;
|
||||
CREATE TABLE `transmog_outfit_slot_info` (
|
||||
`InventorySlotName` text,
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`TransmogOutfitSlotEnum` tinyint NOT NULL DEFAULT '0',
|
||||
`InventorySlotEnum` int NOT NULL DEFAULT '0',
|
||||
`Flags` int NOT NULL DEFAULT '0',
|
||||
`Unused1200` tinyint unsigned NOT NULL DEFAULT '0',
|
||||
`TransmogCollectionType` tinyint unsigned NOT NULL DEFAULT '0',
|
||||
`SecondarySlotID` int NOT NULL DEFAULT '0',
|
||||
`InventorySlotID` int NOT NULL DEFAULT '0',
|
||||
`UnassignedAtlasID` int NOT NULL DEFAULT '0',
|
||||
`UnassignedDisplayAtlasID` int NOT NULL DEFAULT '0',
|
||||
`ItemCostMultiplier` float NOT NULL DEFAULT '0',
|
||||
`IllusionCostMultiplier` float NOT NULL DEFAULT '0',
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_outfit_slot_option`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_outfit_slot_option`;
|
||||
CREATE TABLE `transmog_outfit_slot_option` (
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`Name` text,
|
||||
`OptionEnum` tinyint unsigned NOT NULL DEFAULT '0',
|
||||
`TransmogOutfitSlotInfoID` int unsigned NOT NULL DEFAULT '0',
|
||||
`Flags` int NOT NULL DEFAULT '0',
|
||||
`SecondaryOptionID` int NOT NULL DEFAULT '0',
|
||||
`ItemCostMultiplier` float NOT NULL DEFAULT '0',
|
||||
`IllusionCostMultiplier` float NOT NULL DEFAULT '0',
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_outfit_slot_option_locale`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_outfit_slot_option_locale`;
|
||||
CREATE TABLE `transmog_outfit_slot_option_locale` (
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`locale` varchar(4) NOT NULL,
|
||||
`Name_lang` text,
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`locale`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST COLUMNS(locale)
|
||||
(PARTITION deDE VALUES IN ('deDE') ENGINE = InnoDB,
|
||||
PARTITION esES VALUES IN ('esES') ENGINE = InnoDB,
|
||||
PARTITION esMX VALUES IN ('esMX') ENGINE = InnoDB,
|
||||
PARTITION frFR VALUES IN ('frFR') ENGINE = InnoDB,
|
||||
PARTITION itIT VALUES IN ('itIT') ENGINE = InnoDB,
|
||||
PARTITION koKR VALUES IN ('koKR') ENGINE = InnoDB,
|
||||
PARTITION ptBR VALUES IN ('ptBR') ENGINE = InnoDB,
|
||||
PARTITION ruRU VALUES IN ('ruRU') ENGINE = InnoDB,
|
||||
PARTITION zhCN VALUES IN ('zhCN') ENGINE = InnoDB,
|
||||
PARTITION zhTW VALUES IN ('zhTW') ENGINE = InnoDB);
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_situation`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_situation`;
|
||||
CREATE TABLE `transmog_situation` (
|
||||
`Name` text,
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`SituationEnum` tinyint NOT NULL DEFAULT '0',
|
||||
`Flags` int NOT NULL DEFAULT '0',
|
||||
`TransmogSituationGroupID` int unsigned NOT NULL DEFAULT '0',
|
||||
`OrderIndex` int NOT NULL DEFAULT '0',
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_situation_locale`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_situation_locale`;
|
||||
CREATE TABLE `transmog_situation_locale` (
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`locale` varchar(4) NOT NULL,
|
||||
`Name_lang` text,
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`locale`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST COLUMNS(locale)
|
||||
(PARTITION deDE VALUES IN ('deDE') ENGINE = InnoDB,
|
||||
PARTITION esES VALUES IN ('esES') ENGINE = InnoDB,
|
||||
PARTITION esMX VALUES IN ('esMX') ENGINE = InnoDB,
|
||||
PARTITION frFR VALUES IN ('frFR') ENGINE = InnoDB,
|
||||
PARTITION itIT VALUES IN ('itIT') ENGINE = InnoDB,
|
||||
PARTITION koKR VALUES IN ('koKR') ENGINE = InnoDB,
|
||||
PARTITION ptBR VALUES IN ('ptBR') ENGINE = InnoDB,
|
||||
PARTITION ruRU VALUES IN ('ruRU') ENGINE = InnoDB,
|
||||
PARTITION zhCN VALUES IN ('zhCN') ENGINE = InnoDB,
|
||||
PARTITION zhTW VALUES IN ('zhTW') ENGINE = InnoDB);
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_situation_group`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_situation_group`;
|
||||
CREATE TABLE `transmog_situation_group` (
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`TransmogSituationTriggerID` int unsigned NOT NULL DEFAULT '0',
|
||||
`OrderIndex` int NOT NULL DEFAULT '0',
|
||||
`Flags` int NOT NULL DEFAULT '0',
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_situation_trigger`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_situation_trigger`;
|
||||
CREATE TABLE `transmog_situation_trigger` (
|
||||
`Name` text,
|
||||
`Description` text,
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`TriggerEnum` tinyint unsigned NOT NULL DEFAULT '0',
|
||||
`Flags` int NOT NULL DEFAULT '0',
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `transmog_situation_trigger_locale`
|
||||
--
|
||||
DROP TABLE IF EXISTS `transmog_situation_trigger_locale`;
|
||||
CREATE TABLE `transmog_situation_trigger_locale` (
|
||||
`ID` int unsigned NOT NULL DEFAULT '0',
|
||||
`locale` varchar(4) NOT NULL,
|
||||
`Name_lang` text,
|
||||
`Description_lang` text,
|
||||
`VerifiedBuild` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`locale`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST COLUMNS(locale)
|
||||
(PARTITION deDE VALUES IN ('deDE') ENGINE = InnoDB,
|
||||
PARTITION esES VALUES IN ('esES') ENGINE = InnoDB,
|
||||
PARTITION esMX VALUES IN ('esMX') ENGINE = InnoDB,
|
||||
PARTITION frFR VALUES IN ('frFR') ENGINE = InnoDB,
|
||||
PARTITION itIT VALUES IN ('itIT') ENGINE = InnoDB,
|
||||
PARTITION koKR VALUES IN ('koKR') ENGINE = InnoDB,
|
||||
PARTITION ptBR VALUES IN ('ptBR') ENGINE = InnoDB,
|
||||
PARTITION ruRU VALUES IN ('ruRU') ENGINE = InnoDB,
|
||||
PARTITION zhCN VALUES IN ('zhCN') ENGINE = InnoDB,
|
||||
PARTITION zhTW VALUES IN ('zhTW') ENGINE = InnoDB);
|
||||
@@ -99,7 +99,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
|
||||
"health, power1, power2, power3, power4, power5, power6, power7, power8, power9, power10, instance_id, activeTalentGroup, lootSpecId, exploredZones, knownTitles, actionBars, "
|
||||
"raidDifficulty, legacyRaidDifficulty, fishingSteps, honor, honorLevel, honorRestState, honorRestBonus, numRespecs, "
|
||||
"personalTabardEmblemStyle, personalTabardEmblemColor, personalTabardBorderStyle, personalTabardBorderColor, personalTabardBackgroundColor "
|
||||
"personalTabardEmblemStyle, personalTabardEmblemColor, personalTabardBorderStyle, personalTabardBorderColor, personalTabardBackgroundColor, transmogOutfitEquippedId, transmogOutfitLocked "
|
||||
"FROM characters c LEFT JOIN character_fishingsteps cfs ON c.guid = cfs.guid WHERE c.guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_CUSTOMIZATIONS, "SELECT chrCustomizationOptionID, chrCustomizationChoiceID FROM character_customizations WHERE guid = ? ORDER BY chrCustomizationOptionID", CONNECTION_ASYNC);
|
||||
@@ -150,6 +150,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFITS, "SELECT setguid, setindex, name, iconname, ignore_mask, appearance0, appearance1, appearance2, appearance3, appearance4, "
|
||||
"appearance5, appearance6, appearance7, appearance8, appearance9, appearance10, appearance11, appearance12, appearance13, appearance14, appearance15, appearance16, "
|
||||
"appearance17, appearance18, mainHandEnchant, offHandEnchant FROM character_transmog_outfits WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT, "SELECT transmogOutfitId, name, icon, situationsEnabled FROM character_transmog_outfit WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT_SITUATION, "SELECT transmogOutfitId, situationID, specID, loadoutID, equipmentSetID FROM character_transmog_outfit_situation WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT_SLOT, "SELECT transmogOutfitId, slot, slotOption, itemModifiedAppearanceID, appearanceDisplayType, spellItemEnchantmentID, illusionDisplayType, flags FROM character_transmog_outfit_slot WHERE guid = ? ORDER BY transmogOutfitId, slot, slotOption", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_BGDATA, "SELECT instanceId, team, joinX, joinY, joinZ, joinO, joinMapId, taxiStart, taxiEnd, mountSpell, queueId FROM character_battleground_data WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT talentGroup, glyphId FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT talentId, talentGroup FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
|
||||
@@ -360,6 +363,12 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
"appearance16, appearance17, appearance18, mainHandEnchant, offHandEnchant) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_TRANSMOG_OUTFIT, "DELETE FROM character_transmog_outfits WHERE setguid=?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_TRANSMOG_OUTFIT_2, "INSERT INTO character_transmog_outfit (guid, transmogOutfitId, name, icon, situationsEnabled) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_TRANSMOG_OUTFIT_2, "DELETE FROM character_transmog_outfit WHERE guid = ? AND transmogOutfitId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_TRANSMOG_OUTFIT_SITUATION, "INSERT INTO character_transmog_outfit_situation (guid, transmogOutfitId, situationID, specID, loadoutID, equipmentSetID) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_TRANSMOG_OUTFIT_SITUATION, "DELETE FROM character_transmog_outfit_situation WHERE guid = ? AND transmogOutfitId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_TRANSMOG_OUTFIT_SLOT, "INSERT INTO character_transmog_outfit_slot (guid, transmogOutfitId, slot, slotOption, itemModifiedAppearanceID, appearanceDisplayType, spellItemEnchantmentID, illusionDisplayType, flags) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_TRANSMOG_OUTFIT_SLOT, "DELETE FROM character_transmog_outfit_slot WHERE guid = ? AND transmogOutfitId = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Auras
|
||||
PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, itemGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel) "
|
||||
@@ -481,17 +490,19 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
"taximask, createTime, createMode, cinematic, "
|
||||
"totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, primarySpecialization, "
|
||||
"extra_flags, summonedPetNumber, at_login, "
|
||||
"death_expire_time, taxi_path, totalKills, "
|
||||
"todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, "
|
||||
"power4, power5, power6, power7, power8, power9, power10, latency, activeTalentGroup, lootSpecId, exploredZones, equipmentCache, knownTitles, actionBars, lastLoginBuild) VALUES "
|
||||
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
|
||||
"death_expire_time, taxi_path, totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, "
|
||||
"power1, power2, power3, power4, power5, power6, power7, power8, power9, power10, "
|
||||
"latency, activeTalentGroup, lootSpecId, exploredZones, equipmentCache, knownTitles, actionBars, lastLoginBuild, "
|
||||
"personalTabardEmblemStyle, personalTabardEmblemColor, personalTabardBorderStyle, personalTabardBorderColor, personalTabardBackgroundColor, transmogOutfitEquippedId, transmogOutfitLocked) VALUES "
|
||||
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,inventorySlots=?,inventoryBagFlags=?,bagSlotFlags1=?,bagSlotFlags2=?,bagSlotFlags3=?,bagSlotFlags4=?,bagSlotFlags5=?,"
|
||||
"bankSlots=?,bankTabs=?,bankBagFlags=?,restState=?,playerFlags=?,playerFlagsEx=?,"
|
||||
"map=?,instance_id=?,dungeonDifficulty=?,raidDifficulty=?,legacyRaidDifficulty=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?,"
|
||||
"logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,numRespecs=?,primarySpecialization=?,extra_flags=?,summonedPetNumber=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?,"
|
||||
"totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?,"
|
||||
"watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,power6=?,power7=?,power8=?,power9=?,power10=?,latency=?,activeTalentGroup=?,lootSpecId=?,exploredZones=?,"
|
||||
"equipmentCache=?,knownTitles=?,actionBars=?,online=?,honor=?,honorLevel=?,honorRestState=?,honorRestBonus=?,lastLoginBuild=? WHERE guid=?", CONNECTION_ASYNC);
|
||||
"equipmentCache=?,knownTitles=?,actionBars=?,online=?,honor=?,honorLevel=?,honorRestState=?,honorRestBonus=?,lastLoginBuild=?,"
|
||||
"personalTabardEmblemStyle=?,personalTabardEmblemColor=?,personalTabardBorderStyle=?,personalTabardBorderColor=?,personalTabardBackgroundColor=?,transmogOutfitEquippedId=?,transmogOutfitLocked=? WHERE guid=?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG, "UPDATE characters SET at_login = at_login | ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_REM_AT_LOGIN_FLAG, "UPDATE characters set at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
@@ -626,6 +637,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENTS, "DELETE FROM character_achievement WHERE guid = ? AND achievement NOT IN (456,457,458,459,460,461,462,463,464,465,466,467,1400,1402,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1463,3117,3259,4078,4576,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,6433,6523,6524,6743,6744,6745,6746,6747,6748,6749,6750,6751,6752,6829,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,6869,6870,6871,6872,6873)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_EQUIPMENTSETS, "DELETE FROM character_equipmentsets WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFITS, "DELETE FROM character_transmog_outfits WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFIT_BY_CHAR, "DELETE FROM character_transmog_outfit WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFIT_SITUATION_BY_CHAR, "DELETE FROM character_transmog_outfit_slot WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFIT_SLOT_BY_CHAR, "DELETE FROM character_transmog_outfit_situation WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER, "DELETE FROM guild_eventlog WHERE PlayerGuid1 = ? OR PlayerGuid2 = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_EVENTLOG_BY_PLAYER, "DELETE FROM guild_bank_eventlog WHERE PlayerGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_GLYPHS, "DELETE FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
@@ -107,6 +107,9 @@ enum CharacterDatabaseStatements : uint32
|
||||
CHAR_SEL_CHARACTER_CRITERIAPROGRESS,
|
||||
CHAR_SEL_CHARACTER_EQUIPMENTSETS,
|
||||
CHAR_SEL_CHARACTER_TRANSMOG_OUTFITS,
|
||||
CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT,
|
||||
CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT_SITUATION,
|
||||
CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT_SLOT,
|
||||
CHAR_SEL_CHARACTER_BGDATA,
|
||||
CHAR_SEL_CHARACTER_GLYPHS,
|
||||
CHAR_SEL_CHARACTER_TALENTS,
|
||||
@@ -270,6 +273,13 @@ enum CharacterDatabaseStatements : uint32
|
||||
CHAR_INS_TRANSMOG_OUTFIT,
|
||||
CHAR_DEL_TRANSMOG_OUTFIT,
|
||||
|
||||
CHAR_INS_TRANSMOG_OUTFIT_2,
|
||||
CHAR_DEL_TRANSMOG_OUTFIT_2,
|
||||
CHAR_INS_TRANSMOG_OUTFIT_SITUATION,
|
||||
CHAR_DEL_TRANSMOG_OUTFIT_SITUATION,
|
||||
CHAR_INS_TRANSMOG_OUTFIT_SLOT,
|
||||
CHAR_DEL_TRANSMOG_OUTFIT_SLOT,
|
||||
|
||||
CHAR_INS_AURA,
|
||||
CHAR_INS_AURA_EFFECT,
|
||||
|
||||
@@ -496,6 +506,9 @@ enum CharacterDatabaseStatements : uint32
|
||||
CHAR_DEL_CHAR_ACHIEVEMENTS,
|
||||
CHAR_DEL_CHAR_EQUIPMENTSETS,
|
||||
CHAR_DEL_CHAR_TRANSMOG_OUTFITS,
|
||||
CHAR_DEL_CHAR_TRANSMOG_OUTFIT_BY_CHAR,
|
||||
CHAR_DEL_CHAR_TRANSMOG_OUTFIT_SITUATION_BY_CHAR,
|
||||
CHAR_DEL_CHAR_TRANSMOG_OUTFIT_SLOT_BY_CHAR,
|
||||
CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER,
|
||||
CHAR_DEL_GUILD_BANK_EVENTLOG_BY_PLAYER,
|
||||
CHAR_DEL_CHAR_GLYPHS,
|
||||
|
||||
@@ -1997,6 +1997,26 @@ void HotfixDatabaseConnection::DoPrepareStatements()
|
||||
" WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_TRANSMOG_ILLUSION, "SELECT MAX(ID) + 1 FROM transmog_illusion", CONNECTION_SYNCH);
|
||||
|
||||
// TransmogOutfitEntry.db2
|
||||
PrepareStatement(HOTFIX_SEL_TRANSMOG_OUTFIT_ENTRY, "SELECT Cost, Name, ID, OrderIndex, Source, Flags, SetType, OverrideCostModifier"
|
||||
" FROM transmog_outfit_entry WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_TRANSMOG_OUTFIT_ENTRY, "SELECT MAX(ID) + 1 FROM transmog_outfit_entry", CONNECTION_SYNCH);
|
||||
PREPARE_LOCALE_STMT(HOTFIX_SEL_TRANSMOG_OUTFIT_ENTRY, "SELECT ID, Name_lang FROM transmog_outfit_entry_locale WHERE (`VerifiedBuild` > 0) = ?"
|
||||
" AND locale = ?", CONNECTION_SYNCH);
|
||||
|
||||
// TransmogOutfitSlotInfo.db2
|
||||
PrepareStatement(HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_INFO, "SELECT InventorySlotName, ID, TransmogOutfitSlotEnum, InventorySlotEnum, Flags, "
|
||||
"Unused1200, TransmogCollectionType, SecondarySlotID, InventorySlotID, UnassignedAtlasID, UnassignedDisplayAtlasID, ItemCostMultiplier, "
|
||||
"IllusionCostMultiplier FROM transmog_outfit_slot_info WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_INFO, "SELECT MAX(ID) + 1 FROM transmog_outfit_slot_info", CONNECTION_SYNCH);
|
||||
|
||||
// TransmogOutfitSlotOption.db2
|
||||
PrepareStatement(HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_OPTION, "SELECT ID, Name, OptionEnum, TransmogOutfitSlotInfoID, Flags, SecondaryOptionID, "
|
||||
"ItemCostMultiplier, IllusionCostMultiplier FROM transmog_outfit_slot_option WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_OPTION, "SELECT MAX(ID) + 1 FROM transmog_outfit_slot_option", CONNECTION_SYNCH);
|
||||
PREPARE_LOCALE_STMT(HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_OPTION, "SELECT ID, Name_lang FROM transmog_outfit_slot_option_locale"
|
||||
" WHERE (`VerifiedBuild` > 0) = ? AND locale = ?", CONNECTION_SYNCH);
|
||||
|
||||
// TransmogSet.db2
|
||||
PrepareStatement(HOTFIX_SEL_TRANSMOG_SET, "SELECT Name, ID, ClassMask, TrackingQuestID, Flags, TransmogSetGroupID, ItemNameDescriptionID, "
|
||||
"ParentTransmogSetID, Unknown810, ExpansionID, PatchID, UiOrder, PlayerConditionID FROM transmog_set WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
@@ -2014,6 +2034,25 @@ void HotfixDatabaseConnection::DoPrepareStatements()
|
||||
" WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_TRANSMOG_SET_ITEM, "SELECT MAX(ID) + 1 FROM transmog_set_item", CONNECTION_SYNCH);
|
||||
|
||||
// TransmogSituation.db2
|
||||
PrepareStatement(HOTFIX_SEL_TRANSMOG_SITUATION, "SELECT Name, ID, SituationEnum, Flags, TransmogSituationGroupID, OrderIndex"
|
||||
" FROM transmog_situation WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_TRANSMOG_SITUATION, "SELECT MAX(ID) + 1 FROM transmog_situation", CONNECTION_SYNCH);
|
||||
PREPARE_LOCALE_STMT(HOTFIX_SEL_TRANSMOG_SITUATION, "SELECT ID, Name_lang FROM transmog_situation_locale WHERE (`VerifiedBuild` > 0) = ?"
|
||||
" AND locale = ?", CONNECTION_SYNCH);
|
||||
|
||||
// TransmogSituationGroup.db2
|
||||
PrepareStatement(HOTFIX_SEL_TRANSMOG_SITUATION_GROUP, "SELECT ID, TransmogSituationTriggerID, OrderIndex, Flags FROM transmog_situation_group"
|
||||
" WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_TRANSMOG_SITUATION_GROUP, "SELECT MAX(ID) + 1 FROM transmog_situation_group", CONNECTION_SYNCH);
|
||||
|
||||
// TransmogSituationTrigger.db2
|
||||
PrepareStatement(HOTFIX_SEL_TRANSMOG_SITUATION_TRIGGER, "SELECT Name, Description, ID, TriggerEnum, Flags FROM transmog_situation_trigger"
|
||||
" WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_TRANSMOG_SITUATION_TRIGGER, "SELECT MAX(ID) + 1 FROM transmog_situation_trigger", CONNECTION_SYNCH);
|
||||
PREPARE_LOCALE_STMT(HOTFIX_SEL_TRANSMOG_SITUATION_TRIGGER, "SELECT ID, Name_lang, Description_lang FROM transmog_situation_trigger_locale"
|
||||
" WHERE (`VerifiedBuild` > 0) = ? AND locale = ?", CONNECTION_SYNCH);
|
||||
|
||||
// TransportAnimation.db2
|
||||
PrepareStatement(HOTFIX_SEL_TRANSPORT_ANIMATION, "SELECT ID, PosX, PosY, PosZ, SequenceID, TimeIndex, TransportID FROM transport_animation"
|
||||
" WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
|
||||
@@ -1155,6 +1155,17 @@ enum HotfixDatabaseStatements : uint32
|
||||
HOTFIX_SEL_TRANSMOG_ILLUSION,
|
||||
HOTFIX_SEL_TRANSMOG_ILLUSION_MAX_ID,
|
||||
|
||||
HOTFIX_SEL_TRANSMOG_OUTFIT_ENTRY,
|
||||
HOTFIX_SEL_TRANSMOG_OUTFIT_ENTRY_MAX_ID,
|
||||
HOTFIX_SEL_TRANSMOG_OUTFIT_ENTRY_LOCALE,
|
||||
|
||||
HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_INFO,
|
||||
HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_INFO_MAX_ID,
|
||||
|
||||
HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_OPTION,
|
||||
HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_OPTION_MAX_ID,
|
||||
HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_OPTION_LOCALE,
|
||||
|
||||
HOTFIX_SEL_TRANSMOG_SET,
|
||||
HOTFIX_SEL_TRANSMOG_SET_MAX_ID,
|
||||
HOTFIX_SEL_TRANSMOG_SET_LOCALE,
|
||||
@@ -1166,6 +1177,17 @@ enum HotfixDatabaseStatements : uint32
|
||||
HOTFIX_SEL_TRANSMOG_SET_ITEM,
|
||||
HOTFIX_SEL_TRANSMOG_SET_ITEM_MAX_ID,
|
||||
|
||||
HOTFIX_SEL_TRANSMOG_SITUATION,
|
||||
HOTFIX_SEL_TRANSMOG_SITUATION_MAX_ID,
|
||||
HOTFIX_SEL_TRANSMOG_SITUATION_LOCALE,
|
||||
|
||||
HOTFIX_SEL_TRANSMOG_SITUATION_GROUP,
|
||||
HOTFIX_SEL_TRANSMOG_SITUATION_GROUP_MAX_ID,
|
||||
|
||||
HOTFIX_SEL_TRANSMOG_SITUATION_TRIGGER,
|
||||
HOTFIX_SEL_TRANSMOG_SITUATION_TRIGGER_MAX_ID,
|
||||
HOTFIX_SEL_TRANSMOG_SITUATION_TRIGGER_LOCALE,
|
||||
|
||||
HOTFIX_SEL_TRANSPORT_ANIMATION,
|
||||
HOTFIX_SEL_TRANSPORT_ANIMATION_MAX_ID,
|
||||
|
||||
|
||||
@@ -191,6 +191,8 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
||||
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);
|
||||
PrepareStatement(LOGIN_SEL_BNET_TRANSMOG_OUTFITS, "SELECT transmogOutfitId FROM battlenet_account_transmog_outfits WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_BNET_TRANSMOG_OUTFITS, "INSERT IGNORE INTO battlenet_account_transmog_outfits (battlenetAccountId, transmogOutfitId) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_BNET_WARBAND_SCENES, "SELECT warbandSceneId, isFavorite, hasFanfare FROM battlenet_account_warband_scenes WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_BNET_WARBAND_SCENE, "INSERT INTO battlenet_account_warband_scenes (battlenetAccountId, warbandSceneId, isFavorite, hasFanfare) VALUES (?, ?, ?, ?) "
|
||||
"ON DUPLICATE KEY UPDATE isFavorite = VALUES(isFavorite)", CONNECTION_ASYNC);
|
||||
|
||||
@@ -176,6 +176,8 @@ enum LoginDatabaseStatements : uint32
|
||||
LOGIN_DEL_BNET_ITEM_FAVORITE_APPEARANCE,
|
||||
LOGIN_SEL_BNET_TRANSMOG_ILLUSIONS,
|
||||
LOGIN_INS_BNET_TRANSMOG_ILLUSIONS,
|
||||
LOGIN_SEL_BNET_TRANSMOG_OUTFITS,
|
||||
LOGIN_INS_BNET_TRANSMOG_OUTFITS,
|
||||
LOGIN_SEL_BNET_WARBAND_SCENES,
|
||||
LOGIN_INS_BNET_WARBAND_SCENE,
|
||||
LOGIN_UPD_BNET_WARBAND_SCENE,
|
||||
|
||||
@@ -3227,8 +3227,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
{
|
||||
itemSubclass = itemTemplate->GetSubClass();
|
||||
|
||||
if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sDB2Manager.GetItemModifiedAppearance(visibleItem.ItemID, visibleItem.ItemAppearanceModID))
|
||||
if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(itemModifiedAppearance->ID))
|
||||
if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(visibleItem.ItemModifiedAppearanceID))
|
||||
if (itemModifiedAppearaceExtra->DisplayWeaponSubclassID > 0)
|
||||
itemSubclass = itemModifiedAppearaceExtra->DisplayWeaponSubclassID;
|
||||
}
|
||||
@@ -3247,8 +3246,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
{
|
||||
itemSubclass = itemTemplate->GetSubClass();
|
||||
|
||||
if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sDB2Manager.GetItemModifiedAppearance(visibleItem.ItemID, visibleItem.ItemAppearanceModID))
|
||||
if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(itemModifiedAppearance->ID))
|
||||
if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(visibleItem.ItemModifiedAppearanceID))
|
||||
if (itemModifiedAppearaceExtra->DisplayWeaponSubclassID > 0)
|
||||
itemSubclass = itemModifiedAppearaceExtra->DisplayWeaponSubclassID;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "TransmogMgr.h"
|
||||
|
||||
static constexpr char HYPERLINK_DATA_DELIMITER = ':';
|
||||
|
||||
@@ -527,7 +528,7 @@ bool Trinity::Hyperlinks::LinkTags::transmogillusion::StoreTo(SpellItemEnchantme
|
||||
if (!t.TryConsumeTo(spellItemEnchantmentId))
|
||||
return false;
|
||||
return !!(val = sSpellItemEnchantmentStore.LookupEntry(spellItemEnchantmentId))
|
||||
&& sDB2Manager.GetTransmogIllusionForEnchantment(spellItemEnchantmentId) && t.IsEmpty();
|
||||
&& TransmogMgr::GetTransmogIllusionForSpellItemEnchantment(spellItemEnchantmentId) && t.IsEmpty();
|
||||
}
|
||||
|
||||
bool Trinity::Hyperlinks::LinkTags::transmogset::StoreTo(TransmogSetEntry const*& val, std::string_view text)
|
||||
|
||||
@@ -6579,6 +6579,62 @@ struct TransmogIllusionLoadInfo
|
||||
static constexpr DB2LoadInfo Instance{ Fields, 5, &TransmogIllusionMeta::Instance, HOTFIX_SEL_TRANSMOG_ILLUSION };
|
||||
};
|
||||
|
||||
struct TransmogOutfitEntryLoadInfo
|
||||
{
|
||||
static constexpr DB2FieldMeta Fields[8] =
|
||||
{
|
||||
{ .IsSigned = false, .Type = FT_LONG, .Name = "Cost" },
|
||||
{ .IsSigned = false, .Type = FT_STRING, .Name = "Name" },
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "OrderIndex" },
|
||||
{ .IsSigned = false, .Type = FT_BYTE, .Name = "Source" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "Flags" },
|
||||
{ .IsSigned = false, .Type = FT_BYTE, .Name = "SetType" },
|
||||
{ .IsSigned = false, .Type = FT_FLOAT, .Name = "OverrideCostModifier" },
|
||||
};
|
||||
|
||||
static constexpr DB2LoadInfo Instance{ Fields, 8, &TransmogOutfitEntryMeta::Instance, HOTFIX_SEL_TRANSMOG_OUTFIT_ENTRY };
|
||||
};
|
||||
|
||||
struct TransmogOutfitSlotInfoLoadInfo
|
||||
{
|
||||
static constexpr DB2FieldMeta Fields[13] =
|
||||
{
|
||||
{ .IsSigned = false, .Type = FT_STRING_NOT_LOCALIZED, .Name = "InventorySlotName" },
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{ .IsSigned = true, .Type = FT_BYTE, .Name = "TransmogOutfitSlotEnum" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "InventorySlotEnum" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "Flags" },
|
||||
{ .IsSigned = false, .Type = FT_BYTE, .Name = "Unused1200" },
|
||||
{ .IsSigned = false, .Type = FT_BYTE, .Name = "TransmogCollectionType" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "SecondarySlotID" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "InventorySlotID" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "UnassignedAtlasID" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "UnassignedDisplayAtlasID" },
|
||||
{ .IsSigned = false, .Type = FT_FLOAT, .Name = "ItemCostMultiplier" },
|
||||
{ .IsSigned = false, .Type = FT_FLOAT, .Name = "IllusionCostMultiplier" },
|
||||
};
|
||||
|
||||
static constexpr DB2LoadInfo Instance{ Fields, 13, &TransmogOutfitSlotInfoMeta::Instance, HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_INFO };
|
||||
};
|
||||
|
||||
struct TransmogOutfitSlotOptionLoadInfo
|
||||
{
|
||||
static constexpr DB2FieldMeta Fields[8] =
|
||||
{
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{ .IsSigned = false, .Type = FT_STRING, .Name = "Name" },
|
||||
{ .IsSigned = false, .Type = FT_BYTE, .Name = "OptionEnum" },
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "TransmogOutfitSlotInfoID" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "Flags" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "SecondaryOptionID" },
|
||||
{ .IsSigned = false, .Type = FT_FLOAT, .Name = "ItemCostMultiplier" },
|
||||
{ .IsSigned = false, .Type = FT_FLOAT, .Name = "IllusionCostMultiplier" },
|
||||
};
|
||||
|
||||
static constexpr DB2LoadInfo Instance{ Fields, 8, &TransmogOutfitSlotOptionMeta::Instance, HOTFIX_SEL_TRANSMOG_OUTFIT_SLOT_OPTION };
|
||||
};
|
||||
|
||||
struct TransmogSetLoadInfo
|
||||
{
|
||||
static constexpr DB2FieldMeta Fields[13] =
|
||||
@@ -6625,6 +6681,48 @@ struct TransmogSetItemLoadInfo
|
||||
static constexpr DB2LoadInfo Instance{ Fields, 4, &TransmogSetItemMeta::Instance, HOTFIX_SEL_TRANSMOG_SET_ITEM };
|
||||
};
|
||||
|
||||
struct TransmogSituationLoadInfo
|
||||
{
|
||||
static constexpr DB2FieldMeta Fields[6] =
|
||||
{
|
||||
{ .IsSigned = false, .Type = FT_STRING, .Name = "Name" },
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{ .IsSigned = true, .Type = FT_BYTE, .Name = "SituationEnum" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "Flags" },
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "TransmogSituationGroupID" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "OrderIndex" },
|
||||
};
|
||||
|
||||
static constexpr DB2LoadInfo Instance{ Fields, 6, &TransmogSituationMeta::Instance, HOTFIX_SEL_TRANSMOG_SITUATION };
|
||||
};
|
||||
|
||||
struct TransmogSituationGroupLoadInfo
|
||||
{
|
||||
static constexpr DB2FieldMeta Fields[4] =
|
||||
{
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "TransmogSituationTriggerID" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "OrderIndex" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "Flags" },
|
||||
};
|
||||
|
||||
static constexpr DB2LoadInfo Instance{ Fields, 4, &TransmogSituationGroupMeta::Instance, HOTFIX_SEL_TRANSMOG_SITUATION_GROUP };
|
||||
};
|
||||
|
||||
struct TransmogSituationTriggerLoadInfo
|
||||
{
|
||||
static constexpr DB2FieldMeta Fields[5] =
|
||||
{
|
||||
{ .IsSigned = false, .Type = FT_STRING, .Name = "Name" },
|
||||
{ .IsSigned = false, .Type = FT_STRING, .Name = "Description" },
|
||||
{ .IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{ .IsSigned = false, .Type = FT_BYTE, .Name = "TriggerEnum" },
|
||||
{ .IsSigned = true, .Type = FT_INT, .Name = "Flags" },
|
||||
};
|
||||
|
||||
static constexpr DB2LoadInfo Instance{ Fields, 5, &TransmogSituationTriggerMeta::Instance, HOTFIX_SEL_TRANSMOG_SITUATION_TRIGGER };
|
||||
};
|
||||
|
||||
struct TransportAnimationLoadInfo
|
||||
{
|
||||
static constexpr DB2FieldMeta Fields[7] =
|
||||
|
||||
@@ -382,6 +382,12 @@ DB2Storage<TraitTreeXTraitCostEntry> sTraitTreeXTraitCostStore("Trait
|
||||
DB2Storage<TraitTreeXTraitCurrencyEntry> sTraitTreeXTraitCurrencyStore("TraitTreeXTraitCurrency.db2", &TraitTreeXTraitCurrencyLoadInfo::Instance);
|
||||
DB2Storage<TransmogHolidayEntry> sTransmogHolidayStore("TransmogHoliday.db2", &TransmogHolidayLoadInfo::Instance);
|
||||
DB2Storage<TransmogIllusionEntry> sTransmogIllusionStore("TransmogIllusion.db2", &TransmogIllusionLoadInfo::Instance);
|
||||
DB2Storage<TransmogOutfitEntryEntry> sTransmogOutfitEntryStore("TransmogOutfitEntry.db2", &TransmogOutfitEntryLoadInfo::Instance);
|
||||
DB2Storage<TransmogOutfitSlotInfoEntry> sTransmogOutfitSlotInfoStore("TransmogOutfitSlotInfo.db2", &TransmogOutfitSlotInfoLoadInfo::Instance);
|
||||
DB2Storage<TransmogOutfitSlotOptionEntry> sTransmogOutfitSlotOptionInfoStore("TransmogOutfitSlotOption.db2", &TransmogOutfitSlotOptionLoadInfo::Instance);
|
||||
DB2Storage<TransmogSituationEntry> sTransmogSituationStore("TransmogSituation.db2", &TransmogSituationLoadInfo::Instance);
|
||||
DB2Storage<TransmogSituationGroupEntry> sTransmogSituationGroupStore("TransmogSituationGroup.db2", &TransmogSituationGroupLoadInfo::Instance);
|
||||
DB2Storage<TransmogSituationTriggerEntry> sTransmogSituationTriggerStore("TransmogSituationTrigger.db2", &TransmogSituationTriggerLoadInfo::Instance);
|
||||
DB2Storage<TransmogSetEntry> sTransmogSetStore("TransmogSet.db2", &TransmogSetLoadInfo::Instance);
|
||||
DB2Storage<TransmogSetGroupEntry> sTransmogSetGroupStore("TransmogSetGroup.db2", &TransmogSetGroupLoadInfo::Instance);
|
||||
DB2Storage<TransmogSetItemEntry> sTransmogSetItemStore("TransmogSetItem.db2", &TransmogSetItemLoadInfo::Instance);
|
||||
@@ -426,7 +432,6 @@ typedef std::unordered_map<uint32 /*glyphPropertiesId*/, std::vector<ChrSpeciali
|
||||
typedef std::unordered_map<uint32 /*itemId*/, ItemChildEquipmentEntry const*> ItemChildEquipmentContainer;
|
||||
typedef std::array<ItemClassEntry const*, 21> ItemClassByOldEnumContainer;
|
||||
typedef std::unordered_map<uint32, std::vector<ItemLimitCategoryConditionEntry const*>> ItemLimitCategoryConditionContainer;
|
||||
typedef std::unordered_map<uint32 /*itemId | appearanceMod << 24*/, ItemModifiedAppearanceEntry const*> ItemModifiedAppearanceByItemContainer;
|
||||
typedef std::unordered_map<uint32, std::vector<ItemSetSpellEntry const*>> ItemSetSpellContainer;
|
||||
typedef std::unordered_map<uint32, std::vector<ItemSpecOverrideEntry const*>> ItemSpecOverridesContainer;
|
||||
typedef std::unordered_map<uint32, std::unordered_map<uint32, MapDifficultyEntry const*>> MapDifficultyContainer;
|
||||
@@ -505,7 +510,6 @@ namespace
|
||||
ItemClassByOldEnumContainer _itemClassByOldEnum;
|
||||
std::unordered_set<uint32> _itemsWithCurrencyCost;
|
||||
ItemLimitCategoryConditionContainer _itemCategoryConditions;
|
||||
ItemModifiedAppearanceByItemContainer _itemModifiedAppearancesByItem;
|
||||
ItemSetSpellContainer _itemSetSpells;
|
||||
ItemSpecOverridesContainer _itemSpecOverrides;
|
||||
std::vector<JournalTierEntry const*> _journalTiersByIndex;
|
||||
@@ -536,9 +540,6 @@ namespace
|
||||
TalentsByPosition _talentsByPosition;
|
||||
std::unordered_map<std::pair<uint32, uint32>, TaxiPathEntry const*> _taxiPaths;
|
||||
ToyItemIdsContainer _toys;
|
||||
std::unordered_map<uint32, TransmogIllusionEntry const*> _transmogIllusionsByEnchantmentId;
|
||||
std::unordered_map<uint32, std::vector<TransmogSetEntry const*>> _transmogSetsByItemModifiedAppearance;
|
||||
std::unordered_map<uint32, std::vector<TransmogSetItemEntry const*>> _transmogSetItemsByTransmogSet;
|
||||
std::unordered_map<int32, UiMapBounds> _uiMapBounds;
|
||||
std::unordered_multimap<int32, UiMapAssignmentEntry const*> _uiMapAssignmentByMap[MAX_UI_MAP_SYSTEM];
|
||||
std::unordered_multimap<int32, UiMapAssignmentEntry const*> _uiMapAssignmentByArea[MAX_UI_MAP_SYSTEM];
|
||||
@@ -1013,6 +1014,12 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
|
||||
LOAD_DB2(sTraitTreeXTraitCurrencyStore);
|
||||
LOAD_DB2(sTransmogHolidayStore);
|
||||
LOAD_DB2(sTransmogIllusionStore);
|
||||
LOAD_DB2(sTransmogOutfitEntryStore);
|
||||
LOAD_DB2(sTransmogOutfitSlotInfoStore);
|
||||
LOAD_DB2(sTransmogOutfitSlotOptionInfoStore);
|
||||
LOAD_DB2(sTransmogSituationStore);
|
||||
LOAD_DB2(sTransmogSituationGroupStore);
|
||||
LOAD_DB2(sTransmogSituationTriggerStore);
|
||||
LOAD_DB2(sTransmogSetStore);
|
||||
LOAD_DB2(sTransmogSetGroupStore);
|
||||
LOAD_DB2(sTransmogSetItemStore);
|
||||
@@ -1359,12 +1366,6 @@ void DB2Manager::IndexLoadedStores()
|
||||
for (ItemLimitCategoryConditionEntry const* condition : sItemLimitCategoryConditionStore)
|
||||
_itemCategoryConditions[condition->ParentItemLimitCategoryID].push_back(condition);
|
||||
|
||||
for (ItemModifiedAppearanceEntry const* appearanceMod : sItemModifiedAppearanceStore)
|
||||
{
|
||||
ASSERT(appearanceMod->ItemID <= 0xFFFFFF);
|
||||
_itemModifiedAppearancesByItem[appearanceMod->ItemID | (appearanceMod->ItemAppearanceModifierID << 24)] = appearanceMod;
|
||||
}
|
||||
|
||||
for (ItemSetSpellEntry const* itemSetSpell : sItemSetSpellStore)
|
||||
_itemSetSpells[itemSetSpell->ItemSetID].push_back(itemSetSpell);
|
||||
|
||||
@@ -1576,19 +1577,6 @@ void DB2Manager::IndexLoadedStores()
|
||||
for (ToyEntry const* toy : sToyStore)
|
||||
_toys.insert(toy->ItemID);
|
||||
|
||||
for (TransmogIllusionEntry const* transmogIllusion : sTransmogIllusionStore)
|
||||
_transmogIllusionsByEnchantmentId[transmogIllusion->SpellItemEnchantmentID] = transmogIllusion;
|
||||
|
||||
for (TransmogSetItemEntry const* transmogSetItem : sTransmogSetItemStore)
|
||||
{
|
||||
TransmogSetEntry const* set = sTransmogSetStore.LookupEntry(transmogSetItem->TransmogSetID);
|
||||
if (!set)
|
||||
continue;
|
||||
|
||||
_transmogSetsByItemModifiedAppearance[transmogSetItem->ItemModifiedAppearanceID].push_back(set);
|
||||
_transmogSetItemsByTransmogSet[transmogSetItem->TransmogSetID].push_back(transmogSetItem);
|
||||
}
|
||||
|
||||
std::unordered_multimap<int32, UiMapAssignmentEntry const*> uiMapAssignmentByUiMap;
|
||||
for (UiMapAssignmentEntry const* uiMapAssignment : sUiMapAssignmentStore)
|
||||
{
|
||||
@@ -2649,37 +2637,6 @@ std::vector<ItemLimitCategoryConditionEntry const*> const* DB2Manager::GetItemLi
|
||||
return Trinity::Containers::MapGetValuePtr(_itemCategoryConditions, categoryId);
|
||||
}
|
||||
|
||||
uint32 DB2Manager::GetItemDisplayId(uint32 itemId, uint32 appearanceModId) const
|
||||
{
|
||||
if (ItemModifiedAppearanceEntry const* modifiedAppearance = GetItemModifiedAppearance(itemId, appearanceModId))
|
||||
if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(modifiedAppearance->ItemAppearanceID))
|
||||
return itemAppearance->ItemDisplayInfoID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ItemModifiedAppearanceEntry const* DB2Manager::GetItemModifiedAppearance(uint32 itemId, uint32 appearanceModId) const
|
||||
{
|
||||
auto itr = _itemModifiedAppearancesByItem.find(itemId | (appearanceModId << 24));
|
||||
if (itr != _itemModifiedAppearancesByItem.end())
|
||||
return itr->second;
|
||||
|
||||
// Fall back to unmodified appearance
|
||||
if (appearanceModId)
|
||||
{
|
||||
itr = _itemModifiedAppearancesByItem.find(itemId);
|
||||
if (itr != _itemModifiedAppearancesByItem.end())
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ItemModifiedAppearanceEntry const* DB2Manager::GetDefaultItemModifiedAppearance(uint32 itemId) const
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(_itemModifiedAppearancesByItem, itemId);
|
||||
}
|
||||
|
||||
std::vector<ItemSetSpellEntry const*> const* DB2Manager::GetItemSetSpells(uint32 itemSetId) const
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(_itemSetSpells, itemSetId);
|
||||
@@ -3116,21 +3073,6 @@ bool DB2Manager::IsToyItem(uint32 toy) const
|
||||
return _toys.count(toy) > 0;
|
||||
}
|
||||
|
||||
TransmogIllusionEntry const* DB2Manager::GetTransmogIllusionForEnchantment(uint32 spellItemEnchantmentId) const
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(_transmogIllusionsByEnchantmentId, spellItemEnchantmentId);
|
||||
}
|
||||
|
||||
std::vector<TransmogSetEntry const*> const* DB2Manager::GetTransmogSetsForItemModifiedAppearance(uint32 itemModifiedAppearanceId) const
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(_transmogSetsByItemModifiedAppearance, itemModifiedAppearanceId);
|
||||
}
|
||||
|
||||
std::vector<TransmogSetItemEntry const*> const* DB2Manager::GetTransmogSetItems(uint32 transmogSetId) const
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(_transmogSetItemsByTransmogSet, transmogSetId);
|
||||
}
|
||||
|
||||
struct UiMapAssignmentStatus
|
||||
{
|
||||
UiMapAssignmentEntry const* UiMapAssignment = nullptr;
|
||||
|
||||
@@ -306,6 +306,12 @@ TC_GAME_API extern DB2Storage<TraitTreeXTraitCostEntry> sTraitTreeXT
|
||||
TC_GAME_API extern DB2Storage<TraitTreeXTraitCurrencyEntry> sTraitTreeXTraitCurrencyStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogHolidayEntry> sTransmogHolidayStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogIllusionEntry> sTransmogIllusionStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogOutfitEntryEntry> sTransmogOutfitEntryStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogOutfitSlotInfoEntry> sTransmogOutfitSlotInfoStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogOutfitSlotOptionEntry> sTransmogOutfitSlotOptionInfoStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogSituationEntry> sTransmogSituationStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogSituationGroupEntry> sTransmogSituationGroupStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogSituationTriggerEntry> sTransmogSituationTriggerStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogSetEntry> sTransmogSetStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogSetGroupEntry> sTransmogSetGroupStore;
|
||||
TC_GAME_API extern DB2Storage<TransmogSetItemEntry> sTransmogSetItemStore;
|
||||
@@ -499,9 +505,6 @@ public:
|
||||
ItemClassEntry const* GetItemClassByOldEnum(uint32 itemClass) const;
|
||||
bool HasItemCurrencyCost(uint32 itemId) const;
|
||||
std::vector<ItemLimitCategoryConditionEntry const*> const* GetItemLimitCategoryConditions(uint32 categoryId) const;
|
||||
uint32 GetItemDisplayId(uint32 itemId, uint32 appearanceModId) const;
|
||||
ItemModifiedAppearanceEntry const* GetItemModifiedAppearance(uint32 itemId, uint32 appearanceModId) const;
|
||||
ItemModifiedAppearanceEntry const* GetDefaultItemModifiedAppearance(uint32 itemId) const;
|
||||
std::vector<ItemSetSpellEntry const*> const* GetItemSetSpells(uint32 itemSetId) const;
|
||||
std::vector<ItemSpecOverrideEntry const*> const* GetItemSpecOverrides(uint32 itemId) const;
|
||||
JournalTierEntry const* GetJournalTier(uint32 index) const;
|
||||
@@ -548,9 +551,6 @@ public:
|
||||
TaxiPathEntry const* GetTaxiPath(uint32 from, uint32 to) const;
|
||||
static bool IsTotemCategoryCompatibleWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId, bool requireAllTotems = true);
|
||||
bool IsToyItem(uint32 toy) const;
|
||||
TransmogIllusionEntry const* GetTransmogIllusionForEnchantment(uint32 spellItemEnchantmentId) const;
|
||||
std::vector<TransmogSetEntry const*> const* GetTransmogSetsForItemModifiedAppearance(uint32 itemModifiedAppearanceId) const;
|
||||
std::vector<TransmogSetItemEntry const*> const* GetTransmogSetItems(uint32 transmogSetId) const;
|
||||
static bool GetUiMapPosition(float x, float y, float z, int32 mapId, int32 areaId, int32 wmoDoodadPlacementId, int32 wmoGroupId, UiMapSystem system, bool local,
|
||||
uint32* uiMapId = nullptr, DBCPosition2D* newPos = nullptr);
|
||||
bool Zone2MapCoordinates(uint32 areaId, float& x, float& y) const;
|
||||
|
||||
@@ -4696,6 +4696,57 @@ struct TransmogIllusionEntry
|
||||
EnumFlag<TransmogIllusionFlags> GetFlags() const { return static_cast<TransmogIllusionFlags>(Flags); }
|
||||
};
|
||||
|
||||
struct TransmogOutfitEntryEntry
|
||||
{
|
||||
uint64 Cost;
|
||||
LocalizedString Name;
|
||||
uint32 ID;
|
||||
int32 OrderIndex;
|
||||
uint8 Source;
|
||||
int32 Flags;
|
||||
uint8 SetType;
|
||||
float OverrideCostModifier;
|
||||
|
||||
TransmogOutfitEntrySource GetSource() const { return static_cast<TransmogOutfitEntrySource>(Source); }
|
||||
bool HasFlag(TransmogOutfitEntryFlags flag) const { return EnumFlag(static_cast<TransmogOutfitEntryFlags>(Flags)).HasFlag(flag); }
|
||||
TransmogOutfitSetType GetSetType() const { return static_cast<TransmogOutfitSetType>(SetType); }
|
||||
};
|
||||
|
||||
struct TransmogOutfitSlotInfoEntry
|
||||
{
|
||||
char const* InventorySlotName;
|
||||
uint32 ID;
|
||||
int8 TransmogOutfitSlotEnum;
|
||||
int32 InventorySlotEnum;
|
||||
int32 Flags;
|
||||
uint8 Unused1200;
|
||||
uint8 TransmogCollectionType;
|
||||
int32 SecondarySlotID;
|
||||
int32 InventorySlotID;
|
||||
int32 UnassignedAtlasID;
|
||||
int32 UnassignedDisplayAtlasID;
|
||||
float ItemCostMultiplier;
|
||||
float IllusionCostMultiplier;
|
||||
|
||||
TransmogOutfitSlot GetSlot() const { return static_cast<TransmogOutfitSlot>(TransmogOutfitSlotEnum); }
|
||||
bool HasFlag(TransmogOutfitSlotFlags flag) const { return EnumFlag(static_cast<TransmogOutfitSlotFlags>(Flags)).HasFlag(flag); }
|
||||
};
|
||||
|
||||
struct TransmogOutfitSlotOptionEntry
|
||||
{
|
||||
uint32 ID;
|
||||
LocalizedString Name;
|
||||
uint8 OptionEnum;
|
||||
uint32 TransmogOutfitSlotInfoID;
|
||||
int32 Flags;
|
||||
int32 SecondaryOptionID;
|
||||
float ItemCostMultiplier;
|
||||
float IllusionCostMultiplier;
|
||||
|
||||
TransmogOutfitSlotOption GetOption() const { return static_cast<TransmogOutfitSlotOption>(OptionEnum); }
|
||||
bool HasFlag(TransmogOutfitSlotOptionFlags flag) const { return EnumFlag(static_cast<TransmogOutfitSlotOptionFlags>(Flags)).HasFlag(flag); }
|
||||
};
|
||||
|
||||
struct TransmogSetEntry
|
||||
{
|
||||
LocalizedString Name;
|
||||
@@ -4727,6 +4778,39 @@ struct TransmogSetItemEntry
|
||||
int32 Flags;
|
||||
};
|
||||
|
||||
struct TransmogSituationEntry
|
||||
{
|
||||
LocalizedString Name;
|
||||
uint32 ID;
|
||||
int8 SituationEnum;
|
||||
int32 Flags;
|
||||
uint32 TransmogSituationGroupID;
|
||||
int32 OrderIndex;
|
||||
|
||||
TransmogSituation GetSituation() const { return static_cast<TransmogSituation>(SituationEnum); }
|
||||
bool HasFlag(TransmogSituationFlags flag) const { return EnumFlag(static_cast<TransmogSituationFlags>(Flags)).HasFlag(flag); }
|
||||
};
|
||||
|
||||
struct TransmogSituationGroupEntry
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 TransmogSituationTriggerID;
|
||||
int32 OrderIndex;
|
||||
int32 Flags;
|
||||
};
|
||||
|
||||
struct TransmogSituationTriggerEntry
|
||||
{
|
||||
LocalizedString Name;
|
||||
LocalizedString Description;
|
||||
uint32 ID;
|
||||
uint8 TriggerEnum;
|
||||
int32 Flags;
|
||||
|
||||
TransmogSituationTrigger GetTrigger() const { return static_cast<TransmogSituationTrigger>(TriggerEnum); }
|
||||
bool HasFlag(TransmogSituationTriggerFlags flag) const { return EnumFlag(static_cast<TransmogSituationTriggerFlags>(Flags)).HasFlag(flag); }
|
||||
};
|
||||
|
||||
struct TransportAnimationEntry
|
||||
{
|
||||
uint32 ID;
|
||||
|
||||
@@ -2520,6 +2520,179 @@ enum class TransmogIllusionFlags : int32
|
||||
|
||||
DEFINE_ENUM_FLAG(TransmogIllusionFlags);
|
||||
|
||||
enum class TransmogOutfitDisplayType : uint8
|
||||
{
|
||||
Unassigned = 0,
|
||||
Assigned = 1,
|
||||
Equipped = 2,
|
||||
Hidden = 3,
|
||||
Disabled = 4,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
enum class TransmogOutfitEquipAction : uint8
|
||||
{
|
||||
Equip = 0,
|
||||
EquipAndLock = 1,
|
||||
Remove = 2,
|
||||
RemoveAndLock = 3,
|
||||
Unlock = 4,
|
||||
Lock = 5,
|
||||
};
|
||||
|
||||
enum class TransmogOutfitEntryFlags : int32
|
||||
{
|
||||
AutomaticallyAwardedOnLogin = 0x01,
|
||||
UseOverrideName = 0x02,
|
||||
OnlyAvailableDuringEvent = 0x04,
|
||||
SortedToTopOfList = 0x08,
|
||||
UseOverrideCostModifier = 0x10,
|
||||
IsDefaultEquipped = 0x20
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(TransmogOutfitEntryFlags);
|
||||
|
||||
enum class TransmogOutfitEntrySource : uint8
|
||||
{
|
||||
StampedSource = 0,
|
||||
AutomaticallyAwarded = 1,
|
||||
PlayerPurchased = 2,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
enum class TransmogOutfitSetType : uint8
|
||||
{
|
||||
Equipped = 0,
|
||||
Outfit = 1,
|
||||
CustomSet = 2
|
||||
};
|
||||
|
||||
enum class TransmogOutfitSlot : int8
|
||||
{
|
||||
Head = 0,
|
||||
ShoulderRight = 1,
|
||||
ShoulderLeft = 2,
|
||||
Back = 3,
|
||||
Chest = 4,
|
||||
Tabard = 5,
|
||||
Body = 6,
|
||||
Wrist = 7,
|
||||
Hand = 8,
|
||||
Waist = 9,
|
||||
Legs = 10,
|
||||
Feet = 11,
|
||||
WeaponMainHand = 12,
|
||||
WeaponOffHand = 13,
|
||||
WeaponRanged = 14,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
enum class TransmogOutfitSlotFlags : int32
|
||||
{
|
||||
CannotBeHidden = 0x01,
|
||||
CanHaveIllusions = 0x02,
|
||||
IsSecondarySlot = 0x04
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(TransmogOutfitSlotFlags);
|
||||
|
||||
enum class TransmogOutfitSlotOption : uint8
|
||||
{
|
||||
None = 0,
|
||||
OneHandedWeapon = 1,
|
||||
TwoHandedWeapon = 2,
|
||||
RangedWeapon = 3,
|
||||
OffHand = 4,
|
||||
Shield = 5,
|
||||
DeprecatedReuseMe = 6,
|
||||
FuryTwoHandedWeapon = 7,
|
||||
ArtifactSpecOne = 8,
|
||||
ArtifactSpecTwo = 9,
|
||||
ArtifactSpecThree = 10,
|
||||
ArtifactSpecFour = 11,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
enum class TransmogOutfitSlotOptionFlags : int32
|
||||
{
|
||||
IllusionNotAllowed = 0x01,
|
||||
DynamicOptionName = 0x02,
|
||||
DisablesOffhandSlot = 0x04
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(TransmogOutfitSlotOptionFlags);
|
||||
|
||||
enum class TransmogSituation : int8
|
||||
{
|
||||
AllSpecs = 0,
|
||||
Spec = 1,
|
||||
AllLocations = 2,
|
||||
LocationRested = 3,
|
||||
LocationHouse = 4,
|
||||
LocationCharacterSelect = 5,
|
||||
LocationWorld = 6,
|
||||
LocationDelves = 7,
|
||||
LocationDungeons = 8,
|
||||
LocationRaids = 9,
|
||||
LocationArenas = 10,
|
||||
LocationBattlegrounds = 11,
|
||||
AllMovement = 12,
|
||||
MovementUnmounted = 13,
|
||||
MovementSwimming = 14,
|
||||
MovementGroundMount = 15,
|
||||
MovementFlyingMount = 16,
|
||||
AllEquipmentSets = 17,
|
||||
EquipmentSets = 18,
|
||||
AllRacialForms = 19,
|
||||
FormNative = 20,
|
||||
FormNonNative = 21,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
enum class TransmogSituationFlags : int32
|
||||
{
|
||||
IsPlayerFacing = 0x01,
|
||||
SpecUseTalentLoadout = 0x02,
|
||||
AllSituation = 0x04,
|
||||
DefaultsToOn = 0x08,
|
||||
DynamicallyNamed = 0x10,
|
||||
NoneSituation = 0x20,
|
||||
DisabledSituation = 0x40
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(TransmogSituationFlags);
|
||||
|
||||
enum class TransmogSituationTrigger : uint8
|
||||
{
|
||||
None = 0,
|
||||
Manual = 1,
|
||||
TransmogUpdate = 2,
|
||||
Location = 3,
|
||||
Movement = 4,
|
||||
Specialization = 5,
|
||||
EquipmentSet = 6,
|
||||
Forms = 7,
|
||||
EventOutfit = 8,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
enum class TransmogSituationTriggerFlags : int32
|
||||
{
|
||||
CanLockOutfit = 0x01,
|
||||
CanChangeLockedOutfit = 0x02,
|
||||
IsPlayerFacing = 0x04,
|
||||
SituationsAreExclusive = 0x08,
|
||||
DisabledTrigger = 0x10
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(TransmogSituationTriggerFlags);
|
||||
|
||||
// SummonProperties.dbc, col 1
|
||||
enum SummonPropGroup
|
||||
{
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "SpellMgr.h"
|
||||
#include "StringConvert.h"
|
||||
#include "TradeData.h"
|
||||
#include "TransmogMgr.h"
|
||||
#include "UpdateData.h"
|
||||
#include "World.h"
|
||||
#include "WorldSession.h"
|
||||
@@ -2010,51 +2011,6 @@ bool Item::IsValidTransmogrificationTarget() const
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class ItemTransmogrificationWeaponCategory : uint8
|
||||
{
|
||||
// Two-handed
|
||||
MELEE_2H,
|
||||
RANGED,
|
||||
|
||||
// One-handed
|
||||
AXE_MACE_SWORD_1H,
|
||||
DAGGER,
|
||||
|
||||
INVALID
|
||||
};
|
||||
|
||||
static ItemTransmogrificationWeaponCategory GetTransmogrificationWeaponCategory(ItemTemplate const* proto)
|
||||
{
|
||||
if (proto->GetClass() == ITEM_CLASS_WEAPON)
|
||||
{
|
||||
switch (proto->GetSubClass())
|
||||
{
|
||||
case ITEM_SUBCLASS_WEAPON_AXE2:
|
||||
case ITEM_SUBCLASS_WEAPON_MACE2:
|
||||
case ITEM_SUBCLASS_WEAPON_SWORD2:
|
||||
case ITEM_SUBCLASS_WEAPON_STAFF:
|
||||
case ITEM_SUBCLASS_WEAPON_POLEARM:
|
||||
return ItemTransmogrificationWeaponCategory::MELEE_2H;
|
||||
case ITEM_SUBCLASS_WEAPON_BOW:
|
||||
case ITEM_SUBCLASS_WEAPON_GUN:
|
||||
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
|
||||
return ItemTransmogrificationWeaponCategory::RANGED;
|
||||
case ITEM_SUBCLASS_WEAPON_AXE:
|
||||
case ITEM_SUBCLASS_WEAPON_MACE:
|
||||
case ITEM_SUBCLASS_WEAPON_SWORD:
|
||||
case ITEM_SUBCLASS_WEAPON_WARGLAIVES:
|
||||
case ITEM_SUBCLASS_WEAPON_FIST_WEAPON:
|
||||
return ItemTransmogrificationWeaponCategory::AXE_MACE_SWORD_1H;
|
||||
case ITEM_SUBCLASS_WEAPON_DAGGER:
|
||||
return ItemTransmogrificationWeaponCategory::DAGGER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ItemTransmogrificationWeaponCategory::INVALID;
|
||||
}
|
||||
|
||||
int32 const ItemTransmogrificationSlots[MAX_INVTYPE] =
|
||||
{
|
||||
-1, // INVTYPE_NON_EQUIP
|
||||
@@ -2124,7 +2080,7 @@ bool Item::CanTransmogrifyItemWithItem(Item const* item, ItemModifiedAppearanceE
|
||||
switch (source->GetClass())
|
||||
{
|
||||
case ITEM_CLASS_WEAPON:
|
||||
if (GetTransmogrificationWeaponCategory(source) != GetTransmogrificationWeaponCategory(target))
|
||||
if (source->GetWeaponTransmogOutfitSlotOption() != target->GetWeaponTransmogOutfitSlotOption())
|
||||
return false;
|
||||
break;
|
||||
case ITEM_CLASS_ARMOR:
|
||||
@@ -2495,16 +2451,20 @@ uint32 Item::GetDisplayId(Player const* owner) const
|
||||
if (!itemModifiedAppearanceId)
|
||||
itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
|
||||
|
||||
if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId))
|
||||
if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(transmog->ItemAppearanceID))
|
||||
ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId);
|
||||
if (!itemModifiedAppearance)
|
||||
itemModifiedAppearance = GetItemModifiedAppearance();
|
||||
|
||||
if (itemModifiedAppearance)
|
||||
if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(itemModifiedAppearance->ItemAppearanceID))
|
||||
return itemAppearance->ItemDisplayInfoID;
|
||||
|
||||
return sDB2Manager.GetItemDisplayId(GetEntry(), GetAppearanceModId());
|
||||
return 0;
|
||||
}
|
||||
|
||||
ItemModifiedAppearanceEntry const* Item::GetItemModifiedAppearance() const
|
||||
{
|
||||
return sDB2Manager.GetItemModifiedAppearance(GetEntry(), _bonusData.AppearanceModID);
|
||||
return TransmogMgr::GetItemModifiedAppearance(GetEntry(), _bonusData.AppearanceModID);
|
||||
}
|
||||
|
||||
uint32 Item::GetModifier(ItemModifier modifier) const
|
||||
|
||||
@@ -297,3 +297,49 @@ std::size_t ItemTemplate::CalculateItemSpecBit(ChrSpecializationEntry const* spe
|
||||
{
|
||||
return (spec->ClassID - 1) * MAX_SPECIALIZATIONS + spec->OrderIndex;
|
||||
}
|
||||
|
||||
TransmogOutfitSlotOption ItemTemplate::GetWeaponTransmogOutfitSlotOption() const
|
||||
{
|
||||
switch (GetClass())
|
||||
{
|
||||
case ITEM_CLASS_WEAPON:
|
||||
switch (GetSubClass())
|
||||
{
|
||||
case ITEM_SUBCLASS_WEAPON_AXE2:
|
||||
case ITEM_SUBCLASS_WEAPON_MACE2:
|
||||
case ITEM_SUBCLASS_WEAPON_SWORD2:
|
||||
case ITEM_SUBCLASS_WEAPON_STAFF:
|
||||
case ITEM_SUBCLASS_WEAPON_POLEARM:
|
||||
return TransmogOutfitSlotOption::TwoHandedWeapon;
|
||||
case ITEM_SUBCLASS_WEAPON_BOW:
|
||||
case ITEM_SUBCLASS_WEAPON_GUN:
|
||||
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
|
||||
return TransmogOutfitSlotOption::RangedWeapon;
|
||||
case ITEM_SUBCLASS_WEAPON_AXE:
|
||||
case ITEM_SUBCLASS_WEAPON_MACE:
|
||||
case ITEM_SUBCLASS_WEAPON_SWORD:
|
||||
case ITEM_SUBCLASS_WEAPON_WARGLAIVES:
|
||||
case ITEM_SUBCLASS_WEAPON_FIST_WEAPON:
|
||||
case ITEM_SUBCLASS_WEAPON_DAGGER:
|
||||
return TransmogOutfitSlotOption::OneHandedWeapon;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ITEM_CLASS_ARMOR:
|
||||
switch (GetInventoryType())
|
||||
{
|
||||
case INVTYPE_SHIELD:
|
||||
return TransmogOutfitSlotOption::Shield;
|
||||
case INVTYPE_HOLDABLE:
|
||||
return TransmogOutfitSlotOption::OffHand;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TransmogOutfitSlotOption::None;
|
||||
}
|
||||
|
||||
@@ -967,6 +967,7 @@ struct TC_GAME_API ItemTemplate
|
||||
void GetDamage(uint32 itemLevel, float& minDamage, float& maxDamage) const;
|
||||
bool IsUsableByLootSpecialization(Player const* player, bool alwaysAllowBoundToAccount) const;
|
||||
static std::size_t CalculateItemSpecBit(ChrSpecializationEntry const* spec);
|
||||
TransmogOutfitSlotOption GetWeaponTransmogOutfitSlotOption() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -882,7 +882,7 @@ void VisibleItem::WriteCreate(ByteBuffer& data, Player const* receiver, Unit con
|
||||
data << uint16(ItemAppearanceModID);
|
||||
data << uint16(ItemVisual);
|
||||
data << uint32(ItemModifiedAppearanceID);
|
||||
data << uint8(Field_18);
|
||||
data << uint8(TransmogSlotOption);
|
||||
data.WriteBit(HasTransmog);
|
||||
data.WriteBit(HasIllusion);
|
||||
data.FlushBits();
|
||||
@@ -936,7 +936,7 @@ void VisibleItem::WriteUpdate(bool ignoreChangesMask, ByteBuffer& data, Player c
|
||||
}
|
||||
if (changesMask[9])
|
||||
{
|
||||
data << uint8(Field_18);
|
||||
data << uint8(TransmogSlotOption);
|
||||
}
|
||||
}
|
||||
data.FlushBits();
|
||||
@@ -952,7 +952,7 @@ void VisibleItem::ClearChangesMask()
|
||||
Base::ClearChangesMask(ItemAppearanceModID);
|
||||
Base::ClearChangesMask(ItemVisual);
|
||||
Base::ClearChangesMask(ItemModifiedAppearanceID);
|
||||
Base::ClearChangesMask(Field_18);
|
||||
Base::ClearChangesMask(TransmogSlotOption);
|
||||
_changesMask.ResetAll();
|
||||
}
|
||||
|
||||
@@ -5444,7 +5444,7 @@ void ActivePlayerData::WriteCreate(EnumFlag<UpdateFieldFlag> fieldVisibilityFlag
|
||||
data << uint32(HouseThemes.size());
|
||||
data << uint32(HouseRoomComponentTextures.size());
|
||||
data << uint32(HouseTypes.size());
|
||||
data << uint32(Field_1980.size());
|
||||
data << uint32(UnlockedTransmogOutfits.size());
|
||||
data << uint32(CharacterRestrictions.size());
|
||||
data << uint32(SpellPctModByLabel.size());
|
||||
data << uint32(SpellFlatModByLabel.size());
|
||||
@@ -5563,9 +5563,9 @@ void ActivePlayerData::WriteCreate(EnumFlag<UpdateFieldFlag> fieldVisibilityFlag
|
||||
{
|
||||
data << uint32(HouseTypes[i]);
|
||||
}
|
||||
for (uint32 i = 0; i < Field_1980.size(); ++i)
|
||||
for (uint32 i = 0; i < UnlockedTransmogOutfits.size(); ++i)
|
||||
{
|
||||
data << int32(Field_1980[i]);
|
||||
data << int32(UnlockedTransmogOutfits[i]);
|
||||
}
|
||||
for (uint32 i = 0; i < SpellPctModByLabel.size(); ++i)
|
||||
{
|
||||
@@ -5979,9 +5979,9 @@ void ActivePlayerData::WriteUpdate(Mask const& changesMask, ByteBuffer& data, Pl
|
||||
if (changesMask[29])
|
||||
{
|
||||
if (!ignoreNestedChangesMask)
|
||||
Field_1980.WriteUpdateMask(data);
|
||||
UnlockedTransmogOutfits.WriteUpdateMask(data);
|
||||
else
|
||||
WriteCompleteDynamicFieldUpdateMask(Field_1980.size(), data);
|
||||
WriteCompleteDynamicFieldUpdateMask(UnlockedTransmogOutfits.size(), data);
|
||||
}
|
||||
if (changesMask[30])
|
||||
{
|
||||
@@ -6321,11 +6321,11 @@ void ActivePlayerData::WriteUpdate(Mask const& changesMask, ByteBuffer& data, Pl
|
||||
}
|
||||
if (changesMask[29])
|
||||
{
|
||||
for (uint32 i = 0; i < Field_1980.size(); ++i)
|
||||
for (uint32 i = 0; i < UnlockedTransmogOutfits.size(); ++i)
|
||||
{
|
||||
if (Field_1980.HasChanged(i) || ignoreNestedChangesMask)
|
||||
if (UnlockedTransmogOutfits.HasChanged(i) || ignoreNestedChangesMask)
|
||||
{
|
||||
data << int32(Field_1980[i]);
|
||||
data << int32(UnlockedTransmogOutfits[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7158,7 +7158,7 @@ void ActivePlayerData::ClearChangesMask()
|
||||
Base::ClearChangesMask(HouseThemes);
|
||||
Base::ClearChangesMask(HouseRoomComponentTextures);
|
||||
Base::ClearChangesMask(HouseTypes);
|
||||
Base::ClearChangesMask(Field_1980);
|
||||
Base::ClearChangesMask(UnlockedTransmogOutfits);
|
||||
Base::ClearChangesMask(SpellPctModByLabel);
|
||||
Base::ClearChangesMask(SpellFlatModByLabel);
|
||||
Base::ClearChangesMask(SpellPctModPVPByLabel);
|
||||
|
||||
@@ -262,7 +262,7 @@ struct VisibleItem : public IsUpdateFieldStructureTag, public HasChangesMask<10>
|
||||
UpdateField<uint16, 0, 6> ItemAppearanceModID;
|
||||
UpdateField<uint16, 0, 7> ItemVisual;
|
||||
UpdateField<uint32, 0, 8> ItemModifiedAppearanceID;
|
||||
UpdateField<uint8, 0, 9> Field_18;
|
||||
UpdateField<uint8, 0, 9> TransmogSlotOption;
|
||||
|
||||
using OwnerObject = Unit;
|
||||
void WriteCreate(ByteBuffer& data, Player const* receiver, Unit const* owner) const;
|
||||
@@ -1311,7 +1311,7 @@ struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMas
|
||||
DynamicUpdateField<uint32, 0, 26> HouseThemes;
|
||||
DynamicUpdateField<uint32, 0, 27> HouseRoomComponentTextures;
|
||||
DynamicUpdateField<uint32, 0, 28> HouseTypes;
|
||||
DynamicUpdateField<int32, 0, 29> Field_1980;
|
||||
DynamicUpdateField<int32, 0, 29> UnlockedTransmogOutfits;
|
||||
DynamicUpdateField<UF::SpellPctModByLabel, 0, 31> SpellPctModByLabel;
|
||||
DynamicUpdateField<UF::SpellFlatModByLabel, 32, 33> SpellFlatModByLabel;
|
||||
DynamicUpdateField<UF::SpellPctPVPModByLabel, 32, 34> SpellPctModPVPByLabel;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "Timer.h"
|
||||
#include "TransmogMgr.h"
|
||||
#include "TransmogrificationPackets.h"
|
||||
#include "WorldSession.h"
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
@@ -95,12 +96,36 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
CollectionMgr::CollectionMgr(WorldSession* owner) : _owner(owner), _appearances(std::make_unique<boost::dynamic_bitset<uint32>>()), _transmogIllusions(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>>())
|
||||
{
|
||||
}
|
||||
|
||||
CollectionMgr::~CollectionMgr() = default;
|
||||
|
||||
void CollectionMgr::LoadCharacterData()
|
||||
{
|
||||
LoadToys();
|
||||
LoadHeirlooms();
|
||||
LoadMounts();
|
||||
LoadItemAppearances();
|
||||
LoadTransmogIllusions();
|
||||
LoadTransmogOutfits();
|
||||
LoadWarbandScenes();
|
||||
}
|
||||
|
||||
void CollectionMgr::SaveToDB(LoginDatabaseTransaction trans)
|
||||
{
|
||||
SaveAccountToys(trans);
|
||||
SaveAccountHeirlooms(trans);
|
||||
SaveAccountMounts(trans);
|
||||
SaveAccountItemAppearances(trans);
|
||||
SaveAccountTransmogIllusions(trans);
|
||||
SaveAccountTransmogOutfits(trans);
|
||||
SaveAccountWarbandScenes(trans);
|
||||
}
|
||||
|
||||
void CollectionMgr::LoadToys()
|
||||
{
|
||||
for (auto const& [itemId, flags] : _toys)
|
||||
@@ -529,7 +554,7 @@ void CollectionMgr::LoadAccountItemAppearances(PreparedQueryResult knownAppearan
|
||||
|
||||
for (uint32 hiddenItem : hiddenAppearanceItems)
|
||||
{
|
||||
ItemModifiedAppearanceEntry const* hiddenAppearance = sDB2Manager.GetItemModifiedAppearance(hiddenItem, 0);
|
||||
ItemModifiedAppearanceEntry const* hiddenAppearance = TransmogMgr::GetDefaultItemModifiedAppearance(hiddenItem);
|
||||
ASSERT(hiddenAppearance);
|
||||
if (_appearances->size() <= hiddenAppearance->ID)
|
||||
_appearances->resize(hiddenAppearance->ID + 1);
|
||||
@@ -603,7 +628,7 @@ void CollectionMgr::AddItemAppearance(Item* item)
|
||||
|
||||
void CollectionMgr::AddItemAppearance(uint32 itemId, uint32 appearanceModId /*= 0*/)
|
||||
{
|
||||
ItemModifiedAppearanceEntry const* itemModifiedAppearance = sDB2Manager.GetItemModifiedAppearance(itemId, appearanceModId);
|
||||
ItemModifiedAppearanceEntry const* itemModifiedAppearance = TransmogMgr::GetItemModifiedAppearance(itemId, appearanceModId);
|
||||
if (!CanAddAppearance(itemModifiedAppearance))
|
||||
return;
|
||||
|
||||
@@ -612,11 +637,7 @@ void CollectionMgr::AddItemAppearance(uint32 itemId, uint32 appearanceModId /*=
|
||||
|
||||
void CollectionMgr::AddTransmogSet(uint32 transmogSetId)
|
||||
{
|
||||
std::vector<TransmogSetItemEntry const*> const* items = sDB2Manager.GetTransmogSetItems(transmogSetId);
|
||||
if (!items)
|
||||
return;
|
||||
|
||||
for (TransmogSetItemEntry const* item : *items)
|
||||
for (TransmogSetItemEntry const* item : TransmogMgr::GetTransmogSetItems(transmogSetId))
|
||||
{
|
||||
ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(item->ItemModifiedAppearanceID);
|
||||
if (!itemModifiedAppearance)
|
||||
@@ -628,13 +649,13 @@ void CollectionMgr::AddTransmogSet(uint32 transmogSetId)
|
||||
|
||||
bool CollectionMgr::IsSetCompleted(uint32 transmogSetId) const
|
||||
{
|
||||
std::vector<TransmogSetItemEntry const*> const* transmogSetItems = sDB2Manager.GetTransmogSetItems(transmogSetId);
|
||||
if (!transmogSetItems)
|
||||
std::span<TransmogSetItemEntry const* const> transmogSetItems = TransmogMgr::GetTransmogSetItems(transmogSetId);
|
||||
if (transmogSetItems.empty())
|
||||
return false;
|
||||
|
||||
std::array<int8, EQUIPMENT_SLOT_END> knownPieces;
|
||||
knownPieces.fill(-1);
|
||||
for (TransmogSetItemEntry const* transmogSetItem : *transmogSetItems)
|
||||
for (TransmogSetItemEntry const* transmogSetItem : transmogSetItems)
|
||||
{
|
||||
ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(transmogSetItem->ItemModifiedAppearanceID);
|
||||
if (!itemModifiedAppearance)
|
||||
@@ -756,20 +777,16 @@ void CollectionMgr::AddItemAppearance(ItemModifiedAppearanceEntry const* itemMod
|
||||
owner->UpdateCriteria(CriteriaType::LearnAnyTransmogInSlot, transmogSlot, itemModifiedAppearance->ID);
|
||||
}
|
||||
|
||||
if (std::vector<TransmogSetEntry const*> const* sets = sDB2Manager.GetTransmogSetsForItemModifiedAppearance(itemModifiedAppearance->ID))
|
||||
{
|
||||
for (TransmogSetEntry const* set : *sets)
|
||||
for (TransmogSetEntry const* set : TransmogMgr::GetTransmogSetsForItemModifiedAppearance(itemModifiedAppearance->ID))
|
||||
{
|
||||
if (IsSetCompleted(set->ID))
|
||||
{
|
||||
|
||||
if (Quest const* quest = sObjectMgr->GetQuestTemplate(set->TrackingQuestID))
|
||||
owner->RewardQuest(quest, LootItemType::Item, 0, owner, false);
|
||||
|
||||
owner->UpdateCriteria(CriteriaType::CollectTransmogSetFromGroup, set->TransmogSetGroupID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollectionMgr::AddTemporaryAppearance(ObjectGuid const& itemGuid, ItemModifiedAppearanceEntry const* itemModifiedAppearance)
|
||||
@@ -966,6 +983,55 @@ bool CollectionMgr::HasTransmogIllusion(uint32 transmogIllusionId) const
|
||||
return transmogIllusionId < _transmogIllusions->size() && _transmogIllusions->test(transmogIllusionId);
|
||||
}
|
||||
|
||||
void CollectionMgr::LoadTransmogOutfits()
|
||||
{
|
||||
_owner->GetPlayer()->AddUnlockedTransmogOutfits(_transmogOutfits);
|
||||
}
|
||||
|
||||
void CollectionMgr::LoadAccountTransmogOutfits(PreparedQueryResult unlockedTransmogOutfits)
|
||||
{
|
||||
if (unlockedTransmogOutfits)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = unlockedTransmogOutfits->Fetch();
|
||||
|
||||
int32 transmogOutfitId = fields[0].GetInt32();
|
||||
|
||||
if (!sTransmogOutfitEntryStore.HasRecord(transmogOutfitId))
|
||||
continue;
|
||||
|
||||
_transmogOutfits.insert(transmogOutfitId);
|
||||
|
||||
} while (unlockedTransmogOutfits->NextRow());
|
||||
}
|
||||
|
||||
for (TransmogOutfitEntryEntry const* transmogOutfitEntry : TransmogMgr::GetAutomaticallyUnlockedOutfits())
|
||||
_transmogOutfits.insert(transmogOutfitEntry->ID);
|
||||
}
|
||||
|
||||
void CollectionMgr::SaveAccountTransmogOutfits(LoginDatabaseTransaction trans)
|
||||
{
|
||||
for (int32 transmogOutfitId : _transmogOutfits)
|
||||
{
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_TRANSMOG_OUTFITS);
|
||||
stmt->setUInt32(0, _owner->GetBattlenetAccountId());
|
||||
stmt->setInt32(1, transmogOutfitId);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
void CollectionMgr::AddTransmogOutfit(int32 transmogOutfitId)
|
||||
{
|
||||
if (_transmogOutfits.insert(transmogOutfitId).second)
|
||||
_owner->GetPlayer()->AddUnlockedTransmogOutfit(transmogOutfitId);
|
||||
}
|
||||
|
||||
bool CollectionMgr::HasTransmogOutfit(int32 transmogOutfitId) const
|
||||
{
|
||||
return _transmogOutfits.contains(transmogOutfitId);
|
||||
}
|
||||
|
||||
void CollectionMgr::LoadWarbandScenes()
|
||||
{
|
||||
Player* owner = _owner->GetPlayer();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "Define.h"
|
||||
#include "DatabaseEnvFwd.h"
|
||||
#include "EnumFlag.h"
|
||||
#include "FlatSet.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include <boost/dynamic_bitset_fwd.hpp>
|
||||
#include <map>
|
||||
@@ -117,6 +118,9 @@ public:
|
||||
static void LoadMountDefinitions();
|
||||
static void LoadWarbandSceneDefinitions();
|
||||
|
||||
void LoadCharacterData();
|
||||
void SaveToDB(LoginDatabaseTransaction trans);
|
||||
|
||||
// Account-wide toys
|
||||
void LoadToys();
|
||||
void LoadAccountToys(PreparedQueryResult result);
|
||||
@@ -179,6 +183,12 @@ public:
|
||||
void AddTransmogIllusion(uint32 transmogIllusionId);
|
||||
bool HasTransmogIllusion(uint32 transmogIllusionId) const;
|
||||
|
||||
void LoadTransmogOutfits();
|
||||
void LoadAccountTransmogOutfits(PreparedQueryResult unlockedTransmogOutfits);
|
||||
void SaveAccountTransmogOutfits(LoginDatabaseTransaction trans);
|
||||
void AddTransmogOutfit(int32 transmogOutfitId);
|
||||
bool HasTransmogOutfit(int32 transmogOutfitId) const;
|
||||
|
||||
// Warband Scenes
|
||||
void LoadWarbandScenes();
|
||||
void LoadAccountWarbandScenes(PreparedQueryResult knownWarbandScenes);
|
||||
@@ -204,6 +214,7 @@ private:
|
||||
std::unordered_map<uint32, std::unordered_set<ObjectGuid>> _temporaryAppearances;
|
||||
std::unordered_map<uint32, CollectionItemState> _favoriteAppearances;
|
||||
std::unique_ptr<boost::dynamic_bitset<uint32>> _transmogIllusions;
|
||||
Trinity::Containers::FlatSet<int32> _transmogOutfits;
|
||||
WarbandSceneCollectionContainer _warbandScenes;
|
||||
};
|
||||
|
||||
|
||||
@@ -131,6 +131,8 @@
|
||||
#include "TradeData.h"
|
||||
#include "TraitMgr.h"
|
||||
#include "TraitPacketsCommon.h"
|
||||
#include "TransmogMgr.h"
|
||||
#include "TransmogrificationPackets.h"
|
||||
#include "Transport.h"
|
||||
#include "UpdateData.h"
|
||||
#include "Util.h"
|
||||
@@ -559,6 +561,8 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac
|
||||
|
||||
GetThreatManager().Initialize();
|
||||
|
||||
EquipTransmogOutfit(0, TransmogSituationTrigger::Manual, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4146,6 +4150,18 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
|
||||
stmt->setUInt64(0, guid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFIT_SITUATION_BY_CHAR);
|
||||
stmt->setUInt64(0, guid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFIT_SLOT_BY_CHAR);
|
||||
stmt->setUInt64(0, guid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TRANSMOG_OUTFIT_BY_CHAR);
|
||||
stmt->setUInt64(0, guid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER);
|
||||
stmt->setUInt64(0, guid);
|
||||
stmt->setUInt64(1, guid);
|
||||
@@ -4521,19 +4537,10 @@ Corpse* Player::CreateCorpse()
|
||||
corpse->SetFactionTemplate(sChrRacesStore.AssertEntry(GetRace())->FactionID);
|
||||
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++)
|
||||
{
|
||||
if (m_items[i])
|
||||
{
|
||||
uint32 itemDisplayId = m_items[i]->GetDisplayId(this);
|
||||
uint32 itemInventoryType;
|
||||
if (ItemEntry const* itemEntry = sItemStore.LookupEntry(m_items[i]->GetVisibleEntry(this)))
|
||||
itemInventoryType = itemEntry->InventoryType;
|
||||
else
|
||||
itemInventoryType = m_items[i]->GetTemplate()->GetInventoryType();
|
||||
|
||||
corpse->SetItem(i, itemDisplayId | (itemInventoryType << 24));
|
||||
}
|
||||
}
|
||||
if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(m_playerData->VisibleItems[i].ItemModifiedAppearanceID))
|
||||
if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(itemModifiedAppearance->ItemAppearanceID))
|
||||
if (ItemEntry const* item = sItemStore.LookupEntry(itemModifiedAppearance->ItemID))
|
||||
corpse->SetItem(i, itemAppearance->ItemDisplayInfoID | int32(item->InventoryType) << 24);
|
||||
|
||||
// register for player, but not show
|
||||
GetMap()->AddCorpse(corpse);
|
||||
@@ -6176,6 +6183,7 @@ bool Player::IsActionButtonDataValid(uint8 button, uint64 action, uint8 type) co
|
||||
case ACTION_BUTTON_MACRO:
|
||||
case ACTION_BUTTON_EQSET:
|
||||
case ACTION_BUTTON_DROPDOWN:
|
||||
case ACTION_BUTTON_OUTFIT:
|
||||
break;
|
||||
default:
|
||||
TC_LOG_ERROR("entities.player", "Player::IsActionButtonDataValid: Unknown action type {}", type);
|
||||
@@ -11825,25 +11833,123 @@ void Player::QuickEquipItem(uint16 pos, Item* pItem)
|
||||
}
|
||||
}
|
||||
|
||||
void Player::SetVisibleItemSlot(uint8 slot, Item* pItem)
|
||||
void Player::SetVisibleItemSlot(uint8 slot, Item const* item)
|
||||
{
|
||||
auto itemField = m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::VisibleItems, slot);
|
||||
if (pItem)
|
||||
auto setVisibleItemSlot = [this](uint32 slot, int32 itemId, int32 secondaryItemModifiedAppearanceId, int32 conditionalItemAppearanceId,
|
||||
uint16 itemAppearanceModId, uint16 itemVisual, uint32 itemModifiedAppearanceId, TransmogOutfitSlotOption transmogSlotOption,
|
||||
bool hasTransmog, bool hasIllusion)
|
||||
{
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemID), pItem->GetVisibleEntry(this));
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::SecondaryItemModifiedAppearanceID), pItem->GetVisibleSecondaryModifiedAppearanceId(this));
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemAppearanceModID), pItem->GetVisibleAppearanceModId(this));
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemVisual), pItem->GetVisibleItemVisual(this));
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemModifiedAppearanceID), pItem->GetVisibleModifiedAppearanceId(this));
|
||||
auto itemField = m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::VisibleItems, slot);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemID), itemId);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::SecondaryItemModifiedAppearanceID), secondaryItemModifiedAppearanceId);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ConditionalItemAppearanceID), conditionalItemAppearanceId);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemAppearanceModID), itemAppearanceModId);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemVisual), itemVisual);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemModifiedAppearanceID), itemModifiedAppearanceId);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::TransmogSlotOption), AsUnderlyingType(transmogSlotOption));
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::HasTransmog), hasTransmog);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::HasIllusion), hasIllusion);
|
||||
|
||||
auto transmogMetadata = m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::TransmogMetadata);
|
||||
if (slot == EQUIPMENT_SLOT_MAINHAND)
|
||||
SetUpdateFieldValue(transmogMetadata.ModifyValue(&UF::TransmogOutfitMetadata::StampedOptionMainHand), AsUnderlyingType(transmogSlotOption));
|
||||
else if (slot == EQUIPMENT_SLOT_OFFHAND)
|
||||
SetUpdateFieldValue(transmogMetadata.ModifyValue(&UF::TransmogOutfitMetadata::StampedOptionOffHand), AsUnderlyingType(transmogSlotOption));
|
||||
};
|
||||
|
||||
if (item)
|
||||
{
|
||||
TransmogOutfitSlotOption transmogSlotOption = item->GetTemplate()->GetWeaponTransmogOutfitSlotOption();
|
||||
if (transmogSlotOption == TransmogOutfitSlotOption::TwoHandedWeapon && CanTitanGrip())
|
||||
transmogSlotOption = TransmogOutfitSlotOption::FuryTwoHandedWeapon;
|
||||
|
||||
int32 itemId = item->GetVisibleEntry(this);
|
||||
int32 secondaryItemModifiedAppearanceId = item->GetVisibleSecondaryModifiedAppearanceId(this);
|
||||
int32 conditionalItemAppearanceId = 0;
|
||||
uint16 itemAppearanceModId = item->GetVisibleAppearanceModId(this);
|
||||
uint16 itemVisual = item->GetVisibleItemVisual(this);
|
||||
uint32 itemModifiedAppearanceId = item->GetVisibleModifiedAppearanceId(this);
|
||||
bool hasTransmog = false;
|
||||
bool hasIllusion = false;
|
||||
|
||||
if (!m_activePlayerData->ViewedOutfit->Slots.empty())
|
||||
{
|
||||
TransmogMgr::TransmogOutfitSlotAndOptionInfo const* slotInfo = TransmogMgr::GetSlotAndOption(EquipmentSlots(slot), transmogSlotOption);
|
||||
if (transmogSlotOption != TransmogOutfitSlotOption::None)
|
||||
{
|
||||
// check if artifact override is active
|
||||
TransmogOutfitSlotOption artifactOption = static_cast<TransmogOutfitSlotOption>(AsUnderlyingType(TransmogOutfitSlotOption::ArtifactSpecOne) + GetPrimarySpecializationEntry()->OrderIndex);
|
||||
TransmogMgr::TransmogOutfitSlotAndOptionInfo const* artifactSlotInfo = TransmogMgr::GetSlotAndOption(EquipmentSlots(slot), artifactOption);
|
||||
if (artifactSlotInfo && static_cast<TransmogOutfitDisplayType>(*m_activePlayerData->ViewedOutfit->Slots[artifactSlotInfo->SlotIndex].AppearanceDisplayType) == TransmogOutfitDisplayType::Assigned)
|
||||
{
|
||||
transmogSlotOption = artifactOption;
|
||||
slotInfo = artifactSlotInfo;
|
||||
}
|
||||
}
|
||||
|
||||
if (slotInfo)
|
||||
{
|
||||
auto isTransmogDisplayed = [](TransmogOutfitDisplayType displayType)
|
||||
{
|
||||
return displayType == TransmogOutfitDisplayType::Assigned || displayType == TransmogOutfitDisplayType::Hidden;
|
||||
};
|
||||
|
||||
UF::TransmogOutfitSlotData const& transmogOutfitItem = m_activePlayerData->ViewedOutfit->Slots[slotInfo->SlotIndex];
|
||||
if (isTransmogDisplayed(static_cast<TransmogOutfitDisplayType>(*transmogOutfitItem.AppearanceDisplayType)))
|
||||
{
|
||||
if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(transmogOutfitItem.ItemModifiedAppearanceID))
|
||||
{
|
||||
itemId = itemModifiedAppearance->ItemID;
|
||||
itemAppearanceModId = itemModifiedAppearance->ItemAppearanceModifierID;
|
||||
itemModifiedAppearanceId = itemModifiedAppearance->ID;
|
||||
}
|
||||
|
||||
hasTransmog = true;
|
||||
}
|
||||
|
||||
if (TransmogOutfitSlotInfoEntry const* secondarySlot = sTransmogOutfitSlotInfoStore.LookupEntry(slotInfo->Slot->SecondarySlotID))
|
||||
{
|
||||
if (TransmogMgr::TransmogOutfitSlotAndOptionInfo const* secondarySlotInfo = TransmogMgr::GetSlotAndOption(secondarySlot->GetSlot(), transmogSlotOption))
|
||||
{
|
||||
UF::TransmogOutfitSlotData const& secondaryTransmogOutfitItem = m_activePlayerData->ViewedOutfit->Slots[secondarySlotInfo->SlotIndex];
|
||||
if (isTransmogDisplayed(static_cast<TransmogOutfitDisplayType>(*secondaryTransmogOutfitItem.AppearanceDisplayType))
|
||||
|| static_cast<TransmogOutfitDisplayType>(*secondaryTransmogOutfitItem.AppearanceDisplayType) == TransmogOutfitDisplayType::Equipped)
|
||||
{
|
||||
secondaryItemModifiedAppearanceId = secondaryTransmogOutfitItem.ItemModifiedAppearanceID;
|
||||
hasTransmog = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TransmogOutfitSlotOptionEntry const* secondarySlotOption = sTransmogOutfitSlotOptionInfoStore.LookupEntry(slotInfo->SlotOption ? slotInfo->SlotOption->SecondaryOptionID : 0))
|
||||
{
|
||||
if (TransmogMgr::TransmogOutfitSlotAndOptionInfo const* secondarySlotInfo = TransmogMgr::GetSlotAndOption(slotInfo->Slot->GetSlot(), secondarySlotOption->GetOption()))
|
||||
{
|
||||
UF::TransmogOutfitSlotData const& secondaryTransmogOutfitItem = m_activePlayerData->ViewedOutfit->Slots[secondarySlotInfo->SlotIndex];
|
||||
if (isTransmogDisplayed(static_cast<TransmogOutfitDisplayType>(*secondaryTransmogOutfitItem.AppearanceDisplayType))
|
||||
|| static_cast<TransmogOutfitDisplayType>(*secondaryTransmogOutfitItem.AppearanceDisplayType) == TransmogOutfitDisplayType::Equipped)
|
||||
{
|
||||
secondaryItemModifiedAppearanceId = secondaryTransmogOutfitItem.ItemModifiedAppearanceID;
|
||||
hasTransmog = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isTransmogDisplayed(static_cast<TransmogOutfitDisplayType>(*transmogOutfitItem.IllusionDisplayType)))
|
||||
{
|
||||
if (SpellItemEnchantmentEntry const* spellItemEnchantment = sSpellItemEnchantmentStore.LookupEntry(transmogOutfitItem.SpellItemEnchantmentID))
|
||||
itemVisual = spellItemEnchantment->ItemVisual;
|
||||
|
||||
hasIllusion = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setVisibleItemSlot(slot, itemId, secondaryItemModifiedAppearanceId, conditionalItemAppearanceId, itemAppearanceModId,
|
||||
itemVisual, itemModifiedAppearanceId, transmogSlotOption, hasTransmog, hasIllusion);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemID), 0);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::SecondaryItemModifiedAppearanceID), 0);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemAppearanceModID), 0);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemVisual), 0);
|
||||
SetUpdateFieldValue(itemField.ModifyValue(&UF::VisibleItem::ItemModifiedAppearanceID), 0);
|
||||
}
|
||||
setVisibleItemSlot(slot, 0, 0, 0, 0, 0, 0, TransmogOutfitSlotOption::None, false, false);
|
||||
}
|
||||
|
||||
void Player::VisualizeItem(uint8 slot, Item* pItem)
|
||||
@@ -17579,7 +17685,7 @@ void Player::_LoadEquipmentSets(PreparedQueryResult result)
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
void Player::_LoadTransmogOutfits(PreparedQueryResult result)
|
||||
void Player::_LoadTransmogCustomSets(PreparedQueryResult result)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
//SELECT setguid, setindex, name, iconname, ignore_mask, appearance0, appearance1, appearance2, appearance3, appearance4,
|
||||
@@ -17616,6 +17722,153 @@ void Player::_LoadTransmogOutfits(PreparedQueryResult result)
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
void Player::_LoadTransmogOutfits(PreparedQueryResult setsResult, PreparedQueryResult situationsResult, PreparedQueryResult slotsResult,
|
||||
int32 equippedTransmogOutfitId, bool locked)
|
||||
{
|
||||
struct SetData
|
||||
{
|
||||
std::vector<WorldPackets::Transmogrification::TransmogOutfitSituationInfo> situations;
|
||||
std::vector<WorldPackets::Transmogrification::TransmogOutfitSlotData> slots;
|
||||
};
|
||||
|
||||
std::unordered_map<uint32, SetData> sets;
|
||||
|
||||
// SELECT transmogOutfitId, situationID, specID, loadoutID, equipmentSetID FROM character_transmog_outfit_situation WHERE guid = ?
|
||||
if (situationsResult)
|
||||
{
|
||||
do
|
||||
{
|
||||
DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(PreparedResultSet, (transmogOutfitId)(situationID)(specID)(loadoutID)(equipmentSetID)) fields { *situationsResult };
|
||||
|
||||
uint32 transmogOutfitId = fields.transmogOutfitId().GetUInt32();
|
||||
|
||||
WorldPackets::Transmogrification::TransmogOutfitSituationInfo& situation = sets[transmogOutfitId].situations.emplace_back();
|
||||
situation.SituationID = fields.situationID().GetUInt32();
|
||||
situation.SpecID = fields.specID().GetUInt32();
|
||||
situation.LoadoutID = fields.loadoutID().GetUInt32();
|
||||
situation.EquipmentSetID = fields.equipmentSetID().GetUInt32();
|
||||
|
||||
} while (situationsResult->NextRow());
|
||||
}
|
||||
|
||||
// SELECT transmogOutfitId, slot, slotOption, itemModifiedAppearanceID, appearanceDisplayType, spellItemEnchantmentID, illusionDisplayType, flags FROM character_transmog_outfit_slot guid = ?
|
||||
if (slotsResult)
|
||||
{
|
||||
do
|
||||
{
|
||||
DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(PreparedResultSet, (transmogOutfitId)(slot)(slotOption)(itemModifiedAppearanceID)(appearanceDisplayType)
|
||||
(spellItemEnchantmentID)(illusionDisplayType)(flags)) fields { *slotsResult };
|
||||
|
||||
uint32 transmogOutfitId = fields.transmogOutfitId().GetUInt32();
|
||||
|
||||
WorldPackets::Transmogrification::TransmogOutfitSlotData& slot = sets[transmogOutfitId].slots.emplace_back();
|
||||
slot.Slot = static_cast<TransmogOutfitSlot>(fields.slot().GetInt8());
|
||||
slot.SlotOption = static_cast<TransmogOutfitSlotOption>(fields.slotOption().GetUInt8());
|
||||
slot.ItemModifiedAppearanceID = fields.itemModifiedAppearanceID().GetUInt32();
|
||||
slot.AppearanceDisplayType = static_cast<TransmogOutfitDisplayType>(fields.appearanceDisplayType().GetUInt8());
|
||||
slot.SpellItemEnchantmentID = fields.spellItemEnchantmentID().GetUInt32();
|
||||
slot.IllusionDisplayType = static_cast<TransmogOutfitDisplayType>(fields.illusionDisplayType().GetUInt8());
|
||||
slot.Flags = fields.flags().GetUInt32();
|
||||
|
||||
} while (slotsResult->NextRow());
|
||||
}
|
||||
|
||||
auto activePlayerData = m_values.ModifyValue(&Player::m_activePlayerData);
|
||||
|
||||
// SELECT transmogOutfitId, name, icon, situationsEnabled FROM character_transmog_outfit WHERE guid = ?
|
||||
if (setsResult)
|
||||
{
|
||||
do
|
||||
{
|
||||
DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(PreparedResultSet, (transmogOutfitId)(name)(icon)(situationsEnabled)) fields { *setsResult };
|
||||
|
||||
uint32 transmogOutfitId = fields.transmogOutfitId().GetUInt32();
|
||||
TransmogOutfitEntryEntry const* transmogOutfitEntry = sTransmogOutfitEntryStore.LookupEntry(transmogOutfitId);
|
||||
if (!transmogOutfitEntry || transmogOutfitEntry->GetSetType() == TransmogOutfitSetType::CustomSet)
|
||||
continue;
|
||||
|
||||
if (transmogOutfitEntry->HasFlag(TransmogOutfitEntryFlags::OnlyAvailableDuringEvent) && !IsHolidayActive(HOLIDAY_TRIAL_OF_STYLE))
|
||||
continue;
|
||||
|
||||
WorldPackets::Transmogrification::TransmogOutfitDataInfo outfitInfo;
|
||||
outfitInfo.SetType = transmogOutfitEntry->GetSetType();
|
||||
outfitInfo.Name = fields.name().GetString();
|
||||
outfitInfo.Icon = fields.icon().GetUInt32();
|
||||
outfitInfo.SituationsEnabled = fields.situationsEnabled().GetBool();
|
||||
|
||||
auto transmogOutfit = activePlayerData.ModifyValue(&UF::ActivePlayerData::TransmogOutfits, transmogOutfitId);
|
||||
InitializeNewTransmogOutfit(transmogOutfit, transmogOutfitId, outfitInfo);
|
||||
|
||||
auto setData = sets.extract(transmogOutfitId);
|
||||
if (!setData)
|
||||
continue;
|
||||
|
||||
auto situations = transmogOutfit.ModifyValue(&UF::TransmogOutfitData::Situations);
|
||||
ClearDynamicUpdateFieldValues(situations);
|
||||
for (WorldPackets::Transmogrification::TransmogOutfitSituationInfo const& situationInfo : setData.mapped().situations)
|
||||
{
|
||||
auto situation = AddDynamicUpdateFieldValue(situations);
|
||||
situation.ModifyValue(&UF::TransmogOutfitSituationInfo::SituationID).SetValue(situationInfo.SituationID);
|
||||
situation.ModifyValue(&UF::TransmogOutfitSituationInfo::SpecID).SetValue(situationInfo.SpecID);
|
||||
situation.ModifyValue(&UF::TransmogOutfitSituationInfo::LoadoutID).SetValue(situationInfo.LoadoutID);
|
||||
situation.ModifyValue(&UF::TransmogOutfitSituationInfo::EquipmentSetID).SetValue(situationInfo.EquipmentSetID);
|
||||
}
|
||||
|
||||
for (WorldPackets::Transmogrification::TransmogOutfitSlotData const& slotData : setData.mapped().slots)
|
||||
{
|
||||
TransmogMgr::TransmogOutfitSlotAndOptionInfo const* slotInfo = TransmogMgr::GetSlotAndOption(slotData.Slot, slotData.SlotOption);
|
||||
if (!slotInfo)
|
||||
continue;
|
||||
|
||||
auto slot = transmogOutfit.ModifyValue(&UF::TransmogOutfitData::Slots, slotInfo->SlotIndex);
|
||||
SetUpdateFieldValue(slot.ModifyValue(&UF::TransmogOutfitSlotData::Slot), AsUnderlyingType(slotData.Slot));
|
||||
SetUpdateFieldValue(slot.ModifyValue(&UF::TransmogOutfitSlotData::SlotOption), AsUnderlyingType(slotData.SlotOption));
|
||||
SetUpdateFieldValue(slot.ModifyValue(&UF::TransmogOutfitSlotData::ItemModifiedAppearanceID), slotData.ItemModifiedAppearanceID);
|
||||
SetUpdateFieldValue(slot.ModifyValue(&UF::TransmogOutfitSlotData::AppearanceDisplayType), AsUnderlyingType(slotData.AppearanceDisplayType));
|
||||
SetUpdateFieldValue(slot.ModifyValue(&UF::TransmogOutfitSlotData::SpellItemEnchantmentID), slotData.SpellItemEnchantmentID);
|
||||
SetUpdateFieldValue(slot.ModifyValue(&UF::TransmogOutfitSlotData::IllusionDisplayType), AsUnderlyingType(slotData.IllusionDisplayType));
|
||||
SetUpdateFieldValue(slot.ModifyValue(&UF::TransmogOutfitSlotData::Flags), slotData.Flags);
|
||||
}
|
||||
} while (setsResult->NextRow());
|
||||
}
|
||||
|
||||
for (int32 transmogOutfitId : m_activePlayerData->UnlockedTransmogOutfits)
|
||||
{
|
||||
TransmogOutfitEntryEntry const* transmogOutfitEntry = sTransmogOutfitEntryStore.AssertEntry(transmogOutfitId);
|
||||
|
||||
if (transmogOutfitEntry->HasFlag(TransmogOutfitEntryFlags::OnlyAvailableDuringEvent) && !IsHolidayActive(HOLIDAY_TRIAL_OF_STYLE))
|
||||
continue;
|
||||
|
||||
WorldPackets::Transmogrification::TransmogOutfitDataInfo outfitData;
|
||||
outfitData.SetType = transmogOutfitEntry->GetSetType();
|
||||
outfitData.SituationsEnabled = false;
|
||||
outfitData.Icon = TransmogMgr::DefaultOutfitIcon;
|
||||
outfitData.Name = TransmogMgr::DefaultOutfitName[GetSession()->GetSessionDbcLocale()];
|
||||
if (transmogOutfitEntry->Name.Str[GetSession()->GetSessionDbcLocale()][0])
|
||||
outfitData.Name = transmogOutfitEntry->Name.Str[GetSession()->GetSessionDbcLocale()];
|
||||
|
||||
switch (transmogOutfitEntry->GetSetType())
|
||||
{
|
||||
case TransmogOutfitSetType::Equipped:
|
||||
{
|
||||
outfitData.SituationsEnabled = true;
|
||||
auto equippedOutfit = activePlayerData.ModifyValue(&UF::ActivePlayerData::ViewedOutfit);
|
||||
InitializeNewTransmogOutfit(equippedOutfit, transmogOutfitId, outfitData);
|
||||
break;
|
||||
}
|
||||
case TransmogOutfitSetType::Outfit:
|
||||
if (!m_activePlayerData->TransmogOutfits.Get(transmogOutfitId))
|
||||
CreateTransmogOutfit(transmogOutfitId, outfitData);
|
||||
break;
|
||||
case TransmogOutfitSetType::CustomSet:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EquipTransmogOutfit(equippedTransmogOutfitId, TransmogSituationTrigger::Manual, locked);
|
||||
}
|
||||
|
||||
void Player::_LoadBGData(PreparedQueryResult result)
|
||||
{
|
||||
if (!result)
|
||||
@@ -17717,7 +17970,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
|
||||
// "totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
|
||||
// "health, power1, power2, power3, power4, power5, power6, power7, power8, power9, power10, instance_id, activeTalentGroup, lootSpecId, exploredZones, knownTitles, actionBars, "
|
||||
// "raidDifficulty, legacyRaidDifficulty, fishingSteps, honor, honorLevel, honorRestState, honorRestBonus, numRespecs, "
|
||||
// "personalTabardEmblemStyle, personalTabardEmblemColor, personalTabardBorderStyle, personalTabardBorderColor, personalTabardBackgroundColor "
|
||||
// "personalTabardEmblemStyle, personalTabardEmblemColor, personalTabardBorderStyle, personalTabardBorderColor, personalTabardBackgroundColor, transmogOutfitEquippedId, transmogOutfitLocked "
|
||||
// "FROM characters c LEFT JOIN character_fishingsteps cfs ON c.guid = cfs.guid WHERE c.guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
ObjectGuid::LowType guid;
|
||||
@@ -17795,6 +18048,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
|
||||
int32 personalTabardBorderStyle;
|
||||
int32 personalTabardBorderColor;
|
||||
int32 personalTabardBackgroundColor;
|
||||
int32 transmogOutfitEquippedId;
|
||||
bool transmogOutfitLocked;
|
||||
|
||||
explicit PlayerLoadData(Field const* fields)
|
||||
{
|
||||
@@ -17876,6 +18131,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
|
||||
personalTabardBorderStyle = fields[i++].GetInt32();
|
||||
personalTabardBorderColor = fields[i++].GetInt32();
|
||||
personalTabardBackgroundColor = fields[i++].GetInt32();
|
||||
transmogOutfitEquippedId = fields[i++].GetInt32();
|
||||
transmogOutfitLocked = fields[i++].GetBool();
|
||||
}
|
||||
|
||||
} fields(result->Fetch());
|
||||
@@ -18379,12 +18636,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
|
||||
_LoadTalents(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS));
|
||||
_LoadPvpTalents(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_PVP_TALENTS));
|
||||
_LoadSpells(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELLS), holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELL_FAVORITES));
|
||||
GetSession()->GetCollectionMgr()->LoadToys();
|
||||
GetSession()->GetCollectionMgr()->LoadHeirlooms();
|
||||
GetSession()->GetCollectionMgr()->LoadMounts();
|
||||
GetSession()->GetCollectionMgr()->LoadItemAppearances();
|
||||
GetSession()->GetCollectionMgr()->LoadTransmogIllusions();
|
||||
GetSession()->GetCollectionMgr()->LoadWarbandScenes();
|
||||
GetSession()->GetCollectionMgr()->LoadCharacterData();
|
||||
|
||||
LearnSpecializationSpells();
|
||||
|
||||
@@ -18560,6 +18812,9 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
|
||||
}
|
||||
}
|
||||
|
||||
if (extraflags & PLAYER_EXTRA_FLAG_FREE_TRANSMOG_CLAIMED)
|
||||
SetPlayerLocalFlag(PLAYER_LOCAL_FLAG_FREE_TRANSMOG_CLAIMED);
|
||||
|
||||
InitPvP();
|
||||
|
||||
// RaF stuff.
|
||||
@@ -18569,7 +18824,11 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
|
||||
_LoadDeclinedNames(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES));
|
||||
|
||||
_LoadEquipmentSets(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS));
|
||||
_LoadTransmogOutfits(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFITS));
|
||||
_LoadTransmogCustomSets(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFITS));
|
||||
_LoadTransmogOutfits(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT),
|
||||
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT_SITUATION),
|
||||
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT_SLOT),
|
||||
fields.transmogOutfitEquippedId, fields.transmogOutfitLocked);
|
||||
|
||||
_LoadCUFProfiles(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES));
|
||||
|
||||
@@ -20314,27 +20573,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
|
||||
}
|
||||
stmt->setString(index++, ss.str());
|
||||
|
||||
ss.str("");
|
||||
// cache equipment...
|
||||
for (uint32 i = 0; i < REAGENT_BAG_SLOT_END; ++i)
|
||||
{
|
||||
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
{
|
||||
ss << uint32(item->GetTemplate()->GetInventoryType()) << ' ' << item->GetDisplayId(this) << ' ';
|
||||
if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(item->GetVisibleEnchantmentId(this)))
|
||||
ss << enchant->ItemVisual;
|
||||
else
|
||||
ss << '0';
|
||||
|
||||
ss << ' '
|
||||
<< uint32(sItemStore.AssertEntry(item->GetVisibleEntry(this))->SubclassID) << ' '
|
||||
<< uint32(item->GetVisibleSecondaryModifiedAppearanceId(this)) << ' ';
|
||||
}
|
||||
else
|
||||
ss << "0 0 0 0 0 ";
|
||||
}
|
||||
|
||||
stmt->setString(index++, ss.str());
|
||||
stmt->setString(index++, GetCharacterSelectOutfit());
|
||||
|
||||
ss.str("");
|
||||
for (uint32 i = 0; i < m_activePlayerData->KnownTitles.size(); ++i)
|
||||
@@ -20349,6 +20588,14 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
|
||||
stmt->setUInt32(index++, ClientBuild::GetMinorMajorBugfixVersionForBuild(currentRealm->Build));
|
||||
else
|
||||
stmt->setUInt32(index++, 0);
|
||||
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->EmblemStyle);
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->EmblemColor);
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->BorderStyle);
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->BorderColor);
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->BackgroundColor);
|
||||
stmt->setInt32(index++, m_activePlayerData->TransmogMetadata->TransmogOutfitID);
|
||||
stmt->setBool(index++, m_activePlayerData->TransmogMetadata->Locked);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -20473,27 +20720,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
|
||||
}
|
||||
stmt->setString(index++, ss.str());
|
||||
|
||||
ss.str("");
|
||||
// cache equipment...
|
||||
for (uint32 i = 0; i < REAGENT_BAG_SLOT_END; ++i)
|
||||
{
|
||||
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
{
|
||||
ss << uint32(item->GetTemplate()->GetInventoryType()) << ' ' << item->GetDisplayId(this) << ' ';
|
||||
if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(item->GetVisibleEnchantmentId(this)))
|
||||
ss << enchant->ItemVisual;
|
||||
else
|
||||
ss << '0';
|
||||
|
||||
ss << ' '
|
||||
<< uint32(sItemStore.AssertEntry(item->GetVisibleEntry(this))->SubclassID) << ' '
|
||||
<< uint32(item->GetVisibleSecondaryModifiedAppearanceId(this)) << ' ';
|
||||
}
|
||||
else
|
||||
ss << "0 0 0 0 0 ";
|
||||
}
|
||||
|
||||
stmt->setString(index++, ss.str());
|
||||
stmt->setString(index++, GetCharacterSelectOutfit());
|
||||
|
||||
ss.str("");
|
||||
for (uint32 i = 0; i < m_activePlayerData->KnownTitles.size(); ++i)
|
||||
@@ -20515,6 +20742,14 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
|
||||
else
|
||||
stmt->setUInt32(index++, 0);
|
||||
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->EmblemStyle);
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->EmblemColor);
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->BorderStyle);
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->BorderColor);
|
||||
stmt->setInt32(index++, m_playerData->PersonalTabard->BackgroundColor);
|
||||
stmt->setInt32(index++, m_activePlayerData->TransmogMetadata->TransmogOutfitID);
|
||||
stmt->setBool(index++, m_activePlayerData->TransmogMetadata->Locked);
|
||||
|
||||
// Index
|
||||
stmt->setUInt64(index, GetGUID().GetCounter());
|
||||
}
|
||||
@@ -20554,6 +20789,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
|
||||
m_reputationMgr->SaveToDB(trans);
|
||||
m_questObjectiveCriteriaMgr->SaveToDB(trans);
|
||||
_SaveEquipmentSets(trans);
|
||||
_SaveTransmogOutfits(trans);
|
||||
GetSession()->SaveTutorialsData(trans); // changed only while character in game
|
||||
_SaveInstanceTimeRestrictions(trans);
|
||||
_SaveCurrency(trans);
|
||||
@@ -20569,13 +20805,8 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
|
||||
_SaveStats(trans);
|
||||
|
||||
// TODO: Move this out
|
||||
GetSession()->GetCollectionMgr()->SaveAccountToys(loginTransaction);
|
||||
GetSession()->GetCollectionMgr()->SaveToDB(loginTransaction);
|
||||
GetSession()->GetBattlePetMgr()->SaveToDB(loginTransaction);
|
||||
GetSession()->GetCollectionMgr()->SaveAccountHeirlooms(loginTransaction);
|
||||
GetSession()->GetCollectionMgr()->SaveAccountMounts(loginTransaction);
|
||||
GetSession()->GetCollectionMgr()->SaveAccountItemAppearances(loginTransaction);
|
||||
GetSession()->GetCollectionMgr()->SaveAccountTransmogIllusions(loginTransaction);
|
||||
GetSession()->GetCollectionMgr()->SaveAccountWarbandScenes(loginTransaction);
|
||||
GetSession()->SavePlayerDataAccount(loginTransaction);
|
||||
|
||||
Battlenet::RealmHandle currentRealmId = sRealmList->GetCurrentRealmId();
|
||||
@@ -28047,6 +28278,71 @@ void Player::_SaveEquipmentSets(CharacterDatabaseTransaction trans)
|
||||
}
|
||||
}
|
||||
|
||||
void Player::_SaveTransmogOutfits(CharacterDatabaseTransaction trans)
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = nullptr;
|
||||
ObjectGuid::LowType guid = GetGUID().GetCounter();
|
||||
|
||||
for (uint32 transmogOutfitId : m_changedTransmogOutfits)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_TRANSMOG_OUTFIT_SLOT);
|
||||
stmt->setUInt64(0, guid);
|
||||
stmt->setUInt32(1, transmogOutfitId);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_TRANSMOG_OUTFIT_SITUATION);
|
||||
stmt->setUInt64(0, guid);
|
||||
stmt->setUInt32(1, transmogOutfitId);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_TRANSMOG_OUTFIT_2);
|
||||
stmt->setUInt64(0, guid);
|
||||
stmt->setUInt32(1, transmogOutfitId);
|
||||
trans->Append(stmt);
|
||||
|
||||
UF::TransmogOutfitData const* transmogOutfit = m_activePlayerData->TransmogOutfits.Get(transmogOutfitId);
|
||||
if (!transmogOutfit)
|
||||
continue;
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_TRANSMOG_OUTFIT_2);
|
||||
stmt->setUInt64(0, guid);
|
||||
stmt->setUInt32(1, transmogOutfitId);
|
||||
stmt->setString(2, *transmogOutfit->OutfitInfo->Name);
|
||||
stmt->setUInt32(3, *transmogOutfit->OutfitInfo->Icon);
|
||||
stmt->setBool(4, *transmogOutfit->OutfitInfo->SituationsEnabled);
|
||||
trans->Append(stmt);
|
||||
|
||||
for (UF::TransmogOutfitSituationInfo const& situation : transmogOutfit->Situations)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_TRANSMOG_OUTFIT_SITUATION);
|
||||
stmt->setUInt64(0, guid);
|
||||
stmt->setUInt32(1, transmogOutfitId);
|
||||
stmt->setUInt32(2, *situation.SituationID);
|
||||
stmt->setUInt32(3, *situation.SpecID);
|
||||
stmt->setUInt32(4, *situation.LoadoutID);
|
||||
stmt->setUInt32(5, *situation.EquipmentSetID);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
for (UF::TransmogOutfitSlotData const& slot : transmogOutfit->Slots)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_TRANSMOG_OUTFIT_SLOT);
|
||||
stmt->setUInt64(0, guid);
|
||||
stmt->setUInt32(1, transmogOutfitId);
|
||||
stmt->setInt8(2, *slot.Slot);
|
||||
stmt->setUInt8(3, *slot.SlotOption);
|
||||
stmt->setUInt32(4, *slot.ItemModifiedAppearanceID);
|
||||
stmt->setUInt8(5, *slot.AppearanceDisplayType);
|
||||
stmt->setUInt32(6, *slot.SpellItemEnchantmentID);
|
||||
stmt->setUInt8(7, *slot.IllusionDisplayType);
|
||||
stmt->setUInt32(8, *slot.Flags);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
m_changedTransmogOutfits.clear();
|
||||
}
|
||||
|
||||
void Player::_SaveBGData(CharacterDatabaseTransaction trans)
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_BGDATA);
|
||||
@@ -30891,6 +31187,308 @@ void Player::UpdateWarModeAuras()
|
||||
}
|
||||
}
|
||||
|
||||
void Player::AddUnlockedTransmogOutfits(std::span<int32 const> transmogOutfitIds)
|
||||
{
|
||||
auto unlockedTransmogOutfits = m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::UnlockedTransmogOutfits);
|
||||
for (int32 transmogOutfitId : transmogOutfitIds)
|
||||
AddDynamicUpdateFieldValue(unlockedTransmogOutfits) = transmogOutfitId;
|
||||
}
|
||||
|
||||
void Player::CreateTransmogOutfit(uint32 id, WorldPackets::Transmogrification::TransmogOutfitDataInfo const& outfitData)
|
||||
{
|
||||
auto outfit = m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::TransmogOutfits, id);
|
||||
InitializeNewTransmogOutfit(outfit, id, outfitData);
|
||||
m_changedTransmogOutfits.insert(id);
|
||||
}
|
||||
|
||||
void Player::InitializeNewTransmogOutfit(UF::MutableFieldReference<UF::TransmogOutfitData, false> outfit,
|
||||
uint32 id, WorldPackets::Transmogrification::TransmogOutfitDataInfo const& outfitData)
|
||||
{
|
||||
SetUpdateFieldValue(outfit.ModifyValue(&UF::TransmogOutfitData::Id), id);
|
||||
|
||||
auto outfitInfo = outfit.ModifyValue(&UF::TransmogOutfitData::OutfitInfo);
|
||||
SetUpdateFieldValue(outfitInfo.ModifyValue(&UF::TransmogOutfitDataInfo::SetType), AsUnderlyingType(outfitData.SetType));
|
||||
SetUpdateFieldValue(outfitInfo.ModifyValue(&UF::TransmogOutfitDataInfo::SituationsEnabled), outfitData.SituationsEnabled);
|
||||
SetUpdateFieldValue(outfitInfo.ModifyValue(&UF::TransmogOutfitDataInfo::Icon), outfitData.Icon);
|
||||
SetUpdateFieldValue(outfitInfo.ModifyValue(&UF::TransmogOutfitDataInfo::Name), std::string(outfitData.Name));
|
||||
|
||||
auto situations = outfit.ModifyValue(&UF::TransmogOutfitData::Situations);
|
||||
for (TransmogSituationEntry const* defaultSituation : TransmogMgr::GetDefaultSituations())
|
||||
{
|
||||
auto situation = AddDynamicUpdateFieldValue(situations);
|
||||
situation.ModifyValue(&UF::TransmogOutfitSituationInfo::SituationID).SetValue(defaultSituation->ID);
|
||||
}
|
||||
|
||||
auto slots = outfit.ModifyValue(&UF::TransmogOutfitData::Slots);
|
||||
for (TransmogMgr::TransmogOutfitSlotAndOptionInfo const& slotInfo : TransmogMgr::GetAllSlots())
|
||||
{
|
||||
auto slot = AddDynamicUpdateFieldValue(slots);
|
||||
slot.ModifyValue(&UF::TransmogOutfitSlotData::Slot).SetValue(AsUnderlyingType(slotInfo.Slot->GetSlot()));
|
||||
|
||||
if (slotInfo.SlotOption)
|
||||
{
|
||||
slot.ModifyValue(&UF::TransmogOutfitSlotData::SlotOption).SetValue(AsUnderlyingType(slotInfo.SlotOption->GetOption()));
|
||||
|
||||
switch (slotInfo.SlotOption->GetOption())
|
||||
{
|
||||
case TransmogOutfitSlotOption::ArtifactSpecOne:
|
||||
case TransmogOutfitSlotOption::ArtifactSpecTwo:
|
||||
case TransmogOutfitSlotOption::ArtifactSpecThree:
|
||||
case TransmogOutfitSlotOption::ArtifactSpecFour:
|
||||
// artifacts are disabled by default
|
||||
slot.ModifyValue(&UF::TransmogOutfitSlotData::AppearanceDisplayType).SetValue(AsUnderlyingType(TransmogOutfitDisplayType::Disabled));
|
||||
slot.ModifyValue(&UF::TransmogOutfitSlotData::IllusionDisplayType).SetValue(AsUnderlyingType(TransmogOutfitDisplayType::Disabled));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Player::UpdateTransmogOutfit(uint32 id, WorldPackets::Transmogrification::TransmogOutfitDataInfo const& outfitData)
|
||||
{
|
||||
if (!m_activePlayerData->TransmogOutfits.Get(id))
|
||||
return false;
|
||||
|
||||
auto outfitInfo = m_values.ModifyValue(&Player::m_activePlayerData)
|
||||
.ModifyValue(&UF::ActivePlayerData::TransmogOutfits, id)
|
||||
.ModifyValue(&UF::TransmogOutfitData::OutfitInfo);
|
||||
SetUpdateFieldValue(outfitInfo.ModifyValue(&UF::TransmogOutfitDataInfo::SetType), AsUnderlyingType(outfitData.SetType));
|
||||
SetUpdateFieldValue(outfitInfo.ModifyValue(&UF::TransmogOutfitDataInfo::SituationsEnabled), outfitData.SituationsEnabled);
|
||||
SetUpdateFieldValue(outfitInfo.ModifyValue(&UF::TransmogOutfitDataInfo::Icon), outfitData.Icon);
|
||||
SetUpdateFieldValue(outfitInfo.ModifyValue(&UF::TransmogOutfitDataInfo::Name), std::string(outfitData.Name));
|
||||
|
||||
m_changedTransmogOutfits.insert(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Player::UpdateTransmogOutfitSituations(uint32 id, bool situationsEnabled, std::span<WorldPackets::Transmogrification::TransmogOutfitSituationInfo const> situations)
|
||||
{
|
||||
auto outfit = m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::TransmogOutfits, id);
|
||||
SetUpdateFieldValue(outfit.ModifyValue(&UF::TransmogOutfitData::OutfitInfo).ModifyValue(&UF::TransmogOutfitDataInfo::SituationsEnabled), situationsEnabled);
|
||||
|
||||
auto outfitSituations = outfit.ModifyValue(&UF::TransmogOutfitData::Situations);
|
||||
|
||||
ClearDynamicUpdateFieldValues(outfitSituations);
|
||||
|
||||
for (WorldPackets::Transmogrification::TransmogOutfitSituationInfo const& situation : situations)
|
||||
{
|
||||
auto outfitSituation = AddDynamicUpdateFieldValue(outfitSituations);
|
||||
outfitSituation.ModifyValue(&UF::TransmogOutfitSituationInfo::SituationID).SetValue(situation.SituationID);
|
||||
outfitSituation.ModifyValue(&UF::TransmogOutfitSituationInfo::SpecID).SetValue(situation.SpecID);
|
||||
outfitSituation.ModifyValue(&UF::TransmogOutfitSituationInfo::LoadoutID).SetValue(situation.LoadoutID);
|
||||
outfitSituation.ModifyValue(&UF::TransmogOutfitSituationInfo::EquipmentSetID).SetValue(situation.EquipmentSetID);
|
||||
}
|
||||
|
||||
m_changedTransmogOutfits.insert(id);
|
||||
}
|
||||
|
||||
void Player::UpdateTransmogOutfitSlots(uint32 id, std::span<WorldPackets::Transmogrification::TransmogOutfitSlotData const> slots)
|
||||
{
|
||||
UF::TransmogOutfitData const* transmogOutfit = m_activePlayerData->TransmogOutfits.Get(id);
|
||||
if (!transmogOutfit)
|
||||
return;
|
||||
|
||||
auto outfit = m_values.ModifyValue(&Player::m_activePlayerData)
|
||||
.ModifyValue(&UF::ActivePlayerData::TransmogOutfits, id);
|
||||
|
||||
uint32 outfitSlotIndex = 0;
|
||||
for (WorldPackets::Transmogrification::TransmogOutfitSlotData const& slot : slots)
|
||||
{
|
||||
while (std::pair(*transmogOutfit->Slots[outfitSlotIndex].Slot, *transmogOutfit->Slots[outfitSlotIndex].SlotOption) < std::pair(AsUnderlyingType(slot.Slot), AsUnderlyingType(slot.SlotOption)))
|
||||
if (++outfitSlotIndex >= transmogOutfit->Slots.size())
|
||||
return;
|
||||
|
||||
auto viewedOutfitSlot = outfit.ModifyValue(&UF::TransmogOutfitData::Slots, outfitSlotIndex);
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::Slot), AsUnderlyingType(slot.Slot));
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::SlotOption), AsUnderlyingType(slot.SlotOption));
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::ItemModifiedAppearanceID), slot.ItemModifiedAppearanceID);
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::AppearanceDisplayType), AsUnderlyingType(slot.AppearanceDisplayType));
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::SpellItemEnchantmentID), slot.SpellItemEnchantmentID);
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::IllusionDisplayType), AsUnderlyingType(slot.IllusionDisplayType));
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::Flags), slot.Flags);
|
||||
}
|
||||
|
||||
m_changedTransmogOutfits.insert(id);
|
||||
}
|
||||
|
||||
void Player::EquipTransmogOutfit(uint32 id, TransmogSituationTrigger trigger, Optional<bool> locked)
|
||||
{
|
||||
auto activePlayerData = m_values.ModifyValue(&Player::m_activePlayerData);
|
||||
|
||||
auto transmogMetadata = activePlayerData.ModifyValue(&UF::ActivePlayerData::TransmogMetadata);
|
||||
SetUpdateFieldValue(transmogMetadata.ModifyValue(&UF::TransmogOutfitMetadata::TransmogOutfitID), id);
|
||||
SetUpdateFieldValue(transmogMetadata.ModifyValue(&UF::TransmogOutfitMetadata::SituationTrigger), AsUnderlyingType(trigger));
|
||||
if (locked.has_value())
|
||||
SetUpdateFieldValue(transmogMetadata.ModifyValue(&UF::TransmogOutfitMetadata::Locked), *locked);
|
||||
|
||||
auto viewedOutfit = activePlayerData.ModifyValue(&UF::ActivePlayerData::ViewedOutfit);
|
||||
|
||||
if (UF::TransmogOutfitData const* transmogOutfit = m_activePlayerData->TransmogOutfits.Get(id))
|
||||
{
|
||||
for (UF::TransmogOutfitSlotData const& slot : transmogOutfit->Slots)
|
||||
{
|
||||
uint32 slotIndex = TransmogMgr::GetSlotAndOption(static_cast<TransmogOutfitSlot>(*slot.Slot), static_cast<TransmogOutfitSlotOption>(*slot.SlotOption))->SlotIndex;
|
||||
auto viewedOutfitSlot = viewedOutfit.ModifyValue(&UF::TransmogOutfitData::Slots, slotIndex);
|
||||
if (static_cast<TransmogOutfitDisplayType>(*slot.AppearanceDisplayType) != TransmogOutfitDisplayType::Unassigned)
|
||||
{
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::ItemModifiedAppearanceID), slot.ItemModifiedAppearanceID);
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::AppearanceDisplayType), slot.AppearanceDisplayType);
|
||||
}
|
||||
if (static_cast<TransmogOutfitDisplayType>(*slot.IllusionDisplayType) != TransmogOutfitDisplayType::Unassigned)
|
||||
{
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::SpellItemEnchantmentID), slot.SpellItemEnchantmentID);
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::IllusionDisplayType), slot.IllusionDisplayType);
|
||||
}
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::Flags), slot.Flags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (TransmogMgr::TransmogOutfitSlotAndOptionInfo const& slotInfo : TransmogMgr::GetAllSlots())
|
||||
{
|
||||
auto viewedOutfitSlot = viewedOutfit.ModifyValue(&UF::TransmogOutfitData::Slots, slotInfo.SlotIndex);
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::Slot), AsUnderlyingType(slotInfo.Slot->GetSlot()));
|
||||
|
||||
TransmogOutfitSlotOption slotOption = slotInfo.SlotOption ? slotInfo.SlotOption->GetOption() : TransmogOutfitSlotOption::None;
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::SlotOption), AsUnderlyingType(slotOption));
|
||||
|
||||
if (Item const* item = GetItemByPos(INVENTORY_SLOT_BAG_0, slotInfo.Slot->InventorySlotEnum))
|
||||
{
|
||||
if (item->GetTemplate()->GetWeaponTransmogOutfitSlotOption() == slotOption)
|
||||
{
|
||||
if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = item->GetItemModifiedAppearance())
|
||||
{
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::ItemModifiedAppearanceID), itemModifiedAppearance->ID);
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::AppearanceDisplayType), AsUnderlyingType(TransmogOutfitDisplayType::Equipped));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (slotOption)
|
||||
{
|
||||
case TransmogOutfitSlotOption::ArtifactSpecOne:
|
||||
case TransmogOutfitSlotOption::ArtifactSpecTwo:
|
||||
case TransmogOutfitSlotOption::ArtifactSpecThree:
|
||||
case TransmogOutfitSlotOption::ArtifactSpecFour:
|
||||
// artifacts are disabled by default
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::AppearanceDisplayType), AsUnderlyingType(TransmogOutfitDisplayType::Disabled));
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::IllusionDisplayType), AsUnderlyingType(TransmogOutfitDisplayType::Disabled));
|
||||
break;
|
||||
case TransmogOutfitSlotOption::None:
|
||||
break;
|
||||
default:
|
||||
SetUpdateFieldValue(viewedOutfitSlot.ModifyValue(&UF::TransmogOutfitSlotData::IllusionDisplayType), AsUnderlyingType(TransmogOutfitDisplayType::Equipped));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 equipSlot = EQUIPMENT_SLOT_START; equipSlot < EQUIPMENT_SLOT_END; ++equipSlot)
|
||||
SetVisibleItemSlot(equipSlot, GetItemByPos(INVENTORY_SLOT_BAG_0, equipSlot));
|
||||
}
|
||||
|
||||
std::string Player::GetCharacterSelectOutfit() const
|
||||
{
|
||||
std::vector<UF::TransmogOutfitData const*> outfits;
|
||||
for (auto const& [_, transmogOutfit] : m_activePlayerData->TransmogOutfits)
|
||||
{
|
||||
if (!transmogOutfit.value.OutfitInfo->SituationsEnabled)
|
||||
continue;
|
||||
|
||||
bool isCharacterSelect = transmogOutfit.value.Situations.FindIndexIf([](UF::TransmogOutfitSituationInfo const& situation)
|
||||
{
|
||||
return sTransmogSituationStore.AssertEntry(situation.SituationID)->GetSituation() == TransmogSituation::LocationCharacterSelect;
|
||||
}) >= 0;
|
||||
|
||||
if (!isCharacterSelect)
|
||||
continue;
|
||||
|
||||
outfits.push_back(&transmogOutfit.value);
|
||||
}
|
||||
|
||||
UF::TransmogOutfitData const* outfit = &*m_activePlayerData->ViewedOutfit;
|
||||
if (!outfits.empty())
|
||||
outfit = Trinity::Containers::SelectRandomContainerElement(outfits);
|
||||
|
||||
auto isTransmogDisplayed = [](TransmogOutfitDisplayType displayType)
|
||||
{
|
||||
return displayType == TransmogOutfitDisplayType::Assigned || displayType == TransmogOutfitDisplayType::Hidden;
|
||||
};
|
||||
|
||||
std::string result;
|
||||
for (EquipmentSlots i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i = EquipmentSlots(i + 1))
|
||||
{
|
||||
TransmogOutfitSlotOption transmogSlotOption = TransmogOutfitSlotOption::None;
|
||||
switch (i)
|
||||
{
|
||||
case EQUIPMENT_SLOT_MAINHAND:
|
||||
transmogSlotOption = static_cast<TransmogOutfitSlotOption>(m_activePlayerData->TransmogMetadata->StampedOptionMainHand);
|
||||
break;
|
||||
case EQUIPMENT_SLOT_OFFHAND:
|
||||
transmogSlotOption = static_cast<TransmogOutfitSlotOption>(m_activePlayerData->TransmogMetadata->StampedOptionOffHand);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (TransmogMgr::TransmogOutfitSlotAndOptionInfo const* slotInfo = TransmogMgr::GetSlotAndOption(i, transmogSlotOption))
|
||||
{
|
||||
UF::TransmogOutfitSlotData const& transmogOutfitSlot = outfit->Slots[slotInfo->SlotIndex];
|
||||
|
||||
uint32 itemModifiedAppearanceId = transmogOutfitSlot.ItemModifiedAppearanceID;
|
||||
if (!isTransmogDisplayed(static_cast<TransmogOutfitDisplayType>(*transmogOutfitSlot.AppearanceDisplayType)))
|
||||
itemModifiedAppearanceId = m_activePlayerData->ViewedOutfit->Slots[slotInfo->SlotIndex].ItemModifiedAppearanceID;
|
||||
|
||||
uint32 spellItemEnchantmentId = transmogOutfitSlot.SpellItemEnchantmentID;
|
||||
if (!isTransmogDisplayed(static_cast<TransmogOutfitDisplayType>(*transmogOutfitSlot.IllusionDisplayType)))
|
||||
spellItemEnchantmentId = m_activePlayerData->ViewedOutfit->Slots[slotInfo->SlotIndex].SpellItemEnchantmentID;
|
||||
|
||||
InventoryType inventoryType = INVTYPE_NON_EQUIP;
|
||||
int32 displayId = 0;
|
||||
uint16 itemVisual = 0;
|
||||
uint8 subClass = 0;
|
||||
uint32 secondaryItemModifiedAppearanceId = 0;
|
||||
if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId))
|
||||
{
|
||||
if (ItemEntry const* item = sItemStore.LookupEntry(itemModifiedAppearance->ItemID))
|
||||
{
|
||||
subClass = item->SubclassID;
|
||||
inventoryType = static_cast<InventoryType>(item->InventoryType);
|
||||
}
|
||||
|
||||
if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(itemModifiedAppearance->ItemAppearanceID))
|
||||
displayId = itemAppearance->ItemDisplayInfoID;
|
||||
}
|
||||
|
||||
if (SpellItemEnchantmentEntry const* spellItemEnchantment = sSpellItemEnchantmentStore.LookupEntry(spellItemEnchantmentId))
|
||||
itemVisual = spellItemEnchantment->ItemVisual;
|
||||
|
||||
if (TransmogOutfitSlotInfoEntry const* secondarySlot = sTransmogOutfitSlotInfoStore.LookupEntry(slotInfo->Slot->SecondarySlotID))
|
||||
{
|
||||
if (TransmogMgr::TransmogOutfitSlotAndOptionInfo const* secondarySlotInfo = TransmogMgr::GetSlotAndOption(secondarySlot->GetSlot(), transmogSlotOption))
|
||||
{
|
||||
UF::TransmogOutfitSlotData const& secondaryTransmogOutfitSlot = outfit->Slots[secondarySlotInfo->SlotIndex];
|
||||
|
||||
secondaryItemModifiedAppearanceId = secondaryTransmogOutfitSlot.ItemModifiedAppearanceID;
|
||||
if (!isTransmogDisplayed(static_cast<TransmogOutfitDisplayType>(*secondaryTransmogOutfitSlot.AppearanceDisplayType)))
|
||||
secondaryItemModifiedAppearanceId = m_activePlayerData->ViewedOutfit->Slots[secondarySlotInfo->SlotIndex].ItemModifiedAppearanceID;
|
||||
}
|
||||
}
|
||||
|
||||
Trinity::StringFormatTo(std::back_inserter(result), "{} {} {} {} {} ", inventoryType, displayId, itemVisual, subClass, secondaryItemModifiedAppearanceId);
|
||||
}
|
||||
else
|
||||
result += "0 0 0 0 0 "sv;
|
||||
}
|
||||
|
||||
for (uint32 i = EQUIPMENT_SLOT_END; i < REAGENT_BAG_SLOT_END; ++i)
|
||||
result += "0 0 0 0 0 "sv;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Player::OnPhaseChange()
|
||||
{
|
||||
Unit::OnPhaseChange();
|
||||
|
||||
@@ -135,6 +135,13 @@ namespace WorldPackets
|
||||
struct TraitConfig;
|
||||
struct TraitEntry;
|
||||
}
|
||||
|
||||
namespace Transmogrification
|
||||
{
|
||||
struct TransmogOutfitDataInfo;
|
||||
struct TransmogOutfitSituationInfo;
|
||||
struct TransmogOutfitSlotData;
|
||||
}
|
||||
}
|
||||
|
||||
TC_GAME_API uint32 GetBagSize(Bag const* bag);
|
||||
@@ -334,7 +341,8 @@ enum ActionButtonType
|
||||
ACTION_BUTTON_CMACRO = ACTION_BUTTON_C | ACTION_BUTTON_MACRO,
|
||||
ACTION_BUTTON_COMPANION = 0x50,
|
||||
ACTION_BUTTON_MOUNT = 0x60,
|
||||
ACTION_BUTTON_ITEM = 0x80
|
||||
ACTION_BUTTON_ITEM = 0x80,
|
||||
ACTION_BUTTON_OUTFIT = 0x90
|
||||
};
|
||||
|
||||
enum class HonorGainSource : uint8
|
||||
@@ -548,6 +556,7 @@ enum PlayerLocalFlags
|
||||
PLAYER_LOCAL_FLAG_CHARACTER_BANK_DISABLED = 0x00080000,
|
||||
PLAYER_LOCAL_FLAG_CHARACTER_BANK_CONVERSION_FAILED = 0x00100000,
|
||||
PLAYER_LOCAL_FLAG_ACCOUNT_BANK_DISABLED = 0x00200000,
|
||||
PLAYER_LOCAL_FLAG_FREE_TRANSMOG_CLAIMED = 0x00400000,
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(PlayerLocalFlags);
|
||||
@@ -586,6 +595,8 @@ enum PlayerExtraFlags
|
||||
PLAYER_EXTRA_HAS_RACE_CHANGED = 0x0200,
|
||||
PLAYER_EXTRA_GRANTED_LEVELS_FROM_RAF = 0x0400,
|
||||
PLAYER_EXTRA_LEVEL_BOOSTED = 0x0800,
|
||||
|
||||
PLAYER_EXTRA_FLAG_FREE_TRANSMOG_CLAIMED = 0x1000,
|
||||
};
|
||||
|
||||
// 2^n values
|
||||
@@ -937,6 +948,9 @@ enum PlayerLoginQueryIndex
|
||||
PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT,
|
||||
PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT_SITUATION,
|
||||
PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT_SLOT,
|
||||
PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFITS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_BG_DATA,
|
||||
PLAYER_LOGIN_QUERY_LOAD_GLYPHS,
|
||||
@@ -1264,6 +1278,8 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
void SetBeenGrantedLevelsFromRaF() { m_ExtraFlags |= PLAYER_EXTRA_GRANTED_LEVELS_FROM_RAF; }
|
||||
bool HasLevelBoosted() const { return (m_ExtraFlags & PLAYER_EXTRA_LEVEL_BOOSTED) != 0; }
|
||||
void SetHasLevelBoosted() { m_ExtraFlags |= PLAYER_EXTRA_LEVEL_BOOSTED; }
|
||||
bool HasClaimedFreeTransmog() const { return (m_ExtraFlags & PLAYER_EXTRA_FLAG_FREE_TRANSMOG_CLAIMED) != 0; }
|
||||
void SetHasClaimedFreeTransmog() { m_ExtraFlags |= PLAYER_EXTRA_FLAG_FREE_TRANSMOG_CLAIMED; }
|
||||
|
||||
uint32 GetXP() const { return m_activePlayerData->XP; }
|
||||
uint32 GetXPForNextLevel() const { return m_activePlayerData->NextLevelXP; }
|
||||
@@ -1550,7 +1566,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
void ApplyEquipCooldown(Item* pItem);
|
||||
void QuickEquipItem(uint16 pos, Item* pItem);
|
||||
void VisualizeItem(uint8 slot, Item* pItem);
|
||||
void SetVisibleItemSlot(uint8 slot, Item* pItem);
|
||||
void SetVisibleItemSlot(uint8 slot, Item const* item);
|
||||
Item* BankItem(ItemPosCountVec const& dest, Item* pItem, bool update);
|
||||
void RemoveItem(uint8 bag, uint8 slot, bool update);
|
||||
void MoveItemFromInventory(uint8 bag, uint8 slot, bool update);
|
||||
@@ -2987,6 +3003,18 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
bool CanEnableWarModeInArea() const;
|
||||
void UpdateWarModeAuras();
|
||||
|
||||
void AddUnlockedTransmogOutfits(std::span<int32 const> transmogOutfitIds);
|
||||
void AddUnlockedTransmogOutfit(int32 transmogOutfitIds) { AddUnlockedTransmogOutfits(std::span(&transmogOutfitIds, 1)); }
|
||||
|
||||
void CreateTransmogOutfit(uint32 id, WorldPackets::Transmogrification::TransmogOutfitDataInfo const& outfitData);
|
||||
void InitializeNewTransmogOutfit(UF::MutableFieldReference<UF::TransmogOutfitData, false> outfit,
|
||||
uint32 id, WorldPackets::Transmogrification::TransmogOutfitDataInfo const& outfitData);
|
||||
bool UpdateTransmogOutfit(uint32 id, WorldPackets::Transmogrification::TransmogOutfitDataInfo const& outfitData);
|
||||
void UpdateTransmogOutfitSituations(uint32 id, bool situationsEnabled, std::span<WorldPackets::Transmogrification::TransmogOutfitSituationInfo const> situations);
|
||||
void UpdateTransmogOutfitSlots(uint32 id, std::span<WorldPackets::Transmogrification::TransmogOutfitSlotData const> slots);
|
||||
void EquipTransmogOutfit(uint32 id, TransmogSituationTrigger trigger, Optional<bool> locked);
|
||||
std::string GetCharacterSelectOutfit() const;
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
UF::UpdateField<UF::PlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_PLAYER> m_playerData;
|
||||
@@ -3075,7 +3103,9 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
void _LoadDeclinedNames(PreparedQueryResult result);
|
||||
void _LoadArenaTeamInfo(PreparedQueryResult result);
|
||||
void _LoadEquipmentSets(PreparedQueryResult result);
|
||||
void _LoadTransmogOutfits(PreparedQueryResult result);
|
||||
void _LoadTransmogCustomSets(PreparedQueryResult result);
|
||||
void _LoadTransmogOutfits(PreparedQueryResult setsResult, PreparedQueryResult situationsResult, PreparedQueryResult slotsResult,
|
||||
int32 equippedTransmogOutfitId, bool locked);
|
||||
void _LoadBGData(PreparedQueryResult result);
|
||||
void _LoadGlyphs(PreparedQueryResult result);
|
||||
void _LoadTalents(PreparedQueryResult result);
|
||||
@@ -3106,6 +3136,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
void _SaveSpells(CharacterDatabaseTransaction trans);
|
||||
void _SaveStoredAuraTeleportLocations(CharacterDatabaseTransaction trans);
|
||||
void _SaveEquipmentSets(CharacterDatabaseTransaction trans);
|
||||
void _SaveTransmogOutfits(CharacterDatabaseTransaction trans);
|
||||
void _SaveBGData(CharacterDatabaseTransaction trans);
|
||||
void _SaveGlyphs(CharacterDatabaseTransaction trans) const;
|
||||
void _SaveTalents(CharacterDatabaseTransaction trans);
|
||||
@@ -3254,6 +3285,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
|
||||
std::unique_ptr<Runes> m_runes;
|
||||
EquipmentSetContainer _equipmentSets;
|
||||
std::set<uint32> m_changedTransmogOutfits;
|
||||
|
||||
bool CanNeverSee(WorldObject const* obj, bool ignorePhaseShift = false) const override;
|
||||
bool CanAlwaysSee(WorldObject const* obj) const override;
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#include "TerrainMgr.h"
|
||||
#include "ThreadPool.h"
|
||||
#include "Timer.h"
|
||||
#include "TransmogMgr.h"
|
||||
#include "TransportMgr.h"
|
||||
#include "VMapFactory.h"
|
||||
#include "VMapManager.h"
|
||||
@@ -1509,12 +1510,12 @@ void ObjectMgr::LoadEquipmentTemplates()
|
||||
}
|
||||
|
||||
// AppearanceModId 0 is always valid
|
||||
if (equipmentInfo.Items[i].AppearanceModId && !sDB2Manager.GetItemModifiedAppearance(equipmentInfo.Items[i].ItemId, equipmentInfo.Items[i].AppearanceModId))
|
||||
if (equipmentInfo.Items[i].AppearanceModId && !TransmogMgr::GetItemModifiedAppearance(equipmentInfo.Items[i].ItemId, equipmentInfo.Items[i].AppearanceModId))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Unknown item appearance for (ID={}, AppearanceModID={}) pair in creature_equip_template.ItemID{} creature_equip_template.AppearanceModID{} "
|
||||
"for CreatureID = {} and ID={}, forced to default.",
|
||||
equipmentInfo.Items[i].ItemId, equipmentInfo.Items[i].AppearanceModId, i + 1, i + 1, entry, id);
|
||||
if (ItemModifiedAppearanceEntry const* defaultAppearance = sDB2Manager.GetDefaultItemModifiedAppearance(equipmentInfo.Items[i].ItemId))
|
||||
if (ItemModifiedAppearanceEntry const* defaultAppearance = TransmogMgr::GetDefaultItemModifiedAppearance(equipmentInfo.Items[i].ItemId))
|
||||
equipmentInfo.Items[i].AppearanceModId = defaultAppearance->ItemAppearanceModifierID;
|
||||
else
|
||||
equipmentInfo.Items[i].AppearanceModId = 0;
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "SocialMgr.h"
|
||||
#include "StringConvert.h"
|
||||
#include "SystemPackets.h"
|
||||
#include "TransmogMgr.h"
|
||||
#include "Util.h"
|
||||
#include "World.h"
|
||||
#include <boost/circular_buffer.hpp>
|
||||
@@ -257,6 +258,18 @@ bool LoginQueryHolder::Initialize()
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFITS, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT_SITUATION);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT_SITUATION, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFIT_SLOT);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFIT_SLOT, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUF_PROFILES);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, stmt);
|
||||
@@ -2047,10 +2060,7 @@ void WorldSession::HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipm
|
||||
auto validateIllusion = [this](uint32 enchantId) -> bool
|
||||
{
|
||||
SpellItemEnchantmentEntry const* illusion = sSpellItemEnchantmentStore.LookupEntry(enchantId);
|
||||
if (!illusion)
|
||||
return false;
|
||||
|
||||
if (!illusion->ItemVisual || !illusion->GetFlags().HasFlag(SpellItemEnchantmentFlags::AllowTransmog))
|
||||
if (!illusion || !TransmogMgr::GetTransmogIllusionForSpellItemEnchantment(enchantId))
|
||||
return false;
|
||||
|
||||
if (!ConditionMgr::IsPlayerMeetingCondition(_player, illusion->TransmogUseConditionID))
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "NPCPackets.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "TransmogMgr.h"
|
||||
#include "TransmogrificationPackets.h"
|
||||
|
||||
void WorldSession::HandleTransmogrifyItems(WorldPackets::Transmogrification::TransmogrifyItems& transmogrifyItems)
|
||||
@@ -128,7 +129,7 @@ void WorldSession::HandleTransmogrifyItems(WorldPackets::Transmogrification::Tra
|
||||
return;
|
||||
}
|
||||
|
||||
TransmogIllusionEntry const* illusion = sDB2Manager.GetTransmogIllusionForEnchantment(transmogItem.SpellItemEnchantmentID);
|
||||
TransmogIllusionEntry const* illusion = TransmogMgr::GetTransmogIllusionForSpellItemEnchantment(transmogItem.SpellItemEnchantmentID);
|
||||
if (!illusion)
|
||||
{
|
||||
TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - {}, Name: {} tried to transmogrify illusion using invalid enchant ({}).", player->GetGUID().ToString(), player->GetName(), transmogItem.SpellItemEnchantmentID);
|
||||
@@ -326,6 +327,283 @@ void WorldSession::HandleTransmogrifyItems(WorldPackets::Transmogrification::Tra
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleTransmogOutfitNew(WorldPackets::Transmogrification::TransmogOutfitNew const& transmogOutfitNew)
|
||||
{
|
||||
if (!_player->GetNPCIfCanInteractWith(transmogOutfitNew.Npc, UNIT_NPC_FLAG_TRANSMOGRIFIER, UNIT_NPC_FLAG_2_NONE))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitNew - {} not found or player can't interact with it.",
|
||||
GetPlayerInfo(), transmogOutfitNew.Npc);
|
||||
return;
|
||||
}
|
||||
|
||||
_player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting);
|
||||
|
||||
if (transmogOutfitNew.Source != TransmogOutfitEntrySource::PlayerPurchased)
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitNew - source {} not allowed.",
|
||||
GetPlayerInfo(), transmogOutfitNew.Source);
|
||||
return;
|
||||
}
|
||||
|
||||
if (transmogOutfitNew.Info.SetType != TransmogOutfitSetType::Outfit)
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitNew - set type {} not allowed.",
|
||||
GetPlayerInfo(), transmogOutfitNew.Info.SetType);
|
||||
return;
|
||||
}
|
||||
|
||||
TransmogOutfitEntryEntry const* transmogOutfitEntry = TransmogMgr::GetNextOutfitToUnlock(transmogOutfitNew.Source, _player);
|
||||
if (!transmogOutfitEntry)
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitNew - no next unlockable outfit entry found for source {}.",
|
||||
GetPlayerInfo(), transmogOutfitNew.Source);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_player->HasEnoughMoney(transmogOutfitEntry->Cost))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitNew - not enough money.",
|
||||
GetPlayerInfo());
|
||||
return;
|
||||
}
|
||||
|
||||
GetCollectionMgr()->AddTransmogOutfit(transmogOutfitEntry->ID);
|
||||
_player->CreateTransmogOutfit(transmogOutfitEntry->ID, transmogOutfitNew.Info);
|
||||
_player->ModifyMoney(-int64(transmogOutfitEntry->Cost));
|
||||
|
||||
WorldPackets::Transmogrification::TransmogOutfitNewEntryAdded transmogOutfitNewEntryAdded;
|
||||
transmogOutfitNewEntryAdded.TransmogOutfitID = transmogOutfitEntry->ID;
|
||||
SendPacket(transmogOutfitNewEntryAdded.Write());
|
||||
}
|
||||
|
||||
void WorldSession::HandleTransmogOutfitUpdateInfo(WorldPackets::Transmogrification::TransmogOutfitUpdateInfo const& transmogOutfitUpdateInfo)
|
||||
{
|
||||
if (!_player->GetNPCIfCanInteractWith(transmogOutfitUpdateInfo.Npc, UNIT_NPC_FLAG_TRANSMOGRIFIER, UNIT_NPC_FLAG_2_NONE))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitNew - {} not found or player can't interact with it.",
|
||||
GetPlayerInfo(), transmogOutfitUpdateInfo.Npc);
|
||||
return;
|
||||
}
|
||||
|
||||
_player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting);
|
||||
|
||||
if (!_player->UpdateTransmogOutfit(transmogOutfitUpdateInfo.OutfitID, transmogOutfitUpdateInfo.Info))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateInfo - player does not have outfit {}.",
|
||||
GetPlayerInfo(), transmogOutfitUpdateInfo.OutfitID);
|
||||
return;
|
||||
}
|
||||
|
||||
// SMSG_UPDATE_OBJECT must be received by client before transmog packet for UI to properly update
|
||||
Player::ValuesUpdateForPlayerWithMaskSender sendUpdateObject(_player);
|
||||
sendUpdateObject.ActivePlayerMask.MarkChanged(&UF::ActivePlayerData::TransmogOutfits);
|
||||
sendUpdateObject(_player);
|
||||
|
||||
WorldPackets::Transmogrification::TransmogOutfitInfoUpdated transmogOutfitInfoUpdated;
|
||||
transmogOutfitInfoUpdated.TransmogOutfitID = transmogOutfitUpdateInfo.OutfitID;
|
||||
transmogOutfitInfoUpdated.OutfitInfo = &transmogOutfitUpdateInfo.Info;
|
||||
SendPacket(transmogOutfitInfoUpdated.Write());
|
||||
}
|
||||
|
||||
void WorldSession::HandleTransmogOutfitUpdateSituations(WorldPackets::Transmogrification::TransmogOutfitUpdateSituations const& transmogOutfitUpdateSituations)
|
||||
{
|
||||
if (!_player->GetNPCIfCanInteractWith(transmogOutfitUpdateSituations.Npc, UNIT_NPC_FLAG_TRANSMOGRIFIER, UNIT_NPC_FLAG_2_NONE))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitNew - {} not found or player can't interact with it.",
|
||||
GetPlayerInfo(), transmogOutfitUpdateSituations.Npc);
|
||||
return;
|
||||
}
|
||||
|
||||
_player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting);
|
||||
|
||||
if (!_player->m_activePlayerData->TransmogOutfits.Get(transmogOutfitUpdateSituations.OutfitID))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSituations - player does not have outfit {}.",
|
||||
GetPlayerInfo(), transmogOutfitUpdateSituations.OutfitID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TransmogMgr::ValidateSituations(transmogOutfitUpdateSituations.Situations))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSituations - player sent invalid situations.",
|
||||
GetPlayerInfo());
|
||||
return;
|
||||
}
|
||||
|
||||
_player->UpdateTransmogOutfitSituations(transmogOutfitUpdateSituations.OutfitID, transmogOutfitUpdateSituations.SituationsEnabled,
|
||||
transmogOutfitUpdateSituations.Situations);
|
||||
|
||||
// SMSG_UPDATE_OBJECT must be received by client before transmog packet for UI to properly update
|
||||
Player::ValuesUpdateForPlayerWithMaskSender sendUpdateObject(_player);
|
||||
sendUpdateObject.ActivePlayerMask.MarkChanged(&UF::ActivePlayerData::TransmogOutfits);
|
||||
sendUpdateObject(_player);
|
||||
|
||||
WorldPackets::Transmogrification::TransmogOutfitSituationsUpdated transmogOutfitSituationsUpdated;
|
||||
transmogOutfitSituationsUpdated.TransmogOutfitID = transmogOutfitUpdateSituations.OutfitID;
|
||||
transmogOutfitSituationsUpdated.SituationsEnabled = transmogOutfitUpdateSituations.SituationsEnabled;
|
||||
transmogOutfitSituationsUpdated.Situations = transmogOutfitUpdateSituations.Situations;
|
||||
SendPacket(transmogOutfitSituationsUpdated.Write());
|
||||
}
|
||||
|
||||
void WorldSession::HandleTransmogOutfitUpdateSlots(WorldPackets::Transmogrification::TransmogOutfitUpdateSlots const& transmogOutfitUpdateSlots)
|
||||
{
|
||||
if (!_player->GetNPCIfCanInteractWith(transmogOutfitUpdateSlots.Npc, UNIT_NPC_FLAG_TRANSMOGRIFIER, UNIT_NPC_FLAG_2_NONE))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitNew - {} not found or player can't interact with it.",
|
||||
GetPlayerInfo(), transmogOutfitUpdateSlots.Npc);
|
||||
return;
|
||||
}
|
||||
|
||||
_player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting);
|
||||
|
||||
UF::TransmogOutfitData const* transmogOutfit = _player->m_activePlayerData->TransmogOutfits.Get(transmogOutfitUpdateSlots.OutfitID);
|
||||
if (!transmogOutfit)
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSlots - player does not have outfit {}.",
|
||||
GetPlayerInfo(), transmogOutfitUpdateSlots.OutfitID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TransmogMgr::ValidateSlots(transmogOutfitUpdateSlots.Slots))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSlots - player sent invalid slots.",
|
||||
GetPlayerInfo());
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint32> bindAppearances;
|
||||
|
||||
for (WorldPackets::Transmogrification::TransmogOutfitSlotData const& slot : transmogOutfitUpdateSlots.Slots)
|
||||
{
|
||||
if (slot.ItemModifiedAppearanceID)
|
||||
{
|
||||
auto [hasAppearance, isTemporary] = GetCollectionMgr()->HasItemAppearance(slot.ItemModifiedAppearanceID);
|
||||
if (!hasAppearance)
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSlots - player does not have appearance {} in collection.",
|
||||
GetPlayerInfo(), slot.ItemModifiedAppearanceID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTemporary)
|
||||
bindAppearances.push_back(slot.ItemModifiedAppearanceID);
|
||||
}
|
||||
|
||||
if (slot.SpellItemEnchantmentID && !GetCollectionMgr()->HasTransmogIllusion(TransmogMgr::GetTransmogIllusionForSpellItemEnchantment(slot.SpellItemEnchantmentID)->ID))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSlots - player does not have enchant {} in illusion collection.",
|
||||
GetPlayerInfo(), slot.SpellItemEnchantmentID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmogOutfitUpdateSlots.UseAvailableDiscount && _player->HasPlayerLocalFlag(PLAYER_LOCAL_FLAG_FREE_TRANSMOG_CLAIMED))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSlots - player has already claimed free transmog before.",
|
||||
GetPlayerInfo());
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate cost
|
||||
float baseCost = 0;
|
||||
if (uint32 curveId = sDB2Manager.GetGlobalCurveId(GlobalCurve::TransmogCost))
|
||||
baseCost = sDB2Manager.GetCurveValueAt(curveId, std::max<int32>(_player->GetLevel(), _player->m_activePlayerData->MaxLevel));
|
||||
|
||||
float costMultiplier = 1.0f;
|
||||
TransmogOutfitEntryEntry const* transmogOutfitEntry = sTransmogOutfitEntryStore.AssertEntry(transmogOutfitUpdateSlots.OutfitID);
|
||||
if (transmogOutfitEntry->HasFlag(TransmogOutfitEntryFlags::UseOverrideCostModifier))
|
||||
costMultiplier *= transmogOutfitEntry->OverrideCostModifier;
|
||||
|
||||
if (_player->HasAuraType(SPELL_AURA_MOD_TRANSMOG_OUTFIT_UPDATE_COST))
|
||||
costMultiplier *= _player->m_activePlayerData->TransmogMetadata->CostMod;
|
||||
|
||||
if (sChrRacesStore.AssertEntry(_player->GetRace())->GetFlags().HasFlag(ChrRacesFlag::VoidVendorDiscount))
|
||||
costMultiplier *= 0.5f;
|
||||
|
||||
uint64 cost = 0;
|
||||
|
||||
if (!transmogOutfitUpdateSlots.UseAvailableDiscount)
|
||||
{
|
||||
auto oldSlotItr = transmogOutfit->Slots.begin();
|
||||
auto oldSlotEnd = transmogOutfit->Slots.end();
|
||||
for (WorldPackets::Transmogrification::TransmogOutfitSlotData const& slot : transmogOutfitUpdateSlots.Slots)
|
||||
{
|
||||
oldSlotItr = std::ranges::find(oldSlotItr, oldSlotEnd,
|
||||
std::pair(AsUnderlyingType(slot.Slot), AsUnderlyingType(slot.SlotOption)),
|
||||
[](UF::TransmogOutfitSlotData const& slotData) { return std::pair(*slotData.Slot, *slotData.SlotOption); });
|
||||
|
||||
auto [slotEntry, slotOptionEntry, _] = *TransmogMgr::GetSlotAndOption(slot.Slot, slot.SlotOption);
|
||||
|
||||
if (slot.AppearanceDisplayType == TransmogOutfitDisplayType::Assigned && oldSlotItr->ItemModifiedAppearanceID != slot.ItemModifiedAppearanceID)
|
||||
{
|
||||
if (slotEntry)
|
||||
cost = static_cast<uint64>(std::floor(baseCost * slotEntry->ItemCostMultiplier)) + cost;
|
||||
|
||||
if (slotOptionEntry)
|
||||
cost = static_cast<uint64>(std::floor(baseCost * slotOptionEntry->ItemCostMultiplier)) + cost;
|
||||
}
|
||||
|
||||
if (slot.IllusionDisplayType == TransmogOutfitDisplayType::Assigned && oldSlotItr->SpellItemEnchantmentID != slot.SpellItemEnchantmentID)
|
||||
{
|
||||
if (slotEntry)
|
||||
cost = static_cast<uint64>(std::floor(baseCost * slotEntry->IllusionCostMultiplier)) + cost;
|
||||
|
||||
if (slotOptionEntry)
|
||||
cost = static_cast<uint64>(std::floor(baseCost * slotOptionEntry->IllusionCostMultiplier)) + cost;
|
||||
}
|
||||
|
||||
++oldSlotItr;
|
||||
}
|
||||
|
||||
cost = static_cast<uint64>(std::clamp(costMultiplier, 0.0f, 1.0f) * cost);
|
||||
|
||||
if (cost != transmogOutfitUpdateSlots.Cost)
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSlots - player sent invalid cost {}.",
|
||||
GetPlayerInfo(), transmogOutfitUpdateSlots.Cost);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_player->HasEnoughMoney(cost))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "{} WorldSession::HandleTransmogOutfitUpdateSlots - not enough money.",
|
||||
GetPlayerInfo());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_player->SetPlayerLocalFlag(PLAYER_LOCAL_FLAG_FREE_TRANSMOG_CLAIMED);
|
||||
_player->SetHasClaimedFreeTransmog();
|
||||
}
|
||||
|
||||
_player->ModifyMoney(-int64(cost));
|
||||
|
||||
_player->UpdateTransmogOutfitSlots(transmogOutfitUpdateSlots.OutfitID, transmogOutfitUpdateSlots.Slots);
|
||||
|
||||
if (transmogOutfitUpdateSlots.OutfitID == _player->m_activePlayerData->TransmogMetadata->TransmogOutfitID)
|
||||
_player->EquipTransmogOutfit(transmogOutfitUpdateSlots.OutfitID, TransmogSituationTrigger::TransmogUpdate, {});
|
||||
|
||||
WorldPackets::Transmogrification::TransmogOutfitSlotsUpdated transmogOutfitSlotsUpdated;
|
||||
transmogOutfitSlotsUpdated.TransmogOutfitID = transmogOutfitUpdateSlots.OutfitID;
|
||||
transmogOutfitSlotsUpdated.Slots = transmogOutfitUpdateSlots.Slots;
|
||||
SendPacket(transmogOutfitSlotsUpdated.Write());
|
||||
|
||||
for (uint32 itemModifedAppearanceId : bindAppearances)
|
||||
{
|
||||
std::unordered_set<ObjectGuid> itemsProvidingAppearance = GetCollectionMgr()->GetItemsProvidingTemporaryAppearance(itemModifedAppearanceId);
|
||||
for (ObjectGuid const& itemGuid : itemsProvidingAppearance)
|
||||
{
|
||||
if (Item* item = _player->GetItemByGuid(itemGuid))
|
||||
{
|
||||
item->SetNotRefundable(_player);
|
||||
item->ClearSoulboundTradeable(_player);
|
||||
GetCollectionMgr()->AddItemAppearance(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::SendOpenTransmogrifier(ObjectGuid const& guid)
|
||||
{
|
||||
WorldPackets::NPC::NPCInteractionOpenResult npcInteraction;
|
||||
|
||||
@@ -37,9 +37,164 @@ void TransmogrifyItems::Read()
|
||||
for (TransmogrifyItem& item : Items)
|
||||
_worldPacket >> item;
|
||||
|
||||
_worldPacket.ResetBitPos();
|
||||
_worldPacket >> Bits<1>(CurrentSpecOnly);
|
||||
}
|
||||
|
||||
ByteBuffer& operator>>(ByteBuffer& data, TransmogOutfitDataInfo& transmogOutfitDataInfo)
|
||||
{
|
||||
data.ResetBitPos();
|
||||
data >> As<uint8>(transmogOutfitDataInfo.SetType);
|
||||
data >> transmogOutfitDataInfo.Icon;
|
||||
data >> SizedString::BitsSize<8>(transmogOutfitDataInfo.Name);
|
||||
data >> Bits<1>(transmogOutfitDataInfo.SituationsEnabled);
|
||||
|
||||
data >> SizedString::Data(transmogOutfitDataInfo.Name);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, TransmogOutfitDataInfo const& transmogOutfitDataInfo)
|
||||
{
|
||||
data << As<uint8>(transmogOutfitDataInfo.SetType);
|
||||
data << uint32(transmogOutfitDataInfo.Icon);
|
||||
data << SizedString::BitsSize<8>(transmogOutfitDataInfo.Name);
|
||||
data << Bits<1>(transmogOutfitDataInfo.SituationsEnabled);
|
||||
data.FlushBits();
|
||||
|
||||
data << SizedString::Data(transmogOutfitDataInfo.Name);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void TransmogOutfitNew::Read()
|
||||
{
|
||||
_worldPacket >> Npc;
|
||||
_worldPacket >> As<uint8>(Source);
|
||||
_worldPacket >> Info;
|
||||
}
|
||||
|
||||
WorldPacket const* TransmogOutfitNewEntryAdded::Write()
|
||||
{
|
||||
_worldPacket << uint32(TransmogOutfitID);
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
void TransmogOutfitUpdateInfo::Read()
|
||||
{
|
||||
_worldPacket >> OutfitID;
|
||||
_worldPacket >> Npc;
|
||||
_worldPacket >> Info;
|
||||
}
|
||||
|
||||
WorldPacket const* TransmogOutfitInfoUpdated::Write()
|
||||
{
|
||||
_worldPacket << uint32(TransmogOutfitID);
|
||||
_worldPacket << *OutfitInfo;
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
ByteBuffer& operator>>(ByteBuffer& data, TransmogOutfitSituationInfo& transmogOutfitSituationInfo)
|
||||
{
|
||||
data >> transmogOutfitSituationInfo.SituationID;
|
||||
data >> transmogOutfitSituationInfo.SpecID;
|
||||
data >> transmogOutfitSituationInfo.LoadoutID;
|
||||
data >> transmogOutfitSituationInfo.EquipmentSetID;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, TransmogOutfitSituationInfo const& transmogOutfitSituationInfo)
|
||||
{
|
||||
data << uint32(transmogOutfitSituationInfo.SituationID);
|
||||
data << uint32(transmogOutfitSituationInfo.SpecID);
|
||||
data << uint32(transmogOutfitSituationInfo.LoadoutID);
|
||||
data << uint32(transmogOutfitSituationInfo.EquipmentSetID);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void TransmogOutfitUpdateSituations::Read()
|
||||
{
|
||||
_worldPacket >> OutfitID;
|
||||
_worldPacket >> Npc;
|
||||
_worldPacket >> Size<uint32>(Situations);
|
||||
for (TransmogOutfitSituationInfo& situation : Situations)
|
||||
_worldPacket >> situation;
|
||||
|
||||
_worldPacket.ResetBitPos();
|
||||
_worldPacket >> Bits<1>(SituationsEnabled);
|
||||
}
|
||||
|
||||
WorldPacket const* TransmogOutfitSituationsUpdated::Write()
|
||||
{
|
||||
_worldPacket << uint32(TransmogOutfitID);
|
||||
_worldPacket << Size<uint32>(Situations);
|
||||
|
||||
for (TransmogOutfitSituationInfo const& situation : Situations)
|
||||
_worldPacket << situation;
|
||||
|
||||
_worldPacket << Bits<1>(SituationsEnabled);
|
||||
_worldPacket.FlushBits();
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
ByteBuffer& operator>>(ByteBuffer& data, TransmogOutfitSlotData& transmogOutfitSlotData)
|
||||
{
|
||||
data >> As<int8>(transmogOutfitSlotData.Slot);
|
||||
data >> As<uint8>(transmogOutfitSlotData.SlotOption);
|
||||
data >> transmogOutfitSlotData.ItemModifiedAppearanceID;
|
||||
data >> As<uint8>(transmogOutfitSlotData.AppearanceDisplayType);
|
||||
data >> transmogOutfitSlotData.SpellItemEnchantmentID;
|
||||
data >> As<uint8>(transmogOutfitSlotData.IllusionDisplayType);
|
||||
data >> transmogOutfitSlotData.Flags;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, TransmogOutfitSlotData const& transmogOutfitSlotData)
|
||||
{
|
||||
data << As<int8>(transmogOutfitSlotData.Slot);
|
||||
data << As<uint8>(transmogOutfitSlotData.SlotOption);
|
||||
data << uint32(transmogOutfitSlotData.ItemModifiedAppearanceID);
|
||||
data << As<uint8>(transmogOutfitSlotData.AppearanceDisplayType);
|
||||
data << uint32(transmogOutfitSlotData.SpellItemEnchantmentID);
|
||||
data << As<uint8>(transmogOutfitSlotData.IllusionDisplayType);
|
||||
data << uint32(transmogOutfitSlotData.Flags);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void TransmogOutfitUpdateSlots::Read()
|
||||
{
|
||||
_worldPacket >> OutfitID;
|
||||
_worldPacket >> Size<uint32>(Slots);
|
||||
_worldPacket >> Npc;
|
||||
_worldPacket >> Cost;
|
||||
|
||||
for (TransmogOutfitSlotData& slot : Slots)
|
||||
_worldPacket >> slot;
|
||||
|
||||
_worldPacket.ResetBitPos();
|
||||
_worldPacket >> Bits<1>(UseAvailableDiscount);
|
||||
|
||||
std::ranges::sort(Slots, std::ranges::less(), [](TransmogOutfitSlotData const& slot) { return std::pair(slot.Slot, slot.SlotOption); });
|
||||
}
|
||||
|
||||
WorldPacket const* TransmogOutfitSlotsUpdated::Write()
|
||||
{
|
||||
_worldPacket << uint32(TransmogOutfitID);
|
||||
_worldPacket << Size<uint32>(Slots);
|
||||
|
||||
for (TransmogOutfitSlotData const& slot : Slots)
|
||||
_worldPacket << slot;
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
WorldPacket const* AccountTransmogUpdate::Write()
|
||||
{
|
||||
_worldPacket << Bits<1>(IsFullUpdate);
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
#include "ObjectGuid.h"
|
||||
#include "PacketUtilities.h"
|
||||
|
||||
enum class TransmogOutfitDisplayType : uint8;
|
||||
enum class TransmogOutfitEntrySource : uint8;
|
||||
enum class TransmogOutfitSetType : uint8;
|
||||
enum class TransmogOutfitSlot : int8;
|
||||
enum class TransmogOutfitSlotOption : uint8;
|
||||
|
||||
namespace WorldPackets
|
||||
{
|
||||
namespace Transmogrification
|
||||
@@ -51,6 +57,128 @@ namespace WorldPackets
|
||||
bool CurrentSpecOnly = false;
|
||||
};
|
||||
|
||||
struct TransmogOutfitDataInfo
|
||||
{
|
||||
TransmogOutfitSetType SetType = { };
|
||||
bool SituationsEnabled = false;
|
||||
uint32 Icon = 0;
|
||||
std::string_view Name;
|
||||
};
|
||||
|
||||
class TransmogOutfitNew final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
explicit TransmogOutfitNew(WorldPacket&& packet) : ClientPacket(CMSG_TRANSMOG_OUTFIT_NEW, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
ObjectGuid Npc;
|
||||
TransmogOutfitDataInfo Info;
|
||||
TransmogOutfitEntrySource Source = { };
|
||||
};
|
||||
|
||||
class TransmogOutfitNewEntryAdded final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
explicit TransmogOutfitNewEntryAdded() : ServerPacket(SMSG_TRANSMOG_OUTFIT_NEW_ENTRY_ADDED, 4) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint32 TransmogOutfitID = 0;
|
||||
};
|
||||
|
||||
class TransmogOutfitUpdateInfo final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
explicit TransmogOutfitUpdateInfo(WorldPacket&& packet) : ClientPacket(CMSG_TRANSMOG_OUTFIT_UPDATE_INFO, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint32 OutfitID = 0;
|
||||
ObjectGuid Npc;
|
||||
TransmogOutfitDataInfo Info;
|
||||
};
|
||||
|
||||
class TransmogOutfitInfoUpdated final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
explicit TransmogOutfitInfoUpdated() : ServerPacket(SMSG_TRANSMOG_OUTFIT_INFO_UPDATED, 4 + 1 + 4 + 1 + 1 + 128) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint32 TransmogOutfitID = 0;
|
||||
TransmogOutfitDataInfo const* OutfitInfo = nullptr;
|
||||
};
|
||||
|
||||
struct TransmogOutfitSituationInfo
|
||||
{
|
||||
uint32 SituationID = 0;
|
||||
uint32 SpecID = 0;
|
||||
uint32 LoadoutID = 0;
|
||||
uint32 EquipmentSetID = 0;
|
||||
};
|
||||
|
||||
class TransmogOutfitUpdateSituations final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
explicit TransmogOutfitUpdateSituations(WorldPacket&& packet) : ClientPacket(CMSG_TRANSMOG_OUTFIT_UPDATE_SITUATIONS, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint32 OutfitID = 0;
|
||||
ObjectGuid Npc;
|
||||
bool SituationsEnabled = false;
|
||||
Array<TransmogOutfitSituationInfo, 100> Situations;
|
||||
};
|
||||
|
||||
class TransmogOutfitSituationsUpdated final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
explicit TransmogOutfitSituationsUpdated() : ServerPacket(SMSG_TRANSMOG_OUTFIT_SITUATIONS_UPDATED, 4 + 4 + 10 * (4 + 4 + 4 + 4) + 1) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint32 TransmogOutfitID = 0;
|
||||
bool SituationsEnabled = false;
|
||||
std::span<TransmogOutfitSituationInfo const> Situations;
|
||||
};
|
||||
|
||||
struct TransmogOutfitSlotData
|
||||
{
|
||||
TransmogOutfitSlot Slot = { };
|
||||
TransmogOutfitSlotOption SlotOption = { };
|
||||
TransmogOutfitDisplayType AppearanceDisplayType = { };
|
||||
TransmogOutfitDisplayType IllusionDisplayType = { };
|
||||
uint32 ItemModifiedAppearanceID = 0;
|
||||
uint32 SpellItemEnchantmentID = 0;
|
||||
uint32 Flags = 0;
|
||||
};
|
||||
|
||||
class TransmogOutfitUpdateSlots final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
explicit TransmogOutfitUpdateSlots(WorldPacket&& packet) : ClientPacket(CMSG_TRANSMOG_OUTFIT_UPDATE_SLOTS, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint32 OutfitID = 0;
|
||||
Array<TransmogOutfitSlotData, 30> Slots;
|
||||
ObjectGuid Npc;
|
||||
uint64 Cost = 0;
|
||||
bool UseAvailableDiscount = false;
|
||||
};
|
||||
|
||||
class TransmogOutfitSlotsUpdated final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
explicit TransmogOutfitSlotsUpdated() : ServerPacket(SMSG_TRANSMOG_OUTFIT_SLOTS_UPDATED, 4 + 4 + 30 * (1 + 1 + 4 + 1 + 4 + 1 + 4)) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint32 TransmogOutfitID = 0;
|
||||
std::span<TransmogOutfitSlotData const> Slots;
|
||||
};
|
||||
|
||||
class AccountTransmogUpdate final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -1105,10 +1105,10 @@ void OpcodeTable::InitializeClientOpcodes()
|
||||
DEFINE_HANDLER(CMSG_TRAITS_TALENT_TEST_UNLEARN_SPELLS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_TRANSFER_CURRENCY_FROM_ACCOUNT_CHARACTER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOGRIFY_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogrifyItems);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOG_OUTFIT_NEW, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOG_OUTFIT_UPDATE_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOG_OUTFIT_UPDATE_SITUATIONS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOG_OUTFIT_UPDATE_SLOTS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOG_OUTFIT_NEW, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogOutfitNew);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOG_OUTFIT_UPDATE_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogOutfitUpdateInfo);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOG_OUTFIT_UPDATE_SITUATIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogOutfitUpdateSituations);
|
||||
DEFINE_HANDLER(CMSG_TRANSMOG_OUTFIT_UPDATE_SLOTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogOutfitUpdateSlots);
|
||||
DEFINE_HANDLER(CMSG_TURN_IN_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTurnInPetition);
|
||||
DEFINE_HANDLER(CMSG_TUTORIAL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialFlag);
|
||||
DEFINE_HANDLER(CMSG_UI_MAP_QUEST_LINES_REQUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleUiMapQuestLinesRequest);
|
||||
@@ -2454,10 +2454,10 @@ void OpcodeTable::InitializeServerOpcodes()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAIT_CONFIG_COMMIT_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_ABORTED, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_PENDING, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_INFO_UPDATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_NEW_ENTRY_ADDED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_SITUATIONS_UPDATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_SLOTS_UPDATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_INFO_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_NEW_ENTRY_ADDED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_SITUATIONS_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_SLOTS_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TREASURE_PICKER_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TREASURE_PUNCH_LIST_ITEMS_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_CINEMATIC, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
|
||||
@@ -1136,11 +1136,7 @@ bool WorldSession::IsAddonRegistered(std::string_view prefix) const
|
||||
if (!_filterAddonMessages) // if we have hit the softcap (64) nothing should be filtered
|
||||
return true;
|
||||
|
||||
if (_registeredAddonPrefixes.empty())
|
||||
return false;
|
||||
|
||||
std::vector<std::string>::const_iterator itr = std::find(_registeredAddonPrefixes.begin(), _registeredAddonPrefixes.end(), prefix);
|
||||
return itr != _registeredAddonPrefixes.end();
|
||||
return advstd::ranges::contains(_registeredAddonPrefixes, prefix);
|
||||
}
|
||||
|
||||
void WorldSession::HandleUnregisterAllAddonPrefixesOpcode(WorldPackets::Chat::ChatUnregisterAllAddonPrefixes& /*packet*/) // empty packet
|
||||
@@ -1259,6 +1255,7 @@ public:
|
||||
ITEM_APPEARANCES,
|
||||
ITEM_FAVORITE_APPEARANCES,
|
||||
TRANSMOG_ILLUSIONS,
|
||||
TRANSMOG_OUTFITS,
|
||||
WARBAND_SCENES,
|
||||
PLAYER_DATA_ELEMENTS_ACCOUNT,
|
||||
PLAYER_DATA_FLAGS_ACCOUNT,
|
||||
@@ -1309,6 +1306,10 @@ public:
|
||||
stmt->setUInt32(0, battlenetAccountId);
|
||||
ok = SetPreparedQuery(TRANSMOG_ILLUSIONS, stmt) && ok;
|
||||
|
||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_TRANSMOG_OUTFITS);
|
||||
stmt->setUInt32(0, battlenetAccountId);
|
||||
ok = SetPreparedQuery(TRANSMOG_OUTFITS, stmt) && ok;
|
||||
|
||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_WARBAND_SCENES);
|
||||
stmt->setUInt32(0, battlenetAccountId);
|
||||
ok = SetPreparedQuery(WARBAND_SCENES, stmt) && ok;
|
||||
@@ -1373,6 +1374,7 @@ void WorldSession::InitializeSessionCallback(LoginDatabaseQueryHolder const& hol
|
||||
_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));
|
||||
_collectionMgr->LoadAccountTransmogOutfits(holder.GetPreparedResult(AccountInfoQueryHolder::TRANSMOG_OUTFITS));
|
||||
_collectionMgr->LoadAccountWarbandScenes(holder.GetPreparedResult(AccountInfoQueryHolder::WARBAND_SCENES));
|
||||
LoadPlayerDataAccount(holder.GetPreparedResult(AccountInfoQueryHolder::PLAYER_DATA_ELEMENTS_ACCOUNT), holder.GetPreparedResult(AccountInfoQueryHolder::PLAYER_DATA_FLAGS_ACCOUNT));
|
||||
|
||||
|
||||
@@ -819,6 +819,10 @@ namespace WorldPackets
|
||||
namespace Transmogrification
|
||||
{
|
||||
class TransmogrifyItems;
|
||||
class TransmogOutfitNew;
|
||||
class TransmogOutfitUpdateInfo;
|
||||
class TransmogOutfitUpdateSituations;
|
||||
class TransmogOutfitUpdateSlots;
|
||||
}
|
||||
|
||||
namespace Vehicle
|
||||
@@ -1790,6 +1794,10 @@ class TC_GAME_API WorldSession
|
||||
|
||||
// Transmogrification
|
||||
void HandleTransmogrifyItems(WorldPackets::Transmogrification::TransmogrifyItems& transmogrifyItems);
|
||||
void HandleTransmogOutfitNew(WorldPackets::Transmogrification::TransmogOutfitNew const& transmogOutfitNew);
|
||||
void HandleTransmogOutfitUpdateInfo(WorldPackets::Transmogrification::TransmogOutfitUpdateInfo const& transmogOutfitUpdateInfo);
|
||||
void HandleTransmogOutfitUpdateSituations(WorldPackets::Transmogrification::TransmogOutfitUpdateSituations const& transmogOutfitUpdateSituations);
|
||||
void HandleTransmogOutfitUpdateSlots(WorldPackets::Transmogrification::TransmogOutfitUpdateSlots const& transmogOutfitUpdateSlots);
|
||||
|
||||
// Miscellaneous
|
||||
void HandleSpellClick(WorldPackets::Spells::SpellClick& spellClick);
|
||||
|
||||
@@ -735,7 +735,7 @@ enum AuraType : uint32
|
||||
SPELL_AURA_ADD_FLAT_PVP_MODIFIER_BY_SPELL_LABEL = 648,
|
||||
SPELL_AURA_ADD_PCT_PVP_MODIFIER_BY_SPELL_LABEL = 649,
|
||||
SPELL_AURA_650 = 650,
|
||||
SPELL_AURA_651 = 651,
|
||||
SPELL_AURA_ENABLE_EVENT_TRANSMOG_OUTFIT = 651,
|
||||
SPELL_AURA_652 = 652,
|
||||
SPELL_AURA_653 = 653,
|
||||
SPELL_AURA_654 = 654,
|
||||
|
||||
@@ -720,7 +720,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
|
||||
&AuraEffect::HandleNULL, //648 SPELL_AURA_ADD_FLAT_PVP_MODIFIER_BY_SPELL_LABEL
|
||||
&AuraEffect::HandleNULL, //649 SPELL_AURA_ADD_PCT_PVP_MODIFIER_BY_SPELL_LABEL
|
||||
&AuraEffect::HandleNULL, //650
|
||||
&AuraEffect::HandleNULL, //651
|
||||
&AuraEffect::HandleNULL, //651 SPELL_AURA_ENABLE_EVENT_TRANSMOG_OUTFIT
|
||||
&AuraEffect::HandleNULL, //652
|
||||
&AuraEffect::HandleNULL, //653
|
||||
&AuraEffect::HandleNULL, //654
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "TemporarySummon.h"
|
||||
#include "TradeData.h"
|
||||
#include "TraitPackets.h"
|
||||
#include "TransmogMgr.h"
|
||||
#include "UniqueTrackablePtr.h"
|
||||
#include "Util.h"
|
||||
#include "VMapFactory.h"
|
||||
@@ -4973,7 +4974,10 @@ int32 Spell::GetSpellCastDataAmmo()
|
||||
switch (itemEntry->SubclassID)
|
||||
{
|
||||
case ITEM_SUBCLASS_WEAPON_THROWN:
|
||||
ammoDisplayID = sDB2Manager.GetItemDisplayId(item_id, unitCaster->GetVirtualItemAppearanceMod(i));
|
||||
if (ItemModifiedAppearanceEntry const* modifiedAppearance = TransmogMgr::GetItemModifiedAppearance(item_id, unitCaster->GetVirtualItemAppearanceMod(i)))
|
||||
if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(modifiedAppearance->ItemAppearanceID))
|
||||
ammoDisplayID = itemAppearance->ItemDisplayInfoID;
|
||||
|
||||
ammoInventoryType = itemEntry->InventoryType;
|
||||
break;
|
||||
case ITEM_SUBCLASS_WEAPON_BOW:
|
||||
@@ -4986,7 +4990,10 @@ int32 Spell::GetSpellCastDataAmmo()
|
||||
ammoInventoryType = INVTYPE_AMMO;
|
||||
break;
|
||||
default:
|
||||
nonRangedAmmoDisplayID = sDB2Manager.GetItemDisplayId(item_id, unitCaster->GetVirtualItemAppearanceMod(i));
|
||||
if (ItemModifiedAppearanceEntry const* modifiedAppearance = TransmogMgr::GetItemModifiedAppearance(item_id, unitCaster->GetVirtualItemAppearanceMod(i)))
|
||||
if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(modifiedAppearance->ItemAppearanceID))
|
||||
nonRangedAmmoDisplayID = itemAppearance->ItemDisplayInfoID;
|
||||
|
||||
nonRangedAmmoInventoryType = itemEntry->InventoryType;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -464,6 +464,7 @@ class TC_GAME_API Spell
|
||||
void EffectSetPlayerDataElementCharacter();
|
||||
void EffectSetPlayerDataFlagAccount();
|
||||
void EffectSetPlayerDataFlagCharacter();
|
||||
void EffectEquipTransmogOutfit();
|
||||
|
||||
typedef std::unordered_set<Aura*> UsedSpellMods;
|
||||
|
||||
@@ -632,6 +633,14 @@ class TC_GAME_API Spell
|
||||
// SPELL_EFFECT_UPGRADE_HEIRLOOM
|
||||
uint32 ItemId;
|
||||
|
||||
// SPELL_EFFECT_EQUIP_TRANSMOG_OUTFIT
|
||||
struct
|
||||
{
|
||||
uint32 EquipAction;
|
||||
uint32 TransmogOutfitId;
|
||||
uint32 SituationTrigger;
|
||||
} EquipTransmogOutfit;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 Data[3];
|
||||
|
||||
@@ -436,7 +436,7 @@ NonDefaultConstructible<SpellEffectHandlerFn> SpellEffectHandlers[TOTAL_SPELL_EF
|
||||
&Spell::EffectNULL, //344 SPELL_EFFECT_344
|
||||
&Spell::EffectNULL, //345 SPELL_EFFECT_ASSIST_ACTION
|
||||
&Spell::EffectNULL, //346 SPELL_EFFECT_346
|
||||
&Spell::EffectNULL, //347 SPELL_EFFECT_EQUIP_TRANSMOG_OUTFIT
|
||||
&Spell::EffectEquipTransmogOutfit, //347 SPELL_EFFECT_EQUIP_TRANSMOG_OUTFIT
|
||||
&Spell::EffectNULL, //348 SPELL_EFFECT_GIVE_HOUSE_LEVEL
|
||||
&Spell::EffectNULL, //349 SPELL_EFFECT_LEARN_HOUSE_ROOM
|
||||
&Spell::EffectNULL, //350 SPELL_EFFECT_LEARN_HOUSE_EXTERIOR_COMPONENT
|
||||
@@ -6338,3 +6338,30 @@ void Spell::EffectSetPlayerDataFlagCharacter()
|
||||
|
||||
target->SetDataFlagCharacter(effectInfo->MiscValue, damage != 0);
|
||||
}
|
||||
|
||||
void Spell::EffectEquipTransmogOutfit()
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
Player* target = Object::ToPlayer(unitTarget);
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
Optional<bool> locked;
|
||||
switch (static_cast<TransmogOutfitEquipAction>(m_misc.EquipTransmogOutfit.EquipAction))
|
||||
{
|
||||
case TransmogOutfitEquipAction::EquipAndLock:
|
||||
case TransmogOutfitEquipAction::RemoveAndLock:
|
||||
case TransmogOutfitEquipAction::Lock:
|
||||
locked = true;
|
||||
break;
|
||||
case TransmogOutfitEquipAction::Unlock:
|
||||
locked = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
target->EquipTransmogOutfit(m_misc.EquipTransmogOutfit.TransmogOutfitId, static_cast<TransmogSituationTrigger>(m_misc.EquipTransmogOutfit.SituationTrigger), locked);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TransmogMgr.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "FlatSet.h"
|
||||
#include "MapUtils.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "TransmogrificationPackets.h"
|
||||
#include "Util.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct TransmogOutfitSlotOptionInfo
|
||||
{
|
||||
TransmogOutfitSlotOptionEntry const* Data = nullptr;
|
||||
int32 SlotIndex = -1;
|
||||
};
|
||||
|
||||
struct TransmogOutfitSlotInfo
|
||||
{
|
||||
TransmogOutfitSlotInfoEntry const* Data = nullptr;
|
||||
std::variant<int32, std::unique_ptr<TransmogOutfitSlotOptionInfo[]>> SlotIndexOrOptions;
|
||||
|
||||
int32 GetSlotIndex(TransmogOutfitSlotOption slotOption) const
|
||||
{
|
||||
switch (SlotIndexOrOptions.index())
|
||||
{
|
||||
case 0:
|
||||
return std::get<0>(SlotIndexOrOptions);
|
||||
case 1:
|
||||
return std::get<1>(SlotIndexOrOptions)[AsUnderlyingType(slotOption)].SlotIndex;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<std::pair<uint32 /*itemId*/, uint32 /*appearanceMod*/>, ItemModifiedAppearanceEntry const*> ItemModifiedAppearancesByItem;
|
||||
std::unordered_map<uint32, TransmogIllusionEntry const*> TransmogIllusionBySpellItemEnchantment;
|
||||
std::unordered_map<uint32, Trinity::Containers::FlatSet<TransmogSetEntry const*>> TransmogSetsByItemModifiedAppearance;
|
||||
std::vector<TransmogSetItemEntry const*> TransmogSetItemsByTransmogSet;
|
||||
std::array<std::vector<TransmogOutfitEntryEntry const*>, AsUnderlyingType(TransmogOutfitEntrySource::Max)> TransmogOutfitsBySource;
|
||||
std::vector<TransmogOutfitEntryEntry const*> TransmogOutfitsAutomaticallyCreated;
|
||||
std::vector<TransmogMgr::TransmogOutfitSlotAndOptionInfo> AllSlots;
|
||||
std::array<TransmogOutfitSlotInfo, AsUnderlyingType(TransmogOutfitSlot::Max)> SlotInfoByOutfitSlot;
|
||||
std::array<TransmogOutfitSlotInfo const*, EQUIPMENT_SLOT_END> SlotInfoByInvSlot;
|
||||
std::vector<TransmogSituationEntry const*> DefaultSituations;
|
||||
|
||||
constexpr bool IsArtifactTransmogOutfitSlotOption(TransmogOutfitSlotOption option)
|
||||
{
|
||||
return option == TransmogOutfitSlotOption::ArtifactSpecOne
|
||||
|| option == TransmogOutfitSlotOption::ArtifactSpecTwo
|
||||
|| option == TransmogOutfitSlotOption::ArtifactSpecThree
|
||||
|| option == TransmogOutfitSlotOption::ArtifactSpecFour;
|
||||
}
|
||||
|
||||
bool IsValidTransmogOutfitSlotForItem(ItemTemplate const* item, TransmogOutfitSlot slot, TransmogOutfitSlotOption option)
|
||||
{
|
||||
if (IsArtifactTransmogOutfitSlotOption(option))
|
||||
if (ArtifactEntry const* artifact = sArtifactStore.LookupEntry(item->GetArtifactID()))
|
||||
if (ChrSpecializationEntry const* specialization = sChrSpecializationStore.LookupEntry(artifact->ChrSpecializationID))
|
||||
if ((int8(option) - int8(TransmogOutfitSlotOption::ArtifactSpecOne)) != specialization->OrderIndex)
|
||||
return false;
|
||||
|
||||
switch (item->GetInventoryType())
|
||||
{
|
||||
case INVTYPE_HEAD:
|
||||
return slot == TransmogOutfitSlot::Head;
|
||||
case INVTYPE_SHOULDERS:
|
||||
return slot == TransmogOutfitSlot::ShoulderLeft || slot == TransmogOutfitSlot::ShoulderRight;
|
||||
case INVTYPE_BODY:
|
||||
return slot == TransmogOutfitSlot::Body;
|
||||
case INVTYPE_CHEST:
|
||||
case INVTYPE_ROBE:
|
||||
return slot == TransmogOutfitSlot::Chest;
|
||||
case INVTYPE_WAIST:
|
||||
return slot == TransmogOutfitSlot::Waist;
|
||||
case INVTYPE_LEGS:
|
||||
return slot == TransmogOutfitSlot::Legs;
|
||||
case INVTYPE_FEET:
|
||||
return slot == TransmogOutfitSlot::Feet;
|
||||
case INVTYPE_WRISTS:
|
||||
return slot == TransmogOutfitSlot::Wrist;
|
||||
case INVTYPE_HANDS:
|
||||
return slot == TransmogOutfitSlot::Hand;
|
||||
case INVTYPE_WEAPON:
|
||||
case INVTYPE_WEAPONMAINHAND:
|
||||
case INVTYPE_WEAPONOFFHAND:
|
||||
return slot == TransmogOutfitSlot::WeaponMainHand || slot == TransmogOutfitSlot::WeaponOffHand || IsArtifactTransmogOutfitSlotOption(option);
|
||||
case INVTYPE_SHIELD:
|
||||
case INVTYPE_HOLDABLE:
|
||||
return slot == TransmogOutfitSlot::WeaponOffHand || IsArtifactTransmogOutfitSlotOption(option);
|
||||
case INVTYPE_RANGED:
|
||||
return (slot == TransmogOutfitSlot::WeaponMainHand && option == TransmogOutfitSlotOption::RangedWeapon) || IsArtifactTransmogOutfitSlotOption(option);
|
||||
case INVTYPE_CLOAK:
|
||||
return slot == TransmogOutfitSlot::Back;
|
||||
case INVTYPE_2HWEAPON:
|
||||
return slot == TransmogOutfitSlot::WeaponMainHand || (slot == TransmogOutfitSlot::WeaponOffHand && option == TransmogOutfitSlotOption::FuryTwoHandedWeapon) || IsArtifactTransmogOutfitSlotOption(option);
|
||||
case INVTYPE_TABARD:
|
||||
return slot == TransmogOutfitSlot::Tabard;
|
||||
case INVTYPE_RANGEDRIGHT:
|
||||
return slot == (item->GetSubClass() == ITEM_SUBCLASS_WEAPON_WAND ? TransmogOutfitSlot::WeaponMainHand : TransmogOutfitSlot::WeaponRanged) || IsArtifactTransmogOutfitSlotOption(option);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void TransmogMgr::Load()
|
||||
{
|
||||
for (ItemModifiedAppearanceEntry const* appearanceMod : sItemModifiedAppearanceStore)
|
||||
ItemModifiedAppearancesByItem[{ appearanceMod->ItemID, appearanceMod->ItemAppearanceModifierID }] = appearanceMod;
|
||||
|
||||
for (TransmogIllusionEntry const* transmogIllusion : sTransmogIllusionStore)
|
||||
TransmogIllusionBySpellItemEnchantment[transmogIllusion->SpellItemEnchantmentID] = transmogIllusion;
|
||||
|
||||
for (TransmogSetItemEntry const* transmogSetItem : sTransmogSetItemStore)
|
||||
{
|
||||
TransmogSetEntry const* set = sTransmogSetStore.LookupEntry(transmogSetItem->TransmogSetID);
|
||||
if (!set)
|
||||
continue;
|
||||
|
||||
TransmogSetsByItemModifiedAppearance[transmogSetItem->ItemModifiedAppearanceID].insert(set);
|
||||
TransmogSetItemsByTransmogSet.push_back(transmogSetItem);
|
||||
}
|
||||
|
||||
std::ranges::sort(TransmogSetItemsByTransmogSet, {}, &TransmogSetItemEntry::TransmogSetID);
|
||||
|
||||
for (TransmogOutfitEntryEntry const* transmogOutfitEntry : sTransmogOutfitEntryStore)
|
||||
{
|
||||
if (transmogOutfitEntry->HasFlag(TransmogOutfitEntryFlags::AutomaticallyAwardedOnLogin))
|
||||
TransmogOutfitsAutomaticallyCreated.push_back(transmogOutfitEntry);
|
||||
|
||||
if (transmogOutfitEntry->GetSetType() == TransmogOutfitSetType::Outfit)
|
||||
TransmogOutfitsBySource[AsUnderlyingType(transmogOutfitEntry->GetSource())].push_back(transmogOutfitEntry);
|
||||
}
|
||||
|
||||
for (std::vector<TransmogOutfitEntryEntry const*>& transmogOutfitEntries : TransmogOutfitsBySource)
|
||||
std::ranges::sort(transmogOutfitEntries, {}, &TransmogOutfitEntryEntry::OrderIndex);
|
||||
|
||||
for (TransmogOutfitSlotInfoEntry const* transmogOutfitSlot : sTransmogOutfitSlotInfoStore)
|
||||
{
|
||||
ASSERT(transmogOutfitSlot->GetSlot() < TransmogOutfitSlot::Max);
|
||||
|
||||
TransmogOutfitSlotInfo* slot = &SlotInfoByOutfitSlot[AsUnderlyingType(transmogOutfitSlot->GetSlot())];
|
||||
slot->Data = transmogOutfitSlot;
|
||||
|
||||
if (!transmogOutfitSlot->HasFlag(TransmogOutfitSlotFlags::IsSecondarySlot))
|
||||
{
|
||||
ASSERT(transmogOutfitSlot->InventorySlotEnum < EQUIPMENT_SLOT_END);
|
||||
SlotInfoByInvSlot[transmogOutfitSlot->InventorySlotEnum] = slot;
|
||||
}
|
||||
}
|
||||
|
||||
for (TransmogOutfitSlotOptionEntry const* transmogOutfitSlotOption : sTransmogOutfitSlotOptionInfoStore)
|
||||
{
|
||||
ASSERT(transmogOutfitSlotOption->GetOption() < TransmogOutfitSlotOption::Max);
|
||||
|
||||
TransmogOutfitSlotInfoEntry const* transmogOutfitSlot = sTransmogOutfitSlotInfoStore.AssertEntry(transmogOutfitSlotOption->TransmogOutfitSlotInfoID);
|
||||
|
||||
TransmogOutfitSlotInfo& slotInfo = SlotInfoByOutfitSlot[AsUnderlyingType(transmogOutfitSlot->GetSlot())];
|
||||
if (!std::holds_alternative<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(slotInfo.SlotIndexOrOptions))
|
||||
slotInfo.SlotIndexOrOptions.emplace<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(new TransmogOutfitSlotOptionInfo[AsUnderlyingType(TransmogOutfitSlotOption::Max)]);
|
||||
|
||||
std::get<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(slotInfo.SlotIndexOrOptions)[AsUnderlyingType(transmogOutfitSlotOption->GetOption())].Data = transmogOutfitSlotOption;
|
||||
}
|
||||
|
||||
for (TransmogOutfitSlotInfo& slotInfo : SlotInfoByOutfitSlot)
|
||||
{
|
||||
if (!slotInfo.Data)
|
||||
continue;
|
||||
|
||||
TransmogOutfitSlotAndOptionInfo& slot = AllSlots.emplace_back();
|
||||
slot.Slot = slotInfo.Data;
|
||||
slot.SlotIndex = AllSlots.size() - 1;
|
||||
|
||||
if (std::holds_alternative<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(slotInfo.SlotIndexOrOptions))
|
||||
{
|
||||
// if slot has options, keep adding transmog slots for every option
|
||||
auto options = std::span<TransmogOutfitSlotOptionInfo, AsUnderlyingType(TransmogOutfitSlotOption::Max)>(
|
||||
&std::get<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(slotInfo.SlotIndexOrOptions)[0],
|
||||
AsUnderlyingType(TransmogOutfitSlotOption::Max));
|
||||
|
||||
auto optionItr = std::ranges::find_if(options,
|
||||
[](TransmogOutfitSlotOptionEntry const* option) { return option != nullptr; },
|
||||
&TransmogOutfitSlotOptionInfo::Data);
|
||||
|
||||
slot.SlotOption = optionItr->Data;
|
||||
optionItr->SlotIndex = AllSlots.size() - 1;
|
||||
|
||||
while (++optionItr != options.end())
|
||||
{
|
||||
if (!optionItr->Data)
|
||||
continue;
|
||||
|
||||
TransmogOutfitSlotAndOptionInfo& newSlot = AllSlots.emplace_back();
|
||||
newSlot.Slot = slotInfo.Data;
|
||||
newSlot.SlotOption = optionItr->Data;
|
||||
newSlot.SlotIndex = AllSlots.size() - 1;
|
||||
optionItr->SlotIndex = AllSlots.size() - 1;
|
||||
}
|
||||
}
|
||||
if (std::holds_alternative<int32>(slotInfo.SlotIndexOrOptions))
|
||||
std::get<int32>(slotInfo.SlotIndexOrOptions) = AllSlots.size() - 1;
|
||||
}
|
||||
|
||||
for (TransmogSituationEntry const* transmogSituation : sTransmogSituationStore)
|
||||
if (transmogSituation->HasFlag(TransmogSituationFlags::DefaultsToOn))
|
||||
DefaultSituations.push_back(transmogSituation);
|
||||
}
|
||||
|
||||
ItemModifiedAppearanceEntry const* TransmogMgr::GetItemModifiedAppearance(uint32 itemId, uint32 appearanceModId)
|
||||
{
|
||||
auto itr = ItemModifiedAppearancesByItem.find({ itemId, appearanceModId });
|
||||
if (itr != ItemModifiedAppearancesByItem.end())
|
||||
return itr->second;
|
||||
|
||||
// Fall back to unmodified appearance
|
||||
if (appearanceModId)
|
||||
return GetDefaultItemModifiedAppearance(itemId);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ItemModifiedAppearanceEntry const* TransmogMgr::GetDefaultItemModifiedAppearance(uint32 itemId)
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(ItemModifiedAppearancesByItem, { itemId, 0 });
|
||||
}
|
||||
|
||||
TransmogIllusionEntry const* TransmogMgr::GetTransmogIllusionForSpellItemEnchantment(uint32 spellItemEnchantmentId)
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(TransmogIllusionBySpellItemEnchantment, spellItemEnchantmentId);
|
||||
}
|
||||
|
||||
std::span<TransmogSetEntry const* const> TransmogMgr::GetTransmogSetsForItemModifiedAppearance(uint32 itemModifiedAppearanceId)
|
||||
{
|
||||
std::span<TransmogSetEntry const* const> result;
|
||||
auto itr = TransmogSetsByItemModifiedAppearance.find(itemModifiedAppearanceId);
|
||||
if (itr != TransmogSetsByItemModifiedAppearance.end())
|
||||
result = itr->second;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::span<TransmogSetItemEntry const* const> TransmogMgr::GetTransmogSetItems(uint32 transmogSetId)
|
||||
{
|
||||
return std::ranges::equal_range(TransmogSetItemsByTransmogSet, transmogSetId, {}, &TransmogSetItemEntry::TransmogSetID);
|
||||
}
|
||||
|
||||
std::span<TransmogOutfitEntryEntry const* const> TransmogMgr::GetAutomaticallyUnlockedOutfits()
|
||||
{
|
||||
return TransmogOutfitsAutomaticallyCreated;
|
||||
}
|
||||
|
||||
std::span<TransmogMgr::TransmogOutfitSlotAndOptionInfo const> TransmogMgr::GetAllSlots()
|
||||
{
|
||||
return AllSlots;
|
||||
}
|
||||
|
||||
TransmogMgr::TransmogOutfitSlotAndOptionInfo const* TransmogMgr::GetSlotAndOption(TransmogOutfitSlot slot, TransmogOutfitSlotOption slotOption)
|
||||
{
|
||||
int32 slotIndex = SlotInfoByOutfitSlot[AsUnderlyingType(slot)].GetSlotIndex(slotOption);
|
||||
if (slotIndex >= 0)
|
||||
return &AllSlots[slotIndex];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TransmogMgr::TransmogOutfitSlotAndOptionInfo const* TransmogMgr::GetSlotAndOption(EquipmentSlots inventorySlot, TransmogOutfitSlotOption slotOption)
|
||||
{
|
||||
if (TransmogOutfitSlotInfo const* slotInfo = SlotInfoByInvSlot[inventorySlot])
|
||||
if (int32 slotIndex = slotInfo->GetSlotIndex(slotOption); slotIndex >= 0)
|
||||
return &AllSlots[slotIndex];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::span<TransmogSituationEntry const* const> TransmogMgr::GetDefaultSituations()
|
||||
{
|
||||
return DefaultSituations;
|
||||
}
|
||||
|
||||
TransmogOutfitEntryEntry const* TransmogMgr::GetNextOutfitToUnlock(TransmogOutfitEntrySource source, Player const* player)
|
||||
{
|
||||
if (source >= TransmogOutfitEntrySource::Max)
|
||||
return nullptr;
|
||||
|
||||
TransmogOutfitEntryEntry const* lastOwnedOutfit = nullptr;
|
||||
for (auto const& [id, transmogOutfit] : player->m_activePlayerData->TransmogOutfits)
|
||||
{
|
||||
TransmogOutfitEntryEntry const* transmogOutfitEntry = sTransmogOutfitEntryStore.LookupEntry(transmogOutfit.value.Id);
|
||||
if (!transmogOutfitEntry || transmogOutfitEntry->GetSource() != source)
|
||||
continue;
|
||||
|
||||
if (!lastOwnedOutfit || transmogOutfitEntry->OrderIndex > lastOwnedOutfit->OrderIndex)
|
||||
lastOwnedOutfit = transmogOutfitEntry;
|
||||
}
|
||||
|
||||
if (!lastOwnedOutfit)
|
||||
return TransmogOutfitsBySource[AsUnderlyingType(source)].front();
|
||||
|
||||
auto itr = std::ranges::find(TransmogOutfitsBySource[AsUnderlyingType(source)], lastOwnedOutfit) + 1;
|
||||
if (itr != TransmogOutfitsBySource[AsUnderlyingType(source)].end())
|
||||
return *itr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool TransmogMgr::ValidateSituations(std::span<WorldPackets::Transmogrification::TransmogOutfitSituationInfo const> situations)
|
||||
{
|
||||
struct SituationTriggerStatus
|
||||
{
|
||||
uint8 AllSituationCount = 0;
|
||||
uint8 NoneSituationCount = 0;
|
||||
uint8 RegularSituationCount = 0;
|
||||
};
|
||||
|
||||
std::array<SituationTriggerStatus, AsUnderlyingType(TransmogSituationTrigger::Max)> statusByTrigger;
|
||||
|
||||
for (WorldPackets::Transmogrification::TransmogOutfitSituationInfo const& situation : situations)
|
||||
{
|
||||
TransmogSituationEntry const* transmogSituation = sTransmogSituationStore.LookupEntry(situation.SituationID);
|
||||
if (!transmogSituation)
|
||||
return false;
|
||||
|
||||
TransmogSituationGroupEntry const* transmogSituationGroup = sTransmogSituationGroupStore.LookupEntry(transmogSituation->TransmogSituationGroupID);
|
||||
if (!transmogSituationGroup)
|
||||
return false;
|
||||
|
||||
TransmogSituationTriggerEntry const* transmogSituationTrigger = sTransmogSituationTriggerStore.LookupEntry(transmogSituationGroup->TransmogSituationTriggerID);
|
||||
if (!transmogSituationTrigger)
|
||||
return false;
|
||||
|
||||
SituationTriggerStatus& triggers = statusByTrigger[AsUnderlyingType(transmogSituationTrigger->GetTrigger())];
|
||||
uint8* count = nullptr;
|
||||
if (transmogSituation->HasFlag(TransmogSituationFlags::AllSituation))
|
||||
count = &triggers.AllSituationCount;
|
||||
else if (transmogSituation->HasFlag(TransmogSituationFlags::NoneSituation))
|
||||
count = &triggers.NoneSituationCount;
|
||||
else
|
||||
count = &triggers.RegularSituationCount;
|
||||
|
||||
*count += 1;
|
||||
if (transmogSituationTrigger->HasFlag(TransmogSituationTriggerFlags::SituationsAreExclusive) && *count > 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (SituationTriggerStatus const& triggers : statusByTrigger)
|
||||
if ((triggers.AllSituationCount > 0) + (triggers.NoneSituationCount > 0) + (triggers.RegularSituationCount > 0) > 1) // only 1 group can be active
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransmogMgr::ValidateSlots(std::span<WorldPackets::Transmogrification::TransmogOutfitSlotData const> slots)
|
||||
{
|
||||
for (WorldPackets::Transmogrification::TransmogOutfitSlotData const& slot : slots)
|
||||
{
|
||||
if (slot.Slot >= TransmogOutfitSlot::Max)
|
||||
return false;
|
||||
|
||||
if (slot.SlotOption >= TransmogOutfitSlotOption::Max)
|
||||
return false;
|
||||
|
||||
if (slot.AppearanceDisplayType >= TransmogOutfitDisplayType::Max)
|
||||
return false;
|
||||
|
||||
if (slot.IllusionDisplayType >= TransmogOutfitDisplayType::Max)
|
||||
return false;
|
||||
|
||||
if (!GetSlotAndOption(slot.Slot, slot.SlotOption))
|
||||
return false;
|
||||
|
||||
if (slot.ItemModifiedAppearanceID)
|
||||
{
|
||||
ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(slot.ItemModifiedAppearanceID);
|
||||
if (!itemModifiedAppearance)
|
||||
return false;
|
||||
|
||||
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemModifiedAppearance->ItemID);
|
||||
if (!itemTemplate)
|
||||
return false;
|
||||
|
||||
if (!IsValidTransmogOutfitSlotForItem(itemTemplate, slot.Slot, slot.SlotOption))
|
||||
return false;
|
||||
|
||||
TransmogOutfitSlotOption appearanceSlotOption = itemTemplate->GetWeaponTransmogOutfitSlotOption();
|
||||
if (appearanceSlotOption != slot.SlotOption
|
||||
&& (slot.SlotOption != TransmogOutfitSlotOption::FuryTwoHandedWeapon
|
||||
|| appearanceSlotOption != TransmogOutfitSlotOption::TwoHandedWeapon))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (slot.SpellItemEnchantmentID && !TransmogIllusionBySpellItemEnchantment.contains(slot.SpellItemEnchantmentID))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITYCORE_TRANSMOG_MGR_H
|
||||
#define TRINITYCORE_TRANSMOG_MGR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <span>
|
||||
|
||||
class Player;
|
||||
struct ItemModifiedAppearanceEntry;
|
||||
struct TransmogIllusionEntry;
|
||||
struct TransmogOutfitEntryEntry;
|
||||
struct TransmogOutfitSlotInfoEntry;
|
||||
struct TransmogOutfitSlotOptionEntry;
|
||||
struct TransmogSetEntry;
|
||||
struct TransmogSetItemEntry;
|
||||
struct TransmogSituationEntry;
|
||||
enum EquipmentSlots : uint8;
|
||||
enum class TransmogOutfitEntrySource : uint8;
|
||||
enum class TransmogOutfitSlot : int8;
|
||||
enum class TransmogOutfitSlotOption : uint8;
|
||||
|
||||
namespace WorldPackets::Transmogrification
|
||||
{
|
||||
struct TransmogOutfitSituationInfo;
|
||||
struct TransmogOutfitSlotData;
|
||||
}
|
||||
|
||||
namespace TransmogMgr
|
||||
{
|
||||
struct TransmogOutfitSlotAndOptionInfo
|
||||
{
|
||||
TransmogOutfitSlotInfoEntry const* Slot = nullptr;
|
||||
TransmogOutfitSlotOptionEntry const* SlotOption = nullptr;
|
||||
uint32 SlotIndex = 0;
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, TOTAL_LOCALES> DefaultOutfitName =
|
||||
{
|
||||
"Outfit"sv,
|
||||
"\354\235\230\354\203\201"sv,
|
||||
"Tenue"sv,
|
||||
"Outfit"sv,
|
||||
"\345\244\226\350\247\202\346\226\271\346\241\210"sv,
|
||||
"\346\234\215\350\243\235"sv,
|
||||
"Atuendo"sv,
|
||||
"Indumentaria"sv,
|
||||
"\320\241\320\275\320\260\321\200\321\217\320\266\320\265\320\275\320\270\320\265"sv,
|
||||
""sv,
|
||||
"Roupa"sv,
|
||||
"Completo"sv
|
||||
};
|
||||
|
||||
inline constexpr uint32 DefaultOutfitIcon = 134400;
|
||||
|
||||
void Load();
|
||||
|
||||
ItemModifiedAppearanceEntry const* GetItemModifiedAppearance(uint32 itemId, uint32 appearanceModId);
|
||||
ItemModifiedAppearanceEntry const* GetDefaultItemModifiedAppearance(uint32 itemId);
|
||||
TransmogIllusionEntry const* GetTransmogIllusionForSpellItemEnchantment(uint32 spellItemEnchantmentId);
|
||||
std::span<TransmogSetEntry const* const> GetTransmogSetsForItemModifiedAppearance(uint32 itemModifiedAppearanceId);
|
||||
std::span<TransmogSetItemEntry const* const> GetTransmogSetItems(uint32 transmogSetId);
|
||||
std::span<TransmogOutfitEntryEntry const* const> GetAutomaticallyUnlockedOutfits();
|
||||
std::span<TransmogOutfitSlotAndOptionInfo const> GetAllSlots();
|
||||
TransmogOutfitSlotAndOptionInfo const* GetSlotAndOption(TransmogOutfitSlot slot, TransmogOutfitSlotOption slotOption);
|
||||
TransmogOutfitSlotAndOptionInfo const* GetSlotAndOption(EquipmentSlots inventorySlot, TransmogOutfitSlotOption slotOption);
|
||||
std::span<TransmogSituationEntry const* const> GetDefaultSituations();
|
||||
TransmogOutfitEntryEntry const* GetNextOutfitToUnlock(TransmogOutfitEntrySource source, Player const* player);
|
||||
bool ValidateSituations(std::span<WorldPackets::Transmogrification::TransmogOutfitSituationInfo const> situations);
|
||||
bool ValidateSlots(std::span<WorldPackets::Transmogrification::TransmogOutfitSlotData const> slots);
|
||||
}
|
||||
|
||||
#endif // TRINITYCORE_TRANSMOG_MGR_H
|
||||
@@ -96,6 +96,7 @@
|
||||
#include "TaxiPathGraph.h"
|
||||
#include "TerrainMgr.h"
|
||||
#include "TraitMgr.h"
|
||||
#include "TransmogMgr.h"
|
||||
#include "TransportMgr.h"
|
||||
#include "Unit.h"
|
||||
#include "UpdateTime.h"
|
||||
@@ -2066,6 +2067,9 @@ bool World::SetInitialWorldSettings()
|
||||
TC_LOG_INFO("server.loading", "Loading phase names...");
|
||||
sObjectMgr->LoadPhaseNames();
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading transmog data...");
|
||||
TransmogMgr::Load();
|
||||
|
||||
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
|
||||
|
||||
TC_LOG_INFO("server.worldserver", "World initialized in {} minutes {} seconds", startupDuration / 60000, startupDuration % 60000 / 1000);
|
||||
|
||||
Reference in New Issue
Block a user