internal static void SetStolenForever(this BSExtraDataList entry) { var ownerBad = TESForm.LookupFormById(StolenForeverOwnerFormId); if (ownerBad == null) { return; } var ownerPtr = ownerBad.Cast <TESForm>(); if (ownerPtr == IntPtr.Zero) { return; } var ptr = entry.Cast <BSExtraDataList>(); if (ptr != IntPtr.Zero) { Memory.InvokeCdecl(BetterStealingPlugin._SetListOwner_Func, ptr, ownerPtr); return; } throw new ArgumentNullException(); }
internal static int GetCount(this BSExtraDataList entry) { var ptr = entry.Cast <BSExtraDataList>(); if (ptr != IntPtr.Zero) { return(Memory.InvokeCdecl(BetterStealingPlugin._GetCount_Func, ptr).ToInt32Safe()); } throw new ArgumentNullException(); }
private void ApplyResult(ExtraContainerChanges.ItemEntry entry, BSExtraDataList data, bool detected) { if (!detected) { data.SetOwner(null); } else { data.SetStolenForever(); } }
internal static void SetCustomData(this BSExtraDataList entry, uint data) { var ptr = entry.Cast <BSExtraDataList>(); if (ptr != IntPtr.Zero) { var bytes = BitConverter.GetBytes(data); float arg = BitConverter.ToSingle(bytes, 0); Memory.InvokeCdecl(BetterStealingPlugin._SetNorth_Func, ptr, arg); return; } throw new ArgumentNullException(); }
internal static void PushContainerItem(TESForm baseForm, BSExtraDataList data, int count) { if (baseForm == null || count <= 0) { return; } if (data == null) { return; } var owner = data.GetOwner(); uint cdata = data.GetCustomData(); if (owner == null || (cdata & 0x80000000) != 0) { return; } if (owner.FormId == _InventoryExtensions.StolenForeverOwnerFormId) { return; } int ndata = ++_cdata_counter; if (_cdata_counter >= 0x40000000) { _cdata_counter = 0; } data.SetCustomData((uint)ndata); var ci = new queued_item(); ci.BaseForm = baseForm; ci.Count = count; ci.Owner = owner; ci.CData = (uint)ndata; lock (Locker) { if (QueuedContainer != null) { QueuedContainer.Add(ci); } } }
internal static bool HasEnchantment(this BSExtraDataList entry) { var n = entry.First; while (n != null) { if (n is ExtraEnchantment) { return(true); } n = n.Next; } return(false); }
internal static uint GetCustomData(this BSExtraDataList entry) { var ptr = entry.Cast <BSExtraDataList>(); if (ptr != IntPtr.Zero) { float arg = Memory.InvokeCdeclF(BetterStealingPlugin._GetNorth_Func, ptr); if (arg == 0.0f) { return(0); } var bytes = BitConverter.GetBytes(arg); return(BitConverter.ToUInt32(bytes, 0)); } throw new ArgumentNullException(); }
internal static void SetOwner(this BSExtraDataList entry, TESForm owner) { var ownerptr = owner != null?owner.Cast <TESForm>() : IntPtr.Zero; if (owner != null && ownerptr == IntPtr.Zero) { throw new ArgumentOutOfRangeException(); } var ptr = entry.Cast <BSExtraDataList>(); if (ptr != IntPtr.Zero) { Memory.InvokeCdecl(BetterStealingPlugin._SetListOwner_Func, ptr, ownerptr); return; } throw new ArgumentNullException(); }
internal static bool IsStolenForever(this BSExtraDataList entry) { var owner = entry.GetOwner(); return(owner != null && owner.FormId == StolenForeverOwnerFormId); }
internal static void RemoveContainerItem(TESForm baseForm, BSExtraDataList data, int count) { if (baseForm == null || count <= 0) { return; } if (data == null) { return; } var owner = data.GetOwner(); uint cdata = data.GetCustomData(); if (owner == null || (cdata & 0x80000000) != 0) { return; } if (owner.FormId == _InventoryExtensions.StolenForeverOwnerFormId) { return; } if (cdata != 0) { data.SetCustomData(0); } lock (Locker) { if (QueuedContainer == null) { return; } for (int i = QueuedContainer.Count - 1; i >= 0 && count > 0; i--) { var ci = QueuedContainer[i]; if (!ci.BaseForm.Equals(baseForm)) { continue; } if (ci.CData != cdata) { continue; } if (!ci.Owner.Equals(owner)) { continue; } if (count >= ci.Count) { QueuedContainer.RemoveAt(i); count -= ci.Count; } else { ci.Count -= count; count = 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); }
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); }