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 FishNet.Object; using HarmonyLib; 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 ScheduleOne; using ScheduleOne.Audio; using ScheduleOne.AvatarFramework; using ScheduleOne.AvatarFramework.Equipping; using ScheduleOne.Combat; using ScheduleOne.Core.Items.Framework; using ScheduleOne.DevUtilities; using ScheduleOne.Dialogue; using ScheduleOne.Equipping; using ScheduleOne.FX; using ScheduleOne.ItemFramework; using ScheduleOne.Levelling; using ScheduleOne.Networking; using ScheduleOne.PlayerScripts; using ScheduleOne.Tools; using ScheduleOne.Trash; using ScheduleOne.UI; using ScheduleOne.UI.Shop; using Steamworks; 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("MoreGunsMono")] [assembly: AssemblyConfiguration("Mono")] [assembly: AssemblyFileVersion("1.6.5.0")] [assembly: AssemblyInformationalVersion("1.6.5+a0f53f1260275c51c2e8503266a34bd2e4d56883")] [assembly: AssemblyProduct("MoreGunsMono")] [assembly: AssemblyTitle("MoreGunsMono")] [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(this object obj) where T : class { return obj as 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.Instance != (Object)null) ? Singleton.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 EnableCrosshairForGuns { get; private set; } public static MelonPreferences_Entry AllowMinigunManualReload { get; private set; } public static void Initialize() { Category = MelonPreferences.CreateCategory("MoreGuns-! User Settings"); EnableCrosshairForGuns = Category.CreateEntry("Allow Gun Crosshair", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AllowMinigunManualReload = Category.CreateEntry("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(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(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(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 Damage { get; private set; } public MelonPreferences_Entry ImpactForce { get; private set; } public MelonPreferences_Entry MinAimFOVReduction { get; private set; } public MelonPreferences_Entry MaxAimFOVReduction { get; private set; } public MelonPreferences_Entry AccuracyChangeDuration { get; private set; } public MelonPreferences_Entry MagazineSize { get; private set; } public MelonPreferences_Entry DisplayItemName { get; private set; } public MelonPreferences_Entry DisplayDescription { get; private set; } public MelonPreferences_Entry LegalStatus { get; private set; } public MelonPreferences_Entry RequiredRank { get; private set; } public MelonPreferences_Entry MagDisplayItemName { get; private set; } public MelonPreferences_Entry MagDisplayDescription { get; private set; } public MelonPreferences_Entry MagLegalStatus { get; private set; } public MelonPreferences_Entry MagRequiredRank { get; private set; } public MelonPreferences_Entry PurchasePrice { get; private set; } public MelonPreferences_Entry MagPurchasePrice { get; private set; } public MelonPreferences_Entry ItemName { get; private set; } public MelonPreferences_Entry MagItemName { get; private set; } public MelonPreferences_Entry Available { get; private set; } public MelonPreferences_Entry MagAvailable { get; private set; } public MelonPreferences_Entry AvailableReason { get; private set; } public MelonPreferences_Entry 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(ID + " Damage", gunRangedWeapon.Damage, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ImpactForce = Category.CreateEntry(ID + " Impact Force", gunRangedWeapon.ImpactForce, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MinAimFOVReduction = Category.CreateEntry(ID + " Min Aim FOV Reduction", gunRangedWeapon.MinAimFOVReduction, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MaxAimFOVReduction = Category.CreateEntry(ID + " Max Aim FOV Reduction", gunRangedWeapon.MaxAimFOVReduction, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AccuracyChangeDuration = Category.CreateEntry(ID + " Accuracy Change Duration", gunRangedWeapon.AccuracyChangeDuration, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagazineSize = Category.CreateEntry(ID + " Magazine Size", gunRangedWeapon.MagazineSize, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); IntegerItemDefinition gunIntItemDef = weapon.gunIntItemDef; DisplayItemName = Category.CreateEntry(ID + " Display Name", ((BaseItemDefinition)gunIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); DisplayDescription = Category.CreateEntry(ID + " Display Description", ((BaseItemDefinition)gunIntItemDef).Description, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); LegalStatus = Category.CreateEntry(ID + " Legal Status", ((BaseItemDefinition)gunIntItemDef).legalStatus, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); RequiredRank = Category.CreateEntry(ID + " Required Rank", ((StorableItemDefinition)gunIntItemDef).RequiredRank, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); IntegerItemDefinition magIntItemDef = weapon.magIntItemDef; MagDisplayItemName = Category.CreateEntry(ID + " Mag Display Name", ((BaseItemDefinition)magIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagDisplayDescription = Category.CreateEntry(ID + " Mag Display Description", ((BaseItemDefinition)magIntItemDef).Description, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagLegalStatus = Category.CreateEntry(ID + " Mag Legal Status", (ELegalStatus)0, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagRequiredRank = Category.CreateEntry(ID + " Mag Required Rank", ((StorableItemDefinition)magIntItemDef).RequiredRank, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); PurchasePrice = Category.CreateEntry(ID + " Price", ((StorableItemDefinition)gunIntItemDef).BasePurchasePrice, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ItemName = Category.CreateEntry(ID + " Name", ((BaseItemDefinition)gunIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); Available = Category.CreateEntry(ID + " Shop Availability", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AvailableReason = Category.CreateEntry(ID + " Non-Available Reason", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagPurchasePrice = Category.CreateEntry(ID + " Magazine Price", ((StorableItemDefinition)magIntItemDef).BasePurchasePrice, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagItemName = Category.CreateEntry(ID + " Magazine Name", ((BaseItemDefinition)magIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagAvailable = Category.CreateEntry(ID + " Magazine Shop Availability", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MagAvailableReason = Category.CreateEntry(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 LeftoverAkMagazineMeshIds = new HashSet(); public static void CacheLeftoverMeshesFromGun(GameObject root) { //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_006b: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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) if ((Object)(object)root == (Object)null) { return; } Transform[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { 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[] componentsInChildren2 = ((Component)val).GetComponentsInChildren(true); foreach (MeshFilter obj in componentsInChildren2) { 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[] componentsInChildren; try { componentsInChildren = root.GetComponentsInChildren(true); } catch { return; } foreach (Transform val in componentsInChildren) { 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[] componentsInChildren = ((Component)magazine).GetComponentsInChildren(true); foreach (MeshFilter obj in componentsInChildren) { 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014c: 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[] componentsInChildren = ((Component)magazine).GetComponentsInChildren(true); foreach (MeshFilter obj in componentsInChildren) { 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 componentsInChildren) { if ((Object)(object)((obj2 != null) ? obj2.sharedMesh : null) != (Object)null) { return true; } } } return false; } private static void DisableRenderers(Transform root) { Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { componentsInChildren[i].enabled = false; } } } private static void StripReloadClips(GameObject root) { try { Animation[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Animation val in componentsInChildren) { 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(); 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.Instance; if ((Object)(object)instance?.Animator != (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(); if ((Object)(object)component != (Object)null) { component.Play(); } } } catch { } } private static void StopGunAnimation(Equippable_RangedWeapon weapon) { try { Animation[] componentsInChildren = ((Component)weapon).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && componentsInChildren[i].isPlaying) { componentsInChildren[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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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) if ((Object)(object)weapon == (Object)null) { return null; } Transform result = null; float num = float.MaxValue; Transform[] componentsInChildren = ((Component)weapon).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { 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() == (Object)null) || !((Object)(object)((Component)val).GetComponentInChildren(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[] componentsInChildren = ((Component)weapon).GetComponentsInChildren(true); foreach (Animation val in componentsInChildren) { 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(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_00a2: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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) try { PlayerCamera instance = PlayerSingleton.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(((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(weapon, "weaponItem"); } private static bool TryFindMagazine(string magId, out ItemSlot slot, out IntegerItemInstance magAmmo) { slot = null; magAmmo = null; PlayerInventory instance = PlayerSingleton.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 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 = val.As(); 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[] componentsInChildren; try { componentsInChildren = root.GetComponentsInChildren(true); } catch (Exception ex) { MelonLogger.Warning("MaterialFixup: could not read renderers on " + ((Object)root).name + ": " + ex.Message); return; } if (componentsInChildren == null) { return; } Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if ((Object)(object)val == (Object)null) { continue; } try { Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { continue; } bool flag = false; foreach (Material val2 in sharedMaterials) { 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 = sharedMaterials; } } 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 AssetBundle assetBundle; public static readonly Dictionary Resources = new Dictionary(StringComparer.OrdinalIgnoreCase); public static bool isInitialized; public static Harmony harmony; private static bool harmonyApplied; private static bool bootStarted; private static readonly Dictionary animatorControllers = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary sprites = new Dictionary(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 = AssetBundle.LoadFromMemory(Assets.VoidanesGuns); if ((Object)(object)assetBundle == (Object)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.moregunsmono"); 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) || (Object)(object)assetBundle == (Object)null) { return null; } EnsureSpritesLoaded(); Sprite value; return sprites.TryGetValue(name, out value) ? value : null; } private static void EnsureSpritesLoaded() { if (spritesLoaded || (Object)(object)assetBundle == (Object)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 = 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 = asset.As(); 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 = asset.As(); 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) || (Object)(object)assetBundle == (Object)null) { return null; } EnsureAnimatorControllersLoaded(); RuntimeAnimatorController value; return animatorControllers.TryGetValue(name, out value) ? value : null; } private static void EnsureAnimatorControllersLoaded() { if (animatorControllersLoaded || (Object)(object)assetBundle == (Object)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 = assetBundle.LoadAllAssets(); if (array == null) { return; } Object[] array2 = array; foreach (Object val in array2) { if (!(val == (Object)null)) { RuntimeAnimatorController val2 = val.As(); 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 = val.As(); 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_015f: 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_0168: 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) Renderer[] componentsInChildren = root.GetComponentsInChildren(true); Renderer result = null; float num = -1f; foreach (Renderer val in componentsInChildren) { 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, 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(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 { 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.Instance; bool flag = instance != null && instance.IsHost; Lobby instance2 = Singleton.Instance; int num; if (instance2 != null && !instance2.IsHost) { Lobby instance3 = Singleton.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(((BaseItemDefinition)weapon.gunIntItemDef).legalStatus); handler.AppendLiteral(":"); handler.AppendFormatted(((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(((BaseItemDefinition)weapon.magIntItemDef).legalStatus); handler.AppendLiteral(":"); handler.AppendFormatted(((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.Instance != (Object)null && (Singleton.Instance.IsHost || forceHost)) { Singleton.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_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: 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 knownShops = new List(); [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(); 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; } foreach (ShopListing listing in shop.Listings) { if (listing != null && (Object)(object)listing.Item != (Object)null) { return listing; } } 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_0094: Unknown result type (might be due to invalid IL or missing references) //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?.CanBeDelivered ?? false; val.LimitedStock = template?.LimitedStock ?? false; val.DefaultStock = template?.DefaultStock ?? 0; val.RestockRate = (ERestockRate)((template == null) ? 2 : ((int)template.RestockRate)); val.ConditionalVisibility = false; if (item.ShopCategories == null) { item.ShopCategories = new List(); } 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_001e: 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_0039: 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 list = 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 = list.ToArray(); } else { list.RemoveAll((DialogueChoiceData choice) => choice.ChoiceLabel == "Reload Guns"); node.choices = 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.Instance != (Object)null && Singleton.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(); val2 = ((Component)((Component)val).transform.Find("Windup Sound")).GetComponent(); } 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.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 FloatStack val = PlayerSingleton.Instance?.MoveSpeedMultiplierStack; if (val != null) { val.Remove("MoreGuns"); val.Add(new StackEntry("MoreGuns", multiplier, (EStackMode)2, 0)); GameAccess.Recalculate(val); } } private static void ClearMoveSpeedMultiplier() { FloatStack val = PlayerSingleton.Instance?.MoveSpeedMultiplierStack; 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 false; } ReloadMessage.Show("Take the MiniGun to Stan to reload."); return false; } GunTuning settings = weaponBase.settings; if (settings != null && !settings.canManualyReload) { ReloadMessage.Show(show: true); return false; } GunSettings.EnsureOn(__instance); bool useGunReloadAnim = !string.Equals(a, "rpg", StringComparison.OrdinalIgnoreCase); ManualReload.TryReload(__instance, weaponBase, useGunReloadAnim); return false; } } [HarmonyPatch] public static class SetEquippablePatch { private static int _lastTrailWeaponId; private static float _lastTrailTime; private static Vector3 _lastTrailEnd; private static string _rifleHold; private static string _rifleLowered; private static string _rifleRaised; private static string _rifleRecoil; private static bool _rifleAnimCached; private static bool _rifleTriggerTypeValid; private static ETriggerType _rifleTriggerType; private static string _pistolHold; private static string _pistolLowered; private static string _pistolRaised; private static string _pistolRecoil; private static bool _pistolAnimCached; private static bool _pistolTriggerTypeValid; private static ETriggerType _pistolTriggerType; [HarmonyPatch(typeof(Avatar), "SetEquippable")] [HarmonyPrefix] public static bool Prefix(ref AvatarEquippable __result, string assetPath, Avatar __instance) { if (string.IsNullOrWhiteSpace(assetPath)) { return true; } if (!Tools.Alive((Object)(object)__instance)) { return false; } Object val = Resources.Load(assetPath); if (val != (Object)null) { return true; } try { if ((Object)(object)__instance.CurrentEquippable != (Object)null) { __instance.CurrentEquippable.Unequip(); } } catch { } Object val2 = MoreGunsMod.TryGetAsset(assetPath); if (val2 == (Object)null) { return true; } GameObject val3 = val2.As(); if ((Object)(object)val3 == (Object)null) { return true; } GameObject val4 = Object.Instantiate(val3); if ((Object)(object)val4 == (Object)null) { return true; } AvatarEquippable val5 = ResolveAvatarEquippable(val4); if ((Object)(object)val5 == (Object)null) { MelonLogger.Warning("SetEquippable: no AvatarEquippable on '" + assetPath + "'."); Object.Destroy((Object)(object)val4); return true; } try { val5.AssetPath = assetPath; } catch { GameAccess.Set(val5, "AssetPath", assetPath); } EnsureAvatarWeaponRefs(val5); if (!AvatarReadyForEquip(__instance, val5)) { MelonLogger.Warning("SetEquippable: avatar hand alignment not ready for '" + assetPath + "'."); Object.Destroy((Object)(object)val4); __result = null; return false; } try { GameAccess.SetCurrentEquippable(__instance, val5); val5.Equip(__instance); EnsureAvatarWeaponRefs(val5); MelonCoroutines.Start(ReapplyHoldNextFrame(val5)); __result = val5; } catch (Exception ex) { MelonLogger.Warning("SetEquippable equip failed for '" + assetPath + "': " + ex.Message); try { GameAccess.SetCurrentEquippable(__instance, null); } catch { } try { Object.Destroy((Object)(object)val4); } catch { } __result = null; return false; } return false; } private static IEnumerator ReapplyHoldNextFrame(AvatarEquippable equippable) { yield return null; yield return null; if (!Tools.Alive((Object)(object)equippable)) { yield break; } EnsureAvatarWeaponRefs(equippable); try { string hold = equippable.AnimationTrigger; if (!string.IsNullOrEmpty(hold)) { GameAccess.Call(equippable, "ResetTrigger", hold); GameAccess.Call(equippable, "SetTrigger", hold); } } catch { } } [HarmonyPatch(typeof(AvatarEquippable), "PositionAnimationModel")] [HarmonyPrefix] public static bool PositionAnimationModelPrefix(AvatarEquippable __instance) { if (!Tools.Alive((Object)(object)__instance)) { return false; } EnsureAlignmentPoint(__instance); if (!Tools.Alive((Object)(object)__instance.AlignmentPoint)) { return false; } Avatar val = GameAccess.Get(__instance, "avatar"); if (!Tools.Alive((Object)(object)val) || (Object)(object)val.Animation == (Object)null) { return false; } Transform obj = ResolveHandAlignment(val, __instance); return Tools.Alive((Object)(object)obj); } [HarmonyPatch(typeof(AvatarRangedWeapon), "Shoot", new Type[] { typeof(Vector3) })] [HarmonyPrefix] public static bool ShootPrefix(AvatarRangedWeapon __instance, Vector3 endPoint) { if (!Tools.Alive((Object)(object)__instance)) { return false; } EnsureAvatarWeaponRefs((AvatarEquippable)(object)__instance); if (!Tools.Alive((Object)(object)__instance.FireSound)) { ManualAvatarShoot(__instance); return false; } return true; } [HarmonyPatch(typeof(AvatarRangedWeapon), "Shoot", new Type[] { typeof(Vector3) })] [HarmonyPostfix] public static void ShootPostfix(AvatarRangedWeapon __instance, Vector3 endPoint) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SpawnAvatarBulletTrail(__instance, endPoint); } [HarmonyPatch(typeof(Avatar), "ReceiveEquippableMessage")] [HarmonyPostfix] public static void ReceiveEquippableMessagePostfix(Avatar __instance, string message, object data) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!Tools.Alive((Object)(object)__instance) || !string.Equals(message, "Shoot", StringComparison.Ordinal) || !TryReadVector3(data, out var value)) { return; } AvatarRangedWeapon val = null; try { AvatarEquippable currentEquippable = __instance.CurrentEquippable; val = (AvatarRangedWeapon)(object)((currentEquippable is AvatarRangedWeapon) ? currentEquippable : null); if (!Tools.Alive((Object)(object)val) && Tools.Alive((Object)(object)currentEquippable)) { val = ((Component)currentEquippable).GetComponent(); } } catch { } SpawnAvatarBulletTrail(val, value); } private static void ManualAvatarShoot(AvatarRangedWeapon ranged) { try { ((AvatarWeapon)ranged).Attack(); } catch { try { GameAccess.Call(ranged, "Attack"); } catch { } } try { if (!string.IsNullOrEmpty(ranged.RecoilAnimationTrigger)) { GameAccess.Call(ranged, "ResetTrigger", ranged.RecoilAnimationTrigger); GameAccess.Call(ranged, "SetTrigger", ranged.RecoilAnimationTrigger); } } catch { } try { GameAccess.Set(ranged, "timeSinceLastShot", 0f); } catch { } } private static bool TryReadVector3(object data, out Vector3 value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0024: 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_0030: Unknown result type (might be due to invalid IL or missing references) value = default(Vector3); if (data == null) { return false; } try { if (data is Vector3 val) { value = val; return true; } } catch { } try { value = (Vector3)data; return true; } catch { } return false; } private static void SpawnAvatarBulletTrail(AvatarRangedWeapon ranged, Vector3 endPoint) { //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_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_00ad: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) if (!Tools.Alive((Object)(object)ranged)) { return; } try { Player componentInParent = ((Component)ranged).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && ((NetworkBehaviour)componentInParent).IsOwner) { return; } } catch { } int num; try { num = ((Object)ranged).GetInstanceID(); } catch { num = 0; } float unscaledTime = Time.unscaledTime; if (num != 0 && num == _lastTrailWeaponId && unscaledTime - _lastTrailTime < 0.04f) { Vector3 val = endPoint - _lastTrailEnd; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { return; } } _lastTrailWeaponId = num; _lastTrailTime = unscaledTime; _lastTrailEnd = endPoint; MuzzleAligner.RedirectPlayerTrail = false; Transform val2 = null; try { val2 = ranged.MuzzlePoint; } catch { } if (!Tools.Alive((Object)(object)val2)) { val2 = ((Component)ranged).transform; } Vector3 position = val2.position; Vector3 val3 = endPoint - position; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude < 0.08f) { return; } Vector3 val4 = val3 / magnitude; float num2 = 95f; float num3 = magnitude; try { if (!Singleton.InstanceExists) { return; } FXManager instance = Singleton.Instance; if ((Object)(object)instance == (Object)null) { return; } LayerMask val5 = LayerMask.op_Implicit(-1); try { if (NetworkSingleton.InstanceExists) { val5 = NetworkSingleton.Instance.RangedWeaponLayerMask; } } catch { } instance.CreateBulletTrail(position, val4, num2, num3, val5); } catch { } } internal static void EnsureAvatarWeaponRefs(AvatarEquippable equippable) { EnsureAlignmentPoint(equippable); EnsureRifleHoldAnimations(equippable); AvatarRangedWeapon val = null; try { val = (AvatarRangedWeapon)(object)((equippable is AvatarRangedWeapon) ? equippable : null); } catch { } if (!Tools.Alive((Object)(object)val)) { try { val = ((Component)equippable).GetComponent(); } catch { } } if (Tools.Alive((Object)(object)val)) { EnsureMuzzlePoint(val); EnsureFireSound(val); EnsureRangedAnimationTriggers(val); EnsureUseRanges(val); EnsureSuccessfulHitEvent((AvatarWeapon)(object)val); } } private static void EnsureSuccessfulHitEvent(AvatarWeapon weapon) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown if (!Tools.Alive((Object)(object)weapon)) { return; } try { if (weapon.onSuccessfulHit != null) { return; } } catch { } try { weapon.onSuccessfulHit = new UnityEvent(); } catch { try { GameAccess.Set(weapon, "onSuccessfulHit", (object)new UnityEvent()); } catch { } } } private static void EnsureUseRanges(AvatarRangedWeapon ranged) { if (!Tools.Alive((Object)(object)ranged)) { return; } try { if (((AvatarWeapon)ranged).MaxUseRange < 8f) { ((AvatarWeapon)ranged).MaxUseRange = 18f; } if (((AvatarWeapon)ranged).MinUseRange <= 0.01f || ((AvatarWeapon)ranged).MinUseRange > 5f) { ((AvatarWeapon)ranged).MinUseRange = 1.5f; } } catch { } } private static void EnsureRifleHoldAnimations(AvatarEquippable equippable) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (!Tools.Alive((Object)(object)equippable) || !IsLongGunEquippable(equippable)) { return; } bool flag = IsSmgEquippable(equippable); if (flag) { CachePistolAnimationsFromVanilla(); } else { CacheRifleAnimationsFromVanilla(); } string text = (flag ? _pistolHold : _rifleHold); if (!string.IsNullOrEmpty(text)) { try { equippable.AnimationTrigger = text; } catch { GameAccess.Set(equippable, "AnimationTrigger", text); } } if (!(flag ? _pistolTriggerTypeValid : _rifleTriggerTypeValid)) { return; } ETriggerType val = (flag ? _pistolTriggerType : _rifleTriggerType); try { equippable.TriggerType = val; } catch { GameAccess.Set(equippable, "TriggerType", val); } } private static void EnsureRangedAnimationTriggers(AvatarRangedWeapon ranged) { if (Tools.Alive((Object)(object)ranged) && IsLongGunEquippable((AvatarEquippable)(object)ranged)) { if (IsSmgEquippable((AvatarEquippable)(object)ranged)) { CachePistolAnimationsFromVanilla(); ForceAnim(ranged, "LoweredAnimationTrigger", _pistolLowered); ForceAnim(ranged, "RaisedAnimationTrigger", _pistolRaised); ForceAnim(ranged, "RecoilAnimationTrigger", _pistolRecoil); } else { CacheRifleAnimationsFromVanilla(); ForceAnim(ranged, "LoweredAnimationTrigger", _rifleLowered); ForceAnim(ranged, "RaisedAnimationTrigger", _rifleRaised); ForceAnim(ranged, "RecoilAnimationTrigger", _rifleRecoil); } } } private static bool IsSmgEquippable(AvatarEquippable equippable) { if (!Tools.Alive((Object)(object)equippable)) { return false; } string text = null; try { text = equippable.AssetPath; } catch { text = GameAccess.Get(equippable, "AssetPath"); } if (IsSmgPath(text)) { return true; } try { string pathOrName = (((Object)(object)((Component)equippable).gameObject != (Object)null) ? ((Object)((Component)equippable).gameObject).name : null); if (IsSmgPath(pathOrName)) { return true; } } catch { } return false; } private static bool IsSmgPath(string pathOrName) { if (string.IsNullOrEmpty(pathOrName)) { return false; } string text = pathOrName; int num = Math.Max(pathOrName.LastIndexOf('/'), pathOrName.LastIndexOf('\\')); if (num >= 0 && num + 1 < pathOrName.Length) { text = pathOrName.Substring(num + 1); } return text.IndexOf("smg", StringComparison.OrdinalIgnoreCase) >= 0; } private static bool IsLongGunEquippable(AvatarEquippable equippable) { if (!Tools.Alive((Object)(object)equippable)) { return false; } string text = null; try { text = equippable.AssetPath; } catch { text = GameAccess.Get(equippable, "AssetPath"); } if (IsLongGunPath(text)) { return true; } try { string pathOrName = (((Object)(object)((Component)equippable).gameObject != (Object)null) ? ((Object)((Component)equippable).gameObject).name : null); if (IsLongGunPath(pathOrName)) { return true; } } catch { } try { string animationTrigger = equippable.AnimationTrigger; if (string.IsNullOrEmpty(animationTrigger) || string.Equals(animationTrigger, "RightArm_Hold_ClosedHand", StringComparison.OrdinalIgnoreCase)) { return equippable is AvatarRangedWeapon; } } catch { } return false; } private static bool IsLongGunPath(string pathOrName) { if (string.IsNullOrEmpty(pathOrName)) { return false; } return pathOrName.IndexOf("ak47", StringComparison.OrdinalIgnoreCase) >= 0 || pathOrName.IndexOf("smg", StringComparison.OrdinalIgnoreCase) >= 0 || pathOrName.IndexOf("sniper", StringComparison.OrdinalIgnoreCase) >= 0 || pathOrName.IndexOf("minigun", StringComparison.OrdinalIgnoreCase) >= 0 || pathOrName.IndexOf("rpg", StringComparison.OrdinalIgnoreCase) >= 0; } private static void ForceAnim(AvatarRangedWeapon ranged, string field, string value) { if (string.IsNullOrEmpty(value)) { return; } try { switch (field) { case "LoweredAnimationTrigger": ranged.LoweredAnimationTrigger = value; break; case "RaisedAnimationTrigger": ranged.RaisedAnimationTrigger = value; break; case "RecoilAnimationTrigger": ranged.RecoilAnimationTrigger = value; break; default: GameAccess.Set(ranged, field, value); break; } } catch { GameAccess.Set(ranged, field, value); } } private static void CacheRifleAnimationsFromVanilla() { if (!_rifleAnimCached) { _rifleAnimCached = true; TryCacheAvatarAnims("Avatar/Equippables/PumpShotgun", out _rifleHold, out _rifleLowered, out _rifleRaised, out _rifleRecoil, out _rifleTriggerType, out _rifleTriggerTypeValid); if (string.IsNullOrEmpty(_rifleHold)) { _rifleHold = "Shotgun_Grip_Lowered"; } if (string.IsNullOrEmpty(_rifleLowered)) { _rifleLowered = "Shotgun_Grip_Lowered"; } if (string.IsNullOrEmpty(_rifleRaised)) { _rifleRaised = "Shotgun_Grip_Raised"; } if (string.IsNullOrEmpty(_rifleRecoil)) { _rifleRecoil = "Shotgun_Recoil"; } } } private static void CachePistolAnimationsFromVanilla() { if (!_pistolAnimCached) { _pistolAnimCached = true; TryCacheAvatarAnims("Avatar/Equippables/M1911", out _pistolHold, out _pistolLowered, out _pistolRaised, out _pistolRecoil, out _pistolTriggerType, out _pistolTriggerTypeValid); if (string.IsNullOrEmpty(_pistolHold)) { _pistolHold = "BothHands_Grip_Lowered"; } if (string.IsNullOrEmpty(_pistolLowered)) { _pistolLowered = "BothHands_Grip_Lowered"; } if (string.IsNullOrEmpty(_pistolRaised)) { _pistolRaised = "BothHands_Grip_Raised"; } if (string.IsNullOrEmpty(_pistolRecoil)) { _pistolRecoil = "BothHands_Grip_Recoil"; } } } private static void TryCacheAvatarAnims(string resourcePath, out string hold, out string lowered, out string raised, out string recoil, out ETriggerType triggerType, out bool triggerTypeValid) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected I4, but got Unknown hold = null; lowered = null; raised = null; recoil = null; triggerType = (ETriggerType)0; triggerTypeValid = false; try { Object val = Resources.Load(resourcePath); GameObject val2 = ((val != (Object)null) ? val.As() : null); AvatarRangedWeapon val3 = null; if ((Object)(object)val2 != (Object)null) { val3 = val2.GetComponent() ?? val2.GetComponentInChildren(true); } if (!Tools.Alive((Object)(object)val3)) { return; } try { hold = ((AvatarEquippable)val3).AnimationTrigger; } catch { } try { lowered = val3.LoweredAnimationTrigger; } catch { } try { raised = val3.RaisedAnimationTrigger; } catch { } try { recoil = val3.RecoilAnimationTrigger; } catch { } try { triggerType = (ETriggerType)(int)((AvatarEquippable)val3).TriggerType; triggerTypeValid = true; } catch { } } catch { } } internal static void EnsureAlignmentPoint(AvatarEquippable equippable) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!Tools.Alive((Object)(object)equippable)) { return; } try { if (Tools.Alive((Object)(object)equippable.AlignmentPoint)) { return; } } catch { } Transform val = FindNamedTransform(((Component)equippable).transform, "AlignmentPoint"); if ((Object)(object)val == (Object)null) { GameObject val2 = new GameObject("AlignmentPoint"); val2.transform.SetParent(((Component)equippable).transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val = val2.transform; } try { equippable.AlignmentPoint = val; } catch { GameAccess.Set(equippable, "AlignmentPoint", val); } } private static void EnsureMuzzlePoint(AvatarRangedWeapon ranged) { try { if (Tools.Alive((Object)(object)ranged.MuzzlePoint)) { return; } } catch { } Transform val = FindNamedTransform(((Component)ranged).transform, "MuzzlePoint"); if ((Object)(object)val == (Object)null) { val = ((Component)ranged).transform; } try { ranged.MuzzlePoint = val; } catch { GameAccess.Set(ranged, "MuzzlePoint", val); } } private static void EnsureFireSound(AvatarRangedWeapon ranged) { try { if (Tools.Alive((Object)(object)ranged.FireSound)) { return; } } catch { } AudioSourceController val = null; Transform val2 = FindNamedTransform(((Component)ranged).transform, "Fire Sound") ?? FindNamedTransform(((Component)ranged).transform, "FireSound"); if ((Object)(object)val2 != (Object)null) { try { val = ((Component)val2).GetComponent() ?? ((Component)val2).GetComponentInChildren(true); } catch { } } if (!Tools.Alive((Object)(object)val)) { try { val = ((Component)ranged).GetComponentInChildren(true); } catch { } } if (!Tools.Alive((Object)(object)val)) { return; } try { ranged.FireSound = val; } catch { GameAccess.Set(ranged, "FireSound", val); } } private static bool AvatarReadyForEquip(Avatar avatar, AvatarEquippable equippable) { if (!Tools.Alive((Object)(object)avatar) || (Object)(object)avatar.Animation == (Object)null) { return false; } Transform obj = ResolveHandContainer(avatar, equippable); Transform obj2 = ResolveHandAlignment(avatar, equippable); return Tools.Alive((Object)(object)obj) && Tools.Alive((Object)(object)obj2); } private static Transform ResolveHandContainer(Avatar avatar, AvatarEquippable equippable) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 try { if ((int)equippable.Hand == 0) { return avatar.Animation.LeftHandContainer; } return avatar.Animation.RightHandContainer; } catch { return null; } } private static Transform ResolveHandAlignment(Avatar avatar, AvatarEquippable equippable) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 try { if ((int)equippable.Hand == 0) { return avatar.Animation.LeftHandAlignmentPoint; } return avatar.Animation.RightHandAlignmentPoint; } catch { return null; } } private static Transform FindNamedTransform(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } Transform val = root.Find(name); if ((Object)(object)val != (Object)null) { return val; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name == name) { return val2; } } return null; } private static AvatarEquippable ResolveAvatarEquippable(GameObject root) { if ((Object)(object)root == (Object)null) { return null; } AvatarEquippable component = root.GetComponent(); if ((Object)(object)component != (Object)null) { return component; } try { AvatarRangedWeapon val = root.GetComponent() ?? root.GetComponentInChildren(true); if ((Object)(object)val != (Object)null) { return (AvatarEquippable)(object)val; } } catch { } return root.GetComponentInChildren(true); } } public static class StanNPCPatch { } [HarmonyPatch] public static class TrashRegistryPatch { private const float READY_POLL_INTERVAL = 0.25f; private const float READY_TIMEOUT = 60f; [HarmonyPatch(typeof(TrashManager), "Start")] [HarmonyPostfix] public static void Postfix(TrashManager __instance) { MelonCoroutines.Start(RegisterWhenReady(__instance)); } public static void EnsureTrashId(WeaponBase weapon) { if (!((Object)(object)weapon?.gunMagTrashItem == (Object)null) && !string.IsNullOrEmpty(weapon.ID)) { string iD = weapon.ID + "mag"; string iD2 = weapon.gunMagTrashItem.ID; if (string.IsNullOrEmpty(iD2) || string.Equals(iD2, "trashid", StringComparison.OrdinalIgnoreCase)) { weapon.gunMagTrashItem.ID = iD; } } } private static IEnumerator RegisterWhenReady(TrashManager manager) { float waited = 0f; while (!WeaponBase.AllWeaponsLoaded && waited < 60f) { if ((Object)(object)manager == (Object)null) { yield break; } waited += 0.25f; yield return (object)new WaitForSeconds(0.25f); } if ((Object)(object)manager == (Object)null) { yield break; } List allTrashItems = ((manager.TrashPrefabs != null) ? manager.TrashPrefabs.ToList() : new List()); int added = 0; foreach (WeaponBase weapon in WeaponBase.allWeapons) { TrashItem trash = weapon.gunMagTrashItem; if (!((Object)(object)trash == (Object)null)) { EnsureTrashId(weapon); if (!allTrashItems.Contains(trash)) { allTrashItems.Add(trash); added++; } } } if (added > 0 || allTrashItems.Count > 0) { manager.TrashPrefabs = allTrashItems.ToArray(); } } } } namespace MoreGuns.Guns { public class AK47 : WeaponBase { private static AK47 instance; public static AK47 Instance => instance; public AK47() { if (instance == null) { GunTuning gunTuning = new GunTuning(); gunTuning.SetValues(automatic: true, 1f, jolt: true, windup: false, 0f, manualReload: true); Init("AK47", "ak47", gunTuning); instance = this; } } } public class GunSettings : MonoBehaviour { public bool isAutomatic; public float speedMultiplier; public bool cameraJolt; public bool requireWindup; public float windupTime; public bool canManualyReload; public bool syncMagazineToAmmo; public bool explosiveRounds; public bool IsAutomatic => isAutomatic; public float SpeedMultiplier => speedMultiplier; public bool CameraJolt => cameraJolt; public bool RequireWindup => requireWindup; public float WindupTime => windupTime; public bool CanManualyReload => canManualyReload; public bool SyncMagazineToAmmo => syncMagazineToAmmo; public bool ExplosiveRounds => explosiveRounds; public void Apply(GunTuning tuning) { if (tuning != null) { isAutomatic = tuning.isAutomatic; speedMultiplier = tuning.speedMultiplier; cameraJolt = tuning.cameraJolt; requireWindup = tuning.requireWindup; windupTime = tuning.windupTime; canManualyReload = tuning.canManualyReload; syncMagazineToAmmo = tuning.syncMagazineToAmmo; explosiveRounds = tuning.explosiveRounds; } } public static GunSettings EnsureOn(Equippable_RangedWeapon weapon) { if ((Object)(object)weapon == (Object)null) { return null; } try { GunSettings component = ((Component)weapon).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } catch { return null; } WeaponBase weaponBase = ResolveWeaponBase(weapon); if (weaponBase?.settings == null) { return null; } try { GunSettings gunSettings = ((Component)weapon).gameObject.AddComponent(); gunSettings.Apply(weaponBase.settings); return gunSettings; } catch (Exception ex) { MelonLogger.Warning("GunSettings.EnsureOn failed: " + ex.Message); return null; } } public static WeaponBase ResolveWeaponBase(Equippable_RangedWeapon weapon) { if ((Object)(object)weapon == (Object)null) { return null; } try { IntegerItemInstance val = GameAccess.Get(weapon, "weaponItem"); string text = ((val == null) ? null : ((BaseItemDefinition)(((ItemInstance)val).Definition?)).ID); if (!string.IsNullOrEmpty(text) && WeaponBase.weaponsByName.TryGetValue(text, out var value)) { return value; } } catch { } try { string text2 = (((Object)(object)((Component)weapon).gameObject != (Object)null) ? ((Object)((Component)weapon).gameObject).name : null); if (string.IsNullOrEmpty(text2)) { return null; } string key = text2.Replace("(Clone)", "", StringComparison.OrdinalIgnoreCase).Replace("_Equippable", "", StringComparison.OrdinalIgnoreCase).Replace("_equippable", "", StringComparison.OrdinalIgnoreCase) .Trim() .ToLowerInvariant(); if (WeaponBase.weaponsByName.TryGetValue(key, out var value2)) { return value2; } foreach (WeaponBase allWeapon in WeaponBase.allWeapons) { if (allWeapon == null || string.IsNullOrEmpty(allWeapon.ID) || text2.IndexOf(allWeapon.ID, StringComparison.OrdinalIgnoreCase) < 0) { continue; } return allWeapon; } } catch { } return null; } } public sealed class GunTuning { public bool isAutomatic; public float speedMultiplier = 1f; public bool cameraJolt; public bool requireWindup; public float windupTime; public bool canManualyReload = true; public bool syncMagazineToAmmo; public bool explosiveRounds; public void SetValues(bool automatic, float speed, bool jolt, bool windup, float windupSeconds, bool manualReload, bool syncMag = false, bool explosive = false) { isAutomatic = automatic; speedMultiplier = speed; cameraJolt = jolt; requireWindup = windup; windupTime = windupSeconds; canManualyReload = manualReload; syncMagazineToAmmo = syncMag; explosiveRounds = explosive; } } public class MiniGun : WeaponBase { private static MiniGun instance; public static MiniGun Instance => instance; public MiniGun() { if (instance == null) { GunTuning gunTuning = new GunTuning(); gunTuning.SetValues(automatic: true, 0.75f, jolt: false, windup: true, 2f, Config.AllowMinigunManualReload.Value); Init("MiniGun", "minigun", gunTuning); instance = this; } } } public class RPG : WeaponBase { private static RPG instance; public static RPG Instance => instance; public RPG() { if (instance == null) { GunTuning gunTuning = new GunTuning(); gunTuning.SetValues(automatic: false, 0.5f, jolt: true, windup: false, 0f, manualReload: true, syncMag: true, explosive: true); Init("RPG", "rpg", gunTuning); instance = this; } } } public class SMG : WeaponBase { private static SMG instance; public static SMG Instance => instance; public SMG() { if (instance == null) { GunTuning gunTuning = new GunTuning(); gunTuning.SetValues(automatic: true, 1f, jolt: false, windup: false, 0f, manualReload: true); Init("SMG", "smg", gunTuning); instance = this; } } } public class Sniper : WeaponBase { private static Sniper instance; public static Sniper Instance => instance; public Sniper() { if (instance == null) { GunTuning gunTuning = new GunTuning(); gunTuning.SetValues(automatic: false, 0.7f, jolt: true, windup: false, 0f, manualReload: true); Init("Sniper", "sniper", gunTuning); instance = this; } } } public class WeaponBase { public string name; public string ID; public GameObject gunEquippable; public Equippable_RangedWeapon gunRangedWeapon; public GameObject gunHandgun; public GameObject magAvatarEquippable; public IntegerItemDefinition gunIntItemDef; public IntegerItemDefinition magIntItemDef; public WeaponOption rangedGun; public WeaponOption ammoGun; public GameObject gunMagTrash; public TrashItem gunMagTrashItem; public GameObject magEquippable; public Dictionary animations = new Dictionary(); public GunConfiguration config; public GunTuning settings; public static List allWeapons = new List(); public static Dictionary weaponsByName = new Dictionary(); private static int pendingLoads; private static int startedLoads; public bool IsConfigurationFinished { get; private set; } public static bool AllWeaponsLoaded => startedLoads > 0 && pendingLoads <= 0; public void Init(string name, string ID, GunTuning settings) { this.name = name; this.ID = ID; this.settings = settings; startedLoads++; pendingLoads++; MelonLogger.Msg("Initializing " + ID); MelonCoroutines.Start(LoadGun()); } public void RefreshShopListings() { ArmsDealerInterfacePatch.RefreshListings(); } private IEnumerator LoadGun() { string equippablePath = $"assets/resources/weapons/{ID}/{ID}_equippable.prefab"; string magDefPath = $"assets/resources/weapons/{ID}/magazine/{ID}_magazine.asset"; string gunDefPath = $"assets/resources/weapons/{ID}/{ID}.asset"; string magTrashPath = $"assets/resources/weapons/{ID}/magazine/{ID}_magazine_trash.prefab"; string handgunPath = "assets/resources/avatar/equippables/" + ID + ".prefab"; string magAvatarPath = $"assets/resources/weapons/{ID}/magazine/{ID}_magazine_avatarequippable.prefab"; string magEquippablePath = $"assets/resources/weapons/{ID}/magazine/{ID}_magazine_equippable.prefab"; Object[] loaded = (Object[])(object)new Object[7]; string[] paths = new string[7] { equippablePath, magDefPath, gunDefPath, magTrashPath, handgunPath, magAvatarPath, magEquippablePath }; for (int i = 0; i < paths.Length; i++) { AssetBundleRequest request = MoreGunsMod.assetBundle.LoadAssetAsync(paths[i]); yield return request; if (request.asset == (Object)null) { MelonLogger.Error($"Could not load asset '{paths[i]}' for {ID}. {ID} will not be available."); pendingLoads--; yield break; } loaded[i] = request.asset; } try { FinishLoadGun(loaded, equippablePath); } catch (Exception ex) { Exception ex2 = ex; MelonLogger.Error($"Failed to initialize {ID}: {ex2}"); } finally { pendingLoads--; } } private void FinishLoadGun(Object[] loaded, string equippablePath) { gunEquippable = loaded[0].As(); magIntItemDef = loaded[1].As(); gunIntItemDef = loaded[2].As(); gunMagTrash = loaded[3].As(); gunHandgun = loaded[4].As(); magAvatarEquippable = loaded[5].As(); magEquippable = loaded[6].As(); gunRangedWeapon = gunEquippable.GetComponent(); gunMagTrashItem = gunMagTrash.GetComponent(); if ((Object)(object)gunRangedWeapon == (Object)null) { MelonLogger.Error($"'{equippablePath}' has no Equippable_RangedWeapon component. {ID} will not be available."); return; } WireLoadedAssets(); try { MaterialFixup.FixHierarchy(gunEquippable); MaterialFixup.FixHierarchy(gunHandgun); MaterialFixup.FixHierarchy(gunMagTrash); MaterialFixup.FixHierarchy(magAvatarEquippable); MaterialFixup.FixHierarchy(magEquippable); } catch (Exception ex) { MelonLogger.Warning("Material fixup failed for " + ID + ": " + ex.Message); } try { if (!string.Equals(ID, "ak47", StringComparison.OrdinalIgnoreCase) && !string.Equals(ID, "minigun", StringComparison.OrdinalIgnoreCase) && !string.Equals(ID, "rpg", StringComparison.OrdinalIgnoreCase)) { PreferAk47ReloadClip(gunEquippable); ClearReloadEvents(gunRangedWeapon); } } catch (Exception ex2) { MelonLogger.Warning("Reload clip prefer failed for " + ID + ": " + ex2.Message); } CreateConfig(); SetCustomItemUI(); try { LoadAnimations(); } catch (Exception ex3) { MelonLogger.Warning("Animation load failed for " + ID + ": " + ex3.Message); } ApplySettingsFromConfig(); WeaponBehavior.ApplyTuning(this); MoreGunsMod.RegisterAsset("Avatar/Equippables/" + name, (Object)(object)gunHandgun); MoreGunsMod.RegisterAsset("Avatar/Equippables/" + ID, (Object)(object)gunHandgun); MoreGunsMod.RegisterAsset($"Weapons/{ID}/Magazine/{name}_Magazine_AvatarEquippable", (Object)(object)magAvatarEquippable); if (!string.IsNullOrEmpty(ID)) { ((BaseItemDefinition)gunIntItemDef).ID = ID; if ((Object)(object)magIntItemDef != (Object)null) { ((BaseItemDefinition)magIntItemDef).ID = ID + "mag"; } } if (!string.Equals(ID, "ak47", StringComparison.OrdinalIgnoreCase) && !string.Equals(ID, "minigun", StringComparison.OrdinalIgnoreCase)) { try { MagazineSocketFix.CacheLeftoverMeshesFromGun(gunEquippable); } catch (Exception ex4) { MelonLogger.Warning("Leftover mag cache failed for " + ID + ": " + ex4.Message); } } allWeapons.Add(this); weaponsByName[ID] = this; MelonLogger.Msg("Finished initializing " + ID + "."); ItemRegistryPatch.RegisterWeapons(); } private void WireLoadedAssets() { if ((Object)(object)gunIntItemDef != (Object)null && (Object)(object)gunRangedWeapon != (Object)null) { ((ItemDefinition)gunIntItemDef).Equippable = (Equippable)(object)gunRangedWeapon; } WireItemIcons(); WireMagazineEquippable(); if ((Object)(object)gunRangedWeapon == (Object)null) { return; } if ((Object)(object)magIntItemDef != (Object)null) { gunRangedWeapon.Magazine = (StorableItemDefinition)(object)magIntItemDef; } if ((Object)(object)gunMagTrashItem != (Object)null) { gunRangedWeapon.ReloadTrash = gunMagTrashItem; TrashRegistryPatch.EnsureTrashId(this); } if (!((Object)(object)gunHandgun != (Object)null)) { return; } AvatarEquippable val = gunHandgun.GetComponent() ?? gunHandgun.GetComponentInChildren(true); try { AvatarRangedWeapon val2 = gunHandgun.GetComponent() ?? gunHandgun.GetComponentInChildren(true); if ((Object)(object)val2 != (Object)null) { val = (AvatarEquippable)(object)val2; } } catch { } if ((Object)(object)val != (Object)null) { string text = "Avatar/Equippables/" + name; string path = "Avatar/Equippables/" + ID; try { val.AssetPath = text; } catch { GameAccess.Set(val, "AssetPath", text); } SetEquippablePatch.EnsureAvatarWeaponRefs(val); ((Equippable_Viewmodel)gunRangedWeapon).AvatarEquippable = val; MoreGunsMod.RegisterAsset(text, (Object)(object)gunHandgun); MoreGunsMod.RegisterAsset(path, (Object)(object)gunHandgun); } else { MelonLogger.Error(ID + ": avatar equippable prefab has no AvatarEquippable — remotes will not see/hear this gun."); } } private void WireMagazineEquippable() { if ((Object)(object)magIntItemDef == (Object)null || (Object)(object)magEquippable == (Object)null) { return; } Equippable_Viewmodel val = (Equippable_Viewmodel)(magEquippable.GetComponent() ?? ((object)/*isinst with value type is only supported in some contexts*/) ?? ((object)magEquippable.GetComponentInChildren(true))); if ((Object)(object)val == (Object)null) { MelonLogger.Error(ID + ": magazine equippable prefab has no Equippable_Viewmodel — reload will fail."); return; } ((ItemDefinition)magIntItemDef).Equippable = (Equippable)(object)val; if ((Object)(object)magAvatarEquippable != (Object)null) { AvatarEquippable val2 = magAvatarEquippable.GetComponent() ?? magAvatarEquippable.GetComponentInChildren(true); if ((Object)(object)val2 != (Object)null) { val.AvatarEquippable = val2; } } } private void PreferAk47ReloadClip(GameObject gunRoot) { if ((Object)(object)gunRoot == (Object)null) { return; } Animation[] componentsInChildren = gunRoot.GetComponentsInChildren(true); foreach (Animation val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { AnimationClip clip = val.GetClip("AK47 Reload"); AnimationClip clip2 = val.GetClip("Other Reload"); if ((Object)(object)clip == (Object)null && (Object)(object)clip2 != (Object)null) { val.AddClip(clip2, "AK47 Reload"); } } } } private static void ClearReloadEvents(Equippable_RangedWeapon weapon) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if ((Object)(object)weapon == (Object)null) { return; } try { weapon.onReloadStart = new UnityEvent(); weapon.onReloadEnd = new UnityEvent(); } catch (Exception ex) { MelonLogger.Warning("Could not clear reload events: " + ex.Message); } } private void WireItemIcons() { string text = (string.Equals(ID, "minigun", StringComparison.OrdinalIgnoreCase) ? "MiniGun__Icon" : (name + "__Icon")); string text2 = (string.Equals(ID, "minigun", StringComparison.OrdinalIgnoreCase) ? "MiniGun__Magazine_Icon" : (name + "__Magazine_Icon")); Sprite val = MoreGunsMod.GetSprite(text) ?? MoreGunsMod.GetSprite(ID + "__Icon") ?? (((Object)(object)gunIntItemDef != (Object)null) ? ((BaseItemDefinition)gunIntItemDef).Icon : null); Sprite val2 = MoreGunsMod.GetSprite(text2) ?? MoreGunsMod.GetSprite(ID + "__Magazine_Icon") ?? (((Object)(object)magIntItemDef != (Object)null) ? ((BaseItemDefinition)magIntItemDef).Icon : null); if ((Object)(object)gunIntItemDef != (Object)null && (Object)(object)val != (Object)null) { ((BaseItemDefinition)gunIntItemDef).Icon = val; } if ((Object)(object)magIntItemDef != (Object)null && (Object)(object)val2 != (Object)null) { ((BaseItemDefinition)magIntItemDef).Icon = val2; } } public void CreateConfig() { config = new GunConfiguration(this); } private void SetCustomItemUI() { Object val = Resources.Load("Weapons/M1911/M1911"); if (val == (Object)null) { MelonLogger.Error("Cast to ItemDefinition failed - type mismatch in IL2CPP"); return; } ItemDefinition val2 = val.As(); if ((Object)(object)val2 != (Object)null) { ((ItemDefinition)gunIntItemDef).CustomItemUI = val2.CustomItemUI; ((ItemDefinition)magIntItemDef).CustomItemUI = val2.CustomItemUI; } else { MelonLogger.Error("IL2CPP conversion failed"); } } public void ApplySettingsFromConfig() { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)gunRangedWeapon == (Object)null) && config != null) { gunRangedWeapon.Damage = config.Damage.Value; gunRangedWeapon.ImpactForce = config.ImpactForce.Value; gunRangedWeapon.MinAimFOVReduction = config.MinAimFOVReduction.Value; gunRangedWeapon.MaxAimFOVReduction = config.MaxAimFOVReduction.Value; gunRangedWeapon.AccuracyChangeDuration = config.AccuracyChangeDuration.Value; gunRangedWeapon.MagazineSize = config.MagazineSize.Value; ((BaseItemDefinition)gunIntItemDef).Name = config.DisplayItemName.Value; ((BaseItemDefinition)gunIntItemDef).Description = config.DisplayDescription.Value; ((BaseItemDefinition)gunIntItemDef).legalStatus = config.LegalStatus.Value; ((StorableItemDefinition)gunIntItemDef).RequiredRank = config.RequiredRank.Value; ((BaseItemDefinition)magIntItemDef).Name = config.MagDisplayItemName.Value; ((BaseItemDefinition)magIntItemDef).Description = config.MagDisplayDescription.Value; ((BaseItemDefinition)magIntItemDef).legalStatus = config.MagLegalStatus.Value; ((StorableItemDefinition)magIntItemDef).RequiredRank = config.MagRequiredRank.Value; CreateDialogueControllerOptions(); } } private void CreateDialogueControllerOptions() { //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_0053: 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_007a: Expected O, but got Unknown //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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown ((BaseItemDefinition)gunIntItemDef).Name = config.ItemName.Value; ((StorableItemDefinition)gunIntItemDef).BasePurchasePrice = config.PurchasePrice.Value; rangedGun = new WeaponOption { IsAvailable = config.Available.Value, NotAvailableReason = config.AvailableReason.Value, Item = (StorableItemDefinition)(object)gunIntItemDef }; ((BaseItemDefinition)magIntItemDef).Name = config.MagItemName.Value; ((StorableItemDefinition)magIntItemDef).BasePurchasePrice = config.MagPurchasePrice.Value; ammoGun = new WeaponOption { IsAvailable = config.MagAvailable.Value, NotAvailableReason = config.MagAvailableReason.Value, Item = (StorableItemDefinition)(object)magIntItemDef }; IsConfigurationFinished = true; } private void LoadAnimations() { RuntimeAnimatorController val = ResolveAnimatorController(); if ((Object)(object)val == (Object)null) { MelonLogger.Warning(ID + " has no animator controller; avatar animations will fall back to the default set."); return; } if ((Object)(object)((Equippable_AvatarViewmodel)gunRangedWeapon).AnimatorController == (Object)null) { ((Equippable_AvatarViewmodel)gunRangedWeapon).AnimatorController = val; } try { ViewmodelAvatar instance = Singleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetAnimatorController(val); } } catch { } AnimationClip[] animationClips = val.animationClips; foreach (AnimationClip val2 in animationClips) { if (!((Object)(object)val2 == (Object)null)) { if (((Object)val2).name.Contains("Idle") && !animations.ContainsKey("BothHands_Grip_Lowered")) { animations["BothHands_Grip_Lowered"] = val2; } if (((Object)val2).name.Contains("Aiming") && !animations.ContainsKey("BothHands_Grip_Raised")) { animations["BothHands_Grip_Raised"] = val2; } if (((Object)val2).name.Contains("Fire") && !animations.ContainsKey("BothHands_Grip_Recoil")) { animations["BothHands_Grip_Recoil"] = val2; } } } } private RuntimeAnimatorController ResolveAnimatorController() { RuntimeAnimatorController val = ((Equippable_AvatarViewmodel)gunRangedWeapon).AnimatorController ?? GameAccess.Get(gunRangedWeapon, "AnimatorController"); if ((Object)(object)val != (Object)null) { return val; } string text = (string.Equals(ID, "minigun", StringComparison.OrdinalIgnoreCase) ? "MiniGunAnimator" : "HandgunAnimator"); return MoreGunsMod.GetAnimatorController(text); } } internal static class WeaponBehavior { public static void ApplyTuning(WeaponBase weapon) { if ((Object)(object)weapon?.gunRangedWeapon == (Object)null || weapon.config == null) { return; } Equippable_RangedWeapon gunRangedWeapon = weapon.gunRangedWeapon; bool flag = false; switch (weapon.ID) { case "smg": flag |= Ensure(weapon.config.Damage, 28f); flag |= Ensure(weapon.config.ImpactForce, 120f); flag |= Ensure(weapon.config.MagazineSize, 30); gunRangedWeapon.FireCooldown = 0.055f; gunRangedWeapon.MinSpread = 3f; gunRangedWeapon.MaxSpread = 9f; gunRangedWeapon.Range = 45f; gunRangedWeapon.MustBeCocked = false; break; case "sniper": flag |= Ensure(weapon.config.Damage, 140f); flag |= Ensure(weapon.config.ImpactForce, 450f); flag |= Ensure(weapon.config.MagazineSize, 5); gunRangedWeapon.MustBeCocked = false; gunRangedWeapon.CockedByDefault = true; gunRangedWeapon.AutoCockAfterReload = false; gunRangedWeapon.CockTime = 0.01f; gunRangedWeapon.FireCooldown = 0.65f; gunRangedWeapon.MinSpread = 0.15f; gunRangedWeapon.MaxSpread = 0.8f; gunRangedWeapon.Range = 200f; gunRangedWeapon.MinAimFOVReduction = 12f; gunRangedWeapon.MaxAimFOVReduction = 22f; break; case "rpg": flag |= Ensure(weapon.config.Damage, 200f); flag |= Ensure(weapon.config.ImpactForce, 600f); flag |= Ensure(weapon.config.MagazineSize, 1); gunRangedWeapon.FireCooldown = 1.75f; gunRangedWeapon.MustBeCocked = false; gunRangedWeapon.MinSpread = 0.5f; gunRangedWeapon.MaxSpread = 1.5f; gunRangedWeapon.Range = 120f; break; } gunRangedWeapon.Damage = weapon.config.Damage.Value; gunRangedWeapon.ImpactForce = weapon.config.ImpactForce.Value; gunRangedWeapon.MagazineSize = weapon.config.MagazineSize.Value; if (!flag) { return; } try { weapon.config.Category.SaveToFile(true); } catch { } } private static bool Ensure(MelonPreferences_Entry entry, float intended) { if (Mathf.Approximately(entry.Value, intended)) { return false; } if (Mathf.Approximately(entry.Value, 60f) || entry.Value < intended * 0.4f || entry.Value > intended * 2.5f) { entry.Value = intended; return true; } return false; } private static bool Ensure(MelonPreferences_Entry entry, int intended) { if (entry.Value == intended) { return false; } if (entry.Value == 7 || entry.Value <= 0) { entry.Value = intended; return true; } return false; } public static void SyncMagazineVisualToAmmo(Equippable_RangedWeapon weapon) { if ((Object)(object)weapon == (Object)null) { return; } bool active = weapon.Ammo > 0; SetMagazineObjectsActive(((Component)weapon).transform, active); try { AvatarEquippable avatarEquippable = ((Equippable_Viewmodel)weapon).AvatarEquippable; if ((Object)(object)avatarEquippable != (Object)null) { SetMagazineObjectsActive(((Component)avatarEquippable).transform, active); } } catch { } } public static void CreateExplosionAtAimPoint(Equippable_RangedWeapon weapon) { //IL_0043: 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) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_006e: 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_0071: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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) if ((Object)(object)weapon == (Object)null) { return; } try { CombatManager instance = NetworkSingleton.Instance; PlayerCamera instance2 = PlayerSingleton.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null)) { Vector3 position = ((Component)instance2).transform.position; Vector3 forward = ((Component)instance2).transform.forward; float num = Mathf.Max(10f, weapon.Range); LayerMask rangedWeaponLayerMask = instance.RangedWeaponLayerMask; Vector3 val = position + forward * num; RaycastHit val2 = default(RaycastHit); if (Physics.SphereCast(position, Mathf.Max(0.05f, weapon.RayRadius), forward, ref val2, num, LayerMask.op_Implicit(rangedWeaponLayerMask))) { val = ((RaycastHit)(ref val2)).point; } float num2 = Mathf.Max(weapon.Damage, 180f); ExplosionData val3 = default(ExplosionData); ((ExplosionData)(ref val3))..ctor(7.5f, num2, 450f, true, (EExplosionType)0); instance.CreateExplosion(val, val3); } } catch (Exception ex) { MelonLogger.Warning("RPG explosion failed: " + ex.Message); } } private static void SetMagazineObjectsActive(Transform root, bool active) { if ((Object)(object)root == (Object)null) { return; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string text = ((Object)val).name ?? ""; if ((text.Equals("Magazine", StringComparison.OrdinalIgnoreCase) || text.Equals("Rocket", StringComparison.OrdinalIgnoreCase) || text.IndexOf("MagazineMesh", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("rpg_rocket", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("RPG7 Rocket", StringComparison.OrdinalIgnoreCase) >= 0) && (!((Object)(object)((Component)val).GetComponent() == (Object)null) || !((Object)(object)((Component)val).GetComponent() == (Object)null) || !((Object)(object)((Component)val).GetComponentInChildren(true) == (Object)null)) && ((Component)val).gameObject.activeSelf != active) { ((Component)val).gameObject.SetActive(active); } } } } } } namespace MoreGuns.Gui { public static class ReloadMessage { private const float VISIBLE_SECONDS = 4f; public static GameObject message; public static Text messageText; private static object fadeCoroutine; public static void Initialize(Transform parent) { message = null; messageText = null; MelonCoroutines.Start(LoadAsset(parent)); } public static IEnumerator LoadAsset(Transform parent) { AssetBundleRequest rqMessage = MoreGunsMod.assetBundle.LoadAssetAsync("assets/ui/Reload Message.prefab"); yield return rqMessage; Object UEOMessage = rqMessage.asset; if (UEOMessage == (Object)null) { MelonLogger.Error("Could not load the reload message prefab from the asset bundle."); yield break; } message = Object.Instantiate(UEOMessage.As(), parent); message.SetActive(false); messageText = message.GetComponentInChildren(true); } public static void Show(bool show) { if (!((Object)(object)message == (Object)null)) { message.SetActive(show); if (fadeCoroutine != null) { MelonCoroutines.Stop(fadeCoroutine); fadeCoroutine = null; } if (show) { fadeCoroutine = MelonCoroutines.Start(Fade(message)); } } } public static void Show(string text) { SetText(text); Show(show: true); } public static IEnumerator Fade(GameObject o) { yield return (object)new WaitForSeconds(4f); if ((Object)(object)o != (Object)null) { o.SetActive(false); } fadeCoroutine = null; } public static void SetText(string text) { if ((Object)(object)messageText != (Object)null) { messageText.text = text; } } } public static class Reticle { private const float RETRY_INTERVAL = 0.5f; private const float TIMEOUT = 30f; public static GameObject reticle; public static void Initialize() { reticle = null; MelonCoroutines.Start(FindAndInstantiateCrosshair()); } public static IEnumerator FindAndInstantiateCrosshair() { float waited = 0f; while ((Object)(object)Singleton.Instance == (Object)null || (Object)(object)Singleton.Instance.crosshair == (Object)null) { if (waited >= 30f) { MelonLogger.Warning("Gave up waiting for the HUD crosshair; MoreGuns will not show a custom reticle."); yield break; } waited += 0.5f; yield return (object)new WaitForSeconds(0.5f); } reticle = Object.Instantiate(((Component)Singleton.Instance.crosshair).gameObject, ((Component)Singleton.Instance.crosshair).transform.parent); reticle.SetActive(false); } public static void SetActive(bool active) { if ((Object)(object)reticle != (Object)null) { reticle.SetActive(active); } } } public static class WindupIndicator { public static GameObject windupIndicator; public static Slider windupIndicatorSlider; public static Image backgroundImage; public static Image fillImage; public static void Initialize(Transform parent) { windupIndicator = null; windupIndicatorSlider = null; MelonCoroutines.Start(LoadAsset(parent)); } public static IEnumerator LoadAsset(Transform parent) { AssetBundleRequest rqWindupIndicator = MoreGunsMod.assetBundle.LoadAssetAsync("assets/ui/Windup Indicator.prefab"); yield return rqWindupIndicator; Object UEOWindupIndicator = rqWindupIndicator.asset; if (UEOWindupIndicator == (Object)null) { MelonLogger.Error("Could not load the windup indicator prefab from the asset bundle."); yield break; } windupIndicator = Object.Instantiate(UEOWindupIndicator.As(), parent); windupIndicator.SetActive(false); windupIndicatorSlider = windupIndicator.GetComponent(); backgroundImage = ((Component)windupIndicator.transform.GetChild(0)).GetComponent(); fillImage = ((Component)windupIndicator.transform.GetChild(1).GetChild(0)).GetComponent(); } public static void Show(bool shown) { if ((Object)(object)windupIndicator != (Object)null && windupIndicator.activeSelf != shown) { windupIndicator.SetActive(shown); } } public static void SetValueByTime(float from, float to) { if (to <= 0f || from >= to) { SetValue(100); } else { SetValue((int)(from * 100f / to)); } } public static void SetValue(int value) { if (!((Object)(object)windupIndicatorSlider == (Object)null)) { windupIndicatorSlider.value = value; Show(value != 100); } } } } namespace MoreGuns.Dialogue { public static class StanDialogue { public const string stanDialogueMainOptions = "72f05df5-cfd4-4be3-9239-fc31bb44f49b"; public static void StartSpecialGunReloads() { try { PlayerInventory instance = PlayerSingleton.Instance; if (instance?.hotbarSlots == null) { return; } PlayerCamera instance2 = PlayerSingleton.Instance; for (int i = 0; i < instance.hotbarSlots.Count; i++) { ItemSlot val = (ItemSlot)(object)instance.hotbarSlots[i]; ItemInstance val2 = ((val != null) ? val.ItemInstance : null); if ((Object)(object)((val2 != null) ? val2.Definition : null) == (Object)null) { continue; } string iD = ((BaseItemDefinition)val2.Definition).ID; if (string.IsNullOrEmpty(iD) || !WeaponBase.weaponsByName.TryGetValue(iD, out var value) || value == null) { continue; } IntegerItemInstance val3 = val2.As(); if (val3 == null) { continue; } int num = ResolveCapacity(value); if (val3.Value >= num) { continue; } string text = ResolveMagId(value); if (string.IsNullOrEmpty(text)) { continue; } int num2 = 64; ItemSlot slot; IntegerItemInstance magAmmo; while (val3.Value < num && num2-- > 0 && TryFindMagazine(instance, text, out slot, out magAmmo)) { int value2 = magAmmo.Value; if (value2 <= 0) { RemoveEmptyMag(slot); SpawnMagTrash(value, instance2); continue; } int num3 = Mathf.Min(num - val3.Value, value2); int value3 = val3.Value + num3; val3.SetValue(value3); try { val3.Value = value3; } catch { } int num4 = value2 - num3; if (num4 <= 0) { magAmmo.SetValue(0); try { magAmmo.Value = 0; } catch { } RemoveEmptyMag(slot); SpawnMagTrash(value, instance2); } else { magAmmo.SetValue(num4); try { magAmmo.Value = num4; } catch { } } } } } catch (Exception ex) { MelonLogger.Error("Exception in StartSpecialGunReloads: " + ex.Message); MelonLogger.Error("Stack trace: " + ex.StackTrace); } } private static int ResolveCapacity(WeaponBase source) { try { if (source.config?.MagazineSize != null) { return Mathf.Max(1, source.config.MagazineSize.Value); } } catch { } try { if ((Object)(object)source.gunRangedWeapon != (Object)null) { return Mathf.Max(1, source.gunRangedWeapon.MagazineSize); } } catch { } return 30; } private static string ResolveMagId(WeaponBase source) { if ((Object)(object)source.magIntItemDef != (Object)null && !string.IsNullOrEmpty(((BaseItemDefinition)source.magIntItemDef).ID)) { return ((BaseItemDefinition)source.magIntItemDef).ID; } if (!string.IsNullOrEmpty(source.ID)) { return source.ID + "mag"; } return null; } private static bool TryFindMagazine(PlayerInventory inv, string magId, out ItemSlot slot, out IntegerItemInstance magAmmo) { slot = null; magAmmo = null; if (inv.hotbarSlots != null) { for (int i = 0; i < inv.hotbarSlots.Count; i++) { if (MatchMagSlot((ItemSlot)(object)inv.hotbarSlots[i], magId, out slot, out magAmmo)) { return true; } } } try { List allInventorySlots = inv.GetAllInventorySlots(); if (allInventorySlots != null) { for (int j = 0; j < allInventorySlots.Count; j++) { if (MatchMagSlot(allInventorySlots[j], magId, out slot, out magAmmo)) { return true; } } } } catch { } return false; } private static bool MatchMagSlot(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 = val.As(); if (val2 == null) { return false; } slot = s; magAmmo = val2; return true; } private static void RemoveEmptyMag(ItemSlot magSlot) { if (((magSlot != null) ? magSlot.ItemInstance : null) == null) { return; } try { ((BaseItemInstance)magSlot.ItemInstance).ChangeQuantity(-1); } catch { try { magSlot.ChangeQuantity(-1, false); } catch { } } } private static void SpawnMagTrash(WeaponBase source, PlayerCamera cam) { //IL_0076: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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) try { if (source == null || (Object)(object)cam == (Object)null) { return; } TrashRegistryPatch.EnsureTrashId(source); TrashItem gunMagTrashItem = source.gunMagTrashItem; if (!((Object)(object)gunMagTrashItem == (Object)null)) { if (string.IsNullOrEmpty(gunMagTrashItem.ID) || string.Equals(gunMagTrashItem.ID, "trashid", StringComparison.OrdinalIgnoreCase)) { gunMagTrashItem.ID = source.ID + "mag"; } Vector3 val = ((Component)cam).transform.position - ((Component)cam).transform.up * 0.4f; Object.Instantiate(((Component)gunMagTrashItem).gameObject, val, Random.rotation); } } catch { } } } }