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:
@@ -1132,7 +1132,15 @@ namespace Framework.Constants
|
|||||||
SquishUsingItemLevelAsPlayerLevel = 0x4000,
|
SquishUsingItemLevelAsPlayerLevel = 0x4000,
|
||||||
AlwaysShowPriceInTooltip = 0x8000,
|
AlwaysShowPriceInTooltip = 0x8000,
|
||||||
CosmeticItem = 0x10000,
|
CosmeticItem = 0x10000,
|
||||||
NoSpellEffectTooltipPrefixes = 0x20000
|
NoSpellEffectTooltipPrefixes = 0x20000,
|
||||||
|
IgnoreCosmeticCollectionBehavior = 0x40000,
|
||||||
|
NpcOnly = 0x80000,
|
||||||
|
NotRestorable = 0x100000,
|
||||||
|
DontDisplayAsCraftingReagent = 0x200000,
|
||||||
|
DisplayReagentQualityAsCraftedQuality = 0x400000,
|
||||||
|
NoSalvage = 0x800000,
|
||||||
|
Recraftable = 0x1000000,
|
||||||
|
CcTrinket = 0x2000000,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
|
|||||||
@@ -212,6 +212,10 @@ namespace Framework.Database
|
|||||||
PrepareStatement(HotfixStatements.SEL_CFG_REGIONS, "SELECT ID, Tag, RegionID, Raidorigin, RegionGroupMask, ChallengeOrigin FROM cfg_regions" +
|
PrepareStatement(HotfixStatements.SEL_CFG_REGIONS, "SELECT ID, Tag, RegionID, Raidorigin, RegionGroupMask, ChallengeOrigin FROM cfg_regions" +
|
||||||
" WHERE (`VerifiedBuild` > 0) = ?");
|
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
|
// ChallengeModeItemBonusOverride.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE, "SELECT ID, ItemBonusTreeGroupID, DstItemBonusTreeID, Type, Value, " +
|
||||||
|
"MythicPlusSeasonID, PvPSeasonID, SrcItemBonusTreeID FROM challenge_mode_item_bonus_override WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// CharTitles.db2
|
// CharTitles.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_CHAR_TITLES, "SELECT ID, Name, Name1, MaskID, Flags FROM char_titles WHERE (`VerifiedBuild` > 0) = ?");
|
PrepareStatement(HotfixStatements.SEL_CHAR_TITLES, "SELECT ID, Name, Name1, MaskID, Flags FROM char_titles WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
PrepareStatement(HotfixStatements.SEL_CHAR_TITLES_LOCALE, "SELECT ID, Name_lang, Name1_lang FROM char_titles_locale WHERE (`VerifiedBuild` > 0) = ?" +
|
PrepareStatement(HotfixStatements.SEL_CHAR_TITLES_LOCALE, "SELECT ID, Name_lang, Name1_lang FROM char_titles_locale WHERE (`VerifiedBuild` > 0) = ?" +
|
||||||
@@ -327,6 +331,10 @@ namespace Framework.Database
|
|||||||
PrepareStatement(HotfixStatements.SEL_CINEMATIC_SEQUENCES, "SELECT ID, SoundID, Camera1, Camera2, Camera3, Camera4, Camera5, Camera6, Camera7, Camera8" +
|
PrepareStatement(HotfixStatements.SEL_CINEMATIC_SEQUENCES, "SELECT ID, SoundID, Camera1, Camera2, Camera3, Camera4, Camera5, Camera6, Camera7, Camera8" +
|
||||||
" FROM cinematic_sequences WHERE (`VerifiedBuild` > 0) = ?");
|
" FROM cinematic_sequences WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
|
// ConditionalContentTuning.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_CONDITIONAL_CONTENT_TUNING, "SELECT ID, OrderIndex, RedirectContentTuningID, RedirectFlag, ParentContentTuningID" +
|
||||||
|
" FROM conditional_content_tuning WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// ContentTuning.db2
|
// ContentTuning.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING, "SELECT ID, Flags, ExpansionID, MinLevel, MaxLevel, MinLevelType, MaxLevelType, TargetLevelDelta, " +
|
PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING, "SELECT ID, Flags, ExpansionID, MinLevel, MaxLevel, MinLevelType, MaxLevelType, TargetLevelDelta, " +
|
||||||
"TargetLevelMaxDelta, TargetLevelMin, TargetLevelMax, MinItemLevel, QuestXpMultiplier FROM content_tuning WHERE (`VerifiedBuild` > 0) = ?");
|
"TargetLevelMaxDelta, TargetLevelMin, TargetLevelMax, MinItemLevel, QuestXpMultiplier FROM content_tuning WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
@@ -335,6 +343,10 @@ namespace Framework.Database
|
|||||||
PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING_X_EXPECTED, "SELECT ID, ExpectedStatModID, MinMythicPlusSeasonID, MaxMythicPlusSeasonID, " +
|
PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING_X_EXPECTED, "SELECT ID, ExpectedStatModID, MinMythicPlusSeasonID, MaxMythicPlusSeasonID, " +
|
||||||
"ContentTuningID FROM content_tuning_x_expected WHERE (`VerifiedBuild` > 0) = ?");
|
"ContentTuningID FROM content_tuning_x_expected WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
|
// ContentTuningXLabel.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING_X_LABEL, "SELECT ID, LabelID, ContentTuningID FROM content_tuning_x_label" +
|
||||||
|
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// ConversationLine.db2
|
// ConversationLine.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_CONVERSATION_LINE, "SELECT ID, BroadcastTextID, SpellVisualKitID, AdditionalDuration, NextConversationLineID, " +
|
PrepareStatement(HotfixStatements.SEL_CONVERSATION_LINE, "SELECT ID, BroadcastTextID, SpellVisualKitID, AdditionalDuration, NextConversationLineID, " +
|
||||||
"AnimKitID, SpeechType, StartAnimation, EndAnimation FROM conversation_line WHERE (`VerifiedBuild` > 0) = ?");
|
"AnimKitID, SpeechType, StartAnimation, EndAnimation FROM conversation_line WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
@@ -653,13 +665,20 @@ namespace Framework.Database
|
|||||||
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS, "SELECT ID, Value1, Value2, Value3, Value4, ParentItemBonusListID, Type, OrderIndex FROM item_bonus" +
|
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS, "SELECT ID, Value1, Value2, Value3, Value4, ParentItemBonusListID, Type, OrderIndex FROM item_bonus" +
|
||||||
" WHERE (`VerifiedBuild` > 0) = ?");
|
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
|
// ItemBonusListGroupEntry.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_LIST_GROUP_ENTRY, "SELECT ID, ItemBonusListGroupID, ItemBonusListID, ItemLevelSelectorID, SequenceValue, " +
|
||||||
|
"ItemExtendedCostID, PlayerConditionID, Flags, ItemLogicalCostGroupID FROM item_bonus_list_group_entry WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// ItemBonusListLevelDelta.db2
|
// ItemBonusListLevelDelta.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_LIST_LEVEL_DELTA, "SELECT ItemLevelDelta, ID FROM item_bonus_list_level_delta" +
|
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_LIST_LEVEL_DELTA, "SELECT ItemLevelDelta, ID FROM item_bonus_list_level_delta" +
|
||||||
" WHERE (`VerifiedBuild` > 0) = ?");
|
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
|
// ItemBonusTree.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_TREE, "SELECT ID, Flags, InventoryTypeSlotMask FROM item_bonus_tree WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// ItemBonusTreeNode.db2
|
// ItemBonusTreeNode.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_TREE_NODE, "SELECT ID, ItemContext, ChildItemBonusTreeID, ChildItemBonusListID, ChildItemLevelSelectorID, " +
|
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_TREE_NODE, "SELECT ID, ItemContext, ChildItemBonusTreeID, ChildItemBonusListID, ChildItemLevelSelectorID, " +
|
||||||
"ChildItemBonusListGroupID, IblGroupPointsModSetID, Unknown1010_1, Unknown1010_2, ParentItemBonusTreeID FROM item_bonus_tree_node" +
|
"ChildItemBonusListGroupID, IblGroupPointsModSetID, MinMythicPlusLevel, MaxMythicPlusLevel, ParentItemBonusTreeID FROM item_bonus_tree_node" +
|
||||||
" WHERE (`VerifiedBuild` > 0) = ?");
|
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// ItemChildEquipment.db2
|
// ItemChildEquipment.db2
|
||||||
@@ -670,6 +689,10 @@ namespace Framework.Database
|
|||||||
PrepareStatement(HotfixStatements.SEL_ITEM_CLASS, "SELECT ID, ClassName, ClassID, PriceModifier, Flags FROM item_class WHERE (`VerifiedBuild` > 0) = ?");
|
PrepareStatement(HotfixStatements.SEL_ITEM_CLASS, "SELECT ID, ClassName, ClassID, PriceModifier, Flags FROM item_class WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
PrepareStatement(HotfixStatements.SEL_ITEM_CLASS_LOCALE, "SELECT ID, ClassName_lang FROM item_class_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
|
PrepareStatement(HotfixStatements.SEL_ITEM_CLASS_LOCALE, "SELECT ID, ClassName_lang FROM item_class_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
|
||||||
|
|
||||||
|
// ItemContextPickerEntry.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_ITEM_CONTEXT_PICKER_ENTRY, "SELECT ID, ItemCreationContext, OrderIndex, PVal, LabelID, Flags, PlayerConditionID, " +
|
||||||
|
"ItemContextPickerID FROM item_context_picker_entry WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// ItemCurrencyCost.db2
|
// ItemCurrencyCost.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_ITEM_CURRENCY_COST, "SELECT ID, ItemID FROM item_currency_cost WHERE (`VerifiedBuild` > 0) = ?");
|
PrepareStatement(HotfixStatements.SEL_ITEM_CURRENCY_COST, "SELECT ID, ItemID FROM item_currency_cost WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
@@ -918,6 +941,10 @@ namespace Framework.Database
|
|||||||
PrepareStatement(HotfixStatements.SEL_MOVIE, "SELECT ID, Volume, KeyID, AudioFileDataID, SubtitleFileDataID, SubtitleFileFormat FROM movie" +
|
PrepareStatement(HotfixStatements.SEL_MOVIE, "SELECT ID, Volume, KeyID, AudioFileDataID, SubtitleFileDataID, SubtitleFileFormat FROM movie" +
|
||||||
" WHERE (`VerifiedBuild` > 0) = ?");
|
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
|
// MythicPlusSeason.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_MYTHIC_PLUS_SEASON, "SELECT ID, MilestoneSeason, ExpansionLevel, HeroicLFGDungeonMinGear FROM mythic_plus_season" +
|
||||||
|
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// NameGen.db2
|
// NameGen.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_NAME_GEN, "SELECT ID, Name, RaceID, Sex FROM name_gen WHERE (`VerifiedBuild` > 0) = ?");
|
PrepareStatement(HotfixStatements.SEL_NAME_GEN, "SELECT ID, Name, RaceID, Sex FROM name_gen WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
@@ -991,6 +1018,10 @@ namespace Framework.Database
|
|||||||
// PvpItem.db2
|
// PvpItem.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_PVP_ITEM, "SELECT ID, ItemID, ItemLevelDelta FROM pvp_item WHERE (`VerifiedBuild` > 0) = ?");
|
PrepareStatement(HotfixStatements.SEL_PVP_ITEM, "SELECT ID, ItemID, ItemLevelDelta FROM pvp_item WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
|
// PvpSeason.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_PVP_SEASON, "SELECT ID, MilestoneSeason, AllianceAchievementID, HordeAchievementID FROM pvp_season" +
|
||||||
|
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
|
|
||||||
// PvpTalent.db2
|
// PvpTalent.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_PVP_TALENT, "SELECT Description, ID, SpecID, SpellID, OverridesSpellID, Flags, ActionBarSpellID, PvpTalentCategoryID, " +
|
PrepareStatement(HotfixStatements.SEL_PVP_TALENT, "SELECT Description, ID, SpecID, SpellID, OverridesSpellID, Flags, ActionBarSpellID, PvpTalentCategoryID, " +
|
||||||
"LevelRequired, PlayerConditionID FROM pvp_talent WHERE (`VerifiedBuild` > 0) = ?");
|
"LevelRequired, PlayerConditionID FROM pvp_talent WHERE (`VerifiedBuild` > 0) = ?");
|
||||||
@@ -1646,6 +1677,8 @@ namespace Framework.Database
|
|||||||
|
|
||||||
SEL_CFG_REGIONS,
|
SEL_CFG_REGIONS,
|
||||||
|
|
||||||
|
SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE,
|
||||||
|
|
||||||
SEL_CHAR_TITLES,
|
SEL_CHAR_TITLES,
|
||||||
SEL_CHAR_TITLES_LOCALE,
|
SEL_CHAR_TITLES_LOCALE,
|
||||||
|
|
||||||
@@ -1692,10 +1725,14 @@ namespace Framework.Database
|
|||||||
|
|
||||||
SEL_CINEMATIC_SEQUENCES,
|
SEL_CINEMATIC_SEQUENCES,
|
||||||
|
|
||||||
|
SEL_CONDITIONAL_CONTENT_TUNING,
|
||||||
|
|
||||||
SEL_CONTENT_TUNING,
|
SEL_CONTENT_TUNING,
|
||||||
|
|
||||||
SEL_CONTENT_TUNING_X_EXPECTED,
|
SEL_CONTENT_TUNING_X_EXPECTED,
|
||||||
|
|
||||||
|
SEL_CONTENT_TUNING_X_LABEL,
|
||||||
|
|
||||||
SEL_CONVERSATION_LINE,
|
SEL_CONVERSATION_LINE,
|
||||||
|
|
||||||
SEL_CORRUPTION_EFFECTS,
|
SEL_CORRUPTION_EFFECTS,
|
||||||
@@ -1847,8 +1884,12 @@ namespace Framework.Database
|
|||||||
|
|
||||||
SEL_ITEM_BONUS,
|
SEL_ITEM_BONUS,
|
||||||
|
|
||||||
|
SEL_ITEM_BONUS_LIST_GROUP_ENTRY,
|
||||||
|
|
||||||
SEL_ITEM_BONUS_LIST_LEVEL_DELTA,
|
SEL_ITEM_BONUS_LIST_LEVEL_DELTA,
|
||||||
|
|
||||||
|
SEL_ITEM_BONUS_TREE,
|
||||||
|
|
||||||
SEL_ITEM_BONUS_TREE_NODE,
|
SEL_ITEM_BONUS_TREE_NODE,
|
||||||
|
|
||||||
SEL_ITEM_CHILD_EQUIPMENT,
|
SEL_ITEM_CHILD_EQUIPMENT,
|
||||||
@@ -1856,6 +1897,8 @@ namespace Framework.Database
|
|||||||
SEL_ITEM_CLASS,
|
SEL_ITEM_CLASS,
|
||||||
SEL_ITEM_CLASS_LOCALE,
|
SEL_ITEM_CLASS_LOCALE,
|
||||||
|
|
||||||
|
SEL_ITEM_CONTEXT_PICKER_ENTRY,
|
||||||
|
|
||||||
SEL_ITEM_CURRENCY_COST,
|
SEL_ITEM_CURRENCY_COST,
|
||||||
|
|
||||||
SEL_ITEM_DAMAGE_AMMO,
|
SEL_ITEM_DAMAGE_AMMO,
|
||||||
@@ -1974,6 +2017,8 @@ namespace Framework.Database
|
|||||||
|
|
||||||
SEL_MOVIE,
|
SEL_MOVIE,
|
||||||
|
|
||||||
|
SEL_MYTHIC_PLUS_SEASON,
|
||||||
|
|
||||||
SEL_NAME_GEN,
|
SEL_NAME_GEN,
|
||||||
|
|
||||||
SEL_NAMES_PROFANITY,
|
SEL_NAMES_PROFANITY,
|
||||||
@@ -2006,6 +2051,8 @@ namespace Framework.Database
|
|||||||
|
|
||||||
SEL_PVP_ITEM,
|
SEL_PVP_ITEM,
|
||||||
|
|
||||||
|
SEL_PVP_SEASON,
|
||||||
|
|
||||||
SEL_PVP_TALENT,
|
SEL_PVP_TALENT,
|
||||||
SEL_PVP_TALENT_LOCALE,
|
SEL_PVP_TALENT_LOCALE,
|
||||||
|
|
||||||
|
|||||||
@@ -2736,7 +2736,7 @@ namespace Game.Achievements
|
|||||||
}
|
}
|
||||||
case ModifierTreeType.PlayerHasItemWithBonusListFromTreeAndQuality: // 222
|
case ModifierTreeType.PlayerHasItemWithBonusListFromTreeAndQuality: // 222
|
||||||
{
|
{
|
||||||
var bonusListIDs = Global.DB2Mgr.GetAllItemBonusTreeBonuses(reqValue);
|
var bonusListIDs = ItemBonusMgr.GetAllBonusListsForTree(reqValue);
|
||||||
if (bonusListIDs.Empty())
|
if (bonusListIDs.Empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -2096,9 +2096,9 @@ namespace Game.Chat
|
|||||||
if (!context.IsEmpty())
|
if (!context.IsEmpty())
|
||||||
{
|
{
|
||||||
itemContext = context.ToEnum<ItemContext>();
|
itemContext = context.ToEnum<ItemContext>();
|
||||||
if (itemContext != ItemContext.None && itemContext < ItemContext.Max)
|
if (itemContext < ItemContext.Max)
|
||||||
{
|
{
|
||||||
var contextBonuses = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, itemContext);
|
var contextBonuses = ItemBonusMgr.GetBonusListsForItem(itemId, new(itemContext));
|
||||||
bonusListIDs.AddRange(contextBonuses);
|
bonusListIDs.AddRange(contextBonuses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2156,7 +2156,7 @@ namespace Game.Chat
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item item = playerTarget.StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, itemContext, bonusListIDs);
|
Item item = playerTarget.StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, itemContext, bonusListIDs.Empty() ? null : bonusListIDs);
|
||||||
|
|
||||||
// remove binding (let GM give it to another player later)
|
// remove binding (let GM give it to another player later)
|
||||||
if (player == playerTarget)
|
if (player == playerTarget)
|
||||||
@@ -2208,7 +2208,7 @@ namespace Game.Chat
|
|||||||
|
|
||||||
ItemContext itemContext = ItemContext.None;
|
ItemContext itemContext = ItemContext.None;
|
||||||
if (context.HasValue)
|
if (context.HasValue)
|
||||||
itemContext = (ItemContext)context;
|
itemContext = (ItemContext)context.Value;
|
||||||
|
|
||||||
Player player = handler.GetSession().GetPlayer();
|
Player player = handler.GetSession().GetPlayer();
|
||||||
Player playerTarget = handler.GetSelectedPlayer();
|
Player playerTarget = handler.GetSelectedPlayer();
|
||||||
@@ -2230,13 +2230,13 @@ namespace Game.Chat
|
|||||||
if (msg == InventoryResult.Ok)
|
if (msg == InventoryResult.Ok)
|
||||||
{
|
{
|
||||||
List<uint> bonusListIDsForItem = new(bonusListIDs); // copy, bonuses for each depending on context might be different for each item
|
List<uint> bonusListIDsForItem = new(bonusListIDs); // copy, bonuses for each depending on context might be different for each item
|
||||||
if (itemContext != ItemContext.None && itemContext < ItemContext.Max)
|
if (itemContext < ItemContext.Max)
|
||||||
{
|
{
|
||||||
var contextBonuses = Global.DB2Mgr.GetDefaultItemBonusTree(template.Value.GetId(), itemContext);
|
var contextBonuses = ItemBonusMgr.GetBonusListsForItem(template.Value.GetId(), new(itemContext));
|
||||||
bonusListIDsForItem.AddRange(contextBonuses);
|
bonusListIDsForItem.AddRange(contextBonuses);
|
||||||
}
|
}
|
||||||
|
|
||||||
Item item = playerTarget.StoreNewItem(dest, template.Value.GetId(), true, 0, null, itemContext, bonusListIDsForItem);
|
Item item = playerTarget.StoreNewItem(dest, template.Value.GetId(), true, 0, null, itemContext, bonusListIDsForItem.Empty() ? null : bonusListIDsForItem);
|
||||||
|
|
||||||
// remove binding (let GM give it to another player later)
|
// remove binding (let GM give it to another player later)
|
||||||
if (player == playerTarget)
|
if (player == playerTarget)
|
||||||
@@ -2330,9 +2330,9 @@ namespace Game.Chat
|
|||||||
if (!context.IsEmpty())
|
if (!context.IsEmpty())
|
||||||
{
|
{
|
||||||
itemContext = context.ToEnum<ItemContext>();
|
itemContext = context.ToEnum<ItemContext>();
|
||||||
if (itemContext != ItemContext.None && itemContext < ItemContext.Max)
|
if (itemContext < ItemContext.Max)
|
||||||
{
|
{
|
||||||
var contextBonuses = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, itemContext);
|
var contextBonuses = ItemBonusMgr.GetBonusListsForItem(itemId, new(itemContext));
|
||||||
bonusListIDs.AddRange(contextBonuses);
|
bonusListIDs.AddRange(contextBonuses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2396,7 +2396,7 @@ namespace Game.Chat
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item item = playerTarget.StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, itemContext, bonusListIDs);
|
Item item = playerTarget.StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, itemContext, bonusListIDs.Empty() ? null : bonusListIDs);
|
||||||
|
|
||||||
// remove binding (let GM give it to another player later)
|
// remove binding (let GM give it to another player later)
|
||||||
if (player == playerTarget)
|
if (player == playerTarget)
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ namespace Game.DataStorage
|
|||||||
BroadcastTextStorage = ReadDB2<BroadcastTextRecord>("BroadcastText.db2", HotfixStatements.SEL_BROADCAST_TEXT, HotfixStatements.SEL_BROADCAST_TEXT_LOCALE);
|
BroadcastTextStorage = ReadDB2<BroadcastTextRecord>("BroadcastText.db2", HotfixStatements.SEL_BROADCAST_TEXT, HotfixStatements.SEL_BROADCAST_TEXT_LOCALE);
|
||||||
BroadcastTextDurationStorage = ReadDB2<BroadcastTextDurationRecord>("BroadcastTextDuration.db2", HotfixStatements.SEL_BROADCAST_TEXT_DURATION);
|
BroadcastTextDurationStorage = ReadDB2<BroadcastTextDurationRecord>("BroadcastTextDuration.db2", HotfixStatements.SEL_BROADCAST_TEXT_DURATION);
|
||||||
CfgRegionsStorage = ReadDB2<Cfg_RegionsRecord>("Cfg_Regions.db2", HotfixStatements.SEL_CFG_REGIONS);
|
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);
|
CharTitlesStorage = ReadDB2<CharTitlesRecord>("CharTitles.db2", HotfixStatements.SEL_CHAR_TITLES, HotfixStatements.SEL_CHAR_TITLES_LOCALE);
|
||||||
CharacterLoadoutStorage = ReadDB2<CharacterLoadoutRecord>("CharacterLoadout.db2", HotfixStatements.SEL_CHARACTER_LOADOUT);
|
CharacterLoadoutStorage = ReadDB2<CharacterLoadoutRecord>("CharacterLoadout.db2", HotfixStatements.SEL_CHARACTER_LOADOUT);
|
||||||
CharacterLoadoutItemStorage = ReadDB2<CharacterLoadoutItemRecord>("CharacterLoadoutItem.db2", HotfixStatements.SEL_CHARACTER_LOADOUT_ITEM);
|
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);
|
ChrSpecializationStorage = ReadDB2<ChrSpecializationRecord>("ChrSpecialization.db2", HotfixStatements.SEL_CHR_SPECIALIZATION, HotfixStatements.SEL_CHR_SPECIALIZATION_LOCALE);
|
||||||
CinematicCameraStorage = ReadDB2<CinematicCameraRecord>("CinematicCamera.db2", HotfixStatements.SEL_CINEMATIC_CAMERA);
|
CinematicCameraStorage = ReadDB2<CinematicCameraRecord>("CinematicCamera.db2", HotfixStatements.SEL_CINEMATIC_CAMERA);
|
||||||
CinematicSequencesStorage = ReadDB2<CinematicSequencesRecord>("CinematicSequences.db2", HotfixStatements.SEL_CINEMATIC_SEQUENCES);
|
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);
|
ContentTuningStorage = ReadDB2<ContentTuningRecord>("ContentTuning.db2", HotfixStatements.SEL_CONTENT_TUNING);
|
||||||
ContentTuningXExpectedStorage = ReadDB2<ContentTuningXExpectedRecord>("ContentTuningXExpected.db2", HotfixStatements.SEL_CONTENT_TUNING_X_EXPECTED);
|
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);
|
ConversationLineStorage = ReadDB2<ConversationLineRecord>("ConversationLine.db2", HotfixStatements.SEL_CONVERSATION_LINE);
|
||||||
CorruptionEffectsStorage = ReadDB2<CorruptionEffectsRecord>("CorruptionEffects.db2", HotfixStatements.SEL_CORRUPTION_EFFECTS);
|
CorruptionEffectsStorage = ReadDB2<CorruptionEffectsRecord>("CorruptionEffects.db2", HotfixStatements.SEL_CORRUPTION_EFFECTS);
|
||||||
CreatureDisplayInfoStorage = ReadDB2<CreatureDisplayInfoRecord>("CreatureDisplayInfo.db2", HotfixStatements.SEL_CREATURE_DISPLAY_INFO);
|
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);
|
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);
|
//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);
|
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);
|
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);
|
ItemBonusTreeNodeStorage = ReadDB2<ItemBonusTreeNodeRecord>("ItemBonusTreeNode.db2", HotfixStatements.SEL_ITEM_BONUS_TREE_NODE);
|
||||||
ItemChildEquipmentStorage = ReadDB2<ItemChildEquipmentRecord>("ItemChildEquipment.db2", HotfixStatements.SEL_ITEM_CHILD_EQUIPMENT);
|
ItemChildEquipmentStorage = ReadDB2<ItemChildEquipmentRecord>("ItemChildEquipment.db2", HotfixStatements.SEL_ITEM_CHILD_EQUIPMENT);
|
||||||
ItemClassStorage = ReadDB2<ItemClassRecord>("ItemClass.db2", HotfixStatements.SEL_ITEM_CLASS, HotfixStatements.SEL_ITEM_CLASS_LOCALE);
|
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);
|
ItemCurrencyCostStorage = ReadDB2<ItemCurrencyCostRecord>("ItemCurrencyCost.db2", HotfixStatements.SEL_ITEM_CURRENCY_COST);
|
||||||
ItemDamageAmmoStorage = ReadDB2<ItemDamageRecord>("ItemDamageAmmo.db2", HotfixStatements.SEL_ITEM_DAMAGE_AMMO);
|
ItemDamageAmmoStorage = ReadDB2<ItemDamageRecord>("ItemDamageAmmo.db2", HotfixStatements.SEL_ITEM_DAMAGE_AMMO);
|
||||||
ItemDamageOneHandStorage = ReadDB2<ItemDamageRecord>("ItemDamageOneHand.db2", HotfixStatements.SEL_ITEM_DAMAGE_ONE_HAND);
|
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);
|
MountTypeXCapabilityStorage = ReadDB2<MountTypeXCapabilityRecord>("MountTypeXCapability.db2", HotfixStatements.SEL_MOUNT_TYPE_X_CAPABILITY);
|
||||||
MountXDisplayStorage = ReadDB2<MountXDisplayRecord>("MountXDisplay.db2", HotfixStatements.SEL_MOUNT_X_DISPLAY);
|
MountXDisplayStorage = ReadDB2<MountXDisplayRecord>("MountXDisplay.db2", HotfixStatements.SEL_MOUNT_X_DISPLAY);
|
||||||
MovieStorage = ReadDB2<MovieRecord>("Movie.db2", HotfixStatements.SEL_MOVIE);
|
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);
|
NameGenStorage = ReadDB2<NameGenRecord>("NameGen.db2", HotfixStatements.SEL_NAME_GEN);
|
||||||
NamesProfanityStorage = ReadDB2<NamesProfanityRecord>("NamesProfanity.db2", HotfixStatements.SEL_NAMES_PROFANITY);
|
NamesProfanityStorage = ReadDB2<NamesProfanityRecord>("NamesProfanity.db2", HotfixStatements.SEL_NAMES_PROFANITY);
|
||||||
NamesReservedStorage = ReadDB2<NamesReservedRecord>("NamesReserved.db2", HotfixStatements.SEL_NAMES_RESERVED, HotfixStatements.SEL_NAMES_RESERVED_LOCALE);
|
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);
|
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);
|
PvpDifficultyStorage = ReadDB2<PvpDifficultyRecord>("PVPDifficulty.db2", HotfixStatements.SEL_PVP_DIFFICULTY);
|
||||||
PvpItemStorage = ReadDB2<PvpItemRecord>("PVPItem.db2", HotfixStatements.SEL_PVP_ITEM);
|
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);
|
PvpTalentStorage = ReadDB2<PvpTalentRecord>("PvpTalent.db2", HotfixStatements.SEL_PVP_TALENT, HotfixStatements.SEL_PVP_TALENT_LOCALE);
|
||||||
PvpTalentCategoryStorage = ReadDB2<PvpTalentCategoryRecord>("PvpTalentCategory.db2", HotfixStatements.SEL_PVP_TALENT_CATEGORY);
|
PvpTalentCategoryStorage = ReadDB2<PvpTalentCategoryRecord>("PvpTalentCategory.db2", HotfixStatements.SEL_PVP_TALENT_CATEGORY);
|
||||||
PvpTalentSlotUnlockStorage = ReadDB2<PvpTalentSlotUnlockRecord>("PvpTalentSlotUnlock.db2", HotfixStatements.SEL_PVP_TALENT_SLOT_UNLOCK);
|
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<BroadcastTextRecord> BroadcastTextStorage;
|
||||||
public static DB6Storage<BroadcastTextDurationRecord> BroadcastTextDurationStorage;
|
public static DB6Storage<BroadcastTextDurationRecord> BroadcastTextDurationStorage;
|
||||||
public static DB6Storage<Cfg_RegionsRecord> CfgRegionsStorage;
|
public static DB6Storage<Cfg_RegionsRecord> CfgRegionsStorage;
|
||||||
|
public static DB6Storage<ChallengeModeItemBonusOverrideRecord> ChallengeModeItemBonusOverrideStorage;
|
||||||
public static DB6Storage<CharTitlesRecord> CharTitlesStorage;
|
public static DB6Storage<CharTitlesRecord> CharTitlesStorage;
|
||||||
public static DB6Storage<CharacterLoadoutRecord> CharacterLoadoutStorage;
|
public static DB6Storage<CharacterLoadoutRecord> CharacterLoadoutStorage;
|
||||||
public static DB6Storage<CharacterLoadoutItemRecord> CharacterLoadoutItemStorage;
|
public static DB6Storage<CharacterLoadoutItemRecord> CharacterLoadoutItemStorage;
|
||||||
@@ -530,8 +539,10 @@ namespace Game.DataStorage
|
|||||||
public static DB6Storage<ChrSpecializationRecord> ChrSpecializationStorage;
|
public static DB6Storage<ChrSpecializationRecord> ChrSpecializationStorage;
|
||||||
public static DB6Storage<CinematicCameraRecord> CinematicCameraStorage;
|
public static DB6Storage<CinematicCameraRecord> CinematicCameraStorage;
|
||||||
public static DB6Storage<CinematicSequencesRecord> CinematicSequencesStorage;
|
public static DB6Storage<CinematicSequencesRecord> CinematicSequencesStorage;
|
||||||
|
public static DB6Storage<ConditionalContentTuningRecord> ConditionalContentTuningStorage;
|
||||||
public static DB6Storage<ContentTuningRecord> ContentTuningStorage;
|
public static DB6Storage<ContentTuningRecord> ContentTuningStorage;
|
||||||
public static DB6Storage<ContentTuningXExpectedRecord> ContentTuningXExpectedStorage;
|
public static DB6Storage<ContentTuningXExpectedRecord> ContentTuningXExpectedStorage;
|
||||||
|
public static DB6Storage<ContentTuningXLabelRecord> ContentTuningXLabelStorage;
|
||||||
public static DB6Storage<ConversationLineRecord> ConversationLineStorage;
|
public static DB6Storage<ConversationLineRecord> ConversationLineStorage;
|
||||||
public static DB6Storage<CorruptionEffectsRecord> CorruptionEffectsStorage;
|
public static DB6Storage<CorruptionEffectsRecord> CorruptionEffectsStorage;
|
||||||
public static DB6Storage<CreatureDisplayInfoRecord> CreatureDisplayInfoStorage;
|
public static DB6Storage<CreatureDisplayInfoRecord> CreatureDisplayInfoStorage;
|
||||||
@@ -597,8 +608,11 @@ namespace Game.DataStorage
|
|||||||
public static DB6Storage<ItemArmorTotalRecord> ItemArmorTotalStorage;
|
public static DB6Storage<ItemArmorTotalRecord> ItemArmorTotalStorage;
|
||||||
//public static DB6Storage<ItemBagFamilyRecord> ItemBagFamilyStorage;
|
//public static DB6Storage<ItemBagFamilyRecord> ItemBagFamilyStorage;
|
||||||
public static DB6Storage<ItemBonusRecord> ItemBonusStorage;
|
public static DB6Storage<ItemBonusRecord> ItemBonusStorage;
|
||||||
|
public static DB6Storage<ItemBonusListGroupEntryRecord> ItemBonusListGroupEntryStorage;
|
||||||
public static DB6Storage<ItemBonusListLevelDeltaRecord> ItemBonusListLevelDeltaStorage;
|
public static DB6Storage<ItemBonusListLevelDeltaRecord> ItemBonusListLevelDeltaStorage;
|
||||||
|
public static DB6Storage<ItemBonusTreeRecord> ItemBonusTreeStorage;
|
||||||
public static DB6Storage<ItemBonusTreeNodeRecord> ItemBonusTreeNodeStorage;
|
public static DB6Storage<ItemBonusTreeNodeRecord> ItemBonusTreeNodeStorage;
|
||||||
|
public static DB6Storage<ItemContextPickerEntryRecord> ItemContextPickerEntryStorage;
|
||||||
public static DB6Storage<ItemClassRecord> ItemClassStorage;
|
public static DB6Storage<ItemClassRecord> ItemClassStorage;
|
||||||
public static DB6Storage<ItemChildEquipmentRecord> ItemChildEquipmentStorage;
|
public static DB6Storage<ItemChildEquipmentRecord> ItemChildEquipmentStorage;
|
||||||
public static DB6Storage<ItemCurrencyCostRecord> ItemCurrencyCostStorage;
|
public static DB6Storage<ItemCurrencyCostRecord> ItemCurrencyCostStorage;
|
||||||
@@ -652,6 +666,7 @@ namespace Game.DataStorage
|
|||||||
public static DB6Storage<MountTypeXCapabilityRecord> MountTypeXCapabilityStorage;
|
public static DB6Storage<MountTypeXCapabilityRecord> MountTypeXCapabilityStorage;
|
||||||
public static DB6Storage<MountXDisplayRecord> MountXDisplayStorage;
|
public static DB6Storage<MountXDisplayRecord> MountXDisplayStorage;
|
||||||
public static DB6Storage<MovieRecord> MovieStorage;
|
public static DB6Storage<MovieRecord> MovieStorage;
|
||||||
|
public static DB6Storage<MythicPlusSeasonRecord> MythicPlusSeasonStorage;
|
||||||
public static DB6Storage<NameGenRecord> NameGenStorage;
|
public static DB6Storage<NameGenRecord> NameGenStorage;
|
||||||
public static DB6Storage<NamesProfanityRecord> NamesProfanityStorage;
|
public static DB6Storage<NamesProfanityRecord> NamesProfanityStorage;
|
||||||
public static DB6Storage<NamesReservedRecord> NamesReservedStorage;
|
public static DB6Storage<NamesReservedRecord> NamesReservedStorage;
|
||||||
@@ -667,6 +682,7 @@ namespace Game.DataStorage
|
|||||||
public static DB6Storage<PrestigeLevelInfoRecord> PrestigeLevelInfoStorage;
|
public static DB6Storage<PrestigeLevelInfoRecord> PrestigeLevelInfoStorage;
|
||||||
public static DB6Storage<PvpDifficultyRecord> PvpDifficultyStorage;
|
public static DB6Storage<PvpDifficultyRecord> PvpDifficultyStorage;
|
||||||
public static DB6Storage<PvpItemRecord> PvpItemStorage;
|
public static DB6Storage<PvpItemRecord> PvpItemStorage;
|
||||||
|
public static DB6Storage<PvpSeasonRecord> PvpSeasonStorage;
|
||||||
public static DB6Storage<PvpTalentRecord> PvpTalentStorage;
|
public static DB6Storage<PvpTalentRecord> PvpTalentStorage;
|
||||||
public static DB6Storage<PvpTalentCategoryRecord> PvpTalentCategoryStorage;
|
public static DB6Storage<PvpTalentCategoryRecord> PvpTalentCategoryStorage;
|
||||||
public static DB6Storage<PvpTalentSlotUnlockRecord> PvpTalentSlotUnlockStorage;
|
public static DB6Storage<PvpTalentSlotUnlockRecord> PvpTalentSlotUnlockStorage;
|
||||||
|
|||||||
@@ -90,10 +90,6 @@ namespace Game.DataStorage
|
|||||||
_azeriteTierUnlockLevels[key][azeriteTierUnlock.Tier] = azeriteTierUnlock.AzeriteLevel;
|
_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)
|
foreach (BattlemasterListRecord battlemaster in BattlemasterListStorage.Values)
|
||||||
{
|
{
|
||||||
if (battlemaster.MaxLevel < battlemaster.MinLevel)
|
if (battlemaster.MaxLevel < battlemaster.MinLevel)
|
||||||
@@ -230,12 +226,18 @@ namespace Game.DataStorage
|
|||||||
_chrSpecializationsByIndex[storageIndex][chrSpec.OrderIndex] = chrSpec;
|
_chrSpecializationsByIndex[storageIndex][chrSpec.OrderIndex] = chrSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (ConditionalContentTuningRecord conditionalContentTuning in ConditionalContentTuningStorage.Values)
|
||||||
|
_conditionalContentTuning.Add(conditionalContentTuning.ParentContentTuningID, conditionalContentTuning);
|
||||||
|
|
||||||
foreach (ContentTuningXExpectedRecord contentTuningXExpectedStat in ContentTuningXExpectedStorage.Values)
|
foreach (ContentTuningXExpectedRecord contentTuningXExpectedStat in ContentTuningXExpectedStorage.Values)
|
||||||
{
|
{
|
||||||
if (ExpectedStatModStorage.ContainsKey(contentTuningXExpectedStat.ExpectedStatModID))
|
if (ExpectedStatModStorage.ContainsKey(contentTuningXExpectedStat.ExpectedStatModID))
|
||||||
_expectedStatModsByContentTuning.Add(contentTuningXExpectedStat.ContentTuningID, contentTuningXExpectedStat);
|
_expectedStatModsByContentTuning.Add(contentTuningXExpectedStat.ContentTuningID, contentTuningXExpectedStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (ContentTuningXLabelRecord contentTuningXLabel in ContentTuningXLabelStorage.Values)
|
||||||
|
_contentTuningLabels.Add((contentTuningXLabel.ContentTuningID, contentTuningXLabel.LabelID));
|
||||||
|
|
||||||
foreach (CurrencyContainerRecord currencyContainer in CurrencyContainerStorage.Values)
|
foreach (CurrencyContainerRecord currencyContainer in CurrencyContainerStorage.Values)
|
||||||
_currencyContainers.Add(currencyContainer.CurrencyTypesID, currencyContainer);
|
_currencyContainers.Add(currencyContainer.CurrencyTypesID, currencyContainer);
|
||||||
|
|
||||||
@@ -283,15 +285,6 @@ namespace Game.DataStorage
|
|||||||
foreach (GlyphRequiredSpecRecord glyphRequiredSpec in GlyphRequiredSpecStorage.Values)
|
foreach (GlyphRequiredSpecRecord glyphRequiredSpec in GlyphRequiredSpecStorage.Values)
|
||||||
_glyphRequiredSpecs.Add(glyphRequiredSpec.GlyphPropertiesID, glyphRequiredSpec.ChrSpecializationID);
|
_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)
|
foreach (ItemChildEquipmentRecord itemChildEquipment in ItemChildEquipmentStorage.Values)
|
||||||
{
|
{
|
||||||
//ASSERT(_itemChildEquipment.find(itemChildEquipment.ParentItemID) == _itemChildEquipment.end(), "Item must have max 1 child item.");
|
//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)
|
foreach (ItemLimitCategoryConditionRecord condition in ItemLimitCategoryConditionStorage.Values)
|
||||||
_itemCategoryConditions.Add(condition.ParentItemLimitCategoryID, condition);
|
_itemCategoryConditions.Add(condition.ParentItemLimitCategoryID, condition);
|
||||||
|
|
||||||
foreach (ItemLevelSelectorQualityRecord itemLevelSelectorQuality in ItemLevelSelectorQualityStorage.Values)
|
|
||||||
_itemLevelQualitySelectorQualities.Add(itemLevelSelectorQuality.ParentILSQualitySetID, itemLevelSelectorQuality);
|
|
||||||
|
|
||||||
foreach (var appearanceMod in ItemModifiedAppearanceStorage.Values)
|
foreach (var appearanceMod in ItemModifiedAppearanceStorage.Values)
|
||||||
{
|
{
|
||||||
//ASSERT(appearanceMod.ItemID <= 0xFFFFFF);
|
//ASSERT(appearanceMod.ItemID <= 0xFFFFFF);
|
||||||
@@ -326,12 +316,6 @@ namespace Game.DataStorage
|
|||||||
foreach (var itemSpecOverride in ItemSpecOverrideStorage.Values)
|
foreach (var itemSpecOverride in ItemSpecOverrideStorage.Values)
|
||||||
_itemSpecOverrides.Add(itemSpecOverride.ItemID, itemSpecOverride);
|
_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)
|
foreach (JournalTierRecord journalTier in JournalTierStorage.Values)
|
||||||
_journalTiersByIndex.Add(journalTier);
|
_journalTiersByIndex.Add(journalTier);
|
||||||
|
|
||||||
@@ -1038,9 +1022,18 @@ namespace Game.DataStorage
|
|||||||
return GetChrSpecializationByIndex(class_, PlayerConst.InitialSpecializationIndex);
|
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)
|
if (contentTuning == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -1077,6 +1070,11 @@ namespace Game.DataStorage
|
|||||||
return levels;
|
return levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasContentTuningLabel(uint contentTuningId, int label)
|
||||||
|
{
|
||||||
|
return _contentTuningLabels.Contains((contentTuningId, label));
|
||||||
|
}
|
||||||
|
|
||||||
public string GetCreatureFamilyPetName(CreatureFamily petfamily, Locale locale)
|
public string GetCreatureFamilyPetName(CreatureFamily petfamily, Locale locale)
|
||||||
{
|
{
|
||||||
if (petfamily == CreatureFamily.None)
|
if (petfamily == CreatureFamily.None)
|
||||||
@@ -1261,20 +1259,26 @@ namespace Game.DataStorage
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
float ExpectedStatModReducer(float mod, ContentTuningXExpectedRecord contentTuningXExpected, ExpectedStatType stat)
|
float ExpectedStatModReducer(float mod, ContentTuningXExpectedRecord contentTuningXExpected, ExpectedStatType stat, int ActiveMilestoneSeason)
|
||||||
{
|
{
|
||||||
if (contentTuningXExpected == null)
|
if (contentTuningXExpected == null)
|
||||||
return mod;
|
return mod;
|
||||||
|
|
||||||
//if (contentTuningXExpected->MinMythicPlusSeasonID)
|
if (contentTuningXExpected.MinMythicPlusSeasonID != 0)
|
||||||
// if (MythicPlusSeasonEntry const* mythicPlusSeason = sMythicPlusSeasonStore.LookupEntry(contentTuningXExpected->MinMythicPlusSeasonID))
|
{
|
||||||
// if (MythicPlusSubSeason < mythicPlusSeason->SubSeason)
|
var mythicPlusSeason = MythicPlusSeasonStorage.LookupByKey(contentTuningXExpected.MinMythicPlusSeasonID);
|
||||||
// return mod;
|
if (mythicPlusSeason != null)
|
||||||
|
if (ActiveMilestoneSeason < mythicPlusSeason.MilestoneSeason)
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
//if (contentTuningXExpected->MaxMythicPlusSeasonID)
|
if (contentTuningXExpected.MaxMythicPlusSeasonID != 0)
|
||||||
// if (MythicPlusSeasonEntry const* mythicPlusSeason = sMythicPlusSeasonStore.LookupEntry(contentTuningXExpected->MaxMythicPlusSeasonID))
|
{
|
||||||
// if (MythicPlusSubSeason >= mythicPlusSeason->SubSeason)
|
var mythicPlusSeason = MythicPlusSeasonStorage.LookupByKey(contentTuningXExpected.MaxMythicPlusSeasonID);
|
||||||
// return mod;
|
if (mythicPlusSeason != null)
|
||||||
|
if (ActiveMilestoneSeason >= mythicPlusSeason.MilestoneSeason)
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
var expectedStatMod = ExpectedStatModStorage.LookupByKey(contentTuningXExpected.ExpectedStatModID);
|
var expectedStatMod = ExpectedStatModStorage.LookupByKey(contentTuningXExpected.ExpectedStatModID);
|
||||||
switch (stat)
|
switch (stat)
|
||||||
@@ -1300,11 +1304,9 @@ namespace Game.DataStorage
|
|||||||
}
|
}
|
||||||
|
|
||||||
return mod;
|
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));
|
var expectedStatRecord = _expectedStatsByLevel.LookupByKey(Tuple.Create(level, expansion));
|
||||||
if (expectedStatRecord == null)
|
if (expectedStatRecord == null)
|
||||||
@@ -1338,56 +1340,56 @@ namespace Game.DataStorage
|
|||||||
case ExpectedStatType.CreatureHealth:
|
case ExpectedStatType.CreatureHealth:
|
||||||
value = expectedStatRecord.CreatureHealth;
|
value = expectedStatRecord.CreatureHealth;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.CreatureHealthMod;
|
value *= classMod.CreatureHealthMod;
|
||||||
break;
|
break;
|
||||||
case ExpectedStatType.PlayerHealth:
|
case ExpectedStatType.PlayerHealth:
|
||||||
value = expectedStatRecord.PlayerHealth;
|
value = expectedStatRecord.PlayerHealth;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.PlayerHealthMod;
|
value *= classMod.PlayerHealthMod;
|
||||||
break;
|
break;
|
||||||
case ExpectedStatType.CreatureAutoAttackDps:
|
case ExpectedStatType.CreatureAutoAttackDps:
|
||||||
value = expectedStatRecord.CreatureAutoAttackDps;
|
value = expectedStatRecord.CreatureAutoAttackDps;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.CreatureAutoAttackDPSMod;
|
value *= classMod.CreatureAutoAttackDPSMod;
|
||||||
break;
|
break;
|
||||||
case ExpectedStatType.CreatureArmor:
|
case ExpectedStatType.CreatureArmor:
|
||||||
value = expectedStatRecord.CreatureArmor;
|
value = expectedStatRecord.CreatureArmor;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.CreatureArmorMod;
|
value *= classMod.CreatureArmorMod;
|
||||||
break;
|
break;
|
||||||
case ExpectedStatType.PlayerMana:
|
case ExpectedStatType.PlayerMana:
|
||||||
value = expectedStatRecord.PlayerMana;
|
value = expectedStatRecord.PlayerMana;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.PlayerManaMod;
|
value *= classMod.PlayerManaMod;
|
||||||
break;
|
break;
|
||||||
case ExpectedStatType.PlayerPrimaryStat:
|
case ExpectedStatType.PlayerPrimaryStat:
|
||||||
value = expectedStatRecord.PlayerPrimaryStat;
|
value = expectedStatRecord.PlayerPrimaryStat;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.PlayerPrimaryStatMod;
|
value *= classMod.PlayerPrimaryStatMod;
|
||||||
break;
|
break;
|
||||||
case ExpectedStatType.PlayerSecondaryStat:
|
case ExpectedStatType.PlayerSecondaryStat:
|
||||||
value = expectedStatRecord.PlayerSecondaryStat;
|
value = expectedStatRecord.PlayerSecondaryStat;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.PlayerSecondaryStatMod;
|
value *= classMod.PlayerSecondaryStatMod;
|
||||||
break;
|
break;
|
||||||
case ExpectedStatType.ArmorConstant:
|
case ExpectedStatType.ArmorConstant:
|
||||||
value = expectedStatRecord.ArmorConstant;
|
value = expectedStatRecord.ArmorConstant;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.ArmorConstantMod;
|
value *= classMod.ArmorConstantMod;
|
||||||
break;
|
break;
|
||||||
@@ -1396,7 +1398,7 @@ namespace Game.DataStorage
|
|||||||
case ExpectedStatType.CreatureSpellDamage:
|
case ExpectedStatType.CreatureSpellDamage:
|
||||||
value = expectedStatRecord.CreatureSpellDamage;
|
value = expectedStatRecord.CreatureSpellDamage;
|
||||||
if (!contentTuningMods.Empty())
|
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)
|
if (classMod != null)
|
||||||
value *= classMod.CreatureSpellDamageMod;
|
value *= classMod.CreatureSpellDamageMod;
|
||||||
break;
|
break;
|
||||||
@@ -1440,169 +1442,6 @@ namespace Game.DataStorage
|
|||||||
return _heirlooms.LookupByKey(itemId);
|
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)
|
public ItemChildEquipmentRecord GetItemChildEquipment(uint itemId)
|
||||||
{
|
{
|
||||||
return _itemChildEquipment.LookupByKey(itemId);
|
return _itemChildEquipment.LookupByKey(itemId);
|
||||||
@@ -2383,7 +2222,6 @@ namespace Game.DataStorage
|
|||||||
AzeriteItemMilestonePowerRecord[] _azeriteItemMilestonePowerByEssenceSlot = new AzeriteItemMilestonePowerRecord[SharedConst.MaxAzeriteEssenceSlot];
|
AzeriteItemMilestonePowerRecord[] _azeriteItemMilestonePowerByEssenceSlot = new AzeriteItemMilestonePowerRecord[SharedConst.MaxAzeriteEssenceSlot];
|
||||||
MultiMap<uint, AzeritePowerSetMemberRecord> _azeritePowers = new();
|
MultiMap<uint, AzeritePowerSetMemberRecord> _azeritePowers = new();
|
||||||
Dictionary<(uint azeriteUnlockSetId, ItemContext itemContext), byte[]> _azeriteTierUnlockLevels = 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();
|
Dictionary<(int broadcastTextId, CascLocaleBit cascLocaleBit), int> _broadcastTextDurations = new();
|
||||||
ChrClassUIDisplayRecord[] _uiDisplayByClass = new ChrClassUIDisplayRecord[(int)Class.Max];
|
ChrClassUIDisplayRecord[] _uiDisplayByClass = new ChrClassUIDisplayRecord[(int)Class.Max];
|
||||||
uint[][] _powersByClass = new uint[(int)Class.Max][];
|
uint[][] _powersByClass = new uint[(int)Class.Max][];
|
||||||
@@ -2393,6 +2231,8 @@ namespace Game.DataStorage
|
|||||||
MultiMap<Tuple<byte, byte>, ChrCustomizationOptionRecord> _chrCustomizationOptionsByRaceAndGender = new();
|
MultiMap<Tuple<byte, byte>, ChrCustomizationOptionRecord> _chrCustomizationOptionsByRaceAndGender = new();
|
||||||
Dictionary<uint, MultiMap<uint, uint>> _chrCustomizationRequiredChoices = new();
|
Dictionary<uint, MultiMap<uint, uint>> _chrCustomizationRequiredChoices = new();
|
||||||
ChrSpecializationRecord[][] _chrSpecializationsByIndex = new ChrSpecializationRecord[(int)Class.Max + 1][];
|
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, CurrencyContainerRecord> _currencyContainers = new();
|
||||||
MultiMap<uint, CurvePointRecord> _curvePoints = new();
|
MultiMap<uint, CurvePointRecord> _curvePoints = new();
|
||||||
Dictionary<Tuple<uint, byte, byte, byte>, EmotesTextSoundRecord> _emoteTextSounds = new();
|
Dictionary<Tuple<uint, byte, byte, byte>, EmotesTextSoundRecord> _emoteTextSounds = new();
|
||||||
@@ -2403,16 +2243,11 @@ namespace Game.DataStorage
|
|||||||
Dictionary<uint, HeirloomRecord> _heirlooms = new();
|
Dictionary<uint, HeirloomRecord> _heirlooms = new();
|
||||||
MultiMap<uint, uint> _glyphBindableSpells = new();
|
MultiMap<uint, uint> _glyphBindableSpells = new();
|
||||||
MultiMap<uint, uint> _glyphRequiredSpecs = 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();
|
Dictionary<uint, ItemChildEquipmentRecord> _itemChildEquipment = new();
|
||||||
ItemClassRecord[] _itemClassByOldEnum = new ItemClassRecord[20];
|
ItemClassRecord[] _itemClassByOldEnum = new ItemClassRecord[20];
|
||||||
List<uint> _itemsWithCurrencyCost = new();
|
List<uint> _itemsWithCurrencyCost = new();
|
||||||
MultiMap<uint, ItemLimitCategoryConditionRecord> _itemCategoryConditions = new();
|
MultiMap<uint, ItemLimitCategoryConditionRecord> _itemCategoryConditions = new();
|
||||||
MultiMap<uint, ItemLevelSelectorQualityRecord> _itemLevelQualitySelectorQualities = new();
|
|
||||||
Dictionary<uint, ItemModifiedAppearanceRecord> _itemModifiedAppearancesByItem = new();
|
Dictionary<uint, ItemModifiedAppearanceRecord> _itemModifiedAppearancesByItem = new();
|
||||||
MultiMap<uint, uint> _itemToBonusTree = new();
|
|
||||||
MultiMap<uint, ItemSetSpellRecord> _itemSetSpells = new();
|
MultiMap<uint, ItemSetSpellRecord> _itemSetSpells = new();
|
||||||
MultiMap<uint, ItemSpecOverrideRecord> _itemSpecOverrides = new();
|
MultiMap<uint, ItemSpecOverrideRecord> _itemSpecOverrides = new();
|
||||||
List<JournalTierRecord> _journalTiersByIndex = new();
|
List<JournalTierRecord> _journalTiersByIndex = new();
|
||||||
|
|||||||
@@ -16,6 +16,18 @@ namespace Game.DataStorage
|
|||||||
public uint ChallengeOrigin;
|
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 sealed class CharTitlesRecord
|
||||||
{
|
{
|
||||||
public uint Id;
|
public uint Id;
|
||||||
@@ -317,6 +329,15 @@ namespace Game.DataStorage
|
|||||||
public ushort[] Camera = new ushort[8];
|
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 sealed class ContentTuningRecord
|
||||||
{
|
{
|
||||||
public uint Id;
|
public uint Id;
|
||||||
@@ -357,6 +378,13 @@ namespace Game.DataStorage
|
|||||||
public uint ContentTuningID;
|
public uint ContentTuningID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class ContentTuningXLabelRecord
|
||||||
|
{
|
||||||
|
public uint Id;
|
||||||
|
public int LabelID;
|
||||||
|
public uint ContentTuningID;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class ConversationLineRecord
|
public sealed class ConversationLineRecord
|
||||||
{
|
{
|
||||||
public uint Id;
|
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.
|
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
using Framework.Constants;
|
using Framework.Constants;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Game.DataStorage
|
namespace Game.DataStorage
|
||||||
{
|
{
|
||||||
@@ -99,12 +100,14 @@ namespace Game.DataStorage
|
|||||||
public sealed class ItemBonusListGroupEntryRecord
|
public sealed class ItemBonusListGroupEntryRecord
|
||||||
{
|
{
|
||||||
public uint Id;
|
public uint Id;
|
||||||
public uint ItemBonusListGroupID;
|
public int ItemBonusListGroupID;
|
||||||
public int ItemBonusListID;
|
public int ItemBonusListID;
|
||||||
public int ItemLevelSelectorID;
|
public int ItemLevelSelectorID;
|
||||||
public int OrderIndex;
|
public int SequenceValue;
|
||||||
public int ItemExtendedCostID;
|
public int ItemExtendedCostID;
|
||||||
public int PlayerConditionID;
|
public int PlayerConditionID;
|
||||||
|
public int Flags;
|
||||||
|
public int ItemLogicalCostGroupID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ItemBonusListLevelDeltaRecord
|
public sealed class ItemBonusListLevelDeltaRecord
|
||||||
@@ -120,6 +123,13 @@ namespace Game.DataStorage
|
|||||||
public int ItemID;
|
public int ItemID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class ItemBonusTreeRecord
|
||||||
|
{
|
||||||
|
public uint Id;
|
||||||
|
public int Flags;
|
||||||
|
public int InventoryTypeSlotMask;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class ItemBonusTreeNodeRecord
|
public sealed class ItemBonusTreeNodeRecord
|
||||||
{
|
{
|
||||||
public uint Id;
|
public uint Id;
|
||||||
@@ -129,8 +139,8 @@ namespace Game.DataStorage
|
|||||||
public ushort ChildItemLevelSelectorID;
|
public ushort ChildItemLevelSelectorID;
|
||||||
public uint ChildItemBonusListGroupID;
|
public uint ChildItemBonusListGroupID;
|
||||||
public uint IblGroupPointsModSetID;
|
public uint IblGroupPointsModSetID;
|
||||||
public int Unknown1010_1;
|
public int MinMythicPlusLevel;
|
||||||
public int Unknown1010_2;
|
public int MaxMythicPlusLevel;
|
||||||
public uint ParentItemBonusTreeID;
|
public uint ParentItemBonusTreeID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,11 +161,24 @@ namespace Game.DataStorage
|
|||||||
public byte Flags;
|
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 sealed class ItemCurrencyCostRecord
|
||||||
{
|
{
|
||||||
public uint Id;
|
public uint Id;
|
||||||
public uint ItemID;
|
public uint ItemID;
|
||||||
}
|
}
|
||||||
|
|
||||||
// common struct for:
|
// common struct for:
|
||||||
// ItemDamageAmmo.dbc
|
// ItemDamageAmmo.dbc
|
||||||
// ItemDamageOneHand.dbc
|
// ItemDamageOneHand.dbc
|
||||||
@@ -220,12 +243,16 @@ namespace Game.DataStorage
|
|||||||
public ushort AzeriteUnlockMappingSet;
|
public ushort AzeriteUnlockMappingSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ItemLevelSelectorQualityRecord
|
public sealed class ItemLevelSelectorQualityRecord : IEquatable<ItemLevelSelectorQualityRecord>, IEquatable<ItemQuality>
|
||||||
{
|
{
|
||||||
public uint Id;
|
public uint Id;
|
||||||
public uint QualityItemBonusListID;
|
public uint QualityItemBonusListID;
|
||||||
public sbyte Quality;
|
public sbyte Quality;
|
||||||
public uint ParentILSQualitySetID;
|
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
|
public sealed class ItemLevelSelectorQualitySetRecord
|
||||||
|
|||||||
@@ -229,4 +229,12 @@ namespace Game.DataStorage
|
|||||||
public uint SubtitleFileDataID;
|
public uint SubtitleFileDataID;
|
||||||
public int SubtitleFileFormat;
|
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 byte ItemLevelDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class PvpSeasonRecord
|
||||||
|
{
|
||||||
|
public uint Id;
|
||||||
|
public int MilestoneSeason;
|
||||||
|
public int AllianceAchievementID;
|
||||||
|
public int HordeAchievementID;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class PvpTalentRecord
|
public sealed class PvpTalentRecord
|
||||||
{
|
{
|
||||||
public string Description;
|
public string Description;
|
||||||
|
|||||||
@@ -2715,7 +2715,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||||
float baseHealth = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass);
|
float baseHealth = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass, 0);
|
||||||
|
|
||||||
return (ulong)Math.Max(baseHealth * creatureDifficulty.HealthModifier, 1.0f);
|
return (ulong)Math.Max(baseHealth * creatureDifficulty.HealthModifier, 1.0f);
|
||||||
}
|
}
|
||||||
@@ -2736,7 +2736,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||||
return Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureAutoAttackDps, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass);
|
return Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureAutoAttackDps, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float GetDamageMultiplierForTarget(WorldObject target)
|
public override float GetDamageMultiplierForTarget(WorldObject target)
|
||||||
@@ -2753,7 +2753,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||||
float baseArmor = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureArmor, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass);
|
float baseArmor = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureArmor, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass, 0);
|
||||||
return baseArmor * creatureDifficulty.ArmorModifier;
|
return baseArmor * creatureDifficulty.ArmorModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -969,10 +969,11 @@ namespace Game.Entities
|
|||||||
Loot fishLoot = new(GetMap(), GetGUID(), LootType.Fishing, null);
|
Loot fishLoot = new(GetMap(), GetGUID(), LootType.Fishing, null);
|
||||||
|
|
||||||
uint areaId = GetAreaId();
|
uint areaId = GetAreaId();
|
||||||
|
ItemContext itemContext = ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), lootOwner);
|
||||||
AreaTableRecord areaEntry;
|
AreaTableRecord areaEntry;
|
||||||
while ((areaEntry = CliDB.AreaTableStorage.LookupByKey(areaId)) != null)
|
while ((areaEntry = CliDB.AreaTableStorage.LookupByKey(areaId)) != null)
|
||||||
{
|
{
|
||||||
fishLoot.FillLoot(areaId, LootStorage.Fishing, lootOwner, true, true);
|
fishLoot.FillLoot(areaId, LootStorage.Fishing, lootOwner, true, true, LootModes.Default, itemContext);
|
||||||
if (!fishLoot.IsLooted())
|
if (!fishLoot.IsLooted())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -980,7 +981,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fishLoot.IsLooted())
|
if (fishLoot.IsLooted())
|
||||||
fishLoot.FillLoot(defaultzone, LootStorage.Fishing, lootOwner, true, true);
|
fishLoot.FillLoot(defaultzone, LootStorage.Fishing, lootOwner, true, true, LootModes.Default, itemContext);
|
||||||
|
|
||||||
return fishLoot;
|
return fishLoot;
|
||||||
}
|
}
|
||||||
@@ -992,10 +993,11 @@ namespace Game.Entities
|
|||||||
Loot fishLoot = new(GetMap(), GetGUID(), LootType.FishingJunk, null);
|
Loot fishLoot = new(GetMap(), GetGUID(), LootType.FishingJunk, null);
|
||||||
|
|
||||||
uint areaId = GetAreaId();
|
uint areaId = GetAreaId();
|
||||||
|
ItemContext itemContext = ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), lootOwner);
|
||||||
AreaTableRecord areaEntry;
|
AreaTableRecord areaEntry;
|
||||||
while ((areaEntry = CliDB.AreaTableStorage.LookupByKey(areaId)) != null)
|
while ((areaEntry = CliDB.AreaTableStorage.LookupByKey(areaId)) != null)
|
||||||
{
|
{
|
||||||
fishLoot.FillLoot(areaId, LootStorage.Fishing, lootOwner, true, true, LootModes.JunkFish);
|
fishLoot.FillLoot(areaId, LootStorage.Fishing, lootOwner, true, true, LootModes.JunkFish, itemContext);
|
||||||
if (!fishLoot.IsLooted())
|
if (!fishLoot.IsLooted())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1003,7 +1005,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fishLoot.IsLooted())
|
if (fishLoot.IsLooted())
|
||||||
fishLoot.FillLoot(defaultzone, LootStorage.Fishing, lootOwner, true, true, LootModes.JunkFish);
|
fishLoot.FillLoot(defaultzone, LootStorage.Fishing, lootOwner, true, true, LootModes.JunkFish, itemContext);
|
||||||
|
|
||||||
return fishLoot;
|
return fishLoot;
|
||||||
}
|
}
|
||||||
@@ -1692,7 +1694,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
loot = new Loot(GetMap(), GetGUID(), LootType.Chest, groupRules ? group : null);
|
loot = new Loot(GetMap(), GetGUID(), LootType.Chest, groupRules ? group : null);
|
||||||
loot.SetDungeonEncounterId(info.Chest.DungeonEncounter);
|
loot.SetDungeonEncounterId(info.Chest.DungeonEncounter);
|
||||||
loot.FillLoot(info.GetLootId(), LootStorage.Gameobject, player, !groupRules, false, GetLootMode(), GetMap().GetDifficultyLootItemContext());
|
loot.FillLoot(info.GetLootId(), LootStorage.Gameobject, player, !groupRules, false, GetLootMode(), ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), player));
|
||||||
|
|
||||||
if (GetLootMode() > 0)
|
if (GetLootMode() > 0)
|
||||||
{
|
{
|
||||||
@@ -1731,7 +1733,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
m_personalLoot = LootManager.GenerateDungeonEncounterPersonalLoot(info.Chest.DungeonEncounter, info.Chest.chestPersonalLoot,
|
m_personalLoot = LootManager.GenerateDungeonEncounterPersonalLoot(info.Chest.DungeonEncounter, info.Chest.chestPersonalLoot,
|
||||||
LootStorage.Gameobject, LootType.Chest, this, addon != null ? addon.Mingold : 0, addon != null ? addon.Maxgold : 0,
|
LootStorage.Gameobject, LootType.Chest, this, addon != null ? addon.Mingold : 0, addon != null ? addon.Maxgold : 0,
|
||||||
(ushort)GetLootMode(), GetMap().GetDifficultyLootItemContext(), tappers);
|
(ushort)GetLootMode(), GetMap().GetMapDifficulty(), tappers);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1739,7 +1741,7 @@ namespace Game.Entities
|
|||||||
m_personalLoot[player.GetGUID()] = loot;
|
m_personalLoot[player.GetGUID()] = loot;
|
||||||
|
|
||||||
loot.SetDungeonEncounterId(info.Chest.DungeonEncounter);
|
loot.SetDungeonEncounterId(info.Chest.DungeonEncounter);
|
||||||
loot.FillLoot(info.Chest.chestPersonalLoot, LootStorage.Gameobject, player, true, false, GetLootMode(), GetMap().GetDifficultyLootItemContext());
|
loot.FillLoot(info.Chest.chestPersonalLoot, LootStorage.Gameobject, player, true, false, GetLootMode(), ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), player));
|
||||||
|
|
||||||
if (GetLootMode() > 0 && addon != null)
|
if (GetLootMode() > 0 && addon != null)
|
||||||
loot.GenerateMoneyLoot(addon.Mingold, addon.Maxgold);
|
loot.GenerateMoneyLoot(addon.Mingold, addon.Maxgold);
|
||||||
@@ -1752,7 +1754,7 @@ namespace Game.Entities
|
|||||||
if (info.Chest.chestPushLoot != 0)
|
if (info.Chest.chestPushLoot != 0)
|
||||||
{
|
{
|
||||||
Loot pushLoot = new(GetMap(), GetGUID(), LootType.Chest, null);
|
Loot pushLoot = new(GetMap(), GetGUID(), LootType.Chest, null);
|
||||||
pushLoot.FillLoot(info.Chest.chestPushLoot, LootStorage.Gameobject, player, true, false, GetLootMode(), GetMap().GetDifficultyLootItemContext());
|
pushLoot.FillLoot(info.Chest.chestPushLoot, LootStorage.Gameobject, player, true, false, GetLootMode(), ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), player));
|
||||||
pushLoot.AutoStore(player, ItemConst.NullBag, ItemConst.NullSlot);
|
pushLoot.AutoStore(player, ItemConst.NullBag, ItemConst.NullSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2268,7 +2270,7 @@ namespace Game.Entities
|
|||||||
Player player = user.ToPlayer();
|
Player player = user.ToPlayer();
|
||||||
|
|
||||||
Loot loot = new Loot(GetMap(), GetGUID(), LootType.Fishinghole, null);
|
Loot loot = new Loot(GetMap(), GetGUID(), LootType.Fishinghole, null);
|
||||||
loot.FillLoot(GetGoInfo().GetLootId(), LootStorage.Gameobject, player, true);
|
loot.FillLoot(GetGoInfo().GetLootId(), LootStorage.Gameobject, player, true, false, LootModes.Default, ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), player));
|
||||||
m_personalLoot[player.GetGUID()] = loot;
|
m_personalLoot[player.GetGUID()] = loot;
|
||||||
|
|
||||||
player.SendLoot(loot);
|
player.SendLoot(loot);
|
||||||
@@ -2452,7 +2454,7 @@ namespace Game.Entities
|
|||||||
Loot newLoot = new(GetMap(), GetGUID(), LootType.Chest, null);
|
Loot newLoot = new(GetMap(), GetGUID(), LootType.Chest, null);
|
||||||
m_personalLoot[player.GetGUID()] = newLoot;
|
m_personalLoot[player.GetGUID()] = newLoot;
|
||||||
|
|
||||||
newLoot.FillLoot(info.GatheringNode.chestLoot, LootStorage.Gameobject, player, true, false, GetLootMode(), GetMap().GetDifficultyLootItemContext());
|
newLoot.FillLoot(info.GatheringNode.chestLoot, LootStorage.Gameobject, player, true, false, GetLootMode(), ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), player));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.GatheringNode.triggeredEvent != 0)
|
if (info.GatheringNode.triggeredEvent != 0)
|
||||||
|
|||||||
@@ -1086,26 +1086,19 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
case ItemEnchantmentType.BonusListID:
|
case ItemEnchantmentType.BonusListID:
|
||||||
{
|
{
|
||||||
var bonusesEffect = Global.DB2Mgr.GetItemBonusList(gemEnchant.EffectArg[i]);
|
foreach (var itemBonus in ItemBonusMgr.GetItemBonuses(gemEnchant.EffectArg[i]))
|
||||||
if (bonusesEffect != null)
|
if (itemBonus.BonusType == ItemBonusType.ItemLevel)
|
||||||
{
|
_bonusData.GemItemLevelBonus[slot] += (uint)itemBonus.Value[0];
|
||||||
foreach (ItemBonusRecord itemBonus in bonusesEffect)
|
|
||||||
if (itemBonus.BonusType == ItemBonusType.ItemLevel)
|
|
||||||
|
|
||||||
_bonusData.GemItemLevelBonus[slot] += (uint)itemBonus.Value[0];
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ItemEnchantmentType.BonusListCurve:
|
case ItemEnchantmentType.BonusListCurve:
|
||||||
{
|
{
|
||||||
uint artifactrBonusListId = Global.DB2Mgr.GetItemBonusListForItemLevelDelta((short)Global.DB2Mgr.GetCurveValueAt((uint)Curves.ArtifactRelicItemLevelBonus, gemBaseItemLevel + gemBonus.ItemLevelBonus));
|
uint bonusListId = ItemBonusMgr.GetItemBonusListForItemLevelDelta((short)Global.DB2Mgr.GetCurveValueAt((uint)Curves.ArtifactRelicItemLevelBonus, gemBaseItemLevel + gemBonus.ItemLevelBonus));
|
||||||
if (artifactrBonusListId != 0)
|
if (bonusListId != 0)
|
||||||
{
|
{
|
||||||
var bonusesEffect = Global.DB2Mgr.GetItemBonusList(artifactrBonusListId);
|
foreach (var itemBonus in ItemBonusMgr.GetItemBonuses(bonusListId))
|
||||||
if (bonusesEffect != null)
|
if (itemBonus.BonusType == ItemBonusType.ItemLevel)
|
||||||
foreach (ItemBonusRecord itemBonus in bonusesEffect)
|
_bonusData.GemItemLevelBonus[slot] += (uint)itemBonus.Value[0];
|
||||||
if (itemBonus.BonusType == ItemBonusType.ItemLevel)
|
|
||||||
_bonusData.GemItemLevelBonus[slot] += (uint)itemBonus.Value[0];
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1195,22 +1188,25 @@ namespace Game.Entities
|
|||||||
owner.SendPacket(itemTimeUpdate);
|
owner.SendPacket(itemTimeUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Item CreateItem(uint item, uint count, ItemContext context, Player player = null)
|
public static Item CreateItem(uint itemEntry, uint count, ItemContext context, Player player = null, bool addDefaultBonuses = true)
|
||||||
{
|
{
|
||||||
if (count < 1)
|
if (count < 1)
|
||||||
return null; //don't create item at zero count
|
return null; //don't create item at zero count
|
||||||
|
|
||||||
var pProto = Global.ObjectMgr.GetItemTemplate(item);
|
var pProto = Global.ObjectMgr.GetItemTemplate(itemEntry);
|
||||||
if (pProto != null)
|
if (pProto != null)
|
||||||
{
|
{
|
||||||
if (count > pProto.GetMaxStackSize())
|
if (count > pProto.GetMaxStackSize())
|
||||||
count = pProto.GetMaxStackSize();
|
count = pProto.GetMaxStackSize();
|
||||||
|
|
||||||
Item pItem = Bag.NewItemOrBag(pProto);
|
Item item = Bag.NewItemOrBag(pProto);
|
||||||
if (pItem.Create(Global.ObjectMgr.GetGenerator(HighGuid.Item).Generate(), item, context, player))
|
if (item.Create(Global.ObjectMgr.GetGenerator(HighGuid.Item).Generate(), itemEntry, context, player))
|
||||||
{
|
{
|
||||||
pItem.SetCount(count);
|
item.SetCount(count);
|
||||||
return pItem;
|
if (addDefaultBonuses)
|
||||||
|
item.SetBonuses(ItemBonusMgr.GetBonusListsForItem(itemEntry, new(context)));
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1219,7 +1215,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public Item CloneItem(uint count, Player player = null)
|
public Item CloneItem(uint count, Player player = null)
|
||||||
{
|
{
|
||||||
Item newItem = CreateItem(GetEntry(), count, GetContext(), player);
|
Item newItem = CreateItem(GetEntry(), count, GetContext(), player, false);
|
||||||
if (newItem == null)
|
if (newItem == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -1227,6 +1223,7 @@ namespace Game.Entities
|
|||||||
newItem.SetGiftCreator(GetGiftCreator());
|
newItem.SetGiftCreator(GetGiftCreator());
|
||||||
newItem.ReplaceAllItemFlags((ItemFieldFlags)(m_itemData.DynamicFlags & ~(uint)(ItemFieldFlags.Refundable | ItemFieldFlags.BopTradeable)));
|
newItem.ReplaceAllItemFlags((ItemFieldFlags)(m_itemData.DynamicFlags & ~(uint)(ItemFieldFlags.Refundable | ItemFieldFlags.BopTradeable)));
|
||||||
newItem.SetExpiration(m_itemData.Expiration);
|
newItem.SetExpiration(m_itemData.Expiration);
|
||||||
|
newItem.SetBonuses(m_itemData.ItemBonusKey.GetValue().BonusListIDs);
|
||||||
// player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
|
// player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
|
||||||
if (player != null)
|
if (player != null)
|
||||||
newItem.SetItemRandomBonusList(m_randomBonusListId);
|
newItem.SetItemRandomBonusList(m_randomBonusListId);
|
||||||
@@ -2072,26 +2069,21 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<uint> GetBonusListIDs() { return m_itemData.ItemBonusKey.GetValue().BonusListIDs; }
|
public List<uint> GetBonusListIDs() { return m_itemData.ItemBonusKey.GetValue().BonusListIDs; }
|
||||||
|
|
||||||
public void AddBonuses(uint bonusListID)
|
public void AddBonuses(uint bonusListID)
|
||||||
{
|
{
|
||||||
var bonusListIDs = GetBonusListIDs();
|
var bonusListIDs = GetBonusListIDs();
|
||||||
if (bonusListIDs.Contains(bonusListID))
|
if (bonusListIDs.Contains(bonusListID))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var bonuses = Global.DB2Mgr.GetItemBonusList(bonusListID);
|
ItemBonusKey itemBonusKey = new();
|
||||||
if (bonuses != null)
|
itemBonusKey.ItemID = GetEntry();
|
||||||
{
|
itemBonusKey.BonusListIDs = GetBonusListIDs();
|
||||||
ItemBonusKey itemBonusKey = new();
|
itemBonusKey.BonusListIDs.Add(bonusListID);
|
||||||
itemBonusKey.ItemID = GetEntry();
|
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemBonusKey), itemBonusKey);
|
||||||
itemBonusKey.BonusListIDs = GetBonusListIDs();
|
foreach (var bonus in ItemBonusMgr.GetItemBonuses(bonusListID))
|
||||||
itemBonusKey.BonusListIDs.Add(bonusListID);
|
_bonusData.AddBonus(bonus.BonusType, bonus.Value);
|
||||||
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemBonusKey), itemBonusKey);
|
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemAppearanceModID), (byte)_bonusData.AppearanceModID);
|
||||||
foreach (ItemBonusRecord bonus in bonuses)
|
|
||||||
_bonusData.AddBonus(bonus.BonusType, bonus.Value);
|
|
||||||
|
|
||||||
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemAppearanceModID), (byte)_bonusData.AppearanceModID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBonuses(List<uint> bonusListIDs)
|
public void SetBonuses(List<uint> bonusListIDs)
|
||||||
@@ -2906,10 +2898,8 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void AddBonusList(uint bonusListId)
|
public void AddBonusList(uint bonusListId)
|
||||||
{
|
{
|
||||||
var bonuses = Global.DB2Mgr.GetItemBonusList(bonusListId);
|
foreach (var bonus in ItemBonusMgr.GetItemBonuses(bonusListId))
|
||||||
if (bonuses != null)
|
AddBonus(bonus.BonusType, bonus.Value);
|
||||||
foreach (ItemBonusRecord bonus in bonuses)
|
|
||||||
AddBonus(bonus.BonusType, bonus.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddBonus(ItemBonusType type, int[] values)
|
public void AddBonus(ItemBonusType type, int[] values)
|
||||||
|
|||||||
@@ -0,0 +1,506 @@
|
|||||||
|
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||||
|
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using Framework.Constants;
|
||||||
|
using Game.DataStorage;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Game.Entities
|
||||||
|
{
|
||||||
|
class ItemBonusMgr
|
||||||
|
{
|
||||||
|
static MultiMap<uint /*azeriteUnlockMappingSetId*/, AzeriteUnlockMappingRecord> _azeriteUnlockMappings = new();
|
||||||
|
static MultiMap<uint /*itemBonusTreeId*/, ChallengeModeItemBonusOverrideRecord> _challengeModeItemBonusOverrides = new();
|
||||||
|
static MultiMap<uint /*itemBonusListId*/, ItemBonusRecord> _itemBonusLists = new();
|
||||||
|
static MultiMap<int, ItemBonusListGroupEntryRecord> _itemBonusListGroupEntries = new();
|
||||||
|
static Dictionary<short /*itemLevelDelta*/, uint /*itemBonusListId*/> _itemLevelDeltaToBonusListContainer = new();
|
||||||
|
static SortedMultiMap<uint /*itemLevelSelectorQualitySetId*/, ItemLevelSelectorQualityRecord> _itemLevelQualitySelectorQualities = new();
|
||||||
|
static MultiMap<uint /*itemBonusTreeId*/, ItemBonusTreeNodeRecord> _itemBonusTrees = new();
|
||||||
|
static MultiMap<uint /*itemId*/, uint /*itemBonusTreeId*/> _itemToBonusTree = new();
|
||||||
|
|
||||||
|
public static void Load()
|
||||||
|
{
|
||||||
|
foreach (var azeriteUnlockMapping in CliDB.AzeriteUnlockMappingStorage.Values)
|
||||||
|
_azeriteUnlockMappings.Add(azeriteUnlockMapping.AzeriteUnlockMappingSetID, azeriteUnlockMapping);
|
||||||
|
|
||||||
|
foreach (var challengeModeItemBonusOverride in CliDB.ChallengeModeItemBonusOverrideStorage.Values)
|
||||||
|
_challengeModeItemBonusOverrides.Add(challengeModeItemBonusOverride.SrcItemBonusTreeID, challengeModeItemBonusOverride);
|
||||||
|
|
||||||
|
foreach (var bonus in CliDB.ItemBonusStorage.Values)
|
||||||
|
_itemBonusLists.Add(bonus.ParentItemBonusListID, bonus);
|
||||||
|
|
||||||
|
foreach (var bonusListGroupEntry in CliDB.ItemBonusListGroupEntryStorage.Values)
|
||||||
|
_itemBonusListGroupEntries.Add(bonusListGroupEntry.ItemBonusListGroupID, bonusListGroupEntry);
|
||||||
|
|
||||||
|
foreach (var itemBonusListLevelDelta in CliDB.ItemBonusListLevelDeltaStorage.Values)
|
||||||
|
_itemLevelDeltaToBonusListContainer[itemBonusListLevelDelta.ItemLevelDelta] = itemBonusListLevelDelta.Id;
|
||||||
|
|
||||||
|
foreach (var itemLevelSelectorQuality in CliDB.ItemLevelSelectorQualityStorage.Values)
|
||||||
|
_itemLevelQualitySelectorQualities.Add(itemLevelSelectorQuality.ParentILSQualitySetID, itemLevelSelectorQuality);
|
||||||
|
|
||||||
|
foreach (var bonusTreeNode in CliDB.ItemBonusTreeNodeStorage.Values)
|
||||||
|
_itemBonusTrees.Add(bonusTreeNode.ParentItemBonusTreeID, bonusTreeNode);
|
||||||
|
|
||||||
|
foreach (var itemBonusTreeAssignment in CliDB.ItemXBonusTreeStorage.Values)
|
||||||
|
_itemToBonusTree.Add(itemBonusTreeAssignment.ItemID, itemBonusTreeAssignment.ItemBonusTreeID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemContext GetContextForPlayer(MapDifficultyRecord mapDifficulty, Player player)
|
||||||
|
{
|
||||||
|
ItemContext evalContext(ItemContext currentContext, ItemContext newContext)
|
||||||
|
{
|
||||||
|
if (newContext == ItemContext.None)
|
||||||
|
newContext = currentContext;
|
||||||
|
else if (newContext == ItemContext.ForceToNone)
|
||||||
|
newContext = ItemContext.None;
|
||||||
|
return newContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemContext context = ItemContext.None;
|
||||||
|
var difficulty = CliDB.DifficultyStorage.LookupByKey(mapDifficulty.DifficultyID);
|
||||||
|
if (difficulty != null)
|
||||||
|
context = evalContext(context, (ItemContext)difficulty.ItemContext);
|
||||||
|
|
||||||
|
context = evalContext(context, (ItemContext)mapDifficulty.ItemContext);
|
||||||
|
|
||||||
|
if (mapDifficulty.ItemContextPickerID != 0)
|
||||||
|
{
|
||||||
|
uint contentTuningId = Global.DB2Mgr.GetRedirectedContentTuningId((uint)mapDifficulty.ContentTuningID, player.m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||||
|
|
||||||
|
ItemContextPickerEntryRecord selectedPickerEntry = null;
|
||||||
|
foreach (var itemContextPickerEntry in CliDB.ItemContextPickerEntryStorage.Values)
|
||||||
|
{
|
||||||
|
if (itemContextPickerEntry.ItemContextPickerID != mapDifficulty.ItemContextPickerID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (itemContextPickerEntry.PVal <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool meetsPlayerCondition = false;
|
||||||
|
if (player)
|
||||||
|
{
|
||||||
|
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(itemContextPickerEntry.PlayerConditionID);
|
||||||
|
if (playerCondition != null)
|
||||||
|
meetsPlayerCondition = ConditionManager.IsPlayerMeetingCondition(player, playerCondition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((itemContextPickerEntry.Flags & 0x1) != 0)
|
||||||
|
meetsPlayerCondition = !meetsPlayerCondition;
|
||||||
|
|
||||||
|
if (!meetsPlayerCondition)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (itemContextPickerEntry.LabelID != 0 && !Global.DB2Mgr.HasContentTuningLabel(contentTuningId, itemContextPickerEntry.LabelID))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (selectedPickerEntry == null || selectedPickerEntry.OrderIndex < itemContextPickerEntry.OrderIndex)
|
||||||
|
selectedPickerEntry = itemContextPickerEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedPickerEntry != null)
|
||||||
|
context = evalContext(context, (ItemContext)selectedPickerEntry.ItemCreationContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ItemBonusRecord> GetItemBonuses(uint bonusListId)
|
||||||
|
{
|
||||||
|
return _itemBonusLists.LookupByKey(bonusListId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint GetItemBonusListForItemLevelDelta(short delta)
|
||||||
|
{
|
||||||
|
return _itemLevelDeltaToBonusListContainer.LookupByKey(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CanApplyBonusTreeToItem(ItemTemplate itemTemplate, uint itemBonusTreeId, ItemBonusGenerationParams generationParams)
|
||||||
|
{
|
||||||
|
var bonusTree = CliDB.ItemBonusTreeStorage.LookupByKey(itemBonusTreeId);
|
||||||
|
if (bonusTree != null)
|
||||||
|
{
|
||||||
|
if (bonusTree.InventoryTypeSlotMask != 0)
|
||||||
|
if ((1 << (int)itemTemplate.GetInventoryType() & bonusTree.InventoryTypeSlotMask) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((bonusTree.Flags & 0x8) != 0 && !itemTemplate.HasFlag(ItemFlags2.CasterWeapon))
|
||||||
|
return false;
|
||||||
|
if ((bonusTree.Flags & 0x10) != 0 && itemTemplate.HasFlag(ItemFlags2.CasterWeapon))
|
||||||
|
return false;
|
||||||
|
if ((bonusTree.Flags & 0x20) != 0 && !itemTemplate.HasFlag(ItemFlags4.CcTrinket))
|
||||||
|
return false;
|
||||||
|
if ((bonusTree.Flags & 0x40) != 0 && itemTemplate.HasFlag(ItemFlags4.CcTrinket))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((bonusTree.Flags & 0x4) != 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bonusTreeNodes = _itemBonusTrees.LookupByKey(itemBonusTreeId);
|
||||||
|
if (!bonusTreeNodes.Empty())
|
||||||
|
{
|
||||||
|
bool anyNodeMatched = false;
|
||||||
|
foreach (var bonusTreeNode in bonusTreeNodes)
|
||||||
|
{
|
||||||
|
if (bonusTreeNode.MinMythicPlusLevel > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ItemContext nodeContext = (ItemContext)bonusTreeNode.ItemContext;
|
||||||
|
if (nodeContext == ItemContext.None || nodeContext == generationParams.Context)
|
||||||
|
{
|
||||||
|
if (anyNodeMatched)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
anyNodeMatched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint GetBonusTreeIdOverride(uint itemBonusTreeId, ItemBonusGenerationParams generationParams)
|
||||||
|
{
|
||||||
|
// TODO: configure seasons globally
|
||||||
|
var mythicPlusSeason = CliDB.MythicPlusSeasonStorage.LookupByKey(0);
|
||||||
|
if (mythicPlusSeason != null)
|
||||||
|
{
|
||||||
|
int selectedLevel = -1;
|
||||||
|
int selectedMilestoneSeason = -1;
|
||||||
|
ChallengeModeItemBonusOverrideRecord selectedItemBonusOverride = null;
|
||||||
|
foreach (var itemBonusOverride in _challengeModeItemBonusOverrides.LookupByKey(itemBonusTreeId))
|
||||||
|
{
|
||||||
|
if (itemBonusOverride.Type != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (itemBonusOverride.Value > generationParams.MythicPlusKeystoneLevel.GetValueOrDefault(-1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (itemBonusOverride.MythicPlusSeasonID != 0)
|
||||||
|
{
|
||||||
|
var overrideSeason = CliDB.MythicPlusSeasonStorage.LookupByKey(itemBonusOverride.MythicPlusSeasonID);
|
||||||
|
if (overrideSeason == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mythicPlusSeason.MilestoneSeason < overrideSeason.MilestoneSeason)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (selectedMilestoneSeason > overrideSeason.MilestoneSeason)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (selectedMilestoneSeason == overrideSeason.MilestoneSeason)
|
||||||
|
if (selectedLevel > itemBonusOverride.Value)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
selectedMilestoneSeason = overrideSeason.MilestoneSeason;
|
||||||
|
}
|
||||||
|
else if (selectedLevel > itemBonusOverride.Value)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
selectedLevel = itemBonusOverride.Value;
|
||||||
|
selectedItemBonusOverride = itemBonusOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedItemBonusOverride != null && selectedItemBonusOverride.DstItemBonusTreeID != 0)
|
||||||
|
itemBonusTreeId = (uint)selectedItemBonusOverride.DstItemBonusTreeID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: configure seasons globally
|
||||||
|
var pvpSeason = CliDB.PvpSeasonStorage.LookupByKey(0);
|
||||||
|
if (pvpSeason != null)
|
||||||
|
{
|
||||||
|
int selectedLevel = -1;
|
||||||
|
int selectedMilestoneSeason = -1;
|
||||||
|
ChallengeModeItemBonusOverrideRecord selectedItemBonusOverride = null;
|
||||||
|
foreach (var itemBonusOverride in _challengeModeItemBonusOverrides.LookupByKey(itemBonusTreeId))
|
||||||
|
{
|
||||||
|
if (itemBonusOverride.Type != 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (itemBonusOverride.Value > generationParams.PvpTier.GetValueOrDefault(-1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (itemBonusOverride.PvPSeasonID != 0)
|
||||||
|
{
|
||||||
|
var overrideSeason = CliDB.PvpSeasonStorage.LookupByKey(itemBonusOverride.PvPSeasonID);
|
||||||
|
if (overrideSeason == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pvpSeason.MilestoneSeason < overrideSeason.MilestoneSeason)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (selectedMilestoneSeason > overrideSeason.MilestoneSeason)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (selectedMilestoneSeason == overrideSeason.MilestoneSeason)
|
||||||
|
if (selectedLevel > itemBonusOverride.Value)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
selectedMilestoneSeason = overrideSeason.MilestoneSeason;
|
||||||
|
}
|
||||||
|
else if (selectedLevel > itemBonusOverride.Value)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
selectedLevel = itemBonusOverride.Value;
|
||||||
|
selectedItemBonusOverride = itemBonusOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedItemBonusOverride != null && selectedItemBonusOverride.DstItemBonusTreeID != 0)
|
||||||
|
itemBonusTreeId = (uint)selectedItemBonusOverride.DstItemBonusTreeID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemBonusTreeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ApplyBonusTreeHelper(ItemTemplate itemTemplate, uint itemBonusTreeId, ItemBonusGenerationParams generationParams, int sequenceLevel, ref uint itemLevelSelectorId, List<uint> bonusListIDs)
|
||||||
|
{
|
||||||
|
uint originalItemBonusTreeId = itemBonusTreeId;
|
||||||
|
|
||||||
|
// override bonus tree with season specific values
|
||||||
|
itemBonusTreeId = GetBonusTreeIdOverride(itemBonusTreeId, generationParams);
|
||||||
|
|
||||||
|
if (!CanApplyBonusTreeToItem(itemTemplate, itemBonusTreeId, generationParams))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var treeList = _itemBonusTrees.LookupByKey(itemBonusTreeId);
|
||||||
|
if (treeList.Empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var bonusTreeNode in treeList)
|
||||||
|
{
|
||||||
|
ItemContext nodeContext = (ItemContext)bonusTreeNode.ItemContext;
|
||||||
|
ItemContext requiredContext = nodeContext != ItemContext.ForceToNone ? nodeContext : ItemContext.None;
|
||||||
|
if (nodeContext != ItemContext.None && generationParams.Context != requiredContext)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (generationParams.MythicPlusKeystoneLevel != 0)
|
||||||
|
{
|
||||||
|
if (bonusTreeNode.MinMythicPlusLevel != 0 && generationParams.MythicPlusKeystoneLevel < bonusTreeNode.MinMythicPlusLevel)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bonusTreeNode.MaxMythicPlusLevel != 0 && generationParams.MythicPlusKeystoneLevel > bonusTreeNode.MaxMythicPlusLevel)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bonusTreeNode.ChildItemBonusTreeID != 0)
|
||||||
|
ApplyBonusTreeHelper(itemTemplate, bonusTreeNode.ChildItemBonusTreeID, generationParams, sequenceLevel, ref itemLevelSelectorId, bonusListIDs);
|
||||||
|
else if (bonusTreeNode.ChildItemBonusListID != 0)
|
||||||
|
bonusListIDs.Add(bonusTreeNode.ChildItemBonusListID);
|
||||||
|
else if (bonusTreeNode.ChildItemLevelSelectorID != 0)
|
||||||
|
itemLevelSelectorId = bonusTreeNode.ChildItemLevelSelectorID;
|
||||||
|
else if (bonusTreeNode.ChildItemBonusListGroupID != 0)
|
||||||
|
{
|
||||||
|
int resolvedSequenceLevel = sequenceLevel;
|
||||||
|
switch (originalItemBonusTreeId)
|
||||||
|
{
|
||||||
|
case 4001:
|
||||||
|
resolvedSequenceLevel = 1;
|
||||||
|
break;
|
||||||
|
case 4079:
|
||||||
|
if (generationParams.MythicPlusKeystoneLevel != 0)
|
||||||
|
{
|
||||||
|
switch (bonusTreeNode.IblGroupPointsModSetID)
|
||||||
|
{
|
||||||
|
case 2909: // MythicPlus_End_of_Run levels 2-8
|
||||||
|
resolvedSequenceLevel = (int)Global.DB2Mgr.GetCurveValueAt(62951, generationParams.MythicPlusKeystoneLevel.Value);
|
||||||
|
break;
|
||||||
|
case 2910: // MythicPlus_End_of_Run levels 9-16
|
||||||
|
resolvedSequenceLevel = (int)Global.DB2Mgr.GetCurveValueAt(62952, generationParams.MythicPlusKeystoneLevel.Value);
|
||||||
|
break;
|
||||||
|
case 2911: // MythicPlus_End_of_Run levels 17-20
|
||||||
|
resolvedSequenceLevel = (int)Global.DB2Mgr.GetCurveValueAt(62954, generationParams.MythicPlusKeystoneLevel.Value);
|
||||||
|
break;
|
||||||
|
case 3007: // MythicPlus_Jackpot (weekly reward) levels 2-7
|
||||||
|
resolvedSequenceLevel = (int)Global.DB2Mgr.GetCurveValueAt(64388, generationParams.MythicPlusKeystoneLevel.Value);
|
||||||
|
break;
|
||||||
|
case 3008: // MythicPlus_Jackpot (weekly reward) levels 8-15
|
||||||
|
resolvedSequenceLevel = (int)Global.DB2Mgr.GetCurveValueAt(64389, generationParams.MythicPlusKeystoneLevel.Value);
|
||||||
|
break;
|
||||||
|
case 3009: // MythicPlus_Jackpot (weekly reward) levels 16-20
|
||||||
|
resolvedSequenceLevel = (int)Global.DB2Mgr.GetCurveValueAt(64395, generationParams.MythicPlusKeystoneLevel.Value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4125:
|
||||||
|
resolvedSequenceLevel = 2;
|
||||||
|
break;
|
||||||
|
case 4126:
|
||||||
|
resolvedSequenceLevel = 3;
|
||||||
|
break;
|
||||||
|
case 4127:
|
||||||
|
resolvedSequenceLevel = 4;
|
||||||
|
break;
|
||||||
|
case 4128:
|
||||||
|
switch (generationParams.Context)
|
||||||
|
{
|
||||||
|
case ItemContext.RaidNormal:
|
||||||
|
case ItemContext.RaidRaidFinder:
|
||||||
|
case ItemContext.RaidHeroic:
|
||||||
|
resolvedSequenceLevel = 2;
|
||||||
|
break;
|
||||||
|
case ItemContext.RaidMythic:
|
||||||
|
resolvedSequenceLevel = 6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4140:
|
||||||
|
switch (generationParams.Context)
|
||||||
|
{
|
||||||
|
case ItemContext.DungeonNormal:
|
||||||
|
resolvedSequenceLevel = 2;
|
||||||
|
break;
|
||||||
|
case ItemContext.DungeonHeroic:
|
||||||
|
resolvedSequenceLevel = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var bonusListGroupEntry in _itemBonusListGroupEntries.LookupByKey(bonusTreeNode.ChildItemBonusListGroupID))
|
||||||
|
{
|
||||||
|
if ((resolvedSequenceLevel > 0 || bonusListGroupEntry.SequenceValue <= 0) && resolvedSequenceLevel != bonusListGroupEntry.SequenceValue)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
itemLevelSelectorId = (uint)bonusListGroupEntry.ItemLevelSelectorID;
|
||||||
|
bonusListIDs.Add((uint)bonusListGroupEntry.ItemBonusListID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint GetAzeriteUnlockBonusList(ushort azeriteUnlockMappingSetId, ushort minItemLevel, InventoryType inventoryType)
|
||||||
|
{
|
||||||
|
AzeriteUnlockMappingRecord selectedAzeriteUnlockMapping = null;
|
||||||
|
foreach (var azeriteUnlockMapping in _azeriteUnlockMappings.LookupByKey(azeriteUnlockMappingSetId))
|
||||||
|
{
|
||||||
|
if (minItemLevel < azeriteUnlockMapping.ItemLevel)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (selectedAzeriteUnlockMapping != null && selectedAzeriteUnlockMapping.ItemLevel > azeriteUnlockMapping.ItemLevel)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
selectedAzeriteUnlockMapping = azeriteUnlockMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedAzeriteUnlockMapping != null)
|
||||||
|
{
|
||||||
|
switch (inventoryType)
|
||||||
|
{
|
||||||
|
case InventoryType.Head:
|
||||||
|
return selectedAzeriteUnlockMapping.ItemBonusListHead;
|
||||||
|
case InventoryType.Shoulders:
|
||||||
|
return selectedAzeriteUnlockMapping.ItemBonusListShoulders;
|
||||||
|
case InventoryType.Chest:
|
||||||
|
case InventoryType.Robe:
|
||||||
|
return selectedAzeriteUnlockMapping.ItemBonusListChest;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<uint> GetBonusListsForItem(uint itemId, ItemBonusGenerationParams generationParams)
|
||||||
|
{
|
||||||
|
List<uint> bonusListIDs = new();
|
||||||
|
|
||||||
|
ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(itemId);
|
||||||
|
if (itemTemplate == null)
|
||||||
|
return bonusListIDs;
|
||||||
|
|
||||||
|
uint itemLevelSelectorId = 0;
|
||||||
|
|
||||||
|
foreach (var itemBonusTreeId in _itemToBonusTree.LookupByKey(itemId))
|
||||||
|
ApplyBonusTreeHelper(itemTemplate, itemBonusTreeId, generationParams, 0, ref itemLevelSelectorId, bonusListIDs);
|
||||||
|
|
||||||
|
var selector = CliDB.ItemLevelSelectorStorage.LookupByKey(itemLevelSelectorId);
|
||||||
|
if (selector != null)
|
||||||
|
{
|
||||||
|
short delta = (short)(selector.MinItemLevel - itemTemplate.GetBaseItemLevel());
|
||||||
|
|
||||||
|
uint bonus = GetItemBonusListForItemLevelDelta(delta);
|
||||||
|
if (bonus != 0)
|
||||||
|
bonusListIDs.Add(bonus);
|
||||||
|
|
||||||
|
var selectorQualitySet = CliDB.ItemLevelSelectorQualitySetStorage.LookupByKey(selector.ItemLevelSelectorQualitySetID);
|
||||||
|
if (selectorQualitySet != null)
|
||||||
|
{
|
||||||
|
var itemSelectorQualities = _itemLevelQualitySelectorQualities.LookupByKey(selector.ItemLevelSelectorQualitySetID);
|
||||||
|
if (!itemSelectorQualities.Empty())
|
||||||
|
{
|
||||||
|
ItemQuality quality = ItemQuality.Uncommon;
|
||||||
|
if (selector.MinItemLevel >= selectorQualitySet.IlvlEpic)
|
||||||
|
quality = ItemQuality.Epic;
|
||||||
|
else if (selector.MinItemLevel >= selectorQualitySet.IlvlRare)
|
||||||
|
quality = ItemQuality.Rare;
|
||||||
|
|
||||||
|
var itemSelectorQuality = itemSelectorQualities.First(record => record.Quality < (sbyte)quality);
|
||||||
|
|
||||||
|
if (itemSelectorQuality != null)
|
||||||
|
bonusListIDs.Add(itemSelectorQuality.QualityItemBonusListID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint azeriteUnlockBonusListId = GetAzeriteUnlockBonusList(selector.AzeriteUnlockMappingSet, selector.MinItemLevel, itemTemplate.GetInventoryType());
|
||||||
|
if (azeriteUnlockBonusListId != 0)
|
||||||
|
bonusListIDs.Add(azeriteUnlockBonusListId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bonusListIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void VisitItemBonusTree(uint itemBonusTreeId, Action<ItemBonusTreeNodeRecord> visitor)
|
||||||
|
{
|
||||||
|
var treeItr = _itemBonusTrees.LookupByKey(itemBonusTreeId);
|
||||||
|
if (treeItr.Empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var bonusTreeNode in treeItr)
|
||||||
|
{
|
||||||
|
visitor(bonusTreeNode);
|
||||||
|
if (bonusTreeNode.ChildItemBonusTreeID != 0)
|
||||||
|
VisitItemBonusTree(bonusTreeNode.ChildItemBonusTreeID, visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<uint> GetAllBonusListsForTree(uint itemBonusTreeId)
|
||||||
|
{
|
||||||
|
List<uint> bonusListIDs = new();
|
||||||
|
VisitItemBonusTree(itemBonusTreeId, bonusTreeNode =>
|
||||||
|
{
|
||||||
|
if (bonusTreeNode.ChildItemBonusListID != 0)
|
||||||
|
bonusListIDs.Add(bonusTreeNode.ChildItemBonusListID);
|
||||||
|
});
|
||||||
|
|
||||||
|
return bonusListIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ItemBonusGenerationParams
|
||||||
|
{
|
||||||
|
public ItemBonusGenerationParams(ItemContext context, int? mythicPlusKeystoneLevel = null, int? pvpTier = null)
|
||||||
|
{
|
||||||
|
Context = context;
|
||||||
|
MythicPlusKeystoneLevel = mythicPlusKeystoneLevel;
|
||||||
|
PvpTier = pvpTier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemContext Context;
|
||||||
|
public int? MythicPlusKeystoneLevel;
|
||||||
|
public int? PvpTier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,7 +32,7 @@ namespace Game.Entities
|
|||||||
uint bonusListId = result.Read<uint>(1);
|
uint bonusListId = result.Read<uint>(1);
|
||||||
float chance = result.Read<float>(2);
|
float chance = result.Read<float>(2);
|
||||||
|
|
||||||
if (Global.DB2Mgr.GetItemBonusList(bonusListId) == null)
|
if (ItemBonusMgr.GetItemBonuses(bonusListId).Empty())
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Sql, $"Bonus list {bonusListId} used in `item_random_bonus_list_template` by id {id} doesn't have exist in ItemBonus.db2");
|
Log.outError(LogFilter.Sql, $"Bonus list {bonusListId} used in `item_random_bonus_list_template` by id {id} doesn't have exist in ItemBonus.db2");
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ namespace Game.Entities
|
|||||||
public override float GetBlockPercent(uint attackerLevel)
|
public override float GetBlockPercent(uint attackerLevel)
|
||||||
{
|
{
|
||||||
float blockArmor = (float)m_activePlayerData.ShieldBlock;
|
float blockArmor = (float)m_activePlayerData.ShieldBlock;
|
||||||
float armorConstant = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, attackerLevel, -2, 0, Class.None);
|
float armorConstant = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, attackerLevel, -2, 0, Class.None, 0);
|
||||||
|
|
||||||
if ((blockArmor + armorConstant) == 0)
|
if ((blockArmor + armorConstant) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1209,8 +1209,6 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
Log.outDebug(LogFilter.Player, "STORAGE: Creating initial item, itemId = {0}, count = {1}", itemId, amount);
|
Log.outDebug(LogFilter.Player, "STORAGE: Creating initial item, itemId = {0}, count = {1}", itemId, amount);
|
||||||
|
|
||||||
var bonusListIDs = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, context);
|
|
||||||
|
|
||||||
InventoryResult msg;
|
InventoryResult msg;
|
||||||
// attempt equip by one
|
// attempt equip by one
|
||||||
while (amount > 0)
|
while (amount > 0)
|
||||||
@@ -1219,8 +1217,7 @@ namespace Game.Entities
|
|||||||
if (msg != InventoryResult.Ok)
|
if (msg != InventoryResult.Ok)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Item item = EquipNewItem(eDest, itemId, context, true);
|
EquipNewItem(eDest, itemId, context, true);
|
||||||
item.SetBonuses(bonusListIDs);
|
|
||||||
AutoUnequipOffhandIfNeed();
|
AutoUnequipOffhandIfNeed();
|
||||||
--amount;
|
--amount;
|
||||||
}
|
}
|
||||||
@@ -1234,7 +1231,7 @@ namespace Game.Entities
|
|||||||
msg = CanStoreNewItem(InventorySlots.Bag0, ItemConst.NullSlot, sDest, itemId, amount);
|
msg = CanStoreNewItem(InventorySlots.Bag0, ItemConst.NullSlot, sDest, itemId, amount);
|
||||||
if (msg == InventoryResult.Ok)
|
if (msg == InventoryResult.Ok)
|
||||||
{
|
{
|
||||||
StoreNewItem(sDest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, context, bonusListIDs);
|
StoreNewItem(sDest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, context);
|
||||||
return true; // stored
|
return true; // stored
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1242,18 +1239,20 @@ namespace Game.Entities
|
|||||||
Log.outError(LogFilter.Player, "STORAGE: Can't equip or store initial item {0} for race {1} class {2}, error msg = {3}", itemId, GetRace(), GetClass(), msg);
|
Log.outError(LogFilter.Player, "STORAGE: Can't equip or store initial item {0} for race {1} class {2}, error msg = {3}", itemId, GetRace(), GetClass(), msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item StoreNewItem(List<ItemPosCount> pos, uint itemId, bool update, uint randomBonusListId = 0, List<ObjectGuid> allowedLooters = null, ItemContext context = 0, List<uint> bonusListIDs = null, bool addToCollection = true)
|
public Item StoreNewItem(List<ItemPosCount> pos, uint itemId, bool update, uint randomBonusListId = 0, List<ObjectGuid> allowedLooters = null, ItemContext context = 0, List<uint> bonusListIDs = null, bool addToCollection = true)
|
||||||
{
|
{
|
||||||
uint count = 0;
|
uint count = 0;
|
||||||
foreach (var itemPosCount in pos)
|
foreach (var itemPosCount in pos)
|
||||||
count += itemPosCount.count;
|
count += itemPosCount.count;
|
||||||
|
|
||||||
Item item = Item.CreateItem(itemId, count, context, this);
|
Item item = Item.CreateItem(itemId, count, context, this, bonusListIDs == null);
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
item.SetItemFlag(ItemFieldFlags.NewItem);
|
item.SetItemFlag(ItemFieldFlags.NewItem);
|
||||||
|
|
||||||
item.SetBonuses(bonusListIDs);
|
if (bonusListIDs != null)
|
||||||
|
item.SetBonuses(bonusListIDs);
|
||||||
|
|
||||||
item = StoreItem(pos, item, update);
|
item = StoreItem(pos, item, update);
|
||||||
|
|
||||||
@@ -6090,7 +6089,7 @@ namespace Game.Entities
|
|||||||
InventoryResult msg = CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count);
|
InventoryResult msg = CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count);
|
||||||
if (msg == InventoryResult.Ok)
|
if (msg == InventoryResult.Ok)
|
||||||
{
|
{
|
||||||
Item newitem = StoreNewItem(dest, item.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context, item.BonusListIDs);
|
Item newitem = StoreNewItem(dest, item.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context);
|
||||||
if (ffaItem != null)
|
if (ffaItem != null)
|
||||||
{
|
{
|
||||||
//freeforall case, notify only one player of the removal
|
//freeforall case, notify only one player of the removal
|
||||||
|
|||||||
@@ -922,7 +922,7 @@ namespace Game.Entities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RewardQuestPackage(uint questPackageId, uint onlyItemId = 0)
|
public void RewardQuestPackage(uint questPackageId, ItemContext context, uint onlyItemId = 0)
|
||||||
{
|
{
|
||||||
bool hasFilteredQuestPackageReward = false;
|
bool hasFilteredQuestPackageReward = false;
|
||||||
var questPackageItems = Global.DB2Mgr.GetQuestPackageItems(questPackageId);
|
var questPackageItems = Global.DB2Mgr.GetQuestPackageItems(questPackageId);
|
||||||
@@ -939,7 +939,7 @@ namespace Game.Entities
|
|||||||
List<ItemPosCount> dest = new();
|
List<ItemPosCount> dest = new();
|
||||||
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, questPackageItem.ItemID, questPackageItem.ItemQuantity) == InventoryResult.Ok)
|
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, questPackageItem.ItemID, questPackageItem.ItemQuantity) == InventoryResult.Ok)
|
||||||
{
|
{
|
||||||
Item item = StoreNewItem(dest, questPackageItem.ItemID, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(questPackageItem.ItemID));
|
Item item = StoreNewItem(dest, questPackageItem.ItemID, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(questPackageItem.ItemID), null, context);
|
||||||
SendNewItem(item, questPackageItem.ItemQuantity, true, false);
|
SendNewItem(item, questPackageItem.ItemQuantity, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -959,7 +959,7 @@ namespace Game.Entities
|
|||||||
List<ItemPosCount> dest = new();
|
List<ItemPosCount> dest = new();
|
||||||
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, questPackageItem.ItemID, questPackageItem.ItemQuantity) == InventoryResult.Ok)
|
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, questPackageItem.ItemID, questPackageItem.ItemQuantity) == InventoryResult.Ok)
|
||||||
{
|
{
|
||||||
Item item = StoreNewItem(dest, questPackageItem.ItemID, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(questPackageItem.ItemID));
|
Item item = StoreNewItem(dest, questPackageItem.ItemID, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(questPackageItem.ItemID), null, context);
|
||||||
SendNewItem(item, questPackageItem.ItemQuantity, true, false);
|
SendNewItem(item, questPackageItem.ItemQuantity, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1020,7 +1020,7 @@ namespace Game.Entities
|
|||||||
List<ItemPosCount> dest = new();
|
List<ItemPosCount> dest = new();
|
||||||
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, itemId, quest.RewardItemCount[i]) == InventoryResult.Ok)
|
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, itemId, quest.RewardItemCount[i]) == InventoryResult.Ok)
|
||||||
{
|
{
|
||||||
Item item = StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId));
|
Item item = StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, ItemContext.QuestReward);
|
||||||
SendNewItem(item, quest.RewardItemCount[i], true, false);
|
SendNewItem(item, quest.RewardItemCount[i], true, false);
|
||||||
}
|
}
|
||||||
else if (quest.IsDFQuest())
|
else if (quest.IsDFQuest())
|
||||||
@@ -1035,8 +1035,8 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
if (quest.IsWorldQuest())
|
if (quest.IsWorldQuest())
|
||||||
currencyGainSource = CurrencyGainSource.WorldQuestRewardIgnoreCaps;
|
currencyGainSource = CurrencyGainSource.WorldQuestRewardIgnoreCaps;
|
||||||
|
else
|
||||||
currencyGainSource = CurrencyGainSource.QuestRewardIgnoreCaps;
|
currencyGainSource = CurrencyGainSource.QuestRewardIgnoreCaps;
|
||||||
}
|
}
|
||||||
else if (quest.IsDaily())
|
else if (quest.IsDaily())
|
||||||
currencyGainSource = CurrencyGainSource.DailyQuestReward;
|
currencyGainSource = CurrencyGainSource.DailyQuestReward;
|
||||||
@@ -1058,7 +1058,7 @@ namespace Game.Entities
|
|||||||
List<ItemPosCount> dest = new();
|
List<ItemPosCount> dest = new();
|
||||||
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, rewardId, quest.RewardChoiceItemCount[i]) == InventoryResult.Ok)
|
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, rewardId, quest.RewardChoiceItemCount[i]) == InventoryResult.Ok)
|
||||||
{
|
{
|
||||||
Item item = StoreNewItem(dest, rewardId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(rewardId));
|
Item item = StoreNewItem(dest, rewardId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(rewardId), null, ItemContext.QuestReward);
|
||||||
SendNewItem(item, quest.RewardChoiceItemCount[i], true, false);
|
SendNewItem(item, quest.RewardChoiceItemCount[i], true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1068,7 +1068,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
// QuestPackageItem.db2
|
// QuestPackageItem.db2
|
||||||
if (rewardProto != null && quest.PackageID != 0)
|
if (rewardProto != null && quest.PackageID != 0)
|
||||||
RewardQuestPackage(quest.PackageID, rewardId);
|
RewardQuestPackage(quest.PackageID, ItemContext.QuestReward, rewardId);
|
||||||
break;
|
break;
|
||||||
case LootItemType.Currency:
|
case LootItemType.Currency:
|
||||||
if (CliDB.CurrencyTypesStorage.HasRecord(rewardId) && quest.GetRewChoiceItemsCount() != 0)
|
if (CliDB.CurrencyTypesStorage.HasRecord(rewardId) && quest.GetRewChoiceItemsCount() != 0)
|
||||||
|
|||||||
@@ -585,7 +585,7 @@ namespace Game.Entities
|
|||||||
ApplyLevelScaling();
|
ApplyLevelScaling();
|
||||||
|
|
||||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||||
SetCreateHealth((uint)Math.Max(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, petlevel, creatureDifficulty.GetHealthScalingExpansion(), m_unitData.ContentTuningID, (Class)cinfo.UnitClass) * creatureDifficulty.HealthModifier * GetHealthMod(cinfo.Rank), 1.0f));
|
SetCreateHealth((uint)Math.Max(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, petlevel, creatureDifficulty.GetHealthScalingExpansion(), m_unitData.ContentTuningID, (Class)cinfo.UnitClass, 0) * creatureDifficulty.HealthModifier * GetHealthMod(cinfo.Rank), 1.0f));
|
||||||
SetCreateMana(stats.BaseMana);
|
SetCreateMana(stats.BaseMana);
|
||||||
|
|
||||||
SetCreateStat(Stats.Strength, 22);
|
SetCreateStat(Stats.Strength, 22);
|
||||||
|
|||||||
@@ -773,7 +773,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
creature.m_personalLoot = LootManager.GenerateDungeonEncounterPersonalLoot(dungeonEncounter.Id, creature.GetLootId(),
|
creature.m_personalLoot = LootManager.GenerateDungeonEncounterPersonalLoot(dungeonEncounter.Id, creature.GetLootId(),
|
||||||
LootStorage.Creature, LootType.Corpse, creature, creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax,
|
LootStorage.Creature, LootType.Corpse, creature, creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax,
|
||||||
(ushort)creature.GetLootMode(), creature.GetMap().GetDifficultyLootItemContext(), tappers);
|
(ushort)creature.GetLootMode(), creature.GetMap().GetMapDifficulty(), tappers);
|
||||||
}
|
}
|
||||||
else if (!tappers.Empty())
|
else if (!tappers.Empty())
|
||||||
{
|
{
|
||||||
@@ -784,7 +784,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
uint lootid = creature.GetLootId();
|
uint lootid = creature.GetLootId();
|
||||||
if (lootid != 0)
|
if (lootid != 0)
|
||||||
loot.FillLoot(lootid, LootStorage.Creature, looter, dungeonEncounter != null, false, creature.GetLootMode(), creature.GetMap().GetDifficultyLootItemContext());
|
loot.FillLoot(lootid, LootStorage.Creature, looter, dungeonEncounter != null, false, creature.GetLootMode(), ItemBonusMgr.GetContextForPlayer(creature.GetMap().GetMapDifficulty(), looter));
|
||||||
|
|
||||||
if (creature.GetLootMode() > 0)
|
if (creature.GetLootMode() > 0)
|
||||||
loot.GenerateMoneyLoot(creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax);
|
loot.GenerateMoneyLoot(creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax);
|
||||||
@@ -811,7 +811,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
uint lootid = creature.GetLootId();
|
uint lootid = creature.GetLootId();
|
||||||
if (lootid != 0)
|
if (lootid != 0)
|
||||||
loot.FillLoot(lootid, LootStorage.Creature, tapper, true, false, creature.GetLootMode(), creature.GetMap().GetDifficultyLootItemContext());
|
loot.FillLoot(lootid, LootStorage.Creature, tapper, true, false, creature.GetLootMode(), ItemBonusMgr.GetContextForPlayer(creature.GetMap().GetMapDifficulty(), tapper));
|
||||||
|
|
||||||
if (creature.GetLootMode() > 0)
|
if (creature.GetLootMode() > 0)
|
||||||
loot.GenerateMoneyLoot(creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax);
|
loot.GenerateMoneyLoot(creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax);
|
||||||
|
|||||||
@@ -3886,7 +3886,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Expansion and ContentTuningID necessary? Does Player get a ContentTuningID too ?
|
// Expansion and ContentTuningID necessary? Does Player get a ContentTuningID too ?
|
||||||
float armorConstant = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, attackerLevel, -2, 0, attackerClass);
|
float armorConstant = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, attackerLevel, -2, 0, attackerClass, 0);
|
||||||
if ((armor + armorConstant) == 0)
|
if ((armor + armorConstant) == 0)
|
||||||
return damage;
|
return damage;
|
||||||
|
|
||||||
|
|||||||
@@ -5162,11 +5162,11 @@ namespace Game
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (uint bonusList in vItem.BonusListIDs)
|
foreach (uint bonusListId in vItem.BonusListIDs)
|
||||||
{
|
{
|
||||||
if (Global.DB2Mgr.GetItemBonusList(bonusList) == null)
|
if (ItemBonusMgr.GetItemBonuses(bonusListId).Empty())
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` have Item (Entry: {0}) with invalid bonus {1} for vendor ({2}), ignore", vItem.item, bonusList, vendorentry);
|
Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` have Item (Entry: {0}) with invalid bonus {1} for vendor ({2}), ignore", vItem.item, bonusListId, vendorentry);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -585,8 +585,8 @@ namespace Game
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item bodyItem = new(); // This is not bag and then can be used new Item.
|
Item bodyItem = Item.CreateItem(8383, 1, ItemContext.None, player);
|
||||||
if (!bodyItem.Create(Global.ObjectMgr.GetGenerator(HighGuid.Item).Generate(), 8383, ItemContext.None, player))
|
if (bodyItem == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// in mail template case we need create new item text
|
// in mail template case we need create new item text
|
||||||
|
|||||||
@@ -773,7 +773,7 @@ namespace Game
|
|||||||
_player.SetTitle(CliDB.CharTitlesStorage.LookupByKey(reward.TitleId), false);
|
_player.SetTitle(CliDB.CharTitlesStorage.LookupByKey(reward.TitleId), false);
|
||||||
|
|
||||||
if (reward.PackageId != 0)
|
if (reward.PackageId != 0)
|
||||||
_player.RewardQuestPackage((uint)reward.PackageId);
|
_player.RewardQuestPackage((uint)reward.PackageId, ItemContext.None);
|
||||||
|
|
||||||
if (reward.SkillLineId != 0 && _player.HasSkill((SkillType)reward.SkillLineId))
|
if (reward.SkillLineId != 0 && _player.HasSkill((SkillType)reward.SkillLineId))
|
||||||
_player.UpdateSkillPro((uint)reward.SkillLineId, 1000, reward.SkillPointCount);
|
_player.UpdateSkillPro((uint)reward.SkillLineId, 1000, reward.SkillPointCount);
|
||||||
|
|||||||
@@ -673,11 +673,7 @@ namespace Game.Loots
|
|||||||
generatedLoot.context = _itemContext;
|
generatedLoot.context = _itemContext;
|
||||||
generatedLoot.count = (byte)Math.Min(count, proto.GetMaxStackSize());
|
generatedLoot.count = (byte)Math.Min(count, proto.GetMaxStackSize());
|
||||||
generatedLoot.LootListId = (uint)items.Count;
|
generatedLoot.LootListId = (uint)items.Count;
|
||||||
if (_itemContext != 0)
|
generatedLoot.BonusListIDs = ItemBonusMgr.GetBonusListsForItem(generatedLoot.itemid, new(_itemContext));
|
||||||
{
|
|
||||||
List<uint> bonusListIDs = Global.DB2Mgr.GetDefaultItemBonusTree(generatedLoot.itemid, _itemContext);
|
|
||||||
generatedLoot.BonusListIDs.AddRange(bonusListIDs);
|
|
||||||
}
|
|
||||||
|
|
||||||
items.Add(generatedLoot);
|
items.Add(generatedLoot);
|
||||||
count -= proto.GetMaxStackSize();
|
count -= proto.GetMaxStackSize();
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace Game.Loots
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<ObjectGuid, Loot> GenerateDungeonEncounterPersonalLoot(uint dungeonEncounterId, uint lootId, LootStore store,
|
public static Dictionary<ObjectGuid, Loot> GenerateDungeonEncounterPersonalLoot(uint dungeonEncounterId, uint lootId, LootStore store,
|
||||||
LootType type, WorldObject lootOwner, uint minMoney, uint maxMoney, ushort lootMode, ItemContext context, List<Player> tappers)
|
LootType type, WorldObject lootOwner, uint minMoney, uint maxMoney, ushort lootMode, MapDifficultyRecord mapDifficulty, List<Player> tappers)
|
||||||
{
|
{
|
||||||
Dictionary<Player, Loot> tempLoot = new();
|
Dictionary<Player, Loot> tempLoot = new();
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ namespace Game.Loots
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Loot loot = new(lootOwner.GetMap(), lootOwner.GetGUID(), type, null);
|
Loot loot = new(lootOwner.GetMap(), lootOwner.GetGUID(), type, null);
|
||||||
loot.SetItemContext(context);
|
loot.SetItemContext(ItemBonusMgr.GetContextForPlayer(mapDifficulty, tapper));
|
||||||
loot.SetDungeonEncounterId(dungeonEncounterId);
|
loot.SetDungeonEncounterId(dungeonEncounterId);
|
||||||
loot.GenerateMoneyLoot(minMoney, maxMoney);
|
loot.GenerateMoneyLoot(minMoney, maxMoney);
|
||||||
|
|
||||||
|
|||||||
@@ -3228,19 +3228,6 @@ namespace Game.Maps
|
|||||||
return Global.DB2Mgr.GetMapDifficultyData(GetId(), GetDifficultyID());
|
return Global.DB2Mgr.GetMapDifficultyData(GetId(), GetDifficultyID());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemContext GetDifficultyLootItemContext()
|
|
||||||
{
|
|
||||||
MapDifficultyRecord mapDifficulty = GetMapDifficulty();
|
|
||||||
if (mapDifficulty != null && mapDifficulty.ItemContext != 0)
|
|
||||||
return (ItemContext)mapDifficulty.ItemContext;
|
|
||||||
|
|
||||||
DifficultyRecord difficulty = CliDB.DifficultyStorage.LookupByKey(GetDifficultyID());
|
|
||||||
if (difficulty != null)
|
|
||||||
return (ItemContext)difficulty.ItemContext;
|
|
||||||
|
|
||||||
return ItemContext.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetId()
|
public uint GetId()
|
||||||
{
|
{
|
||||||
return i_mapRecord.Id;
|
return i_mapRecord.Id;
|
||||||
|
|||||||
@@ -4306,7 +4306,7 @@ namespace Game.Spells
|
|||||||
expansion = contentTuning.ExpansionID;
|
expansion = contentTuning.ExpansionID;
|
||||||
|
|
||||||
uint level = caster != null && caster.IsUnit() ? caster.ToUnit().GetLevel() : 1;
|
uint level = caster != null && caster.IsUnit() ? caster.ToUnit().GetLevel() : 1;
|
||||||
tempValue = Global.DB2Mgr.EvaluateExpectedStat(stat, level, expansion, 0, Class.None) * BasePoints / 100.0f;
|
tempValue = Global.DB2Mgr.EvaluateExpectedStat(stat, level, expansion, 0, Class.None, 0) * BasePoints / 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)Math.Round(tempValue);
|
return (int)Math.Round(tempValue);
|
||||||
|
|||||||
@@ -580,6 +580,9 @@ namespace Game
|
|||||||
Log.outInfo(LogFilter.ServerLoading, "Loading Enchant Spells Proc datas...");
|
Log.outInfo(LogFilter.ServerLoading, "Loading Enchant Spells Proc datas...");
|
||||||
Global.SpellMgr.LoadSpellEnchantProcData();
|
Global.SpellMgr.LoadSpellEnchantProcData();
|
||||||
|
|
||||||
|
Log.outInfo(LogFilter.ServerLoading, "Loading item bonus data...");
|
||||||
|
ItemBonusMgr.Load();
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loading Random item bonus list definitions...");
|
Log.outInfo(LogFilter.ServerLoading, "Loading Random item bonus list definitions...");
|
||||||
ItemEnchantmentManager.LoadItemRandomBonusListTemplates();
|
ItemEnchantmentManager.LoadItemRandomBonusListTemplates();
|
||||||
|
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ namespace Scripts.Spells.Monk
|
|||||||
Unit target = GetTarget();
|
Unit target = GetTarget();
|
||||||
float agility = target.GetStat(Stats.Agility);
|
float agility = target.GetStat(Stats.Agility);
|
||||||
float baseAmount = MathFunctions.CalculatePct(agility, effect.GetAmount());
|
float baseAmount = MathFunctions.CalculatePct(agility, effect.GetAmount());
|
||||||
float K = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, target.GetLevel(), -2, 0, target.GetClass());
|
float K = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, target.GetLevel(), -2, 0, target.GetClass(), 0);
|
||||||
|
|
||||||
float newAmount = (baseAmount / (baseAmount + K));
|
float newAmount = (baseAmount / (baseAmount + K));
|
||||||
newAmount *= multiplier;
|
newAmount *= multiplier;
|
||||||
|
|||||||
Reference in New Issue
Block a user