Advertisement
uhmm

Salvage.cs

Feb 3rd, 2022 (edited)
739
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 36.33 KB | None | 0 0
  1. namespace Turbo.plugins.patrick.hotkeys.actions.general {
  2.     using System;
  3.     using System.Collections.Generic;
  4.     using System.Linq;
  5.     using System.Windows.Forms;
  6.     using actions;
  7.     using parameters;
  8.     using parameters.types;
  9.     using plugins.patrick.util.logger;
  10.     using Plugins;
  11.     using util.diablo;
  12.     using util.input;
  13.     using util.thud;
  14.  
  15.     public partial class Salvage : AbstractHotkeyAction {
  16.         public override HotkeyType type => HotkeyType.General;
  17.  
  18.         public override string tooltip => "Salvage items by rules.";
  19.         protected override string GetAttributes() => $"[ SalvageUnknowns: {SalvageUnknowns}, ShouldKeppAllPrimals: {KeepAllPrimals}, LogAllActions: {LogAllActions}, DontReallySalvage: {DontReallySalvage}, DebugInfo1: {DebugInfo1}, DebugInfo2: {DebugInfo2}, ]";
  20.  
  21.         public bool SalvageUnknowns { get; set; } = false;
  22.         public bool KeepAllPrimals { get; set; } = true;
  23.         public bool LogAllActions { get; set; } = true;
  24.         public bool DontReallySalvage { get; set; } = false;
  25.         public bool DebugInfo1 { get; set; } = false;
  26.         public bool DebugInfo2 { get; set; } = false;
  27.  
  28.         private IController _hud;
  29.  
  30.         public override List<AbstractParameter> GetParameters() {
  31.             return new List<AbstractParameter> {
  32.                 SimpleParameter<bool>.of(nameof(SalvageUnknowns), x => SalvageUnknowns = x),
  33.                 SimpleParameter<bool>.of(nameof(KeepAllPrimals), x => KeepAllPrimals = x),
  34.                 SimpleParameter<bool>.of(nameof(LogAllActions), x => LogAllActions = x),
  35.                 SimpleParameter<bool>.of(nameof(DontReallySalvage), x => DontReallySalvage = x),
  36.                 SimpleParameter<bool>.of(nameof(DebugInfo1), x => DebugInfo1 = x),
  37.                 SimpleParameter<bool>.of(nameof(DebugInfo2), x => DebugInfo2 = x),
  38.             };
  39.         }
  40.  
  41.         public override bool PreconditionSatisfied(IController hud) {
  42.             return hud.Game.IsInTown && hud.Render.IsUiElementVisible(UiPathConstants.Blacksmith.UNIQUE_PAGE);
  43.         }
  44.  
  45.         public override void Invoke(IController hud) {
  46.             try {
  47.                 _hud = hud;
  48.                 _hud.Render.WaitForVisiblityAndClickOrAbortHotkeyEvent(UiPathConstants.Blacksmith.SALVAGE_PAGE, 200);
  49.                 _hud.Render.WaitForVisiblityAndClickOrAbortHotkeyEvent(UiPathConstants.Blacksmith.ANVIL);
  50.  
  51.                 foreach (var item in _hud.Inventory.ItemsInInventory.ToList()) {
  52.  
  53.                     if (shouldSalvageItem(item) && !DontReallySalvage) {
  54.                         _hud.Inventory.GetItemRect(item).Click();
  55.                         InputSimulator.PressKey(Keys.Enter);
  56.                         InputSimulator.PressKey(Keys.Enter);
  57.                     }
  58.                 }
  59.             } catch (Exception e) {
  60.                 hud.Debug(e.ToString());
  61.             }
  62.         }
  63.  
  64.         public bool shouldSalvageItem(IItem item) {
  65.             // Skip stackable items, i.e. gifts and gems
  66.             if (item.SnoItem.StackSize > 0) {
  67.                 return false;
  68.             }
  69.  
  70.             // Debug prints if needed
  71.             if (DebugInfo1) {
  72.                 debugPrintAllKnownStats(item);
  73.             }
  74.             if (DebugInfo2) {
  75.                 debugPrintAllStats(item);
  76.             }
  77.  
  78.             // Skip never-salvage items
  79.             if (NEVER_SALVAGE_LIST.Contains(item.SnoItem.NameEnglish)) {
  80.                 if (LogAllActions) {
  81.                     Logger.info($"Kept {item.SnoItem.NameEnglish} because it's in the never-salvage list.");
  82.                 }
  83.                 return false;
  84.             }
  85.  
  86.             // Skip armory set items
  87.             if (_hud.Game.Me.ArmorySets.Any(set => set.ContainsItem(item))) {
  88.                 if (LogAllActions) {
  89.                     Logger.info($"Kept {item.SnoItem.NameEnglish} because it's part of an Armory set.");
  90.                 }
  91.                 return false;
  92.             }
  93.  
  94.             // Salvage all non-legendaries
  95.             if (false == item.IsLegendary) {
  96.                 if (LogAllActions) {
  97.                     Logger.info($"Salvaged {item.SnoItem.NameEnglish} because it's non-legendary.");
  98.                 }
  99.                 return true;
  100.             }
  101.  
  102.             foreach (var stat in item.StatList) {
  103.                 if (stat.Id != null && stat.Attribute != null && stat.Attribute.Code != null) {
  104.                     if (stat.Attribute.Code.Equals("DyeType")) {
  105.                         if (LogAllActions) {
  106.                             Logger.info($"Kept {item.SnoItem.NameEnglish} because it's dyed and probably in use.");
  107.                         }
  108.                         return false;
  109.                     }
  110.                     if (stat.Attribute.Code.Equals("TransmogGBID")) {
  111.                         if (LogAllActions) {
  112.                             Logger.info($"Kept {item.SnoItem.NameEnglish} because it's transmogrified and probably in use.");
  113.                         }
  114.                         return false;
  115.                     }
  116.                     if (stat.Attribute.Code.Equals("EnchantedAffixCount")) {
  117.                         if (LogAllActions) {
  118.                             Logger.info($"Kept {item.SnoItem.NameEnglish} because it's enchanted and probably in use.");
  119.                         }
  120.                         return false;
  121.                     }
  122.                 }
  123.             }
  124.  
  125.             // Primal
  126.             if (KeepAllPrimals && item.AncientRank == 2) {
  127.                 if (LogAllActions) {
  128.                     Logger.info($"Kept {item.SnoItem.NameEnglish} because it's primal.");
  129.                 }
  130.                 return false;
  131.             }
  132.            
  133.             // Salvage all items by blacklist
  134.             if (ALWAYS_SALVAGE_LIST.Contains(item.SnoItem.NameEnglish)) {
  135.                 if (LogAllActions) {
  136.                     Logger.info($"Salvaged {item.SnoItem.NameEnglish} because it's always useless.");
  137.                 }
  138.                 return true;
  139.             }
  140.  
  141.             // Salvage all items by non-ancient blacklist
  142.             if (item.IsLegendary && item.AncientRank == 0 && NONANCIENT_SALVAGE_LIST.Contains(item.SnoItem.NameEnglish)) {
  143.                 if (LogAllActions) {
  144.                     Logger.info($"Salvaged {item.SnoItem.NameEnglish} because it's non-ancient.");
  145.                 }
  146.                 return true;
  147.             }
  148.  
  149.             bool shouldSalvageByDefault = SalvageUnknowns;
  150.  
  151.             // In my opinion, expected behavior for
  152.             if (item.AncientRank > 0 && NONANCIENT_SALVAGE_LIST.Contains(item.SnoItem.NameEnglish)) {
  153.                 shouldSalvageByDefault = false;
  154.             }
  155.  
  156.             var decisionMethod = typeof(Salvage).GetMethod($"is{item.SnoItem.NameEnglish.Replace("'", "").Replace(" ", "").Replace("-", "")}Good");
  157.            if (decisionMethod == null) {
  158.                // Couldn't make a decision for the item, go to default.
  159.                 if (shouldSalvageByDefault) {
  160.                     if (LogAllActions) {
  161.                         Logger.info($"Salvaged {item.SnoItem.NameEnglish} by default.");
  162.                     }
  163.                     return true;
  164.                 } else {
  165.                     if (LogAllActions) {
  166.                         Logger.info($"Kept {item.SnoItem.NameEnglish} by default.");
  167.                     }
  168.                     return false;
  169.                 }
  170.             } else {
  171.                 // Make the decision according to the instructions.
  172.                 if ((bool)decisionMethod.Invoke(this, new object[] { item })) {
  173.                     if (LogAllActions) {
  174.                         Logger.info($"Kept {item.SnoItem.NameEnglish} because it's good.");
  175.                     }
  176.                     return false;
  177.                 } else {
  178.                     if (LogAllActions) {
  179.                         Logger.info($"Salvaged {item.SnoItem.NameEnglish} because it's bad.");
  180.                     }
  181.                     return true;
  182.                 }
  183.             }
  184.         }
  185.  
  186.  
  187.         private static void debugPrintAllKnownStats(IItem item) {
  188.             Logger.info($"Known stat list for \"{item.SnoItem.NameEnglish}\":");
  189.             if (getGemLevel(item) > 0) { Logger.info($"\tGemLevel = {getGemLevel(item)}"); }
  190.             if (getLegendaryAffix(item) > 0) { Logger.info($"\tLegendaryAffix = {getLegendaryAffix(item)}"); }
  191.             if (getStrength(item) > 0) { Logger.info($"\tStrength = {getStrength(item)}"); }
  192.             if (getDexterity(item) > 0) { Logger.info($"\tDexterity = {getDexterity(item)}"); }
  193.             if (getIntelligence(item) > 0) { Logger.info($"\tIntelligence = {getIntelligence(item)}"); }
  194.             if (getVitality(item) > 0) { Logger.info($"\tVitality = {getVitality(item)}"); }
  195.             if (getResistanceAnySecondary(item) > 0) { Logger.info($"\tResistanceAnySecondary = {getResistanceAnySecondary(item)}"); }
  196.             if (getResistancePhysical(item) > 0) { Logger.info($"\tResistancePhysical = {getResistancePhysical(item)}"); }
  197.             if (getResistanceFire(item) > 0) { Logger.info($"\tResistanceFire = {getResistanceFire(item)}"); }
  198.             if (getResistanceLightning(item) > 0) { Logger.info($"\tResistanceLightning = {getResistanceLightning(item)}"); }
  199.             if (getResistanceCold(item) > 0) { Logger.info($"\tResistanceCold = {getResistanceCold(item)}"); }
  200.             if (getResistancePoison(item) > 0) { Logger.info($"\tResistancePoison = {getResistancePoison(item)}"); }
  201.             if (getResistanceArcane(item) > 0) { Logger.info($"\tResistanceArcane = {getResistanceArcane(item)}"); }
  202.             if (getAllResistance(item) > 0) { Logger.info($"\tAllResistance = {getAllResistance(item)}"); }
  203.             if (getLifePercentIncrease(item) > 0) { Logger.info($"\tLifePercentIncrease = {getLifePercentIncrease(item)}"); }
  204.             if (getLifePerKill(item) > 0) { Logger.info($"\tLifePerKill = {getLifePerKill(item)}"); }
  205.             if (getLifePerHit(item) > 0) { Logger.info($"\tLifePerHit = {getLifePerHit(item)}"); }
  206.             if (getLifePerSecond(item) > 0) { Logger.info($"\tLifePerSecond = {getLifePerSecond(item)}"); }
  207.             if (getHealthGlobeBonus(item) > 0) { Logger.info($"\tHealthGlobeBonus = {getHealthGlobeBonus(item)}"); }
  208.             if (getPickupRadius(item) > 0) { Logger.info($"\tPickupRadius = {getPickupRadius(item)}"); }
  209.             if (getGoldFindBonus(item) > 0) { Logger.info($"\tGoldFindBonus = {getGoldFindBonus(item)}"); }
  210.             if (getElementalDamageBonusAny(item) > 0) { Logger.info($"\tElementalDamageBonusAny = {getElementalDamageBonusAny(item)}"); }
  211.             if (getElementalDamageBonusPhysical(item) > 0) { Logger.info($"\tElementalDamageBonusPhysical = {getElementalDamageBonusPhysical(item)}"); }
  212.             if (getElementalDamageBonusFire(item) > 0) { Logger.info($"\tElementalDamageBonusFire = {getElementalDamageBonusFire(item)}"); }
  213.             if (getElementalDamageBonusLightning(item) > 0) { Logger.info($"\tElementalDamageBonusLightning = {getElementalDamageBonusLightning(item)}"); }
  214.             if (getElementalDamageBonusCold(item) > 0) { Logger.info($"\tElementalDamageBonusCold = {getElementalDamageBonusCold(item)}"); }
  215.             if (getElementalDamageBonusPoison(item) > 0) { Logger.info($"\tElementalDamageBonusPoison = {getElementalDamageBonusPoison(item)}"); }
  216.             if (getElementalDamageBonusArcane(item) > 0) { Logger.info($"\tElementalDamageBonusArcane = {getElementalDamageBonusArcane(item)}"); }
  217.             if (getElementalDamageBonusHoly(item) > 0) { Logger.info($"\tElementalDamageBonusHoly = {getElementalDamageBonusHoly(item)}"); }
  218.             if (getCriticalHitDamage(item) > 0) { Logger.info($"\tCriticalHitDamage = {getCriticalHitDamage(item)}"); }
  219.             if (getCriticalHitChance(item) > 0) { Logger.info($"\tCriticalHitChance = {getCriticalHitChance(item)}"); }
  220.             if (getMeleeDamageReduction(item) > 0) { Logger.info($"\tMeleeDamageReduction = {getMeleeDamageReduction(item)}"); }
  221.             if (getRangedDamageReduction(item) > 0) { Logger.info($"\tRangedDamageReduction = {getRangedDamageReduction(item)}"); }
  222.             if (getEliteDamageIncrease(item) > 0) { Logger.info($"\tEliteDamageIncrease = {getEliteDamageIncrease(item)}"); }
  223.             if (getEliteDamageReduction(item) > 0) { Logger.info($"\tEliteDamageReduction = {getEliteDamageReduction(item)}"); }
  224.             if (getExperienceBonusFlat(item) > 0) { Logger.info($"\tExperienceBonusFlat = {getExperienceBonusFlat(item)}"); }
  225.             if (getExperienceBonusPercent(item) > 0) { Logger.info($"\tExperienceBonusPercent = {getExperienceBonusPercent(item)}"); }
  226.             if (getResourceCostReduction(item) > 0) { Logger.info($"\tResourceCostReduction = {getResourceCostReduction(item)}"); }
  227.             if (getCooldownReduction(item) > 0) { Logger.info($"\tCooldownReduction = {getCooldownReduction(item)}"); }
  228.             if (getSockets(item) > 0) { Logger.info($"\tSockets = {getSockets(item)}"); }
  229.             if (getAreaDamage(item) > 0) { Logger.info($"\tAreaDamage = {getAreaDamage(item)}"); }
  230.             if (getThorns(item) > 0) { Logger.info($"\tThorns = {getThorns(item)}"); }
  231.             if (getBaseArmor(item) > 0) { Logger.info($"\tBaseArmor = {getBaseArmor(item)}"); }
  232.             if (getArmorBonus(item) > 0) { Logger.info($"\tArmorBonus = {getArmorBonus(item)}"); }
  233.             if (getAttackSpeedBonus(item) > 0) { Logger.info($"\tAttackSpeedBonus = {getAttackSpeedBonus(item)}"); }
  234.             if (getAverageDamageIncrease(item) > 0) { Logger.info($"\tAverageDamageIncrease = {getAverageDamageIncrease(item)}"); }
  235.             if (getChanceToBleedOnHit(item) > 0) { Logger.info($"\tChanceToBleedOnHit = {getChanceToBleedOnHit(item)}"); }
  236.             if (getChanceToChillOnHit(item) > 0) { Logger.info($"\tChanceToChillOnHit = {getChanceToChillOnHit(item)}"); }
  237.             if (getChanceToSlowOnHit(item) > 0) { Logger.info($"\tChanceToSlowOnHit = {getChanceToSlowOnHit(item)}"); }
  238.             if (getChanceToStunOnHit(item) > 0) { Logger.info($"\tChanceToStunOnHit = {getChanceToStunOnHit(item)}"); }
  239.             if (getChanceToKnockbackOnHit(item) > 0) { Logger.info($"\tChanceToKnockbackOnHit = {getChanceToKnockbackOnHit(item)}"); }
  240.             if (getChanceToFreezeOnHit(item) > 0) { Logger.info($"\tChanceToFreezeOnHit = {getChanceToFreezeOnHit(item)}"); }
  241.             if (getChanceToBlindOnHit(item) > 0) { Logger.info($"\tChanceToBlindOnHit = {getChanceToBlindOnHit(item)}"); }
  242.             if (getChanceToFearOnHit(item) > 0) { Logger.info($"\tChanceToFearOnHit = {getChanceToFearOnHit(item)}"); }
  243.             if (getChanceToImmobilizeOnHit(item) > 0) { Logger.info($"\tChanceToImmobilizeOnHit = {getChanceToImmobilizeOnHit(item)}"); }
  244.             if (getDamagePercentBonus(item) > 0) { Logger.info($"\tDamagePercentBonus = {getDamagePercentBonus(item)}"); }
  245.             if (getSkillDamageAny(item) > 0) { Logger.info($"\tSkillDamageAny = {getSkillDamageAny(item)}"); }
  246.         }
  247.  
  248.         // Print all stats in item.StatList.
  249.         private static void debugPrintAllStats(IItem item) {
  250.             Logger.info($"Full stat list for \"{item.SnoItem.NameEnglish}\":");
  251.             foreach (var stat in item.StatList) {
  252.                 if (stat.Id != null && stat.Attribute != null && stat.Attribute.Code != null) {
  253.                     Logger.info($"\tID: {stat.Id}, Code: {stat.Attribute.Code}, Value: {stat.DoubleValue}");
  254.                 }
  255.             }
  256.         }
  257.  
  258.         // Find a stat of the item by its attributes - "Code" and "Id". Can warn if found a stat with "Code" but
  259.         // couldn't find one that also had the correct "Id", for debugging purposes.
  260.         private static IItemStat getStatByName(IItem item, string idToFind, string codeToFind, bool warnOnMismatch = true) {
  261.             IItemStat statWithOneCorrect = null;
  262.             foreach (var stat in item.StatList) {
  263.                 if (stat.Id != null && stat.Attribute != null) {
  264.                     bool foundId = (idToFind == null) || (stat.Id.Equals(idToFind));
  265.                     bool foundCode = (codeToFind == null) || (stat.Attribute.Code.Equals(codeToFind));
  266.                     if (foundId && foundCode) {
  267.                         return stat;
  268.                     } else if ((idToFind != null) && (codeToFind != null) && (foundId || foundCode)) {
  269.                         statWithOneCorrect = stat;
  270.                     }
  271.                 }
  272.             }
  273.             if (warnOnMismatch && (statWithOneCorrect != null)) {
  274.                 Logger.warn($"Asked for stat with (id={idToFind}, code={codeToFind}) but could only find (id={statWithOneCorrect.Id}, code={statWithOneCorrect.Attribute.Code}).");
  275.             }
  276.             return null;
  277.         }
  278.  
  279.         // Many stats with percent values appear with an approximate fraction value such as 0.90021 to represent 90%.
  280.         private static int roundPercentStat(double value) {
  281.             return (int)Math.Round(value * 100);
  282.         }
  283.  
  284.         // get the rank of a legendary gem or soul shard (1-150), or 0 if it's 0 or isn't a gem.
  285.         private static int getGemLevel(IItem item) {
  286.             IItemStat stat = getStatByName(item, "jewel_rank", null);
  287.             return stat == null ? 0 : (int)stat.DoubleValue;
  288.         }
  289.  
  290.         // get the value of the legendary affix of an item. Percentage affixess will appear as fractions (0.1=10%). Won't work for Leoric's Crown. Might be 1 or 0 for items with a fixed affix or no affix.
  291.         private static double getLegendaryAffix(IItem item) {
  292.             IItemStat stat = getStatByName(item, null,
  293.                 item.SnoItem.NameEnglish.Equals("Leoric's Crown") ? "Gem_Attributes_Multiplier" : "Item_Power_Passive");
  294.             return stat == null ? 0 : stat.DoubleValue;
  295.         }
  296.  
  297.         // get the value of the strength bonus primary stat of an item, or 0 if it doesn't exist.
  298.         private static int getStrength(IItem item) {
  299.             IItemStat stat = getStatByName(item, "str", null);
  300.             return stat == null ? 0 : (int)stat.DoubleValue;
  301.         }
  302.  
  303.         // get the value of the dexterity bonus primary stat of an item, or 0 if it doesn't exist.
  304.         private static int getDexterity(IItem item) {
  305.             IItemStat stat = getStatByName(item, "dex", null);
  306.             return stat == null ? 0 : (int)stat.DoubleValue;
  307.         }
  308.  
  309.         // get the value of the intelligence bonus primary stat of an item, or 0 if it doesn't exist.
  310.         private static int getIntelligence(IItem item) {
  311.             IItemStat stat = getStatByName(item, "int", null);
  312.             return stat == null ? 0 : (int)stat.DoubleValue;
  313.         }
  314.  
  315.         // get the value of the vitality bonus primary stat of an item, or 0 if it doesn't exist.
  316.         private static int getVitality(IItem item) {
  317.             IItemStat stat = getStatByName(item, "vita", null);
  318.             return stat == null ? 0 : (int)stat.DoubleValue;
  319.         }
  320.  
  321.         // get the value of the secondary resistance stat on the item, or 0 if it doesn't exist.
  322.         private static int getResistanceAnySecondary(IItem item) {
  323.             IItemStat stat = getStatByName(item, "anyres", null);
  324.             return stat == null ? 0 : (int)stat.DoubleValue;
  325.         }
  326.  
  327.         // get the value of the physical resistance secondary stat on the item, or 0 if it doesn't exist.
  328.         private static int getResistancePhysical(IItem item) {
  329.             IItemStat stat = getStatByName(item, "ph_res", null);
  330.             return stat == null ? 0 : (int)stat.DoubleValue;
  331.         }
  332.  
  333.         // get the value of the fire resistance secondary stat on the item, or 0 if it doesn't exist.
  334.         private static int getResistanceFire(IItem item) {
  335.             IItemStat stat = getStatByName(item, "f_res", null);
  336.             return stat == null ? 0 : (int)stat.DoubleValue;
  337.         }
  338.  
  339.         // get the value of the lightning resistance secondary stat on the item, or 0 if it doesn't exist.
  340.         private static int getResistanceLightning(IItem item) {
  341.             IItemStat stat = getStatByName(item, "l_res", null);
  342.             return stat == null ? 0 : (int)stat.DoubleValue;
  343.         }
  344.  
  345.         // get the value of the cold resistance secondary stat on the item, or 0 if it doesn't exist.
  346.         private static int getResistanceCold(IItem item) {
  347.             IItemStat stat = getStatByName(item, "c_res", null);
  348.             return stat == null ? 0 : (int)stat.DoubleValue;
  349.         }
  350.  
  351.         // get the value of the poison resistance secondary stat on the item, or 0 if it doesn't exist.
  352.         private static int getResistancePoison(IItem item) {
  353.             IItemStat stat = getStatByName(item, "p_res", null);
  354.             return stat == null ? 0 : (int)stat.DoubleValue;
  355.         }
  356.  
  357.         // get the value of the arcane (and holy) resistance secondary stat on the item, or 0 if it doesn't exist.
  358.         private static int getResistanceArcane(IItem item) {
  359.             IItemStat stat = getStatByName(item, "a_res", null);
  360.             return stat == null ? 0 : (int)stat.DoubleValue;
  361.         }
  362.  
  363.         // get the value of the primary resistance to all elements stat on the item, or 0 if it doesn't exist.
  364.         private static int getAllResistance(IItem item) {
  365.             IItemStat stat = getStatByName(item, "allres", null);
  366.             return stat == null ? 0 : (int)stat.DoubleValue;
  367.         }
  368.  
  369.         // get the value of the primary Life% increase (10%-15% usually), or 0 if it doesn't exist.
  370.         private static int getLifePercentIncrease(IItem item) {
  371.             IItemStat stat = getStatByName(item, "life", null);
  372.             return stat == null ? 0 : (int)stat.DoubleValue;
  373.         }
  374.  
  375.         // get the value of the LPK secondary stat on the item, or 0 if it doesn't exist.
  376.         private static int getLifePerKill(IItem item) {
  377.             IItemStat stat = getStatByName(item, "lok", null);
  378.             return stat == null ? 0 : (int)stat.DoubleValue;
  379.         }
  380.  
  381.         // get the value of the LPH primary stat on the item, usually found on bracers/weapon, or 0 if it doesn't exist.
  382.         private static int getLifePerHit(IItem item) {
  383.             IItemStat stat = getStatByName(item, "loh", null);
  384.             return stat == null ? 0 : (int)stat.DoubleValue;
  385.         }
  386.  
  387.         // get the value of the LPS primary stat on the item, or 0 if it doesn't exist.
  388.         private static int getLifePerSecond(IItem item) {
  389.             IItemStat stat = getStatByName(item, "hpreg", null);
  390.             return stat == null ? 0 : (int)stat.DoubleValue;
  391.         }
  392.  
  393.         // get the value of the secondary health globe bonus stat on the item, or 0 if it doesn't exist.
  394.         private static int getHealthGlobeBonus(IItem item) {
  395.             IItemStat stat = getStatByName(item, "hpglobe", null);
  396.             return stat == null ? 0 : (int)stat.DoubleValue;
  397.         }
  398.  
  399.         // get the value of the secondary bonus to pickup radius stat on the item, usually 1-2 but could be 4-6 on Rondal's Locket, or 0 if it doesn't exist.
  400.         private static int getPickupRadius(IItem item) {
  401.             IItemStat stat = getStatByName(item, "pickup", null);
  402.             return stat == null ? 0 : (int)stat.DoubleValue;
  403.         }
  404.  
  405.         // get the value of the secondary bonus to gold find on the item, or 0 if it doesn't exist.
  406.         private static int getGoldFindBonus(IItem item) {
  407.             IItemStat stat = getStatByName(item, "gf", null);
  408.             return stat == null ? 0 : (int)stat.DoubleValue;
  409.         }
  410.  
  411.         // get the value of the primary elemental damage increase bonus for any element on the item, or 0 if it doesn't exist.
  412.         private static int getElementalDamageBonusAny(IItem item) {
  413.             IItemStat stat = getStatByName(item, "sdmg_any", null);
  414.             return stat == null ? 0 : (int)stat.DoubleValue;
  415.         }
  416.  
  417.         // get the value of the primary physical damage increase bonus on the item, or 0 if it doesn't exist.
  418.         private static int getElementalDamageBonusPhysical(IItem item) {
  419.             IItemStat stat = getStatByName(item, "sdmg_ph", null);
  420.             return stat == null ? 0 : (int)stat.DoubleValue;
  421.         }
  422.  
  423.         // get the value of the primary fire damage increase bonus on the item, or 0 if it doesn't exist.
  424.         private static int getElementalDamageBonusFire(IItem item) {
  425.             IItemStat stat = getStatByName(item, "sdmg_f", null);
  426.             return stat == null ? 0 : (int)stat.DoubleValue;
  427.         }
  428.  
  429.         // get the value of the primary lightning damage increase bonus on the item, or 0 if it doesn't exist.
  430.         private static int getElementalDamageBonusLightning(IItem item) {
  431.             IItemStat stat = getStatByName(item, "sdmg_l", null);
  432.             return stat == null ? 0 : (int)stat.DoubleValue;
  433.         }
  434.  
  435.         // get the value of the primary cold damage increase bonus on the item, or 0 if it doesn't exist.
  436.         private static int getElementalDamageBonusCold(IItem item) {
  437.             IItemStat stat = getStatByName(item, "sdmg_c", null);
  438.             return stat == null ? 0 : (int)stat.DoubleValue;
  439.         }
  440.  
  441.         // get the value of the primary poison damage increase bonus on the item, or 0 if it doesn't exist.
  442.         private static int getElementalDamageBonusPoison(IItem item) {
  443.             IItemStat stat = getStatByName(item, "sdmg_p", null);
  444.             return stat == null ? 0 : (int)stat.DoubleValue;
  445.         }
  446.  
  447.         // get the value of the primary arcane damage increase bonus on the item, or 0 if it doesn't exist.
  448.         private static int getElementalDamageBonusArcane(IItem item) {
  449.             IItemStat stat = getStatByName(item, "sdmg_a", null);
  450.             return stat == null ? 0 : (int)stat.DoubleValue;
  451.         }
  452.  
  453.         // get the value of the primary holy damage increase bonus on the item, or 0 if it doesn't exist.
  454.         private static int getElementalDamageBonusHoly(IItem item) {
  455.             IItemStat stat = getStatByName(item, "sdmg_h", null);
  456.             return stat == null ? 0 : (int)stat.DoubleValue;
  457.         }
  458.  
  459.         // get the value of the primary CHD stat on the item, or 0 if it doesn't exist.
  460.         private static int getCriticalHitDamage(IItem item) {
  461.             IItemStat stat = getStatByName(item, "critdmg", null);
  462.             return stat == null ? 0 : (int)stat.DoubleValue;
  463.         }
  464.  
  465.         // get the value of the primary CHC stat on the item, or 0 if it doesn't exist.
  466.         private static double getCriticalHitChance(IItem item) {
  467.             IItemStat stat = getStatByName(item, "crit", null);
  468.             return stat == null ? 0 : stat.DoubleValue;
  469.         }
  470.  
  471.         // get the value of the primary/secondary reduced damage from melee attacks on the item, or 0 if neither exist.
  472.         private static int getMeleeDamageReduction(IItem item) {
  473.             IItemStat stat = getStatByName(item, null, "Damage_Percent_Reduction_From_Melee");
  474.             return stat == null ? 0 : roundPercentStat(stat.DoubleValue);
  475.         }
  476.  
  477.         // get the value of the primary/secondary reduced damage from ranged attacks on the item, or 0 if neither exist.
  478.         private static int getRangedDamageReduction(IItem item) {
  479.             IItemStat stat = getStatByName(item, null, "Damage_Percent_Reduction_From_Ranged");
  480.             return stat == null ? 0 : roundPercentStat(stat.DoubleValue);
  481.         }
  482.  
  483.         // get the value of the primary damage increase to elites stat on the item, or 0 if it doesn't exist.
  484.         private static int getEliteDamageIncrease(IItem item) {
  485.             IItemStat stat = getStatByName(item, "elitedam", null);
  486.             return stat == null ? 0 : (int)stat.DoubleValue;
  487.         }
  488.  
  489.         // get the value of the primary damage reduction from elites stat on the item, or 0 if it doesn't exist.
  490.         private static int getEliteDamageReduction(IItem item) {
  491.             IItemStat stat = getStatByName(item, "elitedamred", null);
  492.             return stat == null ? 0 : (int)stat.DoubleValue;
  493.         }
  494.  
  495.         // get the value of the secondary bonus to experience per monster killed stat on the item, or 0 if it doens't exist.
  496.         private static int getExperienceBonusFlat(IItem item) {
  497.             IItemStat stat = getStatByName(item, "expbonus", null);
  498.             return stat == null ? 0 : (int)stat.DoubleValue;
  499.         }
  500.  
  501.         // get the value of the primary percent bonus to experience stat, found on Soul Shards, or 0 if it doesn't exist.
  502.         private static int getExperienceBonusPercent(IItem item) {
  503.             IItemStat stat = getStatByName(item, null, "Experience_Bonus_Percent");
  504.             return stat == null ? 0 : roundPercentStat(stat.DoubleValue);
  505.         }
  506.  
  507.         // get the value of the primary RCR stat on the item, or 0 if it doesn't exist.
  508.         private static int getResourceCostReduction(IItem item) {
  509.             IItemStat stat = getStatByName(item, "rescostred", null);
  510.             return stat == null ? 0 : (int)stat.DoubleValue;
  511.         }
  512.  
  513.         // get the value of the primary CDR stat on the item, or 0 if it doesn't exist.
  514.         private static int getCooldownReduction(IItem item) {
  515.             IItemStat stat = getStatByName(item, "cdred", null);
  516.             return stat == null ? 0 : (int)stat.DoubleValue;
  517.         }
  518.  
  519.         // get the value of the percent increase to area damage primary stat on the item, or 0 if it doesn't exist.
  520.         private static int getSockets(IItem item) {
  521.             IItemStat stat = getStatByName(item, "sock", null);
  522.             return stat == null ? 0 : (stat.IntegerValue ?? 0);
  523.         }
  524.  
  525.         // get the value of the percent increase to area damage primary stat on the item, or 0 if it doesn't exist.
  526.         private static int getAreaDamage(IItem item) {
  527.             IItemStat stat = getStatByName(item, "areadmg", null);
  528.             return stat == null ? 0 : (int)stat.DoubleValue;
  529.         }
  530.  
  531.         // get the value of the thorns primary/secondary stat on the item, or 0 if it doesn't exist.
  532.         private static int getThorns(IItem item) {
  533.             IItemStat stat = getStatByName(item, "thorns", null);
  534.             return stat == null ? 0 : (int)stat.DoubleValue;
  535.         }
  536.  
  537.         // get the value of the base armor of the item.
  538.         private static int getBaseArmor(IItem item) {
  539.             IItemStat stat = getStatByName(item, "b_armor", null);
  540.             return stat == null ? 0 : (int)stat.DoubleValue;
  541.         }
  542.  
  543.         // get the value of the armor bonus primary stat on the item, or 0 if it doesn't exist.
  544.         private static int getArmorBonus(IItem item) {
  545.             IItemStat stat = getStatByName(item, "e_armor", null);
  546.             return stat == null ? 0 : (int)stat.DoubleValue;
  547.         }
  548.  
  549.         // get the attack speed bonus primary stat, usually 5%-7% on weapons/gloves/jewelry.
  550.         private static int getAttackSpeedBonus(IItem item) {
  551.             // check for weapon attack speed first, then for gloves/jewelry.
  552.             IItemStat stat = getStatByName(item, "as_extr", null);
  553.             if (stat == null) {
  554.                 stat = getStatByName(item, "ias", null);
  555.                 if (stat == null) {
  556.                     return 0;
  557.                 }
  558.             }
  559.             return (int)stat.DoubleValue;
  560.         }
  561.  
  562.         // Get the flat physical damage increase, usually appears on jewelry and offhands.
  563.         // The ranges for normal/ancient jewelry/offhands are 90-120, 128-157.5, 360-410 and 451-542.5 respectively.
  564.         private static double getAverageDamageIncrease(IItem item) {
  565.             IItemStat stat = getStatByName(item, null, "Damage_Average_Total_All");
  566.             return stat == null ? 0 : stat.DoubleValue;
  567.         }
  568.  
  569.         // get primary chance to bleed on weapon/offhand.
  570.         private static double getChanceToBleedOnHit(IItem item) {
  571.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Bleed_Proc_Chance");
  572.             if (stat == null) {
  573.                 stat = getStatByName(item, null, "On_Hit_Bleed_Proc_Chance");
  574.                 if (stat == null) {
  575.                     return 0;
  576.                 }
  577.             }
  578.             return stat.DoubleValue;
  579.         }
  580.  
  581.         // get secondary chance to CC on hit for weapons/armor.
  582.         private static double getChanceToChillOnHit(IItem item) {
  583.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Chill_Proc_Chance");
  584.             if (stat == null) {
  585.                 stat = getStatByName(item, null, "On_Hit_Chill_Proc_Chance");
  586.                 if (stat == null) {
  587.                     return 0;
  588.                 }
  589.             }
  590.             return stat.DoubleValue;
  591.         }
  592.         private static double getChanceToSlowOnHit(IItem item) {
  593.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Slow_Proc_Chance");
  594.             if (stat == null) {
  595.                 stat = getStatByName(item, null, "On_Hit_Slow_Proc_Chance");
  596.                 if (stat == null) {
  597.                     return 0;
  598.                 }
  599.             }
  600.             return stat.DoubleValue;
  601.         }
  602.         private static double getChanceToStunOnHit(IItem item) {
  603.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Stun_Proc_Chance");
  604.             if (stat == null) {
  605.                 stat = getStatByName(item, null, "On_Hit_Stun_Proc_Chance");
  606.                 if (stat == null) {
  607.                     return 0;
  608.                 }
  609.             }
  610.             return stat.DoubleValue;
  611.         }
  612.         private static double getChanceToKnockbackOnHit(IItem item) {
  613.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Knockback_Proc_Chance");
  614.             if (stat == null) {
  615.                 stat = getStatByName(item, null, "On_Hit_Knockback_Proc_Chance");
  616.                 if (stat == null) {
  617.                     return 0;
  618.                 }
  619.             }
  620.             return stat.DoubleValue;
  621.         }
  622.         private static double getChanceToFreezeOnHit(IItem item) {
  623.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Freeze_Proc_Chance");
  624.             if (stat == null) {
  625.                 stat = getStatByName(item, null, "On_Hit_Freeze_Proc_Chance");
  626.                 if (stat == null) {
  627.                     return 0;
  628.                 }
  629.             }
  630.             return stat.DoubleValue;
  631.         }
  632.         private static double getChanceToBlindOnHit(IItem item) {
  633.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Blind_Proc_Chance");
  634.             if (stat == null) {
  635.                 stat = getStatByName(item, null, "On_Hit_Blind_Proc_Chance");
  636.                 if (stat == null) {
  637.                     return 0;
  638.                 }
  639.             }
  640.             return stat.DoubleValue;
  641.         }
  642.         private static double getChanceToFearOnHit(IItem item) {
  643.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Fear_Proc_Chance");
  644.             if (stat == null) {
  645.                 stat = getStatByName(item, null, "On_Hit_Fear_Proc_Chance");
  646.                 if (stat == null) {
  647.                     return 0;
  648.                 }
  649.             }
  650.             return stat.DoubleValue;
  651.         }
  652.         private static double getChanceToImmobilizeOnHit(IItem item) {
  653.             IItemStat stat = getStatByName(item, null, "Weapon_On_Hit_Immobilize_Proc_Chance");
  654.             if (stat == null) {
  655.                 stat = getStatByName(item, null, "On_Hit_Immobilize_Proc_Chance");
  656.                 if (stat == null) {
  657.                     return 0;
  658.                 }
  659.             }
  660.             return stat.DoubleValue;
  661.         }
  662.  
  663.         // get +6%-10% (or 12%-15% on Soul Shards) damage bonus on weapon primary stat.
  664.         private static int getDamagePercentBonus(IItem item) {
  665.             IItemStat stat = getStatByName(item, "dmg_pbonus", null);
  666.             return stat == null ? 0 : (int)stat.DoubleValue;
  667.         }
  668.  
  669.         // Get the % skill damage increase stat, usually 10%-15% on armor pieces and offhands. Pretty useless.
  670.         private static int getSkillDamageAny(IItem item) {
  671.             IItemStat stat = getStatByName(item, "skilldmg", null);
  672.             return stat == null ? 0 : (int)stat.DoubleValue;
  673.         }
  674.  
  675.         // Use this way:    getSkillDamageSpecific(item, _hud.Sno.SnoPowers.WitchDoctor_Gargantuan.Sno);
  676.         // or this way:     getSkillDamageSpecific(item, 30624);
  677.         private static int getSkillDamageSpecific(IItem item, uint skillSno) {
  678.             IItemStat stat = getStatByName(item, $"Power_Damage_Percent_Bonus#{skillSno}", null);
  679.             return stat == null ? 0 : roundPercentStat(stat.DoubleValue);
  680.         }
  681.  
  682.     }
  683. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement