diff --git a/Source/Framework/Constants/CliDBConst.cs b/Source/Framework/Constants/CliDBConst.cs index 8663f6bde..5d351eeac 100644 --- a/Source/Framework/Constants/CliDBConst.cs +++ b/Source/Framework/Constants/CliDBConst.cs @@ -2152,4 +2152,24 @@ namespace Framework.Constants None = 0, Disabled = 0x1 } + + public enum GlobalCurve + { + CritDiminishing = 0, + MasteryDiminishing = 1, + HasteDiminishing = 2, + SpeedDiminishing = 3, + AvoidanceDiminishing = 4, + VersatilityDoneDiminishing = 5, + LifestealDiminishing = 6, + DodgeDiminishing = 7, + BlockDiminishing = 8, + ParryDiminishing = 9, + + VersatilityTakenDiminishing = 11, + + ContentTuningPvpItemLevelHealthScaling = 13, + ContentTuningPvpLevelDamageScaling = 14, + ContentTuningPvpItemLevelDamageScaling = 15, + } } diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index dd64c90df..246e0e93b 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -461,6 +461,9 @@ namespace Framework.Database // GemProperties.db2 PrepareStatement(HotfixStatements.SEL_GEM_PROPERTIES, "SELECT ID, EnchantId, Type FROM gem_properties"); + // GlobalCurve.db2 + PrepareStatement(HotfixStatements.SEL_GLOBAL_CURVE, "SELECT ID, CurveID, Type FROM global_curve"); + // GlyphBindableSpell.db2 PrepareStatement(HotfixStatements.SEL_GLYPH_BINDABLE_SPELL, "SELECT ID, SpellID, GlyphPropertiesID FROM glyph_bindable_spell"); @@ -1379,6 +1382,8 @@ namespace Framework.Database SEL_GEM_PROPERTIES, + SEL_GLOBAL_CURVE, + SEL_GLYPH_BINDABLE_SPELL, SEL_GLYPH_PROPERTIES, diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index ada86e2c2..09a849b79 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -150,6 +150,7 @@ namespace Game.DataStorage GarrSiteLevelStorage = ReadDB2("GarrSiteLevel.db2", HotfixStatements.SEL_GARR_SITE_LEVEL); GarrSiteLevelPlotInstStorage = ReadDB2("GarrSiteLevelPlotInst.db2", HotfixStatements.SEL_GARR_SITE_LEVEL_PLOT_INST); GemPropertiesStorage = ReadDB2("GemProperties.db2", HotfixStatements.SEL_GEM_PROPERTIES); + GlobalCurveStorage = ReadDB2("GlobalCurve.db2", HotfixStatements.SEL_GLOBAL_CURVE); GlyphBindableSpellStorage = ReadDB2("GlyphBindableSpell.db2", HotfixStatements.SEL_GLYPH_BINDABLE_SPELL); GlyphPropertiesStorage = ReadDB2("GlyphProperties.db2", HotfixStatements.SEL_GLYPH_PROPERTIES); GlyphRequiredSpecStorage = ReadDB2("GlyphRequiredSpec.db2", HotfixStatements.SEL_GLYPH_REQUIRED_SPEC); @@ -508,6 +509,7 @@ namespace Game.DataStorage public static DB6Storage GarrSiteLevelStorage; public static DB6Storage GarrSiteLevelPlotInstStorage; public static DB6Storage GemPropertiesStorage; + public static DB6Storage GlobalCurveStorage; public static DB6Storage GlyphBindableSpellStorage; public static DB6Storage GlyphPropertiesStorage; public static DB6Storage GlyphRequiredSpecStorage; diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index 4202e2365..f22cb926d 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -1370,11 +1370,15 @@ namespace Game.DataStorage return _factionTeams.LookupByKey(faction); } - public HeirloomRecord GetHeirloomByItemId(uint itemId) + public uint GetGlobalCurveId(GlobalCurve globalCurveType) { - return _heirlooms.LookupByKey(itemId); - } + foreach (var globalCurveEntry in CliDB.GlobalCurveStorage.Values) + if (globalCurveEntry.Type == globalCurveType) + return globalCurveEntry.CurveID; + return 0; + } + public List GetGlyphBindableSpells(uint glyphPropertiesId) { return _glyphBindableSpells.LookupByKey(glyphPropertiesId); @@ -1385,6 +1389,11 @@ namespace Game.DataStorage return _glyphRequiredSpecs.LookupByKey(glyphPropertiesId); } + public HeirloomRecord GetHeirloomByItemId(uint itemId) + { + return _heirlooms.LookupByKey(itemId); + } + public List GetItemBonusList(uint bonusListId) { return _itemBonusLists.LookupByKey(bonusListId); diff --git a/Source/Game/DataStorage/Structs/A_Records.cs b/Source/Game/DataStorage/Structs/A_Records.cs index 6593285e3..19cda97ac 100644 --- a/Source/Game/DataStorage/Structs/A_Records.cs +++ b/Source/Game/DataStorage/Structs/A_Records.cs @@ -21,7 +21,7 @@ using System; namespace Game.DataStorage { - public class AchievementRecord + public sealed class AchievementRecord { public string Description; public string Title; diff --git a/Source/Game/DataStorage/Structs/G_Records.cs b/Source/Game/DataStorage/Structs/G_Records.cs index 158ca2d14..042845aaf 100644 --- a/Source/Game/DataStorage/Structs/G_Records.cs +++ b/Source/Game/DataStorage/Structs/G_Records.cs @@ -222,6 +222,13 @@ namespace Game.DataStorage public SocketColor Type; } + public sealed class GlobalCurveRecord + { + public uint Id; + public uint CurveID; + public GlobalCurve Type; + } + public sealed class GlyphBindableSpellRecord { public uint Id; diff --git a/Source/Game/Entities/Player/Player.Combat.cs b/Source/Game/Entities/Player/Player.Combat.cs index 26e2982b2..ed7972102 100644 --- a/Source/Game/Entities/Player/Player.Combat.cs +++ b/Source/Game/Entities/Player/Player.Combat.cs @@ -107,7 +107,7 @@ namespace Game.Entities } public float GetRatingBonusValue(CombatRating cr) { - float baseResult = m_activePlayerData.CombatRatings[(int)cr] * GetRatingMultiplier(cr); + float baseResult = ApplyRatingDiminishing(cr, m_activePlayerData.CombatRatings[(int)cr] * GetRatingMultiplier(cr)); if (cr != CombatRating.ResiliencePlayerDamage) return baseResult; return (float)(1.0f - Math.Pow(0.99f, baseResult)) * 100.0f; @@ -167,6 +167,59 @@ namespace Game.Entities */ } + float ApplyRatingDiminishing(CombatRating cr, float bonusValue) + { + uint diminishingCurveId = 0; + switch (cr) + { + case CombatRating.Dodge: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.DodgeDiminishing); + break; + case CombatRating.Parry: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.ParryDiminishing); + break; + case CombatRating.Block: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.BlockDiminishing); + break; + case CombatRating.CritMelee: + case CombatRating.CritRanged: + case CombatRating.CritSpell: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.CritDiminishing); + break; + case CombatRating.Speed: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.SpeedDiminishing); + break; + case CombatRating.Lifesteal: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.LifestealDiminishing); + break; + case CombatRating.HasteMelee: + case CombatRating.HasteRanged: + case CombatRating.HasteSpell: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.HasteDiminishing); + break; + case CombatRating.Avoidance: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.AvoidanceDiminishing); + break; + case CombatRating.Mastery: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.MasteryDiminishing); + break; + case CombatRating.VersatilityDamageDone: + case CombatRating.VersatilityHealingDone: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.VersatilityDoneDiminishing); + break; + case CombatRating.VersatilityDamageTaken: + diminishingCurveId = Global.DB2Mgr.GetGlobalCurveId(GlobalCurve.VersatilityTakenDiminishing); + break; + default: + break; + } + + if (diminishingCurveId != 0) + return Global.DB2Mgr.GetCurveValueAt(diminishingCurveId, bonusValue); + + return bonusValue; + } + public float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) { float baseExpertise = 7.5f; diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index 582f2453d..d1c132760 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -1368,8 +1368,8 @@ namespace Game.Entities { // explicit affected values float multiplier = GetRatingMultiplier(cr); - float oldVal = oldRating * multiplier; - float newVal = amount * multiplier; + float oldVal = ApplyRatingDiminishing(cr, oldRating * multiplier); + float newVal = ApplyRatingDiminishing(cr, amount * multiplier); switch (cr) { case CombatRating.HasteMelee: diff --git a/sql/updates/hotfixes/master/2021_02_07_00_hotfixes.sql b/sql/updates/hotfixes/master/2021_02_07_00_hotfixes.sql new file mode 100644 index 000000000..063dc1634 --- /dev/null +++ b/sql/updates/hotfixes/master/2021_02_07_00_hotfixes.sql @@ -0,0 +1,11 @@ +-- +-- Table structure for table `global_curve` +-- +DROP TABLE IF EXISTS `global_curve`; +CREATE TABLE `global_curve` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `CurveID` int(11) NOT NULL DEFAULT '0', + `Type` int(11) NOT NULL DEFAULT '0', + `VerifiedBuild` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`,`VerifiedBuild`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;