示例#1
0
        private bool TrinitySell(ACDItem item)
        {
            CachedACDItem cItem = CachedACDItem.GetCachedItem(item);

            // Vanity Items
            if (DataDictionary.VanityItems.Any(i => item.InternalName.StartsWith(i)))
            {
                return(false);
            }

            switch (cItem.TrinityItemBaseType)
            {
            case GItemBaseType.WeaponRange:
            case GItemBaseType.WeaponOneHand:
            case GItemBaseType.WeaponTwoHand:
            case GItemBaseType.Armor:
            case GItemBaseType.Offhand:
            case GItemBaseType.Jewelry:
            case GItemBaseType.FollowerItem:
                return(true);

            case GItemBaseType.Gem:
            case GItemBaseType.Misc:
                if (cItem.TrinityItemType == GItemType.CraftingPlan)
                {
                    return(true);
                }
                return(false);

            case GItemBaseType.Unknown:
                return(false);
            }

            return(false);
        }
示例#2
0
        public static CachedACDItem GetCachedItem(ACDItem item)
        {
            CachedACDItem cItem = new CachedACDItem(item.Stats)
            {
                AcdItem           = item,
                InternalName      = item.InternalName,
                RealName          = item.Name,
                Level             = item.Level,
                Quality           = item.ItemQualityLevel,
                GoldAmount        = item.Gold,
                BalanceID         = item.GameBalanceId,
                DynamicID         = item.DynamicId,
                OneHanded         = item.IsOneHand,
                TwoHanded         = item.IsTwoHand,
                DyeType           = item.DyeType,
                DBItemType        = item.ItemType,
                DBBaseType        = item.ItemBaseType,
                FollowerType      = item.FollowerSpecialType,
                IsUnidentified    = item.IsUnidentified,
                ItemStackQuantity = item.ItemStackQuantity,
                Row                 = item.InventoryRow,
                Column              = item.InventoryColumn,
                ItemLink            = item.ItemLink,
                TrinityItemType     = Trinity.DetermineItemType(item.InternalName, item.ItemType, item.FollowerSpecialType),
                TrinityItemBaseType = Trinity.DetermineBaseType(Trinity.DetermineItemType(item.InternalName, item.ItemType, item.FollowerSpecialType))
            };

            cItem.ComputeUpgrade();

            return(cItem);
        }
示例#3
0
        public static bool GetIsSalvageable(CachedACDItem cItem)
        {
            if (!cItem.IsEquipment)
            {
                return(false);
            }

            if (cItem.AcdItem.IsVendorBought)
            {
                return(false);
            }

            return(true);
        }
示例#4
0
        public static CachedACDItem GetCachedItem(ACDItem item)
        {
            try
            {
                if (!item.IsValid)
                {
                    return(default(CachedACDItem));
                }

                CachedACDItem cItem = new CachedACDItem(item.Stats)
                {
                    AcdItem           = item,
                    InternalName      = item.InternalName,
                    RealName          = item.Name,
                    Level             = item.Level,
                    Quality           = item.GetItemQuality(),
                    GoldAmount        = item.Gold,
                    BalanceID         = item.GameBalanceId,
                    DynamicID         = item.DynamicId,
                    ActorSNO          = item.ActorSNO,
                    OneHanded         = item.IsOneHand,
                    TwoHanded         = item.IsTwoHand,
                    DyeType           = item.DyeType,
                    DBItemType        = item.ItemType,
                    DBBaseType        = item.ItemBaseType,
                    FollowerType      = item.FollowerSpecialType,
                    IsUnidentified    = item.IsUnidentified,
                    ItemStackQuantity = item.ItemStackQuantity,
                    Row             = item.InventoryRow,
                    Column          = item.InventoryColumn,
                    ItemLink        = item.ItemLink,
                    GameBalanceId   = item.GameBalanceId,
                    TrinityItemType = TrinityItemManager.DetermineItemType(item.InternalName, item.ItemType, item.FollowerSpecialType),
                    IsAncient       = item.GetAttribute <int>(ActorAttributeType.AncientRank) > 0,
                };
                TrinityItemBaseType trinityItemBaseType = TrinityItemManager.DetermineBaseType(TrinityItemManager.DetermineItemType(item.InternalName, item.ItemType, item.FollowerSpecialType));
                cItem.TrinityItemBaseType = trinityItemBaseType;
                cItem.IsEquipment         = GetIsEquipment(trinityItemBaseType);
                cItem.IsSalvageable       = GetIsSalvageable(cItem);

                return(cItem);
            }
            catch (Exception ex)
            {
                Logger.LogError("Error getting CachedItem {0}", ex.Message);
                return(default(CachedACDItem));
            }
        }
示例#5
0
        public int CompareTo(object obj)
        {
            CachedACDItem item = (CachedACDItem)obj;

            if (Row < item.Row)
            {
                return(-1);
            }
            if (Column < item.Column)
            {
                return(-1);
            }
            if (Column == item.Column && Row == item.Row)
            {
                return(0);
            }
            return(1);
        }
示例#6
0
        internal static void TrinityOnItemSalvaged(object sender, ItemEventArgs e)
        {
            ACDItem i = e.Item;

            var cachedItem = CachedACDItem.GetCachedItem(i);

            ResetTownRun();
            switch (i.ItemBaseType)
            {
            case ItemBaseType.Gem:
            case ItemBaseType.Misc:
                break;

            default:
                TownRun.LogJunkItems(cachedItem, cachedItem.TrinityItemBaseType, cachedItem.TrinityItemType, ItemValuation.ValueThisItem(cachedItem, cachedItem.TrinityItemType));
                break;
            }
        }
示例#7
0
        public static CachedACDItem GetCachedItem(ACDItem item)
        {
            try
            {
                if (!item.IsValid)
                {
                    return(default(CachedACDItem));
                }

                CachedACDItem cItem = new CachedACDItem(item.Stats)
                {
                    AcdItem           = item,
                    InternalName      = item.InternalName,
                    RealName          = item.Name,
                    Level             = item.Level,
                    Quality           = item.ItemQualityLevel,
                    GoldAmount        = item.Gold,
                    BalanceID         = item.GameBalanceId,
                    DynamicID         = item.DynamicId,
                    OneHanded         = item.IsOneHand,
                    TwoHanded         = item.IsTwoHand,
                    DyeType           = item.DyeType,
                    DBItemType        = item.ItemType,
                    DBBaseType        = item.ItemBaseType,
                    FollowerType      = item.FollowerSpecialType,
                    IsUnidentified    = item.IsUnidentified,
                    ItemStackQuantity = item.ItemStackQuantity,
                    Row                 = item.InventoryRow,
                    Column              = item.InventoryColumn,
                    ItemLink            = item.ItemLink,
                    TrinityItemType     = Trinity.DetermineItemType(item.InternalName, item.ItemType, item.FollowerSpecialType),
                    TrinityItemBaseType = Trinity.DetermineBaseType(Trinity.DetermineItemType(item.InternalName, item.ItemType, item.FollowerSpecialType))
                };

                cItem.ComputeUpgrade();
                return(cItem);
            }
            catch (Exception ex)
            {
                Logger.LogError("Error getting CachedItem {0}", ex.Message);
                return(default(CachedACDItem));
            }
        }
示例#8
0
        /// <summary>
        /// Log the rubbish junk items we salvaged or sold
        /// </summary>
        internal static void LogJunkItems(CachedACDItem acdItem, GItemBaseType itemBaseType, GItemType itemType, double itemValue)
        {
            FileStream LogStream = null;

            try
            {
                string filePath = Path.Combine(FileManager.LoggingPath, "JunkLog - " + Trinity.Player.ActorClass.ToString() + ".log");
                LogStream = File.Open(filePath, FileMode.Append, FileAccess.Write, FileShare.Read);
                using (StreamWriter LogWriter = new StreamWriter(LogStream))
                {
                    if (!_loggedJunkThisStash)
                    {
                        _loggedJunkThisStash = true;
                        LogWriter.WriteLine(DateTime.Now.ToString() + ":");
                        LogWriter.WriteLine("====================");
                    }
                    string isLegendaryItem = "";
                    if (acdItem.Quality >= ItemQuality.Legendary)
                    {
                        isLegendaryItem = " {legendary item}";
                    }
                    LogWriter.WriteLine(itemBaseType.ToString() + " - " + itemType.ToString() + " '" + 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();
                }
            }
        }
示例#9
0
        public bool ShouldSellItem(ACDItem item, ItemEvaluationType evaluationType)
        {
            ItemEvents.ResetTownRun();

            CachedACDItem cItem = CachedACDItem.GetCachedItem(item);

            if (Current.ItemIsProtected(cItem.AcdItem))
            {
                return(false);
            }

            if (Trinity.Settings.Loot.ItemFilterMode == ItemFilterMode.DemonBuddy)
            {
                return(Current.ShouldSellItem(item));
            }
            if (Trinity.Settings.Loot.ItemFilterMode == ItemFilterMode.TrinityWithItemRules)
            {
                return(ItemRulesSalvageSell(item, evaluationType));
            }
            return(TrinitySell(item));
        }
示例#10
0
        public int CompareTo(object obj)
        {
            CachedACDItem item = (CachedACDItem)obj;

            if (this.Row < item.Row)
            {
                return(-1);
            }
            else if (this.Column < item.Column)
            {
                return(-1);
            }
            else if (this.Column == item.Column && this.Row == item.Row)
            {
                return(0);
            }
            else
            {
                return(1);
            }
        }
示例#11
0
        public bool ShouldStashItem(ACDItem item, ItemEvaluationType evaluationType)
        {
            ItemEvents.ResetTownRun();

            if (Current.ItemIsProtected(item))
            {
                return(false);
            }

            // Vanity Items
            if (DataDictionary.VanityItems.Any(i => item.InternalName.StartsWith(i)))
            {
                return(false);
            }

            if (Trinity.Settings.Loot.ItemFilterMode == ItemFilterMode.DemonBuddy)
            {
                return(ItemManager.Current.ShouldStashItem(item));
            }

            CachedACDItem cItem = CachedACDItem.GetCachedItem(item);

            // Now look for Misc items we might want to keep
            GItemType     tItemType = cItem.TrinityItemType;     // DetermineItemType(cItem.InternalName, cItem.DBItemType, cItem.FollowerType);
            GItemBaseType tBaseType = cItem.TrinityItemBaseType; // DetermineBaseType(trinityItemType);

            bool isEquipment = (tBaseType == GItemBaseType.Armor ||
                                tBaseType == GItemBaseType.Jewelry ||
                                tBaseType == GItemBaseType.Offhand ||
                                tBaseType == GItemBaseType.WeaponOneHand ||
                                tBaseType == GItemBaseType.WeaponRange ||
                                tBaseType == GItemBaseType.WeaponTwoHand);

            if (cItem.TrinityItemType == GItemType.HoradricCache && Trinity.Settings.Loot.TownRun.OpenHoradricCaches)
            {
                Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] = (ignoring Horadric Cache)", cItem.RealName, cItem.InternalName);
                return(false);
            }

            // Stash all unidentified items - assume we want to keep them since we are using an identifier over-ride
            if (cItem.IsUnidentified)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] = (autokeep unidentified items)", cItem.RealName, cItem.InternalName);
                }
                return(true);
            }
            if (tItemType == GItemType.StaffOfHerding)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep staff of herding)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(true);
            }
            if (tItemType == GItemType.CraftingMaterial)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep craft materials)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(true);
            }

            if (tItemType == GItemType.Emerald || tItemType == GItemType.Amethyst || tItemType == GItemType.Topaz || tItemType == GItemType.Ruby || tItemType == GItemType.Diamond)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep gems)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(true);
            }
            if (tItemType == GItemType.CraftTome)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep tomes)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(true);
            }
            if (tItemType == GItemType.InfernalKey)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (autokeep infernal key)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(true);
            }
            if (tItemType == GItemType.HealthPotion)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (ignoring potions)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(false);
            }

            if (tItemType == GItemType.CraftingPlan && cItem.Quality >= ItemQuality.Legendary)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (autokeep legendary plans)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(true);
            }

            if (Trinity.Settings.Loot.ItemFilterMode == ItemFilterMode.TrinityWithItemRules)
            {
                Interpreter.InterpreterAction action = Trinity.StashRule.checkItem(item, evaluationType);

                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (" + action + ")", cItem.AcdItem.Name, cItem.AcdItem.InternalName, cItem.AcdItem.ItemType);
                }
                switch (action)
                {
                case Interpreter.InterpreterAction.KEEP:
                    return(true);

                case Interpreter.InterpreterAction.TRASH:
                    return(false);

                case Interpreter.InterpreterAction.SCORE:
                    break;
                }
            }

            if (tItemType == GItemType.CraftingPlan)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (autokeep plans)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(true);
            }

            // Stashing Whites, auto-keep
            if (Trinity.Settings.Loot.TownRun.StashWhites && isEquipment && cItem.Quality <= ItemQuality.Superior)
            {
                Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (stashing whites)", cItem.RealName, cItem.InternalName, tItemType);
                return(true);
            }
            // Else auto-trash
            if (cItem.Quality <= ItemQuality.Superior && (isEquipment || cItem.TrinityItemBaseType == GItemBaseType.FollowerItem))
            {
                Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (trash whites)", cItem.RealName, cItem.InternalName, tItemType);
                return(false);
            }

            // Stashing blues, auto-keep
            if (Trinity.Settings.Loot.TownRun.StashBlues && isEquipment && cItem.Quality >= ItemQuality.Magic1 && cItem.Quality <= ItemQuality.Magic3)
            {
                Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (stashing blues)", cItem.RealName, cItem.InternalName, tItemType);
                return(true);
            }
            // Else auto trash
            if (cItem.Quality >= ItemQuality.Magic1 && cItem.Quality <= ItemQuality.Magic3 && (isEquipment || cItem.TrinityItemBaseType == GItemBaseType.FollowerItem))
            {
                Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (trashing blues)", cItem.RealName, cItem.InternalName, tItemType);
                return(false);
            }

            // Force salvage Rares
            if (Trinity.Settings.Loot.TownRun.ForceSalvageRares && cItem.Quality >= ItemQuality.Rare4 && cItem.Quality <= ItemQuality.Rare6 && (isEquipment || cItem.TrinityItemBaseType == GItemBaseType.FollowerItem))
            {
                Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (force salvage rare)", cItem.RealName, cItem.InternalName, tItemType);
                return(false);
            }

            if (cItem.Quality >= ItemQuality.Legendary)
            {
                if (evaluationType == ItemEvaluationType.Keep)
                {
                    Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (autokeep legendaries)", cItem.RealName, cItem.InternalName, tItemType);
                }
                return(true);
            }

            // Ok now try to do some decent item scoring based on item types
            double iNeedScore = Trinity.ScoreNeeded(item.ItemBaseType);
            double iMyScore   = ItemValuation.ValueThisItem(cItem, tItemType);

            if (evaluationType == ItemEvaluationType.Keep)
            {
                Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "{0} [{1}] [{2}] = {3}", cItem.RealName, cItem.InternalName, tItemType, iMyScore);
            }
            if (iMyScore >= iNeedScore)
            {
                return(true);
            }

            // If we reached this point, then we found no reason to keep the item!
            return(false);
        }
示例#12
0
        public static CachedACDItem GetCachedItem(ACDItem item)
        {
            try
            {
                if (!item.IsValid)
                    return default(CachedACDItem);

                CachedACDItem cItem = new CachedACDItem(item.Stats)
                {
                    AcdItem = item,
                    InternalName = item.InternalName,
                    RealName = item.Name,
                    Level = item.Level,
                    Quality = item.ItemLinkColorQuality(),
                    GoldAmount = item.Gold,
                    BalanceID = item.GameBalanceId,
                    DynamicID = item.DynamicId,
                    ActorSNO = item.ActorSNO,
                    OneHanded = item.IsOneHand,
                    TwoHanded = item.IsTwoHand,
                    DyeType = item.DyeType,
                    DBItemType = item.ItemType,
                    DBBaseType = item.ItemBaseType,
                    FollowerType = item.FollowerSpecialType,
                    IsUnidentified = item.IsUnidentified,
                    ItemStackQuantity = item.ItemStackQuantity,
                    Row = item.InventoryRow,
                    Column = item.InventoryColumn,
                    ItemLink = item.ItemLink,
                    TrinityItemType = TrinityItemManager.DetermineItemType(item.InternalName, item.ItemType, item.FollowerSpecialType),
                    IsAncient = item.GetAttribute<int>(ActorAttributeType.AncientRank) > 0,

                };
                TrinityItemBaseType trinityItemBaseType = TrinityItemManager.DetermineBaseType(TrinityItemManager.DetermineItemType(item.InternalName, item.ItemType, item.FollowerSpecialType));
                cItem.TrinityItemBaseType = trinityItemBaseType;
                cItem.IsEquipment = GetIsEquipment(trinityItemBaseType);
                cItem.IsSalvageable = GetIsSalvageable(cItem);

                return cItem;
            }
            catch (Exception ex)
            {
                Logger.LogError("Error getting CachedItem {0}", ex.Message);
                return default(CachedACDItem);
            }

        }
示例#13
0
        /// <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);
        }
示例#14
0
 internal static bool IsWeaponArmorJewlery(CachedACDItem thisitem)
 {
     return (thisitem.DBBaseType == Zeta.Game.Internals.Actors.ItemBaseType.Armor || thisitem.DBBaseType == Zeta.Game.Internals.Actors.ItemBaseType.Jewelry || thisitem.DBBaseType == Zeta.Game.Internals.Actors.ItemBaseType.Weapon);
 }
示例#15
0
 /// <summary>
 /// Output test scores for everything in the backpack
 /// </summary>
 internal static void TestScoring()
 {
     using (new PerformanceLogger("TestScoring"))
     {
         using (var helper = new Helpers.ZetaCacheHelper())
         {
             try
             {
                 if (TownRun.TestingBackpack) return;
                 TownRun.TestingBackpack = true;
                 //ZetaDia.Actors.Update();
                 if (ZetaDia.Actors.Me == null)
                 {
                     Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Error testing scores - not in game world?");
                     return;
                 }
                 if (ZetaDia.IsInGame && !ZetaDia.IsLoadingWorld)
                 {
                     Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "===== Outputting Test Scores =====");
                     foreach (ACDItem item in ZetaDia.Me.Inventory.Backpack)
                     {
                         if (item.BaseAddress == IntPtr.Zero)
                         {
                             Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "GSError: Diablo 3 memory read error, or item became invalid [TestScore-1]");
                         }
                         else
                         {
                             CachedACDItem cItem = new CachedACDItem(item, item.InternalName, item.Name, item.Level, item.ItemQualityLevel, item.Gold, item.GameBalanceId, item.DynamicId,
                                 item.Stats.WeaponDamagePerSecond, item.IsOneHand, item.IsTwoHand, item.DyeType, item.ItemType, item.ItemBaseType, item.FollowerSpecialType, item.IsUnidentified, item.ItemStackQuantity,
                                 item.Stats);
                             bool bShouldStashTest = TrinityItemManager.Current.ShouldStashItem(item);
                             Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, bShouldStashTest ? "* KEEP *" : "-- TRASH --");
                         }
                     }
                     Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "===== Finished Test Score Outputs =====");
                     //Logger.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Note: See bad scores? Wrong item types? Known DB bug - restart DB before using the test button!");
                 }
                 else
                 {
                     Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Error testing scores - not in game world?");
                 }
                 TownRun.TestingBackpack = false;
             }
             catch (Exception ex)
             {
                 Logger.LogNormal("Exception in TestScoring(): {0}", ex);
                 TownRun.TestingBackpack = false;
             }
         }
     }
 }
示例#16
0
        /// <summary>
        /// Log the nice items we found and stashed
        /// </summary>
        internal static void LogGoodItems(CachedACDItem acdItem, GItemBaseType itemBaseType, GItemType itemType, double itemValue)
        {
            FileStream LogStream = null;

            try
            {
                string filePath = Path.Combine(FileManager.LoggingPath, "StashLog - " + Trinity.Player.ActorClass.ToString() + ".log");
                LogStream = File.Open(filePath, FileMode.Append, FileAccess.Write, FileShare.Read);

                //TODO : Change File Log writing
                using (StreamWriter LogWriter = new StreamWriter(LogStream))
                {
                    if (!_loggedAnythingThisStash)
                    {
                        _loggedAnythingThisStash = true;
                        LogWriter.WriteLine(DateTime.Now.ToString() + ":");
                        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 && Trinity.CheckScoreForNotification(itemBaseType, itemValue))
                        {
                            shouldSendNotifications = true;
                        }
                        if (shouldSendNotifications)
                        {
                            NotificationManager.AddNotificationToQueue(acdItem.RealName + " [" + itemType.ToString() +
                                                                       "] (Score=" + itemValue.ToString() + ". " + ValueItemStatString + ")",
                                                                       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}", ValueItemStatString);
                        Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+");
                    }
                    else
                    {
                        // Check for non-legendary notifications
                        shouldSendNotifications = Trinity.CheckScoreForNotification(itemBaseType, itemValue);
                        if (shouldSendNotifications)
                        {
                            NotificationManager.AddNotificationToQueue(acdItem.RealName + " [" + itemType.ToString() + "] (Score=" + itemValue.ToString() + ". " + ValueItemStatString + ")", ZetaDia.Service.Hero.Name + " new item!", ProwlNotificationPriority.Emergency);
                        }
                    }
                    if (shouldSendNotifications)
                    {
                        NotificationManager.EmailMessage.AppendLine(itemBaseType.ToString() + " - " + itemType.ToString() + " '" + acdItem.RealName + "'. Score = " + Math.Round(itemValue).ToString() + sLegendaryString)
                        .AppendLine("  " + ValueItemStatString)
                        .AppendLine();
                    }
                    LogWriter.WriteLine(itemBaseType.ToString() + " - " + itemType.ToString() + " '" + acdItem.RealName + "'. Score = " + Math.Round(itemValue).ToString() + sLegendaryString);
                    LogWriter.WriteLine("  " + ValueItemStatString);
                    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();
                }
            }
        }
示例#17
0
        private bool TrinitySalvage(ACDItem item)
        {
            CachedACDItem cItem = CachedACDItem.GetCachedItem(item);

            if (cItem.AcdItem.IsVendorBought)
            {
                return(false);
            }

            // Vanity Items
            if (DataDictionary.VanityItems.Any(i => item.InternalName.StartsWith(i)))
            {
                return(false);
            }

            GItemType     trinityItemType     = Trinity.DetermineItemType(cItem.InternalName, cItem.DBItemType, cItem.FollowerType);
            GItemBaseType trinityItemBaseType = Trinity.DetermineBaseType(trinityItemType);

            // Take Salvage Option corresponding to ItemLevel
            SalvageOption salvageOption = GetSalvageOption(cItem.Quality);

            // Stashing Whites
            if (Trinity.Settings.Loot.TownRun.StashWhites && cItem.Quality < ItemQuality.Magic1)
            {
                return(false);
            }

            // Stashing Blues
            if (Trinity.Settings.Loot.TownRun.StashBlues && cItem.Quality > ItemQuality.Superior && cItem.Quality < ItemQuality.Rare4)
            {
                return(false);
            }

            if (cItem.Quality >= ItemQuality.Legendary && salvageOption == SalvageOption.InfernoOnly && cItem.Level >= 60)
            {
                return(true);
            }

            switch (trinityItemBaseType)
            {
            case GItemBaseType.WeaponRange:
            case GItemBaseType.WeaponOneHand:
            case GItemBaseType.WeaponTwoHand:
            case GItemBaseType.Armor:
            case GItemBaseType.Offhand:
                return((cItem.Level >= 61 && salvageOption == SalvageOption.InfernoOnly) || salvageOption == SalvageOption.All);

            case GItemBaseType.Jewelry:
                return((cItem.Level >= 59 && salvageOption == SalvageOption.InfernoOnly) || salvageOption == SalvageOption.All);

            case GItemBaseType.FollowerItem:
                return((cItem.Level >= 60 && salvageOption == SalvageOption.InfernoOnly) || salvageOption == SalvageOption.All);

            case GItemBaseType.Gem:
            case GItemBaseType.Misc:
            case GItemBaseType.Unknown:
                return(false);

            default:
                return(false);
            }
        }
示例#18
0
        public static bool GetIsSalvageable(CachedACDItem cItem)
        {
            if (!cItem.IsEquipment)
                return false;

            if (cItem.AcdItem.IsVendorBought)
                return false;

            return true;
        }