diff options
Diffstat (limited to 'src/server/game')
64 files changed, 5775 insertions, 3076 deletions
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index eec3c81fb35..2d542fc4a70 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -98,6 +98,13 @@ bool AchievementMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTre return false; } + if (achievement->CovenantID && referencePlayer->m_playerData->CovenantID != achievement->CovenantID) + { + TC_LOG_TRACE("criteria.achievement", "AchievementMgr::CanUpdateCriteriaTree: (Id: %u Type %s Achievement %u) Wrong covenant", + criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), achievement->ID); + return false; + } + return CriteriaHandler::CanUpdateCriteriaTree(criteria, tree, referencePlayer); } @@ -522,7 +529,7 @@ void PlayerAchievementMgr::CompletedAchievement(AchievementEntry const* achievem //! Since no common attributes were found, (not even in titleRewardFlags field) //! we explicitly check by ID. Maybe in the future we could move the achievement_reward //! condition fields to the condition system. - if (uint32 titleId = reward->TitleId[achievement->ID == 1793 ? _owner->m_playerData->NativeSex : (_owner->GetTeam() == ALLIANCE ? 0 : 1)]) + if (uint32 titleId = reward->TitleId[achievement->ID == 1793 ? _owner->GetNativeSex() : (_owner->GetTeam() == ALLIANCE ? 0 : 1)]) if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId)) _owner->SetTitle(titleEntry); diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp index 38a30a877ce..bce5b6ecb9c 100644 --- a/src/server/game/Achievements/CriteriaHandler.cpp +++ b/src/server/game/Achievements/CriteriaHandler.cpp @@ -523,6 +523,10 @@ void CriteriaHandler::UpdateCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0 case CRITERIA_TYPE_PRESTIGE_REACHED: case CRITERIA_TYPE_APPEARANCE_UNLOCKED_BY_SLOT: case CRITERIA_TYPE_TRANSMOG_SET_UNLOCKED: + case CRITERIA_TYPE_COMPLETE_QUEST_ACCUMULATE: + case CRITERIA_TYPE_BOUGHT_ITEM_FROM_VENDOR: + case CRITERIA_TYPE_SOLD_ITEM_TO_VENDOR: + case CRITERIA_TYPE_TRAVELLED_TO_AREA: SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; // std case: increment at miscValue1 @@ -810,6 +814,9 @@ void CriteriaHandler::UpdateCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0 case CRITERIA_TYPE_EARN_HONOR_XP: case CRITERIA_TYPE_RELIC_TALENT_UNLOCKED: case CRITERIA_TYPE_REACH_ACCOUNT_HONOR_LEVEL: + case CRITERIA_TYPE_MYTHIC_KEYSTONE_COMPLETED: + case CRITERIA_TYPE_APPLY_CONDUIT: + case CRITERIA_TYPE_CONVERT_ITEMS_TO_CURRENCY: break; // Not implemented yet :( } @@ -1175,6 +1182,10 @@ bool CriteriaHandler::IsCompletedCriteria(Criteria const* criteria, uint64 requi case CRITERIA_TYPE_REACH_ACCOUNT_HONOR_LEVEL: case CRITERIA_TYPE_HEART_OF_AZEROTH_ARTIFACT_POWER_EARNED: case CRITERIA_TYPE_HEART_OF_AZEROTH_LEVEL_REACHED: + case CRITERIA_TYPE_COMPLETE_QUEST_ACCUMULATE: + case CRITERIA_TYPE_BOUGHT_ITEM_FROM_VENDOR: + case CRITERIA_TYPE_SOLD_ITEM_TO_VENDOR: + case CRITERIA_TYPE_TRAVELLED_TO_AREA: return progress->Counter >= requiredAmount; case CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: case CRITERIA_TYPE_COMPLETE_QUEST: @@ -1336,6 +1347,9 @@ bool CriteriaHandler::RequirementsSatisfied(Criteria const* criteria, uint64 mis case CRITERIA_TYPE_WIN_DUEL: case CRITERIA_TYPE_WIN_RATED_ARENA: case CRITERIA_TYPE_WON_AUCTIONS: + case CRITERIA_TYPE_COMPLETE_QUEST_ACCUMULATE: + case CRITERIA_TYPE_BOUGHT_ITEM_FROM_VENDOR: + case CRITERIA_TYPE_SOLD_ITEM_TO_VENDOR: if (!miscValue1) return false; break; @@ -1590,6 +1604,9 @@ bool CriteriaHandler::RequirementsSatisfied(Criteria const* criteria, uint64 mis if (!miscValue2 /*login case*/ || miscValue1 != uint32(criteria->Entry->Asset.EquipmentSlot)) return false; break; + case CRITERIA_TYPE_TRAVELLED_TO_AREA: + if (miscValue1 != uint32(criteria->Entry->Asset.AreaID)) + return false; default: break; } @@ -2017,7 +2034,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6 return false; break; case CRITERIA_ADDITIONAL_CONDITION_SOURCE_NATIVE_SEX: // 98 - if (referencePlayer->m_playerData->NativeSex != uint8(reqValue)) + if (referencePlayer->GetNativeSex() != uint8(reqValue)) return false; break; case CRITERIA_ADDITIONAL_CONDITION_SKILL: // 99 @@ -2701,7 +2718,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6 break; } case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_120: // 264 - if (referencePlayer->getLevel() != 120) + if (referencePlayer->getLevel() != 60) return false; break; case CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_LOWER: // 266 @@ -2720,6 +2737,46 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6 if (essence.AzeriteEssenceID == selectedEssences->AzeriteEssenceID[reqValue] && essence.Rank > secondaryAsset) return true; return false; + case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_IN_RANGE_CT: // 268 + { + uint8 level = referencePlayer->getLevel(); + if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0)) + { + if (secondaryAsset) + return level >= levels->MinLevelWithDelta && level <= levels->MaxLevelWithDelta; + return level >= levels->MinLevel && level <= levels->MaxLevel; + } + return false; + } + case CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_IN_RANGE_CT: // 269 + { + if (!unit) + return false; + uint8 level = unit->getLevel(); + if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0)) + { + if (secondaryAsset) + return level >= levels->MinLevelWithDelta && level <= levels->MaxLevelWithDelta; + return level >= levels->MinLevel && level <= levels->MaxLevel; + } + return false; + } + case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_GREATER_CT: // 272 + { + uint8 level = referencePlayer->getLevel(); + if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0)) + return secondaryAsset ? level >= levels->MinLevelWithDelta : level >= levels->MinLevel; + return false; + } + case CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_GREATER_CT: // 273 + { + if (!unit) + return false; + uint8 level = unit->getLevel(); + if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0)) + return secondaryAsset ? level >= levels->MinLevelWithDelta : level >= levels->MinLevel; + return false; + } case CRITERIA_ADDITIONAL_CONDITION_MAP_OR_COSMETIC_MAP: // 280 { MapEntry const* map = referencePlayer->GetMap()->GetEntry(); @@ -2727,6 +2784,60 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6 return false; break; } + case CRITERIA_ADDITIONAL_CONDITION_COVENANT: // 288 + if (referencePlayer->m_playerData->CovenantID != int32(reqValue)) + return false; + break; + case CRITERIA_ADDITIONAL_CONDITION_SOULBIND: // 291 + if (referencePlayer->m_playerData->SoulbindID != int32(reqValue)) + return false; + break; + case CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE_IN_GROUP: // 293 + { + std::vector<uint32> areas = sDB2Manager.GetAreasForGroup(reqValue); + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(referencePlayer->GetAreaId())) + for (uint32 areaInGroup : areas) + if (areaInGroup == area->ID || areaInGroup == area->ParentAreaID) + return true; + return false; + } + case CRITERIA_ADDITIONAL_CONDITION_SOURCE_IN_SPECIFIC_CHROMIE_TIME: // 300 + if (referencePlayer->m_activePlayerData->UiChromieTimeExpansionID != int32(reqValue)) + return false; + break; + case CRITERIA_ADDITIONAL_CONDITION_SOURCE_IN_ANY_CHROMIE_TIME: // 301 + if (referencePlayer->m_activePlayerData->UiChromieTimeExpansionID == 0) + return false; + break; + case CRITERIA_ADDITIONAL_CONDITION_SOURCE_RUNEFORGE_LEGENDARY_KNOWN: // 303 + { + uint32 block = reqValue / 32; + if (block >= referencePlayer->m_activePlayerData->RuneforgePowers.size()) + return false; + + uint32 bit = reqValue % 32; + return referencePlayer->m_activePlayerData->RuneforgePowers[block] & (1 << bit); + } + case CRITERIA_ADDITIONAL_CONDITION_SHAPESHIFT_FORM_CUSTOMIZATION_DISPLAY: // 308 + { + ShapeshiftFormModelData const* formModelData = sDB2Manager.GetShapeshiftFormModelData(referencePlayer->getRace(), referencePlayer->GetNativeSex(), secondaryAsset); + if (!formModelData) + return false; + uint32 formChoice = referencePlayer->GetCustomizationChoice(formModelData->OptionID); + auto choiceItr = std::find_if(formModelData->Choices->begin(), formModelData->Choices->end(), [formChoice](ChrCustomizationChoiceEntry const* choice) + { + return choice->ID == formChoice; + }); + if (choiceItr == formModelData->Choices->end()) + return false; + if (int32(reqValue) != formModelData->Displays[std::distance(formModelData->Choices->begin(), choiceItr)]->DisplayID) + return false; + break; + } + case CRITERIA_ADDITIONAL_CONDITION_SOURCE_FLYING: // 311 + if (!referencePlayer->IsFlying()) + return false; + break; default: break; } @@ -3106,6 +3217,20 @@ char const* CriteriaMgr::GetCriteriaTypeString(CriteriaTypes type) return "HEART_OF_AZEROTH_ARTIFACT_POWER_EARNED"; case CRITERIA_TYPE_HEART_OF_AZEROTH_LEVEL_REACHED: return "HEART_OF_AZEROTH_LEVEL_REACHED"; + case CRITERIA_TYPE_MYTHIC_KEYSTONE_COMPLETED: + return "MYTHIC_KEYSTONE_COMPLETED"; + case CRITERIA_TYPE_COMPLETE_QUEST_ACCUMULATE: + return "COMPLETE_QUEST_ACCUMULATE"; + case CRITERIA_TYPE_BOUGHT_ITEM_FROM_VENDOR: + return "BOUGHT_ITEM_FROM_VENDOR"; + case CRITERIA_TYPE_SOLD_ITEM_TO_VENDOR: + return "SOLD_ITEM_TO_VENDOR"; + case CRITERIA_TYPE_TRAVELLED_TO_AREA: + return "TRAVELLED_TO_AREA"; + case CRITERIA_TYPE_APPLY_CONDUIT: + return "APPLY_CONDUIT"; + case CRITERIA_TYPE_CONVERT_ITEMS_TO_CURRENCY: + return "CONVERT_ITEMS_TO_CURRENCY"; } return "MISSING_TYPE"; } diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 409c9b4a852..fbf3a370ca0 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -1629,7 +1629,7 @@ bool Battleground::AddSpiritGuide(uint32 type, float x, float y, float z, float // creature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL); // casting visual effect creature->SetChannelSpellId(SPELL_SPIRIT_HEAL_CHANNEL); - creature->SetChannelSpellXSpellVisualId(VISUAL_SPIRIT_HEAL_CHANNEL); + creature->SetChannelVisual({ VISUAL_SPIRIT_HEAL_CHANNEL, 0 }); //creature->CastSpell(creature, SPELL_SPIRIT_HEAL_CHANNEL, true); return true; } diff --git a/src/server/game/Cache/CharacterCache.cpp b/src/server/game/Cache/CharacterCache.cpp index 5e297d3f90b..a078c502e40 100644 --- a/src/server/game/Cache/CharacterCache.cpp +++ b/src/server/game/Cache/CharacterCache.cpp @@ -141,6 +141,15 @@ void CharacterCache::UpdateCharacterData(ObjectGuid const& guid, std::string con _characterCacheByNameStore[name] = &itr->second; } +void CharacterCache::UpdateCharacterGender(ObjectGuid const& guid, uint8 gender) +{ + auto itr = _characterCacheStore.find(guid); + if (itr == _characterCacheStore.end()) + return; + + itr->second.Sex = gender; +} + void CharacterCache::UpdateCharacterLevel(ObjectGuid const& guid, uint8 level) { auto itr = _characterCacheStore.find(guid); diff --git a/src/server/game/Cache/CharacterCache.h b/src/server/game/Cache/CharacterCache.h index c76bb04ecb1..a9a872da837 100644 --- a/src/server/game/Cache/CharacterCache.h +++ b/src/server/game/Cache/CharacterCache.h @@ -48,6 +48,7 @@ class TC_GAME_API CharacterCache void DeleteCharacterCacheEntry(ObjectGuid const& guid, std::string const& name); void UpdateCharacterData(ObjectGuid const& guid, std::string const& name, uint8* gender = nullptr, uint8* race = nullptr); + void UpdateCharacterGender(ObjectGuid const& guid, uint8 gender); void UpdateCharacterLevel(ObjectGuid const& guid, uint8 level); void UpdateCharacterAccountId(ObjectGuid const& guid, uint32 accountId); void UpdateCharacterGuildId(ObjectGuid const& guid, ObjectGuid::LowType guildId); diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h index 4c3f074588e..dbeaf49c757 100644 --- a/src/server/game/Chat/Channels/Channel.h +++ b/src/server/game/Chat/Channels/Channel.h @@ -98,17 +98,18 @@ enum ChannelFlags enum ChannelDBCFlags { - CHANNEL_DBC_FLAG_NONE = 0x00000, - CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG - CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment - CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense - CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade, LFG - CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment, LFG - CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment, LFG - CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense - CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment - CHANNEL_DBC_FLAG_LFG = 0x40000, // LFG - CHANNEL_DBC_FLAG_UNK1 = 0x80000 // General + CHANNEL_DBC_FLAG_NONE = 0x00000, + CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG + CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment + CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense + CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade, LFG + CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment, LFG + CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment, LFG + CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense + CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment + CHANNEL_DBC_FLAG_LFG = 0x40000, // LFG + CHANNEL_DBC_FLAG_UNK1 = 0x80000, // General + CHANNEL_DBC_FLAG_NO_CLIENT_JOIN = 0x200000 }; enum ChannelMemberFlags diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 03c75df9348..bc0e8f64742 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -2547,11 +2547,30 @@ uint32 ConditionMgr::GetPlayerConditionLfgValue(Player const* player, PlayerCond bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, PlayerConditionEntry const* condition) { - if (condition->MinLevel && player->getLevel() < condition->MinLevel) - return false; + if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(condition->ContentTuningID, player->m_playerData->CtrOptions->ContentTuningConditionMask)) + { + uint8 minLevel = condition->Flags & 0x800 ? levels->MinLevelWithDelta : levels->MinLevel; + uint8 maxLevel = 0; + if (!(condition->Flags & 0x20)) + maxLevel = condition->Flags & 0x800 ? levels->MaxLevelWithDelta : levels->MaxLevel; - if (condition->MaxLevel && player->getLevel() > condition->MaxLevel) - return false; + if (condition->Flags & 0x80) + { + if (minLevel && player->getLevel() >= minLevel && (!maxLevel || player->getLevel() <= maxLevel)) + return false; + + if (maxLevel && player->getLevel() <= maxLevel && (!minLevel || player->getLevel() >= minLevel)) + return false; + } + else + { + if (minLevel && player->getLevel() < minLevel) + return false; + + if (maxLevel && player->getLevel() > maxLevel) + return false; + } + } if (condition->RaceMask && !condition->RaceMask.HasRace(player->getRace())) return false; @@ -2562,7 +2581,7 @@ bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, PlayerConditio if (condition->Gender >= 0 && player->getGender() != condition->Gender) return false; - if (condition->NativeGender >= 0 && player->m_playerData->NativeSex != condition->NativeGender) + if (condition->NativeGender >= 0 && player->GetNativeSex() != condition->NativeGender) return false; if (condition->PowerType != -1 && condition->PowerTypeComp) @@ -2946,6 +2965,9 @@ bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, PlayerConditio if (condition->ModifierTreeID && !player->ModifierTreeSatisfied(condition->ModifierTreeID)) return false; + if (condition->CovenantID && player->m_playerData->CovenantID != condition->CovenantID) + return false; + return true; } diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h index 9fa79edfdbd..dde5b4fa2ba 100644 --- a/src/server/game/DataStores/DB2LoadInfo.h +++ b/src/server/game/DataStores/DB2LoadInfo.h @@ -46,6 +46,7 @@ struct AchievementLoadInfo { true, FT_INT, "RewardItemID" }, { false, FT_INT, "CriteriaTree" }, { true, FT_SHORT, "SharesCriteria" }, + { true, FT_INT, "CovenantID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, AchievementMeta::Instance(), HOTFIX_SEL_ACHIEVEMENT); return &loadInfo; @@ -119,7 +120,6 @@ struct AreaTableLoadInfo { false, FT_SHORT, "UwAmbience" }, { false, FT_SHORT, "ZoneMusic" }, { false, FT_SHORT, "UwZoneMusic" }, - { true, FT_BYTE, "ExplorationLevel" }, { false, FT_SHORT, "IntroSound" }, { false, FT_INT, "UwIntroSound" }, { false, FT_BYTE, "FactionGroupMask" }, @@ -129,6 +129,7 @@ struct AreaTableLoadInfo { false, FT_BYTE, "WildBattlePetLevelMin" }, { false, FT_BYTE, "WildBattlePetLevelMax" }, { false, FT_BYTE, "WindSettingsID" }, + { true, FT_INT, "ContentTuningID" }, { true, FT_INT, "Flags1" }, { true, FT_INT, "Flags2" }, { false, FT_SHORT, "LiquidTypeID1" }, @@ -688,7 +689,7 @@ struct BattlePetBreedStateLoadInfo static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, - { false, FT_BYTE, "BattlePetStateID" }, + { true, FT_INT, "BattlePetStateID" }, { false, FT_SHORT, "Value" }, { false, FT_INT, "BattlePetBreedID" }, }; @@ -714,6 +715,7 @@ struct BattlePetSpeciesLoadInfo { true, FT_BYTE, "SourceTypeEnum" }, { true, FT_INT, "CardUIModelSceneID" }, { true, FT_INT, "LoadoutUIModelSceneID" }, + { true, FT_INT, "CovenantID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BattlePetSpeciesMeta::Instance(), HOTFIX_SEL_BATTLE_PET_SPECIES); return &loadInfo; @@ -756,9 +758,9 @@ struct BattlemasterListLoadInfo { true, FT_BYTE, "GroupsAllowed" }, { true, FT_BYTE, "MaxGroupSize" }, { true, FT_SHORT, "HolidayWorldState" }, - { true, FT_BYTE, "Flags" }, + { true, FT_INT, "Flags" }, { true, FT_INT, "IconFileDataID" }, - { true, FT_SHORT, "RequiredPlayerConditionID" }, + { true, FT_INT, "RequiredPlayerConditionID" }, { true, FT_SHORT, "MapID1" }, { true, FT_SHORT, "MapID2" }, { true, FT_SHORT, "MapID3" }, @@ -790,7 +792,7 @@ struct BroadcastTextLoadInfo { false, FT_STRING, "Text" }, { false, FT_STRING, "Text1" }, { false, FT_INT, "ID" }, - { false, FT_BYTE, "LanguageID" }, + { true, FT_INT, "LanguageID" }, { true, FT_INT, "ConditionID" }, { false, FT_SHORT, "EmotesID" }, { false, FT_BYTE, "Flags" }, @@ -827,121 +829,50 @@ struct CfgRegionsLoadInfo } }; -struct CharacterFacialHairStylesLoadInfo -{ - static DB2LoadInfo const* Instance() - { - static DB2FieldMeta const fields[] = - { - { false, FT_INT, "ID" }, - { true, FT_INT, "Geoset1" }, - { true, FT_INT, "Geoset2" }, - { true, FT_INT, "Geoset3" }, - { true, FT_INT, "Geoset4" }, - { true, FT_INT, "Geoset5" }, - { false, FT_BYTE, "RaceID" }, - { false, FT_BYTE, "SexID" }, - { false, FT_BYTE, "VariationID" }, - }; - static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharacterFacialHairStylesMeta::Instance(), HOTFIX_SEL_CHARACTER_FACIAL_HAIR_STYLES); - return &loadInfo; - } -}; - -struct CharBaseSectionLoadInfo +struct CharTitlesLoadInfo { static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, - { false, FT_BYTE, "LayoutResType" }, - { false, FT_BYTE, "VariationEnum" }, - { false, FT_BYTE, "ResolutionVariationEnum" }, + { false, FT_STRING, "Name" }, + { false, FT_STRING, "Name1" }, + { true, FT_SHORT, "MaskID" }, + { true, FT_BYTE, "Flags" }, }; - static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharBaseSectionMeta::Instance(), HOTFIX_SEL_CHAR_BASE_SECTION); + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharTitlesMeta::Instance(), HOTFIX_SEL_CHAR_TITLES); return &loadInfo; } }; -struct CharSectionsLoadInfo +struct CharacterLoadoutLoadInfo { static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { + { true, FT_LONG, "RaceMask" }, { false, FT_INT, "ID" }, - { true, FT_BYTE, "RaceID" }, - { true, FT_BYTE, "SexID" }, - { true, FT_BYTE, "BaseSection" }, - { true, FT_BYTE, "VariationIndex" }, - { true, FT_BYTE, "ColorIndex" }, - { true, FT_SHORT, "Flags" }, - { true, FT_INT, "MaterialResourcesID1" }, - { true, FT_INT, "MaterialResourcesID2" }, - { true, FT_INT, "MaterialResourcesID3" }, + { true, FT_BYTE, "ChrClassID" }, + { true, FT_BYTE, "Purpose" }, }; - static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharSectionsMeta::Instance(), HOTFIX_SEL_CHAR_SECTIONS); + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharacterLoadoutMeta::Instance(), HOTFIX_SEL_CHARACTER_LOADOUT); return &loadInfo; } }; -struct CharStartOutfitLoadInfo +struct CharacterLoadoutItemLoadInfo { static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, - { false, FT_BYTE, "ClassID" }, - { false, FT_BYTE, "SexID" }, - { false, FT_BYTE, "OutfitID" }, - { false, FT_INT, "PetDisplayID" }, - { false, FT_BYTE, "PetFamilyID" }, - { true, FT_INT, "ItemID1" }, - { true, FT_INT, "ItemID2" }, - { true, FT_INT, "ItemID3" }, - { true, FT_INT, "ItemID4" }, - { true, FT_INT, "ItemID5" }, - { true, FT_INT, "ItemID6" }, - { true, FT_INT, "ItemID7" }, - { true, FT_INT, "ItemID8" }, - { true, FT_INT, "ItemID9" }, - { true, FT_INT, "ItemID10" }, - { true, FT_INT, "ItemID11" }, - { true, FT_INT, "ItemID12" }, - { true, FT_INT, "ItemID13" }, - { true, FT_INT, "ItemID14" }, - { true, FT_INT, "ItemID15" }, - { true, FT_INT, "ItemID16" }, - { true, FT_INT, "ItemID17" }, - { true, FT_INT, "ItemID18" }, - { true, FT_INT, "ItemID19" }, - { true, FT_INT, "ItemID20" }, - { true, FT_INT, "ItemID21" }, - { true, FT_INT, "ItemID22" }, - { true, FT_INT, "ItemID23" }, - { true, FT_INT, "ItemID24" }, - { false, FT_INT, "RaceID" }, - }; - static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharStartOutfitMeta::Instance(), HOTFIX_SEL_CHAR_START_OUTFIT); - return &loadInfo; - } -}; - -struct CharTitlesLoadInfo -{ - static DB2LoadInfo const* Instance() - { - static DB2FieldMeta const fields[] = - { - { false, FT_INT, "ID" }, - { false, FT_STRING, "Name" }, - { false, FT_STRING, "Name1" }, - { true, FT_SHORT, "MaskID" }, - { true, FT_BYTE, "Flags" }, + { false, FT_SHORT, "CharacterLoadoutID" }, + { false, FT_INT, "ItemID" }, }; - static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharTitlesMeta::Instance(), HOTFIX_SEL_CHAR_TITLES); + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharacterLoadoutItemMeta::Instance(), HOTFIX_SEL_CHARACTER_LOADOUT_ITEM); return &loadInfo; } }; @@ -952,11 +883,12 @@ struct ChatChannelsLoadInfo { static DB2FieldMeta const fields[] = { - { false, FT_INT, "ID" }, { false, FT_STRING, "Name" }, { false, FT_STRING, "Shortcut" }, + { false, FT_INT, "ID" }, { true, FT_INT, "Flags" }, { true, FT_BYTE, "FactionGroup" }, + { true, FT_INT, "Ruleset" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChatChannelsMeta::Instance(), HOTFIX_SEL_CHAT_CHANNELS); return &loadInfo; @@ -974,14 +906,29 @@ struct ChrClassesLoadInfo { false, FT_STRING, "NameMale" }, { false, FT_STRING, "NameFemale" }, { false, FT_STRING_NOT_LOCALIZED, "PetNameToken" }, + { false, FT_STRING, "Description" }, + { false, FT_STRING, "RoleInfoString" }, + { false, FT_STRING, "DisabledString" }, + { false, FT_STRING, "HyphenatedNameMale" }, + { false, FT_STRING, "HyphenatedNameFemale" }, { false, FT_INT, "ID" }, { false, FT_INT, "CreateScreenFileDataID" }, { false, FT_INT, "SelectScreenFileDataID" }, { false, FT_INT, "IconFileDataID" }, { false, FT_INT, "LowResScreenFileDataID" }, - { true, FT_INT, "StartingLevel" }, + { false, FT_INT, "Flags" }, { false, FT_INT, "SpellTextureBlobFileDataID" }, - { false, FT_SHORT, "Flags" }, + { false, FT_INT, "RolesMask" }, + { false, FT_INT, "ArmorTypeMask" }, + { true, FT_INT, "CharStartKitUnknown901" }, + { true, FT_INT, "MaleCharacterCreationVisualFallback" }, + { true, FT_INT, "MaleCharacterCreationIdleVisualFallback" }, + { true, FT_INT, "FemaleCharacterCreationVisualFallback" }, + { true, FT_INT, "FemaleCharacterCreationIdleVisualFallback" }, + { true, FT_INT, "CharacterCreationIdleGroundVisualFallback" }, + { true, FT_INT, "CharacterCreationGroundVisualFallback" }, + { true, FT_INT, "AlteredFormCharacterCreationIdleVisualFallback" }, + { true, FT_INT, "CharacterCreationAnimLoopWaitTimeMsFallback" }, { false, FT_SHORT, "CinematicSequenceID" }, { false, FT_SHORT, "DefaultSpec" }, { false, FT_BYTE, "PrimaryStatPriority" }, @@ -990,6 +937,9 @@ struct ChrClassesLoadInfo { false, FT_BYTE, "AttackPowerPerAgility" }, { false, FT_BYTE, "AttackPowerPerStrength" }, { false, FT_BYTE, "SpellClassSet" }, + { false, FT_BYTE, "ChatColorR" }, + { false, FT_BYTE, "ChatColorG" }, + { false, FT_BYTE, "ChatColorB" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrClassesMeta::Instance(), HOTFIX_SEL_CHR_CLASSES); return &loadInfo; @@ -1011,6 +961,169 @@ struct ChrClassesXPowerTypesLoadInfo } }; +struct ChrCustomizationChoiceLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_STRING, "Name" }, + { false, FT_INT, "ID" }, + { true, FT_INT, "ChrCustomizationOptionID" }, + { true, FT_INT, "ChrCustomizationReqID" }, + { false, FT_SHORT, "SortOrder" }, + { true, FT_INT, "SwatchColor1" }, + { true, FT_INT, "SwatchColor2" }, + { false, FT_SHORT, "UiOrderIndex" }, + { true, FT_INT, "Flags" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrCustomizationChoiceMeta::Instance(), HOTFIX_SEL_CHR_CUSTOMIZATION_CHOICE); + return &loadInfo; + } +}; + +struct ChrCustomizationDisplayInfoLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { true, FT_INT, "ShapeshiftFormID" }, + { true, FT_INT, "DisplayID" }, + { false, FT_FLOAT, "BarberShopMinCameraDistance" }, + { false, FT_FLOAT, "BarberShopHeightOffset" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrCustomizationDisplayInfoMeta::Instance(), HOTFIX_SEL_CHR_CUSTOMIZATION_DISPLAY_INFO); + return &loadInfo; + } +}; + +struct ChrCustomizationElementLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { true, FT_INT, "ChrCustomizationChoiceID" }, + { true, FT_INT, "RelatedChrCustomizationChoiceID" }, + { true, FT_INT, "ChrCustomizationGeosetID" }, + { true, FT_INT, "ChrCustomizationSkinnedModelID" }, + { true, FT_INT, "ChrCustomizationMaterialID" }, + { true, FT_INT, "ChrCustomizationBoneSetID" }, + { true, FT_INT, "ChrCustomizationCondModelID" }, + { true, FT_INT, "ChrCustomizationDisplayInfoID" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrCustomizationElementMeta::Instance(), HOTFIX_SEL_CHR_CUSTOMIZATION_ELEMENT); + return &loadInfo; + } +}; + +struct ChrCustomizationOptionLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_STRING, "Name" }, + { false, FT_INT, "ID" }, + { false, FT_SHORT, "SecondaryID" }, + { true, FT_INT, "Flags" }, + { true, FT_INT, "ChrModelID" }, + { true, FT_INT, "SortIndex" }, + { true, FT_INT, "ChrCustomizationCategoryID" }, + { true, FT_INT, "OptionType" }, + { false, FT_FLOAT, "BarberShopCostModifier" }, + { true, FT_INT, "ChrCustomizationID" }, + { true, FT_INT, "ChrCustomizationReqID" }, + { true, FT_INT, "UiOrderIndex" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrCustomizationOptionMeta::Instance(), HOTFIX_SEL_CHR_CUSTOMIZATION_OPTION); + return &loadInfo; + } +}; + +struct ChrCustomizationReqLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { true, FT_INT, "Flags" }, + { true, FT_INT, "ClassMask" }, + { true, FT_INT, "AchievementID" }, + { true, FT_INT, "OverrideArchive" }, + { true, FT_INT, "ItemModifiedAppearanceID" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrCustomizationReqMeta::Instance(), HOTFIX_SEL_CHR_CUSTOMIZATION_REQ); + return &loadInfo; + } +}; + +struct ChrCustomizationReqChoiceLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { true, FT_INT, "ChrCustomizationChoiceID" }, + { false, FT_INT, "ChrCustomizationReqID" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrCustomizationReqChoiceMeta::Instance(), HOTFIX_SEL_CHR_CUSTOMIZATION_REQ_CHOICE); + return &loadInfo; + } +}; + +struct ChrModelLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_FLOAT, "FaceCustomizationOffset1" }, + { false, FT_FLOAT, "FaceCustomizationOffset2" }, + { false, FT_FLOAT, "FaceCustomizationOffset3" }, + { false, FT_FLOAT, "CustomizeOffset1" }, + { false, FT_FLOAT, "CustomizeOffset2" }, + { false, FT_FLOAT, "CustomizeOffset3" }, + { false, FT_INT, "ID" }, + { true, FT_INT, "Sex" }, + { true, FT_INT, "DisplayID" }, + { true, FT_INT, "CharComponentTextureLayoutID" }, + { true, FT_INT, "Flags" }, + { true, FT_INT, "SkeletonFileDataID" }, + { true, FT_INT, "ModelFallbackChrModelID" }, + { true, FT_INT, "TextureFallbackChrModelID" }, + { true, FT_INT, "HelmVisFallbackChrModelID" }, + { false, FT_FLOAT, "CustomizeScale" }, + { false, FT_FLOAT, "CustomizeFacing" }, + { false, FT_FLOAT, "CameraDistanceOffset" }, + { false, FT_FLOAT, "BarberShopCameraOffsetScale" }, + { false, FT_FLOAT, "BarberShopCameraRotationOffset" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrModelMeta::Instance(), HOTFIX_SEL_CHR_MODEL); + return &loadInfo; + } +}; + +struct ChrRaceXChrModelLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { true, FT_INT, "ChrRacesID" }, + { true, FT_INT, "ChrModelID" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrRaceXChrModelMeta::Instance(), HOTFIX_SEL_CHR_RACE_X_CHR_MODEL); + return &loadInfo; + } +}; + struct ChrRacesLoadInfo { static DB2LoadInfo const* Instance() @@ -1023,20 +1136,22 @@ struct ChrRacesLoadInfo { false, FT_STRING, "NameFemale" }, { false, FT_STRING, "NameLowercase" }, { false, FT_STRING, "NameFemaleLowercase" }, + { false, FT_STRING, "NameS" }, + { false, FT_STRING, "NameFemaleS" }, + { false, FT_STRING, "NameLowercaseS" }, + { false, FT_STRING, "NameFemaleLowercaseS" }, + { false, FT_STRING, "RaceFantasyDescription" }, + { false, FT_STRING, "NameL" }, + { false, FT_STRING, "NameFemaleL" }, + { false, FT_STRING, "NameLowercaseL" }, + { false, FT_STRING, "NameFemaleLowercaseL" }, { false, FT_INT, "ID" }, { true, FT_INT, "Flags" }, - { false, FT_INT, "MaleDisplayId" }, - { false, FT_INT, "FemaleDisplayId" }, - { false, FT_INT, "HighResMaleDisplayId" }, - { false, FT_INT, "HighResFemaleDisplayId" }, + { true, FT_INT, "BaseLanguage" }, + { true, FT_INT, "ResSicknessSpellID" }, + { true, FT_INT, "SplashSoundID" }, { true, FT_INT, "CreateScreenFileDataID" }, { true, FT_INT, "SelectScreenFileDataID" }, - { false, FT_FLOAT, "MaleCustomizeOffset1" }, - { false, FT_FLOAT, "MaleCustomizeOffset2" }, - { false, FT_FLOAT, "MaleCustomizeOffset3" }, - { false, FT_FLOAT, "FemaleCustomizeOffset1" }, - { false, FT_FLOAT, "FemaleCustomizeOffset2" }, - { false, FT_FLOAT, "FemaleCustomizeOffset3" }, { true, FT_INT, "LowResScreenFileDataID" }, { false, FT_INT, "AlteredFormStartVisualKitID1" }, { false, FT_INT, "AlteredFormStartVisualKitID2" }, @@ -1047,21 +1162,19 @@ struct ChrRacesLoadInfo { true, FT_INT, "HeritageArmorAchievementID" }, { true, FT_INT, "StartingLevel" }, { true, FT_INT, "UiDisplayOrder" }, - { true, FT_INT, "FemaleSkeletonFileDataID" }, - { true, FT_INT, "MaleSkeletonFileDataID" }, - { true, FT_INT, "HelmVisFallbackRaceID" }, + { true, FT_INT, "PlayableRaceBit" }, + { true, FT_INT, "HelmetAnimScalingRaceID" }, { true, FT_INT, "TransmogrifyDisabledSlotMask" }, + { false, FT_FLOAT, "AlteredFormCustomizeOffsetFallback1" }, + { false, FT_FLOAT, "AlteredFormCustomizeOffsetFallback2" }, + { false, FT_FLOAT, "AlteredFormCustomizeOffsetFallback3" }, + { false, FT_FLOAT, "AlteredFormCustomizeRotationFallback" }, { true, FT_SHORT, "FactionID" }, { true, FT_SHORT, "CinematicSequenceID" }, - { true, FT_SHORT, "ResSicknessSpellID" }, - { true, FT_SHORT, "SplashSoundID" }, - { true, FT_BYTE, "BaseLanguage" }, { true, FT_BYTE, "CreatureType" }, { true, FT_BYTE, "Alliance" }, { true, FT_BYTE, "RaceRelated" }, { true, FT_BYTE, "UnalteredVisualRaceID" }, - { true, FT_BYTE, "CharComponentTextureLayoutID" }, - { true, FT_BYTE, "CharComponentTexLayoutHiResID" }, { true, FT_BYTE, "DefaultClassID" }, { true, FT_BYTE, "NeutralRaceID" }, { true, FT_BYTE, "MaleModelFallbackRaceID" }, @@ -1072,6 +1185,7 @@ struct ChrRacesLoadInfo { true, FT_BYTE, "MaleTextureFallbackSex" }, { true, FT_BYTE, "FemaleTextureFallbackRaceID" }, { true, FT_BYTE, "FemaleTextureFallbackSex" }, + { true, FT_BYTE, "UnalteredVisualCustomizationRaceID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrRacesMeta::Instance(), HOTFIX_SEL_CHR_RACES); return &loadInfo; @@ -1152,10 +1266,17 @@ struct ContentTuningLoadInfo static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, - { true, FT_INT, "MinLevel" }, - { true, FT_INT, "MaxLevel" }, { true, FT_INT, "Flags" }, { true, FT_INT, "ExpansionID" }, + { true, FT_INT, "MinLevel" }, + { true, FT_INT, "MaxLevel" }, + { true, FT_INT, "MinLevelType" }, + { true, FT_INT, "MaxLevelType" }, + { true, FT_INT, "TargetLevelDelta" }, + { true, FT_INT, "TargetLevelMaxDelta" }, + { true, FT_INT, "TargetLevelMin" }, + { true, FT_INT, "TargetLevelMax" }, + { true, FT_INT, "MinItemLevel" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ContentTuningMeta::Instance(), HOTFIX_SEL_CONTENT_TUNING); return &loadInfo; @@ -1265,17 +1386,9 @@ struct CreatureDisplayInfoExtraLoadInfo { true, FT_BYTE, "DisplayRaceID" }, { true, FT_BYTE, "DisplaySexID" }, { true, FT_BYTE, "DisplayClassID" }, - { true, FT_BYTE, "SkinID" }, - { true, FT_BYTE, "FaceID" }, - { true, FT_BYTE, "HairStyleID" }, - { true, FT_BYTE, "HairColorID" }, - { true, FT_BYTE, "FacialHairID" }, { true, FT_BYTE, "Flags" }, { true, FT_INT, "BakeMaterialResourcesID" }, { true, FT_INT, "HDBakeMaterialResourcesID" }, - { false, FT_BYTE, "CustomDisplayOption1" }, - { false, FT_BYTE, "CustomDisplayOption2" }, - { false, FT_BYTE, "CustomDisplayOption3" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CreatureDisplayInfoExtraMeta::Instance(), HOTFIX_SEL_CREATURE_DISPLAY_INFO_EXTRA); return &loadInfo; @@ -1423,18 +1536,20 @@ struct CurrencyTypesLoadInfo { false, FT_INT, "ID" }, { false, FT_STRING, "Name" }, { false, FT_STRING, "Description" }, - { false, FT_BYTE, "CategoryID" }, + { true, FT_INT, "CategoryID" }, { true, FT_INT, "InventoryIconFileID" }, { false, FT_INT, "SpellWeight" }, { false, FT_BYTE, "SpellCategory" }, { false, FT_INT, "MaxQty" }, { false, FT_INT, "MaxEarnablePerWeek" }, - { false, FT_INT, "Flags" }, { true, FT_BYTE, "Quality" }, { true, FT_INT, "FactionID" }, { true, FT_INT, "ItemGroupSoundsID" }, - { true, FT_INT, "ConvertToPlayerExperience" }, - { true, FT_INT, "PlayerConditionID" }, + { true, FT_INT, "XpQuestDifficulty" }, + { true, FT_INT, "AwardConditionID" }, + { true, FT_INT, "MaxQtyWorldStateID" }, + { true, FT_INT, "Flags1" }, + { true, FT_INT, "Flags2" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CurrencyTypesMeta::Instance(), HOTFIX_SEL_CURRENCY_TYPES); return &loadInfo; @@ -1465,6 +1580,8 @@ struct CurvePointLoadInfo { false, FT_INT, "ID" }, { false, FT_FLOAT, "PosX" }, { false, FT_FLOAT, "PosY" }, + { false, FT_FLOAT, "PosPreSquishX" }, + { false, FT_FLOAT, "PosPreSquishY" }, { false, FT_SHORT, "CurveID" }, { false, FT_BYTE, "OrderIndex" }, }; @@ -1482,20 +1599,20 @@ struct DestructibleModelDataLoadInfo { false, FT_INT, "ID" }, { true, FT_BYTE, "State0ImpactEffectDoodadSet" }, { false, FT_BYTE, "State0AmbientDoodadSet" }, - { false, FT_SHORT, "State1Wmo" }, + { true, FT_INT, "State1Wmo" }, { true, FT_BYTE, "State1DestructionDoodadSet" }, { true, FT_BYTE, "State1ImpactEffectDoodadSet" }, { false, FT_BYTE, "State1AmbientDoodadSet" }, - { false, FT_SHORT, "State2Wmo" }, + { true, FT_INT, "State2Wmo" }, { true, FT_BYTE, "State2DestructionDoodadSet" }, { true, FT_BYTE, "State2ImpactEffectDoodadSet" }, { false, FT_BYTE, "State2AmbientDoodadSet" }, - { false, FT_SHORT, "State3Wmo" }, + { true, FT_INT, "State3Wmo" }, { false, FT_BYTE, "State3InitDoodadSet" }, { false, FT_BYTE, "State3AmbientDoodadSet" }, { false, FT_BYTE, "EjectDirection" }, { false, FT_BYTE, "DoNotHighlight" }, - { false, FT_SHORT, "State0Wmo" }, + { true, FT_INT, "State0Wmo" }, { false, FT_BYTE, "HealEffect" }, { false, FT_SHORT, "HealEffectSpeed" }, { true, FT_BYTE, "State0NameSet" }, @@ -1543,7 +1660,7 @@ struct DungeonEncounterLoadInfo { false, FT_STRING, "Name" }, { false, FT_INT, "ID" }, { true, FT_SHORT, "MapID" }, - { true, FT_BYTE, "DifficultyID" }, + { true, FT_INT, "DifficultyID" }, { true, FT_INT, "OrderIndex" }, { true, FT_INT, "CompleteWorldStateID" }, { true, FT_BYTE, "Bit" }, @@ -1823,13 +1940,13 @@ struct GameobjectsLoadInfo { false, FT_FLOAT, "Rot3" }, { false, FT_FLOAT, "Rot4" }, { false, FT_INT, "ID" }, - { false, FT_SHORT, "OwnerID" }, - { false, FT_SHORT, "DisplayID" }, + { true, FT_INT, "OwnerID" }, + { true, FT_INT, "DisplayID" }, { false, FT_FLOAT, "Scale" }, - { false, FT_BYTE, "TypeID" }, - { false, FT_BYTE, "PhaseUseFlags" }, - { false, FT_SHORT, "PhaseID" }, - { false, FT_SHORT, "PhaseGroupID" }, + { true, FT_INT, "TypeID" }, + { true, FT_INT, "PhaseUseFlags" }, + { true, FT_INT, "PhaseID" }, + { true, FT_INT, "PhaseGroupID" }, { true, FT_INT, "PropValue1" }, { true, FT_INT, "PropValue2" }, { true, FT_INT, "PropValue3" }, @@ -1879,7 +1996,7 @@ struct GarrBuildingLoadInfo { false, FT_BYTE, "BuildingType" }, { true, FT_INT, "HordeGameObjectID" }, { true, FT_INT, "AllianceGameObjectID" }, - { false, FT_BYTE, "GarrSiteID" }, + { true, FT_INT, "GarrSiteID" }, { false, FT_BYTE, "UpgradeLevel" }, { true, FT_INT, "BuildSeconds" }, { false, FT_SHORT, "CurrencyTypeID" }, @@ -1977,6 +2094,8 @@ struct GarrFollowerLoadInfo { false, FT_BYTE, "ChrClassID" }, { false, FT_BYTE, "Flags" }, { false, FT_BYTE, "Gender" }, + { true, FT_INT, "AutoCombatantID" }, + { true, FT_INT, "CovenantID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrFollowerMeta::Instance(), HOTFIX_SEL_GARR_FOLLOWER); return &loadInfo; @@ -2101,7 +2220,6 @@ struct GemPropertiesLoadInfo { false, FT_INT, "ID" }, { false, FT_SHORT, "EnchantId" }, { true, FT_INT, "Type" }, - { false, FT_SHORT, "MinItemLevel" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GemPropertiesMeta::Instance(), HOTFIX_SEL_GEM_PROPERTIES); return &loadInfo; @@ -2388,6 +2506,7 @@ struct ItemLoadInfo { true, FT_BYTE, "SoundOverrideSubclassID" }, { true, FT_INT, "IconFileDataID" }, { false, FT_BYTE, "ItemGroupSoundsID" }, + { true, FT_INT, "ModifiedCraftingReagentItemID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemMeta::Instance(), HOTFIX_SEL_ITEM); return &loadInfo; @@ -2405,6 +2524,7 @@ struct ItemAppearanceLoadInfo { true, FT_INT, "ItemDisplayInfoID" }, { true, FT_INT, "DefaultIconFileDataID" }, { true, FT_INT, "UiOrder" }, + { true, FT_INT, "PlayerConditionID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemAppearanceMeta::Instance(), HOTFIX_SEL_ITEM_APPEARANCE); return &loadInfo; @@ -2494,6 +2614,7 @@ struct ItemBonusLoadInfo { true, FT_INT, "Value1" }, { true, FT_INT, "Value2" }, { true, FT_INT, "Value3" }, + { true, FT_INT, "Value4" }, { false, FT_SHORT, "ParentItemBonusListID" }, { false, FT_BYTE, "Type" }, { false, FT_BYTE, "OrderIndex" }, @@ -3027,6 +3148,9 @@ struct ItemSparseLoadInfo { true, FT_INT, "Flags3" }, { true, FT_INT, "Flags4" }, { true, FT_INT, "FactionRelated" }, + { true, FT_INT, "ModifiedCraftingReagentItemID" }, + { true, FT_INT, "ContentTuningID" }, + { true, FT_INT, "PlayerLevelToItemLevelCurveID" }, { false, FT_SHORT, "ItemNameDescriptionID" }, { false, FT_SHORT, "RequiredTransmogHoliday" }, { false, FT_SHORT, "RequiredHoliday" }, @@ -3042,7 +3166,6 @@ struct ItemSparseLoadInfo { false, FT_SHORT, "StartQuestID" }, { false, FT_SHORT, "PageID" }, { false, FT_SHORT, "ItemDelay" }, - { false, FT_SHORT, "ScalingStatDistributionID" }, { false, FT_SHORT, "MinFactionID" }, { false, FT_SHORT, "RequiredSkillRank" }, { false, FT_SHORT, "RequiredSkill" }, @@ -3187,8 +3310,6 @@ struct LfgDungeonsLoadInfo { false, FT_INT, "ID" }, { false, FT_STRING, "Name" }, { false, FT_STRING, "Description" }, - { false, FT_BYTE, "MinLevel" }, - { false, FT_SHORT, "MaxLevel" }, { false, FT_BYTE, "TypeID" }, { false, FT_BYTE, "Subtype" }, { true, FT_BYTE, "Faction" }, @@ -3202,9 +3323,6 @@ struct LfgDungeonsLoadInfo { false, FT_BYTE, "GroupID" }, { false, FT_BYTE, "OrderIndex" }, { false, FT_INT, "RequiredPlayerConditionId" }, - { false, FT_BYTE, "TargetLevel" }, - { false, FT_BYTE, "TargetLevelMin" }, - { false, FT_SHORT, "TargetLevelMax" }, { false, FT_SHORT, "RandomID" }, { false, FT_SHORT, "ScenarioID" }, { false, FT_SHORT, "FinalEncounterID" }, @@ -3217,6 +3335,7 @@ struct LfgDungeonsLoadInfo { false, FT_SHORT, "BonusReputationAmount" }, { false, FT_SHORT, "MentorItemLevel" }, { false, FT_BYTE, "MentorCharLevel" }, + { true, FT_INT, "ContentTuningID" }, { true, FT_INT, "Flags1" }, { true, FT_INT, "Flags2" }, }; @@ -3327,6 +3446,7 @@ struct LockLoadInfo static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, + { true, FT_INT, "Flags" }, { true, FT_INT, "Index1" }, { true, FT_INT, "Index2" }, { true, FT_INT, "Index3" }, @@ -3388,6 +3508,7 @@ struct MapLoadInfo { false, FT_INT, "ID" }, { false, FT_STRING_NOT_LOCALIZED, "Directory" }, { false, FT_STRING, "MapName" }, + { false, FT_STRING_NOT_LOCALIZED, "InternalName" }, { false, FT_STRING, "MapDescription0" }, { false, FT_STRING, "MapDescription1" }, { false, FT_STRING, "PvpShortDescription" }, @@ -3694,11 +3815,9 @@ struct PlayerConditionLoadInfo { true, FT_LONG, "RaceMask" }, { false, FT_STRING, "FailureDescription" }, { false, FT_INT, "ID" }, - { false, FT_SHORT, "MinLevel" }, - { false, FT_SHORT, "MaxLevel" }, { true, FT_INT, "ClassMask" }, { false, FT_INT, "SkillLogic" }, - { false, FT_BYTE, "LanguageID" }, + { true, FT_INT, "LanguageID" }, { false, FT_BYTE, "MinLanguage" }, { true, FT_INT, "MaxLanguage" }, { false, FT_SHORT, "MaxFactionID" }, @@ -3714,7 +3833,7 @@ struct PlayerConditionLoadInfo { false, FT_BYTE, "ItemFlags" }, { false, FT_INT, "AuraSpellLogic" }, { false, FT_SHORT, "WorldStateExpressionID" }, - { false, FT_BYTE, "WeatherID" }, + { true, FT_INT, "WeatherID" }, { false, FT_BYTE, "PartyStatus" }, { false, FT_BYTE, "LifetimeMaxPVPRank" }, { false, FT_INT, "AchievementLogic" }, @@ -3723,7 +3842,7 @@ struct PlayerConditionLoadInfo { false, FT_INT, "AreaLogic" }, { false, FT_INT, "LfgLogic" }, { false, FT_INT, "CurrencyLogic" }, - { false, FT_SHORT, "QuestKillID" }, + { true, FT_INT, "QuestKillID" }, { false, FT_INT, "QuestKillLogic" }, { true, FT_BYTE, "MinExpansionLevel" }, { true, FT_BYTE, "MaxExpansionLevel" }, @@ -3734,7 +3853,7 @@ struct PlayerConditionLoadInfo { false, FT_BYTE, "PhaseUseFlags" }, { false, FT_SHORT, "PhaseID" }, { false, FT_INT, "PhaseGroupID" }, - { false, FT_BYTE, "Flags" }, + { true, FT_INT, "Flags" }, { true, FT_BYTE, "ChrSpecializationIndex" }, { true, FT_BYTE, "ChrSpecializationRole" }, { false, FT_INT, "ModifierTreeID" }, @@ -3748,6 +3867,8 @@ struct PlayerConditionLoadInfo { true, FT_BYTE, "MinExpansionTier" }, { false, FT_BYTE, "MinPVPRank" }, { false, FT_BYTE, "MaxPVPRank" }, + { true, FT_INT, "ContentTuningID" }, + { true, FT_INT, "CovenantID" }, { false, FT_SHORT, "SkillID1" }, { false, FT_SHORT, "SkillID2" }, { false, FT_SHORT, "SkillID3" }, @@ -3766,18 +3887,18 @@ struct PlayerConditionLoadInfo { false, FT_BYTE, "MinReputation1" }, { false, FT_BYTE, "MinReputation2" }, { false, FT_BYTE, "MinReputation3" }, - { false, FT_SHORT, "PrevQuestID1" }, - { false, FT_SHORT, "PrevQuestID2" }, - { false, FT_SHORT, "PrevQuestID3" }, - { false, FT_SHORT, "PrevQuestID4" }, - { false, FT_SHORT, "CurrQuestID1" }, - { false, FT_SHORT, "CurrQuestID2" }, - { false, FT_SHORT, "CurrQuestID3" }, - { false, FT_SHORT, "CurrQuestID4" }, - { false, FT_SHORT, "CurrentCompletedQuestID1" }, - { false, FT_SHORT, "CurrentCompletedQuestID2" }, - { false, FT_SHORT, "CurrentCompletedQuestID3" }, - { false, FT_SHORT, "CurrentCompletedQuestID4" }, + { true, FT_INT, "PrevQuestID1" }, + { true, FT_INT, "PrevQuestID2" }, + { true, FT_INT, "PrevQuestID3" }, + { true, FT_INT, "PrevQuestID4" }, + { true, FT_INT, "CurrQuestID1" }, + { true, FT_INT, "CurrQuestID2" }, + { true, FT_INT, "CurrQuestID3" }, + { true, FT_INT, "CurrQuestID4" }, + { true, FT_INT, "CurrentCompletedQuestID1" }, + { true, FT_INT, "CurrentCompletedQuestID2" }, + { true, FT_INT, "CurrentCompletedQuestID3" }, + { true, FT_INT, "CurrentCompletedQuestID4" }, { true, FT_INT, "SpellID1" }, { true, FT_INT, "SpellID2" }, { true, FT_INT, "SpellID3" }, @@ -4185,22 +4306,6 @@ struct RewardPackXItemLoadInfo } }; -struct ScalingStatDistributionLoadInfo -{ - static DB2LoadInfo const* Instance() - { - static DB2FieldMeta const fields[] = - { - { false, FT_INT, "ID" }, - { false, FT_SHORT, "PlayerLevelToItemLevelCurveID" }, - { true, FT_INT, "MinLevel" }, - { true, FT_INT, "MaxLevel" }, - }; - static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ScalingStatDistributionMeta::Instance(), HOTFIX_SEL_SCALING_STAT_DISTRIBUTION); - return &loadInfo; - } -}; - struct ScenarioLoadInfo { static DB2LoadInfo const* Instance() @@ -4230,7 +4335,7 @@ struct ScenarioStepLoadInfo { false, FT_STRING, "Title" }, { false, FT_SHORT, "ScenarioID" }, { false, FT_INT, "Criteriatreeid" }, - { false, FT_SHORT, "RewardQuestID" }, + { true, FT_INT, "RewardQuestID" }, { true, FT_INT, "RelatedStep" }, { false, FT_SHORT, "Supersedes" }, { false, FT_BYTE, "OrderIndex" }, @@ -4343,7 +4448,7 @@ struct SkillLineAbilityLoadInfo { true, FT_BYTE, "AcquireMethod" }, { true, FT_SHORT, "TrivialSkillLineRankHigh" }, { true, FT_SHORT, "TrivialSkillLineRankLow" }, - { true, FT_BYTE, "Flags" }, + { true, FT_INT, "Flags" }, { true, FT_BYTE, "NumSkillUps" }, { true, FT_SHORT, "UniqueBit" }, { true, FT_SHORT, "TradeSkillCategoryID" }, @@ -4488,7 +4593,6 @@ struct SpellCastTimesLoadInfo { { false, FT_INT, "ID" }, { true, FT_INT, "Base" }, - { true, FT_SHORT, "PerLevel" }, { true, FT_INT, "Minimum" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellCastTimesMeta::Instance(), HOTFIX_SEL_SPELL_CAST_TIMES); @@ -4603,7 +4707,6 @@ struct SpellDurationLoadInfo { { false, FT_INT, "ID" }, { true, FT_INT, "Duration" }, - { false, FT_INT, "DurationPerLevel" }, { true, FT_INT, "MaxDuration" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellDurationMeta::Instance(), HOTFIX_SEL_SPELL_DURATION); @@ -4621,7 +4724,7 @@ struct SpellEffectLoadInfo { true, FT_SHORT, "EffectAura" }, { true, FT_INT, "DifficultyID" }, { true, FT_INT, "EffectIndex" }, - { false, FT_INT, "Effect" }, + { true, FT_INT, "Effect" }, { false, FT_FLOAT, "EffectAmplitude" }, { true, FT_INT, "EffectAttributes" }, { true, FT_INT, "EffectAuraPeriod" }, @@ -4715,18 +4818,20 @@ struct SpellItemEnchantmentLoadInfo { static DB2FieldMeta const fields[] = { - { false, FT_INT, "ID" }, { false, FT_STRING, "Name" }, { false, FT_STRING, "HordeName" }, + { false, FT_INT, "ID" }, { false, FT_INT, "EffectArg1" }, { false, FT_INT, "EffectArg2" }, { false, FT_INT, "EffectArg3" }, { false, FT_FLOAT, "EffectScalingPoints1" }, { false, FT_FLOAT, "EffectScalingPoints2" }, { false, FT_FLOAT, "EffectScalingPoints3" }, - { false, FT_INT, "TransmogPlayerConditionID" }, - { false, FT_INT, "TransmogCost" }, { false, FT_INT, "IconFileDataID" }, + { true, FT_INT, "MinItemLevel" }, + { true, FT_INT, "MaxItemLevel" }, + { false, FT_INT, "TransmogUseConditionID" }, + { false, FT_INT, "TransmogCost" }, { true, FT_SHORT, "EffectPointsMin1" }, { true, FT_SHORT, "EffectPointsMin2" }, { true, FT_SHORT, "EffectPointsMin3" }, @@ -4817,10 +4922,10 @@ struct SpellLevelsLoadInfo { { false, FT_INT, "ID" }, { false, FT_BYTE, "DifficultyID" }, - { true, FT_SHORT, "BaseLevel" }, { true, FT_SHORT, "MaxLevel" }, - { true, FT_SHORT, "SpellLevel" }, { false, FT_BYTE, "MaxPassiveAuraLevel" }, + { true, FT_INT, "BaseLevel" }, + { true, FT_INT, "SpellLevel" }, { false, FT_INT, "SpellID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellLevelsMeta::Instance(), HOTFIX_SEL_SPELL_LEVELS); @@ -4849,6 +4954,7 @@ struct SpellMiscLoadInfo { true, FT_INT, "Attributes12" }, { true, FT_INT, "Attributes13" }, { true, FT_INT, "Attributes14" }, + { true, FT_INT, "Attributes15" }, { false, FT_BYTE, "DifficultyID" }, { false, FT_SHORT, "CastingTimeIndex" }, { false, FT_SHORT, "DurationIndex" }, @@ -4860,6 +4966,9 @@ struct SpellMiscLoadInfo { true, FT_INT, "SpellIconFileDataID" }, { true, FT_INT, "ActiveIconFileDataID" }, { true, FT_INT, "ContentTuningID" }, + { true, FT_INT, "ShowFutureSpellPlayerConditionID" }, + { true, FT_INT, "SpellVisualScript" }, + { true, FT_INT, "ActiveSpellVisualScript" }, { false, FT_INT, "SpellID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellMiscMeta::Instance(), HOTFIX_SEL_SPELL_MISC); @@ -4945,7 +5054,7 @@ struct SpellProcsPerMinuteModLoadInfo { { false, FT_INT, "ID" }, { false, FT_BYTE, "Type" }, - { true, FT_SHORT, "Param" }, + { true, FT_INT, "Param" }, { false, FT_FLOAT, "Coeff" }, { false, FT_INT, "SpellProcsPerMinuteID" }, }; @@ -5159,7 +5268,6 @@ struct SpellXSpellVisualLoadInfo { false, FT_BYTE, "DifficultyID" }, { false, FT_INT, "SpellVisualID" }, { false, FT_FLOAT, "Probability" }, - { false, FT_BYTE, "Flags" }, { false, FT_BYTE, "Priority" }, { true, FT_INT, "SpellIconFileID" }, { true, FT_INT, "ActiveIconFileID" }, @@ -5362,6 +5470,23 @@ struct TransmogHolidayLoadInfo } }; +struct TransmogIllusionLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { true, FT_INT, "UnlockConditionID" }, + { true, FT_INT, "TransmogCost" }, + { true, FT_INT, "SpellItemEnchantmentID" }, + { true, FT_INT, "Flags" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TransmogIllusionMeta::Instance(), HOTFIX_SEL_TRANSMOG_ILLUSION); + return &loadInfo; + } +}; + struct TransmogSetLoadInfo { static DB2LoadInfo const* Instance() @@ -5467,14 +5592,13 @@ struct UiMapLoadInfo { true, FT_INT, "Flags" }, { true, FT_INT, "System" }, { true, FT_INT, "Type" }, - { false, FT_INT, "LevelRangeMin" }, - { false, FT_INT, "LevelRangeMax" }, { true, FT_INT, "BountySetID" }, { false, FT_INT, "BountyDisplayLocation" }, { true, FT_INT, "VisibilityPlayerConditionID" }, { true, FT_BYTE, "HelpTextPosition" }, { true, FT_INT, "BkgAtlasID" }, { true, FT_INT, "AlternateUiMapGroup" }, + { true, FT_INT, "ContentTuningID" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, UiMapMeta::Instance(), HOTFIX_SEL_UI_MAP); return &loadInfo; @@ -5526,6 +5650,7 @@ struct UiMapLinkLoadInfo { true, FT_INT, "ChildUiMapID" }, { true, FT_INT, "OverrideHighlightFileDataID" }, { true, FT_INT, "OverrideHighlightAtlasID" }, + { true, FT_INT, "Flags" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, UiMapLinkMeta::Instance(), HOTFIX_SEL_UI_MAP_LINK); return &loadInfo; @@ -5607,9 +5732,9 @@ struct VehicleLoadInfo { false, FT_FLOAT, "FacingLimitRight" }, { false, FT_FLOAT, "FacingLimitLeft" }, { false, FT_FLOAT, "CameraYawOffset" }, - { false, FT_BYTE, "UiLocomotionType" }, { false, FT_SHORT, "VehicleUIIndicatorID" }, { true, FT_INT, "MissileTargetingID" }, + { false, FT_SHORT, "VehiclePOITypeID" }, { false, FT_SHORT, "SeatID1" }, { false, FT_SHORT, "SeatID2" }, { false, FT_SHORT, "SeatID3" }, diff --git a/src/server/game/DataStores/DB2Metadata.h b/src/server/game/DataStores/DB2Metadata.h index 44e0b72e792..555784e56d0 100644 --- a/src/server/game/DataStores/DB2Metadata.h +++ b/src/server/game/DataStores/DB2Metadata.h @@ -24,7 +24,7 @@ struct AchievementMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[16] = + static DB2MetaField const fields[17] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, @@ -42,8 +42,9 @@ struct AchievementMeta { FT_INT, 1, true }, { FT_INT, 1, false }, { FT_SHORT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1260179, 3, 16, 16, 0xB0CDA956, fields, 11); + static DB2Meta instance(1260179, 3, 17, 17, 0x03687ABD, fields, 11); return &instance; } }; @@ -81,7 +82,7 @@ struct AdventureJournalMeta { FT_BYTE, 1, false }, { FT_INT, 1, true }, { FT_SHORT, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, @@ -93,7 +94,7 @@ struct AdventureJournalMeta { FT_INT, 2, false }, { FT_BYTE, 2, false }, }; - static DB2Meta instance(1115949, -1, 22, 22, 0x76736DC1, fields, -1); + static DB2Meta instance(1115949, -1, 22, 22, 0x8591A17C, fields, -1); return &instance; } }; @@ -126,35 +127,19 @@ struct AlliedRaceMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[8] = + static DB2MetaField const fields[9] = { { FT_INT, 1, false }, { FT_INT, 1, true }, - { FT_INT, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, - }; - static DB2Meta instance(1710672, 0, 8, 8, 0xBA13C058, fields, -1); - return &instance; - } -}; - -struct AlliedRaceRacialAbilityMeta -{ - static DB2Meta const* Instance() - { - static DB2MetaField const fields[5] = - { - { FT_STRING, 1, true }, - { FT_STRING, 1, true }, { FT_INT, 1, true }, - { FT_BYTE, 1, false }, { FT_INT, 1, true }, }; - static DB2Meta instance(1720145, -1, 5, 4, 0x5FF19738, fields, 4); + static DB2Meta instance(1710672, 0, 9, 9, 0xCAF97110, fields, -1); return &instance; } }; @@ -178,14 +163,15 @@ struct AnimKitBoneSetMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[5] = { { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_INT, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, - { FT_BYTE, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1375433, -1, 4, 4, 0xE620E362, fields, -1); + static DB2Meta instance(1375433, -1, 5, 5, 0x48CA2284, fields, -1); return &instance; } }; @@ -266,7 +252,7 @@ struct AnimKitSegmentMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[18] = + static DB2MetaField const fields[19] = { { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, @@ -286,8 +272,9 @@ struct AnimKitSegmentMeta { FT_BYTE, 1, true }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, + { FT_FLOAT, 1, true }, }; - static DB2Meta instance(1304324, -1, 18, 18, 0x827B9DD7, fields, 0); + static DB2Meta instance(1304324, -1, 19, 19, 0x3099BD1B, fields, 0); return &instance; } }; @@ -322,6 +309,115 @@ struct AnimReplacementSetMeta } }; +struct AnimaCableMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[35] = + { + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + }; + static DB2Meta instance(3286805, -1, 35, 35, 0xBA340158, fields, -1); + return &instance; + } +}; + +struct AnimaCylinderMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[7] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3286804, -1, 7, 7, 0x033E8736, fields, -1); + return &instance; + } +}; + +struct AnimaMaterialMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[31] = + { + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 3, true }, + }; + static DB2Meta instance(3153990, -1, 31, 31, 0x23D776A4, fields, -1); + return &instance; + } +}; + struct AnimationDataMeta { static DB2Meta const* Instance() @@ -449,7 +545,6 @@ struct AreaTableMeta { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, - { FT_BYTE, 1, true }, { FT_SHORT, 1, false }, { FT_INT, 1, false }, { FT_BYTE, 1, false }, @@ -459,10 +554,11 @@ struct AreaTableMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_INT, 2, true }, { FT_SHORT, 4, false }, }; - static DB2Meta instance(1353545, -1, 23, 23, 0x9944A57F, fields, -1); + static DB2Meta instance(1353545, -1, 23, 23, 0x7EF13BBB, fields, -1); return &instance; } }; @@ -500,9 +596,9 @@ struct AreaTriggerActionSetMeta { static DB2MetaField const fields[1] = { - { FT_SHORT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1352378, -1, 1, 1, 0x7E8012C8, fields, -1); + static DB2Meta instance(1352378, -1, 1, 1, 0xD7673266, fields, -1); return &instance; } }; @@ -562,6 +658,21 @@ struct AreaTriggerSphereMeta } }; +struct ArenaCcItemMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3849793, 0, 3, 2, 0x8611CEBF, fields, 2); + return &instance; + } +}; + struct ArmorLocationMeta { static DB2Meta const* Instance() @@ -957,9 +1068,9 @@ struct AzeriteTierUnlockMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, + { FT_INT, 1, false }, }; - static DB2Meta instance(1846043, -1, 4, 3, 0xD2BEFD49, fields, 3); + static DB2Meta instance(1846043, -1, 4, 3, 0x365B7BC1, fields, 3); return &instance; } }; @@ -1157,11 +1268,11 @@ struct BattlePetBreedStateMeta { static DB2MetaField const fields[3] = { - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(801579, -1, 3, 2, 0x5140A97C, fields, 2); + static DB2Meta instance(801579, -1, 3, 2, 0xBEA26E1B, fields, 2); return &instance; } }; @@ -1214,7 +1325,7 @@ struct BattlePetSpeciesMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[11] = + static DB2MetaField const fields[12] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, @@ -1227,8 +1338,9 @@ struct BattlePetSpeciesMeta { FT_BYTE, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(841622, 2, 11, 11, 0xD48B948B, fields, -1); + static DB2Meta instance(841622, 2, 12, 12, 0x33F39540, fields, -1); return &instance; } }; @@ -1264,6 +1376,20 @@ struct BattlePetSpeciesXAbilityMeta } }; +struct BattlePetSpeciesXCovenantMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_SHORT, 1, false }, + { FT_SHORT, 1, false }, + }; + static DB2Meta instance(3669304, -1, 2, 1, 0xABBC028A, fields, 1); + return &instance; + } +}; + struct BattlePetStateMeta { static DB2Meta const* Instance() @@ -1317,12 +1443,12 @@ struct BattlemasterListMeta { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_SHORT, 1, true }, - { FT_BYTE, 1, true }, { FT_INT, 1, true }, - { FT_SHORT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_SHORT, 16, true }, }; - static DB2Meta instance(1360265, -1, 17, 17, 0x191968B6, fields, -1); + static DB2Meta instance(1360265, -1, 17, 17, 0xBA348260, fields, -1); return &instance; } }; @@ -1397,15 +1523,16 @@ struct BountyMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[5] = + static DB2MetaField const fields[6] = { - { FT_SHORT, 1, false }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(1367866, -1, 5, 4, 0x29E1E7AD, fields, 4); + static DB2Meta instance(1367866, 0, 6, 5, 0x66D9FE53, fields, 5); return &instance; } }; @@ -1417,9 +1544,9 @@ struct BountySetMeta static DB2MetaField const fields[2] = { { FT_INT, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1367865, -1, 2, 2, 0x2C4F72C9, fields, -1); + static DB2Meta instance(1367865, -1, 2, 2, 0xB86A8476, fields, -1); return &instance; } }; @@ -1433,7 +1560,7 @@ struct BroadcastTextMeta { FT_STRING, 1, true }, { FT_STRING, 1, true }, { FT_INT, 1, false }, - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, @@ -1442,7 +1569,7 @@ struct BroadcastTextMeta { FT_SHORT, 3, false }, { FT_SHORT, 3, false }, }; - static DB2Meta instance(841604, 2, 11, 11, 0x1EDED3E1, fields, -1); + static DB2Meta instance(841604, 2, 11, 11, 0x762EC396, fields, -1); return &instance; } }; @@ -1530,18 +1657,22 @@ struct CampaignMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[8] = + static DB2MetaField const fields[12] = { { FT_STRING, 1, true }, { FT_STRING_NOT_LOCALIZED, 1, true }, { FT_STRING, 1, true }, { FT_INT, 1, false }, - { FT_INT, 1, false }, - { FT_INT, 1, false }, - { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 1, false }, }; - static DB2Meta instance(2031607, 3, 8, 8, 0x9794A9C1, fields, -1); + static DB2Meta instance(2031607, 3, 12, 12, 0xA6065A95, fields, -1); return &instance; } }; @@ -1550,14 +1681,15 @@ struct CampaignXConditionMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[5] = { + { FT_STRING, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(2031611, -1, 4, 3, 0x530A9A14, fields, 3); + static DB2Meta instance(2031611, -1, 5, 4, 0xC7C42FAD, fields, 4); return &instance; } }; @@ -1736,15 +1868,15 @@ struct CharComponentTextureSectionsMeta { static DB2MetaField const fields[7] = { - { FT_BYTE, 1, true }, - { FT_BYTE, 1, true }, - { FT_SHORT, 1, true }, - { FT_SHORT, 1, true }, - { FT_SHORT, 1, true }, - { FT_SHORT, 1, true }, - { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1360263, -1, 7, 7, 0x7C4B248E, fields, -1); + static DB2Meta instance(1360263, -1, 7, 7, 0xB6E9C94F, fields, 0); return &instance; } }; @@ -1845,7 +1977,7 @@ struct CharShipmentContainerMeta { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_BYTE, 1, false }, @@ -1853,26 +1985,33 @@ struct CharShipmentContainerMeta { FT_BYTE, 1, true }, { FT_SHORT, 1, false }, }; - static DB2Meta instance(972405, -1, 16, 16, 0x9692590F, fields, -1); + static DB2Meta instance(972405, -1, 16, 16, 0x2278DB5A, fields, -1); return &instance; } }; -struct CharStartOutfitMeta +struct CharStartKitMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[7] = + static DB2MetaField const fields[14] = { + { FT_STRING, 1, true }, + { FT_FLOAT, 3, true }, { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, - { FT_INT, 1, false }, - { FT_BYTE, 1, false }, - { FT_INT, 24, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(1237591, -1, 7, 6, 0x3B34251C, fields, 6); + static DB2Meta instance(3055696, -1, 14, 13, 0xF22C193E, fields, 13); return &instance; } }; @@ -1893,23 +2032,6 @@ struct CharTitlesMeta } }; -struct CharacterFaceBoneSetMeta -{ - static DB2Meta const* Instance() - { - static DB2MetaField const fields[5] = - { - { FT_BYTE, 1, false }, - { FT_INT, 1, true }, - { FT_BYTE, 1, false }, - { FT_INT, 1, true }, - { FT_BYTE, 1, false }, - }; - static DB2Meta instance(1028733, -1, 5, 4, 0x7A686AEA, fields, 4); - return &instance; - } -}; - struct CharacterFacialHairStylesMeta { static DB2Meta const* Instance() @@ -1930,13 +2052,14 @@ struct CharacterLoadoutMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[4] = { { FT_LONG, 1, true }, + { FT_INT, 1, false }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, }; - static DB2Meta instance(1344281, -1, 3, 3, 0xCB8F0F1A, fields, -1); + static DB2Meta instance(1344281, 1, 4, 4, 0x7BA6DD4F, fields, -1); return &instance; } }; @@ -1955,6 +2078,22 @@ struct CharacterLoadoutItemMeta } }; +struct CharacterLoadoutPetMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3724843, -1, 4, 3, 0x10D43187, fields, 3); + return &instance; + } +}; + struct CharacterServiceInfoMeta { static DB2Meta const* Instance() @@ -1982,14 +2121,16 @@ struct ChatChannelsMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[6] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, + { FT_INT, 1, false }, { FT_INT, 1, true }, { FT_BYTE, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1345278, -1, 4, 4, 0x66E15E36, fields, -1); + static DB2Meta instance(1345278, 2, 6, 6, 0x331D8CF2, fields, -1); return &instance; } }; @@ -2041,6 +2182,22 @@ struct ChrClassTitleMeta } }; +struct ChrClassUIChrModelInfoMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_FLOAT, 3, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + }; + static DB2Meta instance(3754770, -1, 4, 4, 0xEC04FE04, fields, -1); + return &instance; + } +}; + struct ChrClassUIDisplayMeta { static DB2Meta const* Instance() @@ -2075,23 +2232,41 @@ struct ChrClassesMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[21] = + static DB2MetaField const fields[39] = { { FT_STRING, 1, true }, { FT_STRING_NOT_LOCALIZED, 1, true }, { FT_STRING, 1, true }, { FT_STRING, 1, true }, { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, - { FT_INT, 1, true }, { FT_INT, 1, false }, + { FT_INT, 1, false }, + { FT_INT, 1, false }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, - { FT_SHORT, 1, false }, + { FT_BYTE, 1, false }, + { FT_BYTE, 1, false }, + { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, @@ -2099,7 +2274,7 @@ struct ChrClassesMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(1361031, 5, 21, 21, 0xB036848B, fields, -1); + static DB2Meta instance(1361031, 10, 39, 39, 0x7EF5ADB3, fields, -1); return &instance; } }; @@ -2118,13 +2293,65 @@ struct ChrClassesXPowerTypesMeta } }; -struct ChrCustomizationMeta +struct ChrCreateClassAnimTargetMeta { static DB2Meta const* Instance() { static DB2MetaField const fields[7] = { + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3671168, -1, 7, 6, 0xBA3B39ED, fields, 6); + return &instance; + } +}; + +struct ChrCreateClassAnimTargetInfoMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3671169, 0, 4, 3, 0x5D06AB00, fields, 3); + return &instance; + } +}; + +struct ChrCustClientChoiceConversionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3590348, 0, 4, 3, 0x531DD388, fields, 3); + return &instance; + } +}; + +struct ChrCustomizationMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[8] = + { { FT_STRING, 1, true }, + { FT_INT, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, @@ -2132,33 +2359,381 @@ struct ChrCustomizationMeta { FT_INT, 3, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(1611874, -1, 7, 6, 0x25807B05, fields, 6); + static DB2Meta instance(1611874, 1, 8, 7, 0xCE94DFDA, fields, 7); return &instance; } }; -struct ChrRacesMeta +struct ChrCustomizationBoneSetMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[47] = + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3460181, -1, 2, 2, 0x46FB30D0, fields, -1); + return &instance; + } +}; + +struct ChrCustomizationCategoryMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[9] = { - { FT_STRING_NOT_LOCALIZED, 1, true }, - { FT_STRING_NOT_LOCALIZED, 1, true }, - { FT_STRING, 1, true }, - { FT_STRING, 1, true }, { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + }; + static DB2Meta instance(3526439, 1, 9, 9, 0x69C90AAA, fields, -1); + return &instance; + } +}; + +struct ChrCustomizationChoiceMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[9] = + { { FT_STRING, 1, true }, { FT_INT, 1, false }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_SHORT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_SHORT, 1, false }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3450554, 1, 9, 9, 0x5E646924, fields, 2); + return &instance; + } +}; + +struct ChrCustomizationCondModelMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 3, true }, + }; + static DB2Meta instance(3460182, -1, 2, 2, 0x5B4D36CD, fields, -1); + return &instance; + } +}; + +struct ChrCustomizationConversionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[7] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3463337, -1, 7, 7, 0x1D1B187B, fields, 4); + return &instance; + } +}; + +struct ChrCustomizationDisplayInfoMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[5] = + { { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + }; + static DB2Meta instance(3593032, 0, 5, 5, 0xE662481C, fields, -1); + return &instance; + } +}; + +struct ChrCustomizationElementMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[9] = + { { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3512765, 0, 9, 9, 0x29E7E6E9, fields, -1); + return &instance; + } +}; + +struct ChrCustomizationGeosetMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3456171, -1, 3, 3, 0xF1B919BA, fields, -1); + return &instance; + } +}; + +struct ChrCustomizationMaterialMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3459652, 0, 3, 3, 0x25D08F0C, fields, -1); + return &instance; + } +}; + +struct ChrCustomizationOptionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[12] = + { + { FT_STRING, 1, true }, { FT_INT, 1, false }, + { FT_SHORT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3384247, 1, 12, 12, 0xEB7143AC, fields, 4); + return &instance; + } +}; + +struct ChrCustomizationReqMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[6] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3450453, 0, 6, 6, 0xEA6C595F, fields, -1); + return &instance; + } +}; + +struct ChrCustomizationReqChoiceMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3580359, -1, 2, 1, 0x263E53D8, fields, 1); + return &instance; + } +}; + +struct ChrCustomizationSkinnedModelMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + }; + static DB2Meta instance(3460183, -1, 4, 4, 0x0A19C75E, fields, -1); + return &instance; + } +}; + +struct ChrModelMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[16] = + { { FT_FLOAT, 3, true }, { FT_FLOAT, 3, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + }; + static DB2Meta instance(3384313, 2, 16, 16, 0xE62BB49C, fields, -1); + return &instance; + } +}; + +struct ChrModelMaterialMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[7] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3566562, 0, 7, 7, 0x09B4418C, fields, 1); + return &instance; + } +}; + +struct ChrModelTextureLayerMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[9] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 3, true }, + { FT_INT, 2, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3548976, 0, 9, 8, 0xB6E31714, fields, 8); + return &instance; + } +}; + +struct ChrModelTextureTargetMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[1] = + { + { FT_INT, 1, false }, + }; + static DB2Meta instance(3536417, 0, 1, 1, 0x28EBA06A, fields, -1); + return &instance; + } +}; + +struct ChrRaceRacialAbilityMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[6] = + { + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3507821, -1, 6, 5, 0xC07F1EE4, fields, 5); + return &instance; + } +}; + +struct ChrRaceXChrModelMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3490304, -1, 2, 2, 0x888FDCA8, fields, 0); + return &instance; + } +}; + +struct ChrRacesMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[50] = + { + { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 3, false }, { FT_INT, 3, false }, @@ -2168,9 +2743,8 @@ struct ChrRacesMeta { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_SHORT, 1, true }, - { FT_SHORT, 1, true }, + { FT_FLOAT, 3, true }, + { FT_FLOAT, 1, true }, { FT_SHORT, 1, true }, { FT_SHORT, 1, true }, { FT_BYTE, 1, true }, @@ -2188,10 +2762,8 @@ struct ChrRacesMeta { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, - { FT_BYTE, 1, true }, - { FT_BYTE, 1, true }, }; - static DB2Meta instance(1305311, 6, 47, 47, 0xC1BC2966, fields, -1); + static DB2Meta instance(1305311, 15, 50, 50, 0x85A50CA9, fields, -1); return &instance; } }; @@ -2462,6 +3034,22 @@ struct ComponentTextureFileDataMeta } }; +struct ConditionalContentTuningMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3501965, -1, 4, 3, 0x209DE3DD, fields, 3); + return &instance; + } +}; + struct ConfigurationWarningMeta { static DB2Meta const* Instance() @@ -2480,15 +3068,22 @@ struct ContentTuningMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[5] = + static DB2MetaField const fields[12] = { { FT_INT, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1962930, 0, 5, 5, 0x3C5246D1, fields, -1); + static DB2Meta instance(1962930, 0, 12, 12, 0x7802E330, fields, -1); return &instance; } }; @@ -2595,6 +3190,26 @@ struct CorruptionEffectsMeta } }; +struct CovenantMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[8] = + { + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3384973, 2, 8, 8, 0x551DD981, fields, -1); + return &instance; + } +}; + struct CreatureMeta { static DB2Meta const* Instance() @@ -2622,17 +3237,19 @@ struct CreatureDifficultyMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[7] = + static DB2MetaField const fields[9] = { { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_INT, 1, true }, - { FT_INT, 7, true }, + { FT_INT, 8, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(879282, -1, 7, 6, 0xA7D21F05, fields, 6); + static DB2Meta instance(879282, -1, 9, 8, 0x592C0350, fields, 8); return &instance; } }; @@ -2692,25 +3309,32 @@ struct CreatureDisplayInfoCondMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[15] = + static DB2MetaField const fields[8] = { { FT_LONG, 1, true }, + { FT_INT, 1, false }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_INT, 1, false }, - { FT_INT, 1, false }, - { FT_INT, 1, false }, - { FT_INT, 1, false }, - { FT_INT, 1, false }, - { FT_INT, 1, false }, { FT_INT, 1, true }, - { FT_INT, 2, true }, - { FT_INT, 2, true }, - { FT_INT, 2, true }, { FT_INT, 3, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(1332686, -1, 15, 14, 0x89765207, fields, 14); + static DB2Meta instance(1332686, 1, 8, 7, 0x0AA29755, fields, 7); + return &instance; + } +}; + +struct CreatureDisplayInfoCondXChoiceMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3670439, -1, 2, 2, 0xE8CD17F9, fields, 0); return &instance; } }; @@ -2735,22 +3359,17 @@ struct CreatureDisplayInfoExtraMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[12] = + static DB2MetaField const fields[7] = { - { FT_BYTE, 1, true }, - { FT_BYTE, 1, true }, - { FT_BYTE, 1, true }, - { FT_BYTE, 1, true }, - { FT_BYTE, 1, true }, + { FT_INT, 1, false }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, - { FT_BYTE, 3, false }, }; - static DB2Meta instance(1264997, -1, 12, 12, 0xC4CF4823, fields, -1); + static DB2Meta instance(1264997, 0, 7, 7, 0x1BE6635C, fields, -1); return &instance; } }; @@ -2770,6 +3389,21 @@ struct CreatureDisplayInfoGeosetDataMeta } }; +struct CreatureDisplayInfoOptionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3692043, -1, 3, 2, 0x2155E881, fields, 2); + return &instance; + } +}; + struct CreatureDisplayInfoTrnMeta { static DB2Meta const* Instance() @@ -2981,6 +3615,21 @@ struct CreatureXDisplayInfoMeta } }; +struct CreatureXUiWidgetSetMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3055738, -1, 3, 3, 0xCB7DB164, fields, -1); + return &instance; + } +}; + struct CriteriaMeta { static DB2Meta const* Instance() @@ -3076,24 +3725,25 @@ struct CurrencyTypesMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[14] = + static DB2MetaField const fields[15] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, false }, { FT_BYTE, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, - { FT_INT, 1, false }, { FT_BYTE, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 2, true }, }; - static DB2Meta instance(1095531, -1, 14, 14, 0x16E369D6, fields, -1); + static DB2Meta instance(1095531, -1, 15, 15, 0x33B2E0C5, fields, -1); return &instance; } }; @@ -3116,13 +3766,14 @@ struct CurvePointMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[4] = { { FT_FLOAT, 2, true }, + { FT_FLOAT, 2, true }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(892586, -1, 3, 3, 0x2C43C039, fields, -1); + static DB2Meta instance(892586, -1, 4, 4, 0x2E31C506, fields, -1); return &instance; } }; @@ -3147,7 +3798,7 @@ struct DecalPropertiesMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[18] = + static DB2MetaField const fields[22] = { { FT_INT, 1, false }, { FT_INT, 1, true }, @@ -3167,8 +3818,12 @@ struct DecalPropertiesMeta { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 4, true }, + { FT_FLOAT, 4, true }, }; - static DB2Meta instance(1278176, 0, 18, 18, 0x43F203C0, fields, -1); + static DB2Meta instance(1278176, 0, 22, 22, 0xF090CC1E, fields, -1); return &instance; } }; @@ -3210,20 +3865,20 @@ struct DestructibleModelDataMeta { { FT_BYTE, 1, true }, { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, false }, { FT_SHORT, 1, false }, { FT_BYTE, 1, true }, @@ -3231,7 +3886,7 @@ struct DestructibleModelDataMeta { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, }; - static DB2Meta instance(1122116, -1, 22, 22, 0x1E0D0E51, fields, -1); + static DB2Meta instance(1122116, -1, 22, 22, 0xFFFAFB89, fields, -1); return &instance; } }; @@ -3344,7 +3999,7 @@ struct DungeonEncounterMeta { FT_STRING, 1, true }, { FT_INT, 1, false }, { FT_SHORT, 1, true }, - { FT_BYTE, 1, true }, + { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_BYTE, 1, true }, @@ -3353,7 +4008,7 @@ struct DungeonEncounterMeta { FT_INT, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(1347279, 1, 11, 11, 0xFED52D20, fields, 2); + static DB2Meta instance(1347279, 1, 11, 11, 0x5BFA4FD8, fields, 2); return &instance; } }; @@ -3483,10 +4138,10 @@ struct EnvironmentalDamageMeta { static DB2MetaField const fields[2] = { - { FT_BYTE, 1, false }, + { FT_BYTE, 1, true }, { FT_SHORT, 1, false }, }; - static DB2Meta instance(1278398, -1, 2, 2, 0x7E47BDEE, fields, -1); + static DB2Meta instance(1278398, -1, 2, 2, 0x792416B2, fields, -1); return &instance; } }; @@ -3555,6 +4210,25 @@ struct ExpectedStatModMeta } }; +struct ExtraAbilityInfoMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[7] = + { + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3527889, 1, 7, 7, 0x1DEAB5A7, fields, 2); + return &instance; + } +}; + struct FactionMeta { static DB2Meta const* Instance() @@ -3793,6 +4467,22 @@ struct GameClockDebugMeta } }; +struct GameObjectAnimGroupMemberMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, false }, + }; + static DB2Meta instance(3565753, -1, 4, 4, 0xC165C488, fields, 0); + return &instance; + } +}; + struct GameObjectArtKitMeta { static DB2Meta const* Instance() @@ -3815,10 +4505,10 @@ struct GameObjectDiffAnimMapMeta { { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(1302847, -1, 4, 3, 0xBE81E7C9, fields, 3); + static DB2Meta instance(1302847, -1, 4, 3, 0xDB388EFA, fields, 3); return &instance; } }; @@ -3865,16 +4555,33 @@ struct GameObjectsMeta { FT_FLOAT, 3, true }, { FT_FLOAT, 4, true }, { FT_INT, 1, false }, - { FT_SHORT, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_FLOAT, 1, true }, - { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 8, true }, }; - static DB2Meta instance(841620, 3, 12, 12, 0x9DBD8029, fields, 4); + static DB2Meta instance(841620, 3, 12, 12, 0x816F3855, fields, 4); + return &instance; + } +}; + +struct GameParameterMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[5] = + { + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3405438, -1, 5, 5, 0xC81AA519, fields, -1); return &instance; } }; @@ -3883,14 +4590,15 @@ struct GameTipsMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[5] = { { FT_STRING, 1, true }, { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1368021, -1, 4, 4, 0xAC5C7C88, fields, -1); + static DB2Meta instance(1368021, -1, 5, 5, 0xF24F7ABD, fields, -1); return &instance; } }; @@ -3952,6 +4660,68 @@ struct GarrAbilityEffectMeta } }; +struct GarrAutoCombatantMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[10] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3305399, 0, 10, 10, 0xBC77BB9B, fields, -1); + return &instance; + } +}; + +struct GarrAutoSpellMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[8] = + { + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3305400, 2, 8, 8, 0xDFD06B4A, fields, -1); + return &instance; + } +}; + +struct GarrAutoSpellEffectMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[8] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_BYTE, 1, false }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3307335, 0, 8, 8, 0x8A09C203, fields, 1); + return &instance; + } +}; + struct GarrBuildingMeta { static DB2Meta const* Instance() @@ -3966,7 +4736,7 @@ struct GarrBuildingMeta { FT_BYTE, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, true }, - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, false }, { FT_INT, 1, true }, { FT_SHORT, 1, false }, @@ -3983,7 +4753,7 @@ struct GarrBuildingMeta { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(929747, -1, 24, 24, 0x36C47766, fields, -1); + static DB2Meta instance(929747, -1, 24, 24, 0x69CFEA8D, fields, -1); return &instance; } }; @@ -4064,7 +4834,7 @@ struct GarrEncounterMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[8] = + static DB2MetaField const fields[9] = { { FT_STRING, 1, true }, { FT_INT, 1, false }, @@ -4074,8 +4844,9 @@ struct GarrEncounterMeta { FT_FLOAT, 1, true }, { FT_FLOAT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(975304, 1, 8, 8, 0x878A0152, fields, -1); + static DB2Meta instance(975304, 1, 9, 9, 0x785239C5, fields, -1); return &instance; } }; @@ -4101,11 +4872,11 @@ struct GarrEncounterXMechanicMeta { static DB2MetaField const fields[3] = { - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, false }, { FT_SHORT, 1, false }, }; - static DB2Meta instance(967961, -1, 3, 2, 0x8ACECE98, fields, 2); + static DB2Meta instance(967961, -1, 3, 2, 0x7E4E18F9, fields, 2); return &instance; } }; @@ -4146,7 +4917,7 @@ struct GarrFollowerMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[32] = + static DB2MetaField const fields[34] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, @@ -4180,8 +4951,10 @@ struct GarrFollowerMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(949906, 3, 32, 32, 0x1651FD00, fields, -1); + static DB2Meta instance(949906, 3, 34, 34, 0x712646FC, fields, -1); return &instance; } }; @@ -4327,10 +5100,10 @@ struct GarrMechanicSetXMechanicMeta static DB2MetaField const fields[3] = { { FT_INT, 1, false }, - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_INT, 1, false }, }; - static DB2Meta instance(1391531, 0, 3, 2, 0xD8ABDEEA, fields, 2); + static DB2Meta instance(1391531, 0, 3, 2, 0x146817DD, fields, 2); return &instance; } }; @@ -4356,7 +5129,7 @@ struct GarrMissionMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[29] = + static DB2MetaField const fields[32] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, @@ -4373,8 +5146,9 @@ struct GarrMissionMeta { FT_BYTE, 1, false }, { FT_SHORT, 1, false }, { FT_INT, 1, false }, - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_INT, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, true }, { FT_SHORT, 1, false }, { FT_INT, 1, true }, @@ -4386,9 +5160,29 @@ struct GarrMissionMeta { FT_BYTE, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(967962, 5, 32, 32, 0x09B91DB9, fields, 17); + return &instance; + } +}; + +struct GarrMissionSetMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[6] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(967962, 5, 29, 28, 0x379617D1, fields, 28); + static DB2Meta instance(3055759, -1, 6, 6, 0x62B4E01D, fields, -1); return &instance; } }; @@ -4426,15 +5220,16 @@ struct GarrMissionXEncounterMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[5] = + static DB2MetaField const fields[6] = { { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_BYTE, 1, false }, + { FT_BYTE, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(967960, 0, 5, 4, 0xFFEB2050, fields, 4); + static DB2Meta instance(967960, 0, 6, 5, 0x2926B50E, fields, 5); return &instance; } }; @@ -4443,13 +5238,14 @@ struct GarrMissionXFollowerMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[4] = { { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_BYTE, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(1359096, -1, 3, 2, 0x653A593A, fields, 2); + static DB2Meta instance(1359096, -1, 4, 3, 0x2B1293BC, fields, 3); return &instance; } }; @@ -4620,7 +5416,7 @@ struct GarrTalentMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[13] = + static DB2MetaField const fields[15] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, @@ -4635,8 +5431,45 @@ struct GarrTalentMeta { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1361032, 2, 13, 13, 0x9A9E08BC, fields, 3); + static DB2Meta instance(1361032, 2, 15, 15, 0xE4B665DF, fields, 3); + return &instance; + } +}; + +struct GarrTalentCostMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[9] = + { + { FT_LONG, 1, false }, + { FT_INT, 1, false }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3514438, 1, 9, 9, 0xA5152E26, fields, 2); + return &instance; + } +}; + +struct GarrTalentMapPOIMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_FLOAT, 2, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3534056, -1, 2, 2, 0x11363DB5, fields, -1); return &instance; } }; @@ -4685,11 +5518,25 @@ struct GarrTalentResearchMeta } }; +struct GarrTalentSocketPropertiesMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3612617, -1, 2, 2, 0x6EBDB6D1, fields, -1); + return &instance; + } +}; + struct GarrTalentTreeMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[9] = + static DB2MetaField const fields[12] = { { FT_STRING, 1, true }, { FT_INT, 1, false }, @@ -4700,8 +5547,11 @@ struct GarrTalentTreeMeta { FT_BYTE, 1, true }, { FT_SHORT, 1, false }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1361030, 1, 9, 9, 0x8DF3F074, fields, -1); + static DB2Meta instance(1361030, 1, 12, 12, 0xA9265795, fields, -1); return &instance; } }; @@ -4710,15 +5560,18 @@ struct GarrTypeMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[5] = + static DB2MetaField const fields[8] = { { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, { FT_INT, 2, true }, }; - static DB2Meta instance(1333161, -1, 5, 5, 0x5CBB1F5F, fields, -1); + static DB2Meta instance(1333161, -1, 8, 8, 0x2D0BF086, fields, -1); return &instance; } }; @@ -4770,13 +5623,40 @@ struct GemPropertiesMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[2] = { { FT_SHORT, 1, false }, { FT_INT, 1, true }, - { FT_SHORT, 1, false }, }; - static DB2Meta instance(1343604, -1, 3, 3, 0xE674AE42, fields, -1); + static DB2Meta instance(1343604, -1, 2, 2, 0x62229700, fields, -1); + return &instance; + } +}; + +struct GlobalCurveMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3752002, -1, 2, 2, 0x6EE9627F, fields, -1); + return &instance; + } +}; + +struct GlobalGameContentTuningMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3756368, -1, 2, 2, 0x2594D1ED, fields, -1); return &instance; } }; @@ -4796,6 +5676,20 @@ struct GlobalStringsMeta } }; +struct GlobalTable_PlayerConditionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3476011, -1, 2, 2, 0x331A6B6C, fields, -1); + return &instance; + } +}; + struct GlyphBindableSpellMeta { static DB2Meta const* Instance() @@ -4853,6 +5747,21 @@ struct GlyphRequiredSpecMeta } }; +struct GossipXUIDisplayInfoMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3622253, 0, 3, 3, 0xC9A649B0, fields, -1); + return &instance; + } +}; + struct GradientEffectMeta { static DB2Meta const* Instance() @@ -4885,14 +5794,19 @@ struct GroundEffectDoodadMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[9] = { { FT_INT, 1, true }, { FT_BYTE, 1, false }, { FT_FLOAT, 1, true }, { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1308057, -1, 4, 4, 0x7AC0B592, fields, -1); + static DB2Meta instance(1308057, -1, 9, 9, 0x549FA0D3, fields, -1); return &instance; } }; @@ -4901,14 +5815,15 @@ struct GroundEffectTextureMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[5] = { { FT_INT, 1, false }, { FT_BYTE, 1, false }, { FT_SHORT, 4, false }, { FT_BYTE, 4, true }, + { FT_BYTE, 4, true }, }; - static DB2Meta instance(1308499, -1, 4, 4, 0x50B304D6, fields, -1); + static DB2Meta instance(1308499, -1, 5, 5, 0x32807C98, fields, -1); return &instance; } }; @@ -4924,17 +5839,17 @@ struct GroupFinderActivityMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, true }, { FT_SHORT, 1, false }, - { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, { FT_INT, 1, false }, { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, + { FT_INT, 1, true }, }; - static DB2Meta instance(974813, -1, 14, 14, 0xB0090189, fields, -1); + static DB2Meta instance(974813, -1, 14, 14, 0xD3114D3D, fields, -1); return &instance; } }; @@ -5163,13 +6078,14 @@ struct HelmetGeosetDataMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[4] = { { FT_INT, 1, true }, { FT_BYTE, 1, true }, + { FT_BYTE, 1, false }, { FT_INT, 1, true }, }; - static DB2Meta instance(2821752, -1, 3, 2, 0x4C7DCA12, fields, 2); + static DB2Meta instance(2821752, -1, 4, 3, 0x7667436E, fields, 3); return &instance; } }; @@ -5338,7 +6254,7 @@ struct ItemMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[8] = + static DB2MetaField const fields[9] = { { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, @@ -5348,8 +6264,9 @@ struct ItemMeta { FT_BYTE, 1, true }, { FT_INT, 1, true }, { FT_BYTE, 1, false }, + { FT_INT, 1, true }, }; - static DB2Meta instance(841626, -1, 8, 8, 0x4517779D, fields, -1); + static DB2Meta instance(841626, -1, 9, 9, 0x5432FBBA, fields, -1); return &instance; } }; @@ -5358,14 +6275,15 @@ struct ItemAppearanceMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[5] = { { FT_BYTE, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(982462, -1, 4, 4, 0x83D2C1C9, fields, -1); + static DB2Meta instance(982462, -1, 5, 5, 0x02129C17, fields, -1); return &instance; } }; @@ -5447,12 +6365,12 @@ struct ItemBonusMeta { static DB2MetaField const fields[4] = { - { FT_INT, 3, true }, + { FT_INT, 4, true }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(959070, -1, 4, 4, 0xE119360C, fields, 1); + static DB2Meta instance(959070, -1, 4, 4, 0x84110DA5, fields, 1); return &instance; } }; @@ -5470,19 +6388,33 @@ struct ItemBonusListMeta } }; +struct ItemBonusListGroupMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[1] = + { + { FT_INT, 1, true }, + }; + static DB2Meta instance(3755382, -1, 1, 1, 0x25BF4C79, fields, -1); + return &instance; + } +}; + struct ItemBonusListGroupEntryMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[5] = + static DB2MetaField const fields[6] = { { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(3025306, -1, 5, 4, 0xCA17B2FF, fields, 4); + static DB2Meta instance(3025306, -1, 6, 6, 0x9FB5C578, fields, 0); return &instance; } }; @@ -5529,6 +6461,20 @@ struct ItemBonusSequenceSpellMeta } }; +struct ItemBonusTreeMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3055768, -1, 2, 2, 0xF295C11C, fields, -1); + return &instance; + } +}; + struct ItemBonusTreeNodeMeta { static DB2Meta const* Instance() @@ -5608,6 +6554,22 @@ struct ItemCurrencyCostMeta } }; +struct ItemCurrencyValueMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 4, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3755770, 0, 4, 3, 0xD411AFA8, fields, 3); + return &instance; + } +}; + struct ItemDamageAmmoMeta { static DB2Meta const* Instance() @@ -5714,12 +6676,12 @@ struct ItemDisplayInfoMeta { FT_INT, 1, true }, { FT_INT, 2, false }, { FT_INT, 2, true }, - { FT_BYTE, 2, false }, + { FT_INT, 2, true }, { FT_INT, 6, true }, { FT_INT, 6, true }, { FT_INT, 2, true }, }; - static DB2Meta instance(1266429, -1, 15, 15, 0x404901C8, fields, -1); + static DB2Meta instance(1266429, -1, 15, 15, 0xB923D577, fields, -1); return &instance; } }; @@ -5947,6 +6909,21 @@ struct ItemNameDescriptionMeta } }; +struct ItemNameSlotOverrideMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3723474, -1, 3, 2, 0x3333801A, fields, 2); + return &instance; + } +}; + struct ItemPetFoodMeta { static DB2Meta const* Instance() @@ -6012,7 +6989,7 @@ struct ItemSearchNameMeta { FT_SHORT, 1, false }, { FT_INT, 4, true }, }; - static DB2Meta instance(1273408, 2, 14, 14, 0x9C53DE68, fields, -1); + static DB2Meta instance(1273408, 2, 14, 14, 0xA5ED136F, fields, -1); return &instance; } }; @@ -6054,7 +7031,7 @@ struct ItemSparseMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[62] = + static DB2MetaField const fields[64] = { { FT_LONG, 1, true }, { FT_STRING, 1, true }, @@ -6079,6 +7056,9 @@ struct ItemSparseMeta { FT_FLOAT, 1, true }, { FT_INT, 4, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, @@ -6097,7 +7077,6 @@ struct ItemSparseMeta { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, - { FT_SHORT, 1, false }, { FT_SHORT, 1, true }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, @@ -6119,7 +7098,7 @@ struct ItemSparseMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(1572924, -1, 62, 62, 0xAC420B53, fields, -1); + static DB2Meta instance(1572924, -1, 64, 64, 0x12CC2F52, fields, -1); return &instance; } }; @@ -6160,10 +7139,11 @@ struct ItemSubClassMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[10] = + static DB2MetaField const fields[11] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, + { FT_INT, 1, false }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, false }, @@ -6173,7 +7153,7 @@ struct ItemSubClassMeta { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, }; - static DB2Meta instance(1261604, -1, 10, 10, 0x2B018A83, fields, 2); + static DB2Meta instance(1261604, 2, 11, 11, 0x2EDFDAA6, fields, 3); return &instance; } }; @@ -6238,6 +7218,20 @@ struct ItemXBonusTreeMeta } }; +struct ItemXItemEffectMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3177687, -1, 2, 1, 0x5D602214, fields, 1); + return &instance; + } +}; + struct JournalEncounterMeta { static DB2Meta const* Instance() @@ -6412,11 +7406,12 @@ struct JournalTierMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[1] = + static DB2MetaField const fields[2] = { { FT_STRING, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1349056, -1, 1, 1, 0x2ABC8A8B, fields, -1); + static DB2Meta instance(1349056, -1, 2, 2, 0xBD0C2DC1, fields, -1); return &instance; } }; @@ -6464,25 +7459,6 @@ struct KeystoneAffixMeta } }; -struct LFGDungeonExpansionMeta -{ - static DB2Meta const* Instance() - { - static DB2MetaField const fields[7] = - { - { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, - { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_SHORT, 1, false }, - }; - static DB2Meta instance(1343606, -1, 7, 6, 0x074C83A4, fields, 6); - return &instance; - } -}; - struct LFGDungeonGroupMeta { static DB2Meta const* Instance() @@ -6503,13 +7479,11 @@ struct LFGDungeonsMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[33] = + static DB2MetaField const fields[29] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, - { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, true }, { FT_INT, 1, true }, @@ -6522,9 +7496,6 @@ struct LFGDungeonsMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_INT, 1, false }, - { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, @@ -6537,9 +7508,10 @@ struct LFGDungeonsMeta { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_INT, 2, true }, }; - static DB2Meta instance(1361033, -1, 33, 33, 0x4D903335, fields, -1); + static DB2Meta instance(1361033, -1, 29, 29, 0x0BAF7AF1, fields, -1); return &instance; } }; @@ -6623,7 +7595,7 @@ struct LightDataMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[37] = + static DB2MetaField const fields[40] = { { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, @@ -6653,6 +7625,8 @@ struct LightDataMeta { FT_FLOAT, 1, true }, { FT_FLOAT, 1, true }, { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, true }, @@ -6662,8 +7636,9 @@ struct LightDataMeta { FT_FLOAT, 1, true }, { FT_INT, 1, false }, { FT_FLOAT, 4, true }, + { FT_FLOAT, 4, true }, }; - static DB2Meta instance(1375580, -1, 37, 37, 0x07423F4E, fields, 0); + static DB2Meta instance(1375580, -1, 40, 40, 0x14259798, fields, 0); return &instance; } }; @@ -6921,14 +7896,15 @@ struct LockMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[5] = { + { FT_INT, 1, true }, { FT_INT, 8, true }, { FT_SHORT, 8, false }, { FT_BYTE, 8, false }, { FT_BYTE, 8, false }, }; - static DB2Meta instance(1343608, -1, 4, 4, 0x2BD710C7, fields, -1); + static DB2Meta instance(1343608, -1, 5, 5, 0x2EDD6B10, fields, -1); return &instance; } }; @@ -6937,15 +7913,16 @@ struct LockTypeMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[5] = + static DB2MetaField const fields[6] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, { FT_STRING, 1, true }, { FT_STRING_NOT_LOCALIZED, 1, true }, { FT_INT, 1, false }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1284823, 4, 5, 5, 0x1BCEC060, fields, -1); + static DB2Meta instance(1284823, 4, 6, 6, 0xC811899B, fields, -1); return &instance; } }; @@ -6980,6 +7957,53 @@ struct LookAtControllerMeta } }; +struct LoreTextMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3311370, -1, 3, 3, 0x196A0B3F, fields, -1); + return &instance; + } +}; + +struct LoreTextPublicMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[6] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_BYTE, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3479846, 0, 6, 5, 0x19A70CF2, fields, 5); + return &instance; + } +}; + +struct MCRSlotXMCRCategoryMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3390955, -1, 2, 1, 0x342AD8FB, fields, 1); + return &instance; + } +}; + struct MailTemplateMeta { static DB2Meta const* Instance() @@ -7117,10 +8141,11 @@ struct MapMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[23] = + static DB2MetaField const fields[24] = { { FT_STRING_NOT_LOCALIZED, 1, true }, { FT_STRING, 1, true }, + { FT_STRING_NOT_LOCALIZED, 1, true }, { FT_STRING, 1, true }, { FT_STRING, 1, true }, { FT_STRING, 1, true }, @@ -7143,7 +8168,7 @@ struct MapMeta { FT_INT, 1, true }, { FT_INT, 2, true }, }; - static DB2Meta instance(1349477, -1, 23, 23, 0xDA9493AF, fields, -1); + static DB2Meta instance(1349477, -1, 24, 24, 0x793F4E8E, fields, -1); return &instance; } }; @@ -7167,15 +8192,16 @@ struct MapChallengeModeMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[5] = + static DB2MetaField const fields[6] = { { FT_STRING, 1, true }, { FT_INT, 1, false }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, + { FT_INT, 1, false }, { FT_SHORT, 3, true }, }; - static DB2Meta instance(801709, 1, 5, 5, 0xD1A78B20, fields, 2); + static DB2Meta instance(801709, 1, 6, 6, 0x0531FF07, fields, 2); return &instance; } }; @@ -7270,6 +8296,35 @@ struct MaterialMeta } }; +struct MawPowerMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(2991315, 0, 3, 3, 0xEE3C69AF, fields, 1); + return &instance; + } +}; + +struct MawPowerRarityMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(2997952, -1, 2, 2, 0x88D5E656, fields, -1); + return &instance; + } +}; + struct MinorTalentMeta { static DB2Meta const* Instance() @@ -7354,6 +8409,80 @@ struct ModelRibbonQualityMeta } }; +struct ModifiedCraftingCategoryMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_STRING, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3386486, -1, 2, 2, 0xEC698BBC, fields, -1); + return &instance; + } +}; + +struct ModifiedCraftingReagentItemMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_STRING, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3386487, -1, 4, 4, 0xCC09E623, fields, -1); + return &instance; + } +}; + +struct ModifiedCraftingReagentSlotMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_STRING, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3386488, -1, 2, 2, 0x79B765B9, fields, -1); + return &instance; + } +}; + +struct ModifiedCraftingSpellSlotMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3390956, -1, 4, 4, 0xF450A714, fields, 0); + return &instance; + } +}; + +struct ModifiedReagentItemMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3386490, 0, 2, 2, 0x8CB2494F, fields, -1); + return &instance; + } +}; + struct ModifierTreeMeta { static DB2Meta const* Instance() @@ -7982,6 +9111,20 @@ struct ParticleColorMeta } }; +struct ParticulateMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3396285, -1, 2, 2, 0x41991AD7, fields, -1); + return &instance; + } +}; + struct ParticulateSoundMeta { static DB2Meta const* Instance() @@ -8143,11 +9286,9 @@ struct PlayerConditionMeta { FT_LONG, 1, true }, { FT_STRING, 1, true }, { FT_INT, 1, false }, - { FT_SHORT, 1, false }, - { FT_SHORT, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, false }, - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, false }, { FT_INT, 1, true }, { FT_SHORT, 1, false }, @@ -8163,7 +9304,7 @@ struct PlayerConditionMeta { FT_BYTE, 1, false }, { FT_INT, 1, false }, { FT_SHORT, 1, false }, - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_INT, 1, false }, @@ -8172,7 +9313,7 @@ struct PlayerConditionMeta { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_INT, 1, false }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, @@ -8183,7 +9324,7 @@ struct PlayerConditionMeta { FT_BYTE, 1, false }, { FT_SHORT, 1, false }, { FT_INT, 1, false }, - { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_BYTE, 1, true }, { FT_BYTE, 1, true }, { FT_INT, 1, false }, @@ -8197,14 +9338,16 @@ struct PlayerConditionMeta { FT_BYTE, 1, true }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_SHORT, 4, false }, { FT_SHORT, 4, false }, { FT_SHORT, 4, false }, { FT_INT, 3, false }, { FT_BYTE, 3, false }, - { FT_SHORT, 4, false }, - { FT_SHORT, 4, false }, - { FT_SHORT, 4, false }, + { FT_INT, 4, true }, + { FT_INT, 4, true }, + { FT_INT, 4, true }, { FT_INT, 4, true }, { FT_INT, 4, true }, { FT_INT, 4, false }, @@ -8222,7 +9365,7 @@ struct PlayerConditionMeta { FT_INT, 6, false }, { FT_INT, 2, true }, }; - static DB2Meta instance(1045411, 2, 81, 81, 0x5BE293E6, fields, -1); + static DB2Meta instance(1045411, 2, 81, 81, 0x19151309, fields, -1); return &instance; } }; @@ -8508,7 +9651,7 @@ struct QuestFeedbackEffectMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[7] = + static DB2MetaField const fields[8] = { { FT_STRING_NOT_LOCALIZED, 1, true }, { FT_INT, 1, false }, @@ -8517,8 +9660,9 @@ struct QuestFeedbackEffectMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1343388, -1, 7, 7, 0x279132CC, fields, -1); + static DB2Meta instance(1343388, -1, 8, 8, 0x540D504A, fields, -1); return &instance; } }; @@ -8543,13 +9687,14 @@ struct QuestLineMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[4] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, { FT_INT, 1, false }, + { FT_INT, 1, true }, }; - static DB2Meta instance(973430, -1, 3, 3, 0x860E7B54, fields, -1); + static DB2Meta instance(973430, -1, 4, 4, 0x20DB8520, fields, -1); return &instance; } }; @@ -8606,7 +9751,7 @@ struct QuestPOIBlobMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[7] = + static DB2MetaField const fields[9] = { { FT_INT, 1, false }, { FT_SHORT, 1, true }, @@ -8614,9 +9759,11 @@ struct QuestPOIBlobMeta { FT_BYTE, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, false }, { FT_INT, 1, false }, }; - static DB2Meta instance(1251882, 0, 7, 7, 0xED2583D9, fields, 1); + static DB2Meta instance(1251882, 0, 9, 9, 0x3C4D1099, fields, 1); return &instance; } }; @@ -8625,14 +9772,15 @@ struct QuestPOIPointMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[4] = + static DB2MetaField const fields[5] = { { FT_INT, 1, false }, { FT_SHORT, 1, true }, { FT_SHORT, 1, true }, + { FT_SHORT, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(1251883, 0, 4, 3, 0xCCABC187, fields, 3); + static DB2Meta instance(1251883, 0, 5, 4, 0xD291971B, fields, 4); return &instance; } }; @@ -8703,16 +9851,16 @@ struct QuestV2CliTaskMeta { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_INT, 1, false }, - { FT_INT, 1, false }, - { FT_INT, 1, false }, { FT_INT, 1, true }, - { FT_SHORT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 1, false }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 3, true }, { FT_INT, 3, false }, }; - static DB2Meta instance(1028735, 3, 25, 25, 0xC85E3AAF, fields, -1); + static DB2Meta instance(1028735, 3, 25, 25, 0x7AE578CB, fields, -1); return &instance; } }; @@ -8744,6 +9892,69 @@ struct QuestXPMeta } }; +struct QuestXUIQuestDetailsThemeMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3448517, -1, 2, 2, 0xE5F50D56, fields, -1); + return &instance; + } +}; + +struct QuestXUiWidgetSetMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3923421, -1, 2, 2, 0x9D15AFB1, fields, -1); + return &instance; + } +}; + +struct RTPCMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[6] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3405439, 0, 6, 6, 0x0D410D54, fields, 5); + return &instance; + } +}; + +struct RTPCDataMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[5] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3405440, -1, 5, 5, 0x25A83DE9, fields, 0); + return &instance; + } +}; + struct RafActivityMeta { static DB2Meta const* Instance() @@ -8776,6 +9987,24 @@ struct RandPropPointsMeta } }; +struct RecipeProgressionGroupEntryMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[6] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3671785, -1, 6, 6, 0x6D84AC24, fields, 0); + return &instance; + } +}; + struct RelicSlotTierRequirementMeta { static DB2Meta const* Instance() @@ -8808,6 +10037,37 @@ struct RelicTalentMeta } }; +struct RenownRewardsMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[19] = + { + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3743117, 3, 19, 19, 0xE58AA7BC, fields, 4); + return &instance; + } +}; + struct ResearchBranchMeta { static DB2Meta const* Instance() @@ -8979,47 +10239,56 @@ struct RopeEffectMeta } }; -struct SDReplacementModelMeta +struct RuneforgeLegendaryAbilityMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[1] = + static DB2MetaField const fields[9] = { + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(1712172, -1, 1, 1, 0x5C3E39E7, fields, -1); + static DB2Meta instance(3500241, 1, 9, 9, 0x61DAAC70, fields, -1); return &instance; } }; -struct SSAOSettingsMeta +struct SDReplacementModelMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[5] = + static DB2MetaField const fields[1] = { - { FT_INT, 1, false }, - { FT_FLOAT, 1, true }, - { FT_FLOAT, 1, true }, - { FT_FLOAT, 1, true }, - { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(2056369, 0, 5, 5, 0x20BC890C, fields, -1); + static DB2Meta instance(1712172, -1, 1, 1, 0x5C3E39E7, fields, -1); return &instance; } }; -struct ScalingStatDistributionMeta +struct SSAOSettingsMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[8] = { - { FT_SHORT, 1, false }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, + { FT_INT, 1, false }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, }; - static DB2Meta instance(1141728, -1, 3, 3, 0xE9A4FF63, fields, -1); + static DB2Meta instance(2056369, 0, 8, 8, 0xD7975681, fields, -1); return &instance; } }; @@ -9065,7 +10334,7 @@ struct ScenarioStepMeta { FT_STRING, 1, true }, { FT_SHORT, 1, false }, { FT_INT, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_SHORT, 1, false }, { FT_BYTE, 1, false }, @@ -9073,7 +10342,7 @@ struct ScenarioStepMeta { FT_INT, 1, false }, { FT_SHORT, 1, false }, }; - static DB2Meta instance(1132761, -1, 11, 11, 0x9FD44A1F, fields, 2); + static DB2Meta instance(1132761, -1, 11, 11, 0xA19BAF50, fields, 2); return &instance; } }; @@ -9166,58 +10435,6 @@ struct ScheduledIntervalMeta } }; -struct ScheduledWorldStateMeta -{ - static DB2Meta const* Instance() - { - static DB2MetaField const fields[8] = - { - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - }; - static DB2Meta instance(1327083, -1, 8, 8, 0x1AE5AC2A, fields, 0); - return &instance; - } -}; - -struct ScheduledWorldStateGroupMeta -{ - static DB2Meta const* Instance() - { - static DB2MetaField const fields[5] = - { - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - }; - static DB2Meta instance(1327084, -1, 5, 5, 0x139E018C, fields, -1); - return &instance; - } -}; - -struct ScheduledWorldStateXUniqCatMeta -{ - static DB2Meta const* Instance() - { - static DB2MetaField const fields[3] = - { - { FT_INT, 1, false }, - { FT_INT, 1, true }, - { FT_INT, 1, true }, - }; - static DB2Meta instance(1388724, 0, 3, 2, 0xCA3A84D6, fields, 2); - return &instance; - } -}; - struct ScreenEffectMeta { static DB2Meta const* Instance() @@ -9242,6 +10459,19 @@ struct ScreenEffectMeta } }; +struct ScreenEffectTypeMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[1] = + { + { FT_INT, 1, true }, + }; + static DB2Meta instance(3063174, -1, 1, 1, 0xBE649273, fields, -1); + return &instance; + } +}; + struct ScreenLocationMeta { static DB2Meta const* Instance() @@ -9363,13 +10593,13 @@ struct SkillLineAbilityMeta { FT_BYTE, 1, true }, { FT_SHORT, 1, true }, { FT_SHORT, 1, true }, - { FT_BYTE, 1, true }, + { FT_INT, 1, true }, { FT_BYTE, 1, true }, { FT_SHORT, 1, true }, { FT_SHORT, 1, true }, { FT_SHORT, 1, true }, }; - static DB2Meta instance(1266278, 1, 15, 15, 0xF0DE0EBD, fields, 2); + static DB2Meta instance(1266278, 1, 15, 15, 0x765222E5, fields, 2); return &instance; } }; @@ -9393,6 +10623,121 @@ struct SkillRaceClassInfoMeta } }; +struct SkySceneXPlayerConditionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3581893, -1, 2, 1, 0xBF5812B6, fields, 1); + return &instance; + } +}; + +struct SoulbindMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[7] = + { + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3488583, 1, 7, 7, 0xD29923C2, fields, -1); + return &instance; + } +}; + +struct SoulbindConduitMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3594380, 0, 4, 4, 0x5F7D8851, fields, -1); + return &instance; + } +}; + +struct SoulbindConduitItemMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3604984, -1, 2, 2, 0xA64372DE, fields, -1); + return &instance; + } +}; + +struct SoulbindConduitRankMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3620681, -1, 4, 3, 0xE97AAA36, fields, 3); + return &instance; + } +}; + +struct SoulbindConduitRankPropertiesMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3858895, -1, 3, 3, 0xB2FCF094, fields, -1); + return &instance; + } +}; + +struct SoulbindUIDisplayInfoMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[9] = + { + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3490472, 1, 9, 9, 0x58274CBA, fields, -1); + return &instance; + } +}; + struct SoundAmbienceMeta { static DB2Meta const* Instance() @@ -9707,6 +11052,23 @@ struct SoundOverrideMeta } }; +struct SoundParameterMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[5] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3405441, -1, 5, 5, 0xD1E7724D, fields, -1); + return &instance; + } +}; + struct SoundProviderPreferencesMeta { static DB2Meta const* Instance() @@ -9943,13 +11305,12 @@ struct SpellCastTimesMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[2] = { { FT_INT, 1, true }, - { FT_SHORT, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(1134089, -1, 3, 3, 0x9BD18C05, fields, -1); + static DB2Meta instance(1134089, -1, 2, 2, 0xA423CA34, fields, -1); return &instance; } }; @@ -10240,13 +11601,12 @@ struct SpellDurationMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[3] = + static DB2MetaField const fields[2] = { { FT_INT, 1, true }, - { FT_INT, 1, false }, { FT_INT, 1, true }, }; - static DB2Meta instance(1137828, -1, 3, 3, 0x70784BCD, fields, -1); + static DB2Meta instance(1137828, -1, 2, 2, 0x8C317431, fields, -1); return &instance; } }; @@ -10260,7 +11620,7 @@ struct SpellEffectMeta { FT_SHORT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, - { FT_INT, 1, false }, + { FT_INT, 1, true }, { FT_FLOAT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, @@ -10286,7 +11646,7 @@ struct SpellEffectMeta { FT_SHORT, 2, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(1140088, -1, 28, 27, 0x63D5AFF5, fields, 27); + static DB2Meta instance(1140088, -1, 28, 27, 0x8E2EAEB1, fields, 27); return &instance; } }; @@ -10411,13 +11771,16 @@ struct SpellItemEnchantmentMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[20] = + static DB2MetaField const fields[23] = { { FT_STRING, 1, true }, { FT_STRING, 1, true }, + { FT_INT, 1, false }, { FT_INT, 3, false }, { FT_FLOAT, 3, true }, { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, { FT_INT, 1, false }, { FT_INT, 1, false }, { FT_SHORT, 3, true }, @@ -10434,7 +11797,7 @@ struct SpellItemEnchantmentMeta { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, }; - static DB2Meta instance(1362771, -1, 20, 20, 0x3933F488, fields, -1); + static DB2Meta instance(1362771, 2, 23, 23, 0x9E09787D, fields, -1); return &instance; } }; @@ -10509,12 +11872,12 @@ struct SpellLevelsMeta { { FT_BYTE, 1, false }, { FT_SHORT, 1, true }, - { FT_SHORT, 1, true }, - { FT_SHORT, 1, true }, { FT_BYTE, 1, false }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1140079, -1, 6, 5, 0xDC8F8F3D, fields, 5); + static DB2Meta instance(1140079, -1, 6, 5, 0x79D1C0A1, fields, 5); return &instance; } }; @@ -10536,9 +11899,9 @@ struct SpellMiscMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[13] = + static DB2MetaField const fields[16] = { - { FT_INT, 14, true }, + { FT_INT, 15, true }, { FT_BYTE, 1, false }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, @@ -10551,8 +11914,11 @@ struct SpellMiscMeta { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1003144, -1, 13, 12, 0x82FFFB5F, fields, 12); + static DB2Meta instance(1003144, -1, 16, 15, 0xB252FDD7, fields, 15); return &instance; } }; @@ -10704,11 +12070,11 @@ struct SpellProcsPerMinuteModMeta static DB2MetaField const fields[4] = { { FT_BYTE, 1, false }, - { FT_SHORT, 1, true }, + { FT_INT, 1, true }, { FT_FLOAT, 1, true }, { FT_SHORT, 1, false }, }; - static DB2Meta instance(1133525, -1, 4, 3, 0x147FD7E9, fields, 3); + static DB2Meta instance(1133525, -1, 4, 3, 0x2EF9CF3F, fields, 3); return &instance; } }; @@ -10793,6 +12159,41 @@ struct SpellScalingMeta } }; +struct SpellScriptMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[6] = + { + { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3055899, 3, 6, 6, 0xA2577E7A, fields, -1); + return &instance; + } +}; + +struct SpellScriptTextMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[5] = + { + { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3055901, 1, 5, 4, 0x1DD3B137, fields, 4); + return &instance; + } +}; + struct SpellShapeshiftMeta { static DB2Meta const* Instance() @@ -10884,7 +12285,7 @@ struct SpellVisualMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[15] = + static DB2MetaField const fields[16] = { { FT_FLOAT, 3, true }, { FT_FLOAT, 3, true }, @@ -10900,9 +12301,10 @@ struct SpellVisualMeta { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_INT, 1, false }, + { FT_INT, 1, true }, { FT_INT, 1, false }, }; - static DB2Meta instance(897952, -1, 15, 15, 0x17962AA0, fields, -1); + static DB2Meta instance(897952, -1, 16, 16, 0xD49A0A98, fields, -1); return &instance; } }; @@ -10931,7 +12333,7 @@ struct SpellVisualColorEffectMeta { FT_FLOAT, 1, true }, { FT_INT, 1, true }, { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, + { FT_BYTE, 1, true }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, { FT_SHORT, 1, false }, @@ -10940,7 +12342,7 @@ struct SpellVisualColorEffectMeta { FT_FLOAT, 1, true }, { FT_INT, 1, false }, }; - static DB2Meta instance(1094006, -1, 11, 11, 0x41C2763B, fields, -1); + static DB2Meta instance(1094006, -1, 11, 11, 0x316310A7, fields, -1); return &instance; } }; @@ -11046,7 +12448,7 @@ struct SpellVisualKitModelAttachMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[22] = + static DB2MetaField const fields[23] = { { FT_FLOAT, 3, true }, { FT_FLOAT, 3, true }, @@ -11069,9 +12471,10 @@ struct SpellVisualKitModelAttachMeta { FT_BYTE, 1, false }, { FT_INT, 1, false }, { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(897953, 2, 22, 21, 0xB8BDA6F9, fields, 21); + static DB2Meta instance(897953, 2, 23, 22, 0xF2BEEF44, fields, 22); return &instance; } }; @@ -11080,7 +12483,7 @@ struct SpellVisualMissileMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[17] = + static DB2MetaField const fields[18] = { { FT_FLOAT, 3, true }, { FT_FLOAT, 3, true }, @@ -11098,9 +12501,24 @@ struct SpellVisualMissileMeta { FT_SHORT, 1, false }, { FT_INT, 1, false }, { FT_BYTE, 1, true }, + { FT_INT, 1, true }, { FT_SHORT, 1, false }, }; - static DB2Meta instance(897954, 2, 17, 16, 0xBE91C62B, fields, 16); + static DB2Meta instance(897954, 2, 18, 17, 0x68D6B039, fields, 17); + return &instance; + } +}; + +struct SpellVisualScreenEffectMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3607312, -1, 2, 2, 0x879B50D1, fields, -1); return &instance; } }; @@ -11123,14 +12541,13 @@ struct SpellXSpellVisualMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[13] = + static DB2MetaField const fields[12] = { { FT_INT, 1, false }, { FT_BYTE, 1, false }, { FT_INT, 1, false }, { FT_FLOAT, 1, true }, { FT_BYTE, 1, false }, - { FT_BYTE, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_SHORT, 1, false }, @@ -11139,7 +12556,7 @@ struct SpellXSpellVisualMeta { FT_INT, 1, false }, { FT_INT, 1, true }, }; - static DB2Meta instance(1101657, 0, 13, 12, 0x8D0B1C8F, fields, 12); + static DB2Meta instance(1101657, 0, 12, 11, 0xE4509F95, fields, 11); return &instance; } }; @@ -11316,6 +12733,22 @@ struct TaxiPathNodeMeta } }; +struct TerrainColorGradingRampMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3501705, -1, 4, 4, 0x2031C9AD, fields, -1); + return &instance; + } +}; + struct TerrainMaterialMeta { static DB2Meta const* Instance() @@ -11365,20 +12798,21 @@ struct TextureBlendSetMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[10] = + static DB2MetaField const fields[11] = { { FT_INT, 3, true }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, { FT_BYTE, 1, false }, + { FT_INT, 1, true }, { FT_FLOAT, 3, true }, { FT_FLOAT, 3, true }, { FT_FLOAT, 3, true }, { FT_FLOAT, 3, true }, { FT_FLOAT, 4, true }, }; - static DB2Meta instance(1328721, -1, 10, 10, 0x9CDAC82F, fields, -1); + static DB2Meta instance(1328721, -1, 11, 11, 0x1BBA6A98, fields, -1); return &instance; } }; @@ -11398,6 +12832,22 @@ struct TextureFileDataMeta } }; +struct TierTransitionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + }; + static DB2Meta instance(3076928, -1, 4, 4, 0x467A48BA, fields, -1); + return &instance; + } +}; + struct TotemCategoryMeta { static DB2Meta const* Instance() @@ -11453,12 +12903,11 @@ struct TradeSkillItemMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[2] = + static DB2MetaField const fields[1] = { { FT_SHORT, 1, false }, - { FT_BYTE, 1, true }, }; - static DB2Meta instance(1329070, -1, 2, 2, 0xF7BCB2E0, fields, -1); + static DB2Meta instance(1329070, -1, 1, 1, 0x55557361, fields, -1); return &instance; } }; @@ -11489,7 +12938,7 @@ struct TransmogDefaultLevelMeta { FT_BYTE, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(2399695, -1, 2, 2, 0x5B2F3204, fields, -1); + static DB2Meta instance(2399695, -1, 2, 2, 0xC7625152, fields, -1); return &instance; } }; @@ -11508,6 +12957,23 @@ struct TransmogHolidayMeta } }; +struct TransmogIllusionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[5] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3580450, 0, 5, 5, 0xE579B752, fields, -1); + return &instance; + } +}; + struct TransmogSetMeta { static DB2Meta const* Instance() @@ -11624,10 +13090,76 @@ struct TrophyMeta { { FT_STRING, 1, true }, { FT_BYTE, 1, false }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, false }, + }; + static DB2Meta instance(975024, -1, 4, 4, 0x27A846CD, fields, -1); + return &instance; + } +}; + +struct UIChromieTimeExpansionInfoMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[10] = + { + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3488582, 2, 10, 10, 0x3EEBBD91, fields, -1); + return &instance; + } +}; + +struct UICovenantAbilityMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_BYTE, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3502042, -1, 4, 4, 0x7286CBAB, fields, 0); + return &instance; + } +}; + +struct UICovenantPreviewMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[16] = + { + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(975024, -1, 4, 4, 0x05F94D28, fields, -1); + static DB2Meta instance(3502043, 2, 16, 16, 0x09E1B4C7, fields, -1); return &instance; } }; @@ -11662,6 +13194,63 @@ struct UIExpansionDisplayInfoIconMeta } }; +struct UIScriptedAnimationEffectMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[17] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + }; + static DB2Meta instance(3556601, 0, 17, 17, 0xBBA9C412, fields, -1); + return &instance; + } +}; + +struct UISplashScreenMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[16] = + { + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_STRING, 1, true }, + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_BYTE, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(2960122, 7, 16, 16, 0xCB8F573D, fields, -1); + return &instance; + } +}; + struct UiCamFbackTransmogChrRaceMeta { static DB2Meta const* Instance() @@ -11746,6 +13335,31 @@ struct UiCanvasMeta } }; +struct UiCovenantDisplayInfoMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[13] = + { + { FT_INT, 1, false }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3509132, 0, 13, 13, 0x577C57A9, fields, -1); + return &instance; + } +}; + struct UiItemInteractionMeta { static DB2Meta const* Instance() @@ -11768,7 +13382,7 @@ struct UiItemInteractionMeta { FT_INT, 1, true }, { FT_INT, 1, true }, }; - static DB2Meta instance(3182424, 4, 15, 15, 0x32F22391, fields, -1); + static DB2Meta instance(3182424, 4, 15, 15, 0x62BB4D7F, fields, -1); return &instance; } }; @@ -11777,7 +13391,7 @@ struct UiMapMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[14] = + static DB2MetaField const fields[13] = { { FT_STRING, 1, true }, { FT_INT, 1, false }, @@ -11785,16 +13399,15 @@ struct UiMapMeta { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, - { FT_INT, 1, false }, - { FT_INT, 1, false }, { FT_INT, 1, true }, { FT_INT, 1, false }, { FT_INT, 1, true }, { FT_BYTE, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(1957206, 1, 14, 14, 0xF982A2E5, fields, 2); + static DB2Meta instance(1957206, 1, 13, 13, 0x18361012, fields, 2); return &instance; } }; @@ -11926,7 +13539,7 @@ struct UiMapLinkMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[8] = + static DB2MetaField const fields[9] = { { FT_FLOAT, 2, true }, { FT_FLOAT, 2, true }, @@ -11936,8 +13549,9 @@ struct UiMapLinkMeta { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(2030690, 2, 8, 8, 0x033167B1, fields, 3); + static DB2Meta instance(2030690, 2, 9, 9, 0x90B080E2, fields, 3); return &instance; } }; @@ -12058,6 +13672,21 @@ struct UiPartyPoseMeta } }; +struct UiQuestDetailsThemeMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_STRING, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3448518, -1, 3, 3, 0xDFF2A61D, fields, -1); + return &instance; + } +}; + struct UiTextureAtlasMeta { static DB2Meta const* Instance() @@ -12088,6 +13717,20 @@ struct UiTextureAtlasElementMeta } }; +struct UiTextureAtlasElementOverrideMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3765186, -1, 2, 1, 0x6B5B752D, fields, 1); + return &instance; + } +}; + struct UiTextureAtlasMemberMeta { static DB2Meta const* Instance() @@ -12129,7 +13772,7 @@ struct UiWidgetMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[8] = + static DB2MetaField const fields[9] = { { FT_STRING_NOT_LOCALIZED, 1, true }, { FT_INT, 1, false }, @@ -12139,8 +13782,9 @@ struct UiWidgetMeta { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_BYTE, 1, true }, }; - static DB2Meta instance(1983278, 1, 8, 8, 0xF2FE9CB9, fields, -1); + static DB2Meta instance(1983278, 1, 9, 9, 0xBCC7B06B, fields, -1); return &instance; } }; @@ -12190,6 +13834,20 @@ struct UiWidgetMapMeta } }; +struct UiWidgetSetMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_BYTE, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3055925, -1, 2, 2, 0x7CB0FD20, fields, -1); + return &instance; + } +}; + struct UiWidgetStringSourceMeta { static DB2Meta const* Instance() @@ -12227,17 +13885,33 @@ struct UiWidgetVisualizationMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[7] = + static DB2MetaField const fields[9] = { { FT_STRING_NOT_LOCALIZED, 1, true }, + { FT_INT, 1, false }, { FT_BYTE, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, { FT_SHORT, 1, true }, { FT_INT, 1, true }, { FT_INT, 1, true }, + { FT_BYTE, 1, true }, }; - static DB2Meta instance(1983276, -1, 7, 7, 0x07795E95, fields, -1); + static DB2Meta instance(1983276, 1, 9, 9, 0x6089B8EF, fields, -1); + return &instance; + } +}; + +struct UiWidgetXWidgetSetMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[2] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3386363, -1, 2, 1, 0xA8FB2A6F, fields, 1); return &instance; } }; @@ -12336,13 +14010,30 @@ struct VehicleMeta { FT_FLOAT, 1, true }, { FT_FLOAT, 1, true }, { FT_FLOAT, 1, true }, - { FT_BYTE, 1, false }, { FT_SHORT, 1, false }, { FT_INT, 1, true }, + { FT_SHORT, 1, false }, { FT_SHORT, 8, false }, { FT_SHORT, 3, false }, }; - static DB2Meta instance(1368621, -1, 18, 18, 0x51C0ABAB, fields, -1); + static DB2Meta instance(1368621, -1, 18, 18, 0xF04F7E8F, fields, -1); + return &instance; + } +}; + +struct VehiclePOITypeMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[5] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3311405, -1, 5, 5, 0x8C0FAD10, fields, -1); return &instance; } }; @@ -12453,7 +14144,7 @@ struct VignetteMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[9] = + static DB2MetaField const fields[10] = { { FT_STRING, 1, true }, { FT_INT, 1, false }, @@ -12464,8 +14155,9 @@ struct VignetteMeta { FT_FLOAT, 1, true }, { FT_BYTE, 1, true }, { FT_INT, 1, true }, + { FT_INT, 1, true }, }; - static DB2Meta instance(892861, -1, 9, 9, 0x4AC89FFC, fields, -1); + static DB2Meta instance(892861, -1, 10, 10, 0x8256C3F7, fields, -1); return &instance; } }; @@ -12515,6 +14207,22 @@ struct VocalUISoundsMeta } }; +struct VolumeFogConditionMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[4] = + { + { FT_INT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_FLOAT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3587230, -1, 4, 3, 0x93FE029C, fields, 3); + return &instance; + } +}; + struct WMOAreaTableMeta { static DB2Meta const* Instance() @@ -12770,9 +14478,10 @@ struct WeatherMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[22] = + static DB2MetaField const fields[23] = { { FT_BYTE, 1, false }, + { FT_BYTE, 1, false }, { FT_FLOAT, 1, true }, { FT_INT, 1, false }, { FT_SHORT, 1, false }, @@ -12795,7 +14504,7 @@ struct WeatherMeta { FT_FLOAT, 2, true }, { FT_FLOAT, 3, true }, }; - static DB2Meta instance(1343311, -1, 22, 22, 0x50346E3B, fields, -1); + static DB2Meta instance(1343311, -1, 23, 23, 0xD65D6CD5, fields, -1); return &instance; } }; @@ -12814,6 +14523,21 @@ struct WeatherXParticulateMeta } }; +struct WeeklyRewardChestThresholdMeta +{ + static DB2Meta const* Instance() + { + static DB2MetaField const fields[3] = + { + { FT_INT, 1, true }, + { FT_INT, 1, true }, + { FT_INT, 1, true }, + }; + static DB2Meta instance(3580962, -1, 3, 3, 0x73C0E8B4, fields, -1); + return &instance; + } +}; + struct WindSettingsMeta { static DB2Meta const* Instance() @@ -12843,9 +14567,9 @@ struct WorldBossLockoutMeta static DB2MetaField const fields[2] = { { FT_STRING, 1, true }, - { FT_SHORT, 1, false }, + { FT_INT, 1, true }, }; - static DB2Meta instance(975279, -1, 2, 2, 0x4FB18779, fields, -1); + static DB2Meta instance(975279, -1, 2, 2, 0xDBCC9926, fields, -1); return &instance; } }; @@ -13016,7 +14740,7 @@ struct ZoneLightMeta { static DB2Meta const* Instance() { - static DB2MetaField const fields[6] = + static DB2MetaField const fields[7] = { { FT_STRING_NOT_LOCALIZED, 1, true }, { FT_SHORT, 1, false }, @@ -13024,8 +14748,9 @@ struct ZoneLightMeta { FT_BYTE, 1, false }, { FT_FLOAT, 1, true }, { FT_FLOAT, 1, true }, + { FT_SHORT, 1, false }, }; - static DB2Meta instance(1310253, -1, 6, 6, 0x5BE043F9, fields, -1); + static DB2Meta instance(1310253, -1, 7, 7, 0x1065A739, fields, -1); return &instance; } }; diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 1d74072f3a0..90ec65c3b30 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -27,6 +27,8 @@ #include "Regex.h" #include "Timer.h" #include "Util.h" +#include "World.h" +#include "advstd.h" #include <boost/filesystem/operations.hpp> #include <array> #include <bitset> @@ -80,14 +82,20 @@ DB2Storage<BattlePetSpeciesStateEntry> sBattlePetSpeciesStateStore("Bat DB2Storage<BattlemasterListEntry> sBattlemasterListStore("BattlemasterList.db2", BattlemasterListLoadInfo::Instance()); DB2Storage<BroadcastTextEntry> sBroadcastTextStore("BroadcastText.db2", BroadcastTextLoadInfo::Instance()); DB2Storage<Cfg_RegionsEntry> sCfgRegionsStore("Cfg_Regions.db2", CfgRegionsLoadInfo::Instance()); -DB2Storage<CharacterFacialHairStylesEntry> sCharacterFacialHairStylesStore("CharacterFacialHairStyles.db2", CharacterFacialHairStylesLoadInfo::Instance()); -DB2Storage<CharBaseSectionEntry> sCharBaseSectionStore("CharBaseSection.db2", CharBaseSectionLoadInfo::Instance()); -DB2Storage<CharSectionsEntry> sCharSectionsStore("CharSections.db2", CharSectionsLoadInfo::Instance()); -DB2Storage<CharStartOutfitEntry> sCharStartOutfitStore("CharStartOutfit.db2", CharStartOutfitLoadInfo::Instance()); DB2Storage<CharTitlesEntry> sCharTitlesStore("CharTitles.db2", CharTitlesLoadInfo::Instance()); +DB2Storage<CharacterLoadoutEntry> sCharacterLoadoutStore("CharacterLoadout.db2", CharacterLoadoutLoadInfo::Instance()); +DB2Storage<CharacterLoadoutItemEntry> sCharacterLoadoutItemStore("CharacterLoadoutItem.db2", CharacterLoadoutItemLoadInfo::Instance()); DB2Storage<ChatChannelsEntry> sChatChannelsStore("ChatChannels.db2", ChatChannelsLoadInfo::Instance()); DB2Storage<ChrClassesEntry> sChrClassesStore("ChrClasses.db2", ChrClassesLoadInfo::Instance()); DB2Storage<ChrClassesXPowerTypesEntry> sChrClassesXPowerTypesStore("ChrClassesXPowerTypes.db2", ChrClassesXPowerTypesLoadInfo::Instance()); +DB2Storage<ChrCustomizationChoiceEntry> sChrCustomizationChoiceStore("ChrCustomizationChoice.db2", ChrCustomizationChoiceLoadInfo::Instance()); +DB2Storage<ChrCustomizationDisplayInfoEntry> sChrCustomizationDisplayInfoStore("ChrCustomizationDisplayInfo.db2", ChrCustomizationDisplayInfoLoadInfo::Instance()); +DB2Storage<ChrCustomizationElementEntry> sChrCustomizationElementStore("ChrCustomizationElement.db2", ChrCustomizationElementLoadInfo::Instance()); +DB2Storage<ChrCustomizationOptionEntry> sChrCustomizationOptionStore("ChrCustomizationOption.db2", ChrCustomizationOptionLoadInfo::Instance()); +DB2Storage<ChrCustomizationReqEntry> sChrCustomizationReqStore("ChrCustomizationReq.db2", ChrCustomizationReqLoadInfo::Instance()); +DB2Storage<ChrCustomizationReqChoiceEntry> sChrCustomizationReqChoiceStore("ChrCustomizationReqChoice.db2", ChrCustomizationReqChoiceLoadInfo::Instance()); +DB2Storage<ChrModelEntry> sChrModelStore("ChrModel.db2", ChrModelLoadInfo::Instance()); +DB2Storage<ChrRaceXChrModelEntry> sChrRaceXChrModelStore("ChrRaceXChrModel.db2", ChrRaceXChrModelLoadInfo::Instance()); DB2Storage<ChrRacesEntry> sChrRacesStore("ChrRaces.db2", ChrRacesLoadInfo::Instance()); DB2Storage<ChrSpecializationEntry> sChrSpecializationStore("ChrSpecialization.db2", ChrSpecializationLoadInfo::Instance()); DB2Storage<CinematicCameraEntry> sCinematicCameraStore("CinematicCamera.db2", CinematicCameraLoadInfo::Instance()); @@ -221,7 +229,6 @@ DB2Storage<RandPropPointsEntry> sRandPropPointsStore("RandPropPo DB2Storage<RewardPackEntry> sRewardPackStore("RewardPack.db2", RewardPackLoadInfo::Instance()); DB2Storage<RewardPackXCurrencyTypeEntry> sRewardPackXCurrencyTypeStore("RewardPackXCurrencyType.db2", RewardPackXCurrencyTypeLoadInfo::Instance()); DB2Storage<RewardPackXItemEntry> sRewardPackXItemStore("RewardPackXItem.db2", RewardPackXItemLoadInfo::Instance()); -DB2Storage<ScalingStatDistributionEntry> sScalingStatDistributionStore("ScalingStatDistribution.db2", ScalingStatDistributionLoadInfo::Instance()); DB2Storage<ScenarioEntry> sScenarioStore("Scenario.db2", ScenarioLoadInfo::Instance()); DB2Storage<ScenarioStepEntry> sScenarioStepStore("ScenarioStep.db2", ScenarioStepLoadInfo::Instance()); DB2Storage<SceneScriptEntry> sSceneScriptStore("SceneScript.db2", SceneScriptLoadInfo::Instance()); @@ -276,6 +283,7 @@ DB2Storage<TaxiPathNodeEntry> sTaxiPathNodeStore("TaxiPathNode DB2Storage<TotemCategoryEntry> sTotemCategoryStore("TotemCategory.db2", TotemCategoryLoadInfo::Instance()); DB2Storage<ToyEntry> sToyStore("Toy.db2", ToyLoadInfo::Instance()); DB2Storage<TransmogHolidayEntry> sTransmogHolidayStore("TransmogHoliday.db2", TransmogHolidayLoadInfo::Instance()); +DB2Storage<TransmogIllusionEntry> sTransmogIllusionStore("TransmogIllusion.db2", TransmogIllusionLoadInfo::Instance()); DB2Storage<TransmogSetEntry> sTransmogSetStore("TransmogSet.db2", TransmogSetLoadInfo::Instance()); DB2Storage<TransmogSetGroupEntry> sTransmogSetGroupStore("TransmogSetGroup.db2", TransmogSetGroupLoadInfo::Instance()); DB2Storage<TransmogSetItemEntry> sTransmogSetItemStore("TransmogSetItem.db2", TransmogSetItemLoadInfo::Instance()); @@ -316,9 +324,7 @@ typedef std::unordered_map<uint32 /*areaGroupId*/, std::vector<uint32/*areaId*/> typedef std::unordered_map<uint32, std::vector<ArtifactPowerEntry const*>> ArtifactPowersContainer; typedef std::unordered_map<uint32, std::unordered_set<uint32>> ArtifactPowerLinksContainer; typedef std::unordered_map<std::pair<uint32, uint8>, ArtifactPowerRankEntry const*> ArtifactPowerRanksContainer; -typedef std::unordered_map<uint32, CharStartOutfitEntry const*> CharStartOutfitContainer; typedef ChrSpecializationEntry const* ChrSpecializationByIndexContainer[MAX_CLASSES + 1][MAX_SPECIALIZATIONS]; -typedef std::unordered_map<uint32, ChrSpecializationEntry const*> ChrSpecialzationByClassContainer; typedef std::unordered_map<uint32 /*curveID*/, std::vector<CurvePointEntry const*>> CurvePointsContainer; typedef std::map<std::tuple<uint32, uint8, uint8, uint8>, EmotesTextSoundEntry const*> EmotesTextSoundContainer; typedef std::unordered_map<uint32, std::vector<uint32>> FactionTeamContainer; @@ -380,12 +386,13 @@ namespace std::unordered_map<uint32 /*azeritePowerSetId*/, std::vector<AzeritePowerSetMemberEntry const*>> _azeritePowers; std::unordered_map<std::pair<uint32 /*azeriteUnlockSetId*/, ItemContext>, std::array<uint8, MAX_AZERITE_EMPOWERED_TIER>> _azeriteTierUnlockLevels; std::unordered_map<std::pair<uint32 /*itemId*/, ItemContext>, AzeriteUnlockMappingEntry const*> _azeriteUnlockMappings; - std::set<std::tuple<uint8, uint8, uint32>> _characterFacialHairStyles; - std::multimap<std::tuple<uint8, uint8, CharBaseSectionVariation>, CharSectionsEntry const*> _charSections; - CharStartOutfitContainer _charStartOutfits; - uint32 _powersByClass[MAX_CLASSES][MAX_POWERS]; + std::array<std::array<uint32, MAX_POWERS>, MAX_CLASSES> _powersByClass; + std::unordered_map<uint32 /*chrCustomizationOptionId*/, std::vector<ChrCustomizationChoiceEntry const*>> _chrCustomizationChoicesByOption; + std::unordered_map<std::pair<uint8, uint8>, ChrModelEntry const*> _chrModelsByRaceAndGender; + std::map<std::tuple<uint8 /*race*/, uint8/*gender*/, uint8/*shapeshift*/>, ShapeshiftFormModelData> _chrCustomizationChoicesForShapeshifts; + std::unordered_map<std::pair<uint8 /*race*/, uint8/*gender*/>, std::vector<ChrCustomizationOptionEntry const*>> _chrCustomizationOptionsByRaceAndGender; + std::unordered_map<uint32 /*chrCustomizationReqId*/, std::unordered_map<uint32 /*chrCustomizationOptionId*/, std::vector<uint32>>> _chrCustomizationRequiredChoices; ChrSpecializationByIndexContainer _chrSpecializationsByIndex; - ChrSpecialzationByClassContainer _defaultChrSpecializationsByClass; CurvePointsContainer _curvePoints; EmotesTextSoundContainer _emoteTextSounds; std::unordered_map<std::pair<uint32 /*level*/, int32 /*expansion*/>, ExpectedStatEntry const*> _expectedStatsByLevel; @@ -600,14 +607,20 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul LOAD_DB2(sBattlemasterListStore); LOAD_DB2(sBroadcastTextStore); LOAD_DB2(sCfgRegionsStore); - LOAD_DB2(sCharacterFacialHairStylesStore); - LOAD_DB2(sCharBaseSectionStore); - LOAD_DB2(sCharSectionsStore); - LOAD_DB2(sCharStartOutfitStore); LOAD_DB2(sCharTitlesStore); + LOAD_DB2(sCharacterLoadoutStore); + LOAD_DB2(sCharacterLoadoutItemStore); LOAD_DB2(sChatChannelsStore); LOAD_DB2(sChrClassesStore); LOAD_DB2(sChrClassesXPowerTypesStore); + LOAD_DB2(sChrCustomizationChoiceStore); + LOAD_DB2(sChrCustomizationDisplayInfoStore); + LOAD_DB2(sChrCustomizationElementStore); + LOAD_DB2(sChrCustomizationOptionStore); + LOAD_DB2(sChrCustomizationReqStore); + LOAD_DB2(sChrCustomizationReqChoiceStore); + LOAD_DB2(sChrModelStore); + LOAD_DB2(sChrRaceXChrModelStore); LOAD_DB2(sChrRacesStore); LOAD_DB2(sChrSpecializationStore); LOAD_DB2(sCinematicCameraStore); @@ -741,7 +754,6 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul LOAD_DB2(sRewardPackStore); LOAD_DB2(sRewardPackXCurrencyTypeStore); LOAD_DB2(sRewardPackXItemStore); - LOAD_DB2(sScalingStatDistributionStore); LOAD_DB2(sScenarioStore); LOAD_DB2(sScenarioStepStore); LOAD_DB2(sSceneScriptStore); @@ -796,6 +808,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul LOAD_DB2(sTotemCategoryStore); LOAD_DB2(sToyStore); LOAD_DB2(sTransmogHolidayStore); + LOAD_DB2(sTransmogIllusionStore); LOAD_DB2(sTransmogSetStore); LOAD_DB2(sTransmogSetGroupStore); LOAD_DB2(sTransmogSetItemStore); @@ -910,46 +923,13 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul ASSERT(BATTLE_PET_SPECIES_MAX_ID >= sBattlePetSpeciesStore.GetNumRows(), "BATTLE_PET_SPECIES_MAX_ID (%d) must be equal to or greater than %u", BATTLE_PET_SPECIES_MAX_ID, sBattlePetSpeciesStore.GetNumRows()); - for (CharacterFacialHairStylesEntry const* characterFacialStyle : sCharacterFacialHairStylesStore) - _characterFacialHairStyles.emplace(characterFacialStyle->RaceID, characterFacialStyle->SexID, characterFacialStyle->VariationID); - - std::array<CharBaseSectionVariation, SECTION_TYPE_MAX> sectionToBase = { {} }; - for (CharBaseSectionEntry const* charBaseSection : sCharBaseSectionStore) - { - ASSERT(charBaseSection->ResolutionVariationEnum < SECTION_TYPE_MAX, - "SECTION_TYPE_MAX (%d) must be equal to or greater than %u", uint32(SECTION_TYPE_MAX), uint32(charBaseSection->ResolutionVariationEnum + 1)); - ASSERT(charBaseSection->VariationEnum < AsUnderlyingType(CharBaseSectionVariation::Count), - "CharBaseSectionVariation::Count %u must be equal to or greater than %u", uint32(CharBaseSectionVariation::Count), uint32(charBaseSection->VariationEnum + 1)); - - sectionToBase[charBaseSection->ResolutionVariationEnum] = static_cast<CharBaseSectionVariation>(charBaseSection->VariationEnum); - } - - std::map<std::tuple<uint8, uint8, CharBaseSectionVariation>, std::set<std::pair<uint8, uint8>>> addedSections; - for (CharSectionsEntry const* charSection : sCharSectionsStore) - { - ASSERT(charSection->BaseSection < SECTION_TYPE_MAX, - "SECTION_TYPE_MAX (%d) must be equal to or greater than %u", uint32(SECTION_TYPE_MAX), uint32(charSection->BaseSection + 1)); - - std::tuple<uint8, uint8, CharBaseSectionVariation> sectionKey{ charSection->RaceID, charSection->SexID, sectionToBase[charSection->BaseSection] }; - std::pair<uint8, uint8> sectionCombination{ charSection->VariationIndex, charSection->ColorIndex }; - if (addedSections[sectionKey].count(sectionCombination)) - continue; - - addedSections[sectionKey].insert(sectionCombination); - _charSections.insert({ sectionKey, charSection }); - } - - for (CharStartOutfitEntry const* outfit : sCharStartOutfitStore) - _charStartOutfits[outfit->RaceID | (outfit->ClassID << 8) | (outfit->SexID << 16)] = outfit; - { std::set<ChrClassesXPowerTypesEntry const*, ChrClassesXPowerTypesEntryComparator> powers; for (ChrClassesXPowerTypesEntry const* power : sChrClassesXPowerTypesStore) powers.insert(power); - for (uint32 i = 0; i < MAX_CLASSES; ++i) - for (uint32 j = 0; j < MAX_POWERS; ++j) - _powersByClass[i][j] = MAX_POWERS; + for (std::size_t i = 0; i < _powersByClass.size(); ++i) + _powersByClass[i].fill(MAX_POWERS); for (ChrClassesXPowerTypesEntry const* power : powers) { @@ -964,6 +944,59 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul } } + for (ChrCustomizationChoiceEntry const* customizationChoice : sChrCustomizationChoiceStore) + _chrCustomizationChoicesByOption[customizationChoice->ChrCustomizationOptionID].push_back(customizationChoice); + + std::unordered_multimap<uint32, std::pair<uint32, uint8>> shapeshiftFormByModel; + std::unordered_map<uint32, ChrCustomizationDisplayInfoEntry const*> displayInfoByCustomizationChoice; + + // build shapeshift form model lookup + for (ChrCustomizationElementEntry const* customizationElement : sChrCustomizationElementStore) + { + if (ChrCustomizationDisplayInfoEntry const* customizationDisplayInfo = sChrCustomizationDisplayInfoStore.LookupEntry(customizationElement->ChrCustomizationDisplayInfoID)) + { + if (ChrCustomizationChoiceEntry const* customizationChoice = sChrCustomizationChoiceStore.LookupEntry(customizationElement->ChrCustomizationChoiceID)) + { + displayInfoByCustomizationChoice[customizationElement->ChrCustomizationChoiceID] = customizationDisplayInfo; + if (ChrCustomizationOptionEntry const* customizationOption = sChrCustomizationOptionStore.LookupEntry(customizationChoice->ChrCustomizationOptionID)) + shapeshiftFormByModel.emplace(customizationOption->ChrModelID, std::make_pair(customizationOption->ID, uint8(customizationDisplayInfo->ShapeshiftFormID))); + } + } + } + + std::unordered_map<uint32, std::vector<ChrCustomizationOptionEntry const*>> customizationOptionsByModel; + for (ChrCustomizationOptionEntry const* customizationOption : sChrCustomizationOptionStore) + customizationOptionsByModel[customizationOption->ChrModelID].push_back(customizationOption); + + for (ChrCustomizationReqChoiceEntry const* reqChoice : sChrCustomizationReqChoiceStore) + if (ChrCustomizationChoiceEntry const* customizationChoice = sChrCustomizationChoiceStore.LookupEntry(reqChoice->ChrCustomizationChoiceID)) + _chrCustomizationRequiredChoices[reqChoice->ChrCustomizationReqID][customizationChoice->ChrCustomizationOptionID].push_back(reqChoice->ChrCustomizationChoiceID); + + for (ChrRaceXChrModelEntry const* raceModel : sChrRaceXChrModelStore) + { + if (ChrModelEntry const* model = sChrModelStore.LookupEntry(raceModel->ChrModelID)) + { + _chrModelsByRaceAndGender[{ uint8(raceModel->ChrRacesID), uint8(model->Sex) }] = model; + + if (std::vector<ChrCustomizationOptionEntry const*> const* customizationOptionsForModel = Trinity::Containers::MapGetValuePtr(customizationOptionsByModel, model->ID)) + _chrCustomizationOptionsByRaceAndGender[{ uint8(raceModel->ChrRacesID), uint8(model->Sex) }] = *customizationOptionsForModel; + + // link shapeshift displays to race/gender/form + for (std::pair<uint32 const, std::pair<uint32, uint8>> const& shapeshiftOptionsForModel : Trinity::Containers::MapEqualRange(shapeshiftFormByModel, model->ID)) + { + ShapeshiftFormModelData& data = _chrCustomizationChoicesForShapeshifts[{ uint8(raceModel->ChrRacesID), uint8(model->Sex), shapeshiftOptionsForModel.second.second }]; + data.OptionID = shapeshiftOptionsForModel.second.first; + data.Choices = Trinity::Containers::MapGetValuePtr(_chrCustomizationChoicesByOption, shapeshiftOptionsForModel.second.first); + if (data.Choices) + { + data.Displays.resize(data.Choices->size()); + for (std::size_t i = 0; i < data.Choices->size(); ++i) + data.Displays[i] = Trinity::Containers::MapGetValuePtr(displayInfoByCustomizationChoice, (*data.Choices)[i]->ID); + } + } + } + } + memset(_chrSpecializationsByIndex, 0, sizeof(_chrSpecializationsByIndex)); for (ChrSpecializationEntry const* chrSpec : sChrSpecializationStore) { @@ -978,8 +1011,6 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul } _chrSpecializationsByIndex[storageIndex][chrSpec->OrderIndex] = chrSpec; - if (chrSpec->Flags & CHR_SPECIALIZATION_FLAG_RECOMMENDED) - _defaultChrSpecializationsByClass[chrSpec->ClassID] = chrSpec; } for (ContentTuningXExpectedEntry const* contentTuningXExpectedStat : sContentTuningXExpectedStore) @@ -1247,7 +1278,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul uiMapAssignmentByUiMap.emplace(uiMapAssignment->UiMapID, uiMapAssignment); if (UiMapEntry const* uiMap = sUiMapStore.LookupEntry(uiMapAssignment->UiMapID)) { - ASSERT(uiMap->System < MAX_UI_MAP_SYSTEM, "MAX_TALENT_TIERS must be at least %u", uiMap->System + 1); + ASSERT(uiMap->System < MAX_UI_MAP_SYSTEM, "MAX_UI_MAP_SYSTEM must be at least %u", uiMap->System + 1); if (uiMapAssignment->MapID >= 0) _uiMapAssignmentByMap[uiMap->System].emplace(uiMapAssignment->MapID, uiMapAssignment); if (uiMapAssignment->AreaID) @@ -1269,12 +1300,12 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul memset(&bounds, 0, sizeof(bounds)); if (UiMapEntry const* parentUiMap = sUiMapStore.LookupEntry(uiMap->ParentUiMapID)) { - if (parentUiMap->Flags & 0x80) + if (parentUiMap->GetFlags().HasFlag(UiMapFlag::NoWorldPositions)) continue; UiMapAssignmentEntry const* uiMapAssignment = nullptr; UiMapAssignmentEntry const* parentUiMapAssignment = nullptr; - for (auto uiMapAssignmentForMap : Trinity::Containers::MapEqualRange(uiMapAssignmentByUiMap, uiMap->ID)) + for (std::pair<int32 const, UiMapAssignmentEntry const*> const& uiMapAssignmentForMap : Trinity::Containers::MapEqualRange(uiMapAssignmentByUiMap, uiMap->ID)) { if (uiMapAssignmentForMap.second->MapID >= 0 && uiMapAssignmentForMap.second->Region[1].X - uiMapAssignmentForMap.second->Region[0].X > 0 && @@ -1288,7 +1319,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul if (!uiMapAssignment) continue; - for (auto uiMapAssignmentForMap : Trinity::Containers::MapEqualRange(uiMapAssignmentByUiMap, uiMap->ParentUiMapID)) + for (std::pair<int32 const, UiMapAssignmentEntry const*> const& uiMapAssignmentForMap : Trinity::Containers::MapEqualRange(uiMapAssignmentByUiMap, uiMap->ParentUiMapID)) { if (uiMapAssignmentForMap.second->MapID == uiMapAssignment->MapID && uiMapAssignmentForMap.second->Region[1].X - uiMapAssignmentForMap.second->Region[0].X > 0 && @@ -1510,9 +1541,7 @@ std::vector<uint8> const* DB2Manager::GetHotfixBlobData(uint32 tableHash, int32 uint32 DB2Manager::GetEmptyAnimStateID() const { - return 1484; - // TEMP: well... AnimationData.db2 in 8.3.0 has more rows than max hardcoded anim id in client - // return sAnimationDataStore.GetNumRows(); + return sAnimationDataStore.GetNumRows(); } void DB2Manager::InsertNewHotfix(uint32 tableHash, uint32 recordId) @@ -1642,50 +1671,41 @@ char const* DB2Manager::GetBroadcastTextValue(BroadcastTextEntry const* broadcas return broadcastText->Text[DEFAULT_LOCALE]; } -bool DB2Manager::HasCharacterFacialHairStyle(uint8 race, uint8 gender, uint8 variationId) const +char const* DB2Manager::GetClassName(uint8 class_, LocaleConstant locale /*= DEFAULT_LOCALE*/) { - return _characterFacialHairStyles.find(std::make_tuple(race, gender, variationId)) != _characterFacialHairStyles.end(); + ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); + if (!classEntry) + return ""; + + if (classEntry->Name[locale][0] != '\0') + return classEntry->Name[locale]; + + return classEntry->Name[DEFAULT_LOCALE]; } -bool DB2Manager::HasCharSections(uint8 race, uint8 gender, CharBaseSectionVariation variation) const +uint32 DB2Manager::GetPowerIndexByClass(Powers power, uint32 classId) const { - auto range = Trinity::Containers::MapEqualRange(_charSections, std::make_tuple(race, gender, variation)); - return range.begin() != range.end(); + return _powersByClass[classId][power]; } -CharSectionsEntry const* DB2Manager::GetCharSectionEntry(uint8 race, uint8 gender, CharBaseSectionVariation variation, uint8 variationIndex, uint8 colorIndex) const +std::vector<ChrCustomizationChoiceEntry const*> const* DB2Manager::GetCustomiztionChoices(uint32 chrCustomizationOptionId) const { - for (auto const& section : Trinity::Containers::MapEqualRange(_charSections, std::make_tuple(race, gender, variation))) - if (section.second->VariationIndex == variationIndex && section.second->ColorIndex == colorIndex) - return section.second; - - return nullptr; + return Trinity::Containers::MapGetValuePtr(_chrCustomizationChoicesByOption, chrCustomizationOptionId); } -CharStartOutfitEntry const* DB2Manager::GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender) const +std::vector<ChrCustomizationOptionEntry const*> const* DB2Manager::GetCustomiztionOptions(uint8 race, uint8 gender) const { - auto itr = _charStartOutfits.find(race | (class_ << 8) | (gender << 16)); - if (itr == _charStartOutfits.end()) - return nullptr; - - return itr->second; + return Trinity::Containers::MapGetValuePtr(_chrCustomizationOptionsByRaceAndGender, { race,gender }); } -char const* DB2Manager::GetClassName(uint8 class_, LocaleConstant locale /*= DEFAULT_LOCALE*/) +std::unordered_map<uint32, std::vector<uint32>> const* DB2Manager::GetRequiredCustomizationChoices(uint32 chrCustomizationReqId) const { - ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); - if (!classEntry) - return ""; - - if (classEntry->Name[locale][0] != '\0') - return classEntry->Name[locale]; - - return classEntry->Name[DEFAULT_LOCALE]; + return Trinity::Containers::MapGetValuePtr(_chrCustomizationRequiredChoices, chrCustomizationReqId); } -uint32 DB2Manager::GetPowerIndexByClass(Powers power, uint32 classId) const +ChrModelEntry const* DB2Manager::GetChrModel(uint8 race, uint8 gender) const { - return _powersByClass[classId][power]; + return Trinity::Containers::MapGetValuePtr(_chrModelsByRaceAndGender, { race, gender }); } char const* DB2Manager::GetChrRaceName(uint8 race, LocaleConstant locale /*= DEFAULT_LOCALE*/) @@ -1707,11 +1727,54 @@ ChrSpecializationEntry const* DB2Manager::GetChrSpecializationByIndex(uint32 cla ChrSpecializationEntry const* DB2Manager::GetDefaultChrSpecializationForClass(uint32 class_) const { - auto itr = _defaultChrSpecializationsByClass.find(class_); - if (itr != _defaultChrSpecializationsByClass.end()) - return itr->second; + return GetChrSpecializationByIndex(class_, INITIAL_SPECIALIZATION_INDEX); +} - return nullptr; +Optional<ContentTuningLevels> DB2Manager::GetContentTuningData(uint32 contentTuningId, uint32 /*replacementConditionMask*/, bool forItem /*= false*/) const +{ + ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(contentTuningId); + if (!contentTuning) + return {}; + + if (forItem && contentTuning->GetFlags().HasFlag(ContentTuningFlag::DisabledForItem)) + return {}; + + auto getLevelAdjustment = [](ContentTuningCalcType type) -> int32 + { + switch (type) + { + case ContentTuningCalcType::PlusOne: + return 1; + case ContentTuningCalcType::PlusMaxLevelForExpansion: + return GetMaxLevelForExpansion(sWorld->getIntConfig(CONFIG_EXPANSION)); + default: + break; + } + + return 0; + }; + + ContentTuningLevels levels; + levels.MinLevel = contentTuning->MinLevel + getLevelAdjustment(static_cast<ContentTuningCalcType>(contentTuning->MinLevelType)); + levels.MaxLevel = contentTuning->MaxLevel + getLevelAdjustment(static_cast<ContentTuningCalcType>(contentTuning->MaxLevelType)); + levels.MinLevelWithDelta = advstd::clamp<int32>(levels.MinLevel + contentTuning->TargetLevelDelta, 1, MAX_LEVEL); + levels.MaxLevelWithDelta = advstd::clamp<int32>(levels.MaxLevel + contentTuning->TargetLevelMaxDelta, 1, MAX_LEVEL); + + // clamp after calculating levels with delta (delta can bring "overflown" level back into correct range) + levels.MinLevel = advstd::clamp<int32>(levels.MinLevel, 1, MAX_LEVEL); + levels.MaxLevel = advstd::clamp<int32>(levels.MaxLevel, 1, MAX_LEVEL); + + if (contentTuning->TargetLevelMin) + levels.TargetLevelMin = contentTuning->TargetLevelMin; + else + levels.TargetLevelMin = levels.MinLevelWithDelta; + + if (contentTuning->TargetLevelMax) + levels.TargetLevelMax = contentTuning->TargetLevelMax; + else + levels.TargetLevelMax = levels.MaxLevelWithDelta; + + return levels; } char const* DB2Manager::GetCreatureFamilyPetName(uint32 petfamily, LocaleConstant locale) @@ -2609,6 +2672,11 @@ std::vector<RewardPackXItemEntry const*> const* DB2Manager::GetRewardPackItemsBy return nullptr; } +ShapeshiftFormModelData const* DB2Manager::GetShapeshiftFormModelData(uint8 race, uint8 gender, uint8 form) const +{ + return Trinity::Containers::MapGetValuePtr(_chrCustomizationChoicesForShapeshifts, { race, gender, form }); +} + std::vector<SkillLineEntry const*> const* DB2Manager::GetSkillLinesForParentSkill(uint32 parentSkillId) const { return Trinity::Containers::MapGetValuePtr(_skillLinesByParentSkillLine, parentSkillId); diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 665b56e178f..b0dfb56f9cc 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -20,6 +20,7 @@ #include "DB2Store.h" #include "DB2Structure.h" +#include <Optional.h> #include "SharedDefines.h" #include <map> #include <set> @@ -64,10 +65,13 @@ TC_GAME_API extern DB2Storage<BattlePetSpeciesStateEntry> sBattlePetSp TC_GAME_API extern DB2Storage<BattlemasterListEntry> sBattlemasterListStore; TC_GAME_API extern DB2Storage<BroadcastTextEntry> sBroadcastTextStore; TC_GAME_API extern DB2Storage<Cfg_RegionsEntry> sCfgRegionsStore; -TC_GAME_API extern DB2Storage<CharStartOutfitEntry> sCharStartOutfitStore; TC_GAME_API extern DB2Storage<CharTitlesEntry> sCharTitlesStore; +TC_GAME_API extern DB2Storage<CharacterLoadoutEntry> sCharacterLoadoutStore; +TC_GAME_API extern DB2Storage<CharacterLoadoutItemEntry> sCharacterLoadoutItemStore; TC_GAME_API extern DB2Storage<ChatChannelsEntry> sChatChannelsStore; TC_GAME_API extern DB2Storage<ChrClassesEntry> sChrClassesStore; +TC_GAME_API extern DB2Storage<ChrCustomizationReqEntry> sChrCustomizationReqStore; +TC_GAME_API extern DB2Storage<ChrCustomizationOptionEntry> sChrCustomizationOptionStore; TC_GAME_API extern DB2Storage<ChrRacesEntry> sChrRacesStore; TC_GAME_API extern DB2Storage<ChrSpecializationEntry> sChrSpecializationStore; TC_GAME_API extern DB2Storage<CinematicCameraEntry> sCinematicCameraStore; @@ -163,7 +167,6 @@ TC_GAME_API extern DB2Storage<QuestSortEntry> sQuestSortSt TC_GAME_API extern DB2Storage<QuestXPEntry> sQuestXPStore; TC_GAME_API extern DB2Storage<RandPropPointsEntry> sRandPropPointsStore; TC_GAME_API extern DB2Storage<RewardPackEntry> sRewardPackStore; -TC_GAME_API extern DB2Storage<ScalingStatDistributionEntry> sScalingStatDistributionStore; TC_GAME_API extern DB2Storage<ScenarioEntry> sScenarioStore; TC_GAME_API extern DB2Storage<ScenarioStepEntry> sScenarioStepStore; TC_GAME_API extern DB2Storage<SkillLineEntry> sSkillLineStore; @@ -220,6 +223,23 @@ TC_GAME_API extern DB2Storage<WorldEffectEntry> sWorldEffect TC_GAME_API extern DB2Storage<WorldMapOverlayEntry> sWorldMapOverlayStore; TC_GAME_API extern DB2Storage<WorldStateExpressionEntry> sWorldStateExpressionStore; +struct ContentTuningLevels +{ + int16 MinLevel = 0; + int16 MaxLevel = 0; + int16 MinLevelWithDelta = 0; + int16 MaxLevelWithDelta = 0; + int16 TargetLevelMin = 0; + int16 TargetLevelMax = 0; +}; + +struct ShapeshiftFormModelData +{ + uint32 OptionID; + std::vector<ChrCustomizationChoiceEntry const*> const* Choices; + std::vector<ChrCustomizationDisplayInfoEntry const*> Displays; +}; + struct TaxiPathBySourceAndDestination { TaxiPathBySourceAndDestination() : ID(0), price(0) { } @@ -298,15 +318,16 @@ public: std::vector<AzeritePowerSetMemberEntry const*> const* GetAzeritePowers(uint32 itemId) const; uint32 GetRequiredAzeriteLevelForAzeritePowerTier(uint32 azeriteUnlockSetId, ItemContext context, uint32 tier) const; static char const* GetBroadcastTextValue(BroadcastTextEntry const* broadcastText, LocaleConstant locale = DEFAULT_LOCALE, uint8 gender = GENDER_MALE, bool forceGender = false); - bool HasCharacterFacialHairStyle(uint8 race, uint8 gender, uint8 variationId) const; - bool HasCharSections(uint8 race, uint8 gender, CharBaseSectionVariation variation) const; - CharSectionsEntry const* GetCharSectionEntry(uint8 race, uint8 gender, CharBaseSectionVariation variation, uint8 variationIndex, uint8 color) const; - CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender) const; static char const* GetClassName(uint8 class_, LocaleConstant locale = DEFAULT_LOCALE); uint32 GetPowerIndexByClass(Powers power, uint32 classId) const; + std::vector<ChrCustomizationChoiceEntry const*> const* GetCustomiztionChoices(uint32 chrCustomizationOptionId) const; + std::vector<ChrCustomizationOptionEntry const*> const* GetCustomiztionOptions(uint8 race, uint8 gender) const; + std::unordered_map<uint32, std::vector<uint32>> const* GetRequiredCustomizationChoices(uint32 chrCustomizationReqId) const; + ChrModelEntry const* GetChrModel(uint8 race, uint8 gender) const; static char const* GetChrRaceName(uint8 race, LocaleConstant locale = DEFAULT_LOCALE); ChrSpecializationEntry const* GetChrSpecializationByIndex(uint32 class_, uint32 index) const; ChrSpecializationEntry const* GetDefaultChrSpecializationForClass(uint32 class_) const; + Optional<ContentTuningLevels> GetContentTuningData(uint32 contentTuningId, uint32 replacementConditionMask, bool forItem = false) const; static char const* GetCreatureFamilyPetName(uint32 petfamily, LocaleConstant locale); float GetCurveValueAt(uint32 curveId, float x) const; EmotesTextSoundEntry const* GetTextSoundEmoteFor(uint32 emote, uint8 race, uint8 gender, uint8 class_) const; @@ -354,6 +375,7 @@ public: uint32 GetQuestUniqueBitFlag(uint32 questId); std::vector<RewardPackXCurrencyTypeEntry const*> const* GetRewardPackCurrencyTypesByRewardID(uint32 rewardPackID) const; std::vector<RewardPackXItemEntry const*> const* GetRewardPackItemsByRewardID(uint32 rewardPackID) const; + ShapeshiftFormModelData const* GetShapeshiftFormModelData(uint8 race, uint8 gender, uint8 form) const; std::vector<SkillLineEntry const*> const* GetSkillLinesForParentSkill(uint32 parentSkillId) const; std::vector<SkillLineAbilityEntry const*> const* GetSkillLineAbilitiesBySkill(uint32 skillId) const; SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_); diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index b1b0b3f093f..36f315edb80 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -43,6 +43,7 @@ struct AchievementEntry int32 RewardItemID; uint32 CriteriaTree; int16 SharesCriteria; // referenced achievement (counting of all completed criterias) + int32 CovenantID; }; struct AnimationDataEntry @@ -83,7 +84,6 @@ struct AreaTableEntry uint16 UwAmbience; uint16 ZoneMusic; uint16 UwZoneMusic; - int8 ExplorationLevel; uint16 IntroSound; uint32 UwIntroSound; uint8 FactionGroupMask; @@ -93,6 +93,7 @@ struct AreaTableEntry uint8 WildBattlePetLevelMin; uint8 WildBattlePetLevelMax; uint8 WindSettingsID; + int32 ContentTuningID; int32 Flags[2]; uint16 LiquidTypeID[4]; @@ -407,7 +408,7 @@ struct BattlePetBreedQualityEntry struct BattlePetBreedStateEntry { uint32 ID; - uint8 BattlePetStateID; + int32 BattlePetStateID; uint16 Value; uint32 BattlePetBreedID; }; @@ -425,6 +426,7 @@ struct BattlePetSpeciesEntry int8 SourceTypeEnum; int32 CardUIModelSceneID; int32 LoadoutUIModelSceneID; + int32 CovenantID; }; struct BattlePetSpeciesStateEntry @@ -451,9 +453,9 @@ struct BattlemasterListEntry int8 GroupsAllowed; int8 MaxGroupSize; int16 HolidayWorldState; - int8 Flags; + int32 Flags; int32 IconFileDataID; - int16 RequiredPlayerConditionID; + int32 RequiredPlayerConditionID; int16 MapID[16]; }; @@ -464,7 +466,7 @@ struct BroadcastTextEntry LocalizedString Text; LocalizedString Text1; uint32 ID; - uint8 LanguageID; + int32 LanguageID; int32 ConditionID; uint16 EmotesID; uint8 Flags; @@ -484,65 +486,40 @@ struct Cfg_RegionsEntry uint32 ChallengeOrigin; }; -struct CharacterFacialHairStylesEntry +struct CharTitlesEntry { uint32 ID; - int32 Geoset[5]; - uint8 RaceID; - uint8 SexID; - uint8 VariationID; + LocalizedString Name; + LocalizedString Name1; + int16 MaskID; + int8 Flags; }; -struct CharBaseSectionEntry +struct CharacterLoadoutEntry { + Trinity::RaceMask<int64> RaceMask; uint32 ID; - uint8 LayoutResType; - uint8 VariationEnum; - uint8 ResolutionVariationEnum; -}; + int8 ChrClassID; + int8 Purpose; -struct CharSectionsEntry -{ - uint32 ID; - int8 RaceID; - int8 SexID; - int8 BaseSection; - int8 VariationIndex; - int8 ColorIndex; - int16 Flags; - int32 MaterialResourcesID[3]; + bool IsForNewCharacter() const { return Purpose == 9; } }; -#define MAX_OUTFIT_ITEMS 24 - -struct CharStartOutfitEntry +struct CharacterLoadoutItemEntry { uint32 ID; - uint8 ClassID; - uint8 SexID; - uint8 OutfitID; - uint32 PetDisplayID; // Pet Model ID for starting pet - uint8 PetFamilyID; // Pet Family Entry for starting pet - int32 ItemID[MAX_OUTFIT_ITEMS]; - uint32 RaceID; -}; - -struct CharTitlesEntry -{ - uint32 ID; - LocalizedString Name; - LocalizedString Name1; - int16 MaskID; - int8 Flags; + uint16 CharacterLoadoutID; + uint32 ItemID; }; struct ChatChannelsEntry { - uint32 ID; LocalizedString Name; LocalizedString Shortcut; + uint32 ID; int32 Flags; int8 FactionGroup; + int32 Ruleset; }; struct ChrClassesEntry @@ -552,14 +529,29 @@ struct ChrClassesEntry LocalizedString NameMale; LocalizedString NameFemale; char const* PetNameToken; + LocalizedString Description; + LocalizedString RoleInfoString; + LocalizedString DisabledString; + LocalizedString HyphenatedNameMale; + LocalizedString HyphenatedNameFemale; uint32 ID; uint32 CreateScreenFileDataID; uint32 SelectScreenFileDataID; uint32 IconFileDataID; uint32 LowResScreenFileDataID; - int32 StartingLevel; + uint32 Flags; uint32 SpellTextureBlobFileDataID; - uint16 Flags; + uint32 RolesMask; + uint32 ArmorTypeMask; + int32 CharStartKitUnknown901; + int32 MaleCharacterCreationVisualFallback; + int32 MaleCharacterCreationIdleVisualFallback; + int32 FemaleCharacterCreationVisualFallback; + int32 FemaleCharacterCreationIdleVisualFallback; + int32 CharacterCreationIdleGroundVisualFallback; + int32 CharacterCreationGroundVisualFallback; + int32 AlteredFormCharacterCreationIdleVisualFallback; + int32 CharacterCreationAnimLoopWaitTimeMsFallback; uint16 CinematicSequenceID; uint16 DefaultSpec; uint8 PrimaryStatPriority; @@ -568,6 +560,9 @@ struct ChrClassesEntry uint8 AttackPowerPerAgility; uint8 AttackPowerPerStrength; uint8 SpellClassSet; + uint8 ChatColorR; + uint8 ChatColorG; + uint8 ChatColorB; }; struct ChrClassesXPowerTypesEntry @@ -577,6 +572,103 @@ struct ChrClassesXPowerTypesEntry uint32 ClassID; }; +struct ChrCustomizationChoiceEntry +{ + LocalizedString Name; + uint32 ID; + int32 ChrCustomizationOptionID; + int32 ChrCustomizationReqID; + uint16 SortOrder; + int32 SwatchColor1; + int32 SwatchColor2; + uint16 UiOrderIndex; + int32 Flags; +}; + +struct ChrCustomizationDisplayInfoEntry +{ + uint32 ID; + int32 ShapeshiftFormID; + int32 DisplayID; + float BarberShopMinCameraDistance; + float BarberShopHeightOffset; +}; + +struct ChrCustomizationElementEntry +{ + uint32 ID; + int32 ChrCustomizationChoiceID; + int32 RelatedChrCustomizationChoiceID; + int32 ChrCustomizationGeosetID; + int32 ChrCustomizationSkinnedModelID; + int32 ChrCustomizationMaterialID; + int32 ChrCustomizationBoneSetID; + int32 ChrCustomizationCondModelID; + int32 ChrCustomizationDisplayInfoID; +}; + +struct ChrCustomizationOptionEntry +{ + LocalizedString Name; + uint32 ID; + uint16 SecondaryID; + int32 Flags; + int32 ChrModelID; + int32 SortIndex; + int32 ChrCustomizationCategoryID; + int32 OptionType; + float BarberShopCostModifier; + int32 ChrCustomizationID; + int32 ChrCustomizationReqID; + int32 UiOrderIndex; +}; + +struct ChrCustomizationReqEntry +{ + uint32 ID; + int32 Flags; + int32 ClassMask; + int32 AchievementID; + int32 OverrideArchive; // -1: allow any, otherwise must match OverrideArchive cvar + int32 ItemModifiedAppearanceID; + + EnumFlag<ChrCustomizationReqFlag> GetFlags() const { return static_cast<ChrCustomizationReqFlag>(Flags); } +}; + +struct ChrCustomizationReqChoiceEntry +{ + uint32 ID; + int32 ChrCustomizationChoiceID; + uint32 ChrCustomizationReqID; +}; + +struct ChrModelEntry +{ + float FaceCustomizationOffset[3]; + float CustomizeOffset[3]; + uint32 ID; + int32 Sex; + int32 DisplayID; + int32 CharComponentTextureLayoutID; + int32 Flags; + int32 SkeletonFileDataID; + int32 ModelFallbackChrModelID; + int32 TextureFallbackChrModelID; + int32 HelmVisFallbackChrModelID; + float CustomizeScale; + float CustomizeFacing; + float CameraDistanceOffset; + float BarberShopCameraOffsetScale; + float BarberShopCameraRotationOffset; +}; + +struct ChrRaceXChrModelEntry +{ + uint32 ID; + int32 ChrRacesID; + int32 ChrModelID; +}; + struct ChrRacesEntry { char const* ClientPrefix; @@ -585,37 +677,39 @@ struct ChrRacesEntry LocalizedString NameFemale; LocalizedString NameLowercase; LocalizedString NameFemaleLowercase; + LocalizedString NameS; + LocalizedString NameFemaleS; + LocalizedString NameLowercaseS; + LocalizedString NameFemaleLowercaseS; + LocalizedString RaceFantasyDescription; + LocalizedString NameL; + LocalizedString NameFemaleL; + LocalizedString NameLowercaseL; + LocalizedString NameFemaleLowercaseL; uint32 ID; int32 Flags; - uint32 MaleDisplayId; - uint32 FemaleDisplayId; - uint32 HighResMaleDisplayId; - uint32 HighResFemaleDisplayId; + int32 BaseLanguage; + int32 ResSicknessSpellID; + int32 SplashSoundID; int32 CreateScreenFileDataID; int32 SelectScreenFileDataID; - float MaleCustomizeOffset[3]; - float FemaleCustomizeOffset[3]; int32 LowResScreenFileDataID; uint32 AlteredFormStartVisualKitID[3]; uint32 AlteredFormFinishVisualKitID[3]; int32 HeritageArmorAchievementID; int32 StartingLevel; int32 UiDisplayOrder; - int32 FemaleSkeletonFileDataID; - int32 MaleSkeletonFileDataID; - int32 HelmVisFallbackRaceID; + int32 PlayableRaceBit; + int32 HelmetAnimScalingRaceID; int32 TransmogrifyDisabledSlotMask; + float AlteredFormCustomizeOffsetFallback[3]; + float AlteredFormCustomizeRotationFallback; int16 FactionID; int16 CinematicSequenceID; - int16 ResSicknessSpellID; - int16 SplashSoundID; - int8 BaseLanguage; int8 CreatureType; int8 Alliance; int8 RaceRelated; int8 UnalteredVisualRaceID; - int8 CharComponentTextureLayoutID; - int8 CharComponentTexLayoutHiResID; int8 DefaultClassID; int8 NeutralRaceID; int8 MaleModelFallbackRaceID; @@ -626,6 +720,7 @@ struct ChrRacesEntry int8 MaleTextureFallbackSex; int8 FemaleTextureFallbackRaceID; int8 FemaleTextureFallbackSex; + int8 UnalteredVisualCustomizationRaceID; }; #define MAX_MASTERY_SPELLS 2 @@ -671,10 +766,31 @@ struct CinematicSequencesEntry struct ContentTuningEntry { uint32 ID; - int32 MinLevel; - int32 MaxLevel; int32 Flags; int32 ExpansionID; + int32 MinLevel; + int32 MaxLevel; + int32 MinLevelType; + int32 MaxLevelType; + int32 TargetLevelDelta; + int32 TargetLevelMaxDelta; + int32 TargetLevelMin; + int32 TargetLevelMax; + int32 MinItemLevel; + + EnumFlag<ContentTuningFlag> GetFlags() const { return static_cast<ContentTuningFlag>(Flags); } + + int32 GetScalingFactionGroup() const + { + EnumFlag<ContentTuningFlag> flags = GetFlags(); + if (flags.HasFlag(ContentTuningFlag::Horde)) + return 5; + + if (flags.HasFlag(ContentTuningFlag::Alliance)) + return 3; + + return 0; + } }; struct ContentTuningXExpectedEntry @@ -742,15 +858,9 @@ struct CreatureDisplayInfoExtraEntry int8 DisplayRaceID; int8 DisplaySexID; int8 DisplayClassID; - int8 SkinID; - int8 FaceID; - int8 HairStyleID; - int8 HairColorID; - int8 FacialHairID; int8 Flags; int32 BakeMaterialResourcesID; int32 HDBakeMaterialResourcesID; - uint8 CustomDisplayOption[3]; }; struct CreatureFamilyEntry @@ -866,6 +976,7 @@ struct CriteriaEntry // CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31 // CRITERIA_TYPE_ENTER_AREA = 163 // CRITERIA_TYPE_LEAVE_AREA = 164 + // CRITERIA_TYPE_TRAVELED_TO_AREA = 225 int32 AreaID; // CRITERIA_TYPE_OWN_ITEM = 36 @@ -977,18 +1088,19 @@ struct CurrencyTypesEntry uint32 ID; LocalizedString Name; LocalizedString Description; - uint8 CategoryID; + int32 CategoryID; int32 InventoryIconFileID; uint32 SpellWeight; uint8 SpellCategory; uint32 MaxQty; uint32 MaxEarnablePerWeek; - uint32 Flags; int8 Quality; int32 FactionID; int32 ItemGroupSoundsID; - int32 ConvertToPlayerExperience; - int32 PlayerConditionID; + int32 XpQuestDifficulty; + int32 AwardConditionID; + int32 MaxQtyWorldStateID; + int32 Flags[2]; }; struct CurveEntry @@ -1002,6 +1114,7 @@ struct CurvePointEntry { uint32 ID; DBCPosition2D Pos; + DBCPosition2D PosPreSquish; uint16 CurveID; uint8 OrderIndex; }; @@ -1011,20 +1124,20 @@ struct DestructibleModelDataEntry uint32 ID; int8 State0ImpactEffectDoodadSet; uint8 State0AmbientDoodadSet; - uint16 State1Wmo; + int32 State1Wmo; int8 State1DestructionDoodadSet; int8 State1ImpactEffectDoodadSet; uint8 State1AmbientDoodadSet; - uint16 State2Wmo; + int32 State2Wmo; int8 State2DestructionDoodadSet; int8 State2ImpactEffectDoodadSet; uint8 State2AmbientDoodadSet; - uint16 State3Wmo; + int32 State3Wmo; uint8 State3InitDoodadSet; uint8 State3AmbientDoodadSet; uint8 EjectDirection; uint8 DoNotHighlight; - uint16 State0Wmo; + int32 State0Wmo; uint8 HealEffect; uint16 HealEffectSpeed; int8 State0NameSet; @@ -1056,7 +1169,7 @@ struct DungeonEncounterEntry LocalizedString Name; uint32 ID; int16 MapID; - int8 DifficultyID; + int32 DifficultyID; int32 OrderIndex; int32 CompleteWorldStateID; int8 Bit; @@ -1240,13 +1353,13 @@ struct GameObjectsEntry DBCPosition3D Pos; float Rot[4]; uint32 ID; - uint16 OwnerID; - uint16 DisplayID; + int32 OwnerID; + int32 DisplayID; float Scale; - uint8 TypeID; - uint8 PhaseUseFlags; - uint16 PhaseID; - uint16 PhaseGroupID; + int32 TypeID; + int32 PhaseUseFlags; + int32 PhaseID; + int32 PhaseGroupID; int32 PropValue[8]; }; @@ -1273,7 +1386,7 @@ struct GarrBuildingEntry uint8 BuildingType; int32 HordeGameObjectID; int32 AllianceGameObjectID; - uint8 GarrSiteID; + int32 GarrSiteID; uint8 UpgradeLevel; int32 BuildSeconds; uint16 CurrencyTypeID; @@ -1346,6 +1459,8 @@ struct GarrFollowerEntry uint8 ChrClassID; uint8 Flags; uint8 Gender; + int32 AutoCombatantID; + int32 CovenantID; }; struct GarrFollowerXAbilityEntry @@ -1411,7 +1526,6 @@ struct GemPropertiesEntry uint32 ID; uint16 EnchantId; int32 Type; - uint16 MinItemLevel; }; struct GlyphBindableSpellEntry @@ -1539,6 +1653,7 @@ struct ItemEntry int8 SoundOverrideSubclassID; int32 IconFileDataID; uint8 ItemGroupSoundsID; + int32 ModifiedCraftingReagentItemID; }; struct ItemAppearanceEntry @@ -1548,6 +1663,7 @@ struct ItemAppearanceEntry int32 ItemDisplayInfoID; int32 DefaultIconFileDataID; int32 UiOrder; + int32 PlayerConditionID; }; struct ItemArmorQualityEntry @@ -1582,7 +1698,7 @@ struct ItemBagFamilyEntry struct ItemBonusEntry { uint32 ID; - int32 Value[3]; + int32 Value[4]; uint16 ParentItemBonusListID; uint8 Type; uint8 OrderIndex; @@ -1592,11 +1708,12 @@ struct ItemBonusEntry //struct ItemBonusListGroupEntryEntry //{ // uint32 ID; +// int32 ItemBonusListGroupID; // int32 ItemBonusListID; // int32 ItemLevelSelectorID; // int32 OrderIndex; // int32 ItemExtendedCostID; -// int32 ItemBonusListGroupID; +// int32 PlayerConditionID; //}; struct ItemBonusListLevelDeltaEntry @@ -1853,6 +1970,9 @@ struct ItemSparseEntry float PriceRandomValue; int32 Flags[MAX_ITEM_PROTO_FLAGS]; int32 FactionRelated; + int32 ModifiedCraftingReagentItemID; + int32 ContentTuningID; + int32 PlayerLevelToItemLevelCurveID; uint16 ItemNameDescriptionID; uint16 RequiredTransmogHoliday; uint16 RequiredHoliday; @@ -1867,7 +1987,6 @@ struct ItemSparseEntry uint16 StartQuestID; uint16 PageID; uint16 ItemDelay; - uint16 ScalingStatDistributionID; uint16 MinFactionID; uint16 RequiredSkillRank; uint16 RequiredSkill; @@ -1932,8 +2051,6 @@ struct LFGDungeonsEntry uint32 ID; LocalizedString Name; LocalizedString Description; - uint8 MinLevel; - uint16 MaxLevel; uint8 TypeID; uint8 Subtype; int8 Faction; @@ -1947,9 +2064,6 @@ struct LFGDungeonsEntry uint8 GroupID; uint8 OrderIndex; uint32 RequiredPlayerConditionId; - uint8 TargetLevel; - uint8 TargetLevelMin; - uint16 TargetLevelMax; uint16 RandomID; uint16 ScenarioID; uint16 FinalEncounterID; @@ -1962,6 +2076,7 @@ struct LFGDungeonsEntry uint16 BonusReputationAmount; uint16 MentorItemLevel; uint8 MentorCharLevel; + int32 ContentTuningID; int32 Flags[2]; // Helpers @@ -2009,6 +2124,7 @@ struct LiquidTypeEntry struct LockEntry { uint32 ID; + int32 Flags; int32 Index[MAX_LOCK_CASE]; uint16 Skill[MAX_LOCK_CASE]; uint8 Type[MAX_LOCK_CASE]; @@ -2026,6 +2142,7 @@ struct MapEntry uint32 ID; char const* Directory; LocalizedString MapName; + char const* InternalName; LocalizedString MapDescription0; // Horde LocalizedString MapDescription1; // Alliance LocalizedString PvpShortDescription; @@ -2237,11 +2354,9 @@ struct PlayerConditionEntry Trinity::RaceMask<int64> RaceMask; LocalizedString FailureDescription; uint32 ID; - uint16 MinLevel; - uint16 MaxLevel; int32 ClassMask; uint32 SkillLogic; - uint8 LanguageID; + int32 LanguageID; uint8 MinLanguage; int32 MaxLanguage; uint16 MaxFactionID; @@ -2257,7 +2372,7 @@ struct PlayerConditionEntry uint8 ItemFlags; uint32 AuraSpellLogic; uint16 WorldStateExpressionID; - uint8 WeatherID; + int32 WeatherID; uint8 PartyStatus; uint8 LifetimeMaxPVPRank; uint32 AchievementLogic; @@ -2266,7 +2381,7 @@ struct PlayerConditionEntry uint32 AreaLogic; uint32 LfgLogic; uint32 CurrencyLogic; - uint16 QuestKillID; + int32 QuestKillID; uint32 QuestKillLogic; int8 MinExpansionLevel; int8 MaxExpansionLevel; @@ -2277,7 +2392,7 @@ struct PlayerConditionEntry uint8 PhaseUseFlags; uint16 PhaseID; uint32 PhaseGroupID; - uint8 Flags; + int32 Flags; int8 ChrSpecializationIndex; int8 ChrSpecializationRole; uint32 ModifierTreeID; @@ -2291,14 +2406,16 @@ struct PlayerConditionEntry int8 MinExpansionTier; uint8 MinPVPRank; uint8 MaxPVPRank; + int32 ContentTuningID; + int32 CovenantID; uint16 SkillID[4]; uint16 MinSkill[4]; uint16 MaxSkill[4]; uint32 MinFactionID[3]; uint8 MinReputation[3]; - uint16 PrevQuestID[4]; - uint16 CurrQuestID[4]; - uint16 CurrentCompletedQuestID[4]; + int32 PrevQuestID[4]; + int32 CurrQuestID[4]; + int32 CurrentCompletedQuestID[4]; int32 SpellID[4]; int32 ItemID[4]; uint32 ItemCount[4]; @@ -2480,14 +2597,6 @@ struct RewardPackXItemEntry uint32 RewardPackID; }; -struct ScalingStatDistributionEntry -{ - uint32 ID; - uint16 PlayerLevelToItemLevelCurveID; - int32 MinLevel; - int32 MaxLevel; -}; - struct ScenarioEntry { uint32 ID; @@ -2505,7 +2614,7 @@ struct ScenarioStepEntry LocalizedString Title; uint16 ScenarioID; uint32 Criteriatreeid; - uint16 RewardQuestID; + int32 RewardQuestID; int32 RelatedStep; // Bonus step can only be completed if scenario is in the step specified in this field uint16 Supersedes; // Used in conjunction with Proving Grounds scenarios, when sequencing steps (Not using step order?) uint8 OrderIndex; @@ -2576,7 +2685,7 @@ struct SkillLineAbilityEntry int8 AcquireMethod; int16 TrivialSkillLineRankHigh; int16 TrivialSkillLineRankLow; - int8 Flags; + int32 Flags; int8 NumSkillUps; int16 UniqueBit; int16 TradeSkillCategoryID; @@ -2664,7 +2773,6 @@ struct SpellCastTimesEntry { uint32 ID; int32 Base; - int16 PerLevel; int32 Minimum; }; @@ -2728,7 +2836,6 @@ struct SpellDurationEntry { uint32 ID; int32 Duration; - uint32 DurationPerLevel; int32 MaxDuration; }; @@ -2738,7 +2845,7 @@ struct SpellEffectEntry int16 EffectAura; int32 DifficultyID; int32 EffectIndex; - uint32 Effect; + int32 Effect; float EffectAmplitude; int32 EffectAttributes; int32 EffectAuraPeriod; @@ -2794,14 +2901,16 @@ struct SpellInterruptsEntry struct SpellItemEnchantmentEntry { - uint32 ID; LocalizedString Name; LocalizedString HordeName; + uint32 ID; uint32 EffectArg[MAX_ITEM_ENCHANTMENT_EFFECTS]; float EffectScalingPoints[MAX_ITEM_ENCHANTMENT_EFFECTS]; - uint32 TransmogPlayerConditionID; - uint32 TransmogCost; uint32 IconFileDataID; + int32 MinItemLevel; + int32 MaxItemLevel; + uint32 TransmogUseConditionID; + uint32 TransmogCost; int16 EffectPointsMin[MAX_ITEM_ENCHANTMENT_EFFECTS]; uint16 ItemVisual; uint16 Flags; @@ -2840,17 +2949,17 @@ struct SpellLevelsEntry { uint32 ID; uint8 DifficultyID; - int16 BaseLevel; int16 MaxLevel; - int16 SpellLevel; uint8 MaxPassiveAuraLevel; + int32 BaseLevel; + int32 SpellLevel; uint32 SpellID; }; struct SpellMiscEntry { uint32 ID; - int32 Attributes[14]; + int32 Attributes[15]; uint8 DifficultyID; uint16 CastingTimeIndex; uint16 DurationIndex; @@ -2862,6 +2971,9 @@ struct SpellMiscEntry int32 SpellIconFileDataID; int32 ActiveIconFileDataID; int32 ContentTuningID; + int32 ShowFutureSpellPlayerConditionID; + int32 SpellVisualScript; + int32 ActiveSpellVisualScript; uint32 SpellID; }; @@ -2908,7 +3020,7 @@ struct SpellProcsPerMinuteModEntry { uint32 ID; uint8 Type; - int16 Param; + int32 Param; float Coeff; uint32 SpellProcsPerMinuteID; }; @@ -3017,7 +3129,6 @@ struct SpellXSpellVisualEntry uint8 DifficultyID; uint32 SpellVisualID; float Probability; - uint8 Flags; uint8 Priority; int32 SpellIconFileID; int32 ActiveIconFileID; @@ -3123,6 +3234,15 @@ struct TransmogHolidayEntry int32 RequiredTransmogHoliday; }; +struct TransmogIllusionEntry +{ + uint32 ID; + int32 UnlockConditionID; + int32 TransmogCost; + int32 SpellItemEnchantmentID; + int32 Flags; +}; + struct TransmogSetEntry { LocalizedString Name; @@ -3179,14 +3299,15 @@ struct UiMapEntry int32 Flags; int32 System; int32 Type; - uint32 LevelRangeMin; - uint32 LevelRangeMax; int32 BountySetID; uint32 BountyDisplayLocation; int32 VisibilityPlayerConditionID; int8 HelpTextPosition; int32 BkgAtlasID; int32 AlternateUiMapGroup; + int32 ContentTuningID; + + EnumFlag<UiMapFlag> GetFlags() const { return EnumFlag<UiMapFlag>(static_cast<UiMapFlag>(Flags)); } }; struct UiMapAssignmentEntry @@ -3213,6 +3334,7 @@ struct UiMapLinkEntry int32 ChildUiMapID; int32 OverrideHighlightFileDataID; int32 OverrideHighlightAtlasID; + int32 Flags; }; struct UiMapXMapArtEntry @@ -3262,9 +3384,9 @@ struct VehicleEntry float FacingLimitRight; float FacingLimitLeft; float CameraYawOffset; - uint8 UiLocomotionType; uint16 VehicleUIIndicatorID; int32 MissileTargetingID; + uint16 VehiclePOITypeID; uint16 SeatID[8]; uint16 PowerDisplayID[3]; }; diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 21f89c7b301..f9b79bbe2b1 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -44,11 +44,11 @@ enum LevelLimit // Client expected level limitation, like as used in DBC item max levels for "until max player level" // use as default max player level, must be fit max level for used client // also see MAX_LEVEL and STRONG_MAX_LEVEL define - DEFAULT_MAX_LEVEL = 120, + DEFAULT_MAX_LEVEL = 60, // client supported max level for player/pets/etc. Avoid overflow or client stability affected. // also see GT_MAX_LEVEL define - MAX_LEVEL = 120, + MAX_LEVEL = 123, // Server side limitation. Base at used code requirements. // also see MAX_LEVEL and GT_MAX_LEVEL define @@ -188,7 +188,7 @@ enum AzeriteTierUnlockSetFlags AZERITE_TIER_UNLOCK_SET_FLAG_DEFAULT = 0x1 }; -#define BATTLE_PET_SPECIES_MAX_ID 2873 +#define BATTLE_PET_SPECIES_MAX_ID 3084 enum BattlemasterListFlags { @@ -212,6 +212,22 @@ enum ChrSpecializationFlag CHR_SPECIALIZATION_FLAG_RECOMMENDED = 0x40, }; +enum class ContentTuningCalcType : int32 +{ + Base = 0, + PlusOne = 1, + PlusMaxLevelForExpansion = 2 +}; + +enum class ContentTuningFlag : int32 +{ + DisabledForItem = 0x04, + Horde = 0x8, + Alliance = 0x10 +}; + +DEFINE_ENUM_FLAG(ContentTuningFlag); + enum class CorruptionEffectsFlag { None = 0, @@ -507,24 +523,50 @@ enum CriteriaAdditionalCondition //CRITERIA_ADDITIONAL_CONDITION_UNK_265 = 265, CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_LOWER = 266, CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_GREATER = 267, - //CRITERIA_ADDITIONAL_CONDITION_UNK_268 = 268, - //CRITERIA_ADDITIONAL_CONDITION_UNK_269 = 269, + CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_IN_RANGE_CT = 268, + CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_IN_RANGE_CT = 269, //CRITERIA_ADDITIONAL_CONDITION_UNK_270 = 270, //CRITERIA_ADDITIONAL_CONDITION_UNK_271 = 271, - //CRITERIA_ADDITIONAL_CONDITION_UNK_272 = 272, - //CRITERIA_ADDITIONAL_CONDITION_UNK_273 = 273, + CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_GREATER_CT = 272, // compare levels using content tuning + CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_GREATER_CT = 273, // compare levels using content tuning //CRITERIA_ADDITIONAL_CONDITION_UNK_274 = 274, //CRITERIA_ADDITIONAL_CONDITION_UNK_275 = 275, //CRITERIA_ADDITIONAL_CONDITION_UNK_276 = 276, - //CRITERIA_ADDITIONAL_CONDITION_UNK_277 = 277, + CRITERIA_ADDITIONAL_CONDITION_RAF_RECRUIT_IN_PARTY = 277, // NYI //CRITERIA_ADDITIONAL_CONDITION_UNK_278 = 278, //CRITERIA_ADDITIONAL_CONDITION_UNK_279 = 279, CRITERIA_ADDITIONAL_CONDITION_MAP_OR_COSMETIC_MAP = 280, //CRITERIA_ADDITIONAL_CONDITION_UNK_281 = 281, - CRITERIA_ADDITIONAL_CONDITION_HAS_ENTITLEMENT = 282, - CRITERIA_ADDITIONAL_CONDITION_HAS_QUEST_SESSION = 283, + CRITERIA_ADDITIONAL_CONDITION_HAS_ENTITLEMENT = 282, // NYI + CRITERIA_ADDITIONAL_CONDITION_HAS_QUEST_SESSION = 283, // NYI //CRITERIA_ADDITIONAL_CONDITION_UNK_284 = 284, //CRITERIA_ADDITIONAL_CONDITION_UNK_285 = 285, + //CRITERIA_ADDITIONAL_CONDITION_UNK_286 = 286, + //CRITERIA_ADDITIONAL_CONDITION_UNK_287 = 287, + CRITERIA_ADDITIONAL_CONDITION_COVENANT = 288, + //CRITERIA_ADDITIONAL_CONDITION_UNK_289 = 289, // related to pvp ranking + CRITERIA_ADDITIONAL_CONDITION_PERMANENT_ANIMA_DIVERSION_TALENT = 290, // NYI + CRITERIA_ADDITIONAL_CONDITION_SOULBIND = 291, + //CRITERIA_ADDITIONAL_CONDITION_UNK_292 = 292, + CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE_IN_GROUP = 293, + //CRITERIA_ADDITIONAL_CONDITION_UNK_294 = 294, + //CRITERIA_ADDITIONAL_CONDITION_UNK_295 = 295, + //CRITERIA_ADDITIONAL_CONDITION_UNK_296 = 296, + //CRITERIA_ADDITIONAL_CONDITION_UNK_297 = 297, + //CRITERIA_ADDITIONAL_CONDITION_UNK_298 = 298, + //CRITERIA_ADDITIONAL_CONDITION_UNK_299 = 299, + CRITERIA_ADDITIONAL_CONDITION_SOURCE_IN_SPECIFIC_CHROMIE_TIME = 300, + CRITERIA_ADDITIONAL_CONDITION_SOURCE_IN_ANY_CHROMIE_TIME = 301, + //CRITERIA_ADDITIONAL_CONDITION_UNK_302 = 302, + CRITERIA_ADDITIONAL_CONDITION_SOURCE_RUNEFORGE_LEGENDARY_KNOWN = 303, + //CRITERIA_ADDITIONAL_CONDITION_UNK_304 = 304, + //CRITERIA_ADDITIONAL_CONDITION_UNK_305 = 305, + //CRITERIA_ADDITIONAL_CONDITION_UNK_306 = 306, + CRITERIA_ADDITIONAL_CONDITION_SOULBIND_CONDUIT_RANK = 307, // NYI + CRITERIA_ADDITIONAL_CONDITION_SHAPESHIFT_FORM_CUSTOMIZATION_DISPLAY = 308, + CRITERIA_ADDITIONAL_CONDITION_SOULBIND_MIN_CONDUITS_AT_RANK = 309, // NYI + CRITERIA_ADDITIONAL_CONDITION_IS_RESTRICTED_ACCOUNT = 310, // NYI + CRITERIA_ADDITIONAL_CONDITION_SOURCE_FLYING = 311, }; enum CriteriaFlags @@ -763,10 +805,24 @@ enum CriteriaTypes : uint8 CRITERIA_TYPE_RELIC_TALENT_UNLOCKED = 211, CRITERIA_TYPE_REACH_ACCOUNT_HONOR_LEVEL = 213, CRITERIA_TYPE_HEART_OF_AZEROTH_ARTIFACT_POWER_EARNED= 214, - CRITERIA_TYPE_HEART_OF_AZEROTH_LEVEL_REACHED = 215 -}; - -#define CRITERIA_TYPE_TOTAL 219 + CRITERIA_TYPE_HEART_OF_AZEROTH_LEVEL_REACHED = 215, + CRITERIA_TYPE_MYTHIC_KEYSTONE_COMPLETED = 216, // NYI + // 217 - 0 criterias + CRITERIA_TYPE_COMPLETE_QUEST_ACCUMULATE = 218, + CRITERIA_TYPE_BOUGHT_ITEM_FROM_VENDOR = 219, + CRITERIA_TYPE_SOLD_ITEM_TO_VENDOR = 220, + // 221 - 0 criterias + // 222 - 0 criterias + // 223 - 0 criterias + // 224 - 0 criterias + CRITERIA_TYPE_TRAVELLED_TO_AREA = 225, + // 226 - 0 criterias + // 227 - 0 criterias + CRITERIA_TYPE_APPLY_CONDUIT = 228, + CRITERIA_TYPE_CONVERT_ITEMS_TO_CURRENCY = 229, +}; + +#define CRITERIA_TYPE_TOTAL 230 enum CriteriaTreeFlags : uint16 { @@ -790,50 +846,20 @@ enum CriteriaTreeOperator : uint8 CRITERIA_TREE_OPERATOR_SUM_CHILDREN_WEIGHT = 9 }; -enum class CharBaseSectionVariation : uint8 +enum class ChrCustomizationOptionFlag : int32 { - Skin = 0, - Face = 1, - FacialHair = 2, - Hair = 3, - Underwear = 4, - CustomDisplay1 = 5, - CustomDisplay2 = 6, - CustomDisplay3 = 7, - - Count + Disabled = 0x4, }; -enum CharSectionFlags -{ - SECTION_FLAG_PLAYER = 0x01, - SECTION_FLAG_DEATH_KNIGHT = 0x04, - SECTION_FLAG_DEMON_HUNTER = 0x20, - SECTION_FLAG_CONDITIONAL = 0x400 -}; +DEFINE_ENUM_FLAG(ChrCustomizationOptionFlag) -enum CharSectionType +enum class ChrCustomizationReqFlag : int32 { - SECTION_TYPE_SKIN_LOW_RES = 0, - SECTION_TYPE_FACE_LOW_RES = 1, - SECTION_TYPE_FACIAL_HAIR_LOW_RES = 2, - SECTION_TYPE_HAIR_LOW_RES = 3, - SECTION_TYPE_UNDERWEAR_LOW_RES = 4, - SECTION_TYPE_SKIN = 5, - SECTION_TYPE_FACE = 6, - SECTION_TYPE_FACIAL_HAIR = 7, - SECTION_TYPE_HAIR = 8, - SECTION_TYPE_UNDERWEAR = 9, - SECTION_TYPE_CUSTOM_DISPLAY_1_LOW_RES = 10, - SECTION_TYPE_CUSTOM_DISPLAY_1 = 11, - SECTION_TYPE_CUSTOM_DISPLAY_2_LOW_RES = 12, - SECTION_TYPE_CUSTOM_DISPLAY_2 = 13, - SECTION_TYPE_CUSTOM_DISPLAY_3_LOW_RES = 14, - SECTION_TYPE_CUSTOM_DISPLAY_3 = 15, - - SECTION_TYPE_MAX + HasRequirements = 0x1 }; +DEFINE_ENUM_FLAG(ChrCustomizationReqFlag) + enum Curves { CURVE_ID_ARTIFACT_RELIC_ITEM_LEVEL_BONUS = 1718, @@ -1013,7 +1039,7 @@ enum ItemBonusType ITEM_BONUS_ITEM_LEVEL = 1, ITEM_BONUS_STAT = 2, ITEM_BONUS_QUALITY = 3, - ITEM_BONUS_DESCRIPTION = 4, + ITEM_BONUS_NAME_SUBTITLE = 4, // Text under name ITEM_BONUS_SUFFIX = 5, ITEM_BONUS_SOCKET = 6, ITEM_BONUS_APPEARANCE = 7, @@ -1033,6 +1059,10 @@ enum ItemBonusType ITEM_BONUS_OVERRIDE_CAN_DISENCHANT = 21, ITEM_BONUS_OVERRIDE_CAN_SCRAP = 22, ITEM_BONUS_ITEM_EFFECT_ID = 23, + ITEM_BONUS_MODIFIED_CRAFTING_STAT = 25, + ITEM_BONUS_REQUIRED_LEVEL_CURVE = 27, + ITEM_BONUS_DESCRIPTION_TEXT = 30, // Item description + ITEM_BONUS_OVERRIDE_NAME = 31, // ItemNameDescription id }; enum class ItemContext : uint8 @@ -1292,7 +1322,7 @@ enum SpellShapeshiftFormFlags SHAPESHIFT_FORM_PREVENT_EMOTE_SOUNDS = 0x1000 }; -#define TaxiMaskSize 319 +#define TaxiMaskSize 336 typedef std::array<uint8, TaxiMaskSize> TaxiMask; enum TotemCategoryType @@ -1380,12 +1410,36 @@ enum TaxiPathNodeFlags TAXI_PATH_NODE_FLAG_STOP = 0x2 }; +enum class UiMapFlag : int32 +{ + None = 0, + NoHighlight = 0x00000001, + ShowOverlays = 0x00000002, + ShowTaxiNodes = 0x00000004, + GarrisonMap = 0x00000008, + FallbackToParentMap = 0x00000010, + NoHighlightTexture = 0x00000020, + ShowTaskObjectives = 0x00000040, + NoWorldPositions = 0x00000080, + HideArchaeologyDigs = 0x00000100, + Deprecated = 0x00000200, + HideIcons = 0x00000400, + HideVignettes = 0x00000800, + ForceAllOverlayExplored = 0x00001000, + FlightMapShowZoomOut = 0x00002000, + FlightMapAutoZoom = 0x00004000, + ForceOnNavbar = 0x00008000 +}; + +DEFINE_ENUM_FLAG(UiMapFlag) + enum UiMapSystem : int8 { UI_MAP_SYSTEM_WORLD = 0, UI_MAP_SYSTEM_TAXI = 1, UI_MAP_SYSTEM_ADVENTURE = 2, - MAX_UI_MAP_SYSTEM = 3 + UI_MAP_SYSTEM_MINIMAP = 3, + MAX_UI_MAP_SYSTEM }; enum UiMapType : int8 diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index de4ea7d41b2..54bc82c9be0 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -44,15 +44,14 @@ namespace lfg { -LFGDungeonData::LFGDungeonData() : id(0), name(), map(0), type(0), expansion(0), group(0), minlevel(0), - maxlevel(0), difficulty(DIFFICULTY_NONE), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f), - requiredItemLevel(0) +LFGDungeonData::LFGDungeonData() : id(0), name(), map(0), type(0), expansion(0), group(0), contentTuningId(0), + difficulty(DIFFICULTY_NONE), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f), requiredItemLevel(0) { } LFGDungeonData::LFGDungeonData(LFGDungeonsEntry const* dbc) : id(dbc->ID), name(dbc->Name[sWorld->GetDefaultDbcLocale()]), map(dbc->MapID), type(uint8(dbc->TypeID)), expansion(uint8(dbc->ExpansionLevel)), group(uint8(dbc->GroupID)), - minlevel(uint8(dbc->MinLevel)), maxlevel(uint8(dbc->MaxLevel)), difficulty(Difficulty(dbc->DifficultyID)), + contentTuningId(uint32(dbc->ContentTuningID)), difficulty(Difficulty(dbc->DifficultyID)), seasonal((dbc->Flags[0] & LFG_FLAG_SEASONAL) != 0), x(0.0f), y(0.0f), z(0.0f), o(0.0f), requiredItemLevel(0) { @@ -1651,48 +1650,55 @@ LfgLockMap LFGMgr::GetLockedDungeons(ObjectGuid guid) if (!dungeon) // should never happen - We provide a list from sLfgDungeonsStore continue; - uint32 lockStatus = 0; - if (denyJoin) - lockStatus = LFG_LOCKSTATUS_RAID_LOCKED; - else if (dungeon->expansion > expansion) - lockStatus = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; - else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player)) - lockStatus = LFG_LOCKSTATUS_NOT_IN_SEASON; - else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_LFG_MAP, dungeon->map, player)) - lockStatus = LFG_LOCKSTATUS_RAID_LOCKED; - else if (dungeon->difficulty > DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) - lockStatus = LFG_LOCKSTATUS_RAID_LOCKED; - else if (dungeon->minlevel > level) - lockStatus = LFG_LOCKSTATUS_TOO_LOW_LEVEL; - else if (dungeon->maxlevel < level) - lockStatus = LFG_LOCKSTATUS_TOO_HIGH_LEVEL; - else if (dungeon->seasonal && !IsSeasonActive(dungeon->id)) - lockStatus = LFG_LOCKSTATUS_NOT_IN_SEASON; - else if (dungeon->requiredItemLevel > player->GetAverageItemLevel()) - lockStatus = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; - else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty))) + uint32 lockStatus = [&]() -> uint32 { - if (ar->achievement && !player->HasAchieved(ar->achievement)) - lockStatus = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT; - else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A)) - lockStatus = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; - else if (player->GetTeam() == HORDE && ar->quest_H && !player->GetQuestRewardStatus(ar->quest_H)) - lockStatus = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; - else + if (denyJoin) + return LFG_LOCKSTATUS_RAID_LOCKED; + if (dungeon->expansion > expansion) + return LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; + if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player)) + return LFG_LOCKSTATUS_NOT_IN_SEASON; + if (DisableMgr::IsDisabledFor(DISABLE_TYPE_LFG_MAP, dungeon->map, player)) + return LFG_LOCKSTATUS_RAID_LOCKED; + if (dungeon->difficulty > DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) + return LFG_LOCKSTATUS_RAID_LOCKED; + if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(dungeon->contentTuningId, player->m_playerData->CtrOptions->ContentTuningConditionMask)) + { + if (levels->MinLevel > level) + return LFG_LOCKSTATUS_TOO_LOW_LEVEL; + if (levels->MaxLevel < level) + return LFG_LOCKSTATUS_TOO_HIGH_LEVEL; + } + if (dungeon->seasonal && !IsSeasonActive(dungeon->id)) + return LFG_LOCKSTATUS_NOT_IN_SEASON; + if (dungeon->requiredItemLevel > player->GetAverageItemLevel()) + return LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; + if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty))) + { + if (ar->achievement && !player->HasAchieved(ar->achievement)) + return LFG_LOCKSTATUS_MISSING_ACHIEVEMENT; + if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A)) + return LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; + if (player->GetTeam() == HORDE && ar->quest_H && !player->GetQuestRewardStatus(ar->quest_H)) + return LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; + + if (ar->item) { if (!player->HasItemCount(ar->item) && (!ar->item2 || !player->HasItemCount(ar->item2))) - lockStatus = LFG_LOCKSTATUS_MISSING_ITEM; + return LFG_LOCKSTATUS_MISSING_ITEM; } else if (ar->item2 && !player->HasItemCount(ar->item2)) - lockStatus = LFG_LOCKSTATUS_MISSING_ITEM; - } + return LFG_LOCKSTATUS_MISSING_ITEM; + } - /* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED) - lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; - lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; - lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; - */ + /* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED) + lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; + lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; + lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; + */ + return 0; + }(); if (lockStatus) lock[dungeon->Entry()] = LfgLockInfoData(lockStatus, dungeon->requiredItemLevel, player->GetAverageItemLevel()); @@ -2086,15 +2092,23 @@ uint32 LFGMgr::GetLFGDungeonEntry(uint32 id) return 0; } -LfgDungeonSet LFGMgr::GetRandomAndSeasonalDungeons(uint8 level, uint8 expansion) +LfgDungeonSet LFGMgr::GetRandomAndSeasonalDungeons(uint8 level, uint8 expansion, uint32 contentTuningReplacementConditionMask) { LfgDungeonSet randomDungeons; for (lfg::LFGDungeonContainer::const_iterator itr = LfgDungeonStore.begin(); itr != LfgDungeonStore.end(); ++itr) { lfg::LFGDungeonData const& dungeon = itr->second; - if ((dungeon.type == lfg::LFG_TYPE_RANDOM || (dungeon.seasonal && sLFGMgr->IsSeasonActive(dungeon.id))) - && dungeon.expansion <= expansion && dungeon.minlevel <= level && level <= dungeon.maxlevel) - randomDungeons.insert(dungeon.Entry()); + if (!(dungeon.type == lfg::LFG_TYPE_RANDOM || (dungeon.seasonal && sLFGMgr->IsSeasonActive(dungeon.id)))) + continue; + + if (dungeon.expansion > expansion) + continue; + + if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(dungeon.contentTuningId, contentTuningReplacementConditionMask)) + if (levels->MinLevel > level || level > levels->MaxLevel) + continue; + + randomDungeons.insert(dungeon.Entry()); } return randomDungeons; } diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 2c2063d0ff4..6174a1c1ec2 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -299,8 +299,7 @@ struct LFGDungeonData uint8 type; uint8 expansion; uint8 group; - uint8 minlevel; - uint8 maxlevel; + uint32 contentTuningId; Difficulty difficulty; bool seasonal; float x, y, z, o; @@ -398,7 +397,7 @@ class TC_GAME_API LFGMgr /// Gets the random dungeon reward corresponding to given dungeon and player level LfgReward const* GetRandomDungeonReward(uint32 dungeon, uint8 level); /// Returns all random and seasonal dungeons for given level and expansion - LfgDungeonSet GetRandomAndSeasonalDungeons(uint8 level, uint8 expansion); + LfgDungeonSet GetRandomAndSeasonalDungeons(uint8 level, uint8 expansion, uint32 contentTuningReplacementConditionMask); /// Teleport a player to/from selected dungeon void TeleportPlayer(Player* player, bool out, bool fromOpcode = false); /// Inits new proposal to boot a player diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp index d3f549cb30a..c5d50dc9ed6 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp @@ -117,7 +117,8 @@ bool AreaTrigger::Create(uint32 spellMiscId, Unit* caster, Unit* target, SpellIn SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::SpellID), spell->Id); SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::SpellForVisuals), spell->Id); - SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::SpellXSpellVisualID), spellVisual.SpellXSpellVisualID); + SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::SpellVisual).ModifyValue(&UF::SpellCastVisual::SpellXSpellVisualID), spellVisual.SpellXSpellVisualID); + SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::SpellVisual).ModifyValue(&UF::SpellCastVisual::ScriptVisualID), spellVisual.ScriptVisualID); SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::TimeToTargetScale), GetMiscTemplate()->TimeToTargetScale != 0 ? GetMiscTemplate()->TimeToTargetScale : *m_areaTriggerData->Duration); SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::BoundsRadius2D), GetTemplate()->MaxSearchRadius); SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::DecalPropertiesID), GetMiscTemplate()->DecalPropertiesId); diff --git a/src/server/game/Entities/Conversation/Conversation.cpp b/src/server/game/Entities/Conversation/Conversation.cpp index 32648507033..1e622b642f9 100644 --- a/src/server/game/Entities/Conversation/Conversation.cpp +++ b/src/server/game/Entities/Conversation/Conversation.cpp @@ -169,7 +169,7 @@ bool Conversation::Create(ObjectGuid::LowType lowGuid, uint32 conversationEntry, for (uint16 actorIndex : actorIndices) { UF::ConversationActor const* actor = actorIndex < m_conversationData->Actors.size() ? &m_conversationData->Actors[actorIndex] : nullptr; - if (!actor || (!actor->CreatureID && actor->ActorGUID.IsEmpty())) + if (!actor || (!actor->CreatureID && actor->ActorGUID.IsEmpty() && !actor->NoActorObject)) { TC_LOG_ERROR("entities.conversation", "Failed to create conversation (Id: %u) due to missing actor (Idx: %u).", conversationEntry, actorIndex); return false; diff --git a/src/server/game/Entities/Conversation/Conversation.h b/src/server/game/Entities/Conversation/Conversation.h index b17dbd9d393..821bfcaa30f 100644 --- a/src/server/game/Entities/Conversation/Conversation.h +++ b/src/server/game/Entities/Conversation/Conversation.h @@ -25,14 +25,6 @@ class Unit; class SpellInfo; -namespace UF -{ - inline bool operator==(ConversationLine const& left, ConversationLine const& right) - { - return left.ConversationLineID == right.ConversationLineID; - } -} - class TC_GAME_API Conversation : public WorldObject, public GridObject<Conversation> { public: diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 234be6705c3..299117ace95 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -102,9 +102,6 @@ void Corpse::SaveToDB() for (uint16 index = 0; index < EQUIPMENT_SLOT_END; ++index) items << m_corpseData->Items[index] << ' '; - uint32 bytes1 = (uint32(*m_corpseData->RaceID) << 8) | (uint32(*m_corpseData->Sex) << 16) | (uint32(*m_corpseData->SkinID) << 24); - uint32 bytes2 = (uint32(*m_corpseData->FaceID)) | (uint32(*m_corpseData->HairStyleID) << 8) | (uint32(*m_corpseData->HairColorID) << 16) | (uint32(*m_corpseData->FacialHairStyleID) << 24); - uint16 index = 0; CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CORPSE); stmt->setUInt64(index++, GetOwnerGUID().GetCounter()); // guid @@ -115,8 +112,8 @@ void Corpse::SaveToDB() stmt->setUInt16(index++, GetMapId()); // mapId stmt->setUInt32(index++, m_corpseData->DisplayID); // displayId stmt->setString(index++, items.str()); // itemCache - stmt->setUInt32(index++, bytes1); // bytes1 - stmt->setUInt32(index++, bytes2); // bytes2 + stmt->setUInt8 (index++, m_corpseData->RaceID); // race + stmt->setUInt8 (index++, m_corpseData->Sex); // gender stmt->setUInt8 (index++, m_corpseData->Flags); // flags stmt->setUInt8 (index++, m_corpseData->DynamicFlags); // dynFlags stmt->setUInt32(index++, uint32(m_time)); // time @@ -133,6 +130,16 @@ void Corpse::SaveToDB() trans->Append(stmt); } + for (UF::ChrCustomizationChoice customization : m_corpseData->Customizations) + { + index = 0; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CORPSE_CUSTOMIZATIONS); + stmt->setUInt64(index++, GetOwnerGUID().GetCounter()); // OwnerGuid + stmt->setUInt32(index++, customization.ChrCustomizationOptionID); + stmt->setUInt32(index++, customization.ChrCustomizationChoiceID); + trans->Append(stmt); + } + CharacterDatabase.CommitTransaction(trans); } @@ -150,12 +157,16 @@ void Corpse::DeleteFromDB(ObjectGuid const& ownerGuid, CharacterDatabaseTransact stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE_PHASES); stmt->setUInt64(0, ownerGuid.GetCounter()); CharacterDatabase.ExecuteOrAppend(trans, stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE_CUSTOMIZATIONS); + stmt->setUInt64(0, ownerGuid.GetCounter()); + CharacterDatabase.ExecuteOrAppend(trans, stmt); } bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ? + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, race, gender, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ? float posX = fields[0].GetFloat(); float posY = fields[1].GetFloat(); @@ -172,15 +183,8 @@ bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) for (uint32 index = 0; index < EQUIPMENT_SLOT_END; ++index) SetItem(index, atoul(items[index])); - uint32 bytes1 = fields[7].GetUInt32(); - uint32 bytes2 = fields[8].GetUInt32(); - SetRace((bytes1 >> 8) & 0xFF); - SetSex((bytes1 >> 16) & 0xFF); - SetSkin((bytes1 >> 24) & 0xFF); - SetFace(bytes2 & 0xFF); - SetHairStyle((bytes2 >> 8) & 0xFF); - SetHairColor((bytes2 >> 16) & 0xFF); - SetFacialHairStyle((bytes2 >> 24) & 0xFF); + SetRace(fields[7].GetUInt8()); + SetSex(fields[8].GetUInt8()); SetFlags(fields[9].GetUInt8()); SetCorpseDynamicFlags(CorpseDynFlags(fields[10].GetUInt8())); SetOwnerGUID(ObjectGuid::Create<HighGuid::Player>(fields[14].GetUInt64())); diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h index 5f3b234158a..fc3030ff2ac 100644 --- a/src/server/game/Entities/Corpse/Corpse.h +++ b/src/server/game/Entities/Corpse/Corpse.h @@ -21,6 +21,7 @@ #include "Object.h" #include "DatabaseEnvFwd.h" #include "GridDefines.h" +#include "IteratorPair.h" #include "Loot.h" enum CorpseType @@ -83,15 +84,21 @@ class TC_GAME_API Corpse : public WorldObject, public GridObject<Corpse> void SetDisplayId(uint32 displayId) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::DisplayID), displayId); } void SetRace(uint8 race) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::RaceID), race); } void SetSex(uint8 sex) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::Sex), sex); } - void SetSkin(uint8 skin) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::SkinID), skin); } - void SetFace(uint8 face) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::FaceID), face); } - void SetHairStyle(uint8 hairStyle) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::HairStyleID), hairStyle); } - void SetHairColor(uint8 hairColor) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::HairColorID), hairColor); } - void SetFacialHairStyle(uint8 facialHairStyle) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::FacialHairStyleID), facialHairStyle); } void SetFlags(uint32 flags) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::Flags), flags); } void SetFactionTemplate(int32 factionTemplate) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::FactionTemplate), factionTemplate); } void SetItem(uint32 slot, uint32 item) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::Items, slot), item); } - void SetCustomDisplayOption(uint32 slot, uint8 customDisplayOption) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::CustomDisplayOption, slot), customDisplayOption); } + + template<typename Iter> + void SetCustomizations(Trinity::IteratorPair<Iter> customizations) + { + ClearDynamicUpdateFieldValues(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::Customizations)); + for (auto&& customization : customizations) + { + UF::ChrCustomizationChoice& newChoice = AddDynamicUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::Customizations)); + newChoice.ChrCustomizationOptionID = customization.ChrCustomizationOptionID; + newChoice.ChrCustomizationChoiceID = customization.ChrCustomizationChoiceID; + } + } time_t const& GetGhostTime() const { return m_time; } void ResetGhostTime() { m_time = time(nullptr); } diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp index cb00b2f41d2..550ca700d90 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -100,7 +100,8 @@ bool DynamicObject::CreateDynamicObject(ObjectGuid::LowType guidlow, Unit* caste auto dynamicObjectData = m_values.ModifyValue(&DynamicObject::m_dynamicObjectData); SetUpdateFieldValue(dynamicObjectData.ModifyValue(&UF::DynamicObjectData::Caster), caster->GetGUID()); SetUpdateFieldValue(dynamicObjectData.ModifyValue(&UF::DynamicObjectData::Type), type); - SetUpdateFieldValue(dynamicObjectData.ModifyValue(&UF::DynamicObjectData::SpellXSpellVisualID), spellVisual.SpellXSpellVisualID); + SetUpdateFieldValue(dynamicObjectData.ModifyValue(&UF::DynamicObjectData::SpellVisual).ModifyValue(&UF::SpellCastVisual::SpellXSpellVisualID), spellVisual.SpellXSpellVisualID); + SetUpdateFieldValue(dynamicObjectData.ModifyValue(&UF::DynamicObjectData::SpellVisual).ModifyValue(&UF::SpellCastVisual::ScriptVisualID), spellVisual.ScriptVisualID); SetUpdateFieldValue(dynamicObjectData.ModifyValue(&UF::DynamicObjectData::SpellID), spell->Id); SetUpdateFieldValue(dynamicObjectData.ModifyValue(&UF::DynamicObjectData::Radius), radius); SetUpdateFieldValue(dynamicObjectData.ModifyValue(&UF::DynamicObjectData::CastTime), GameTime::GetGameTimeMS()); diff --git a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp index 7f56bc235bc..f81b2e1a6b2 100644 --- a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp +++ b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp @@ -76,7 +76,7 @@ void AzeriteItem::SaveToDB(CharacterDatabaseTransaction& trans) for (std::size_t j = 0; j < MAX_AZERITE_ESSENCE_SLOT; ++j) stmt->setUInt32(5 + specIndex * 5 + j, m_azeriteItemData->SelectedEssences[specIndex].AzeriteEssenceID[j]); } - for (; specIndex < MAX_SPECIALIZATIONS; ++specIndex) + for (; specIndex < 4; ++specIndex) { stmt->setUInt32(4 + specIndex * 5, 0); for (std::size_t j = 0; j < MAX_AZERITE_ESSENCE_SLOT; ++j) diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 9accf6abf42..aa250eb5dd2 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -265,43 +265,28 @@ ItemModifier const AppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS] = ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1, ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_2, ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_3, - ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4 + ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4, + ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_5 }; -static uint64 constexpr AppearanceModifierMaskSpecSpecific = - (UI64LIT(1) << ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1) | - (UI64LIT(1) << ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_2) | - (UI64LIT(1) << ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_3) | - (UI64LIT(1) << ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4); - ItemModifier const IllusionModifierSlotBySpec[MAX_SPECIALIZATIONS] = { ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1, ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2, ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3, - ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4 + ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4, + ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_5 }; -static uint64 constexpr IllusionModifierMaskSpecSpecific = - (UI64LIT(1) << ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1) | - (UI64LIT(1) << ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2) | - (UI64LIT(1) << ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3) | - (UI64LIT(1) << ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4); - ItemModifier const SecondaryAppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS] = { ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_1, ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_2, ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_3, - ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_4 + ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_4, + ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_5 }; -static uint64 constexpr SecondaryAppearanceModifierMaskSpecSpecific = - (UI64LIT(1) << ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_1) | - (UI64LIT(1) << ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_2) | - (UI64LIT(1) << ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_3) | - (UI64LIT(1) << ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_4); - void ItemAdditionalLoadInfo::Init(std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo>* loadInfo, PreparedQueryResult artifactResult, PreparedQueryResult azeriteItemResult, PreparedQueryResult azeriteItemMilestonePowersResult, PreparedQueryResult azeriteItemUnlockedEssencesResult, @@ -363,7 +348,7 @@ void ItemAdditionalLoadInfo::Init(std::unordered_map<ObjectGuid::LowType, ItemAd info.AzeriteItem->Xp = fields[1].GetUInt64(); info.AzeriteItem->Level = fields[2].GetUInt32(); info.AzeriteItem->KnowledgeLevel = fields[3].GetUInt32(); - for (std::size_t i = 0; i < MAX_SPECIALIZATIONS; ++i) + for (std::size_t i = 0; i < info.AzeriteItem->SelectedAzeriteEssences.size(); ++i) { uint32 specializationId = fields[4 + i * 4].GetUInt32(); if (!sChrSpecializationStore.LookupEntry(specializationId)) @@ -1411,8 +1396,8 @@ void Item::SetGem(uint16 slot, ItemDynamicFieldGems const* gem, uint32 gemScalin gemBonus.AddBonusList(bonusListId); uint32 gemBaseItemLevel = gemTemplate->GetBaseItemLevel(); - if (ScalingStatDistributionEntry const* ssd = sScalingStatDistributionStore.LookupEntry(gemBonus.ScalingStatDistribution)) - if (uint32 scaledIlvl = uint32(sDB2Manager.GetCurveValueAt(ssd->PlayerLevelToItemLevelCurveID, gemScalingLevel))) + if (gemBonus.PlayerLevelToItemLevelCurveId) + if (uint32 scaledIlvl = uint32(sDB2Manager.GetCurveValueAt(gemBonus.PlayerLevelToItemLevelCurveId, gemScalingLevel))) gemBaseItemLevel = scaledIlvl; _bonusData.GemRelicType[slot] = gemBonus.RelicType; @@ -1848,7 +1833,7 @@ bool Item::HasStats() const ItemTemplate const* proto = GetTemplate(); Player const* owner = GetOwner(); for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) - if ((owner ? GetItemStatValue(i, owner) : proto->GetItemStatAllocation(i)) != 0) + if ((owner ? GetItemStatValue(i, owner) : proto->GetStatPercentEditor(i)) != 0) return true; return false; @@ -1857,7 +1842,7 @@ bool Item::HasStats() const bool Item::HasStats(WorldPackets::Item::ItemInstance const& /*itemInstance*/, BonusData const* bonus) { for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) - if (bonus->ItemStatAllocation[i] != 0) + if (bonus->StatPercentEditor[i] != 0) return true; return false; @@ -2179,19 +2164,14 @@ uint32 Item::GetItemLevel(ItemTemplate const* itemTemplate, BonusData const& bon if (AzeriteLevelInfoEntry const* azeriteLevelInfo = sAzeriteLevelInfoStore.LookupEntry(azeriteLevel)) itemLevel = azeriteLevelInfo->ItemLevel; - if (ScalingStatDistributionEntry const* ssd = sScalingStatDistributionStore.LookupEntry(bonusData.ScalingStatDistribution)) + if (bonusData.PlayerLevelToItemLevelCurveId) { if (fixedLevel) level = fixedLevel; - else - level = std::min(std::max(int32(level), ssd->MinLevel), ssd->MaxLevel); - - if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(bonusData.ContentTuningId)) - if ((contentTuning->Flags & 2 || contentTuning->MinLevel || contentTuning->MaxLevel) && !(contentTuning->Flags & 4)) - level = std::min(std::max(int32(level), contentTuning->MinLevel), contentTuning->MaxLevel); + else if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(bonusData.ContentTuningId, 0, true)) + level = std::min(std::max(int16(level), levels->MinLevel), levels->MaxLevel); - if (uint32 heirloomIlvl = uint32(sDB2Manager.GetCurveValueAt(ssd->PlayerLevelToItemLevelCurveID, level))) - itemLevel = heirloomIlvl; + itemLevel = uint32(sDB2Manager.GetCurveValueAt(bonusData.PlayerLevelToItemLevelCurveId, level)); } itemLevel += bonusData.ItemLevelBonus; @@ -2223,7 +2203,7 @@ int32 Item::GetItemStatValue(uint32 index, Player const* owner) const { case ITEM_MOD_CORRUPTION: case ITEM_MOD_CORRUPTION_RESISTANCE: - return _bonusData.ItemStatAllocation[index]; + return _bonusData.StatPercentEditor[index]; default: break; } @@ -2231,7 +2211,7 @@ int32 Item::GetItemStatValue(uint32 index, Player const* owner) const uint32 itemLevel = GetItemLevel(owner); if (uint32 randomPropPoints = GetRandomPropertyPoints(itemLevel, GetQuality(), GetTemplate()->GetInventoryType(), GetTemplate()->GetSubClass())) { - float statValue = float(_bonusData.ItemStatAllocation[index] * randomPropPoints) * 0.0001f; + float statValue = float(_bonusData.StatPercentEditor[index] * randomPropPoints) * 0.0001f; if (GtItemSocketCostPerLevelEntry const* gtCost = sItemSocketCostPerLevelGameTable.GetRow(itemLevel)) statValue -= float(int32(_bonusData.ItemStatSocketCostMultiplier[index] * gtCost->SocketCost)); @@ -2288,11 +2268,11 @@ ItemDisenchantLootEntry const* Item::GetDisenchantLoot(ItemTemplate const* itemT uint32 Item::GetDisplayId(Player const* owner) const { - ItemModifier transmogModifier = ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS; - if (*m_itemData->ModifiersMask & AppearanceModifierMaskSpecSpecific) - transmogModifier = AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]; + uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]); + if (!itemModifiedAppearanceId) + itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS); - if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(GetModifier(transmogModifier))) + if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId)) if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(transmog->ItemAppearanceID)) return itemAppearance->ItemDisplayInfoID; @@ -2306,51 +2286,56 @@ ItemModifiedAppearanceEntry const* Item::GetItemModifiedAppearance() const uint32 Item::GetModifier(ItemModifier modifier) const { - if (!(*m_itemData->ModifiersMask & (1 << modifier))) - return 0; + int32 modifierIndex = m_itemData->Modifiers->Values.FindIndexIf([modifier](UF::ItemMod mod) + { + return mod.Type == modifier; + }); - uint32 valueIndex = 0; - uint32 mask = m_itemData->ModifiersMask; - for (uint32 i = 0; i < modifier; ++i) - if (mask & (1 << i)) - ++valueIndex; + if (modifierIndex != -1) + return m_itemData->Modifiers->Values[modifierIndex].Value; - return m_itemData->Modifiers[valueIndex]; + return 0; } void Item::SetModifier(ItemModifier modifier, uint32 value) { - uint32 valueIndex = 0; - uint32 mask = m_itemData->ModifiersMask; - for (uint32 i = 0; i < modifier; ++i) - if (mask & (1 << i)) - ++valueIndex; + int32 modifierIndex = m_itemData->Modifiers->Values.FindIndexIf([modifier](UF::ItemMod mod) + { + return mod.Type == modifier; + }); if (value) { - if (mask & (1 << modifier)) - return; + if (modifierIndex == -1) + { + UF::ItemMod& mod = AddDynamicUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData) + .ModifyValue(&UF::ItemData::Modifiers).ModifyValue(&UF::ItemModList::Values)); - SetUpdateFieldFlagValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::ModifiersMask), 1 << modifier); - InsertDynamicUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Modifiers), valueIndex) = value; + mod.Value = value; + mod.Type = modifier; + } + else + SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData) + .ModifyValue(&UF::ItemData::Modifiers) + .ModifyValue(&UF::ItemModList::Values, modifierIndex) + .ModifyValue(&UF::ItemMod::Value), value); } else { - if (!(mask & (1 << modifier))) + if (modifierIndex == -1) return; - RemoveUpdateFieldFlagValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::ModifiersMask), 1 << modifier); - RemoveDynamicUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Modifiers), valueIndex); + RemoveDynamicUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Modifiers).ModifyValue(&UF::ItemModList::Values), modifierIndex); } } uint32 Item::GetVisibleEntry(Player const* owner) const { - ItemModifier transmogModifier = ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS; - if (*m_itemData->ModifiersMask & AppearanceModifierMaskSpecSpecific) - transmogModifier = AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]; + uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]); + if (!itemModifiedAppearanceId) + itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS); - if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(GetModifier(transmogModifier))) + if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId)) return transmog->ItemID; return GetEntry(); @@ -2358,11 +2343,11 @@ uint32 Item::GetVisibleEntry(Player const* owner) const uint16 Item::GetVisibleAppearanceModId(Player const* owner) const { - ItemModifier transmogModifier = ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS; - if (*m_itemData->ModifiersMask & AppearanceModifierMaskSpecSpecific) - transmogModifier = AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]; + uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]); + if (!itemModifiedAppearanceId) + itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS); - if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(GetModifier(transmogModifier))) + if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId)) return transmog->ItemAppearanceModifierID; return uint16(GetAppearanceModId()); @@ -2370,14 +2355,14 @@ uint16 Item::GetVisibleAppearanceModId(Player const* owner) const uint32 Item::GetVisibleEnchantmentId(Player const* owner) const { - ItemModifier illusionModifier = ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS; - if (*m_itemData->ModifiersMask & IllusionModifierMaskSpecSpecific) - illusionModifier = IllusionModifierSlotBySpec[owner->GetActiveTalentGroup()]; + uint32 enchantmentId = GetModifier(IllusionModifierSlotBySpec[owner->GetActiveTalentGroup()]); + if (!enchantmentId) + enchantmentId = GetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS); - if (uint32 enchantIllusion = GetModifier(illusionModifier)) - return enchantIllusion; + if (!enchantmentId) + enchantmentId = GetEnchantmentId(PERM_ENCHANTMENT_SLOT); - return GetEnchantmentId(PERM_ENCHANTMENT_SLOT); + return enchantmentId; } uint16 Item::GetVisibleItemVisual(Player const* owner) const @@ -2625,13 +2610,10 @@ void Item::SetFixedLevel(uint8 level) if (!_bonusData.HasFixedLevel || GetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL)) return; - if (ScalingStatDistributionEntry const* ssd = sScalingStatDistributionStore.LookupEntry(_bonusData.ScalingStatDistribution)) + if (_bonusData.PlayerLevelToItemLevelCurveId) { - level = std::min(std::max(int32(level), ssd->MinLevel), ssd->MaxLevel); - - if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(_bonusData.ContentTuningId)) - if ((contentTuning->Flags & 2 || contentTuning->MinLevel || contentTuning->MaxLevel) && !(contentTuning->Flags & 4)) - level = std::min(std::max(int32(level), contentTuning->MinLevel), contentTuning->MaxLevel); + if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(_bonusData.ContentTuningId, 0, true)) + level = std::min(std::max(int16(level), levels->MinLevel), levels->MaxLevel); SetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL, level); } @@ -2639,12 +2621,14 @@ void Item::SetFixedLevel(uint8 level) int32 Item::GetRequiredLevel() const { + int32 fixedLevel = GetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL); + if (_bonusData.RequiredLevelCurve) + return sDB2Manager.GetCurveValueAt(_bonusData.RequiredLevelCurve, fixedLevel); if (_bonusData.RequiredLevelOverride) return _bonusData.RequiredLevelOverride; - else if (_bonusData.HasFixedLevel) - return GetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL); - else - return _bonusData.RequiredLevel; + if (_bonusData.HasFixedLevel && _bonusData.PlayerLevelToItemLevelCurveId) + return fixedLevel; + return _bonusData.RequiredLevel; } void BonusData::Initialize(ItemTemplate const* proto) @@ -2653,13 +2637,13 @@ void BonusData::Initialize(ItemTemplate const* proto) ItemLevelBonus = 0; RequiredLevel = proto->GetBaseRequiredLevel(); for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) - ItemStatType[i] = proto->GetItemStatType(i); + ItemStatType[i] = proto->GetStatModifierBonusStat(i); for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) - ItemStatAllocation[i] = proto->GetItemStatAllocation(i); + StatPercentEditor[i] = proto->GetStatPercentEditor(i); for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) - ItemStatSocketCostMultiplier[i] = proto->GetItemStatSocketCostMultiplier(i); + ItemStatSocketCostMultiplier[i] = proto->GetStatPercentageOfSocket(i); for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i) { @@ -2673,8 +2657,8 @@ void BonusData::Initialize(ItemTemplate const* proto) AppearanceModID = 0; RepairCostMultiplier = 1.0f; - ScalingStatDistribution = proto->GetScalingStatDistribution(); - ContentTuningId = 0; + ContentTuningId = proto->GetScalingStatContentTuning(); + PlayerLevelToItemLevelCurveId = proto->GetPlayerLevelToItemLevelCurveId(); RelicType = -1; HasFixedLevel = false; RequiredLevelOverride = 0; @@ -2683,6 +2667,7 @@ void BonusData::Initialize(ItemTemplate const* proto) AzeriteTierUnlockSetId = azeriteEmpoweredItem->AzeriteTierUnlockSetID; Suffix = 0; + RequiredLevelCurve = 0; EffectCount = 0; for (ItemEffectEntry const* itemEffect : proto->Effects) @@ -2698,6 +2683,7 @@ void BonusData::Initialize(ItemTemplate const* proto) _state.AppearanceModPriority = std::numeric_limits<int32>::max(); _state.ScalingStatDistributionPriority = std::numeric_limits<int32>::max(); _state.AzeriteTierUnlockSetPriority = std::numeric_limits<int32>::max(); + _state.RequiredLevelCurvePriority = std::numeric_limits<int32>::max(); _state.HasQualityBonus = false; } @@ -2721,7 +2707,7 @@ void BonusData::AddBonusList(uint32 bonusListId) AddBonus(bonus->Type, bonus->Value); } -void BonusData::AddBonus(uint32 type, int32 const (&values)[3]) +void BonusData::AddBonus(uint32 type, int32 const (&values)[4]) { switch (type) { @@ -2738,7 +2724,7 @@ void BonusData::AddBonus(uint32 type, int32 const (&values)[3]) if (statIndex < MAX_ITEM_PROTO_STATS) { ItemStatType[statIndex] = values[0]; - ItemStatAllocation[statIndex] += values[1]; + StatPercentEditor[statIndex] += values[1]; } break; } @@ -2788,8 +2774,8 @@ void BonusData::AddBonus(uint32 type, int32 const (&values)[3]) case ITEM_BONUS_SCALING_STAT_DISTRIBUTION_FIXED: if (values[1] < _state.ScalingStatDistributionPriority) { - ScalingStatDistribution = static_cast<uint32>(values[0]); ContentTuningId = static_cast<uint32>(values[2]); + PlayerLevelToItemLevelCurveId = static_cast<uint32>(values[3]); _state.ScalingStatDistributionPriority = values[1]; HasFixedLevel = type == ITEM_BONUS_SCALING_STAT_DISTRIBUTION_FIXED; } @@ -2820,5 +2806,14 @@ void BonusData::AddBonus(uint32 type, int32 const (&values)[3]) if (ItemEffectEntry const* itemEffect = sItemEffectStore.LookupEntry(values[0])) Effects[EffectCount++] = itemEffect; break; + case ITEM_BONUS_REQUIRED_LEVEL_CURVE: + if (values[2] < _state.RequiredLevelCurvePriority) + { + RequiredLevelCurve = values[0]; + _state.RequiredLevelCurvePriority = values[2]; + if (values[1]) + ContentTuningId = static_cast<uint32>(values[1]); + } + break; } } diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 53744f5b1b5..4d2e84cabda 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -71,14 +71,14 @@ struct BonusData int32 ItemLevelBonus; int32 RequiredLevel; int32 ItemStatType[MAX_ITEM_PROTO_STATS]; - int32 ItemStatAllocation[MAX_ITEM_PROTO_STATS]; + int32 StatPercentEditor[MAX_ITEM_PROTO_STATS]; float ItemStatSocketCostMultiplier[MAX_ITEM_PROTO_STATS]; uint32 SocketColor[MAX_ITEM_PROTO_SOCKETS]; ItemBondingType Bonding; uint32 AppearanceModID; float RepairCostMultiplier; - uint32 ScalingStatDistribution; uint32 ContentTuningId; + uint32 PlayerLevelToItemLevelCurveId; uint32 DisenchantLootId; uint32 GemItemLevelBonus[MAX_ITEM_PROTO_SOCKETS]; int32 GemRelicType[MAX_ITEM_PROTO_SOCKETS]; @@ -87,6 +87,7 @@ struct BonusData int32 RequiredLevelOverride; int32 AzeriteTierUnlockSetId; uint32 Suffix; + int32 RequiredLevelCurve; std::array<ItemEffectEntry const*, 13> Effects; std::size_t EffectCount; bool CanDisenchant; @@ -96,7 +97,7 @@ struct BonusData void Initialize(ItemTemplate const* proto); void Initialize(WorldPackets::Item::ItemInstance const& itemInstance); void AddBonusList(uint32 bonusListId); - void AddBonus(uint32 type, int32 const (&values)[3]); + void AddBonus(uint32 type, int32 const (&values)[4]); private: struct @@ -105,6 +106,7 @@ private: int32 AppearanceModPriority; int32 ScalingStatDistributionPriority; int32 AzeriteTierUnlockSetPriority; + int32 RequiredLevelCurvePriority; bool HasQualityBonus; } _state; }; @@ -137,7 +139,7 @@ struct AzeriteItemData uint32 KnowledgeLevel; std::vector<uint32> AzeriteItemMilestonePowers; std::vector<AzeriteEssencePowerEntry const*> UnlockedAzeriteEssences; - std::array<AzeriteItemSelectedEssencesData, MAX_SPECIALIZATIONS> SelectedAzeriteEssences = { }; + std::array<AzeriteItemSelectedEssencesData, 4> SelectedAzeriteEssences = { }; }; struct AzeriteEmpoweredItemData @@ -335,7 +337,7 @@ class TC_GAME_API Item : public Object uint32 GetDisplayId(Player const* owner) const; ItemModifiedAppearanceEntry const* GetItemModifiedAppearance() const; float GetRepairCostMultiplier() const { return _bonusData.RepairCostMultiplier; } - uint32 GetScalingStatDistribution() const { return _bonusData.ScalingStatDistribution; } + uint32 GetScalingContentTuningId() const { return _bonusData.ContentTuningId; } ItemDisenchantLootEntry const* GetDisenchantLoot(Player const* owner) const; static ItemDisenchantLootEntry const* GetDisenchantLoot(ItemTemplate const* itemTemplate, uint32 quality, uint32 itemLevel); void SetFixedLevel(uint8 level); diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index 86ddaea9e41..990ee108dc6 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -46,8 +46,8 @@ enum ItemModType ITEM_MOD_CRIT_SPELL_RATING = 21, ITEM_MOD_CORRUPTION = 22, ITEM_MOD_CORRUPTION_RESISTANCE = 23, - ITEM_MOD_HIT_TAKEN_SPELL_RATING = 24, - ITEM_MOD_CRIT_TAKEN_MELEE_RATING = 25, + ITEM_MOD_MODIFIED_CRAFTING_STAT_1 = 24, + ITEM_MOD_MODIFIED_CRAFTING_STAT_2 = 25, ITEM_MOD_CRIT_TAKEN_RANGED_RATING = 26, ITEM_MOD_CRIT_TAKEN_SPELL_RATING = 27, ITEM_MOD_HASTE_MELEE_RATING = 28, @@ -757,10 +757,11 @@ struct TC_GAME_API ItemTemplate uint32 GetRequiredReputationRank() const { return ExtendedData->MinReputation; } uint32 GetMaxCount() const { return ExtendedData->MaxCount; } uint32 GetContainerSlots() const { return ExtendedData->ContainerSlots; } - int32 GetItemStatType(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->StatModifierBonusStat[index]; } - int32 GetItemStatAllocation(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->StatPercentEditor[index]; } - float GetItemStatSocketCostMultiplier(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->StatPercentageOfSocket[index]; } - uint32 GetScalingStatDistribution() const { return ExtendedData->ScalingStatDistributionID; } + int32 GetStatModifierBonusStat(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->StatModifierBonusStat[index]; } + int32 GetStatPercentEditor(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->StatPercentEditor[index]; } + float GetStatPercentageOfSocket(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->StatPercentageOfSocket[index]; } + uint32 GetScalingStatContentTuning() const { return ExtendedData->ContentTuningID; } + uint32 GetPlayerLevelToItemLevelCurveId() const { return ExtendedData->PlayerLevelToItemLevelCurveID; } uint32 GetDamageType() const { return ExtendedData->DamageDamageType; } uint32 GetDelay() const { return ExtendedData->ItemDelay; } float GetRangedModRange() const { return ExtendedData->ItemRange; } diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.cpp b/src/server/game/Entities/Object/Updates/UpdateFields.cpp index 98e01cbe141..4b0581b623c 100644 --- a/src/server/game/Entities/Object/Updates/UpdateFields.cpp +++ b/src/server/game/Entities/Object/Updates/UpdateFields.cpp @@ -16,7 +16,10 @@ */ #include "UpdateFields.h" +#include "AreaTrigger.h" #include "ByteBuffer.h" +#include "Corpse.h" +#include "DynamicObject.h" #include "Player.h" #include "ViewerDependentValues.h" @@ -119,6 +122,75 @@ void ItemEnchantment::ClearChangesMask() _changesMask.ResetAll(); } +void ItemMod::WriteCreate(ByteBuffer& data, Item const* owner, Player const* receiver) const +{ + data << int32(Value); + data << uint8(Type); +} + +void ItemMod::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Item const* owner, Player const* receiver) const +{ + data << int32(Value); + data << uint8(Type); +} + +bool ItemMod::operator==(ItemMod const& right) const +{ + return Value == right.Value + && Type == right.Type; +} + +void ItemModList::WriteCreate(ByteBuffer& data, Item const* owner, Player const* receiver) const +{ + data.WriteBits(Values.size(), 6); + for (std::size_t i = 0; i < Values.size(); ++i) + { + Values[i].WriteCreate(data, owner, receiver); + } + data.FlushBits(); +} + +void ItemModList::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Item const* owner, Player const* receiver) const +{ + UpdateMask<1> changesMask = _changesMask; + if (ignoreChangesMask) + changesMask.SetAll(); + + data.WriteBits(changesMask.GetBlock(0), 1); + + if (changesMask[0]) + { + if (changesMask[0]) + { + if (!ignoreChangesMask) + Values.WriteUpdateMask(data, 6); + else + WriteCompleteDynamicFieldUpdateMask(Values.size(), data, 6); + } + } + data.FlushBits(); + if (changesMask[0]) + { + if (changesMask[0]) + { + for (std::size_t i = 0; i < Values.size(); ++i) + { + if (Values.HasChanged(i) || ignoreChangesMask) + { + Values[i].WriteUpdate(data, ignoreChangesMask, owner, receiver); + } + } + } + } + data.FlushBits(); +} + +void ItemModList::ClearChangesMask() +{ + Base::ClearChangesMask(Values); + _changesMask.ResetAll(); +} + void ArtifactPower::WriteCreate(ByteBuffer& data, Item const* owner, Player const* receiver) const { data << int16(ArtifactPowerID); @@ -133,6 +205,13 @@ void ArtifactPower::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Item c data << uint8(CurrentRankWithBonus); } +bool ArtifactPower::operator==(ArtifactPower const& right) const +{ + return ArtifactPowerID == right.ArtifactPowerID + && PurchasedRank == right.PurchasedRank + && CurrentRankWithBonus == right.CurrentRankWithBonus; +} + void SocketedGem::WriteCreate(ByteBuffer& data, Item const* owner, Player const* receiver) const { data << int32(ItemID); @@ -216,27 +295,19 @@ void ItemData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi data << uint32(MaxDurability); } data << uint32(CreatePlayedTime); - if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) - { - data << uint32(ModifiersMask); - } data << int32(Context); + data << int32(CreateTime); if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) { data << uint64(ArtifactXP); data << uint8(ItemAppearanceModID); } - data << uint32(Modifiers.size()); data << uint32(ArtifactPowers.size()); data << uint32(Gems.size()); if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) { data << uint32(DynamicFlags2); } - for (std::size_t i = 0; i < Modifiers.size(); ++i) - { - data << int32(Modifiers[i]); - } for (std::size_t i = 0; i < ArtifactPowers.size(); ++i) { ArtifactPowers[i].WriteCreate(data, owner, receiver); @@ -245,11 +316,12 @@ void ItemData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi { Gems[i].WriteCreate(data, owner, receiver); } + Modifiers->WriteCreate(data, owner, receiver); } void ItemData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Item const* owner, Player const* receiver) const { - UpdateMask<40> allowedMaskForTarget({ 0xFC0149FFu, 0x000000FFu }); + UpdateMask<40> allowedMaskForTarget({ 0xFC04E4FFu, 0x000000FFu }); AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags); WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver); } @@ -257,13 +329,13 @@ void ItemData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi void ItemData::AppendAllowedFieldsMaskForFlag(UpdateMask<40>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const { if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) - allowedMaskForTarget |= { 0x03FEB600u, 0x00000000u }; + allowedMaskForTarget |= { 0x03FB1B00u, 0x00000000u }; } void ItemData::FilterDisallowedFieldsMaskForFlag(UpdateMask<40>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const { if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) - changesMask &= { 0xFC0149FFu, 0xFFFFFFFFu }; + changesMask &= { 0xFC04E4FFu, 0xFFFFFFFFu }; } void ItemData::WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, bool ignoreNestedChangesMask, Item const* owner, Player const* receiver) const @@ -290,18 +362,11 @@ void ItemData::WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, if (changesMask[2]) { if (!ignoreNestedChangesMask) - Modifiers.WriteUpdateMask(data); - else - WriteCompleteDynamicFieldUpdateMask(Modifiers.size(), data); - } - if (changesMask[3]) - { - if (!ignoreNestedChangesMask) ArtifactPowers.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(ArtifactPowers.size(), data); } - if (changesMask[4]) + if (changesMask[3]) { if (!ignoreNestedChangesMask) Gems.WriteUpdateMask(data); @@ -314,16 +379,6 @@ void ItemData::WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, { if (changesMask[2]) { - for (std::size_t i = 0; i < Modifiers.size(); ++i) - { - if (Modifiers.HasChanged(i) || ignoreNestedChangesMask) - { - data << int32(Modifiers[i]); - } - } - } - if (changesMask[3]) - { for (std::size_t i = 0; i < ArtifactPowers.size(); ++i) { if (ArtifactPowers.HasChanged(i) || ignoreNestedChangesMask) @@ -332,7 +387,7 @@ void ItemData::WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, } } } - if (changesMask[4]) + if (changesMask[3]) { for (std::size_t i = 0; i < Gems.size(); ++i) { @@ -342,59 +397,59 @@ void ItemData::WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, } } } - if (changesMask[5]) + if (changesMask[4]) { data << Owner; } - if (changesMask[6]) + if (changesMask[5]) { data << ContainedIn; } - if (changesMask[7]) + if (changesMask[6]) { data << Creator; } - if (changesMask[8]) + if (changesMask[7]) { data << GiftCreator; } - if (changesMask[9]) + if (changesMask[8]) { data << uint32(StackCount); } - if (changesMask[10]) + if (changesMask[9]) { data << uint32(Expiration); } - if (changesMask[11]) + if (changesMask[10]) { data << uint32(DynamicFlags); } - if (changesMask[12]) + if (changesMask[11]) { data << uint32(Durability); } - if (changesMask[13]) + if (changesMask[12]) { data << uint32(MaxDurability); } - if (changesMask[14]) + if (changesMask[13]) { data << uint32(CreatePlayedTime); } - if (changesMask[15]) + if (changesMask[14]) { - data << uint32(ModifiersMask); + data << int32(Context); } - if (changesMask[16]) + if (changesMask[15]) { - data << int32(Context); + data << int32(CreateTime); } - if (changesMask[17]) + if (changesMask[16]) { data << uint64(ArtifactXP); } - if (changesMask[18]) + if (changesMask[17]) { data << uint8(ItemAppearanceModID); } @@ -402,6 +457,10 @@ void ItemData::WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, { data << uint32(DynamicFlags2); } + if (changesMask[18]) + { + Modifiers->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + } } if (changesMask[20]) { @@ -428,7 +487,6 @@ void ItemData::WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, void ItemData::ClearChangesMask() { Base::ClearChangesMask(BonusListIDs); - Base::ClearChangesMask(Modifiers); Base::ClearChangesMask(ArtifactPowers); Base::ClearChangesMask(Gems); Base::ClearChangesMask(Owner); @@ -441,10 +499,11 @@ void ItemData::ClearChangesMask() Base::ClearChangesMask(Durability); Base::ClearChangesMask(MaxDurability); Base::ClearChangesMask(CreatePlayedTime); - Base::ClearChangesMask(ModifiersMask); Base::ClearChangesMask(Context); + Base::ClearChangesMask(CreateTime); Base::ClearChangesMask(ArtifactXP); Base::ClearChangesMask(ItemAppearanceModID); + Base::ClearChangesMask(Modifiers); Base::ClearChangesMask(DynamicFlags2); Base::ClearChangesMask(SpellCharges); Base::ClearChangesMask(Enchantment); @@ -549,6 +608,12 @@ void UnlockedAzeriteEssence::WriteUpdate(ByteBuffer& data, bool ignoreChangesMas data << uint32(Rank); } +bool UnlockedAzeriteEssence::operator==(UnlockedAzeriteEssence const& right) const +{ + return AzeriteEssenceID == right.AzeriteEssenceID + && Rank == right.Rank; +} + void SelectedAzeriteEssences::WriteCreate(ByteBuffer& data, AzeriteItem const* owner, Player const* receiver) const { for (std::size_t i = 0; i < 4; ++i) @@ -624,52 +689,59 @@ void AzeriteItemData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fi { data << uint32(UnlockedEssenceMilestones[i]); } + data.FlushBits(); + data.WriteBit(Enabled); for (std::size_t i = 0; i < SelectedEssences.size(); ++i) { SelectedEssences[i].WriteCreate(data, owner, receiver); } + data.FlushBits(); } void AzeriteItemData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, AzeriteItem const* owner, Player const* receiver) const { - UpdateMask<9> allowedMaskForTarget({ 0x0000000Fu }); + UpdateMask<10> allowedMaskForTarget({ 0x0000001Fu }); AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags); WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver); } -void AzeriteItemData::AppendAllowedFieldsMaskForFlag(UpdateMask<9>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const +void AzeriteItemData::AppendAllowedFieldsMaskForFlag(UpdateMask<10>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const { if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) - allowedMaskForTarget |= { 0x000001F0u }; + allowedMaskForTarget |= { 0x000003E0u }; } -void AzeriteItemData::FilterDisallowedFieldsMaskForFlag(UpdateMask<9>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const +void AzeriteItemData::FilterDisallowedFieldsMaskForFlag(UpdateMask<10>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const { if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) - changesMask &= { 0xFFFFFE0Fu }; + changesMask &= { 0xFFFFFC1Fu }; } -void AzeriteItemData::WriteUpdate(ByteBuffer& data, UpdateMask<9> const& changesMask, bool ignoreNestedChangesMask, AzeriteItem const* owner, Player const* receiver) const +void AzeriteItemData::WriteUpdate(ByteBuffer& data, UpdateMask<10> const& changesMask, bool ignoreNestedChangesMask, AzeriteItem const* owner, Player const* receiver) const { - data.WriteBits(changesMask.GetBlock(0), 9); + data.WriteBits(changesMask.GetBlock(0), 10); if (changesMask[0]) { if (changesMask[1]) { + data.WriteBit(Enabled); + } + if (changesMask[2]) + { if (!ignoreNestedChangesMask) UnlockedEssences.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(UnlockedEssences.size(), data); } - if (changesMask[2]) + if (changesMask[3]) { if (!ignoreNestedChangesMask) SelectedEssences.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(SelectedEssences.size(), data); } - if (changesMask[3]) + if (changesMask[4]) { if (!ignoreNestedChangesMask) UnlockedEssenceMilestones.WriteUpdateMask(data); @@ -680,7 +752,7 @@ void AzeriteItemData::WriteUpdate(ByteBuffer& data, UpdateMask<9> const& changes data.FlushBits(); if (changesMask[0]) { - if (changesMask[1]) + if (changesMask[2]) { for (std::size_t i = 0; i < UnlockedEssences.size(); ++i) { @@ -690,7 +762,7 @@ void AzeriteItemData::WriteUpdate(ByteBuffer& data, UpdateMask<9> const& changes } } } - if (changesMask[3]) + if (changesMask[4]) { for (std::size_t i = 0; i < UnlockedEssenceMilestones.size(); ++i) { @@ -700,7 +772,7 @@ void AzeriteItemData::WriteUpdate(ByteBuffer& data, UpdateMask<9> const& changes } } } - if (changesMask[2]) + if (changesMask[3]) { for (std::size_t i = 0; i < SelectedEssences.size(); ++i) { @@ -710,31 +782,33 @@ void AzeriteItemData::WriteUpdate(ByteBuffer& data, UpdateMask<9> const& changes } } } - if (changesMask[4]) + if (changesMask[5]) { data << uint64(Xp); } - if (changesMask[5]) + if (changesMask[6]) { data << uint32(Level); } - if (changesMask[6]) + if (changesMask[7]) { data << uint32(AuraLevel); } - if (changesMask[7]) + if (changesMask[8]) { data << uint32(KnowledgeLevel); } - if (changesMask[8]) + if (changesMask[9]) { data << int32(DEBUGknowledgeWeek); } } + data.FlushBits(); } void AzeriteItemData::ClearChangesMask() { + Base::ClearChangesMask(Enabled); Base::ClearChangesMask(UnlockedEssences); Base::ClearChangesMask(UnlockedEssenceMilestones); Base::ClearChangesMask(SelectedEssences); @@ -746,32 +820,57 @@ void AzeriteItemData::ClearChangesMask() _changesMask.ResetAll(); } +void SpellCastVisual::WriteCreate(ByteBuffer& data, Object const* owner, Player const* receiver) const +{ + data << int32(SpellXSpellVisualID); + data << int32(ScriptVisualID); +} + +void SpellCastVisual::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Object const* owner, Player const* receiver) const +{ + data << int32(SpellXSpellVisualID); + data << int32(ScriptVisualID); +} + +bool SpellCastVisual::operator==(SpellCastVisual const& right) const +{ + return SpellXSpellVisualID == right.SpellXSpellVisualID + && ScriptVisualID == right.ScriptVisualID; +} + void UnitChannel::WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const { data << int32(SpellID); - data << int32(SpellXSpellVisualID); + SpellVisual.WriteCreate(data, owner, receiver); } void UnitChannel::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const { data << int32(SpellID); - data << int32(SpellXSpellVisualID); + SpellVisual.WriteUpdate(data, ignoreChangesMask, owner, receiver); +} + +bool UnitChannel::operator==(UnitChannel const& right) const +{ + return SpellID == right.SpellID + && SpellVisual == right.SpellVisual; } void VisibleItem::WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const { data << int32(ItemID); + data << int32(ItemModifiedAppearanceID); data << uint16(ItemAppearanceModID); data << uint16(ItemVisual); } void VisibleItem::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const { - UpdateMask<4> changesMask = _changesMask; + UpdateMask<5> changesMask = _changesMask; if (ignoreChangesMask) changesMask.SetAll(); - data.WriteBits(changesMask.GetBlock(0), 4); + data.WriteBits(changesMask.GetBlock(0), 5); data.FlushBits(); if (changesMask[0]) @@ -782,10 +881,14 @@ void VisibleItem::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit con } if (changesMask[2]) { - data << uint16(ItemAppearanceModID); + data << int32(ItemModifiedAppearanceID); } if (changesMask[3]) { + data << uint16(ItemAppearanceModID); + } + if (changesMask[4]) + { data << uint16(ItemVisual); } } @@ -794,6 +897,7 @@ void VisibleItem::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit con void VisibleItem::ClearChangesMask() { Base::ClearChangesMask(ItemID); + Base::ClearChangesMask(ItemModifiedAppearanceID); Base::ClearChangesMask(ItemAppearanceModID); Base::ClearChangesMask(ItemVisual); _changesMask.ResetAll(); @@ -811,6 +915,12 @@ void PassiveSpellHistory::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, data << int32(AuraSpellID); } +bool PassiveSpellHistory::operator==(PassiveSpellHistory const& right) const +{ + return SpellID == right.SpellID + && AuraSpellID == right.AuraSpellID; +} + void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Unit const* owner, Player const* receiver) const { data << int32(ViewerDependentValue<DisplayIDTag>::GetValue(DisplayID, owner, receiver)); @@ -823,6 +933,7 @@ void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi data << uint32(StateAnimKitID); data << uint32(StateWorldEffectIDs->size()); data << uint32(StateWorldEffectsQuestObjectiveID); + data << int32(SpellOverrideNameID); for (std::size_t i = 0; i < StateWorldEffectIDs->size(); ++i) { data << uint32((*StateWorldEffectIDs)[i]); @@ -893,6 +1004,8 @@ void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi data << float(BoundingRadius); data << float(CombatReach); data << float(DisplayScale); + data << int32(CreatureFamily); + data << int32(CreatureType); data << int32(NativeDisplayID); data << float(NativeXDisplayScale); data << int32(MountDisplayID); @@ -913,6 +1026,7 @@ void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi data << uint32(PetExperience); data << uint32(PetNextLevelExperience); data << float(ModCastingSpeed); + data << float(ModCastingSpeedNeg); data << float(ModSpellHaste); data << float(ModHaste); data << float(ModRangedHaste); @@ -983,7 +1097,6 @@ void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi data << uint32(BattlePetCompanionNameTimestamp); data << int32(InteractSpellID); data << int32(ScaleDuration); - data << int32(SpellOverrideNameID); data << int32(LooksLikeMountID); data << int32(LooksLikeCreatureID); data << int32(LookAtControllerID); @@ -993,6 +1106,7 @@ void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi data << uint32(WorldEffects.size()); data << uint32(ChannelObjects.size()); data << SkinningOwnerGUID; + data << uint32(SilencedSchoolMask); for (std::size_t i = 0; i < PassiveSpells.size(); ++i) { PassiveSpells[i].WriteCreate(data, owner, receiver); @@ -1009,35 +1123,35 @@ void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi void UnitData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Unit const* owner, Player const* receiver) const { - UpdateMask<192> allowedMaskForTarget({ 0xFFFFEFFFu, 0xFC3FBFFFu, 0x0001EFFFu, 0xFFBFFFF9u, 0x003F8007u, 0x00000000u }); + UpdateMask<196> allowedMaskForTarget({ 0xFFFFDFFFu, 0xE1FF7FFFu, 0x001EFFFFu, 0xFBFFFF81u, 0x03F8007Fu, 0x00000000u, 0x00000000u }); AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags); WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver); } -void UnitData::AppendAllowedFieldsMaskForFlag(UpdateMask<192>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const +void UnitData::AppendAllowedFieldsMaskForFlag(UpdateMask<196>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const { if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) - allowedMaskForTarget |= { 0x00001000u, 0x03C04000u, 0xFFFE1000u, 0x00400006u, 0xFFC07FF8u, 0xFFFFFFFFu }; + allowedMaskForTarget |= { 0x00002000u, 0x1E008000u, 0xFFE10000u, 0x0400007Eu, 0xFC07FF80u, 0xFFFFFFFFu, 0x0000000Fu }; if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::UnitAll)) - allowedMaskForTarget |= { 0x00000000u, 0x00000000u, 0x00000000u, 0x00400000u, 0x00007FF8u, 0x00000000u }; + allowedMaskForTarget |= { 0x00000000u, 0x00000000u, 0x00000000u, 0x04000000u, 0x0007FF80u, 0x00000000u, 0x00000000u }; if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Empath)) - allowedMaskForTarget |= { 0x00000000u, 0x03C00000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x000007F8u }; + allowedMaskForTarget |= { 0x00000000u, 0x1E000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00007F80u, 0x00000000u }; } -void UnitData::FilterDisallowedFieldsMaskForFlag(UpdateMask<192>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const +void UnitData::FilterDisallowedFieldsMaskForFlag(UpdateMask<196>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const { if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner)) - changesMask &= { 0xFFFFEFFFu, 0xFC3FBFFFu, 0x0001EFFFu, 0xFFBFFFF9u, 0x003F8007u, 0x00000000u }; + changesMask &= { 0xFFFFDFFFu, 0xE1FF7FFFu, 0x001EFFFFu, 0xFBFFFF81u, 0x03F8007Fu, 0x00000000u, 0xFFFFFFF0u }; if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag::UnitAll)) - changesMask &= { 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFBFFFFFu, 0xFFFF8007u, 0xFFFFFFFFu }; + changesMask &= { 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFBFFFFFFu, 0xFFF8007Fu, 0xFFFFFFFFu, 0xFFFFFFFFu }; if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Empath)) - changesMask &= { 0xFFFFFFFFu, 0xFC3FFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFF807u }; + changesMask &= { 0xFFFFFFFFu, 0xE1FFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFF807Fu, 0xFFFFFFFFu }; } -void UnitData::WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMask, bool ignoreNestedChangesMask, Unit const* owner, Player const* receiver) const +void UnitData::WriteUpdate(ByteBuffer& data, UpdateMask<196> const& changesMask, bool ignoreNestedChangesMask, Unit const* owner, Player const* receiver) const { - data.WriteBits(changesMask.GetBlocksMask(0), 6); - for (std::size_t i = 0; i < 6; ++i) + data.WriteBits(changesMask.GetBlocksMask(0), 7); + for (std::size_t i = 0; i < 7; ++i) if (changesMask.GetBlock(i)) data.WriteBits(changesMask.GetBlock(i), 32); @@ -1132,509 +1246,525 @@ void UnitData::WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMask, } if (changesMask[10]) { - data << Charm; + data << int32(SpellOverrideNameID); } if (changesMask[11]) { - data << Summon; + data << Charm; } if (changesMask[12]) { - data << Critter; + data << Summon; } if (changesMask[13]) { - data << CharmedBy; + data << Critter; } if (changesMask[14]) { - data << SummonedBy; + data << CharmedBy; } if (changesMask[15]) { - data << CreatedBy; + data << SummonedBy; } if (changesMask[16]) { - data << DemonCreator; + data << CreatedBy; } if (changesMask[17]) { - data << LookAtControllerTarget; + data << DemonCreator; } if (changesMask[18]) { - data << Target; + data << LookAtControllerTarget; } if (changesMask[19]) { - data << BattlePetCompanionGUID; + data << Target; } if (changesMask[20]) { - data << uint64(BattlePetDBID); + data << BattlePetCompanionGUID; } if (changesMask[21]) { - ChannelData->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + data << uint64(BattlePetDBID); } if (changesMask[22]) { - data << uint32(SummonedByHomeRealm); + ChannelData->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } if (changesMask[23]) { - data << uint8(Race); + data << uint32(SummonedByHomeRealm); } if (changesMask[24]) { - data << uint8(ClassId); + data << uint8(Race); } if (changesMask[25]) { - data << uint8(PlayerClassId); + data << uint8(ClassId); } if (changesMask[26]) { - data << uint8(Sex); + data << uint8(PlayerClassId); } if (changesMask[27]) { - data << uint8(DisplayPower); + data << uint8(Sex); } if (changesMask[28]) { - data << uint32(OverrideDisplayPowerID); + data << uint8(DisplayPower); } if (changesMask[29]) { - data << int64(Health); + data << uint32(OverrideDisplayPowerID); } if (changesMask[30]) { - data << int64(MaxHealth); + data << int64(Health); } if (changesMask[31]) { - data << int32(Level); + data << int64(MaxHealth); } } if (changesMask[32]) { if (changesMask[33]) { - data << int32(EffectiveLevel); + data << int32(Level); } if (changesMask[34]) { - data << int32(ContentTuningID); + data << int32(EffectiveLevel); } if (changesMask[35]) { - data << int32(ScalingLevelMin); + data << int32(ContentTuningID); } if (changesMask[36]) { - data << int32(ScalingLevelMax); + data << int32(ScalingLevelMin); } if (changesMask[37]) { - data << int32(ScalingLevelDelta); + data << int32(ScalingLevelMax); } if (changesMask[38]) { - data << int32(ScalingFactionGroup); + data << int32(ScalingLevelDelta); } if (changesMask[39]) { - data << int32(ScalingHealthItemLevelCurveID); + data << int32(ScalingFactionGroup); } if (changesMask[40]) { - data << int32(ScalingDamageItemLevelCurveID); + data << int32(ScalingHealthItemLevelCurveID); } if (changesMask[41]) { - data << int32(ViewerDependentValue<FactionTemplateTag>::GetValue(FactionTemplate, owner, receiver)); + data << int32(ScalingDamageItemLevelCurveID); } if (changesMask[42]) { - data << uint32(ViewerDependentValue<FlagsTag>::GetValue(Flags, owner, receiver)); + data << int32(ViewerDependentValue<FactionTemplateTag>::GetValue(FactionTemplate, owner, receiver)); } if (changesMask[43]) { - data << uint32(Flags2); + data << uint32(ViewerDependentValue<FlagsTag>::GetValue(Flags, owner, receiver)); } if (changesMask[44]) { - data << uint32(Flags3); + data << uint32(Flags2); } if (changesMask[45]) { - data << uint32(ViewerDependentValue<AuraStateTag>::GetValue(AuraState, owner, receiver)); + data << uint32(Flags3); } if (changesMask[46]) { - data << uint32(RangedAttackRoundBaseTime); + data << uint32(ViewerDependentValue<AuraStateTag>::GetValue(AuraState, owner, receiver)); } if (changesMask[47]) { - data << float(BoundingRadius); + data << uint32(RangedAttackRoundBaseTime); } if (changesMask[48]) { - data << float(CombatReach); + data << float(BoundingRadius); } if (changesMask[49]) { - data << float(DisplayScale); + data << float(CombatReach); } if (changesMask[50]) { - data << int32(NativeDisplayID); + data << float(DisplayScale); } if (changesMask[51]) { - data << float(NativeXDisplayScale); + data << int32(CreatureFamily); } if (changesMask[52]) { - data << int32(MountDisplayID); + data << int32(CreatureType); } if (changesMask[53]) { - data << int32(CosmeticMountDisplayID); + data << int32(NativeDisplayID); } if (changesMask[54]) { - data << float(MinDamage); + data << float(NativeXDisplayScale); } if (changesMask[55]) { - data << float(MaxDamage); + data << int32(MountDisplayID); } if (changesMask[56]) { - data << float(MinOffHandDamage); + data << int32(CosmeticMountDisplayID); } if (changesMask[57]) { - data << float(MaxOffHandDamage); + data << float(MinDamage); } if (changesMask[58]) { - data << uint8(StandState); + data << float(MaxDamage); } if (changesMask[59]) { - data << uint8(PetTalentPoints); + data << float(MinOffHandDamage); } if (changesMask[60]) { - data << uint8(VisFlags); + data << float(MaxOffHandDamage); } if (changesMask[61]) { - data << uint8(AnimTier); + data << uint8(StandState); } if (changesMask[62]) { - data << uint32(PetNumber); + data << uint8(PetTalentPoints); } if (changesMask[63]) { - data << uint32(PetNameTimestamp); + data << uint8(VisFlags); } } if (changesMask[64]) { if (changesMask[65]) { - data << uint32(PetExperience); + data << uint8(AnimTier); } if (changesMask[66]) { - data << uint32(PetNextLevelExperience); + data << uint32(PetNumber); } if (changesMask[67]) { - data << float(ModCastingSpeed); + data << uint32(PetNameTimestamp); } if (changesMask[68]) { - data << float(ModSpellHaste); + data << uint32(PetExperience); } if (changesMask[69]) { - data << float(ModHaste); + data << uint32(PetNextLevelExperience); } if (changesMask[70]) { - data << float(ModRangedHaste); + data << float(ModCastingSpeed); } if (changesMask[71]) { - data << float(ModHasteRegen); + data << float(ModCastingSpeedNeg); } if (changesMask[72]) { - data << float(ModTimeRate); + data << float(ModSpellHaste); } if (changesMask[73]) { - data << int32(CreatedBySpell); + data << float(ModHaste); } if (changesMask[74]) { - data << int32(EmoteState); + data << float(ModRangedHaste); } if (changesMask[75]) { - data << int32(BaseMana); + data << float(ModHasteRegen); } if (changesMask[76]) { - data << int32(BaseHealth); + data << float(ModTimeRate); } if (changesMask[77]) { - data << uint8(SheatheState); + data << int32(CreatedBySpell); } if (changesMask[78]) { - data << uint8(ViewerDependentValue<PvpFlagsTag>::GetValue(PvpFlags, owner, receiver)); + data << int32(EmoteState); } if (changesMask[79]) { - data << uint8(PetFlags); + data << int32(BaseMana); } if (changesMask[80]) { - data << uint8(ShapeshiftForm); + data << int32(BaseHealth); } if (changesMask[81]) { - data << int32(AttackPower); + data << uint8(SheatheState); } if (changesMask[82]) { - data << int32(AttackPowerModPos); + data << uint8(ViewerDependentValue<PvpFlagsTag>::GetValue(PvpFlags, owner, receiver)); } if (changesMask[83]) { - data << int32(AttackPowerModNeg); + data << uint8(PetFlags); } if (changesMask[84]) { - data << float(AttackPowerMultiplier); + data << uint8(ShapeshiftForm); } if (changesMask[85]) { - data << int32(RangedAttackPower); + data << int32(AttackPower); } if (changesMask[86]) { - data << int32(RangedAttackPowerModPos); + data << int32(AttackPowerModPos); } if (changesMask[87]) { - data << int32(RangedAttackPowerModNeg); + data << int32(AttackPowerModNeg); } if (changesMask[88]) { - data << float(RangedAttackPowerMultiplier); + data << float(AttackPowerMultiplier); } if (changesMask[89]) { - data << int32(MainHandWeaponAttackPower); + data << int32(RangedAttackPower); } if (changesMask[90]) { - data << int32(OffHandWeaponAttackPower); + data << int32(RangedAttackPowerModPos); } if (changesMask[91]) { - data << int32(RangedWeaponAttackPower); + data << int32(RangedAttackPowerModNeg); } if (changesMask[92]) { - data << int32(SetAttackSpeedAura); + data << float(RangedAttackPowerMultiplier); } if (changesMask[93]) { - data << float(Lifesteal); + data << int32(MainHandWeaponAttackPower); } if (changesMask[94]) { - data << float(MinRangedDamage); + data << int32(OffHandWeaponAttackPower); } if (changesMask[95]) { - data << float(MaxRangedDamage); + data << int32(RangedWeaponAttackPower); } } if (changesMask[96]) { if (changesMask[97]) { - data << float(ManaCostModifierModifier); + data << int32(SetAttackSpeedAura); } if (changesMask[98]) { - data << float(MaxHealthModifier); + data << float(Lifesteal); } if (changesMask[99]) { - data << float(HoverHeight); + data << float(MinRangedDamage); } if (changesMask[100]) { - data << int32(MinItemLevelCutoff); + data << float(MaxRangedDamage); } if (changesMask[101]) { - data << int32(MinItemLevel); + data << float(ManaCostModifierModifier); } if (changesMask[102]) { - data << int32(MaxItemLevel); + data << float(MaxHealthModifier); } if (changesMask[103]) { - data << int32(AzeriteItemLevel); + data << float(HoverHeight); } if (changesMask[104]) { - data << int32(WildBattlePetLevel); + data << int32(MinItemLevelCutoff); } if (changesMask[105]) { - data << uint32(BattlePetCompanionNameTimestamp); + data << int32(MinItemLevel); } if (changesMask[106]) { - data << int32(InteractSpellID); + data << int32(MaxItemLevel); } if (changesMask[107]) { - data << int32(ScaleDuration); + data << int32(AzeriteItemLevel); } if (changesMask[108]) { - data << int32(SpellOverrideNameID); + data << int32(WildBattlePetLevel); } if (changesMask[109]) { - data << int32(LooksLikeMountID); + data << uint32(BattlePetCompanionNameTimestamp); } if (changesMask[110]) { - data << int32(LooksLikeCreatureID); + data << int32(InteractSpellID); } if (changesMask[111]) { - data << int32(LookAtControllerID); + data << int32(ScaleDuration); } if (changesMask[112]) { - data << int32(TaxiNodesID); + data << int32(LooksLikeMountID); } if (changesMask[113]) { - data << GuildGUID; + data << int32(LooksLikeCreatureID); } if (changesMask[114]) { + data << int32(LookAtControllerID); + } + if (changesMask[115]) + { + data << int32(TaxiNodesID); + } + if (changesMask[116]) + { + data << GuildGUID; + } + if (changesMask[117]) + { data << SkinningOwnerGUID; } + if (changesMask[118]) + { + data << uint32(SilencedSchoolMask); + } } - if (changesMask[115]) + if (changesMask[119]) { for (std::size_t i = 0; i < 2; ++i) { - if (changesMask[116 + i]) + if (changesMask[120 + i]) { data << uint32(ViewerDependentValue<NpcFlagsTag>::GetValue(NpcFlags[i], i, owner, receiver)); } } } - if (changesMask[118]) + if (changesMask[122]) { for (std::size_t i = 0; i < 6; ++i) { - if (changesMask[119 + i]) + if (changesMask[123 + i]) { data << int32(Power[i]); } - if (changesMask[125 + i]) + if (changesMask[129 + i]) { data << int32(MaxPower[i]); } - if (changesMask[131 + i]) + if (changesMask[135 + i]) { data << float(PowerRegenFlatModifier[i]); } - if (changesMask[137 + i]) + if (changesMask[141 + i]) { data << float(PowerRegenInterruptedFlatModifier[i]); } } } - if (changesMask[143]) + if (changesMask[147]) { for (std::size_t i = 0; i < 3; ++i) { - if (changesMask[144 + i]) + if (changesMask[148 + i]) { VirtualItems[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } } } - if (changesMask[147]) + if (changesMask[151]) { for (std::size_t i = 0; i < 2; ++i) { - if (changesMask[148 + i]) + if (changesMask[152 + i]) { data << uint32(AttackRoundBaseTime[i]); } } } - if (changesMask[150]) + if (changesMask[154]) { for (std::size_t i = 0; i < 4; ++i) { - if (changesMask[151 + i]) + if (changesMask[155 + i]) { data << int32(Stats[i]); } - if (changesMask[155 + i]) + if (changesMask[159 + i]) { data << int32(StatPosBuff[i]); } - if (changesMask[159 + i]) + if (changesMask[163 + i]) { data << int32(StatNegBuff[i]); } } } - if (changesMask[163]) + if (changesMask[167]) { for (std::size_t i = 0; i < 7; ++i) { - if (changesMask[164 + i]) + if (changesMask[168 + i]) { data << int32(Resistances[i]); } - if (changesMask[171 + i]) + if (changesMask[175 + i]) { data << int32(BonusResistanceMods[i]); } - if (changesMask[178 + i]) + if (changesMask[182 + i]) { data << int32(PowerCostModifier[i]); } - if (changesMask[185 + i]) + if (changesMask[189 + i]) { data << float(PowerCostMultiplier[i]); } @@ -1653,6 +1783,7 @@ void UnitData::ClearChangesMask() Base::ClearChangesMask(StateAnimID); Base::ClearChangesMask(StateAnimKitID); Base::ClearChangesMask(StateWorldEffectsQuestObjectiveID); + Base::ClearChangesMask(SpellOverrideNameID); Base::ClearChangesMask(Charm); Base::ClearChangesMask(Summon); Base::ClearChangesMask(Critter); @@ -1692,6 +1823,8 @@ void UnitData::ClearChangesMask() Base::ClearChangesMask(BoundingRadius); Base::ClearChangesMask(CombatReach); Base::ClearChangesMask(DisplayScale); + Base::ClearChangesMask(CreatureFamily); + Base::ClearChangesMask(CreatureType); Base::ClearChangesMask(NativeDisplayID); Base::ClearChangesMask(NativeXDisplayScale); Base::ClearChangesMask(MountDisplayID); @@ -1709,6 +1842,7 @@ void UnitData::ClearChangesMask() Base::ClearChangesMask(PetExperience); Base::ClearChangesMask(PetNextLevelExperience); Base::ClearChangesMask(ModCastingSpeed); + Base::ClearChangesMask(ModCastingSpeedNeg); Base::ClearChangesMask(ModSpellHaste); Base::ClearChangesMask(ModHaste); Base::ClearChangesMask(ModRangedHaste); @@ -1748,13 +1882,13 @@ void UnitData::ClearChangesMask() Base::ClearChangesMask(BattlePetCompanionNameTimestamp); Base::ClearChangesMask(InteractSpellID); Base::ClearChangesMask(ScaleDuration); - Base::ClearChangesMask(SpellOverrideNameID); Base::ClearChangesMask(LooksLikeMountID); Base::ClearChangesMask(LooksLikeCreatureID); Base::ClearChangesMask(LookAtControllerID); Base::ClearChangesMask(TaxiNodesID); Base::ClearChangesMask(GuildGUID); Base::ClearChangesMask(SkinningOwnerGUID); + Base::ClearChangesMask(SilencedSchoolMask); Base::ClearChangesMask(NpcFlags); Base::ClearChangesMask(Power); Base::ClearChangesMask(MaxPower); @@ -1772,6 +1906,24 @@ void UnitData::ClearChangesMask() _changesMask.ResetAll(); } +void ChrCustomizationChoice::WriteCreate(ByteBuffer& data, Object const* owner, Player const* receiver) const +{ + data << uint32(ChrCustomizationOptionID); + data << uint32(ChrCustomizationChoiceID); +} + +void ChrCustomizationChoice::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Object const* owner, Player const* receiver) const +{ + data << uint32(ChrCustomizationOptionID); + data << uint32(ChrCustomizationChoiceID); +} + +bool ChrCustomizationChoice::operator==(ChrCustomizationChoice const& right) const +{ + return ChrCustomizationOptionID == right.ChrCustomizationOptionID + && ChrCustomizationChoiceID == right.ChrCustomizationChoiceID; +} + void QuestLog::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const { data << int32(QuestID); @@ -1907,6 +2059,27 @@ void ArenaCooldown::ClearChangesMask() _changesMask.ResetAll(); } +void CTROptions::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const +{ + data << int32(ContentTuningConditionMask); + data << uint32(Field_4); + data << uint32(ExpansionLevelMask); +} + +void CTROptions::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const +{ + data << int32(ContentTuningConditionMask); + data << uint32(Field_4); + data << uint32(ExpansionLevelMask); +} + +bool CTROptions::operator==(CTROptions const& right) const +{ + return ContentTuningConditionMask == right.ContentTuningConditionMask + && Field_4 == right.Field_4 + && ExpansionLevelMask == right.ExpansionLevelMask; +} + void PlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const { data << DuelArbiter; @@ -1917,15 +2090,7 @@ void PlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi data << uint32(GuildRankID); data << uint32(GuildDeleteDate); data << int32(GuildLevel); - data << uint8(SkinID); - data << uint8(FaceID); - data << uint8(HairStyleID); - data << uint8(HairColorID); - for (std::size_t i = 0; i < 3; ++i) - { - data << uint8(CustomDisplayOption[i]); - } - data << uint8(FacialHairStyleID); + data << uint32(Customizations.size()); data << uint8(PartyType); data << uint8(NativeSex); data << uint8(Inebriation); @@ -1959,8 +2124,13 @@ void PlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi data << uint32(ArenaCooldowns.size()); data << int32(Field_B0); data << int32(Field_B4); - data << Field_F8; - data << int32(Field_108); + CtrOptions->WriteCreate(data, owner, receiver); + data << int32(CovenantID); + data << int32(SoulbindID); + for (std::size_t i = 0; i < Customizations.size(); ++i) + { + Customizations[i].WriteCreate(data, owner, receiver); + } if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::PartyMember)) { for (std::size_t i = 0; i < QuestSessionQuestLog.size(); ++i) @@ -1972,6 +2142,7 @@ void PlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi { ArenaCooldowns[i].WriteCreate(data, owner, receiver); } + data.FlushBits(); if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::PartyMember)) { data.WriteBit(HasQuestSession); @@ -1982,24 +2153,24 @@ void PlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi void PlayerData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const { - UpdateMask<192> allowedMaskForTarget({ 0xFFFFFFF5u, 0x000001FFu, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFF80u }); + UpdateMask<185> allowedMaskForTarget({ 0xFFFFFFEDu, 0x00000003u, 0x00000000u, 0x00000000u, 0x00000000u, 0x01FFFFFFu }); AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags); WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver); } -void PlayerData::AppendAllowedFieldsMaskForFlag(UpdateMask<192>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const +void PlayerData::AppendAllowedFieldsMaskForFlag(UpdateMask<185>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const { if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::PartyMember)) - allowedMaskForTarget |= { 0x0000000Au, 0xFFFFFE00u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x0000007Fu }; + allowedMaskForTarget |= { 0x00000012u, 0xFFFFFFFCu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x00000000u }; } -void PlayerData::FilterDisallowedFieldsMaskForFlag(UpdateMask<192>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const +void PlayerData::FilterDisallowedFieldsMaskForFlag(UpdateMask<185>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const { if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag::PartyMember)) - changesMask &= { 0xFFFFFFF5u, 0x000001FFu, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFF80u }; + changesMask &= { 0xFFFFFFEDu, 0x00000003u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFFFu }; } -void PlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const +void PlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<185> const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const { data.WriteBits(changesMask.GetBlocksMask(0), 6); for (std::size_t i = 0; i < 6; ++i) @@ -2020,11 +2191,18 @@ void PlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMas if (changesMask[3]) { if (!ignoreNestedChangesMask) + Customizations.WriteUpdateMask(data); + else + WriteCompleteDynamicFieldUpdateMask(Customizations.size(), data); + } + if (changesMask[4]) + { + if (!ignoreNestedChangesMask) QuestSessionQuestLog.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(QuestSessionQuestLog.size(), data); } - if (changesMask[4]) + if (changesMask[5]) { if (!ignoreNestedChangesMask) ArenaCooldowns.WriteUpdateMask(data); @@ -2037,6 +2215,16 @@ void PlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMas { if (changesMask[3]) { + for (std::size_t i = 0; i < Customizations.size(); ++i) + { + if (Customizations.HasChanged(i) || ignoreNestedChangesMask) + { + Customizations[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + } + } + } + if (changesMask[4]) + { for (std::size_t i = 0; i < QuestSessionQuestLog.size(); ++i) { if (QuestSessionQuestLog.HasChanged(i) || ignoreNestedChangesMask) @@ -2048,7 +2236,7 @@ void PlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMas } } } - if (changesMask[4]) + if (changesMask[5]) { for (std::size_t i = 0; i < ArenaCooldowns.size(); ++i) { @@ -2058,149 +2246,123 @@ void PlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMas } } } - if (changesMask[5]) - { - data << DuelArbiter; - } if (changesMask[6]) { - data << WowAccount; + data << DuelArbiter; } if (changesMask[7]) { - data << LootTargetGUID; + data << WowAccount; } if (changesMask[8]) { - data << uint32(PlayerFlags); + data << LootTargetGUID; } if (changesMask[9]) { - data << uint32(PlayerFlagsEx); + data << uint32(PlayerFlags); } if (changesMask[10]) { - data << uint32(GuildRankID); + data << uint32(PlayerFlagsEx); } if (changesMask[11]) { - data << uint32(GuildDeleteDate); + data << uint32(GuildRankID); } if (changesMask[12]) { - data << int32(GuildLevel); + data << uint32(GuildDeleteDate); } if (changesMask[13]) { - data << uint8(SkinID); + data << int32(GuildLevel); } if (changesMask[14]) { - data << uint8(FaceID); + data << uint8(PartyType); } if (changesMask[15]) { - data << uint8(HairStyleID); + data << uint8(NativeSex); } if (changesMask[16]) { - data << uint8(HairColorID); + data << uint8(Inebriation); } if (changesMask[17]) { - data << uint8(FacialHairStyleID); + data << uint8(PvpTitle); } if (changesMask[18]) { - data << uint8(PartyType); + data << uint8(ArenaFaction); } if (changesMask[19]) { - data << uint8(NativeSex); + data << uint32(DuelTeam); } if (changesMask[20]) { - data << uint8(Inebriation); + data << int32(GuildTimeStamp); } if (changesMask[21]) { - data << uint8(PvpTitle); + data << int32(PlayerTitle); } if (changesMask[22]) { - data << uint8(ArenaFaction); + data << int32(FakeInebriation); } if (changesMask[23]) { - data << uint32(DuelTeam); + data << uint32(VirtualPlayerRealm); } if (changesMask[24]) { - data << int32(GuildTimeStamp); + data << uint32(CurrentSpecID); } if (changesMask[25]) { - data << int32(PlayerTitle); + data << int32(TaxiMountAnimKitID); } if (changesMask[26]) { - data << int32(FakeInebriation); + data << uint8(CurrentBattlePetBreedQuality); } if (changesMask[27]) { - data << uint32(VirtualPlayerRealm); + data << int32(HonorLevel); } if (changesMask[28]) { - data << uint32(CurrentSpecID); + data << int32(Field_B0); } if (changesMask[29]) { - data << int32(TaxiMountAnimKitID); + data << int32(Field_B4); } if (changesMask[30]) { - data << uint8(CurrentBattlePetBreedQuality); + CtrOptions->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } if (changesMask[31]) { - data << int32(HonorLevel); + data << int32(CovenantID); } } if (changesMask[32]) { if (changesMask[33]) { - data << int32(Field_B0); - } - if (changesMask[34]) - { - data << int32(Field_B4); - } - if (changesMask[35]) - { - data << Field_F8; - } - if (changesMask[36]) - { - data << int32(Field_108); - } - } - if (changesMask[37]) - { - for (std::size_t i = 0; i < 3; ++i) - { - if (changesMask[38 + i]) - { - data << uint8(CustomDisplayOption[i]); - } + data << int32(SoulbindID); } } - if (changesMask[41]) + if (changesMask[34]) { for (std::size_t i = 0; i < 125; ++i) { - if (changesMask[42 + i]) + if (changesMask[35 + i]) { if (noQuestLogChangesMask) QuestLog[i].WriteCreate(data, owner, receiver); @@ -2209,21 +2371,21 @@ void PlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMas } } } - if (changesMask[167]) + if (changesMask[160]) { for (std::size_t i = 0; i < 19; ++i) { - if (changesMask[168 + i]) + if (changesMask[161 + i]) { VisibleItems[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } } } - if (changesMask[187]) + if (changesMask[180]) { for (std::size_t i = 0; i < 4; ++i) { - if (changesMask[188 + i]) + if (changesMask[181 + i]) { data << float(AvgItemLevel[i]); } @@ -2236,6 +2398,7 @@ void PlayerData::ClearChangesMask() { Base::ClearChangesMask(HasQuestSession); Base::ClearChangesMask(HasLevelLink); + Base::ClearChangesMask(Customizations); Base::ClearChangesMask(QuestSessionQuestLog); Base::ClearChangesMask(ArenaCooldowns); Base::ClearChangesMask(DuelArbiter); @@ -2246,11 +2409,6 @@ void PlayerData::ClearChangesMask() Base::ClearChangesMask(GuildRankID); Base::ClearChangesMask(GuildDeleteDate); Base::ClearChangesMask(GuildLevel); - Base::ClearChangesMask(SkinID); - Base::ClearChangesMask(FaceID); - Base::ClearChangesMask(HairStyleID); - Base::ClearChangesMask(HairColorID); - Base::ClearChangesMask(FacialHairStyleID); Base::ClearChangesMask(PartyType); Base::ClearChangesMask(NativeSex); Base::ClearChangesMask(Inebriation); @@ -2267,9 +2425,9 @@ void PlayerData::ClearChangesMask() Base::ClearChangesMask(HonorLevel); Base::ClearChangesMask(Field_B0); Base::ClearChangesMask(Field_B4); - Base::ClearChangesMask(Field_F8); - Base::ClearChangesMask(Field_108); - Base::ClearChangesMask(CustomDisplayOption); + Base::ClearChangesMask(CtrOptions); + Base::ClearChangesMask(CovenantID); + Base::ClearChangesMask(SoulbindID); Base::ClearChangesMask(QuestLog); Base::ClearChangesMask(VisibleItems); Base::ClearChangesMask(AvgItemLevel); @@ -2484,6 +2642,14 @@ void CharacterRestriction::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, data.FlushBits(); } +bool CharacterRestriction::operator==(CharacterRestriction const& right) const +{ + return Field_0 == right.Field_0 + && Field_4 == right.Field_4 + && Field_8 == right.Field_8 + && Type == right.Type; +} + void SpellPctModByLabel::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const { data << int32(ModIndex); @@ -2498,6 +2664,13 @@ void SpellPctModByLabel::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, P data << int32(LabelID); } +bool SpellPctModByLabel::operator==(SpellPctModByLabel const& right) const +{ + return ModIndex == right.ModIndex + && ModifierValue == right.ModifierValue + && LabelID == right.LabelID; +} + void SpellFlatModByLabel::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const { data << int32(ModIndex); @@ -2512,6 +2685,13 @@ void SpellFlatModByLabel::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, data << int32(LabelID); } +bool SpellFlatModByLabel::operator==(SpellFlatModByLabel const& right) const +{ + return ModIndex == right.ModIndex + && ModifierValue == right.ModifierValue + && LabelID == right.LabelID; +} + void Research::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const { data << int16(ResearchProjectID); @@ -2522,13 +2702,81 @@ void Research::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player cons data << int16(ResearchProjectID); } -void ReplayedQuest::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const +bool Research::operator==(Research const& right) const { - data << int32(QuestID); - data << uint32(ReplayTime); + return ResearchProjectID == right.ResearchProjectID; } -void ReplayedQuest::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const +void MawPower::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const +{ + data << int32(Field_0); + data << int32(Field_4); + data << int32(Field_8); +} + +void MawPower::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const +{ + data << int32(Field_0); + data << int32(Field_4); + data << int32(Field_8); +} + +bool MawPower::operator==(MawPower const& right) const +{ + return Field_0 == right.Field_0 + && Field_4 == right.Field_4 + && Field_8 == right.Field_8; +} + +void MultiFloorExplore::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const +{ + data << uint32(WorldMapOverlayIDs.size()); + for (std::size_t i = 0; i < WorldMapOverlayIDs.size(); ++i) + { + data << int32(WorldMapOverlayIDs[i]); + } +} + +void MultiFloorExplore::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const +{ + data << uint32(WorldMapOverlayIDs.size()); + for (std::size_t i = 0; i < WorldMapOverlayIDs.size(); ++i) + { + data << int32(WorldMapOverlayIDs[i]); + } + data.FlushBits(); +} + +bool MultiFloorExplore::operator==(MultiFloorExplore const& right) const +{ + return WorldMapOverlayIDs == right.WorldMapOverlayIDs; +} + +void RecipeProgressionInfo::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const +{ + data << uint16(RecipeProgressionGroupID); + data << uint16(Experience); +} + +void RecipeProgressionInfo::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const +{ + data << uint16(RecipeProgressionGroupID); + data << uint16(Experience); +} + +bool RecipeProgressionInfo::operator==(RecipeProgressionInfo const& right) const +{ + return RecipeProgressionGroupID == right.RecipeProgressionGroupID + && Experience == right.Experience; +} + +void ActivePlayerUnk901::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const +{ + data << Field_0; + data << int32(Field_10); +} + +void ActivePlayerUnk901::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const { UpdateMask<3> changesMask = _changesMask; if (ignoreChangesMask) @@ -2541,19 +2789,19 @@ void ReplayedQuest::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player { if (changesMask[1]) { - data << int32(QuestID); + data << Field_0; } if (changesMask[2]) { - data << uint32(ReplayTime); + data << int32(Field_10); } } } -void ReplayedQuest::ClearChangesMask() +void ActivePlayerUnk901::ClearChangesMask() { - Base::ClearChangesMask(QuestID); - Base::ClearChangesMask(ReplayTime); + Base::ClearChangesMask(Field_0); + Base::ClearChangesMask(Field_10); _changesMask.ResetAll(); } @@ -2604,6 +2852,41 @@ void QuestSession::ClearChangesMask() _changesMask.ResetAll(); } +void ReplayedQuest::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const +{ + data << int32(QuestID); + data << uint32(ReplayTime); +} + +void ReplayedQuest::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const +{ + UpdateMask<3> changesMask = _changesMask; + if (ignoreChangesMask) + changesMask.SetAll(); + + data.WriteBits(changesMask.GetBlock(0), 3); + + data.FlushBits(); + if (changesMask[0]) + { + if (changesMask[1]) + { + data << int32(QuestID); + } + if (changesMask[2]) + { + data << uint32(ReplayTime); + } + } +} + +void ReplayedQuest::ClearChangesMask() +{ + Base::ClearChangesMask(QuestID); + Base::ClearChangesMask(ReplayTime); + _changesMask.ResetAll(); +} + void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const { for (std::size_t i = 0; i < 199; ++i) @@ -2661,10 +2944,10 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f data << int32(ModDamageDonePos[i]); data << int32(ModDamageDoneNeg[i]); data << float(ModDamageDonePercent[i]); + data << float(ModHealingDonePercent[i]); } data << int32(ModHealingDonePos); data << float(ModHealingPercent); - data << float(ModHealingDonePercent); data << float(ModPeriodicHealingDonePercent); for (std::size_t i = 0; i < 3; ++i) { @@ -2677,7 +2960,7 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f data << float(OverrideAPBySpellPowerPercent); data << int32(ModTargetResistance); data << int32(ModTargetPhysicalResistance); - data << int32(LocalFlags); + data << uint32(LocalFlags); data << uint8(GrantableLevels); data << uint8(MultiActionBars); data << uint8(LifetimeMaxRank); @@ -2712,13 +2995,16 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f data << float(UiSpellHitModifier); data << int32(HomeRealmTimeOffset); data << float(ModPetHaste); + data << int8(JailersTowerLevelMax); + data << int8(JailersTowerLevel); data << uint8(LocalRegenFlags); data << uint8(AuraVision); data << uint8(NumBackpackSlots); data << int32(OverrideSpellsID); - data << int32(LfgBonusFactionID); data << uint16(LootSpecID); data << uint32(OverrideZonePVPType); + data << BnetAccount; + data << uint64(GuildClubMemberID); for (std::size_t i = 0; i < 4; ++i) { data << uint32(BagSlotFlags[i]); @@ -2750,6 +3036,8 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f data << uint32(Transmog.size()); data << uint32(ConditionalTransmog.size()); data << uint32(SelfResSpells.size()); + data << uint32(RuneforgePowers.size()); + data << uint32(TransmogIllusions.size()); data << uint32(CharacterRestrictions.size()); data << uint32(SpellPctModByLabel.size()); data << uint32(SpellFlatModByLabel.size()); @@ -2761,8 +3049,13 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f Research[i][j].WriteCreate(data, owner, receiver); } } + data << uint32(MawPowers.size()); + data << uint32(MultiFloorExploration.size()); + data << uint32(RecipeProgression.size()); data << uint32(ReplayedQuests.size()); data << uint32(DisabledSpells.size()); + data << int32(UiChromieTimeExpansionID); + data << int32(TransportServerTime); for (std::size_t i = 0; i < KnownTitles.size(); ++i) { data << uint64(KnownTitles[i]); @@ -2811,6 +3104,14 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f { data << int32(SelfResSpells[i]); } + for (std::size_t i = 0; i < RuneforgePowers.size(); ++i) + { + data << uint32(RuneforgePowers[i]); + } + for (std::size_t i = 0; i < TransmogIllusions.size(); ++i) + { + data << uint32(TransmogIllusions[i]); + } for (std::size_t i = 0; i < SpellPctModByLabel.size(); ++i) { SpellPctModByLabel[i].WriteCreate(data, owner, receiver); @@ -2819,6 +3120,18 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f { SpellFlatModByLabel[i].WriteCreate(data, owner, receiver); } + for (std::size_t i = 0; i < MawPowers.size(); ++i) + { + MawPowers[i].WriteCreate(data, owner, receiver); + } + for (std::size_t i = 0; i < MultiFloorExploration.size(); ++i) + { + MultiFloorExploration[i].WriteCreate(data, owner, receiver); + } + for (std::size_t i = 0; i < RecipeProgression.size(); ++i) + { + RecipeProgression[i].WriteCreate(data, owner, receiver); + } for (std::size_t i = 0; i < ReplayedQuests.size(); ++i) { ReplayedQuests[i].WriteCreate(data, owner, receiver); @@ -2831,19 +3144,21 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f { PvpInfo[i].WriteCreate(data, owner, receiver); } + data.FlushBits(); data.WriteBit(BackpackAutoSortDisabled); data.WriteBit(BankAutoSortDisabled); data.WriteBit(SortBagsRightToLeft); data.WriteBit(InsertItemsLeftToRight); - data.WriteBit(QuestSession.is_initialized()); - for (std::size_t i = 0; i < CharacterRestrictions.size(); ++i) - { - CharacterRestrictions[i].WriteCreate(data, owner, receiver); - } + data.WriteBits(QuestSession.is_initialized(), 1); + Field_1410->WriteCreate(data, owner, receiver); if (QuestSession.is_initialized()) { QuestSession->WriteCreate(data, owner, receiver); } + for (std::size_t i = 0; i < CharacterRestrictions.size(); ++i) + { + CharacterRestrictions[i].WriteCreate(data, owner, receiver); + } data.FlushBits(); } @@ -2852,12 +3167,12 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f WriteUpdate(data, _changesMask, false, owner, receiver); } -void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const +void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1511> const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const { for (std::size_t i = 0; i < 1; ++i) data << uint32(changesMask.GetBlocksMask(i)); - data.WriteBits(changesMask.GetBlocksMask(1), 15); - for (std::size_t i = 0; i < 47; ++i) + data.WriteBits(changesMask.GetBlocksMask(1), 16); + for (std::size_t i = 0; i < 48; ++i) if (changesMask.GetBlock(i)) data.WriteBits(changesMask.GetBlock(i), 32); @@ -2966,18 +3281,32 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha if (changesMask[17]) { if (!ignoreNestedChangesMask) + RuneforgePowers.WriteUpdateMask(data); + else + WriteCompleteDynamicFieldUpdateMask(RuneforgePowers.size(), data); + } + if (changesMask[18]) + { + if (!ignoreNestedChangesMask) + TransmogIllusions.WriteUpdateMask(data); + else + WriteCompleteDynamicFieldUpdateMask(TransmogIllusions.size(), data); + } + if (changesMask[19]) + { + if (!ignoreNestedChangesMask) CharacterRestrictions.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(CharacterRestrictions.size(), data); } - if (changesMask[18]) + if (changesMask[20]) { if (!ignoreNestedChangesMask) SpellPctModByLabel.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(SpellPctModByLabel.size(), data); } - if (changesMask[19]) + if (changesMask[21]) { if (!ignoreNestedChangesMask) SpellFlatModByLabel.WriteUpdateMask(data); @@ -2985,25 +3314,16 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha WriteCompleteDynamicFieldUpdateMask(SpellFlatModByLabel.size(), data); } } - if (changesMask[22]) + if (changesMask[27]) { for (std::size_t i = 0; i < 1; ++i) { - if (changesMask[23 + i]) + if (changesMask[28 + i]) { if (!ignoreNestedChangesMask) Research[i].WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(Research[i].size(), data); - } - } - } - if (changesMask[22]) - { - for (std::size_t i = 0; i < 1; ++i) - { - if (changesMask[23 + i]) - { for (std::size_t j = 0; j < Research[i].size(); ++j) { if (Research[i].HasChanged(j) || ignoreNestedChangesMask) @@ -3014,17 +3334,37 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha } } } - data.FlushBits(); if (changesMask[0]) { - if (changesMask[20]) + if (changesMask[22]) + { + if (!ignoreNestedChangesMask) + MawPowers.WriteUpdateMask(data); + else + WriteCompleteDynamicFieldUpdateMask(MawPowers.size(), data); + } + if (changesMask[23]) + { + if (!ignoreNestedChangesMask) + MultiFloorExploration.WriteUpdateMask(data); + else + WriteCompleteDynamicFieldUpdateMask(MultiFloorExploration.size(), data); + } + if (changesMask[24]) + { + if (!ignoreNestedChangesMask) + RecipeProgression.WriteUpdateMask(data); + else + WriteCompleteDynamicFieldUpdateMask(RecipeProgression.size(), data); + } + if (changesMask[25]) { if (!ignoreNestedChangesMask) ReplayedQuests.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(ReplayedQuests.size(), data); } - if (changesMask[21]) + if (changesMask[26]) { if (!ignoreNestedChangesMask) DisabledSpells.WriteUpdateMask(data); @@ -3155,8 +3495,28 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha } } } + if (changesMask[17]) + { + for (std::size_t i = 0; i < RuneforgePowers.size(); ++i) + { + if (RuneforgePowers.HasChanged(i) || ignoreNestedChangesMask) + { + data << uint32(RuneforgePowers[i]); + } + } + } if (changesMask[18]) { + for (std::size_t i = 0; i < TransmogIllusions.size(); ++i) + { + if (TransmogIllusions.HasChanged(i) || ignoreNestedChangesMask) + { + data << uint32(TransmogIllusions[i]); + } + } + } + if (changesMask[20]) + { for (std::size_t i = 0; i < SpellPctModByLabel.size(); ++i) { if (SpellPctModByLabel.HasChanged(i) || ignoreNestedChangesMask) @@ -3165,7 +3525,7 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha } } } - if (changesMask[19]) + if (changesMask[21]) { for (std::size_t i = 0; i < SpellFlatModByLabel.size(); ++i) { @@ -3175,7 +3535,37 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha } } } - if (changesMask[20]) + if (changesMask[22]) + { + for (std::size_t i = 0; i < MawPowers.size(); ++i) + { + if (MawPowers.HasChanged(i) || ignoreNestedChangesMask) + { + MawPowers[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + } + } + } + if (changesMask[23]) + { + for (std::size_t i = 0; i < MultiFloorExploration.size(); ++i) + { + if (MultiFloorExploration.HasChanged(i) || ignoreNestedChangesMask) + { + MultiFloorExploration[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + } + } + } + if (changesMask[24]) + { + for (std::size_t i = 0; i < RecipeProgression.size(); ++i) + { + if (RecipeProgression.HasChanged(i) || ignoreNestedChangesMask) + { + RecipeProgression[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + } + } + } + if (changesMask[25]) { for (std::size_t i = 0; i < ReplayedQuests.size(); ++i) { @@ -3185,7 +3575,7 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha } } } - if (changesMask[21]) + if (changesMask[26]) { for (std::size_t i = 0; i < DisabledSpells.size(); ++i) { @@ -3195,7 +3585,7 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha } } } - if (changesMask[17]) + if (changesMask[19]) { for (std::size_t i = 0; i < CharacterRestrictions.size(); ++i) { @@ -3205,325 +3595,344 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha } } } - if (changesMask[24]) - { - data << FarsightObject; - } - if (changesMask[25]) - { - data << SummonedBattlePetGUID; - } - if (changesMask[26]) - { - data << uint64(Coinage); - } - if (changesMask[27]) - { - data << int32(XP); - } - if (changesMask[28]) - { - data << int32(NextLevelXP); - } if (changesMask[29]) { - data << int32(TrialXP); + data << FarsightObject; } if (changesMask[30]) { - Skill->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + data << SummonedBattlePetGUID; } if (changesMask[31]) { - data << int32(CharacterPoints); + data << uint64(Coinage); } if (changesMask[32]) { - data << int32(MaxTalentTiers); + data << int32(XP); } if (changesMask[33]) { - data << int32(TrackCreatureMask); + data << int32(NextLevelXP); } } if (changesMask[34]) { if (changesMask[35]) { - data << float(MainhandExpertise); + data << int32(TrialXP); } if (changesMask[36]) { - data << float(OffhandExpertise); + Skill->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } if (changesMask[37]) { - data << float(RangedExpertise); + data << int32(CharacterPoints); } if (changesMask[38]) { - data << float(CombatRatingExpertise); + data << int32(MaxTalentTiers); } if (changesMask[39]) { - data << float(BlockPercentage); + data << int32(TrackCreatureMask); } if (changesMask[40]) { - data << float(DodgePercentage); + data << float(MainhandExpertise); } if (changesMask[41]) { - data << float(DodgePercentageFromAttribute); + data << float(OffhandExpertise); } if (changesMask[42]) { - data << float(ParryPercentage); + data << float(RangedExpertise); } if (changesMask[43]) { - data << float(ParryPercentageFromAttribute); + data << float(CombatRatingExpertise); } if (changesMask[44]) { - data << float(CritPercentage); + data << float(BlockPercentage); } if (changesMask[45]) { - data << float(RangedCritPercentage); + data << float(DodgePercentage); } if (changesMask[46]) { - data << float(OffhandCritPercentage); + data << float(DodgePercentageFromAttribute); } if (changesMask[47]) { - data << float(SpellCritPercentage); + data << float(ParryPercentage); } if (changesMask[48]) { - data << int32(ShieldBlock); + data << float(ParryPercentageFromAttribute); } if (changesMask[49]) { - data << float(ShieldBlockCritPercentage); + data << float(CritPercentage); } if (changesMask[50]) { - data << float(Mastery); + data << float(RangedCritPercentage); } if (changesMask[51]) { - data << float(Speed); + data << float(OffhandCritPercentage); } if (changesMask[52]) { - data << float(Avoidance); + data << float(SpellCritPercentage); } if (changesMask[53]) { - data << float(Sturdiness); + data << int32(ShieldBlock); } if (changesMask[54]) { - data << int32(Versatility); + data << float(ShieldBlockCritPercentage); } if (changesMask[55]) { - data << float(VersatilityBonus); + data << float(Mastery); } if (changesMask[56]) { - data << float(PvpPowerDamage); + data << float(Speed); } if (changesMask[57]) { - data << float(PvpPowerHealing); + data << float(Avoidance); } if (changesMask[58]) { - data << int32(ModHealingDonePos); + data << float(Sturdiness); } if (changesMask[59]) { - data << float(ModHealingPercent); + data << int32(Versatility); } if (changesMask[60]) { - data << float(ModHealingDonePercent); + data << float(VersatilityBonus); } if (changesMask[61]) { - data << float(ModPeriodicHealingDonePercent); + data << float(PvpPowerDamage); } if (changesMask[62]) { - data << float(ModSpellPowerPercent); + data << float(PvpPowerHealing); } if (changesMask[63]) { - data << float(ModResiliencePercent); + data << int32(ModHealingDonePos); } if (changesMask[64]) { - data << float(OverrideSpellPowerByAPPercent); + data << float(ModHealingPercent); } if (changesMask[65]) { - data << float(OverrideAPBySpellPowerPercent); + data << float(ModPeriodicHealingDonePercent); } } if (changesMask[66]) { if (changesMask[67]) { - data << int32(ModTargetResistance); + data << float(ModSpellPowerPercent); } if (changesMask[68]) { - data << int32(ModTargetPhysicalResistance); + data << float(ModResiliencePercent); } if (changesMask[69]) { - data << int32(LocalFlags); + data << float(OverrideSpellPowerByAPPercent); } if (changesMask[70]) { - data << uint8(GrantableLevels); + data << float(OverrideAPBySpellPowerPercent); } if (changesMask[71]) { - data << uint8(MultiActionBars); + data << int32(ModTargetResistance); } if (changesMask[72]) { - data << uint8(LifetimeMaxRank); + data << int32(ModTargetPhysicalResistance); } if (changesMask[73]) { - data << uint8(NumRespecs); + data << uint32(LocalFlags); } if (changesMask[74]) { - data << uint32(PvpMedals); + data << uint8(GrantableLevels); } if (changesMask[75]) { - data << uint16(TodayHonorableKills); + data << uint8(MultiActionBars); } if (changesMask[76]) { - data << uint16(YesterdayHonorableKills); + data << uint8(LifetimeMaxRank); } if (changesMask[77]) { - data << uint32(LifetimeHonorableKills); + data << uint8(NumRespecs); } if (changesMask[78]) { - data << int32(WatchedFactionIndex); + data << uint32(PvpMedals); } if (changesMask[79]) { - data << int32(MaxLevel); + data << uint16(TodayHonorableKills); } if (changesMask[80]) { - data << int32(ScalingPlayerLevelDelta); + data << uint16(YesterdayHonorableKills); } if (changesMask[81]) { - data << int32(MaxCreatureScalingLevel); + data << uint32(LifetimeHonorableKills); } if (changesMask[82]) { - data << int32(PetSpellPower); + data << int32(WatchedFactionIndex); } if (changesMask[83]) { - data << float(UiHitModifier); + data << int32(MaxLevel); } if (changesMask[84]) { - data << float(UiSpellHitModifier); + data << int32(ScalingPlayerLevelDelta); } if (changesMask[85]) { - data << int32(HomeRealmTimeOffset); + data << int32(MaxCreatureScalingLevel); } if (changesMask[86]) { - data << float(ModPetHaste); + data << int32(PetSpellPower); } if (changesMask[87]) { - data << uint8(LocalRegenFlags); + data << float(UiHitModifier); } if (changesMask[88]) { - data << uint8(AuraVision); + data << float(UiSpellHitModifier); } if (changesMask[89]) { - data << uint8(NumBackpackSlots); + data << int32(HomeRealmTimeOffset); } if (changesMask[90]) { - data << int32(OverrideSpellsID); + data << float(ModPetHaste); } if (changesMask[91]) { - data << int32(LfgBonusFactionID); + data << int8(JailersTowerLevelMax); } if (changesMask[92]) { - data << uint16(LootSpecID); + data << int8(JailersTowerLevel); } if (changesMask[93]) { - data << uint32(OverrideZonePVPType); + data << uint8(LocalRegenFlags); } if (changesMask[94]) { - data << int32(Honor); + data << uint8(AuraVision); } if (changesMask[95]) { - data << int32(HonorNextLevel); + data << uint8(NumBackpackSlots); } if (changesMask[96]) { - data << int32(PvpRewardAchieved); + data << int32(OverrideSpellsID); } if (changesMask[97]) { - data << int32(PvpTierMaxFromWins); + data << uint16(LootSpecID); } } if (changesMask[98]) { if (changesMask[99]) { - data << int32(PvpLastWeeksRewardAchieved); + data << uint32(OverrideZonePVPType); } if (changesMask[100]) { - data << int32(PvpLastWeeksTierMaxFromWins); + data << BnetAccount; } if (changesMask[101]) { - data << int32(PvpLastWeeksRewardClaimed); + data << uint64(GuildClubMemberID); } if (changesMask[102]) { + data << int32(Honor); + } + if (changesMask[103]) + { + data << int32(HonorNextLevel); + } + if (changesMask[104]) + { + data << int32(PvpRewardAchieved); + } + if (changesMask[105]) + { + data << int32(PvpTierMaxFromWins); + } + if (changesMask[106]) + { + data << int32(PvpLastWeeksRewardAchieved); + } + if (changesMask[107]) + { + data << int32(PvpLastWeeksTierMaxFromWins); + } + if (changesMask[108]) + { + data << int32(PvpLastWeeksRewardClaimed); + } + if (changesMask[109]) + { data << uint8(NumBankSlots); } + if (changesMask[112]) + { + data << int32(UiChromieTimeExpansionID); + } + if (changesMask[113]) + { + data << int32(TransportServerTime); + } } - data.FlushBits(); if (changesMask[98]) { - data.WriteBit(QuestSession.is_initialized()); - if (changesMask[103]) + data.WriteBits(QuestSession.is_initialized(), 1); + if (changesMask[111]) + { + Field_1410->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + } + if (changesMask[110]) { if (QuestSession.is_initialized()) { @@ -3531,157 +3940,161 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& cha } } } - if (changesMask[104]) + if (changesMask[114]) { for (std::size_t i = 0; i < 199; ++i) { - if (changesMask[105 + i]) + if (changesMask[115 + i]) { data << InvSlots[i]; } } } - if (changesMask[304]) + if (changesMask[314]) { for (std::size_t i = 0; i < 2; ++i) { - if (changesMask[305 + i]) + if (changesMask[315 + i]) { data << uint32(TrackResourceMask[i]); } } } - if (changesMask[307]) + if (changesMask[317]) { for (std::size_t i = 0; i < 192; ++i) { - if (changesMask[308 + i]) + if (changesMask[318 + i]) { data << uint64(ExploredZones[i]); } } } - if (changesMask[500]) + if (changesMask[510]) { for (std::size_t i = 0; i < 2; ++i) { - if (changesMask[501 + i]) + if (changesMask[511 + i]) { RestInfo[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } } } - if (changesMask[503]) + if (changesMask[513]) { for (std::size_t i = 0; i < 7; ++i) { - if (changesMask[504 + i]) + if (changesMask[514 + i]) { data << int32(ModDamageDonePos[i]); } - if (changesMask[511 + i]) + if (changesMask[521 + i]) { data << int32(ModDamageDoneNeg[i]); } - if (changesMask[518 + i]) + if (changesMask[528 + i]) { data << float(ModDamageDonePercent[i]); } + if (changesMask[535 + i]) + { + data << float(ModHealingDonePercent[i]); + } } } - if (changesMask[525]) + if (changesMask[542]) { for (std::size_t i = 0; i < 3; ++i) { - if (changesMask[526 + i]) + if (changesMask[543 + i]) { data << float(WeaponDmgMultipliers[i]); } - if (changesMask[529 + i]) + if (changesMask[546 + i]) { data << float(WeaponAtkSpeedMultipliers[i]); } } } - if (changesMask[532]) + if (changesMask[549]) { for (std::size_t i = 0; i < 12; ++i) { - if (changesMask[533 + i]) + if (changesMask[550 + i]) { data << uint32(BuybackPrice[i]); } - if (changesMask[545 + i]) + if (changesMask[562 + i]) { data << uint32(BuybackTimestamp[i]); } } } - if (changesMask[557]) + if (changesMask[574]) { for (std::size_t i = 0; i < 32; ++i) { - if (changesMask[558 + i]) + if (changesMask[575 + i]) { data << int32(CombatRatings[i]); } } } - if (changesMask[597]) + if (changesMask[614]) { for (std::size_t i = 0; i < 4; ++i) { - if (changesMask[598 + i]) + if (changesMask[615 + i]) { data << uint32(NoReagentCostMask[i]); } } } - if (changesMask[602]) + if (changesMask[619]) { for (std::size_t i = 0; i < 2; ++i) { - if (changesMask[603 + i]) + if (changesMask[620 + i]) { data << int32(ProfessionSkillLine[i]); } } } - if (changesMask[605]) + if (changesMask[622]) { for (std::size_t i = 0; i < 4; ++i) { - if (changesMask[606 + i]) + if (changesMask[623 + i]) { data << uint32(BagSlotFlags[i]); } } } - if (changesMask[610]) + if (changesMask[627]) { for (std::size_t i = 0; i < 7; ++i) { - if (changesMask[611 + i]) + if (changesMask[628 + i]) { data << uint32(BankBagSlotFlags[i]); } } } - if (changesMask[618]) + if (changesMask[635]) { for (std::size_t i = 0; i < 875; ++i) { - if (changesMask[619 + i]) + if (changesMask[636 + i]) { data << uint64(QuestCompleted[i]); } } } - if (changesMask[590]) + if (changesMask[607]) { for (std::size_t i = 0; i < 6; ++i) { - if (changesMask[591 + i]) + if (changesMask[608 + i]) { PvpInfo[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } @@ -3709,8 +4122,13 @@ void ActivePlayerData::ClearChangesMask() Base::ClearChangesMask(Transmog); Base::ClearChangesMask(ConditionalTransmog); Base::ClearChangesMask(SelfResSpells); + Base::ClearChangesMask(RuneforgePowers); + Base::ClearChangesMask(TransmogIllusions); Base::ClearChangesMask(SpellPctModByLabel); Base::ClearChangesMask(SpellFlatModByLabel); + Base::ClearChangesMask(MawPowers); + Base::ClearChangesMask(MultiFloorExploration); + Base::ClearChangesMask(RecipeProgression); Base::ClearChangesMask(ReplayedQuests); Base::ClearChangesMask(DisabledSpells); Base::ClearChangesMask(CharacterRestrictions); @@ -3749,7 +4167,6 @@ void ActivePlayerData::ClearChangesMask() Base::ClearChangesMask(PvpPowerHealing); Base::ClearChangesMask(ModHealingDonePos); Base::ClearChangesMask(ModHealingPercent); - Base::ClearChangesMask(ModHealingDonePercent); Base::ClearChangesMask(ModPeriodicHealingDonePercent); Base::ClearChangesMask(ModSpellPowerPercent); Base::ClearChangesMask(ModResiliencePercent); @@ -3775,13 +4192,16 @@ void ActivePlayerData::ClearChangesMask() Base::ClearChangesMask(UiSpellHitModifier); Base::ClearChangesMask(HomeRealmTimeOffset); Base::ClearChangesMask(ModPetHaste); + Base::ClearChangesMask(JailersTowerLevelMax); + Base::ClearChangesMask(JailersTowerLevel); Base::ClearChangesMask(LocalRegenFlags); Base::ClearChangesMask(AuraVision); Base::ClearChangesMask(NumBackpackSlots); Base::ClearChangesMask(OverrideSpellsID); - Base::ClearChangesMask(LfgBonusFactionID); Base::ClearChangesMask(LootSpecID); Base::ClearChangesMask(OverrideZonePVPType); + Base::ClearChangesMask(BnetAccount); + Base::ClearChangesMask(GuildClubMemberID); Base::ClearChangesMask(Honor); Base::ClearChangesMask(HonorNextLevel); Base::ClearChangesMask(PvpRewardAchieved); @@ -3790,7 +4210,10 @@ void ActivePlayerData::ClearChangesMask() Base::ClearChangesMask(PvpLastWeeksTierMaxFromWins); Base::ClearChangesMask(PvpLastWeeksRewardClaimed); Base::ClearChangesMask(NumBankSlots); + Base::ClearChangesMask(Field_1410); Base::ClearChangesMask(QuestSession); + Base::ClearChangesMask(UiChromieTimeExpansionID); + Base::ClearChangesMask(TransportServerTime); Base::ClearChangesMask(InvSlots); Base::ClearChangesMask(TrackResourceMask); Base::ClearChangesMask(ExploredZones); @@ -3798,6 +4221,7 @@ void ActivePlayerData::ClearChangesMask() Base::ClearChangesMask(ModDamageDonePos); Base::ClearChangesMask(ModDamageDoneNeg); Base::ClearChangesMask(ModDamageDonePercent); + Base::ClearChangesMask(ModHealingDonePercent); Base::ClearChangesMask(WeaponDmgMultipliers); Base::ClearChangesMask(WeaponAtkSpeedMultipliers); Base::ClearChangesMask(BuybackPrice); @@ -3833,13 +4257,14 @@ void GameObjectData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fie data << float(ParentRotation->z); data << float(ParentRotation->w); data << int32(FactionTemplate); - data << int32(ViewerDependentValue<LevelTag>::GetValue(Level, owner, receiver)); data << int8(ViewerDependentValue<StateTag>::GetValue(State, owner, receiver)); data << int8(TypeID); data << uint8(PercentHealth); data << uint32(ArtKit); data << uint32(EnableDoodadSets.size()); data << uint32(CustomParam); + data << int32(ViewerDependentValue<LevelTag>::GetValue(Level, owner, receiver)); + data << uint32(AnimGroupInstance); for (std::size_t i = 0; i < EnableDoodadSets.size(); ++i) { data << int32(EnableDoodadSets[i]); @@ -3851,9 +4276,9 @@ void GameObjectData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fie WriteUpdate(data, _changesMask, false, owner, receiver); } -void GameObjectData::WriteUpdate(ByteBuffer& data, UpdateMask<20> const& changesMask, bool ignoreNestedChangesMask, GameObject const* owner, Player const* receiver) const +void GameObjectData::WriteUpdate(ByteBuffer& data, UpdateMask<21> const& changesMask, bool ignoreNestedChangesMask, GameObject const* owner, Player const* receiver) const { - data.WriteBits(changesMask.GetBlock(0), 20); + data.WriteBits(changesMask.GetBlock(0), 21); if (changesMask[0]) { @@ -3939,27 +4364,31 @@ void GameObjectData::WriteUpdate(ByteBuffer& data, UpdateMask<20> const& changes } if (changesMask[14]) { - data << int32(ViewerDependentValue<LevelTag>::GetValue(Level, owner, receiver)); + data << int8(ViewerDependentValue<StateTag>::GetValue(State, owner, receiver)); } if (changesMask[15]) { - data << int8(ViewerDependentValue<StateTag>::GetValue(State, owner, receiver)); + data << int8(TypeID); } if (changesMask[16]) { - data << int8(TypeID); + data << uint8(PercentHealth); } if (changesMask[17]) { - data << uint8(PercentHealth); + data << uint32(ArtKit); } if (changesMask[18]) { - data << uint32(ArtKit); + data << uint32(CustomParam); } if (changesMask[19]) { - data << uint32(CustomParam); + data << int32(ViewerDependentValue<LevelTag>::GetValue(Level, owner, receiver)); + } + if (changesMask[20]) + { + data << uint32(AnimGroupInstance); } } } @@ -3979,19 +4408,20 @@ void GameObjectData::ClearChangesMask() Base::ClearChangesMask(Flags); Base::ClearChangesMask(ParentRotation); Base::ClearChangesMask(FactionTemplate); - Base::ClearChangesMask(Level); Base::ClearChangesMask(State); Base::ClearChangesMask(TypeID); Base::ClearChangesMask(PercentHealth); Base::ClearChangesMask(ArtKit); Base::ClearChangesMask(CustomParam); + Base::ClearChangesMask(Level); + Base::ClearChangesMask(AnimGroupInstance); _changesMask.ResetAll(); } void DynamicObjectData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, DynamicObject const* owner, Player const* receiver) const { data << Caster; - data << int32(SpellXSpellVisualID); + SpellVisual->WriteCreate(data, owner, receiver); data << int32(SpellID); data << float(Radius); data << uint32(CastTime); @@ -4016,7 +4446,7 @@ void DynamicObjectData::WriteUpdate(ByteBuffer& data, UpdateMask<7> const& chang } if (changesMask[2]) { - data << int32(SpellXSpellVisualID); + SpellVisual->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } if (changesMask[3]) { @@ -4040,7 +4470,7 @@ void DynamicObjectData::WriteUpdate(ByteBuffer& data, UpdateMask<7> const& chang void DynamicObjectData::ClearChangesMask() { Base::ClearChangesMask(Caster); - Base::ClearChangesMask(SpellXSpellVisualID); + Base::ClearChangesMask(SpellVisual); Base::ClearChangesMask(SpellID); Base::ClearChangesMask(Radius); Base::ClearChangesMask(CastTime); @@ -4062,16 +4492,13 @@ void CorpseData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi data << uint8(Unused); data << uint8(RaceID); data << uint8(Sex); - data << uint8(SkinID); - data << uint8(FaceID); - data << uint8(HairStyleID); - data << uint8(HairColorID); - data << uint8(FacialHairStyleID); + data << uint32(Customizations.size()); data << uint32(Flags); data << int32(FactionTemplate); - for (std::size_t i = 0; i < 3; ++i) + data << uint32(StateSpellVisualKitID); + for (std::size_t i = 0; i < Customizations.size(); ++i) { - data << uint8(CustomDisplayOption[i]); + Customizations[i].WriteCreate(data, owner, receiver); } } @@ -4080,101 +4507,96 @@ void CorpseData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi WriteUpdate(data, _changesMask, false, owner, receiver); } -void CorpseData::WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, bool ignoreNestedChangesMask, Corpse const* owner, Player const* receiver) const +void CorpseData::WriteUpdate(ByteBuffer& data, UpdateMask<33> const& changesMask, bool ignoreNestedChangesMask, Corpse const* owner, Player const* receiver) const { data.WriteBits(changesMask.GetBlocksMask(0), 2); for (std::size_t i = 0; i < 2; ++i) if (changesMask.GetBlock(i)) data.WriteBits(changesMask.GetBlock(i), 32); + if (changesMask[0]) + { + if (changesMask[1]) + { + if (!ignoreNestedChangesMask) + Customizations.WriteUpdateMask(data); + else + WriteCompleteDynamicFieldUpdateMask(Customizations.size(), data); + } + } data.FlushBits(); if (changesMask[0]) { if (changesMask[1]) { - data << uint32(DynamicFlags); + for (std::size_t i = 0; i < Customizations.size(); ++i) + { + if (Customizations.HasChanged(i) || ignoreNestedChangesMask) + { + Customizations[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + } + } } if (changesMask[2]) { - data << Owner; + data << uint32(DynamicFlags); } if (changesMask[3]) { - data << PartyGUID; + data << Owner; } if (changesMask[4]) { - data << GuildGUID; + data << PartyGUID; } if (changesMask[5]) { - data << uint32(DisplayID); + data << GuildGUID; } if (changesMask[6]) { - data << uint8(Unused); + data << uint32(DisplayID); } if (changesMask[7]) { - data << uint8(RaceID); + data << uint8(Unused); } if (changesMask[8]) { - data << uint8(Sex); + data << uint8(RaceID); } if (changesMask[9]) { - data << uint8(SkinID); + data << uint8(Sex); } if (changesMask[10]) { - data << uint8(FaceID); + data << uint32(Flags); } if (changesMask[11]) { - data << uint8(HairStyleID); + data << int32(FactionTemplate); } if (changesMask[12]) { - data << uint8(HairColorID); - } - if (changesMask[13]) - { - data << uint8(FacialHairStyleID); - } - if (changesMask[14]) - { - data << uint32(Flags); - } - if (changesMask[15]) - { - data << int32(FactionTemplate); + data << uint32(StateSpellVisualKitID); } } - if (changesMask[16]) + if (changesMask[13]) { for (std::size_t i = 0; i < 19; ++i) { - if (changesMask[17 + i]) + if (changesMask[14 + i]) { data << uint32(Items[i]); } } } - if (changesMask[36]) - { - for (std::size_t i = 0; i < 3; ++i) - { - if (changesMask[37 + i]) - { - data << uint8(CustomDisplayOption[i]); - } - } - } } void CorpseData::ClearChangesMask() { + Base::ClearChangesMask(Customizations); Base::ClearChangesMask(DynamicFlags); Base::ClearChangesMask(Owner); Base::ClearChangesMask(PartyGUID); @@ -4183,15 +4605,10 @@ void CorpseData::ClearChangesMask() Base::ClearChangesMask(Unused); Base::ClearChangesMask(RaceID); Base::ClearChangesMask(Sex); - Base::ClearChangesMask(SkinID); - Base::ClearChangesMask(FaceID); - Base::ClearChangesMask(HairStyleID); - Base::ClearChangesMask(HairColorID); - Base::ClearChangesMask(FacialHairStyleID); Base::ClearChangesMask(Flags); Base::ClearChangesMask(FactionTemplate); + Base::ClearChangesMask(StateSpellVisualKitID); Base::ClearChangesMask(Items); - Base::ClearChangesMask(CustomDisplayOption); _changesMask.ResetAll(); } @@ -4203,6 +4620,7 @@ void ScaleCurve::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player data << Points[i]; } data << uint32(ParameterCurve); + data.FlushBits(); data.WriteBit(OverrideActive); data.FlushBits(); } @@ -4258,7 +4676,6 @@ void ScaleCurve::ClearChangesMask() void AreaTriggerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, AreaTrigger const* owner, Player const* receiver) const { - OverrideScaleCurve->WriteCreate(data, owner, receiver); data << Caster; data << uint32(Duration); data << uint32(TimeToTarget); @@ -4266,10 +4683,11 @@ void AreaTriggerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fi data << uint32(TimeToTargetExtraScale); data << int32(SpellID); data << int32(SpellForVisuals); - data << int32(SpellXSpellVisualID); + SpellVisual->WriteCreate(data, owner, receiver); data << float(BoundsRadius2D); data << uint32(DecalPropertiesID); data << CreatingEffectGUID; + OverrideScaleCurve->WriteCreate(data, owner, receiver); ExtraScaleCurve->WriteCreate(data, owner, receiver); } @@ -4319,7 +4737,7 @@ void AreaTriggerData::WriteUpdate(ByteBuffer& data, UpdateMask<14> const& change } if (changesMask[10]) { - data << int32(SpellXSpellVisualID); + SpellVisual->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } if (changesMask[11]) { @@ -4351,7 +4769,7 @@ void AreaTriggerData::ClearChangesMask() Base::ClearChangesMask(TimeToTargetExtraScale); Base::ClearChangesMask(SpellID); Base::ClearChangesMask(SpellForVisuals); - Base::ClearChangesMask(SpellXSpellVisualID); + Base::ClearChangesMask(SpellVisual); Base::ClearChangesMask(BoundsRadius2D); Base::ClearChangesMask(DecalPropertiesID); Base::ClearChangesMask(CreatingEffectGUID); @@ -4413,6 +4831,7 @@ void ConversationLine::WriteCreate(ByteBuffer& data, Conversation const* owner, data << int32(UiCameraID); data << uint8(ActorIndex); data << uint8(Flags); + data << uint8(ChatType); } void ConversationLine::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Conversation const* owner, Player const* receiver) const @@ -4422,6 +4841,17 @@ void ConversationLine::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Con data << int32(UiCameraID); data << uint8(ActorIndex); data << uint8(Flags); + data << uint8(ChatType); +} + +bool ConversationLine::operator==(ConversationLine const& right) const +{ + return ConversationLineID == right.ConversationLineID + && StartTime == right.StartTime + && UiCameraID == right.UiCameraID + && ActorIndex == right.ActorIndex + && Flags == right.Flags + && ChatType == right.ChatType; } void ConversationActor::WriteCreate(ByteBuffer& data, Conversation const* owner, Player const* receiver) const @@ -4431,6 +4861,7 @@ void ConversationActor::WriteCreate(ByteBuffer& data, Conversation const* owner, data << ActorGUID; data << int32(Field_18); data.WriteBits(Type, 1); + data.WriteBits(NoActorObject, 1); data.FlushBits(); } @@ -4441,9 +4872,20 @@ void ConversationActor::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Co data << ActorGUID; data << int32(Field_18); data.WriteBits(Type, 1); + data.WriteBits(NoActorObject, 1); data.FlushBits(); } +bool ConversationActor::operator==(ConversationActor const& right) const +{ + return CreatureID == right.CreatureID + && CreatureDisplayInfoID == right.CreatureDisplayInfoID + && ActorGUID == right.ActorGUID + && Field_18 == right.Field_18 + && Type == right.Type + && NoActorObject == right.NoActorObject; +} + void ConversationData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Conversation const* owner, Player const* receiver) const { data << uint32(Lines->size()); diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.h b/src/server/game/Entities/Object/Updates/UpdateFields.h index f2faeffd2c5..787742ac021 100644 --- a/src/server/game/Entities/Object/Updates/UpdateFields.h +++ b/src/server/game/Entities/Object/Updates/UpdateFields.h @@ -66,6 +66,26 @@ struct ItemEnchantment : public IsUpdateFieldStructureTag, public HasChangesMask void ClearChangesMask(); }; +struct ItemMod : public IsUpdateFieldStructureTag +{ + int32 Value; + uint8 Type; + + void WriteCreate(ByteBuffer& data, Item const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Item const* owner, Player const* receiver) const; + bool operator==(ItemMod const& right) const; + bool operator!=(ItemMod const& right) const { return !(*this == right); } +}; + +struct ItemModList : public IsUpdateFieldStructureTag, public HasChangesMask<1> +{ + DynamicUpdateField<UF::ItemMod, 0, 0> Values; + + void WriteCreate(ByteBuffer& data, Item const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Item const* owner, Player const* receiver) const; + void ClearChangesMask(); +}; + struct ArtifactPower : public IsUpdateFieldStructureTag { int16 ArtifactPowerID; @@ -74,6 +94,8 @@ struct ArtifactPower : public IsUpdateFieldStructureTag void WriteCreate(ByteBuffer& data, Item const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Item const* owner, Player const* receiver) const; + bool operator==(ArtifactPower const& right) const; + bool operator!=(ArtifactPower const& right) const { return !(*this == right); } }; struct SocketedGem : public IsUpdateFieldStructureTag, public HasChangesMask<20> @@ -90,23 +112,23 @@ struct SocketedGem : public IsUpdateFieldStructureTag, public HasChangesMask<20> struct ItemData : public IsUpdateFieldStructureTag, public HasChangesMask<40> { UpdateField<std::vector<int32>, 0, 1> BonusListIDs; - DynamicUpdateField<int32, 0, 2> Modifiers; - DynamicUpdateField<UF::ArtifactPower, 0, 3> ArtifactPowers; - DynamicUpdateField<UF::SocketedGem, 0, 4> Gems; - UpdateField<ObjectGuid, 0, 5> Owner; - UpdateField<ObjectGuid, 0, 6> ContainedIn; - UpdateField<ObjectGuid, 0, 7> Creator; - UpdateField<ObjectGuid, 0, 8> GiftCreator; - UpdateField<uint32, 0, 9> StackCount; - UpdateField<uint32, 0, 10> Expiration; - UpdateField<uint32, 0, 11> DynamicFlags; - UpdateField<uint32, 0, 12> Durability; - UpdateField<uint32, 0, 13> MaxDurability; - UpdateField<uint32, 0, 14> CreatePlayedTime; - UpdateField<uint32, 0, 15> ModifiersMask; - UpdateField<int32, 0, 16> Context; - UpdateField<uint64, 0, 17> ArtifactXP; - UpdateField<uint8, 0, 18> ItemAppearanceModID; + DynamicUpdateField<UF::ArtifactPower, 0, 2> ArtifactPowers; + DynamicUpdateField<UF::SocketedGem, 0, 3> Gems; + UpdateField<ObjectGuid, 0, 4> Owner; + UpdateField<ObjectGuid, 0, 5> ContainedIn; + UpdateField<ObjectGuid, 0, 6> Creator; + UpdateField<ObjectGuid, 0, 7> GiftCreator; + UpdateField<uint32, 0, 8> StackCount; + UpdateField<uint32, 0, 9> Expiration; + UpdateField<uint32, 0, 10> DynamicFlags; + UpdateField<uint32, 0, 11> Durability; + UpdateField<uint32, 0, 12> MaxDurability; + UpdateField<uint32, 0, 13> CreatePlayedTime; + UpdateField<int32, 0, 14> Context; + UpdateField<int32, 0, 15> CreateTime; + UpdateField<uint64, 0, 16> ArtifactXP; + UpdateField<uint8, 0, 17> ItemAppearanceModID; + UpdateField<UF::ItemModList, 0, 18> Modifiers; UpdateField<uint32, 0, 19> DynamicFlags2; UpdateFieldArray<int32, 5, 20, 21> SpellCharges; UpdateFieldArray<UF::ItemEnchantment, 13, 26, 27> Enchantment; @@ -147,6 +169,8 @@ struct UnlockedAzeriteEssence : public IsUpdateFieldStructureTag void WriteCreate(ByteBuffer& data, AzeriteItem const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AzeriteItem const* owner, Player const* receiver) const; + bool operator==(UnlockedAzeriteEssence const& right) const; + bool operator!=(UnlockedAzeriteEssence const& right) const { return !(*this == right); } }; struct SelectedAzeriteEssences : public IsUpdateFieldStructureTag, public HasChangesMask<8> @@ -160,39 +184,54 @@ struct SelectedAzeriteEssences : public IsUpdateFieldStructureTag, public HasCha void ClearChangesMask(); }; -struct AzeriteItemData : public IsUpdateFieldStructureTag, public HasChangesMask<9> +struct AzeriteItemData : public IsUpdateFieldStructureTag, public HasChangesMask<10> { - DynamicUpdateField<UF::UnlockedAzeriteEssence, 0, 1> UnlockedEssences; - DynamicUpdateField<uint32, 0, 3> UnlockedEssenceMilestones; - DynamicUpdateField<UF::SelectedAzeriteEssences, 0, 2> SelectedEssences; - UpdateField<uint64, 0, 4> Xp; - UpdateField<uint32, 0, 5> Level; - UpdateField<uint32, 0, 6> AuraLevel; - UpdateField<uint32, 0, 7> KnowledgeLevel; - UpdateField<int32, 0, 8> DEBUGknowledgeWeek; + UpdateField<bool, 0, 1> Enabled; + DynamicUpdateField<UF::UnlockedAzeriteEssence, 0, 2> UnlockedEssences; + DynamicUpdateField<uint32, 0, 4> UnlockedEssenceMilestones; + DynamicUpdateField<UF::SelectedAzeriteEssences, 0, 3> SelectedEssences; + UpdateField<uint64, 0, 5> Xp; + UpdateField<uint32, 0, 6> Level; + UpdateField<uint32, 0, 7> AuraLevel; + UpdateField<uint32, 0, 8> KnowledgeLevel; + UpdateField<int32, 0, 9> DEBUGknowledgeWeek; void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, AzeriteItem const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, AzeriteItem const* owner, Player const* receiver) const; - void WriteUpdate(ByteBuffer& data, UpdateMask<9> const& changesMask, bool ignoreNestedChangesMask, AzeriteItem const* owner, Player const* receiver) const; - void AppendAllowedFieldsMaskForFlag(UpdateMask<9>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; - void FilterDisallowedFieldsMaskForFlag(UpdateMask<9>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; + void WriteUpdate(ByteBuffer& data, UpdateMask<10> const& changesMask, bool ignoreNestedChangesMask, AzeriteItem const* owner, Player const* receiver) const; + void AppendAllowedFieldsMaskForFlag(UpdateMask<10>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; + void FilterDisallowedFieldsMaskForFlag(UpdateMask<10>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; void ClearChangesMask(); }; +struct SpellCastVisual : public IsUpdateFieldStructureTag +{ + int32 SpellXSpellVisualID; + int32 ScriptVisualID; + + void WriteCreate(ByteBuffer& data, Object const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Object const* owner, Player const* receiver) const; + bool operator==(SpellCastVisual const& right) const; + bool operator!=(SpellCastVisual const& right) const { return !(*this == right); } +}; + struct UnitChannel : public IsUpdateFieldStructureTag { int32 SpellID; - int32 SpellXSpellVisualID; + UF::SpellCastVisual SpellVisual; void WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const; + bool operator==(UnitChannel const& right) const; + bool operator!=(UnitChannel const& right) const { return !(*this == right); } }; -struct VisibleItem : public IsUpdateFieldStructureTag, public HasChangesMask<4> +struct VisibleItem : public IsUpdateFieldStructureTag, public HasChangesMask<5> { UpdateField<int32, 0, 1> ItemID; - UpdateField<uint16, 0, 2> ItemAppearanceModID; - UpdateField<uint16, 0, 3> ItemVisual; + UpdateField<int32, 0, 2> ItemModifiedAppearanceID; + UpdateField<uint16, 0, 3> ItemAppearanceModID; + UpdateField<uint16, 0, 4> ItemVisual; void WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const; @@ -206,9 +245,11 @@ struct PassiveSpellHistory : public IsUpdateFieldStructureTag void WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const; + bool operator==(PassiveSpellHistory const& right) const; + bool operator!=(PassiveSpellHistory const& right) const { return !(*this == right); } }; -struct UnitData : public IsUpdateFieldStructureTag, public HasChangesMask<192> +struct UnitData : public IsUpdateFieldStructureTag, public HasChangesMask<196> { UpdateField<std::vector<uint32>, 0, 1> StateWorldEffectIDs; DynamicUpdateField<UF::PassiveSpellHistory, 0, 2> PassiveSpells; @@ -220,136 +261,151 @@ struct UnitData : public IsUpdateFieldStructureTag, public HasChangesMask<192> UpdateField<uint32, 0, 7> StateAnimID; UpdateField<uint32, 0, 8> StateAnimKitID; UpdateField<uint32, 0, 9> StateWorldEffectsQuestObjectiveID; - UpdateField<ObjectGuid, 0, 10> Charm; - UpdateField<ObjectGuid, 0, 11> Summon; - UpdateField<ObjectGuid, 0, 12> Critter; - UpdateField<ObjectGuid, 0, 13> CharmedBy; - UpdateField<ObjectGuid, 0, 14> SummonedBy; - UpdateField<ObjectGuid, 0, 15> CreatedBy; - UpdateField<ObjectGuid, 0, 16> DemonCreator; - UpdateField<ObjectGuid, 0, 17> LookAtControllerTarget; - UpdateField<ObjectGuid, 0, 18> Target; - UpdateField<ObjectGuid, 0, 19> BattlePetCompanionGUID; - UpdateField<uint64, 0, 20> BattlePetDBID; - UpdateField<UF::UnitChannel, 0, 21> ChannelData; - UpdateField<uint32, 0, 22> SummonedByHomeRealm; - UpdateField<uint8, 0, 23> Race; - UpdateField<uint8, 0, 24> ClassId; - UpdateField<uint8, 0, 25> PlayerClassId; - UpdateField<uint8, 0, 26> Sex; - UpdateField<uint8, 0, 27> DisplayPower; - UpdateField<uint32, 0, 28> OverrideDisplayPowerID; - UpdateField<int64, 0, 29> Health; - UpdateField<int64, 0, 30> MaxHealth; - UpdateField<int32, 0, 31> Level; - UpdateField<int32, 32, 33> EffectiveLevel; - UpdateField<int32, 32, 34> ContentTuningID; - UpdateField<int32, 32, 35> ScalingLevelMin; - UpdateField<int32, 32, 36> ScalingLevelMax; - UpdateField<int32, 32, 37> ScalingLevelDelta; - UpdateField<int32, 32, 38> ScalingFactionGroup; - UpdateField<int32, 32, 39> ScalingHealthItemLevelCurveID; - UpdateField<int32, 32, 40> ScalingDamageItemLevelCurveID; - UpdateField<int32, 32, 41> FactionTemplate; + UpdateField<int32, 0, 10> SpellOverrideNameID; + UpdateField<ObjectGuid, 0, 11> Charm; + UpdateField<ObjectGuid, 0, 12> Summon; + UpdateField<ObjectGuid, 0, 13> Critter; + UpdateField<ObjectGuid, 0, 14> CharmedBy; + UpdateField<ObjectGuid, 0, 15> SummonedBy; + UpdateField<ObjectGuid, 0, 16> CreatedBy; + UpdateField<ObjectGuid, 0, 17> DemonCreator; + UpdateField<ObjectGuid, 0, 18> LookAtControllerTarget; + UpdateField<ObjectGuid, 0, 19> Target; + UpdateField<ObjectGuid, 0, 20> BattlePetCompanionGUID; + UpdateField<uint64, 0, 21> BattlePetDBID; + UpdateField<UF::UnitChannel, 0, 22> ChannelData; + UpdateField<uint32, 0, 23> SummonedByHomeRealm; + UpdateField<uint8, 0, 24> Race; + UpdateField<uint8, 0, 25> ClassId; + UpdateField<uint8, 0, 26> PlayerClassId; + UpdateField<uint8, 0, 27> Sex; + UpdateField<uint8, 0, 28> DisplayPower; + UpdateField<uint32, 0, 29> OverrideDisplayPowerID; + UpdateField<int64, 0, 30> Health; + UpdateField<int64, 0, 31> MaxHealth; + UpdateField<int32, 32, 33> Level; + UpdateField<int32, 32, 34> EffectiveLevel; + UpdateField<int32, 32, 35> ContentTuningID; + UpdateField<int32, 32, 36> ScalingLevelMin; + UpdateField<int32, 32, 37> ScalingLevelMax; + UpdateField<int32, 32, 38> ScalingLevelDelta; + UpdateField<int32, 32, 39> ScalingFactionGroup; + UpdateField<int32, 32, 40> ScalingHealthItemLevelCurveID; + UpdateField<int32, 32, 41> ScalingDamageItemLevelCurveID; + UpdateField<int32, 32, 42> FactionTemplate; struct FactionTemplateTag : ViewerDependentValueTag<int32> {}; - UpdateField<uint32, 32, 42> Flags; + UpdateField<uint32, 32, 43> Flags; struct FlagsTag : ViewerDependentValueTag<uint32> {}; - UpdateField<uint32, 32, 43> Flags2; - UpdateField<uint32, 32, 44> Flags3; - UpdateField<uint32, 32, 45> AuraState; + UpdateField<uint32, 32, 44> Flags2; + UpdateField<uint32, 32, 45> Flags3; + UpdateField<uint32, 32, 46> AuraState; struct AuraStateTag : ViewerDependentValueTag<uint32> {}; - UpdateField<uint32, 32, 46> RangedAttackRoundBaseTime; - UpdateField<float, 32, 47> BoundingRadius; - UpdateField<float, 32, 48> CombatReach; - UpdateField<float, 32, 49> DisplayScale; - UpdateField<int32, 32, 50> NativeDisplayID; - UpdateField<float, 32, 51> NativeXDisplayScale; - UpdateField<int32, 32, 52> MountDisplayID; - UpdateField<int32, 32, 53> CosmeticMountDisplayID; - UpdateField<float, 32, 54> MinDamage; - UpdateField<float, 32, 55> MaxDamage; - UpdateField<float, 32, 56> MinOffHandDamage; - UpdateField<float, 32, 57> MaxOffHandDamage; - UpdateField<uint8, 32, 58> StandState; - UpdateField<uint8, 32, 59> PetTalentPoints; - UpdateField<uint8, 32, 60> VisFlags; - UpdateField<uint8, 32, 61> AnimTier; - UpdateField<uint32, 32, 62> PetNumber; - UpdateField<uint32, 32, 63> PetNameTimestamp; - UpdateField<uint32, 64, 65> PetExperience; - UpdateField<uint32, 64, 66> PetNextLevelExperience; - UpdateField<float, 64, 67> ModCastingSpeed; - UpdateField<float, 64, 68> ModSpellHaste; - UpdateField<float, 64, 69> ModHaste; - UpdateField<float, 64, 70> ModRangedHaste; - UpdateField<float, 64, 71> ModHasteRegen; - UpdateField<float, 64, 72> ModTimeRate; - UpdateField<int32, 64, 73> CreatedBySpell; - UpdateField<int32, 64, 74> EmoteState; - UpdateField<int32, 64, 75> BaseMana; - UpdateField<int32, 64, 76> BaseHealth; - UpdateField<uint8, 64, 77> SheatheState; - UpdateField<uint8, 64, 78> PvpFlags; + UpdateField<uint32, 32, 47> RangedAttackRoundBaseTime; + UpdateField<float, 32, 48> BoundingRadius; + UpdateField<float, 32, 49> CombatReach; + UpdateField<float, 32, 50> DisplayScale; + UpdateField<int32, 32, 51> CreatureFamily; + UpdateField<int32, 32, 52> CreatureType; + UpdateField<int32, 32, 53> NativeDisplayID; + UpdateField<float, 32, 54> NativeXDisplayScale; + UpdateField<int32, 32, 55> MountDisplayID; + UpdateField<int32, 32, 56> CosmeticMountDisplayID; + UpdateField<float, 32, 57> MinDamage; + UpdateField<float, 32, 58> MaxDamage; + UpdateField<float, 32, 59> MinOffHandDamage; + UpdateField<float, 32, 60> MaxOffHandDamage; + UpdateField<uint8, 32, 61> StandState; + UpdateField<uint8, 32, 62> PetTalentPoints; + UpdateField<uint8, 32, 63> VisFlags; + UpdateField<uint8, 64, 65> AnimTier; + UpdateField<uint32, 64, 66> PetNumber; + UpdateField<uint32, 64, 67> PetNameTimestamp; + UpdateField<uint32, 64, 68> PetExperience; + UpdateField<uint32, 64, 69> PetNextLevelExperience; + UpdateField<float, 64, 70> ModCastingSpeed; + UpdateField<float, 64, 71> ModCastingSpeedNeg; + UpdateField<float, 64, 72> ModSpellHaste; + UpdateField<float, 64, 73> ModHaste; + UpdateField<float, 64, 74> ModRangedHaste; + UpdateField<float, 64, 75> ModHasteRegen; + UpdateField<float, 64, 76> ModTimeRate; + UpdateField<int32, 64, 77> CreatedBySpell; + UpdateField<int32, 64, 78> EmoteState; + UpdateField<int32, 64, 79> BaseMana; + UpdateField<int32, 64, 80> BaseHealth; + UpdateField<uint8, 64, 81> SheatheState; + UpdateField<uint8, 64, 82> PvpFlags; struct PvpFlagsTag : ViewerDependentValueTag<uint8> {}; - UpdateField<uint8, 64, 79> PetFlags; - UpdateField<uint8, 64, 80> ShapeshiftForm; - UpdateField<int32, 64, 81> AttackPower; - UpdateField<int32, 64, 82> AttackPowerModPos; - UpdateField<int32, 64, 83> AttackPowerModNeg; - UpdateField<float, 64, 84> AttackPowerMultiplier; - UpdateField<int32, 64, 85> RangedAttackPower; - UpdateField<int32, 64, 86> RangedAttackPowerModPos; - UpdateField<int32, 64, 87> RangedAttackPowerModNeg; - UpdateField<float, 64, 88> RangedAttackPowerMultiplier; - UpdateField<int32, 64, 89> MainHandWeaponAttackPower; - UpdateField<int32, 64, 90> OffHandWeaponAttackPower; - UpdateField<int32, 64, 91> RangedWeaponAttackPower; - UpdateField<int32, 64, 92> SetAttackSpeedAura; - UpdateField<float, 64, 93> Lifesteal; - UpdateField<float, 64, 94> MinRangedDamage; - UpdateField<float, 64, 95> MaxRangedDamage; - UpdateField<float, 96, 97> ManaCostModifierModifier; - UpdateField<float, 96, 98> MaxHealthModifier; - UpdateField<float, 96, 99> HoverHeight; - UpdateField<int32, 96, 100> MinItemLevelCutoff; - UpdateField<int32, 96, 101> MinItemLevel; - UpdateField<int32, 96, 102> MaxItemLevel; - UpdateField<int32, 96, 103> AzeriteItemLevel; - UpdateField<int32, 96, 104> WildBattlePetLevel; - UpdateField<uint32, 96, 105> BattlePetCompanionNameTimestamp; - UpdateField<int32, 96, 106> InteractSpellID; - UpdateField<int32, 96, 107> ScaleDuration; - UpdateField<int32, 96, 108> SpellOverrideNameID; - UpdateField<int32, 96, 109> LooksLikeMountID; - UpdateField<int32, 96, 110> LooksLikeCreatureID; - UpdateField<int32, 96, 111> LookAtControllerID; - UpdateField<int32, 96, 112> TaxiNodesID; - UpdateField<ObjectGuid, 96, 113> GuildGUID; - UpdateField<ObjectGuid, 96, 114> SkinningOwnerGUID; - UpdateFieldArray<uint32, 2, 115, 116> NpcFlags; + UpdateField<uint8, 64, 83> PetFlags; + UpdateField<uint8, 64, 84> ShapeshiftForm; + UpdateField<int32, 64, 85> AttackPower; + UpdateField<int32, 64, 86> AttackPowerModPos; + UpdateField<int32, 64, 87> AttackPowerModNeg; + UpdateField<float, 64, 88> AttackPowerMultiplier; + UpdateField<int32, 64, 89> RangedAttackPower; + UpdateField<int32, 64, 90> RangedAttackPowerModPos; + UpdateField<int32, 64, 91> RangedAttackPowerModNeg; + UpdateField<float, 64, 92> RangedAttackPowerMultiplier; + UpdateField<int32, 64, 93> MainHandWeaponAttackPower; + UpdateField<int32, 64, 94> OffHandWeaponAttackPower; + UpdateField<int32, 64, 95> RangedWeaponAttackPower; + UpdateField<int32, 96, 97> SetAttackSpeedAura; + UpdateField<float, 96, 98> Lifesteal; + UpdateField<float, 96, 99> MinRangedDamage; + UpdateField<float, 96, 100> MaxRangedDamage; + UpdateField<float, 96, 101> ManaCostModifierModifier; + UpdateField<float, 96, 102> MaxHealthModifier; + UpdateField<float, 96, 103> HoverHeight; + UpdateField<int32, 96, 104> MinItemLevelCutoff; + UpdateField<int32, 96, 105> MinItemLevel; + UpdateField<int32, 96, 106> MaxItemLevel; + UpdateField<int32, 96, 107> AzeriteItemLevel; + UpdateField<int32, 96, 108> WildBattlePetLevel; + UpdateField<uint32, 96, 109> BattlePetCompanionNameTimestamp; + UpdateField<int32, 96, 110> InteractSpellID; + UpdateField<int32, 96, 111> ScaleDuration; + UpdateField<int32, 96, 112> LooksLikeMountID; + UpdateField<int32, 96, 113> LooksLikeCreatureID; + UpdateField<int32, 96, 114> LookAtControllerID; + UpdateField<int32, 96, 115> TaxiNodesID; + UpdateField<ObjectGuid, 96, 116> GuildGUID; + UpdateField<ObjectGuid, 96, 117> SkinningOwnerGUID; + UpdateField<uint32, 96, 118> SilencedSchoolMask; + UpdateFieldArray<uint32, 2, 119, 120> NpcFlags; struct NpcFlagsTag : ViewerDependentValueTag<uint32> {}; - UpdateFieldArray<int32, 6, 118, 119> Power; - UpdateFieldArray<int32, 6, 118, 125> MaxPower; - UpdateFieldArray<float, 6, 118, 131> PowerRegenFlatModifier; - UpdateFieldArray<float, 6, 118, 137> PowerRegenInterruptedFlatModifier; - UpdateFieldArray<UF::VisibleItem, 3, 143, 144> VirtualItems; - UpdateFieldArray<uint32, 2, 147, 148> AttackRoundBaseTime; - UpdateFieldArray<int32, 4, 150, 151> Stats; - UpdateFieldArray<int32, 4, 150, 155> StatPosBuff; - UpdateFieldArray<int32, 4, 150, 159> StatNegBuff; - UpdateFieldArray<int32, 7, 163, 164> Resistances; - UpdateFieldArray<int32, 7, 163, 171> BonusResistanceMods; - UpdateFieldArray<int32, 7, 163, 178> PowerCostModifier; - UpdateFieldArray<float, 7, 163, 185> PowerCostMultiplier; + UpdateFieldArray<int32, 6, 122, 123> Power; + UpdateFieldArray<int32, 6, 122, 129> MaxPower; + UpdateFieldArray<float, 6, 122, 135> PowerRegenFlatModifier; + UpdateFieldArray<float, 6, 122, 141> PowerRegenInterruptedFlatModifier; + UpdateFieldArray<UF::VisibleItem, 3, 147, 148> VirtualItems; + UpdateFieldArray<uint32, 2, 151, 152> AttackRoundBaseTime; + UpdateFieldArray<int32, 4, 154, 155> Stats; + UpdateFieldArray<int32, 4, 154, 159> StatPosBuff; + UpdateFieldArray<int32, 4, 154, 163> StatNegBuff; + UpdateFieldArray<int32, 7, 167, 168> Resistances; + UpdateFieldArray<int32, 7, 167, 175> BonusResistanceMods; + UpdateFieldArray<int32, 7, 167, 182> PowerCostModifier; + UpdateFieldArray<float, 7, 167, 189> PowerCostMultiplier; void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Unit const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Unit const* owner, Player const* receiver) const; - void WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMask, bool ignoreNestedChangesMask, Unit const* owner, Player const* receiver) const; - void AppendAllowedFieldsMaskForFlag(UpdateMask<192>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; - void FilterDisallowedFieldsMaskForFlag(UpdateMask<192>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; + void WriteUpdate(ByteBuffer& data, UpdateMask<196> const& changesMask, bool ignoreNestedChangesMask, Unit const* owner, Player const* receiver) const; + void AppendAllowedFieldsMaskForFlag(UpdateMask<196>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; + void FilterDisallowedFieldsMaskForFlag(UpdateMask<196>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; void ClearChangesMask(); }; +struct ChrCustomizationChoice : public IsUpdateFieldStructureTag +{ + uint32 ChrCustomizationOptionID; + uint32 ChrCustomizationChoiceID; + + void WriteCreate(ByteBuffer& data, Object const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Object const* owner, Player const* receiver) const; + bool operator==(ChrCustomizationChoice const& right) const; + bool operator!=(ChrCustomizationChoice const& right) const { return !(*this == right); } +}; + struct QuestLog : public IsUpdateFieldStructureTag, public HasChangesMask<31> { UpdateField<int32, 0, 1> QuestID; @@ -379,53 +435,61 @@ struct ArenaCooldown : public IsUpdateFieldStructureTag, public HasChangesMask<8 void ClearChangesMask(); }; -struct PlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<192> +struct CTROptions : public IsUpdateFieldStructureTag +{ + int32 ContentTuningConditionMask; + uint32 Field_4; + uint32 ExpansionLevelMask; + + void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + bool operator==(CTROptions const& right) const; + bool operator!=(CTROptions const& right) const { return !(*this == right); } +}; + +struct PlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<185> { UpdateField<bool, 0, 1> HasQuestSession; UpdateField<bool, 0, 2> HasLevelLink; - DynamicUpdateField<UF::QuestLog, 0, 3> QuestSessionQuestLog; - DynamicUpdateField<UF::ArenaCooldown, 0, 4> ArenaCooldowns; - UpdateField<ObjectGuid, 0, 5> DuelArbiter; - UpdateField<ObjectGuid, 0, 6> WowAccount; - UpdateField<ObjectGuid, 0, 7> LootTargetGUID; - UpdateField<uint32, 0, 8> PlayerFlags; - UpdateField<uint32, 0, 9> PlayerFlagsEx; - UpdateField<uint32, 0, 10> GuildRankID; - UpdateField<uint32, 0, 11> GuildDeleteDate; - UpdateField<int32, 0, 12> GuildLevel; - UpdateField<uint8, 0, 13> SkinID; - UpdateField<uint8, 0, 14> FaceID; - UpdateField<uint8, 0, 15> HairStyleID; - UpdateField<uint8, 0, 16> HairColorID; - UpdateField<uint8, 0, 17> FacialHairStyleID; - UpdateField<uint8, 0, 18> PartyType; - UpdateField<uint8, 0, 19> NativeSex; - UpdateField<uint8, 0, 20> Inebriation; - UpdateField<uint8, 0, 21> PvpTitle; - UpdateField<uint8, 0, 22> ArenaFaction; - UpdateField<uint32, 0, 23> DuelTeam; - UpdateField<int32, 0, 24> GuildTimeStamp; - UpdateField<int32, 0, 25> PlayerTitle; - UpdateField<int32, 0, 26> FakeInebriation; - UpdateField<uint32, 0, 27> VirtualPlayerRealm; - UpdateField<uint32, 0, 28> CurrentSpecID; - UpdateField<int32, 0, 29> TaxiMountAnimKitID; - UpdateField<uint8, 0, 30> CurrentBattlePetBreedQuality; - UpdateField<int32, 0, 31> HonorLevel; - UpdateField<int32, 32, 33> Field_B0; - UpdateField<int32, 32, 34> Field_B4; - UpdateField<ObjectGuid, 32, 35> Field_F8; - UpdateField<int32, 32, 36> Field_108; - UpdateFieldArray<uint8, 3, 37, 38> CustomDisplayOption; - UpdateFieldArray<UF::QuestLog, 125, 41, 42> QuestLog; - UpdateFieldArray<UF::VisibleItem, 19, 167, 168> VisibleItems; - UpdateFieldArray<float, 4, 187, 188> AvgItemLevel; + DynamicUpdateField<UF::ChrCustomizationChoice, 0, 3> Customizations; + DynamicUpdateField<UF::QuestLog, 0, 4> QuestSessionQuestLog; + DynamicUpdateField<UF::ArenaCooldown, 0, 5> ArenaCooldowns; + UpdateField<ObjectGuid, 0, 6> DuelArbiter; + UpdateField<ObjectGuid, 0, 7> WowAccount; + UpdateField<ObjectGuid, 0, 8> LootTargetGUID; + UpdateField<uint32, 0, 9> PlayerFlags; + UpdateField<uint32, 0, 10> PlayerFlagsEx; + UpdateField<uint32, 0, 11> GuildRankID; + UpdateField<uint32, 0, 12> GuildDeleteDate; + UpdateField<int32, 0, 13> GuildLevel; + UpdateField<uint8, 0, 14> PartyType; + UpdateField<uint8, 0, 15> NativeSex; + UpdateField<uint8, 0, 16> Inebriation; + UpdateField<uint8, 0, 17> PvpTitle; + UpdateField<uint8, 0, 18> ArenaFaction; + UpdateField<uint32, 0, 19> DuelTeam; + UpdateField<int32, 0, 20> GuildTimeStamp; + UpdateField<int32, 0, 21> PlayerTitle; + UpdateField<int32, 0, 22> FakeInebriation; + UpdateField<uint32, 0, 23> VirtualPlayerRealm; + UpdateField<uint32, 0, 24> CurrentSpecID; + UpdateField<int32, 0, 25> TaxiMountAnimKitID; + UpdateField<uint8, 0, 26> CurrentBattlePetBreedQuality; + UpdateField<int32, 0, 27> HonorLevel; + UpdateField<int32, 0, 28> Field_B0; + UpdateField<int32, 0, 29> Field_B4; + UpdateField<UF::CTROptions, 0, 30> CtrOptions; + UpdateField<int32, 0, 31> CovenantID; + UpdateField<int32, 32, 33> SoulbindID; + UpdateFieldArray<UF::QuestLog, 125, 34, 35> QuestLog; + UpdateFieldArray<UF::VisibleItem, 19, 160, 161> VisibleItems; + UpdateFieldArray<float, 4, 180, 181> AvgItemLevel; void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const; - void WriteUpdate(ByteBuffer& data, UpdateMask<192> const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const; - void AppendAllowedFieldsMaskForFlag(UpdateMask<192>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; - void FilterDisallowedFieldsMaskForFlag(UpdateMask<192>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; + void WriteUpdate(ByteBuffer& data, UpdateMask<185> const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const; + void AppendAllowedFieldsMaskForFlag(UpdateMask<185>& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; + void FilterDisallowedFieldsMaskForFlag(UpdateMask<185>& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags) const; void ClearChangesMask(); bool IsQuestLogChangesMaskSkipped() const { return false; } // bandwidth savings aren't worth the cpu time }; @@ -481,6 +545,8 @@ struct CharacterRestriction : public IsUpdateFieldStructureTag void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + bool operator==(CharacterRestriction const& right) const; + bool operator!=(CharacterRestriction const& right) const { return !(*this == right); } }; struct SpellPctModByLabel : public IsUpdateFieldStructureTag @@ -491,6 +557,8 @@ struct SpellPctModByLabel : public IsUpdateFieldStructureTag void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + bool operator==(SpellPctModByLabel const& right) const; + bool operator!=(SpellPctModByLabel const& right) const { return !(*this == right); } }; struct SpellFlatModByLabel : public IsUpdateFieldStructureTag @@ -501,6 +569,8 @@ struct SpellFlatModByLabel : public IsUpdateFieldStructureTag void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + bool operator==(SpellFlatModByLabel const& right) const; + bool operator!=(SpellFlatModByLabel const& right) const { return !(*this == right); } }; struct Research : public IsUpdateFieldStructureTag @@ -509,12 +579,47 @@ struct Research : public IsUpdateFieldStructureTag void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + bool operator==(Research const& right) const; + bool operator!=(Research const& right) const { return !(*this == right); } }; -struct ReplayedQuest : public IsUpdateFieldStructureTag, public HasChangesMask<3> +struct MawPower : public IsUpdateFieldStructureTag { - UpdateField<int32, 0, 1> QuestID; - UpdateField<uint32, 0, 2> ReplayTime; + int32 Field_0; + int32 Field_4; + int32 Field_8; + + void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + bool operator==(MawPower const& right) const; + bool operator!=(MawPower const& right) const { return !(*this == right); } +}; + +struct MultiFloorExplore : public IsUpdateFieldStructureTag +{ + std::vector<int32> WorldMapOverlayIDs; + + void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + bool operator==(MultiFloorExplore const& right) const; + bool operator!=(MultiFloorExplore const& right) const { return !(*this == right); } +}; + +struct RecipeProgressionInfo : public IsUpdateFieldStructureTag +{ + uint16 RecipeProgressionGroupID; + uint16 Experience; + + void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + bool operator==(RecipeProgressionInfo const& right) const; + bool operator!=(RecipeProgressionInfo const& right) const { return !(*this == right); } +}; + +struct ActivePlayerUnk901 : public IsUpdateFieldStructureTag, public HasChangesMask<3> +{ + UpdateField<ObjectGuid, 0, 1> Field_0; + UpdateField<int32, 0, 2> Field_10; void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; @@ -531,13 +636,23 @@ struct QuestSession : public IsUpdateFieldStructureTag, public HasChangesMask<87 void ClearChangesMask(); }; -struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<1494> +struct ReplayedQuest : public IsUpdateFieldStructureTag, public HasChangesMask<3> +{ + UpdateField<int32, 0, 1> QuestID; + UpdateField<uint32, 0, 2> ReplayTime; + + void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const; + void ClearChangesMask(); +}; + +struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<1511> { UpdateField<bool, 0, 1> BackpackAutoSortDisabled; UpdateField<bool, 0, 2> BankAutoSortDisabled; UpdateField<bool, 0, 3> SortBagsRightToLeft; UpdateField<bool, 0, 4> InsertItemsLeftToRight; - UpdateFieldArray<DynamicUpdateFieldBase<UF::Research>, 1, 22, 23> Research; + UpdateFieldArray<DynamicUpdateFieldBase<UF::Research>, 1, 27, 28> Research; DynamicUpdateField<uint64, 0, 5> KnownTitles; DynamicUpdateField<uint16, 0, 6> ResearchSites; DynamicUpdateField<uint32, 0, 7> ResearchSiteProgress; @@ -550,114 +665,125 @@ struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMas DynamicUpdateField<uint32, 0, 14> Transmog; DynamicUpdateField<int32, 0, 15> ConditionalTransmog; DynamicUpdateField<int32, 0, 16> SelfResSpells; - DynamicUpdateField<UF::SpellPctModByLabel, 0, 18> SpellPctModByLabel; - DynamicUpdateField<UF::SpellFlatModByLabel, 0, 19> SpellFlatModByLabel; - DynamicUpdateField<UF::ReplayedQuest, 0, 20> ReplayedQuests; - DynamicUpdateField<int32, 0, 21> DisabledSpells; - DynamicUpdateField<UF::CharacterRestriction, 0, 17> CharacterRestrictions; - UpdateField<ObjectGuid, 0, 24> FarsightObject; - UpdateField<ObjectGuid, 0, 25> SummonedBattlePetGUID; - UpdateField<uint64, 0, 26> Coinage; - UpdateField<int32, 0, 27> XP; - UpdateField<int32, 0, 28> NextLevelXP; - UpdateField<int32, 0, 29> TrialXP; - UpdateField<UF::SkillInfo, 0, 30> Skill; - UpdateField<int32, 0, 31> CharacterPoints; - UpdateField<int32, 0, 32> MaxTalentTiers; - UpdateField<int32, 0, 33> TrackCreatureMask; - UpdateField<float, 34, 35> MainhandExpertise; - UpdateField<float, 34, 36> OffhandExpertise; - UpdateField<float, 34, 37> RangedExpertise; - UpdateField<float, 34, 38> CombatRatingExpertise; - UpdateField<float, 34, 39> BlockPercentage; - UpdateField<float, 34, 40> DodgePercentage; - UpdateField<float, 34, 41> DodgePercentageFromAttribute; - UpdateField<float, 34, 42> ParryPercentage; - UpdateField<float, 34, 43> ParryPercentageFromAttribute; - UpdateField<float, 34, 44> CritPercentage; - UpdateField<float, 34, 45> RangedCritPercentage; - UpdateField<float, 34, 46> OffhandCritPercentage; - UpdateField<float, 34, 47> SpellCritPercentage; - UpdateField<int32, 34, 48> ShieldBlock; - UpdateField<float, 34, 49> ShieldBlockCritPercentage; - UpdateField<float, 34, 50> Mastery; - UpdateField<float, 34, 51> Speed; - UpdateField<float, 34, 52> Avoidance; - UpdateField<float, 34, 53> Sturdiness; - UpdateField<int32, 34, 54> Versatility; - UpdateField<float, 34, 55> VersatilityBonus; - UpdateField<float, 34, 56> PvpPowerDamage; - UpdateField<float, 34, 57> PvpPowerHealing; - UpdateField<int32, 34, 58> ModHealingDonePos; - UpdateField<float, 34, 59> ModHealingPercent; - UpdateField<float, 34, 60> ModHealingDonePercent; - UpdateField<float, 34, 61> ModPeriodicHealingDonePercent; - UpdateField<float, 34, 62> ModSpellPowerPercent; - UpdateField<float, 34, 63> ModResiliencePercent; - UpdateField<float, 34, 64> OverrideSpellPowerByAPPercent; - UpdateField<float, 34, 65> OverrideAPBySpellPowerPercent; - UpdateField<int32, 66, 67> ModTargetResistance; - UpdateField<int32, 66, 68> ModTargetPhysicalResistance; - UpdateField<int32, 66, 69> LocalFlags; - UpdateField<uint8, 66, 70> GrantableLevels; - UpdateField<uint8, 66, 71> MultiActionBars; - UpdateField<uint8, 66, 72> LifetimeMaxRank; - UpdateField<uint8, 66, 73> NumRespecs; - UpdateField<uint32, 66, 74> PvpMedals; - UpdateField<uint16, 66, 75> TodayHonorableKills; - UpdateField<uint16, 66, 76> YesterdayHonorableKills; - UpdateField<uint32, 66, 77> LifetimeHonorableKills; - UpdateField<int32, 66, 78> WatchedFactionIndex; - UpdateField<int32, 66, 79> MaxLevel; - UpdateField<int32, 66, 80> ScalingPlayerLevelDelta; - UpdateField<int32, 66, 81> MaxCreatureScalingLevel; - UpdateField<int32, 66, 82> PetSpellPower; - UpdateField<float, 66, 83> UiHitModifier; - UpdateField<float, 66, 84> UiSpellHitModifier; - UpdateField<int32, 66, 85> HomeRealmTimeOffset; - UpdateField<float, 66, 86> ModPetHaste; - UpdateField<uint8, 66, 87> LocalRegenFlags; - UpdateField<uint8, 66, 88> AuraVision; - UpdateField<uint8, 66, 89> NumBackpackSlots; - UpdateField<int32, 66, 90> OverrideSpellsID; - UpdateField<int32, 66, 91> LfgBonusFactionID; - UpdateField<uint16, 66, 92> LootSpecID; - UpdateField<uint32, 66, 93> OverrideZonePVPType; - UpdateField<int32, 66, 94> Honor; - UpdateField<int32, 66, 95> HonorNextLevel; - UpdateField<int32, 66, 96> PvpRewardAchieved; - UpdateField<int32, 66, 97> PvpTierMaxFromWins; - UpdateField<int32, 98, 99> PvpLastWeeksRewardAchieved; - UpdateField<int32, 98, 100> PvpLastWeeksTierMaxFromWins; - UpdateField<int32, 98, 101> PvpLastWeeksRewardClaimed; - UpdateField<uint8, 98, 102> NumBankSlots; - OptionalUpdateField<UF::QuestSession, 98, 103> QuestSession; - UpdateFieldArray<ObjectGuid, 199, 104, 105> InvSlots; - UpdateFieldArray<uint32, 2, 304, 305> TrackResourceMask; - UpdateFieldArray<uint64, 192, 307, 308> ExploredZones; - UpdateFieldArray<UF::RestInfo, 2, 500, 501> RestInfo; - UpdateFieldArray<int32, 7, 503, 504> ModDamageDonePos; - UpdateFieldArray<int32, 7, 503, 511> ModDamageDoneNeg; - UpdateFieldArray<float, 7, 503, 518> ModDamageDonePercent; - UpdateFieldArray<float, 3, 525, 526> WeaponDmgMultipliers; - UpdateFieldArray<float, 3, 525, 529> WeaponAtkSpeedMultipliers; - UpdateFieldArray<uint32, 12, 532, 533> BuybackPrice; - UpdateFieldArray<uint32, 12, 532, 545> BuybackTimestamp; - UpdateFieldArray<int32, 32, 557, 558> CombatRatings; - UpdateFieldArray<UF::PVPInfo, 6, 590, 591> PvpInfo; - UpdateFieldArray<uint32, 4, 597, 598> NoReagentCostMask; - UpdateFieldArray<int32, 2, 602, 603> ProfessionSkillLine; - UpdateFieldArray<uint32, 4, 605, 606> BagSlotFlags; - UpdateFieldArray<uint32, 7, 610, 611> BankBagSlotFlags; - UpdateFieldArray<uint64, 875, 618, 619> QuestCompleted; + DynamicUpdateField<uint32, 0, 17> RuneforgePowers; + DynamicUpdateField<uint32, 0, 18> TransmogIllusions; + DynamicUpdateField<UF::SpellPctModByLabel, 0, 20> SpellPctModByLabel; + DynamicUpdateField<UF::SpellFlatModByLabel, 0, 21> SpellFlatModByLabel; + DynamicUpdateField<UF::MawPower, 0, 22> MawPowers; + DynamicUpdateField<UF::MultiFloorExplore, 0, 23> MultiFloorExploration; + DynamicUpdateField<UF::RecipeProgressionInfo, 0, 24> RecipeProgression; + DynamicUpdateField<UF::ReplayedQuest, 0, 25> ReplayedQuests; + DynamicUpdateField<int32, 0, 26> DisabledSpells; + DynamicUpdateField<UF::CharacterRestriction, 0, 19> CharacterRestrictions; + UpdateField<ObjectGuid, 0, 29> FarsightObject; + UpdateField<ObjectGuid, 0, 30> SummonedBattlePetGUID; + UpdateField<uint64, 0, 31> Coinage; + UpdateField<int32, 0, 32> XP; + UpdateField<int32, 0, 33> NextLevelXP; + UpdateField<int32, 34, 35> TrialXP; + UpdateField<UF::SkillInfo, 34, 36> Skill; + UpdateField<int32, 34, 37> CharacterPoints; + UpdateField<int32, 34, 38> MaxTalentTiers; + UpdateField<int32, 34, 39> TrackCreatureMask; + UpdateField<float, 34, 40> MainhandExpertise; + UpdateField<float, 34, 41> OffhandExpertise; + UpdateField<float, 34, 42> RangedExpertise; + UpdateField<float, 34, 43> CombatRatingExpertise; + UpdateField<float, 34, 44> BlockPercentage; + UpdateField<float, 34, 45> DodgePercentage; + UpdateField<float, 34, 46> DodgePercentageFromAttribute; + UpdateField<float, 34, 47> ParryPercentage; + UpdateField<float, 34, 48> ParryPercentageFromAttribute; + UpdateField<float, 34, 49> CritPercentage; + UpdateField<float, 34, 50> RangedCritPercentage; + UpdateField<float, 34, 51> OffhandCritPercentage; + UpdateField<float, 34, 52> SpellCritPercentage; + UpdateField<int32, 34, 53> ShieldBlock; + UpdateField<float, 34, 54> ShieldBlockCritPercentage; + UpdateField<float, 34, 55> Mastery; + UpdateField<float, 34, 56> Speed; + UpdateField<float, 34, 57> Avoidance; + UpdateField<float, 34, 58> Sturdiness; + UpdateField<int32, 34, 59> Versatility; + UpdateField<float, 34, 60> VersatilityBonus; + UpdateField<float, 34, 61> PvpPowerDamage; + UpdateField<float, 34, 62> PvpPowerHealing; + UpdateField<int32, 34, 63> ModHealingDonePos; + UpdateField<float, 34, 64> ModHealingPercent; + UpdateField<float, 34, 65> ModPeriodicHealingDonePercent; + UpdateField<float, 66, 67> ModSpellPowerPercent; + UpdateField<float, 66, 68> ModResiliencePercent; + UpdateField<float, 66, 69> OverrideSpellPowerByAPPercent; + UpdateField<float, 66, 70> OverrideAPBySpellPowerPercent; + UpdateField<int32, 66, 71> ModTargetResistance; + UpdateField<int32, 66, 72> ModTargetPhysicalResistance; + UpdateField<uint32, 66, 73> LocalFlags; + UpdateField<uint8, 66, 74> GrantableLevels; + UpdateField<uint8, 66, 75> MultiActionBars; + UpdateField<uint8, 66, 76> LifetimeMaxRank; + UpdateField<uint8, 66, 77> NumRespecs; + UpdateField<uint32, 66, 78> PvpMedals; + UpdateField<uint16, 66, 79> TodayHonorableKills; + UpdateField<uint16, 66, 80> YesterdayHonorableKills; + UpdateField<uint32, 66, 81> LifetimeHonorableKills; + UpdateField<int32, 66, 82> WatchedFactionIndex; + UpdateField<int32, 66, 83> MaxLevel; + UpdateField<int32, 66, 84> ScalingPlayerLevelDelta; + UpdateField<int32, 66, 85> MaxCreatureScalingLevel; + UpdateField<int32, 66, 86> PetSpellPower; + UpdateField<float, 66, 87> UiHitModifier; + UpdateField<float, 66, 88> UiSpellHitModifier; + UpdateField<int32, 66, 89> HomeRealmTimeOffset; + UpdateField<float, 66, 90> ModPetHaste; + UpdateField<int8, 66, 91> JailersTowerLevelMax; + UpdateField<int8, 66, 92> JailersTowerLevel; + UpdateField<uint8, 66, 93> LocalRegenFlags; + UpdateField<uint8, 66, 94> AuraVision; + UpdateField<uint8, 66, 95> NumBackpackSlots; + UpdateField<int32, 66, 96> OverrideSpellsID; + UpdateField<uint16, 66, 97> LootSpecID; + UpdateField<uint32, 98, 99> OverrideZonePVPType; + UpdateField<ObjectGuid, 98, 100> BnetAccount; + UpdateField<uint64, 98, 101> GuildClubMemberID; + UpdateField<int32, 98, 102> Honor; + UpdateField<int32, 98, 103> HonorNextLevel; + UpdateField<int32, 98, 104> PvpRewardAchieved; + UpdateField<int32, 98, 105> PvpTierMaxFromWins; + UpdateField<int32, 98, 106> PvpLastWeeksRewardAchieved; + UpdateField<int32, 98, 107> PvpLastWeeksTierMaxFromWins; + UpdateField<int32, 98, 108> PvpLastWeeksRewardClaimed; + UpdateField<uint8, 98, 109> NumBankSlots; + UpdateField<UF::ActivePlayerUnk901, 98, 111> Field_1410; + OptionalUpdateField<UF::QuestSession, 98, 110> QuestSession; + UpdateField<int32, 98, 112> UiChromieTimeExpansionID; + UpdateField<int32, 98, 113> TransportServerTime; + UpdateFieldArray<ObjectGuid, 199, 114, 115> InvSlots; + UpdateFieldArray<uint32, 2, 314, 315> TrackResourceMask; + UpdateFieldArray<uint64, 192, 317, 318> ExploredZones; + UpdateFieldArray<UF::RestInfo, 2, 510, 511> RestInfo; + UpdateFieldArray<int32, 7, 513, 514> ModDamageDonePos; + UpdateFieldArray<int32, 7, 513, 521> ModDamageDoneNeg; + UpdateFieldArray<float, 7, 513, 528> ModDamageDonePercent; + UpdateFieldArray<float, 7, 513, 535> ModHealingDonePercent; + UpdateFieldArray<float, 3, 542, 543> WeaponDmgMultipliers; + UpdateFieldArray<float, 3, 542, 546> WeaponAtkSpeedMultipliers; + UpdateFieldArray<uint32, 12, 549, 550> BuybackPrice; + UpdateFieldArray<uint32, 12, 549, 562> BuybackTimestamp; + UpdateFieldArray<int32, 32, 574, 575> CombatRatings; + UpdateFieldArray<UF::PVPInfo, 6, 607, 608> PvpInfo; + UpdateFieldArray<uint32, 4, 614, 615> NoReagentCostMask; + UpdateFieldArray<int32, 2, 619, 620> ProfessionSkillLine; + UpdateFieldArray<uint32, 4, 622, 623> BagSlotFlags; + UpdateFieldArray<uint32, 7, 627, 628> BankBagSlotFlags; + UpdateFieldArray<uint64, 875, 635, 636> QuestCompleted; void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const; - void WriteUpdate(ByteBuffer& data, UpdateMask<1494> const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, UpdateMask<1511> const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const; void ClearChangesMask(); }; -struct GameObjectData : public IsUpdateFieldStructureTag, public HasChangesMask<20> +struct GameObjectData : public IsUpdateFieldStructureTag, public HasChangesMask<21> { UpdateField<std::vector<uint32>, 0, 1> StateWorldEffectIDs; DynamicUpdateField<int32, 0, 2> EnableDoodadSets; @@ -673,25 +799,26 @@ struct GameObjectData : public IsUpdateFieldStructureTag, public HasChangesMask< struct FlagsTag : ViewerDependentValueTag<uint32> {}; UpdateField<QuaternionData, 0, 12> ParentRotation; UpdateField<int32, 0, 13> FactionTemplate; - UpdateField<int32, 0, 14> Level; - struct LevelTag : ViewerDependentValueTag<int32> {}; - UpdateField<int8, 0, 15> State; + UpdateField<int8, 0, 14> State; struct StateTag : ViewerDependentValueTag<int8> {}; - UpdateField<int8, 0, 16> TypeID; - UpdateField<uint8, 0, 17> PercentHealth; - UpdateField<uint32, 0, 18> ArtKit; - UpdateField<uint32, 0, 19> CustomParam; + UpdateField<int8, 0, 15> TypeID; + UpdateField<uint8, 0, 16> PercentHealth; + UpdateField<uint32, 0, 17> ArtKit; + UpdateField<uint32, 0, 18> CustomParam; + UpdateField<int32, 0, 19> Level; + struct LevelTag : ViewerDependentValueTag<int32> {}; + UpdateField<uint32, 0, 20> AnimGroupInstance; void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, GameObject const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, GameObject const* owner, Player const* receiver) const; - void WriteUpdate(ByteBuffer& data, UpdateMask<20> const& changesMask, bool ignoreNestedChangesMask, GameObject const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, UpdateMask<21> const& changesMask, bool ignoreNestedChangesMask, GameObject const* owner, Player const* receiver) const; void ClearChangesMask(); }; struct DynamicObjectData : public IsUpdateFieldStructureTag, public HasChangesMask<7> { UpdateField<ObjectGuid, 0, 1> Caster; - UpdateField<int32, 0, 2> SpellXSpellVisualID; + UpdateField<UF::SpellCastVisual, 0, 2> SpellVisual; UpdateField<int32, 0, 3> SpellID; UpdateField<float, 0, 4> Radius; UpdateField<uint32, 0, 5> CastTime; @@ -703,29 +830,25 @@ struct DynamicObjectData : public IsUpdateFieldStructureTag, public HasChangesMa void ClearChangesMask(); }; -struct CorpseData : public IsUpdateFieldStructureTag, public HasChangesMask<40> -{ - UpdateField<uint32, 0, 1> DynamicFlags; - UpdateField<ObjectGuid, 0, 2> Owner; - UpdateField<ObjectGuid, 0, 3> PartyGUID; - UpdateField<ObjectGuid, 0, 4> GuildGUID; - UpdateField<uint32, 0, 5> DisplayID; - UpdateField<uint8, 0, 6> Unused; - UpdateField<uint8, 0, 7> RaceID; - UpdateField<uint8, 0, 8> Sex; - UpdateField<uint8, 0, 9> SkinID; - UpdateField<uint8, 0, 10> FaceID; - UpdateField<uint8, 0, 11> HairStyleID; - UpdateField<uint8, 0, 12> HairColorID; - UpdateField<uint8, 0, 13> FacialHairStyleID; - UpdateField<uint32, 0, 14> Flags; - UpdateField<int32, 0, 15> FactionTemplate; - UpdateFieldArray<uint32, 19, 16, 17> Items; - UpdateFieldArray<uint8, 3, 36, 37> CustomDisplayOption; +struct CorpseData : public IsUpdateFieldStructureTag, public HasChangesMask<33> +{ + DynamicUpdateField<UF::ChrCustomizationChoice, 0, 1> Customizations; + UpdateField<uint32, 0, 2> DynamicFlags; + UpdateField<ObjectGuid, 0, 3> Owner; + UpdateField<ObjectGuid, 0, 4> PartyGUID; + UpdateField<ObjectGuid, 0, 5> GuildGUID; + UpdateField<uint32, 0, 6> DisplayID; + UpdateField<uint8, 0, 7> Unused; + UpdateField<uint8, 0, 8> RaceID; + UpdateField<uint8, 0, 9> Sex; + UpdateField<uint32, 0, 10> Flags; + UpdateField<int32, 0, 11> FactionTemplate; + UpdateField<uint32, 0, 12> StateSpellVisualKitID; + UpdateFieldArray<uint32, 19, 13, 14> Items; void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Corpse const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Corpse const* owner, Player const* receiver) const; - void WriteUpdate(ByteBuffer& data, UpdateMask<40> const& changesMask, bool ignoreNestedChangesMask, Corpse const* owner, Player const* receiver) const; + void WriteUpdate(ByteBuffer& data, UpdateMask<33> const& changesMask, bool ignoreNestedChangesMask, Corpse const* owner, Player const* receiver) const; void ClearChangesMask(); }; @@ -752,7 +875,7 @@ struct AreaTriggerData : public IsUpdateFieldStructureTag, public HasChangesMask UpdateField<uint32, 0, 7> TimeToTargetExtraScale; UpdateField<int32, 0, 8> SpellID; UpdateField<int32, 0, 9> SpellForVisuals; - UpdateField<int32, 0, 10> SpellXSpellVisualID; + UpdateField<UF::SpellCastVisual, 0, 10> SpellVisual; UpdateField<float, 0, 11> BoundsRadius2D; UpdateField<uint32, 0, 12> DecalPropertiesID; UpdateField<ObjectGuid, 0, 13> CreatingEffectGUID; @@ -783,9 +906,12 @@ struct ConversationLine : public IsUpdateFieldStructureTag int32 UiCameraID; uint8 ActorIndex; uint8 Flags; + uint8 ChatType; void WriteCreate(ByteBuffer& data, Conversation const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Conversation const* owner, Player const* receiver) const; + bool operator==(ConversationLine const& right) const; + bool operator!=(ConversationLine const& right) const { return !(*this == right); } }; struct ConversationActor : public IsUpdateFieldStructureTag @@ -795,9 +921,12 @@ struct ConversationActor : public IsUpdateFieldStructureTag ObjectGuid ActorGUID; int32 Field_18; uint32 Type; + uint32 NoActorObject; void WriteCreate(ByteBuffer& data, Conversation const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Conversation const* owner, Player const* receiver) const; + bool operator==(ConversationActor const& right) const; + bool operator!=(ConversationActor const& right) const { return !(*this == right); } }; struct ConversationData : public IsUpdateFieldStructureTag, public HasChangesMask<5> diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 446da0feb52..e3af501cb59 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -172,6 +172,7 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this) m_team = 0; m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE); + m_customizationsChanged = false; memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT); @@ -439,7 +440,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac return false; } - if (!ValidateAppearance(createInfo->Race, createInfo->Class, createInfo->Sex, createInfo->HairStyle, createInfo->HairColor, createInfo->Face, createInfo->FacialHairStyle, createInfo->Skin, createInfo->CustomDisplay, true)) + if (!GetSession()->ValidateAppearance(Races(createInfo->Race), Classes(createInfo->Class), Gender(createInfo->Sex), MakeChrCustomizationChoiceRange(createInfo->Customizations))) { TC_LOG_ERROR("entities.player.cheat", "Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with invalid appearance attributes - refusing to do so", GetSession()->GetAccountId(), m_name.c_str()); @@ -478,13 +479,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac SetWatchedFactionIndex(-1); - SetSkinId(createInfo->Skin); - SetFaceId(createInfo->Face); - SetHairStyleId(createInfo->HairStyle); - SetHairColorId(createInfo->HairColor); - SetFacialHairStyleId(createInfo->FacialHairStyle); - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - SetCustomDisplayOption(i, createInfo->CustomDisplay[i]); + SetCustomizations(Trinity::Containers::MakeIteratorPair(createInfo->Customizations.begin(), createInfo->Customizations.end())); SetRestState(REST_TYPE_XP, (GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0) ? REST_STATE_RAF_LINKED : REST_STATE_NOT_RAF_LINKED); SetRestState(REST_TYPE_HONOR, REST_STATE_NOT_RAF_LINKED); SetNativeSex(createInfo->Sex); @@ -559,47 +554,8 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac } // original items - if (CharStartOutfitEntry const* oEntry = sDB2Manager.GetCharStartOutfitEntry(createInfo->Race, createInfo->Class, createInfo->Sex)) - { - for (int j = 0; j < MAX_OUTFIT_ITEMS; ++j) - { - if (oEntry->ItemID[j] <= 0) - continue; - - uint32 itemId = oEntry->ItemID[j]; - - // just skip, reported in ObjectMgr::LoadItemTemplates - ItemTemplate const* iProto = sObjectMgr->GetItemTemplate(itemId); - if (!iProto) - continue; - - // BuyCount by default - uint32 count = iProto->GetBuyCount(); - - // special amount for food/drink - if (iProto->GetClass() == ITEM_CLASS_CONSUMABLE && iProto->GetSubClass() == ITEM_SUBCLASS_FOOD_DRINK) - { - if (iProto->Effects.size() >= 1) - { - switch (iProto->Effects[0]->SpellCategoryID) - { - case SPELL_CATEGORY_FOOD: // food - count = getClass() == CLASS_DEATH_KNIGHT ? 10 : 4; - break; - case SPELL_CATEGORY_DRINK: // drink - count = 2; - break; - } - } - if (iProto->GetMaxStackSize() < count) - count = iProto->GetMaxStackSize(); - } - StoreNewItemInBestSlots(itemId, count); - } - } - - for (PlayerCreateInfoItems::const_iterator item_id_itr = info->item.begin(); item_id_itr != info->item.end(); ++item_id_itr) - StoreNewItemInBestSlots(item_id_itr->item_id, item_id_itr->item_amount); + for (PlayerCreateInfoItem initialItem : info->item) + StoreNewItemInBestSlots(initialItem.item_id, initialItem.item_amount); // bags and main-hand weapon must equipped at this moment // now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon) @@ -2532,13 +2488,13 @@ void Player::InitStatsForLevel(bool reapplyMods) SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModHealingDonePos), 0); SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModHealingPercent), 1.0f); - SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModHealingDonePercent), 1.0f); SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModPeriodicHealingDonePercent), 1.0f); for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDoneNeg, i), 0); SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePos, i), 0); SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePercent, i), 1.0f); + SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModHealingDonePercent, i), 1.0f); } SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModSpellPowerPercent), 1.0f); @@ -3973,6 +3929,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe stmt->setUInt64(0, guid); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_CUSTOMIZATIONS); + stmt->setUInt64(0, guid); + trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_ACCOUNT_DATA); stmt->setUInt64(0, guid); trans->Append(stmt); @@ -4477,12 +4437,8 @@ Corpse* Player::CreateCorpse() flags |= CORPSE_FLAG_FFA_PVP; corpse->SetRace(getRace()); - corpse->SetSex(m_playerData->NativeSex); - corpse->SetSkin(m_playerData->SkinID); - corpse->SetFace(m_playerData->FaceID); - corpse->SetHairStyle(m_playerData->HairStyleID); - corpse->SetHairColor(m_playerData->HairColorID); - corpse->SetFacialHairStyle(m_playerData->FacialHairStyleID); + corpse->SetSex(GetNativeSex()); + corpse->SetCustomizations(Trinity::Containers::MakeIteratorPair(m_playerData->Customizations.begin(), m_playerData->Customizations.end())); corpse->SetFlags(flags); corpse->SetDisplayId(GetNativeDisplayId()); corpse->SetFactionTemplate(sChrRacesStore.AssertEntry(getRace())->FactionID); @@ -4798,6 +4754,9 @@ bool Player::CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, Area if ((channel->Flags & CHANNEL_DBC_FLAG_GUILD_REQ) && GetGuildId()) return false; + if (channel->Flags & CHANNEL_DBC_FLAG_NO_CLIENT_JOIN) + return false; + return true; } @@ -4850,6 +4809,9 @@ void Player::UpdateLocalChannels(uint32 newZone) if (!channelEntry) continue; + if (!(channelEntry->Flags & CHANNEL_DBC_FLAG_INITIAL)) + continue; + Channel* usedChannel = nullptr; for (Channel* channel : m_channels) { @@ -6153,7 +6115,7 @@ void Player::CheckAreaExploreAndOutdoor() UpdateCriteria(CRITERIA_TYPE_EXPLORE_AREA, GetAreaId()); - if (areaEntry->ExplorationLevel > 0) + if (Optional<ContentTuningLevels> areaLevels = sDB2Manager.GetContentTuningData(areaEntry->ContentTuningID, m_playerData->CtrOptions->ContentTuningConditionMask)) { if (getLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { @@ -6161,11 +6123,12 @@ void Player::CheckAreaExploreAndOutdoor() } else { - int32 diff = int32(getLevel()) - areaEntry->ExplorationLevel; + int16 areaLevel = std::min(std::max(int16(getLevel()), areaLevels->MinLevel), areaLevels->MaxLevel); + int32 diff = int32(getLevel()) - areaLevel; uint32 XP; if (diff < -5) { - XP = uint32(sObjectMgr->GetBaseXP(getLevel()+5)*sWorld->getRate(RATE_XP_EXPLORE)); + XP = uint32(sObjectMgr->GetBaseXP(getLevel() + 5) * sWorld->getRate(RATE_XP_EXPLORE)); } else if (diff > 5) { @@ -6173,11 +6136,11 @@ void Player::CheckAreaExploreAndOutdoor() if (exploration_percent < 0) exploration_percent = 0; - XP = uint32(sObjectMgr->GetBaseXP(areaEntry->ExplorationLevel)*exploration_percent/100*sWorld->getRate(RATE_XP_EXPLORE)); + XP = uint32(sObjectMgr->GetBaseXP(areaLevel) * exploration_percent / 100 * sWorld->getRate(RATE_XP_EXPLORE)); } else { - XP = uint32(sObjectMgr->GetBaseXP(areaEntry->ExplorationLevel)*sWorld->getRate(RATE_XP_EXPLORE)); + XP = uint32(sObjectMgr->GetBaseXP(areaLevel) * sWorld->getRate(RATE_XP_EXPLORE)); } GiveXP(XP, nullptr); @@ -6329,8 +6292,9 @@ void Player::RewardReputation(Unit* victim, float rate) Map const* map = GetMap(); if (map->IsNonRaidDungeon()) if (LFGDungeonsEntry const* dungeon = DB2Manager::GetLfgDungeon(map->GetId(), map->GetDifficultyID())) - if (dungeon->TargetLevel == 80) - ChampioningFaction = GetChampioningFaction(); + if (Optional<ContentTuningLevels> dungeonLevels = sDB2Manager.GetContentTuningData(dungeon->ContentTuningID, m_playerData->CtrOptions->ContentTuningConditionMask)) + if (dungeonLevels->TargetLevelMax == int16(GetMaxLevelForExpansion(EXPANSION_WRATH_OF_THE_LICH_KING))) + ChampioningFaction = GetChampioningFaction(); } uint32 team = GetTeam(); @@ -6862,7 +6826,7 @@ void Player::ModifyCurrency(uint32 id, int32 count, bool printLog/* = true*/, bo // Currency that is immediately converted into reputation with that faction instead if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(currency->FactionID)) { - if (currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) + if (currency->Flags[0] & CURRENCY_FLAG_HIGH_PRECISION) count /= 100; GetReputationMgr().ModifyReputation(factionEntry, count, false, true); return; @@ -7152,6 +7116,8 @@ void Player::UpdateArea(uint32 newArea) _restMgr->SetRestFlag(REST_FLAG_IN_FACTION_AREA); else _restMgr->RemoveRestFlag(REST_FLAG_IN_FACTION_AREA); + + UpdateCriteria(CRITERIA_TYPE_TRAVELLED_TO_AREA, newArea); } void Player::UpdateZone(uint32 newZone, uint32 newArea) @@ -11542,9 +11508,12 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool return EQUIP_ERR_CLIENT_LOCKED_OUT; } - ScalingStatDistributionEntry const* ssd = pItem->GetScalingStatDistribution() ? sScalingStatDistributionStore.LookupEntry(pItem->GetScalingStatDistribution()) : nullptr; + Optional<ContentTuningLevels> requiredLevels; // check allowed level (extend range to upper values if MaxLevel more or equal max player level, this let GM set high level with 1...max range items) - if (ssd && ssd->MaxLevel < DEFAULT_MAX_LEVEL && ssd->MaxLevel < getLevel() && !sDB2Manager.GetHeirloomByItemId(pProto->GetId())) + if (pItem->GetQuality() == ITEM_QUALITY_HEIRLOOM) + requiredLevels = sDB2Manager.GetContentTuningData(pItem->GetScalingContentTuningId(), 0, true); + + if (requiredLevels && requiredLevels->MaxLevel < DEFAULT_MAX_LEVEL && requiredLevels->MaxLevel < getLevel() && !sDB2Manager.GetHeirloomByItemId(pProto->GetId())) return EQUIP_ERR_NOT_EQUIPPABLE; uint8 eslot = FindEquipSlot(pProto, slot, swap); @@ -14975,15 +14944,17 @@ uint32 Player::GetDefaultGossipMenuForSource(WorldObject* source) int32 Player::GetQuestMinLevel(Quest const* quest) const { - if (quest->GetQuestLevel() == -1 && quest->GetQuestScalingFactionGroup()) + if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(quest->GetContentTuningId(), m_playerData->CtrOptions->ContentTuningConditionMask)) { ChrRacesEntry const* race = sChrRacesStore.AssertEntry(getRace()); FactionTemplateEntry const* raceFaction = sFactionTemplateStore.LookupEntry(race->FactionID); - if (!raceFaction || raceFaction->FactionGroup != quest->GetQuestScalingFactionGroup()) - return quest->GetQuestMaxScalingLevel(); + if (!raceFaction || raceFaction->FactionGroup != sContentTuningStore.AssertEntry(quest->GetContentTuningId())->GetScalingFactionGroup()) + return questLevels->MaxLevel; + + return questLevels->MinLevelWithDelta; } - return quest->GetMinLevel(); + return 0; } int32 Player::GetQuestLevel(Quest const* quest) const @@ -14991,10 +14962,10 @@ int32 Player::GetQuestLevel(Quest const* quest) const if (!quest) return 0; - if (quest->GetQuestLevel() == -1) + if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(quest->GetContentTuningId(), m_playerData->CtrOptions->ContentTuningConditionMask)) { int32 minLevel = GetQuestMinLevel(quest); - int32 maxLevel = quest->GetQuestMaxScalingLevel(); + int32 maxLevel = questLevels->MaxLevel; int32 level = getLevel(); if (level >= minLevel) return std::min(level, maxLevel); @@ -15002,7 +14973,7 @@ int32 Player::GetQuestLevel(Quest const* quest) const return minLevel; } - return quest->GetQuestLevel(); + return 0; } void Player::PrepareQuestMenu(ObjectGuid guid) @@ -15913,6 +15884,7 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew UpdateCriteria(CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, quest->GetQuestId()); UpdateCriteria(CRITERIA_TYPE_COMPLETE_QUEST_COUNT); UpdateCriteria(CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId()); + UpdateCriteria(CRITERIA_TYPE_COMPLETE_QUEST_ACCUMULATE, 1); // make full db save SaveToDB(false); @@ -17918,20 +17890,6 @@ bool Player::IsLoading() const bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - //"SELECT guid, account, name, race, class, gender, level, xp, money, skin, face, hairStyle, hairColor, facialStyle, customDisplay1, customDisplay2, customDisplay3, inventorySlots, bankSlots, restState, playerFlags, playerFlagsEx, " - // 22 23 24 25 26 27 28 29 30 31 32 33 34 - //"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, " - // 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 - //"resettalents_time, primarySpecialization, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, " - // 50 51 52 53 54 55 - //"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, " - // 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 - //"health, power1, power2, power3, power4, power5, power6, instance_id, activeTalentGroup, lootSpecId, exploredZones, knownTitles, actionBars, raidDifficulty, legacyRaidDifficulty, fishing_steps " - // 72 73 74 75 76 - //"honor, honorLevel, honor_rest_state, honor_rest_bonus, numRespecs " - // - //"FROM characters WHERE guid = ?", CONNECTION_ASYNC); PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM); if (!result) { @@ -17941,15 +17899,158 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) return false; } - Field* fields = result->Fetch(); - - uint32 dbAccountId = fields[1].GetUInt32(); + struct PlayerLoadData + { + // "SELECT c.guid, account, name, race, class, gender, level, xp, money, inventorySlots, bankSlots, restState, playerFlags, playerFlagsEx, " + // "position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, " + // "resettalents_time, primarySpecialization, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, " + // "totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, " + // "health, power1, power2, power3, power4, power5, power6, instance_id, activeTalentGroup, lootSpecId, exploredZones, knownTitles, actionBars, raidDifficulty, legacyRaidDifficulty, fishingSteps, " + // "honor, honorLevel, honorRestState, honorRestBonus, numRespecs " + // "FROM characters c LEFT JOIN character_fishingsteps cfs ON c.guid = cfs.guid WHERE c.guid = ?", CONNECTION_ASYNC); + + ObjectGuid::LowType guid; + uint32 account; + std::string name; + uint8 race; + uint8 class_; + Gender gender; + uint8 level; + uint32 xp; + uint64 money; + uint8 inventorySlots; + uint8 bankSlots; + PlayerRestState restState; + PlayerFlags playerFlags; + PlayerFlagsEx playerFlagsEx; + float position_x; + float position_y; + float position_z; + uint16 map; + float orientation; + std::string taximask; + uint8 cinematic; + uint32 totaltime; + uint32 leveltime; + float rest_bonus; + uint32 logout_time; + uint8 is_logout_resting; + uint32 resettalents_cost; + uint32 resettalents_time; + uint32 primarySpecialization; + float trans_x; + float trans_y; + float trans_z; + float trans_o; + ObjectGuid::LowType transguid; + uint16 extra_flags; + uint8 stable_slots; + uint16 at_login; + uint16 zone; + uint8 online; + uint32 death_expire_time; + std::string taxi_path; + Difficulty dungeonDifficulty; + uint32 totalKills; + uint16 todayKills; + uint16 yesterdayKills; + uint32 chosenTitle; + uint32 watchedFaction; + uint8 drunk; + uint32 health; + std::array<uint32, MAX_POWERS_PER_CLASS> powers; + uint32 instance_id; + uint8 activeTalentGroup; + uint32 lootSpecId; + std::string exploredZones; + std::string knownTitles; + uint8 actionBars; + Difficulty raidDifficulty; + Difficulty legacyRaidDifficulty; + uint8 fishingSteps; + uint32 honor; + uint32 honorLevel; + PlayerRestState honorRestState; + float honorRestBonus; + uint8 numRespecs; + + PlayerLoadData(Field* fields) + { + std::size_t i = 0; + guid = fields[i++].GetUInt64(); + account = fields[i++].GetUInt32(); + name = fields[i++].GetString(); + race = fields[i++].GetUInt8(); + class_ = fields[i++].GetUInt8(); + gender = Gender(fields[i++].GetUInt8()); + level = fields[i++].GetUInt8(); + xp = fields[i++].GetUInt32(); + money = fields[i++].GetUInt64(); + inventorySlots = fields[i++].GetUInt8(); + bankSlots = fields[i++].GetUInt8(); + restState = PlayerRestState(fields[i++].GetUInt8()); + playerFlags = PlayerFlags(fields[i++].GetUInt32()); + playerFlagsEx = PlayerFlagsEx(fields[i++].GetUInt32()); + position_x = fields[i++].GetFloat(); + position_y = fields[i++].GetFloat(); + position_z = fields[i++].GetFloat(); + map = fields[i++].GetUInt16(); + orientation = fields[i++].GetFloat(); + taximask = fields[i++].GetString(); + cinematic = fields[i++].GetUInt8(); + totaltime = fields[i++].GetUInt32(); + leveltime = fields[i++].GetUInt32(); + rest_bonus = fields[i++].GetFloat(); + logout_time = fields[i++].GetUInt32(); + is_logout_resting = fields[i++].GetUInt8(); + resettalents_cost = fields[i++].GetUInt32(); + resettalents_time = fields[i++].GetUInt32(); + primarySpecialization = fields[i++].GetUInt32(); + trans_x = fields[i++].GetFloat(); + trans_y = fields[i++].GetFloat(); + trans_z = fields[i++].GetFloat(); + trans_o = fields[i++].GetFloat(); + transguid = fields[i++].GetUInt64(); + extra_flags = fields[i++].GetUInt16(); + stable_slots = fields[i++].GetUInt8(); + at_login = fields[i++].GetUInt16(); + zone = fields[i++].GetUInt16(); + online = fields[i++].GetUInt8(); + death_expire_time = fields[i++].GetUInt32(); + taxi_path = fields[i++].GetString(); + dungeonDifficulty = Difficulty(fields[i++].GetUInt8()); + totalKills = fields[i++].GetUInt32(); + todayKills = fields[i++].GetUInt16(); + yesterdayKills = fields[i++].GetUInt16(); + chosenTitle = fields[i++].GetUInt32(); + watchedFaction = fields[i++].GetUInt32(); + drunk = fields[i++].GetUInt8(); + health = fields[i++].GetUInt32(); + for (uint32& power : powers) + power = fields[i++].GetUInt32(); + instance_id = fields[i++].GetUInt32(); + activeTalentGroup = fields[i++].GetUInt8(); + lootSpecId = fields[i++].GetUInt32(); + exploredZones = fields[i++].GetString(); + knownTitles = fields[i++].GetString(); + actionBars = fields[i++].GetUInt8(); + raidDifficulty = Difficulty(fields[i++].GetUInt8()); + legacyRaidDifficulty = Difficulty(fields[i++].GetUInt8()); + fishingSteps = fields[i++].GetUInt8(); + honor = fields[i++].GetUInt32(); + honorLevel = fields[i++].GetUInt32(); + honorRestState = PlayerRestState(fields[i++].GetUInt8()); + honorRestBonus = fields[i++].GetFloat(); + numRespecs = fields[i++].GetUInt8(); + } + + } fields(result->Fetch()); // check if the character's account in the db and the logged in account match. // player should be able to load/delete character only with correct account! - if (dbAccountId != GetSession()->GetAccountId()) + if (fields.account != GetSession()->GetAccountId()) { - TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) loading from wrong account (is: %u, should be: %u)", guid.ToString().c_str(), GetSession()->GetAccountId(), dbAccountId); + TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) loading from wrong account (is: %u, should be: %u)", guid.ToString().c_str(), GetSession()->GetAccountId(), fields.account); return false; } @@ -17961,7 +18062,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) Object::_Create(guid); - m_name = fields[2].GetString(); + m_name = std::move(fields.name); // check name limitations if (ObjectMgr::CheckPlayerName(m_name, GetSession()->GetSessionDbcLocale()) != CHAR_NAME_SUCCESS || @@ -17974,19 +18075,18 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) return false; } - // overwrite possible wrong/corrupted guid SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::WowAccount), GetSession()->GetAccountGUID()); + SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::BnetAccount), GetSession()->GetBattlenetAccountGUID()); - uint8 gender = fields[5].GetUInt8(); - if (!IsValidGender(gender)) + if (!IsValidGender(fields.gender)) { - TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong gender (%u), can't load.", guid.ToString().c_str(), gender); + TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong gender (%u), can't load.", guid.ToString().c_str(), uint32(fields.gender)); return false; } - SetRace(fields[3].GetUInt8()); - SetClass(fields[4].GetUInt8()); - SetGender(gender); + SetRace(fields.race); + SetClass(fields.class_); + SetGender(fields.gender); // check if race/class combination is valid PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); @@ -17996,16 +18096,16 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) return false; } - SetLevel(fields[6].GetUInt8()); - SetXP(fields[7].GetUInt32()); + SetLevel(fields.level); + SetXP(fields.xp); - Tokenizer exploredZones(fields[66].GetString(), ' '); + Tokenizer exploredZones(fields.exploredZones, ' '); if (exploredZones.size() == PLAYER_EXPLORED_ZONES_SIZE * 2) for (std::size_t i = 0; i < exploredZones.size(); ++i) SetUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ExploredZones, i / 2), (uint64(atoul(exploredZones[i])) << (32 * (i % 2)))); - Tokenizer knownTitles(fields[67].GetString(), ' '); + Tokenizer knownTitles(fields.knownTitles, ' '); if (!(knownTitles.size() % 2)) { for (std::size_t i = 0; i < knownTitles.size(); ++i) @@ -18020,50 +18120,41 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) m_achievementMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS)); m_questObjectiveCriteriaMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA_PROGRESS)); - uint64 money = fields[8].GetUInt64(); - if (money > MAX_MONEY_AMOUNT) - money = MAX_MONEY_AMOUNT; - SetMoney(money); - - std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> customDisplay; - customDisplay[0] = fields[14].GetUInt8(); - customDisplay[1] = fields[15].GetUInt8(); - customDisplay[2] = fields[16].GetUInt8(); - - SetSkinId(fields[9].GetUInt8()); - SetFaceId(fields[10].GetUInt8()); - SetHairStyleId(fields[11].GetUInt8()); - SetHairColorId(fields[12].GetUInt8()); - SetFacialHairStyleId(fields[13].GetUInt8()); - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - SetCustomDisplayOption(i, customDisplay[i]); - SetInventorySlotCount(fields[17].GetUInt8()); - SetBankBagSlotCount(fields[18].GetUInt8()); - SetNativeSex(gender); - SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::Inebriation), fields[55].GetUInt8()); - SetPlayerFlags(PlayerFlags(fields[20].GetUInt32())); - SetPlayerFlagsEx(PlayerFlagsEx(fields[21].GetUInt32())); - SetWatchedFactionIndex(fields[54].GetUInt32()); - - if (!ValidateAppearance( - fields[3].GetUInt8(), // race - fields[4].GetUInt8(), // class - gender, - m_playerData->HairStyleID, - m_playerData->HairColorID, - m_playerData->FaceID, - m_playerData->FacialHairStyleID, - m_playerData->SkinID, - customDisplay)) + SetMoney(std::min(fields.money, MAX_MONEY_AMOUNT)); + + std::vector<UF::ChrCustomizationChoice> customizations; + if (PreparedQueryResult customizationsResult = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUSTOMIZATIONS)) + { + do + { + Field* fields = customizationsResult->Fetch(); + customizations.emplace_back(); + UF::ChrCustomizationChoice& choice = customizations.back(); + choice.ChrCustomizationOptionID = fields[0].GetUInt32(); + choice.ChrCustomizationChoiceID = fields[1].GetUInt32(); + + } while (customizationsResult->NextRow()); + } + + SetCustomizations(Trinity::Containers::MakeIteratorPair(customizations.begin(), customizations.end()), false); + SetInventorySlotCount(fields.inventorySlots); + SetBankBagSlotCount(fields.bankSlots); + SetNativeSex(fields.gender); + SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::Inebriation), fields.drunk); + SetPlayerFlags(fields.playerFlags); + SetPlayerFlagsEx(fields.playerFlagsEx); + SetWatchedFactionIndex(fields.watchedFaction); + + if (!GetSession()->ValidateAppearance(Races(getRace()), Classes(getClass()), fields.gender, MakeChrCustomizationChoiceRange(customizations))) { TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong Appearance values (Hair/Skin/Color), can't load.", guid.ToString().c_str()); return false; } // set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise) - SetMultiActionBars(fields[68].GetUInt8()); + SetMultiActionBars(fields.actionBars); - m_fishingSteps = fields[71].GetUInt8(); + m_fishingSteps = fields.fishingSteps; InitDisplayIds(); @@ -18092,27 +18183,23 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) InitPrimaryProfessions(); // to max set before any spell loaded // init saved position, and fix it later if problematic - ObjectGuid::LowType transLowGUID = fields[41].GetUInt64(); - - Relocate(fields[22].GetFloat(), fields[23].GetFloat(), fields[24].GetFloat(), fields[26].GetFloat()); - - uint32 mapId = fields[25].GetUInt16(); - uint32 instanceId = fields[63].GetUInt32(); + Relocate(fields.position_x, fields.position_y, fields.position_z, fields.orientation); - SetDungeonDifficultyID(CheckLoadedDungeonDifficultyID(Difficulty(fields[49].GetUInt8()))); - SetRaidDifficultyID(CheckLoadedRaidDifficultyID(Difficulty(fields[69].GetUInt8()))); - SetLegacyRaidDifficultyID(CheckLoadedLegacyRaidDifficultyID(Difficulty(fields[70].GetUInt8()))); + uint32 mapId = fields.map; + uint32 instanceId = fields.instance_id; - std::string taxi_nodes = fields[48].GetString(); + SetDungeonDifficultyID(CheckLoadedDungeonDifficultyID(fields.dungeonDifficulty)); + SetRaidDifficultyID(CheckLoadedRaidDifficultyID(fields.raidDifficulty)); + SetLegacyRaidDifficultyID(CheckLoadedLegacyRaidDifficultyID(fields.legacyRaidDifficulty)); #define RelocateToHomebind(){ mapId = m_homebindMapId; instanceId = 0; Relocate(m_homebindX, m_homebindY, m_homebindZ); } _LoadGroup(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GROUP)); _LoadCurrency(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CURRENCY)); - SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::LifetimeHonorableKills), fields[50].GetUInt32()); - SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::TodayHonorableKills), fields[51].GetUInt16()); - SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::YesterdayHonorableKills), fields[52].GetUInt16()); + SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::LifetimeHonorableKills), fields.totalKills); + SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::TodayHonorableKills), fields.totalKills); + SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::YesterdayHonorableKills), fields.yesterdayKills); _LoadBoundInstances(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES)); _LoadInstanceTimeRestrictions(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES)); @@ -18183,9 +18270,9 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) } } // currently we do not support transport in bg - else if (transLowGUID) + else if (fields.transguid) { - ObjectGuid transGUID = ObjectGuid::Create<HighGuid::Transport>(transLowGUID); + ObjectGuid transGUID = ObjectGuid::Create<HighGuid::Transport>(fields.transguid); Transport* transport = nullptr; if (Transport* go = HashMapHolder<Transport>::Find(transGUID)) @@ -18193,7 +18280,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) if (transport) { - float x = fields[37].GetFloat(), y = fields[38].GetFloat(), z = fields[39].GetFloat(), o = fields[40].GetFloat(); + float x = fields.trans_x, y = fields.trans_y, z = fields.trans_z, o = fields.trans_o; m_movementInfo.transport.pos.Relocate(x, y, z, o); transport->CalculatePassengerPosition(x, y, z, &o); @@ -18221,13 +18308,13 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) else { TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has problems with transport guid (" UI64FMTD "). Teleport to bind location.", - guid.ToString().c_str(), transLowGUID); + guid.ToString().c_str(), fields.transguid); RelocateToHomebind(); } } // currently we do not support taxi in instance - else if (!taxi_nodes.empty()) + else if (!fields.taxi_path.empty()) { instanceId = 0; @@ -18237,7 +18324,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) for (int i = 0; i < 2; ++i) m_taxi.AddTaxiDestination(m_bgData.taxiPath[i]); } - else if (!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes, GetTeam())) + else if (!m_taxi.LoadTaxiDestinationsFromString(fields.taxi_path, GetTeam())) { // problems with taxi path loading TaxiNodesEntry const* nodeEntry = nullptr; @@ -18388,7 +18475,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) SaveRecallPosition(); time_t now = time(nullptr); - time_t logoutTime = time_t(fields[32].GetUInt32()); + time_t logoutTime = time_t(fields.logout_time); // since last logout (in seconds) uint32 time_diff = uint32(now - logoutTime); //uint64 is excessive for a time_diff in seconds.. uint32 allows for 136~ year difference. @@ -18401,18 +18488,18 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) SetDrunkValue(newDrunkValue); - m_cinematic = fields[28].GetUInt8(); - m_Played_time[PLAYED_TIME_TOTAL] = fields[29].GetUInt32(); - m_Played_time[PLAYED_TIME_LEVEL] = fields[30].GetUInt32(); + m_cinematic = fields.cinematic; + m_Played_time[PLAYED_TIME_TOTAL] = fields.totaltime; + m_Played_time[PLAYED_TIME_LEVEL] = fields.leveltime; - SetTalentResetCost(fields[34].GetUInt32()); - SetTalentResetTime(time_t(fields[35].GetUInt32())); + SetTalentResetCost(fields.resettalents_cost); + SetTalentResetTime(time_t(fields.resettalents_time)); - m_taxi.LoadTaxiMask(fields[27].GetString()); // must be before InitTaxiNodesForLevel + m_taxi.LoadTaxiMask(fields.taximask); // must be before InitTaxiNodesForLevel - uint32 extraflags = fields[42].GetUInt16(); + uint32 extraflags = fields.extra_flags; - m_stableSlots = fields[43].GetUInt8(); + m_stableSlots = fields.stable_slots; if (m_stableSlots > MAX_PET_STABLES) { TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) can't have more stable slots than %u, but has %u in DB", @@ -18420,7 +18507,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) m_stableSlots = MAX_PET_STABLES; } - m_atLoginFlags = fields[44].GetUInt16(); + m_atLoginFlags = fields.at_login; if (HasAtLoginFlag(AT_LOGIN_RENAME)) { @@ -18433,7 +18520,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) m_lastHonorUpdateTime = logoutTime; UpdateHonorFields(); - m_deathExpireTime = time_t(fields[47].GetUInt32()); + m_deathExpireTime = time_t(fields.death_expire_time); if (m_deathExpireTime > now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP) m_deathExpireTime = now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP - 1; @@ -18449,20 +18536,20 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) InitRunes(); // rest bonus can only be calculated after InitStatsForLevel() - _restMgr->LoadRestBonus(REST_TYPE_XP, PlayerRestState(fields[19].GetUInt8()), fields[31].GetFloat()); + _restMgr->LoadRestBonus(REST_TYPE_XP, fields.restState, fields.rest_bonus); // load skills after InitStatsForLevel because it triggering aura apply also _LoadSkills(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SKILLS)); UpdateSkillsForLevel(); //update skills after load, to make sure they are correctly update at player load - SetNumRespecs(fields[76].GetUInt8()); - SetPrimarySpecialization(fields[36].GetUInt32()); - SetActiveTalentGroup(fields[64].GetUInt8()); + SetNumRespecs(fields.numRespecs); + SetPrimarySpecialization(fields.primarySpecialization); + SetActiveTalentGroup(fields.activeTalentGroup); ChrSpecializationEntry const* primarySpec = sChrSpecializationStore.LookupEntry(GetPrimarySpecialization()); if (!primarySpec || primarySpec->ClassID != getClass() || GetActiveTalentGroup() >= MAX_SPECIALIZATIONS) ResetTalentSpecialization(); - uint32 lootSpecId = fields[65].GetUInt32(); + uint32 lootSpecId = fields.lootSpecId; if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(lootSpecId)) if (chrSpec->ClassID == getClass()) SetLootSpecId(lootSpecId); @@ -18528,7 +18615,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) // check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES // note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded - uint32 curTitle = fields[53].GetUInt32(); + uint32 curTitle = fields.chosenTitle; if (curTitle && !HasTitle(curTitle)) curTitle = 0; @@ -18551,14 +18638,14 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) UpdateAllStats(); // restore remembered power/health values (but not more max values) - uint32 savedHealth = fields[56].GetUInt32(); + uint32 savedHealth = fields.health; SetHealth(savedHealth > GetMaxHealth() ? GetMaxHealth() : savedHealth); uint32 loadedPowers = 0; for (uint32 i = 0; i < MAX_POWERS; ++i) { if (GetPowerIndex(Powers(i)) != MAX_POWERS) { - uint32 savedPower = fields[56 + loadedPowers].GetUInt32(); + uint32 savedPower = fields.powers[loadedPowers]; uint32 maxPower = m_unitData->MaxPower[loadedPowers]; SetPower(Powers(i), (savedPower > maxPower) ? maxPower : savedPower); if (++loadedPowers >= MAX_POWERS_PER_CLASS) @@ -18653,16 +18740,16 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES))) _garrison = std::move(garrison); - _InitHonorLevelOnLoadFromDB(fields[72].GetUInt32(), fields[73].GetUInt32()); + _InitHonorLevelOnLoadFromDB(fields.honor, fields.honorLevel); - _restMgr->LoadRestBonus(REST_TYPE_HONOR, PlayerRestState(fields[74].GetUInt8()), fields[75].GetFloat()); + _restMgr->LoadRestBonus(REST_TYPE_HONOR, fields.honorRestState, fields.honorRestBonus); if (time_diff > 0) { //speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour) float bubble0 = 0.031f; //speed collect rest bonus in offline, in logout, in tavern, city (section/in hour) float bubble1 = 0.125f; - float bubble = fields[33].GetUInt8() > 0 + float bubble = fields.is_logout_resting > 0 ? bubble1 * sWorld->getRate(RATE_REST_OFFLINE_IN_TAVERN_OR_CITY) : bubble0 * sWorld->getRate(RATE_REST_OFFLINE_IN_WILDERNESS); @@ -20361,17 +20448,10 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba stmt->setString(index++, GetName()); stmt->setUInt8(index++, getRace()); stmt->setUInt8(index++, getClass()); - stmt->setUInt8(index++, m_playerData->NativeSex); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect + stmt->setUInt8(index++, GetNativeSex()); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect stmt->setUInt8(index++, getLevel()); stmt->setUInt32(index++, m_activePlayerData->XP); stmt->setUInt64(index++, GetMoney()); - stmt->setUInt8(index++, m_playerData->SkinID); - stmt->setUInt8(index++, m_playerData->FaceID); - stmt->setUInt8(index++, m_playerData->HairStyleID); - stmt->setUInt8(index++, m_playerData->HairColorID); - stmt->setUInt8(index++, m_playerData->FacialHairStyleID); - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - stmt->setUInt8(index++, m_playerData->CustomDisplayOption[i]); stmt->setUInt8(index++, GetInventorySlotCount()); stmt->setUInt8(index++, GetBankBagSlotCount()); stmt->setUInt8(index++, m_activePlayerData->RestInfo[REST_TYPE_XP].StateID); @@ -20493,17 +20573,10 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba stmt->setString(index++, GetName()); stmt->setUInt8(index++, getRace()); stmt->setUInt8(index++, getClass()); - stmt->setUInt8(index++, m_playerData->NativeSex); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect + stmt->setUInt8(index++, GetNativeSex()); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect stmt->setUInt8(index++, getLevel()); stmt->setUInt32(index++, m_activePlayerData->XP); stmt->setUInt64(index++, GetMoney()); - stmt->setUInt8(index++, m_playerData->SkinID); - stmt->setUInt8(index++, m_playerData->FaceID); - stmt->setUInt8(index++, m_playerData->HairStyleID); - stmt->setUInt8(index++, m_playerData->HairColorID); - stmt->setUInt8(index++, m_playerData->FacialHairStyleID); - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - stmt->setUInt8(index++, m_playerData->CustomDisplayOption[i]); stmt->setUInt8(index++, GetInventorySlotCount()); stmt->setUInt8(index++, GetBankBagSlotCount()); stmt->setUInt8(index++, m_activePlayerData->RestInfo[REST_TYPE_XP].StateID); @@ -20660,6 +20733,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba if (m_mailsUpdated) //save mails only when needed _SaveMail(trans); + _SaveCustomizations(trans); _SaveBGData(trans); _SaveInventory(trans); _SaveVoidStorage(trans); @@ -20735,6 +20809,39 @@ void Player::SaveGoldToDB(CharacterDatabaseTransaction& trans) const trans->Append(stmt); } +template<typename iterator> +void SavePlayerCustomizations(CharacterDatabaseTransaction trans, ObjectGuid::LowType guid, Trinity::IteratorPair<iterator> customizations) +{ + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_CUSTOMIZATIONS); + stmt->setUInt64(0, guid); + trans->Append(stmt); + + for (auto&& customization : customizations) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_CUSTOMIZATION); + stmt->setUInt64(0, guid); + stmt->setUInt32(1, customization.ChrCustomizationOptionID); + stmt->setUInt32(2, customization.ChrCustomizationChoiceID); + trans->Append(stmt); + } +} + +void Player::SaveCustomizations(CharacterDatabaseTransaction trans, ObjectGuid::LowType guid, + Trinity::IteratorPair<UF::ChrCustomizationChoice const*> customizations) +{ + SavePlayerCustomizations(trans, guid, customizations); +} + +void Player::_SaveCustomizations(CharacterDatabaseTransaction trans) +{ + if (!m_customizationsChanged) + return; + + m_customizationsChanged = false; + + SavePlayerCustomizations(trans, GetGUID().GetCounter(), Trinity::Containers::MakeIteratorPair(m_playerData->Customizations.begin(), m_playerData->Customizations.end())); +} + void Player::_SaveActions(CharacterDatabaseTransaction& trans) { CharacterDatabasePreparedStatement* stmt; @@ -22761,7 +22868,7 @@ void Player::InitDisplayIds() return; } - uint8 gender = m_playerData->NativeSex; + Gender gender = GetNativeSex(); switch (gender) { case GENDER_FEMALE: @@ -22773,7 +22880,8 @@ void Player::InitDisplayIds() SetNativeDisplayId(info->displayId_m); break; default: - TC_LOG_ERROR("entities.player", "Player::InitDisplayIds: Player '%s' (%s) has invalid gender %u", GetName().c_str(), GetGUID().ToString().c_str(), gender); + TC_LOG_ERROR("entities.player", "Player::InitDisplayIds: Player '%s' (%s) has invalid gender %u", GetName().c_str(), GetGUID().ToString().c_str(), uint32(gender)); + break; } SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::StateAnimID), sDB2Manager.GetEmptyAnimStateID()); @@ -23224,6 +23332,8 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin if (pProto->GetQuality() > ITEM_QUALITY_EPIC || (pProto->GetQuality() == ITEM_QUALITY_EPIC && pProto->GetBaseItemLevel() >= MinNewsItemLevel)) if (Guild* guild = GetGuild()) guild->AddGuildNews(GUILD_NEWS_ITEM_PURCHASED, GetGUID(), 0, item); + + UpdateCriteria(CRITERIA_TYPE_BOUGHT_ITEM_FROM_VENDOR, 1); return true; } @@ -25904,51 +26014,24 @@ bool Player::CanCaptureTowerPoint() const IsAlive()); // live player } -uint32 Player::GetBarberShopCost(BarberShopStyleEntry const* newHairStyle, uint8 newHairColor, BarberShopStyleEntry const* newFacialHair, BarberShopStyleEntry const* newSkin, BarberShopStyleEntry const* newFace, std::array<BarberShopStyleEntry const*, PLAYER_CUSTOM_DISPLAY_SIZE> const& newCustomDisplay) const -{ - uint8 hairstyle = m_playerData->HairStyleID; - uint8 haircolor = m_playerData->HairColorID; - uint8 facialhair = m_playerData->FacialHairStyleID; - uint8 skincolor = m_playerData->SkinID; - uint8 face = m_playerData->FaceID; - std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> customDisplay; - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - customDisplay[i] = m_playerData->CustomDisplayOption[i]; - - if ((hairstyle == newHairStyle->Data) && - (haircolor == newHairColor) && - (facialhair == newFacialHair->Data) && - (!newSkin || (newSkin->Data == skincolor)) && - (!newFace || (newFace->Data == face)) && - (!newCustomDisplay[0] || (newCustomDisplay[0]->Data == customDisplay[0])) && - (!newCustomDisplay[1] || (newCustomDisplay[1]->Data == customDisplay[1])) && - (!newCustomDisplay[2] || (newCustomDisplay[2]->Data == customDisplay[2]))) - return 0; - +int64 Player::GetBarberShopCost(Trinity::IteratorPair<UF::ChrCustomizationChoice const*> newCustomizations) const +{ GtBarberShopCostBaseEntry const* bsc = sBarberShopCostBaseGameTable.GetRow(getLevel()); if (!bsc) // shouldn't happen - return 0xFFFFFFFF; - - uint32 cost = 0; - - if (hairstyle != newHairStyle->Data) - cost += uint32(bsc->Cost * newHairStyle->CostModifier); - - if ((haircolor != newHairColor) && (hairstyle == newHairStyle->Data)) - cost += uint32(bsc->Cost * 0.5f); // +1/2 of price - - if (facialhair != newFacialHair->Data) - cost += uint32(bsc->Cost * newFacialHair->CostModifier); - - if (newSkin && skincolor != newSkin->Data) - cost += uint32(bsc->Cost * newSkin->CostModifier); + return 0; - if (newFace && face != newFace->Data) - cost += uint32(bsc->Cost * newFace->CostModifier); + int64 cost = 0; + for (UF::ChrCustomizationChoice const& newChoice : newCustomizations) + { + int32 currentCustomizationIndex = m_playerData->Customizations.FindIndexIf([&](UF::ChrCustomizationChoice const& currentCustomization) + { + return currentCustomization.ChrCustomizationOptionID == newChoice.ChrCustomizationOptionID; + }); - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - if (newCustomDisplay[i] && customDisplay[i] != newCustomDisplay[i]->Data) - cost += uint32(bsc->Cost * newCustomDisplay[i]->CostModifier); + if (currentCustomizationIndex == -1 || m_playerData->Customizations[currentCustomizationIndex].ChrCustomizationChoiceID != newChoice.ChrCustomizationChoiceID) + if (ChrCustomizationOptionEntry const* customizationOption = sChrCustomizationOptionStore.LookupEntry(newChoice.ChrCustomizationOptionID)) + cost += bsc->Cost * customizationOption->BarberShopCostModifier; + } return cost; } @@ -28513,139 +28596,6 @@ void Player::RemoveSocial() m_social = nullptr; } -uint32 GetSelectionFromContext(uint32 context, uint32 playerClass) -{ - switch (context) - { - case 1: - if (playerClass == CLASS_DEATH_KNIGHT) - return 1; - if (playerClass == CLASS_DEMON_HUNTER) - return 3; - return 0; - case 2: - if (playerClass == CLASS_DEATH_KNIGHT) - return 5; - if (playerClass == CLASS_DEMON_HUNTER) - return 6; - return 4; - case 3: - return 7; - case 4: - if (playerClass == CLASS_DEATH_KNIGHT) - return 9; - if (playerClass == CLASS_DEMON_HUNTER) - return 10; - return 8; - default: - if (playerClass == CLASS_DEATH_KNIGHT) - return 1; - if (playerClass == CLASS_DEMON_HUNTER) - return 2; - return 0; - } - - return 0; -} - -bool ComponentFlagsMatch(CharSectionsEntry const* entry, uint32 selection) -{ - switch (selection) - { - case 0: - if (!(entry->Flags & 1)) - return false; - return !(entry->Flags & 0x2C); - case 1: - if (!(entry->Flags & 1)) - return false; - if (!(entry->Flags & 0x94)) - return false; - return !(entry->Flags & 8); - case 2: - if (!(entry->Flags & 1)) - return false; - if (!(entry->Flags & 0x70)) - return false; - return !(entry->Flags & 8); - case 3: - if (!(entry->Flags & 1)) - return false; - if (!(entry->Flags & 0x20)) - return false; - return !(entry->Flags & 8); - case 4: - case 8: - if (!(entry->Flags & 3)) - return false; - return !(entry->Flags & 0x2C); - case 5: - case 9: - if (!(entry->Flags & 3)) - return false; - if (!(entry->Flags & 0x94)) - return false; - return !(entry->Flags & 8); - case 6: - case 10: - if (!(entry->Flags & 3)) - return false; - if (!(entry->Flags & 0x70)) - return false; - return !(entry->Flags & 8); - case 7: - return true; - default: - break; - } - - return false; -} - -bool IsSectionFlagValid(CharSectionsEntry const* entry, uint8 class_, bool create) -{ - if (create) - return ComponentFlagsMatch(entry, GetSelectionFromContext(0, class_)); - - return ComponentFlagsMatch(entry, GetSelectionFromContext(2, class_)); -} - -bool IsSectionValid(uint8 race, uint8 class_, uint8 gender, CharBaseSectionVariation variation, uint8 variationIndex, uint8 colorIndex, bool create) -{ - CharSectionsEntry const* section = sDB2Manager.GetCharSectionEntry(race, gender, variation, variationIndex, colorIndex); - if (section) - return IsSectionFlagValid(section, class_, create); - - return false; -} - -bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHairID, uint8 skinColor, std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> const& customDisplay, bool create /*= false*/) -{ - if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::Skin, 0, skinColor, create)) - return false; - - if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::Face, faceID, skinColor, create)) - return false; - - if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::Hair, hairID, hairColor, create)) - return false; - - if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::FacialHair, facialHairID, hairColor, create)) - if (sDB2Manager.HasCharSections(race, gender, CharBaseSectionVariation::FacialHair) || !sDB2Manager.HasCharacterFacialHairStyle(race, gender, facialHairID)) - return false; - - if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::CustomDisplay1, customDisplay[0], 0, create)) - return false; - - if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::CustomDisplay2, customDisplay[1], 0, create)) - return false; - - if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::CustomDisplay3, customDisplay[2], 0, create)) - return false; - - return true; -} - uint32 Player::GetDefaultSpecId() const { return ASSERT_NOTNULL(sDB2Manager.GetDefaultChrSpecializationForClass(getClass()))->ID; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 66cf959b9b5..8ffe328ef5a 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -757,6 +757,7 @@ enum PlayedTimeIndex enum PlayerLoginQueryIndex { PLAYER_LOGIN_QUERY_LOAD_FROM, + PLAYER_LOGIN_QUERY_LOAD_CUSTOMIZATIONS, PLAYER_LOGIN_QUERY_LOAD_GROUP, PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES, PLAYER_LOGIN_QUERY_LOAD_AURAS, @@ -1064,7 +1065,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> uint8 GetChatFlags() const; std::string autoReplyMsg; - uint32 GetBarberShopCost(BarberShopStyleEntry const* newHairStyle, uint8 newHairColor, BarberShopStyleEntry const* newFacialHair, BarberShopStyleEntry const* newSkin, BarberShopStyleEntry const* newFace, std::array<BarberShopStyleEntry const*, PLAYER_CUSTOM_DISPLAY_SIZE> const& newCustomDisplay) const; + int64 GetBarberShopCost(Trinity::IteratorPair<UF::ChrCustomizationChoice const*> newCustomizations) const; PlayerSocial* GetSocial() const { return m_social; } void RemoveSocial(); @@ -1484,7 +1485,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> static bool IsValidGender(uint8 Gender) { return Gender <= GENDER_FEMALE; } static bool IsValidClass(uint8 Class) { return ((1 << (Class - 1)) & CLASSMASK_ALL_PLAYABLE) != 0; } static bool IsValidRace(uint8 Race) { return Trinity::RaceMask<uint64>{ RACEMASK_ALL_PLAYABLE }.HasRace(Race); } - static bool ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> const& customDisplay, bool create = false); /*********************************************************/ /*** SAVE SYSTEM ***/ @@ -1495,6 +1495,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void SaveInventoryAndGoldToDB(CharacterDatabaseTransaction& trans); // fast save function for item/money cheating preventing void SaveGoldToDB(CharacterDatabaseTransaction& trans) const; + static void SaveCustomizations(CharacterDatabaseTransaction trans, ObjectGuid::LowType guid, + Trinity::IteratorPair<UF::ChrCustomizationChoice const*> customizations); static void SetUInt32ValueInArray(Tokenizer& data, uint16 index, uint32 value); static void SavePositionInDB(WorldLocation const& loc, uint16 zoneId, ObjectGuid guid, CharacterDatabaseTransaction& trans); @@ -2438,17 +2440,39 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void RemovePlayerFlagEx(PlayerFlagsEx flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::PlayerFlagsEx), flags); } void SetPlayerFlagsEx(PlayerFlagsEx flags) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::PlayerFlagsEx), flags); } - void SetSkinId(uint8 skinId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::SkinID), skinId); } - void SetFaceId(uint8 faceId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::FaceID), faceId); } - void SetHairStyleId(uint8 hairStyleId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::HairStyleID), hairStyleId); } - void SetHairColorId(uint8 hairColorId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::HairColorID), hairColorId); } - void SetFacialHairStyleId(uint8 facialHairStyleId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::FacialHairStyleID), facialHairStyleId); } + uint32 GetCustomizationChoice(uint32 chrCustomizationOptionId) const + { + int32 choiceIndex = m_playerData->Customizations.FindIndexIf([chrCustomizationOptionId](UF::ChrCustomizationChoice choice) + { + return choice.ChrCustomizationOptionID == chrCustomizationOptionId; + }); + + if (choiceIndex >= 0) + return m_playerData->Customizations[choiceIndex].ChrCustomizationChoiceID; + + return 0; + } + + template<typename Iter> + void SetCustomizations(Trinity::IteratorPair<Iter> customizations, bool markChanged = true) + { + if (markChanged) + m_customizationsChanged = true; + + ClearDynamicUpdateFieldValues(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::Customizations)); + for (auto&& customization : customizations) + { + UF::ChrCustomizationChoice& newChoice = AddDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::Customizations)); + newChoice.ChrCustomizationOptionID = customization.ChrCustomizationOptionID; + newChoice.ChrCustomizationChoiceID = customization.ChrCustomizationChoiceID; + } + } + Gender GetNativeSex() const { return Gender(*m_playerData->NativeSex); } void SetNativeSex(uint8 sex) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::NativeSex), sex); } void SetPvpTitle(uint8 pvpTitle) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::PvpTitle), pvpTitle); } void SetArenaFaction(uint8 arenaFaction) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::ArenaFaction), arenaFaction); } void ApplyModFakeInebriation(int32 mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::FakeInebriation), mod, apply); } void SetVirtualPlayerRealm(uint32 virtualRealmAddress) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::VirtualPlayerRealm), virtualRealmAddress); } - void SetCustomDisplayOption(uint32 slot, uint8 customDisplayOption) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::CustomDisplayOption, slot), customDisplayOption); } void AddHeirloom(int32 itemId, uint32 flags) { @@ -2600,6 +2624,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> /*** SAVE SYSTEM ***/ /*********************************************************/ + void _SaveCustomizations(CharacterDatabaseTransaction trans); void _SaveActions(CharacterDatabaseTransaction& trans); void _SaveAuras(CharacterDatabaseTransaction& trans); void _SaveInventory(CharacterDatabaseTransaction& trans); @@ -2639,6 +2664,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> uint32 m_team; uint32 m_nextSave; + bool m_customizationsChanged; time_t m_speakTime; uint32 m_speakCount; Difficulty m_dungeonDifficulty; @@ -2872,4 +2898,15 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> TC_GAME_API void AddItemsSetItem(Player* player, Item* item); TC_GAME_API void RemoveItemsSetItem(Player* player, ItemTemplate const* proto); +// Transforms a container of customization choices with continuous storage into iterator pair that does not depend on container +// and doesn't force implementations in header files +template<typename Container> +Trinity::IteratorPair<UF::ChrCustomizationChoice const*> MakeChrCustomizationChoiceRange(Container const& container) +{ + static_assert(std::is_same<typename Container::value_type, UF::ChrCustomizationChoice>::value, + "MakeChrCustomizationChoiceRange must be used with containers of UF::ChrCustomizationChoice"); + + return { container.data(), container.data() + container.size() }; +} + #endif diff --git a/src/server/game/Entities/Player/RestMgr.cpp b/src/server/game/Entities/Player/RestMgr.cpp index 123e09a108d..13083a0a74a 100644 --- a/src/server/game/Entities/Player/RestMgr.cpp +++ b/src/server/game/Entities/Player/RestMgr.cpp @@ -127,7 +127,11 @@ uint32 RestMgr::GetRestBonusFor(RestTypes restType, uint32 xp) if (rested_bonus > xp) // max rested_bonus == xp or (r+x) = 200% xp rested_bonus = xp; - SetRestBonus(restType, GetRestBonus(restType) - rested_bonus); + uint32 rested_loss = rested_bonus; + if (restType == REST_TYPE_XP) + AddPct(rested_loss, _player->GetTotalAuraModifier(SPELL_AURA_MOD_RESTED_XP_CONSUMPTION)); + + SetRestBonus(restType, GetRestBonus(restType) - rested_loss); TC_LOG_DEBUG("entities.player", "RestMgr::GetRestBonus: Player '%s' (%s) gain %u xp (+%u Rested Bonus). Rested points=%f", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), xp + rested_bonus, rested_bonus, GetRestBonus(restType)); return rested_bonus; diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 5be8dac7af0..b5822d11f8a 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -74,7 +74,7 @@ void Totem::InitStats(uint32 duration) // Get spell cast by totem if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(GetSpell(), GetMap()->GetDifficultyID())) - if (totemSpell->CalcCastTime(getLevel())) // If spell has cast time -> its an active totem + if (totemSpell->CalcCastTime()) // If spell has cast time -> its an active totem m_type = TOTEM_ACTIVE; m_duration = duration; diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index fc19f60d77d..a312228ffc0 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -573,7 +573,8 @@ void Player::UpdateHealingDonePercentMod() for (AuraEffect const* auraEffect : GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT)) AddPct(value, auraEffect->GetAmount()); - SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModHealingDonePercent), value); + for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i) + SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModHealingDonePercent, i), value); } float const m_diminishing_k[MAX_CLASSES] = diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b8e9166bbe5..a09f5bb6032 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -7080,29 +7080,22 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto return std::max(crit_chance, 0.0f); } -uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* /*victim*/) +uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim) { // Calculate critical bonus - int32 crit_bonus = damage; + int32 crit_bonus = damage * 2; float crit_mod = 0.0f; - switch (spellProto->DmgClass) - { - case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100% - case SPELL_DAMAGE_CLASS_RANGED: - /// @todo write here full calculation for melee/ranged spells - crit_bonus += damage; - break; - default: - crit_bonus += damage / 2; // for spells is 50% - break; - } - crit_mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellProto->GetSchoolMask()) - 1.0f) * 100; if (crit_bonus != 0) AddPct(crit_bonus, crit_mod); + AddPct(crit_bonus, victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRITICAL_DAMAGE_TAKEN_FROM_CASTER, [&](AuraEffect const* aurEff) + { + return aurEff->GetCasterGUID() == GetGUID(); + })); + crit_bonus -= damage; if (damage > uint32(crit_bonus)) @@ -7230,7 +7223,14 @@ float Unit::SpellHealingPctDone(Unit* /*victim*/, SpellInfo const* spellProto) c return 1.0f; if (Player const* thisPlayer = ToPlayer()) - return thisPlayer->m_activePlayerData->ModHealingDonePercent; + { + float maxModDamagePercentSchool = 0.0f; + for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i) + if (spellProto->GetSchoolMask() & (1 << i)) + maxModDamagePercentSchool = std::max(maxModDamagePercentSchool, thisPlayer->m_activePlayerData->ModHealingDonePercent[i]); + + return maxModDamagePercentSchool; + } float DoneTotalMod = 1.0f; @@ -11081,7 +11081,7 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp if (overTime > 0 && CastingTime > 0 && DirectDamage) { // mainly for DoTs which are 3500 here otherwise - uint32 OriginalCastTime = spellProto->CalcCastTime(getLevel()); + uint32 OriginalCastTime = spellProto->CalcCastTime(); if (OriginalCastTime > 7000) OriginalCastTime = 7000; if (OriginalCastTime < 1500) OriginalCastTime = 1500; // Portion to Over Time @@ -11160,7 +11160,7 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect DotFactor /= DotTicks; } - int32 CastingTime = spellInfo->IsChanneled() ? spellInfo->GetDuration() : spellInfo->CalcCastTime(getLevel()); + int32 CastingTime = spellInfo->IsChanneled() ? spellInfo->GetDuration() : spellInfo->CalcCastTime(); // Distribute Damage over multiple effects, reduce by AoE CastingTime = GetCastingTimeForBonus(spellInfo, damagetype, CastingTime); @@ -12634,396 +12634,56 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form, uint32 spellId) const if (ShapeshiftForm(artifactAppearance->OverrideShapeshiftFormID) == form) return artifactAppearance->OverrideShapeshiftDisplayID; - switch (form) + if (ShapeshiftFormModelData const* formModelData = sDB2Manager.GetShapeshiftFormModelData(getRace(), thisPlayer->GetNativeSex(), form)) { - case FORM_CAT_FORM: - // Based on Hair color - if (getRace() == RACE_NIGHTELF) - { - uint8 hairColor = thisPlayer->m_playerData->HairColorID; - if (HasAura(210333)) // Glyph of the Feral Chameleon - hairColor = urand(0, 10); - - switch (hairColor) - { - case 7: // Violet - case 8: - return 29405; - case 3: // Light Blue - return 29406; - case 0: // Green - case 1: // Light Green - case 2: // Dark Green - return 29407; - case 4: // White - return 29408; - default: // Original - Dark Blue - return 892; - } - } - else if (getRace() == RACE_TROLL) - { - uint8 hairColor = thisPlayer->m_playerData->HairColorID; - if (HasAura(210333)) // Glyph of the Feral Chameleon - hairColor = urand(0, 12); - - switch (hairColor) - { - case 0: // Red - case 1: - return 33668; - case 2: // Yellow - case 3: - return 33667; - case 4: // Blue - case 5: - case 6: - return 33666; - case 7: // Purple - case 10: - return 33665; - default: // Original - White - return 33669; - } - } - else if (getRace() == RACE_WORGEN) - { - // Based on Skin color - uint8 skinColor = thisPlayer->m_playerData->SkinID; - if (HasAura(210333)) // Glyph of the Feral Chameleon - skinColor = urand(0, 9); - - // Male - if (getGender() == GENDER_MALE) - { - switch (skinColor) - { - case 1: // Brown - return 33662; - case 2: // Black - case 7: - return 33661; - case 4: // Yellow - return 33664; - case 3: // White - case 5: - return 33663; - default: // Original - Gray - return 33660; - } - } - // Female - else - { - switch (skinColor) - { - case 5: // Brown - case 6: - return 33662; - case 7: // Black - case 8: - return 33661; - case 3: // yellow - case 4: - return 33664; - case 2: // White - return 33663; - default: // Original - Gray - return 33660; - } - } - } - // Based on Skin color - else if (getRace() == RACE_TAUREN) - { - uint8 skinColor = thisPlayer->m_playerData->SkinID; - if (HasAura(210333)) // Glyph of the Feral Chameleon - skinColor = urand(0, 20); - - // Male - if (getGender() == GENDER_MALE) - { - switch (skinColor) - { - case 12: // White - case 13: - case 14: - case 18: // Completly White - return 29409; - case 9: // Light Brown - case 10: - case 11: - return 29410; - case 6: // Brown - case 7: - case 8: - return 29411; - case 0: // Dark - case 1: - case 2: - case 3: // Dark Grey - case 4: - case 5: - return 29412; - default: // Original - Grey - return 8571; - } - } - // Female - else - { - switch (skinColor) - { - case 10: // White - return 29409; - case 6: // Light Brown - case 7: - return 29410; - case 4: // Brown - case 5: - return 29411; - case 0: // Dark - case 1: - case 2: - case 3: - return 29412; - default: // Original - Grey - return 8571; - } - } - } - else if (Player::TeamForRace(getRace()) == ALLIANCE) - return 892; - else - return 8571; - case FORM_BEAR_FORM: - // Based on Hair color - if (getRace() == RACE_NIGHTELF) - { - uint8 hairColor = thisPlayer->m_playerData->HairColorID; - if (HasAura(107059)) // Glyph of the Ursol Chameleon - hairColor = urand(0, 8); + bool useRandom = false; + switch (form) + { + case FORM_CAT_FORM: useRandom = HasAura(210333); break; // Glyph of the Feral Chameleon + case FORM_TRAVEL_FORM: useRandom = HasAura(344336); break; // Glyph of the Swift Chameleon + case FORM_AQUATIC_FORM: useRandom = HasAura(344338); break; // Glyph of the Aquatic Chameleon + case FORM_BEAR_FORM: useRandom = HasAura(107059); break; // Glyph of the Ursol Chameleon + case FORM_FLIGHT_FORM: useRandom = HasAura(344342); break; // Glyph of the Aerial Chameleon + default: + break; + } - switch (hairColor) - { - case 0: // Green - case 1: // Light Green - case 2: // Dark Green - return 29413; // 29415? - case 6: // Dark Blue - return 29414; - case 4: // White - return 29416; - case 3: // Light Blue - return 29417; - default: // Original - Violet - return 29415; - } - } - else if (getRace() == RACE_TROLL) - { - uint8 hairColor = thisPlayer->m_playerData->HairColorID; - if (HasAura(107059)) // Glyph of the Ursol Chameleon - hairColor = urand(0, 14); + if (useRandom) + { + std::vector<uint32> displayIds; + displayIds.reserve(formModelData->Choices->size()); - switch (hairColor) - { - case 0: // Red - case 1: - return 33657; - case 2: // Yellow - case 3: - return 33659; - case 7: // Purple - case 10: - return 33656; - case 8: // White - case 9: - case 11: - case 12: - return 33658; - default: // Original - Blue - return 33655; - } - } - else if (getRace() == RACE_WORGEN) + for (std::size_t i = 0; i < formModelData->Choices->size(); ++i) { - // Based on Skin color - uint8 skinColor = thisPlayer->m_playerData->SkinID; - if (HasAura(107059)) // Glyph of the Ursol Chameleon - skinColor = urand(0, 8); - - // Male - if (getGender() == GENDER_MALE) + if (ChrCustomizationDisplayInfoEntry const* displayInfo = formModelData->Displays[i]) { - switch (skinColor) - { - case 1: // Brown - return 33652; - case 2: // Black - case 7: - return 33651; - case 4: // Yellow - return 33653; - case 3: // White - case 5: - return 33654; - default: // Original - Gray - return 33650; - } - } - // Female - else - { - switch (skinColor) - { - case 5: // Brown - case 6: - return 33652; - case 7: // Black - case 8: - return 33651; - case 3: // yellow - case 4: - return 33654; - case 2: // White - return 33653; - default: // Original - Gray - return 33650; - } + ChrCustomizationReqEntry const* choiceReq = sChrCustomizationReqStore.LookupEntry((*formModelData->Choices)[i]->ChrCustomizationReqID); + if (!choiceReq || thisPlayer->GetSession()->MeetsChrCustomizationReq(choiceReq, Classes(getClass()), false, + MakeChrCustomizationChoiceRange(thisPlayer->m_playerData->Customizations))) + displayIds.push_back(displayInfo->DisplayID); } } - // Based on Skin color - else if (getRace() == RACE_TAUREN) - { - uint8 skinColor = thisPlayer->m_playerData->SkinID; - if (HasAura(107059)) // Glyph of the Ursol Chameleon - skinColor = urand(0, 20); - // Male - if (getGender() == GENDER_MALE) - { - switch (skinColor) - { - case 0: // Dark (Black) - case 1: - case 2: - return 29418; - case 3: // White - case 4: - case 5: - case 12: - case 13: - case 14: - return 29419; - case 9: // Light Brown/Grey - case 10: - case 11: - case 15: - case 16: - case 17: - return 29420; - case 18: // Completly White - return 29421; - default: // Original - Brown - return 2289; - } - } - // Female - else - { - switch (skinColor) - { - case 0: // Dark (Black) - case 1: - return 29418; - case 2: // White - case 3: - return 29419; - case 6: // Light Brown/Grey - case 7: - case 8: - case 9: - return 29420; - case 10: // Completly White - return 29421; - default: // Original - Brown - return 2289; - } - } - } - else if (Player::TeamForRace(getRace()) == ALLIANCE) - return 29415; - else - return 2289; - case FORM_FLIGHT_FORM: - if (Player::TeamForRace(getRace()) == ALLIANCE) - return 20857; - return 20872; - case FORM_FLIGHT_FORM_EPIC: - if (HasAura(219062)) // Glyph of the Sentinel - { - switch (getRace()) - { - case RACE_NIGHTELF: // Blue - return 64328; - case RACE_TAUREN: // Brown - return 64329; - case RACE_WORGEN: // Purple - return 64330; - case RACE_TROLL: // White - return 64331; - default: - break; - } - } - if (Player::TeamForRace(getRace()) == ALLIANCE) - return (getRace() == RACE_WORGEN ? 37729 : 21243); - if (getRace() == RACE_TROLL) - return 37730; - return 21244; - case FORM_MOONKIN_FORM: - { - switch (getRace()) - { - case RACE_NIGHTELF: - return 15374; - case RACE_TAUREN: - return 15375; - case RACE_WORGEN: - return 37173; - case RACE_TROLL: - return 37174; - default: - break; - } - break; + if (!displayIds.empty()) + return Trinity::Containers::SelectRandomContainerElement(displayIds); } - case FORM_AQUATIC_FORM: - if (HasAura(114333)) // Glyph of the Orca - return 4591; - return 2428; - case FORM_TRAVEL_FORM: + else { - if (HasAura(131113)) // Glyph of the Cheetah - return 1043; - - if (HasAura(224122)) // Glyph of the Doe - return 70450; - - switch (getRace()) + if (uint32 formChoice = thisPlayer->GetCustomizationChoice(formModelData->OptionID)) { - case RACE_NIGHTELF: - case RACE_WORGEN: - return 40816; - case RACE_TROLL: - case RACE_TAUREN: - return 45339; - default: - break; + auto choiceItr = std::find_if(formModelData->Choices->begin(), formModelData->Choices->end(), [formChoice](ChrCustomizationChoiceEntry const* choice) + { + return choice->ID == formChoice; + }); + + if (choiceItr != formModelData->Choices->end()) + if (ChrCustomizationDisplayInfoEntry const* displayInfo = formModelData->Displays[std::distance(formModelData->Choices->begin(), choiceItr)]) + return displayInfo->DisplayID; } - break; } + } + switch (form) + { case FORM_GHOST_WOLF: { if (HasAura(58135)) // Glyph of Spectral Wolf diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 1c32fc3ff8b..9480942eea5 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1646,13 +1646,14 @@ class TC_GAME_API Unit : public WorldObject .ModifyValue(&UF::UnitData::ChannelData) .ModifyValue(&UF::UnitChannel::SpellID), channelSpellId); } - uint32 GetChannelSpellXSpellVisualId() const { return m_unitData->ChannelData->SpellXSpellVisualID; } - void SetChannelSpellXSpellVisualId(SpellCastVisual channelVisual) + uint32 GetChannelSpellXSpellVisualId() const { return m_unitData->ChannelData->SpellVisual.SpellXSpellVisualID; } + uint32 GetChannelScriptVisualId() const { return m_unitData->ChannelData->SpellVisual.ScriptVisualID; } + void SetChannelVisual(SpellCastVisual channelVisual) { SetUpdateFieldValue(m_values .ModifyValue(&Unit::m_unitData) .ModifyValue(&UF::UnitData::ChannelData) - .ModifyValue(&UF::UnitChannel::SpellXSpellVisualID), channelVisual.SpellXSpellVisualID); + .ModifyValue(&UF::UnitChannel::SpellVisual), channelVisual); } void AddChannelObject(ObjectGuid guid) { AddDynamicUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ChannelObjects)) = guid; } void SetChannelObject(uint32 slot, ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ChannelObjects, slot), guid); } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 6831a01a1f7..2b5be2e3fd5 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -3122,25 +3122,6 @@ void ObjectMgr::LoadItemTemplates() itemItr->second.Effects.push_back(effectEntry); } - // Check if item templates for DBC referenced character start outfit are present - std::set<uint32> notFoundOutfit; - for (CharStartOutfitEntry const* entry : sCharStartOutfitStore) - { - for (int j = 0; j < MAX_OUTFIT_ITEMS; ++j) - { - if (entry->ItemID[j] <= 0) - continue; - - uint32 item_id = entry->ItemID[j]; - - if (!GetItemTemplate(item_id)) - notFoundOutfit.insert(item_id); - } - } - - for (std::set<uint32>::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr) - TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not exist but is referenced in `CharStartOutfit.dbc`", *itr); - TC_LOG_INFO("server.loading", ">> Loaded %u item templates in %u ms", sparseCount, GetMSTimeDiffToNow(oldMSTime)); } @@ -3422,31 +3403,22 @@ void ObjectMgr::PlayerCreateInfoAddItemHelper(uint32 race_, uint32 class_, uint3 return; if (count > 0) - _playerInfo[race_][class_]->item.push_back(PlayerCreateInfoItem(itemId, count)); + _playerInfo[race_][class_]->item.emplace_back(itemId, count); else { if (count < -1) TC_LOG_ERROR("sql.sql", "Invalid count %i specified on item %u be removed from original player create info (use -1)!", count, itemId); - for (uint32 gender = 0; gender < GENDER_NONE; ++gender) - { - if (CharStartOutfitEntry const* entry = sDB2Manager.GetCharStartOutfitEntry(race_, class_, gender)) - { - bool found = false; - for (uint8 x = 0; x < MAX_OUTFIT_ITEMS; ++x) - { - if (entry->ItemID[x] > 0 && uint32(entry->ItemID[x]) == itemId) - { - found = true; - const_cast<CharStartOutfitEntry*>(entry)->ItemID[x] = 0; - break; - } - } + PlayerCreateInfoItems& items = _playerInfo[race_][class_]->item; - if (!found) - TC_LOG_ERROR("sql.sql", "Item %u specified to be removed from original create info not found in dbc!", itemId); - } + auto erased = std::remove_if(items.begin(), items.end(), [itemId](PlayerCreateInfoItem const& item) { return item.item_id == itemId; }); + if (erased == items.end()) + { + TC_LOG_ERROR("sql.sql", "Item %u specified to be removed from original create info not found in db2!", itemId); + return; } + + items.erase(erased, items.end()); } } @@ -3480,41 +3452,42 @@ void ObjectMgr::LoadPlayerInfo() float positionZ = fields[6].GetFloat(); float orientation = fields[7].GetFloat(); - if (current_race >= MAX_RACES) + if (!sChrRacesStore.LookupEntry(current_race)) { TC_LOG_ERROR("sql.sql", "Wrong race %u in `playercreateinfo` table, ignoring.", current_race); continue; } - ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(current_race); - if (!rEntry) + if (!sChrClassesStore.LookupEntry(current_class)) { - TC_LOG_ERROR("sql.sql", "Wrong race %u in `playercreateinfo` table, ignoring.", current_race); + TC_LOG_ERROR("sql.sql", "Wrong class %u in `playercreateinfo` table, ignoring.", current_class); continue; } - if (current_class >= MAX_CLASSES) + // accept DB data only for valid position (and non instanceable) + if (!MapManager::IsValidMapCoord(mapId, positionX, positionY, positionZ, orientation)) { - TC_LOG_ERROR("sql.sql", "Wrong class %u in `playercreateinfo` table, ignoring.", current_class); + TC_LOG_ERROR("sql.sql", "Wrong home position for class %u race %u pair in `playercreateinfo` table, ignoring.", current_class, current_race); continue; } - if (!sChrClassesStore.LookupEntry(current_class)) + if (sMapStore.LookupEntry(mapId)->Instanceable()) { - TC_LOG_ERROR("sql.sql", "Wrong class %u in `playercreateinfo` table, ignoring.", current_class); + TC_LOG_ERROR("sql.sql", "Home position in instanceable map for class %u race %u pair in `playercreateinfo` table, ignoring.", current_class, current_race); continue; } - // accept DB data only for valid position (and non instanceable) - if (!MapManager::IsValidMapCoord(mapId, positionX, positionY, positionZ, orientation)) + ChrModelEntry const* maleModel = sDB2Manager.GetChrModel(current_race, GENDER_MALE); + if (!maleModel) { - TC_LOG_ERROR("sql.sql", "Wrong home position for class %u race %u pair in `playercreateinfo` table, ignoring.", current_class, current_race); + TC_LOG_ERROR("sql.sql", "Missing male model for race %u, ignoring.", current_race); continue; } - if (sMapStore.LookupEntry(mapId)->Instanceable()) + ChrModelEntry const* femaleModel = sDB2Manager.GetChrModel(current_race, GENDER_FEMALE); + if (!femaleModel) { - TC_LOG_ERROR("sql.sql", "Home position in instanceable map for class %u race %u pair in `playercreateinfo` table, ignoring.", current_class, current_race); + TC_LOG_ERROR("sql.sql", "Missing female model for race %u, ignoring.", current_race); continue; } @@ -3525,8 +3498,8 @@ void ObjectMgr::LoadPlayerInfo() info->positionY = positionY; info->positionZ = positionZ; info->orientation = orientation; - info->displayId_m = rEntry->MaleDisplayId; - info->displayId_f = rEntry->FemaleDisplayId; + info->displayId_m = maleModel->DisplayID; + info->displayId_f = femaleModel->DisplayID; _playerInfo[current_race][current_class] = info; ++count; @@ -3540,6 +3513,60 @@ void ObjectMgr::LoadPlayerInfo() // Load playercreate items TC_LOG_INFO("server.loading", "Loading Player Create Items Data..."); { + std::unordered_map<uint32, std::vector<ItemTemplate const*>> itemsByCharacterLoadout; + for (CharacterLoadoutItemEntry const* characterLoadoutItem : sCharacterLoadoutItemStore) + if (ItemTemplate const* itemTemplate = GetItemTemplate(characterLoadoutItem->ItemID)) + itemsByCharacterLoadout[characterLoadoutItem->CharacterLoadoutID].push_back(itemTemplate); + + for (CharacterLoadoutEntry const* characterLoadout : sCharacterLoadoutStore) + { + if (!characterLoadout->IsForNewCharacter()) + continue; + + std::vector<ItemTemplate const*> const* items = Trinity::Containers::MapGetValuePtr(itemsByCharacterLoadout, characterLoadout->ID); + if (!items) + continue; + + for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex) + { + if (!characterLoadout->RaceMask.HasRace(raceIndex)) + continue; + + if (PlayerInfo* playerInfo = _playerInfo[raceIndex][characterLoadout->ChrClassID]) + { + for (ItemTemplate const* itemTemplate : *items) + { + // BuyCount by default + uint32 count = itemTemplate->GetBuyCount(); + + // special amount for food/drink + if (itemTemplate->GetClass() == ITEM_CLASS_CONSUMABLE && itemTemplate->GetSubClass() == ITEM_SUBCLASS_FOOD_DRINK) + { + if (!itemTemplate->Effects.empty()) + { + switch (itemTemplate->Effects[0]->SpellCategoryID) + { + case SPELL_CATEGORY_FOOD: // food + count = characterLoadout->ChrClassID == CLASS_DEATH_KNIGHT ? 10 : 4; + break; + case SPELL_CATEGORY_DRINK: // drink + count = 2; + break; + } + } + if (itemTemplate->GetMaxStackSize() < count) + count = itemTemplate->GetMaxStackSize(); + } + + playerInfo->item.emplace_back(itemTemplate->GetId(), count); + } + } + } + } + } + + TC_LOG_INFO("server.loading", "Loading Player Create Items Override Data..."); + { uint32 oldMSTime = getMSTime(); // 0 1 2 3 QueryResult result = WorldDatabase.Query("SELECT race, class, itemid, amount FROM playercreateinfo_item"); diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 56d2e458474..487ac491966 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -535,7 +535,7 @@ void Guild::Member::SetStats(Player* player) m_name = player->GetName(); m_level = player->getLevel(); m_class = player->getClass(); - _gender = player->m_playerData->NativeSex; + _gender = player->GetNativeSex(); m_zoneId = player->GetZoneId(); m_accountId = player->GetSession()->GetAccountId(); m_achievementPoints = player->GetAchievementPoints(); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 49283ac0c26..9b4b8f41f97 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -31,6 +31,7 @@ #include "Chat.h" #include "ClientConfigPackets.h" #include "Common.h" +#include "Containers.h" #include "DatabaseEnv.h" #include "DB2Stores.h" #include "EquipmentSetPackets.h" @@ -88,6 +89,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_FROM, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_CUSTOMIZATIONS); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUSTOMIZATIONS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER); stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GROUP, stmt); @@ -307,16 +312,78 @@ bool LoginQueryHolder::Initialize() return res; } -void WorldSession::HandleCharEnum(PreparedQueryResult result) +class EnumCharactersQueryHolder : public CharacterDatabaseQueryHolder +{ +public: + enum + { + CHARACTERS, + CUSTOMIZATIONS, + + MAX + }; + + EnumCharactersQueryHolder() + { + SetSize(MAX); + } + + bool Initialize(uint32 accountId, bool withDeclinedNames, bool isDeletedCharacters) + { + _isDeletedCharacters = isDeletedCharacters; + + constexpr CharacterDatabaseStatements statements[2][3] = + { + { CHAR_SEL_ENUM, CHAR_SEL_ENUM_DECLINED_NAME, CHAR_SEL_ENUM_CUSTOMIZATIONS }, + { CHAR_SEL_UNDELETE_ENUM, CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME, CHAR_SEL_UNDELETE_ENUM_CUSTOMIZATIONS } + }; + + bool result = true; + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(statements[isDeletedCharacters ? 1 : 0][withDeclinedNames ? 1 : 0]); + stmt->setUInt8(0, PET_SAVE_AS_CURRENT); + stmt->setUInt32(1, accountId); + result &= SetPreparedQuery(CHARACTERS, stmt); + + stmt = CharacterDatabase.GetPreparedStatement(statements[isDeletedCharacters ? 1 : 0][2]); + stmt->setUInt32(0, accountId); + result &= SetPreparedQuery(CUSTOMIZATIONS, stmt); + + return result; + } + + bool IsDeletedCharacters() const { return _isDeletedCharacters; } + +private: + bool _isDeletedCharacters = false; +}; + +void WorldSession::HandleCharEnum(CharacterDatabaseQueryHolder* holder) { WorldPackets::Character::EnumCharactersResult charEnum; charEnum.Success = true; - charEnum.IsDeletedCharacters = false; + charEnum.IsDeletedCharacters = static_cast<EnumCharactersQueryHolder*>(holder)->IsDeletedCharacters(); charEnum.DisabledClassesMask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK); - _legitCharacters.clear(); + if (!charEnum.IsDeletedCharacters) + _legitCharacters.clear(); - if (result) + std::unordered_map<ObjectGuid::LowType, std::vector<UF::ChrCustomizationChoice>> customizations; + if (PreparedQueryResult customizationsResult = holder->GetPreparedResult(EnumCharactersQueryHolder::CUSTOMIZATIONS)) + { + do + { + Field* fields = customizationsResult->Fetch(); + std::vector<UF::ChrCustomizationChoice>& customizationsForCharacter = customizations[fields[0].GetUInt64()]; + + customizationsForCharacter.emplace_back(); + UF::ChrCustomizationChoice& choice = customizationsForCharacter.back(); + choice.ChrCustomizationOptionID = fields[1].GetUInt32(); + choice.ChrCustomizationChoiceID = fields[2].GetUInt32(); + + } while (customizationsResult->NextRow()); + } + + if (PreparedQueryResult result = holder->GetPreparedResult(EnumCharactersQueryHolder::CHARACTERS)) { do { @@ -324,32 +391,33 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result) WorldPackets::Character::EnumCharactersResult::CharacterInfo& charInfo = charEnum.Characters.back(); + if (std::vector<UF::ChrCustomizationChoice>* customizationsForChar = Trinity::Containers::MapGetValuePtr(customizations, charInfo.Guid.GetCounter())) + charInfo.Customizations = std::move(*customizationsForChar); + TC_LOG_INFO("network", "Loading char guid %s from account %u.", charInfo.Guid.ToString().c_str(), GetAccountId()); - if (!Player::ValidateAppearance(charInfo.RaceID, charInfo.ClassID, charInfo.SexID, charInfo.HairStyle, charInfo.HairColor, charInfo.FaceID, charInfo.FacialHair, charInfo.SkinID, charInfo.CustomDisplay)) + if (!charEnum.IsDeletedCharacters) { - TC_LOG_ERROR("entities.player.loading", "Player %s has wrong Appearance values (Hair/Skin/Color), forcing recustomize", charInfo.Guid.ToString().c_str()); + if (!ValidateAppearance(Races(charInfo.RaceID), Classes(charInfo.ClassID), Gender(charInfo.SexID), MakeChrCustomizationChoiceRange(charInfo.Customizations))) + { + TC_LOG_ERROR("entities.player.loading", "Player %s has wrong Appearance values (Hair/Skin/Color), forcing recustomize", charInfo.Guid.ToString().c_str()); - // Make sure customization always works properly - send all zeroes instead - charInfo.SkinID = 0; - charInfo.FaceID = 0; - charInfo.HairStyle = 0; - charInfo.HairColor = 0; - charInfo.FacialHair = 0; + charInfo.Customizations.clear(); - if (!(charInfo.Flags2 == CHAR_CUSTOMIZE_FLAG_CUSTOMIZE)) - { - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE)); - stmt->setUInt64(1, charInfo.Guid.GetCounter()); - CharacterDatabase.Execute(stmt); - charInfo.Flags2 = CHAR_CUSTOMIZE_FLAG_CUSTOMIZE; + if (!(charInfo.Flags2 == CHAR_CUSTOMIZE_FLAG_CUSTOMIZE)) + { + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE)); + stmt->setUInt64(1, charInfo.Guid.GetCounter()); + CharacterDatabase.Execute(stmt); + charInfo.Flags2 = CHAR_CUSTOMIZE_FLAG_CUSTOMIZE; + } } - } - // Do not allow locked characters to login - if (!(charInfo.Flags & (CHARACTER_FLAG_LOCKED_FOR_TRANSFER | CHARACTER_FLAG_LOCKED_BY_BILLING))) - _legitCharacters.insert(charInfo.Guid); + // Do not allow locked characters to login + if (!(charInfo.Flags & (CHARACTER_FLAG_LOCKED_FOR_TRANSFER | CHARACTER_FLAG_LOCKED_BY_BILLING))) + _legitCharacters.insert(charInfo.Guid); + } if (!sCharacterCache->HasCharacterCacheEntry(charInfo.Guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. sCharacterCache->AddCharacterCacheEntry(charInfo.Guid, GetAccountId(), charInfo.Name, charInfo.SexID, charInfo.RaceID, charInfo.ClassID, charInfo.ExperienceLevel, false); @@ -370,6 +438,8 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result) } SendPacket(charEnum.Write()); + + delete holder; } void WorldSession::HandleCharEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/) @@ -379,58 +449,123 @@ void WorldSession::HandleCharEnumOpcode(WorldPackets::Character::EnumCharacters& CharacterDatabase.Execute(stmt); /// get all the data necessary for loading all characters (along with their pets) on the account + EnumCharactersQueryHolder* holder = new EnumCharactersQueryHolder(); + if (!holder->Initialize(GetAccountId(), sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED), false)) + { + HandleCharEnum(holder); + return; + } - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED)) - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM_DECLINED_NAME); - else - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM); + _charEnumCallback = CharacterDatabase.DelayQueryHolder(holder); +} - stmt->setUInt8(0, PET_SAVE_AS_CURRENT); - stmt->setUInt32(1, GetAccountId()); +void WorldSession::HandleCharUndeleteEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/) +{ + /// get all the data necessary for loading all undeleted characters (along with their pets) on the account + EnumCharactersQueryHolder* holder = new EnumCharactersQueryHolder(); + if (!holder->Initialize(GetAccountId(), sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED), true)) + { + HandleCharEnum(holder); + return; + } - _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharEnum, this, std::placeholders::_1))); + _charEnumCallback = CharacterDatabase.DelayQueryHolder(holder); } -void WorldSession::HandleCharUndeleteEnum(PreparedQueryResult result) +bool WorldSession::MeetsChrCustomizationReq(ChrCustomizationReqEntry const* req, Classes playerClass, + bool checkRequiredDependentChoices, Trinity::IteratorPair<UF::ChrCustomizationChoice const*> selectedChoices) const { - WorldPackets::Character::EnumCharactersResult charEnum; - charEnum.Success = true; - charEnum.IsDeletedCharacters = true; - charEnum.DisabledClassesMask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK); + if (!req->GetFlags().HasFlag(ChrCustomizationReqFlag::HasRequirements)) + return true; - if (result) + if (req->ClassMask && !(req->ClassMask & (1 << (playerClass - 1)))) + return false; + + if (req->AchievementID /*&& !HasAchieved(req->AchievementID)*/) + return false; + + if (req->ItemModifiedAppearanceID && !GetCollectionMgr()->HasItemAppearance(req->ItemModifiedAppearanceID).first) + return false; + + if (checkRequiredDependentChoices) { - do + if (std::unordered_map<uint32, std::vector<uint32>> const* requiredChoices = sDB2Manager.GetRequiredCustomizationChoices(req->ID)) { - Field* fields = result->Fetch(); - WorldPackets::Character::EnumCharactersResult::CharacterInfo charInfo(fields); - - TC_LOG_INFO("network", "Loading undeleted char guid %s from account %u.", charInfo.Guid.ToString().c_str(), GetAccountId()); + for (std::pair<uint32 const /*chrCustomizationOptionId*/, std::vector<uint32>> const& requiredChoicesForOption : *requiredChoices) + { + bool hasRequiredChoiceForOption = false; + for (uint32 requiredChoice : requiredChoicesForOption.second) + { + auto choiceItr = std::find_if(selectedChoices.begin(), selectedChoices.end(), [requiredChoice](UF::ChrCustomizationChoice const& choice) + { + return choice.ChrCustomizationChoiceID == requiredChoice; + }); - if (!sCharacterCache->HasCharacterCacheEntry(charInfo.Guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. - sCharacterCache->AddCharacterCacheEntry(charInfo.Guid, GetAccountId(), charInfo.Name, charInfo.SexID, charInfo.RaceID, charInfo.ClassID, charInfo.ExperienceLevel, true); + if (choiceItr != selectedChoices.end()) + { + hasRequiredChoiceForOption = true; + break; + } + } - charEnum.Characters.emplace_back(charInfo); + if (!hasRequiredChoiceForOption) + return false; + } } - while (result->NextRow()); } - SendPacket(charEnum.Write()); + return true; } -void WorldSession::HandleCharUndeleteEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/) +bool WorldSession::ValidateAppearance(Races race, Classes playerClass, Gender gender, Trinity::IteratorPair<UF::ChrCustomizationChoice const*> customizations) { - /// get all the data necessary for loading all undeleted characters (along with their pets) on the account - CharacterDatabasePreparedStatement* stmt = nullptr; - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED)) - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME); - else - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_UNDELETE_ENUM); + std::vector<ChrCustomizationOptionEntry const*> const* options = sDB2Manager.GetCustomiztionOptions(race, gender); + if (!options) + return false; + + uint32 previousOption = 0; + + for (UF::ChrCustomizationChoice playerChoice : customizations) + { + // check uniqueness of options + if (playerChoice.ChrCustomizationOptionID == previousOption) + return false; + + previousOption = playerChoice.ChrCustomizationOptionID; + + // check if we can use this option + auto customizationOptionDataItr = std::find_if(options->begin(), options->end(), [&](ChrCustomizationOptionEntry const* option) + { + return option->ID == playerChoice.ChrCustomizationOptionID; + }); - stmt->setUInt8(0, PET_SAVE_AS_CURRENT); - stmt->setUInt32(1, GetAccountId()); + // option not found for race/gender combination + if (customizationOptionDataItr == options->end()) + return false; - _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharUndeleteEnum, this, std::placeholders::_1))); + if (ChrCustomizationReqEntry const* req = sChrCustomizationReqStore.LookupEntry((*customizationOptionDataItr)->ChrCustomizationReqID)) + if (!MeetsChrCustomizationReq(req, playerClass, false, customizations)) + return false; + + std::vector<ChrCustomizationChoiceEntry const*> const* choicesForOption = sDB2Manager.GetCustomiztionChoices(playerChoice.ChrCustomizationOptionID); + if (!choicesForOption) + return false; + + auto customizationChoiceDataItr = std::find_if(choicesForOption->begin(), choicesForOption->end(), [&](ChrCustomizationChoiceEntry const* choice) + { + return choice->ID == playerChoice.ChrCustomizationChoiceID; + }); + + // choice not found for option + if (customizationChoiceDataItr == choicesForOption->end()) + return false; + + if (ChrCustomizationReqEntry const* req = sChrCustomizationReqStore.LookupEntry((*customizationChoiceDataItr)->ChrCustomizationReqID)) + if (!MeetsChrCustomizationReq(req, playerClass, true, customizations)) + return false; + } + + return true; } void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharacter& charCreate) @@ -673,19 +808,6 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact if (checkDemonHunterReqs) { - uint8 accClass = field[2].GetUInt8(); - if (accClass == CLASS_DEMON_HUNTER) - { - if (freeDemonHunterSlots > 0) - --freeDemonHunterSlots; - - if (freeDemonHunterSlots == 0) - { - SendCharCreate(CHAR_CREATE_FAILED); - return; - } - } - if (!hasDemonHunterReqLevel) { uint8 accLevel = field[0].GetUInt8(); @@ -746,7 +868,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact { TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Create Character: %s %s", GetAccountId(), GetRemoteAddress().c_str(), newChar->GetName().c_str(), newChar->GetGUID().ToString().c_str()); sScriptMgr->OnPlayerCreate(newChar.get()); - sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->m_playerData->NativeSex, newChar->getRace(), newChar->getClass(), newChar->getLevel(), false); + sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->GetNativeSex(), newChar->getRace(), newChar->getClass(), newChar->getLevel(), false); SendCharCreate(CHAR_CREATE_SUCCESS, newChar->GetGUID()); } @@ -763,7 +885,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO); stmt->setUInt32(0, GetAccountId()); - stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEMON_HUNTER) ? 12 : 1); + stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEMON_HUNTER) ? 1200 : 1); // 200 (max chars per realm) + 1000 (max deleted chars per realm) queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt)); })); } @@ -1532,41 +1654,7 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPackets::Character::SetPlay void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance& packet) { - BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(packet.NewHairStyle); - if (!bs_hair || bs_hair->Type != 0 || bs_hair->Race != _player->getRace() || bs_hair->Sex != _player->m_playerData->NativeSex) - return; - - BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(packet.NewFacialHair); - if (!bs_facialHair || bs_facialHair->Type != 2 || bs_facialHair->Race != _player->getRace() || bs_facialHair->Sex != _player->m_playerData->NativeSex) - return; - - BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(packet.NewSkinColor); - if (bs_skinColor && (bs_skinColor->Type != 3 || bs_skinColor->Race != _player->getRace() || bs_skinColor->Sex != _player->m_playerData->NativeSex)) - return; - - BarberShopStyleEntry const* bs_face = sBarberShopStyleStore.LookupEntry(packet.NewFace); - if (bs_face && (bs_face->Type != 4 || bs_face->Race != _player->getRace() || bs_face->Sex != _player->m_playerData->NativeSex)) - return; - - std::array<BarberShopStyleEntry const*, PLAYER_CUSTOM_DISPLAY_SIZE> customDisplayEntries; - std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> customDisplay; - for (std::size_t i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - { - BarberShopStyleEntry const* bs_customDisplay = sBarberShopStyleStore.LookupEntry(packet.NewCustomDisplay[i]); - if (bs_customDisplay && (bs_customDisplay->Type != 5 + i || bs_customDisplay->Race != _player->getRace() || bs_customDisplay->Sex != _player->m_playerData->NativeSex)) - return; - - customDisplayEntries[i] = bs_customDisplay; - customDisplay[i] = bs_customDisplay ? bs_customDisplay->Data : 0; - } - - if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->m_playerData->NativeSex, - bs_hair->Data, - packet.NewHairColor, - bs_face ? bs_face->Data : _player->m_playerData->FaceID, - bs_facialHair->Data, - bs_skinColor ? bs_skinColor->Data : _player->m_playerData->SkinID, - customDisplay)) + if (!ValidateAppearance(Races(_player->getRace()), Classes(_player->getClass()), Gender(packet.NewSex), MakeChrCustomizationChoiceRange(packet.Customizations))) return; GameObject* go = _player->FindNearestGameObjectOfType(GAMEOBJECT_TYPE_BARBER_CHAIR, 5.0f); @@ -1582,12 +1670,12 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance return; } - uint32 cost = _player->GetBarberShopCost(bs_hair, packet.NewHairColor, bs_facialHair, bs_skinColor, bs_face, customDisplayEntries); + int64 cost = _player->GetBarberShopCost(MakeChrCustomizationChoiceRange(packet.Customizations)); // 0 - ok // 1, 3 - not enough money // 2 - you have to sit on barber chair - if (!_player->HasEnoughMoney((uint64)cost)) + if (!_player->HasEnoughMoney(cost)) { SendPacket(WorldPackets::Character::BarberShopResult(WorldPackets::Character::BarberShopResult::ResultEnum::NoMoney).Write()); return; @@ -1595,23 +1683,17 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance SendPacket(WorldPackets::Character::BarberShopResult(WorldPackets::Character::BarberShopResult::ResultEnum::Success).Write()); - _player->ModifyMoney(-int64(cost)); // it isn't free + _player->ModifyMoney(-cost); // it isn't free _player->UpdateCriteria(CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost); - _player->SetHairStyleId(bs_hair->Data); - _player->SetHairColorId(packet.NewHairColor); - _player->SetFacialHairStyleId(bs_facialHair->Data); - if (bs_skinColor) - _player->SetSkinId(bs_skinColor->Data); - if (bs_face) - _player->SetFaceId(bs_face->Data); - - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - _player->SetCustomDisplayOption(i, customDisplay[i]); + _player->SetNativeSex(packet.NewSex); + _player->SetCustomizations(Trinity::Containers::MakeIteratorPair(packet.Customizations.begin(), packet.Customizations.end())); _player->UpdateCriteria(CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); _player->SetStandState(UNIT_STAND_STATE_STAND); + + sCharacterCache->UpdateCharacterGender(_player->GetGUID(), packet.NewSex); } void WorldSession::HandleCharCustomizeOpcode(WorldPackets::Character::CharCustomize& packet) @@ -1642,13 +1724,12 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<WorldPackets::Cha Field* fields = result->Fetch(); std::string oldName = fields[0].GetString(); - uint8 plrRace = fields[1].GetUInt8(); - uint8 plrClass = fields[2].GetUInt8(); - uint8 plrGender = fields[3].GetUInt8(); + Races plrRace = Races(fields[1].GetUInt8()); + Classes plrClass = Classes(fields[2].GetUInt8()); + Gender plrGender = Gender(fields[3].GetUInt8()); uint16 atLoginFlags = fields[4].GetUInt16(); - if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo->HairStyleID, customizeInfo->HairColorID, customizeInfo->FaceID, - customizeInfo->FacialHairStyleID, customizeInfo->SkinID, customizeInfo->CustomDisplay)) + if (!ValidateAppearance(plrRace, plrClass, plrGender, MakeChrCustomizationChoiceRange(customizeInfo->Customizations))) { SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get()); return; @@ -1708,22 +1789,7 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<WorldPackets::Cha ObjectGuid::LowType lowGuid = customizeInfo->CharGUID.GetCounter(); /// Customize - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE); - - stmt->setUInt8(0, customizeInfo->SexID); - stmt->setUInt8(1, customizeInfo->SkinID); - stmt->setUInt8(2, customizeInfo->FaceID); - stmt->setUInt8(3, customizeInfo->HairStyleID); - stmt->setUInt8(4, customizeInfo->HairColorID); - stmt->setUInt8(5, customizeInfo->FacialHairStyleID); - stmt->setUInt8(6, customizeInfo->CustomDisplay[0]); - stmt->setUInt8(7, customizeInfo->CustomDisplay[1]); - stmt->setUInt8(8, customizeInfo->CustomDisplay[2]); - stmt->setUInt64(9, lowGuid); - - trans->Append(stmt); - } + Player::SaveCustomizations(trans, lowGuid, MakeChrCustomizationChoiceRange(customizeInfo->Customizations)); /// Name Change and update atLogin flags { @@ -1823,7 +1889,7 @@ void WorldSession::HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipm if (!illusion->ItemVisual || !(illusion->Flags & ENCHANTMENT_COLLECTABLE)) return false; - if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(illusion->TransmogPlayerConditionID)) + if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(illusion->TransmogUseConditionID)) if (!sConditionMgr->IsPlayerMeetingCondition(_player, condition)) return false; @@ -2055,21 +2121,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPa } // Customize - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE); - stmt->setUInt8(0, factionChangeInfo->SexID); - stmt->setUInt8(1, factionChangeInfo->SkinID); - stmt->setUInt8(2, factionChangeInfo->FaceID); - stmt->setUInt8(3, factionChangeInfo->HairStyleID); - stmt->setUInt8(4, factionChangeInfo->HairColorID); - stmt->setUInt8(5, factionChangeInfo->FacialHairStyleID); - stmt->setUInt8(6, factionChangeInfo->CustomDisplay[0]); - stmt->setUInt8(7, factionChangeInfo->CustomDisplay[1]); - stmt->setUInt8(8, factionChangeInfo->CustomDisplay[2]); - stmt->setUInt64(9, lowGuid); - - trans->Append(stmt); - } + Player::SaveCustomizations(trans, lowGuid, MakeChrCustomizationChoiceRange(factionChangeInfo->Customizations)); // Race Change { diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index d2822839f8a..dd9646d8dd2 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -459,6 +459,7 @@ void WorldSession::HandleSellItemOpcode(WorldPackets::Item::SellItem& packet) } _player->UpdateCriteria(CRITERIA_TYPE_MONEY_FROM_VENDORS, money); + _player->UpdateCriteria(CRITERIA_TYPE_SOLD_ITEM_TO_VENDOR, 1); if (packet.Amount < pItem->GetCount()) // need split items { diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index b2982d5c36d..f84ebc3d67e 100644 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -145,7 +145,8 @@ void WorldSession::SendLfgPlayerLockInfo() // Get Random dungeons that can be done at a certain level and expansion uint8 level = GetPlayer()->getLevel(); - lfg::LfgDungeonSet const& randomDungeons = sLFGMgr->GetRandomAndSeasonalDungeons(level, GetExpansion()); + uint32 contentTuningReplacementConditionMask = GetPlayer()->m_playerData->CtrOptions->ContentTuningConditionMask; + lfg::LfgDungeonSet const& randomDungeons = sLFGMgr->GetRandomAndSeasonalDungeons(level, GetExpansion(), contentTuningReplacementConditionMask); WorldPackets::LFG::LfgPlayerInfo lfgPlayerInfo; diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index b888816666a..c26aa694795 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -290,7 +290,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest { for (QuestPackageItemEntry const* questPackageItem : *questPackageItems) { - if (questPackageItem->ItemID != packet.Choice.Item.ItemID) + if (uint32(questPackageItem->ItemID) != packet.Choice.Item.ItemID) continue; if (_player->CanSelectQuestPackageItem(questPackageItem)) @@ -307,7 +307,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest { for (QuestPackageItemEntry const* questPackageItem : *questPackageItems) { - if (questPackageItem->ItemID != packet.Choice.Item.ItemID) + if (uint32(questPackageItem->ItemID) != packet.Choice.Item.ItemID) continue; itemValid = true; diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 8ccfd1c29c3..94c3c73147e 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -539,10 +539,11 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPackets::Spells::GetMirrorI mirrorImageComponentedData.Gender = creator->getGender(); mirrorImageComponentedData.ClassID = creator->getClass(); - Guild* guild = player->GetGuild(); - for (UF::ChrCustomizationChoice customization : player->m_playerData->Customizations) - mirrorImageComponentedData.Customizations.push_back({ customization.ChrCustomizationOptionID, customization.ChrCustomizationChoiceID }); + for (UF::ChrCustomizationChoice const& customization : player->m_playerData->Customizations) + mirrorImageComponentedData.Customizations.push_back(customization); + + Guild* guild = player->GetGuild(); mirrorImageComponentedData.GuildGUID = (guild ? guild->GetGUID() : ObjectGuid::Empty); mirrorImageComponentedData.ItemDisplayID.reserve(11); diff --git a/src/server/game/Handlers/TransmogrificationHandler.cpp b/src/server/game/Handlers/TransmogrificationHandler.cpp index 37e3d3228de..b7faf646a82 100644 --- a/src/server/game/Handlers/TransmogrificationHandler.cpp +++ b/src/server/game/Handlers/TransmogrificationHandler.cpp @@ -141,11 +141,11 @@ void WorldSession::HandleTransmogrifyItems(WorldPackets::Transmogrification::Tra return; } - if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(illusion->TransmogPlayerConditionID)) + if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(illusion->TransmogUseConditionID)) { if (!sConditionMgr->IsPlayerMeetingCondition(player, condition)) { - TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - %s, Name: %s tried to transmogrify illusion using not collected enchant (%d).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.SpellItemEnchantmentID); + TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - %s, Name: %s tried to transmogrify illusion using not allowed enchant (%d).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.SpellItemEnchantmentID); return; } } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index b96fb726d50..bd844ac6329 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -18,6 +18,7 @@ #include "Map.h" #include "Battleground.h" #include "CellImpl.h" +#include "CharacterPackets.h" #include "Conversation.h" #include "DatabaseEnv.h" #include "DisableMgr.h" @@ -4777,16 +4778,26 @@ time_t Map::GetLinkedRespawnTime(ObjectGuid guid) const void Map::LoadCorpseData() { + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES); + stmt->setUInt32(0, GetId()); + stmt->setUInt32(1, GetInstanceId()); + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ? + PreparedQueryResult result = CharacterDatabase.Query(stmt); + if (!result) + return; + std::unordered_map<ObjectGuid::LowType, std::unordered_set<uint32>> phases; + std::unordered_map<ObjectGuid::LowType, std::vector<UF::ChrCustomizationChoice>> customizations; - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_PHASES); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_PHASES); stmt->setUInt32(0, GetId()); stmt->setUInt32(1, GetInstanceId()); // 0 1 // SELECT OwnerGuid, PhaseId FROM corpse_phases cp LEFT JOIN corpse c ON cp.OwnerGuid = c.guid WHERE c.mapId = ? AND c.instanceId = ? - PreparedQueryResult phaseResult = CharacterDatabase.Query(stmt); - if (phaseResult) + if (PreparedQueryResult phaseResult = CharacterDatabase.Query(stmt)) { do { @@ -4799,15 +4810,23 @@ void Map::LoadCorpseData() } while (phaseResult->NextRow()); } - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES); - stmt->setUInt32(0, GetId()); - stmt->setUInt32(1, GetInstanceId()); + // 0 1 2 + // SELECT cc.ownerGuid, cc.chrCustomizationOptionID, cc.chrCustomizationChoiceID FROM corpse_customizations cc LEFT JOIN corpse c ON cc.ownerGuid = c.guid WHERE c.mapId = ? AND c.instanceId = ? + if (PreparedQueryResult customizationResult = CharacterDatabase.Query(stmt)) + { + do + { + Field* fields = customizationResult->Fetch(); + ObjectGuid::LowType guid = fields[0].GetUInt64(); + std::vector<UF::ChrCustomizationChoice>& customizationsForCorpse = customizations[guid]; - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ? - PreparedQueryResult result = CharacterDatabase.Query(stmt); - if (!result) - return; + customizationsForCorpse.emplace_back(); + UF::ChrCustomizationChoice& choice = customizationsForCorpse.back(); + choice.ChrCustomizationOptionID = fields[1].GetUInt32(); + choice.ChrCustomizationChoiceID = fields[2].GetUInt32(); + + } while (customizationResult->NextRow()); + } do { @@ -4830,6 +4849,8 @@ void Map::LoadCorpseData() for (uint32 phaseId : phases[guid]) PhasingHandler::AddPhase(corpse, phaseId, false); + corpse->SetCustomizations(Trinity::Containers::MakeIteratorPair(customizations[guid].begin(), customizations[guid].end())); + AddCorpse(corpse); } while (result->NextRow()); @@ -4907,19 +4928,12 @@ Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= bones->SetDisplayId(corpse->m_corpseData->DisplayID); bones->SetRace(corpse->m_corpseData->RaceID); bones->SetSex(corpse->m_corpseData->Sex); - bones->SetSkin(corpse->m_corpseData->SkinID); - bones->SetFace(corpse->m_corpseData->FaceID); - bones->SetHairStyle(corpse->m_corpseData->HairStyleID); - bones->SetHairColor(corpse->m_corpseData->HairColorID); - bones->SetFacialHairStyle(corpse->m_corpseData->FacialHairStyleID); + bones->SetCustomizations(Trinity::Containers::MakeIteratorPair(corpse->m_corpseData->Customizations.begin(), corpse->m_corpseData->Customizations.end())); bones->SetFlags(corpse->m_corpseData->Flags | CORPSE_FLAG_BONES); bones->SetFactionTemplate(corpse->m_corpseData->FactionTemplate); for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) bones->SetItem(i, corpse->m_corpseData->Items[i]); - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - bones->SetCustomDisplayOption(i, corpse->m_corpseData->CustomDisplayOption[i]); - bones->SetCellCoord(corpse->GetCellCoord()); bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 9c87ab14765..8fbbe27d99b 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -72,7 +72,7 @@ enum LootModes LOOT_MODE_JUNK_FISH = 0x8000 }; -#define MAX_CHARACTERS_PER_REALM 16 +#define MAX_CHARACTERS_PER_REALM 200 enum Expansions { @@ -85,34 +85,36 @@ enum Expansions EXPANSION_WARLORDS_OF_DRAENOR = 5, EXPANSION_LEGION = 6, EXPANSION_BATTLE_FOR_AZEROTH = 7, - MAX_EXPANSIONS, EXPANSION_SHADOWLANDS = 8, + MAX_EXPANSIONS, MAX_ACCOUNT_EXPANSIONS }; -#define CURRENT_EXPANSION EXPANSION_BATTLE_FOR_AZEROTH +#define CURRENT_EXPANSION EXPANSION_SHADOWLANDS -inline uint32 GetMaxLevelForExpansion(uint32 expansion) +constexpr uint32 GetMaxLevelForExpansion(uint32 expansion) { switch (expansion) { case EXPANSION_CLASSIC: - return 60; + return 30; case EXPANSION_THE_BURNING_CRUSADE: - return 70; + return 30; case EXPANSION_WRATH_OF_THE_LICH_KING: - return 80; + return 30; case EXPANSION_CATACLYSM: - return 85; + return 35; case EXPANSION_MISTS_OF_PANDARIA: - return 90; + return 35; case EXPANSION_WARLORDS_OF_DRAENOR: - return 100; + return 40; case EXPANSION_LEGION: - return 110; + return 45; case EXPANSION_BATTLE_FOR_AZEROTH: - return 120; + return 50; + case EXPANSION_SHADOWLANDS: + return 60; default: break; } @@ -864,9 +866,14 @@ enum SpellAttr13 SPELL_ATTR13_UNK23 = 0x00800000 // 23 }; +enum SpellAttr14 +{ +}; + #define MIN_SPECIALIZATION_LEVEL 10 -#define MAX_SPECIALIZATIONS 4 +#define MAX_SPECIALIZATIONS 5 #define PET_SPEC_OVERRIDE_CLASS_INDEX MAX_CLASSES +#define INITIAL_SPECIALIZATION_INDEX 4 // Custom values enum SpellClickUserTypes @@ -1313,6 +1320,18 @@ enum SpellEffectName SPELL_EFFECT_UPGRADE_ITEM = 269, SPELL_EFFECT_270 = 270, SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM = 271, + SPELL_EFFECT_SET_COVENANT = 272, + SPELL_EFFECT_CRAFT_RUNEFORGE_LEGENDARY = 273, + SPELL_EFFECT_274 = 274, + SPELL_EFFECT_275 = 275, + SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION = 276, + SPELL_EFFECT_SET_CHROMIE_TIME = 277, + SPELL_EFFECT_278 = 278, + SPELL_EFFECT_LEARN_GARR_TALENT = 279, + SPELL_EFFECT_280 = 280, + SPELL_EFFECT_LEARN_SOULBIND_CONDUIT = 281, + SPELL_EFFECT_CONVERT_ITEMS_TO_CURRENCY = 282, + SPELL_EFFECT_283 = 283, TOTAL_SPELL_EFFECTS }; @@ -2380,6 +2399,7 @@ enum Targets TARGET_UNK_148 = 148, TARGET_UNK_149 = 149, TARGET_UNIT_OWN_CRITTER = 150, // own battle pet from UNIT_FIELD_CRITTER + TARGET_UNK_151 = 151, TOTAL_SPELL_TARGETS }; diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 55285fe0394..a1d8520c8dd 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -26,6 +26,7 @@ #include "QuestPackets.h" #include "SpellMgr.h" #include "World.h" +#include "WorldSession.h" Quest::Quest(Field* questRecord) { @@ -280,17 +281,16 @@ uint32 Quest::XPValue(Player const* player) const if (!questXp || _rewardXPDifficulty >= 10) return 0; - float multiplier = 1.0f; - if (questLevel != player->getLevel()) - multiplier = sXpGameTable.GetRow(std::min<int32>(player->getLevel(), questLevel))->Divisor / sXpGameTable.GetRow(player->getLevel())->Divisor; - - int32 diffFactor = 2 * (questLevel + (GetQuestLevel() == -1 ? 0 : 5) - player->getLevel()) + 10; + int32 diffFactor = 2 * (questLevel - player->getLevel()) + 12; if (diffFactor < 1) diffFactor = 1; else if (diffFactor > 10) diffFactor = 10; - uint32 xp = diffFactor * questXp->Difficulty[_rewardXPDifficulty] * _rewardXPMultiplier / 10 * multiplier; + uint32 xp = diffFactor * questXp->Difficulty[_rewardXPDifficulty] * _rewardXPMultiplier / 10; + if (player->getLevel() >= GetMaxLevelForExpansion(CURRENT_EXPANSION - 1) && player->GetSession()->GetExpansion() == CURRENT_EXPANSION && _expansion < CURRENT_EXPANSION) + xp = uint32(xp / 9.0f); + if (xp <= 100) xp = 5 * ((xp + 2) / 5); else if (xp <= 500) diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 3312aa5f89b..1a2e5fe6c50 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -404,12 +404,6 @@ class TC_GAME_API Quest bool HasSpecialFlag(uint32 flag) const { return (_specialFlags & flag) != 0; } void SetSpecialFlag(uint32 flag) { _specialFlags |= flag; } - // DEPRECATED - int32 GetMinLevel() const { return 0; } - int32 GetQuestLevel() const { return 0; } - int32 GetQuestScalingFactionGroup() const { return 0; } - int32 GetQuestMaxScalingLevel() const { return 0; } - // table data accessors: uint32 GetQuestId() const { return _id; } uint32 GetQuestType() const { return _type; } diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp index 86ebe42cb7f..4353e10d403 100644 --- a/src/server/game/Server/Packets/CharacterPackets.cpp +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -22,9 +22,7 @@ #include "Player.h" #include "World.h" -namespace WorldPackets -{ -namespace Character +namespace UF { ByteBuffer& operator<<(ByteBuffer& data, ChrCustomizationChoice const& customizationChoice) { @@ -41,6 +39,25 @@ ByteBuffer& operator>>(ByteBuffer& data, ChrCustomizationChoice& customizationCh return data; } +} + +namespace WorldPackets +{ +namespace Character +{ +void SortCustomizations(Array<ChrCustomizationChoice, 50>& customizations) +{ + auto first = customizations.begin(); + auto last = customizations.end(); + for (auto itr = first; itr != last; ++itr) + { + auto insertion = std::upper_bound(first, itr, *itr, [](ChrCustomizationChoice const& left, ChrCustomizationChoice const& right) + { + return left.ChrCustomizationOptionID < right.ChrCustomizationOptionID; + }); + std::rotate(insertion, itr, std::next(itr)); + } +} EnumCharacters::EnumCharacters(WorldPacket&& packet) : ClientPacket(std::move(packet)) { @@ -49,15 +66,13 @@ EnumCharacters::EnumCharacters(WorldPacket&& packet) : ClientPacket(std::move(pa EnumCharactersResult::CharacterInfo::CharacterInfo(Field* fields) { - // 0 1 2 3 4 5 6 7 - // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.skin, characters.face, characters.hairStyle, " - // 8 9 10 11 12 13 - // "characters.hairColor, characters.facialStyle, characters.customDisplay1, characters.customDisplay2, characters.customDisplay3, characters.level, " - // 14 15 16 17 18 + // 0 1 2 3 4 5 + // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.level, " + // 6 7 8 9 10 // "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, " - // 19 20 21 22 23 24 25 + // 11 12 13 14 15 16 17 // "guild_member.guildid, characters.playerFlags, characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, " - // 26 27 28 29 30 31 + // 18 19 20 21 22 23 // "character_banned.guid, characters.slot, characters.logout_time, characters.activeTalentGroup, characters.lastLoginBuild, character_declinedname.genitive" Guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); @@ -65,24 +80,16 @@ EnumCharactersResult::CharacterInfo::CharacterInfo(Field* fields) RaceID = fields[2].GetUInt8(); ClassID = fields[3].GetUInt8(); SexID = fields[4].GetUInt8(); - SkinID = fields[5].GetUInt8(); - FaceID = fields[6].GetUInt8(); - HairStyle = fields[7].GetUInt8(); - HairColor = fields[8].GetUInt8(); - FacialHair = fields[9].GetUInt8(); - CustomDisplay[0] = fields[10].GetUInt8(); - CustomDisplay[1] = fields[11].GetUInt8(); - CustomDisplay[2] = fields[12].GetUInt8(); - ExperienceLevel = fields[13].GetUInt8(); - ZoneID = int32(fields[14].GetUInt16()); - MapID = int32(fields[15].GetUInt16()); - PreloadPos = Position(fields[16].GetFloat(), fields[17].GetFloat(), fields[18].GetFloat()); - - if (ObjectGuid::LowType guildId = fields[19].GetUInt64()) + ExperienceLevel = fields[5].GetUInt8(); + ZoneID = int32(fields[6].GetUInt16()); + MapID = int32(fields[7].GetUInt16()); + PreloadPos = Position(fields[8].GetFloat(), fields[8].GetFloat(), fields[10].GetFloat()); + + if (ObjectGuid::LowType guildId = fields[11].GetUInt64()) GuildGUID = ObjectGuid::Create<HighGuid::Guild>(guildId); - uint32 playerFlags = fields[20].GetUInt32(); - uint32 atLoginFlags = fields[21].GetUInt16(); + uint32 playerFlags = fields[12].GetUInt32(); + uint32 atLoginFlags = fields[13].GetUInt16(); if (atLoginFlags & AT_LOGIN_RESURRECT) playerFlags &= ~PLAYER_FLAGS_GHOST; @@ -93,10 +100,10 @@ EnumCharactersResult::CharacterInfo::CharacterInfo(Field* fields) if (atLoginFlags & AT_LOGIN_RENAME) Flags |= CHARACTER_FLAG_RENAME; - if (fields[26].GetUInt64()) + if (fields[18].GetUInt64()) Flags |= CHARACTER_FLAG_LOCKED_BY_BILLING; - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[31].GetString().empty()) + if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[23].GetString().empty()) Flags |= CHARACTER_FLAG_DECLINED; if (atLoginFlags & AT_LOGIN_CUSTOMIZE) @@ -113,10 +120,10 @@ EnumCharactersResult::CharacterInfo::CharacterInfo(Field* fields) // show pet at selection character in character list only for non-ghost character if (!(playerFlags & PLAYER_FLAGS_GHOST) && (ClassID == CLASS_WARLOCK || ClassID == CLASS_HUNTER || ClassID == CLASS_DEATH_KNIGHT)) { - if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(fields[22].GetUInt32())) + if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(fields[14].GetUInt32())) { - PetCreatureDisplayID = fields[23].GetUInt32(); - PetExperienceLevel = fields[24].GetUInt16(); + PetCreatureDisplayID = fields[15].GetUInt32(); + PetExperienceLevel = fields[16].GetUInt16(); PetCreatureFamilyID = creatureInfo->family; } } @@ -125,13 +132,13 @@ EnumCharactersResult::CharacterInfo::CharacterInfo(Field* fields) ProfessionIds[0] = 0; ProfessionIds[1] = 0; - Tokenizer equipment(fields[25].GetString(), ' '); - ListPosition = fields[27].GetUInt8(); - LastPlayedTime = fields[28].GetUInt32(); - if (ChrSpecializationEntry const* spec = sDB2Manager.GetChrSpecializationByIndex(ClassID, fields[29].GetUInt8())) + Tokenizer equipment(fields[17].GetString(), ' '); + ListPosition = fields[19].GetUInt8(); + LastPlayedTime = fields[20].GetUInt32(); + if (ChrSpecializationEntry const* spec = sDB2Manager.GetChrSpecializationByIndex(ClassID, fields[21].GetUInt8())) SpecID = spec->ID; - LastLoginVersion = fields[30].GetUInt32(); + LastLoginVersion = fields[22].GetUInt32(); for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot) { @@ -292,6 +299,8 @@ void CreateCharacter::Read() for (ChrCustomizationChoice& customization : CreateInfo->Customizations) _worldPacket >> customization; + + SortCustomizations(CreateInfo->Customizations); } WorldPacket const* CreateChar::Write() @@ -343,6 +352,8 @@ void CharCustomize::Read() for (ChrCustomizationChoice& customization : CustomizeInfo->Customizations) _worldPacket >> customization; + SortCustomizations(CustomizeInfo->Customizations); + CustomizeInfo->CharName = _worldPacket.ReadString(_worldPacket.ReadBits(6)); } @@ -361,6 +372,8 @@ void CharRaceOrFactionChange::Read() RaceOrFactionChangeInfo->Name = _worldPacket.ReadString(nameLength); for (ChrCustomizationChoice& customization : RaceOrFactionChangeInfo->Customizations) _worldPacket >> customization; + + SortCustomizations(RaceOrFactionChangeInfo->Customizations); } WorldPacket const* CharFactionChangeResult::Write() @@ -516,6 +529,8 @@ void AlterApperance::Read() _worldPacket >> NewSex; for (ChrCustomizationChoice& customization : Customizations) _worldPacket >> customization; + + SortCustomizations(Customizations); } WorldPacket const* BarberShopResult::Write() diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h index d34e5d7e301..2cfc28b3e09 100644 --- a/src/server/game/Server/Packets/CharacterPackets.h +++ b/src/server/game/Server/Packets/CharacterPackets.h @@ -26,23 +26,25 @@ #include "RaceMask.h" #include "SharedDefines.h" #include "UnitDefines.h" +#include "UpdateFields.h" #include <array> #include <memory> class Field; +namespace UF +{ + struct ChrCustomizationChoice; + + ByteBuffer& operator<<(ByteBuffer& data, ChrCustomizationChoice const& customizationChoice); + ByteBuffer& operator>>(ByteBuffer& data, ChrCustomizationChoice& customizationChoice); +} + namespace WorldPackets { namespace Character { - struct ChrCustomizationChoice - { - uint32 ChrCustomizationOptionID = 0; - uint32 ChrCustomizationChoiceID = 0; - }; - - ByteBuffer& operator<<(ByteBuffer& data, ChrCustomizationChoice const& customizationChoice); - ByteBuffer& operator>>(ByteBuffer& data, ChrCustomizationChoice& customizationChoice); + using ChrCustomizationChoice = UF::ChrCustomizationChoice; class EnumCharacters final : public ClientPacket { diff --git a/src/server/game/Server/Packets/InspectPackets.cpp b/src/server/game/Server/Packets/InspectPackets.cpp index 0abe35115fe..7143abbf655 100644 --- a/src/server/game/Server/Packets/InspectPackets.cpp +++ b/src/server/game/Server/Packets/InspectPackets.cpp @@ -77,12 +77,12 @@ void WorldPackets::Inspect::PlayerModelDisplayInfo::Initialize(Player const* pla GUID = player->GetGUID(); SpecializationID = player->GetPrimarySpecialization(); Name = player->GetName(); - GenderID = player->m_playerData->NativeSex; + GenderID = player->GetNativeSex(); Race = player->getRace(); ClassID = player->getClass(); - for (UF::ChrCustomizationChoice customization : player->m_playerData->Customizations) - Customizations.push_back({ customization.ChrCustomizationOptionID, customization.ChrCustomizationChoiceID }); + for (UF::ChrCustomizationChoice const& customization : player->m_playerData->Customizations) + Customizations.push_back(customization); for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) if (::Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp index e6cdb28ee60..d1a113b9ed6 100644 --- a/src/server/game/Server/Packets/QueryPackets.cpp +++ b/src/server/game/Server/Packets/QueryPackets.cpp @@ -133,7 +133,7 @@ bool WorldPackets::Query::PlayerGuidLookupData::Initialize(ObjectGuid const& gui BnetAccountID = player->GetSession()->GetBattlenetAccountGUID(); Name = player->GetName(); Race = player->getRace(); - Sex = player->m_playerData->NativeSex; + Sex = player->GetNativeSex(); ClassID = player->getClass(); Level = player->getLevel(); diff --git a/src/server/game/Server/Packets/ScenarioPackets.h b/src/server/game/Server/Packets/ScenarioPackets.h index 1322b2922e3..7e58d9bb502 100644 --- a/src/server/game/Server/Packets/ScenarioPackets.h +++ b/src/server/game/Server/Packets/ScenarioPackets.h @@ -22,7 +22,7 @@ #include "PacketUtilities.h" #include "AchievementPackets.h" -#define MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE 50 +#define MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE 66 struct ScenarioPOI; diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 74119b46016..a9bb542d0ca 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -899,6 +899,9 @@ void WorldSession::ProcessQueryCallbacks() //! HandlePlayerLoginOpcode if (_charLoginCallback.valid() && _charLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready) HandlePlayerLogin(reinterpret_cast<LoginQueryHolder*>(_charLoginCallback.get())); + + if (_charEnumCallback.valid() && _charEnumCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready) + HandleCharEnum(static_cast<CharacterDatabaseQueryHolder*>(_charEnumCallback.get())); } TransactionCallback& WorldSession::AddTransactionCallback(TransactionCallback&& callback) diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 5f990c35e52..423d83d582e 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -27,9 +27,11 @@ #include "AuthDefines.h" #include "DatabaseEnvFwd.h" #include "Duration.h" +#include "IteratorPair.h" #include "LockedQueue.h" #include "ObjectGuid.h" #include "Packet.h" +#include "RaceMask.h" #include "SharedDefines.h" #include <array> #include <unordered_map> @@ -49,6 +51,7 @@ class WorldSession; class WorldSocket; struct AuctionPosting; struct BlackMarketTemplate; +struct ChrCustomizationReqEntry; struct DeclinedName; struct ItemTemplate; struct MovementInfo; @@ -76,6 +79,11 @@ namespace rbac class RBACData; } +namespace UF +{ + struct ChrCustomizationChoice; +} + namespace WorldPackets { namespace Achievement @@ -1117,9 +1125,8 @@ class TC_GAME_API WorldSession void Handle_EarlyProccess(WorldPackets::Null& null); // just mark packets processed in WorldSocket::OnRead void LogUnprocessedTail(WorldPacket const* packet); - void HandleCharEnum(PreparedQueryResult result); + void HandleCharEnum(CharacterDatabaseQueryHolder* holder); void HandleCharEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/); - void HandleCharUndeleteEnum(PreparedQueryResult result); void HandleCharUndeleteEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/); void HandleCharDeleteOpcode(WorldPackets::Character::CharDelete& charDelete); void HandleCharCreateOpcode(WorldPackets::Character::CreateCharacter& charCreate); @@ -1145,6 +1152,10 @@ class TC_GAME_API WorldSession void HandleGetUndeleteCooldownStatus(WorldPackets::Character::GetUndeleteCharacterCooldownStatus& /*getCooldown*/); void HandleUndeleteCooldownStatusCallback(PreparedQueryResult result); void HandleCharUndeleteOpcode(WorldPackets::Character::UndeleteCharacter& undeleteInfo); + bool MeetsChrCustomizationReq(ChrCustomizationReqEntry const* req, Classes playerClass, + bool checkRequiredDependentChoices, Trinity::IteratorPair<UF::ChrCustomizationChoice const*> selectedChoices) const; + bool ValidateAppearance(Races race, Classes playerClass, Gender gender, + Trinity::IteratorPair<UF::ChrCustomizationChoice const*> customizations); // customizations must be sorted void SendCharCreate(ResponseCodes result, ObjectGuid const& guid = ObjectGuid::Empty); void SendCharDelete(ResponseCodes result); @@ -1768,6 +1779,7 @@ class TC_GAME_API WorldSession QueryResultHolderFuture _realmAccountLoginCallback; QueryResultHolderFuture _accountLoginCallback; QueryResultHolderFuture _charLoginCallback; + QueryResultHolderFuture _charEnumCallback; QueryCallbackProcessor _queryProcessor; AsyncCallbackProcessor<TransactionCallback> _transactionCallbacks; diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 51762d02c43..7c471793585 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -558,11 +558,21 @@ enum AuraType : uint32 SPELL_AURA_486 = 486, SPELL_AURA_487 = 487, SPELL_AURA_488 = 488, - SPELL_AURA_489 = 489, + SPELL_AURA_MOD_ALTERNATIVE_DEFAULT_LANGUAGE = 489, SPELL_AURA_490 = 490, SPELL_AURA_491 = 491, SPELL_AURA_492 = 492, SPELL_AURA_493 = 493, // 1 spell, 267116 - Animal Companion (modifies Call Pet) + SPELL_AURA_SET_POWER_POINT_CHARGE = 494, // NYI + SPELL_AURA_TRIGGER_SPELL_ON_EXPIRE = 495, // NYI + SPELL_AURA_ALLOW_CHANGING_EQUIPMENT_IN_TORGHAST = 496, // NYI + SPELL_AURA_MOD_ANIMA_GAIN = 497, // NYI + SPELL_AURA_CURRENCY_LOSS_PCT_ON_DEATH = 498, // NYI + SPELL_AURA_MOD_RESTED_XP_CONSUMPTION = 499, + SPELL_AURA_IGNORE_SPELL_CHARGE_COOLDOWN = 500, // NYI + SPELL_AURA_MOD_CRITICAL_DAMAGE_TAKEN_FROM_CASTER = 501, + SPELL_AURA_MOD_VERSATILITY_DAMAGE_DONE_BENEFIT = 502, // NYI + SPELL_AURA_MOD_VERSATILITY_HEALING_DONE_BENEFIT = 503, // NYI TOTAL_AURAS }; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index f41173573e6..b01003763d2 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -555,11 +555,21 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //486 &AuraEffect::HandleNULL, //487 &AuraEffect::HandleNULL, //488 - &AuraEffect::HandleNULL, //489 + &AuraEffect::HandleNULL, //489 SPELL_AURA_MOD_ALTERNATIVE_DEFAULT_LANGUAGE &AuraEffect::HandleNULL, //490 &AuraEffect::HandleNULL, //491 &AuraEffect::HandleNULL, //492 &AuraEffect::HandleNULL, //493 + &AuraEffect::HandleNULL, //494 SPELL_AURA_SET_POWER_POINT_CHARGE + &AuraEffect::HandleNULL, //495 SPELL_AURA_TRIGGER_SPELL_ON_EXPIRE + &AuraEffect::HandleNULL, //496 SPELL_AURA_ALLOW_CHANGING_EQUIPMENT_IN_TORGHAST + &AuraEffect::HandleNULL, //497 SPELL_AURA_MOD_ANIMA_GAIN + &AuraEffect::HandleNULL, //498 SPELL_AURA_CURRENCY_LOSS_PCT_ON_DEATH + &AuraEffect::HandleNULL, //499 SPELL_AURA_MOD_RESTED_XP_CONSUMPTION + &AuraEffect::HandleNULL, //500 SPELL_AURA_IGNORE_SPELL_CHARGE_COOLDOWN + &AuraEffect::HandleNULL, //501 SPELL_AURA_MOD_CRITICAL_DAMAGE_TAKEN_FROM_CASTER + &AuraEffect::HandleNULL, //502 SPELL_AURA_MOD_VERSATILITY_DAMAGE_DONE_BENEFIT + &AuraEffect::HandleNULL, //503 SPELL_AURA_MOD_VERSATILITY_HEALING_DONE_BENEFIT }; AuraEffect::AuraEffect(Aura* base, uint32 effIndex, int32 *baseAmount, Unit* caster) : diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 8cf98594710..d6217551d25 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3003,13 +3003,13 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered if (!player->GetCommandStatus(CHEAT_CASTTIME)) { // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail) - m_casttime = m_spellInfo->CalcCastTime(player->getLevel(), this); + m_casttime = m_spellInfo->CalcCastTime(this); } else m_casttime = 0; // Set cast time to 0 if .cheat casttime is enabled. } else - m_casttime = m_spellInfo->CalcCastTime(m_caster->getLevel(), this); + m_casttime = m_spellInfo->CalcCastTime(this); // don't allow channeled spells / spells with cast time to be cast while moving // exception are only channeled spells that have no casttime and SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING @@ -4495,7 +4495,7 @@ void Spell::SendChannelUpdate(uint32 time) { m_caster->ClearChannelObjects(); m_caster->SetChannelSpellId(0); - m_caster->SetChannelSpellXSpellVisualId({}); + m_caster->SetChannelVisual({}); } WorldPackets::Spells::SpellChannelUpdate spellChannelUpdate; @@ -4539,7 +4539,7 @@ void Spell::SendChannelStart(uint32 duration) m_caster->AddChannelObject(target.targetGUID); m_caster->SetChannelSpellId(m_spellInfo->Id); - m_caster->SetChannelSpellXSpellVisualId(m_SpellVisual); + m_caster->SetChannelVisual(m_SpellVisual); } void Spell::SendResurrectRequest(Player* target) @@ -8049,6 +8049,14 @@ bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target) } //namespace Trinity +SpellCastVisual::operator UF::SpellCastVisual() const +{ + UF::SpellCastVisual visual; + visual.SpellXSpellVisualID = SpellXSpellVisualID; + visual.ScriptVisualID = ScriptVisualID; + return visual; +} + SpellCastVisual::operator WorldPackets::Spells::SpellCastVisual() const { return { int32(SpellXSpellVisualID), int32(ScriptVisualID) }; diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index aa273c977de..11a196d2ed4 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -23,6 +23,7 @@ #include "ObjectGuid.h" #include "Position.h" #include "SharedDefines.h" +#include "SpellDefines.h" #include <memory> namespace WorldPackets diff --git a/src/server/game/Spells/SpellDefines.h b/src/server/game/Spells/SpellDefines.h index 0df1fbe0e6b..30eb419f53f 100644 --- a/src/server/game/Spells/SpellDefines.h +++ b/src/server/game/Spells/SpellDefines.h @@ -20,6 +20,11 @@ #include "Define.h" +namespace UF +{ + struct SpellCastVisual; +} + namespace WorldPackets { namespace Spells @@ -33,6 +38,7 @@ struct SpellCastVisual uint32 SpellXSpellVisualID = 0; uint32 ScriptVisualID = 0; + operator UF::SpellCastVisual() const; operator WorldPackets::Spells::SpellCastVisual() const; }; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 27343ea9689..7db4fc958d5 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -350,6 +350,18 @@ NonDefaultConstructible<pEffect> SpellEffects[TOTAL_SPELL_EFFECTS] = &Spell::EffectNULL, //269 SPELL_EFFECT_UPGRADE_ITEM &Spell::EffectNULL, //270 SPELL_EFFECT_270 &Spell::EffectApplyAreaAura, //271 SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM + &Spell::EffectNULL, //272 SPELL_EFFECT_SET_COVENANT + &Spell::EffectNULL, //273 SPELL_EFFECT_CRAFT_RUNEFORGE_LEGENDARY + &Spell::EffectNULL, //274 SPELL_EFFECT_274 + &Spell::EffectNULL, //275 SPELL_EFFECT_275 + &Spell::EffectNULL, //276 SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION + &Spell::EffectNULL, //277 SPELL_EFFECT_SET_CHROMIE_TIME + &Spell::EffectNULL, //278 SPELL_EFFECT_270 + &Spell::EffectNULL, //279 SPELL_EFFECT_LEARN_GARR_TALENT + &Spell::EffectNULL, //280 SPELL_EFFECT_270 + &Spell::EffectNULL, //281 SPELL_EFFECT_LEARN_SOULBIND_CONDUIT + &Spell::EffectNULL, //282 SPELL_EFFECT_CONVERT_ITEMS_TO_CURRENCY + &Spell::EffectNULL, //283 SPELL_EFFECT_283 }; void Spell::EffectNULL(SpellEffIndex /*effIndex*/) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 3c2ea638171..b0864d5b5d7 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -368,6 +368,7 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 148 {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 149 {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 150 TARGET_UNIT_OWN_CRITTER + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 151 }; SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry const* _effect) @@ -1062,6 +1063,18 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 269 SPELL_EFFECT_UPGRADE_ITEM {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 270 SPELL_EFFECT_270 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 271 SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 272 SPELL_EFFECT_SET_COVENANT + {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 273 SPELL_EFFECT_CRAFT_RUNEFORGE_LEGENDARY + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 274 SPELL_EFFECT_274 + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 275 SPELL_EFFECT_275 + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 276 SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 277 SPELL_EFFECT_SET_CHROMIE_TIME + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 278 SPELL_EFFECT_270 + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 279 SPELL_EFFECT_LEARN_GARR_TALENT + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 280 SPELL_EFFECT_270 + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 281 SPELL_EFFECT_LEARN_SOULBIND_CONDUIT + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 282 SPELL_EFFECT_CONVERT_ITEMS_TO_CURRENCY + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 283 SPELL_EFFECT_283 }; SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, SpellInfoLoadHelper const& data, SpellVisualVector&& visuals) @@ -1100,6 +1113,7 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, S AttributesEx11 = _misc ? _misc->Attributes[11] : 0; AttributesEx12 = _misc ? _misc->Attributes[12] : 0; AttributesEx13 = _misc ? _misc->Attributes[13] : 0; + AttributesEx14 = _misc ? _misc->Attributes[14] : 0; CastTimeEntry = _misc ? (_misc->CastingTimeIndex ? sSpellCastTimesStore.LookupEntry(_misc->CastingTimeIndex) : nullptr) : nullptr; DurationEntry = _misc ? (_misc->DurationIndex ? sSpellDurationStore.LookupEntry(_misc->DurationIndex) : nullptr) : nullptr; RangeIndex = _misc ? _misc->RangeIndex : 0; @@ -3655,31 +3669,11 @@ int32 SpellInfo::GetMaxDuration() const return (DurationEntry->MaxDuration == -1) ? -1 : abs(DurationEntry->MaxDuration); } -uint32 SpellInfo::CalcCastTime(uint8 level, Spell* spell /*= nullptr*/) const +uint32 SpellInfo::CalcCastTime(Spell* spell /*= nullptr*/) const { int32 castTime = 0; if (CastTimeEntry) - { - int32 calcLevel = spell ? spell->GetCaster()->getLevel() : 0; - if (MaxLevel && uint32(calcLevel) > MaxLevel) - calcLevel = MaxLevel; - - if (HasAttribute(SPELL_ATTR13_UNK17)) - calcLevel *= 5; - - if (MaxLevel && uint32(calcLevel) > MaxLevel) - calcLevel = MaxLevel; - - if (BaseLevel) - calcLevel -= BaseLevel; - - if (calcLevel < 0) - calcLevel = 0; - - castTime = CastTimeEntry->Base + CastTimeEntry->PerLevel * level; - if (castTime < CastTimeEntry->Minimum) - castTime = CastTimeEntry->Minimum; - } + castTime = std::max(CastTimeEntry->Base, CastTimeEntry->Minimum); if (castTime <= 0) return 0; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 81fb91fe020..b208ffdbc94 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -456,6 +456,7 @@ class TC_GAME_API SpellInfo uint32 AttributesEx11; uint32 AttributesEx12; uint32 AttributesEx13; + uint32 AttributesEx14; uint32 AttributesCu; std::bitset<MAX_SPELL_EFFECTS> NegativeEffects; uint64 Stances; @@ -555,6 +556,7 @@ class TC_GAME_API SpellInfo bool HasAttribute(SpellAttr11 attribute) const { return !!(AttributesEx11 & attribute); } bool HasAttribute(SpellAttr12 attribute) const { return !!(AttributesEx12 & attribute); } bool HasAttribute(SpellAttr13 attribute) const { return !!(AttributesEx13 & attribute); } + bool HasAttribute(SpellAttr14 attribute) const { return !!(AttributesEx14 & attribute); } bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } bool HasAnyAuraInterruptFlag() const; @@ -645,7 +647,7 @@ class TC_GAME_API SpellInfo uint32 GetMaxTicks() const; - uint32 CalcCastTime(uint8 level = 0, Spell* spell = nullptr) const; + uint32 CalcCastTime(Spell* spell = nullptr) const; uint32 GetRecoveryTime() const; std::vector<SpellPowerCost> CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask, Spell* spell = nullptr) const; diff --git a/src/server/game/Storages/WhoListStorage.cpp b/src/server/game/Storages/WhoListStorage.cpp index 6b42c0bd71e..7638d9c19ac 100644 --- a/src/server/game/Storages/WhoListStorage.cpp +++ b/src/server/game/Storages/WhoListStorage.cpp @@ -62,7 +62,7 @@ void WhoListStorageMgr::Update() guildGuid = guild->GetGUID(); _whoListStorage.emplace_back(itr->second->GetGUID(), itr->second->GetTeam(), itr->second->GetSession()->GetSecurity(), itr->second->getLevel(), - itr->second->getClass(), itr->second->getRace(), itr->second->GetZoneId(), itr->second->m_playerData->NativeSex, itr->second->IsVisible(), + itr->second->getClass(), itr->second->getRace(), itr->second->GetZoneId(), itr->second->GetNativeSex(), itr->second->IsVisible(), itr->second->IsGameMaster(), widePlayerName, wideGuildName, playerName, guildName, guildGuid); } } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 21d8258278a..b182464c063 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -877,10 +877,11 @@ void World::LoadConfigSettings(bool reload) m_int64_configs[CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK] = sConfigMgr->GetInt64Default("CharacterCreating.Disabled.RaceMask", 0); m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.ClassMask", 0); - m_int_configs[CONFIG_CHARACTERS_PER_REALM] = sConfigMgr->GetIntDefault("CharactersPerRealm", MAX_CHARACTERS_PER_REALM); + m_int_configs[CONFIG_CHARACTERS_PER_REALM] = sConfigMgr->GetIntDefault("CharactersPerRealm", 50); if (m_int_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_int_configs[CONFIG_CHARACTERS_PER_REALM] > MAX_CHARACTERS_PER_REALM) { - TC_LOG_ERROR("server.loading", "CharactersPerRealm (%i) must be in range 1..10. Set to 10.", m_int_configs[CONFIG_CHARACTERS_PER_REALM]); + TC_LOG_ERROR("server.loading", "CharactersPerRealm (%i) must be in range 1..%d. Set to %d.", + m_int_configs[CONFIG_CHARACTERS_PER_REALM], MAX_CHARACTERS_PER_REALM, MAX_CHARACTERS_PER_REALM); m_int_configs[CONFIG_CHARACTERS_PER_REALM] = MAX_CHARACTERS_PER_REALM; } @@ -892,14 +893,7 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = m_int_configs[CONFIG_CHARACTERS_PER_REALM]; } - m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM] = sConfigMgr->GetIntDefault("DemonHuntersPerRealm", 1); - if (int32(m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM]) < 0 || m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM] > 16) - { - TC_LOG_ERROR("server.loading", "DemonHuntersPerRealm (%i) must be in range 0..16. Set to 1.", m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM]); - m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM] = 1; - } - - m_int_configs[CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEMON_HUNTER] = sConfigMgr->GetIntDefault("CharacterCreating.MinLevelForDemonHunter", 70); + m_int_configs[CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEMON_HUNTER] = sConfigMgr->GetIntDefault("CharacterCreating.MinLevelForDemonHunter", 0); m_int_configs[CONFIG_SKIP_CINEMATICS] = sConfigMgr->GetIntDefault("SkipCinematics", 0); if (int32(m_int_configs[CONFIG_SKIP_CINEMATICS]) < 0 || m_int_configs[CONFIG_SKIP_CINEMATICS] > 2) diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 5b5551fbacc..693ae1f39d3 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -244,7 +244,6 @@ enum WorldIntConfigs CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK, CONFIG_CHARACTERS_PER_ACCOUNT, CONFIG_CHARACTERS_PER_REALM, - CONFIG_DEMON_HUNTERS_PER_REALM, CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEMON_HUNTER, CONFIG_SKIP_CINEMATICS, CONFIG_MAX_PLAYER_LEVEL, |