public void RandomizeTrees(Random random, Permutation permutation, SkillSplitter.Assignment split) { // >= 700: prosthetics // < 400: skills before mushin GameEditor editor = game.Editor; PARAM param = game.Params["SkillParam"]; // Orderings for skills which completely supersede each other. (For prosthetics, just use their natural id ordering) Dictionary <int, int> skillOrderings = new Dictionary <int, int> { [110] = 111, // Nightjar slash [210] = 211, // Ichimonji [310] = 311, // Praying Strikes }; Dictionary <int, ItemKey> texts = new Dictionary <int, ItemKey> { [0] = game.ItemForName("Shinobi Esoteric Text"), [1] = game.ItemForName("Prosthetic Esoteric Text"), [2] = game.ItemForName("Ashina Esoteric Text"), [3] = game.ItemForName("Senpou Esoteric Text"), // [4] = game.ItemForName("Mushin Esoteric Text"), }; SortedDictionary <ItemKey, string> names = game.Names(); string descName(int desc) { return(names[new ItemKey(ItemType.WEAPON, desc)]); } Dictionary <int, SkillData> allData = new Dictionary <int, SkillData>(); Dictionary <int, SkillSlot> allSlots = new Dictionary <int, SkillSlot>(); Dictionary <ItemKey, SkillData> skillItems = new Dictionary <ItemKey, SkillData>(); List <SkillData> skills = new List <SkillData>(); List <SkillSlot> skillSlots = new List <SkillSlot>(); List <SkillData> prosthetics = new List <SkillData>(); List <SkillSlot> prostheticSlots = new List <SkillSlot>(); bool explain = false; foreach (PARAM.Row r in param.Rows) { SkillData data = new SkillData { ID = (int)r.ID, Item = (int)r["SkilLDescriptionId"].Value, Equip = (int)r["Unk1"].Value, Flag = (int)r["EventFlagId"].Value, Placeholder = (int)r["Unk5"].Value, SpEffects = new[] { (int)r["Unk2"].Value, (int)r["Unk3"].Value }, EmblemChange = (byte)r["Unk10"].Value != 0, }; data.Key = new ItemKey(ItemType.WEAPON, data.Item); skillItems[data.Key] = data; SkillSlot slot = new SkillSlot { ID = (int)r.ID, Col = (short)r["MenuDisplayPositionIndexXZ"].Value, Row = (short)r["MenuDisplayPositionIndexY"].Value, Text = data.ID < 400 && texts.TryGetValue((byte)r["Unk7"].Value, out ItemKey text) ? text : null, }; if (explain) { Console.WriteLine($"{r.ID}: {data.Item}, {data.Equip}, {descName(data.Item)}"); } if (data.ID < 400) { skills.Add(data); skillSlots.Add(slot); } else if (data.ID >= 700) { prosthetics.Add(data); prostheticSlots.Add(slot); } allData[data.ID] = data; allSlots[slot.ID] = slot; } void applyData(PARAM.Row r, SkillData data) { r["SkilLDescriptionId"].Value = data.Item; r["EventFlagId"].Value = data.Flag; r["Unk1"].Value = data.Equip; r["Unk2"].Value = data.SpEffects[0]; r["Unk3"].Value = data.SpEffects[0]; r["Unk5"].Value = data.Placeholder; r["Unk10"].Value = (byte)(data.EmblemChange ? 1 : 0); } Shuffle(random, skills); Shuffle(random, skillSlots); Shuffle(random, prosthetics); Shuffle(random, prostheticSlots); // Skills rando if (split == null) { Dictionary <ItemKey, string> textWeight = new Dictionary <ItemKey, string>(); Dictionary <ItemKey, string> textLocations = texts.Values.ToDictionary(t => t, t => { SlotKey target = permutation.GetFiniteTargetKey(t); textWeight[t] = permutation.GetLogOrder(target); SlotAnnotation sn = ann.Slot(data.Location(target).LocScope); if (explain) { Console.WriteLine($"{game.Name(t)} in {sn.Area} - {sn.Text}. Lateness {(permutation.ItemLateness.TryGetValue(t, out double val) ? val : -1)}"); } return(sn.Area); });