Decompiled source of Grenade Launcher v1.0.2
BepInEx\plugins\DocValentyne-GrenadeLauncher\GrenadeLauncher.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; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using PluginConfig.API; using PluginConfig.API.Decorators; using PluginConfig.API.Fields; using Sandbox.Arm; using ULTRAKILL.Cheats; using ULTRAKILL.Enemy; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("GrenadeLauncher")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+4cb420845310a5af127943c5c300f3a8f26a3252")] [assembly: AssemblyProduct("GrenadeLauncher")] [assembly: AssemblyTitle("GrenadeLauncher")] [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 GrenadeLauncherMod { [BepInPlugin("docvalentyne.ultrakill.grenadelauncher", "Grenade Launcher", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "docvalentyne.ultrakill.grenadelauncher"; public const string Name = "Grenade Launcher"; public const string Version = "1.0.2"; private readonly Dictionary<int, ConfigEntry<bool>> slotLoadouts = new Dictionary<int, ConfigEntry<bool>>(); private readonly Dictionary<string, ConfigEntry<bool>> variantLoadouts = new Dictionary<string, ConfigEntry<bool>>(); private readonly Dictionary<int, ConfigEntry<bool>> variantMigrations = new Dictionary<int, ConfigEntry<bool>>(); private Harmony harmony; private GameObject runtimeHost; internal static Plugin Instance { get; private set; } internal static ManualLogSource LogSource { get; private set; } internal bool GrenadeModeEnabled { get { return GetSlotEntry(GameProgressSaver.currentSlot).Value; } set { GetSlotEntry(GameProgressSaver.currentSlot).Value = value; ((BaseUnityPlugin)this).Config.Save(); TerminalIntegration.RefreshAll(); } } internal bool AnyGrenadeModeEnabled { get { int slot = Math.Max(0, GameProgressSaver.currentSlot); if (!GetVariantMigrationEntry(slot).Value) { return GetSlotEntry(slot).Value; } if (!GetVariantEntry(slot, 0).Value && !GetVariantEntry(slot, 1).Value) { return GetVariantEntry(slot, 2).Value; } return true; } } internal bool IsGrenadeModeEnabled(int variation) { if (variation < 0 || variation > 2) { return false; } int slot = Math.Max(0, GameProgressSaver.currentSlot); if (!GetVariantMigrationEntry(slot).Value) { return GetSlotEntry(slot).Value; } return GetVariantEntry(slot, variation).Value; } internal bool IsGrenadeModeEnabled(RocketLauncher launcher) { if ((Object)(object)launcher != (Object)null) { return IsGrenadeModeEnabled(launcher.variation); } return false; } internal void SetGrenadeModeEnabled(int variation, bool enabled) { if (variation >= 0 && variation <= 2) { int slot = Math.Max(0, GameProgressSaver.currentSlot); EnsureVariantMigration(); GetVariantEntry(slot, variation).Value = enabled; ((BaseUnityPlugin)this).Config.Save(); } } internal void EnsureVariantMigration() { int slot = Math.Max(0, GameProgressSaver.currentSlot); ConfigEntry<bool> variantMigrationEntry = GetVariantMigrationEntry(slot); if (!variantMigrationEntry.Value) { bool value = GetSlotEntry(slot).Value; for (int i = 0; i < 3; i++) { GetVariantEntry(slot, i).Value = value; } variantMigrationEntry.Value = true; ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Migrated the old all-rocket loadout to per-variant Grenade Launcher choices for save slot " + slot + ".")); } } private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown Instance = this; LogSource = ((BaseUnityPlugin)this).Logger; PluginSettings.Initialize(); harmony = new Harmony("docvalentyne.ultrakill.grenadelauncher"); harmony.PatchAll(typeof(Plugin).Assembly); runtimeHost = new GameObject("Grenade Launcher Runtime"); Object.DontDestroyOnLoad((Object)(object)runtimeHost); ((Object)runtimeHost).hideFlags = (HideFlags)61; runtimeHost.AddComponent<TerminalIntegration>(); runtimeHost.AddComponent<AlternateFireRuntime>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Grenade Launcher v1.0.2 loaded."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } GrenadeSpawnContext.Reset(); GrenadeLauncherHookContext.Reset(); AlternateFireRuntime.CleanupAll(); TerminalIntegration.Cleanup(); if ((Object)(object)runtimeHost != (Object)null) { Object.Destroy((Object)(object)runtimeHost); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } if (LogSource == ((BaseUnityPlugin)this).Logger) { LogSource = null; } } private ConfigEntry<bool> GetSlotEntry(int slot) { if (slot < 0) { slot = 0; } if (!slotLoadouts.TryGetValue(slot, out var value)) { value = ((BaseUnityPlugin)this).Config.Bind<bool>("Loadout", "SaveSlot" + slot + "UsesGrenadeLauncher", false, "Equip Grenade Launcher primary fire for all three Rocket Launcher variants in this save slot."); slotLoadouts.Add(slot, value); } return value; } private ConfigEntry<bool> GetVariantEntry(int slot, int variation) { string key = slot + ":" + variation; if (!variantLoadouts.TryGetValue(key, out var value)) { value = ((BaseUnityPlugin)this).Config.Bind<bool>("Loadout", "SaveSlot" + slot + "RocketVariant" + variation + "UsesGrenadeLauncher", false, "Use the alternate Grenade Launcher form for this Rocket Launcher variant."); variantLoadouts.Add(key, value); } return value; } private ConfigEntry<bool> GetVariantMigrationEntry(int slot) { if (!variantMigrations.TryGetValue(slot, out var value)) { value = ((BaseUnityPlugin)this).Config.Bind<bool>("Loadout", "SaveSlot" + slot + "PerVariantLoadoutMigrated", false, "Whether the old all-rocket setting has been copied to the native per-variant terminal controls."); variantMigrations.Add(slot, value); } return value; } } [HarmonyPatch(typeof(LeaderboardController), "SubmitCyberGrindScore")] internal static class CyberGrindLeaderboardPatch { private static bool Prefix() { ManualLogSource logSource = Plugin.LogSource; if (logSource != null) { logSource.LogInfo((object)"Blocked Cyber Grind leaderboard submission while Grenade Launcher is loaded; local high score remains enabled."); } return false; } } internal enum GrenadeProjectileProfile { Primary, GreenContact, BlueDelivery } internal static class GrenadeSpawnContext { private static int depth; internal static bool Active => depth > 0; internal static GrenadeProjectileProfile Profile { get; private set; } internal static void Enter(GrenadeProjectileProfile profile = GrenadeProjectileProfile.Primary) { if (depth == 0) { Profile = profile; } depth++; } internal static void Exit() { depth = Math.Max(0, depth - 1); } internal static void Reset() { depth = 0; Profile = GrenadeProjectileProfile.Primary; } } internal static class SharedRocketFireCooldown { private static float readyAt; internal static bool Ready { get { if (!CooldownRules.NoWeaponCooldown) { return Time.time >= readyAt; } return true; } } internal static void Mark(float duration) { if (!CooldownRules.NoWeaponCooldown) { readyAt = Mathf.Max(readyAt, Time.time + Mathf.Max(0.05f, duration)); } } internal static void Reset() { readyAt = 0f; } } internal static class CooldownRules { internal static bool NoWeaponCooldown => NoWeaponCooldown.NoCooldown; } [HarmonyPatch(typeof(RocketLauncher), "Shoot")] internal static class RocketLauncherShootPatch { private struct State { internal bool Active; internal bool EnteredContext; internal bool Executed; internal bool SharedEnforced; internal bool NotifyGreenPrimary; internal bool NotifyBluePrimary; internal float RateOfFire; internal float SharedInterval; } private static readonly FieldRef<RocketLauncher, WeaponIdentifier> WeaponId = AccessTools.FieldRefAccess<RocketLauncher, WeaponIdentifier>("wid"); private static bool Prefix(RocketLauncher __instance, out State __state) { bool flag = (Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.IsGrenadeModeEnabled(__instance); bool flag2 = (Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.AnyGrenadeModeEnabled; WeaponIdentifier val = WeaponId.Invoke(__instance); bool flag3 = (Object)(object)val != (Object)null && val.duplicate; __state = new State { Active = flag, SharedEnforced = (flag2 && !flag3), RateOfFire = __instance.rateOfFire, SharedInterval = (flag ? PluginSettings.FireInterval : __instance.rateOfFire) }; if (__state.SharedEnforced && !SharedRocketFireCooldown.Ready) { return false; } __state.Executed = true; if (!__state.Active) { return true; } __instance.rateOfFire = PluginSettings.FireInterval; if (!GrenadeSpawnContext.Active) { __state.NotifyGreenPrimary = __instance.variation == 1; __state.NotifyBluePrimary = __instance.variation == 0; GrenadeSpawnContext.Enter(); __state.EnteredContext = true; } return true; } private static Exception Finalizer(RocketLauncher __instance, State __state, Exception __exception) { Restore(__instance, __state); if (__exception == null && __state.Executed && __state.SharedEnforced) { SharedRocketFireCooldown.Mark(__state.SharedInterval); } if (__exception == null && __state.NotifyGreenPrimary) { AlternateFireController.OnGreenPrimaryFired(); } if (__exception == null && __state.NotifyBluePrimary) { AlternateFireController.OnBluePrimaryFired(); } return __exception; } private static void Restore(RocketLauncher launcher, State state) { if (state.Active) { launcher.rateOfFire = state.RateOfFire; if (state.EnteredContext) { GrenadeSpawnContext.Exit(); } } } } [HarmonyPatch(typeof(CameraController), "CameraShake", new Type[] { typeof(float) })] internal static class GrenadeLauncherCameraShakePatch { private static bool Prefix() { return !GrenadeSpawnContext.Active; } } [HarmonyPatch(typeof(ObjectTracker), "GetGrenade")] internal static class GrenadeLauncherWhiplashPatch { private static void Postfix(ref Grenade __result) { if (!((Object)(object)__result == (Object)null)) { GrenadeLauncherProjectile component = ((Component)__result).GetComponent<GrenadeLauncherProjectile>(); if ((Object)(object)component != (Object)null && !component.CanBeWhiplashed) { __result = null; } if ((Object)(object)__result != (Object)null && (Object)(object)((Component)__result).GetComponent<BlueHookDeliveryProjectile>() != (Object)null) { __result = null; } } } } internal static class GrenadeLauncherHookContext { private static int depth; internal static bool Active => depth > 0; internal static void Enter() { depth++; } internal static void Exit() { depth = Math.Max(0, depth - 1); } internal static void Reset() { depth = 0; } } [HarmonyPatch(typeof(HookArm), "FixedUpdate")] internal static class GrenadeLauncherHookArmPatch { private static void Prefix() { GrenadeLauncherHookContext.Enter(); } private static Exception Finalizer(Exception __exception) { GrenadeLauncherHookContext.Exit(); return __exception; } } [HarmonyPatch(typeof(Grenade), "Explode", new Type[] { typeof(bool), typeof(bool), typeof(bool), typeof(float), typeof(bool), typeof(GameObject), typeof(bool) })] internal static class GrenadeLauncherHookExplosionPatch { private static bool Prefix(Grenade __instance) { if ((Object)(object)((Component)__instance).GetComponent<BlueHookDeliveryProjectile>() != (Object)null) { return false; } GrenadeLauncherProjectile component = ((Component)__instance).GetComponent<GrenadeLauncherProjectile>(); if ((Object)(object)component == (Object)null) { return true; } if (component.IsStuck) { if (StuckDetonationContext.CanCurrentBeamDetonate) { component.DetonateStuck(); } return false; } return !GrenadeLauncherHookContext.Active; } } internal static class PluginSettings { internal const string ArcOriginal = "Original TF2-scaled arc"; internal const string ArcCurrent = "Current snappier arc"; internal const string ArcCustom = "Custom gravity"; private static StringListField arcPreset; private static FloatSliderField damage; private static FloatSliderField speed; private static FloatSliderField upwardVelocity; private static FloatSliderField customGravity; private static FloatSliderField fireInterval; private static FloatSliderField explosionSize; private static FloatSliderField knockback; private static FloatSliderField lifetime; private static FloatSliderField surfaceFuse; private static FloatSliderField hookFuseGrace; private static FloatSliderField surfaceDamage; private static FloatSliderField bounceRetention; private static FloatSliderField parryDamage; private static FloatSliderField parryExplosionSize; private static FloatSliderField parrySpeed; private static FloatSliderField directSelfDamage; private static FloatSliderField surfaceSelfDamage; private static FloatSliderField parrySelfDamage; private static BoolField eyeHeightScaling; private static FloatSliderField fallbackEyeHeight; private static Texture2D configuratorIconTexture; private static Sprite configuratorIconSprite; private static readonly Dictionary<EnemyType, FloatSliderField> enemyDamageMultipliers = new Dictionary<EnemyType, FloatSliderField>(); private static readonly Dictionary<EnemyType, float> releaseEnemyDamageDefaults = new Dictionary<EnemyType, float> { { (EnemyType)0, 120f }, { (EnemyType)33, 110f }, { (EnemyType)2, 85f }, { (EnemyType)4, 100f }, { (EnemyType)31, 200f }, { (EnemyType)38, 175f }, { (EnemyType)14, 125f } }; private static FloatSliderField greenCooldown; private static FloatSliderField greenSpeed; private static FloatSliderField greenUpwardVelocity; private static FloatSliderField greenGravity; private static FloatSliderField greenDirectDamage; private static FloatSliderField greenSurfaceDamage; private static FloatSliderField greenDirectExplosionSize; private static FloatSliderField greenSurfaceExplosionSize; private static FloatSliderField greenDirectSelfDamage; private static FloatSliderField greenSurfaceSelfDamage; private static FloatSliderField greenKnockback; private static FloatSliderField greenLifetime; private static FloatSliderField gelProjectileSpeed; private static FloatSliderField gelCoveragePerDroplet; private static FloatSliderField gelCoverageRequired; private static FloatSliderField gelSpotSize; private static FloatSliderField stuckDamage; private static FloatSliderField greenStuckDamage; private static FloatSliderField stuckExplosionSize; private static FloatSliderField stuckSelfDamage; private static FloatSliderField stuckKnockback; private static FloatSliderField stuckChainRadius; private static FloatSliderField stuckChainPropagationSpeed; private static BoolField enemyCarrierDirectDamage; private static BoolField timedFuseDetonatesStuck; private static FloatSliderField blueDistance; private static FloatSliderField blueCooldown; private static FloatSliderField blueSlingshotForce; private static FloatSliderField bluePointSize; private static FloatSliderField pipeDreamDistance; private static FloatSliderField moonShotDistance; private static FloatSliderField pipeDreamStylePoints; private static FloatSliderField moonShotStylePoints; private static FloatSliderField outSnipedStylePoints; private static FloatSliderField walkingBombStylePoints; private static FloatSliderField pipeDreamDamageMultiplier; private static FloatSliderField pipeDreamExplosionSizeMultiplier; private static FloatSliderField moonShotDamageMultiplier; private static FloatSliderField moonShotExplosionSizeMultiplier; private static BoolField rangeTelemetry; internal static float Damage { get { FloatSliderField obj = damage; if (obj == null) { return 4f; } return obj.value; } } internal static float SpeedMultiplier { get { FloatSliderField obj = speed; if (obj == null) { return 1f; } return obj.value; } } internal static float UpwardVelocityMultiplier { get { FloatSliderField obj = upwardVelocity; if (obj == null) { return 1f; } return obj.value; } } internal static float FireInterval { get { FloatSliderField obj = fireInterval; if (obj == null) { return 0.6f; } return obj.value; } } internal static float ExplosionSizeMultiplier { get { FloatSliderField obj = explosionSize; if (obj == null) { return 0.9f; } return obj.value; } } internal static float KnockbackMultiplier { get { FloatSliderField obj = knockback; if (obj == null) { return 1f; } return obj.value; } } internal static float Lifetime { get { FloatSliderField obj = lifetime; if (obj == null) { return 15f; } return obj.value; } } internal static float SurfaceFuse { get { FloatSliderField obj = surfaceFuse; if (obj == null) { return 1f; } return obj.value; } } internal static float HookFuseGrace { get { FloatSliderField obj = hookFuseGrace; if (obj == null) { return 0.1f; } return obj.value; } } internal static float SurfaceDamage { get { FloatSliderField obj = surfaceDamage; if (obj == null) { return 2.5f; } return obj.value; } } internal static float BounceRetention { get { FloatSliderField obj = bounceRetention; if (obj == null) { return 0.1f; } return obj.value; } } internal static float ParryDamage { get { FloatSliderField obj = parryDamage; if (obj == null) { return 4.5f; } return obj.value; } } internal static float ParryExplosionSize { get { FloatSliderField obj = parryExplosionSize; if (obj == null) { return 1f; } return obj.value; } } internal static float ParrySpeedMultiplier { get { FloatSliderField obj = parrySpeed; if (obj == null) { return 3f; } return obj.value; } } internal static float DirectSelfDamage { get { FloatSliderField obj = directSelfDamage; if (obj == null) { return 35f; } return obj.value; } } internal static float SurfaceSelfDamage { get { FloatSliderField obj = surfaceSelfDamage; if (obj == null) { return 25f; } return obj.value; } } internal static float ParrySelfDamage { get { FloatSliderField obj = parrySelfDamage; if (obj == null) { return 30f; } return obj.value; } } internal static bool EyeHeightScaling { get { BoolField obj = eyeHeightScaling; if (obj == null) { return true; } return obj.value; } } internal static float FallbackEyeHeight { get { FloatSliderField obj = fallbackEyeHeight; if (obj == null) { return 2.9f; } return obj.value; } } internal static float GravityMultiplier { get { StringListField obj = arcPreset; string text = ((obj != null) ? obj.value : null) ?? "Original TF2-scaled arc"; if (text == "Original TF2-scaled arc") { return 1f; } if (text == "Current snappier arc") { return 2f; } FloatSliderField obj2 = customGravity; if (obj2 == null) { return 1f; } return obj2.value; } } internal static float GreenCooldown { get { FloatSliderField obj = greenCooldown; if (obj == null) { return 6f; } return obj.value; } } internal static float GreenSpeedMultiplier { get { FloatSliderField obj = greenSpeed; if (obj == null) { return 1.5f; } return obj.value; } } internal static float GreenUpwardVelocityMultiplier { get { FloatSliderField obj = greenUpwardVelocity; if (obj == null) { return 1f; } return obj.value; } } internal static float GreenGravityMultiplier { get { FloatSliderField obj = greenGravity; if (obj == null) { return 1f; } return obj.value; } } internal static float GreenDirectDamage { get { FloatSliderField obj = greenDirectDamage; if (obj == null) { return 6f; } return obj.value; } } internal static float GreenSurfaceDamage { get { FloatSliderField obj = greenSurfaceDamage; if (obj == null) { return 4f; } return obj.value; } } internal static float GreenDirectExplosionSize { get { FloatSliderField obj = greenDirectExplosionSize; if (obj == null) { return 1.4f; } return obj.value; } } internal static float GreenSurfaceExplosionSize { get { FloatSliderField obj = greenSurfaceExplosionSize; if (obj == null) { return 1f; } return obj.value; } } internal static float GreenDirectSelfDamage { get { FloatSliderField obj = greenDirectSelfDamage; if (obj == null) { return 35f; } return obj.value; } } internal static float GreenSurfaceSelfDamage { get { FloatSliderField obj = greenSurfaceSelfDamage; if (obj == null) { return 35f; } return obj.value; } } internal static float GreenKnockbackMultiplier { get { FloatSliderField obj = greenKnockback; if (obj == null) { return 1f; } return obj.value; } } internal static float GreenLifetime { get { FloatSliderField obj = greenLifetime; if (obj == null) { return 15f; } return obj.value; } } internal static float GelProjectileSpeedMultiplier { get { FloatSliderField obj = gelProjectileSpeed; if (obj == null) { return 1f; } return obj.value; } } internal static float GelCoveragePerDroplet { get { FloatSliderField obj = gelCoveragePerDroplet; return ((obj != null) ? obj.value : 4f) / 100f; } } internal static float GelCoverageRequired { get { FloatSliderField obj = gelCoverageRequired; return ((obj != null) ? obj.value : 75f) / 100f; } } internal static float GelSpotSize { get { FloatSliderField obj = gelSpotSize; if (obj == null) { return 1.25f; } return obj.value; } } internal static float StuckDamage { get { FloatSliderField obj = stuckDamage; if (obj == null) { return 4f; } return obj.value; } } internal static float GreenStuckDamage { get { FloatSliderField obj = greenStuckDamage; if (obj == null) { return 6f; } return obj.value; } } internal static float StuckExplosionSize { get { FloatSliderField obj = stuckExplosionSize; if (obj == null) { return 1.3f; } return obj.value; } } internal static float StuckSelfDamage { get { FloatSliderField obj = stuckSelfDamage; if (obj == null) { return 45f; } return obj.value; } } internal static float StuckKnockbackMultiplier { get { FloatSliderField obj = stuckKnockback; if (obj == null) { return 1f; } return obj.value; } } internal static float StuckChainRadiusMultiplier { get { FloatSliderField obj = stuckChainRadius; if (obj == null) { return 2f; } return obj.value; } } internal static float StuckChainPropagationSpeed { get { FloatSliderField obj = stuckChainPropagationSpeed; if (obj == null) { return 50f; } return obj.value; } } internal static bool EnemyCarrierTakesDirectDamage { get { BoolField obj = enemyCarrierDirectDamage; if (obj == null) { return true; } return obj.value; } } internal static bool TimedFuseDetonatesStuck { get { BoolField obj = timedFuseDetonatesStuck; if (obj == null) { return false; } return obj.value; } } internal static float BlueDistance { get { FloatSliderField obj = blueDistance; if (obj == null) { return 27f; } return obj.value; } } internal static float BlueCooldown { get { FloatSliderField obj = blueCooldown; if (obj == null) { return 7f; } return obj.value; } } internal static float BlueSlingshotForce { get { FloatSliderField obj = blueSlingshotForce; if (obj == null) { return 0f; } return obj.value; } } internal static float BluePointSize { get { FloatSliderField obj = bluePointSize; if (obj == null) { return 1f; } return obj.value; } } internal static float PipeDreamMinimumDistance { get { FloatSliderField obj = pipeDreamDistance; if (obj == null) { return 56f; } return obj.value; } } internal static float MoonShotMinimumDistance { get { FloatSliderField obj = moonShotDistance; if (obj == null) { return 125f; } return obj.value; } } internal static int PipeDreamStylePoints { get { FloatSliderField obj = pipeDreamStylePoints; return Mathf.RoundToInt((obj != null) ? obj.value : 100f); } } internal static int MoonShotStylePoints { get { FloatSliderField obj = moonShotStylePoints; return Mathf.RoundToInt((obj != null) ? obj.value : 500f); } } internal static int OutSnipedStylePoints { get { FloatSliderField obj = outSnipedStylePoints; return Mathf.RoundToInt((obj != null) ? obj.value : 500f); } } internal static int WalkingBombStylePoints { get { FloatSliderField obj = walkingBombStylePoints; return Mathf.RoundToInt((obj != null) ? obj.value : 90f); } } internal static float PipeDreamDamageMultiplier { get { FloatSliderField obj = pipeDreamDamageMultiplier; if (obj == null) { return 1f; } return obj.value; } } internal static float PipeDreamExplosionSizeMultiplier { get { FloatSliderField obj = pipeDreamExplosionSizeMultiplier; if (obj == null) { return 1f; } return obj.value; } } internal static float MoonShotDamageMultiplier { get { FloatSliderField obj = moonShotDamageMultiplier; if (obj == null) { return 1.15f; } return obj.value; } } internal static float MoonShotExplosionSizeMultiplier { get { FloatSliderField obj = moonShotExplosionSizeMultiplier; if (obj == null) { return 1.15f; } return obj.value; } } internal static bool RangeTelemetryEnabled { get { BoolField obj = rangeTelemetry; if (obj == null) { return false; } return obj.value; } } internal static float GetEnemyDamageMultiplier(EnemyType enemyType) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!enemyDamageMultipliers.TryGetValue(enemyType, out var value)) { return 1f; } return Mathf.Max(0f, value.value) / 100f; } internal unsafe static void Initialize() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0315: 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_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Expected O, but got Unknown //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Expected O, but got Unknown //IL_035a: Expected O, but got Unknown //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Expected O, but got Unknown //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) PluginConfigurator val = PluginConfigurator.Create("Grenade Launcher", "docvalentyne.ultrakill.grenadelauncher"); ApplyConfiguratorIcon(val); new ConfigHeader(val.rootPanel, "Get comfortable with the weapon before changing its settings.", 24); arcPreset = new StringListField(val.rootPanel, "Arc preset", "arcPreset", new string[3] { "Current snappier arc", "Original TF2-scaled arc", "Custom gravity" }, "Original TF2-scaled arc"); damage = Slider(val, "Damage", "damage", 0f, 10f, 4f, 2); MigrateDamageDefault(); speed = Slider(val, "Projectile speed multiplier", "speedMultiplier", 0.1f, 3f, 1f, 2); upwardVelocity = Slider(val, "Upward velocity multiplier", "upwardVelocityMultiplier", 0f, 3f, 1f, 2); customGravity = Slider(val, "Custom gravity multiplier", "customGravityMultiplier", 0.1f, 5f, 1f, 2); fireInterval = Slider(val, "Fire interval (seconds)", "fireInterval", 0.1f, 2f, 0.6f, 2); explosionSize = Slider(val, "Explosion size (rocket = 1)", "explosionSizeMultiplier", 0.25f, 3f, 0.9f, 2); knockback = Slider(val, "Explosion knockback (rocket = 1)", "knockbackMultiplier", 0f, 3f, 1f, 2); lifetime = Slider(val, "Silent projectile lifetime", "projectileLifetime", 1f, 60f, 15f, 1); surfaceFuse = Slider(val, "Surface fuse (seconds)", "surfaceFuse", 0.1f, 10f, 1f, 2); hookFuseGrace = Slider(val, "Fuse time added per Whiplash hook (seconds)", "hookFuseGrace", 0f, 2f, 0.1f, 2); surfaceDamage = Slider(val, "Surface detonation damage", "surfaceDamage", 0f, 10f, 2.5f, 2); bounceRetention = Slider(val, "Surface bounce speed retention", "bounceRetention", 0f, 1f, 0.1f, 2); parryDamage = Slider(val, "Parried grenade damage", "parryDamage", 0f, 20f, 4.5f, 2); parryExplosionSize = Slider(val, "Parried explosion size (rocket = 1)", "parryExplosionSize", 0.25f, 5f, 1f, 2); parrySpeed = Slider(val, "Parried projectile speed multiplier", "parrySpeedMultiplier", 0.1f, 5f, 3f, 2); directSelfDamage = Slider(val, "Direct explosion self damage (HP)", "directSelfDamage", 0f, 100f, 35f, 0); surfaceSelfDamage = Slider(val, "Timed explosion self damage (HP)", "surfaceSelfDamage", 0f, 100f, 25f, 0); parrySelfDamage = Slider(val, "Parried explosion self damage (HP)", "parrySelfDamage", 0f, 100f, 30f, 0); ConfigPanel val2 = new ConfigPanel(val.rootPanel, "Debug / trajectory calibration", "debugTrajectoryCalibration") { headerText = "Only change these when diagnosing trajectory calibration." }; eyeHeightScaling = new BoolField(val2, "Use eye-height calibration", "eyeHeightScaling", true); fallbackEyeHeight = Slider(val2, "Fallback V1 eye height", "fallbackEyeHeight", 0.5f, 10f, 2.9f, 2); InitializeAlternateSettings(val); ConfigPanel val3 = new ConfigPanel(val.rootPanel, "Enemy grenade damage", "enemyDamageMultipliers"); val3.headerText = "Damage percentage is applied after ULTRAKILL's normal explosive weakness or resistance."; enemyDamageMultipliers.Clear(); foreach (EnemyType item in from EnemyType val4 in Enum.GetValues(typeof(EnemyType)) orderby ((object)(*(EnemyType*)(&val4))/*cast due to .constrained prefix*/).ToString() select val4) { enemyDamageMultipliers[item] = Slider(val3, FriendlyEnemyName(item) + " damage (%)", "enemyDamage_" + ((object)(*(EnemyType*)(&item))/*cast due to .constrained prefix*/).ToString(), 0f, 500f, releaseEnemyDamageDefaults.TryGetValue(item, out var value) ? value : 100f, 0); } } private static void ApplyConfiguratorIcon(PluginConfigurator configurator) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("GrenadeLauncherMod.icon.png"); if (stream == null) { ManualLogSource logSource = Plugin.LogSource; if (logSource != null) { logSource.LogWarning((object)"Embedded Plugin Configurator icon was not found."); } return; } byte[] array = new byte[stream.Length]; int i; int num; for (i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } if (i != array.Length) { ManualLogSource logSource2 = Plugin.LogSource; if (logSource2 != null) { logSource2.LogWarning((object)"Embedded Plugin Configurator icon could not be read completely."); } return; } configuratorIconTexture = new Texture2D(2, 2, (TextureFormat)4, false); ((Object)configuratorIconTexture).name = "Grenade Launcher Icon"; if (!ImageConversion.LoadImage(configuratorIconTexture, array, false)) { Object.Destroy((Object)(object)configuratorIconTexture); configuratorIconTexture = null; ManualLogSource logSource3 = Plugin.LogSource; if (logSource3 != null) { logSource3.LogWarning((object)"Embedded Plugin Configurator icon was not a valid image."); } } else { configuratorIconSprite = Sprite.Create(configuratorIconTexture, new Rect(0f, 0f, (float)((Texture)configuratorIconTexture).width, (float)((Texture)configuratorIconTexture).height), new Vector2(0.5f, 0.5f)); ((Object)configuratorIconSprite).name = "Grenade Launcher Icon"; configurator.icon = configuratorIconSprite; } } private static FloatSliderField Slider(PluginConfigurator configurator, string displayName, string guid, float minimum, float maximum, float defaultValue, int decimals) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown return new FloatSliderField(configurator.rootPanel, displayName, guid, new Tuple<float, float>(minimum, maximum), defaultValue, decimals); } private static FloatSliderField Slider(ConfigPanel panel, string displayName, string guid, float minimum, float maximum, float defaultValue, int decimals) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown return new FloatSliderField(panel, displayName, guid, new Tuple<float, float>(minimum, maximum), defaultValue, decimals); } private unsafe static string FriendlyEnemyName(EnemyType enemyType) { string text = ((object)(*(EnemyType*)(&enemyType))/*cast due to .constrained prefix*/).ToString(); StringBuilder stringBuilder = new StringBuilder(text.Length + 8); for (int i = 0; i < text.Length; i++) { char c = text[i]; if (i > 0 && char.IsUpper(c) && !char.IsUpper(text[i - 1])) { stringBuilder.Append(' '); } stringBuilder.Append(c); } return stringBuilder.ToString(); } private static void MigrateDamageDefault() { ConfigEntry<int> val = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<int>("Migration", "DefaultsVersion", 0, "Internal version used to apply changed defaults once without overwriting later customization."); if (val.Value < 1) { if (Mathf.Approximately(damage.value, 3f)) { damage.value = 4f; } val.Value = 1; ((BaseUnityPlugin)Plugin.Instance).Config.Save(); } } private static void InitializeAlternateSettings(PluginConfigurator configurator) { //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_0035: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01cb: Expected O, but got Unknown //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Expected O, but got Unknown //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Expected O, but got Unknown //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Expected O, but got Unknown //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Expected O, but got Unknown //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Expected O, but got Unknown //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Expected O, but got Unknown //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Expected O, but got Unknown //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Expected O, but got Unknown //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Expected O, but got Unknown //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Expected O, but got Unknown //IL_03a2: Expected O, but got Unknown //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Expected O, but got Unknown //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Expected O, but got Unknown //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Expected O, but got Unknown //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Expected O, but got Unknown //IL_044a: Expected O, but got Unknown //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Expected O, but got Unknown //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Expected O, but got Unknown //IL_04ae: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Expected O, but got Unknown //IL_04d3: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Expected O, but got Unknown //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Expected O, but got Unknown //IL_051d: Unknown result type (might be due to invalid IL or missing references) //IL_053d: Expected O, but got Unknown //IL_0542: Unknown result type (might be due to invalid IL or missing references) //IL_0562: Expected O, but got Unknown //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_0587: Expected O, but got Unknown //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_05ac: Expected O, but got Unknown //IL_05d0: Expected O, but got Unknown //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_05ea: Unknown result type (might be due to invalid IL or missing references) //IL_0605: Expected O, but got Unknown //IL_0600: Unknown result type (might be due to invalid IL or missing references) //IL_060a: Expected O, but got Unknown ConfigPanel val = new ConfigPanel(configurator.rootPanel, "Green contact grenade", "greenContactGrenade"); greenCooldown = Slider(val, "Cooldown (seconds)", "greenCooldown", 0.05f, 10f, 6f, 2); greenSpeed = Slider(val, "Projectile speed multiplier", "greenSpeedMultiplier", 0.1f, 5f, 1.5f, 2); greenUpwardVelocity = Slider(val, "Upward velocity multiplier", "greenUpwardVelocityMultiplier", 0f, 5f, 1f, 2); greenGravity = Slider(val, "Gravity multiplier", "greenGravityMultiplier", 0.1f, 5f, 1f, 2); greenDirectDamage = Slider(val, "Direct hit damage", "greenDirectDamage", 0f, 20f, 6f, 2); greenSurfaceDamage = Slider(val, "Surface contact damage", "greenSurfaceDamage", 0f, 20f, 4f, 2); greenDirectExplosionSize = Slider(val, "Direct explosion size (rocket = 1)", "greenDirectExplosionSize", 0.1f, 5f, 1.4f, 2); greenSurfaceExplosionSize = Slider(val, "Surface explosion size (rocket = 1)", "greenSurfaceExplosionSize", 0.1f, 5f, 1f, 2); greenDirectSelfDamage = Slider(val, "Direct self damage (HP)", "greenDirectSelfDamage", 0f, 100f, 35f, 0); greenSurfaceSelfDamage = Slider(val, "Surface self damage (HP)", "greenSurfaceSelfDamage", 0f, 100f, 35f, 0); greenKnockback = Slider(val, "Explosion knockback (rocket = 1)", "greenKnockbackMultiplier", 0f, 5f, 1f, 2); greenLifetime = Slider(val, "Silent projectile lifetime", "greenLifetime", 1f, 60f, 15f, 1); ConfigPanel val2 = new ConfigPanel(configurator.rootPanel, "Red blue-gel system", "redGelSystem"); gelProjectileSpeed = Slider(val2, "Gel projectile speed multiplier", "gelProjectileSpeedMultiplier", 0.1f, 5f, 1f, 2); gelCoveragePerDroplet = Slider(val2, "Enemy coverage per droplet (%)", "gelCoveragePerDroplet", 0.1f, 100f, 4f, 1); gelCoverageRequired = Slider(val2, "Enemy coverage required (%)", "gelCoverageRequired", 0f, 100f, 75f, 1); gelSpotSize = Slider(val2, "Terrain gel size (normal = 1)", "gelSpotSize", 0.1f, 5f, 1.25f, 2); stuckDamage = Slider(val2, "Primary stuck grenade damage", "stuckDamage", 0f, 20f, 4f, 2); greenStuckDamage = Slider(val2, "Green stuck grenade damage", "greenStuckDamage", 0f, 20f, 6f, 2); stuckExplosionSize = Slider(val2, "Stuck explosion size (rocket = 1)", "stuckExplosionSize", 0.1f, 5f, 1.3f, 2); stuckSelfDamage = Slider(val2, "Stuck explosion self damage (HP)", "stuckSelfDamage", 0f, 100f, 45f, 0); stuckKnockback = Slider(val2, "Stuck explosion knockback (rocket = 1)", "stuckKnockbackMultiplier", 0f, 5f, 1f, 2); stuckChainRadius = Slider(val2, "Stuck grenade chain radius multiplier", "stuckChainRadiusMultiplier", 0f, 10f, 2f, 2); stuckChainPropagationSpeed = Slider(val2, "Chain propagation speed (units/second)", "stuckChainPropagationSpeed", 1f, 200f, 50f, 1); enemyCarrierDirectDamage = new BoolField(val2, "Enemy carrier takes direct-hit damage", "enemyCarrierDirectDamage", true); timedFuseDetonatesStuck = new BoolField(val2, "Timed-fuse explosions detonate stuck grenades", "timedFuseDetonatesStuck", false); ConfigPanel val3 = new ConfigPanel(configurator.rootPanel, "Blue slingshot point", "blueSlingshotPoint"); blueDistance = Slider(val3, "Placement distance", "bluePlacementDistance", 5.5f, 200f, 27f, 1); blueCooldown = Slider(val3, "Cooldown (seconds)", "blueCooldown", 0.05f, 10f, 7f, 2); blueSlingshotForce = Slider(val3, "Extra slingshot force", "blueSlingshotForce", -50f, 200f, 0f, 1); bluePointSize = Slider(val3, "Hook point size multiplier", "bluePointSize", 0.25f, 4f, 1f, 2); ConfigPanel val4 = new ConfigPanel(configurator.rootPanel, "Style bonuses", "styleBonuses"); pipeDreamDistance = Slider(val4, "PIPE DREAM minimum distance", "pipeDreamMinimumDistance", 1f, 250f, 56f, 1); moonShotDistance = Slider(val4, "MOON SHOT / OUT-SNIPED minimum distance", "moonShotMinimumDistance", 1f, 400f, 125f, 1); pipeDreamStylePoints = Slider(val4, "PIPE DREAM style points", "pipeDreamStylePoints", 0f, 5000f, 100f, 0); moonShotStylePoints = Slider(val4, "MOON SHOT style points", "moonShotStylePoints", 0f, 5000f, 500f, 0); outSnipedStylePoints = Slider(val4, "OUT-SNIPED style points", "outSnipedStylePoints", 0f, 5000f, 500f, 0); walkingBombStylePoints = Slider(val4, "WALKING BOMB style points", "walkingBombStylePoints", 0f, 5000f, 90f, 0); pipeDreamDamageMultiplier = Slider(val4, "PIPE DREAM damage multiplier", "pipeDreamDamageMultiplier", 0f, 10f, 1f, 2); pipeDreamExplosionSizeMultiplier = Slider(val4, "PIPE DREAM explosion size multiplier", "pipeDreamExplosionSizeMultiplier", 0.1f, 10f, 1f, 2); moonShotDamageMultiplier = Slider(val4, "MOON SHOT damage multiplier", "moonShotDamageMultiplier", 0f, 10f, 1.15f, 2); moonShotExplosionSizeMultiplier = Slider(val4, "MOON SHOT explosion size multiplier", "moonShotExplosionSizeMultiplier", 0.1f, 10f, 1.15f, 2); rangeTelemetry = new BoolField(new ConfigPanel(configurator.rootPanel, "Debug logging", "debugLogging") { headerText = "These settings only write diagnostic information to the BepInEx log." }, "Log direct-hit ranges", "rangeTelemetry", false); } } [HarmonyPatch(typeof(Grenade), "Awake")] internal static class GrenadeAwakePatch { private static void Postfix(Grenade __instance) { //IL_0030: 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) if (!GrenadeSpawnContext.Active) { return; } if (GrenadeSpawnContext.Profile == GrenadeProjectileProfile.BlueDelivery) { if ((Object)(object)((Component)__instance).GetComponent<BlueHookDeliveryProjectile>() == (Object)null) { BlueHookDeliveryProjectile blueHookDeliveryProjectile = ((Component)__instance).gameObject.AddComponent<BlueHookDeliveryProjectile>(); blueHookDeliveryProjectile.Grenade = __instance; blueHookDeliveryProjectile.Target = BlueHookDeliveryContext.Target; } } else if ((Object)(object)((Component)__instance).GetComponent<GrenadeLauncherProjectile>() == (Object)null) { GrenadeLauncherProjectile grenadeLauncherProjectile = ((Component)__instance).gameObject.AddComponent<GrenadeLauncherProjectile>(); grenadeLauncherProjectile.Grenade = __instance; grenadeLauncherProjectile.Profile = GrenadeSpawnContext.Profile; } } } [HarmonyPatch(typeof(Grenade), "FixedUpdate")] internal static class GrenadeFixedUpdatePatch { private static bool Prefix(Grenade __instance) { if ((Object)(object)((Component)__instance).GetComponent<GrenadeLauncherProjectile>() == (Object)null) { return (Object)(object)((Component)__instance).GetComponent<BlueHookDeliveryProjectile>() == (Object)null; } return false; } } [HarmonyPatch(typeof(CustomGravity), "FixedUpdate")] internal static class GrenadeCustomGravityPatch { private static bool Prefix(CustomGravity __instance) { if ((Object)(object)((Component)__instance).GetComponent<GrenadeLauncherProjectile>() == (Object)null) { return (Object)(object)((Component)__instance).GetComponent<BlueHookDeliveryProjectile>() == (Object)null; } return false; } } [HarmonyPatch(typeof(Grenade), "Start")] internal static class GrenadeStartPatch { private static void Postfix(Grenade __instance) { ((Component)__instance).GetComponent<GrenadeLauncherProjectile>()?.Launch(); ((Component)__instance).GetComponent<BlueHookDeliveryProjectile>()?.Launch(); } } [HarmonyPatch(typeof(Grenade), "OnCollisionEnter")] internal static class GrenadeOnCollisionEnterPatch { private static bool Prefix(Grenade __instance, Collision collision) { //IL_0039: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_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) if ((Object)(object)((Component)__instance).GetComponent<BlueHookDeliveryProjectile>() != (Object)null) { return false; } GrenadeLauncherProjectile component = ((Component)__instance).GetComponent<GrenadeLauncherProjectile>(); if ((Object)(object)component == (Object)null) { return true; } ContactPoint val = (ContactPoint)((collision.contactCount > 0) ? collision.GetContact(0) : default(ContactPoint)); Vector3 collisionNormal = ((collision.contactCount > 0) ? ((ContactPoint)(ref val)).normal : Vector3.zero); Vector3 collisionPoint = ((collision.contactCount > 0) ? ((ContactPoint)(ref val)).point : ((Component)__instance).transform.position); component.HandleCollision(collision.collider, -collision.relativeVelocity, collisionNormal, collisionPoint); return false; } } [HarmonyPatch(typeof(Grenade), "Collision", new Type[] { typeof(Collider), typeof(Vector3) })] internal static class GrenadeCollisionPatch { private static bool Prefix(Grenade __instance, Collider other, Vector3 velocity) { //IL_0024: 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_0030: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)__instance).GetComponent<BlueHookDeliveryProjectile>() != (Object)null) { return false; } GrenadeLauncherProjectile component = ((Component)__instance).GetComponent<GrenadeLauncherProjectile>(); if ((Object)(object)component == (Object)null) { return true; } component.HandleCollision(other, velocity, Vector3.zero, ((Component)__instance).transform.position); return false; } } [HarmonyPatch(typeof(Explosion), "Collide")] internal static class GrenadeLauncherExplosionPatch { private struct State { internal bool ChangedMultiplier; internal float EnemyDamageMultiplier; internal bool ChangedDamage; internal int Damage; internal GrenadeLauncherExplosionMarker Marker; internal EnemyIdentifier Enemy; } private static bool Prefix(Explosion __instance, Collider other, out State __state) { //IL_011d: 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_00f6: Invalid comparison between Unknown and I4 __state = default(State); GrenadeLauncherExplosionMarker componentInParent = ((Component)__instance).GetComponentInParent<GrenadeLauncherExplosionMarker>(); GrenadeLauncherProjectile grenadeLauncherProjectile = (((Object)(object)other != (Object)null) ? ((Component)other).GetComponentInParent<GrenadeLauncherProjectile>() : null); if ((Object)(object)grenadeLauncherProjectile != (Object)null && grenadeLauncherProjectile.IsStuck) { if ((Object)(object)componentInParent != (Object)null && componentInParent.Mode == GrenadeExplosionMode.Surface && !PluginSettings.TimedFuseDetonatesStuck) { return false; } if (!__instance.enemy && (Object)(object)__instance.sourceWeapon != (Object)null) { grenadeLauncherProjectile.DetonateStuck(); } return false; } if ((Object)(object)componentInParent == (Object)null) { return true; } EnemyIdentifier val = GrenadeLauncherProjectile.TryGetLivingEnemy(other); if ((Object)(object)val == (Object)null) { return true; } __state.Marker = componentInParent; __state.Enemy = val; if (PluginSettings.EnemyCarrierTakesDirectDamage && componentInParent.StuckHostEnemyId != 0 && ((Object)val).GetInstanceID() == componentInParent.StuckHostEnemyId) { __state.ChangedDamage = true; __state.Damage = __instance.damage; __instance.damage = Mathf.RoundToInt(Mathf.Max(0f, componentInParent.StuckCarrierDamage) * 10f); } if (componentInParent.Parried && (int)val.enemyType == 4) { componentInParent.DamageBlockedEnemy(val, other); return false; } __state.ChangedMultiplier = true; __state.EnemyDamageMultiplier = __instance.enemyDamageMultiplier; __instance.enemyDamageMultiplier *= PluginSettings.GetEnemyDamageMultiplier(val.enemyType); return true; } private static Exception Finalizer(Explosion __instance, State __state, Exception __exception) { if (__state.ChangedMultiplier) { __instance.enemyDamageMultiplier = __state.EnemyDamageMultiplier; } if (__state.ChangedDamage) { __instance.damage = __state.Damage; } if (__exception == null && (Object)(object)__state.Marker != (Object)null && (Object)(object)__state.Enemy != (Object)null) { __state.Marker.TryAwardLongRangeStyle(__state.Enemy); __state.Marker.TryAwardWalkingBomb(__state.Enemy); __state.Marker.QueueDirectHitTelemetry(__state.Enemy); } return __exception; } } internal enum GrenadeExplosionMode { Direct, Surface, Parried, GreenDirect, GreenSurface, Stuck } internal enum GrenadeLongRangeStyle { None, PipeDream, MoonShot } internal static class GrenadeStyleAwards { private const string PipeDreamId = "grenadelauncher.pipe_dream"; private const string MoonShotId = "grenadelauncher.moon_shot"; private const string OutSnipedId = "grenadelauncher.out_sniped"; private const string WalkingBombId = "grenadelauncher.walking_bomb"; private static StyleHUD registeredHud; private static readonly HashSet<int> walkingBombAwardedChains = new HashSet<int>(); internal static void Award(GrenadeLongRangeStyle style, EnemyIdentifier enemy, GameObject sourceWeapon) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 StyleHUD val = EnsureRegistered(enemy); if ((Object)(object)val == (Object)null) { return; } int num; object obj; if (style == GrenadeLongRangeStyle.MoonShot && (int)enemy.enemyType == 20) { num = (enemy.dead ? 1 : 0); if (num != 0) { obj = "grenadelauncher.out_sniped"; goto IL_0042; } } else { num = 0; } obj = ((style == GrenadeLongRangeStyle.MoonShot) ? "grenadelauncher.moon_shot" : "grenadelauncher.pipe_dream"); goto IL_0042; IL_0042: string text = (string)obj; int num2 = ((num != 0) ? PluginSettings.OutSnipedStylePoints : ((style == GrenadeLongRangeStyle.MoonShot) ? PluginSettings.MoonShotStylePoints : PluginSettings.PipeDreamStylePoints)); val.AddPoints(num2, text, sourceWeapon, enemy, -1, "", ""); } internal static void AwardWalkingBomb(int chainId, EnemyIdentifier enemy, GameObject sourceWeapon) { if (chainId > 0 && walkingBombAwardedChains.Add(chainId)) { StyleHUD val = EnsureRegistered(enemy); if ((Object)(object)val != (Object)null) { val.AddPoints(PluginSettings.WalkingBombStylePoints, "grenadelauncher.walking_bomb", sourceWeapon, enemy, -1, "", ""); } } } internal static void ResetWalkingBombChains() { walkingBombAwardedChains.Clear(); } private static StyleHUD EnsureRegistered(EnemyIdentifier enemy) { StyleHUD instance = MonoSingleton<StyleHUD>.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)enemy == (Object)null) { return null; } if ((Object)(object)registeredHud != (Object)(object)instance) { instance.RegisterStyleItem("grenadelauncher.pipe_dream", "<color=#00ffffff>PIPE DREAM</color>"); instance.RegisterStyleItem("grenadelauncher.moon_shot", "<color=#FFD700>MOON SHOT</color>"); instance.RegisterStyleItem("grenadelauncher.out_sniped", "<color=#FFD700>OUT-SNIPED</color>"); instance.RegisterStyleItem("grenadelauncher.walking_bomb", "<color=#00ffffff>WALKING BOMB</color>"); registeredHud = instance; } return instance; } } internal sealed class GrenadeLauncherExplosionMarker : MonoBehaviour { private readonly HashSet<int> manuallyDamagedEnemies = new HashSet<int>(); private readonly HashSet<int> styleAwardedEnemies = new HashSet<int>(); private bool walkingBombAwarded; private bool telemetryQueued; private EnemyIdentifier telemetryEnemy; internal bool Parried; internal GrenadeExplosionMode Mode; internal float Damage; internal GameObject SourceWeapon; internal int DirectEnemyId; internal GrenadeLongRangeStyle LongRangeStyle; internal int StuckHostEnemyId; internal float StuckCarrierDamage; internal int StuckChainGroupId; internal GrenadeProjectileProfile DirectProfile; internal float DirectPlanarDistance; internal float DirectStraightDistance; internal float TheoreticalSameHeightRange; internal float LaunchElevationDegrees; internal float ConfiguredStyleThreshold; internal void TryAwardLongRangeStyle(EnemyIdentifier enemy) { if (!((Object)(object)enemy == (Object)null) && LongRangeStyle != GrenadeLongRangeStyle.None && ((Object)enemy).GetInstanceID() == DirectEnemyId && styleAwardedEnemies.Add(DirectEnemyId)) { GrenadeStyleAwards.Award(LongRangeStyle, enemy, SourceWeapon); } } internal void TryAwardWalkingBomb(EnemyIdentifier enemy) { if (!walkingBombAwarded && !((Object)(object)enemy == (Object)null) && enemy.dead && StuckHostEnemyId != 0 && ((Object)enemy).GetInstanceID() != StuckHostEnemyId) { walkingBombAwarded = true; GrenadeStyleAwards.AwardWalkingBomb(StuckChainGroupId, enemy, SourceWeapon); } } internal void QueueDirectHitTelemetry(EnemyIdentifier enemy) { if (PluginSettings.RangeTelemetryEnabled && !telemetryQueued && !((Object)(object)enemy == (Object)null) && DirectEnemyId != 0 && ((Object)enemy).GetInstanceID() == DirectEnemyId) { telemetryQueued = true; telemetryEnemy = enemy; ((MonoBehaviour)this).StartCoroutine(LogDirectHitTelemetryAtEndOfFrame()); } } private IEnumerator LogDirectHitTelemetryAtEndOfFrame() { yield return (object)new WaitForEndOfFrame(); string arg = (((Object)(object)telemetryEnemy != (Object)null) ? ((object)Unsafe.As<EnemyType, EnemyType>(ref telemetryEnemy.enemyType)/*cast due to .constrained prefix*/).ToString() : "Destroyed"); bool flag = (Object)(object)telemetryEnemy == (Object)null || telemetryEnemy.dead; float num = ((TheoreticalSameHeightRange > 0.001f) ? (DirectPlanarDistance / TheoreticalSameHeightRange) : 0f); string text = ((DirectProfile == GrenadeProjectileProfile.GreenContact) ? "GREEN" : "PRIMARY"); ManualLogSource logSource = Plugin.LogSource; if (logSource != null) { logSource.LogInfo((object)("[RangeTelemetry] " + text + " direct hit | " + $"planar={DirectPlanarDistance:0.###}u | straight={DirectStraightDistance:0.###}u | " + $"launchElevation={LaunchElevationDegrees:0.###}deg | " + $"calculatedSameHeightMax={TheoreticalSameHeightRange:0.###}u | ratio={num:0.###} | " + $"styleThreshold={ConfiguredStyleThreshold:0.###}u | " + $"enemy={arg} | killed={flag}")); } } internal void DamageBlockedEnemy(EnemyIdentifier enemy, Collider hitCollider) { //IL_0037: 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_005f: 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_006d: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)enemy == (Object)null) && !enemy.dead && manuallyDamagedEnemies.Add(((Object)enemy).GetInstanceID())) { enemy.hitter = "grenadelauncherparry"; float num = Damage * PluginSettings.GetEnemyDamageMultiplier(enemy.enemyType); Vector3 val; if (!((Object)(object)hitCollider != (Object)null)) { val = ((Component)this).transform.position; } else { Bounds bounds = hitCollider.bounds; val = ((Bounds)(ref bounds)).ClosestPoint(((Component)this).transform.position); } Vector3 val2 = val; GameObject val3 = (((Object)(object)hitCollider != (Object)null) ? ((Component)hitCollider).gameObject : ((Component)enemy).gameObject); enemy.DeliverDamage(val3, Vector3.zero, val2, num, false, 0f, SourceWeapon, false, true); } } } [DefaultExecutionOrder(10000)] internal sealed class GrenadeLauncherProjectile : MonoBehaviour { private const float Tf2DemomanEyeHeightHu = 68f; private const float Tf2ForwardSpeedHu = 1200f; private const float Tf2UpwardSpeedHu = 200f; private const float Tf2GravityHu = 800f; private static int nextChainGroupId; internal Grenade Grenade; internal GrenadeProjectileProfile Profile; private Rigidbody body; private readonly List<CustomGravity> customGravityComponents = new List<CustomGravity>(1); private Collider[] ownColliders = Array.Empty<Collider>(); private ParryReceiver parryReceiver; private bool launched; private bool finished; private bool bounced; private bool parried; private bool stuck; private int stuckHostEnemyId; private int chainGroupId; private bool wasHooked; private GelStainMarker stuckGelStain; private GelCoverage stuckGelCoverage; private float launchForwardSpeed; private float launchElevationDegrees; private float sameHeightMaximumRange; private Vector3 launchPosition; private Vector3 capturedGravity; private Collider lastBounceSurface; private Vector3 lastBounceNormal; private Vector3 lastBouncePoint; private bool hasLastBouncePoint; private float bornAt; private float fuseRemaining = -1f; private float chainDetonationAt = -1f; private Vector3 simulatedVelocity; private Vector3 lastVelocity; private Quaternion lastFixedRotation; private static bool loggedTrajectory; private static bool loggedExplosion; private static bool loggedPortalRotation; private static bool loggedRejectedExternalChange; internal bool CanBeWhiplashed { get { if (Profile == GrenadeProjectileProfile.Primary && bounced && !stuck) { return !finished; } return false; } } internal bool IsStuck { get { if (stuck) { return !finished; } return false; } } internal int ChainGroupId => chainGroupId; internal void Launch() { //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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) //IL_017d: 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_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0201: 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_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: 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_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Expected O, but got Unknown //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Expected O, but got Unknown if (launched || (Object)(object)Grenade == (Object)null) { return; } launched = true; bornAt = Time.time; body = (((Object)(object)Grenade.rb != (Object)null) ? Grenade.rb : ((Component)this).GetComponent<Rigidbody>()); if ((Object)(object)body == (Object)null) { Plugin.LogSource.LogWarning((object)"Grenade projectile had no Rigidbody; removing it."); Object.Destroy((Object)(object)((Component)this).gameObject); return; } ownColliders = ((Component)this).GetComponentsInChildren<Collider>(true); float eyeHeight = TrajectoryCalibration.GetEyeHeight(); float num = eyeHeight / 68f; float num2 = ((Profile == GrenadeProjectileProfile.GreenContact) ? (PluginSettings.SpeedMultiplier * PluginSettings.GreenSpeedMultiplier) : PluginSettings.SpeedMultiplier); float num3 = ((Profile == GrenadeProjectileProfile.GreenContact) ? (PluginSettings.UpwardVelocityMultiplier * PluginSettings.GreenUpwardVelocityMultiplier) : PluginSettings.UpwardVelocityMultiplier); float num4 = ((Profile == GrenadeProjectileProfile.GreenContact) ? (PluginSettings.GreenGravityMultiplier * PluginSettings.GravityMultiplier) : PluginSettings.GravityMultiplier); launchForwardSpeed = 1200f * num * Mathf.Max(0.05f, num2); float num5 = 200f * num * Mathf.Max(0f, num3); float num6 = 800f * num * Mathf.Max(0.05f, num4); launchPosition = ((Component)this).transform.position; Vector3 val = Physics.gravity; NewMovement instance = MonoSingleton<NewMovement>.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.rb != (Object)null) { val = PhysicsExtensions.GetGravityVector(instance.rb); } Vector3 val2 = Physics.gravity; float num7 = Mathf.Max(0.01f, ((Vector3)(ref val2)).magnitude); float num8 = ((Vector3)(ref val)).magnitude / num7; Vector3 val3 = ((((Vector3)(ref val)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val)).normalized : Vector3.down); capturedGravity = val3 * num6 * num8; LockNativeGravity(); body.velocity = ((Component)this).transform.forward * launchForwardSpeed + ((Component)this).transform.up * num5; float magnitude = ((Vector3)(ref capturedGravity)).magnitude; float num9 = Vector3.Dot(body.velocity, -val3); val2 = Vector3.ProjectOnPlane(body.velocity, val3); float magnitude2 = ((Vector3)(ref val2)).magnitude; launchElevationDegrees = Mathf.Atan2(num9, Mathf.Max(0.0001f, magnitude2)) * 57.29578f; sameHeightMaximumRange = ((magnitude > 0.001f && num9 > 0f) ? (magnitude2 * (2f * num9 / magnitude)) : 0f); simulatedVelocity = body.velocity; lastVelocity = simulatedVelocity; lastFixedRotation = ((Component)this).transform.rotation; if (Profile == GrenadeProjectileProfile.Primary) { parryReceiver = ((Component)this).GetComponent<ParryReceiver>(); if ((Object)(object)parryReceiver == (Object)null) { parryReceiver = ((Component)this).gameObject.AddComponent<ParryReceiver>(); } if (parryReceiver.onParry == null) { parryReceiver.onParry = new UnityEvent(); } parryReceiver.parryHeal = false; parryReceiver.disappearOnParry = false; parryReceiver.onParry.AddListener(new UnityAction(Parry)); ((Behaviour)parryReceiver).enabled = false; } else { parryReceiver = ((Component)this).GetComponent<ParryReceiver>(); if ((Object)(object)parryReceiver != (Object)null) { ((Behaviour)parryReceiver).enabled = false; } } if (!loggedTrajectory) { loggedTrajectory = true; Plugin.LogSource.LogInfo((object)($"TF2 trajectory converted from V1 eye height {eyeHeight:0.###}: " + $"forward {launchForwardSpeed:0.###} u/s, up {num5:0.###} u/s, " + $"captured gravity {capturedGravity} u/s².")); } } private void OnDestroy() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown if ((Object)(object)parryReceiver != (Object)null && parryReceiver.onParry != null) { parryReceiver.onParry.RemoveListener(new UnityAction(Parry)); } GelSystem.UnregisterStuck(this); } private void FixedUpdate() { //IL_0122: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: 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) //IL_01cd: 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_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: 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_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: 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_0296: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0338: 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_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) if (!launched || finished || (Object)(object)body == (Object)null) { return; } if (stuck) { if (chainDetonationAt >= 0f && Time.time >= chainDetonationAt) { DetonateStuck(); } return; } float num = ((Profile == GrenadeProjectileProfile.GreenContact) ? PluginSettings.GreenLifetime : PluginSettings.Lifetime); if (Time.time - bornAt >= Mathf.Max(1f, num)) { FinishSilently(); return; } if ((Object)(object)Grenade != (Object)null && Grenade.hooked) { Grenade.CanCollideWithPlayer(false); if (!wasHooked && bounced && !parried && fuseRemaining >= 0f) { fuseRemaining += Mathf.Max(0f, PluginSettings.HookFuseGrace); } wasHooked = true; lastFixedRotation = ((Component)this).transform.rotation; return; } if (wasHooked) { wasHooked = false; if (!body.isKinematic) { simulatedVelocity = body.velocity; lastVelocity = simulatedVelocity; } } if ((Object)(object)Grenade != (Object)null && Grenade.frozen) { return; } if (bounced && !parried && fuseRemaining >= 0f) { fuseRemaining -= Time.fixedDeltaTime; if (fuseRemaining <= 0f) { Explode(GrenadeExplosionMode.Surface); return; } } if (body.isKinematic) { lastFixedRotation = ((Component)this).transform.rotation; return; } Vector3 velocity = body.velocity; Vector3 val = lastVelocity; Vector3 val2 = velocity - val; bool flag = ((Vector3)(ref val2)).sqrMagnitude > 4f && Time.time - bornAt > Time.fixedDeltaTime * 2f; bool flag2 = flag && IsMagnitudePreservingRotation(val, velocity); if (flag2) { Quaternion val3 = ((Component)this).transform.rotation * Quaternion.Inverse(lastFixedRotation); simulatedVelocity = velocity; lastVelocity = velocity; capturedGravity = val3 * capturedGravity; } if (flag2 && !loggedPortalRotation) { loggedPortalRotation = true; Plugin.LogSource.LogInfo((object)("Detected a seamless portal transform; rotating the captured launch trajectory and gravity. " + $"expected {val}, actual {velocity}, " + $"rigidbody gravity={body.useGravity}, world gravity={Physics.gravity}.")); } else if (flag && !flag2 && !loggedRejectedExternalChange) { loggedRejectedExternalChange = true; Plugin.LogSource.LogWarning((object)("Rejected an external grenade velocity change to preserve the custom trajectory: " + $"expected {val}, actual {velocity}, " + $"rigidbody gravity={body.useGravity}, world gravity={Physics.gravity}.")); } LockNativeGravity(); if (!parried) { simulatedVelocity += capturedGravity * Time.fixedDeltaTime; } body.velocity = simulatedVelocity; lastVelocity = simulatedVelocity; if (((Vector3)(ref simulatedVelocity)).sqrMagnitude > 0.01f) { Vector3 val4 = ((((Vector3)(ref capturedGravity)).sqrMagnitude > 0.001f) ? (-((Vector3)(ref capturedGravity)).normalized) : Vector3.up); ((Component)this).transform.rotation = Quaternion.LookRotation(((Vector3)(ref simulatedVelocity)).normalized, val4); } lastFixedRotation = ((Component)this).transform.rotation; } private static bool IsMagnitudePreservingRotation(Vector3 before, Vector3 after) { //IL_003f: 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) float magnitude = ((Vector3)(ref before)).magnitude; float magnitude2 = ((Vector3)(ref after)).magnitude; if (magnitude < 0.5f || magnitude2 < 0.5f) { return false; } float num = Mathf.Max(0.35f, magnitude * 0.015f); if (Mathf.Abs(magnitude - magnitude2) <= num) { return Vector3.Angle(before, after) >= 2f; } return false; } private void LockNativeGravity() { if ((Object)(object)body == (Object)null) { return; } body.useGravity = false; PhysicsExtensions.SetGravityMode(body, false); ((Component)body).GetComponents<CustomGravity>(customGravityComponents); foreach (CustomGravity customGravityComponent in customGravityComponents) { if ((Object)(object)customGravityComponent != (Object)null) { customGravityComponent.useGravity = false; } } } internal void HandleCollision(Collider other, Vector3 incomingVelocity, Vector3 collisionNormal, Vector3 collisionPoint) { //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0176: 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_01d5: 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_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Invalid comparison between Unknown and I4 if (finished || (Object)(object)other == (Object)null || stuck || ((Component)other).CompareTag("Player") || ((Component)other).gameObject.layer == 14 || ((Component)other).gameObject.layer == 20) { return; } if ((Object)(object)((Component)other).GetComponentInParent<Grenade>() != (Object)null) { Collider[] array = ownColliders; foreach (Collider val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)other) { Physics.IgnoreCollision(val, other, true); } } if ((Object)(object)body != (Object)null && !body.isKinematic) { body.velocity = simulatedVelocity; } return; } if (Profile == GrenadeProjectileProfile.Primary) { Glass componentInParent = ((Component)other).GetComponentInParent<Glass>(); if ((Object)(object)componentInParent != (Object)null) { componentInParent.Shatter(); Collider[] array = ownColliders; foreach (Collider val2 in array) { if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)other) { Physics.IgnoreCollision(val2, other, true); } } if ((Object)(object)body != (Object)null && !body.isKinematic) { body.velocity = simulatedVelocity; } return; } } EnemyIdentifier val3 = TryGetLivingEnemy(other); if (!other.isTrigger || !((Object)(object)val3 == (Object)null)) { if (GelSystem.TryGetStickTarget(other, val3, collisionPoint, out var stain, out var coverage)) { StickToGel(other, collisionNormal, collisionPoint, val3, stain, coverage); } else if (Profile == GrenadeProjectileProfile.GreenContact) { Explode(((Object)(object)val3 != (Object)null) ? GrenadeExplosionMode.GreenDirect : GrenadeExplosionMode.GreenSurface, val3); } else if (parried) { Explode(GrenadeExplosionMode.Parried); } else if (!bounced && (Object)(object)val3 != (Object)null && (int)val3.enemyType != 4) { Explode(GrenadeExplosionMode.Direct, val3); } else { Bounce(other, incomingVelocity, collisionNormal, collisionPoint); } } } internal static EnemyIdentifier TryGetLivingEnemy(Collider other) { if ((Object)(object)other == (Object)null) { return null; } EnemyIdentifierIdentifier val = null; if ((Object)(object)other.attachedRigidbody != (Object)null) { val = ((Component)other.attachedRigidbody).GetComponent<EnemyIdentifierIdentifier>(); } if ((Object)(object)val == (Object)null) { val = ((Component)other).GetComponentInParent<EnemyIdentifierIdentifier>(); } if ((Object)(object)val != (Object)null && (Object)(object)val.eid != (Object)null && !val.eid.dead) { return val.eid; } EnemyIdentifier componentInParent = ((Component)other).GetComponentInParent<EnemyIdentifier>(); if (!((Object)(object)componentInParent != (Object)null) || componentInParent.dead) { return null; } return componentInParent; } private void Bounce(Collider surface, Vector3 incomingVelocity, Vector3 collisionNormal, Vector3 collisionPoint) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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) //IL_014d: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0177: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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) if ((Object)(object)body == (Object)null) { return; } if (!bounced) { bounced = true; fuseRemaining = Mathf.Max(0.1f, PluginSettings.SurfaceFuse); if ((Object)(object)parryReceiver != (Object)null) { ((Behaviour)parryReceiver).enabled = true; } } Vector3 val = ((((Vector3)(ref lastVelocity)).sqrMagnitude > 0.01f) ? lastVelocity : incomingVelocity); Vector3 val2 = collisionNormal; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { Bounds bounds = surface.bounds; Vector3 val3 = ((Bounds)(ref bounds)).ClosestPoint(((Component)this).transform.position); val2 = ((Component)this).transform.position - val3; } if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? (-((Vector3)(ref val)).normalized) : (-((Vector3)(ref capturedGravity)).normalized)); } ((Vector3)(ref val2)).Normalize(); if (((Vector3)(ref val)).sqrMagnitude > 0.01f && Vector3.Dot(val2, val) > 0f) { val2 = -val2; } lastBounceSurface = surface; lastBounceNormal = val2; lastBouncePoint = collisionPoint; hasLastBouncePoint = true; float num = Mathf.Clamp01(PluginSettings.BounceRetention); body.constraints = (RigidbodyConstraints)0; simulatedVelocity = Vector3.Reflect(val, val2) * num; if (!body.isKinematic) { body.velocity = simulatedVelocity; Rigidbody obj = body; obj.angularVelocity *= num; } lastVelocity = simulatedVelocity; } private void Parry() { //IL_0079: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) if (!finished && bounced && !((Object)(object)body == (Object)null)) { parried = true; fuseRemaining = -1f; if ((Object)(object)parryReceiver != (Object)null) { ((Behaviour)parryReceiver).enabled = false; } Grenade.CanCollideWithPlayer(false); CameraController instance = MonoSingleton<CameraController>.Instance; Vector3 val = (((Object)(object)instance != (Object)null) ? ((Component)instance).transform.forward : ((Component)this).transform.forward); body.constraints = (RigidbodyConstraints)0; simulatedVelocity = ((Vector3)(ref val)).normalized * launchForwardSpeed * Mathf.Max(0.1f, PluginSettings.ParrySpeedMultiplier); if (body.isKinematic) { body.isKinematic = false; } body.velocity = simulatedVelocity; body.angularVelocity = Vector3.zero; lastVelocity = simulatedVelocity; ((Component)this).transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, ((Component)this).transform.up); if (IsParriedIntoLastSurface(((Vector3)(ref val)).normalized)) { Explode(GrenadeExplosionMode.Parried); } } } private bool IsParriedIntoLastSurface(Vector3 direction) { //IL_0023: 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_0029: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_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_0075: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: 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_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)lastBounceSurface == (Object)null) { return false; } float fullProjectileClearance = GetFullProjectileClearance(); RaycastHit val = default(RaycastHit); bool num = lastBounceSurface.Raycast(new Ray(((Component)this).transform.position, direction), ref val, fullProjectileClearance); Vector3 val2 = ((Component)this).transform.position - direction * fullProjectileClearance; RaycastHit val3 = default(RaycastHit); bool num2 = lastBounceSurface.Raycast(new Ray(val2, direction), ref val3, fullProjectileClearance * 2f); float num3 = (num2 ? Vector3.Dot(((RaycastHit)(ref val3)).point - ((Component)this).transform.position, direction) : float.PositiveInfinity); bool flag = num2 && num3 >= -0.05f; RaycastHit val4 = default(RaycastHit); bool flag2 = Physics.Raycast(((Component)this).transform.position, direction, ref val4, fullProjectileClearance, -1, (QueryTriggerInteraction)1) && (Object)(object)((RaycastHit)(ref val4)).collider != (Object)null && !((Component)((RaycastHit)(ref val4)).collider).transform.IsChildOf(((Component)this).transform) && !((Component)((RaycastHit)(ref val4)).collider).CompareTag("Player"); Bounds bounds = lastBounceSurface.bounds; Vector3 val5 = ((Bounds)(ref bounds)).ClosestPoint(((Component)this).transform.position); float num4 = Vector3.Distance(((Component)this).transform.position, val5); float num5 = (hasLastBouncePoint ? Vector3.Distance(((Component)this).transform.position, lastBouncePoint) : float.PositiveInfinity); float num6 = ((((Vector3)(ref lastBounceNormal)).sqrMagnitude >= 0.01f) ? Vector3.Dot(direction, lastBounceNormal) : float.NaN); bool num7 = ((Vector3)(ref lastBounceNormal)).sqrMagnitude >= 0.01f && num6 < -0.05f; Vector3 val6 = (hasLastBouncePoint ? (lastBouncePoint - ((Component)this).transform.position) : Vector3.zero); float num8 = (hasLastBouncePoint ? Mathf.Abs(Vector3.Dot(val6, lastBounceNormal)) : float.PositiveInfinity); float num9; if (!hasLastBouncePoint) { num9 = float.PositiveInfinity; } else { Vector3 val7 = Vector3.ProjectOnPlane(val6, lastBounceNormal); num9 = ((Vector3)(ref val7)).magnitude; } float num10 = num9; bool flag3 = hasLastBouncePoint && num8 <= fullProjectileClearance + 0.25f && num10 <= fullProjectileClearance; bool flag4 = num7 && (num4 <= fullProjectileClearance || num5 <= fullProjectileClearance || flag3); return num || flag || flag2 || flag4; } private float GetFullProjectileClearance() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) float num = 0.75f; Collider[] array = ownColliders; foreach (Collider val in array) { if (!((Object)(object)val == (Object)null) && val.enabled && !val.isTrigger) { Bounds bounds = val.bounds; float num2 = Vector3.Distance(((Component)this).transform.position, ((Bounds)(ref bounds)).center); Vector3 extents = ((Bounds)(ref bounds)).extents; float num3 = num2 + ((Vector3)(ref extents)).magnitude; num = Mathf.Max(num, num3 + 0.2f); } } return num; } private void StickToGel(Collider surface, Vector3 collisionNormal, Vector3 collisionPoint, EnemyIdentifier hostEnemy, GelStainMarker gelStain, GelCoverage gelCoverage) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00dd: Unknown result type (might be due to