using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using Animancer; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Pigeon.Math; using Pigeon.Movement; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Sparroh")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("AlwaysPracticeMakesPerfect")] [assembly: AssemblyTitle("AlwaysPracticeMakesPerfect")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class ConfigManager { private const float DebounceSeconds = 0.25f; private const float DefaultWindowDuration = 0.45f; private const float DefaultReloadSpeedMultiplier = 2.5f; private static ConfigFile config; private static ManualLogSource logger; private static FileSystemWatcher configWatcher; private static volatile bool reloadPending; private static float lastReloadTime; public static ConfigEntry EnablePracticeMakesPerfect { get; private set; } public static ConfigEntry WindowDuration { get; private set; } public static ConfigEntry ReloadSpeedMultiplier { get; private set; } public static void Initialize(ConfigFile configFile, ManualLogSource log) { config = configFile; logger = log; EnablePracticeMakesPerfect = config.Bind("General", "Enable Practice Makes Perfect", true, "Enables the Practice Makes Perfect reload timing mini-game on all weapons."); WindowDuration = config.Bind("General", "Window Duration", 0.45f, "Width of the timing window during reload (seconds of animation time). Vanilla upgrade uses a short window."); ReloadSpeedMultiplier = config.Bind("General", "Reload Speed Multiplier", 2.5f, "Reload animation speed multiplier applied when you press Fire inside the timing window."); try { SetupFileWatcher(); } catch (Exception ex) { logger.LogError((object)("Error setting up config file watcher: " + ex.Message)); } } public static void Tick() { if (!reloadPending || Time.unscaledTime - lastReloadTime < 0.25f) { return; } reloadPending = false; lastReloadTime = Time.unscaledTime; try { config.Reload(); logger.LogInfo((object)($"Config reloaded. Enable={EnablePracticeMakesPerfect.Value}, " + $"Window={WindowDuration.Value}, Speed={ReloadSpeedMultiplier.Value}")); } catch (Exception ex) { logger.LogError((object)("Error reloading config: " + ex.Message)); } } public static void Dispose() { if (configWatcher != null) { configWatcher.EnableRaisingEvents = false; configWatcher.Changed -= OnConfigFileChanged; configWatcher.Created -= OnConfigFileChanged; configWatcher.Renamed -= OnConfigFileChanged; configWatcher.Dispose(); configWatcher = null; } } private static void SetupFileWatcher() { configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.alwayspracticemakesperfect.cfg"); configWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite; configWatcher.Changed += OnConfigFileChanged; configWatcher.Created += OnConfigFileChanged; configWatcher.Renamed += OnConfigFileChanged; configWatcher.EnableRaisingEvents = true; } private static void OnConfigFileChanged(object sender, FileSystemEventArgs e) { reloadPending = true; } } internal static class InstaReloadPatches { private enum FeedbackKind { None, Success, Miss } private sealed class GenericInstaReloadState { public Gun Gun; public float WindowCenterNormalized; public bool Active; public bool Succeeded; public int LastTickFrame; } private static class ListPool { private static readonly Stack> pool = new Stack>(); public static List Get() { if (pool.Count <= 0) { return new List(8); } return pool.Pop(); } public static void Release(List list) { list.Clear(); pool.Push(list); } } private static readonly FieldInfo animatorField = AccessTools.Field(typeof(Gun), "animator"); private static readonly FieldInfo reloadAnimationField = AccessTools.Field(typeof(Gun), "reloadAnimation"); private static readonly FieldInfo hudField = AccessTools.Field(typeof(Gun), "hud"); private static readonly FieldInfo instaReloadTimeField = AccessTools.Field(typeof(FastReloadShotgun), "instaReloadTime"); private static readonly Dictionary genericStates = new Dictionary(); private static GameObject sharedBarRoot; private static RectTransform trackRt; private static RectTransform sweetSpotRt; private static Image sweetSpotImage; private static RectTransform cursorRt; private static Image cursorImage; private static TextMeshProUGUI promptLabel; private static bool barVisible; private static float feedbackUntil; private static FeedbackKind feedbackKind; private static float lfProgress01; private static float lfSweetMin01; private static float lfSweetMax01; private static bool lfInWindow; private static bool lfBarArmed; private static bool loggedMissingAnimator; private static bool loggedFirstState; private static bool loggedFirstTick; private static bool loggedFirstWindow; private const float BarWidth = 280f; private const float BarHeight = 14f; private const float CursorWidth = 3f; private const float AnchorY = 0.3f; private static readonly Color TrackColor = new Color(0.05f, 0.07f, 0.1f, 0.72f); private static readonly Color SweetSpotIdle = new Color(0.98f, 0.82f, 0.35f, 0.45f); private static readonly Color SweetSpotActive = new Color(0.98f, 0.82f, 0.35f, 0.92f); private static readonly Color SweetSpotSuccess = new Color(0.2f, 0.9f, 0.45f, 0.95f); private static readonly Color SweetSpotMiss = new Color(0.95f, 0.3f, 0.35f, 0.9f); private static readonly Color CursorIdle = new Color(0.95f, 0.96f, 0.98f, 0.95f); private static readonly Color CursorActive = new Color(1f, 0.92f, 0.35f, 1f); private static readonly Color PromptColor = new Color(1f, 0.92f, 0.35f, 1f); internal static void Cleanup() { HideBar(); genericStates.Clear(); if ((Object)(object)sharedBarRoot != (Object)null) { Object.Destroy((Object)(object)sharedBarRoot); sharedBarRoot = null; trackRt = null; sweetSpotRt = null; sweetSpotImage = null; cursorRt = null; cursorImage = null; promptLabel = null; } } internal static void TickTrackedGuns() { if (!ConfigManager.EnablePracticeMakesPerfect.Value) { if (genericStates.Count > 0) { genericStates.Clear(); HideBar(); } return; } TickFeedbackExpiry(); if (genericStates.Count == 0) { return; } List list = ListPool.Get(); list.AddRange(genericStates.Keys); for (int i = 0; i < list.Count; i++) { int key = list[i]; if (genericStates.TryGetValue(key, out var value) && value.Active && value.LastTickFrame != Time.frameCount) { Gun gun = value.Gun; if ((Object)(object)gun == (Object)null) { genericStates.Remove(key); } else { TickGun(gun); } } } ListPool.Release(list); } private static void TickFeedbackExpiry() { if (feedbackKind != FeedbackKind.None && !(Time.unscaledTime < feedbackUntil)) { feedbackKind = FeedbackKind.None; HideBar(); } } [HarmonyPatch(typeof(FastReloadShotgun), "OnUpgradesEnabled")] [HarmonyPostfix] private static void FastReloadShotgun_OnUpgradesEnabled_Postfix(FastReloadShotgun __instance) { if (ConfigManager.EnablePracticeMakesPerfect.Value && !((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner) { ref LeadFlingerData data = ref __instance.Data; if (!(data.instaReloadDuration > 0f)) { data.instaReloadDuration = Mathf.Max(0.01f, ConfigManager.WindowDuration.Value); data.instaReloadSpeed = Mathf.Max(1f, ConfigManager.ReloadSpeedMultiplier.Value); ((Gun)__instance).SetUpgradeFlag_Owner((GearUpgradeFlags)268435456, true); } } } [HarmonyPatch(typeof(FastReloadShotgun), "OnReload")] [HarmonyPostfix] private static void FastReloadShotgun_OnReload_Postfix(FastReloadShotgun __instance) { if (ConfigManager.EnablePracticeMakesPerfect.Value && !((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner) { ref LeadFlingerData data = ref __instance.Data; if (data.instaReloadDuration <= 0f) { data.instaReloadDuration = Mathf.Max(0.01f, ConfigManager.WindowDuration.Value); data.instaReloadSpeed = Mathf.Max(1f, ConfigManager.ReloadSpeedMultiplier.Value); } if (!(instaReloadTimeField == null) && !((float)instaReloadTimeField.GetValue(__instance) > 0f)) { float instaReloadDuration = data.instaReloadDuration; float num = ((Random)(ref Random.shared)).NextFloat(instaReloadDuration * 0.7f, 0.7f); instaReloadTimeField.SetValue(__instance, num); } } } [HarmonyPatch(typeof(FastReloadShotgun), "OnActiveUpdate")] [HarmonyPrefix] private static void FastReloadShotgun_OnActiveUpdate_Prefix(FastReloadShotgun __instance) { //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) lfBarArmed = false; if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner || !ConfigManager.EnablePracticeMakesPerfect.Value) { return; } ref LeadFlingerData data = ref __instance.Data; if (data.instaReloadDuration <= 0f || instaReloadTimeField == null || !((Gun)__instance).Reloading || !((Gun)__instance).Active) { return; } float num = (float)instaReloadTimeField.GetValue(__instance); if (num <= 0f) { return; } object? obj = animatorField?.GetValue(__instance); PlayerAnimation val = (PlayerAnimation)((obj is PlayerAnimation) ? obj : null); if ((Object)(object)val == (Object)null) { return; } AnimancerState currentState = val.CurrentState; if (currentState == null) { return; } object obj2 = reloadAnimationField?.GetValue(__instance); if ((obj2 != null && object.Equals(currentState.Key, obj2)) || !(currentState.NormalizedTime <= 0f) || !(currentState.Time <= 0f)) { float num2 = currentState.Duration; if (num2 <= 0.001f) { num2 = Mathf.Max(currentState.Length, 0.01f); } float time = currentState.Time; float num3 = data.instaReloadDuration * 0.5f; float num4 = num2 * num; lfProgress01 = Mathf.Clamp01(time / num2); lfSweetMin01 = Mathf.Clamp01((num4 - num3) / num2); lfSweetMax01 = Mathf.Clamp01((num4 + num3) / num2); lfInWindow = time >= num4 - num3 && time <= num4 + num3; lfBarArmed = true; bool flag = false; try { PlayerActions player = PlayerInput.Controls.Player; flag = ((PlayerActions)(ref player)).Fire.WasPressedThisFrame(); } catch { } if (flag) { FlashFeedback(lfInWindow ? FeedbackKind.Success : FeedbackKind.Miss); } } } [HarmonyPatch(typeof(FastReloadShotgun), "OnActiveUpdate")] [HarmonyPostfix] private static void FastReloadShotgun_OnActiveUpdate_Postfix(FastReloadShotgun __instance) { if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner) { return; } SuppressVanillaPopup(__instance); if (!ConfigManager.EnablePracticeMakesPerfect.Value) { if (barVisible && feedbackKind == FeedbackKind.None) { HideBar(); } } else if (feedbackKind != FeedbackKind.None) { UpdateBarVisual(lfProgress01, lfSweetMin01, lfSweetMax01, lfInWindow); } else if (!lfBarArmed) { if (barVisible) { HideBar(); } } else { UpdateBarVisual(lfProgress01, lfSweetMin01, lfSweetMax01, lfInWindow); } } private static void SuppressVanillaPopup(FastReloadShotgun gun) { if (!ConfigManager.EnablePracticeMakesPerfect.Value) { return; } try { object? obj = hudField?.GetValue(gun); FastShotgunHUD val = (FastShotgunHUD)((obj is FastShotgunHUD) ? obj : null); if ((Object)(object)val?.InstaReloadPopup != (Object)null && val.InstaReloadPopup.activeSelf) { val.InstaReloadPopup.SetActive(false); } } catch { } } [HarmonyPatch(typeof(Gun), "ForceStartReload")] [HarmonyPostfix] private static void Gun_ForceStartReload_Postfix(Gun __instance) { if (ConfigManager.EnablePracticeMakesPerfect.Value && !((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && !(__instance is FastReloadShotgun) && __instance.Reloading) { float num = Mathf.Max(0.01f, ConfigManager.WindowDuration.Value); float num2 = ((Random)(ref Random.shared)).NextFloat(num * 0.7f, 0.7f); int instanceID = ((Object)__instance).GetInstanceID(); genericStates[instanceID] = new GenericInstaReloadState { Gun = __instance, WindowCenterNormalized = num2, Active = true, Succeeded = false, LastTickFrame = -1 }; feedbackKind = FeedbackKind.None; if (!loggedFirstState) { loggedFirstState = true; SparrohPlugin.Logger.LogInfo((object)("[PMPA] Generic insta-reload armed for " + ((object)__instance).GetType().Name + " " + $"(center={num2:F3}, window={num:F3}).")); } } } [HarmonyPatch(typeof(Gun), "Update")] [HarmonyPostfix] private static void Gun_Update_Postfix(Gun __instance) { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && !(__instance is FastReloadShotgun) && __instance.Active) { TickGun(__instance); } } [HarmonyPatch(typeof(Gun), "Disable")] [HarmonyPostfix] private static void Gun_Disable_Postfix(Gun __instance) { if (!((Object)(object)__instance == (Object)null)) { genericStates.Remove(((Object)__instance).GetInstanceID()); if (feedbackKind == FeedbackKind.None) { HideBar(); } } } [HarmonyPatch(typeof(Gun), "OnDestroy")] [HarmonyPrefix] private static void Gun_OnDestroy_Prefix(Gun __instance) { if (!((Object)(object)__instance == (Object)null)) { genericStates.Remove(((Object)__instance).GetInstanceID()); if (feedbackKind == FeedbackKind.None) { HideBar(); } } } private static void TickGun(Gun gun) { //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gun == (Object)null || gun is FastReloadShotgun) { return; } int instanceID = ((Object)gun).GetInstanceID(); if (!ConfigManager.EnablePracticeMakesPerfect.Value) { if (genericStates.Remove(instanceID)) { HideBar(); } } else { if (!genericStates.TryGetValue(instanceID, out var value) || !value.Active || value.LastTickFrame == Time.frameCount) { return; } value.LastTickFrame = Time.frameCount; if (!loggedFirstTick) { loggedFirstTick = true; SparrohPlugin.Logger.LogInfo((object)("[PMPA] First generic tick on " + ((object)gun).GetType().Name + ".")); } if (!gun.Reloading || !gun.Active) { genericStates.Remove(instanceID); if (feedbackKind == FeedbackKind.None) { HideBar(); } return; } if (value.Succeeded) { if (feedbackKind == FeedbackKind.None) { HideBar(); } return; } object? obj = animatorField?.GetValue(gun); PlayerAnimation val = (PlayerAnimation)((obj is PlayerAnimation) ? obj : null); if ((Object)(object)val == (Object)null) { if (!loggedMissingAnimator) { loggedMissingAnimator = true; SparrohPlugin.Logger.LogWarning((object)"[PMPA] Could not access Gun.animator."); } return; } AnimancerState currentState = val.CurrentState; if (currentState == null) { if (feedbackKind == FeedbackKind.None) { HideBar(); } return; } object obj2 = reloadAnimationField?.GetValue(gun); if ((obj2 == null || !object.Equals(currentState.Key, obj2)) && currentState.NormalizedTime <= 0f && currentState.Time <= 0f) { if (feedbackKind == FeedbackKind.None) { HideBar(); } return; } float num = Mathf.Max(0.01f, ConfigManager.WindowDuration.Value) * 0.5f; float num2 = currentState.Duration; if (num2 <= 0.001f) { num2 = Mathf.Max(currentState.Length, 0.01f); } float time = currentState.Time; float num3 = num2 * value.WindowCenterNormalized; bool flag = time >= num3 - num && time <= num3 + num; bool flag2 = false; try { PlayerActions player = PlayerInput.Controls.Player; flag2 = ((PlayerActions)(ref player)).Fire.WasPressedThisFrame(); } catch { } float progress = Mathf.Clamp01(time / num2); float sweetMin = Mathf.Clamp01((num3 - num) / num2); float sweetMax = Mathf.Clamp01((num3 + num) / num2); if (flag) { if (!loggedFirstWindow) { loggedFirstWindow = true; SparrohPlugin.Logger.LogInfo((object)("[PMPA] Timing window open on " + ((object)gun).GetType().Name + " " + $"(t={time:F3}, center={num3:F3}, half={num:F3}).")); } if (flag2) { value.Succeeded = true; value.Active = false; ((AnimancerNode)currentState).Speed = ((AnimancerNode)currentState).Speed * Mathf.Max(1f, ConfigManager.ReloadSpeedMultiplier.Value); FlashFeedback(FeedbackKind.Success); TryTriggerReloadEffect(gun); SparrohPlugin.Logger.LogInfo((object)$"[PMPA] Success on {((object)gun).GetType().Name}; speed now {((AnimancerNode)currentState).Speed:F2}."); } } else if (flag2) { value.Active = false; genericStates.Remove(instanceID); FlashFeedback(FeedbackKind.Miss); } _ = feedbackKind; UpdateBarVisual(progress, sweetMin, sweetMax, flag); } } private static void EnsureBar() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_005e: 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_0088: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)sharedBarRoot != (Object)null)) { sharedBarRoot = new GameObject("AlwaysPracticeMakesPerfect_ReloadBar"); Object.DontDestroyOnLoad((Object)(object)sharedBarRoot); Canvas obj = sharedBarRoot.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 9000; CanvasScaler obj2 = sharedBarRoot.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; sharedBarRoot.AddComponent(); GameObject val = new GameObject("Container"); val.transform.SetParent(sharedBarRoot.transform, false); RectTransform obj3 = val.AddComponent(); obj3.anchorMin = new Vector2(0.5f, 0.3f); obj3.anchorMax = new Vector2(0.5f, 0.3f); obj3.pivot = new Vector2(0.5f, 0.5f); obj3.sizeDelta = new Vector2(304f, 54f); GameObject val2 = new GameObject("Track"); val2.transform.SetParent(val.transform, false); trackRt = val2.AddComponent(); trackRt.anchorMin = new Vector2(0.5f, 0.5f); trackRt.anchorMax = new Vector2(0.5f, 0.5f); trackRt.pivot = new Vector2(0.5f, 0.5f); trackRt.sizeDelta = new Vector2(280f, 14f); Image obj4 = val2.AddComponent(); ((Graphic)obj4).color = TrackColor; ((Graphic)obj4).raycastTarget = false; GameObject val3 = new GameObject("Outline"); val3.transform.SetParent(val.transform, false); RectTransform obj5 = val3.AddComponent(); obj5.anchorMin = new Vector2(0.5f, 0.5f); obj5.anchorMax = new Vector2(0.5f, 0.5f); obj5.pivot = new Vector2(0.5f, 0.5f); obj5.sizeDelta = new Vector2(284f, 18f); ((Transform)obj5).SetSiblingIndex(0); Image obj6 = val3.AddComponent(); ((Graphic)obj6).color = new Color(0.25f, 0.4f, 0.5f, 0.55f); ((Graphic)obj6).raycastTarget = false; GameObject val4 = new GameObject("SweetSpot"); val4.transform.SetParent(val2.transform, false); sweetSpotRt = val4.AddComponent(); sweetSpotRt.anchorMin = new Vector2(0f, 0f); sweetSpotRt.anchorMax = new Vector2(0f, 1f); sweetSpotRt.pivot = new Vector2(0f, 0.5f); sweetSpotRt.anchoredPosition = Vector2.zero; sweetSpotRt.sizeDelta = new Vector2(20f, 0f); sweetSpotImage = val4.AddComponent(); ((Graphic)sweetSpotImage).color = SweetSpotIdle; ((Graphic)sweetSpotImage).raycastTarget = false; GameObject val5 = new GameObject("Cursor"); val5.transform.SetParent(val2.transform, false); cursorRt = val5.AddComponent(); cursorRt.anchorMin = new Vector2(0f, 0.5f); cursorRt.anchorMax = new Vector2(0f, 0.5f); cursorRt.pivot = new Vector2(0.5f, 0.5f); cursorRt.sizeDelta = new Vector2(3f, 24f); cursorRt.anchoredPosition = Vector2.zero; cursorImage = val5.AddComponent(); ((Graphic)cursorImage).color = CursorIdle; ((Graphic)cursorImage).raycastTarget = false; GameObject val6 = new GameObject("Prompt"); val6.transform.SetParent(val.transform, false); RectTransform obj7 = val6.AddComponent(); obj7.anchorMin = new Vector2(0.5f, 0.5f); obj7.anchorMax = new Vector2(0.5f, 0.5f); obj7.pivot = new Vector2(0.5f, 0f); obj7.anchoredPosition = new Vector2(0f, 13f); obj7.sizeDelta = new Vector2(280f, 28f); promptLabel = val6.AddComponent(); ((TMP_Text)promptLabel).text = "FIRE"; ((TMP_Text)promptLabel).alignment = (TextAlignmentOptions)514; ((TMP_Text)promptLabel).fontSize = 22f; ((TMP_Text)promptLabel).fontStyle = (FontStyles)1; ((Graphic)promptLabel).color = PromptColor; ((Graphic)promptLabel).raycastTarget = false; if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null) { ((TMP_Text)promptLabel).font = TMP_Settings.defaultFontAsset; } ((Component)promptLabel).gameObject.SetActive(false); sharedBarRoot.SetActive(false); barVisible = false; } } private static void UpdateBarVisual(float progress01, float sweetMin01, float sweetMax01, bool inWindow) { //IL_0050: 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) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) EnsureBar(); progress01 = Mathf.Clamp01(progress01); sweetMin01 = Mathf.Clamp01(sweetMin01); sweetMax01 = Mathf.Clamp01(Mathf.Max(sweetMax01, sweetMin01 + 0.01f)); float num = sweetMin01 * 280f; float num2 = Mathf.Max(4f, (sweetMax01 - sweetMin01) * 280f); sweetSpotRt.anchoredPosition = new Vector2(num, 0f); sweetSpotRt.sizeDelta = new Vector2(num2, 0f); cursorRt.anchoredPosition = new Vector2(progress01 * 280f, 0f); if (feedbackKind == FeedbackKind.Success) { ((Graphic)sweetSpotImage).color = SweetSpotSuccess; ((Graphic)cursorImage).color = SweetSpotSuccess; if ((Object)(object)promptLabel != (Object)null) { ((TMP_Text)promptLabel).text = "NICE"; ((Graphic)promptLabel).color = SweetSpotSuccess; ((Component)promptLabel).gameObject.SetActive(true); } } else if (feedbackKind == FeedbackKind.Miss) { ((Graphic)sweetSpotImage).color = SweetSpotMiss; ((Graphic)cursorImage).color = SweetSpotMiss; if ((Object)(object)promptLabel != (Object)null) { ((TMP_Text)promptLabel).text = "MISS"; ((Graphic)promptLabel).color = SweetSpotMiss; ((Component)promptLabel).gameObject.SetActive(true); } } else if (inWindow) { float num3 = 0.85f + 0.15f * Mathf.Sin(Time.unscaledTime * 14f); Color sweetSpotActive = SweetSpotActive; sweetSpotActive.a *= num3; ((Graphic)sweetSpotImage).color = sweetSpotActive; ((Graphic)cursorImage).color = CursorActive; if ((Object)(object)promptLabel != (Object)null) { ((TMP_Text)promptLabel).text = "FIRE"; ((Graphic)promptLabel).color = PromptColor; ((Component)promptLabel).gameObject.SetActive(true); } } else { ((Graphic)sweetSpotImage).color = SweetSpotIdle; ((Graphic)cursorImage).color = CursorIdle; if ((Object)(object)promptLabel != (Object)null) { ((Component)promptLabel).gameObject.SetActive(false); } } if (!sharedBarRoot.activeSelf) { sharedBarRoot.SetActive(true); } barVisible = true; } private static void FlashFeedback(FeedbackKind kind) { feedbackKind = kind; feedbackUntil = Time.unscaledTime + 0.35f; } private static void HideBar() { feedbackKind = FeedbackKind.None; if ((Object)(object)sharedBarRoot != (Object)null && sharedBarRoot.activeSelf) { sharedBarRoot.SetActive(false); } barVisible = false; } private static void TryTriggerReloadEffect(Gun gun) { try { (AccessTools.Method(((object)gun).GetType(), "TriggerEffectReload", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(Gun), "TriggerEffectReload", (Type[])null, (Type[])null))?.Invoke(gun, null); } catch { } } } [BepInPlugin("sparroh.alwayspracticemakesperfect", "AlwaysPracticeMakesPerfect", "1.1.0")] [MycoMod(/*Could not decode attribute arguments.*/)] public class SparrohPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.alwayspracticemakesperfect"; public const string PluginName = "AlwaysPracticeMakesPerfect"; public const string PluginVersion = "1.1.0"; internal static ManualLogSource Logger; private Harmony harmony; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; ConfigManager.Initialize(((BaseUnityPlugin)this).Config, Logger); harmony = new Harmony("sparroh.alwayspracticemakesperfect"); try { harmony.PatchAll(typeof(InstaReloadPatches)); Logger.LogInfo((object)"Harmony patches applied."); } catch (Exception ex) { Logger.LogError((object)("Error applying patches: " + ex.Message)); } Logger.LogInfo((object)"AlwaysPracticeMakesPerfect v1.1.0 loaded successfully."); } private void Update() { ConfigManager.Tick(); try { InstaReloadPatches.TickTrackedGuns(); } catch (Exception ex) { Logger.LogError((object)("Error in insta-reload tick: " + ex.Message)); } } private void OnDestroy() { InstaReloadPatches.Cleanup(); ConfigManager.Dispose(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } namespace AlwaysPracticeMakesPerfect { public static class MyPluginInfo { public const string PLUGIN_GUID = "AlwaysPracticeMakesPerfect"; public const string PLUGIN_NAME = "AlwaysPracticeMakesPerfect"; public const string PLUGIN_VERSION = "1.1.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }