private void init() { NeverKeywords = (Settings.Instance.IgnoreKeywords ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList(); AlwaysKeywords = (Settings.Instance.AlwaysKeywords ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList(); RequiredKeywords = (Settings.Instance.RequireKeywords ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList(); MaxPrice = Settings.Instance.MaxPrice; if (Settings.Instance.Enabled) { Events.OnMainMenu.Register(e => { ExcludeForms = CachedFormList.TryParse(Settings.Instance.ExcludeFormIds ?? "", "BetterStealing", "ExcludeFormIds"); }); this.InstallHook("send steal alarm #1", 36427, 0, 7, "48 8B C4 44 89 48 20", ctx => { var info = StealInfo.Begin(); if (info == null) { return; } info.Type = StealInfo.GetCalledFromType(Memory.ReadPointer(ctx.SP)); info.Thief = MemoryObject.FromAddress <Actor>(ctx.CX); info.TargetObjRef = MemoryObject.FromAddress <TESObjectREFR>(ctx.DX); info.TargetObjBase = MemoryObject.FromAddress <TESForm>(ctx.R8); info.TargetObjCount = ctx.R9.ToInt32Safe(); info.UnspecifiedItemsWorth = Memory.ReadInt32(ctx.SP + 0x28); info.OwnerForm = MemoryObject.FromAddress <TESForm>(Memory.ReadPointer(ctx.SP + 0x30)); }); this.InstallHook("send steal alarm #2", 36427, 0x9D3, 7, "48 81 C4 38 01 00 00", ctx => { var info = StealInfo.Get(); if (info == null) { return; } info.WasDetected = Memory.ReadUInt8(ctx.SP + 0x40) != 0; info.State = 1; ApplyStolenSoon.Queue(1); }); this.InstallHook("open container", 50195, 0x20, 5, "E8", ctx => { StealInfo.BeginContainer(); ApplyFixCDataSoon.Queue(3); var pickpocket = _InventoryExtensions.GetCurrentlyPickPocketing(); if (pickpocket != null) { var info = StealInfo.Begin(); if (info != null) { info.Type = StealTypes.PickPocketCustom; info.Thief = PlayerCharacter.Instance; info.TargetObjRef = pickpocket; info.TargetObjBase = null; info.TargetObjCount = 0; info.WasDetected = false; info.UnspecifiedItemsWorth = 0; info.OwnerForm = pickpocket.BaseForm; info.State = 1; FinishPickPocketCheck.Queue(3); } } }); this.InstallHook("actor add item", 36525, 0, 5, "44 89 4C 24 20", ctx => { var pickpocket = _InventoryExtensions.GetCurrentlyPickPocketing(); if (pickpocket != null) { var who = MemoryObject.FromAddress <TESObjectREFR>(ctx.CX); if (who == null || !(who is Actor) || !((Actor)who).IsPlayer) { return; } var where = MemoryObject.FromAddress <TESObjectREFR>(Memory.ReadPointer(ctx.SP + 0x28)); if (where == null || !where.Equals(pickpocket)) { return; } var item = MemoryObject.FromAddress <TESForm>(ctx.DX); var data = MemoryObject.FromAddress <BSExtraDataList>(ctx.R8); int count = ctx.R9.ToInt32Safe(); StealInfo.PushContainerItem(item, data, count); } else { var stealing = _InventoryExtensions.GetCurrentlyStealingFromContainer(); if (stealing == null) { return; } var who = MemoryObject.FromAddress <TESObjectREFR>(ctx.CX); if (who == null || !(who is Actor) || !((Actor)who).IsPlayer) { return; } var where = MemoryObject.FromAddress <TESObjectREFR>(Memory.ReadPointer(ctx.SP + 0x28)); if (where == null || !where.Equals(stealing)) { return; } var item = MemoryObject.FromAddress <TESForm>(ctx.DX); var data = MemoryObject.FromAddress <BSExtraDataList>(ctx.R8); int count = ctx.R9.ToInt32Safe(); StealInfo.PushContainerItem(item, data, count); } }); this.InstallHook("object add item", 19282, 0, 6, "40 55 56 57 41 54", ctx => { var pickpocket = _InventoryExtensions.GetCurrentlyPickPocketing(); if (pickpocket != null) { var who = MemoryObject.FromAddress <TESObjectREFR>(ctx.CX); if (who == null || !who.Equals(pickpocket)) { return; } var where = MemoryObject.FromAddress <TESObjectREFR>(Memory.ReadPointer(ctx.SP + 0x28)); if (where == null || !(where is Actor) || !((Actor) where).IsPlayer) { return; } var item = MemoryObject.FromAddress <TESForm>(ctx.DX); var data = MemoryObject.FromAddress <BSExtraDataList>(ctx.R8); int count = ctx.R9.ToInt32Safe(); StealInfo.RemoveContainerItem(item, data, count); } else { var stealing = _InventoryExtensions.GetCurrentlyStealingFromContainer(); if (stealing == null) { return; } var who = MemoryObject.FromAddress <TESObjectREFR>(ctx.CX); if (who == null || !who.Equals(stealing)) { return; } var where = MemoryObject.FromAddress <TESObjectREFR>(Memory.ReadPointer(ctx.SP + 0x28)); if (where == null || !(where is Actor) || !((Actor) where).IsPlayer) { return; } var item = MemoryObject.FromAddress <TESForm>(ctx.DX); var data = MemoryObject.FromAddress <BSExtraDataList>(ctx.R8); int count = ctx.R9.ToInt32Safe(); StealInfo.RemoveContainerItem(item, data, count); } }); Events.OnFrame.Register(e => { FinishPickPocketCheck.Do(); ApplyStolenSoon.Do(); ApplyFixCDataSoon.Do(); }); _SetItemOwner_Func = NetScriptFramework.Main.GameInfo.GetAddressOf(15784); _SetListOwner_Func = NetScriptFramework.Main.GameInfo.GetAddressOf(11463); _GetCount_Func = NetScriptFramework.Main.GameInfo.GetAddressOf(11558); _GetNorth_Func = NetScriptFramework.Main.GameInfo.GetAddressOf(11773); _SetNorth_Func = NetScriptFramework.Main.GameInfo.GetAddressOf(11774); _ContOpenType_Var = NetScriptFramework.Main.GameInfo.GetAddressOf(519396); _ContOpen_Var = NetScriptFramework.Main.GameInfo.GetAddressOf(519421); _CalcCost_Func = NetScriptFramework.Main.GameInfo.GetAddressOf(15757); } if (Settings.Instance.FixBadStolenItemCount) { var ptr = NetScriptFramework.Main.GameInfo.GetAddressOf(15821, 0x110A, 0, "0F B7 95 A0 01 00 00"); Memory.WriteBytes(ptr, new byte[] { 0x8B, 0x54, 0x24, 0x60, 0x90, 0x90, 0x90 }, true); } }
/// <summary> /// Tries to parse from input. Returns null if failed. /// </summary> /// <param name="input">The input.</param> /// <param name="pluginForLog">The plugin for log.</param> /// <param name="settingNameForLog">The setting name for log.</param> /// <param name="warnOnMissingForm">If set to <c>true</c> warn on missing form.</param> /// <param name="dontWriteAnythingToLog">Don't write any errors to log if failed to parse.</param> /// <returns></returns> public static CachedFormList TryParse(string input, string pluginForLog, string settingNameForLog, bool warnOnMissingForm = true, bool dontWriteAnythingToLog = false) { if (string.IsNullOrEmpty(settingNameForLog)) { settingNameForLog = "unknown form list setting"; } if (string.IsNullOrEmpty(pluginForLog)) { pluginForLog = "unknown plugin"; } var ls = new CachedFormList(); var spl = input.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var x in spl) { string idstr; string file; int ix = x.IndexOf(':'); if (ix <= 0) { if (!dontWriteAnythingToLog) { NetScriptFramework.Main.Log.AppendLine("Failed to parse " + settingNameForLog + " for " + pluginForLog + "! Invalid input: `" + x + "`."); } return(null); } idstr = x.Substring(0, ix); file = x.Substring(ix + 1); if (!idstr.All(q => (q >= '0' && q <= '9') || (q >= 'a' && q <= 'f') || (q >= 'A' && q <= 'F'))) { if (!dontWriteAnythingToLog) { NetScriptFramework.Main.Log.AppendLine("Failed to parse " + settingNameForLog + " for " + pluginForLog + "! Invalid form ID: `" + idstr + "`."); } return(null); } if (string.IsNullOrEmpty(file)) { if (!dontWriteAnythingToLog) { NetScriptFramework.Main.Log.AppendLine("Failed to parse " + settingNameForLog + " for " + pluginForLog + "! Missing file name."); } return(null); } uint id = 0; if (!uint.TryParse(idstr, System.Globalization.NumberStyles.HexNumber, null, out id) || (id & 0xFF000000) != 0) { if (!dontWriteAnythingToLog) { NetScriptFramework.Main.Log.AppendLine("Failed to parse " + settingNameForLog + " for " + pluginForLog + "! Invalid form ID: `" + idstr + "`. Don't include plugin index in form ID."); } return(null); } var form = NetScriptFramework.SkyrimSE.TESForm.LookupFormFromFile(id, file); if (form == null) { if (!dontWriteAnythingToLog && warnOnMissingForm) { NetScriptFramework.Main.Log.AppendLine("Failed to find form " + settingNameForLog + " for " + pluginForLog + "! Form ID was " + id.ToString("X") + " and file was " + file + "."); } continue; } if (ls.Ids.Add(form.FormId)) { ls.Forms.Add(form); } } return(ls); }