using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using FistVR; using FistVR.Ugc; using HarmonyLib; using UnityEngine; using Valve.Newtonsoft.Json; using Valve.Newtonsoft.Json.Linq; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("quaternion.reggie.modded")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.5.0.0")] [assembly: AssemblyInformationalVersion("0.5.0")] [assembly: AssemblyProduct("quaternion.reggie.modded")] [assembly: AssemblyTitle("quaternion.reggie.modded")] [assembly: AssemblyVersion("0.5.0.0")] [BepInPlugin("quaternion.reggie.modded", "Trench Rat Reggie Modded", "0.5.0")] public sealed class ReggieModded : BaseUnityPlugin { public sealed class Catalog { public string version; public List items; } public sealed class Candidate { public string id; public string pool; public string package; public string name; public List requiredPeerIds; } [HarmonyPatch(typeof(UgcManager), "DiscoverFromLocalStudio")] private static class Discover { private static void Postfix(List __0) { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown Dictionary dictionary = (Dictionary)AccessTools.Field(typeof(UgcManager), "_contentModulesById").GetValue(null); if (dictionary.ContainsKey("quaternion.reggiemodded")) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)"Another copy of the modded module was found; using that copy without registering a duplicate."); return; } string text = Path.Combine(Path.Combine(directory, "studio"), "quaternion.reggiemodded"); JObject val = JObject.Parse(File.ReadAllText(Path.Combine(text, "module.json"))); if ((string)val["Id"] != "quaternion.reggiemodded") { throw new InvalidOperationException("Incorrect bundled module ID."); } MethodInfo obj = AccessTools.Method(typeof(UgcManager), "DiscoverFromDirectoryRecurse", new Type[5] { typeof(List), typeof(UgcModule), typeof(string), typeof(string), typeof(bool) }, (Type[])null) ?? throw new MissingMethodException("Unsupported H3VR native discovery API."); UgcModule val2 = new UgcModule("quaternion.reggiemodded", (string)val["Name"]); dictionary.Add("quaternion.reggiemodded", val2); obj.Invoke(null, new object[5] { __0, val2, text, text, false }); ((BaseUnityPlugin)instance).Logger.LogInfo((object)"Registered standalone native modded character from this profile."); } } [HarmonyPatch(typeof(TNH_LevelLoader), "ValidateCharacter")] private static class Validate { private static void Prefix(TNH_CharacterDef __0) { Prepare(__0); } } [HarmonyPatch(typeof(TNH_Manager), "InitTables")] private static class Initialize { private static void Prefix(TNH_Manager __instance) { Prepare(__instance.C); } } public const string Module = "quaternion.reggiemodded"; public const string Character = "quaternion.reggiemodded:WW1_Looter"; private static ReggieModded instance; private static string directory; private static Catalog catalog; private static readonly Dictionary> originals = new Dictionary>(); private static readonly Dictionary> originalPools = new Dictionary>(); private static ObjectTableDef equipment; private static readonly Dictionary> originalEras = new Dictionary>(); private static readonly Dictionary> originalSets = new Dictionary>(); private static string lastReport; private void Awake() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) instance = this; directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); catalog = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(directory, "optional-items.json"))); if (catalog == null || catalog.items == null) { throw new InvalidOperationException("Optional item catalog is missing."); } new Harmony("quaternion.reggie.modded").PatchAll(typeof(ReggieModded).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Optional catalog loaded: " + catalog.items.Count + " exact IDs. Missing item packs are optional.")); } public static void Prepare(TNH_CharacterDef character) { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Expected O, but got Unknown //IL_03c4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || character.UgcId != "quaternion.reggiemodded:WW1_Looter") { return; } Dictionary> dictionary = new Dictionary>(StringComparer.Ordinal); List list = new List(); List list2 = new List(); if (!originalEras.ContainsKey(character)) { originalEras.Add(character, new List(character.ValidAmmoEras)); } if (!originalSets.ContainsKey(character)) { originalSets.Add(character, new List(character.ValidAmmoSets)); } HashSet hashSet = new HashSet(originalEras[character]); HashSet hashSet2 = new HashSet(originalSets[character]); foreach (Candidate item in catalog.items) { if (!IM.OD.TryGetValue(item.id, out var value) || (Object)(object)value == (Object)null || (item.requiredPeerIds != null && !item.requiredPeerIds.Any((string id) => IM.OD.ContainsKey(id)))) { continue; } if (IsGunPool(item.pool) && !HasAmmo(value)) { list2.Add(new { id = item.id, reason = "No registered compatible ammunition; install this weapon's dependencies." }); continue; } hashSet.Add(value.TagEra); hashSet2.Add(value.TagSet); if (item.pool != "Ammo") { if (!dictionary.TryGetValue(item.pool, out var value2)) { dictionary.Add(item.pool, value2 = new List()); } if (!value2.Contains(item.id)) { value2.Add(item.id); } } list.Add(new { item.id, item.pool, item.package }); } character.ValidAmmoEras = hashSet.ToList(); character.ValidAmmoSets = hashSet2.ToList(); string[] array = new string[6] { "Sidearms", "Rifles", "Shotguns", "Support", "Melee", "Grenades" }; ObjectTableDef val = default(ObjectTableDef); foreach (string text in array) { if (!UgcManager.TryGetItem("quaternion.reggiemodded:WW1_" + text, ref val)) { throw new InvalidOperationException("Bundled pool missing: " + text); } if (!originals.TryGetValue(val, out var value3)) { originals.Add(val, value3 = new List(val.IDOverride)); } List list3 = new List(value3); if (dictionary.TryGetValue(text, out var value4)) { foreach (string item2 in value4) { if (!list3.Contains(item2)) { list3.Add(item2); } } } val.IDOverride = list3; } TNH_LootPoolDef equipPool = character.SosigLootTable.LootGroup_Boxes.EquipPool; if (!originalPools.TryGetValue(equipPool, out var value5)) { originalPools.Add(equipPool, value5 = new List(equipPool.Entries)); } equipPool.Entries = new List(value5); if (dictionary.TryGetValue("Equipment", out var value6) && value6.Count > 0) { if ((Object)(object)equipment == (Object)null) { equipment = ScriptableObject.CreateInstance(); ((Object)equipment).name = "Reggie optional equipment"; equipment.UgcId = "quaternion.reggiemodded:OptionalEquipment"; equipment.Category = (ObjectCategory)9; equipment.UseIDListOverride = true; } equipment.IDOverride = value6; equipPool.Entries.Add(new PoolEntry { TableDef = equipment, MinLevelAppears = 0, MaxLevelAppears = 99, Rarity = 1f }); } string text2 = JsonConvert.SerializeObject((object)new { character = "quaternion.reggiemodded:WW1_Looter", catalog = catalog.version, supportedIds = catalog.items.Count, registered = list, rejected = list2, pools = dictionary.ToDictionary((KeyValuePair> p) => p.Key, (KeyValuePair> p) => p.Value.Count) }, (Formatting)1); if (text2 != lastReport) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)("Reggie optional items: " + list.Count + " registered; " + list2.Count + " missing ammo. Vanilla fallbacks retained.")); try { File.WriteAllText(Path.Combine(Paths.ConfigPath, "quaternion.reggie.modded.audit.json"), text2); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Could not write item report: " + ex.Message)); } lastReport = text2; } } private static bool HasAmmo(FVRObject gun) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if ((int)gun.MagazineType != 0 && (!IM.CompatMags.TryGetValue(gun.MagazineType, out var value) || value == null || value.Count == 0)) { return false; } if (AM.SRoundDisplayDataDic.TryGetValue(gun.RoundType, out var value2) && (Object)(object)value2 != (Object)null && value2.Classes != null && value2.Classes.Length != 0) { return value2.Classes.Any((DisplayDataClass c) => (Object)(object)c.ObjectID != (Object)null); } return false; } private static bool IsGunPool(string pool) { switch (pool) { default: return pool == "Support"; case "Sidearms": case "Rifles": case "Shotguns": return true; } } }