Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of More Guns Forked IL2CPP v1.6.5
MoreGuns.dll
Decompiled 7 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using HarmonyLib; using Il2CppFishNet.Object; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.InteropTypes.Fields; using Il2CppScheduleOne; using Il2CppScheduleOne.Audio; using Il2CppScheduleOne.AvatarFramework; using Il2CppScheduleOne.AvatarFramework.Equipping; using Il2CppScheduleOne.Combat; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Dialogue; using Il2CppScheduleOne.Equipping; using Il2CppScheduleOne.FX; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Levelling; using Il2CppScheduleOne.Networking; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.Tools; using Il2CppScheduleOne.Trash; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.Shop; using Il2CppSteamworks; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MoreGuns; using MoreGuns.Dialogue; using MoreGuns.Gui; using MoreGuns.Guns; using MoreGuns.Patches; using MoreGuns.Sync; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(MoreGunsMod), "MoreGuns", "1.6.5", "Voidane", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: HarmonyDontPatchAll] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("MoreGuns")] [assembly: AssemblyConfiguration("Il2Cpp")] [assembly: AssemblyFileVersion("1.6.5.0")] [assembly: AssemblyInformationalVersion("1.6.5+a0f53f1260275c51c2e8503266a34bd2e4d56883")] [assembly: AssemblyProduct("MoreGuns")] [assembly: AssemblyTitle("MoreGuns")] [assembly: AssemblyVersion("1.6.5.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal static class ModVersion { public const string Current = "1.6.5"; } namespace MoreGuns { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Assets { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { ResourceManager resourceManager = new ResourceManager("MoreGuns.Assets", typeof(Assets).Assembly); resourceMan = resourceManager; } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] VoidanesGuns { get { object obj = ResourceManager.GetObject("VoidanesGuns", resourceCulture); return (byte[])obj; } } internal Assets() { } } internal static class Compat { public static T As<T>(this Object obj) where T : Object { return (obj == null) ? default(T) : ((Il2CppObjectBase)obj).TryCast<T>(); } public static string LocalPlayerId() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) try { return ((object)SteamUser.GetSteamID()/*cast due to .constrained prefix*/).ToString(); } catch { return "unknown"; } } public static CSteamID LobbySteamId() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) ulong num = (((Object)(object)Singleton<Lobby>.Instance != (Object)null) ? Singleton<Lobby>.Instance.LobbyID : 0); return new CSteamID(num); } } public static class Config { public static string folderPath = "UserData/MoreGuns.cfg"; public const string PREFIX = "MoreGuns"; public static MelonPreferences_Category Category { get; private set; } public static MelonPreferences_Entry<bool> EnableCrosshairForGuns { get; private set; } public static MelonPreferences_Entry<bool> AllowMinigunManualReload { get; private set; } public static void Initialize() { Category = MelonPreferences.CreateCategory("MoreGuns-! User Settings"); EnableCrosshairForGuns = Category.CreateEntry<bool>("Allow Gun Crosshair", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AllowMinigunManualReload = Category.CreateEntry<bool>("Allow Minigun Manual Reload", true, (string)null, "If false, the MiniGun can only be reloaded by talking to Stan.", false, false, (ValueValidator)null, (string)null); Category.SetFilePath(folderPath); Category.SaveToFile(true); } } internal static class GameAccess { private static readonly Dictionary<(Type Type, string Name), MemberInfo> MemberCache = new Dictionary<(Type, string), MemberInfo>(); private static readonly Dictionary<(Type Type, string Name, int ArgCount), MethodInfo> MethodCache = new Dictionary<(Type, string, int), MethodInfo>(); private const BindingFlags Flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public static void Call(object instance, string method, params object[] args) { if (instance != null) { FindMethod(instance.GetType(), method, (args != null) ? args.Length : 0)?.Invoke(instance, args); } } public static T Call<T>(object instance, string method, params object[] args) { if (instance == null) { return default(T); } return (FindMethod(instance.GetType(), method, (args != null) ? args.Length : 0)?.Invoke(instance, args) is T val) ? val : default(T); } public static void Set(object instance, string member, object value) { if (instance == null) { return; } MemberInfo memberInfo = ResolveMember(instance.GetType(), member); MemberInfo memberInfo2 = memberInfo; if (!(memberInfo2 is FieldInfo fieldInfo)) { if (memberInfo2 is PropertyInfo { CanWrite: not false } propertyInfo) { propertyInfo.SetValue(instance, value); } } else { fieldInfo.SetValue(instance, value); } } public static T Get<T>(object instance, string member) { if (instance == null) { return default(T); } MemberInfo memberInfo = ResolveMember(instance.GetType(), member); MemberInfo memberInfo2 = memberInfo; if (!(memberInfo2 is FieldInfo fieldInfo)) { if (memberInfo2 is PropertyInfo { CanRead: not false } propertyInfo) { return (propertyInfo.GetValue(instance) is T val) ? val : default(T); } return default(T); } return (fieldInfo.GetValue(instance) is T val2) ? val2 : default(T); } public static bool CanFire(Equippable_RangedWeapon weapon, bool checkAmmo) { return Call<bool>(weapon, "CanFire", new object[1] { checkAmmo }); } public static void Cock(Equippable_RangedWeapon weapon) { Call(weapon, "Cock"); } public static void Recalculate(FloatStack stack) { Call(stack, "Recalculate"); } public static void SetCurrentEquippable(object avatar, AvatarEquippable equippable) { Set(avatar, "CurrentEquippable", equippable); } public static void CreateListingUI(ShopInterface shop, ShopListing listing) { Call(shop, "CreateListingUI", listing); } public static void RefreshShownItems(ShopInterface shop) { Call(shop, "RefreshShownItems"); } private static MemberInfo ResolveMember(Type type, string name) { (Type, string) key = (type, name); if (MemberCache.TryGetValue(key, out var value)) { return value; } MemberInfo memberInfo = FindOnType(type, name); if (memberInfo == null && type.BaseType != null) { memberInfo = FindOnType(type.BaseType, name); } MemberCache[key] = memberInfo; return memberInfo; } private static MemberInfo FindOnType(Type type, string name) { PropertyInfo propertyInfo = type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (propertyInfo != null) { return propertyInfo; } return type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); } private static MethodInfo FindMethod(Type type, string name, int argCount) { (Type, string, int) key = (type, name, argCount); if (MethodCache.TryGetValue(key, out var value)) { return value; } MethodInfo methodInfo = MatchMethod(type, name, argCount); if (methodInfo == null && type.BaseType != null) { methodInfo = MatchMethod(type.BaseType, name, argCount); } MethodCache[key] = methodInfo; return methodInfo; } private static MethodInfo MatchMethod(Type type, string name, int argCount) { MethodInfo[] methods = type.GetMethods(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); foreach (MethodInfo methodInfo in methods) { if (string.Equals(methodInfo.Name, name, StringComparison.OrdinalIgnoreCase) && methodInfo.GetParameters().Length == argCount) { return methodInfo; } } return null; } } public class GunConfiguration { public static string folderPath = "UserData/MoreGuns.cfg"; public string ID { get; private set; } public MelonPreferences_Category Category { get; private set; } public MelonPreferences_Entry<float> Damage { get; private set; } public MelonPreferences_Entry<float> ImpactForce { get; private set; } public MelonPreferences_Entry<float> MinAimFOVReduction { get; private set; } public MelonPreferences_Entry<float> MaxAimFOVReduction { get; private set; } public MelonPreferences_Entry<float> AccuracyChangeDuration { get; private set; } public MelonPreferences_Entry<int> MagazineSize { get; private set; } public MelonPreferences_Entry<string> DisplayItemName { get; private set; } public MelonPreferences_Entry<string> DisplayDescription { get; private set; } public MelonPreferences_Entry<ELegalStatus> LegalStatus { get; private set; } public MelonPreferences_Entry<FullRank> RequiredRank { get; private set; } public MelonPreferences_Entry<string> MagDisplayItemName { get; private set; } public MelonPreferences_Entry<string> MagDisplayDescription { get; private set; } public MelonPreferences_Entry<ELegalStatus> MagLegalStatus { get; private set; } public MelonPreferences_Entry<FullRank> MagRequiredRank { get; private set; } public MelonPreferences_Entry<float> PurchasePrice { get; private set; } public MelonPreferences_Entry<float> MagPurchasePrice { get; private set; } public MelonPreferences_Entry<string> ItemName { get; private set; } public MelonPreferences_Entry<string> MagItemName { get; private set; } public MelonPreferences_Entry<bool> Available { get; private set; } public MelonPreferences_Entry<bool> MagAvailable { get; private set; } public MelonPreferences_Entry<string> AvailableReason { get; private set; } public MelonPreferences_Entry<string> MagAvailableReason { get; private set; } public event Action OnSettingChanged; public GunConfiguration(WeaponBase weapon) { ID = weapon.ID; string text = "MoreGuns-" + ID + " Settings"; string text2 = ID + " Settings"; Category = MelonPreferences.CreateCategory(text, text2); InitializePreferences(ID, weapon); Category.SetFilePath(folderPath); Category.SaveToFile(true); MelonLogger.Msg("Loaded configuration for " + ID + " from: " + folderPath); } private void InitializePreferences(string ID, WeaponBase weapon) { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) Equippable_RangedWeapon gunRangedWeapon = weapon.gunRangedWeapon; Damage = Category.CreateEntry<float>(ID + " Damage", gunRangedWeapon.Damage, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ImpactForce = Category.CreateEntry<float>(ID + " Impact Force", gunRangedWeapon.ImpactForce, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MinAimFOVReduction = Category.CreateEntry<float>(ID + " Min Aim FOV Reduction", gunRangedWeapon.MinAimFOVReduction, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MaxAimFOVReduction = Category.CreateEntry<float>(ID + " Max Aim FOV Reduction", gunRangedWeapon.MaxAimFOVReduction, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AccuracyChangeDuration = Category.CreateEntry<float>(ID + " Accuracy Change Duration", gunRangedWeapon.AccuracyChangeDuration, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagazineSize = Category.CreateEntry<int>(ID + " Magazine Size", gunRangedWeapon.MagazineSize, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); IntegerItemDefinition gunIntItemDef = weapon.gunIntItemDef; DisplayItemName = Category.CreateEntry<string>(ID + " Display Name", ((BaseItemDefinition)gunIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); DisplayDescription = Category.CreateEntry<string>(ID + " Display Description", ((BaseItemDefinition)gunIntItemDef).Description, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); LegalStatus = Category.CreateEntry<ELegalStatus>(ID + " Legal Status", ((BaseItemDefinition)gunIntItemDef).legalStatus, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); RequiredRank = Category.CreateEntry<FullRank>(ID + " Required Rank", ((StorableItemDefinition)gunIntItemDef).RequiredRank, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); IntegerItemDefinition magIntItemDef = weapon.magIntItemDef; MagDisplayItemName = Category.CreateEntry<string>(ID + " Mag Display Name", ((BaseItemDefinition)magIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagDisplayDescription = Category.CreateEntry<string>(ID + " Mag Display Description", ((BaseItemDefinition)magIntItemDef).Description, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagLegalStatus = Category.CreateEntry<ELegalStatus>(ID + " Mag Legal Status", (ELegalStatus)0, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagRequiredRank = Category.CreateEntry<FullRank>(ID + " Mag Required Rank", ((StorableItemDefinition)magIntItemDef).RequiredRank, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); PurchasePrice = Category.CreateEntry<float>(ID + " Price", ((StorableItemDefinition)gunIntItemDef).BasePurchasePrice, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ItemName = Category.CreateEntry<string>(ID + " Name", ((BaseItemDefinition)gunIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); Available = Category.CreateEntry<bool>(ID + " Shop Availability", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AvailableReason = Category.CreateEntry<string>(ID + " Non-Available Reason", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagPurchasePrice = Category.CreateEntry<float>(ID + " Magazine Price", ((StorableItemDefinition)magIntItemDef).BasePurchasePrice, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagItemName = Category.CreateEntry<string>(ID + " Magazine Name", ((BaseItemDefinition)magIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagAvailable = Category.CreateEntry<bool>(ID + " Magazine Shop Availability", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagAvailableReason = Category.CreateEntry<string>(ID + " Magazine Non-Available Reason", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null); } public void HandleSettingsUpdate() { MelonLogger.Msg("Updating More Guns Settings"); Category.LoadFromFile(true); this.OnSettingChanged?.Invoke(); } } internal static class MagazineSocketFix { private static readonly HashSet<int> LeftoverAkMagazineMeshIds = new HashSet<int>(); public static void CacheLeftoverMeshesFromGun(GameObject root) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } Transform[] array = Il2CppArrayBase<Transform>.op_Implicit(root.GetComponentsInChildren<Transform>(true)); foreach (Transform val in array) { if ((Object)(object)val == (Object)null || ((Object)val).name != "Magazine" || ((Component)val).gameObject.activeSelf) { continue; } Vector3 localScale = val.localScale; Vector3 localPosition = val.localPosition; if ((!(localScale.x >= 5f) || !(localScale.x < 40f)) && !(Mathf.Abs(localPosition.z) > 1f) && !(Mathf.Abs(localPosition.x) > 1.5f) && (!(localScale.x > 0f) || !(localScale.x < 0.05f))) { continue; } MeshFilter[] array2 = Il2CppArrayBase<MeshFilter>.op_Implicit(((Component)val).GetComponentsInChildren<MeshFilter>(true)); foreach (MeshFilter obj in array2) { Mesh val2 = ((obj != null) ? obj.sharedMesh : null); if ((Object)(object)val2 != (Object)null) { LeftoverAkMagazineMeshIds.Add(((Object)val2).GetInstanceID()); } } } } [Obsolete("Use CacheLeftoverMeshesFromGun on smg/sniper/rpg instead.")] public static void CacheAkMagazineMeshes(GameObject akRoot) { } public static void FixGunHierarchy(GameObject root) { if ((Object)(object)root == (Object)null) { return; } string text = ((Object)root).name ?? ""; if (IsAkRootName(text)) { return; } bool flag = text.IndexOf("rpg", StringComparison.OrdinalIgnoreCase) >= 0; Transform[] array; try { array = Il2CppArrayBase<Transform>.op_Implicit(root.GetComponentsInChildren<Transform>(true)); } catch { return; } foreach (Transform val in array) { if ((Object)(object)val == (Object)null) { continue; } if (((Object)val).name == "MagazineMesh") { try { Object.Destroy((Object)(object)((Component)val).gameObject); } catch { } } else { if (((Object)val).name != "Magazine") { continue; } if (flag) { if (!IsRpgAkLeftover(val)) { continue; } } else if (!IsLegacyAkMagazine(val)) { continue; } try { Object.Destroy((Object)(object)((Component)val).gameObject); } catch { ((Component)val).gameObject.SetActive(false); DisableRenderers(val); } } } StripReloadClips(root); } private static bool IsAkRootName(string rootName) { return rootName.IndexOf("ak47", StringComparison.OrdinalIgnoreCase) >= 0 || rootName.Equals("AK47", StringComparison.OrdinalIgnoreCase) || rootName.Equals("K47", StringComparison.OrdinalIgnoreCase) || rootName.IndexOf("AK47_", StringComparison.OrdinalIgnoreCase) >= 0; } private static bool IsRpgAkLeftover(Transform magazine) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (((Component)magazine).gameObject.activeSelf) { return false; } Vector3 localScale = magazine.localScale; if (localScale.x >= 40f) { return false; } if (localScale.x > 0f && localScale.x < 0.05f) { return true; } MeshFilter[] array = Il2CppArrayBase<MeshFilter>.op_Implicit(((Component)magazine).GetComponentsInChildren<MeshFilter>(true)); foreach (MeshFilter obj in array) { Mesh val = ((obj != null) ? obj.sharedMesh : null); if (!((Object)(object)val == (Object)null)) { if (LeftoverAkMagazineMeshIds.Contains(((Object)val).GetInstanceID())) { return true; } string text = ((Object)val).name ?? ""; if (text.IndexOf("AK", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } return false; } private static bool IsLegacyAkMagazine(Transform magazine) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) Vector3 localScale = magazine.localScale; Vector3 localPosition = magazine.localPosition; if ((localScale.x >= 5f && localScale.x < 40f) || (localScale.y >= 5f && localScale.y < 40f) || (localScale.z >= 5f && localScale.z < 40f) || Mathf.Abs(localPosition.z) > 1f || Mathf.Abs(localPosition.x) > 1.5f) { return true; } if (((Component)magazine).gameObject.activeSelf) { return false; } MeshFilter[] array = Il2CppArrayBase<MeshFilter>.op_Implicit(((Component)magazine).GetComponentsInChildren<MeshFilter>(true)); foreach (MeshFilter obj in array) { Mesh val = ((obj != null) ? obj.sharedMesh : null); if (!((Object)(object)val == (Object)null)) { if (LeftoverAkMagazineMeshIds.Contains(((Object)val).GetInstanceID())) { return true; } string text = ((Object)val).name ?? ""; if (text.IndexOf("AK", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } if (localScale.x > 0f && localScale.x < 0.05f) { foreach (MeshFilter obj2 in array) { if ((Object)(object)((obj2 != null) ? obj2.sharedMesh : null) != (Object)null) { return true; } } } return false; } private static void DisableRenderers(Transform root) { Renderer[] array = Il2CppArrayBase<Renderer>.op_Implicit(((Component)root).GetComponentsInChildren<Renderer>(true)); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null) { array[i].enabled = false; } } } private static void StripReloadClips(GameObject root) { try { Animation[] array = Il2CppArrayBase<Animation>.op_Implicit(root.GetComponentsInChildren<Animation>(true)); foreach (Animation val in array) { if (!((Object)(object)val == (Object)null)) { TryRemoveClip(val, "Other Reload"); TryRemoveClip(val, "OtherReload"); TryRemoveClip(val, "AK47 Reload"); TryRemoveClip(val, "AK47Reload"); } } } catch (Exception ex) { MelonLogger.Warning("StripReloadClips: " + ex.Message); } } private static void TryRemoveClip(Animation anim, string clipName) { try { AnimationClip clip = anim.GetClip(clipName); if ((Object)(object)clip != (Object)null) { anim.RemoveClip(clip); } } catch { } } } internal static class ManualReload { public static bool TryReload(Equippable_RangedWeapon weapon, WeaponBase source = null, bool useGunReloadAnim = true) { if ((Object)(object)weapon == (Object)null) { return false; } if (source == null) { source = GunSettings.ResolveWeaponBase(weapon); } try { try { if (weapon.IsReloading) { GameAccess.Set(weapon, "IsReloading", false); } } catch { } IntegerItemInstance val = ResolveGunAmmo(weapon); if (val == null) { MelonLogger.Warning("ManualReload: no IntegerItemInstance on equipped weapon."); return false; } int num = Mathf.Max(1, weapon.MagazineSize); if (source != null && source.config != null) { num = Mathf.Max(num, source.config.MagazineSize.Value); } if (val.Value >= num) { return true; } string text = ResolveMagazineId(weapon, source); if (string.IsNullOrEmpty(text)) { MelonLogger.Warning("ManualReload: magazine ID is missing."); return false; } if (!TryFindMagazine(text, out var slot, out var magAmmo)) { return false; } int value = magAmmo.Value; if (value <= 0) { return false; } int take = Mathf.Min(num - val.Value, value); float seconds = 2.5f; try { if (weapon.ReloadStartTime > 0.2f) { seconds = weapon.ReloadStartTime; } } catch { } MelonCoroutines.Start(ReloadRoutine(weapon, source, val, slot, magAmmo, take, num, seconds, useGunReloadAnim)); return true; } catch (Exception value2) { MelonLogger.Error($"ManualReload failed: {value2}"); return false; } } private static IEnumerator ReloadRoutine(Equippable_RangedWeapon weapon, WeaponBase source, IntegerItemInstance gunAmmo, ItemSlot magSlot, IntegerItemInstance magAmmo, int take, int capacity, float seconds, bool useGunReloadAnim) { try { GameAccess.Set(weapon, "IsReloading", true); } catch { } PlayReloadFeedback(weapon, source, useGunReloadAnim); float wait = Mathf.Clamp(seconds, 0.5f, 5f); bool isAk = source != null && string.Equals(source.ID, "ak47", StringComparison.OrdinalIgnoreCase); if (useGunReloadAnim && !isAk) { yield return AnimateSeatedMagazine(weapon, wait); } else { yield return (object)new WaitForSeconds(wait); } if ((Object)(object)weapon == (Object)null || gunAmmo == null || magAmmo == null) { try { if ((Object)(object)weapon != (Object)null) { GameAccess.Set(weapon, "IsReloading", false); } yield break; } catch { yield break; } } try { int newAmmo = Mathf.Min(capacity, gunAmmo.Value + take); int actuallyTook = newAmmo - gunAmmo.Value; if (actuallyTook <= 0) { try { GameAccess.Set(weapon, "IsReloading", false); yield break; } catch { yield break; } } gunAmmo.SetValue(newAmmo); try { gunAmmo.Value = newAmmo; } catch { } int left = magAmmo.Value - actuallyTook; bool emptiedMag = false; if (left <= 0) { emptiedMag = true; magAmmo.SetValue(0); try { magAmmo.Value = 0; } catch { } try { ((BaseItemInstance)magSlot.ItemInstance).ChangeQuantity(-1); } catch { try { magSlot.ChangeQuantity(-1, false); } catch (Exception ex) { Exception ex2 = ex; MelonLogger.Warning("ManualReload: could not remove empty mag: " + ex2.Message); } } } else { magAmmo.SetValue(left); try { magAmmo.Value = left; } catch { } } if (emptiedMag) { SpawnTrashSafe(weapon, source); } if (weapon.MustBeCocked && weapon.AutoCockAfterReload) { try { GameAccess.Set(weapon, "IsCocked", true); } catch { } try { GameAccess.Set(weapon, "IsCocking", false); } catch { } } GunSettings settings = ((Component)weapon).GetComponent<GunSettings>(); if ((Object)(object)settings != (Object)null && settings.SyncMagazineToAmmo) { WeaponBehavior.SyncMagazineVisualToAmmo(weapon); } } catch (Exception ex) { Exception ex3 = ex; MelonLogger.Error($"ManualReload apply failed: {ex3}"); } finally { try { GameAccess.Set(weapon, "IsReloading", false); } catch { } } } private static void PlayReloadFeedback(Equippable_RangedWeapon weapon, WeaponBase source, bool useGunReloadAnim) { if (useGunReloadAnim) { if (source != null && string.Equals(source.ID, "ak47", StringComparison.OrdinalIgnoreCase)) { try { if (weapon.onReloadStart != null) { weapon.onReloadStart.Invoke(); } } catch (Exception) { PlayGunReloadClip(weapon); PlayReloadSound(weapon); } } else { try { MagazineSocketFix.FixGunHierarchy(((Component)weapon).gameObject); } catch { } StopGunAnimation(weapon); PlayReloadSound(weapon); } } else { PlayReloadSound(weapon); } string text = null; try { text = weapon.ReloadStartAnimTrigger; } catch { } if (string.IsNullOrEmpty(text)) { text = "MagazineReload"; } try { ViewmodelAvatar instance = Singleton<ViewmodelAvatar>.Instance; if ((Object)(object)((instance != null) ? instance.Animator : null) != (Object)null) { instance.Animator.SetTrigger(text); } } catch { } try { Player local = Player.Local; if ((Object)(object)local != (Object)null) { local.SetAnimationTrigger(text); try { local.SendAnimationTrigger(text); return; } catch { return; } } } catch { } } private static void PlayReloadSound(Equippable_RangedWeapon weapon) { try { Transform val = FindDeep(((Component)weapon).transform, "Reload Sound"); if ((Object)(object)val != (Object)null) { AudioSourceController component = ((Component)val).GetComponent<AudioSourceController>(); if ((Object)(object)component != (Object)null) { component.Play(); } } } catch { } } private static void StopGunAnimation(Equippable_RangedWeapon weapon) { try { Animation[] array = Il2CppArrayBase<Animation>.op_Implicit(((Component)weapon).GetComponentsInChildren<Animation>(true)); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && array[i].isPlaying) { array[i].Stop(); } } } catch { } } private static IEnumerator AnimateSeatedMagazine(Equippable_RangedWeapon weapon, float seconds) { Transform mag = null; Vector3 homePos = Vector3.zero; Quaternion homeRot = Quaternion.identity; Vector3 homeScale = Vector3.one; try { MagazineSocketFix.FixGunHierarchy(((Component)weapon).gameObject); mag = FindSeatedMagazine(weapon); if ((Object)(object)mag != (Object)null) { homePos = mag.localPosition; homeRot = mag.localRotation; homeScale = mag.localScale; } } catch (Exception) { } if ((Object)(object)mag == (Object)null) { yield return (object)new WaitForSeconds(seconds); yield break; } float drop = Mathf.Clamp(0.22f + homeScale.y * 0.5f, 0.15f, 0.45f); Vector3 ejected = homePos + new Vector3(0f, 0f - drop, 0f); float outTime = seconds * 0.32f; float holdTime = seconds * 0.2f; float naturalIn = Mathf.Max(0.2f, seconds - outTime - holdTime); float inTime = Mathf.Max(0.12f, naturalIn * 0.5f); float padAfter = Mathf.Max(0f, naturalIn - inTime); float t = 0f; while (t < outTime && (Object)(object)mag != (Object)null) { t += Time.deltaTime; float u = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(t / outTime)); mag.localPosition = Vector3.Lerp(homePos, ejected, u); yield return null; } if ((Object)(object)mag != (Object)null) { mag.localPosition = ejected; ((Component)mag).gameObject.SetActive(false); } yield return (object)new WaitForSeconds(holdTime); if ((Object)(object)mag != (Object)null) { mag.localPosition = ejected; mag.localScale = homeScale; mag.localRotation = homeRot; ((Component)mag).gameObject.SetActive(true); } t = 0f; while (t < inTime && (Object)(object)mag != (Object)null) { t += Time.deltaTime; float u2 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(t / inTime)); mag.localPosition = Vector3.Lerp(ejected, homePos, u2); yield return null; } if ((Object)(object)mag != (Object)null) { mag.localPosition = homePos; mag.localRotation = homeRot; mag.localScale = homeScale; ((Component)mag).gameObject.SetActive(true); } if (padAfter > 0.01f) { yield return (object)new WaitForSeconds(padAfter); } } private static Transform FindSeatedMagazine(Equippable_RangedWeapon weapon) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)weapon == (Object)null) { return null; } Transform result = null; float num = float.MaxValue; Transform[] array = Il2CppArrayBase<Transform>.op_Implicit(((Component)weapon).GetComponentsInChildren<Transform>(true)); foreach (Transform val in array) { if ((Object)(object)val == (Object)null || ((Object)val).name != "Magazine") { continue; } Vector3 localScale = val.localScale; Vector3 localPosition = val.localPosition; if (!(localScale.x >= 5f) && !(localScale.y >= 5f) && !(localScale.z >= 5f) && !(Mathf.Abs(localPosition.z) > 1f) && !(Mathf.Abs(localPosition.x) > 1.5f) && (!((Object)(object)((Component)val).GetComponent<MeshFilter>() == (Object)null) || !((Object)(object)((Component)val).GetComponentInChildren<MeshFilter>(true) == (Object)null))) { float num2 = ((Vector3)(ref localPosition)).sqrMagnitude + (((Component)val).gameObject.activeSelf ? 0f : 100f); if (num2 < num) { num = num2; result = val; } } } return result; } private static void PlayGunReloadClip(Equippable_RangedWeapon weapon) { try { string[] array = new string[3] { "AK47 Reload", "Other Reload", "Reload" }; Animation[] array2 = Il2CppArrayBase<Animation>.op_Implicit(((Component)weapon).GetComponentsInChildren<Animation>(true)); foreach (Animation val in array2) { if ((Object)(object)val == (Object)null) { continue; } for (int j = 0; j < array.Length; j++) { if (!((Object)(object)val.GetClip(array[j]) == (Object)null)) { val.Play(array[j]); return; } } } PlayAnimation componentInChildren = ((Component)weapon).GetComponentInChildren<PlayAnimation>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.Play("AK47 Reload"); } } catch { } } private static string ResolveMagazineId(Equippable_RangedWeapon weapon, WeaponBase source) { try { if ((Object)(object)weapon.Magazine != (Object)null && !string.IsNullOrEmpty(((BaseItemDefinition)weapon.Magazine).ID)) { return ((BaseItemDefinition)weapon.Magazine).ID; } } catch { } if ((Object)(object)source?.magIntItemDef != (Object)null && !string.IsNullOrEmpty(((BaseItemDefinition)source.magIntItemDef).ID)) { return ((BaseItemDefinition)source.magIntItemDef).ID; } if (source != null && !string.IsNullOrEmpty(source.ID)) { return source.ID + "mag"; } return null; } private static void SpawnTrashSafe(Equippable_RangedWeapon weapon, WeaponBase source) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) try { PlayerCamera instance = PlayerSingleton<PlayerCamera>.Instance; if ((Object)(object)instance == (Object)null) { return; } TrashItem val = ResolveTrashPrefab(weapon, source); if ((Object)(object)val == (Object)null) { return; } if (source != null) { TrashRegistryPatch.EnsureTrashId(source); } if ((string.IsNullOrEmpty(val.ID) || string.Equals(val.ID, "trashid", StringComparison.OrdinalIgnoreCase)) && source != null && !string.IsNullOrEmpty(source.ID)) { val.ID = source.ID + "mag"; } Vector3 val2 = ((Component)instance).transform.position - ((Component)instance).transform.up * 0.4f; try { Object.Instantiate<GameObject>(((Component)val).gameObject, val2, Random.rotation); } catch { } } catch { } } private static TrashItem ResolveTrashPrefab(Equippable_RangedWeapon weapon, WeaponBase source) { try { TrashItem reloadTrash = weapon.ReloadTrash; if ((Object)(object)reloadTrash != (Object)null) { return reloadTrash; } } catch { } return source?.gunMagTrashItem; } private static Transform FindDeep(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } if (((Object)root).name == name) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindDeep(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static IntegerItemInstance ResolveGunAmmo(Equippable_RangedWeapon weapon) { return GameAccess.Get<IntegerItemInstance>(weapon, "weaponItem"); } private static bool TryFindMagazine(string magId, out ItemSlot slot, out IntegerItemInstance magAmmo) { slot = null; magAmmo = null; PlayerInventory instance = PlayerSingleton<PlayerInventory>.Instance; if ((Object)(object)instance == (Object)null) { return false; } if (instance.hotbarSlots != null) { for (int i = 0; i < instance.hotbarSlots.Count; i++) { if (MatchSlot((ItemSlot)(object)instance.hotbarSlots[i], magId, out slot, out magAmmo)) { return true; } } } try { List<ItemSlot> allInventorySlots = instance.GetAllInventorySlots(); if (allInventorySlots != null) { for (int j = 0; j < allInventorySlots.Count; j++) { if (MatchSlot(allInventorySlots[j], magId, out slot, out magAmmo)) { return true; } } } } catch { } return false; } private static bool MatchSlot(ItemSlot s, string magId, out ItemSlot slot, out IntegerItemInstance magAmmo) { slot = null; magAmmo = null; ItemInstance val = ((s != null) ? s.ItemInstance : null); if ((Object)(object)((val != null) ? val.Definition : null) == (Object)null) { return false; } if (!string.Equals(((BaseItemDefinition)val.Definition).ID, magId, StringComparison.OrdinalIgnoreCase)) { return false; } IntegerItemInstance val2 = ((Object)(object)val).As<IntegerItemInstance>(); if (val2 == null) { return false; } slot = s; magAmmo = val2; return true; } } internal static class MaterialFixup { private static Shader _lit; private static Shader _unlit; private static Shader _particles; private static bool _resolved; public static void FixHierarchy(GameObject root) { if ((Object)(object)root == (Object)null) { return; } EnsureShaders(); if ((Object)(object)_lit == (Object)null && (Object)(object)_unlit == (Object)null && (Object)(object)_particles == (Object)null) { return; } Renderer[] array; try { array = Il2CppArrayBase<Renderer>.op_Implicit(root.GetComponentsInChildren<Renderer>(true)); } catch (Exception ex) { MelonLogger.Warning("MaterialFixup: could not read renderers on " + ((Object)root).name + ": " + ex.Message); return; } if (array == null) { return; } Renderer[] array2 = array; foreach (Renderer val in array2) { if ((Object)(object)val == (Object)null) { continue; } try { Material[] array3 = Il2CppArrayBase<Material>.op_Implicit((Il2CppArrayBase<Material>)(object)val.sharedMaterials); if (array3 == null || array3.Length == 0) { continue; } bool flag = false; foreach (Material val2 in array3) { if ((Object)(object)val2 == (Object)null) { continue; } try { if (FixMaterial(val2)) { flag = true; } } catch (Exception ex2) { MelonLogger.Warning("MaterialFixup: skipped '" + ((Object)val2).name + "': " + ex2.Message); } } if (flag) { val.sharedMaterials = Il2CppReferenceArray<Material>.op_Implicit(array3); } } catch (Exception ex3) { MelonLogger.Warning("MaterialFixup: renderer '" + ((Object)val).name + "' failed: " + ex3.Message); } } } private static void EnsureShaders() { if (!_resolved) { _resolved = true; _lit = Shader.Find("Universal Render Pipeline/Lit"); _unlit = Shader.Find("Universal Render Pipeline/Unlit"); _particles = Shader.Find("Universal Render Pipeline/Particles/Unlit") ?? Shader.Find("Universal Render Pipeline/Particles/Simple Lit"); if ((Object)(object)_lit == (Object)null && (Object)(object)_unlit == (Object)null) { MelonLogger.Warning("Could not find URP Lit/Unlit shaders; gun materials may stay transparent."); } } } private static bool FixMaterial(Material mat) { //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) string text = ((Object)mat).name ?? string.Empty; string text2 = text.ToLowerInvariant(); bool flag = text2.Contains("particle") || text2.Contains("muzzle") || text2.Contains("flash") || text2.Contains("smoke") || text2.Contains("tracer") || text2.Contains("ray"); bool flag2 = text2.Contains("glass"); Shader val = (flag ? (_particles ?? _unlit ?? _lit) : ((!flag2) ? (_lit ?? _unlit) : (_lit ?? _unlit))); if ((Object)(object)val == (Object)null) { return false; } Texture val2 = GetTexture(mat, "_BaseMap") ?? GetTexture(mat, "_MainTex"); Color val3 = Color.white; try { if (mat.HasProperty("_BaseColor")) { val3 = mat.GetColor("_BaseColor"); } else if (mat.HasProperty("_Color")) { val3 = mat.GetColor("_Color"); } } catch { val3 = Color.white; } mat.shader = val; if ((Object)(object)val2 != (Object)null) { if (mat.HasProperty("_BaseMap")) { mat.SetTexture("_BaseMap", val2); } if (mat.HasProperty("_MainTex")) { mat.SetTexture("_MainTex", val2); } } if (mat.HasProperty("_BaseColor")) { mat.SetColor("_BaseColor", val3); } if (mat.HasProperty("_Color")) { mat.SetColor("_Color", val3); } if (flag) { SetSurfaceTransparent(mat); if (mat.HasProperty("_Blend")) { mat.SetFloat("_Blend", 0f); } if (mat.HasProperty("_Cutoff")) { mat.SetFloat("_Cutoff", 0.1f); } } else if (!flag2) { SetSurfaceOpaque(mat); } return true; } private static Texture GetTexture(Material mat, string property) { try { return mat.HasProperty(property) ? mat.GetTexture(property) : null; } catch { return null; } } private static void SetSurfaceOpaque(Material mat) { if (mat.HasProperty("_Surface")) { mat.SetFloat("_Surface", 0f); } mat.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); mat.SetOverrideTag("RenderType", "Opaque"); mat.renderQueue = 2000; if (mat.HasProperty("_ZWrite")) { mat.SetFloat("_ZWrite", 1f); } } private static void SetSurfaceTransparent(Material mat) { if (mat.HasProperty("_Surface")) { mat.SetFloat("_Surface", 1f); } mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); mat.SetOverrideTag("RenderType", "Transparent"); mat.renderQueue = 3000; if (mat.HasProperty("_ZWrite")) { mat.SetFloat("_ZWrite", 0f); } } } public class MoreGunsMod : MelonMod { public static Transform map; public static Transform container; public static Transform midcanal; public static Transform stanNPC; public static Il2CppAssetBundle assetBundle; public static readonly Dictionary<string, Object> Resources = new Dictionary<string, Object>(StringComparer.OrdinalIgnoreCase); public static bool isInitialized; public static Harmony harmony; private static bool harmonyApplied; private static bool bootStarted; private static readonly Dictionary<string, RuntimeAnimatorController> animatorControllers = new Dictionary<string, RuntimeAnimatorController>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase); private static bool animatorControllersLoaded; private static bool spritesLoaded; public override void OnInitializeMelon() { MelonLogger.Msg("Thank you for using More Guns! Discord: discord.gg/XB7ruKtJje"); assetBundle = Il2CppAssetBundleManager.LoadFromMemory(Il2CppStructArray<byte>.op_Implicit(Assets.VoidanesGuns)); if (assetBundle == null) { MelonLogger.Error("The asset bundle could not be loaded. MoreGuns will not run."); isInitialized = false; return; } isInitialized = true; Config.Initialize(); new AK47(); new MiniGun(); new Sniper(); new SMG(); new RPG(); } public override void OnApplicationQuit() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (!isInitialized) { return; } if (sceneName != "Main") { ItemRegistryPatch.Reset(); bootStarted = false; return; } if (!bootStarted) { bootStarted = true; MelonCoroutines.Start(BootAfterSaveSettles()); } try { NetworkController.SyncConfiguration(); } catch (Exception value) { MelonLogger.Error($"Failed to sync MoreGuns configuration: {value}"); } MelonCoroutines.Start(ItemRegistryPatch.RegisterWhenReady()); Reticle.Initialize(); GameObject val = GameObject.Find("UI/HUD"); if ((Object)(object)val == (Object)null) { MelonLogger.Warning("Could not find 'UI/HUD'; the reload message and windup indicator will be unavailable."); return; } ReloadMessage.Initialize(val.transform); WindupIndicator.Initialize(val.transform); } private static IEnumerator BootAfterSaveSettles() { float waited = 0f; while ((Object)(object)GameObject.Find("Player_Local") == (Object)null && waited < 90f) { yield return (object)new WaitForSeconds(0.25f); waited += 0.25f; } yield return (object)new WaitForSecondsRealtime(2.5f); if (!harmonyApplied) { harmony = new Harmony("com.voidane.moregunsil2cpp"); MelonLogger.Msg("Applying MoreGuns Harmony patches after save settle (batched)..."); yield return SafeHarmony.ApplyBatched(harmony, typeof(ArmsDealerInterfacePatch), typeof(CameraJoltPatch), typeof(DialoguePatch), typeof(Equippalbe_RangedWeaponPatch), typeof(ItemRegistryPatch), typeof(RangedWeaponEquipPatch), typeof(ReloadingPatch), typeof(SetEquippablePatch), typeof(TrashRegistryPatch)); harmonyApplied = true; } while (!SafeHarmony.PatchesLive) { yield return null; } MelonCoroutines.Start(ArmsDealerInterfacePatch.FindAndInjectAfterHarmony()); } public static void RegisterAsset(string path, Object asset) { Resources[path] = asset; } public static Object TryGetAsset(string path) { if (path != null && Resources.TryGetValue(path, out var value)) { return value; } return null; } public static Sprite GetSprite(string name) { if (string.IsNullOrEmpty(name) || assetBundle == null) { return null; } EnsureSpritesLoaded(); Sprite value; return sprites.TryGetValue(name, out value) ? value : null; } private static void EnsureSpritesLoaded() { if (spritesLoaded || assetBundle == null) { return; } spritesLoaded = true; try { string[] array = new string[20] { "assets/sprite/ak47__icon.asset", "assets/sprite/ak47__magazine_icon.asset", "assets/sprite/minigun__icon.asset", "assets/sprite/minigun__magazine_icon.asset", "assets/sprite/sniper__icon.asset", "assets/sprite/sniper__magazine_icon.asset", "assets/sprite/smg__icon.asset", "assets/sprite/smg__magazine_icon.asset", "assets/sprite/rpg__icon.asset", "assets/sprite/rpg__magazine_icon.asset", "AK47__Icon", "AK47__Magazine_Icon", "MiniGun__Icon", "MiniGun__Magazine_Icon", "Sniper__Icon", "Sniper__Magazine_Icon", "SMG__Icon", "SMG__Magazine_Icon", "RPG__Icon", "RPG__Magazine_Icon" }; string[] array2 = array; foreach (string text in array2) { TryCacheSprite(assetBundle.LoadAsset(text)); } Object[] array3 = Il2CppArrayBase<Object>.op_Implicit((Il2CppArrayBase<Object>)(object)assetBundle.LoadAllAssets()); if (array3 != null) { Object[] array4 = array3; foreach (Object asset in array4) { TryCacheSprite(asset); } } string[] array5 = new string[10] { "Sniper__Icon", "Sniper__Magazine_Icon", "SMG__Icon", "SMG__Magazine_Icon", "RPG__Icon", "RPG__Magazine_Icon", "AK47__Icon", "AK47__Magazine_Icon", "MiniGun__Icon", "MiniGun__Magazine_Icon" }; string[] array6 = array5; foreach (string text2 in array6) { if (!sprites.ContainsKey(text2)) { TryCacheSpriteFromTexture(assetBundle.LoadAsset(text2), text2); } } } catch (Exception ex) { MelonLogger.Warning("Failed to preload sprites: " + ex.Message); } } private static void TryCacheSprite(Object asset) { if (!(asset == (Object)null)) { Sprite val = ((Object)(object)asset).As<Sprite>(); if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name)) { sprites[((Object)val).name] = val; } } } private static void TryCacheSpriteFromTexture(Object asset, string name) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!(asset == (Object)null) && !string.IsNullOrEmpty(name)) { Texture2D val = ((Object)(object)asset).As<Texture2D>(); if (!((Object)(object)val == (Object)null)) { Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)val2).name = name; sprites[name] = val2; } } } public static RuntimeAnimatorController GetAnimatorController(string name) { if (string.IsNullOrEmpty(name) || assetBundle == null) { return null; } EnsureAnimatorControllersLoaded(); RuntimeAnimatorController value; return animatorControllers.TryGetValue(name, out value) ? value : null; } private static void EnsureAnimatorControllersLoaded() { if (animatorControllersLoaded || assetBundle == null) { return; } animatorControllersLoaded = true; try { TryLoadAnimatorByPath("assets/animatorcontroller/handgunanimator.controller", "HandgunAnimator"); TryLoadAnimatorByPath("assets/animatorcontroller/minigunanimator.controller", "MiniGunAnimator"); TryLoadAnimatorByPath("HandgunAnimator", "HandgunAnimator"); TryLoadAnimatorByPath("MiniGunAnimator", "MiniGunAnimator"); if (animatorControllers.Count != 0) { return; } Object[] array = Il2CppArrayBase<Object>.op_Implicit((Il2CppArrayBase<Object>)(object)assetBundle.LoadAllAssets()); if (array == null) { return; } Object[] array2 = array; foreach (Object val in array2) { if (!(val == (Object)null)) { RuntimeAnimatorController val2 = ((Object)(object)val).As<RuntimeAnimatorController>(); if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(((Object)val2).name)) { animatorControllers[((Object)val2).name] = val2; } } } } catch (Exception ex) { MelonLogger.Warning("Failed to preload animator controllers: " + ex.Message); } } private static void TryLoadAnimatorByPath(string path, string cacheName) { if (animatorControllers.ContainsKey(cacheName)) { return; } Object val = assetBundle.LoadAsset(path); if (val == (Object)null) { return; } RuntimeAnimatorController val2 = ((Object)(object)val).As<RuntimeAnimatorController>(); if (!((Object)(object)val2 == (Object)null)) { animatorControllers[cacheName] = val2; if (!string.IsNullOrEmpty(((Object)val2).name)) { animatorControllers[((Object)val2).name] = val2; } } } public static void StopProcess() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } isInitialized = false; } } internal static class MuzzleAligner { public static Vector3 LastMuzzleWorldPos { get; private set; } public static bool HasLastMuzzle { get; private set; } public static bool RedirectPlayerTrail { get; set; } public static void Align(GameObject root, string bodyToken) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) HasLastMuzzle = false; RedirectPlayerTrail = false; if ((Object)(object)root == (Object)null) { return; } try { Transform val = FindDeep(root.transform, "MuzzlePoint"); if ((Object)(object)val == (Object)null) { return; } Transform val2 = FindBarrelAnchor(root.transform); if ((Object)(object)val2 != (Object)null) { val.position = val2.position; val.rotation = val2.rotation; } else { Renderer val3 = FindBodyRenderer(root, bodyToken); if ((Object)(object)val3 == (Object)null) { return; } Vector3 position = FindBarrelTip(val3, val); val.position = position; } Vector3 position2 = val.position; SnapNearNamed(root.transform, "Muzzle Flash", position2, 0.5f); SnapNearNamed(root.transform, "Flash Orange", position2, 0.5f); SnapNearNamed(root.transform, "Flash Red", position2, 0.5f); SnapNearNamed(root.transform, "Point Light", position2, 0.5f); SnapNearNamed(root.transform, "Point Light (1)", position2, 0.5f); LastMuzzleWorldPos = position2; HasLastMuzzle = true; } catch (Exception ex) { MelonLogger.Warning("MuzzleAligner failed: " + ex.Message); } } public static void RememberFrom(Equippable_RangedWeapon weapon) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) HasLastMuzzle = false; RedirectPlayerTrail = false; if ((Object)(object)weapon == (Object)null) { return; } try { Transform val = FindDeep(((Component)weapon).transform, "MuzzlePoint"); if (!((Object)(object)val == (Object)null)) { LastMuzzleWorldPos = val.position; HasLastMuzzle = true; RedirectPlayerTrail = true; } } catch { } } private static Transform FindBarrelAnchor(Transform root) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[5] { "Muzzle Flash", "Flash Orange", "Flash Red", "Point Light", "Point Light (1)" }; Transform result = null; float num = 0.25f; for (int i = 0; i < array.Length; i++) { Transform val = FindDeep(root, array[i]); if (!((Object)(object)val == (Object)null)) { Vector3 localPosition = val.localPosition; float magnitude = ((Vector3)(ref localPosition)).magnitude; if (magnitude > num) { num = magnitude; result = val; } } } return result; } private static Renderer FindBodyRenderer(GameObject root, string bodyToken) { //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) Renderer[] array = Il2CppArrayBase<Renderer>.op_Implicit(root.GetComponentsInChildren<Renderer>(true)); Renderer result = null; float num = -1f; foreach (Renderer val in array) { if ((Object)(object)val == (Object)null || !val.enabled || !((Component)val).gameObject.activeInHierarchy) { continue; } string text = ((Object)((Component)val).gameObject).name ?? ""; if (text.IndexOf("Magazine", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Flash", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Bullet", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Smoke", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Shell", StringComparison.OrdinalIgnoreCase) >= 0) { continue; } Vector3 lossyScale = ((Component)val).transform.lossyScale; if (!(lossyScale.x >= 5f) && !(lossyScale.y >= 5f) && !(lossyScale.z >= 5f)) { bool flag = !string.IsNullOrEmpty(bodyToken) && text.IndexOf(bodyToken, StringComparison.OrdinalIgnoreCase) >= 0; Bounds bounds = val.bounds; Vector3 size = ((Bounds)(ref bounds)).size; float sqrMagnitude = ((Vector3)(ref size)).sqrMagnitude; float num2 = sqrMagnitude + (flag ? 1000f : 0f); if (num2 > num) { num = num2; result = val; } } } return result; } private static Vector3 FindBarrelTip(Renderer body, Transform muzzle) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = body.bounds; Vector3 val = muzzle.forward; if (((Vector3)(ref val)).sqrMagnitude < 0.01f && (Object)(object)muzzle.parent != (Object)null) { val = -muzzle.parent.right; } ((Vector3)(ref val)).Normalize(); Vector3 val2 = ((Bounds)(ref bounds)).center; float num = float.MinValue; Vector3 center = ((Bounds)(ref bounds)).center; Vector3 extents = ((Bounds)(ref bounds)).extents; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Vector3 val3 = center + new Vector3(extents.x * (float)i, extents.y * (float)j, extents.z * (float)k); float num2 = Vector3.Dot(val3 - center, val); if (num2 > num) { num = num2; val2 = val3; } } } } return val2 + val * 0.02f; } private static void SnapNearNamed(Transform root, string name, Vector3 worldPos, float maxDist) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) Transform val = FindDeep(root, name); if (!((Object)(object)val == (Object)null) && (Vector3.Distance(val.position, worldPos) <= maxDist || name.StartsWith("Flash", StringComparison.Ordinal) || name.StartsWith("Muzzle", StringComparison.Ordinal) || name.StartsWith("Point Light", StringComparison.Ordinal))) { val.position = worldPos; } } private static Transform FindDeep(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } if (((Object)root).name == name) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindDeep(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } } internal static class SafeHarmony { public static bool PatchesLive { get; private set; } public static void Apply(Harmony harmony, params Type[] patchClasses) { foreach (Type patchClass in patchClasses) { TryPatch(harmony, patchClass); } PatchesLive = true; } public static IEnumerator ApplyBatched(Harmony harmony, params Type[] patchClasses) { PatchesLive = false; int ok = 0; foreach (Type patchClass in patchClasses) { if (TryPatch(harmony, patchClass)) { ok++; } yield return null; yield return null; yield return null; } MelonLogger.Msg($"MoreGuns Harmony applied {ok}/{patchClasses.Length} patch classes (batched)."); yield return (object)new WaitForSecondsRealtime(2f); PatchesLive = true; MelonLogger.Msg("MoreGuns Harmony patch gate open."); } private static bool TryPatch(Harmony harmony, Type patchClass) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) try { new PatchClassProcessor(harmony, patchClass).Patch(); return true; } catch (Exception ex) { MelonLogger.Error("Harmony class " + patchClass.Name + " failed to bind: " + ex.Message); return false; } } } public static class Tools { public static class LegalStatus { public static ELegalStatus StringConvertToELegalStatus(string eLegalStatus) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (Enum.TryParse<ELegalStatus>(eLegalStatus, out ELegalStatus result)) { return result; } throw new ArgumentException("Could not convert '" + eLegalStatus + "' to an ELegalStatus."); } } public static class Rank { public static FullRank Parse(string rank, string tier) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (!Enum.TryParse<ERank>(rank?.Trim(), out ERank result)) { throw new ArgumentException("Could not convert '" + rank + "' to an ERank."); } if (!int.TryParse(tier?.Trim(), out var result2)) { throw new ArgumentException("Could not convert '" + tier + "' to a rank tier."); } return new FullRank { Rank = result, Tier = result2 }; } } public static bool Alive(Object obj) { if (obj == null) { return false; } try { if (((Il2CppObjectBase)obj).WasCollected || ((Il2CppObjectBase)obj).Pointer == IntPtr.Zero) { return false; } } catch { return false; } try { return obj != (Object)null; } catch { return false; } } public static bool IsLocalPlayerHeld(Equippable_RangedWeapon weapon) { if (!Alive((Object)(object)weapon)) { return false; } try { Player local = Player.Local; if ((Object)(object)local == (Object)null) { return false; } Transform transform = ((Component)local).transform; Transform val = ((Component)weapon).transform; for (int i = 0; i < 12; i++) { if (!Alive((Object)(object)val)) { break; } if ((Object)(object)val == (Object)(object)transform) { return true; } val = val.parent; } } catch { return false; } return false; } } } namespace MoreGuns.Sync { public static class NetworkController { private const string IDENTIFICATION_PREFIX = "moreguns_settings"; private const int FIELD_COUNT = 25; private static readonly string version = typeof(MoreGunsMod).Assembly.GetName().Version.ToString(); public static StringBuilder payload = new StringBuilder(); public static bool forceHost = false; public static bool forceClient = false; public static bool IsSynced { get; private set; } = false; public static void SyncConfiguration() { Lobby instance = Singleton<Lobby>.Instance; bool flag = instance != null && instance.IsHost; Lobby instance2 = Singleton<Lobby>.Instance; int num; if (instance2 != null && !instance2.IsHost) { Lobby instance3 = Singleton<Lobby>.Instance; num = ((instance3 != null && instance3.IsInLobby) ? 1 : 0); } else { num = 0; } bool flag2 = (byte)num != 0; payload = new StringBuilder(); StringBuilder stringBuilder = payload; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder); handler.AppendFormatted("moreguns_settings"); handler.AppendLiteral("_"); handler.AppendFormatted(version); handler.AppendLiteral("|"); stringBuilder.Append(ref handler); if (flag || forceHost) { MelonCoroutines.Start(SyncHostToLobbyPayload()); return; } if (flag2 || forceClient) { MelonCoroutines.Start(WaitOnLobbyPayload()); return; } foreach (WeaponBase allWeapon in WeaponBase.allWeapons) { allWeapon.ApplySettingsFromConfig(); } MelonCoroutines.Start(SyncHostToLobbyPayload()); } public static IEnumerator WaitOnLobbyPayload() { string data; while (true) { data = SteamMatchmaking.GetLobbyData(Compat.LobbySteamId(), "MoreGunsConfig"); if (!string.IsNullOrEmpty(data) && data.IndexOf('@') >= 0) { break; } yield return (object)new WaitForSeconds(1f); } HostToClientConfigurationSync(data); } private static IEnumerator SyncHostToLobbyPayload() { foreach (WeaponBase weapon in WeaponBase.allWeapons) { if (weapon != null && !((Object)(object)weapon.gunRangedWeapon == (Object)null) && weapon.config != null) { weapon.ApplySettingsFromConfig(); while (!weapon.IsConfigurationFinished) { yield return (object)new WaitForSeconds(0.05f); } StringBuilder stringBuilder = payload; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(25, 25, stringBuilder); handler.AppendLiteral("@"); handler.AppendFormatted(weapon.ID); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.gunRangedWeapon.Damage); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.gunRangedWeapon.ImpactForce); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.gunRangedWeapon.MinAimFOVReduction); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.gunRangedWeapon.MaxAimFOVReduction); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.gunRangedWeapon.AccuracyChangeDuration); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.gunRangedWeapon.MagazineSize); handler.AppendLiteral(":"); handler.AppendFormatted(((BaseItemDefinition)weapon.gunIntItemDef).Name); handler.AppendLiteral(":"); handler.AppendFormatted(((BaseItemDefinition)weapon.gunIntItemDef).Description); handler.AppendLiteral(":"); handler.AppendFormatted<ELegalStatus>(((BaseItemDefinition)weapon.gunIntItemDef).legalStatus); handler.AppendLiteral(":"); handler.AppendFormatted<ERank>(((StorableItemDefinition)weapon.gunIntItemDef).RequiredRank.Rank); handler.AppendLiteral(":"); handler.AppendFormatted(((StorableItemDefinition)weapon.gunIntItemDef).RequiredRank.Tier); handler.AppendLiteral(":"); handler.AppendFormatted(((BaseItemDefinition)weapon.magIntItemDef).Name); handler.AppendLiteral(":"); handler.AppendFormatted(((BaseItemDefinition)weapon.magIntItemDef).Description); handler.AppendLiteral(":"); handler.AppendFormatted<ELegalStatus>(((BaseItemDefinition)weapon.magIntItemDef).legalStatus); handler.AppendLiteral(":"); handler.AppendFormatted<ERank>(((StorableItemDefinition)weapon.magIntItemDef).RequiredRank.Rank); handler.AppendLiteral(":"); handler.AppendFormatted(((StorableItemDefinition)weapon.magIntItemDef).RequiredRank.Tier); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.rangedGun.Name); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.rangedGun.Price); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.rangedGun.IsAvailable); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.rangedGun.NotAvailableReason); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.ammoGun.Name); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.ammoGun.Price); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.ammoGun.IsAvailable); handler.AppendLiteral(":"); handler.AppendFormatted(weapon.ammoGun.NotAvailableReason); stringBuilder.Append(ref handler); } } try { if ((Object)(object)Singleton<Lobby>.Instance != (Object)null && (Singleton<Lobby>.Instance.IsHost || forceHost)) { Singleton<Lobby>.Instance.SetLobbyData("MoreGunsConfig", payload.ToString()); } } catch (Exception ex) { MelonLogger.Warning("Failed to publish MoreGuns lobby config: " + ex.Message); } } private static void HostToClientConfigurationSync(string data) { //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) string[] array = (from item in data.Split('|') where !string.IsNullOrEmpty(item) select item).ToArray(); if (!IsModValidForSync(array[0])) { MelonLogger.Warning("MoreGuns is outdated with the host or server."); MelonLogger.Warning($"Your Version: {"moreguns_settings"}_{version}, Host Version: {array[0]}"); } string[] array2 = (from item in array[1].Split('@') where !string.IsNullOrEmpty(item) select item).ToArray(); string[] array3 = array2; foreach (string text in array3) { string[] array4 = text.Split(':'); if (array4.Length < 25) { MelonLogger.Warning($"Skipping malformed weapon entry in host payload (got {array4.Length} fields, expected {25})."); } else { if (!WeaponBase.weaponsByName.TryGetValue(array4[0], out var value) || !float.TryParse(array4[1], out var result) || !float.TryParse(array4[2], out var result2) || !float.TryParse(array4[3], out var result3) || !float.TryParse(array4[4], out var result4) || !float.TryParse(array4[5], out var result5) || !int.TryParse(array4[6], out var result6)) { continue; } string name = array4[7]; string description = array4[8]; ELegalStatus legalStatus = Tools.LegalStatus.StringConvertToELegalStatus(array4[9]); FullRank requiredRank = Tools.Rank.Parse(array4[10], array4[11]); string name2 = array4[12]; string description2 = array4[13]; ELegalStatus legalStatus2 = Tools.LegalStatus.StringConvertToELegalStatus(array4[14]); FullRank requiredRank2 = Tools.Rank.Parse(array4[15], array4[16]); string name3 = array4[17]; if (float.TryParse(array4[18], out var result7) && bool.TryParse(array4[19], out var result8)) { string notAvailableReason = array4[20]; string name4 = array4[21]; if (float.TryParse(array4[22], out var result9) && bool.TryParse(array4[23], out var result10)) { string notAvailableReason2 = array4[24]; value.gunRangedWeapon.Damage = result; value.gunRangedWeapon.ImpactForce = result2; value.gunRangedWeapon.MinAimFOVReduction = result3; value.gunRangedWeapon.MaxAimFOVReduction = result4; value.gunRangedWeapon.AccuracyChangeDuration = result5; value.gunRangedWeapon.MagazineSize = result6; ((BaseItemDefinition)value.gunIntItemDef).Name = name; ((BaseItemDefinition)value.gunIntItemDef).Description = description; ((BaseItemDefinition)value.gunIntItemDef).legalStatus = legalStatus; ((StorableItemDefinition)value.gunIntItemDef).RequiredRank = requiredRank; ((BaseItemDefinition)value.magIntItemDef).Name = name2; ((BaseItemDefinition)value.magIntItemDef).Description = description2; ((BaseItemDefinition)value.magIntItemDef).legalStatus = legalStatus2; ((StorableItemDefinition)value.magIntItemDef).RequiredRank = requiredRank2; ((BaseItemDefinition)value.gunIntItemDef).Name = name3; ((StorableItemDefinition)value.gunIntItemDef).BasePurchasePrice = result7; value.rangedGun.IsAvailable = result8; value.rangedGun.NotAvailableReason = notAvailableReason; ((BaseItemDefinition)value.magIntItemDef).Name = name4; ((StorableItemDefinition)value.magIntItemDef).BasePurchasePrice = result9; value.ammoGun.IsAvailable = result10; value.ammoGun.NotAvailableReason = notAvailableReason2; value.RefreshShopListings(); } } } } } private static bool IsModValidForSync(string pIdentify) { string text = "moreguns_settings_" + version; return pIdentify == text; } } } namespace MoreGuns.Patches { [HarmonyPatch] public static class ArmsDealerInterfacePatch { private const string SHOP_OBJECT_NAME = "ArmsDealerInterface"; private const float READY_POLL_INTERVAL = 0.25f; private const float READY_TIMEOUT = 60f; private static readonly List<ShopInterface> knownShops = new List<ShopInterface>(); [HarmonyPatch(typeof(ShopInterface), "Awake")] [HarmonyPostfix] public static void PostfixAwake(ShopInterface __instance) { if (!((Object)(object)__instance == (Object)null) && !(((Object)((Component)__instance).gameObject).name != "ArmsDealerInterface")) { if (!knownShops.Contains(__instance)) { knownShops.Add(__instance); } MelonCoroutines.Start(InjectWhenReady(__instance)); } } public static IEnumerator FindAndInjectAfterHarmony() { while (!SafeHarmony.PatchesLive) { yield return null; } float waited = 0f; while (waited < 60f) { GameObject go = GameObject.Find("ArmsDealerInterface"); if ((Object)(object)go != (Object)null) { ShopInterface shop = go.GetComponent<ShopInterface>(); if ((Object)(object)shop != (Object)null) { if (!knownShops.Contains(shop)) { knownShops.Add(shop); } while (!WeaponBase.AllWeaponsLoaded && waited < 60f) { waited += 0.25f; yield return (object)new WaitForSeconds(0.25f); } yield return null; Inject(shop); yield break; } } waited += 0.25f; yield return (object)new WaitForSeconds(0.25f); } MelonLogger.Warning($"Could not find {"ArmsDealerInterface"} after {60f}s."); } private static IEnumerator InjectWhenReady(ShopInterface shop) { while (!SafeHarmony.PatchesLive) { yield return null; } float waited = 0f; while (!WeaponBase.AllWeaponsLoaded) { if ((Object)(object)shop == (Object)null) { yield break; } if (waited >= 60f) { MelonLogger.Warning($"Weapons were still loading after {60f}s; adding whatever is ready to {"ArmsDealerInterface"}."); break; } waited += 0.25f; yield return (object)new WaitForSeconds(0.25f); } yield return null; yield return null; if (!((Object)(object)shop == (Object)null)) { Inject(shop); } } public static void InjectAllKnownShops() { knownShops.RemoveAll((ShopInterface shop) => (Object)(object)shop == (Object)null); foreach (ShopInterface knownShop in knownShops) { try { Inject(knownShop); } catch (Exception ex) { MelonLogger.Warning("Shop inject failed: " + ex.Message); } } } private static void Inject(ShopInterface shop) { if ((Object)(object)shop == (Object)null || !SafeHarmony.PatchesLive) { return; } if (shop.Listings == null) { MelonLogger.Warning("ArmsDealerInterface has no listing collection; skipping MoreGuns listings."); return; } if (!knownShops.Contains(shop)) { knownShops.Add(shop); } ShopListing template = FindTemplate(shop); int num = 0; foreach (WeaponBase allWeapon in WeaponBase.allWeapons) { try { if (AddListing(shop, (StorableItemDefinition)(object)allWeapon.gunIntItemDef, template)) { num++; } if (AddListing(shop, (StorableItemDefinition)(object)allWeapon.magIntItemDef, template)) { num++; } } catch (Exception ex) { MelonLogger.Warning("Failed to add shop listing for " + allWeapon?.ID + ": " + ex.Message); } } if (num > 0) { GameAccess.RefreshShownItems(shop); MelonLogger.Msg($"Added {num} MoreGuns listing(s) to {"ArmsDealerInterface"}."); } } private static ShopListing FindTemplate(ShopInterface shop) { if (shop.Listings == null) { return null; } Enumerator<ShopListing> enumerator = shop.Listings.GetEnumerator(); while (enumerator.MoveNext()) { ShopListing current = enumerator.Current; if (current != null && (Object)(object)current.Item != (Object)null) { return current; } } return null; } private static bool AddListing(ShopInterface shop, StorableItemDefinition item, ShopListing template) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || string.IsNullOrEmpty(((BaseItemDefinition)item).ID)) { return false; } if (shop.GetListing(((BaseItemDefinition)item).ID) != null) { return false; } ShopListing val = new ShopListing(); val.name = ((BaseItemDefinition)item).Name; val.Item = item; val.CanBeDelivered = template != null && template.CanBeDelivered; val.LimitedStock = template != null && template.LimitedStock; val.DefaultStock = ((template != null) ? template.DefaultStock : 0); val.RestockRate = (ERestockRate)((template == null) ? 2 : ((int)template.RestockRate)); val.ConditionalVisibility = false; if (item.ShopCategories == null) { item.ShopCategories = new List<CategoryInstance>(); } shop.Listings.Add(val); val.Initialize(shop); if (val.LimitedStock) { val.SetStock(val.DefaultStock, false); } GameAccess.CreateListingUI(shop, val); return true; } public static void RefreshListings() { knownShops.RemoveAll((ShopInterface shop) => (Object)(object)shop == (Object)null); foreach (ShopInterface knownShop in knownShops) { GameAccess.RefreshShownItems(knownShop); } } } [HarmonyPatch] public static class CameraJoltPatch { public static string ID = ""; [HarmonyPatch(typeof(PlayerCamera), "JoltCamera")] [HarmonyPrefix] public static bool Prefix(PlayerCamera __instance) { if (WeaponBase.weaponsByName.TryGetValue(ID, out var value)) { return value.settings == null || value.settings.cameraJolt; } return true; } [HarmonyPatch(typeof(Equippable_RangedWeapon), "Fire")] [HarmonyPrefix] public static void Prefix(Equippable_RangedWeapon __instance) { try { ID = ((Object)((Component)__instance).gameObject).name.Replace("_Equippable(Clone)", "").ToLower(); } catch { ID = ""; } } } [HarmonyPatch] public static class DialoguePatch { public static bool isInititalized; private static DialogueChoiceData reloadDialogue; [HarmonyPatch(typeof(DialogueHandler), "ShowNode")] [HarmonyPrefix] public static void Prefix(DialogueHandler __instance, DialogueNodeData node) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if (!isInititalized) { reloadDialogue = new DialogueChoiceData { Guid = "voiddial-stan-guns-opti-reloadmultgn", ChoiceText = "Reload Guns", ChoiceLabel = "Reload Guns" }; isInititalized = true; } List<DialogueChoiceData> list = ((IEnumerable<DialogueChoiceData>)node.choices).ToList(); if (node.Guid == "72f05df5-cfd4-4be3-9239-fc31bb44f49b" && ((Object)__instance.NPC).name == "Stan") { foreach (DialogueChoiceData item in list) { if (item.ChoiceLabel == "Reload Guns") { return; } } list.Add(reloadDialogue); node.choices = Il2CppReferenceArray<DialogueChoiceData>.op_Implicit(list.ToArray()); } else { list.RemoveAll((DialogueChoiceData choice) => choice.ChoiceLabel == "Reload Guns"); node.choices = Il2CppReferenceArray<DialogueChoiceData>.op_Implicit(list.ToArray()); } } [HarmonyPatch(typeof(DialogueController_ArmsDealer), "ChoiceCallback")] [HarmonyPrefix] public static void Prefix(DialogueController_ArmsDealer __instance, string choiceLabel) { if (choiceLabel == "Reload Guns") { StanDialogue.StartSpecialGunReloads(); } } } [HarmonyPatch] public static class Equippalbe_RangedWeaponPatch { private static float timeSinceLastAutoFire; private static float timeSinceWindingUp; [HarmonyPatch(typeof(Equippable_RangedWeapon), "UpdateInput")] [HarmonyPostfix] public static void Postfix(Equippable_RangedWeapon __instance) { if (Time.timeScale == 0f) { return; } try { if ((Object)(object)Singleton<PauseMenu>.Instance != (Object)null && Singleton<PauseMenu>.Instance.IsPaused) { return; } } catch { return; } GunSettings gunSettings = GunSettings.EnsureOn(__instance); if ((Object)(object)gunSettings == (Object)null) { return; } bool button = GameInput.GetButton((ButtonCode)0); bool button2 = GameInput.GetButton((ButtonCode)1); if (gunSettings.RequireWindup) { PlayAnimation val = null; AudioSourceController val2 = null; try { val = ((Component)((Component)__instance).transform.GetChild(0)).GetComponent<PlayAnimation>(); val2 = ((Component)((Component)val).transform.Find("Windup Sound")).GetComponent<AudioSourceController>(); } catch { return; } if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return; } timeSinceWindingUp += Time.deltaTime; WindupIndicator.SetValueByTime(timeSinceWindingUp, gunSettings.WindupTime); if (button2) { if (timeSinceWindingUp <= gunSettings.WindupTime || !button) { val.Play("MiniGun Windup"); if (!val2.IsPlaying) { val2.Play(); } } } else { WindupIndicator.SetValue(0); timeSinceWindingUp = 0f; val2.Stop(); } } if (gunSettings.IsAutomatic && (!gunSettings.RequireWindup || timeSinceWindingUp > gunSettings.WindupTime)) { timeSinceLastAutoFire += Time.deltaTime; if (button) { if (timeSinceLastAutoFire >= __instance.FireCooldown) { timeSinceLastAutoFire = 0f; if (GameAccess.CanFire(__instance, checkAmmo: false) && __instance.Ammo > 0) { if (!__instance.MustBeCocked || __instance.IsCocked) { __instance.Fire(); } else { GameAccess.Cock(__instance); } } } } else { timeSinceLastAutoFire = __instance.FireCooldown; } } if (gunSettings.SyncMagazineToAmmo && !__instance.IsReloading) { WeaponBehavior.SyncMagazineVisualToAmmo(__instance); } } [HarmonyPatch(typeof(Equippable_RangedWeapon), "Fire")] [HarmonyPrefix] public static bool Prefix(Equippable_RangedWeapon __instance) { GunSettings gunSettings = GunSettings.EnsureOn(__instance); if ((Object)(object)gunSettings == (Object)null) { return true; } if (gunSettings.RequireWindup && timeSinceWindingUp < gunSettings.WindupTime) { return false; } MuzzleAligner.RememberFrom(__instance); return true; } [HarmonyPatch(typeof(FXManager), "CreateBulletTrail")] [HarmonyPrefix] public static void PrefixBulletTrail(ref Vector3 start) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (MuzzleAligner.RedirectPlayerTrail && MuzzleAligner.HasLastMuzzle) { start = MuzzleAligner.LastMuzzleWorldPos; MuzzleAligner.RedirectPlayerTrail = false; } } [HarmonyPatch(typeof(Equippable_RangedWeapon), "Fire")] [HarmonyPostfix] public static void PostfixFire(Equippable_RangedWeapon __instance) { MuzzleAligner.RedirectPlayerTrail = false; GunSettings gunSettings = GunSettings.EnsureOn(__instance); if (!((Object)(object)gunSettings == (Object)null)) { if (gunSettings.ExplosiveRounds) { WeaponBehavior.CreateExplosionAtAimPoint(__instance); } if (gunSettings.SyncMagazineToAmmo) { WeaponBehavior.SyncMagazineVisualToAmmo(__instance); } } } [HarmonyPatch(typeof(Equippable_RangedWeapon), "Reload")] [HarmonyPostfix] public static void PostfixReload(Equippable_RangedWeapon __instance) { GunSettings gunSettings = GunSettings.EnsureOn(__instance); if ((Object)(object)gunSettings != (Object)null && gunSettings.SyncMagazineToAmmo) { WeaponBehavior.SyncMagazineVisualToAmmo(__instance); } } } [HarmonyPatch] public static class ItemRegistryPatch { private static bool isRegistering; private static bool Prepare() { return TargetMethod() != null; } private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Registry), "_GetItem", new Type[2] { typeof(string), typeof(bool) }, (Type[])null); } public static void Prefix(Registry __instance, string ID) { if (!isRegistering && !((Object)(object)__instance == (Object)null) && IsOurId(ID)) { RegisterInto(__instance); } } public static void Reset() { isRegistering = false; } public static IEnumerator RegisterWhenReady() { float waited = 0f; while ((!WeaponBase.AllWeaponsLoaded || WeaponBase.allWeapons.Count == 0) && !(waited >= 60f)) { waited += 0.25f; yield return (object)new WaitForSeconds(0.25f); } RegisterWeapons(); } public static void RegisterWeapons() { Registry registry = null; try { registry = Singleton<Registry>.Instance; } catch { } RegisterInto(registry); } private static bool IsOurId(string id) { if (string.IsNullOrEmpty(id) || WeaponBase.weaponsByName.Count == 0) { return false; } if (WeaponBase.weaponsByName.ContainsKey(id)) { return true; } if (id.Length > 3 && id.EndsWith("mag", StringComparison.OrdinalIgnoreCase)) { string key = id.Substring(0, id.Length - 3); if (WeaponBase.weaponsByName.ContainsKey(key)) { return true; } } foreach (string key2 in WeaponBase.weaponsByName.Keys) { if (string.Equals(key2, id, StringComparison.OrdinalIgnoreCase)) { return true; } if (string.Equals(key2 + "mag", id, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static void RegisterInto(Registry registry) { if ((Object)(object)registry == (Object)null || isRegistering || WeaponBase.allWeapons.Count == 0) { return; } isRegistering = true; try { foreach (WeaponBase allWeapon in WeaponBase.allWeapons) { if (!((Object)(object)allWeapon?.gunIntItemDef == (Object)null) && !string.IsNullOrEmpty(allWeapon.ID)) { ((BaseItemDefinition)allWeapon.gunIntItemDef).ID = allWeapon.ID; if ((Object)(object)allWeapon.magIntItemDef != (Object)null) { ((BaseItemDefinition)allWeapon.magIntItemDef).ID = allWeapon.ID + "mag"; } bool flag = AddIfMissing(registry, (ItemDefinition)(object)allWeapon.gunIntItemDef); bool flag2 = AddIfMissing(registry, (ItemDefinition)(object)allWeapon.magIntItemDef); if (flag || flag2) { MelonLogger.Msg("Registered " + allWeapon.ID + " item definition and magazine."); } } } } catch (Exception value) { MelonLogger.Error($"Failed to register More Guns items: {value}"); } finally { isRegistering = false; } } private static bool AddIfMissing(Registry registry, ItemDefinition definition) { if ((Object)(object)definition == (Object)null || string.IsNullOrEmpty(((BaseItemDefinition)definition).ID)) { return false; } try { if (Registry.ItemExists(((BaseItemDefinition)definition).ID)) { return false; } } catch { } try { registry.AddToRegistry(definition); } catch { GameAccess.Call(registry, "AddToRegistry", definition); } return true; } } [HarmonyPatch] public static class RangedWeaponEquipPatch { private const string MOVE_SPEED_LABEL = "MoreGuns"; [HarmonyPatch(typeof(Equippable_RangedWeapon), "Equip")] [HarmonyPostfix] public static void PostfixEquip(Equippable_RangedWeapon __instance) { WeaponBase weaponBase = GunSettings.ResolveWeaponBase(__instance); if (weaponBase != null && !string.Equals(weaponBase.ID, "ak47", StringComparison.OrdinalIgnoreCase) && !string.Equals(weaponBase.ID, "minigun", StringComparison.OrdinalIgnoreCase)) { try { MagazineSocketFix.FixGunHierarchy(((Component)__instance).gameObject); } catch { } try { MuzzleAligner.Align(((Component)__instance).gameObject, weaponBase.name ?? weaponBase.ID); } catch { } } GunSettings gunSettings = GunSettings.EnsureOn(__instance); if (!((Object)(object)gunSettings == (Object)null)) { Reticle.SetActive(Config.EnableCrosshairForGuns.Value); if (gunSettings.RequireWindup) { WindupIndicator.Show(shown: true); } SetMoveSpeedMultiplier(gunSettings.SpeedMultiplier); if (gunSettings.SyncMagazineToAmmo) { WeaponBehavior.SyncMagazineVisualToAmmo(__instance); } } } [HarmonyPatch(typeof(Equippable_RangedWeapon), "Unequip")] [HarmonyPostfix] public static void PostfixUnequip(Equippable_RangedWeapon __instance) { Reticle.SetActive(active: false); WindupIndicator.Show(shown: false); ClearMoveSpeedMultiplier(); } private static void SetMoveSpeedMultiplier(float multiplier) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown PlayerMovement instance = PlayerSingleton<PlayerMovement>.Instance; FloatStack val = ((instance != null) ? instance.MoveSpeedMultiplierStack : null); if (val != null) { val.Remove("MoreGuns"); val.Add(new StackEntry("MoreGuns", multiplier, (EStackMode)2, 0)); GameAccess.Recalculate(val); } } private static void ClearMoveSpeedMultiplier() { PlayerMovement instance = PlayerSingleton<PlayerMovement>.Instance; FloatStack val = ((instance != null) ? instance.MoveSpeedMultiplierStack : null); if (val != null) { val.Remove("MoreGuns"); GameAccess.Recalculate(val); } } } [HarmonyPatch] public static class ReloadingPatch { [HarmonyPatch(typeof(Equippable_RangedWeapon), "Reload")] [HarmonyPrefix] public static bool Prefix(Equippable_RangedWeapon __instance) { WeaponBase weaponBase = GunSettings.ResolveWeaponBase(__instance); if (weaponBase == null) { return true; } string a = weaponBase.ID ?? ""; if (string.Equals(a, "minigun", StringComparison.OrdinalIgnoreCase)) { if (Config.AllowMinigunManualReload != null && Config.AllowMinigunManualReload.Value) { ManualReload.TryReload(__instance, weaponBase, useGunReloadAnim: false); return f