Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ImprovedCrossbows v1.0.2
ImprovedCrossbows.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("ImprovedCrossbows")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("ImprovedCrossbows")] [assembly: AssemblyTitle("ImprovedCrossbows")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ImprovedCrossbows { [HarmonyPatch(typeof(Attack), "GetProjectileSpawnPoint")] internal static class AimAtCrosshair { private const float MaxAimDistance = 500f; private const float MaxCorrectionDegrees = 15f; private static int rayMask; private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[32]; internal static int RayMask { get { if (rayMask == 0) { rayMask = LayerMask.GetMask(new string[12] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle" }); } return rayMask; } } private static void Postfix(Attack __instance, Humanoid ___m_character, ItemData ___m_weapon, Vector3 spawnPoint, ref Vector3 aimDir) { //IL_0017: 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_003f: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)___m_character != (Object)(object)Player.m_localPlayer) && Plugin.IsCrossbow(___m_weapon) && TryGetCorrectedDir(___m_character, spawnPoint, aimDir, out var corrected)) { float launchAngle = __instance.m_launchAngle; aimDir = ((launchAngle != 0f) ? (Quaternion.AngleAxis(0f - launchAngle, Vector3.Cross(Vector3.up, corrected)) * corrected) : corrected); } } internal static bool TryGetCrosshairTarget(Humanoid shooter, Vector3 spawnPoint, out Vector3 target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0026: Unknown result type (might be due to invalid IL or missing references) target = default(Vector3); Camera mainCamera = Utils.GetMainCamera(); if ((Object)(object)mainCamera == (Object)null) { return false; } target = FindCrosshairTarget(((Component)mainCamera).transform, shooter, spawnPoint); return true; } private static bool TryGetCorrectedDir(Humanoid shooter, Vector3 spawnPoint, Vector3 vanillaDir, out Vector3 corrected) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_003d: Unknown result type (might be due to invalid IL or missing references) corrected = vanillaDir; if (!Plugin.AimAtCrosshair || !TryGetCrosshairTarget(shooter, spawnPoint, out var target)) { return false; } Vector3 val = target - spawnPoint; Vector3 normalized = ((Vector3)(ref val)).normalized; if (Vector3.Angle(vanillaDir, normalized) > 15f) { return false; } corrected = normalized; return true; } private static Vector3 FindCrosshairTarget(Transform camera, Humanoid shooter, Vector3 spawnPoint) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) Vector3 position = camera.position; Vector3 forward = camera.forward; float num = Vector3.Dot(spawnPoint - position, forward); int num2 = Physics.RaycastNonAlloc(position, forward, Hits, 500f, RayMask, (QueryTriggerInteraction)1); float num3 = 500f; for (int i = 0; i < num2; i++) { RaycastHit val = Hits[i]; if (!(((RaycastHit)(ref val)).distance <= num) && !(((RaycastHit)(ref val)).distance >= num3) && !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>() == (Object)(object)shooter)) { num3 = ((RaycastHit)(ref val)).distance; } } return position + forward * num3; } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] [HarmonyPriority(200)] internal static class ImpactMarker { private const float MaxObstacleDistance = 30f; private const float TargetTolerance = 0.5f; private const float Size = 12f; private const int TextureSize = 64; private static readonly Color MarkerColor = new Color(1f, 0.3f, 0.25f, 0.9f); private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[16]; private static Image marker; private static Sprite sprite; private static string originJointName; private static Transform originJoint; private static bool wasShown; private static void Postfix(Camera ___m_camera) { //IL_0004: 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_0137: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_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_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) bool flag = false; Vector3 val = default(Vector3); Player localPlayer = Player.m_localPlayer; if (Plugin.ShowImpactMarker && Zoom.IsZoomingIn && (Object)(object)localPlayer != (Object)null && (Object)(object)Hud.instance != (Object)null && FindObstacle(localPlayer, out var obstacle)) { val = ___m_camera.WorldToScreenPoint(((RaycastHit)(ref obstacle)).point); flag = val.z > 0f; if (flag && !wasShown && Plugin.DebugLogging) { Plugin.Log.LogInfo((object)("Impact marker: bolt would hit " + ((Object)((RaycastHit)(ref obstacle)).collider).name + " at " + $"{Vector3.Distance(((Component)localPlayer).transform.position, ((RaycastHit)(ref obstacle)).point):0.0} m")); } } if (!flag && wasShown && Plugin.DebugLogging) { Plugin.Log.LogInfo((object)"Impact marker: hidden"); } wasShown = flag; if ((Object)(object)marker == (Object)null) { if (!flag) { return; } Create(((Component)Hud.instance.m_crosshair).transform); } ((Component)marker).gameObject.SetActive(flag); if (flag) { RectTransform val2 = (RectTransform)((Component)Hud.instance.m_crosshair).transform; Canvas canvas = ((Graphic)Hud.instance.m_crosshair).canvas; Camera val3 = (((int)canvas.renderMode == 0) ? null : canvas.worldCamera); Vector2 val4 = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle(val2, Vector2.op_Implicit(val), val3, ref val4); RectTransform val5 = (RectTransform)((Component)marker).transform; Vector2 val6 = val4; Rect rect = val2.rect; val5.anchoredPosition = val6 - ((Rect)(ref rect)).center; } } private static bool FindObstacle(Player player, out RaycastHit obstacle) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: 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_01f3: 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_01d3: 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_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) obstacle = default(RaycastHit); ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (!Plugin.IsCrossbow(currentWeapon)) { return false; } Attack attack = currentWeapon.m_shared.m_attack; ItemData ammoItem = ((Humanoid)player).GetAmmoItem(); GameObject val = ((ammoItem != null && (Object)(object)ammoItem.m_shared.m_attack.m_attackProjectile != (Object)null) ? ammoItem.m_shared.m_attack.m_attackProjectile : attack.m_attackProjectile); Projectile val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Projectile>() : null); float num = (((Object)(object)val2 != (Object)null) ? val2.m_rayRadius : 0f); Transform attackOrigin = GetAttackOrigin(player, attack); Transform transform = ((Component)player).transform; Vector3 val3 = attackOrigin.position + transform.up * attack.m_attackHeight + transform.forward * attack.m_attackRange + transform.right * attack.m_attackOffset; if (!AimAtCrosshair.TryGetCrosshairTarget((Humanoid)(object)player, val3, out var target)) { return false; } Vector3 val4 = target - val3; float num2 = Mathf.Min(((Vector3)(ref val4)).magnitude - 0.5f, 32f); if (num2 <= 0f) { return false; } Vector3 normalized = ((Vector3)(ref val4)).normalized; int num3 = ((num > 0f) ? Physics.SphereCastNonAlloc(val3, num, normalized, Hits, num2, AimAtCrosshair.RayMask, (QueryTriggerInteraction)1) : Physics.RaycastNonAlloc(val3, normalized, Hits, num2, AimAtCrosshair.RayMask, (QueryTriggerInteraction)1)); bool flag = false; for (int i = 0; i < num3; i++) { RaycastHit val5 = Hits[i]; if ((!flag || !(((RaycastHit)(ref val5)).distance >= ((RaycastHit)(ref obstacle)).distance)) && !((Object)(object)((Component)((RaycastHit)(ref val5)).collider).GetComponentInParent<Character>() == (Object)(object)player)) { if (((RaycastHit)(ref val5)).distance == 0f && ((RaycastHit)(ref val5)).point == Vector3.zero) { ((RaycastHit)(ref val5)).point = val3; } obstacle = val5; flag = true; } } if (flag) { return Vector3.Distance(transform.position, ((RaycastHit)(ref obstacle)).point) <= 30f; } return false; } private static Transform GetAttackOrigin(Player player, Attack attack) { if (string.IsNullOrEmpty(attack.m_attackOriginJoint)) { return ((Component)player).transform; } if ((Object)(object)originJoint == (Object)null || originJointName != attack.m_attackOriginJoint || !originJoint.IsChildOf(((Component)player).transform)) { originJointName = attack.m_attackOriginJoint; originJoint = Utils.FindChild(((Character)player).GetVisual().transform, originJointName, (IterativeSearchType)0); } if (!((Object)(object)originJoint != (Object)null)) { return ((Component)player).transform; } return originJoint; } private static void Create(Transform crosshair) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_004c: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)sprite == (Object)null) { sprite = CreateCrossSprite(); } GameObject val = new GameObject("ImprovedCrossbows_ImpactMarker", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(crosshair, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; val2.sizeDelta = new Vector2(12f, 12f); marker = val.GetComponent<Image>(); marker.sprite = sprite; ((Graphic)marker).color = MarkerColor; ((Graphic)marker).raycastTarget = false; } private static Sprite CreateCrossSprite() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, true) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)2 }; float num = 5.12f; float num2 = 6.4f; Color32[] array = (Color32[])(object)new Color32[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num3 = (float)j + 0.5f; float num4 = (float)i + 0.5f; float num5 = Mathf.Abs(num3 - num4) / Mathf.Sqrt(2f); float num6 = Mathf.Abs(num3 + num4 - 64f) / Mathf.Sqrt(2f); float num7 = Mathf.Clamp01(num - Mathf.Min(num5, num6) + 0.5f); float num8 = Mathf.Min(Mathf.Min(num3, 64f - num3), Mathf.Min(num4, 64f - num4)); num7 *= Mathf.Clamp01(num8 - num2 + 0.5f); array[i * 64 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num7 * 255f)); } } val.SetPixels32(array); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f)); } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] internal static class LoadedStateSave { internal const string LoadedKey = "Iteravio.ImprovedCrossbows.Loaded"; private static void Prefix(Humanoid __instance, ItemData item) { if (!Plugin.KeepLoadedWhenUnequipped || !Plugin.IsCrossbow(item)) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer || LoadedStateRestore.WeaponLoaded.Invoke(val) != item) { return; } foreach (ItemData allItem in ((Humanoid)val).GetInventory().GetAllItems()) { allItem.m_customData.Remove("Iteravio.ImprovedCrossbows.Loaded"); } item.m_customData["Iteravio.ImprovedCrossbows.Loaded"] = "1"; } } [HarmonyPatch(typeof(Player), "UpdateWeaponLoading")] internal static class LoadedStateRestore { internal static readonly FieldRef<Player, ItemData> WeaponLoaded = AccessTools.FieldRefAccess<Player, ItemData>("m_weaponLoaded"); private static readonly Action<Player, ItemData> SetWeaponLoaded = AccessTools.MethodDelegate<Action<Player, ItemData>>(AccessTools.Method(typeof(Player), "SetWeaponLoaded", (Type[])null, (Type[])null), (object)null, true); private static void Prefix(Player __instance, ItemData weapon) { if (weapon != null && weapon != WeaponLoaded.Invoke(__instance) && weapon.m_customData.Remove("Iteravio.ImprovedCrossbows.Loaded") && Plugin.KeepLoadedWhenUnequipped && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { SetWeaponLoaded(__instance, weapon); if (Plugin.DebugLogging) { Plugin.Log.LogInfo((object)("Restored loaded state of " + weapon.m_shared.m_name)); } } } } [BepInPlugin("Iteravio.ImprovedCrossbows", "ImprovedCrossbows", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "Iteravio.ImprovedCrossbows"; public const string PluginName = "ImprovedCrossbows"; public const string PluginVersion = "1.0.2"; private const string MainSection = "Improved Crossbows"; internal static ManualLogSource Log; private static ConfigEntry<bool> pauseReloadWhileRunning; private static ConfigEntry<bool> keepLoadedWhenUnequipped; private static ConfigEntry<bool> aimAtCrosshair; private static ConfigEntry<bool> showImpactMarker; private static ConfigEntry<int> recoilPercent; private static ConfigEntry<bool> zoomWithBlockButton; private static ConfigEntry<float> zoomMagnification; private static ConfigEntry<int> zoomMoveSpeedPercent; private static ConfigEntry<bool> showReloadAroundCrosshair; private static ConfigEntry<int> reloadRingOpacityPercent; private static ConfigEntry<bool> bigSneakAttackNumbers; private static ConfigEntry<bool> muffleSoundWhileZooming; private static ConfigEntry<bool> debugLogging; private static readonly FieldRef<Player, float> ActionQueuePause = AccessTools.FieldRefAccess<Player, float>("m_actionQueuePause"); internal static bool PauseReloadWhileRunning => pauseReloadWhileRunning.Value; internal static bool KeepLoadedWhenUnequipped => keepLoadedWhenUnequipped.Value; internal static bool AimAtCrosshair => aimAtCrosshair.Value; internal static bool ShowImpactMarker => showImpactMarker.Value; internal static float RecoilFactor => (float)recoilPercent.Value / 100f; internal static bool ZoomWithBlockButton => zoomWithBlockButton.Value; internal static float ZoomMagnification => zoomMagnification.Value; internal static float MoveSpeedFactorWhileZooming => (float)zoomMoveSpeedPercent.Value / 100f; internal static bool ShowReloadAroundCrosshair => showReloadAroundCrosshair.Value; internal static float ReloadRingOpacity => (float)reloadRingOpacityPercent.Value / 100f; internal static bool BigSneakAttackNumbers => bigSneakAttackNumbers.Value; internal static bool MuffleSoundWhileZooming => muffleSoundWhileZooming.Value; internal static bool DebugLogging => debugLogging.Value; internal static bool IsReloadPaused(Player player) { return ActionQueuePause.Invoke(player) > 0f; } private void Awake() { //IL_023b: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; pauseReloadWhileRunning = ((BaseUnityPlugin)this).Config.Bind<bool>("Improved Crossbows", "PauseReloadWhileRunning", true, Synced("Running pauses a crossbow reload instead of cancelling it. Jumping and dodging still cancel it. Vanilla: cancels.", null, 12)); keepLoadedWhenUnequipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Improved Crossbows", "KeepLoadedWhenUnequipped", true, Synced("The last crossbow you put away stays loaded. Vanilla: unloads.", null, 11)); aimAtCrosshair = ((BaseUnityPlugin)this).Config.Bind<bool>("Improved Crossbows", "AimAtCrosshair", true, Synced("Bolts fly toward your crosshair. Vanilla: parallel to it, so they land low.", null, 10)); showImpactMarker = ((BaseUnityPlugin)this).Config.Bind<bool>("Improved Crossbows", "ShowImpactMarker", true, Synced("While zoomed, a red X marks an obstacle within 30 m that would block your shot. Vanilla: none.", null, 9)); recoilPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Improved Crossbows", "PercentRecoil", 50, Synced("Crossbow recoil as a percentage of vanilla. Vanilla: 100%.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), 8)); zoomWithBlockButton = ((BaseUnityPlugin)this).Config.Bind<bool>("Improved Crossbows", "ZoomWithBlockButton", true, Synced("Holding Block with a crossbow zooms in instead of blocking. Vanilla: blocks.", null, 7)); zoomMagnification = ((BaseUnityPlugin)this).Config.Bind<float>("Improved Crossbows", "ZoomMagnification", 2f, Synced("Zoom strength. Higher Crossbows skill zooms in faster. Vanilla: no zoom.", (AcceptableValueBase)(object)new AcceptableValueList<float>(new float[5] { 1.5f, 2f, 2.5f, 3f, 4f }), 6)); zoomMoveSpeedPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Improved Crossbows", "PercentMoveSpeedWhileZooming", 50, Synced("Jogging and running speed while zooming, as a percentage of normal. Vanilla: 100% (as it has no zoom).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), 5)); muffleSoundWhileZooming = ((BaseUnityPlugin)this).Config.Bind<bool>("Improved Crossbows", "MuffleSoundWhileZooming", true, Local("Sounds get slightly muffled while zooming. Local, not synced. Vanilla: no muffle (as it has no zoom : D).", null, 4)); showReloadAroundCrosshair = ((BaseUnityPlugin)this).Config.Bind<bool>("Improved Crossbows", "ShowReloadAroundCrosshair", true, Local("Reload progress shows as a ring around the crosshair. Local, not synced. Vanilla: bar at the bottom.", null, 3)); reloadRingOpacityPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Improved Crossbows", "PercentReloadRingOpacity", 25, Local("Opacity of the reload ring and its yellow flash. 100 = solid, lower = more see-through. Local, not synced. Vanilla: no ring.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), 2)); bigSneakAttackNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("Improved Crossbows", "BigSneakAttackNumbers", true, Local("Your sneak attacks show you a big orange damage number with the multiplier. Local, not synced. Vanilla: normal number.", null, 1)); debugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogCrossbowState", false, "Log your crossbow's loaded, reload and zoom state when it changes. Local, not synced."); new Harmony("Iteravio.ImprovedCrossbows").PatchAll(); } private void Update() { if (debugLogging.Value) { DebugStatus.Update(); } } private static ConfigDescription Synced(string description, AcceptableValueBase range, int order) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown return new ConfigDescription(description, range, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = order } }); } private static ConfigDescription Local(string description, AcceptableValueBase range, int order) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown return new ConfigDescription(description, range, new object[1] { (object)new ConfigurationManagerAttributes { Order = order } }); } internal static bool IsCrossbow(ItemData item) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if (item != null) { return (int)item.m_shared.m_skillType == 14; } return false; } } internal static class DebugStatus { private static string lastKey; internal static void Update() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 Player localPlayer = Player.m_localPlayer; ItemData val = (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null); if (!Plugin.IsCrossbow(val)) { lastKey = null; return; } string text = default(string); float num = default(float); MinorActionData val2 = default(MinorActionData); localPlayer.GetActionProgress(ref text, ref num, ref val2); bool flag = val2 != null && (int)val2.m_type == 2; string text2 = ((!flag) ? "none" : (Plugin.IsReloadPaused(localPlayer) ? "paused" : "running")); string text3 = ((Zoom.Progress <= 0f) ? "out" : ((Zoom.Progress >= 1f) ? "full" : (Zoom.IsZoomingIn ? "zooming in" : "zooming out"))); string text4 = $"{val.m_shared.m_name}|{((Humanoid)localPlayer).IsWeaponLoaded()}|{text2}|{text3}"; if (!(text4 == lastKey)) { lastKey = text4; string arg = (flag ? $"{text2} at {num:0%}" : text2); Plugin.Log.LogInfo((object)("Crossbow " + val.m_shared.m_name + ": " + $"loaded {((Humanoid)localPlayer).IsWeaponLoaded()}, reload {arg}, zoom {text3}")); } } } [HarmonyPatch(typeof(Attack), "OnAttackTrigger")] internal static class Recoil { private static void Prefix(Attack __instance, Humanoid ___m_character, ItemData ___m_weapon) { if (!((Object)(object)___m_character != (Object)(object)Player.m_localPlayer) && Plugin.IsCrossbow(___m_weapon)) { __instance.m_recoilPushback *= Plugin.RecoilFactor; } } } [HarmonyPatch(typeof(Player), "CheckRun")] internal static class ReloadPause { internal static bool InCheckRun; private static void Prefix(Player __instance) { InCheckRun = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Plugin.PauseReloadWhileRunning; } private static void Finalizer() { InCheckRun = false; } } [HarmonyPatch(typeof(Player), "ClearActionQueue")] internal static class ReloadPauseClearActionQueue { private const float ResumeDelaySeconds = 0.2f; private static bool Prefix(List<MinorActionData> ___m_actionQueue, ref float ___m_actionQueuePause) { if (!ReloadPause.InCheckRun) { return true; } MinorActionData val = ___m_actionQueue.Find((MinorActionData a) => (int)a.m_type == 2); if (val == null || !Plugin.IsCrossbow(val.m_item)) { return true; } ___m_actionQueue.Clear(); ___m_actionQueue.Add(val); ___m_actionQueuePause = Mathf.Max(___m_actionQueuePause, 0.2f); return false; } } [HarmonyPatch(typeof(Hud), "UpdateActionProgress")] internal static class ReloadRing { private const float Diameter = 26f; private const float Thickness = 1.6f; private const int TextureSize = 256; private const float FlashSeconds = 0.2f; private const float FlashMaxScale = 1.25f; private const float MaxFinishSeconds = 2f; private const float DefaultFinishSeconds = 1.16f; private const float SweepFillPerSecond = 4f; private const float TrackAlpha = 0.15f; private const float FillAlpha = 0.8f; private const float PausedAlpha = 0.45f; private static readonly Color FlashColor = Color.yellow; private static Sprite ringSprite; private static Image track; private static Image fill; private static Image flash; private static readonly Dictionary<string, float> finishSeconds = new Dictionary<string, float>(); private static bool wasReloading; private static float reloadSeconds; private static string reloadAnimation; private static float finishTime = -1f; private static float flashTime = 0.2f; private static float lastFill; private static bool sweeping; private static void Postfix(Hud __instance, Player player) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) string text = default(string); float num = default(float); MinorActionData val = default(MinorActionData); player.GetActionProgress(ref text, ref num, ref val); bool flag = val != null && (int)val.m_type == 2 && Plugin.IsCrossbow(val.m_item); bool showReloadAroundCrosshair = Plugin.ShowReloadAroundCrosshair; bool flag2 = ((Humanoid)player).IsWeaponLoaded(); if (flag) { reloadSeconds = val.m_duration; reloadAnimation = val.m_item.m_shared.m_attack.m_reloadAnimation; } float value; float num2 = (finishSeconds.TryGetValue(reloadAnimation ?? "", out value) ? value : 1.16f); float num3 = Mathf.Max(0.01f, reloadSeconds + num2); if (wasReloading && !flag && flag2) { finishTime = 0f; } wasReloading = flag; bool flag3 = false; if (finishTime >= 0f) { finishTime += Time.deltaTime; if (!flag2 || !Plugin.IsCrossbow(((Humanoid)player).GetCurrentWeapon())) { finishTime = -1f; } else if (!((Character)player).InMinorAction() || finishTime > 2f) { if (finishTime <= 2f) { finishSeconds[reloadAnimation ?? ""] = finishTime; } if (Plugin.DebugLogging) { Plugin.Log.LogInfo((object)$"Ready to fire {finishTime:0.00} s after reload (expected {num2:0.00} s)"); } finishTime = -1f; sweeping = showReloadAroundCrosshair; } else { flag3 = true; } } if (sweeping) { if (!flag2 || !Plugin.IsCrossbow(((Humanoid)player).GetCurrentWeapon())) { sweeping = false; } else if ((lastFill += Time.deltaTime * 4f) >= 1f) { sweeping = false; flashTime = 0f; } } bool flag4 = showReloadAroundCrosshair && (flag || flag3 || sweeping); if (flag4) { __instance.m_actionBarRoot.SetActive(false); } if ((Object)(object)fill == (Object)null) { if (!flag4) { return; } Create(((Component)__instance.m_crosshair).transform); } ((Component)track).gameObject.SetActive(flag4); ((Component)fill).gameObject.SetActive(flag4); float num4 = Plugin.ReloadRingOpacity / 0.8f; if (flag4) { if (!sweeping) { lastFill = Mathf.Clamp01((flag ? val.m_time : (reloadSeconds + finishTime)) / num3); } fill.fillAmount = lastFill; ((Graphic)fill).color = White(((flag && Plugin.IsReloadPaused(player)) ? 0.45f : 0.8f) * num4); ((Graphic)track).color = White(0.15f * num4); } UpdateFlash(Mathf.Min(1f, num4)); if (flag4 || ((Component)flash).gameObject.activeSelf) { HideStealth(__instance); } } private static void HideStealth(Hud hud) { ((Component)hud.m_stealthBar).gameObject.SetActive(false); hud.m_hidden.SetActive(false); hud.m_targeted.SetActive(false); hud.m_targetedAlert.SetActive(false); } private static void UpdateFlash(float maxAlpha) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) bool flag = flashTime < 0.2f; ((Component)flash).gameObject.SetActive(flag); if (flag) { flashTime += Time.deltaTime; float num = Mathf.Clamp01(flashTime / 0.2f); ((Component)flash).transform.localScale = Vector3.one * Mathf.Lerp(1f, 1.25f, num); Color flashColor = FlashColor; flashColor.a = (1f - num) * maxAlpha; ((Graphic)flash).color = flashColor; } } private static Color White(float alpha) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) return new Color(1f, 1f, 1f, alpha); } private static void Create(Transform crosshair) { if ((Object)(object)ringSprite == (Object)null) { ringSprite = CreateRingSprite(); } track = CreateImage("ImprovedCrossbows_ReloadTrack", crosshair); fill = CreateImage("ImprovedCrossbows_ReloadFill", crosshair); fill.type = (Type)3; fill.fillMethod = (FillMethod)4; fill.fillOrigin = 2; fill.fillClockwise = true; flash = CreateImage("ImprovedCrossbows_ReloadFlash", crosshair); ((Component)flash).gameObject.SetActive(false); } private static Image CreateImage(string name, Transform parent) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_004d: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0076: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(parent, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; val2.anchoredPosition = Vector2.zero; val2.sizeDelta = new Vector2(26f, 26f); Image component = val.GetComponent<Image>(); component.sprite = ringSprite; ((Graphic)component).raycastTarget = false; return component; } private static Sprite CreateRingSprite() { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(256, 256, (TextureFormat)4, true) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)2 }; float num = 127.5f; float num2 = 127f; float num3 = num2 - 15.753846f; Color32[] array = (Color32[])(object)new Color32[65536]; for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { float num4 = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(num, num)); float num5 = Mathf.Clamp01(num2 - num4 + 0.5f) * Mathf.Clamp01(num4 - num3 + 0.5f); array[i * 256 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num5 * 255f)); } } val.SetPixels32(array); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f)); } } internal static class SneakAttackText { private struct HitState { public Character Victim; public HitData Hit; public float BackstabTimeBefore; } [HarmonyPatch(typeof(Character), "RPC_Damage")] private static class RpcDamagePatch { private static void Prefix(Character __instance, HitData hit, out HitState __state) { __state = new HitState { Victim = victim, Hit = currentHit, BackstabTimeBefore = backstabTimeBefore }; victim = __instance; currentHit = hit; backstabTimeBefore = BackstabTime.Invoke(__instance); } private static void Finalizer(HitState __state) { victim = __state.Victim; currentHit = __state.Hit; backstabTimeBefore = __state.BackstabTimeBefore; } } [HarmonyPatch(typeof(DamageText), "ShowText", new Type[] { typeof(DamageModifier), typeof(Vector3), typeof(float), typeof(bool) })] private static class ShowTextPatch { private static void Prefix(Vector3 pos, float dmg) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)victim == (Object)null) && BackstabTime.Invoke(victim) != backstabTimeBefore) { backstabTimeBefore = BackstabTime.Invoke(victim); if (currentHit.GetAttacker() is Player) { ZRoutedRpc.instance.InvokeRoutedRPC(((ZDOID)(ref currentHit.m_attacker)).UserID, "Iteravio.ImprovedCrossbows.SneakAttackText", new object[3] { pos, dmg, currentHit.m_backstabBonus }); } } } } [HarmonyPatch(typeof(DamageText), "Awake")] private static class RegisterPatch { private static void Postfix() { ZRoutedRpc.instance.Register<Vector3, float, float>("Iteravio.ImprovedCrossbows.SneakAttackText", (Action<long, Vector3, float, float>)OnSneakAttackText); } } [HarmonyPatch(typeof(DamageText), "RPC_DamageText")] private static class SuppressPatch { private static bool Prefix(ZPackage pkg) { //IL_0015: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (Time.time > suppressUntil) { return true; } int num = pkg.ReadInt(); Vector3 val = pkg.ReadVector3(); pkg.SetPos(0); if (num == 7 || val != suppressPos) { return true; } suppressUntil = -1f; return false; } } private const string RpcName = "Iteravio.ImprovedCrossbows.SneakAttackText"; private const float SuppressWindowSeconds = 2f; private static readonly FieldRef<Character, float> BackstabTime = AccessTools.FieldRefAccess<Character, float>("m_backstabTime"); private static readonly Action<DamageText, long, ZPackage> ShowDamageTextLocally = AccessTools.MethodDelegate<Action<DamageText, long, ZPackage>>(AccessTools.Method(typeof(DamageText), "RPC_DamageText", (Type[])null, (Type[])null), (object)null, true); private static Character victim; private static HitData currentHit; private static float backstabTimeBefore; private static Vector3 suppressPos; private static float suppressUntil = -1f; private static void OnSneakAttackText(long sender, Vector3 pos, float dmg, float bonus) { //IL_0015: 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) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (Plugin.BigSneakAttackNumbers && !((Object)(object)DamageText.instance == (Object)null)) { suppressPos = pos; suppressUntil = Time.time + 2f; string text = dmg.ToString("0.#", CultureInfo.InvariantCulture) + " (x" + bonus.ToString("0.#", CultureInfo.InvariantCulture) + ")"; ZPackage val = new ZPackage(); val.Write(7); val.Write(pos); val.Write(text); val.Write(false); val.SetPos(0); ShowDamageTextLocally(DamageText.instance, ZNet.GetUID(), val); } } } internal static class Zoom { [HarmonyPatch(typeof(Player), "SetControls")] [HarmonyPriority(200)] private static class SetControlsPatch { private static void Prefix(Player __instance, ref bool block, ref bool blockHold, bool jump, bool dodge) { held = blockHold && Plugin.ZoomWithBlockButton && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && __instance.GetDoodadController() == null && Plugin.IsCrossbow(((Humanoid)__instance).GetCurrentWeapon()); if (!(!held || jump || dodge)) { block = false; blockHold = false; } } } [HarmonyPatch] private static class MoveSpeedPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Player), "GetJogSpeedFactor", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Player), "GetRunSpeedFactor", (Type[])null, (Type[])null); } private static void Postfix(Player __instance, ref float __result) { if (IsZoomingIn && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { __result *= Plugin.MoveSpeedFactorWhileZooming; } } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static class UpdateCameraPatch { private static void Postfix(GameCamera __instance, Camera ___m_camera, bool ___m_freeFly, AudioListener ___m_listner) { Player localPlayer = Player.m_localPlayer; IsZoomingIn = held && !___m_freeFly && (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && Plugin.ZoomWithBlockButton && Plugin.IsCrossbow(((Humanoid)localPlayer).GetCurrentWeapon()) && ((Humanoid)localPlayer).IsWeaponLoaded() && !((Character)localPlayer).InMinorAction() && !((Character)localPlayer).InAttack(); if (IsZoomingIn) { float num = Mathf.Max(0.1f, 2f * (1f - ((Character)localPlayer).GetSkillFactor((SkillType)14))); Progress = Mathf.MoveTowards(Progress, 1f, Time.deltaTime / num); } else { float num2 = (shotZoomOut ? 0.1f : 0.3f); Progress = Mathf.MoveTowards(Progress, 0f, Time.deltaTime / num2); if (Progress <= 0f) { shotZoomOut = false; } } UpdateMuffle(___m_listner); UpdatePlayerBounds(localPlayer); if (!(Progress <= 0f || ___m_freeFly)) { float fieldOfView = (___m_camera.fieldOfView = Mathf.Lerp(__instance.m_fov, __instance.m_fov / Plugin.ZoomMagnification, Progress)); __instance.m_skyCamera.fieldOfView = fieldOfView; } } } [HarmonyPatch(typeof(Attack), "Start")] private static class AttackStartPatch { private static void Postfix(bool __result, Humanoid character, ItemData weapon) { if (__result && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && Plugin.IsCrossbow(weapon)) { shotZoomOut = Progress > 0f; IsZoomingIn = false; if ((Object)(object)muffle != (Object)null) { ((Behaviour)muffle).enabled = false; } } } } private const float MinZoomInSeconds = 0.1f; private const float ZoomOutSeconds = 0.3f; private const float ShotZoomOutSeconds = 0.1f; private static bool held; private static bool shotZoomOut; private const float OpenCutoffHz = 22000f; private const float MuffledCutoffHz = 8000f; private static AudioLowPassFilter muffle; private const float BoundsRescanSeconds = 0.5f; private static readonly List<SkinnedMeshRenderer> boundsChanged = new List<SkinnedMeshRenderer>(); private static float nextBoundsScan; internal static float Progress { get; private set; } internal static bool IsZoomingIn { get; private set; } private static void UpdateMuffle(AudioListener listener) { if ((Object)(object)listener == (Object)null) { return; } if ((Object)(object)muffle == (Object)null) { muffle = ((Component)listener).GetComponent<AudioLowPassFilter>(); if ((Object)(object)muffle == (Object)null) { muffle = ((Component)listener).gameObject.AddComponent<AudioLowPassFilter>(); } ((Behaviour)muffle).enabled = false; } bool flag = Progress > 0f && !shotZoomOut && Plugin.MuffleSoundWhileZooming; ((Behaviour)muffle).enabled = flag; if (flag) { muffle.cutoffFrequency = Mathf.Exp(Mathf.Lerp(Mathf.Log(22000f), Mathf.Log(8000f), Progress)); } } private static void UpdatePlayerBounds(Player player) { if (Progress > 0f && (Object)(object)player != (Object)null) { if (Time.time < nextBoundsScan) { return; } nextBoundsScan = Time.time + 0.5f; SkinnedMeshRenderer[] componentsInChildren = ((Component)player).GetComponentsInChildren<SkinnedMeshRenderer>(); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (!val.updateWhenOffscreen) { val.updateWhenOffscreen = true; boundsChanged.Add(val); } } } else { if (boundsChanged.Count == 0) { return; } foreach (SkinnedMeshRenderer item in boundsChanged) { if ((Object)(object)item != (Object)null) { item.updateWhenOffscreen = false; } } boundsChanged.Clear(); nextBoundsScan = 0f; } } } }