Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of Endgame Arsenal v1.0.2
ScheduleIEndgameArsenal.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using HarmonyLib; using Il2Cpp; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppRootMotion; using Il2CppRootMotion.FinalIK; using Il2CppScheduleOne; using Il2CppScheduleOne.Audio; using Il2CppScheduleOne.AvatarFramework; using Il2CppScheduleOne.AvatarFramework.Animation; using Il2CppScheduleOne.AvatarFramework.Equipping; using Il2CppScheduleOne.Core.Audio; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Equipping; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Levelling; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.Persistence; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.Storage; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.Items; using Il2CppScheduleOne.UI.Shop; using Il2CppSystem.Collections.Generic; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using ScheduleIEndgameArsenal; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(ArsenalMod), "Schedule I Endgame Arsenal", "1.0.2", "nacho", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)] [assembly: HarmonyDontPatchAll] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("ScheduleIEndgameArsenal")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+c02009702c06e41397470955ed5c61813b6c6995")] [assembly: AssemblyProduct("ScheduleIEndgameArsenal")] [assembly: AssemblyTitle("ScheduleIEndgameArsenal")] [assembly: AssemblyVersion("1.0.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } } namespace ScheduleIEndgameArsenal { public sealed class ArsenalMod : MelonMod { private Harmony? patches; private ArsenalSettings? settings; private bool settingsDirty = true; private float nextAttempt; private int failureCount; private bool ready; public override void OnInitializeMelon() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown settings = new ArsenalSettings(delegate { settingsDirty = true; nextAttempt = 0f; }); RegistryAndShop.BindSettings(settings); patches = new Harmony("nacho.schedulei.endgamearsenal"); RegistryAndShop.Initialize(patches); WeaponBehavior.Initialize(patches); AvatarWeapons.Initialize(patches); HandPoses.Initialize(patches); SniperScope.Initialize(patches); SniperTargets.Initialize(patches); SniperChamber.Initialize(patches); ((MelonBase)this).LoggerInstance.Msg("Endgame Arsenal 1.0.2: weapon unlock ranks, gun prices and ammo prices are available in Mod Manager & Phone App settings."); } public override void OnUpdate() { SniperChamber.Update(); if (ready) { SniperScope.Update(); } if ((ready && RegistryAndShop.PortraitsComplete && !settingsDirty) || Time.unscaledTime < nextAttempt) { return; } nextAttempt = Time.unscaledTime + 1f; try { if (ready) { if (settingsDirty) { settingsDirty = !RegistryAndShop.ApplySettings(); } if (!RegistryAndShop.PortraitsComplete) { RegistryAndShop.RetryModelPortraits(); } return; } bool flag = RegistryAndShop.TryRegister(); LoadManager instance = Singleton<LoadManager>.Instance; if ((Object)(object)instance == (Object)null || !instance.IsGameLoaded || instance.IsLoading) { return; } if (!flag) { nextAttempt = Time.unscaledTime + 5f; if (failureCount++ < 3) { ((MelonBase)this).LoggerInstance.Warning("Arsenal items could not initialize from the game's M1911 and magazine templates. Retrying in 5 seconds."); } return; } if (RegistryAndShop.TryAddToStan() && !ready) { ready = true; settingsDirty = !RegistryAndShop.ApplySettings(); ((MelonBase)this).LoggerInstance.Msg("Stan's shop has the three endgame weapons and their matching rounds. Native rank requirements apply."); } failureCount = 0; } catch (Exception ex) { nextAttempt = Time.unscaledTime + 5f; if (failureCount++ < 3) { ((MelonBase)this).LoggerInstance.Warning("Arsenal setup will retry: " + ex.GetType().Name + ": " + ex.Message); } } } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { nextAttempt = 0f; ready = false; settingsDirty = true; failureCount = 0; WeaponBehavior.Reset(); SniperScope.Reset(); SniperChamber.Reset(); HandPoses.Reset(); } public override void OnDeinitializeMelon() { SniperChamber.Reset(); SniperScope.Reset(); HandPoses.Reset(); settings?.Dispose(); Harmony? obj = patches; if (obj != null) { obj.UnpatchSelf(); } } } internal sealed class ArsenalSettings : IDisposable { private sealed class WeaponEntries { private readonly WeaponShopSettings defaults; private readonly MelonPreferences_Entry<ArsenalUnlockRank> rank; private readonly MelonPreferences_Entry<int> tier; private readonly MelonPreferences_Entry<float> price; private readonly MelonPreferences_Entry<float> ammoPrice; internal WeaponShopSettings Value { get; private set; } internal WeaponEntries(ArsenalSettings owner, string prefix, WeaponSpec spec) { defaults = Defaults(spec); string text = spec.Name + ": "; rank = owner.Add(prefix + "UnlockRank", (ArsenalUnlockRank)spec.Rank, text + "unlock rank", "Street Rat through Kingpin. Applies to this gun and its matching ammunition at Stan's shop."); tier = owner.Add(prefix + "UnlockTier", spec.Tier, text + "unlock tier", "1–5 (I–V) within the chosen rank. Applies to this gun and its matching ammunition."); price = owner.Add(prefix + "Price", spec.Price, text + "gun price", "$0–$1,000,000 per gun at Stan's shop. Zero makes the gun free."); ammoPrice = owner.Add(prefix + "AmmoPrice", spec.AmmoPrice, text + "ammunition price", $"$0–$100,000 per {spec.Capacity}-round pack at Stan's shop. Zero makes ammunition free."); } internal void Refresh() { WeaponShopSettings value = ArsenalSettingsPolicy.Normalize(rank.Value, tier.Value, price.Value, ammoPrice.Value, defaults); if (rank.Value != (ArsenalUnlockRank)value.Rank) { rank.Value = (ArsenalUnlockRank)value.Rank; } if (tier.Value != value.Tier) { tier.Value = value.Tier; } if (price.Value != value.Price) { price.Value = value.Price; } if (ammoPrice.Value != value.AmmoPrice) { ammoPrice.Value = value.AmmoPrice; } Value = value; } } private readonly MelonPreferences_Category category; private readonly Action changed; private readonly List<Action> unsubscribe = new List<Action>(12); private readonly WeaponEntries automaticPistol; private readonly WeaponEntries m4; private readonly WeaponEntries sniper; private bool refreshing = true; private bool disposed; internal ArsenalSettings(Action changed) { this.changed = changed ?? throw new ArgumentNullException("changed"); category = MelonPreferences.CreateCategory("ScheduleIEndgameArsenal", "Endgame Arsenal"); automaticPistol = new WeaponEntries(this, "AutomaticPistol", FindDefaults("eg_auto_pistol")); m4 = new WeaponEntries(this, "M4", FindDefaults("eg_m4")); sniper = new WeaponEntries(this, "Sniper", FindDefaults("eg_sniper")); Refresh(); refreshing = false; category.SaveToFile(false); } internal WeaponShopSettings For(WeaponSpec spec) { return spec.Id switch { "eg_auto_pistol" => automaticPistol.Value, "eg_m4" => m4.Value, "eg_sniper" => sniper.Value, _ => ArsenalSettingsPolicy.Normalize((ArsenalUnlockRank)spec.Rank, spec.Tier, spec.Price, spec.AmmoPrice, Defaults(spec)), }; } internal void Save() { if (!disposed) { category.SaveToFile(false); } } public void Dispose() { if (disposed) { return; } disposed = true; foreach (Action item in unsubscribe) { item(); } unsubscribe.Clear(); } private void EntryChanged() { if (!refreshing && !disposed) { refreshing = true; try { Refresh(); } finally { refreshing = false; } category.SaveToFile(false); changed(); } } private void Refresh() { automaticPistol.Refresh(); m4.Refresh(); sniper.Refresh(); } private MelonPreferences_Entry<T> Add<T>(string key, T defaultValue, string title, string description) { MelonPreferences_Entry<T> entry = category.CreateEntry<T>(key, defaultValue, title, description, false, false, (ValueValidator)null, (string)null); LemonAction<T, T> handler = delegate { EntryChanged(); }; ((MelonEventBase<LemonAction<T, T>>)(object)entry.OnEntryValueChanged).Subscribe(handler, 0, false); unsubscribe.Add(delegate { ((MelonEventBase<LemonAction<T, T>>)(object)entry.OnEntryValueChanged).Unsubscribe(handler); }); return entry; } private static WeaponSpec FindDefaults(string id) { return WeaponCatalog.Find(id) ?? throw new InvalidOperationException("Missing weapon settings defaults: " + id); } private static WeaponShopSettings Defaults(WeaponSpec spec) { return new WeaponShopSettings(spec.Rank, spec.Tier, spec.Price, spec.AmmoPrice); } } public enum ArsenalUnlockRank { Street_Rat, Hoodlum, Peddler, Hustler, Bagman, Enforcer, Shot_Caller, Block_Boss, Underlord, Baron, Kingpin } internal readonly record struct WeaponShopSettings(int Rank, int Tier, float Price, float AmmoPrice); internal static class ArsenalSettingsPolicy { internal const float MaximumWeaponPrice = 1000000f; internal const float MaximumAmmoPrice = 100000f; internal static WeaponShopSettings Normalize(ArsenalUnlockRank rank, int tier, float price, float ammoPrice, WeaponShopSettings defaults) { return new WeaponShopSettings(Math.Clamp((int)rank, 0, 10), Math.Clamp(tier, 1, 5), Price(price, defaults.Price, 1000000f), Price(ammoPrice, defaults.AmmoPrice, 100000f)); } private static float Price(float value, float fallback, float maximum) { return Math.Clamp(float.IsFinite(value) ? value : fallback, 0f, maximum); } } internal static class AvatarWeapons { public const string PathPrefix = "EndgameArsenal/"; public static void Initialize(Harmony harmony) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0049: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(Avatar), "SetEquippable", (Type[])null, (Type[])null), new HarmonyMethod(typeof(AvatarWeapons), "BeforeSet", (Type[])null), new HarmonyMethod(typeof(AvatarWeapons), "AfterSet", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static void BeforeSet(Avatar __instance, ref string assetPath, out WeaponSpec? __state) { HandPoses.ClearAvatar(__instance); __state = null; if (string.IsNullOrEmpty(assetPath) || !assetPath.StartsWith("EndgameArsenal/", StringComparison.Ordinal)) { return; } WeaponSpec weaponSpec = WeaponCatalog.Find(assetPath.Substring("EndgameArsenal/".Length)); if (weaponSpec == null) { return; } RegistryAndShop.TryRegister(); if (string.IsNullOrEmpty(RegistryAndShop.BaseAvatarAssetPath)) { return; } __state = weaponSpec; object obj2; if (HandPoses.IsLongGun(weaponSpec)) { GameObject obj = Resources.Load<GameObject>("Avatar/Equippables/PumpShotgun"); if ((Object)(object)((obj != null) ? obj.GetComponent<AvatarEquippable>() : null) != (Object)null) { obj2 = "Avatar/Equippables/PumpShotgun"; goto IL_008c; } } obj2 = RegistryAndShop.BaseAvatarAssetPath; goto IL_008c; IL_008c: assetPath = (string)obj2; } private static void AfterSet(AvatarEquippable? __result, WeaponSpec? __state) { if (__state == null || (Object)(object)__result == (Object)null) { return; } try { ApplyAppearance(__result, __state); } catch (Exception ex) { MelonLogger.Warning("Unable to create held " + __state.Name + ": " + ex.Message); } } public static void ApplyAppearance(AvatarEquippable avatar, WeaponSpec spec) { //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) string text = spec.Id + "_OriginalModel"; if ((Object)(object)((Component)avatar).transform.Find(text) == (Object)null) { foreach (Renderer componentsInChild in ((Component)avatar).GetComponentsInChildren<Renderer>(true)) { componentsInChild.enabled = false; } AvatarRangedWeapon val = ((Il2CppObjectBase)avatar).TryCast<AvatarRangedWeapon>(); GameObject val2 = WeaponVisuals.Build(spec.Id, ((Component)avatar).transform); if ((Object)(object)val != (Object)null && (Object)(object)val.MuzzlePoint != (Object)null) { val2.transform.rotation = val.MuzzlePoint.rotation; } if ((Object)(object)avatar.AlignmentPoint != (Object)null) { val2.transform.position = avatar.AlignmentPoint.position; } } avatar.AssetPath = "EndgameArsenal/" + spec.Id; AvatarRangedWeapon val3 = ((Il2CppObjectBase)avatar).TryCast<AvatarRangedWeapon>(); if ((Object)(object)val3 == (Object)null) { return; } val3.MagazineSize = spec.Capacity; val3.Damage = spec.Damage; val3.MaxFireRate = 1f / spec.FireInterval; val3.ImpactForce = Math.Max(100f, spec.Damage * 2.5f); Transform val4 = ((Component)avatar).transform.Find(text); if (!((Object)(object)val4 == (Object)null)) { Transform val5 = val4.Find("ArsenalMuzzle"); if ((Object)(object)val5 == (Object)null) { val5 = new GameObject("ArsenalMuzzle").transform; val5.SetParent(val4, false); Transform val6 = val5; string id = spec.Id; Vector3 localPosition = ((id == "eg_auto_pistol") ? new Vector3(0f, 0.101f, 0.2f) : ((!(id == "eg_m4")) ? new Vector3(0f, 0.097f, 0.713f) : new Vector3(0f, 0.095f, 0.476f))); val6.localPosition = localPosition; } val3.MuzzlePoint = val5; HandPoses.BindAvatar(avatar, spec, val4); } } } internal readonly record struct BallisticsTuning(float BloomPerShot, float HipBloomDegrees, float AimBloomDegrees, float PitchPerShot, float YawPerShot, float AimRecoilScale, float MaxPitch, float MaxYaw, float RecoveryDelay, float BloomRecoveryPerSecond, float RecoilRecoveryPerSecond) { public static BallisticsTuning For(string id) { return id switch { "eg_auto_pistol" => new BallisticsTuning(0.14f, 3.4f, 1.7f, 0.72f, 0.25f, 0.65f, 7f, 1.6f, 0.18f, 1.3f, 6f), "eg_m4" => new BallisticsTuning(0.11f, 2.6f, 1.15f, 0.48f, 0.15f, 0.65f, 5.5f, 1.1f, 0.2f, 1.2f, 5f), "eg_sniper" => new BallisticsTuning(0.3f, 2f, 0.12f, 1.8f, 0.22f, 0.4f, 4f, 0.8f, 0.3f, 1.4f, 5.5f), _ => default(BallisticsTuning), }; } } internal readonly record struct BallisticsSample(float PitchDegrees, float YawDegrees, float BloomDegrees); internal sealed class BallisticsState { private double lastUpdate = double.NaN; private double lastShot = double.NegativeInfinity; public float Bloom { get; private set; } public float Pitch { get; private set; } public float Yaw { get; private set; } public void Advance(double now, BallisticsTuning tuning) { if (double.IsFinite(now)) { if (double.IsNaN(lastUpdate) || now < lastUpdate) { float num = (Yaw = 0f); float bloom = (Pitch = num); Bloom = bloom; lastShot = double.NegativeInfinity; lastUpdate = now; } else { float num4 = (float)Math.Max(0.0, now - Math.Max(lastUpdate, lastShot + (double)tuning.RecoveryDelay)); Bloom = TowardZero(Bloom, num4 * tuning.BloomRecoveryPerSecond); Pitch = TowardZero(Pitch, num4 * tuning.RecoilRecoveryPerSecond); Yaw = TowardZero(Yaw, num4 * tuning.RecoilRecoveryPerSecond); lastUpdate = now; } } } public void RecordShot(double now, float aim, float lateralSample, BallisticsTuning tuning) { Advance(now, tuning); if (double.IsFinite(now)) { float num = 1f + (tuning.AimRecoilScale - 1f) * Unit(aim); Bloom = Math.Clamp(Bloom + tuning.BloomPerShot, 0f, 1f); Pitch = Math.Clamp(Pitch + tuning.PitchPerShot * num, 0f, tuning.MaxPitch); Yaw = Math.Clamp(Yaw + Math.Clamp(Finite(lateralSample), -1f, 1f) * tuning.YawPerShot * num, 0f - tuning.MaxYaw, tuning.MaxYaw); lastShot = now; } } public BallisticsSample Sample(float aim, BallisticsTuning tuning) { float num = tuning.HipBloomDegrees + (tuning.AimBloomDegrees - tuning.HipBloomDegrees) * Unit(aim); return new BallisticsSample(Pitch, Yaw, Bloom * num); } internal static float Unit(float value) { return Math.Clamp(Finite(value), 0f, 1f); } private static float Finite(float value) { if (!float.IsFinite(value)) { return 0f; } return value; } private static float TowardZero(float value, float amount) { return (float)Math.Sign(value) * Math.Max(0f, Math.Abs(value) - Math.Max(0f, amount)); } } internal static class BallisticsMath { private const float ToRadians = (float)Math.PI / 180f; public static Vector3 OffsetDirection(Vector3 nativeDirection, Vector3 cameraUp, BallisticsSample sample, float areaSample, float azimuthSample) { Vector3 vector = NormalizeOr(nativeDirection, Vector3.UnitZ); Vector3 vector2 = Right(vector, cameraUp); Vector3 vector3 = Vector3.Cross(vector, vector2); float x = sample.PitchDegrees * ((float)Math.PI / 180f); float x2 = sample.YawDegrees * ((float)Math.PI / 180f); Vector3 vector4 = vector * (MathF.Cos(x) * MathF.Cos(x2)) + vector2 * (MathF.Cos(x) * MathF.Sin(x2)) + vector3 * MathF.Sin(x); float x3 = Math.Clamp(sample.BloomDegrees, 0f, 45f) * ((float)Math.PI / 180f); float num = 1f - BallisticsState.Unit(areaSample) * (1f - MathF.Cos(x3)); float num2 = MathF.Sqrt(Math.Max(0f, 1f - num * num)); float x4 = BallisticsState.Unit(azimuthSample) * ((float)Math.PI * 2f); Vector3 vector5 = Right(vector4, cameraUp); Vector3 vector6 = Vector3.Cross(vector4, vector5); return NormalizeOr(vector4 * num + vector5 * (num2 * MathF.Cos(x4)) + vector6 * (num2 * MathF.Sin(x4)), vector); } private static Vector3 Right(Vector3 forward, Vector3 up) { Vector3 vector = Vector3.Cross(up, forward); if (!Valid(vector) || vector.LengthSquared() < 1E-06f) { vector = Vector3.Cross((Math.Abs(forward.Y) < 0.99f) ? Vector3.UnitY : Vector3.UnitX, forward); } return Vector3.Normalize(vector); } private static Vector3 NormalizeOr(Vector3 vector, Vector3 fallback) { if (!Valid(vector) || !(vector.LengthSquared() >= 1E-06f)) { return fallback; } return Vector3.Normalize(vector); } private static bool Valid(Vector3 vector) { if (float.IsFinite(vector.X) && float.IsFinite(vector.Y)) { return float.IsFinite(vector.Z); } return false; } } internal static class HandPoses { private sealed class SupportState { private readonly Avatar avatar; private readonly Transform model; private readonly AvatarEquippable? equippable; private readonly IKSolverLimb solver; private readonly Transform palm; private readonly Transform wristTarget; private readonly Transform wrist; private readonly Vector3 palmOffset; private readonly Transform? oldTarget; private readonly Vector3 oldPosition; private readonly Quaternion oldRotation; private readonly float oldPositionWeight; private readonly float oldRotationWeight; private bool applied; private float blend; private SupportState(Avatar avatar, Transform model, WeaponSpec spec, AvatarEquippable? equippable, IKSolverLimb solver) { //IL_0058: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) this.avatar = avatar; this.model = model; this.equippable = equippable; this.solver = solver; wrist = ((Point)((IKSolverTrigonometric)solver).bone3).transform; palmOffset = (((Object)(object)avatar.LeftHandAlignmentPoint != (Object)null) ? wrist.InverseTransformPoint(avatar.LeftHandAlignmentPoint.position) : Vector3.zero); palm = Child(model, "ArsenalSupportPalm"); palm.localPosition = ((spec.Id == "eg_m4") ? new Vector3(0f, 0.07f, 0.255f) : new Vector3(0f, 0.057f, 0.292f)); wristTarget = Child(model, "ArsenalSupportWrist"); oldTarget = ((IKSolverTrigonometric)solver).target; oldPosition = ((IKSolver)solver).IKPosition; oldRotation = ((IKSolverTrigonometric)solver).IKRotation; oldPositionWeight = ((IKSolver)solver).IKPositionWeight; oldRotationWeight = ((IKSolverTrigonometric)solver).IKRotationWeight; } public static SupportState? TryCreate(Avatar avatar, Animator? animator, Transform model, WeaponSpec spec, AvatarEquippable? equippable) { //IL_0121: 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) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown AvatarAnimation animation = avatar.Animation; object obj; if (animation == null) { obj = null; } else { AvatarIKController ikController = animation._ikController; obj = ((ikController != null) ? ikController.BodyIK : null); } BipedIK val = (BipedIK)obj; IKSolverLimb val2 = ((val != null) ? val.GetGoalIK((AvatarIKGoal)2) : null); object obj2; if (val2 == null) { obj2 = null; } else { TrigonometricBone bone = ((IKSolverTrigonometric)val2).bone1; obj2 = ((bone != null) ? ((Point)bone).transform : null); } if (!((Object)obj2 == (Object)null)) { TrigonometricBone bone2 = ((IKSolverTrigonometric)val2).bone2; if (!((Object)(object)((bone2 != null) ? ((Point)bone2).transform : null) == (Object)null)) { TrigonometricBone bone3 = ((IKSolverTrigonometric)val2).bone3; if (!((Object)(object)((bone3 != null) ? ((Point)bone3).transform : null) == (Object)null)) { goto IL_015a; } } } BipedReferences obj3 = ((val != null) ? val.references : null); Transform val3 = ((obj3 != null) ? obj3.leftUpperArm : null); Transform val4 = ((obj3 != null) ? obj3.leftForearm : null); Transform val5 = ((obj3 != null) ? obj3.leftHand : null); if (((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null) && (Object)(object)animator != (Object)null && animator.isHuman) { val3 = animator.GetBoneTransform((HumanBodyBones)13); val4 = animator.GetBoneTransform((HumanBodyBones)15); val5 = animator.GetBoneTransform((HumanBodyBones)17); } if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null) { return null; } val2 = new IKSolverLimb { goal = (AvatarIKGoal)2, bendModifier = (BendModifier)0, bendModifierWeight = 1f }; if (!((IKSolverTrigonometric)val2).SetChain(val3, val4, val5, ((Component)avatar).transform)) { return null; } ((IKSolverTrigonometric)val2).SetBendPlaneToCurrent(); goto IL_015a; IL_015a: if (!((IKSolver)val2).initiated) { ((IKSolver)val2).Initiate(((Component)avatar).transform); } return new SupportState(avatar, model, spec, equippable, val2); } public bool Matches(Avatar candidate, Transform candidateModel) { if ((Object)(object)avatar == (Object)(object)candidate) { return (Object)(object)model == (Object)(object)candidateModel; } return false; } public bool IsEquipped() { if ((Object)(object)avatar != (Object)null && (Object)(object)model != (Object)null && (Object)(object)equippable != (Object)null && (Object)(object)avatar.CurrentEquippable != (Object)null) { return ((Il2CppObjectBase)avatar.CurrentEquippable).Pointer == ((Il2CppObjectBase)equippable).Pointer; } return false; } public void Apply() { //IL_00df: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) AvatarEquippable? obj = equippable; AvatarRangedWeapon val = ((obj != null) ? ((Il2CppObjectBase)obj).TryCast<AvatarRangedWeapon>() : null); if (!((Object)(object)avatar == (Object)null) && !((Object)(object)model == (Object)null) && !((Object)(object)wrist == (Object)null) && !avatar.Ragdolled && !avatar.IsCulled) { AvatarAnimation animation = avatar.Animation; if (animation == null || !animation.IsSeated) { AvatarAnimation animation2 = avatar.Animation; if ((animation2 == null || !animation2.StandUpAnimationPlaying) && (!((Object)(object)val != (Object)null) || (!val.isReloading && !(val.timeEquipped < val.EquipTime)))) { blend = Mathf.MoveTowards(blend, 1f, Time.deltaTime * 7f); wristTarget.position = palm.position - wrist.TransformVector(palmOffset); wristTarget.rotation = wrist.rotation; ((IKSolverTrigonometric)solver).target = wristTarget; ((IKSolver)solver).IKPosition = wristTarget.position; ((IKSolverTrigonometric)solver).IKRotation = wristTarget.rotation; ((IKSolver)solver).IKPositionWeight = blend; ((IKSolverTrigonometric)solver).IKRotationWeight = blend; applied = true; ((IKSolver)solver).Update(); return; } } } Release(); } public void Release() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) blend = 0f; if (applied && solver != null) { applied = false; if (!((Object)(object)((IKSolverTrigonometric)solver).target != (Object)(object)wristTarget)) { ((IKSolverTrigonometric)solver).target = oldTarget; ((IKSolver)solver).IKPosition = oldPosition; ((IKSolverTrigonometric)solver).IKRotation = oldRotation; ((IKSolver)solver).IKPositionWeight = oldPositionWeight; ((IKSolverTrigonometric)solver).IKRotationWeight = oldRotationWeight; } } } private static Transform Child(Transform parent, string name) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) Transform val = parent.Find(name); if ((Object)(object)val != (Object)null) { return val; } val = new GameObject(name).transform; val.SetParent(parent, false); return val; } } private static readonly Dictionary<IntPtr, SupportState> Avatars = new Dictionary<IntPtr, SupportState>(); private static Equippable_RangedWeapon? firstPersonWeapon; private static SupportState? firstPersonState; private static int failures; public static void Initialize(Harmony harmony) { harmony.Patch((MethodBase)AccessTools.Method(typeof(Equippable_RangedWeapon), "Equip", (Type[])null, (Type[])null), (HarmonyMethod)null, Patch("AfterEquip"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Equippable_RangedWeapon), "Unequip", (Type[])null, (Type[])null), Patch("BeforeUnequip"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ViewmodelAvatar), "SetBoneTransforms", (Type[])null, (Type[])null), (HarmonyMethod)null, Patch("AfterViewmodelTransforms"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(AvatarAnimation), "LateUpdate", (Type[])null, (Type[])null), (HarmonyMethod)null, Patch("AfterAvatarAnimation"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static HarmonyMethod Patch(string name) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return new HarmonyMethod(typeof(HandPoses), name, (Type[])null); } internal static bool IsLongGun(WeaponSpec? spec) { if (!(spec?.Id == "eg_m4")) { return spec?.Id == "eg_sniper"; } return true; } private static void AfterEquip(Equippable_RangedWeapon __instance) { ClearFirstPerson(); if (IsLongGun(WeaponBehavior.GetSpec(__instance))) { firstPersonWeapon = __instance; } } private static void BeforeUnequip(Equippable_RangedWeapon __instance) { if ((Object)(object)firstPersonWeapon != (Object)null && ((Il2CppObjectBase)firstPersonWeapon).Pointer == ((Il2CppObjectBase)__instance).Pointer) { ClearFirstPerson(); } } private static void AfterViewmodelTransforms(ViewmodelAvatar __instance) { if ((Object)(object)firstPersonWeapon == (Object)null) { return; } try { Equippable_RangedWeapon val = firstPersonWeapon; WeaponSpec spec = WeaponBehavior.GetSpec(val); PlayerInventory instance = PlayerSingleton<PlayerInventory>.Instance; if (!IsLongGun(spec) || (Object)(object)((instance != null) ? instance.Equippable : null) == (Object)null || ((Il2CppObjectBase)instance.Equippable).Pointer != ((Il2CppObjectBase)val).Pointer) { ClearFirstPerson(); return; } Avatar avatar = __instance.Avatar; Transform val2 = ((Component)val).transform.Find(spec.Id + "_OriginalModel"); if ((Object)(object)avatar == (Object)null || (Object)(object)val2 == (Object)null) { return; } if (firstPersonState == null || !firstPersonState.Matches(avatar, val2)) { firstPersonState?.Release(); firstPersonState = SupportState.TryCreate(avatar, __instance.Animator, val2, spec, null); } if (firstPersonState != null) { if (!__instance.IsVisible || !((Behaviour)val).isActiveAndEnabled || !((Equippable_AvatarViewmodel)val).equipAnimDone || val.IsReloading || val.IsCocking) { firstPersonState.Release(); } else { firstPersonState.Apply(); } } } catch (Exception ex) { ClearFirstPerson(); Warn(ex); } } internal static void BindAvatar(AvatarEquippable equippable, WeaponSpec spec, Transform model) { Avatar avatar = equippable.avatar; if (!IsLongGun(spec) || (Object)(object)((avatar != null) ? avatar.Animation : null) == (Object)null) { return; } IntPtr pointer = ((Il2CppObjectBase)avatar.Animation).Pointer; if (Avatars.TryGetValue(pointer, out SupportState value)) { if (value.Matches(avatar, model)) { return; } value.Release(); } SupportState supportState = SupportState.TryCreate(avatar, avatar.Animation._animator, model, spec, equippable); if (supportState != null) { Avatars[pointer] = supportState; } } internal static void ClearAvatar(Avatar? avatar) { if (!((Object)(object)((avatar != null) ? avatar.Animation : null) == (Object)null) && Avatars.Remove(((Il2CppObjectBase)avatar.Animation).Pointer, out SupportState value)) { value.Release(); } } private static void AfterAvatarAnimation(AvatarAnimation __instance) { if (!Avatars.TryGetValue(((Il2CppObjectBase)__instance).Pointer, out SupportState value)) { return; } try { if (!value.IsEquipped()) { value.Release(); Avatars.Remove(((Il2CppObjectBase)__instance).Pointer); } else { value.Apply(); } } catch (Exception ex) { value.Release(); Avatars.Remove(((Il2CppObjectBase)__instance).Pointer); Warn(ex); } } public static void Reset() { ClearFirstPerson(); foreach (SupportState value in Avatars.Values) { value.Release(); } Avatars.Clear(); failures = 0; } private static void ClearFirstPerson() { firstPersonState?.Release(); firstPersonState = null; firstPersonWeapon = null; } private static void Warn(Exception ex) { if (failures++ < 3) { MelonLogger.Warning("Long-gun support hand could not update: " + ex.GetType().Name + ": " + ex.Message); } } } internal static class ModelIcons { private const int Resolution = 256; internal static Sprite Render(string id, bool ammo) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0040: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00e0: 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_011e: Expected O, but got Unknown //IL_0167: 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) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) Vector3 previewDirection = RuntimePreviewGenerator.PreviewDirection; float padding = RuntimePreviewGenerator.Padding; Color backgroundColor = RuntimePreviewGenerator.BackgroundColor; bool orthographicMode = RuntimePreviewGenerator.OrthographicMode; bool useLocalBounds = RuntimePreviewGenerator.UseLocalBounds; float renderSupersampling = RuntimePreviewGenerator.RenderSupersampling; bool markTextureNonReadable = RuntimePreviewGenerator.MarkTextureNonReadable; Camera previewRenderCamera = RuntimePreviewGenerator.PreviewRenderCamera; Camera renderCamera = RuntimePreviewGenerator.renderCamera; Vector3 camPos = RuntimePreviewGenerator.CamPos; Quaternion camRot = RuntimePreviewGenerator.CamRot; GameObject val = null; GameObject val2 = null; GameObject val3 = null; Texture2D val4 = null; try { val = (ammo ? WeaponVisuals.BuildAmmo(id, null) : WeaponVisuals.Build(id, null)); ((Object)val).hideFlags = (HideFlags)61; val.transform.rotation = (ammo ? Quaternion.Euler(-28f, 0f, 0f) : Quaternion.Euler(-32f, 0f, 0f)); val.transform.position = RuntimePreviewGenerator.PREVIEW_POSITION; RuntimePreviewGenerator.PreviewDirection = new Vector3(-1f, -0.18f, -0.15f); RuntimePreviewGenerator.Padding = 0.12f; RuntimePreviewGenerator.BackgroundColor = Color.clear; RuntimePreviewGenerator.OrthographicMode = true; RuntimePreviewGenerator.UseLocalBounds = false; RuntimePreviewGenerator.RenderSupersampling = 2f; RuntimePreviewGenerator.MarkTextureNonReadable = false; RuntimePreviewGenerator.SetLayerRecursively(val.transform); val3 = new GameObject("EndgameArsenal_PortraitCamera"); ((Object)val3).hideFlags = (HideFlags)61; Camera val5 = val3.AddComponent<Camera>(); ((Behaviour)val5).enabled = false; val5.orthographic = true; val5.aspect = 1f; val5.cullingMask = 1 << RuntimePreviewGenerator.PREVIEW_LAYER; val5.clearFlags = (CameraClearFlags)2; val5.backgroundColor = Color.clear; val5.nearClipPlane = 0.01f; val5.allowHDR = false; val5.allowMSAA = false; ((Component)val5).transform.rotation = Quaternion.LookRotation(RuntimePreviewGenerator.PreviewDirection, Vector3.up); Bounds val6 = default(Bounds); if (!RuntimePreviewGenerator.CalculateBounds(val.transform, true, ((Component)val5).transform.rotation, ref val6)) { throw new InvalidOperationException("Item portrait model has no visible render bounds."); } RuntimePreviewGenerator.CalculateCameraPosition(val5, val6, RuntimePreviewGenerator.Padding); RuntimePreviewGenerator.PreviewRenderCamera = val5; RuntimePreviewGenerator.CamPos = ((Component)val5).transform.position; RuntimePreviewGenerator.CamRot = ((Component)val5).transform.rotation; ValidateFraming(val5, val.transform); val2 = new GameObject("EndgameArsenal_PortraitLighting"); ((Object)val2).hideFlags = (HideFlags)61; AddLight(val2.transform, "Key", new Vector3(45f, -45f, 0f), 1.55f); AddLight(val2.transform, "Fill", new Vector3(325f, 145f, 0f), 0.65f); val4 = RuntimePreviewGenerator.GenerateModelPreview(val.transform, 256, 256, false, true); if ((Object)(object)val4 == (Object)null) { throw new InvalidOperationException("Native item portrait renderer returned no texture."); } bool flag = false; Il2CppStructArray<Color32> pixels = val4.GetPixels32(); foreach (Color32 item in (Il2CppArrayBase<Color32>)(object)pixels) { if (item.a > 32) { flag = true; break; } } if (!flag) { throw new InvalidOperationException("Native item portrait renderer returned a blank image for " + id + "; model layer and camera framing were validated."); } if (((Il2CppArrayBase<Color32>)(object)pixels)[0].a > 8 || ((Il2CppArrayBase<Color32>)(object)pixels)[((Texture)val4).width - 1].a > 8 || ((Il2CppArrayBase<Color32>)(object)pixels)[((Il2CppArrayBase<Color32>)(object)pixels).Length - 1].a > 8) { throw new InvalidOperationException("Native item portrait renderer did not preserve the transparent background."); } ((Object)val4).name = id + (ammo ? "_ammo" : "_weapon") + "_ModelPortrait"; ((Object)val4).hideFlags = (HideFlags)61; ((Texture)val4).filterMode = (FilterMode)1; ((Texture)val4).wrapMode = (TextureWrapMode)1; val4.Apply(false, true); Sprite obj = Sprite.Create(val4, new Rect(0f, 0f, (float)((Texture)val4).width, (float)((Texture)val4).height), new Vector2(0.5f, 0.5f), 256f); ((Object)obj).name = ((Object)val4).name + "_Sprite"; ((Object)obj).hideFlags = (HideFlags)61; val4 = null; return obj; } finally { RuntimePreviewGenerator.PreviewDirection = previewDirection; RuntimePreviewGenerator.Padding = padding; RuntimePreviewGenerator.BackgroundColor = backgroundColor; RuntimePreviewGenerator.OrthographicMode = orthographicMode; RuntimePreviewGenerator.UseLocalBounds = useLocalBounds; RuntimePreviewGenerator.RenderSupersampling = renderSupersampling; RuntimePreviewGenerator.MarkTextureNonReadable = markTextureNonReadable; RuntimePreviewGenerator.PreviewRenderCamera = previewRenderCamera; RuntimePreviewGenerator.renderCamera = renderCamera; RuntimePreviewGenerator.CamPos = camPos; RuntimePreviewGenerator.CamRot = camRot; if ((Object)(object)val3 != (Object)null) { val3.SetActive(false); Object.Destroy((Object)(object)val3); } if ((Object)(object)val2 != (Object)null) { val2.SetActive(false); Object.Destroy((Object)(object)val2); } if ((Object)(object)val != (Object)null) { val.SetActive(false); Object.Destroy((Object)(object)val); } if ((Object)(object)val4 != (Object)null) { Object.Destroy((Object)(object)val4); } } } private static void ValidateFraming(Camera camera, Transform model) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_006d: 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_0088: 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_00a2: Unknown result type (might be due to invalid IL or missing references) bool flag = false; foreach (Renderer componentsInChild in ((Component)model).GetComponentsInChildren<Renderer>(true)) { if (componentsInChild.enabled && ((Component)componentsInChild).gameObject.activeInHierarchy) { if ((camera.cullingMask & (1 << ((Component)componentsInChild).gameObject.layer)) == 0) { throw new InvalidOperationException("Item portrait camera excludes a model renderer's layer."); } Bounds bounds = componentsInChild.bounds; Vector3 val = camera.WorldToViewportPoint(((Bounds)(ref bounds)).center); if (val.z > camera.nearClipPlane && val.x >= 0f && val.x <= 1f && val.y >= 0f && val.y <= 1f) { flag = true; } } } if (!flag) { throw new InvalidOperationException("Item portrait model is outside its calculated camera frame."); } } private static void AddLight(Transform parent, string name, Vector3 rotation, float intensity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.transform.rotation = Quaternion.Euler(rotation); Light obj = val.AddComponent<Light>(); obj.type = (LightType)1; obj.color = Color.white; obj.intensity = intensity; obj.shadows = (LightShadows)0; obj.cullingMask = 1 << RuntimePreviewGenerator.PREVIEW_LAYER; } } internal static class RegistryAndShop { private static readonly Dictionary<string, IntegerItemDefinition> definitions = new Dictionary<string, IntegerItemDefinition>(StringComparer.Ordinal); private static readonly HashSet<string> modelPortraits = new HashSet<string>(StringComparer.Ordinal); private static readonly HashSet<string> itemIds = new HashSet<string>(WeaponCatalog.All.SelectMany((WeaponSpec spec) => new string[2] { spec.Id, spec.AmmoId }), StringComparer.Ordinal); private static readonly Dictionary<string, (FullRank Rank, Unlockable Unlock)> ownedUnlocks = new Dictionary<string, (FullRank, Unlockable)>(StringComparer.Ordinal); private static ArsenalSettings? settings; private static IntPtr unlockManagerPointer; private static GameObject? prototypes; private static bool registering; private static int hookFailures; private static int portraitFailures; private static float nextPortraitAttempt; public static string BaseAvatarAssetPath { get; private set; } = "Avatar/Equippables/M1911"; public static bool PortraitsComplete => modelPortraits.Count == WeaponCatalog.All.Length * 2; public static void BindSettings(ArsenalSettings value) { settings = value; } public static void Initialize(Harmony harmony) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(Registry), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(RegistryAndShop), "RegistryAwake", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Registry), "_GetItem", new Type[2] { typeof(string), typeof(bool) }, (Type[])null), new HarmonyMethod(typeof(RegistryAndShop), "BeforeLookup", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static void RegistryAwake(Registry __instance) { RegisterFromHook(__instance); } private static void BeforeLookup(Registry __instance, string ID) { if (IsArsenalId(ID)) { RegisterFromHook(__instance); } } private static void RegisterFromHook(Registry registry) { try { TryRegister(registry); } catch (Exception ex) { if (hookFailures++ < 3) { MelonLogger.Warning("Endgame Arsenal registration will retry: " + ex.GetType().Name + ": " + ex.Message); } } } public static bool TryRegister() { return TryRegister(Singleton<Registry>.Instance); } private static bool TryRegister(Registry? registry) { //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown if (registering || (Object)(object)registry == (Object)null || registry.ItemDictionary == null) { return false; } registering = true; try { if (definitions.Count == WeaponCatalog.All.Length * 2) { bool flag = true; foreach (IntegerItemDefinition value2 in definitions.Values) { if ((Object)(object)value2 == (Object)null || !Registry.ItemExists(((BaseItemDefinition)value2).ID)) { flag = false; break; } } if (flag) { return true; } } IntegerItemDefinition val = Resources.Load<IntegerItemDefinition>("Weapons/M1911/M1911"); if ((Object)(object)val == (Object)null) { return false; } Equippable equippable = ((ItemDefinition)val).Equippable; Equippable_RangedWeapon val2 = ((equippable != null) ? ((Il2CppObjectBase)equippable).TryCast<Equippable_RangedWeapon>() : null); object obj; if (val2 == null) { obj = null; } else { StorableItemDefinition magazine = val2.Magazine; obj = ((magazine != null) ? ((Il2CppObjectBase)magazine).TryCast<IntegerItemDefinition>() : null); } IntegerItemDefinition val3 = (IntegerItemDefinition)obj; if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)((StorableItemDefinition)val).StoredItem == (Object)null || (Object)(object)((StorableItemDefinition)val3).StoredItem == (Object)null) { return false; } if ((Object)(object)prototypes == (Object)null) { prototypes = new GameObject("EndgameArsenal_Prototypes"); prototypes.SetActive(false); Object.DontDestroyOnLoad((Object)(object)prototypes); } if ((Object)(object)((Equippable_Viewmodel)val2).AvatarEquippable != (Object)null && !string.IsNullOrWhiteSpace(((Equippable_Viewmodel)val2).AvatarEquippable.AssetPath)) { BaseAvatarAssetPath = ((Equippable_Viewmodel)val2).AvatarEquippable.AssetPath; } WeaponSpec[] all = WeaponCatalog.All; foreach (WeaponSpec weaponSpec in all) { if (!definitions.TryGetValue(weaponSpec.Id, out IntegerItemDefinition value) || (Object)(object)value == (Object)null) { BuildDefinitions(weaponSpec, val, val2, val3); } AddIfMissing(registry, definitions[weaponSpec.AmmoId]); AddIfMissing(registry, definitions[weaponSpec.Id]); } hookFailures = 0; return true; } finally { registering = false; } } private static void AddIfMissing(Registry registry, IntegerItemDefinition definition) { if (!Registry.ItemExists(((BaseItemDefinition)definition).ID)) { registry.AddToRegistry((ItemDefinition)(object)definition); } } private static void BuildDefinitions(WeaponSpec spec, IntegerItemDefinition template, Equippable_RangedWeapon weaponTemplate, IntegerItemDefinition ammoTemplate) { IntegerItemDefinition val = Object.Instantiate<IntegerItemDefinition>(ammoTemplate); ConfigureDefinition(val, spec, ammo: true); val.DefaultValue = spec.Capacity; ((StorableItemDefinition)val).StoredItem = CloneStored(((StorableItemDefinition)ammoTemplate).StoredItem, spec, customGunModel: false); if ((Object)(object)((ItemDefinition)ammoTemplate).Equippable != (Object)null) { GameObject val2 = ClonePrototype(((Component)((ItemDefinition)ammoTemplate).Equippable).gameObject, spec.AmmoId + "_Equippable"); HideRenderers(val2.transform); WeaponVisuals.BuildAmmo(spec.Id, val2.transform); ((ItemDefinition)val).Equippable = val2.GetComponent<Equippable>(); } IntegerItemDefinition val3 = Object.Instantiate<IntegerItemDefinition>(template); ConfigureDefinition(val3, spec, ammo: false); val3.DefaultValue = spec.Capacity; ((StorableItemDefinition)val3).StoredItem = CloneStored(((StorableItemDefinition)template).StoredItem, spec, customGunModel: true); GameObject val4 = ClonePrototype(((Component)weaponTemplate).gameObject, spec.Id + "_Equippable"); Equippable_RangedWeapon component = val4.GetComponent<Equippable_RangedWeapon>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Native M1911 clone has no ranged weapon component."); } HideRenderers(val4.transform); WeaponVisuals.Build(spec.Id, val4.transform); if ((Object)(object)((Equippable_Viewmodel)weaponTemplate).AvatarEquippable != (Object)null) { AvatarEquippable component2 = ClonePrototype(((Component)((Equippable_Viewmodel)weaponTemplate).AvatarEquippable).gameObject, spec.Id + "_AvatarEquippable").GetComponent<AvatarEquippable>(); component2.AssetPath = "EndgameArsenal/" + spec.Id; ((Equippable_Viewmodel)component).AvatarEquippable = component2; } WeaponBehavior.Configure(component, spec, (StorableItemDefinition)(object)val); ((ItemDefinition)val3).Equippable = (Equippable)(object)component; definitions[spec.AmmoId] = val; definitions[spec.Id] = val3; } private static void ConfigureDefinition(IntegerItemDefinition definition, WeaponSpec spec, bool ammo) { ((Object)definition).name = (ammo ? spec.AmmoId : spec.Id); ((BaseItemDefinition)definition).ID = (ammo ? spec.AmmoId : spec.Id); ((BaseItemDefinition)definition).Name = (ammo ? spec.AmmoName : spec.Name); ((BaseItemDefinition)definition).StackLimit = 1; ApplyDefinitionSettings(definition, spec, ammo); ((BaseItemDefinition)definition).UsableInFilters = true; ((Object)definition).hideFlags = (HideFlags)32; } private static void ApplyDefinitionSettings(IntegerItemDefinition definition, WeaponSpec spec, bool ammo) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) WeaponShopSettings weaponShopSettings = settings?.For(spec) ?? new WeaponShopSettings(spec.Rank, spec.Tier, spec.Price, spec.AmmoPrice); FullRank val = new FullRank { Rank = (ERank)weaponShopSettings.Rank, Tier = weaponShopSettings.Tier }; ((StorableItemDefinition)definition).BasePurchasePrice = (ammo ? weaponShopSettings.AmmoPrice : weaponShopSettings.Price); ((StorableItemDefinition)definition).RequiresLevelToPurchase = true; ((StorableItemDefinition)definition).RequiredRank = val; ((BaseItemDefinition)definition).Description = (ammo ? $"A {spec.Capacity}-round magazine of ammunition for the {spec.Name}. Compatible only with this weapon." : $"{spec.Name}. Holds {spec.Capacity} rounds and uses {spec.AmmoName}. Available from Stan at {RankLabel(val)}."); } private unsafe static string RankLabel(FullRank rank) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) return ((object)(*(ERank*)(&rank.Rank))/*cast due to .constrained prefix*/).ToString().Replace('_', ' ') + " " + (new string[6] { "", "I", "II", "III", "IV", "V" })[rank.Tier]; } private static GameObject ClonePrototype(GameObject original, string name) { GameObject obj = Object.Instantiate<GameObject>(original, prototypes.transform, false); ((Object)obj).name = name; obj.SetActive(true); return obj; } private static StoredItem CloneStored(StoredItem original, WeaponSpec spec, bool customGunModel) { GameObject val = ClonePrototype(((Component)original).gameObject, (customGunModel ? spec.Id : spec.AmmoId) + "_Stored"); StoredItem component = val.GetComponent<StoredItem>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Native item clone has no storage component."); } HideRenderers(val.transform); if (customGunModel) { WeaponVisuals.Build(spec.Id, val.transform); return component; } WeaponVisuals.BuildAmmo(spec.Id, val.transform); return component; } private static void HideRenderers(Transform parent) { foreach (Renderer componentsInChild in ((Component)parent).GetComponentsInChildren<Renderer>(true)) { componentsInChild.enabled = false; } } private static bool IsArsenalId(string? id) { if (id != null) { return itemIds.Contains(id); } return false; } public static StorableItemDefinition? GetDefinition(string id) { if (!definitions.TryGetValue(id, out IntegerItemDefinition value)) { return null; } return (StorableItemDefinition?)(object)value; } public static bool TryAddToStan() { if (!TryRegister()) { return false; } ShopInterface shop = FindStanShop(); if ((Object)(object)shop == (Object)null || shop.Listings == null || (Object)(object)shop.ListingContainer == (Object)null) { return false; } bool unlocksRegistered = false; ShopInitialization.Complete(delegate { bool flag = false; WeaponSpec[] all = WeaponCatalog.All; foreach (WeaponSpec weaponSpec in all) { flag |= AddListing(shop, (StorableItemDefinition)(object)definitions[weaponSpec.Id]); flag |= AddListing(shop, (StorableItemDefinition)(object)definitions[weaponSpec.AmmoId]); } if (flag) { shop.RefreshUnlockStatus(); shop.RefreshShownItems(); } unlocksRegistered = RegisterUnlocks(); }, RefreshModelPortraits, ReportPortraitFailure); return unlocksRegistered; } private static ShopInterface? FindStanShop() { foreach (Stan item in Resources.FindObjectsOfTypeAll<Stan>()) { if ((Object)(object)item != (Object)null && (Object)(object)item.ShopInterface != (Object)null) { return item.ShopInterface; } } GameObject obj = GameObject.Find("ArmsDealerInterface"); if (obj == null) { return null; } return obj.GetComponent<ShopInterface>(); } public static bool ApplySettings() { if (settings == null || definitions.Count != WeaponCatalog.All.Length * 2) { return false; } WeaponSpec[] all = WeaponCatalog.All; foreach (WeaponSpec weaponSpec in all) { ApplyDefinitionSettings(definitions[weaponSpec.Id], weaponSpec, ammo: false); ApplyDefinitionSettings(definitions[weaponSpec.AmmoId], weaponSpec, ammo: true); } ShopInterface val = FindStanShop(); if ((Object)(object)val == (Object)null || val.Listings == null || !RegisterUnlocks()) { return false; } Cart cart = val.Cart; if ((Object)(object)cart != (Object)null) { Enumerator<ShopListing> enumerator = val.Listings.GetEnumerator(); while (enumerator.MoveNext()) { ShopListing current = enumerator.Current; if ((Object)(object)((current != null) ? current.Item : null) != (Object)null && IsArsenalId(((BaseItemDefinition)current.Item).ID) && cart.GetCartCount(current) > 0 && !current.Item.IsUnlocked) { cart.RemoveListing(current); } } if (cart.cartEntries != null) { Enumerator<CartEntry> enumerator2 = cart.cartEntries.GetEnumerator(); while (enumerator2.MoveNext()) { CartEntry current2 = enumerator2.Current; object obj; if (current2 == null) { obj = null; } else { ShopListing listing = current2.Listing; obj = ((listing != null) ? listing.Item : null); } if ((Object)obj != (Object)null && IsArsenalId(((BaseItemDefinition)current2.Listing.Item).ID)) { current2.UpdatePrice(); } } } cart.UpdateTotal(); cart.UpdateProblem(); } val.RefreshUnlockStatus(); if (val.listingUI != null) { Enumerator<ListingUI> enumerator3 = val.listingUI.GetEnumerator(); while (enumerator3.MoveNext()) { ListingUI current3 = enumerator3.Current; object obj2; if (current3 == null) { obj2 = null; } else { ShopListing listing2 = current3.Listing; obj2 = ((listing2 != null) ? listing2.Item : null); } if ((Object)obj2 != (Object)null && IsArsenalId(((BaseItemDefinition)current3.Listing.Item).ID)) { current3.UpdatePrice(); current3.UpdateButtons(); } } } val.RefreshShownItems(); ShopInterfaceDetailPanel detailPanel = val.DetailPanel; if ((Object)(object)((detailPanel != null) ? detailPanel.Panel : null) != (Object)null && ((Component)detailPanel.Panel).gameObject.activeSelf) { ListingUI listingUI = detailPanel._listingUI; object obj3; if (listingUI == null) { obj3 = null; } else { ShopListing listing3 = listingUI.Listing; obj3 = ((listing3 != null) ? listing3.Item : null); } if ((Object)obj3 != (Object)null && IsArsenalId(((BaseItemDefinition)detailPanel._listingUI.Listing.Item).ID)) { detailPanel.Open(detailPanel._listingUI); } } return true; } public static void RetryModelPortraits() { ShopInitialization.RefreshOptional(RefreshModelPortraits, ReportPortraitFailure); } private static void RefreshModelPortraits() { if (PortraitsComplete || Time.unscaledTime < nextPortraitAttempt) { return; } nextPortraitAttempt = Time.unscaledTime + 5f; bool changed = false; WeaponSpec[] all = WeaponCatalog.All; foreach (WeaponSpec spec in all) { ShopInitialization.RefreshOptional(delegate { if (!modelPortraits.Contains(spec.Id)) { ((BaseItemDefinition)definitions[spec.Id]).Icon = WeaponVisuals.Icon(spec.Id, ammo: false); modelPortraits.Add(spec.Id); changed = true; } }, ReportPortraitFailure); ShopInitialization.RefreshOptional(delegate { if (!modelPortraits.Contains(spec.AmmoId)) { ((BaseItemDefinition)definitions[spec.AmmoId]).Icon = WeaponVisuals.Icon(spec.Id, ammo: true); modelPortraits.Add(spec.AmmoId); changed = true; } }, ReportPortraitFailure); } if (!changed) { return; } foreach (ListingUI item in Resources.FindObjectsOfTypeAll<ListingUI>()) { object obj; if (item == null) { obj = null; } else { ShopListing listing = item.Listing; obj = ((listing != null) ? listing.Item : null); } StorableItemDefinition val = (StorableItemDefinition)obj; if ((Object)(object)val != (Object)null && IsArsenalId(((BaseItemDefinition)val).ID) && (Object)(object)item.Icon != (Object)null) { item.Icon.sprite = ((BaseItemDefinition)val).Icon; } } foreach (ItemUI item2 in Resources.FindObjectsOfTypeAll<ItemUI>()) { object obj2; if (item2 == null) { obj2 = null; } else { ItemInstance itemInstance = item2.itemInstance; obj2 = ((itemInstance != null) ? itemInstance.Definition : null); } ItemDefinition val2 = (ItemDefinition)obj2; if ((Object)(object)val2 != (Object)null && IsArsenalId(((BaseItemDefinition)val2).ID) && (Object)(object)item2.IconImg != (Object)null) { item2.IconImg.sprite = ((BaseItemDefinition)val2).Icon; } } LevelManager instance = NetworkSingleton<LevelManager>.Instance; if ((Object)(object)instance == (Object)null || unlockManagerPointer != ((Il2CppObjectBase)instance).Pointer) { return; } foreach (KeyValuePair<string, (FullRank, Unlockable)> ownedUnlock in ownedUnlocks) { if (definitions.TryGetValue(ownedUnlock.Key, out IntegerItemDefinition value) && (Object)(object)value != (Object)null) { ownedUnlock.Value.Item2.Icon = ((BaseItemDefinition)value).Icon; } } } private static void ReportPortraitFailure(Exception ex) { if (portraitFailures++ < 3) { MelonLogger.Warning("Arsenal portrait update will retry; Stan's items remain available: " + ex.GetType().Name + ": " + ex.Message); } } private static bool AddListing(ShopInterface shop, StorableItemDefinition definition) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) //IL_002f: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (shop.GetListing(((BaseItemDefinition)definition).ID) != null) { return false; } ShopListing val = new ShopListing { name = ((BaseItemDefinition)definition).Name, Item = definition, OverridePrice = false, LimitedStock = false, DefaultStock = 0, RestockRate = (ERestockRate)2, CanBeDelivered = false, ConditionalVisibility = false }; shop.Listings.Add(val); val.Initialize(shop); shop.CreateListingUI(val); return true; } private static bool RegisterUnlocks() { //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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) //IL_0088: 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_00cd: 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_0091: 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_0130: 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) LevelManager instance = NetworkSingleton<LevelManager>.Instance; if ((Object)(object)instance == (Object)null || instance.Unlockables == null) { return false; } if (unlockManagerPointer != ((Il2CppObjectBase)instance).Pointer) { ownedUnlocks.Clear(); unlockManagerPointer = ((Il2CppObjectBase)instance).Pointer; } foreach (IntegerItemDefinition value2 in definitions.Values) { FullRank requiredRank = ((StorableItemDefinition)value2).RequiredRank; Unlockable val; if (ownedUnlocks.TryGetValue(((BaseItemDefinition)value2).ID, out (FullRank, Unlockable) value)) { if (value.Item1.Rank == requiredRank.Rank && value.Item1.Tier == requiredRank.Tier && ContainsUnlock(instance, requiredRank, value.Item2)) { value.Item2.Icon = ((BaseItemDefinition)value2).Icon; continue; } RemoveOwnedUnlock(instance, value.Item1, value.Item2); val = value.Item2; val.Rank = requiredRank; val.Icon = ((BaseItemDefinition)value2).Icon; } else { val = new Unlockable(requiredRank, ((BaseItemDefinition)value2).Name, ((BaseItemDefinition)value2).Icon); } instance.AddUnlockable(val); if (ContainsUnlock(instance, requiredRank, val)) { ownedUnlocks[((BaseItemDefinition)value2).ID] = (requiredRank, val); } else { ownedUnlocks.Remove(((BaseItemDefinition)value2).ID); } } return true; } private static bool ContainsUnlock(LevelManager manager, FullRank rank, Unlockable unlock) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!manager.Unlockables.ContainsKey(rank)) { return false; } Enumerator<Unlockable> enumerator = manager.Unlockables[rank].GetEnumerator(); while (enumerator.MoveNext()) { Unlockable current = enumerator.Current; if (current != null && ((Il2CppObjectBase)current).Pointer == ((Il2CppObjectBase)unlock).Pointer) { return true; } } return false; } private static void RemoveOwnedUnlock(LevelManager manager, FullRank rank, Unlockable unlock) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!manager.Unlockables.ContainsKey(rank)) { return; } List<Unlockable> val = manager.Unlockables[rank]; for (int num = val.Count - 1; num >= 0; num--) { if (val[num] != null && ((Il2CppObjectBase)val[num]).Pointer == ((Il2CppObjectBase)unlock).Pointer) { val.RemoveAt(num); } } } } internal sealed class ScopeOverlay : IDisposable { private readonly GameObject root; private readonly RectTransform eyepiece; private readonly RectTransform[] shades = (RectTransform[])(object)new RectTransform[4]; private readonly RectTransform labelRect; private readonly Text label; private Texture2D? lensTexture; private Texture2D? blackTexture; private bool disposed; private int width; private int height; private float magnification = -1f; internal bool IsAlive { get { if (!disposed) { return (Object)(object)root != (Object)null; } return false; } } internal bool IsVisible { get { if (IsAlive) { return root.activeSelf; } return false; } } internal ScopeOverlay() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) root = new GameObject("Endgame Arsenal Sniper Eyepiece"); try { root.AddComponent<RectTransform>(); Canvas obj = root.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 250; CanvasGroup obj2 = root.AddComponent<CanvasGroup>(); obj2.interactable = false; obj2.blocksRaycasts = false; root.SetActive(false); blackTexture = MakeTexture("EndgameArsenal_ScopeOutside", 1, new byte[4] { 0, 0, 0, 255 }); lensTexture = MakeTexture("EndgameArsenal_ScopeEyepiece", 1024, ScopeOverlayPixels.Generate()); for (int i = 0; i < shades.Length; i++) { shades[i] = MakeImage("Opaque outside " + i, root.transform, (Texture)(object)blackTexture); } eyepiece = MakeImage("Lens and reticle", root.transform, (Texture)(object)lensTexture); labelRect = NewRect("Magnification", root.transform); label = ((Component)labelRect).gameObject.AddComponent<Text>(); ((Graphic)label).raycastTarget = false; label.alignment = (TextAnchor)4; ((Graphic)label).color = new Color(0.79f, 0.83f, 0.84f, 1f); label.supportRichText = false; label.horizontalOverflow = (HorizontalWrapMode)1; label.verticalOverflow = (VerticalWrapMode)1; HUD instance = Singleton<HUD>.Instance; label.font = (((Object)(object)instance != (Object)null && (Object)(object)instance.fpsLabel != (Object)null && (Object)(object)instance.fpsLabel.font != (Object)null) ? instance.fpsLabel.font : Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf")); } catch { Dispose(); throw; } } internal void Show(float zoom) { if (!IsAlive) { return; } int num = Screen.width; int num2 = Screen.height; if (num <= 0 || num2 <= 0) { Hide(); return; } if (num != width || num2 != height) { width = num; height = num2; float num3 = (float)Math.Min(width, height) * 0.9f; float num4 = ((float)width - num3) * 0.5f; float num5 = ((float)height - num3) * 0.5f; Layout(eyepiece, 0f, 0f, num3, num3); Layout(shades[0], 0f, (num3 + num5) * 0.5f, width, num5); Layout(shades[1], 0f, (0f - (num3 + num5)) * 0.5f, width, num5); Layout(shades[2], (0f - (num3 + num4)) * 0.5f, 0f, num4, num3); Layout(shades[3], (num3 + num4) * 0.5f, 0f, num4, num3); label.fontSize = (int)Math.Clamp(Math.Round((double)height / 60.0), 13.0, 24.0); Layout(labelRect, 0f, (0f - num3) * 0.5f - num5 * 0.5f, Math.Max(num3, 280f), Math.Max(num5, (float)label.fontSize * 1.8f)); } if (magnification != zoom) { magnification = zoom; label.text = $"{zoom:0}× · Scroll to zoom"; } if (!root.activeSelf) { root.SetActive(true); } } internal void Hide() { if (IsAlive && root.activeSelf) { root.SetActive(false); } } public void Dispose() { if (!disposed) { disposed = true; if ((Object)(object)root != (Object)null) { root.SetActive(false); Object.Destroy((Object)(object)root); } if ((Object)(object)lensTexture != (Object)null) { Object.Destroy((Object)(object)lensTexture); } if ((Object)(object)blackTexture != (Object)null) { Object.Destroy((Object)(object)blackTexture); } lensTexture = null; blackTexture = null; } } private static RectTransform NewRect(string name, Transform parent) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0035: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = new GameObject(name).AddComponent<RectTransform>(); ((Transform)obj).SetParent(parent, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); obj.pivot = val; Vector2 anchorMin = (obj.anchorMax = val); obj.anchorMin = anchorMin; return obj; } private static RectTransform MakeImage(string name, Transform parent, Texture texture) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = NewRect(name, parent); RawImage obj2 = ((Component)obj).gameObject.AddComponent<RawImage>(); obj2.texture = texture; ((Graphic)obj2).color = Color.white; ((Graphic)obj2).raycastTarget = false; return obj; } private static void Layout(RectTransform rect, float x, float y, float width, float height) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) rect.anchoredPosition = new Vector2(x, y); rect.sizeDelta = new Vector2(width, height); } private static Texture2D MakeTexture(string name, int side, byte[] rgba) { //IL_0004: 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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0027: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(side, side, (TextureFormat)4, false) { name = name, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)32 }; try { Il2CppStructArray<Color32> val2 = new Il2CppStructArray<Color32>((long)(side * side)); for (int i = 0; i < ((Il2CppArrayBase<Color32>)(object)val2).Length; i++) { int num = i * 4; ((Il2CppArrayBase<Color32>)(object)val2)[i] = new Color32(rgba[num], rgba[num + 1], rgba[num + 2], rgba[num + 3]); } val.SetPixels32(val2); val.Apply(false, true); return val; } catch { Object.Destroy((Object)(object)val); throw; } } } internal static class ScopeOverlayPixels { internal const int Size = 1024; private const double LensRadius = 0.851; internal static byte[] Generate() { byte[] array = new byte[4194304]; for (int i = 0; i < 1024; i++) { for (int j = 0; j < 1024; j++) { double num = ((double)j + 0.5 - 512.0) / 512.0; double num2 = ((double)i + 0.5 - 512.0) / 512.0; double num3 = Math.Sqrt(num * num + num2 * num2); int at = (i * 1024 + j) * 4; if (num3 >= 0.851) { Ring(array, at, num, num2, num3); continue; } double num4 = Smooth((num3 - 0.69) / 0.16100000000000003); Set(array, at, 3, 9, 12, (int)(num4 * num4 * 202.0)); double a = Math.Atan2(num2, num); double alpha = Gaussian((num3 - 0.814) / 0.014) * (Gaussian(AngleDistance(a, 2.24) / 0.36) * 0.24 + Gaussian(AngleDistance(a, -0.86) / 0.46) * 0.1); Blend(array, at, 103, 145, 158, alpha); Reticle(array, at, num, num2); } } return array; } private static void Ring(byte[] rgba, int at, double dx, double dy, double r) { if (r >= 0.985) { Set(rgba, at, 0, 0, 0, 255); return; } double num = Math.Clamp((0.0 - dx + dy) / Math.Max(r, 0.001) * 0.46 + 0.36, 0.0, 1.0); double num2; double num3; if (r >= 0.97) { num2 = 4.0 + Smooth((0.985 - r) / 0.015) * (10.0 + num * 15.0); num3 = 1.0; } else if (r >= 0.913) { double num4 = 0.5 + 0.5 * Math.Cos((r - 0.913) * 920.0); num2 = 13.0 + num * 10.0 - num4 * 5.0; num3 = 1.0; } else if (r >= 0.898) { double num5 = Math.Sin((r - 0.898) / 0.015 * Math.PI); num2 = 21.0 + num5 * (8.0 + num * 30.0); num3 = 4.0; } else if (r >= 0.863) { double num6 = (r - 0.863) / 0.035; num2 = 4.0 + num6 * num6 * (12.0 + num * 12.0); num3 = 2.0; } else { double num7 = Gaussian((r - 0.857) / 0.0025); num2 = 4.0 + num7 * (10.0 + num * 18.0); num3 = 2.0; } Set(rgba, at, (int)num2, (int)(num2 + num3), (int)(num2 + num3 * 1.7), 255); } private static void Reticle(byte[] rgba, int at, double x, double y) { double num = Math.Abs(x); double num2 = Math.Abs(y); double val = Math.Max(Coverage(num2, 0.0015) * Smooth((num - 0.012) / 0.004), Coverage(num, 0.0015) * Smooth((num2 - 0.012) / 0.004)); val = Math.Max(val, Coverage(num2, 0.0047) * Smooth((num - 0.62) / 0.025)); val = Math.Max(val, Coverage(num, 0.0047) * Smooth((num2 - 0.62) / 0.025)); val = Math.Max(val, Coverage(Math.Sqrt(x * x + y * y), 0.0032)); for (int i = 1; i <= 5; i++) { double num3 = (double)i * 0.1; double val2 = Math.Sqrt((num - num3) * (num - num3) + y * y); double val3 = Math.Sqrt(x * x + (num2 - num3) * (num2 - num3)); val = Math.Max(val, Coverage(Math.Min(val2, val3), 0.0047)); double num4 = num3 - 0.05; double val4 = Coverage(Math.Abs(num - num4), 0.0011) * Coverage(num2, 0.0095); double val5 = Coverage(Math.Abs(num2 - num4), 0.0011) * Coverage(num, 0.0095); val = Math.Max(val, Math.Max(val4, val5)); } Blend(rgba, at, 8, 10, 10, val * 0.96); } private static double Coverage(double distance, double halfWidth) { return Math.Clamp((halfWidth + 0.0009765625 - distance) * 1024.0 * 0.5, 0.0, 1.0); } private static double Smooth(double value) { value = Math.Clamp(value, 0.0, 1.0); return value * value * (3.0 - 2.0 * value); } private static double Gaussian(double value) { return Math.Exp((0.0 - value) * value * 2.0); } private static double AngleDistance(double a, double b) { double num; for (num = a - b; num > Math.PI; num -= Math.PI * 2.0) { } for (; num < -Math.PI; num += Math.PI * 2.0) { } return num; } private static void Set(byte[] rgba, int at, int r, int g, int b, int a) { rgba[at] = (byte)Math.Clamp(r, 0, 255); rgba[at + 1] = (byte)Math.Clamp(g, 0, 255); rgba[at + 2] = (byte)Math.Clamp(b, 0, 255); rgba[at + 3] = (byte)Math.Clamp(a, 0, 255); } private static void Blend(byte[] rgba, int at, int r, int g, int b, double alpha) { alpha = Math.Clamp(alpha, 0.0, 1.0); if (!(alpha <= 0.0)) { double num = (double)(int)rgba[at + 3] / 255.0; double num2 = alpha + num * (1.0 - alpha); rgba[at] = (byte)Math.Clamp(((double)r * alpha + (double)(int)rgba[at] * num * (1.0 - alpha)) / num2, 0.0, 255.0); rgba[at + 1] = (byte)Math.Clamp(((double)g * alpha + (double)(int)rgba[at + 1] * num * (1.0 - alpha)) / num2, 0.0, 255.0); rgba[at + 2] = (byte)Math.Clamp(((double)b * alpha + (double)(int)rgba[at + 2] * num * (1.0 - alpha)) / num2, 0.0, 255.0); rgba[at + 3] = (byte)(num2 * 255.0); } } } internal static class ScopeZoomPolicy { public static readonly float[] Magnifications = new float[4] { 2f, 4f, 6f, 8f }; public const int DefaultStep = 1; public static int Step(int current, float wheel) { current = Math.Clamp(current, 0, Magnifications.Length - 1); if (float.IsNaN(wheel) || wheel == 0f) { return current; } return Math.Clamp(current + ((wheel > 0f) ? 1 : (-1)), 0, Magnifications.Length - 1); } public static float FieldOfView(float normalFov, float magnification) { if (!float.IsFinite(normalFov)) { normalFov = 75f; } if (!float.IsFinite(magnification)) { magnification = 4f; } normalFov = Math.Clamp(normalFov, 20f, 140f); magnification = Math.Clamp(magnification, 1f, 8f); double num = (double)normalFov * Math.PI / 180.0; return (float)Math.Clamp(2.0 * Math.Atan(Math.Tan(num / 2.0) / (double)magnification) * 180.0 / Math.PI, 5.0, normalFov); } } internal static class ShopInitialization { public static void Complete(Action initializeShop, Action refreshPortraits, Action<Exception> reportPortraitFailure) { initializeShop(); RefreshOptional(refreshPortraits, reportPortraitFailure); } public static void RefreshOptional(Action refresh, Action<Exception> reportFailure) { try { refresh(); } catch (Exception obj) { reportFailure(obj); } } } internal static class SniperChamber { private sealed class Cycle { public Equippable_RangedWeapon? LocalWeapon; public AvatarRangedWeapon? AvatarWeapon; public float Due; public AudioSourceController? Sound; public float End; } private const float ShotDelay = 0.2f; private const string NativeRackPrefab = "Weapons/Shotty/PumpShotgun_Equipped"; private static readonly Dictionary<IntPtr, Cycle> Cycles = new Dictionary<IntPtr, Cycle>(); private static AudioClip? boltClip; private static bool reportedFailure; public static void Initialize(Harmony harmony) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0049: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00a7: 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_00c9: Expected O, but got Unknown //IL_00c9: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(Equippable_RangedWeapon), "Fire", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SniperChamber), "BeforeFire", (Type[])null), new HarmonyMethod(typeof(SniperChamber), "AfterFire", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Equippable_RangedWeapon), "Unequip", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SniperChamber), "BeforeUnequip", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(AvatarRangedWeapon), "Shoot", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SniperChamber), "BeforeAvatarShoot", (Type[])null), new HarmonyMethod(typeof(SniperChamber), "AfterAvatarShoot", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(AvatarRangedWeapon), "Unequip", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SniperChamber), "BeforeAvatarUnequip", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static void BeforeFire(Equippable_RangedWeapon __instance, out int __state) { __state = ((WeaponBehavior.GetSpec(__instance)?.Id == "eg_sniper") ? __instance.Ammo : (-1)); } private static void AfterFire(Equippable_RangedWeapon __instance, int __state) { try { if (__state > 0 && __instance.Ammo < __state) { Schedule(((Il2CppObjectBase)__instance).Pointer, new Cycle { LocalWeapon = __instance }); } } catch (Exception ex) { ReportFailure(ex); } } private static void BeforeUnequip(Equippable_RangedWeapon __instance) { Cancel(((Il2CppObjectBase)__instance).Pointer); } private static void BeforeAvatarShoot(AvatarRangedWeapon __instance, out bool __state) { __state = false; try { if (!(((AvatarEquippable)__instance).AssetPath != "EndgameArsenal/eg_sniper")) { Player local = Player.Local; Avatar val = ((local != null) ? local.Avatar : null); if (!((Object)(object)val != (Object)null) || !((Object)(object)((AvatarEquippable)__instance).avatar != (Object)null) || !(((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)((AvatarEquippable)__instance).avatar).Pointer)) { __state = __instance.timeSinceLastShot > 0f; } } } catch (Exception ex) { ReportFailure(ex); } } private static void AfterAvatarShoot(AvatarRangedWeapon __instance, bool __state) { try { if (__state) { Schedule(((Il2CppObjectBase)__instance).Pointer, new Cycle { AvatarWeapon = __instance }); } } catch (Exception ex) { ReportFailure(ex); } } private static void BeforeAvatarUnequip(AvatarRangedWeapon __instance) { Cancel(((Il2CppObjectBase)__instance).Pointer); } private static void Schedule(IntPtr key, Cycle cycle) { Cancel(key); cycle.Due = Time.time + 0.2f; Cycles[key] = cycle; } public static void Update() { //IL_0133: Unknown result type (might be due to invalid IL or missing references) if (Cycles.Count == 0) { return; } IntPtr[] array = Cycles.Keys.ToArray(); foreach (IntPtr key in array) { Cycle cycle = Cycles[key]; try { if (!StillEquipped(cycle)) { Cancel(key); } else if ((Object)(object)cycle.Sound != (Object)null) { if (Time.time >= cycle.End) { Cancel(key); } } else { if (Time.time < cycle.Due || Time.timeScale <= 0f) { continue; } AudioManager instance = Singleton<AudioManager>.Instance; if ((Object)(object)instance == (Object)null) { Cancel(key); continue; } AudioClip clip = GetClip(); Transform val = (((Object)(object)cycle.LocalWeapon != (Object)null) ? ((Component)cycle.LocalWeapon).transform : ((Component)cycle.AvatarWeapon).transform); float num = Random.Range(0.94f, 1f); AudioSourceController val2 = (cycle.Sound = instance.CreateAudioSourceController((EAudioType)2, clip, 0.13f, (Object)(object)cycle.LocalWeapon == (Object)null)); ((Object)((Component)val2).gameObject).name = "ArsenalSniperBoltSound"; ((Component)val2).transform.SetParent(val, false); ((Component)val2).transform.localPosition = Vector3.zero; val2.SetLoop(false); val2.SetBasePitch(num); val2.SetSpacialBlend(((Object)(object)cycle.LocalWeapon == (Object)null) ? 1f : 0f); val2.ApplyMixer(); AudioSource component = ((Component)val2).GetComponent<AudioSource>(); if ((Object)(object)component != (Object)null) { component.playOnAwake = false; component.dopplerLevel = 0f; component.minDistance = 1.5f; component.maxDistance = 20f; component.rolloffMode = (AudioRolloffMode)0; } val2.Play(); cycle.End = Time.time + clip.length / num + 0.05f; continue; } } catch (Exception ex) { Cancel(key); ReportFailure(ex); } } } private static bool StillEquipped(Cycle cycle) { if ((Object)(object)cycle.LocalWeapon != (Object)null) { Equippable_RangedWeapon localWeapon = cycle.LocalWeapon; PlayerInventory instance = PlayerSingleton<PlayerInventory>.Instance; Equippable val = ((instance != null) ? instance.Equippable : null); if (((Behaviour)localWeapon).isActiveAndEnabled && (Object)(object)val != (Object)null && ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)localWeapon).Pointer && WeaponBehavior.GetSpec(localWeapon)?.Id == "eg_sniper") { return !localWeapon.IsReloading; } return false; } AvatarRangedWeapon avatarWeapon = cycle.AvatarWeapon; if ((Object)(object)avatarWeapon == (Object)null || !((Behaviour)avatarWeapon).isActiveAndEnabled || !((AvatarEquippable)avatarWeapon)._equipped || ((AvatarEquippable)avatarWeapon).AssetPath != "EndgameArsenal/eg_sniper") { return false; } Avatar avatar = ((AvatarEquippable)avatarWeapon).avatar; AvatarEquippable val2 = ((avatar != null) ? avatar.CurrentEquippable : null); if ((Object)(object)val2 != (Object)null) { return ((Il2CppObjectBase)val2).Pointer == ((Il2CppObjectBase)avatarWeapon).Pointer; } return false; } public static void Reset() { IntPtr[] array = Cycles.Keys.ToArray(); for (int i = 0; i < array.Length; i++) { Cancel(array[i]); } boltClip = null; reportedFailure = false; } private static void Cancel(IntPtr key) { if (!Cycles.Remove(key, out Cycle value) || (Object)(object)value.Sound == (Object)null) { return; } try { value.Sound.Stop(); Object.Destroy((Object)(object)((Component)value.Sound).gameObject); } catch { } } private static void ReportFailure(Exception ex) { if (!reportedFailure) { reportedFailure = true; MelonLogger.Warning("Sniper bolt audio could not play: " + ex.GetType().Name + ": " + ex.Message); } } private static AudioClip GetClip() { if ((Object)(object)boltClip != (Object)null) { return boltClip; } GameObject val = Resources.Load<GameObject>("Weapons/Shotty/PumpShotgun_Equipped"); if ((Object)(object)val != (Object)null) { foreach (AudioSource componentsInChild in val.GetComponentsInChildren<AudioSource>(true)) { if (!(((Object)((Component)componentsInChild).gameObject).name != "Cock sound")) { AudioClip clip = componentsInChild.clip; if (!((Object)(object)clip == (Object)null) && !(clip.length <= 0f)) { boltClip = clip; return clip; } } } } throw new InvalidOperationException("The installed pump-action cocking clip could not be found."); } } internal static class SniperScope { private static ScopeOverlay? overlay; private static float nextOverlayAttempt; private static int overlayFailures; private static readonly List<(Renderer Renderer, bool Enabled)> hiddenRenderers = new List<(Renderer, bool)>(); private static IntPtr hiddenWeaponPointer; private static int zoomStep = 1; private static int lastWheelFrame = -1; private static IntPtr equippedPointer; public static void Initialize(Harmony harmony) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(Equippable_RangedWeapon), "UpdateInput", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SniperScope), "BeforeInput", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.PropertyGetter(typeof(GameInput), "MouseScrollDelta"), (HarmonyMethod)null, new HarmonyMethod(typeof(SniperScope), "AfterMouseScroll", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } public static void Reset() { ResetScopeState(); overlay?.Dispose(); overlay = null; nextOverlayAttempt = 0f; overlayFailures = 0; } private static void ResetScopeState() { SniperTargets.Reset(); zoomStep = 1; lastWheelFrame = -1; equippedPointer = IntPtr.Zero; RestoreModel(); overlay?.Hide(); } public static void Update() { Equippable_RangedWeapon val = ActiveSniper(); if (val == null || (Object)(object)val == (Object)null) { if (equippedPointer != IntPtr.Zero) { ResetScopeState(); } return; } if (equippedPointer != ((Il2CppObjectBase)val).Pointer) { ResetScopeState(); equippedPointer = ((Il2CppObjectBase)val).Pointer; } bool flag = ScopeAllowsZoom(val); if (flag) { ReadWheel(); } SniperTargets.UpdateScope(val, flag && val.Aim >= 0.98f); bool scoped = UpdateOverlay(flag && val.Aim >= 0.98f); UpdateModelVisibility(val, scoped); } private static Equippable_RangedWeapon? ActiveSniper() { PlayerInventory instance = PlayerSingleton<PlayerInventory>.Instance; object obj; if (instance == null) { obj = null; } else { Equippable equippable = instance.Equippable; obj = ((equippable != null) ? ((Il2CppObjectBase)equippable).TryCast<Equippable_RangedWeapon>() : null); } Equippable_RangedWeapon val = (Equippable_RangedWeapon)obj; if (val == null || !((Object)(object)val != (Object)null) || !(WeaponBehavior.GetSpec(val)?.Id == "eg_sniper")) { return null; } return val; } private static bool ScopeAllowsZoom(Equippable_RangedWeapon weapon) { PlayerCamera instance = PlayerSingleton<PlayerCamera>.Instance; PlayerInventory instance2 = PlayerSingleton<PlayerInventory>.Instance; Player local = Player.Local; if (Application.isFocused && Time.timeScale > 0f && !GameInput.IsTyping && ((Behaviour)weapon).isActiveAndEnabled && !weapon.IsReloading && weapon.aimStarted && GameInput.GetButton((ButtonCode)1) && (Object)(object)instance2 != (Object)null && instance2.HotbarEnabled && instance2.EquippingEnabled && (Object)(object)local != (Object)null && !local.IsArrested && !local.IsTased && !local.IsUnconscious && !local.IsRagdolled && !local.IsSleeping && !local.IsInVehicle && (Object)(object)instance != (Object)null && instance.ActiveUIElementCount == 0 && !instance.FreeCamEnabled) { if (!((Object)(object)Singleton<PauseMenu>.Instance == (Object)null)) { return !Singleton<PauseMenu>.Instance.IsPaused; } return true; } return false; } internal static bool IsFullyScoped(Equippable_RangedWeapon weapon) { if (weapon.Aim >= 0.98f) { return ScopeAllowsZoom(weapon); } return false; } private static void ReadWheel() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (lastWheelFrame != Time.frameCount) { float y = GameInput.MouseWheelAxis.y; if (y != 0f) { lastWheelFrame = Time.frameCount; zoomStep = ScopeZoomPolicy.Step(zoomStep, y); } } } private static void AfterMouseScroll(ref float __result) { Equippable_RangedWeapon val = ActiveSniper(); if (val != null && !((Object)(object)val == (Object)null) && ScopeAllowsZoom(val)) { if (equippedPointer != ((Il2CppObjectBase)val).Pointer) { ResetScopeState(); equippedPointer = ((Il2CppObjectBase)val).Pointer; } ReadWheel(); __result = 0f; } } private static void BeforeInput(Equippable_RangedWeapon __instance) { if (!(WeaponBehavior.GetSpec(__instance)?.Id != "eg_sniper")) { if (equippedPointer != ((Il2CppObjectBase)__instance).Pointer) { ResetScopeState(); equippedPointer = ((Il2CppObjectBase)__instance).Pointer; } bool num = ScopeAllowsZoom(__instance); if (num) { ReadWheel(); } Settings instance = Singleton<Settings>.Instance; float num2 = ((instance != null) ? instance.CameraFOV : 75f); float num3 = (num ? ScopeZoomPolicy.FieldOfView(num2, ScopeZoomPolicy.Magnifications[zoomStep]) : num2); __instance.MinAimFOVReduction = num2 - num3; __instance.MaxAimFOVReduction = num2 - num3; } } private static bool UpdateOverlay(bool visible) { if (!visible) { overlay?.Hide(); return false; } if (Screen.width <= 0 || Screen.height <= 0) { overlay?.Hide(); return false; } if (Time.unscaledTime < nextOverlayAttempt) { return false; } try { if (overlay == null || !overlay.IsAlive) { overlay?.Dispose(); overlay = new ScopeOverlay(); } overlay.Show(ScopeZoomPolicy.Magnifications[zoomStep]); overlayFailures = 0; return overlay.IsVisible; } catch (Exception ex) { overlay?.Dispose(); overlay = null; nextOverlayAttempt = Time.unscaledTime + 5f; if (overlayFailures++ < 3) { MelonLogger.Warning("Sniper eyepiece UI will retry: " + ex.GetType().Name + ": " + ex.Message); } return false; } } private static void UpdateModelVisibility(Equippable_RangedWeapon weapon, bool scoped) { if (!scoped) { RestoreModel(); return; } if (hiddenWeaponPointer != ((Il2CppObjectBase)weapon).Pointer) { RestoreModel(); Transform val = ((Component)weapon).transform.Find("eg_sniper_OriginalModel"); if ((Object)(object)val == (Object)null) { return; } foreach (Renderer componentsInChild in ((Component)val).GetComponentsInChildren<Renderer>(true)) { hiddenRenderers.Add((componentsInChild, componentsInChild.enable