diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index a09617ed0..ecc4840b6 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -233,7 +233,7 @@ namespace Framework.Database // ChrCustomizationElement.db2 PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_ELEMENT, "SELECT ID, ChrCustomizationChoiceID, RelatedChrCustomizationChoiceID, " + "ChrCustomizationGeosetID, ChrCustomizationSkinnedModelID, ChrCustomizationMaterialID, ChrCustomizationBoneSetID, " + - "ChrCustomizationCondModelID, ChrCustomizationDisplayInfoID FROM chr_customization_element"); + "ChrCustomizationCondModelID, ChrCustomizationDisplayInfoID, ChrCustItemGeoModifyID FROM chr_customization_element"); // ChrCustomizationOption.db2 PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_OPTION, "SELECT Name, ID, SecondaryID, Flags, ChrModelID, SortIndex, ChrCustomizationCategoryID, " + @@ -546,8 +546,8 @@ namespace Framework.Database PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_LIST_LEVEL_DELTA, "SELECT ItemLevelDelta, ID FROM item_bonus_list_level_delta"); // ItemBonusTreeNode.db2 - PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_TREE_NODE, "SELECT ID, ItemContext, ChildItemBonusTreeID, ChildItemBonusListID, ChildItemLevelSelectorID, " + - "ParentItemBonusTreeID FROM item_bonus_tree_node"); + PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_TREE_NODE, "SELECT ID, ItemContext, ChildItemBonusTreeID, ChildItemBonusListID, ChildItemLevelSelectorID, " + + "ItemBonusListGroupID, ParentItemBonusTreeNodeID, ParentItemBonusTreeID FROM item_bonus_tree_node"); // ItemChildEquipment.db2 PrepareStatement(HotfixStatements.SEL_ITEM_CHILD_EQUIPMENT, "SELECT ID, ParentItemID, ChildItemID, ChildItemEquipSlot FROM item_child_equipment"); @@ -837,8 +837,9 @@ namespace Framework.Database "Difficulty8, Difficulty9, Difficulty10 FROM quest_xp"); // RandPropPoints.db2 - PrepareStatement(HotfixStatements.SEL_RAND_PROP_POINTS, "SELECT ID, DamageReplaceStat, DamageSecondary, Epic1, Epic2, Epic3, Epic4, Epic5, Superior1, " + - "Superior2, Superior3, Superior4, Superior5, Good1, Good2, Good3, Good4, Good5 FROM rand_prop_points"); + PrepareStatement(HotfixStatements.SEL_RAND_PROP_POINTS, "SELECT ID, DamageReplaceStatF, DamageSecondaryF, DamageReplaceStat, DamageSecondary, EpicF1, " + + "EpicF2, EpicF3, EpicF4, EpicF5, SuperiorF1, SuperiorF2, SuperiorF3, SuperiorF4, SuperiorF5, GoodF1, GoodF2, GoodF3, GoodF4, GoodF5, Epic1, " + + "Epic2, Epic3, Epic4, Epic5, Superior1, Superior2, Superior3, Superior4, Superior5, Good1, Good2, Good3, Good4, Good5 FROM rand_prop_points"); // RewardPack.db2 PrepareStatement(HotfixStatements.SEL_REWARD_PACK, "SELECT ID, CharTitleID, Money, ArtifactXPDifficulty, ArtifactXPMultiplier, ArtifactXPCategoryID, " + diff --git a/Source/Game/DataStorage/Structs/C_Records.cs b/Source/Game/DataStorage/Structs/C_Records.cs index 46e2842cd..0ce205b96 100644 --- a/Source/Game/DataStorage/Structs/C_Records.cs +++ b/Source/Game/DataStorage/Structs/C_Records.cs @@ -157,6 +157,7 @@ namespace Game.DataStorage public int ChrCustomizationBoneSetID; public int ChrCustomizationCondModelID; public int ChrCustomizationDisplayInfoID; + public int ChrCustItemGeoModifyID; } public sealed class ChrCustomizationOptionRecord diff --git a/Source/Game/DataStorage/Structs/I_Records.cs b/Source/Game/DataStorage/Structs/I_Records.cs index 187e5e0b4..b3b8ca9c1 100644 --- a/Source/Game/DataStorage/Structs/I_Records.cs +++ b/Source/Game/DataStorage/Structs/I_Records.cs @@ -139,6 +139,8 @@ namespace Game.DataStorage public ushort ChildItemBonusTreeID; public ushort ChildItemBonusListID; public ushort ChildItemLevelSelectorID; + public int ItemBonusListGroupID; + public int ParentItemBonusTreeNodeID; public uint ParentItemBonusTreeID; } diff --git a/Source/Game/DataStorage/Structs/R_Records.cs b/Source/Game/DataStorage/Structs/R_Records.cs index c0f386a5d..f88fc3d91 100644 --- a/Source/Game/DataStorage/Structs/R_Records.cs +++ b/Source/Game/DataStorage/Structs/R_Records.cs @@ -20,8 +20,13 @@ namespace Game.DataStorage public sealed class RandPropPointsRecord { public uint Id; + public float DamageReplaceStatF; + public float DamageSecondaryF; public int DamageReplaceStat; public int DamageSecondary; + public float[] EpicF = new float[5]; + public float[] SuperiorF = new float[5]; + public float[] GoodF = new float[5]; public uint[] Epic = new uint[5]; public uint[] Superior = new uint[5]; public uint[] Good = new uint[5]; diff --git a/Source/Game/Entities/Item/Item.cs b/Source/Game/Entities/Item/Item.cs index 2ad5f72af..44fc8b2b6 100644 --- a/Source/Game/Entities/Item/Item.cs +++ b/Source/Game/Entities/Item/Item.cs @@ -1091,7 +1091,7 @@ namespace Game.Entities public byte GetGemCountWithID(uint GemID) { - var list = (List)m_itemData.Gems.GetEnumerator(); + var list = (List)m_itemData.Gems; return (byte)list.Count(gemData => gemData.ItemId == GemID); } @@ -1804,7 +1804,7 @@ namespace Game.Entities return Math.Min(Math.Max(itemLevel, 1), 1300); } - public int GetItemStatValue(uint index, Player owner) + public float GetItemStatValue(uint index, Player owner) { Cypher.Assert(index < ItemConst.MaxStats); switch ((ItemModType)GetItemStatType(index)) @@ -1817,18 +1817,18 @@ namespace Game.Entities } uint itemLevel = GetItemLevel(owner); - uint randomPropPoints = ItemEnchantmentManager.GetRandomPropertyPoints(itemLevel, GetQuality(), GetTemplate().GetInventoryType(), GetTemplate().GetSubClass()); + float randomPropPoints = ItemEnchantmentManager.GetRandomPropertyPoints(itemLevel, GetQuality(), GetTemplate().GetInventoryType(), GetTemplate().GetSubClass()); if (randomPropPoints != 0) { - float statValue = (_bonusData.StatPercentEditor[index] * randomPropPoints) * 0.0001f; + float statValue = _bonusData.StatPercentEditor[index] * randomPropPoints * 0.0001f; GtItemSocketCostPerLevelRecord gtCost = CliDB.ItemSocketCostPerLevelGameTable.GetRow(itemLevel); if (gtCost != null) - statValue -= (_bonusData.ItemStatSocketCostMultiplier[index] * gtCost.SocketCost); + statValue -= _bonusData.ItemStatSocketCostMultiplier[index] * gtCost.SocketCost; - return (int)(Math.Floor(statValue + 0.5f)); + return statValue; } - return 0; + return 0f; } public ItemDisenchantLootRecord GetDisenchantLoot(Player owner) diff --git a/Source/Game/Entities/Item/ItemEnchantment.cs b/Source/Game/Entities/Item/ItemEnchantment.cs index f1ce35253..799351824 100644 --- a/Source/Game/Entities/Item/ItemEnchantment.cs +++ b/Source/Game/Entities/Item/ItemEnchantment.cs @@ -91,7 +91,7 @@ namespace Game.Entities return tab.BonusListIDs.SelectRandomElementByWeight(x => (float)tab.Chances[tab.BonusListIDs.IndexOf(x)]); } - public static uint GetRandomPropertyPoints(uint itemLevel, ItemQuality quality, InventoryType inventoryType, uint subClass) + public static float GetRandomPropertyPoints(uint itemLevel, ItemQuality quality, InventoryType inventoryType, uint subClass) { uint propIndex; @@ -147,14 +147,14 @@ namespace Game.Entities switch (quality) { case ItemQuality.Uncommon: - return randPropPointsEntry.Good[propIndex]; + return randPropPointsEntry.GoodF[propIndex]; case ItemQuality.Rare: case ItemQuality.Heirloom: - return randPropPointsEntry.Superior[propIndex]; + return randPropPointsEntry.SuperiorF[propIndex]; case ItemQuality.Epic: case ItemQuality.Legendary: case ItemQuality.Artifact: - return randPropPointsEntry.Epic[propIndex]; + return randPropPointsEntry.EpicF[propIndex]; } return 0; diff --git a/Source/Game/Entities/Player/Player.Items.cs b/Source/Game/Entities/Player/Player.Items.cs index 727899977..ee2b82b30 100644 --- a/Source/Game/Entities/Player/Player.Items.cs +++ b/Source/Game/Entities/Player/Player.Items.cs @@ -3625,7 +3625,7 @@ namespace Game.Entities if (statType == -1) continue; - int val = item.GetItemStatValue(i, this); + float val = item.GetItemStatValue(i, this); if (val == 0) continue; @@ -3692,16 +3692,16 @@ namespace Game.Entities ApplyRatingMod(CombatRating.CritSpell, (int)(val * combatRatingMultiplier), apply); break; case ItemModType.CritTakenRangedRating: - ApplyRatingMod(CombatRating.CritRanged, val, apply); + ApplyRatingMod(CombatRating.CritRanged, (int)val, apply); break; case ItemModType.HasteMeleeRating: - ApplyRatingMod(CombatRating.HasteMelee, val, apply); + ApplyRatingMod(CombatRating.HasteMelee, (int)val, apply); break; case ItemModType.HasteRangedRating: - ApplyRatingMod(CombatRating.HasteRanged, val, apply); + ApplyRatingMod(CombatRating.HasteRanged, (int)val, apply); break; case ItemModType.HasteSpellRating: - ApplyRatingMod(CombatRating.HasteSpell, val, apply); + ApplyRatingMod(CombatRating.HasteSpell, (int)val, apply); break; case ItemModType.HitRating: ApplyRatingMod(CombatRating.HitMelee, (int)(val * combatRatingMultiplier), apply); @@ -3737,19 +3737,19 @@ namespace Game.Entities ApplyRatingMod(CombatRating.VersatilityHealingDone, (int)(val * combatRatingMultiplier), apply); break; case ItemModType.ManaRegeneration: - ApplyManaRegenBonus(val, apply); + ApplyManaRegenBonus((int)val, apply); break; case ItemModType.ArmorPenetrationRating: - ApplyRatingMod(CombatRating.ArmorPenetration, val, apply); + ApplyRatingMod(CombatRating.ArmorPenetration, (int)val, apply); break; case ItemModType.SpellPower: - ApplySpellPowerBonus(val, apply); + ApplySpellPowerBonus((int)val, apply); break; case ItemModType.HealthRegen: - ApplyHealthRegenBonus(val, apply); + ApplyHealthRegenBonus((int)val, apply); break; case ItemModType.SpellPenetration: - ApplySpellPenetrationBonus(val, apply); + ApplySpellPenetrationBonus((int)val, apply); break; case ItemModType.MasteryRating: ApplyRatingMod(CombatRating.Mastery, (int)(val * combatRatingMultiplier), apply); @@ -3776,13 +3776,13 @@ namespace Game.Entities HandleStatFlatModifier(UnitMods.ResistanceArcane, UnitModifierFlatType.Base, (float)val, apply); break; case ItemModType.PvpPower: - ApplyRatingMod(CombatRating.PvpPower, val, apply); + ApplyRatingMod(CombatRating.PvpPower, (int)val, apply); break; case ItemModType.Corruption: - ApplyRatingMod(CombatRating.Corruption, val, apply); + ApplyRatingMod(CombatRating.Corruption, (int)val, apply); break; case ItemModType.CorruptionResistance: - ApplyRatingMod(CombatRating.CorruptionResistance, val, apply); + ApplyRatingMod(CombatRating.CorruptionResistance, (int)val, apply); break; case ItemModType.CrSpeed: ApplyRatingMod(CombatRating.Speed, (int)(val * combatRatingMultiplier), apply); diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index 3c37d178f..b5f5f0994 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -3929,7 +3929,7 @@ namespace Game.Spells if (randPropPoints == null) randPropPoints = CliDB.RandPropPointsStorage.LookupByKey(CliDB.RandPropPointsStorage.Count - 1); - tempValue = _spellInfo.Scaling._Class == -8 ? randPropPoints.DamageReplaceStat : randPropPoints.DamageSecondary; + tempValue = _spellInfo.Scaling._Class == -8 ? randPropPoints.DamageReplaceStatF : randPropPoints.DamageSecondaryF; } else tempValue = ItemEnchantmentManager.GetRandomPropertyPoints(effectiveItemLevel, ItemQuality.Rare, InventoryType.Chest, 0); diff --git a/sql/updates/hotfixes/master/2021_04_09_00_hotfixes.sql b/sql/updates/hotfixes/master/2021_04_09_00_hotfixes.sql new file mode 100644 index 000000000..d57197330 --- /dev/null +++ b/sql/updates/hotfixes/master/2021_04_09_00_hotfixes.sql @@ -0,0 +1,24 @@ +ALTER TABLE `chr_customization_element` ADD `ChrCustItemGeoModifyID` int(11) NOT NULL DEFAULT '0' AFTER `ChrCustomizationDisplayInfoID`; + +ALTER TABLE `item_bonus_tree_node` + ADD `ItemBonusListGroupID` int(11) NOT NULL DEFAULT '0' AFTER `ChildItemLevelSelectorID`, + ADD `ParentItemBonusTreeNodeID` int(11) NOT NULL DEFAULT '0' AFTER `ItemBonusListGroupID`; + +ALTER TABLE `rand_prop_points` + ADD `DamageReplaceStatF` float NOT NULL DEFAULT '0' AFTER `ID`, + ADD `DamageSecondaryF` float NOT NULL DEFAULT '0' AFTER `DamageReplaceStatF`, + ADD `EpicF1` float NOT NULL DEFAULT '0' AFTER `DamageSecondary`, + ADD `EpicF2` float NOT NULL DEFAULT '0' AFTER `EpicF1`, + ADD `EpicF3` float NOT NULL DEFAULT '0' AFTER `EpicF2`, + ADD `EpicF4` float NOT NULL DEFAULT '0' AFTER `EpicF3`, + ADD `EpicF5` float NOT NULL DEFAULT '0' AFTER `EpicF4`, + ADD `SuperiorF1` float NOT NULL DEFAULT '0' AFTER `Epic5`, + ADD `SuperiorF2` float NOT NULL DEFAULT '0' AFTER `SuperiorF1`, + ADD `SuperiorF3` float NOT NULL DEFAULT '0' AFTER `SuperiorF2`, + ADD `SuperiorF4` float NOT NULL DEFAULT '0' AFTER `SuperiorF3`, + ADD `SuperiorF5` float NOT NULL DEFAULT '0' AFTER `SuperiorF4`, + ADD `GoodF1` float NOT NULL DEFAULT '0' AFTER `SuperiorF5`, + ADD `GoodF2` float NOT NULL DEFAULT '0' AFTER `GoodF1`, + ADD `GoodF3` float NOT NULL DEFAULT '0' AFTER `GoodF2`, + ADD `GoodF4` float NOT NULL DEFAULT '0' AFTER `GoodF3`, + ADD `GoodF5` float NOT NULL DEFAULT '0' AFTER `GoodF4`;