public PickupItem(ACDItem item, TrinityItemBaseType trinityItemBaseType, TrinityItemType trinityItemType) { Name = item.Name; InternalName = Trinity.NameNumberTrimRegex.Replace(item.InternalName, ""); ; Level = item.Level; Quality = item.ItemQualityLevel; BalanceID = item.GameBalanceId; DBBaseType = item.ItemBaseType; DBItemType = item.ItemType; TBaseType = trinityItemBaseType; TType = trinityItemType; IsOneHand = item.IsOneHand; IsTwoHand = item.IsTwoHand; ItemFollowerType = item.FollowerSpecialType; DynamicID = item.DynamicId; ActorSNO = item.ActorSNO; ACDGuid = item.ACDGuid; WorldId = Trinity.Player.WorldID; }
public PickupItem(ACDItem item, TrinityItemBaseType trinityItemBaseType, TrinityItemType trinityItemType) { Name = item.Name; InternalName = Trinity.NameNumberTrimRegex.Replace(item.InternalName, "");; Level = item.Level; Quality = item.ItemQualityLevel; BalanceID = item.GameBalanceId; DBBaseType = item.ItemBaseType; DBItemType = item.ItemType; TBaseType = trinityItemBaseType; TType = trinityItemType; IsOneHand = item.IsOneHand; IsTwoHand = item.IsTwoHand; ItemFollowerType = item.FollowerSpecialType; DynamicID = item.DynamicId; ActorSNO = item.ActorSNO; ACDGuid = item.ACDGuid; WorldId = Trinity.Player.WorldID; }
public static ActorClass GetClassRestriction(TrinityItemType type) { switch (type) { case TrinityItemType.Flail: case TrinityItemType.CrusaderShield: case TrinityItemType.TwoHandFlail: return(ActorClass.Crusader); case TrinityItemType.FistWeapon: case TrinityItemType.SpiritStone: case TrinityItemType.TwoHandDaibo: return(ActorClass.Monk); case TrinityItemType.VoodooMask: case TrinityItemType.Mojo: case TrinityItemType.CeremonialKnife: return(ActorClass.Witchdoctor); case TrinityItemType.MightyBelt: case TrinityItemType.MightyWeapon: return(ActorClass.Barbarian); case TrinityItemType.WizardHat: case TrinityItemType.Orb: return(ActorClass.Wizard); case TrinityItemType.Scythe: case TrinityItemType.TwoHandScythe: case TrinityItemType.Phylactery: return(ActorClass.Necromancer); case TrinityItemType.HandCrossbow: case TrinityItemType.Cloak: case TrinityItemType.Quiver: case TrinityItemType.TwoHandBow: case TrinityItemType.TwoHandCrossbow: return(ActorClass.DemonHunter); } return(ActorClass.Invalid); }
/// <summary> /// The bizarre mystery function to score your lovely items! /// </summary> /// <param name="item"></param> /// <param name="itemType"></param> /// <returns></returns> internal static double ValueThisItem(CachedACDItem item, TrinityItemType itemType) { // Reset static variables TotalItemPoints = 0; IsInvalidItem = true; ItemMaxStats = new double[Constants.TOTALSTATS]; ItemMaxPoints = new double[Constants.TOTALSTATS]; baseItemType = TrinityItemManager.DetermineBaseType(itemType); BestFinalBonus = 1d; HadStat = new double[Constants.TOTALSTATS] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; HadPoints = new double[Constants.TOTALSTATS] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; SafeLifePercentage = 0; SocketsCanReplacePrimaries = false; HighestScoringPrimary = 0; WhichPrimaryIsHighest = 0; AmountHighestScoringPrimary = 0; TotalRequirements = 0; GlobalMultiplier = 1; TownRun.JunkItemStatString = ""; TownRun.ValueItemStatString = ""; // Checks for Invalid Item Types CheckForInvalidItemType(itemType); // Double safety check for unidentified items if (item.IsUnidentified) IsInvalidItem = true; // Make sure we got a valid item here, otherwise score it a big fat 0 if (IsInvalidItem) { Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "-- Invalid Item Type or Unidentified?"); return 0; } Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "NEXT ITEM= " + item.RealName + " - " + item.InternalName + " [" + baseItemType.ToString() + " - " + itemType.ToString() + "]"); ResetValuationStatStrings(); // We loop through all of the stats, in a particular order. The order *IS* important, because it pulls up primary stats first, BEFORE other stats for (int i = 0; i <= (Constants.TOTALSTATS - 1); i++) { double TempStatistic = 0; // Now we lookup each stat on this item we are scoring, and store it in the variable "iTempStatistic" - which is used for calculations further down switch (i) { case Constants.DEXTERITY: TempStatistic = item.Dexterity; break; case Constants.INTELLIGENCE: TempStatistic = item.Intelligence; break; case Constants.STRENGTH: TempStatistic = item.Strength; break; case Constants.VITALITY: TempStatistic = item.Vitality; break; case Constants.LIFEPERCENT: TempStatistic = item.LifePercent; break; case Constants.LIFEONHIT: TempStatistic = item.LifeOnHit; break; case Constants.LIFESTEAL: TempStatistic = item.LifeSteal; break; case Constants.LIFEREGEN: TempStatistic = item.HealthPerSecond; break; case Constants.MAGICFIND: TempStatistic = item.MagicFind; break; case Constants.GOLDFIND: TempStatistic = item.GoldFind; break; case Constants.MOVEMENTSPEED: TempStatistic = item.MovementSpeed; break; case Constants.PICKUPRADIUS: TempStatistic = item.PickUpRadius; break; case Constants.SOCKETS: TempStatistic = item.Sockets; break; case Constants.CRITCHANCE: TempStatistic = item.CritPercent; break; case Constants.CRITDAMAGE: TempStatistic = item.CritDamagePercent; break; case Constants.ATTACKSPEED: TempStatistic = item.AttackSpeedPercent; break; case Constants.MINDAMAGE: TempStatistic = item.MinDamage; break; case Constants.MAXDAMAGE: TempStatistic = item.MaxDamage; break; case Constants.BLOCKCHANCE: TempStatistic = item.BlockChance; break; case Constants.THORNS: TempStatistic = item.Thorns; break; case Constants.ALLRESIST: TempStatistic = item.ResistAll; break; case Constants.RANDOMRESIST: if (item.ResistArcane > TempStatistic) TempStatistic = item.ResistArcane; if (item.ResistCold > TempStatistic) TempStatistic = 0; //thisitem.ResistCold; if (item.ResistFire > TempStatistic) TempStatistic = item.ResistFire; if (item.ResistHoly > TempStatistic) TempStatistic = item.ResistHoly; if (item.ResistLightning > TempStatistic) TempStatistic = 0; //thisitem.ResistLightning; if (item.ResistPhysical > TempStatistic) TempStatistic = item.ResistPhysical; if (item.ResistPoison > TempStatistic) TempStatistic = 0; //thisitem.ResistPoison; break; case Constants.TOTALDPS: TempStatistic = item.WeaponDamagePerSecond; break; case Constants.ARMOR: TempStatistic = item.ArmorBonus; break; case Constants.MAXDISCIPLINE: TempStatistic = item.MaxDiscipline; break; case Constants.MAXMANA: TempStatistic = item.MaxMana; break; case Constants.ARCANECRIT: TempStatistic = item.ArcaneOnCrit; break; case Constants.MANAREGEN: TempStatistic = item.ManaRegen; break; case Constants.GLOBEBONUS: TempStatistic = item.GlobeBonus; break; } HadStat[i] = TempStatistic; HadPoints[i] = 0; // Now we check that the current statistic in the "for" loop, actually exists on this item, and is a stat we are measuring (has >0 in the "max stats" array) if (ItemMaxStats[i] > 0 && TempStatistic > 0) { // Final bonus granted is an end-of-score multiplier. 1 = 100%, so all items start off with 100%, of course! double FinalBonusGranted = 1; // Item Stat Ratio is what PERCENTAGE of the *MAXIMUM POSSIBLE STAT*, this stat is at. // Note that stats OVER the max will get a natural score boost, since this value will be over 1! double itemStatRatio = TempStatistic / ItemMaxStats[i]; // Now multiply the "max points" value, by that percentage, as the start/basis of the scoring for this statistic double iTempPoints = ItemMaxPoints[i] * itemStatRatio; Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "--- " + Constants.StatNames[i] + ": " + TempStatistic.ToString("0") + " out of " + ItemMaxStats[i].ToString() + " (" + ItemMaxPoints[i].ToString() + " * " + itemStatRatio.ToString("0.000") + " = " + iTempPoints.ToString("0") + ")"); // Check if this statistic is over the "bonus threshold" array value for this stat - if it is, then it gets a score bonus when over a certain % of max-stat if (itemStatRatio > Constants.BonusThreshold[i] && Constants.BonusThreshold[i] > 0f) { FinalBonusGranted += ((itemStatRatio - Constants.BonusThreshold[i]) * 0.9); } // We're going to store the life % stat here for quick-calculations against other stats. Don't edit this bit! if (i == Constants.LIFEPERCENT) { if (ItemMaxStats[Constants.LIFEPERCENT] > 0) { SafeLifePercentage = (TempStatistic / ItemMaxStats[Constants.LIFEPERCENT]); } else { SafeLifePercentage = 0; } } // This *REMOVES* score from follower items for stats that followers don't care about if (baseItemType == TrinityItemBaseType.FollowerItem && (i == Constants.CRITDAMAGE || i == Constants.LIFEONHIT || i == Constants.ALLRESIST)) FinalBonusGranted -= 0.9; // Bonus 15% for being *at* the stat cap (ie - completely maxed out, or very very close to), but not for the socket stat (since sockets are usually 0 or 1!) if (i != Constants.SOCKETS) { if ((TempStatistic / ItemMaxStats[i]) >= 0.99) FinalBonusGranted += 0.15; // Else bonus 10% for being in final 95% else if ((TempStatistic / ItemMaxStats[i]) >= 0.95) FinalBonusGranted += 0.10; } // Socket handling // Sockets give special bonuses for certain items, depending how close to the max-socket-count it is for that item // It also enables bonus scoring for stats which usually rely on a high primary stat - since a socket can make up for a lack of a high primary (you can socket a +primary stat!) if (i == Constants.SOCKETS) { // Off-handers get less value from sockets if (baseItemType == TrinityItemBaseType.Offhand) { FinalBonusGranted -= 0.35; } // Chest if (itemType == TrinityItemType.Chest || itemType == TrinityItemType.Cloak) { if (TempStatistic >= 2) { SocketsCanReplacePrimaries = true; if (TempStatistic >= 3) FinalBonusGranted += 0.25; } } // Pants if (itemType == TrinityItemType.Legs) { if (TempStatistic >= 2) { SocketsCanReplacePrimaries = true; FinalBonusGranted += 0.25; } } // Helmets can have a bonus for a socket since it gives amazing MF/GF if (TempStatistic >= 1 && (itemType == TrinityItemType.Helm || itemType == TrinityItemType.WizardHat || itemType == TrinityItemType.VoodooMask || itemType == TrinityItemType.SpiritStone)) { SocketsCanReplacePrimaries = true; } // And rings and amulets too if (TempStatistic >= 1 && (itemType == TrinityItemType.Ring || itemType == TrinityItemType.Amulet)) { SocketsCanReplacePrimaries = true; } } // Right, here's quite a long bit of code, but this is basically all about granting all sorts of bonuses based on primary stat values of all different ranges // For all item types *EXCEPT* weapons if (baseItemType != TrinityItemBaseType.WeaponRange && baseItemType != TrinityItemBaseType.WeaponOneHand && baseItemType != TrinityItemBaseType.WeaponTwoHand) { double SpecialBonus = 0; if (i > Constants.LIFEPERCENT) { // Knock off points for being particularly low if ((TempStatistic / ItemMaxStats[i]) < 0.2 && (Constants.BonusThreshold[i] <= 0f || Constants.BonusThreshold[i] >= 0.2)) FinalBonusGranted -= 0.35; else if ((TempStatistic / ItemMaxStats[i]) < 0.4 && (Constants.BonusThreshold[i] <= 0f || Constants.BonusThreshold[i] >= 0.4)) FinalBonusGranted -= 0.15; // Remove 80% if below minimum threshold if ((TempStatistic / ItemMaxStats[i]) < Constants.MinimumThreshold[i] && Constants.MinimumThreshold[i] > 0f) FinalBonusGranted -= 0.8; // Primary stat/vitality minimums or zero-check reductions on other stats if (Constants.StatMinimumPrimary[i] > 0) { // Remove 40% from all stats if there is no prime stat present or vitality/life present and this is below 90% of max if (((TempStatistic / ItemMaxStats[i]) < .90) && ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) < Constants.StatMinimumPrimary[i]) && ((HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) < (Constants.StatMinimumPrimary[i] + 0.1)) && ((HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) < Constants.StatMinimumPrimary[i]) && ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) < Constants.StatMinimumPrimary[i]) && (SafeLifePercentage < (Constants.StatMinimumPrimary[i] * 2.5)) && !SocketsCanReplacePrimaries) { if (itemType != TrinityItemType.Ring && itemType != TrinityItemType.Amulet) FinalBonusGranted -= 0.4; else FinalBonusGranted -= 0.3; // And another 25% off for armor and all resist which are more useful with primaries, as long as not jewelry if ((i == Constants.ARMOR || i == Constants.ALLRESIST || i == Constants.RANDOMRESIST) && itemType != TrinityItemType.Ring && itemType != TrinityItemType.Amulet && !SocketsCanReplacePrimaries) FinalBonusGranted -= 0.15; } } else { // Almost no primary stats or health at all if (HadStat[Constants.DEXTERITY] <= 60 && HadStat[Constants.STRENGTH] <= 60 && HadStat[Constants.INTELLIGENCE] <= 60 && HadStat[Constants.VITALITY] <= 60 && SafeLifePercentage < 0.9 && !SocketsCanReplacePrimaries) { // So 35% off for all items except jewelry which is 20% off if (itemType != TrinityItemType.Ring && itemType != TrinityItemType.Amulet) { FinalBonusGranted -= 0.35; // And another 25% off for armor and all resist which are more useful with primaries if (i == Constants.ARMOR || i == Constants.ALLRESIST) FinalBonusGranted -= 0.15; } else { FinalBonusGranted -= 0.20; } } } if (baseItemType == TrinityItemBaseType.Armor || baseItemType == TrinityItemBaseType.Jewelry) { // Grant a 50% bonus to stats if a primary is above 200 AND (vitality above 200 or life% within 90% max) if ((HadStat[Constants.DEXTERITY] > 200 || HadStat[Constants.STRENGTH] > 200 || HadStat[Constants.INTELLIGENCE] > 200) && (HadStat[Constants.VITALITY] > 200 || SafeLifePercentage > .97)) { if (0.5 > SpecialBonus) SpecialBonus = 0.5; } // Else grant a 40% bonus to stats if a primary is above 200 if (HadStat[Constants.DEXTERITY] > 200 || HadStat[Constants.STRENGTH] > 200 || HadStat[Constants.INTELLIGENCE] > 200) { if (0.4 > SpecialBonus) SpecialBonus = 0.4; } // Grant a 30% bonus if vitality > 200 or life percent within 90% of max if (HadStat[Constants.VITALITY] > 200 || SafeLifePercentage > .97) { if (0.3 > SpecialBonus) SpecialBonus = 0.3; } } // Checks for various primary & health levels if ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > .85 || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > .85 || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > .85) { if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .6 || SafeLifePercentage > .90) { if (0.5 > SpecialBonus) SpecialBonus = 0.5; } else if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .35 || SafeLifePercentage > .85) { if (0.4 > SpecialBonus) SpecialBonus = 0.4; } else { if (0.2 > SpecialBonus) SpecialBonus = 0.2; } } if ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > .75 || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > .75 || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > .75) { if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .6 || SafeLifePercentage > .90) { if (0.35 > SpecialBonus) SpecialBonus = 0.35; } else if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .35 || SafeLifePercentage > .85) { if (0.30 > SpecialBonus) SpecialBonus = 0.30; } else { if (0.15 > SpecialBonus) SpecialBonus = 0.15; } } if ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > .65 || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > .65 || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > .65) { if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .6 || SafeLifePercentage > .90) { if (0.26 > SpecialBonus) SpecialBonus = 0.26; } else if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .35 || SafeLifePercentage > .85) { if (0.22 > SpecialBonus) SpecialBonus = 0.22; } else { if (0.11 > SpecialBonus) SpecialBonus = 0.11; } } if ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > .55 || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > .55 || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > .55) { if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .6 || SafeLifePercentage > .90) { if (0.18 > SpecialBonus) SpecialBonus = 0.18; } else if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .35 || SafeLifePercentage > .85) { if (0.14 > SpecialBonus) SpecialBonus = 0.14; } else { if (0.08 > SpecialBonus) SpecialBonus = 0.08; } } if ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > .5 || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > .5 || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > .5) { if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .6 || SafeLifePercentage > .90) { if (0.12 > SpecialBonus) SpecialBonus = 0.12; } else if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .35 || SafeLifePercentage > .85) { if (0.05 > SpecialBonus) SpecialBonus = 0.05; } else { if (0.03 > SpecialBonus) SpecialBonus = 0.03; } } if (itemType == TrinityItemType.Ring || itemType == TrinityItemType.Amulet) { if ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > .4 || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > .4 || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > .4) { if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .6 || SafeLifePercentage > .90) { if (0.10 > SpecialBonus) SpecialBonus = 0.10; } else if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .35 || SafeLifePercentage > .85) { if (0.08 > SpecialBonus) SpecialBonus = 0.08; } else { if (0.05 > SpecialBonus) SpecialBonus = 0.05; } } } if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .8 || SafeLifePercentage > .98) { if (0.20 > SpecialBonus) SpecialBonus = 0.20; } if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .7 || SafeLifePercentage > .95) { if (0.16 > SpecialBonus) SpecialBonus = 0.16; } if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .6 || SafeLifePercentage > .92) { if (0.12 > SpecialBonus) SpecialBonus = 0.12; } if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .55 || SafeLifePercentage > .89) { if (0.07 > SpecialBonus) SpecialBonus = 0.07; } else if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .5 || SafeLifePercentage > .87) { if (0.05 > SpecialBonus) SpecialBonus = 0.05; } else if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > .45 || SafeLifePercentage > .86) { if (0.02 > SpecialBonus) SpecialBonus = 0.02; } } // This stat is one after life percent stat // Shields get less of a special bonus from high prime stats if (itemType == TrinityItemType.Shield) SpecialBonus *= 0.7; if (SpecialBonus > 0) Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "------- special bonus =" + SpecialBonus.ToString(), true); FinalBonusGranted += SpecialBonus; } if (i == Constants.LIFESTEAL && itemType == TrinityItemType.MightyBelt) FinalBonusGranted += 0.3; if (i == Constants.TOTALDPS) { // Knock off points for being particularly low if ((TempStatistic / ItemMaxStats[i]) < Constants.MinimumThreshold[i] && Constants.MinimumThreshold[i] > 0f) FinalBonusGranted -= 0.5; } else { // Knock off points for being particularly low if ((TempStatistic / ItemMaxStats[i]) < Constants.MinimumThreshold[i] && Constants.MinimumThreshold[i] > 0f) FinalBonusGranted -= 0.35; } // Grant a 20% bonus to vitality or Life%, for being paired with any prime stat above minimum threshold +.1 if (((i == Constants.VITALITY && (TempStatistic / ItemMaxStats[Constants.VITALITY]) > Constants.MinimumThreshold[Constants.VITALITY]) || i == Constants.LIFEPERCENT && (TempStatistic / ItemMaxStats[Constants.LIFEPERCENT]) > Constants.MinimumThreshold[Constants.LIFEPERCENT]) && ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > (Constants.MinimumThreshold[Constants.DEXTERITY] + 0.1) || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > (Constants.MinimumThreshold[Constants.STRENGTH] + 0.1) || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > (Constants.MinimumThreshold[Constants.INTELLIGENCE] + 0.1))) FinalBonusGranted += 0.2; // Blue item point reduction for non-weapons if (item.Quality < ItemQuality.Rare4 && (baseItemType == TrinityItemBaseType.Armor || baseItemType == TrinityItemBaseType.Offhand || baseItemType == TrinityItemBaseType.Jewelry || baseItemType == TrinityItemBaseType.FollowerItem) && ((TempStatistic / ItemMaxStats[i]) < 0.88)) FinalBonusGranted -= 0.9; // Special all-resist bonuses if (i == Constants.ALLRESIST) { // Shields with < 60% max all resist, lost some all resist score if (itemType == TrinityItemType.Shield && (TempStatistic / ItemMaxStats[i]) <= 0.6) FinalBonusGranted -= 0.30; double iSpecialBonus = 0; // All resist gets a special bonus if paired with good strength and some vitality if ((HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > 0.7 && (HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > 0.3) if (0.45 > iSpecialBonus) iSpecialBonus = 0.45; // All resist gets a smaller special bonus if paired with good dexterity and some vitality if ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > 0.7 && (HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > 0.3) if (0.35 > iSpecialBonus) iSpecialBonus = 0.35; // All resist gets a slight special bonus if paired with good intelligence and some vitality if ((HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > 0.7 && (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > 0.3) if (0.25 > iSpecialBonus) iSpecialBonus = 0.25; // Smaller bonuses for smaller stats // All resist gets a special bonus if paired with good strength and some vitality if ((HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > 0.55 && (HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > 0.3) if (0.45 > iSpecialBonus) iSpecialBonus = 0.20; // All resist gets a smaller special bonus if paired with good dexterity and some vitality if ((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > 0.55 && (HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > 0.3) if (0.35 > iSpecialBonus) iSpecialBonus = 0.15; // All resist gets a slight special bonus if paired with good intelligence and some vitality if ((HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > 0.55 && (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > 0.3) if (0.25 > iSpecialBonus) iSpecialBonus = 0.10; // This stat is one after life percent stat FinalBonusGranted += iSpecialBonus; // Global bonus to everything //if ((ItemMaxStats[i] - TempStatistic) < 10.2f) // GlobalMultiplier += 0.05; } // All resist special bonuses if (itemType != TrinityItemType.Ring && itemType != TrinityItemType.Amulet) { // Shields get 10% less on everything if (itemType == TrinityItemType.Shield) FinalBonusGranted -= 0.10; // Prime stat gets a 20% bonus if 50 from max possible if ((i == Constants.DEXTERITY || i == Constants.STRENGTH || i == Constants.INTELLIGENCE || i == Constants.VITALITY) && (ItemMaxStats[i] - TempStatistic) < 50.5f) FinalBonusGranted += 0.25; // Reduce a prime stat by 75% if less than 100 *OR* less than 50% max if ((i == Constants.DEXTERITY || i == Constants.STRENGTH || i == Constants.INTELLIGENCE) && (TempStatistic < 100 || ((TempStatistic / ItemMaxStats[i]) < 0.5))) FinalBonusGranted -= 0.75; // Reduce a vitality/life% stat by 60% if less than 80 vitality/less than 60% max possible life% if ((i == Constants.VITALITY && TempStatistic < 80) || (i == Constants.LIFEPERCENT && ((TempStatistic / ItemMaxStats[Constants.LIFEPERCENT]) < 0.6))) FinalBonusGranted -= 0.6; // Grant 10% to any 4 main stat above 200 if ((i == Constants.DEXTERITY || i == Constants.STRENGTH || i == Constants.INTELLIGENCE || i == Constants.VITALITY) && TempStatistic > 200) FinalBonusGranted += 0.1; // Special stat handling stuff for non-jewelry types // Within 2 block chance if (i == Constants.BLOCKCHANCE && (ItemMaxStats[i] - TempStatistic) < 2.3f) FinalBonusGranted += 1; // Within final 5 gold find if (i == Constants.GOLDFIND && (ItemMaxStats[i] - TempStatistic) < 5.3f) { FinalBonusGranted += 0.04; // Even bigger bonus if got prime stat & vit if (((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > Constants.MinimumThreshold[Constants.DEXTERITY] || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > Constants.MinimumThreshold[Constants.STRENGTH] || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > Constants.MinimumThreshold[Constants.INTELLIGENCE]) && (HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > Constants.MinimumThreshold[Constants.VITALITY]) FinalBonusGranted += 0.02; } // Within final 3 gold find if (i == Constants.GOLDFIND && (ItemMaxStats[i] - TempStatistic) < 3.3f) { FinalBonusGranted += 0.04; } // Within final 2 gold find if (i == Constants.GOLDFIND && (ItemMaxStats[i] - TempStatistic) < 2.3f) { FinalBonusGranted += 0.05; } // Within final 3 magic find if (i == Constants.MAGICFIND && (ItemMaxStats[i] - TempStatistic) < 3.3f) FinalBonusGranted += 0.08; // Within final 2 magic find if (i == Constants.MAGICFIND && (ItemMaxStats[i] - TempStatistic) < 2.3f) { FinalBonusGranted += 0.04; // Even bigger bonus if got prime stat & vit if (((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > Constants.MinimumThreshold[Constants.DEXTERITY] || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > Constants.MinimumThreshold[Constants.STRENGTH] || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > Constants.MinimumThreshold[Constants.INTELLIGENCE]) && (HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > Constants.MinimumThreshold[Constants.VITALITY]) FinalBonusGranted += 0.03; } // Within final magic find if (i == Constants.MAGICFIND && (ItemMaxStats[i] - TempStatistic) < 1.3f) { FinalBonusGranted += 0.05; } // Within final 10 all resist if (i == Constants.ALLRESIST && (ItemMaxStats[i] - TempStatistic) < 10.2f) { FinalBonusGranted += 0.05; // Even bigger bonus if got prime stat & vit if (((HadStat[Constants.DEXTERITY] / ItemMaxStats[Constants.DEXTERITY]) > Constants.MinimumThreshold[Constants.DEXTERITY] || (HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > Constants.MinimumThreshold[Constants.STRENGTH] || (HadStat[Constants.INTELLIGENCE] / ItemMaxStats[Constants.INTELLIGENCE]) > Constants.MinimumThreshold[Constants.INTELLIGENCE]) && (HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY]) > Constants.MinimumThreshold[Constants.VITALITY]) FinalBonusGranted += 0.20; } // Within final 50 armor if (i == Constants.ARMOR && (ItemMaxStats[i] - TempStatistic) < 50.2f) { FinalBonusGranted += 0.10; if ((HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > Constants.MinimumThreshold[Constants.STRENGTH]) FinalBonusGranted += 0.10; } // Within final 15 armor if (i == Constants.ARMOR && (ItemMaxStats[i] - TempStatistic) < 15.2f) FinalBonusGranted += 0.15; // Within final 5 critical hit damage if (i == Constants.CRITDAMAGE && (ItemMaxStats[i] - TempStatistic) < 5.2f) FinalBonusGranted += 0.25; // More than 2.5 crit chance out if (i == Constants.CRITCHANCE && (ItemMaxStats[i] - TempStatistic) > 2.45f) FinalBonusGranted -= 0.35; // More than 20 crit damage out if (i == Constants.CRITDAMAGE && (ItemMaxStats[i] - TempStatistic) > 19.95f) FinalBonusGranted -= 0.35; // More than 2 attack speed out if (i == Constants.ATTACKSPEED && (ItemMaxStats[i] - TempStatistic) > 1.95f) FinalBonusGranted -= 0.35; // More than 2 move speed if (i == Constants.MOVEMENTSPEED && (ItemMaxStats[i] - TempStatistic) > 1.95f) FinalBonusGranted -= 0.35; // More than 5 gold find out if (i == Constants.GOLDFIND && (ItemMaxStats[i] - TempStatistic) > 5.2f) FinalBonusGranted -= 0.40; // More than 8 gold find out if (i == Constants.GOLDFIND && (ItemMaxStats[i] - TempStatistic) > 8.2f) FinalBonusGranted -= 0.1; // More than 5 magic find out if (i == Constants.MAGICFIND && (ItemMaxStats[i] - TempStatistic) > 5.2f) FinalBonusGranted -= 0.40; // More than 7 magic find out if (i == Constants.MAGICFIND && (ItemMaxStats[i] - TempStatistic) > 7.2f) FinalBonusGranted -= 0.1; // More than 20 all resist out if (i == Constants.ALLRESIST && (ItemMaxStats[i] - TempStatistic) > 20.2f) FinalBonusGranted -= 0.50; // More than 30 all resist out if (i == Constants.ALLRESIST && (ItemMaxStats[i] - TempStatistic) > 30.2f) FinalBonusGranted -= 0.20; } // And now for jewelry checks... if (itemType == TrinityItemType.Ring || itemType == TrinityItemType.Amulet) { // Global bonus to everything if jewelry has an all resist above 50% if (i == Constants.ALLRESIST && (TempStatistic / ItemMaxStats[i]) > 0.5) GlobalMultiplier += 0.08; // Within final 10 all resist if (i == Constants.ALLRESIST && (ItemMaxStats[i] - TempStatistic) < 10.2f) FinalBonusGranted += 0.10; // Within final 5 critical hit damage if (i == Constants.CRITDAMAGE && (ItemMaxStats[i] - TempStatistic) < 5.2f) FinalBonusGranted += 0.25; // Within 3 block chance if (i == Constants.BLOCKCHANCE && (ItemMaxStats[i] - TempStatistic) < 3.3f) FinalBonusGranted += 0.15; // Reduce a prime stat by 60% if less than 60 if ((i == Constants.DEXTERITY || i == Constants.STRENGTH || i == Constants.INTELLIGENCE) && (TempStatistic < 60 || ((TempStatistic / ItemMaxStats[i]) < 0.3))) FinalBonusGranted -= 0.6; // Reduce a vitality/life% stat by 50% if less than 50 vitality/less than 40% max possible life% if ((i == Constants.VITALITY && TempStatistic < 50) || (i == Constants.LIFEPERCENT && ((TempStatistic / ItemMaxStats[Constants.LIFEPERCENT]) < 0.4))) FinalBonusGranted -= 0.5; // Grant 20% to any 4 main stat above 150 if ((i == Constants.DEXTERITY || i == Constants.STRENGTH || i == Constants.INTELLIGENCE || i == Constants.VITALITY) && TempStatistic > 150) FinalBonusGranted += 0.2; // Special stat handling stuff for jewelry if (itemType == TrinityItemType.Ring) { // Prime stat gets a 25% bonus if 30 from max possible if ((i == Constants.DEXTERITY || i == Constants.STRENGTH || i == Constants.INTELLIGENCE || i == Constants.VITALITY) && (ItemMaxStats[i] - TempStatistic) < 30.5f) FinalBonusGranted += 0.25; // Within final 5 magic find if (i == Constants.MAGICFIND && (ItemMaxStats[i] - TempStatistic) < 5.2f) FinalBonusGranted += 0.4; // Within final 5 gold find if (i == Constants.GOLDFIND && (ItemMaxStats[i] - TempStatistic) < 5.2f) FinalBonusGranted += 0.35; // Within final 45 life on hit if (i == Constants.LIFEONHIT && (ItemMaxStats[i] - TempStatistic) < 45.2f) FinalBonusGranted += 1.2; } else { // Prime stat gets a 25% bonus if 60 from max possible if ((i == Constants.DEXTERITY || i == Constants.STRENGTH || i == Constants.INTELLIGENCE || i == Constants.VITALITY) && (ItemMaxStats[i] - TempStatistic) < 60.5f) FinalBonusGranted += 0.25; // Within final 10 magic find if (i == Constants.MAGICFIND && (ItemMaxStats[i] - TempStatistic) < 10.2f) FinalBonusGranted += 0.4; // Within final 10 gold find if (i == Constants.GOLDFIND && (ItemMaxStats[i] - TempStatistic) < 10.2f) FinalBonusGranted += 0.35; // Within final 40 life on hit if (i == Constants.LIFEONHIT && (ItemMaxStats[i] - TempStatistic) < 40.2f) FinalBonusGranted += 1.2; } // Within final 50 armor if (i == Constants.ARMOR && (ItemMaxStats[i] - TempStatistic) < 50.2f) { FinalBonusGranted += 0.30; if ((HadStat[Constants.STRENGTH] / ItemMaxStats[Constants.STRENGTH]) > Constants.MinimumThreshold[Constants.STRENGTH]) FinalBonusGranted += 0.30; } // Within final 15 armor if (i == Constants.ARMOR && (ItemMaxStats[i] - TempStatistic) < 15.2f) FinalBonusGranted += 0.20; // More than 2.5 crit chance out if (i == Constants.CRITCHANCE && (ItemMaxStats[i] - TempStatistic) > 5.55f) FinalBonusGranted -= 0.20; // More than 20 crit damage out if (i == Constants.CRITDAMAGE && (ItemMaxStats[i] - TempStatistic) > 19.95f) FinalBonusGranted -= 0.20; // More than 2 attack speed out if (i == Constants.ATTACKSPEED && (ItemMaxStats[i] - TempStatistic) > 1.95f) FinalBonusGranted -= 0.20; // More than 15 gold find out if (i == Constants.GOLDFIND && (ItemMaxStats[i] - TempStatistic) > 15.2f) FinalBonusGranted -= 0.1; // More than 15 magic find out if (i == Constants.MAGICFIND && (ItemMaxStats[i] - TempStatistic) > 15.2f) FinalBonusGranted -= 0.1; // More than 30 all resist out if (i == Constants.ALLRESIST && (ItemMaxStats[i] - TempStatistic) > 20.2f) FinalBonusGranted -= 0.1; // More than 40 all resist out if (i == Constants.ALLRESIST && (ItemMaxStats[i] - TempStatistic) > 30.2f) FinalBonusGranted -= 0.1; } // All the "set to 0" checks now // Disable specific primary stat scoring for certain class-specific item types if ((itemType == TrinityItemType.VoodooMask || itemType == TrinityItemType.WizardHat || itemType == TrinityItemType.Wand || itemType == TrinityItemType.CeremonialKnife || itemType == TrinityItemType.Mojo || itemType == TrinityItemType.Orb) && (i == Constants.STRENGTH || i == Constants.DEXTERITY)) FinalBonusGranted = 0; if ((itemType == TrinityItemType.Quiver || itemType == TrinityItemType.HandCrossbow || itemType == TrinityItemType.Cloak || itemType == TrinityItemType.SpiritStone || itemType == TrinityItemType.TwoHandDaibo || itemType == TrinityItemType.FistWeapon) && (i == Constants.STRENGTH || i == Constants.INTELLIGENCE)) FinalBonusGranted = 0; if ((itemType == TrinityItemType.MightyBelt || itemType == TrinityItemType.MightyWeapon || itemType == TrinityItemType.TwoHandMighty) && (i == Constants.DEXTERITY || i == Constants.INTELLIGENCE)) FinalBonusGranted = 0; // Remove unwanted follower stats for specific follower types if (itemType == TrinityItemType.FollowerEnchantress && (i == Constants.STRENGTH || i == Constants.DEXTERITY)) FinalBonusGranted = 0; if (itemType == TrinityItemType.FollowerEnchantress && (i == Constants.INTELLIGENCE || i == Constants.VITALITY)) FinalBonusGranted -= 0.4; if (itemType == TrinityItemType.FollowerScoundrel && (i == Constants.STRENGTH || i == Constants.INTELLIGENCE)) FinalBonusGranted = 0; if (itemType == TrinityItemType.FollowerScoundrel && (i == Constants.DEXTERITY || i == Constants.VITALITY)) FinalBonusGranted -= 0.4; if (itemType == TrinityItemType.FollowerTemplar && (i == Constants.DEXTERITY || i == Constants.INTELLIGENCE)) FinalBonusGranted = 0; if (itemType == TrinityItemType.FollowerTemplar && (i == Constants.STRENGTH || i == Constants.VITALITY)) FinalBonusGranted -= 0.4; // Attack speed is always on a quiver so forget it if ((itemType == TrinityItemType.Quiver) && (i == Constants.ATTACKSPEED)) FinalBonusGranted = 0; // Single resists worth nothing without all-resist if (i == Constants.RANDOMRESIST && (HadStat[Constants.ALLRESIST] / ItemMaxStats[Constants.ALLRESIST]) < Constants.MinimumThreshold[Constants.ALLRESIST]) FinalBonusGranted = 0; if (FinalBonusGranted < 0) FinalBonusGranted = 0; // Grant the final bonus total iTempPoints *= FinalBonusGranted; // If it's a primary stat, log the highest scoring primary... else add these points to the running total if (i == Constants.DEXTERITY || i == Constants.STRENGTH || i == Constants.INTELLIGENCE) { Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "---- +" + iTempPoints.ToString("0") + " (*" + FinalBonusGranted.ToString("0.00") + " multiplier) [MUST BE MAX STAT SCORE TO COUNT]", true); if (iTempPoints > HighestScoringPrimary) { HighestScoringPrimary = iTempPoints; WhichPrimaryIsHighest = i; AmountHighestScoringPrimary = TempStatistic; } } else { Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "---- +" + iTempPoints.ToString("0") + " score (*" + FinalBonusGranted.ToString("0.00") + " multiplier)", true); TotalItemPoints += iTempPoints; } HadPoints[i] = iTempPoints; // For item logs if (i != Constants.DEXTERITY && i != Constants.STRENGTH && i != Constants.INTELLIGENCE) { if (TownRun.ValueItemStatString != "") TownRun.ValueItemStatString += ". "; TownRun.ValueItemStatString += Constants.StatNames[i] + "=" + Math.Round(TempStatistic).ToString(); if (TownRun.JunkItemStatString != "") TownRun.JunkItemStatString += ". "; TownRun.JunkItemStatString += Constants.StatNames[i] + "=" + Math.Round(TempStatistic).ToString(); } } } // Now add on one of the three primary stat scores, whichever was higher if (HighestScoringPrimary > 0) { // Give a 30% of primary-stat-score-possible bonus to the primary scoring if paired with a good amount of life % or vitality if ((HadStat[Constants.VITALITY] / ItemMaxStats[Constants.VITALITY] > (Constants.MinimumThreshold[Constants.VITALITY] + 0.1)) || SafeLifePercentage > 0.85) HighestScoringPrimary += ItemMaxPoints[WhichPrimaryIsHighest] * 0.3; // Reduce a primary a little if there is no vitality or life if ((HadStat[Constants.VITALITY] < 40) || SafeLifePercentage < 0.7) HighestScoringPrimary *= 0.8; TotalItemPoints += HighestScoringPrimary; TownRun.ValueItemStatString = Constants.StatNames[WhichPrimaryIsHighest] + "=" + Math.Round(AmountHighestScoringPrimary).ToString() + ". " + TownRun.ValueItemStatString; TownRun.JunkItemStatString = Constants.StatNames[WhichPrimaryIsHighest] + "=" + Math.Round(AmountHighestScoringPrimary).ToString() + ". " + TownRun.JunkItemStatString; } Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "--- +" + TotalItemPoints.ToString("0") + " total score pre-special reductions. (GlobalMultiplier=" + GlobalMultiplier.ToString("0.000") + ")", true); // Global multiplier TotalItemPoints *= GlobalMultiplier; // 2 handed weapons and ranged weapons lose a large score for low DPS if (baseItemType == TrinityItemBaseType.WeaponRange || baseItemType == TrinityItemBaseType.WeaponTwoHand) { if ((HadStat[Constants.TOTALDPS] / ItemMaxStats[Constants.TOTALDPS]) <= 0.7) TotalItemPoints *= 0.75; } // Weapons should get a nice 15% bonus score for having very high primaries if (baseItemType == TrinityItemBaseType.WeaponRange || baseItemType == TrinityItemBaseType.WeaponOneHand || baseItemType == TrinityItemBaseType.WeaponTwoHand) { if (HighestScoringPrimary > 0 && (HighestScoringPrimary >= ItemMaxPoints[WhichPrimaryIsHighest] * 0.9)) { TotalItemPoints *= 1.15; } // And an extra 15% for a very high vitality if (HadStat[Constants.VITALITY] > 0 && (HadStat[Constants.VITALITY] >= ItemMaxPoints[Constants.VITALITY] * 0.9)) { TotalItemPoints *= 1.15; } // And an extra 15% for a very high life-on-hit if (HadStat[Constants.LIFEONHIT] > 0 && (HadStat[Constants.LIFEONHIT] >= ItemMaxPoints[Constants.LIFEONHIT] * 0.9)) { TotalItemPoints *= 1.15; } } // Shields if (itemType == TrinityItemType.Shield) { // Strength/Dex based shield calculations if (WhichPrimaryIsHighest == Constants.STRENGTH || WhichPrimaryIsHighest == Constants.DEXTERITY) { if (HadStat[Constants.BLOCKCHANCE] < 20) { TotalItemPoints *= 0.7; } else if (HadStat[Constants.BLOCKCHANCE] < 25) { TotalItemPoints *= 0.9; } } // Intelligence/no primary based shields else { if (HadStat[Constants.BLOCKCHANCE] < 28) TotalItemPoints -= HadPoints[Constants.BLOCKCHANCE]; } } // Quivers if (itemType == TrinityItemType.Quiver) { TotalRequirements = 0; if (HadStat[Constants.DEXTERITY] >= 100) TotalRequirements++; else TotalRequirements -= 3; if (HadStat[Constants.DEXTERITY] >= 160) TotalRequirements++; if (HadStat[Constants.DEXTERITY] >= 250) TotalRequirements++; if (HadStat[Constants.ATTACKSPEED] < 14) TotalRequirements -= 2; if (HadStat[Constants.VITALITY] >= 70 || SafeLifePercentage >= 0.85) TotalRequirements++; else TotalRequirements--; if (HadStat[Constants.VITALITY] >= 260) TotalRequirements++; if (HadStat[Constants.MAXDISCIPLINE] >= 8) TotalRequirements++; if (HadStat[Constants.MAXDISCIPLINE] >= 10) TotalRequirements++; if (HadStat[Constants.SOCKETS] >= 1) TotalRequirements++; if (HadStat[Constants.CRITCHANCE] >= 6) TotalRequirements++; if (HadStat[Constants.CRITCHANCE] >= 8) TotalRequirements++; if (HadStat[Constants.LIFEPERCENT] >= 8) TotalRequirements++; if (HadStat[Constants.MAGICFIND] >= 18) TotalRequirements++; if (TotalRequirements < 4) TotalItemPoints *= 0.4; else if (TotalRequirements < 5) TotalItemPoints *= 0.5; if (TotalRequirements >= 7) TotalItemPoints *= 1.2; } // Mojos and Sources if (itemType == TrinityItemType.Orb || itemType == TrinityItemType.Mojo) { TotalRequirements = 0; if (HadStat[Constants.INTELLIGENCE] >= 100) TotalRequirements++; else if (HadStat[Constants.INTELLIGENCE] < 80) TotalRequirements -= 3; else if (HadStat[Constants.INTELLIGENCE] < 100) TotalRequirements -= 1; if (HadStat[Constants.INTELLIGENCE] >= 160) TotalRequirements++; if (HadStat[Constants.MAXDAMAGE] >= 250) TotalRequirements++; else TotalRequirements -= 2; if (HadStat[Constants.MAXDAMAGE] >= 340) TotalRequirements++; if (HadStat[Constants.MINDAMAGE] >= 50) TotalRequirements++; else TotalRequirements--; if (HadStat[Constants.MINDAMAGE] >= 85) TotalRequirements++; if (HadStat[Constants.VITALITY] >= 70) TotalRequirements++; if (HadStat[Constants.SOCKETS] >= 1) TotalRequirements++; if (HadStat[Constants.CRITCHANCE] >= 6) TotalRequirements++; if (HadStat[Constants.CRITCHANCE] >= 8) TotalRequirements++; if (HadStat[Constants.LIFEPERCENT] >= 8) TotalRequirements++; if (HadStat[Constants.MAGICFIND] >= 15) TotalRequirements++; if (HadStat[Constants.MAXMANA] >= 60) TotalRequirements++; if (HadStat[Constants.ARCANECRIT] >= 8) TotalRequirements++; if (HadStat[Constants.ARCANECRIT] >= 10) TotalRequirements++; if (TotalRequirements < 4) TotalItemPoints *= 0.4; else if (TotalRequirements < 5) TotalItemPoints *= 0.5; if (TotalRequirements >= 8) TotalItemPoints *= 1.2; } // Chests/cloaks/pants without a socket lose 17% of total score if ((itemType == TrinityItemType.Chest || itemType == TrinityItemType.Cloak || itemType == TrinityItemType.Legs) && HadStat[Constants.SOCKETS] == 0) TotalItemPoints *= 0.83; // Boots with no movement speed get reduced score if ((itemType == TrinityItemType.Boots) && HadStat[Constants.MOVEMENTSPEED] <= 6) TotalItemPoints *= 0.75; // Helmets if (itemType == TrinityItemType.Helm || itemType == TrinityItemType.WizardHat || itemType == TrinityItemType.VoodooMask || itemType == TrinityItemType.SpiritStone) { // Helmets without a socket lose 20% of total score, and most of any MF/GF bonus if (HadStat[Constants.SOCKETS] == 0) { TotalItemPoints *= 0.8; if (HadStat[Constants.MAGICFIND] > 0 || HadStat[Constants.GOLDFIND] > 0) { if (HadStat[Constants.MAGICFIND] > 0 && HadStat[Constants.GOLDFIND] > 0) TotalItemPoints -= ((HadPoints[Constants.MAGICFIND] * 0.25) + (HadPoints[Constants.GOLDFIND] * 0.25)); else TotalItemPoints -= ((HadPoints[Constants.MAGICFIND] * 0.65) + (HadPoints[Constants.GOLDFIND] * 0.65)); } } } Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "--- +" + TotalItemPoints.ToString("0") + " total score after special reductions. (TotalRequirements=" + TotalRequirements + ")", true); GetBestFinalPoints(itemType); TotalItemPoints *= BestFinalBonus; Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "TOTAL: " + TotalItemPoints.ToString("0") + "(Final Bonus=" + BestFinalBonus.ToString("0.00") + ")"); Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, ""); return Math.Round(TotalItemPoints); }
/// <summary> /// Define Special Reductions /// </summary> /// <param name="itemType"></param> private static void GetBestFinalPoints(TrinityItemType itemType) { // Gold-find and pickup radius combined if ((HadStat[Constants.GOLDFIND] / ItemMaxStats[Constants.GOLDFIND] > 0.55) && (HadStat[Constants.PICKUPRADIUS] / ItemMaxStats[Constants.PICKUPRADIUS] > 0.5)) TotalItemPoints += (((ItemMaxPoints[Constants.PICKUPRADIUS] + ItemMaxPoints[Constants.GOLDFIND]) / 2) * 0.25); // All-resist and pickup radius combined if ((HadStat[Constants.ALLRESIST] / ItemMaxStats[Constants.ALLRESIST] > 0.55) && (HadStat[Constants.PICKUPRADIUS] > 0)) TotalItemPoints += (((ItemMaxPoints[Constants.PICKUPRADIUS] + ItemMaxPoints[Constants.ALLRESIST]) / 2) * 0.65); // Special crit hit/crit chance/attack speed combos a.k.a Trifecta! if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.8)) && (HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.8)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.8))) { if (BestFinalBonus < 3.2 && itemType != TrinityItemType.Quiver) BestFinalBonus = 3.2; } /* * 2.3 Bonus for 80% 2 of 3 CritDmg/Crit%/AttackSpd Combo */ // 80% of crit chance, 80% crit damage of max for item if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.8)) && (HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.8))) { if (BestFinalBonus < 2.3) BestFinalBonus = 2.3; } // 80% of crit chance, 80% of attack speed of max for item if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.8)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.8))) { if (BestFinalBonus < 2.1 && itemType != TrinityItemType.Quiver) BestFinalBonus = 2.1; } // 80% of crit damage, 80% of attack speed of max for item if ((HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.8)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.8))) { if (BestFinalBonus < 1.8 && itemType != TrinityItemType.Quiver) BestFinalBonus = 1.8; } /* * 2.1 Bonus for 65% 2 of 3 CritDmg/Crit%/AttackSpd Combo */ // 65% crit chance, 65% crit damage, 65% attack speed of max for item if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.65)) && (HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.65)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.65))) { if (BestFinalBonus < 2.1 && itemType != TrinityItemType.Quiver) BestFinalBonus = 2.1; } // 65% crit chance, 65% crit damage if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.65)) && (HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.65))) { if (BestFinalBonus < 1.9) BestFinalBonus = 1.9; } // 65% crit chance, 65% attack speed of max for item if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.65)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.65))) { if (BestFinalBonus < 1.7 && itemType != TrinityItemType.Quiver) BestFinalBonus = 1.7; } // 65% crit damage, 65% attack speed of max for item if ((HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.65)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.65))) { if (BestFinalBonus < 1.5 && itemType != TrinityItemType.Quiver) BestFinalBonus = 1.5; } /* * 1.7 Bonus for 45% 2 of 3 CritDmg/Crit%/AttackSpd Combo */ // 45% crit chance, 45% crit damage, 45% attack speed of max for item if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.45)) && (HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.45)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.45))) { if (BestFinalBonus < 1.7 && itemType != TrinityItemType.Quiver) BestFinalBonus = 1.7; } // 45% crit chance, 45% crit damage, 45% attack speed of max for item if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.45)) && (HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.45))) { if (BestFinalBonus < 1.4) BestFinalBonus = 1.4; } // 45% crit chance, 45% attack speed of max for item if ((HadStat[Constants.CRITCHANCE] > (ItemMaxStats[Constants.CRITCHANCE] * 0.45)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.45))) { if (BestFinalBonus < 1.3 && itemType != TrinityItemType.Quiver) BestFinalBonus = 1.3; } // 45% crit damage, 45% attack speed of max for item if ((HadStat[Constants.CRITDAMAGE] > (ItemMaxStats[Constants.CRITDAMAGE] * 0.45)) && (HadStat[Constants.ATTACKSPEED] > (ItemMaxStats[Constants.ATTACKSPEED] * 0.45))) { if (BestFinalBonus < 1.1 && itemType != TrinityItemType.Quiver) BestFinalBonus = 1.1; } }
private static void CheckForInvalidItemType(TrinityItemType itemType) { // One Handed Weapons if (itemType == TrinityItemType.Axe || itemType == TrinityItemType.CeremonialKnife || itemType == TrinityItemType.Dagger || itemType == TrinityItemType.FistWeapon || itemType == TrinityItemType.Mace || itemType == TrinityItemType.MightyWeapon || itemType == TrinityItemType.Spear || itemType == TrinityItemType.Sword || itemType == TrinityItemType.Wand || itemType == TrinityItemType.HandCrossbow) { Array.Copy(Constants.MaxPointsWeaponOneHand, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.WeaponPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Two Handed Weapons if (itemType == TrinityItemType.TwoHandAxe || itemType == TrinityItemType.TwoHandDaibo || itemType == TrinityItemType.TwoHandMace || itemType == TrinityItemType.TwoHandMighty || itemType == TrinityItemType.TwoHandPolearm || itemType == TrinityItemType.TwoHandStaff || itemType == TrinityItemType.TwoHandSword || itemType == TrinityItemType.TwoHandCrossbow || itemType == TrinityItemType.TwoHandBow) { Array.Copy(Constants.MaxPointsWeaponTwoHand, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.WeaponPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Off-handed stuff // Mojo, Source, Quiver if (itemType == TrinityItemType.Mojo || itemType == TrinityItemType.Orb || itemType == TrinityItemType.Quiver) { Array.Copy(Constants.MaxPointsOffHand, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Shields if (itemType == TrinityItemType.Shield) { Array.Copy(Constants.MaxPointsShield, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Jewelry // Ring if (itemType == TrinityItemType.Amulet) { Array.Copy(Constants.MaxPointsAmulet, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.JewelryPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Ring if (itemType == TrinityItemType.Ring) { Array.Copy(Constants.MaxPointsRing, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.JewelryPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Armor // Belt if (itemType == TrinityItemType.Belt) { Array.Copy(Constants.MaxPointsBelt, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Boots if (itemType == TrinityItemType.Boots) { Array.Copy(Constants.MaxPointsBoots, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Bracers if (itemType == TrinityItemType.Bracer) { Array.Copy(Constants.MaxPointsBracer, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Chest if (itemType == TrinityItemType.Chest) { Array.Copy(Constants.MaxPointsChest, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } if (itemType == TrinityItemType.Cloak) { Array.Copy(Constants.MaxPointsCloak, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Gloves if (itemType == TrinityItemType.Gloves) { Array.Copy(Constants.MaxPointsGloves, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Helm if (itemType == TrinityItemType.Helm) { Array.Copy(Constants.MaxPointsHelm, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Pants if (itemType == TrinityItemType.Legs) { Array.Copy(Constants.MaxPointsPants, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } if (itemType == TrinityItemType.MightyBelt) { Array.Copy(Constants.MaxPointsMightyBelt, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Shoulders if (itemType == TrinityItemType.Shoulder) { Array.Copy(Constants.MaxPointsShoulders, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } if (itemType == TrinityItemType.SpiritStone) { Array.Copy(Constants.MaxPointsSpiritStone, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } if (itemType == TrinityItemType.VoodooMask) { Array.Copy(Constants.MaxPointsVoodooMask, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Wizard Hat if (itemType == TrinityItemType.WizardHat) { Array.Copy(Constants.MaxPointsWizardHat, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.ArmorPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } // Follower Items if (itemType == TrinityItemType.FollowerEnchantress || itemType == TrinityItemType.FollowerScoundrel || itemType == TrinityItemType.FollowerTemplar) { Array.Copy(Constants.MaxPointsFollower, ItemMaxStats, Constants.TOTALSTATS); Array.Copy(Constants.JewelryPointsAtMax, ItemMaxPoints, Constants.TOTALSTATS); IsInvalidItem = false; } }
/// <summary> /// Get all the possible options for multi-value item properties. /// For example Skill Damage for Quiver can be for the Sentry, Cluster Arrow, Multishot etc. /// </summary> public static List<object> GetItemPropertyVariants(ItemProperty prop, TrinityItemType itemType) { var result = new List<object>(); switch (prop) { case ItemProperty.SkillDamage: var classRestriction = (Item.GetClassRestriction(itemType)); result = GetSkillsForItemType(itemType, classRestriction).Cast<object>().ToList(); break; case ItemProperty.ElementalDamage: result = new List<object> { Element.Poison.ToEnumValue(), Element.Holy.ToEnumValue(), Element.Cold.ToEnumValue(), Element.Arcane.ToEnumValue(), Element.Fire.ToEnumValue(), Element.Physical.ToEnumValue(), Element.Lightning.ToEnumValue(), Element.Any.ToEnumValue() }; break; case ItemProperty.ElementalResist: result = new List<object> { Element.Poison.ToEnumValue(), Element.Holy.ToEnumValue(), Element.Cold.ToEnumValue(), Element.Arcane.ToEnumValue(), Element.Fire.ToEnumValue(), Element.Physical.ToEnumValue(), Element.Lightning.ToEnumValue(), Element.Any.ToEnumValue() }; break; } return result; }
public static List<Skill> GetSkillsForItemType(TrinityItemType itemType, ActorClass actorClass = ActorClass.Invalid) { var result = new List<Skill>(); if (actorClass != ActorClass.Invalid) { var kvp = new KeyValuePair<TrinityItemType, ActorClass>(itemType, actorClass); result.AddRange(SkillDamageByItemTypeAndClass[kvp]); } else { var actorClasses = new List<ActorClass> { ActorClass.Monk, ActorClass.DemonHunter, ActorClass.Witchdoctor, ActorClass.Wizard, ActorClass.Crusader, ActorClass.Barbarian }; foreach (var ac in actorClasses) { var kvp = new KeyValuePair<TrinityItemType, ActorClass>(itemType, ac); result.AddRange(SkillDamageByItemTypeAndClass[kvp]); } } return result; }
/// <summary> /// Log the rubbish junk items we salvaged or sold /// </summary> internal static void LogJunkItems(CachedACDItem acdItem, TrinityItemBaseType itemBaseType, TrinityItemType itemType, double itemValue) { FileStream logStream = null; try { string filePath = Path.Combine(FileManager.LoggingPath, "JunkLog - " + Trinity.Player.ActorClass + ".log"); logStream = File.Open(filePath, FileMode.Append, FileAccess.Write, FileShare.Read); using (var logWriter = new StreamWriter(logStream)) { if (!_loggedJunkThisStash) { _loggedJunkThisStash = true; logWriter.WriteLine(DateTime.Now + ":"); logWriter.WriteLine("===================="); } string isLegendaryItem = ""; if (acdItem.Quality >= ItemQuality.Legendary) isLegendaryItem = " {legendary item}"; logWriter.WriteLine(itemBaseType + " - " + itemType + " '" + acdItem.RealName + "'. Score = " + itemValue.ToString("0") + isLegendaryItem); if (JunkItemStatString != "") logWriter.WriteLine(" " + JunkItemStatString); else logWriter.WriteLine(" (no scorable attributes)"); logWriter.WriteLine(""); } logStream.Close(); } catch (IOException) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Fatal Error: File access error for junk log file."); if (logStream != null) logStream.Close(); } }
/// <summary> /// Log the rubbish junk items we salvaged or sold /// </summary> internal static void LogJunkItems(CachedACDItem acdItem, TrinityItemBaseType itemBaseType, TrinityItemType itemType, double itemValue) { FileStream logStream = null; try { string filePath = Path.Combine(FileManager.LoggingPath, "JunkLog - " + Trinity.Player.ActorClass + ".log"); logStream = File.Open(filePath, FileMode.Append, FileAccess.Write, FileShare.Read); using (var logWriter = new StreamWriter(logStream)) { if (!_loggedJunkThisStash) { _loggedJunkThisStash = true; logWriter.WriteLine(DateTime.Now + ":"); logWriter.WriteLine("===================="); } string isLegendaryItem = ""; if (acdItem.Quality >= ItemQuality.Legendary) { isLegendaryItem = " {legendary item}"; } logWriter.WriteLine(itemBaseType + " - " + itemType + " '" + acdItem.RealName + "'. Score = " + itemValue.ToString("0") + isLegendaryItem); if (JunkItemStatString != "") { logWriter.WriteLine(" " + JunkItemStatString); } else { logWriter.WriteLine(" (no scorable attributes)"); } logWriter.WriteLine(""); } logStream.Close(); } catch (IOException) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Fatal Error: File access error for junk log file."); if (logStream != null) { logStream.Close(); } } }
private static void RefreshStepMainObjectType(ref bool AddToCache) { // Now do stuff specific to object types switch (CurrentCacheObject.Type) { case TrinityObjectType.Player: { AddToCache = RefreshUnit(); break; } // Handle Unit-type Objects case TrinityObjectType.Unit: { // Not allowed to kill monsters due to profile settings if (!CombatBase.IsCombatAllowed) { AddToCache = false; c_IgnoreSubStep = "CombatDisabled"; break; } AddToCache = RefreshUnit(); break; } // Handle Item-type Objects case TrinityObjectType.Item: { // Not allowed to loot due to profile settings // rrrix disabled this since noobs can't figure out their profile is broken... looting is always enabled now //if (!LootTargeting.Instance.AllowedToLoot || LootTargeting.Instance.DisableLooting) //{ // AddToCache = false; // c_IgnoreSubStep = "LootingDisabled"; // break; //} _cItemTinityItemType = TrinityItemManager.DetermineItemType(CurrentCacheObject.InternalName, c_DBItemType, c_item_tFollowerType); var isPickupNoClick = DataDictionary.NoPickupClickTypes.Contains(_cItemTinityItemType); if (!isPickupNoClick && TrinityItemManager.FindValidBackpackLocation(true) == new Vector2(-1, -1)) { AddToCache = false; c_IgnoreSubStep = "NoFreeSlots"; break; } AddToCache = RefreshItem(); break; } // Handle Gold case TrinityObjectType.Gold: { // Not allowed to loot due to profile settings //if (!LootTargeting.Instance.AllowedToLoot || LootTargeting.Instance.DisableLooting) //{ // AddToCache = false; // c_IgnoreSubStep = "LootingDisabled"; // break; //} AddToCache = RefreshGold(); break; } case TrinityObjectType.PowerGlobe: case TrinityObjectType.HealthGlobe: case TrinityObjectType.ProgressionGlobe: { AddToCache = true; break; } // Handle Avoidance Objects case TrinityObjectType.Avoidance: { if (Settings.Combat.Misc.AvoidAOE) { AddToCache = RefreshAvoidance(); if (!AddToCache) { c_IgnoreSubStep = "RefreshAvoidance"; } } break; } // Handle Other-type Objects case TrinityObjectType.Destructible: case TrinityObjectType.Door: case TrinityObjectType.Barricade: case TrinityObjectType.Container: case TrinityObjectType.Shrine: case TrinityObjectType.Interactable: case TrinityObjectType.HealthWell: case TrinityObjectType.CursedChest: case TrinityObjectType.CursedShrine: { AddToCache = RefreshGizmo(); break; } // Object switch on type (to separate shrines, destructibles, barricades etc.) default: { DebugUtil.LogUnknown(c_diaObject); c_IgnoreSubStep = "Unknown." + c_diaObject.ActorType; AddToCache = false; break; } } }
/// <summary> /// Initializes variable set for single object refresh /// </summary> private static void RefreshStepInit() { CurrentCacheObject = new TrinityCacheObject(); // Start this object as off as unknown type CurrentCacheObject.Type = TrinityObjectType.Unknown; CurrentCacheObject.GizmoType = GizmoType.None; CurrentCacheObject.Distance = 0f; CurrentCacheObject.Radius = 0f; c_ZDiff = 0f; c_ItemDisplayName = ""; c_ItemLink = ""; CurrentCacheObject.InternalName = ""; c_IgnoreReason = ""; c_IgnoreSubStep = ""; CurrentCacheObject.ACDGuid = -1; CurrentCacheObject.RActorGuid = -1; CurrentCacheObject.DynamicID = -1; CurrentCacheObject.GameBalanceID = -1; CurrentCacheObject.ActorSNO = -1; c_ItemLevel = -1; c_GoldStackSize = -1; c_HitPointsPct = -1; c_HitPoints = -1; c_IsOneHandedItem = false; c_IsTwoHandedItem = false; c_unit_IsElite = false; c_unit_IsRare = false; c_unit_IsUnique = false; c_unit_IsMinion = false; c_unit_IsTreasureGoblin = false; c_unit_IsAttackable = false; c_unit_HasShieldAffix = false; c_IsEliteRareUnique = false; c_IsObstacle = false; c_HasBeenNavigable = false; c_HasBeenRaycastable = false; c_HasBeenInLoS = false; c_ItemMd5Hash = string.Empty; c_ItemQuality = ItemQuality.Invalid; c_DBItemBaseType = ItemBaseType.None; c_DBItemType = ItemType.Unknown; c_item_tFollowerType = FollowerType.None; _cItemTinityItemType = TrinityItemType.Unknown; c_unit_MonsterSize = MonsterSize.Unknown; c_diaObject = null; c_diaGizmo = null; c_CurrentAnimation = SNOAnim.Invalid; c_HasDotDPS = false; c_MonsterAffixes = MonsterAffixes.None; }
public LItem GetitemTypeRule(TrinityItemType itemType) { return(ItemTypes.FirstOrDefault(sr => sr.TrinityItemType == itemType)); }
public static ItemSelectionType ToItemSelectionType(this TrinityItemType trinityItemType) { ItemSelectionType result; return(Enum.TryParse(trinityItemType.ToString(), out result) ? result : ItemSelectionType.Unknown); }
public bool ShouldStash(TrinityItem item) { if (Core.ProfileSettings.Options.ShouldKeepInBackpack(item.ActorSnoId)) { Core.Logger.Debug($"Profile Setting Keep in Backpack - Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(false); } if (item.IsAncient && Core.Settings.ItemList.AlwaysStashAncients) { Core.Logger.Debug($"Stashing due to ItemList setting - Always stash ancients. (col={item.InventoryColumn}, row={item.InventoryRow}). Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(true); } if (item.IsPrimalAncient && Core.Settings.ItemList.AlwaysStashPrimalAncients) { Core.Logger.Debug($"Stashing due to ItemList setting - Always stash primal ancients. (col={item.InventoryColumn}, row={item.InventoryRow}). Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(true); } // 451002, //sir williams - 451002 (TentacleBear_C_Unique_Cosmetic_02) // portrait - 410998 (Cosmetic_Portrait_Frame_1) if (item.InternalNameLowerCase.Contains("cosmetic")) { return(true); } if (item.IsProtected()) { Core.Logger.Debug($"Not stashing due to item being in a protected slot (col={item.InventoryColumn}, row={item.InventoryRow}). Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(false); } if (Core.Player.IsInventoryLockedForGreaterRift || !Core.Settings.Items.KeepLegendaryUnid && Core.Player.ParticipatingInTieredLootRun) { Core.Logger.Debug($"Not stashing due to inventory locked, keep unidentified setting or participating in loot run. Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(false); } if (item.RawItemType == RawItemType.TreasureBag) { return(Core.Settings.Items.StashTreasureBags); } if (GameData.VanityItems.Any(i => item.InternalName.StartsWith(i))) { return(true); } if (GameData.TransmogTable.Contains(item.GameBalanceId) || item.InternalName.StartsWith("Transmog") || item.ActorSnoId == 110952) //Rakanishu's Blade { var setting = Core.Settings.Items.SpecialItems.HasFlag(SpecialItemTypes.TransmogWhites); Core.Logger.Log($"Transmog found! - Stash Setting={setting} {item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId}"); return(setting); } if (item.RawItemType == RawItemType.CosmeticPet) { Core.Logger.Log($"Pet found! - Stashing it {item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId}"); return(true); } if (item.RawItemType == RawItemType.CosmeticWings) { Core.Logger.Log($"Wings found! - Stashing it {item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId}"); return(true); } if (item.RawItemType == RawItemType.CosmeticPennant) { Core.Logger.Log($"Wings found! - Stashing it {item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId}"); return(true); } if (item.RawItemType == RawItemType.CosmeticPortraitFrame) { Core.Logger.Log($"Portrait found! - Stashing it {item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId}"); return(true); } if (Core.Settings.Items.SpecialItems.HasFlag(SpecialItemTypes.RottenMushroom) && item.ActorSnoId == (int)SNOActor.A1_BlackMushroom) { Core.Logger.Log($"Rotten Mushroom found! - Stash Setting. Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(true); } if (GameData.HerdingMatsSnoIds.Contains(item.ActorSnoId)) { Core.Logger.Log($"Staff of Herding Mat found! - Stash Setting. Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(true); } // Now look for Misc items we might want to keep TrinityItemType tItemType = item.TrinityItemType; TrinityItemBaseType tBaseType = item.TrinityItemBaseType; // Keep any high gems placed in backpack while levelling, so we can socket items with them. if (item.IsGem && item.GemQuality >= GemQuality.Marquise && ZetaDia.Me.Level < 70) { return(false); } var isHandledLegendaryType = item.ItemBaseType == ItemBaseType.Armor || item.ItemBaseType == ItemBaseType.Jewelry || item.ItemBaseType == ItemBaseType.Weapon || item.IsPotion; if (item.ItemQualityLevel >= ItemQuality.Legendary && isHandledLegendaryType) { /* Stash items that hasn't had their legendary power extracted if the CubeExtractOption is set, if we have no currency for extracting it we can assume it would have been salvaged instead. * if (Core.Settings.KanaisCube.ExtractLegendaryPowers != CubeExtractOption.None && !Core.Inventory.Currency.HasCurrency(TransmuteRecipe.ExtractLegendaryPower)) * { * Item legendaryItem = Legendary.GetItem(item); * * if (legendaryItem != null && legendaryItem.LegendaryAffix != "" && * Core.Inventory.Stash.ByActorSno(legendaryItem.Id) != null && * !ZetaDia.Storage.PlayerDataManager.ActivePlayerData.KanaisPowersExtractedActorSnoIds.Contains( * legendaryItem.Id)) * { * Core.Logger.Debug($"Stashing due to legendary power hasn't been extracted yet."); * return true; * } * }*/ if (Core.Settings.Items.LegendaryMode == LegendaryMode.Ignore) { Core.Logger.Log($"TRASHING: Ignore Legendary. Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(false); } if (Core.Settings.Items.LegendaryMode == LegendaryMode.AlwaysStash) { Core.Logger.Log($"STASHING: Always Stash Legendary Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(true); } if (Core.Settings.Items.LegendaryMode == LegendaryMode.StashAncients) { if (item.IsAncient) { Core.Logger.Log($"STASHING: Only Stash Ancients Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(true); } Core.Logger.Log($"TRASHING: Only Stash Ancients Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(false); } if (Core.Settings.ItemList.AlwaysTrashNonAncients && !item.IsAncient) { Core.Logger.Log($"TRASHING: ItemList Option - Always Sell/Salvage Non-Ancients Item={item.Name} InternalName={item.InternalName} Sno={item.ActorSnoId} GbId={item.GameBalanceId} RawItemType={item.RawItemType}"); return(false); } } bool isEquipment = (tBaseType == TrinityItemBaseType.Armor || tBaseType == TrinityItemBaseType.Jewelry || tBaseType == TrinityItemBaseType.Offhand || tBaseType == TrinityItemBaseType.WeaponOneHand || tBaseType == TrinityItemBaseType.WeaponRange || tBaseType == TrinityItemBaseType.WeaponTwoHand); if (item.ItemType == ItemType.KeystoneFragment) { return(true); } if (item.TrinityItemType == TrinityItemType.HoradricCache) { return(false); } if (item.IsUnidentified) { Core.Logger.Log("{0} [{1}] = (autokeep unidentified items)", item.Name, item.InternalName); return(true); } if (tItemType == TrinityItemType.StaffOfHerding) { Core.Logger.Log(LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep staff of herding)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.CraftingMaterial || item.IsCraftingReagent) { Core.Logger.Log(LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep craft materials)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.Emerald || tItemType == TrinityItemType.Amethyst || tItemType == TrinityItemType.Topaz || tItemType == TrinityItemType.Ruby || tItemType == TrinityItemType.Diamond) { Core.Logger.Log(LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep gems)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.CraftTome) { Core.Logger.Log(LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep tomes)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.InfernalKey) { Core.Logger.Log("{0} [{1}] [{2}] = (autokeep infernal key)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.HealthPotion) { var equippedPotion = Core.Player.EquippedHealthPotion; if (equippedPotion == null) { Core.Logger.Debug("Potion being stashed because an equipped potion was not found."); return(true); } if (equippedPotion.AnnId == item.AnnId) { Core.Logger.Debug($"{item.Name} [{item.InternalName}] [{tItemType}] = (dont stash equipped potion)"); return(false); } } if (tItemType == TrinityItemType.CraftingPlan && item.ItemQualityLevel >= ItemQuality.Legendary) { Core.Logger.Log("{0} [{1}] [{2}] = (autokeep legendary plans)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.ConsumableAddSockets) { Core.Logger.Log("{0} [{1}] [{2}] = (autokeep Ramaladni's Gift)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.PortalDevice) { Core.Logger.Log("{0} [{1}] [{2}] = (autokeep Machines)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.UberReagent) { Core.Logger.Log("{0} [{1}] [{2}] = (autokeep Uber Reagents)", item.Name, item.InternalName, tItemType); return(true); } if (tItemType == TrinityItemType.TieredLootrunKey) { Core.Logger.Log("{0} [{1}] [{2}] = (ignoring Tiered Rift Keys)", item.Name, item.InternalName, tItemType); return(false); } if (tItemType == TrinityItemType.CraftingPlan) { Core.Logger.Log("{0} [{1}] [{2}] = (autokeep plans)", item.Name, item.InternalName, tItemType); return(true); } if (item.ItemQualityLevel <= ItemQuality.Superior && (isEquipment || item.TrinityItemBaseType == TrinityItemBaseType.FollowerItem)) { Core.Logger.Log("{0} [{1}] [{2}] = (trash whites)", item.Name, item.InternalName, tItemType); return(false); } if (item.ItemQualityLevel >= ItemQuality.Magic1 && item.ItemQualityLevel <= ItemQuality.Magic3 && (isEquipment || item.TrinityItemBaseType == TrinityItemBaseType.FollowerItem)) { Core.Logger.Log("{0} [{1}] [{2}] = (trashing blues)", item.Name, item.InternalName, tItemType); return(false); } if (item.ItemQualityLevel >= ItemQuality.Rare4 && item.ItemQualityLevel <= ItemQuality.Rare6 && (isEquipment || item.TrinityItemBaseType == TrinityItemBaseType.FollowerItem)) { Core.Logger.Log("{0} [{1}] [{2}] = (force salvage rare)", item.Name, item.InternalName, tItemType); return(false); } if (item.ItemQualityLevel >= ItemQuality.Legendary && Core.Settings.Items.LegendaryMode == LegendaryMode.ItemList && (item.IsEquipment || item.TrinityItemBaseType == TrinityItemBaseType.FollowerItem || item.IsPotion)) { var result = ItemListEvaluator.ShouldStashItem(item); Core.Logger.Log("{0} [{1}] [{2}] = {3}", item.Name, item.InternalName, tItemType, "ItemListCheck=" + (result ? "KEEP" : "TRASH")); return(result); } if (item.ItemQualityLevel >= ItemQuality.Legendary) { Core.Logger.Log("{0} [{1}] [{2}] = (autokeep legendaries)", item.Name, item.InternalName, tItemType); return(true); } // If we reached this point, then we found no reason to keep the item! return(false); }
/// <summary> /// Log the nice items we found and stashed /// </summary> internal static void LogGoodItems(CachedACDItem acdItem, TrinityItemBaseType itemBaseType, TrinityItemType itemType, double itemValue) { FileStream logStream = null; try { string filePath = Path.Combine(FileManager.LoggingPath, "StashLog - " + Trinity.Player.ActorClass + ".log"); logStream = File.Open(filePath, FileMode.Append, FileAccess.Write, FileShare.Read); //TODO : Change File Log writing using (var logWriter = new StreamWriter(logStream)) { if (!_loggedAnythingThisStash) { _loggedAnythingThisStash = true; logWriter.WriteLine(DateTime.Now + ":"); logWriter.WriteLine("===================="); } string sLegendaryString = ""; bool shouldSendNotifications = false; if (acdItem.Quality >= ItemQuality.Legendary) { if (!Trinity.Settings.Notification.LegendaryScoring) shouldSendNotifications = true; else if (Trinity.Settings.Notification.LegendaryScoring && ItemValuation.CheckScoreForNotification(itemBaseType, itemValue)) shouldSendNotifications = true; if (shouldSendNotifications) NotificationManager.AddNotificationToQueue(acdItem.RealName + " [" + itemType + "] (Score=" + itemValue + ". " + acdItem.AcdItem.Stats + ")", ZetaDia.Service.Hero.Name + " new legendary!", ProwlNotificationPriority.Emergency); sLegendaryString = " {legendary item}"; // Change made by bombastic Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+=+=+=+=+=+=+=+=+ LEGENDARY FOUND +=+=+=+=+=+=+=+=+"); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+ Name: {0} ({1})", acdItem.RealName, itemType); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+ Score: {0:0}", itemValue); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+ Attributes: {0}", acdItem.AcdItem.Stats.ToString()); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+"); } else { // Check for non-legendary notifications shouldSendNotifications = ItemValuation.CheckScoreForNotification(itemBaseType, itemValue); if (shouldSendNotifications) NotificationManager.AddNotificationToQueue(acdItem.RealName + " [" + itemType + "] (Score=" + itemValue + ". " + acdItem.AcdItem.Stats + ")", ZetaDia.Service.Hero.BattleTagName + " new item!", ProwlNotificationPriority.Normal); } if (shouldSendNotifications) { NotificationManager.EmailMessage.AppendLine(itemBaseType + " - " + itemType + " '" + acdItem.RealName + "'. Score = " + Math.Round(itemValue) + sLegendaryString) .AppendLine(" " + acdItem.AcdItem.Stats) .AppendLine(); } logWriter.WriteLine(itemBaseType + " - " + itemType + " '" + acdItem.RealName + "'. Score = " + Math.Round(itemValue) + sLegendaryString); logWriter.WriteLine(" " + acdItem.AcdItem.Stats); logWriter.WriteLine(""); } logStream.Close(); } catch (IOException) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Fatal Error: File access error for stash log file."); if (logStream != null) logStream.Close(); } }
/// <summary> /// Log the nice items we found and stashed /// </summary> internal static void LogGoodItems(CachedACDItem acdItem, TrinityItemBaseType itemBaseType, TrinityItemType itemType, double itemValue) { FileStream logStream = null; try { string filePath = Path.Combine(FileManager.LoggingPath, "StashLog - " + Trinity.Player.ActorClass + ".log"); logStream = File.Open(filePath, FileMode.Append, FileAccess.Write, FileShare.Read); //TODO : Change File Log writing using (var logWriter = new StreamWriter(logStream)) { if (!_loggedAnythingThisStash) { _loggedAnythingThisStash = true; logWriter.WriteLine(DateTime.Now + ":"); logWriter.WriteLine("===================="); } string sLegendaryString = ""; bool shouldSendNotifications = false; if (acdItem.Quality >= ItemQuality.Legendary) { if (!Trinity.Settings.Notification.LegendaryScoring) { shouldSendNotifications = true; } else if (Trinity.Settings.Notification.LegendaryScoring && ItemValuation.CheckScoreForNotification(itemBaseType, itemValue)) { shouldSendNotifications = true; } if (shouldSendNotifications) { NotificationManager.AddNotificationToQueue(acdItem.RealName + " [" + itemType + "] (Score=" + itemValue + ". " + acdItem.AcdItem.Stats + ")", ZetaDia.Service.Hero.Name + " new legendary!", ProwlNotificationPriority.Emergency); } sLegendaryString = " {legendary item}"; // Change made by bombastic Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+=+=+=+=+=+=+=+=+ LEGENDARY FOUND +=+=+=+=+=+=+=+=+"); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+ Name: {0} ({1})", acdItem.RealName, itemType); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+ Score: {0:0}", itemValue); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+ Attributes: {0}", acdItem.AcdItem.Stats.ToString()); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+"); } else { // Check for non-legendary notifications shouldSendNotifications = ItemValuation.CheckScoreForNotification(itemBaseType, itemValue); if (shouldSendNotifications) { NotificationManager.AddNotificationToQueue(acdItem.RealName + " [" + itemType + "] (Score=" + itemValue + ". " + acdItem.AcdItem.Stats + ")", ZetaDia.Service.Hero.BattleTagName + " new item!", ProwlNotificationPriority.Normal); } } if (shouldSendNotifications) { NotificationManager.EmailMessage.AppendLine(itemBaseType + " - " + itemType + " '" + acdItem.RealName + "'. Score = " + Math.Round(itemValue) + sLegendaryString) .AppendLine(" " + acdItem.AcdItem.Stats) .AppendLine(); } logWriter.WriteLine(itemBaseType + " - " + itemType + " '" + acdItem.RealName + "'. Score = " + Math.Round(itemValue) + sLegendaryString); logWriter.WriteLine(" " + acdItem.AcdItem.Stats); logWriter.WriteLine(""); } logStream.Close(); } catch (IOException) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Fatal Error: File access error for stash log file."); if (logStream != null) { logStream.Close(); } } }