using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BubbleGun.Combat; using BubbleGun.Weapon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [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("BubbleGun")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Bubble Gun weapon mod for R.E.P.O. - fires rainbow bubbles that pop, arm on hard surfaces, and chain-detonate.")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2")] [assembly: AssemblyProduct("BubbleGun")] [assembly: AssemblyTitle("BubbleGun")] [assembly: AssemblyVersion("0.1.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 BubbleGun { [BepInPlugin("com.amgru.bubblegun", "BubbleGun", "0.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.amgru.bubblegun"; public const string PluginName = "BubbleGun"; public const string PluginVersion = "0.1.2"; internal static ConfigEntry ModEnabled = null; internal static ConfigEntry ExplosionDamage = null; internal static ConfigEntry ExplosionRadius = null; internal static ConfigEntry ExplosionKnockback = null; internal static ConfigEntry ChainReactionRadius = null; internal static ConfigEntry ArmedLifetime = null; internal static ConfigEntry TankCapacity = null; internal static ConfigEntry TankDrainRate = null; internal static ConfigEntry TankRechargeRate = null; internal static ConfigEntry BubbleSpeed = null; private Harmony? harmony; internal static string PluginDirectory { get; private set; } = string.Empty; private void Awake() { //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty; ModEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Enables or disables the Bubble Gun."); ExplosionDamage = ((BaseUnityPlugin)this).Config.Bind("Explosion", "Damage", 24, "Damage dealt to enemies by a bubble pop. Tuned as a moderate 4/10 blast."); ExplosionRadius = ((BaseUnityPlugin)this).Config.Bind("Explosion", "Radius", 2.2f, "Radius of the minor bubble explosion."); ExplosionKnockback = ((BaseUnityPlugin)this).Config.Bind("Explosion", "Knockback", 24f, "Impulse applied to enemies hit by bubble explosions."); ChainReactionRadius = ((BaseUnityPlugin)this).Config.Bind("Explosion", "ChainReactionRadius", 3.6f, "Distance at which a popping bubble detonates other nearby bubbles."); ArmedLifetime = ((BaseUnityPlugin)this).Config.Bind("Explosion", "ArmedLifetime", 60f, "Seconds a bubble remains as a static bomb after touching inorganic geometry."); TankCapacity = ((BaseUnityPlugin)this).Config.Bind("Gun", "TankCapacity", 100f, "Maximum Bubble tank capacity."); TankDrainRate = ((BaseUnityPlugin)this).Config.Bind("Gun", "DrainRate", 4f, "Bubble units drained per second while firing."); TankRechargeRate = ((BaseUnityPlugin)this).Config.Bind("Gun", "RechargeRate", 0f, "Bubble units recharged per second when not firing. Bubble Gun does not auto-recharge."); BubbleSpeed = ((BaseUnityPlugin)this).Config.Bind("Gun", "BubbleSpeed", 5.5f, "Initial speed of bubble projectiles in m/s."); BubbleGunRuntime.Enabled = ModEnabled.Value; BubbleGunRuntime.PluginDirectory = PluginDirectory; harmony = new Harmony("com.amgru.bubblegun"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} loaded. Enabled={2}", "BubbleGun", "0.1.2", ModEnabled.Value)); } private void OnDestroy() { Harmony? obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } } namespace BubbleGun.Patches { [HarmonyPatch(typeof(ItemGun), "Shoot")] internal static class ItemGunShootPatch { private static bool Prefix(ItemGun __instance) { if ((((Component)__instance).GetComponent() ?? ((Component)__instance).GetComponentInChildren(true) ?? ((Component)__instance).GetComponentInParent())?.item?.itemName != "Bubble Gun") { return true; } BubbleGunController.OnItemGunShoot(__instance); return false; } } [HarmonyPatch(typeof(ItemGun), "Update")] internal static class ItemGunUpdatePatch { private static void Postfix(ItemGun __instance) { if ((((Component)__instance).GetComponent() ?? ((Component)__instance).GetComponentInChildren(true) ?? ((Component)__instance).GetComponentInParent())?.item?.itemName != "Bubble Gun") { return; } Renderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { string name = ((object)val).GetType().Name; if ((name == "LineRenderer" || name == "TrailRenderer") && val.enabled) { val.enabled = false; } } Component[] componentsInChildren2 = ((Component)__instance).GetComponentsInChildren(true); bool flag = default(bool); foreach (Component val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !(((object)val2).GetType().Name != "ParticleSystem")) { object obj = ((object)val2).GetType().GetProperty("isPlaying")?.GetValue(val2); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { ((object)val2).GetType().GetMethod("Stop", Type.EmptyTypes)?.Invoke(val2, null); } } } } } [HarmonyPatch(typeof(PhysGrabObject), "Update")] internal static class PhysGrabObjectUpdatePatch { private static void Postfix(PhysGrabObject __instance) { BubbleGunController.OnPhysGrabObjectUpdate(__instance); } } [HarmonyPatch(typeof(PlayerController), "Start")] internal static class PlayerControllerStartPatch { private static void Postfix(PlayerController __instance) { } } } namespace BubbleGun.Combat { internal static class BubbleCombat { private static readonly FieldInfo EnemyHasHealthField = AccessTools.Field(typeof(Enemy), "HasHealth"); private static readonly FieldInfo EnemyHealthField = AccessTools.Field(typeof(Enemy), "Health"); private static readonly FieldInfo EnemyHasRigidbodyField = AccessTools.Field(typeof(Enemy), "HasRigidbody"); private static readonly FieldInfo EnemyRigidbodyField = AccessTools.Field(typeof(Enemy), "Rigidbody"); private static readonly FieldInfo EnemyRbField = AccessTools.Field(typeof(EnemyRigidbody), "rb"); internal static Enemy? FindEnemy(Collider collider) { Enemy componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && Object.op_Implicit((Object)(object)componentInParent)) { return componentInParent; } EnemyRigidbody componentInParent2 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null && (Object)(object)componentInParent2.enemy != (Object)null && Object.op_Implicit((Object)(object)componentInParent2.enemy)) { return componentInParent2.enemy; } if (!((Object)(object)collider.attachedRigidbody != (Object)null)) { return null; } return ((Component)collider.attachedRigidbody).GetComponent()?.enemy; } internal static PlayerController? FindPlayer(Collider collider) { PlayerController componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && Object.op_Implicit((Object)(object)componentInParent)) { return componentInParent; } PlayerAvatar componentInParent2 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null && Object.op_Implicit((Object)(object)componentInParent2)) { PlayerController val = ((Component)componentInParent2).GetComponent() ?? ((Component)componentInParent2).GetComponentInParent(); if ((Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val)) { return val; } } return null; } internal static PlayerAvatar? FindPlayerAvatar(Collider collider) { PlayerController val = FindPlayer(collider); if ((Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val) && (Object)(object)val.playerAvatarScript != (Object)null && Object.op_Implicit((Object)(object)val.playerAvatarScript)) { return val.playerAvatarScript; } PlayerAvatar componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && Object.op_Implicit((Object)(object)componentInParent)) { return componentInParent; } if ((Object)(object)collider.attachedRigidbody != (Object)null) { componentInParent = ((Component)collider.attachedRigidbody).GetComponent() ?? ((Component)collider.attachedRigidbody).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && Object.op_Implicit((Object)(object)componentInParent)) { return componentInParent; } } return null; } internal static void DamageEnemy(Enemy enemy, int damage, Vector3 hitPosition) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } Vector3 val = ((Component)enemy).transform.position - hitPosition; Vector3 val2 = ((Vector3)(ref val)).normalized; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = Vector3.forward; } object value = EnemyHasHealthField.GetValue(enemy); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { object? value2 = EnemyHealthField.GetValue(enemy); EnemyHealth val3 = (EnemyHealth)((value2 is EnemyHealth) ? value2 : null); if (val3 != null) { val3.Hurt(Mathf.Max(0, damage), val2); Debug.Log((object)$"[BubbleGun] Bubble tick: {damage} damage to {((Object)enemy).name}."); return; } } Debug.Log((object)$"[BubbleGun] Would deal {damage} to {((Object)enemy).name} but no EnemyHealth hook available."); } internal static void HealPlayer(PlayerAvatar playerAvatar, int amount) { if (SemiFunc.IsMasterClientOrSingleplayer()) { PlayerHealth val = playerAvatar.playerHealth ?? ((Component)playerAvatar).GetComponent() ?? ((Component)playerAvatar).GetComponentInChildren(true) ?? ((Component)playerAvatar).GetComponentInParent(); if ((Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val)) { val.HealOther(Mathf.Max(0, amount), true); playerAvatar.HealedOther(); Debug.Log((object)$"[BubbleGun] Bubble tick: healed {amount} HP on {((Object)playerAvatar).name}."); } else { Debug.Log((object)$"[BubbleGun] Would heal {amount} HP on {((Object)playerAvatar).name} but no PlayerHealth component was found."); } } } internal static Rigidbody? GetEnemyRigidbody(Enemy enemy) { object value = EnemyHasRigidbodyField.GetValue(enemy); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { object? value2 = EnemyRigidbodyField.GetValue(enemy); EnemyRigidbody val = (EnemyRigidbody)((value2 is EnemyRigidbody) ? value2 : null); if (val != null) { object? value3 = EnemyRbField.GetValue(val); Rigidbody val2 = (Rigidbody)((value3 is Rigidbody) ? value3 : null); if (val2 != null) { return val2; } } } return null; } } } namespace BubbleGun.Weapon { public sealed class BubbleBomb : MonoBehaviour { private enum BubbleState { Floating, Armed, Detonated } private static readonly List ActiveBubbles = new List(); private static readonly HashSet SeenEnemies = new HashSet(); private BubbleState state; private Rigidbody? rb; private Renderer? bubbleRenderer; private Material? bubbleMaterial; private float spawnTime; private float expiresAt; private float armedLifetime; private float explosionRadius; private float chainReactionRadius; private int explosionDamage; private float explosionKnockback; private BubbleGunNetworkProxy? networkProxy; private int bubbleId; private Transform? ignoredRoot; private Vector3 armedSurfaceNormal = Vector3.up; private float hueOffset; private Vector3 baseScale = Vector3.one; private float nextArmedEnemyCheckAt; private const float ContactGraceSeconds = 0.16f; private const float ContactRadius = 0.14f; private const float ArmedEnemyTriggerRadius = 0.75f; private const float BubbleWeight = 0.11f; private const float VerticalBob = 0.06f; private const float SideDrift = 0.055f; internal void Initialize(float flightLifetime, float armedLifetime, float explosionRadius, float chainReactionRadius, int explosionDamage, float explosionKnockback, BubbleGunNetworkProxy? networkProxy, int bubbleId, Transform? ignoredRoot) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) spawnTime = Time.time; expiresAt = Time.time + Mathf.Max(0.25f, flightLifetime); this.armedLifetime = Mathf.Max(1f, armedLifetime); this.explosionRadius = Mathf.Clamp(explosionRadius, 0.5f, 8f); this.chainReactionRadius = Mathf.Clamp(chainReactionRadius, 0.5f, 10f); this.explosionDamage = Mathf.Clamp(explosionDamage, 0, 24); this.explosionKnockback = Mathf.Clamp(explosionKnockback, 0f, 80f); this.networkProxy = networkProxy; this.bubbleId = bubbleId; this.ignoredRoot = ignoredRoot; hueOffset = Random.value; baseScale = ((Component)this).transform.localScale; rb = ((Component)this).GetComponent(); bubbleRenderer = ((Component)this).GetComponent(); bubbleMaterial = (((Object)(object)bubbleRenderer != (Object)null) ? bubbleRenderer.material : null); ActiveBubbles.Add(this); } private void OnDestroy() { ActiveBubbles.Remove(this); } private void Update() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) AnimateRainbowShell(); if (state == BubbleState.Floating && (Object)(object)rb != (Object)null) { float num = Mathf.Sin((Time.time + hueOffset) * 2.1f) * 0.055f; float num2 = Mathf.Sin((Time.time + hueOffset) * 3.4f) * 0.06f; rb.AddForce(Vector3.down * 0.11f + Vector3.up * num2 + ((Component)this).transform.right * num, (ForceMode)5); } else if (state == BubbleState.Armed && Time.time >= nextArmedEnemyCheckAt) { nextArmedEnemyCheckAt = Time.time + 0.08f; CheckArmedEnemyContact(); } if (Time.time >= expiresAt) { if (state == BubbleState.Armed) { Detonate(chainTriggered: false); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } else if (Time.time - spawnTime >= 0.16f && state == BubbleState.Floating) { CheckContacts(); } } private void OnTriggerEnter(Collider other) { if (Time.time - spawnTime < 0.16f) { return; } if (state == BubbleState.Armed) { if ((Object)(object)other != (Object)null && (Object)(object)BubbleCombat.FindEnemy(other) != (Object)null) { Detonate(chainTriggered: false); } } else if (state == BubbleState.Floating) { HandleContact(other); } } internal void ChainDetonate(Vector3 sourcePosition) { //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) if (state != BubbleState.Detonated) { float num = Mathf.Clamp(Vector3.Distance(((Component)this).transform.position, sourcePosition) * 0.09f, 0.05f, 0.5f); ((MonoBehaviour)this).Invoke("DetonateFromChain", num); } } private void DetonateFromChain() { Detonate(chainTriggered: true); } private void CheckContacts() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, 0.14f, -1, (QueryTriggerInteraction)2); foreach (Collider val in array) { if ((Object)(object)val != (Object)null && HandleContact(val)) { break; } } } private void CheckArmedEnemyContact() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, 0.75f, -1, (QueryTriggerInteraction)2); foreach (Collider val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)BubbleCombat.FindPlayerAvatar(val) != (Object)null) && (Object)(object)BubbleCombat.FindEnemy(val) != (Object)null) { Detonate(chainTriggered: false); break; } } } private bool HandleContact(Collider other) { if ((Object)(object)other == (Object)null || (Object)(object)((Component)other).transform == (Object)(object)((Component)this).transform || (Object)(object)((Component)other).GetComponentInParent() == (Object)(object)this) { return false; } if (IsIgnoredCollider(other) || (Object)(object)BubbleCombat.FindPlayerAvatar(other) != (Object)null) { return false; } if ((Object)(object)BubbleCombat.FindEnemy(other) != (Object)null) { Detonate(chainTriggered: false); return true; } if (other.isTrigger) { return false; } return ArmOnSurface(other); } private bool ArmOnSurface(Collider surface) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_002d: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00eb: Unknown result type (might be due to invalid IL or missing references) if (state != 0) { return false; } Vector3 val = surface.ClosestPoint(((Component)this).transform.position); Vector3 val2 = ((Component)this).transform.position - val; float magnitude = ((Vector3)(ref val2)).magnitude; float num = Mathf.Max(0.04f, ((Component)this).transform.lossyScale.x * 0.65f); if (magnitude < 0.02f || magnitude > num) { return false; } state = BubbleState.Armed; expiresAt = Time.time + armedLifetime; armedSurfaceNormal = val2 / magnitude; ((Component)this).transform.position = val + armedSurfaceNormal * Mathf.Max(0.025f, ((Component)this).transform.lossyScale.x * 0.32f); if ((Object)(object)rb != (Object)null) { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; rb.isKinematic = true; } Debug.Log((object)$"[BubbleGun] Bubble armed on {((Object)surface).name} for {armedLifetime:0.0}s."); return true; } private bool IsIgnoredCollider(Collider other) { if ((Object)(object)ignoredRoot != (Object)null && ((Component)other).transform.IsChildOf(ignoredRoot)) { return true; } ItemAttributes componentInParent = ((Component)other).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.item != (Object)null) { return componentInParent.item.itemName == "Bubble Gun"; } return false; } private void Detonate(bool chainTriggered) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (state != BubbleState.Detonated) { state = BubbleState.Detonated; Vector3 position = ((Component)this).transform.position; SpawnExplosionVisual(position, chainTriggered, explosionRadius); ApplyExplosionDamage(position); TriggerNearbyBubbles(position); networkProxy?.BroadcastBubblePop(bubbleId, position, explosionRadius, chainTriggered); Debug.Log((object)$"[BubbleGun] Bubble popped at {position}; radius={explosionRadius:0.0}, chain={chainTriggered}."); Object.Destroy((Object)(object)((Component)this).gameObject); } } private void ApplyExplosionDamage(Vector3 position) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer()) { networkProxy?.RequestExplosionDamage(position, explosionRadius, explosionDamage, explosionKnockback); return; } SeenEnemies.Clear(); Collider[] array = Physics.OverlapSphere(position, explosionRadius, -1, (QueryTriggerInteraction)2); foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } Enemy val2 = BubbleCombat.FindEnemy(val); if ((Object)(object)val2 != (Object)null && Object.op_Implicit((Object)(object)val2) && SeenEnemies.Add(((Object)val2).GetInstanceID())) { BubbleCombat.DamageEnemy(val2, explosionDamage, position); Rigidbody enemyRigidbody = BubbleCombat.GetEnemyRigidbody(val2); if ((Object)(object)enemyRigidbody != (Object)null && Object.op_Implicit((Object)(object)enemyRigidbody)) { enemyRigidbody.AddExplosionForce(explosionKnockback, position, explosionRadius, 0.45f, (ForceMode)1); } } } } private void TriggerNearbyBubbles(Vector3 position) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) for (int num = ActiveBubbles.Count - 1; num >= 0; num--) { BubbleBomb bubbleBomb = ActiveBubbles[num]; if (!((Object)(object)bubbleBomb == (Object)null) && !((Object)(object)bubbleBomb == (Object)(object)this) && bubbleBomb.state != BubbleState.Detonated && Vector3.Distance(position, ((Component)bubbleBomb).transform.position) <= chainReactionRadius) { bubbleBomb.ChainDetonate(position); } } } private void AnimateRainbowShell() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_00f2: 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_0096: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)bubbleMaterial == (Object)null)) { Color val = Color.HSVToRGB(Mathf.Repeat(hueOffset + Time.time * 0.12f, 1f), 0.55f, 1f); val.a = ((state == BubbleState.Armed) ? 0.46f : 0.34f); bubbleMaterial.color = val; if (bubbleMaterial.HasProperty("_EmissionColor")) { bubbleMaterial.SetColor("_EmissionColor", val * ((state == BubbleState.Armed) ? 0.55f : 0.35f)); } float num = ((state == BubbleState.Armed) ? (1f + Mathf.Sin(Time.time * 8f) * 0.035f) : (1f + Mathf.Sin(Time.time * 2.2f + hueOffset) * 0.018f)); ((Component)this).transform.localScale = baseScale * num; } } private static void SpawnExplosionVisual(Vector3 position, bool chainTriggered, float explosionRadius) { //IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj).name = (chainTriggered ? "BubbleChainPopVfx" : "BubblePopVfx"); obj.transform.position = position; obj.transform.localScale = Vector3.one * 0.18f; Collider val = default(Collider); if (obj.TryGetComponent(ref val)) { Object.Destroy((Object)(object)val); } Material material = obj.GetComponent().material; material.color = (chainTriggered ? new Color(1f, 0.62f, 0.95f, 0.58f) : new Color(0.78f, 0.95f, 1f, 0.42f)); TrySetTransparent(material); float targetScale = (chainTriggered ? Mathf.Max(2.8f, explosionRadius * 1.45f) : 2.2f); float lifetime = (chainTriggered ? 0.42f : 0.28f); obj.AddComponent().Initialize(lifetime, targetScale); } private static void TrySetTransparent(Material mat) { try { mat.SetFloat("_Mode", 3f); mat.SetInt("_SrcBlend", 5); mat.SetInt("_DstBlend", 10); mat.SetInt("_ZWrite", 0); mat.DisableKeyword("_ALPHATEST_ON"); mat.EnableKeyword("_ALPHABLEND_ON"); mat.DisableKeyword("_ALPHAPREMULTIPLY_ON"); mat.renderQueue = 3000; } catch { } try { mat.SetFloat("_Surface", 1f); mat.SetFloat("_Blend", 0f); mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); } catch { } } } public sealed class BubbleGunController : MonoBehaviour { private sealed class HeldGunState { public float BubbleTank; public float FireRequestedUntil; public float SprayAccumulator; public float Pressure; public float NextNetworkSprayAt; public bool Initialized; public Component? Battery; } private static readonly FieldInfo? PlayerAvatarIsLocalField = typeof(PlayerAvatar).GetField("isLocal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? GrabbedPhysGrabObjectField = typeof(PhysGrabber).GetField("grabbedPhysGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? HeldByLocalPlayerField = typeof(PhysGrabObject).GetField("heldByLocalPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? ToggleImpulseField = typeof(ItemToggle).GetField("toggleImpulse", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly Dictionary HeldGunStates = new Dictionary(); private static readonly Dictionary BatteryLifeFields = new Dictionary(); private static readonly Dictionary BatteryActiveFields = new Dictionary(); private PlayerController? playerController; private float BubbleTank; private bool inputUnavailableLogged; private const float GlobFireInterval = 0.05f; private const float TriggerRequestWindow = 0.18f; private const float PressureRisePerSecond = 7.5f; private const float PressureFallPerSecond = 5.5f; private const float SprayDropletsPerSecond = 18f; private const int MaxDropletsPerFrame = 2; private const float BubbleFlightLifetime = 7f; private const float BubbleLaunchUpward = 0.22f; private const float SprayConeAngle = 5.5f; private const float BubbleRangeMultiplier = 0.9f; private static Material? _BubbleMaterial; internal const string BubbleGunItemName = "Bubble Gun"; private const string BarrelMarkerName = "BubbleGun Barrel Origin"; public float TankFraction { get { if (!(Plugin.TankCapacity.Value > 0f)) { return 0f; } return BubbleTank / Plugin.TankCapacity.Value; } } internal static void OnItemGunShoot(ItemGun gun) { if (BubbleGunRuntime.Enabled && !((Object)(object)gun == (Object)null) && Object.op_Implicit((Object)(object)gun)) { PhysGrabObject val = ((Component)gun).GetComponent() ?? ((Component)gun).GetComponentInParent(); int key = (((Object)(object)val != (Object)null) ? ((Object)val).GetInstanceID() : ((Object)gun).GetInstanceID()); if (!HeldGunStates.TryGetValue(key, out HeldGunState value)) { value = new HeldGunState { BubbleTank = Plugin.TankCapacity.Value, Initialized = true }; HeldGunStates[key] = value; } value.FireRequestedUntil = Time.time + 0.18f; value.Pressure = Mathf.Max(value.Pressure, 0.25f); } } internal static void OnPhysGrabObjectUpdate(PhysGrabObject physGrabObject) { if (!BubbleGunRuntime.Enabled || (Object)(object)physGrabObject == (Object)null || !Object.op_Implicit((Object)(object)physGrabObject)) { return; } ItemAttributes val = ((Component)physGrabObject).GetComponent() ?? ((Component)physGrabObject).GetComponentInChildren(true) ?? ((Component)physGrabObject).GetComponentInParent(); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.item == (Object)null) && !(val.item.itemName != "Bubble Gun")) { int instanceID = ((Object)physGrabObject).GetInstanceID(); if (!HeldGunStates.TryGetValue(instanceID, out HeldGunState value)) { value = new HeldGunState(); HeldGunStates[instanceID] = value; } if (!value.Initialized) { value.BubbleTank = Plugin.TankCapacity.Value; value.Battery = FindBattery(((Component)physGrabObject).gameObject); SetBattery(value); value.Initialized = true; } BubbleGunNetworkProxy networkProxy = EnsureNetworkProxy(physGrabObject); SyncTankFromBattery(value); if (!IsHeldByLocalPlayer(physGrabObject)) { UpdateSprayState(value, firing: false, null, null, null); SetBattery(value); return; } bool firing; bool num = TryGetItemUseHeld(physGrabObject, out firing) && firing; bool flag = Time.time < value.FireRequestedUntil; bool firing2 = num || flag; Transform val2 = FindDeep(((Component)physGrabObject).transform, "BubbleGun Barrel Origin") ?? ((Component)physGrabObject).transform; Transform aim = (((Object)(object)PlayerController.instance != (Object)null && (Object)(object)PlayerController.instance.cameraGameObject != (Object)null) ? PlayerController.instance.cameraGameObject.transform : val2); UpdateSprayState(value, firing2, val2, aim, networkProxy); SetBattery(value); } } private void Start() { playerController = ((Component)this).GetComponent(); if ((Object)(object)playerController != (Object)null) { BubbleTank = Plugin.TankCapacity.Value; Debug.Log((object)$"[BubbleGun] Controller attached to {((Object)playerController).name}. Tank={BubbleTank:0.0}"); } } private void Update() { } private bool IsLocalController() { if ((Object)(object)playerController == (Object)null || !Object.op_Implicit((Object)(object)playerController)) { return false; } if ((Object)(object)PlayerController.instance != (Object)null && (Object)(object)PlayerController.instance != (Object)(object)playerController) { return false; } PlayerAvatar playerAvatarScript = playerController.playerAvatarScript; if ((Object)(object)playerAvatarScript == (Object)null || !Object.op_Implicit((Object)(object)playerAvatarScript)) { return (Object)(object)PlayerController.instance == (Object)(object)playerController; } object obj = PlayerAvatarIsLocalField?.GetValue(playerAvatarScript); if (obj is bool) { return (bool)obj; } return (Object)(object)PlayerController.instance == (Object)(object)playerController; } private bool TryGetFireHeld(out bool firing) { try { firing = SemiFunc.InputHold((InputKey)2); return true; } catch (Exception ex) { firing = false; if (!inputUnavailableLogged) { inputUnavailableLogged = true; Debug.LogWarning((object)("[BubbleGun] Fire input is unavailable; Bubble firing is disabled for this player controller. " + ex.GetType().Name + ": " + ex.Message)); } return false; } } private static bool TryGetItemUseHeld(PhysGrabObject physGrabObject, out bool firing) { bool flag = false; try { flag = SemiFunc.InputHold((InputKey)2); } catch { flag = false; } ItemToggle val = ((Component)physGrabObject).GetComponent() ?? ((Component)physGrabObject).GetComponentInChildren(true) ?? ((Component)physGrabObject).GetComponentInParent(); bool flag2 = default(bool); int num; if ((Object)(object)val != (Object)null) { object obj2 = ToggleImpulseField?.GetValue(val); if (obj2 is bool) { flag2 = (bool)obj2; num = 1; } else { num = 0; } } else { num = 0; } bool flag3 = (byte)((uint)num & (flag2 ? 1u : 0u)) != 0; firing = flag || ((Object)(object)val != (Object)null && (val.toggleState || flag3)); return true; } private static bool IsHeldByLocalPlayer(PhysGrabObject physGrabObject) { object obj = HeldByLocalPlayerField?.GetValue(physGrabObject); if (obj is bool) { return (bool)obj; } PhysGrabber instance = PhysGrabber.instance; if ((Object)(object)instance == (Object)null || !Object.op_Implicit((Object)(object)instance)) { return false; } object? obj2 = GrabbedPhysGrabObjectField?.GetValue(instance); PhysGrabObject val = (PhysGrabObject)((obj2 is PhysGrabObject) ? obj2 : null); if ((Object)(object)val != (Object)null) { return (Object)(object)val == (Object)(object)physGrabObject; } return false; } private bool TryGetHeldBubbleGun(out Transform barrel, out Transform aim) { barrel = null; aim = null; PhysGrabber instance = PhysGrabber.instance; if ((Object)(object)instance == (Object)null || !Object.op_Implicit((Object)(object)instance)) { return false; } object? obj = GrabbedPhysGrabObjectField?.GetValue(instance); PhysGrabObject val = (PhysGrabObject)((obj is PhysGrabObject) ? obj : null); if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val)) { return false; } ItemAttributes val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInChildren(true) ?? ((Component)val).GetComponentInParent(); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.item == (Object)null || val2.item.itemName != "Bubble Gun") { return false; } barrel = FindDeep(((Component)val).transform, "BubbleGun Barrel Origin") ?? ((Component)val).transform; aim = (Transform)(((Object)(object)playerController.cameraGameObject != (Object)null) ? ((object)playerController.cameraGameObject.transform) : ((object)barrel)); return true; } private static void UpdateSprayState(HeldGunState state, bool firing, Transform? barrel, Transform? aim, BubbleGunNetworkProxy? networkProxy) { float num = ((firing && state.BubbleTank > 0f) ? 1f : 0f); float num2 = ((num > state.Pressure) ? 7.5f : 5.5f); state.Pressure = Mathf.MoveTowards(state.Pressure, num, num2 * Time.deltaTime); if (state.Pressure <= 0.02f || (Object)(object)barrel == (Object)null || (Object)(object)aim == (Object)null || state.BubbleTank <= 0f) { state.SprayAccumulator = 0f; return; } float num3 = Mathf.Min(Plugin.TankDrainRate.Value, 5f); state.BubbleTank = Mathf.Max(0f, state.BubbleTank - num3 * state.Pressure * Time.deltaTime); state.SprayAccumulator += Time.deltaTime * Mathf.Lerp(28f, 18f, state.Pressure); int num4 = Mathf.Min(2, Mathf.FloorToInt(state.SprayAccumulator)); if (num4 > 0) { state.SprayAccumulator -= num4; for (int i = 0; i < num4; i++) { FireGlob(barrel, aim, state.Pressure, networkProxy); } } } private static void BroadcastRemoteSpray(HeldGunState state, bool firing, Transform barrel, Transform aim, BubbleGunNetworkProxy? networkProxy) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (firing && !(state.Pressure <= 0.05f) && !((Object)(object)networkProxy == (Object)null) && !(Time.time < state.NextNetworkSprayAt)) { state.NextNetworkSprayAt = Time.time + 0.06f; networkProxy.BroadcastSpray(barrel.position, aim.forward, state.Pressure); } } private static BubbleGunNetworkProxy? EnsureNetworkProxy(PhysGrabObject physGrabObject) { PhotonView val = ((Component)physGrabObject).GetComponent() ?? ((Component)physGrabObject).GetComponentInChildren(true) ?? ((Component)physGrabObject).GetComponentInParent(); if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val)) { return null; } BubbleGunNetworkProxy bubbleGunNetworkProxy = ((Component)val).GetComponent(); if ((Object)(object)bubbleGunNetworkProxy == (Object)null || !Object.op_Implicit((Object)(object)bubbleGunNetworkProxy)) { bubbleGunNetworkProxy = ((Component)val).gameObject.AddComponent(); } bubbleGunNetworkProxy.SetPhotonView(val); return bubbleGunNetworkProxy; } private static Component? FindBattery(GameObject root) { Component[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "ItemBattery") { TrySetBatteryActive(val, active: true); return val; } } return null; } private static void SetBattery(HeldGunState state) { if (!((Object)(object)state.Battery == (Object)null) && Object.op_Implicit((Object)(object)state.Battery)) { FieldInfo batteryLifeField = GetBatteryLifeField(state.Battery); if (batteryLifeField != null) { batteryLifeField.SetValue(state.Battery, Mathf.Clamp(state.BubbleTank, 0f, Plugin.TankCapacity.Value)); } TrySetBatteryActive(state.Battery, active: true); } } private static void SyncTankFromBattery(HeldGunState state) { if (!((Object)(object)state.Battery == (Object)null) && Object.op_Implicit((Object)(object)state.Battery)) { if (GetBatteryLifeField(state.Battery)?.GetValue(state.Battery) is float num && num > state.BubbleTank) { state.BubbleTank = Mathf.Clamp(num, 0f, Plugin.TankCapacity.Value); } TrySetBatteryActive(state.Battery, active: true); } } private static FieldInfo? GetBatteryLifeField(Component battery) { Type type = ((object)battery).GetType(); if (!BatteryLifeFields.TryGetValue(type, out FieldInfo value)) { value = type.GetField("batteryLife", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); BatteryLifeFields[type] = value; } return value; } private static void TrySetBatteryActive(Component battery, bool active) { Type type = ((object)battery).GetType(); if (!BatteryActiveFields.TryGetValue(type, out FieldInfo value)) { value = type.GetField("batteryActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); BatteryActiveFields[type] = value; } value?.SetValue(battery, active); } private static void FireSprayBurst(Transform barrel, Transform aim, float pressure = 1f) { for (int i = 0; i < 2; i++) { FireGlob(barrel, aim, pressure, null); } } private static void FireGlob(Transform barrel, Transform aim, float pressure, BubbleGunNetworkProxy? networkProxy) { //IL_0001: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) Vector3 val = barrel.right * Random.Range(-0.024f, 0.024f); Vector3 val2 = barrel.up * Random.Range(-0.02f, 0.02f); Vector3 position = barrel.position + val + val2 + aim.forward * 0.18f; PhysGrabObject componentInParent = ((Component)barrel).GetComponentInParent(); Transform ignoredRoot = ((componentInParent != null) ? ((Component)componentInParent).transform : null); GameObject val3 = CreateGlobObject(position); int bubbleId = networkProxy?.CreateBubbleId() ?? ((Object)val3).GetInstanceID(); Vector3 val4 = Quaternion.Euler(Random.Range(-5.5f, 5.5f), Random.Range(-5.5f, 5.5f), Random.Range(-2f, 2f)) * aim.forward; Rigidbody val5 = default(Rigidbody); if (val3.TryGetComponent(ref val5)) { float num = Mathf.Max(Plugin.BubbleSpeed.Value, 2f); float num2 = Mathf.Lerp(num * 0.7f, num * 1.15f, pressure); float num3 = Random.Range(num2 * 0.82f, num2) * 0.9f; val5.velocity = ((Vector3)(ref val4)).normalized * num3 + Vector3.up * Random.Range(0.03f, 0.22f); networkProxy?.BroadcastBubbleLaunch(bubbleId, position, val5.velocity, val3.transform.localScale.x, 7f, Plugin.ArmedLifetime.Value); } val3.AddComponent().Initialize(7f, Plugin.ArmedLifetime.Value, Plugin.ExplosionRadius.Value, Plugin.ChainReactionRadius.Value, Plugin.ExplosionDamage.Value, Plugin.ExplosionKnockback.Value, networkProxy, bubbleId, ignoredRoot); } internal static void SpawnRemoteVisualSpray(Vector3 barrelPosition, Vector3 aimForward, float pressure, int seed) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0129: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) State state = Random.state; Random.InitState(seed); try { int num = Mathf.Clamp(Mathf.RoundToInt(Mathf.Lerp(5f, 11f, pressure)), 5, 11); Vector3 val = ((((Vector3)(ref aimForward)).sqrMagnitude > 0.01f) ? ((Vector3)(ref aimForward)).normalized : Vector3.forward); Rigidbody val3 = default(Rigidbody); for (int i = 0; i < num; i++) { GameObject obj = CreateGlobObject(barrelPosition); Transform transform = obj.transform; transform.localScale *= 1.45f; Vector3 val2 = Quaternion.Euler(Random.Range(-5.5f, 5.5f), Random.Range(-5.5f, 5.5f), Random.Range(-2f, 2f)) * val; if (obj.TryGetComponent(ref val3)) { float num2 = Mathf.Max(Plugin.BubbleSpeed.Value, 2f); float num3 = Mathf.Lerp(num2 * 0.7f, num2 * 1.15f, pressure); val3.velocity = ((Vector3)(ref val2)).normalized * Random.Range(num3 * 0.82f, num3) * 0.9f; } obj.AddComponent().Initialize(7f); } } finally { Random.state = state; } } internal static void SpawnRemoteVisualBubble(int bubbleId, Vector3 position, Vector3 velocity, float scale, float flightLifetime, float armedLifetime, int seed) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) State state = Random.state; Random.InitState(seed); try { GameObject obj = CreateGlobObject(position); obj.transform.localScale = Vector3.one * Mathf.Clamp(scale, 0.08f, 0.45f); Rigidbody val = default(Rigidbody); if (obj.TryGetComponent(ref val)) { val.velocity = velocity; } obj.AddComponent().Initialize(bubbleId, flightLifetime, armedLifetime); } finally { Random.state = state; } } private static GameObject CreateGlobObject(Vector3 position) { //IL_0017: 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_0039: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj).name = "BubbleBomb"; obj.transform.position = position; float num = Random.Range(0.16f, 0.26f); obj.transform.localScale = Vector3.one * num; Collider val = default(Collider); if (obj.TryGetComponent(ref val)) { val.isTrigger = true; } Rigidbody obj2 = obj.AddComponent(); obj2.collisionDetectionMode = (CollisionDetectionMode)2; obj2.useGravity = false; obj2.drag = 0.24f; obj2.angularDrag = 0.15f; Renderer val2 = default(Renderer); if (obj.TryGetComponent(ref val2)) { val2.material = GetOrCreateBubbleMaterial(); } return obj; } private static Material GetOrCreateBubbleMaterial() { if ((Object)(object)_BubbleMaterial != (Object)null && Object.op_Implicit((Object)(object)_BubbleMaterial)) { return _BubbleMaterial; } _BubbleMaterial = CreateBubbleMaterial(); return _BubbleMaterial; } private static Material CreateBubbleMaterial() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive((PrimitiveType)0); Material val2; try { val2 = new Material(val.GetComponent().sharedMaterial); } finally { Object.Destroy((Object)(object)val); } val2.color = new Color(0.78f, 0.92f, 1f, 0.34f); TrySetTransparent(val2); if (val2.HasProperty("_EmissionColor")) { val2.EnableKeyword("_EMISSION"); val2.SetColor("_EmissionColor", new Color(0.25f, 0.42f, 0.9f, 0.45f)); } return val2; } private static void TrySetTransparent(Material mat) { try { mat.SetFloat("_Mode", 3f); mat.SetInt("_SrcBlend", 5); mat.SetInt("_DstBlend", 10); mat.SetInt("_ZWrite", 0); mat.DisableKeyword("_ALPHATEST_ON"); mat.EnableKeyword("_ALPHABLEND_ON"); mat.DisableKeyword("_ALPHAPREMULTIPLY_ON"); mat.renderQueue = 3000; } catch { } try { mat.SetFloat("_Surface", 1f); mat.SetFloat("_Blend", 0f); mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); } catch { } } private static Transform? FindDeep(Transform root, string name) { Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == name) { return val; } } return null; } } public sealed class BubbleGunNetworkProxy : MonoBehaviour { private PhotonView? photonView; private int packetCounter; private int bubbleCounter; internal void SetPhotonView(PhotonView view) { photonView = view; } internal void BroadcastSpray(Vector3 barrelPosition, Vector3 aimForward, float pressure) { //IL_006c: 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) if (SemiFunc.IsMultiplayer() && !((Object)(object)photonView == (Object)null) && Object.op_Implicit((Object)(object)photonView)) { int num = (photonView.ViewID * 397) ^ packetCounter++ ^ Mathf.RoundToInt(Time.time * 1000f); photonView.RPC("RemoteSprayRPC", (RpcTarget)1, new object[4] { barrelPosition, aimForward, pressure, num }); } } internal int CreateBubbleId() { return ((((Object)(object)photonView != (Object)null && Object.op_Implicit((Object)(object)photonView)) ? photonView.ViewID : ((Object)this).GetInstanceID()) * 397) ^ ++bubbleCounter ^ Mathf.RoundToInt(Time.time * 1000f); } internal void BroadcastBubbleLaunch(int bubbleId, Vector3 position, Vector3 velocity, float scale, float flightLifetime, float armedLifetime) { //IL_0075: 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) if (SemiFunc.IsMultiplayer() && !((Object)(object)photonView == (Object)null) && Object.op_Implicit((Object)(object)photonView)) { int num = (photonView.ViewID * 397) ^ packetCounter++ ^ Mathf.RoundToInt(Time.time * 1000f); photonView.RPC("RemoteBubbleLaunchRPC", (RpcTarget)1, new object[7] { bubbleId, position, velocity, scale, flightLifetime, armedLifetime, num }); } } internal void BroadcastBubblePop(int bubbleId, Vector3 position, float radius, bool chainTriggered) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.IsMultiplayer() && !((Object)(object)photonView == (Object)null) && Object.op_Implicit((Object)(object)photonView)) { photonView.RPC("RemoteBubblePopRPC", (RpcTarget)1, new object[4] { bubbleId, position, radius, chainTriggered }); } } internal void RequestExplosionDamage(Vector3 position, float radius, int damage, float knockback) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMultiplayer() || SemiFunc.IsMasterClientOrSingleplayer()) { ApplyExplosionDamageAsMaster(position, radius, damage, knockback); } else if (!((Object)(object)photonView == (Object)null) && Object.op_Implicit((Object)(object)photonView)) { photonView.RPC("RequestExplosionDamageRPC", (RpcTarget)2, new object[4] { position, radius, damage, knockback }); } } [PunRPC] private void RemoteSprayRPC(Vector3 barrelPosition, Vector3 aimForward, float pressure, int seed) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (BubbleGunRuntime.Enabled) { BubbleGunController.SpawnRemoteVisualSpray(barrelPosition, aimForward, Mathf.Clamp01(pressure), seed); } } [PunRPC] private void RemoteBubbleLaunchRPC(int bubbleId, Vector3 position, Vector3 velocity, float scale, float flightLifetime, float armedLifetime, int seed) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (BubbleGunRuntime.Enabled) { BubbleGunController.SpawnRemoteVisualBubble(bubbleId, position, velocity, scale, flightLifetime, armedLifetime, seed); } } [PunRPC] private void RemoteBubblePopRPC(int bubbleId, Vector3 position, float radius, bool chainTriggered) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (BubbleGunRuntime.Enabled) { BubbleRemoteVisualBubble.PopFromNetwork(bubbleId, position, radius, chainTriggered); } } [PunRPC] private void RequestExplosionDamageRPC(Vector3 position, float radius, int damage, float knockback) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (BubbleGunRuntime.Enabled && PhotonNetwork.IsMasterClient) { ApplyExplosionDamageAsMaster(position, radius, damage, knockback); } } internal static void SpawnPopVfx(Vector3 position, float radius, bool chainTriggered) { //IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj).name = (chainTriggered ? "BubbleChainPopRemoteVfx" : "BubblePopRemoteVfx"); obj.transform.position = position; obj.transform.localScale = Vector3.one * 0.14f; Collider val = default(Collider); if (obj.TryGetComponent(ref val)) { Object.Destroy((Object)(object)val); } Material material = obj.GetComponent().material; material.color = new Color(0.78f, 0.95f, 1f, 0.38f); TrySetTransparent(material); float targetScale = (chainTriggered ? Mathf.Max(2.8f, radius * 1.45f) : Mathf.Max(0.5f, radius)); float lifetime = (chainTriggered ? 0.42f : 0.24f); obj.AddComponent().Initialize(lifetime, targetScale); } private static void ApplyExplosionDamageAsMaster(Vector3 position, float radius, int damage, float knockback) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } HashSet hashSet = new HashSet(); Collider[] array = Physics.OverlapSphere(position, Mathf.Clamp(radius, 0.5f, 8f), -1, (QueryTriggerInteraction)2); foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } Enemy val2 = BubbleCombat.FindEnemy(val); if (!((Object)(object)val2 == (Object)null) && Object.op_Implicit((Object)(object)val2) && hashSet.Add(((Object)val2).GetInstanceID())) { BubbleCombat.DamageEnemy(val2, Mathf.Clamp(damage, 0, 24), position); Rigidbody enemyRigidbody = BubbleCombat.GetEnemyRigidbody(val2); if ((Object)(object)enemyRigidbody != (Object)null && Object.op_Implicit((Object)(object)enemyRigidbody)) { enemyRigidbody.AddExplosionForce(Mathf.Clamp(knockback, 0f, 80f), position, radius, 0.45f, (ForceMode)1); } } } } private static void TrySetTransparent(Material mat) { try { mat.SetFloat("_Mode", 3f); mat.SetInt("_SrcBlend", 5); mat.SetInt("_DstBlend", 10); mat.SetInt("_ZWrite", 0); mat.DisableKeyword("_ALPHATEST_ON"); mat.EnableKeyword("_ALPHABLEND_ON"); mat.DisableKeyword("_ALPHAPREMULTIPLY_ON"); mat.renderQueue = 3000; } catch { } try { mat.SetFloat("_Surface", 1f); mat.SetFloat("_Blend", 0f); mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); } catch { } } } internal static class BubbleGunRuntime { internal static bool Enabled { get; set; } = true; internal static string PluginDirectory { get; set; } = string.Empty; } public sealed class BubbleVisualBubble : MonoBehaviour { private Material? material; private Vector3 baseScale; private float expiresAt; private float hueOffset; internal void Initialize(float lifetime) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) expiresAt = Time.time + lifetime; baseScale = ((Component)this).transform.localScale; hueOffset = Random.value; Renderer component = ((Component)this).GetComponent(); material = ((component != null) ? component.material : null); } private void Update() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if (Time.time >= expiresAt) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } float num = 1f + Mathf.Sin(Time.time * 2.1f + hueOffset) * 0.018f; ((Component)this).transform.localScale = baseScale * num; if (!((Object)(object)material == (Object)null)) { Color val = Color.HSVToRGB(Mathf.Repeat(hueOffset + Time.time * 0.12f, 1f), 0.55f, 1f); val.a = 0.28f; material.color = val; if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", val * 0.32f); } } } } public sealed class BubblePopVfx : MonoBehaviour { private Material? material; private Vector3 startScale; private float startTime; private float lifetime; private float targetScale; internal void Initialize(float lifetime, float targetScale) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) this.lifetime = Mathf.Max(0.05f, lifetime); this.targetScale = Mathf.Max(0.1f, targetScale); startTime = Time.time; startScale = ((Component)this).transform.localScale; Renderer component = ((Component)this).GetComponent(); material = ((component != null) ? component.material : null); } private void Update() { //IL_0020: 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) //IL_0036: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01((Time.time - startTime) / lifetime); ((Component)this).transform.localScale = Vector3.Lerp(startScale, Vector3.one * targetScale, num); if ((Object)(object)material != (Object)null) { Color color = Color.HSVToRGB(Mathf.Repeat(Time.time * 0.8f, 1f), 0.48f, 1f); color.a = Mathf.Lerp(0.42f, 0f, num); material.color = color; } if (num >= 1f) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } public sealed class BubbleRemoteVisualBubble : MonoBehaviour { private enum VisualState { Floating, Armed, Popped } private static readonly Dictionary RemoteBubbles = new Dictionary(); private VisualState state; private Rigidbody? rb; private Material? material; private Vector3 baseScale; private int bubbleId; private float spawnTime; private float expiresAt; private float armedLifetime; private float hueOffset; private const float ContactGraceSeconds = 0.16f; private const float ContactRadius = 0.14f; private const float BubbleWeight = 0.11f; private const float VerticalBob = 0.06f; private const float SideDrift = 0.055f; internal void Initialize(int bubbleId, float flightLifetime, float armedLifetime) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) this.bubbleId = bubbleId; spawnTime = Time.time; expiresAt = Time.time + Mathf.Max(0.25f, flightLifetime); this.armedLifetime = Mathf.Max(1f, armedLifetime); baseScale = ((Component)this).transform.localScale; hueOffset = Random.value; rb = ((Component)this).GetComponent(); Renderer component = ((Component)this).GetComponent(); material = ((component != null) ? component.material : null); RemoteBubbles[bubbleId] = this; } private void OnDestroy() { if (RemoteBubbles.TryGetValue(bubbleId, out BubbleRemoteVisualBubble value) && (Object)(object)value == (Object)(object)this) { RemoteBubbles.Remove(bubbleId); } } internal static void PopFromNetwork(int bubbleId, Vector3 position, float radius, bool chainTriggered) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (RemoteBubbles.TryGetValue(bubbleId, out BubbleRemoteVisualBubble value) && (Object)(object)value != (Object)null && Object.op_Implicit((Object)(object)value)) { value.Pop(position, radius, chainTriggered); } else { BubbleGunNetworkProxy.SpawnPopVfx(position, radius, chainTriggered); } } private void Update() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) AnimateShell(); if (state == VisualState.Floating && (Object)(object)rb != (Object)null) { float num = Mathf.Sin((Time.time + hueOffset) * 2.1f) * 0.055f; float num2 = Mathf.Sin((Time.time + hueOffset) * 3.4f) * 0.06f; rb.AddForce(Vector3.down * 0.11f + Vector3.up * num2 + ((Component)this).transform.right * num, (ForceMode)5); CheckContacts(); } if (Time.time >= expiresAt) { if (state == VisualState.Armed) { expiresAt = Time.time + 5f; } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } } private void OnTriggerEnter(Collider other) { if (state == VisualState.Floating) { HandleContact(other); } } private void CheckContacts() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (Time.time - spawnTime < 0.16f) { return; } Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, 0.14f, -1, (QueryTriggerInteraction)2); foreach (Collider val in array) { if ((Object)(object)val != (Object)null && HandleContact(val)) { break; } } } private bool HandleContact(Collider other) { if ((Object)(object)other == (Object)null || (Object)(object)((Component)other).transform == (Object)(object)((Component)this).transform || (Object)(object)((Component)other).GetComponentInParent() == (Object)(object)this) { return false; } if ((Object)(object)((Component)other).GetComponentInParent() != (Object)null || (Object)(object)((Component)other).GetComponentInParent() != (Object)null || IsBubbleGunCollider(other)) { return false; } if ((Object)(object)((Component)other).GetComponentInParent() != (Object)null || (Object)(object)((Component)other).GetComponentInParent() != (Object)null) { return false; } if (other.isTrigger) { return false; } return ArmOnSurface(other); } private bool ArmOnSurface(Collider surface) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_002d: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if (state != 0) { return false; } Vector3 val = surface.ClosestPoint(((Component)this).transform.position); Vector3 val2 = ((Component)this).transform.position - val; float magnitude = ((Vector3)(ref val2)).magnitude; float num = Mathf.Max(0.04f, ((Component)this).transform.lossyScale.x * 0.65f); if (magnitude < 0.02f || magnitude > num) { return false; } state = VisualState.Armed; expiresAt = Time.time + armedLifetime; Vector3 val3 = val2 / magnitude; ((Component)this).transform.position = val + val3 * Mathf.Max(0.025f, ((Component)this).transform.lossyScale.x * 0.32f); if ((Object)(object)rb != (Object)null) { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; rb.isKinematic = true; } return true; } private static bool IsBubbleGunCollider(Collider other) { ItemAttributes componentInParent = ((Component)other).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.item != (Object)null) { return componentInParent.item.itemName == "Bubble Gun"; } return false; } private void Pop(Vector3 position, float radius, bool chainTriggered) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (state != VisualState.Popped) { state = VisualState.Popped; BubbleGunNetworkProxy.SpawnPopVfx(position, radius, chainTriggered); Object.Destroy((Object)(object)((Component)this).gameObject); } } private void AnimateShell() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_00f2: 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_0096: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { Color val = Color.HSVToRGB(Mathf.Repeat(hueOffset + Time.time * 0.12f, 1f), 0.55f, 1f); val.a = ((state == VisualState.Armed) ? 0.46f : 0.3f); material.color = val; if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", val * ((state == VisualState.Armed) ? 0.5f : 0.3f)); } float num = ((state == VisualState.Armed) ? (1f + Mathf.Sin(Time.time * 8f) * 0.035f) : (1f + Mathf.Sin(Time.time * 2.2f + hueOffset) * 0.018f)); ((Component)this).transform.localScale = baseScale * num; } } } }