public async Task EditEntryReextractTest(string filename, string entryFilepath, string replacementFile, string expectedDir) { using (ArcFile arcFile = new ArcFile(filename)) { ContainerEntry arcEntry = arcFile.GetEntry(entryFilepath); if (arcEntry == null) { Assert.Fail("Entry not found."); } using (FileStream fileStream = new FileStream(replacementFile, FileMode.Open, FileAccess.Read)) { await arcEntry.SetData(fileStream); } await arcFile.SaveAs("temp.arc", progress); } using (ArcFile arcFile = new ArcFile("temp.arc")) { await arcFile.ExtractAllAsync("tempdir", false, progress); } File.Move(expectedDir + "/" + entryFilepath, "backup"); File.Copy(replacementFile, expectedDir + "/" + entryFilepath); bool eq = Compare.CompareDirectories(expectedDir, "tempdir"); File.Delete(expectedDir + "/" + entryFilepath); File.Move("backup", expectedDir + "/" + entryFilepath); DirectoryInfo directoryInfo = new DirectoryInfo("tempdir"); directoryInfo.Delete(true); File.Delete("temp.arc"); File.Delete("temp.bin"); Assert.IsTrue(eq); }
// Load All Container Arrays from SQL void LoadFromSQL(string tablename) { // Empty the Array first for (int i = 0; i < Items.Length; i++) { Items[i] = null; } SqlWrapper sql = new SqlWrapper(); DataTable dt = sql.ReadDatatable("SELECT * FROM " + tablename + " WHERE container=" + Type + " AND ID=" + Instance); foreach (DataRow row in dt.Rows) { int place = (Int32)row["placement"]; if (place < NumberOfSlots) { if (((Int32)row["type"] != 0) && ((Int32)row["instance"] != 0)) { // Do stuff with instanced items // Create item from lowid/highid interpolated by QL and read stats from sql } else { ContainerEntry ce = new ContainerEntry(); ce.LowID = (Int32)row["lowid"]; ce.HighID = (Int32)row["highid"]; ce.QL = (Int32)row["quality"]; ce.Amount = (Int32)row["multiplecount"]; ce.Flags = (uint)row["flags"]; ce.InstanceID = 0; ce.Type = 0; Items[place] = ce; } } } }
public void ContainerIndex_Basics() { int threshold = 20000; using (ContainerIndex index = ContainerIndex.OpenWrite("Sample.cdx")) { // Add three top level containers index.Start(threshold - 3); index.Start(threshold - 2); index.Start(threshold - 1); // Add 100 adjacent peers for (int i = 1; i <= 100; ++i) { int start = i * threshold; index.Start(start); index.End(start + threshold - 1); } int end = (101 * threshold) - 1; // Close the top level parents index.End(end + 1); index.End(end + 2); index.End(end + 3); } using (ContainerIndex index = ContainerIndex.OpenRead("Sample.cdx")) { // Verify 103 entries read back Assert.AreEqual(103, index.Count); for (int i = 1; i < 100; ++i) { int start = i * threshold; int end = start + threshold - 1; // Verify positions inside each container return that container Assert.AreEqual(start, index.NearestIndexedContainer(start).StartByteOffset); Assert.AreEqual(start, index.NearestIndexedContainer(start + 1).StartByteOffset); Assert.AreEqual(start, index.NearestIndexedContainer(end - 1).StartByteOffset); Assert.AreEqual(start, index.NearestIndexedContainer(end).StartByteOffset); // Verify the correct three parents are returned ContainerEntry entry = index.NearestIndexedContainer(start); entry = index.Parent(entry); Assert.AreEqual(threshold - 1, entry.StartByteOffset); entry = index.Parent(entry); Assert.AreEqual(threshold - 2, entry.StartByteOffset); entry = index.Parent(entry); Assert.AreEqual(threshold - 3, entry.StartByteOffset); entry = index.Parent(entry); Assert.AreEqual(-1, entry.StartByteOffset); } } }
public async Task PatchFont() { try { ClearStatus(); ContainerEntry fontEntry = ArcFile.GetEntry("im2nx_font.par"); if (fontEntry == null) { throw new FileNotFoundException("File im2nx_font.par not found. Make sure you are opening disc.arc"); } using (Stream parStream = await fontEntry.GetData()) { ReportMessage("Reading im2nx_font.par..."); Font font = await Task.Run(() => Font.CreateFromPar(parStream)); ReportMessage("Patching font..."); await Task.Run(() => font.AddDigraphs()); ReportMessage("Writing font as par..."); using MemoryStream memStream = new MemoryStream(); await font.WriteFontPar(memStream, false); memStream.Position = 0; await fontEntry.SetData(memStream); } ReportMessage("Done."); } catch (Exception ex) { ReportException(ex); } }
public async Task EditThenSaveArcAsTwice(string filename, string entryPath, string replacementFile, string expectedFile) { using (ArcFile arcFile = new ArcFile(filename)) { ContainerEntry arcEntry = arcFile.GetEntry(entryPath); if (arcEntry == null) { Assert.Fail("Entry not found."); } using (FileStream fileStream = new FileStream(replacementFile, FileMode.Open, FileAccess.Read)) { await arcEntry.SetData(fileStream); } await arcFile.SaveAs("temp1.arc", progress); await arcFile.SaveAs("temp2.arc", progress); } bool eq1 = Compare.CompareFiles(expectedFile, "temp1.arc"); bool eq2 = Compare.CompareFiles(ArcFile.GetBinName(expectedFile), "temp1.bin"); bool eq3 = Compare.CompareFiles(expectedFile, "temp2.arc"); bool eq4 = Compare.CompareFiles(ArcFile.GetBinName(expectedFile), "temp2.bin"); File.Delete("temp1.arc"); File.Delete("temp1.bin"); File.Delete("temp2.arc"); File.Delete("temp2.bin"); Assert.IsTrue(eq1); Assert.IsTrue(eq2); Assert.IsTrue(eq3); Assert.IsTrue(eq4); }
/// <summary> /// Gets the instance. /// </summary> /// <param name="service">The service.</param> /// <param name="key">The key.</param> /// <returns></returns> public Object GetInstance(Type service, String key) { ContainerEntry entry = GetEntry(service, key); if (entry != null) { return(entry.Single()()); } if (typeof(Delegate).IsAssignableFrom(service)) { Type typeToCreate = service.GetGenericArguments()[0]; Type factoryFactoryType = typeof(FactoryFactory <>).MakeGenericType(typeToCreate); Object factoryFactoryHost = Activator.CreateInstance(factoryFactoryType); MethodInfo factoryFactoryMethod = factoryFactoryType.GetMethod("Create"); return(factoryFactoryMethod.Invoke(factoryFactoryHost, new Object[] { this })); } if (typeof(IEnumerable).IsAssignableFrom(service)) { Type listType = service.GetGenericArguments()[0]; IList <Object> instances = GetAllInstances(listType).ToList(); Array array = Array.CreateInstance(listType, instances.Count); for (Int32 i = 0; i < array.Length; i++) { array.SetValue(instances[i], i); } return(array); } return(null); }
private object GetInstance(ContainerEntry entry) { if (entry.Instance == null || entry.LifeCycle == LifeCycle.Transient) { var parameters = ResolveConstructorParameters(entry); entry.CreateInstance(parameters.ToArray()); } return(entry.Instance); }
private IEnumerable <object> ResolveConstructorParameters(ContainerEntry entry) { var constructorInfo = entry.ConcreteType.GetTypeInfo().GetConstructors().First(); foreach (var parameter in constructorInfo.GetParameters()) { yield return(ResolveObject(parameter.ParameterType)); } }
private ContainerEntry GetOrCreateEntry(Type service, string key) { var entry = _entries.Find(x => x.Service == service && x.Key == key); if (entry is null) { entry = new ContainerEntry { Service = service, Key = key }; _entries.Add(entry); } return(entry); }
/// <summary> /// The get or create entry. /// </summary> /// <param name="service"> /// The service. /// </param> /// <param name="key"> /// The key. /// </param> /// <returns> /// The <see cref="ContainerEntry"/>. /// </returns> private ContainerEntry GetOrCreateEntry(Type service, string key) { var entry = this.mEntries.FirstOrDefault(x => x.Service == service && x.Key == key); if (entry == null) { entry = new ContainerEntry { Service = service, Key = key }; this.mEntries.Add(entry); } return(entry); }
ContainerEntry GetOrCreateEntry(Type service, string key) { var entry = GetEntry(service, key); if (entry == null) { entry = new ContainerEntry { Service = service, Key = key }; entries.Add(entry); } return(entry); }
void RemoveItem(int Place, int Amount) { ContainerEntry ce = (ContainerEntry)Items[Place]; if (Items[Place] == null) { throw new NoNullAllowedException("Item at place " + Place + " of Container " + Type + ":" + Instance + " is NULL"); } ce.Amount -= Amount; if (ce.Amount <= 0) { Items[Place] = null; } }
private ContainerEntry AncestorAtDepth(ContainerEntry entry, int entryDepth, int desiredDepth) { if (entryDepth < desiredDepth) { return(ContainerEntry.Empty); } while (entryDepth > desiredDepth) { entry = _containerIndex.Parent(entry); entryDepth--; } return(entry); }
public async Task WriteXlsxTest(string xlsxName, string arcName, string commuList) { using CommuToXlsx commu = new CommuToXlsx(xlsxName, true); using StreamReader streamReader = new StreamReader(commuList); using ArcFile arcFile = new ArcFile(arcName); while (!streamReader.EndOfStream) { string fileName = streamReader.ReadLine(); using EntryStack entryStack = await arcFile.GetEntryRecursive(fileName); ContainerEntry entry = entryStack.Entry; using Stream memStream = await entry.GetData(); commu.GetAndWriteCommu(memStream, fileName); } }
private async Task <EntryStack> GetEntryRecursive(string fileName, EntryStack stack) { int parIndex = fileName.IndexOf("_par/"); int ptaIndex = fileName.IndexOf("_pta/"); int index; if (parIndex == -1) { index = ptaIndex; } else if (ptaIndex == -1) { index = parIndex; } else { index = Math.Min(parIndex, ptaIndex); } if (index == -1) { ContainerEntry entry = GetEntry(fileName); if (entry == null) { stack.Dispose(); return(null); } stack.Entry = entry; return(stack); } else { ContainerEntry entry = GetEntry(fileName.Substring(0, index) + '.' + fileName.Substring(index + 1, 3)); if (entry == null) { stack.Dispose(); return(null); } Stream stream = await entry.GetData(); stack.Push(stream); ParFile parFile = new ParFile(stream); stack.Push(parFile); return(await parFile.GetEntryRecursive(fileName.Substring(index + 5))); } }
/// <summary> /// The get on create or replace entry. /// </summary> /// <param name="service"> /// The service. /// </param> /// <param name="key"> /// The key. /// </param> /// <returns> /// The <see cref="ContainerEntry"/>. /// </returns> private ContainerEntry GetOnCreateOrReplaceEntry(Type service, string key) { lock (_entries) { var entry = _entries.FirstOrDefault(x => x.Service == service && x.Key == key); if (entry != null) { _entries.Remove(entry); } entry = new ContainerEntry { Service = service, Key = key }; _entries.Add(entry); return(entry); } }
private ContainerEntry GetOrCreateEntry(Type service, string key) { if (service == null) { throw new ArgumentNullException(nameof(service)); } var entry = _entries.FirstOrDefault(x => x.Service == service && x.Key == key); if (entry == null) { entry = new ContainerEntry { Service = service, Key = key }; _entries.Add(entry); } return(entry); }
public async Task GetEntryAndWriteToFile(string filename, string entryFilepath, string expectedFile) { using ArcFile arcFile = new ArcFile(filename); ContainerEntry arcEntry = arcFile.GetEntry(entryFilepath); if (arcEntry == null) { Assert.Fail("Entry not found."); } using (Stream stream = await arcEntry.GetData()) { using FileStream fileStream = new FileStream("temp.dat", FileMode.Create, FileAccess.Write); stream.CopyTo(fileStream); } bool eq = Compare.CompareFiles(expectedFile, "temp.dat"); File.Delete("temp.dat"); Assert.IsTrue(eq); }
// Add Item To Container bool AddItem(int place, int lowID, int HighID, int Type, uint InstanceItemID, int Amount, int QL, uint Flags) { if (place == 0x6f) { // find next free int i = 0; while (i < NumberOfSlots) { if (Items[i] == null) { break; } i++; } // No free slot found? if (i == NumberOfSlots) { return(false); } place = i; } if ((Type == 0) && (InstanceItemID == 0)) { ContainerEntry ce = new ContainerEntry(); ce.Type = 0; ce.InstanceID = 0; ce.LowID = lowID; ce.HighID = HighID; ce.QL = QL; ce.Flags = Flags; Items[place] = ce; } else { //Instanced items stuff here } return(true); }
// Save All Container Arrays To SQL void SaveToSQL(string tablename) { SqlWrapper sql = new SqlWrapper(); sql.SqlDelete("DELETE FROM " + tablename + " WHERE container=" + Type + " AND ID=" + Instance); for (int i = 0; i < Items.Length; i++) { if (Items[i] is ContainerEntry) { // Not instanced items first ContainerEntry ce = (ContainerEntry)Items[i]; sql.SqlInsert("INSERT INTO " + tablename + " (ID,Placement, flags, multiplecount, type,instance, lowid,highid, quality,nothing, container) VALUES (" + Instance + "," + i + "," + ce.Flags + "," + ce.Amount + ",0,0," + ce.LowID + "," + ce.HighID + "," + ce.QL + ",0," + Type + ")"); } else { // Do instanced items stuff here // insert into inventory table AND store item's stats } } }
public void ContainerIndex_EndToEnd() { string jsonFilePath = @"Content\Medium.json"; string bionFilePath = Path.ChangeExtension(jsonFilePath, ".bion"); string dictionaryPath = Path.ChangeExtension(bionFilePath, "dict.bion"); string comparePath = Path.ChangeExtension(jsonFilePath, "compare.json"); JsonBionConverter.JsonToBion(jsonFilePath, bionFilePath, dictionaryPath); using (WordCompressor compressor = WordCompressor.OpenRead(dictionaryPath)) using (ContainerIndex cIndex = ContainerIndex.OpenRead(Path.ChangeExtension(bionFilePath, ".cdx"))) using (BionReader reader = new BionReader(File.OpenRead(bionFilePath), cIndex, compressor)) { for (int i = 0; i < cIndex.Count; ++i) { ContainerEntry container = cIndex[i]; // Seek to container start reader.Seek(container.StartByteOffset); // Verify a container start is there int depth = reader.Depth; reader.Read(); bool isObject = (reader.TokenType == BionToken.StartObject); Assert.AreEqual((isObject ? BionToken.StartObject : BionToken.StartArray), reader.TokenType); // Read until the depth is back to the same value while (reader.Depth != depth) { reader.Read(); } // Verify this is the end container position Assert.AreEqual((isObject ? BionToken.EndObject : BionToken.EndArray), reader.TokenType); Assert.AreEqual(container.EndByteOffset, reader.BytesRead); } } }
private static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state) { // 0. Initialize method contextual variables and configurations. ILinkCache cache = state.LinkCache; string configFilePath = Path.Combine(state.ExtraSettingsDataPath, "currency-replacer-config.json"); string errorMessage = ""; if (!File.Exists(configFilePath)) { errorMessage = "Cannot find currency-replacer-config.json for Currency Replacer Rules."; SynthesisLog(errorMessage); throw new FileNotFoundException(errorMessage, configFilePath); } SynthesisLog("**********************************", true); SynthesisLog("Currency Configuration File Used:"); SynthesisLog(File.ReadAllText(configFilePath)); SynthesisLog("**********************************"); CurrencyConfig config; try { config = JsonConvert.DeserializeObject <CurrencyConfig>(File.ReadAllText(configFilePath)); } catch (JsonSerializationException jsonException) { errorMessage = "Failed to parse currency-replacer-config.json, please review expected format."; SynthesisLog(errorMessage, true); throw new JsonSerializationException(errorMessage, jsonException); } // 1. Detect presence of Coins of Tamriel V2 Replacer plugin. if (!state.LoadOrder.TryGetValue(CoinsOfTamrielV2.ModKey, out var coinsOfTamrielContainer) || coinsOfTamrielContainer.Mod is null) { throw new MissingModException(CoinsOfTamrielV2.ModKey, $"Mod {CoinsOfTamrielV2.ModKey.Name} was not found in Load Order."); } var coinsIndex = state.LoadOrder.IndexOf(CoinsOfTamrielV2.ModKey); // 2. Patching ALL Containers for Currency Related information dynamically. var coinsOfTamrielMod = coinsOfTamrielContainer.Mod; var nativeContainers = coinsOfTamrielMod.Containers; // 2.a. Find Winning Containers we are allowed to clone, change and apply our algorithm to. var containersToPatch = state.LoadOrder .PriorityOrder .Container() .WinningContextOverrides() .Where(context => { // Detection Triggers ... return(!nativeContainers.Contains(context.Record) && (context.Record.Items?.Any(container => container.Item.Item.IsOneOf( LootGoldChange, LootPerkGoldenTouch, LootPerkGoldenTouchChange, LootImperialLuck, LootFalmerGoldBoss, Gold)) ?? false) && context.Record.Matches(MatchType.Nordic, config)); }); // TESTING SECTION // containersToPatch.ForEach(ctx => SynthesisLog( $"Container {ctx.Record.FormKey}: {ctx.Record.EditorID} - {ctx.Record.Name} from {ctx.ModKey.FileName} eligible.")); return; // TESTING SECTION // // 2.b. Patch up Native containers originating within Coins of Tamriel plugin that are left over. // NOTE: Will only patch against the most recent override, i.e. The load order provided must be already // conflict resolved for everything UPTO BUT NOT INCLUSIVE OF Coins of Tamriel V2 itself. #region Test 1 // Test 1 : Overriding containers proof of concept works as expected. var counter = 0; foreach (var container in nativeContainers) { //state.LoadOrder.ListedOrder.Take(coinsOfTamrielContainer.index) // .Do(x => Console.WriteLine(x.ModKey)); var containerContext = state.LoadOrder.ListedOrder.Take(coinsIndex) .Reverse() .Container() .WinningContextOverrides() .FirstOrDefault(recentContainer => container.FormKey == recentContainer.Record.FormKey); if (containerContext is null) { continue; } var closestWinningContainer = containerContext.Record; SynthesisLog($"{containerContext.ModKey} for {containerContext.Record.Name}"); //var cond2 = !Equals(closestWinningContainer, container); //var cond3 = !closestWinningContainer?.FormKey.ModKey.IsSkyrimBaseMod(); //SynthesisLog($"{cond1} {cond2} {cond3}"); if (!Equals(closestWinningContainer, container) && !Implicits.Get(state.PatchMod.GameRelease).BaseMasters.Contains(containerContext.ModKey)) { SynthesisLog("reached B"); var adjustedContainer = state.PatchMod.Containers.GetOrAddAsOverride(closestWinningContainer); //var goldenTouchChange = state.LinkCache.Lookup<ILeveledItemGetter>(Skyrim.LeveledItem.LootPerkGoldenTouchChange); var itemsToReplace = adjustedContainer.Items?.FindAll(i => i.Item.Item.Equals(LootPerkGoldenTouchChange)); ContainerEntry goldenTouchChangeNordic = new ContainerEntry { Item = new ContainerItem() { Count = 1, Item = CoinsOfTamrielV2.LeveledItem.LootPerkGoldenTouchChangeNordic } }; itemsToReplace?.ForEach(goldenTouchChange => adjustedContainer.Items.Replace <ContainerEntry>(goldenTouchChange, goldenTouchChangeNordic)); counter++; } } SynthesisLog($"Performed {counter} replacements in Containers", true); #endregion // 3. Patched Leveled List items based on predicate dynamically. // 4. Patch REFRs with randomized generated variations of coins/currencies across worldspaces and cells. // P.S: Activator, Flora, NAVI, Quest are either used in the above or are unrelated and don't need patching. }
public static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state) { List <IngrCombination> combinations = new List <IngrCombination>(); IEnumerable <IIngredientGetter> ingredients = state.LoadOrder.PriorityOrder.OnlyEnabled().Ingredient().WinningOverrides(); ingredients = from ingrs in ingredients where !SkipPlugins.Contains(ingrs.FormKey.ModKey.Name.ToLower()) select ingrs; ingredients = from ingrs in ingredients where (!SkipIngrs.Intersect(ingrs.Name?.ToString()?.Split() !).Any() || SkipIngrs.Contains(ingrs.Name?.ToString())) select ingrs; ingredients = from ingrs in ingredients where !String.IsNullOrEmpty(ingrs.Name?.String) select ingrs; IEnumerator <IIngredientGetter> enumerator = ingredients.GetEnumerator(); int i = 0; int percent = (int)(ingredients.Count() * outputPercentage); while (enumerator.MoveNext()) { sw.Start(); if (i % percent == 0) { Console.WriteLine(i + " out of " + ingredients.Count() + " ingredients processed."); } List <IIngredientGetter> remainingingr = ingredients.Skip(i).ToList(); IIngredientGetter[] potionRecipeList = getIngredientsMatchingOneIngredient(enumerator.Current, remainingingr); if (String.IsNullOrEmpty(enumerator.Current.Name?.String)) { i++; continue; } foreach (IIngredientGetter ingr in potionRecipeList) { IEnumerable <IEffectGetter> ActiveEffects = ingr.Effects.Intersect(enumerator.Current.Effects).ToArray(); ActiveEffects = ActiveEffects.Distinct(); IEffectGetter[] ActiveEffectsA = ActiveEffects.ToArray(); if (ActiveEffectsA.Length < 1) { continue; } String potionString = "<font face='$HandwrittenFont'><font size='26'>"; potionString += "-<b>" + (enumerator.Current.Name + "<br><b>-<b>" + ingr.Name + "</b>"); List <String?> mgeflist = new List <String?>(); List <String?> mgeflists = new List <String?>(); foreach (IEffectGetter effect in ActiveEffectsA) { state.LinkCache.TryResolve <IMagicEffectGetter>(effect.BaseEffect.FormKey, out var mgeffect); mgeflist.Add(mgeffect?.Name?.String); mgeflists.AddRange(mgeffect?.Name?.String?.Split() !); } String prefix = "Potion"; int type = 0; if (!mgeflists.Intersect(potionWords.ToList()).Any() && mgeflists.Intersect(poisonWords.ToList()).Any()) { prefix = "Poison"; type = 1; if (mgeflist.Count() <= poisonSkipThreshold) { continue; } poisonRecipeCount++; } else if (mgeflists.Intersect(potionWords.ToList()).Any() && mgeflists.Intersect(poisonWords.ToList()).Any()) { prefix = "Impure Potion"; type = 2; if (mgeflist.Count() <= impureSkipThreshold) { continue; } impurepotionRecipeCount++; } else { if (mgeflist.Count() <= potionSkipThreshold) { continue; } potionRecipeCount++; } potionString += ("</font><font face='$HandwrittenFont'><font size='18'><br> to make " + prefix + " of "); String potionName = "Recipe: "; for (int k = 0; k < mgeflist.Count(); k++) { if (k > 0) { potionName += " and "; potionString += ("<br>"); } potionName += mgeflist[k]; potionString += (mgeflist[k]); } String sstring = ""; if (mgeflist.Count() > 1) { sstring = "s"; } potionString += ("<br></font><font size='14'> Contains " + mgeflist.Count() + " Effect" + sstring); potionString += "<\\font>"; IIngredientGetter[] ingrss = { enumerator.Current, ingr }; combinations.Add(new IngrCombination(potionName, ingrss, mgeflist?.ToArray() !, potionString, type)); } int j = i + 1; IEnumerator <IIngredientGetter> enumerator2 = remainingingr.GetEnumerator(); while (enumerator2.MoveNext()) { if (enumerator2.Current.Name?.Equals(enumerator.Current.Name) ?? true || String.IsNullOrEmpty(enumerator2.Current.Name?.String) || !enumerator.Current.Effects.Intersect(enumerator2.Current.Effects).Any()) { j++; continue; } List <IIngredientGetter> remainingingr2 = ingredients.Skip(j).ToList(); IIngredientGetter[] potionRecipeList2 = getIngredientsMatchingTwoIngredients(enumerator.Current, enumerator2.Current, remainingingr2); foreach (IIngredientGetter ingr in potionRecipeList2) { IEnumerable <IEffectGetter> ActiveEffects = ingr.Effects.Intersect(enumerator.Current.Effects); IEnumerable <IEffectGetter> ActiveEffects2 = ingr.Effects.Intersect(enumerator2.Current.Effects); IEnumerable <IEffectGetter> ActiveEffects3 = enumerator.Current.Effects.Intersect(enumerator2.Current.Effects); ActiveEffects.ToList().AddRange(ActiveEffects2); ActiveEffects.ToList().AddRange(ActiveEffects3); ActiveEffects = ActiveEffects.Distinct(); IEffectGetter[] ActiveEffectsA = ActiveEffects.ToArray(); if (ActiveEffectsA.Length < 1) { continue; } String potionString = "<font face='$HandwrittenFont'><font size='26'>"; potionString += "-<b>" + (enumerator.Current.Name + "<br></b>-<b>" + enumerator2.Current.Name + "<br></b>-<b>" + ingr.Name + "</b>"); List <String?> mgeflist = new List <String?>(); List <String?> mgeflists = new List <String?>(); foreach (IEffectGetter effect in ActiveEffects) { state.LinkCache.TryResolve <IMagicEffectGetter>(effect.BaseEffect.FormKey, out var mgeffect); mgeflist.Add(mgeffect?.Name?.String); mgeflists.AddRange(mgeffect?.Name?.String?.Split() !); } String prefix = "Potion"; int type = 0; if (!mgeflists.Intersect(potionWords.ToList()).Any() && mgeflists.Intersect(poisonWords.ToList()).Any()) { prefix = "Poison"; type = 1; if (mgeflist.Count() <= poisonSkipThreshold) { continue; } poisonRecipeCount++; } else if (mgeflist.Intersect(potionWords.ToList()).Any() && mgeflists.Intersect(poisonWords.ToList()).Any()) { prefix = "Impure Potion"; type = 2; if (mgeflists.Count() <= impureSkipThreshold) { continue; } impurepotionRecipeCount++; } else { if (mgeflist.Count() <= potionSkipThreshold) { continue; } potionRecipeCount++; } potionString += ("</font><font face='$HandwrittenFont'><font size='18'><br> to make " + prefix + " of: <br></font><font face='$HandwrittenFont'><font size='26'>"); String potionName = "Recipe: "; for (int k = 0; k < mgeflist.Count(); k++) { if (k > 0) { potionName += " and "; potionString += ("<br>"); } potionName += mgeflist[k]; potionString += (mgeflist[k]); } String sstring = ""; if (mgeflist.Count() > 1) { sstring = "s"; } potionString += ("<br></font><font size='14'> Contains " + mgeflist.Count() + " Effect" + sstring); potionString += "<\\font>"; IIngredientGetter[] ingrss = { enumerator.Current, enumerator2.Current, ingr }; combinations.Add(new IngrCombination(potionName, ingrss, mgeflist?.ToArray() !, potionString, type)); } j++; } i++; if (i % percent == 0) { sw.Stop(); Console.WriteLine("time elapsed: " + sw.Elapsed.TotalSeconds + " seconds"); sw.Reset(); } } Console.WriteLine("Creating Leveled lists..."); IEnumerable <IBookGetter> books = from book in state.LoadOrder.PriorityOrder.Book().WinningOverrides() where book.FormKey.Equals(new FormKey(new ModKey("Skyrim", ModType.Master), 0x0F5CB1)) select book; IBookGetter noteTemplate = books.ToList()[0]; Console.WriteLine("Creating " + combinations.Count() + " recipes."); percent = (int)(combinations.Count() * outputPercentage); i = 0; /* Main leveled list that gets added to recipe drop */ LeveledItem mainpotionRecipeLVLI = state.PatchMod.LeveledItems.AddNew(); LeveledItemEntry mainpotionRecipeLVLIentry = new LeveledItemEntry(); mainpotionRecipeLVLI.Entries = new Noggog.ExtendedList <LeveledItemEntry>(); LeveledItemEntryData mainpotionRecipeLVLIentrydata = new LeveledItemEntryData(); GlobalInt mainpotionGlobal = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); mainpotionGlobal.Data = new Random().Next(minChance, maxChance); state.PatchMod.Globals.Set(mainpotionGlobal); mainpotionRecipeLVLI.Global = mainpotionGlobal; mainpotionRecipeLVLI.EditorID = "mainpotionRecipeList"; /* Must split sub leveled lists because it can only hold 128 items */ uint potionRecipeListCount = (potionRecipeCount / 128) + 1; uint poisonRecipeListCount = (poisonRecipeCount / 128) + 1; uint impurepotionRecipeListCount = (impurepotionRecipeCount / 128) + 1; LeveledItem[] potionRecipeLVLIs = new LeveledItem[potionRecipeListCount]; uint masterpotionRecipeListCount = ((potionRecipeListCount + poisonRecipeListCount + impurepotionRecipeListCount) / 128) + 1; LeveledItem[] masterpotionRecipeLVLIs = new LeveledItem[masterpotionRecipeListCount]; LeveledItemEntry[] masterpotionRecipeLVLIentries = new LeveledItemEntry[masterpotionRecipeListCount]; LeveledItemEntryData[] masterpotionRecipeLVLIentriesdata = new LeveledItemEntryData[masterpotionRecipeListCount]; GlobalInt[] masterpotionGlobals = new GlobalInt[masterpotionRecipeListCount]; LeveledItemEntry[] potionRecipeLVLIentries = new LeveledItemEntry[potionRecipeListCount]; LeveledItemEntryData[] potionRecipeLVLIentriesdata = new LeveledItemEntryData[potionRecipeListCount]; GlobalInt[] potionGlobals = new GlobalInt[potionRecipeListCount]; for (int k = 0; k < masterpotionRecipeListCount; k++) { masterpotionRecipeLVLIentries[k] = new LeveledItemEntry(); masterpotionRecipeLVLIentriesdata[k] = new LeveledItemEntryData(); masterpotionRecipeLVLIs[k] = state.PatchMod.LeveledItems.AddNew(); masterpotionRecipeLVLIs[k].Entries = new Noggog.ExtendedList <LeveledItemEntry>(); masterpotionGlobals[k] = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); masterpotionGlobals[k].Data = new Random().Next(5, 25); state.PatchMod.Globals.Set(masterpotionGlobals[k]); masterpotionRecipeLVLIs[k].Global = masterpotionGlobals[k]; masterpotionRecipeLVLIs[k].EditorID = "masterpotionRecipeList" + k; masterpotionRecipeLVLIentriesdata[k].Reference = masterpotionRecipeLVLIs[k].FormKey; masterpotionRecipeLVLIentriesdata[k].Level = 1; masterpotionRecipeLVLIentriesdata[k].Count = 1; } for (int l = 0; l < potionRecipeListCount; l++) { potionRecipeLVLIentries[l] = new LeveledItemEntry(); potionRecipeLVLIentriesdata[l] = new LeveledItemEntryData(); potionRecipeLVLIs[l] = state.PatchMod.LeveledItems.AddNew(); potionRecipeLVLIs[l].Entries = new Noggog.ExtendedList <LeveledItemEntry>(); potionGlobals[l] = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); potionGlobals[l].Data = new Random().Next(5, 25); state.PatchMod.Globals.Set(potionGlobals[l]); potionRecipeLVLIs[i].Global = potionGlobals[l]; potionRecipeLVLIs[l].EditorID = "potionRecipeList" + l; potionRecipeLVLIentriesdata[l].Reference = potionRecipeLVLIs[l].FormKey; potionRecipeLVLIentriesdata[l].Level = 1; potionRecipeLVLIentriesdata[l].Count = 1; } LeveledItem[] poisonRecipeLVLIs = new LeveledItem[poisonRecipeListCount]; LeveledItemEntry[] poisonRecipeLVLIentries = new LeveledItemEntry[poisonRecipeListCount]; LeveledItemEntryData[] poisonRecipeLVLIentriesdata = new LeveledItemEntryData[poisonRecipeListCount]; GlobalInt[] poisonGlobals = new GlobalInt[poisonRecipeListCount]; for (int l = 0; l < poisonRecipeListCount; l++) { poisonRecipeLVLIentries[l] = new LeveledItemEntry(); poisonRecipeLVLIentriesdata[l] = new LeveledItemEntryData(); poisonRecipeLVLIs[l] = state.PatchMod.LeveledItems.AddNew(); poisonRecipeLVLIs[l].Entries = new Noggog.ExtendedList <LeveledItemEntry>(); poisonGlobals[l] = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); poisonGlobals[l].Data = new Random().Next(5, 25); state.PatchMod.Globals.Set(poisonGlobals[l]); poisonRecipeLVLIs[i].Global = poisonGlobals[l]; poisonRecipeLVLIs[l].EditorID = "poisonRecipeList" + l; poisonRecipeLVLIentriesdata[l].Reference = poisonRecipeLVLIs[l].FormKey; poisonRecipeLVLIentriesdata[l].Level = 1; poisonRecipeLVLIentriesdata[l].Count = 1; } LeveledItem[] impurepotionRecipeLVLIs = new LeveledItem[impurepotionRecipeListCount]; LeveledItemEntry[] impurepotionRecipeLVLIentries = new LeveledItemEntry[impurepotionRecipeListCount]; LeveledItemEntryData[] impurepotionRecipeLVLIentriesdata = new LeveledItemEntryData[impurepotionRecipeListCount]; GlobalInt[] impurepotionGlobals = new GlobalInt[impurepotionRecipeListCount]; for (int l = 0; l < impurepotionRecipeListCount; l++) { impurepotionRecipeLVLIentries[l] = new LeveledItemEntry(); impurepotionRecipeLVLIentriesdata[l] = new LeveledItemEntryData(); impurepotionRecipeLVLIs[l] = state.PatchMod.LeveledItems.AddNew(); impurepotionRecipeLVLIs[l].Entries = new Noggog.ExtendedList <LeveledItemEntry>(); impurepotionGlobals[l] = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); impurepotionGlobals[l].Data = new Random().Next(5, 25); state.PatchMod.Globals.Set(impurepotionGlobals[l]); impurepotionRecipeLVLIs[i].Global = impurepotionGlobals[l]; impurepotionRecipeLVLIs[l].EditorID = "impurepotionRecipeList" + l; impurepotionRecipeLVLIentriesdata[l].Reference = impurepotionRecipeLVLIs[l].FormKey; impurepotionRecipeLVLIentriesdata[l].Level = 1; impurepotionRecipeLVLIentriesdata[l].Count = 1; } Console.WriteLine("Splitting potions into lists (" + potionRecipeListCount + " " + poisonRecipeListCount + " " + impurepotionRecipeListCount + ")"); uint potionIndex = 0, poisonIndex = 0, impurepotionIndex = 0; IEffectGetter[] effectCache = getAllEffects(ingredients).ToArray(); Dictionary <String, int> nameCache = new Dictionary <String, int>(); foreach (IngrCombination ic in combinations) { if (i % percent == 0) { Console.WriteLine(i + " out of " + combinations.Count() + " recipes created."); } IBook newRecipe = noteTemplate.DeepCopy(); newRecipe.FormKey = state.PatchMod.GetNextFormKey(); newRecipe.Description = ic.RecipeName; newRecipe.Name = ic.RecipeName; newRecipe.BookText = ic.PotionString; newRecipe.Weight = recipeWeight; String?name = "recipeof"; foreach (String?s in ic.MyEffects !) { name += s; } name = name.Replace(" ", String.Empty); int nameIndex = 0; if (nameCache.TryGetValue(name, out nameIndex)) { nameCache[name] = nameIndex + 1; name = name + nameCache[name]; } else { nameCache.Add(name, 0); name = name + "0"; } newRecipe.EditorID = name; state.PatchMod.Books.Set((Book)newRecipe); LeveledItemEntry lie = new LeveledItemEntry(); LeveledItemEntryData data = new LeveledItemEntryData(); data.Level = 1; data.Count = 1; data.Reference = new FormLink <IItemGetter>(newRecipe.FormKey); lie.Data = data; switch (ic.Type) { case 0: potionRecipeLVLIentriesdata[potionIndex / 128].Reference = potionRecipeLVLIs[potionIndex / 128].FormKey; potionRecipeLVLIentries[potionIndex / 128].Data = potionRecipeLVLIentriesdata[potionIndex / 128]; potionRecipeLVLIs[potionIndex / 128].Entries?.Add(lie); potionIndex++; break; case 1: poisonRecipeLVLIentriesdata[poisonIndex / 128].Reference = poisonRecipeLVLIs[poisonIndex / 128].FormKey; poisonRecipeLVLIentries[poisonIndex / 128].Data = poisonRecipeLVLIentriesdata[poisonIndex / 128]; poisonRecipeLVLIs[poisonIndex / 128].Entries?.Add(lie); poisonIndex++; break; case 2: impurepotionRecipeLVLIentriesdata[impurepotionIndex / 128].Reference = impurepotionRecipeLVLIs[impurepotionIndex / 128].FormKey; impurepotionRecipeLVLIentries[impurepotionIndex / 128].Data = impurepotionRecipeLVLIentriesdata[impurepotionIndex / 128]; impurepotionRecipeLVLIs[impurepotionIndex / 128].Entries?.Add(lie); impurepotionIndex++; break; } i++; } Console.WriteLine("Linking recipes to potion leveled list"); IEnumerable <ILeveledItemGetter> lvlilists = from list in state.LoadOrder.PriorityOrder.OnlyEnabled().LeveledItem().WinningOverrides() where list.EditorID?.Equals("LItemPotionAll") ?? true select list; ILeveledItemGetter allList = lvlilists.ToList()[0]; LeveledItem modifiedList = state.PatchMod.LeveledItems.GetOrAddAsOverride(allList); potionIndex = 0; poisonIndex = 0; impurepotionIndex = 0; for (int l = 0; l < masterpotionRecipeListCount; l++) { masterpotionRecipeLVLIentriesdata[l].Reference = masterpotionRecipeLVLIs[l].FormKey; masterpotionRecipeLVLIentries[l].Data = masterpotionRecipeLVLIentriesdata[l]; for (int k = 0; k < 128; k++) { if (potionIndex < potionRecipeLVLIentries.Count()) { masterpotionRecipeLVLIs[l].Entries?.Add(potionRecipeLVLIentries[potionIndex++]); } else if (poisonIndex < poisonRecipeLVLIentries.Count()) { masterpotionRecipeLVLIs[l].Entries?.Add(poisonRecipeLVLIentries[poisonIndex++]); } else if (impurepotionIndex < impurepotionRecipeLVLIentries.Count()) { masterpotionRecipeLVLIs[l].Entries?.Add(impurepotionRecipeLVLIentries[impurepotionIndex++]); } else { break; } } mainpotionRecipeLVLI.Entries?.Add(masterpotionRecipeLVLIentries[l]); } foreach (LeveledItem li in potionRecipeLVLIs) { state.PatchMod.LeveledItems.Set(li); } foreach (LeveledItem li in poisonRecipeLVLIs) { state.PatchMod.LeveledItems.Set(li); } foreach (LeveledItem li in impurepotionRecipeLVLIs) { state.PatchMod.LeveledItems.Set(li); } foreach (LeveledItem li in masterpotionRecipeLVLIs) { state.PatchMod.LeveledItems.Set(li); } mainpotionRecipeLVLIentrydata.Reference = mainpotionRecipeLVLI.FormKey; mainpotionRecipeLVLIentry.Data = mainpotionRecipeLVLIentrydata; mainpotionRecipeLVLIentrydata.Count = 1; mainpotionRecipeLVLIentrydata.Level = 1; modifiedList.Entries?.Add(mainpotionRecipeLVLIentry); state.PatchMod.LeveledItems.Set(mainpotionRecipeLVLI); Console.WriteLine("Adding recipes to defined containers"); IEnumerable <IContainerGetter> chests = from list in state.LoadOrder.PriorityOrder.OnlyEnabled().Container().WinningOverrides() where containerEditorIDs?.ToList().Contains(list.EditorID !) ?? true select list; ContainerEntry potionListContainerEntry = new ContainerEntry(); ContainerItem potionListContainerItem = new ContainerItem(); potionListContainerItem.Item = mainpotionRecipeLVLI.FormKey; potionListContainerItem.Count = 1; potionListContainerEntry.Item = potionListContainerItem; foreach (IContainerGetter chest in chests) { Container rChest = state.PatchMod.Containers.GetOrAddAsOverride(chest); rChest.Items?.Add(potionListContainerEntry); } }
/// <summary> /// Get Or Create Entry /// </summary> /// <param name="service"></param> /// <param name="key"></param> /// <returns></returns> private ContainerEntry GetOrCreateEntry(Type service, string key) { var entry = this.GetEntry(service, key); if (entry == null) { entry = new ContainerEntry { Service = service, Key = key }; this.entries.Add(entry); } return entry; }
public static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state) { badKeywordsF = (from keyword in state.LoadOrder.PriorityOrder.OnlyEnabled().Keyword().WinningOverrides() where badKeywords.Contains(keyword.EditorID) select(IFormLink <IKeyword>)(new FormLink <IKeyword>(keyword.FormKey))).ToList(); IEnumerable <IIngredientGetter> ingredients = state.LoadOrder.PriorityOrder.OnlyEnabled().Ingredient().WinningOverrides().Where(x => !SkipPlugins.Contains(x.FormKey.ModKey.Name.ToLower())).Where(x => (!SkipIngrs.Intersect(x.Name?.ToString()?.Split() !).Any() || SkipIngrs.Contains(x.Name?.ToString()))).Where(x => !String.IsNullOrEmpty(x.Name?.String)).ToList(); allIngredients = ingredients; percent = (int)(ingredients.Count() * outputPercentage); totalIngredientCount = ingredients.Count(); Thread[] threads = new Thread[workerThreadCount]; int partitionsize = (ingredients.Count() / workerThreadCount); /* Split ingredient list evenly across threads */ IEnumerable <IIngredientGetter>[] ingredientsL = ingredients.Partition(partitionsize).ToArray(); /* If there is a remainder add it to last thread */ if (ingredientsL.Length > workerThreadCount) { ingredientsL[ingredientsL.Length - 2] = ingredientsL[ingredientsL.Length - 2].Concat(ingredientsL[ingredientsL.Length - 1]); } sw.Start(); Console.WriteLine("Using " + workerThreadCount + " threads to handle " + partitionsize + " ingredients each."); int startindex = 0; for (int u = 0; u < workerThreadCount; u++) { ListProcessor lp = new ListProcessor(u, state, ingredientsL[u], startindex); threads[u] = new Thread(new ThreadStart(lp.run)); threads[u].Start(); startindex += partitionsize; } while (!finishedProcessing) { if (totalProcessedCount % percent == 0) { if (reportedCount != totalProcessedCount) { Console.WriteLine(totalProcessedCount + " out of " + ingredients.Count() + " ingredients processed."); sw.Stop(); Console.WriteLine("time elapsed: " + sw.Elapsed.TotalSeconds + " seconds"); sw.Reset(); sw.Start(); reportedCount = totalProcessedCount; } } Thread.Sleep(100); } ; Console.WriteLine("Terminating Threads."); for (int u = 0; u < workerThreadCount; u++) { threads[u].Join(); } Console.WriteLine("Creating Leveled lists..."); IEnumerable <IBookGetter> books = from book in state.LoadOrder.PriorityOrder.Book().WinningOverrides() where book.FormKey.Equals(new FormKey(new ModKey("Skyrim", ModType.Master), 0x0F5CB1)) select book; IBookGetter noteTemplate = books.ToList()[0]; Console.WriteLine("Creating " + combinations.Count + " recipes."); percent = (int)(combinations.Count * outputPercentage); int i = 0; /* Main leveled list that gets added to recipe drop */ LeveledItem mainpotionRecipeLVLI = state.PatchMod.LeveledItems.AddNew(); LeveledItemEntry mainpotionRecipeLVLIentry = new LeveledItemEntry(); mainpotionRecipeLVLI.Entries = new Noggog.ExtendedList <LeveledItemEntry>(); LeveledItemEntryData mainpotionRecipeLVLIentrydata = new LeveledItemEntryData(); GlobalInt mainpotionGlobal = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); mainpotionGlobal.Data = new Random().Next(minChance, maxChance); state.PatchMod.Globals.Set(mainpotionGlobal); mainpotionRecipeLVLI.Global = mainpotionGlobal; mainpotionRecipeLVLI.EditorID = "mainpotionRecipeList"; /* Must split sub leveled lists because it can only hold 128 items */ uint potionRecipeListCount = (potionRecipeCount / 128) + 1; uint poisonRecipeListCount = (poisonRecipeCount / 128) + 1; uint impurepotionRecipeListCount = (impurepotionRecipeCount / 128) + 1; LeveledItem[] potionRecipeLVLIs = new LeveledItem[potionRecipeListCount]; uint masterpotionRecipeListCount = ((potionRecipeListCount + poisonRecipeListCount + impurepotionRecipeListCount) / 128) + 1; LeveledItem[] masterpotionRecipeLVLIs = new LeveledItem[masterpotionRecipeListCount]; LeveledItemEntry[] masterpotionRecipeLVLIentries = new LeveledItemEntry[masterpotionRecipeListCount]; LeveledItemEntryData[] masterpotionRecipeLVLIentriesdata = new LeveledItemEntryData[masterpotionRecipeListCount]; GlobalInt[] masterpotionGlobals = new GlobalInt[masterpotionRecipeListCount]; LeveledItemEntry[] potionRecipeLVLIentries = new LeveledItemEntry[potionRecipeListCount]; LeveledItemEntryData[] potionRecipeLVLIentriesdata = new LeveledItemEntryData[potionRecipeListCount]; GlobalInt[] potionGlobals = new GlobalInt[potionRecipeListCount]; for (int k = 0; k < masterpotionRecipeListCount; k++) { masterpotionRecipeLVLIentries[k] = new LeveledItemEntry(); masterpotionRecipeLVLIentriesdata[k] = new LeveledItemEntryData(); masterpotionRecipeLVLIs[k] = state.PatchMod.LeveledItems.AddNew(); masterpotionRecipeLVLIs[k].Entries = new Noggog.ExtendedList <LeveledItemEntry>(); masterpotionGlobals[k] = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); masterpotionGlobals[k].Data = new Random().Next(5, 25);//Chance of picking a recipe from this list state.PatchMod.Globals.Set(masterpotionGlobals[k]); masterpotionRecipeLVLIs[k].Global = masterpotionGlobals[k]; masterpotionRecipeLVLIs[k].EditorID = "masterpotionRecipeList" + k; masterpotionRecipeLVLIentriesdata[k].Reference = masterpotionRecipeLVLIs[k].FormKey; masterpotionRecipeLVLIentriesdata[k].Level = 1; masterpotionRecipeLVLIentriesdata[k].Count = 1; } for (int l = 0; l < potionRecipeListCount; l++) { potionRecipeLVLIentries[l] = new LeveledItemEntry(); potionRecipeLVLIentriesdata[l] = new LeveledItemEntryData(); potionRecipeLVLIs[l] = state.PatchMod.LeveledItems.AddNew(); potionRecipeLVLIs[l].Entries = new Noggog.ExtendedList <LeveledItemEntry>(); potionGlobals[l] = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); potionGlobals[l].Data = new Random().Next(5, 25);//Chance of picking a recipe from this list state.PatchMod.Globals.Set(potionGlobals[l]); potionRecipeLVLIs[i].Global = potionGlobals[l]; potionRecipeLVLIs[l].EditorID = "potionRecipeList" + l; potionRecipeLVLIentriesdata[l].Reference = potionRecipeLVLIs[l].FormKey; potionRecipeLVLIentriesdata[l].Level = 1; potionRecipeLVLIentriesdata[l].Count = 1; } LeveledItem[] poisonRecipeLVLIs = new LeveledItem[poisonRecipeListCount]; LeveledItemEntry[] poisonRecipeLVLIentries = new LeveledItemEntry[poisonRecipeListCount]; LeveledItemEntryData[] poisonRecipeLVLIentriesdata = new LeveledItemEntryData[poisonRecipeListCount]; GlobalInt[] poisonGlobals = new GlobalInt[poisonRecipeListCount]; for (int l = 0; l < poisonRecipeListCount; l++) { poisonRecipeLVLIentries[l] = new LeveledItemEntry(); poisonRecipeLVLIentriesdata[l] = new LeveledItemEntryData(); poisonRecipeLVLIs[l] = state.PatchMod.LeveledItems.AddNew(); poisonRecipeLVLIs[l].Entries = new Noggog.ExtendedList <LeveledItemEntry>(); poisonGlobals[l] = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); poisonGlobals[l].Data = new Random().Next(5, 25);//Chance of picking a recipe from this list state.PatchMod.Globals.Set(poisonGlobals[l]); poisonRecipeLVLIs[i].Global = poisonGlobals[l]; poisonRecipeLVLIs[l].EditorID = "poisonRecipeList" + l; poisonRecipeLVLIentriesdata[l].Reference = poisonRecipeLVLIs[l].FormKey; poisonRecipeLVLIentriesdata[l].Level = 1; poisonRecipeLVLIentriesdata[l].Count = 1; } LeveledItem[] impurepotionRecipeLVLIs = new LeveledItem[impurepotionRecipeListCount]; LeveledItemEntry[] impurepotionRecipeLVLIentries = new LeveledItemEntry[impurepotionRecipeListCount]; LeveledItemEntryData[] impurepotionRecipeLVLIentriesdata = new LeveledItemEntryData[impurepotionRecipeListCount]; GlobalInt[] impurepotionGlobals = new GlobalInt[impurepotionRecipeListCount]; for (int l = 0; l < impurepotionRecipeListCount; l++) { impurepotionRecipeLVLIentries[l] = new LeveledItemEntry(); impurepotionRecipeLVLIentriesdata[l] = new LeveledItemEntryData(); impurepotionRecipeLVLIs[l] = state.PatchMod.LeveledItems.AddNew(); impurepotionRecipeLVLIs[l].Entries = new Noggog.ExtendedList <LeveledItemEntry>(); impurepotionGlobals[l] = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE); impurepotionGlobals[l].Data = new Random().Next(5, 25);//Chance of picking a recipe from this list state.PatchMod.Globals.Set(impurepotionGlobals[l]); impurepotionRecipeLVLIs[i].Global = impurepotionGlobals[l]; impurepotionRecipeLVLIs[l].EditorID = "impurepotionRecipeList" + l; impurepotionRecipeLVLIentriesdata[l].Reference = impurepotionRecipeLVLIs[l].FormKey; impurepotionRecipeLVLIentriesdata[l].Level = 1; impurepotionRecipeLVLIentriesdata[l].Count = 1; } Console.WriteLine("Splitting potions into lists (" + potionRecipeListCount + " " + poisonRecipeListCount + " " + impurepotionRecipeListCount + ")"); uint potionIndex = 0, poisonIndex = 0, impurepotionIndex = 0; Dictionary <String, int> nameCache = new Dictionary <String, int>(); foreach (IngrCombination ic in combinations) { if (i % percent == 0) { Console.WriteLine(i + " out of " + combinations.Count + " recipes created."); } IBook newRecipe = noteTemplate.DeepCopy(); newRecipe.FormKey = state.PatchMod.GetNextFormKey(); String prefix = "[Potion]"; if (ic.Type == 1) { prefix = "[Poison]"; } if (ic.Type == 2) { prefix = "[Impure Potion]"; } newRecipe.Description = prefix + ic.RecipeName; newRecipe.Name = ic.RecipeName; newRecipe.BookText = ic.PotionString; newRecipe.Weight = recipeWeight; newRecipe.Value = recipeValue; String?name = "recipeof"; foreach (String?s in ic.MyEffects !) { name += s; } name = name.Replace(" ", String.Empty); int nameIndex = 0; if (nameCache.TryGetValue(name, out nameIndex)) { nameCache[name] = nameIndex + 1; name = name + nameCache[name]; } else { nameCache.Add(name, 0); name = name + "0"; } newRecipe.EditorID = name; /* Add ingredients to CACO learning recipe script */ if (state.LoadOrder.ContainsKey(ModKey.FromNameAndExtension("Complete Alchemy & Cooking Overhaul.esp"))) { String[] s = (from scriptentry in newRecipe.VirtualMachineAdapter?.Scripts where scriptentry.Name.Equals("CACO_AlchemyRecipeScript") select scriptentry.Name).ToArray(); if (s.Length < 1 && learnEffectsFromRecipe)//For adding recipe to a brand new item (not a copy of a vanilla recipe) { ScriptEntry cacoscript = new ScriptEntry(); cacoscript.Name = "CACO_AlchemyRecipeScript"; newRecipe.VirtualMachineAdapter?.Scripts.Add(cacoscript); } if (newRecipe.VirtualMachineAdapter?.Scripts != null)//For modiying a copy of a vanilla recipe modified by CACO(default) { foreach (ScriptEntry se in newRecipe.VirtualMachineAdapter?.Scripts !) { if (se == null) { continue; } if (se.Name.Equals("CACO_AlchemyRecipeScript")) { if (!learnEffectsFromRecipe) { newRecipe.VirtualMachineAdapter?.Scripts?.Remove(se); continue; } int[,] ingrEffectIndex = new int[3, 4]; for (int j = 0; j < ingrEffectIndex.GetLength(0); j++) { for (int k = 0; k < ingrEffectIndex.GetLength(1); k++) { ingrEffectIndex[j, k] = -1; } } for (int j = 0; j < ic.MyIngrs.Length; j++) { int offset = 0; for (int k = 0; k < ic.MyIngrs[j].Effects.Count; k++) { foreach (String mgefname in ic.MyEffects) { state.LinkCache.TryResolve <IMagicEffectGetter>(ic.MyIngrs[j].Effects[k].BaseEffect.FormKey, out var mgeffect); if (mgeffect?.Name?.String?.Equals(mgefname) ?? true) { ingrEffectIndex[j, offset++] = k; } } } } bool[,] exists = new bool[3, 4]; bool[] rexists = new bool[3]; bool trexist = false, nvarexist = false, arrexist = false; foreach (ScriptProperty sp in se.Properties)//Scan CACO learning script properties { switch (sp.Name) { case "ThisRecipe": sp.Flags = ScriptProperty.Flag.Edited; ((ScriptObjectProperty)sp).Object = new FormLink <ISkyrimMajorRecordGetter>(newRecipe.FormKey); trexist = true; break; case "NoValueAfterRead": sp.Flags = ScriptProperty.Flag.Edited; ((ScriptBoolProperty)sp).Data = hasValueAfterRead; nvarexist = true; break; case "CACO_AlchemyRecipesRead": arrexist = true; break; } for (int j = 0; j < 3; j++) { if (sp.Name.Equals("Ingredient0" + (j + 1))) { if (ic.MyIngrs.Length > j) { sp.Flags = ScriptProperty.Flag.Edited; ((ScriptObjectProperty)sp).Object = new FormLink <ISkyrimMajorRecordGetter>(ic.MyIngrs[j].FormKey); rexists[j] = true; } } } for (int j = 0; j < 3; j++) { for (int k = 0; k < 4; k++) { if (sp.Name.Equals("Ingredient0" + (j + 1) + "Effect" + (k + 1))) { if (ingrEffectIndex[j, k] != -1) { ((ScriptIntProperty)sp).Data = ingrEffectIndex[j, k]; exists[j, k] = true; } } } } } for (int j = 0; j < rexists.Length; j++) { if (ic.MyIngrs.Length > j) { if (!rexists[j]) { ScriptObjectProperty sop = new ScriptObjectProperty(); sop.Object = new FormLink <ISkyrimMajorRecordGetter>(ic.MyIngrs[j].FormKey); sop.Name = "Ingredient0" + (j + 1); sop.Flags = ScriptProperty.Flag.Edited; se.Properties.Add(sop); } } } for (int j = 0; j < exists.GetLength(0); j++) { for (int k = 0; k < exists.GetLength(1); k++) { if (ic.MyIngrs.Length > j) { if (!exists[j, k] && ingrEffectIndex[j, k] != -1) { ScriptIntProperty sip = new ScriptIntProperty(); sip.Data = ingrEffectIndex[j, k]; sip.Name = "Ingredient0" + (j + 1) + "Effect" + (k + 1); sip.Flags = ScriptProperty.Flag.Edited; se.Properties.Add(sip); } } } } if (!trexist) { ScriptObjectProperty sop = new ScriptObjectProperty(); sop.Object = new FormLink <ISkyrimMajorRecordGetter>(newRecipe.FormKey); sop.Name = "ThisRecipe"; sop.Flags = ScriptProperty.Flag.Edited; se.Properties.Add(sop); } if (!nvarexist) { ScriptBoolProperty sbp = new ScriptBoolProperty(); sbp.Data = hasValueAfterRead; sbp.Name = "NoValueAfterRead"; sbp.Flags = ScriptProperty.Flag.Edited; se.Properties.Add(sbp); } if (arrexist) { FormList fl = new FormList(new FormKey(new ModKey("Complete Alchemy & Cooking Overhaul.esp", ModType.Plugin), 0xA2C667), SkyrimRelease.SkyrimSE); ScriptObjectProperty sop = new ScriptObjectProperty(); sop.Object = fl; sop.Name = "CACO_AlchemyRecipesRead"; sop.Flags = ScriptProperty.Flag.Edited; se.Properties.Add(sop); } } } } } state.PatchMod.Books.Set((Book)newRecipe); LeveledItemEntry lie = new LeveledItemEntry(); LeveledItemEntryData data = new LeveledItemEntryData(); data.Level = 1; data.Count = 1; data.Reference = new FormLink <IItemGetter>(newRecipe.FormKey); lie.Data = data; switch (ic.Type) { case 0: potionRecipeLVLIentriesdata[potionIndex / 128].Reference = potionRecipeLVLIs[potionIndex / 128].FormKey; potionRecipeLVLIentries[potionIndex / 128].Data = potionRecipeLVLIentriesdata[potionIndex / 128]; potionRecipeLVLIs[potionIndex / 128].Entries?.Add(lie); potionIndex++; break; case 1: poisonRecipeLVLIentriesdata[poisonIndex / 128].Reference = poisonRecipeLVLIs[poisonIndex / 128].FormKey; poisonRecipeLVLIentries[poisonIndex / 128].Data = poisonRecipeLVLIentriesdata[poisonIndex / 128]; poisonRecipeLVLIs[poisonIndex / 128].Entries?.Add(lie); poisonIndex++; break; case 2: impurepotionRecipeLVLIentriesdata[impurepotionIndex / 128].Reference = impurepotionRecipeLVLIs[impurepotionIndex / 128].FormKey; impurepotionRecipeLVLIentries[impurepotionIndex / 128].Data = impurepotionRecipeLVLIentriesdata[impurepotionIndex / 128]; impurepotionRecipeLVLIs[impurepotionIndex / 128].Entries?.Add(lie); impurepotionIndex++; break; } i++; } Console.WriteLine("Linking recipes to potion leveled list"); IEnumerable <ILeveledItemGetter> lvlilists = from list in state.LoadOrder.PriorityOrder.OnlyEnabled().LeveledItem().WinningOverrides() where list.EditorID?.Equals("LItemPotionAll") ?? true select list; ILeveledItemGetter allList = lvlilists.ToList()[0]; LeveledItem modifiedList = state.PatchMod.LeveledItems.GetOrAddAsOverride(allList); potionIndex = 0; poisonIndex = 0; impurepotionIndex = 0; for (int l = 0; l < masterpotionRecipeListCount; l++) { masterpotionRecipeLVLIentriesdata[l].Reference = masterpotionRecipeLVLIs[l].FormKey; masterpotionRecipeLVLIentries[l].Data = masterpotionRecipeLVLIentriesdata[l]; for (int k = 0; k < 128; k++) { if (potionIndex < potionRecipeLVLIentries.Length) { masterpotionRecipeLVLIs[l].Entries?.Add(potionRecipeLVLIentries[potionIndex++]); } else if (poisonIndex < poisonRecipeLVLIentries.Length) { masterpotionRecipeLVLIs[l].Entries?.Add(poisonRecipeLVLIentries[poisonIndex++]); } else if (impurepotionIndex < impurepotionRecipeLVLIentries.Length) { masterpotionRecipeLVLIs[l].Entries?.Add(impurepotionRecipeLVLIentries[impurepotionIndex++]); } else { break; } } mainpotionRecipeLVLI.Entries?.Add(masterpotionRecipeLVLIentries[l]); } foreach (LeveledItem li in potionRecipeLVLIs) { state.PatchMod.LeveledItems.Set(li); } foreach (LeveledItem li in poisonRecipeLVLIs) { state.PatchMod.LeveledItems.Set(li); } foreach (LeveledItem li in impurepotionRecipeLVLIs) { state.PatchMod.LeveledItems.Set(li); } foreach (LeveledItem li in masterpotionRecipeLVLIs) { state.PatchMod.LeveledItems.Set(li); } mainpotionRecipeLVLIentrydata.Reference = mainpotionRecipeLVLI.FormKey; mainpotionRecipeLVLIentry.Data = mainpotionRecipeLVLIentrydata; mainpotionRecipeLVLIentrydata.Count = 1; mainpotionRecipeLVLIentrydata.Level = 1; modifiedList.Entries?.Add(mainpotionRecipeLVLIentry); state.PatchMod.LeveledItems.Set(mainpotionRecipeLVLI); Console.WriteLine("Adding recipes to defined containers"); IEnumerable <IContainerGetter> chests = from list in state.LoadOrder.PriorityOrder.OnlyEnabled().Container().WinningOverrides() where containerEditorIDs?.ToList().Contains(list.EditorID !) ?? true select list; ContainerEntry potionListContainerEntry = new ContainerEntry(); ContainerItem potionListContainerItem = new ContainerItem(); potionListContainerItem.Item = mainpotionRecipeLVLI.FormKey; potionListContainerItem.Count = 1; potionListContainerEntry.Item = potionListContainerItem; foreach (IContainerGetter chest in chests) { Container rChest = state.PatchMod.Containers.GetOrAddAsOverride(chest); rChest.Items?.Add(potionListContainerEntry); } }
public int Write(JsonTextWriter writer, ISearchResult wordMatches, int skip = 0, int take = -1) { int matchCount = 0; ContainerEntry lastRun = ContainerEntry.Empty; ContainerEntry lastResult = ContainerEntry.Empty; while (!wordMatches.Done) { int count = wordMatches.Page(ref _termPositions); for (int i = 0; i < count; ++i) { long position = _termPositions[i]; // If this position isn't in the last run's results array, find the run which contains it if (!lastRun.Contains(position)) { // Close previous run, if any if (!lastRun.IsEmpty()) { WriteRunSubsetEnd(writer); } // Find containing run lastRun = FindContainerAtDepth(position, _runDepth); // Write run subset _bionReader.Seek(lastRun.StartByteOffset); WriteRunSubsetStart(writer); } // Find and write result ContainerEntry result = FindContainerAtDepth(position, _runDepth + 2); if (!result.IsEmpty() && !lastResult.Equals(result)) { matchCount++; if (matchCount <= skip) { continue; } _bionReader.Seek(result.StartByteOffset); JsonBionConverter.BionToJson(_bionReader, writer); if (take >= 0 && matchCount >= skip + take) { break; } } } if (take >= 0 && matchCount >= skip + take) { break; } } // Close last run, if any if (!lastRun.IsEmpty()) { WriteRunSubsetEnd(writer); } return(matchCount); }
private ContainerEntry FindContainerAtDepth(long position, int desiredDepth) { // Find the first container ending after position. ContainerEntry firstAfter = _containerIndex.FirstEndingAfter(position); int firstAfterDepth = _containerIndex.Depth(firstAfter); // Find the ancestor at the desired depth. If there is one, and it contains position, we can use it ContainerEntry firstAtDepth = AncestorAtDepth(firstAfter, firstAfterDepth, desiredDepth); if (firstAtDepth.Contains(position)) { return(firstAtDepth); } // If nothing deep enough was indexed, we must find the nearest point of known depth and walk the BION long seekToPosition; int seekToDepth; // The nearest point is... if (firstAfter.StartByteOffset < position) { // The start of the first container ending after position, if it starts before position seekToPosition = firstAfter.StartByteOffset; seekToDepth = firstAfterDepth - 1; } else if (firstAfter.Index > 0) { // The end of the container before that, if it started after position ContainerEntry lastBefore = _containerIndex[firstAfter.Index - 1]; seekToPosition = lastBefore.EndByteOffset; seekToDepth = _containerIndex.Depth(lastBefore) - 1; } else { // The start of the document, if the first container was found seekToPosition = 0; seekToDepth = 0; } // Seek to that position and read until we find a container at the right depth which contains position _bionReader.Seek(seekToPosition); long lastContainerStart = -1; long lastContainerEnd = -1; while (_bionReader.BytesRead < position + 3) { _bionReader.Read(); if (_bionReader.Depth + seekToDepth == desiredDepth) { lastContainerStart = _bionReader.BytesRead - 1; _bionReader.SkipRest(); lastContainerEnd = _bionReader.BytesRead; } } ContainerEntry found = new ContainerEntry(lastContainerStart, lastContainerEnd, -1); if (!found.Contains(position)) { return(ContainerEntry.Empty); } return(found); }
// Add Item To Container bool AddItem(int place, int lowID, int HighID, int Type, uint InstanceItemID, int Amount, int QL, uint Flags) { if (place == 0x6f) { // find next free int i = 0; while (i < NumberOfSlots) { if (Items[i] == null) break; i++; } // No free slot found? if (i == NumberOfSlots) return false; place = i; } if ((Type == 0) && (InstanceItemID == 0)) { ContainerEntry ce = new ContainerEntry(); ce.Type = 0; ce.InstanceID = 0; ce.LowID = lowID; ce.HighID = HighID; ce.QL = QL; ce.Flags = Flags; Items[place] = ce; } else { //Instanced items stuff here } return true; }
/// <summary> /// Gets all instances. /// </summary> /// <param name="service">The service.</param> /// <returns></returns> public IEnumerable <Object> GetAllInstances(Type service) { ContainerEntry entry = GetEntry(service, null); return(entry != null?entry.Select(x => x()) : new Object[0]); }
// Load All Container Arrays from SQL void LoadFromSQL(string tablename) { // Empty the Array first for (int i = 0; i < Items.Length; i++) Items[i] = null; SqlWrapper sql = new SqlWrapper(); DataTable dt = sql.ReadDatatable("SELECT * FROM " + tablename + " WHERE container=" + Type + " AND ID=" + Instance); foreach (DataRow row in dt.Rows) { int place = (Int32)row["placement"]; if (place < NumberOfSlots) { if (((Int32)row["type"] != 0) && ((Int32)row["instance"] != 0)) { // Do stuff with instanced items // Create item from lowid/highid interpolated by QL and read stats from sql } else { ContainerEntry ce = new ContainerEntry(); ce.LowID = (Int32)row["lowid"]; ce.HighID = (Int32)row["highid"]; ce.QL = (Int32)row["quality"]; ce.Amount = (Int32)row["multiplecount"]; ce.Flags = (uint)row["flags"]; ce.InstanceID = 0; ce.Type = 0; Items[place] = ce; } } } }