internal static void ForeachEntry(this ExtraContainerChanges.ItemEntry item, ForeachItemDelegate func)
        {
            if (item == null || func == null)
            {
                return;
            }

            int total = item.Count;
            int left  = total;
            var ls    = item.ExtraData;

            if (ls != null)
            {
                foreach (var x in ls)
                {
                    if (x != null)
                    {
                        int c = x.GetCount();
                        if (c <= 0)
                        {
                            continue;
                        }

                        left -= c;
                        func(x, c);
                    }
                }
            }

            if (left > 0)
            {
                func(null, left);
            }
        }
Exemple #2
0
 private void ApplyResult(ExtraContainerChanges.ItemEntry entry, BSExtraDataList data, bool detected)
 {
     if (!detected)
     {
         data.SetOwner(null);
     }
     else
     {
         data.SetStolenForever();
     }
 }
Exemple #3
0
        /// <summary>
        /// Get the type of soul in a soul gem. Will return <see cref="SoulLevels.None"/>
        /// if there is no soul in the soul gem.
        /// </summary>
        /// <param name="itemEntry">The soul gem</param>
        /// <returns>The soul in the given soul gem</returns>
        public static SoulLevels GetSoulType([NotNull] this ExtraContainerChanges.ItemEntry itemEntry)
        {
            SoulLevels result = 0;

            var item = itemEntry.Template;

            if (item == null)
            {
                return(result);
            }

            var formPtr = item.Cast <TESForm>();

            if (formPtr == IntPtr.Zero)
            {
                return(result);
            }


            if (item.FormType != FormTypes.SoulGem)
            {
                return(result);
            }

            var baseSoul = Memory.ReadUInt8(formPtr + 0x108);

            BSSimpleList <BSExtraDataList> extraData = itemEntry.ExtraData;

            if (extraData == null)
            {
                return((SoulLevels)baseSoul);
            }

            extraData.Where(x => x != null).Do(x =>
            {
                var ptr = x.Cast <BSExtraDataList>();
                if (ptr == IntPtr.Zero)
                {
                    return;
                }

                var soul = Memory.InvokeCdecl(AddressLibrary.GetSoulTypeFunc, ptr).ToUInt8();
                if (soul == 0)
                {
                    soul = baseSoul;
                }

                result = (SoulLevels)soul;
            });

            return(result);
        }
Exemple #4
0
        /// <summary>
        /// Tries to get the extra enchantment of an item. The extra enchantment is different
        /// from a base enchantment in the way that the extra enchantment is what you apply
        /// when enchanting the item using the enchantment table and the base enchantment being
        /// the enchantment set in the actual form.
        /// </summary>
        /// <param name="itemEntry">The item</param>
        /// <param name="enchantment">The <see cref="ExtraEnchantment"/> of an item if return true</param>
        /// <returns>True if getting the extra enchantment as successful, false if not</returns>
        public static bool TryGetExtraEnchantment([NotNull] this ExtraContainerChanges.ItemEntry itemEntry,
                                                  out ExtraEnchantment enchantment)
        {
            enchantment = null;

            var item = itemEntry.Template;

            if (item == null)
            {
                return(false);
            }

            BSSimpleList <BSExtraDataList> extraData = itemEntry.ExtraData;

            if (extraData == null)
            {
                return(false);
            }

            ExtraEnchantment extraEnchantment = null;

            extraData.Where(x => x != null).Do(x =>
            {
                var n = x.First;
                while (n != null)
                {
                    if (n is ExtraEnchantment nEnchantment)
                    {
                        extraEnchantment = nEnchantment;
                        break;
                    }

                    n = n.Next;
                }
            });

            enchantment = extraEnchantment;
            return(extraEnchantment != null);
        }
Exemple #5
0
        /// <summary>
        /// Tries to get the base enchantment of an item. The base enchantment is different
        /// from an extra enchantment in the way that the extra enchantment is what you apply
        /// when enchanting the item using the enchantment table and the base enchantment being
        /// the enchantment set in the actual form.
        /// <para>THIS WILL CRASH YOUR GAME IF THE ITEM DOES NOT HAVE AN BASE ENCHANTMENT!</para>
        /// </summary>
        /// <param name="itemEntry">The item</param>
        /// <param name="enchantment">The pointer to the base enchantment if return true, else <see cref="IntPtr.Zero"/></param>
        /// <returns>True if getting the base enchantment was successful, false if not</returns>
        public static bool TryGetBaseEnchantment([NotNull] this ExtraContainerChanges.ItemEntry itemEntry, out IntPtr enchantment)
        {
            enchantment = IntPtr.Zero;
            var item = itemEntry.Template;

            if (item == null)
            {
                return(false);
            }

            var formPtr = item.Cast <TESForm>();

            if (formPtr == IntPtr.Zero)
            {
                return(false);
            }

            var baseEnchantmentPtr = Memory.InvokeCdecl(AddressLibrary.GetEnchantmentFunc, formPtr);

            enchantment = baseEnchantmentPtr;
            return(baseEnchantmentPtr != IntPtr.Zero);
        }
Exemple #6
0
        internal static bool CheckConditions(ExtraContainerChanges.ItemEntry entry, BSExtraDataList data, TESForm item)
        {
            // Game has a hardcoded check to ignore gold when it comes to ownership.
            if (item.FormId == 0xF)
            {
                return(false);
            }

            {
                var excludeForms = BetterStealingPlugin.ExcludeForms;
                if (excludeForms != null && excludeForms.Contains(item.FormId))
                {
                    return(false);
                }
            }

            if (Settings.Instance.ExcludeEnchantedItems)
            {
                if (data != null && data.HasEnchantment())
                {
                    return(false);
                }
            }

            var ls = BetterStealingPlugin.NeverKeywords;

            if (ls.Count != 0)
            {
                foreach (var x in ls)
                {
                    if (item.HasKeywordText(x))
                    {
                        return(false);
                    }
                }
            }

            ls = BetterStealingPlugin.AlwaysKeywords;
            if (ls.Count != 0)
            {
                foreach (var x in ls)
                {
                    if (item.HasKeywordText(x))
                    {
                        return(true);
                    }
                }
            }

            ls = BetterStealingPlugin.RequiredKeywords;
            if (ls.Count != 0)
            {
                bool has = false;
                foreach (var x in ls)
                {
                    if (item.HasKeywordText(x))
                    {
                        has = true;
                        break;
                    }
                }

                if (!has)
                {
                    return(false);
                }
            }

            int maxPrice = BetterStealingPlugin.MaxPrice;

            if (maxPrice > 0)
            {
                int cost;
                if (entry != null)
                {
                    cost = Memory.InvokeCdecl(BetterStealingPlugin._CalcCost_Func, entry.Cast <ExtraContainerChanges.ItemEntry>()).ToInt32Safe();
                }
                else
                {
                    cost = item.GoldValue;
                }

                if (cost > maxPrice)
                {
                    return(false);
                }
            }

            // Price, keyword, ID, type, etc.

            return(true);
        }
Exemple #7
0
        private bool ProcessInventory(ExtraContainerChanges.Data inventory, TESObjectREFR instance, TESForm item, TESForm owner, int count, uint?cdata = null)
        {
            if (inventory == null || item == null)
            {
                return(false);
            }

            // Special case for references, it might already be handled before. Containers have this check elsewhere.
            if (instance != null && instance.ExtraDataList.IsStolenForever())
            {
                return(false);
            }

            ExtraContainerChanges.ItemEntry entry = null;
            BSExtraDataList best      = null;
            int             bestCount = 0;

            foreach (var o in inventory.Objects)
            {
                var template = o.Template;
                if (template == null)
                {
                    continue;
                }

                if (!item.Equals(template))
                {
                    continue;
                }

                entry = o;

                o.ForeachEntry((data, icount) =>
                {
                    // Already not stolen.
                    var iowner = data != null ? data.GetOwner() : null;
                    if (iowner == null)
                    {
                        return;
                    }

                    if (cdata.HasValue && cdata.Value != data.GetCustomData())
                    {
                        return;
                    }

                    if (data.IsStolenForever())
                    {
                        return;
                    }

                    if (!CheckConditions(o, data, item))
                    {
                        return;
                    }

                    if (best == null || Math.Abs(count - bestCount) > Math.Abs(count - icount))
                    {
                        best      = data;
                        bestCount = icount;
                    }
                });

                break;
            }

            if (best == null)
            {
                return(false);
            }

            this.ApplyResult(entry, best, this.WasDetected);
            return(true);
        }