using System; using System.Linq; using ACE.Entity.Enum; using ACE.Entity.Enum.Properties; using ACE.Server.Managers; namespace ACE.Server.WorldObjects { partial class Creature { // Ratings: // http://asheron.wikia.com/wiki/Rating private static float GetRatingMod(int rating) { if (rating == 0) return 1.0f; if (rating >= 0) return GetPositiveRatingMod(rating); else return GetNegativeRatingMod(-rating); } /// /// Returns a 1.xx rating modifier by default, /// or a 0.xx rating modifier if negative /// public static float GetPositiveRatingMod(int rating) { if (rating < 0) return GetNegativeRatingMod(-rating); // formula: (100 + rating) / 100 = 1.xx modifier var ratingMod = (100 + rating) / 100.0f; return ratingMod; } /// /// Returns a 0.xx rating modifier by default, /// or a 1.xx rating modifier if negative /// public static float GetNegativeRatingMod(int rating, bool allowBug = false) { if (rating < 0 && !allowBug) return GetPositiveRatingMod(-rating); if (allowBug) { // with the bug allowed for DRR reduction from void dots, // this method will produce unbalanced modifiers for negative ratings // as negative rating approaches -100, it ramps up in a curve to infinity, eventually getting a divide by 0 crash for -100 // values less than -100 would produce negative multipliers, which would result in undefined behavior throughout the system, // such as negative damage numbers. even with the bug enabled, we still limit to -99 on the lower end to prevent system failure rating = Math.Max(rating, -99); } // formula: 100 / (100 + rating) = 0.xx modifier var ratingMod = 100.0f / (100 + rating); return ratingMod; } // - Damage rating - increases all damage done to a target, including critical hits // Formula: (100 + ) / 100 = 1.xx modifier to damage public float GetDamageRating(int damageRating) { return GetPositiveRatingMod(damageRating); } // - Critical damage rating - increases critical hit damage done to a target // Formula: (100 + ) / 100 = 1.xx modifier to critical damage public float GetCriticalDamageRating(int criticalDmgRating) { return GetPositiveRatingMod(criticalDmgRating); } // - Damage resistance rating - decreases the amount of all incoming damage, including critical hits // Formula: 100 / (100 + ) = 0.xxx modifier to incoming damage public float GetDamageResistanceRating(int damageResistanceRating) { return GetNegativeRatingMod(damageResistanceRating); } // - Critical damage resistance rating - decreases critical hit damage received // Formula: 100 / (100 + ) = 0.xxx modifier to critical hit damage received public float GetCriticalDamageResistanceRating(int criticalDmgResistanceRating) { return GetNegativeRatingMod(criticalDmgResistanceRating); } // - DoT resistance rating - decreases the effectiveness of damage over time (DoT) spells cast upon the user // Formula: 100 / (100 + = 0.xxx modifier to outgoing incoming DoT attacks public float GetDamageOverTimeResistanceRating(int dotResistanceRating) { return GetNegativeRatingMod(dotResistanceRating); } // - Health drain resistance rating - decreases the effect of drain spells cast upon the target // Formula: 100 / (100 + ) = 0.xxx modifier to incoming health drains public float GetHealthDrainResistanceRating(int healthDrainResistRating) { return GetNegativeRatingMod(healthDrainResistRating); } // - Healing boost rating - increases the amount of health received from consumables, healing kits, and life magic // Formula: (100 + ) / 100 = 1.xx modifier to healing public float GetHealingBoostRating(int healingBoostRating) { return GetPositiveRatingMod(healingBoostRating); } // - Aetheria Surge rating - increases the chance that Aetheria will surge // Formula: (100 + ) / 100 = 1.xx modifier to Aetheria Surges public float GetAetheriaSurgeRating(int aetheriaSurgeRating) { return GetPositiveRatingMod(aetheriaSurgeRating); } // - Mana charge rating - increases the amount of mana released from mana stones into magical items // Formula: (100 + ) / 100 = 1.xx modifier to mana charges public float GetManaChargeRating(int manaChargeRating) { return GetPositiveRatingMod(manaChargeRating); } // - Mana reduction rating - decreases the amount of mana consumed in equipped magical items // Formula: 100 / (100 + ) = 0.xxx modifier to magical item mana consumed public float GetManaReductionRating(int manaReductionRating) { return GetNegativeRatingMod(manaReductionRating); } // - Damage reduction rating - debuff applied to decrease the effective damage rating of the target // Formula: 100 / (100 + ) = 0.xxx modifier to outgoing damage public float GetDamageReductionRating(int damageReductionRating) { return GetNegativeRatingMod(damageReductionRating); } // - Healing reduction rating - debuff applied to decrease the effective healing rate of the target // Formula: 100 / (100 + ) = 0.xxx modifier to healing public float GetHealingReductionRating(int healingReductionRating) { return GetNegativeRatingMod(healingReductionRating); } // - Damage resistance reduction rating - debuff applied to decrease the effective damage resistance rating of the target // Formula: 100 / (100 + ) = 0.xxx modifier to incoming damage public float GetDamageResistanceReductionRating(int damageResistReduceRating) { return GetNegativeRatingMod(damageResistReduceRating); } // - Player Killer damage rating - increases all damage done to other players, including critical hits // Formula: (100 + / 100 = 1.xx modifier to PK damage public float GetPKDamageRating(int pkDamageRating) { return GetPositiveRatingMod(pkDamageRating); } // - Player Killer damage resistance rating - decreases all incoming damage done by other players, including critical hits // Formula: 100 / (100 + ) = 0.xxx modifier to incoming PK damage public float GetPKDamageResistanceRating(int pkDamageResistRating) { return GetNegativeRatingMod(pkDamageResistRating); } /// /// Converts a 1.xx modifier to a +x rating, /// or a 0.xx modifier to a -x rating. /// public static int ModToRating(float mod) { if (mod >= 1.0f) return (int)Math.Round(mod * 100 - 100); else return (int)Math.Round(-100 / mod + 100); } /// /// Returns a modifier to an implicitly negative rating (ie. damage resistance) /// public static int NegativeModToRating(float mod) { return -ModToRating(mod); } /// /// Combines rating modifiers additively /// /// A list of rating modifiers public static float AdditiveCombine(params float[] mods) { int totalRating = 0; foreach (var mod in mods) totalRating += ModToRating(mod); return GetRatingMod(totalRating); } public int GetDamageRating() { // get from base properties (monsters)? var damageRating = DamageRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.DamageRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearDamage); // weakness as negative damage rating? // TODO: this should be factored in as a separate weakness rating... var weaknessRating = EnchantmentManager.GetRating(PropertyInt.WeaknessRating); var augBonus = 0; var lumAugBonus = 0; if (this is Player player) { augBonus = player.AugmentationDamageBonus * 3; lumAugBonus = player.LumAugDamageRating; } // heritage / weapon type bonus factored in elsewhere? return damageRating + equipment + enchantments - weaknessRating + augBonus + lumAugBonus; } public int GetDamageResistRating(CombatType? combatType = null, bool directDamage = true) { // get from base properties (monsters)? var damageResistRating = DamageResistRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.DamageResistRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearDamageResist); // nether DoTs as negative DRR? // TODO: this should be factored in as a separate nether damage rating... var netherDotDamageRating = directDamage ? EnchantmentManager.GetNetherDotDamageRating() : 0; var augBonus = 0; var lumAugBonus = 0; var specBonus = 0; if (this is Player player) { augBonus = player.AugmentationDamageReduction * 3; lumAugBonus = player.LumAugDamageReductionRating; specBonus = GetSpecDefenseBonus(combatType); } return damageResistRating + equipment + enchantments - netherDotDamageRating + augBonus + lumAugBonus + specBonus; } public float GetDamageResistRatingMod(CombatType? combatType = null, bool directDamage = true) { var damageResistRating = GetDamageResistRating(combatType, directDamage); var allowBug = PropertyManager.GetBool("allow_negative_rating_curve").Item; return GetNegativeRatingMod(damageResistRating, allowBug); } public int GetSpecDefenseBonus(CombatType? combatType) { // https://asheron.fandom.com/wiki/Announcements_-_2013/02_-_Balance_of_Power // New bonus added to specialized defenses against damage of their respective attack type. (Applied in both PvE & PvP) // - Specialized Melee Defense skill now adds 1 Damage Rating Resist for every 60 pts against melee attacks // - Specialized Missile Defense skill now adds 1 Damage Rating Resist for every 50 pts against missile attacks // - Specialized Magic Defense skill now adds 1 Damage Rating Resist for every 50 pts against magic attacks // only applies to players if (combatType == null || !(this is Player player)) return 0; var skill = GetDefenseSkill(combatType.Value); var creatureSkill = player.GetCreatureSkill(skill); // ensure defense skill is specialized if (creatureSkill.AdvancementClass != SkillAdvancementClass.Specialized) return 0; var divisor = skill == Skill.MeleeDefense ? 60 : 50; // floor? return (int)creatureSkill.Base / divisor; } public int GetCritRating() { // crit chance // get from base properties (monsters)? var critChanceRating = CritRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.CritRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearCrit); // augmentations var augBonus = 0; if (this is Player player) augBonus = player.AugmentationCriticalExpertise; return critChanceRating + enchantments + equipment + augBonus; } public int GetCritDamageRating() { // get from base properties (monsters)? var critDamageRating = CritDamageRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.CritDamageRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearCritDamage); // augmentations var augBonus = 0; var lumAugBonus = 0; if (this is Player player) { augBonus = player.AugmentationCriticalPower * 3; lumAugBonus = player.LumAugCritDamageRating; } return critDamageRating + equipment + enchantments + augBonus + lumAugBonus; } public int GetCritResistRating() { // crit resist chance // get from base properties (monsters)? var critResistRating = CritResistRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.CritResistRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearCritResist); // no augs / lum augs? return critResistRating + enchantments + equipment; } public int GetCritDamageResistRating() { // get from base properties (monsters)? var critDamageResistRating = CritDamageResistRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.CritDamageResistRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearCritDamageResist); var lumAugBonus = 0; if (this is Player player) lumAugBonus = player.LumAugCritReductionRating; return critDamageResistRating + equipment + enchantments + lumAugBonus; } public int GetHealingBoostRating() { // get from base properties (monsters)? var healBoostRating = HealingBoostRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.HealingBoostRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearHealingBoost); var lumAugBonus = 0; if (this is Player player) lumAugBonus = player.LumAugHealingRating; return healBoostRating + equipment + enchantments + lumAugBonus; } public int GetHealingResistRating() { // debuff? var healResistRating = HealingResistRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.HealingResistRating); return healResistRating + enchantments; } public float GetHealingRatingMod() { var boostMod = GetPositiveRatingMod(GetHealingBoostRating()); var resistMod = GetNegativeRatingMod(GetHealingResistRating()); return boostMod * resistMod; } public int GetLifeResistRating() { // only affects health drain? // only cast by Sigil of Perserverance (Aetheria)? // get from base properties (monsters)? var lifeResistRating = LifeResistRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.LifeResistRating); return lifeResistRating + enchantments; } public float GetLifeResistRatingMod() { return GetNegativeRatingMod(GetLifeResistRating()); } public int GetDotResistanceRating() { // get from base properties (monsters)? var dotResistRating = DotResistRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.DotResistRating); return dotResistRating + enchantments; } public int GetNetherResistRating() { // there is a property defined for this, // but does anything use this? // get from base properties (monsters)? var netherResistRating = NetherResistRating ?? 0; // additive enchantments var enchantments = EnchantmentManager.GetRating(PropertyInt.NetherResistRating); return netherResistRating + enchantments; } public int GetGearMaxHealth() { return GetEquippedItemsRatingSum(PropertyInt.GearMaxHealth); } public int GetPKDamageRating() { var pkDamageRating = PKDamageRating ?? 0; // additive enchantments? var enchantments = EnchantmentManager.GetRating(PropertyInt.PKDamageRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearPKDamageRating); return pkDamageRating + equipment + enchantments; } public int GetPKDamageResistRating() { var pkDamageResistRating = PKDamageResistRating ?? 0; // additive enchantments? var enchantments = EnchantmentManager.GetRating(PropertyInt.PKDamageResistRating); // equipment ratings var equipment = GetEquippedItemsRatingSum(PropertyInt.GearPKDamageResistRating); return pkDamageResistRating + equipment + enchantments; } public int GetGearPKDamageRating() { return GetEquippedItemsRatingSum(PropertyInt.GearPKDamageRating); } public int GetGearPKDamageResistRating() { return GetEquippedItemsRatingSum(PropertyInt.GearPKDamageResistRating); } public int GetItemManaReductionRating() { // only comes from luminance aug? var lumAugBonus = 0; if (this is Player player) lumAugBonus = player.LumAugItemManaUsage; return lumAugBonus; } public int GetManaChargeRating() { // only comes from luminance aug? var lumAugBonus = 0; if (this is Player player) lumAugBonus = player.LumAugItemManaGain; return lumAugBonus; } } }