Пример #1
0
 public void Write(
     MutagenWriter writer,
     ILensFlareGetter item,
     RecordTypeConverter?recordTypeConverter = null)
 {
     using (HeaderExport.Header(
                writer: writer,
                record: recordTypeConverter.ConvertToCustom(RecordTypes.LENS),
                type: Mutagen.Bethesda.Binary.ObjectType.Record))
     {
         try
         {
             SkyrimMajorRecordBinaryWriteTranslation.WriteEmbedded(
                 item: item,
                 writer: writer);
             MajorRecordBinaryWriteTranslation.WriteRecordTypes(
                 item: item,
                 writer: writer,
                 recordTypeConverter: recordTypeConverter);
         }
         catch (Exception ex)
         {
             throw RecordException.Factory(ex, item.FormKey, item.EditorID);
         }
     }
 }
Пример #2
0
 public virtual void Write(
     MutagenWriter writer,
     IGlobalGetter item,
     RecordTypeConverter?recordTypeConverter = null)
 {
     using (HeaderExport.Header(
                writer: writer,
                record: recordTypeConverter.ConvertToCustom(RecordTypes.GLOB),
                type: Mutagen.Bethesda.Binary.ObjectType.Record))
     {
         try
         {
             OblivionMajorRecordBinaryWriteTranslation.WriteEmbedded(
                 item: item,
                 writer: writer);
             writer.MetaData.FormVersion = item.FormVersion;
             WriteRecordTypes(
                 item: item,
                 writer: writer,
                 recordTypeConverter: recordTypeConverter);
             writer.MetaData.FormVersion = null;
         }
         catch (Exception ex)
         {
             throw RecordException.Factory(ex, item.FormKey, item.EditorID);
         }
     }
 }
Пример #3
0
        public static Dictionary <CustomSet <ModKey>, RecordsClassifiedByMasters <TMod, TModGetter> > ClassifyRecordsByReferencedMasters <TMod, TModGetter>(
            TModGetter patchMod,
            CustomSetFactory <ModKey> setFactory,
            int maximumMastersPerMod = MAXIMUM_MASTERS_PER_MOD)
            where TMod : class, IMod, TModGetter
            where TModGetter : class, IModGetter, IMajorRecordContextEnumerable <TMod, TModGetter>
        {
            var recordSets       = new Dictionary <CustomSet <ModKey>, RecordsClassifiedByMasters <TMod, TModGetter> >();
            var masterSetBuilder = setFactory.NewSet();

            var patchModKey = patchMod.ModKey;

            var linkCache = patchMod.ToUntypedImmutableLinkCache();

            foreach (IModContext <TMod, TModGetter, IMajorRecordCommon, IMajorRecordCommonGetter>?context in patchMod.EnumerateMajorRecordContexts <IMajorRecordCommon, IMajorRecordCommonGetter>(linkCache, false))
            {
                masterSetBuilder.Clear();

                bool isNewRecord = false;

                IModContext?thisContext = context;
                while (thisContext is not null)
                {
                    var record = context.Record;
                    var modKey = record.FormKey.ModKey;
                    masterSetBuilder.Add(modKey);

                    if (modKey == patchModKey)
                    {
                        isNewRecord = true;
                    }

                    // TODO Does this include all child records?
                    foreach (var link in record.ContainedFormLinks)
                    {
                        masterSetBuilder.Add(link.FormKey.ModKey);
                    }

                    thisContext = thisContext.Parent;

                    int recordMasterCount = masterSetBuilder.Count;
                    if (recordMasterCount > maximumMastersPerMod)
                    {
                        throw RecordException.Factory(new Exception($"Too many masters ({recordMasterCount}) referenced by one record"), record);
                    }
                }

                CustomSet <ModKey> masterSet = masterSetBuilder.ToCustomSet();
                var recordSet = recordSets.Autovivify(masterSet, () => new(masterSet));

                recordSet.contextSet.Add(context);

                if (isNewRecord)
                {
                    recordSet.hasNewRecords = true;
                }
            }

            return(recordSets);
        }
Пример #4
0
 public T this[FormKey key]
 {
     get
     {
         try
         {
             return(ConstructWrapper(this._locs[key]));
         }
         catch (Exception ex)
         {
             throw RecordException.Factory(ex, key, edid: null);
         }
     }
 }
Пример #5
0
 public IEnumerator <IKeyValue <T, FormKey> > GetEnumerator()
 {
     foreach (var kv in this._locs)
     {
         KeyValue <T, FormKey> item;
         try
         {
             item = new KeyValue <T, FormKey>(kv.Key, ConstructWrapper(kv.Value));
         }
         catch (Exception ex)
         {
             throw RecordException.Factory(ex, kv.Key, edid: null);
         }
         yield return(item);
     }
 }
Пример #6
0
 public virtual void Write(
     MutagenWriter writer,
     IAPlacedGetter item,
     RecordTypeConverter?recordTypeConverter = null)
 {
     try
     {
         Fallout4MajorRecordBinaryWriteTranslation.WriteEmbedded(
             item: item,
             writer: writer);
         MajorRecordBinaryWriteTranslation.WriteRecordTypes(
             item: item,
             writer: writer,
             recordTypeConverter: recordTypeConverter);
     }
     catch (Exception ex)
     {
         throw RecordException.Factory(ex, item.FormKey, item.EditorID);
     }
 }
Пример #7
0
        public static void RunPatch(SynthesisState <ISkyrimMod, ISkyrimModGetter> state)
        {
            foreach (var armorAddon in state.LoadOrder.PriorityOrder.WinningOverrides <IArmorAddonGetter>())
            {
                try
                {
                    if (armorAddon.BodyTemplate == null || !(armorAddon.BodyTemplate.FirstPersonFlags.HasFlag(BipedObjectFlag.Body) && armorAddon.BodyTemplate.FirstPersonFlags.HasFlag(BipedObjectFlag.Amulet)))
                    {
                        continue;
                    }

                    // Ignore things that are probably skins like Miraak's hidden skin
                    if (armorAddon.BodyTemplate.FirstPersonFlags.HasFlag(BipedObjectFlag.Head) &&
                        armorAddon.BodyTemplate.FirstPersonFlags.HasFlag(BipedObjectFlag.Hair) &&
                        armorAddon.BodyTemplate.FirstPersonFlags.HasFlag(BipedObjectFlag.Hands))
                    {
                        continue;
                    }

                    // Ignore Naked Torso and Child Clothes
                    if (armorAddon.EditorID == null || armorAddon.EditorID.Contains("Naked") || armorAddon.EditorID.Contains("Child"))
                    {
                        continue;
                    }

                    var modifiedArmorAddon = state.PatchMod.ArmorAddons.GetOrAddAsOverride(armorAddon);

                    if (modifiedArmorAddon.BodyTemplate == null)
                    {
                        modifiedArmorAddon.BodyTemplate = new BodyTemplate();
                    }

                    modifiedArmorAddon.BodyTemplate.FirstPersonFlags &= ~BipedObjectFlag.Amulet;
                }
                catch (Exception ex)
                {
                    throw RecordException.Factory(ex, armorAddon);
                }
            }
        }
Пример #8
0
        public void PatchArmors()
        {
            /**
             * 1. Loop over all armors.
             * 2. For each armor, iterate over its keywords and match it to the tier rank in armor_rankings.json. Grab the HIGHEST tier.
             * 3. Based on that tier + armor slot + armor type, assign it a keyword from the appropiate ASX_<armor> keyword from Light/HeavyArmorKeywordCollection
             * 4. If description setting is turned on, update the item description.
             */
            foreach (var armor in this.state.LoadOrder.PriorityOrder.WinningOverrides <IArmorGetter>())
            {
                try
                {
                    if (armor.EditorID == null || armor.Keywords == null || armor.BodyTemplate == null || armor.BodyTemplate.ArmorType == ArmorType.Clothing)
                    {
                        continue;
                    }

                    string armorType;
                    Dictionary <string, List <FormKey> > armorKeysMap;
                    if (armor.BodyTemplate.ArmorType == ArmorType.LightArmor)
                    {
                        armorKeysMap = ActionSpeedX.FormKeys.Keywords.LightArmorKeywordCollection;
                        armorType    = LIGHT;
                    }
                    else
                    {
                        armorKeysMap = ActionSpeedX.FormKeys.Keywords.HeavyArmorKeywordCollection;
                        armorType    = HEAVY;
                    }

                    int tier = -1;

                    /* We want to grab the highest material tier as some items can have multiple material keywrods
                     * Loop over the armorRankings(see armor_materials.json) and check the current armors keywords for a match.
                     * Item.key = int/str, item.val=List(armor material strings)
                     */

                    foreach (var keyword in armor.Keywords)
                    {
                        if (keyword.TryResolve(state.LinkCache, out var kw))
                        {
                            if (kw.EditorID != null && this.materialRanks.ContainsKey(kw.EditorID))
                            {
                                int rank = this.materialRanks[kw.EditorID];
                                if (rank > tier)
                                {
                                    tier = rank;
                                }
                            }
                        }
                    }

                    if (tier < 0)
                    {
                        Console.WriteLine($"No recognized material type for {armor.EditorID}. Skipping. ");
                        // tier = 1;
                        continue;
                    }
                    else
                    {
                        tier--; //correct array access
                    }
                    string slot;

                    if (armor.Keywords.Contains(Skyrim.Keyword.ArmorBoots))
                    {
                        slot = BOOTS;
                    }
                    else if (armor.Keywords.Contains(Skyrim.Keyword.ArmorCuirass))
                    {
                        slot = CUIRASS;
                    }
                    else if (armor.Keywords.Contains(Skyrim.Keyword.ArmorGauntlets))
                    {
                        slot = GAUNTLETS;
                    }
                    else if (armor.Keywords.Contains(Skyrim.Keyword.ArmorHelmet))
                    {
                        slot = HELMET;
                    }
                    else if (armor.Keywords.Contains(Skyrim.Keyword.ArmorShield))
                    {
                        slot = SHIELD;
                    }
                    else
                    {
                        Console.WriteLine("No matching equip slot for " + armor.EditorID);
                        continue;
                    }
                    var nw = state.PatchMod.Armors.GetOrAddAsOverride(armor);
                    nw.Keywords?.Add(armorKeysMap[slot][tier]);
                    if (this.settings.Descriptions)
                    {
                        PatchArmorDescription(nw, armorType, slot, tier);
                    }
                } catch (Exception e)

                {
                    throw RecordException.Factory("Error processing armor record", armor, e);
                }
            }
        }
Пример #9
0
        public void PatchNpcs()
        {
            /*
             * 1. Loop over all npcs.
             * 2. Verify it is not a ghost, an inherited template, and has a valid race
             * 3. Check if it has a match with a race in races.json
             * 4. Add perks based on settings.json
             *
             */

            foreach (var npc in this.state.LoadOrder.PriorityOrder.WinningOverrides <INpcGetter>())
            {
                try
                {
                    if (npc.Configuration.TemplateFlags.HasFlag(NpcConfiguration.TemplateFlag.SpellList) || npc.EditorID == null)
                    {
                        continue;                                                                                                           // Perks are inherited from a template
                    }
                    if (npc.Keywords != null && npc.Keywords.Contains(Skyrim.Keyword.ActorTypeGhost))
                    {
                        continue;                                                                               // Ghost shouldnt be affected by armor
                    }
                    if (!npc.Race.TryResolve(state.LinkCache, out var race) || race.EditorID == null || !this.racesToPatch.Contains(race.EditorID))
                    {
                        continue;
                    }

                    var npcCopy = this.state.PatchMod.Npcs.GetOrAddAsOverride(npc);
                    if (npcCopy.Perks == null)
                    {
                        npcCopy.Perks = new ExtendedList <PerkPlacement>();
                    }
                    foreach (var perk in this.perksToAdd)
                    {
                        PerkPlacement p = new PerkPlacement {
                            Rank = 1, Perk = perk.AsLink <IPerkGetter>()
                        };
                        npcCopy.Perks.Add(p);
                    }

                    if (npc.EditorID == "Player" && this.settings.Racials)
                    {
                        // a quest runs after racemenu that will sift and apply the correct racial perk. This perk is removed after.
                        PerkPlacement p = new PerkPlacement {
                            Rank = 1, Perk = FormKeys.Perks.ASX_DummyPerk.AsLink <IPerkGetter>()
                        };
                        npcCopy.Perks.Add(p);
                        continue;
                    }

                    if (this.settings.Racials && ActionSpeedX.FormKeys.Perks.RacialPerks.ContainsKey(race.EditorID))
                    {
                        PerkPlacement p = new PerkPlacement {
                            Rank = 1, Perk = FormKeys.Perks.RacialPerks[race.EditorID].AsLink <IPerkGetter>()
                        };
                        npcCopy.Perks.Add(p);
                    }

                    if (this.settings.Factions && npc.Factions != null)
                    {
                        foreach (var faction in npc.Factions)
                        {
                            if (faction.Faction.TryResolve(this.state.LinkCache, out var wtf) && wtf.EditorID != null && ActionSpeedX.FormKeys.Perks.FactionPerks.ContainsKey(wtf.EditorID))
                            {
                                PerkPlacement p = new PerkPlacement {
                                    Rank = 1, Perk = FormKeys.Perks.FactionPerks[wtf.EditorID].AsLink <IPerkGetter>()
                                };
                                npcCopy.Perks.Add(p);
                            }
                        }
                    }
                } catch (Exception e)
                {
                    throw RecordException.Factory("Error processing npc record", npc, e);
                }
            }
        }
Пример #10
0
        public static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state)
        {
            // Loop over all NPCs in the load order
            foreach (var npc in state.LoadOrder.PriorityOrder.Npc().WinningOverrides())
            {
                try
                {
                    // Skip NPC if it inherits spells from its template
                    if (npc.Configuration.TemplateFlags.HasFlag(NpcConfiguration.TemplateFlag.SpellList))
                    {
                        continue;
                    }

                    // Find if the NPC has PerkSkill or AlchemySkill perks
                    var hasPerkSkillBoosts    = false;
                    var hasAlchemySkillBoosts = false;

                    foreach (var perk in npc.Perks.EmptyIfNull())
                    {
                        if (perk.Perk.Equals(Skyrim.Perk.AlchemySkillBoosts))
                        {
                            hasAlchemySkillBoosts = true;
                        }
                        if (perk.Perk.Equals(Skyrim.Perk.PerkSkillBoosts))
                        {
                            hasPerkSkillBoosts = true;
                        }
                        if (hasAlchemySkillBoosts && hasPerkSkillBoosts)
                        {
                            break;
                        }
                    }

                    // If NPC has both, it is safe
                    if (hasAlchemySkillBoosts && hasPerkSkillBoosts)
                    {
                        continue;
                    }

                    // Otherwise, add the NPC to the patch
                    var modifiedNpc = state.PatchMod.Npcs.GetOrAddAsOverride(npc);

                    // Ensure perk list exists
                    modifiedNpc.Perks ??= new ExtendedList <PerkPlacement>();

                    // Add missing perks
                    if (!hasAlchemySkillBoosts)
                    {
                        modifiedNpc.Perks.Add(new PerkPlacement()
                        {
                            Perk = Skyrim.Perk.AlchemySkillBoosts,
                            Rank = 1
                        });
                    }

                    if (!hasPerkSkillBoosts)
                    {
                        modifiedNpc.Perks.Add(new PerkPlacement()
                        {
                            Perk = Skyrim.Perk.PerkSkillBoosts,
                            Rank = 1
                        });
                    }
                }
                catch (Exception ex)
                {
                    throw RecordException.Factory(ex, npc);
                }
            }
        }