Core/Items: Item bonus generation improvements
* Pass ItemContext to item creation wherever possible * Support scaling item levels with m+ keystone levels (not used currently) * Fixed item link validation when client sends it as default uninitialized bonus list with context only * Support scaling items depending on current active season (seasons not implemented) * Implemented content tuning redirection Port From (https://github.com/TrinityCore/TrinityCore/commit/0fb8765a6638fd947b59fce44d5c31251d0cdadd)
This commit is contained in:
@@ -87,6 +87,7 @@ namespace Game.DataStorage
|
||||
BroadcastTextStorage = ReadDB2<BroadcastTextRecord>("BroadcastText.db2", HotfixStatements.SEL_BROADCAST_TEXT, HotfixStatements.SEL_BROADCAST_TEXT_LOCALE);
|
||||
BroadcastTextDurationStorage = ReadDB2<BroadcastTextDurationRecord>("BroadcastTextDuration.db2", HotfixStatements.SEL_BROADCAST_TEXT_DURATION);
|
||||
CfgRegionsStorage = ReadDB2<Cfg_RegionsRecord>("Cfg_Regions.db2", HotfixStatements.SEL_CFG_REGIONS);
|
||||
ChallengeModeItemBonusOverrideStorage = ReadDB2<ChallengeModeItemBonusOverrideRecord>("ChallengeModeItemBonusOverride.db2", HotfixStatements.SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE);
|
||||
CharTitlesStorage = ReadDB2<CharTitlesRecord>("CharTitles.db2", HotfixStatements.SEL_CHAR_TITLES, HotfixStatements.SEL_CHAR_TITLES_LOCALE);
|
||||
CharacterLoadoutStorage = ReadDB2<CharacterLoadoutRecord>("CharacterLoadout.db2", HotfixStatements.SEL_CHARACTER_LOADOUT);
|
||||
CharacterLoadoutItemStorage = ReadDB2<CharacterLoadoutItemRecord>("CharacterLoadoutItem.db2", HotfixStatements.SEL_CHARACTER_LOADOUT_ITEM);
|
||||
@@ -106,8 +107,10 @@ namespace Game.DataStorage
|
||||
ChrSpecializationStorage = ReadDB2<ChrSpecializationRecord>("ChrSpecialization.db2", HotfixStatements.SEL_CHR_SPECIALIZATION, HotfixStatements.SEL_CHR_SPECIALIZATION_LOCALE);
|
||||
CinematicCameraStorage = ReadDB2<CinematicCameraRecord>("CinematicCamera.db2", HotfixStatements.SEL_CINEMATIC_CAMERA);
|
||||
CinematicSequencesStorage = ReadDB2<CinematicSequencesRecord>("CinematicSequences.db2", HotfixStatements.SEL_CINEMATIC_SEQUENCES);
|
||||
ConditionalContentTuningStorage = ReadDB2<ConditionalContentTuningRecord>("ConditionalContentTuning.db2", HotfixStatements.SEL_CONDITIONAL_CONTENT_TUNING);
|
||||
ContentTuningStorage = ReadDB2<ContentTuningRecord>("ContentTuning.db2", HotfixStatements.SEL_CONTENT_TUNING);
|
||||
ContentTuningXExpectedStorage = ReadDB2<ContentTuningXExpectedRecord>("ContentTuningXExpected.db2", HotfixStatements.SEL_CONTENT_TUNING_X_EXPECTED);
|
||||
ContentTuningXLabelStorage = ReadDB2<ContentTuningXLabelRecord>("ContentTuningXLabel.db2", HotfixStatements.SEL_CONTENT_TUNING_X_LABEL);
|
||||
ConversationLineStorage = ReadDB2<ConversationLineRecord>("ConversationLine.db2", HotfixStatements.SEL_CONVERSATION_LINE);
|
||||
CorruptionEffectsStorage = ReadDB2<CorruptionEffectsRecord>("CorruptionEffects.db2", HotfixStatements.SEL_CORRUPTION_EFFECTS);
|
||||
CreatureDisplayInfoStorage = ReadDB2<CreatureDisplayInfoRecord>("CreatureDisplayInfo.db2", HotfixStatements.SEL_CREATURE_DISPLAY_INFO);
|
||||
@@ -173,10 +176,13 @@ namespace Game.DataStorage
|
||||
ItemArmorTotalStorage = ReadDB2<ItemArmorTotalRecord>("ItemArmorTotal.db2", HotfixStatements.SEL_ITEM_ARMOR_TOTAL);
|
||||
//ItemBagFamilyStorage = ReadDB2<ItemBagFamilyRecord>("ItemBagFamily.db2", HotfixStatements.SEL_ITEM_BAG_FAMILY, HotfixStatements.SEL_ITEM_BAG_FAMILY_LOCALE);
|
||||
ItemBonusStorage = ReadDB2<ItemBonusRecord>("ItemBonus.db2", HotfixStatements.SEL_ITEM_BONUS);
|
||||
ItemBonusListGroupEntryStorage = ReadDB2<ItemBonusListGroupEntryRecord>("ItemBonusListGroupEntry.db2", HotfixStatements.SEL_ITEM_BONUS_LIST_GROUP_ENTRY);
|
||||
ItemBonusListLevelDeltaStorage = ReadDB2<ItemBonusListLevelDeltaRecord>("ItemBonusListLevelDelta.db2", HotfixStatements.SEL_ITEM_BONUS_LIST_LEVEL_DELTA);
|
||||
ItemBonusTreeStorage = ReadDB2<ItemBonusTreeRecord>("ItemBonusTree.db2", HotfixStatements.SEL_ITEM_BONUS_TREE);
|
||||
ItemBonusTreeNodeStorage = ReadDB2<ItemBonusTreeNodeRecord>("ItemBonusTreeNode.db2", HotfixStatements.SEL_ITEM_BONUS_TREE_NODE);
|
||||
ItemChildEquipmentStorage = ReadDB2<ItemChildEquipmentRecord>("ItemChildEquipment.db2", HotfixStatements.SEL_ITEM_CHILD_EQUIPMENT);
|
||||
ItemClassStorage = ReadDB2<ItemClassRecord>("ItemClass.db2", HotfixStatements.SEL_ITEM_CLASS, HotfixStatements.SEL_ITEM_CLASS_LOCALE);
|
||||
ItemContextPickerEntryStorage = ReadDB2<ItemContextPickerEntryRecord>("ItemContextPickerEntry.db2", HotfixStatements.SEL_ITEM_CONTEXT_PICKER_ENTRY);
|
||||
ItemCurrencyCostStorage = ReadDB2<ItemCurrencyCostRecord>("ItemCurrencyCost.db2", HotfixStatements.SEL_ITEM_CURRENCY_COST);
|
||||
ItemDamageAmmoStorage = ReadDB2<ItemDamageRecord>("ItemDamageAmmo.db2", HotfixStatements.SEL_ITEM_DAMAGE_AMMO);
|
||||
ItemDamageOneHandStorage = ReadDB2<ItemDamageRecord>("ItemDamageOneHand.db2", HotfixStatements.SEL_ITEM_DAMAGE_ONE_HAND);
|
||||
@@ -228,6 +234,7 @@ namespace Game.DataStorage
|
||||
MountTypeXCapabilityStorage = ReadDB2<MountTypeXCapabilityRecord>("MountTypeXCapability.db2", HotfixStatements.SEL_MOUNT_TYPE_X_CAPABILITY);
|
||||
MountXDisplayStorage = ReadDB2<MountXDisplayRecord>("MountXDisplay.db2", HotfixStatements.SEL_MOUNT_X_DISPLAY);
|
||||
MovieStorage = ReadDB2<MovieRecord>("Movie.db2", HotfixStatements.SEL_MOVIE);
|
||||
MythicPlusSeasonStorage = ReadDB2<MythicPlusSeasonRecord>("MythicPlusSeason.db2", HotfixStatements.SEL_MYTHIC_PLUS_SEASON);
|
||||
NameGenStorage = ReadDB2<NameGenRecord>("NameGen.db2", HotfixStatements.SEL_NAME_GEN);
|
||||
NamesProfanityStorage = ReadDB2<NamesProfanityRecord>("NamesProfanity.db2", HotfixStatements.SEL_NAMES_PROFANITY);
|
||||
NamesReservedStorage = ReadDB2<NamesReservedRecord>("NamesReserved.db2", HotfixStatements.SEL_NAMES_RESERVED, HotfixStatements.SEL_NAMES_RESERVED_LOCALE);
|
||||
@@ -243,6 +250,7 @@ namespace Game.DataStorage
|
||||
PrestigeLevelInfoStorage = ReadDB2<PrestigeLevelInfoRecord>("PrestigeLevelInfo.db2", HotfixStatements.SEL_PRESTIGE_LEVEL_INFO, HotfixStatements.SEL_PRESTIGE_LEVEL_INFO_LOCALE);
|
||||
PvpDifficultyStorage = ReadDB2<PvpDifficultyRecord>("PVPDifficulty.db2", HotfixStatements.SEL_PVP_DIFFICULTY);
|
||||
PvpItemStorage = ReadDB2<PvpItemRecord>("PVPItem.db2", HotfixStatements.SEL_PVP_ITEM);
|
||||
PvpSeasonStorage = ReadDB2<PvpSeasonRecord>("PvpSeason.db2", HotfixStatements.SEL_PVP_SEASON);
|
||||
PvpTalentStorage = ReadDB2<PvpTalentRecord>("PvpTalent.db2", HotfixStatements.SEL_PVP_TALENT, HotfixStatements.SEL_PVP_TALENT_LOCALE);
|
||||
PvpTalentCategoryStorage = ReadDB2<PvpTalentCategoryRecord>("PvpTalentCategory.db2", HotfixStatements.SEL_PVP_TALENT_CATEGORY);
|
||||
PvpTalentSlotUnlockStorage = ReadDB2<PvpTalentSlotUnlockRecord>("PvpTalentSlotUnlock.db2", HotfixStatements.SEL_PVP_TALENT_SLOT_UNLOCK);
|
||||
@@ -511,6 +519,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<BroadcastTextRecord> BroadcastTextStorage;
|
||||
public static DB6Storage<BroadcastTextDurationRecord> BroadcastTextDurationStorage;
|
||||
public static DB6Storage<Cfg_RegionsRecord> CfgRegionsStorage;
|
||||
public static DB6Storage<ChallengeModeItemBonusOverrideRecord> ChallengeModeItemBonusOverrideStorage;
|
||||
public static DB6Storage<CharTitlesRecord> CharTitlesStorage;
|
||||
public static DB6Storage<CharacterLoadoutRecord> CharacterLoadoutStorage;
|
||||
public static DB6Storage<CharacterLoadoutItemRecord> CharacterLoadoutItemStorage;
|
||||
@@ -530,8 +539,10 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<ChrSpecializationRecord> ChrSpecializationStorage;
|
||||
public static DB6Storage<CinematicCameraRecord> CinematicCameraStorage;
|
||||
public static DB6Storage<CinematicSequencesRecord> CinematicSequencesStorage;
|
||||
public static DB6Storage<ConditionalContentTuningRecord> ConditionalContentTuningStorage;
|
||||
public static DB6Storage<ContentTuningRecord> ContentTuningStorage;
|
||||
public static DB6Storage<ContentTuningXExpectedRecord> ContentTuningXExpectedStorage;
|
||||
public static DB6Storage<ContentTuningXLabelRecord> ContentTuningXLabelStorage;
|
||||
public static DB6Storage<ConversationLineRecord> ConversationLineStorage;
|
||||
public static DB6Storage<CorruptionEffectsRecord> CorruptionEffectsStorage;
|
||||
public static DB6Storage<CreatureDisplayInfoRecord> CreatureDisplayInfoStorage;
|
||||
@@ -597,8 +608,11 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<ItemArmorTotalRecord> ItemArmorTotalStorage;
|
||||
//public static DB6Storage<ItemBagFamilyRecord> ItemBagFamilyStorage;
|
||||
public static DB6Storage<ItemBonusRecord> ItemBonusStorage;
|
||||
public static DB6Storage<ItemBonusListGroupEntryRecord> ItemBonusListGroupEntryStorage;
|
||||
public static DB6Storage<ItemBonusListLevelDeltaRecord> ItemBonusListLevelDeltaStorage;
|
||||
public static DB6Storage<ItemBonusTreeRecord> ItemBonusTreeStorage;
|
||||
public static DB6Storage<ItemBonusTreeNodeRecord> ItemBonusTreeNodeStorage;
|
||||
public static DB6Storage<ItemContextPickerEntryRecord> ItemContextPickerEntryStorage;
|
||||
public static DB6Storage<ItemClassRecord> ItemClassStorage;
|
||||
public static DB6Storage<ItemChildEquipmentRecord> ItemChildEquipmentStorage;
|
||||
public static DB6Storage<ItemCurrencyCostRecord> ItemCurrencyCostStorage;
|
||||
@@ -652,6 +666,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<MountTypeXCapabilityRecord> MountTypeXCapabilityStorage;
|
||||
public static DB6Storage<MountXDisplayRecord> MountXDisplayStorage;
|
||||
public static DB6Storage<MovieRecord> MovieStorage;
|
||||
public static DB6Storage<MythicPlusSeasonRecord> MythicPlusSeasonStorage;
|
||||
public static DB6Storage<NameGenRecord> NameGenStorage;
|
||||
public static DB6Storage<NamesProfanityRecord> NamesProfanityStorage;
|
||||
public static DB6Storage<NamesReservedRecord> NamesReservedStorage;
|
||||
@@ -667,6 +682,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<PrestigeLevelInfoRecord> PrestigeLevelInfoStorage;
|
||||
public static DB6Storage<PvpDifficultyRecord> PvpDifficultyStorage;
|
||||
public static DB6Storage<PvpItemRecord> PvpItemStorage;
|
||||
public static DB6Storage<PvpSeasonRecord> PvpSeasonStorage;
|
||||
public static DB6Storage<PvpTalentRecord> PvpTalentStorage;
|
||||
public static DB6Storage<PvpTalentCategoryRecord> PvpTalentCategoryStorage;
|
||||
public static DB6Storage<PvpTalentSlotUnlockRecord> PvpTalentSlotUnlockStorage;
|
||||
|
||||
@@ -90,10 +90,6 @@ namespace Game.DataStorage
|
||||
_azeriteTierUnlockLevels[key][azeriteTierUnlock.Tier] = azeriteTierUnlock.AzeriteLevel;
|
||||
}
|
||||
|
||||
MultiMap<uint, AzeriteUnlockMappingRecord> azeriteUnlockMappings = new();
|
||||
foreach (AzeriteUnlockMappingRecord azeriteUnlockMapping in AzeriteUnlockMappingStorage.Values)
|
||||
azeriteUnlockMappings.Add(azeriteUnlockMapping.AzeriteUnlockMappingSetID, azeriteUnlockMapping);
|
||||
|
||||
foreach (BattlemasterListRecord battlemaster in BattlemasterListStorage.Values)
|
||||
{
|
||||
if (battlemaster.MaxLevel < battlemaster.MinLevel)
|
||||
@@ -230,12 +226,18 @@ namespace Game.DataStorage
|
||||
_chrSpecializationsByIndex[storageIndex][chrSpec.OrderIndex] = chrSpec;
|
||||
}
|
||||
|
||||
foreach (ConditionalContentTuningRecord conditionalContentTuning in ConditionalContentTuningStorage.Values)
|
||||
_conditionalContentTuning.Add(conditionalContentTuning.ParentContentTuningID, conditionalContentTuning);
|
||||
|
||||
foreach (ContentTuningXExpectedRecord contentTuningXExpectedStat in ContentTuningXExpectedStorage.Values)
|
||||
{
|
||||
if (ExpectedStatModStorage.ContainsKey(contentTuningXExpectedStat.ExpectedStatModID))
|
||||
_expectedStatModsByContentTuning.Add(contentTuningXExpectedStat.ContentTuningID, contentTuningXExpectedStat);
|
||||
}
|
||||
|
||||
foreach (ContentTuningXLabelRecord contentTuningXLabel in ContentTuningXLabelStorage.Values)
|
||||
_contentTuningLabels.Add((contentTuningXLabel.ContentTuningID, contentTuningXLabel.LabelID));
|
||||
|
||||
foreach (CurrencyContainerRecord currencyContainer in CurrencyContainerStorage.Values)
|
||||
_currencyContainers.Add(currencyContainer.CurrencyTypesID, currencyContainer);
|
||||
|
||||
@@ -283,15 +285,6 @@ namespace Game.DataStorage
|
||||
foreach (GlyphRequiredSpecRecord glyphRequiredSpec in GlyphRequiredSpecStorage.Values)
|
||||
_glyphRequiredSpecs.Add(glyphRequiredSpec.GlyphPropertiesID, glyphRequiredSpec.ChrSpecializationID);
|
||||
|
||||
foreach (var bonus in ItemBonusStorage.Values)
|
||||
_itemBonusLists.Add(bonus.ParentItemBonusListID, bonus);
|
||||
|
||||
foreach (ItemBonusListLevelDeltaRecord itemBonusListLevelDelta in ItemBonusListLevelDeltaStorage.Values)
|
||||
_itemLevelDeltaToBonusListContainer[itemBonusListLevelDelta.ItemLevelDelta] = itemBonusListLevelDelta.Id;
|
||||
|
||||
foreach (var bonusTreeNode in ItemBonusTreeNodeStorage.Values)
|
||||
_itemBonusTrees.Add(bonusTreeNode.ParentItemBonusTreeID, bonusTreeNode);
|
||||
|
||||
foreach (ItemChildEquipmentRecord itemChildEquipment in ItemChildEquipmentStorage.Values)
|
||||
{
|
||||
//ASSERT(_itemChildEquipment.find(itemChildEquipment.ParentItemID) == _itemChildEquipment.end(), "Item must have max 1 child item.");
|
||||
@@ -311,9 +304,6 @@ namespace Game.DataStorage
|
||||
foreach (ItemLimitCategoryConditionRecord condition in ItemLimitCategoryConditionStorage.Values)
|
||||
_itemCategoryConditions.Add(condition.ParentItemLimitCategoryID, condition);
|
||||
|
||||
foreach (ItemLevelSelectorQualityRecord itemLevelSelectorQuality in ItemLevelSelectorQualityStorage.Values)
|
||||
_itemLevelQualitySelectorQualities.Add(itemLevelSelectorQuality.ParentILSQualitySetID, itemLevelSelectorQuality);
|
||||
|
||||
foreach (var appearanceMod in ItemModifiedAppearanceStorage.Values)
|
||||
{
|
||||
//ASSERT(appearanceMod.ItemID <= 0xFFFFFF);
|
||||
@@ -326,12 +316,6 @@ namespace Game.DataStorage
|
||||
foreach (var itemSpecOverride in ItemSpecOverrideStorage.Values)
|
||||
_itemSpecOverrides.Add(itemSpecOverride.ItemID, itemSpecOverride);
|
||||
|
||||
foreach (var itemBonusTreeAssignment in ItemXBonusTreeStorage.Values)
|
||||
_itemToBonusTree.Add(itemBonusTreeAssignment.ItemID, itemBonusTreeAssignment.ItemBonusTreeID);
|
||||
|
||||
foreach (var pair in _azeriteEmpoweredItems)
|
||||
LoadAzeriteEmpoweredItemUnlockMappings(azeriteUnlockMappings, pair.Key);
|
||||
|
||||
foreach (JournalTierRecord journalTier in JournalTierStorage.Values)
|
||||
_journalTiersByIndex.Add(journalTier);
|
||||
|
||||
@@ -1038,9 +1022,18 @@ namespace Game.DataStorage
|
||||
return GetChrSpecializationByIndex(class_, PlayerConst.InitialSpecializationIndex);
|
||||
}
|
||||
|
||||
public ContentTuningLevels? GetContentTuningData(uint contentTuningId, uint replacementConditionMask, bool forItem = false)
|
||||
public uint GetRedirectedContentTuningId(uint contentTuningId, uint redirectFlag)
|
||||
{
|
||||
ContentTuningRecord contentTuning = ContentTuningStorage.LookupByKey(contentTuningId);
|
||||
foreach (var conditionalContentTuning in _conditionalContentTuning.LookupByKey(contentTuningId))
|
||||
if ((conditionalContentTuning.RedirectFlag & redirectFlag) != 0)
|
||||
return (uint)conditionalContentTuning.RedirectContentTuningID;
|
||||
|
||||
return contentTuningId;
|
||||
}
|
||||
|
||||
public ContentTuningLevels? GetContentTuningData(uint contentTuningId, uint redirectFlag, bool forItem = false)
|
||||
{
|
||||
ContentTuningRecord contentTuning = ContentTuningStorage.LookupByKey(GetRedirectedContentTuningId(contentTuningId, redirectFlag));
|
||||
if (contentTuning == null)
|
||||
return null;
|
||||
|
||||
@@ -1077,6 +1070,11 @@ namespace Game.DataStorage
|
||||
return levels;
|
||||
}
|
||||
|
||||
public bool HasContentTuningLabel(uint contentTuningId, int label)
|
||||
{
|
||||
return _contentTuningLabels.Contains((contentTuningId, label));
|
||||
}
|
||||
|
||||
public string GetCreatureFamilyPetName(CreatureFamily petfamily, Locale locale)
|
||||
{
|
||||
if (petfamily == CreatureFamily.None)
|
||||
@@ -1261,20 +1259,26 @@ namespace Game.DataStorage
|
||||
return null;
|
||||
}
|
||||
|
||||
float ExpectedStatModReducer(float mod, ContentTuningXExpectedRecord contentTuningXExpected, ExpectedStatType stat)
|
||||
float ExpectedStatModReducer(float mod, ContentTuningXExpectedRecord contentTuningXExpected, ExpectedStatType stat, int ActiveMilestoneSeason)
|
||||
{
|
||||
if (contentTuningXExpected == null)
|
||||
return mod;
|
||||
|
||||
//if (contentTuningXExpected->MinMythicPlusSeasonID)
|
||||
// if (MythicPlusSeasonEntry const* mythicPlusSeason = sMythicPlusSeasonStore.LookupEntry(contentTuningXExpected->MinMythicPlusSeasonID))
|
||||
// if (MythicPlusSubSeason < mythicPlusSeason->SubSeason)
|
||||
// return mod;
|
||||
if (contentTuningXExpected.MinMythicPlusSeasonID != 0)
|
||||
{
|
||||
var mythicPlusSeason = MythicPlusSeasonStorage.LookupByKey(contentTuningXExpected.MinMythicPlusSeasonID);
|
||||
if (mythicPlusSeason != null)
|
||||
if (ActiveMilestoneSeason < mythicPlusSeason.MilestoneSeason)
|
||||
return mod;
|
||||
}
|
||||
|
||||
//if (contentTuningXExpected->MaxMythicPlusSeasonID)
|
||||
// if (MythicPlusSeasonEntry const* mythicPlusSeason = sMythicPlusSeasonStore.LookupEntry(contentTuningXExpected->MaxMythicPlusSeasonID))
|
||||
// if (MythicPlusSubSeason >= mythicPlusSeason->SubSeason)
|
||||
// return mod;
|
||||
if (contentTuningXExpected.MaxMythicPlusSeasonID != 0)
|
||||
{
|
||||
var mythicPlusSeason = MythicPlusSeasonStorage.LookupByKey(contentTuningXExpected.MaxMythicPlusSeasonID);
|
||||
if (mythicPlusSeason != null)
|
||||
if (ActiveMilestoneSeason >= mythicPlusSeason.MilestoneSeason)
|
||||
return mod;
|
||||
}
|
||||
|
||||
var expectedStatMod = ExpectedStatModStorage.LookupByKey(contentTuningXExpected.ExpectedStatModID);
|
||||
switch (stat)
|
||||
@@ -1300,11 +1304,9 @@ namespace Game.DataStorage
|
||||
}
|
||||
|
||||
return mod;
|
||||
|
||||
// int32 MythicPlusSubSeason = 0;
|
||||
}
|
||||
|
||||
public float EvaluateExpectedStat(ExpectedStatType stat, uint level, int expansion, uint contentTuningId, Class unitClass)
|
||||
public float EvaluateExpectedStat(ExpectedStatType stat, uint level, int expansion, uint contentTuningId, Class unitClass, int mythicPlusMilestoneSeason)
|
||||
{
|
||||
var expectedStatRecord = _expectedStatsByLevel.LookupByKey(Tuple.Create(level, expansion));
|
||||
if (expectedStatRecord == null)
|
||||
@@ -1338,56 +1340,56 @@ namespace Game.DataStorage
|
||||
case ExpectedStatType.CreatureHealth:
|
||||
value = expectedStatRecord.CreatureHealth;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.CreatureHealthMod;
|
||||
break;
|
||||
case ExpectedStatType.PlayerHealth:
|
||||
value = expectedStatRecord.PlayerHealth;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.PlayerHealthMod;
|
||||
break;
|
||||
case ExpectedStatType.CreatureAutoAttackDps:
|
||||
value = expectedStatRecord.CreatureAutoAttackDps;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.CreatureAutoAttackDPSMod;
|
||||
break;
|
||||
case ExpectedStatType.CreatureArmor:
|
||||
value = expectedStatRecord.CreatureArmor;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.CreatureArmorMod;
|
||||
break;
|
||||
case ExpectedStatType.PlayerMana:
|
||||
value = expectedStatRecord.PlayerMana;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.PlayerManaMod;
|
||||
break;
|
||||
case ExpectedStatType.PlayerPrimaryStat:
|
||||
value = expectedStatRecord.PlayerPrimaryStat;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.PlayerPrimaryStatMod;
|
||||
break;
|
||||
case ExpectedStatType.PlayerSecondaryStat:
|
||||
value = expectedStatRecord.PlayerSecondaryStat;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.PlayerSecondaryStatMod;
|
||||
break;
|
||||
case ExpectedStatType.ArmorConstant:
|
||||
value = expectedStatRecord.ArmorConstant;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.ArmorConstantMod;
|
||||
break;
|
||||
@@ -1396,7 +1398,7 @@ namespace Game.DataStorage
|
||||
case ExpectedStatType.CreatureSpellDamage:
|
||||
value = expectedStatRecord.CreatureSpellDamage;
|
||||
if (!contentTuningMods.Empty())
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat));
|
||||
value *= contentTuningMods.Sum(expectedStatMod => ExpectedStatModReducer(1.0f, expectedStatMod, stat, mythicPlusMilestoneSeason));
|
||||
if (classMod != null)
|
||||
value *= classMod.CreatureSpellDamageMod;
|
||||
break;
|
||||
@@ -1440,169 +1442,6 @@ namespace Game.DataStorage
|
||||
return _heirlooms.LookupByKey(itemId);
|
||||
}
|
||||
|
||||
public List<ItemBonusRecord> GetItemBonusList(uint bonusListId)
|
||||
{
|
||||
return _itemBonusLists.LookupByKey(bonusListId);
|
||||
}
|
||||
|
||||
public uint GetItemBonusListForItemLevelDelta(short delta)
|
||||
{
|
||||
return _itemLevelDeltaToBonusListContainer.LookupByKey(delta);
|
||||
}
|
||||
|
||||
void VisitItemBonusTree(uint itemBonusTreeId, bool visitChildren, Action<ItemBonusTreeNodeRecord> visitor)
|
||||
{
|
||||
var bonusTreeNodeList = _itemBonusTrees.LookupByKey(itemBonusTreeId);
|
||||
if (bonusTreeNodeList.Empty())
|
||||
return;
|
||||
|
||||
foreach (var bonusTreeNode in bonusTreeNodeList)
|
||||
{
|
||||
visitor(bonusTreeNode);
|
||||
if (visitChildren && bonusTreeNode.ChildItemBonusTreeID != 0)
|
||||
VisitItemBonusTree(bonusTreeNode.ChildItemBonusTreeID, true, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
public List<uint> GetDefaultItemBonusTree(uint itemId, ItemContext itemContext)
|
||||
{
|
||||
List<uint> bonusListIDs = new();
|
||||
|
||||
ItemSparseRecord proto = ItemSparseStorage.LookupByKey(itemId);
|
||||
if (proto == null)
|
||||
return bonusListIDs;
|
||||
|
||||
var itemIdRange = _itemToBonusTree.LookupByKey(itemId);
|
||||
if (itemIdRange == null)
|
||||
return bonusListIDs;
|
||||
|
||||
ushort itemLevelSelectorId = 0;
|
||||
foreach (var itemBonusTreeId in itemIdRange)
|
||||
{
|
||||
uint matchingNodes = 0;
|
||||
VisitItemBonusTree(itemBonusTreeId, false, bonusTreeNode =>
|
||||
{
|
||||
if ((ItemContext)bonusTreeNode.ItemContext == ItemContext.None || itemContext == (ItemContext)bonusTreeNode.ItemContext)
|
||||
++matchingNodes;
|
||||
});
|
||||
|
||||
if (matchingNodes != 1)
|
||||
continue;
|
||||
|
||||
VisitItemBonusTree(itemBonusTreeId, true, bonusTreeNode =>
|
||||
{
|
||||
ItemContext requiredContext = (ItemContext)bonusTreeNode.ItemContext != ItemContext.ForceToNone ? (ItemContext)bonusTreeNode.ItemContext : ItemContext.None;
|
||||
if ((ItemContext)bonusTreeNode.ItemContext != ItemContext.None && itemContext != requiredContext)
|
||||
return;
|
||||
|
||||
if (bonusTreeNode.ChildItemBonusListID != 0)
|
||||
{
|
||||
bonusListIDs.Add(bonusTreeNode.ChildItemBonusListID);
|
||||
}
|
||||
else if (bonusTreeNode.ChildItemLevelSelectorID != 0)
|
||||
{
|
||||
itemLevelSelectorId = bonusTreeNode.ChildItemLevelSelectorID;
|
||||
}
|
||||
});
|
||||
}
|
||||
ItemLevelSelectorRecord selector = ItemLevelSelectorStorage.LookupByKey(itemLevelSelectorId);
|
||||
if (selector != null)
|
||||
{
|
||||
short delta = (short)(selector.MinItemLevel - proto.ItemLevel);
|
||||
|
||||
uint bonus = GetItemBonusListForItemLevelDelta(delta);
|
||||
if (bonus != 0)
|
||||
bonusListIDs.Add(bonus);
|
||||
|
||||
ItemLevelSelectorQualitySetRecord selectorQualitySet = ItemLevelSelectorQualitySetStorage.LookupByKey(selector.ItemLevelSelectorQualitySetID);
|
||||
if (selectorQualitySet != null)
|
||||
{
|
||||
var itemSelectorQualities = _itemLevelQualitySelectorQualities.LookupByKey(selector.ItemLevelSelectorQualitySetID);
|
||||
if (itemSelectorQualities != null)
|
||||
{
|
||||
ItemQuality quality = ItemQuality.Uncommon;
|
||||
if (selector.MinItemLevel >= selectorQualitySet.IlvlEpic)
|
||||
quality = ItemQuality.Epic;
|
||||
else if (selector.MinItemLevel >= selectorQualitySet.IlvlRare)
|
||||
quality = ItemQuality.Rare;
|
||||
|
||||
var itemSelectorQuality = itemSelectorQualities.Find(p => p.Quality < (sbyte)quality);
|
||||
|
||||
if (itemSelectorQuality != null)
|
||||
bonusListIDs.Add(itemSelectorQuality.QualityItemBonusListID);
|
||||
}
|
||||
}
|
||||
|
||||
AzeriteUnlockMappingRecord azeriteUnlockMapping = _azeriteUnlockMappings.LookupByKey((proto.Id, itemContext));
|
||||
if (azeriteUnlockMapping != null)
|
||||
{
|
||||
switch (proto.inventoryType)
|
||||
{
|
||||
case InventoryType.Head:
|
||||
bonusListIDs.Add(azeriteUnlockMapping.ItemBonusListHead);
|
||||
break;
|
||||
case InventoryType.Shoulders:
|
||||
bonusListIDs.Add(azeriteUnlockMapping.ItemBonusListShoulders);
|
||||
break;
|
||||
case InventoryType.Chest:
|
||||
case InventoryType.Robe:
|
||||
bonusListIDs.Add(azeriteUnlockMapping.ItemBonusListChest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bonusListIDs;
|
||||
}
|
||||
|
||||
public List<uint> GetAllItemBonusTreeBonuses(uint itemBonusTreeId)
|
||||
{
|
||||
List<uint> bonusListIDs = new();
|
||||
VisitItemBonusTree(itemBonusTreeId, true, bonusTreeNode =>
|
||||
{
|
||||
if (bonusTreeNode.ChildItemBonusListID != 0)
|
||||
bonusListIDs.Add(bonusTreeNode.ChildItemBonusListID);
|
||||
});
|
||||
return bonusListIDs;
|
||||
}
|
||||
|
||||
void LoadAzeriteEmpoweredItemUnlockMappings(MultiMap<uint, AzeriteUnlockMappingRecord> azeriteUnlockMappingsBySet, uint itemId)
|
||||
{
|
||||
var itemIdRange = _itemToBonusTree.LookupByKey(itemId);
|
||||
if (itemIdRange == null)
|
||||
return;
|
||||
|
||||
foreach (var itemTreeItr in itemIdRange)
|
||||
{
|
||||
VisitItemBonusTree(itemTreeItr, true, bonusTreeNode =>
|
||||
{
|
||||
if (bonusTreeNode.ChildItemBonusListID == 0 && bonusTreeNode.ChildItemLevelSelectorID != 0)
|
||||
{
|
||||
ItemLevelSelectorRecord selector = ItemLevelSelectorStorage.LookupByKey(bonusTreeNode.ChildItemLevelSelectorID);
|
||||
if (selector == null)
|
||||
return;
|
||||
|
||||
var azeriteUnlockMappings = azeriteUnlockMappingsBySet.LookupByKey(selector.AzeriteUnlockMappingSet);
|
||||
if (azeriteUnlockMappings != null)
|
||||
{
|
||||
AzeriteUnlockMappingRecord selectedAzeriteUnlockMapping = null;
|
||||
foreach (AzeriteUnlockMappingRecord azeriteUnlockMapping in azeriteUnlockMappings)
|
||||
{
|
||||
if (azeriteUnlockMapping.ItemLevel > selector.MinItemLevel ||
|
||||
(selectedAzeriteUnlockMapping != null && selectedAzeriteUnlockMapping.ItemLevel > azeriteUnlockMapping.ItemLevel))
|
||||
continue;
|
||||
|
||||
selectedAzeriteUnlockMapping = azeriteUnlockMapping;
|
||||
}
|
||||
|
||||
if (selectedAzeriteUnlockMapping != null)
|
||||
_azeriteUnlockMappings[(itemId, (ItemContext)bonusTreeNode.ItemContext)] = selectedAzeriteUnlockMapping;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ItemChildEquipmentRecord GetItemChildEquipment(uint itemId)
|
||||
{
|
||||
return _itemChildEquipment.LookupByKey(itemId);
|
||||
@@ -2383,7 +2222,6 @@ namespace Game.DataStorage
|
||||
AzeriteItemMilestonePowerRecord[] _azeriteItemMilestonePowerByEssenceSlot = new AzeriteItemMilestonePowerRecord[SharedConst.MaxAzeriteEssenceSlot];
|
||||
MultiMap<uint, AzeritePowerSetMemberRecord> _azeritePowers = new();
|
||||
Dictionary<(uint azeriteUnlockSetId, ItemContext itemContext), byte[]> _azeriteTierUnlockLevels = new();
|
||||
Dictionary<(uint itemId, ItemContext itemContext), AzeriteUnlockMappingRecord> _azeriteUnlockMappings = new();
|
||||
Dictionary<(int broadcastTextId, CascLocaleBit cascLocaleBit), int> _broadcastTextDurations = new();
|
||||
ChrClassUIDisplayRecord[] _uiDisplayByClass = new ChrClassUIDisplayRecord[(int)Class.Max];
|
||||
uint[][] _powersByClass = new uint[(int)Class.Max][];
|
||||
@@ -2393,6 +2231,8 @@ namespace Game.DataStorage
|
||||
MultiMap<Tuple<byte, byte>, ChrCustomizationOptionRecord> _chrCustomizationOptionsByRaceAndGender = new();
|
||||
Dictionary<uint, MultiMap<uint, uint>> _chrCustomizationRequiredChoices = new();
|
||||
ChrSpecializationRecord[][] _chrSpecializationsByIndex = new ChrSpecializationRecord[(int)Class.Max + 1][];
|
||||
MultiMap<uint, ConditionalContentTuningRecord> _conditionalContentTuning = new();
|
||||
List<(uint, int)> _contentTuningLabels = new();
|
||||
MultiMap<uint, CurrencyContainerRecord> _currencyContainers = new();
|
||||
MultiMap<uint, CurvePointRecord> _curvePoints = new();
|
||||
Dictionary<Tuple<uint, byte, byte, byte>, EmotesTextSoundRecord> _emoteTextSounds = new();
|
||||
@@ -2403,16 +2243,11 @@ namespace Game.DataStorage
|
||||
Dictionary<uint, HeirloomRecord> _heirlooms = new();
|
||||
MultiMap<uint, uint> _glyphBindableSpells = new();
|
||||
MultiMap<uint, uint> _glyphRequiredSpecs = new();
|
||||
MultiMap<uint, ItemBonusRecord> _itemBonusLists = new();
|
||||
Dictionary<short, uint> _itemLevelDeltaToBonusListContainer = new();
|
||||
MultiMap<uint, ItemBonusTreeNodeRecord> _itemBonusTrees = new();
|
||||
Dictionary<uint, ItemChildEquipmentRecord> _itemChildEquipment = new();
|
||||
ItemClassRecord[] _itemClassByOldEnum = new ItemClassRecord[20];
|
||||
List<uint> _itemsWithCurrencyCost = new();
|
||||
MultiMap<uint, ItemLimitCategoryConditionRecord> _itemCategoryConditions = new();
|
||||
MultiMap<uint, ItemLevelSelectorQualityRecord> _itemLevelQualitySelectorQualities = new();
|
||||
Dictionary<uint, ItemModifiedAppearanceRecord> _itemModifiedAppearancesByItem = new();
|
||||
MultiMap<uint, uint> _itemToBonusTree = new();
|
||||
MultiMap<uint, ItemSetSpellRecord> _itemSetSpells = new();
|
||||
MultiMap<uint, ItemSpecOverrideRecord> _itemSpecOverrides = new();
|
||||
List<JournalTierRecord> _journalTiersByIndex = new();
|
||||
|
||||
@@ -16,6 +16,18 @@ namespace Game.DataStorage
|
||||
public uint ChallengeOrigin;
|
||||
}
|
||||
|
||||
public sealed class ChallengeModeItemBonusOverrideRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int ItemBonusTreeGroupID;
|
||||
public int DstItemBonusTreeID;
|
||||
public sbyte Type;
|
||||
public int Value;
|
||||
public int MythicPlusSeasonID;
|
||||
public int PvPSeasonID;
|
||||
public uint SrcItemBonusTreeID;
|
||||
}
|
||||
|
||||
public sealed class CharTitlesRecord
|
||||
{
|
||||
public uint Id;
|
||||
@@ -317,6 +329,15 @@ namespace Game.DataStorage
|
||||
public ushort[] Camera = new ushort[8];
|
||||
}
|
||||
|
||||
public sealed class ConditionalContentTuningRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int OrderIndex;
|
||||
public int RedirectContentTuningID;
|
||||
public int RedirectFlag;
|
||||
public uint ParentContentTuningID;
|
||||
}
|
||||
|
||||
public sealed class ContentTuningRecord
|
||||
{
|
||||
public uint Id;
|
||||
@@ -357,6 +378,13 @@ namespace Game.DataStorage
|
||||
public uint ContentTuningID;
|
||||
}
|
||||
|
||||
public sealed class ContentTuningXLabelRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int LabelID;
|
||||
public uint ContentTuningID;
|
||||
}
|
||||
|
||||
public sealed class ConversationLineRecord
|
||||
{
|
||||
public uint Id;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
using System;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
@@ -99,12 +100,14 @@ namespace Game.DataStorage
|
||||
public sealed class ItemBonusListGroupEntryRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint ItemBonusListGroupID;
|
||||
public int ItemBonusListGroupID;
|
||||
public int ItemBonusListID;
|
||||
public int ItemLevelSelectorID;
|
||||
public int OrderIndex;
|
||||
public int SequenceValue;
|
||||
public int ItemExtendedCostID;
|
||||
public int PlayerConditionID;
|
||||
public int Flags;
|
||||
public int ItemLogicalCostGroupID;
|
||||
}
|
||||
|
||||
public sealed class ItemBonusListLevelDeltaRecord
|
||||
@@ -120,6 +123,13 @@ namespace Game.DataStorage
|
||||
public int ItemID;
|
||||
}
|
||||
|
||||
public sealed class ItemBonusTreeRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int Flags;
|
||||
public int InventoryTypeSlotMask;
|
||||
}
|
||||
|
||||
public sealed class ItemBonusTreeNodeRecord
|
||||
{
|
||||
public uint Id;
|
||||
@@ -129,8 +139,8 @@ namespace Game.DataStorage
|
||||
public ushort ChildItemLevelSelectorID;
|
||||
public uint ChildItemBonusListGroupID;
|
||||
public uint IblGroupPointsModSetID;
|
||||
public int Unknown1010_1;
|
||||
public int Unknown1010_2;
|
||||
public int MinMythicPlusLevel;
|
||||
public int MaxMythicPlusLevel;
|
||||
public uint ParentItemBonusTreeID;
|
||||
}
|
||||
|
||||
@@ -151,11 +161,24 @@ namespace Game.DataStorage
|
||||
public byte Flags;
|
||||
}
|
||||
|
||||
public sealed class ItemContextPickerEntryRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte ItemCreationContext;
|
||||
public byte OrderIndex;
|
||||
public int PVal;
|
||||
public int LabelID;
|
||||
public uint Flags;
|
||||
public uint PlayerConditionID;
|
||||
public uint ItemContextPickerID;
|
||||
}
|
||||
|
||||
public sealed class ItemCurrencyCostRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint ItemID;
|
||||
}
|
||||
|
||||
// common struct for:
|
||||
// ItemDamageAmmo.dbc
|
||||
// ItemDamageOneHand.dbc
|
||||
@@ -220,12 +243,16 @@ namespace Game.DataStorage
|
||||
public ushort AzeriteUnlockMappingSet;
|
||||
}
|
||||
|
||||
public sealed class ItemLevelSelectorQualityRecord
|
||||
public sealed class ItemLevelSelectorQualityRecord : IEquatable<ItemLevelSelectorQualityRecord>, IEquatable<ItemQuality>
|
||||
{
|
||||
public uint Id;
|
||||
public uint QualityItemBonusListID;
|
||||
public sbyte Quality;
|
||||
public uint ParentILSQualitySetID;
|
||||
|
||||
public bool Equals(ItemLevelSelectorQualityRecord other) { return Quality < other.Quality; }
|
||||
|
||||
public bool Equals(ItemQuality quality) { return Quality < (sbyte)quality; }
|
||||
}
|
||||
|
||||
public sealed class ItemLevelSelectorQualitySetRecord
|
||||
|
||||
@@ -229,4 +229,12 @@ namespace Game.DataStorage
|
||||
public uint SubtitleFileDataID;
|
||||
public int SubtitleFileFormat;
|
||||
}
|
||||
|
||||
public sealed class MythicPlusSeasonRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int MilestoneSeason;
|
||||
public int ExpansionLevel;
|
||||
public int HeroicLFGDungeonMinGear;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +178,14 @@ namespace Game.DataStorage
|
||||
public byte ItemLevelDelta;
|
||||
}
|
||||
|
||||
public sealed class PvpSeasonRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int MilestoneSeason;
|
||||
public int AllianceAchievementID;
|
||||
public int HordeAchievementID;
|
||||
}
|
||||
|
||||
public sealed class PvpTalentRecord
|
||||
{
|
||||
public string Description;
|
||||
|
||||
Reference in New Issue
Block a user