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<Candidate> items;
}
public sealed class Candidate
{
public string id;
public string pool;
public string package;
public string name;
public List<string> requiredPeerIds;
}
[HarmonyPatch(typeof(UgcManager), "DiscoverFromLocalStudio")]
private static class Discover
{
private static void Postfix(List<IUgcItem> __0)
{
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Expected O, but got Unknown
Dictionary<string, UgcModule> dictionary = (Dictionary<string, UgcModule>)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<IUgcItem>),
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<ObjectTableDef, List<string>> originals = new Dictionary<ObjectTableDef, List<string>>();
private static readonly Dictionary<TNH_LootPoolDef, List<PoolEntry>> originalPools = new Dictionary<TNH_LootPoolDef, List<PoolEntry>>();
private static ObjectTableDef equipment;
private static readonly Dictionary<TNH_CharacterDef, List<OTagEra>> originalEras = new Dictionary<TNH_CharacterDef, List<OTagEra>>();
private static readonly Dictionary<TNH_CharacterDef, List<OTagSet>> originalSets = new Dictionary<TNH_CharacterDef, List<OTagSet>>();
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<Catalog>(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<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.Ordinal);
List<object> list = new List<object>();
List<object> list2 = new List<object>();
if (!originalEras.ContainsKey(character))
{
originalEras.Add(character, new List<OTagEra>(character.ValidAmmoEras));
}
if (!originalSets.ContainsKey(character))
{
originalSets.Add(character, new List<OTagSet>(character.ValidAmmoSets));
}
HashSet<OTagEra> hashSet = new HashSet<OTagEra>(originalEras[character]);
HashSet<OTagSet> hashSet2 = new HashSet<OTagSet>(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<string>());
}
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<ObjectTableDef>("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<string>(val.IDOverride));
}
List<string> list3 = new List<string>(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<PoolEntry>(equipPool.Entries));
}
equipPool.Entries = new List<PoolEntry>(value5);
if (dictionary.TryGetValue("Equipment", out var value6) && value6.Count > 0)
{
if ((Object)(object)equipment == (Object)null)
{
equipment = ScriptableObject.CreateInstance<ObjectTableDef>();
((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<string, List<string>> p) => p.Key, (KeyValuePair<string, List<string>> 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;
}
}
}