Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RepoMutantEnemies v0.8.0
Matsu.MergedEnemyMod.dll
Decompiled 11 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using REPOLib.Modules; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Matsu.MergedEnemyMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Matsu.MergedEnemyMod")] [assembly: AssemblyTitle("Matsu.MergedEnemyMod")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Matsu.MergedEnemyMod { internal static class FusionShared { private static ParticleScriptExplosion? _sharedExplosion; private static GameObject? _explosionPrefab; private static readonly List<PlayerAvatar> _noPlayers = new List<PlayerAvatar>(); private static FieldInfo? _healthCurrentField; private static FieldInfo? _impactDetectorField; private static MethodInfo? _hurtMultiplierMethod; private static FieldInfo? _explSizeField; private static FieldInfo? _explDmgField; private static FieldInfo? _explDmgEnemyField; private const string AuraLightName = "MatsuMutationAura"; private static FieldInfo? _tumbleField; private static FieldInfo? _tumblePhysGrabObjectField; private static FieldInfo? _clientPositionField; private static FieldInfo? _clientPositionCurrentField; private static FieldInfo? _visualPositionField; private static FieldInfo? _isDisabledField; public static List<PlayerAvatar> AllPlayers() { GameDirector instance = GameDirector.instance; if (!((Object)(object)instance != (Object)null) || instance.PlayerList == null) { return _noPlayers; } return instance.PlayerList; } public static bool NearestPlayerWithin(Vector3 from, float range) { //IL_001e: 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) foreach (PlayerAvatar item in AllPlayers()) { if (!((Object)(object)item == (Object)null) && Vector3.Distance(from, ((Component)item).transform.position) <= range) { return true; } } return false; } public static List<PlayerAvatar> PlayersInRadius(Vector3 center, float radius) { //IL_0024: 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) List<PlayerAvatar> list = new List<PlayerAvatar>(); foreach (PlayerAvatar item in AllPlayers()) { if (!((Object)(object)item == (Object)null) && Vector3.Distance(center, ((Component)item).transform.position) <= radius) { list.Add(item); } } return list; } public static PlayerAvatar? NearestPlayer(Vector3 from, float maxDistance) { //IL_0022: 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) PlayerAvatar result = null; float num = maxDistance; foreach (PlayerAvatar item in AllPlayers()) { if (!((Object)(object)item == (Object)null)) { float num2 = Vector3.Distance(from, ((Component)item).transform.position); if (num2 <= num) { num = num2; result = item; } } } return result; } public static List<PhysGrabObject> PhysObjectsInRadius(Vector3 center, float radius) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) HashSet<PhysGrabObject> hashSet = new HashSet<PhysGrabObject>(); Collider[] array = Physics.OverlapSphere(center, radius); foreach (Collider val in array) { if (!((Object)(object)val == (Object)null)) { PhysGrabObject componentInParent = ((Component)val).GetComponentInParent<PhysGrabObject>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.rb != (Object)null && !componentInParent.grabbed && (Object)(object)((Component)componentInParent).GetComponentInParent<EnemyParent>() == (Object)null) { hashSet.Add(componentInParent); } } } return new List<PhysGrabObject>(hashSet); } private static void SetExplField(ParticlePrefabExplosion pe, ref FieldInfo? cache, string name, object val) { try { if ((object)cache == null) { cache = typeof(ParticlePrefabExplosion).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } cache?.SetValue(pe, val); } catch { } } public static ParticlePrefabExplosion? ExplodeAuthoritative(Vector3 pos, float size, int playerDmg, int enemyDmg, PhysGrabObject? ignoreSelf = null, Enemy? enemyHost = null) { //IL_002c: 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_0087: Unknown result type (might be due to invalid IL or missing references) ParticlePrefabExplosion val = null; if ((Object)(object)_sharedExplosion == (Object)null) { _sharedExplosion = Object.FindObjectOfType<ParticleScriptExplosion>(true); } if ((Object)(object)_sharedExplosion != (Object)null) { try { val = _sharedExplosion.Spawn(pos, size, playerDmg, enemyDmg, 1f, false, false, 1f); } catch { val = null; } } if ((Object)(object)val == (Object)null) { if ((Object)(object)_explosionPrefab == (Object)null) { _explosionPrefab = Resources.Load<GameObject>("Effects/Part Prefab Explosion"); } if ((Object)(object)_explosionPrefab != (Object)null) { val = Object.Instantiate<GameObject>(_explosionPrefab, pos, Quaternion.identity).GetComponent<ParticlePrefabExplosion>(); if ((Object)(object)val != (Object)null) { SetExplField(val, ref _explSizeField, "explosionSize", size); SetExplField(val, ref _explDmgField, "explosionDamage", playerDmg); SetExplField(val, ref _explDmgEnemyField, "explosionDamageEnemy", enemyDmg); try { ParticleSystem particleFire = val.particleFire; if (particleFire != null) { particleFire.Play(); } ParticleSystem particleSmoke = val.particleSmoke; if (particleSmoke != null) { particleSmoke.Play(); } if ((Object)(object)val.light != (Object)null) { ((Behaviour)val.light).enabled = true; } } catch { } } } } if ((Object)(object)val != (Object)null && (Object)(object)val.HurtCollider != (Object)null) { try { if ((Object)(object)ignoreSelf != (Object)null && val.HurtCollider.ignoreObjects != null) { val.HurtCollider.ignoreObjects.Add(ignoreSelf); } if ((Object)(object)enemyHost != (Object)null) { val.HurtCollider.enemyHost = enemyHost; } } catch { } } return val; } public static void ApplyMutationGlow(Transform root, Color color) { //IL_002e: 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_0040: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } try { Transform val = root.Find("MatsuMutationAura"); Light val2; if ((Object)(object)val != (Object)null) { val2 = ((Component)val).GetComponent<Light>(); } else { GameObject val3 = new GameObject("MatsuMutationAura"); val3.transform.SetParent(root, false); val3.transform.localPosition = Vector3.zero; val2 = val3.AddComponent<Light>(); val2.type = (LightType)2; val2.shadows = (LightShadows)0; } if ((Object)(object)val2 != (Object)null) { val2.color = color; val2.range = Plugin.MutationAuraRange.Value; val2.intensity = Plugin.MutationAuraIntensity.Value; } } catch { } Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true); foreach (Renderer val4 in componentsInChildren) { if ((Object)(object)val4 == (Object)null) { continue; } Material[] materials = val4.materials; foreach (Material val5 in materials) { if (!((Object)(object)val5 == (Object)null)) { try { val5.SetFloat("_FresnelAmount", 1f); val5.SetFloat("_FresnelScale", 1f); val5.SetFloat("_FresnelPower", 5f); val5.SetFloat("_FresnelBias", 0f); val5.SetColor("_FresnelColor", color); val5.SetFloat("_FresnelEmission", 1f); } catch { } } } } } public static void SetHealthCurrent(EnemyHealth health, int value) { try { if (_healthCurrentField == null) { _healthCurrentField = typeof(EnemyHealth).GetField("healthCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } _healthCurrentField?.SetValue(health, value); } catch { } } public static void BoostThrownImpact(PhysGrabObject obj, float multiplier, float time) { try { if (_impactDetectorField == null) { _impactDetectorField = typeof(PhysGrabObject).GetField("impactDetector", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object obj2 = _impactDetectorField?.GetValue(obj); if (obj2 != null) { if (_hurtMultiplierMethod == null) { _hurtMultiplierMethod = obj2.GetType().GetMethod("PlayerHurtMultiplier", BindingFlags.Instance | BindingFlags.Public); } _hurtMultiplierMethod?.Invoke(obj2, new object[2] { multiplier, time }); } } catch { } } public static bool TryGetSafeRandomPoint(Vector3 from, out Vector3 point) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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) int mask = LayerMask.GetMask(new string[1] { "Default" }); NavMeshHit val2 = default(NavMeshHit); RaycastHit val3 = default(RaycastHit); for (int i = 0; i < 16; i++) { LevelPoint val = SemiFunc.LevelPointGet(from, 0f, 9999f); if (!((Object)(object)val == (Object)null) && NavMesh.SamplePosition(((Component)val).transform.position + Random.insideUnitSphere * 3f, ref val2, 5f, -1) && Physics.Raycast(((NavMeshHit)(ref val2)).position + Vector3.up * 0.5f, Vector3.down, ref val3, 3f, mask, (QueryTriggerInteraction)1)) { point = ((RaycastHit)(ref val3)).point + Vector3.up * 0.6f; return true; } } point = from; return false; } public static PhysGrabObject? GetPlayerPhysGrabObject(PlayerAvatar player) { try { if ((object)_tumbleField == null) { _tumbleField = typeof(PlayerAvatar).GetField("tumble", BindingFlags.Instance | BindingFlags.NonPublic); } object obj = _tumbleField?.GetValue(player); if (obj == null) { return null; } if ((object)_tumblePhysGrabObjectField == null) { _tumblePhysGrabObjectField = obj.GetType().GetField("physGrabObject", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj2 = _tumblePhysGrabObjectField?.GetValue(obj); return (PhysGrabObject?)((obj2 is PhysGrabObject) ? obj2 : null); } catch { return null; } } public static void SetPlayerClientPosition(PlayerAvatar player, Vector3 pos) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) try { if ((object)_clientPositionField == null) { _clientPositionField = typeof(PlayerAvatar).GetField("clientPosition", BindingFlags.Instance | BindingFlags.NonPublic); } if ((object)_clientPositionCurrentField == null) { _clientPositionCurrentField = typeof(PlayerAvatar).GetField("clientPositionCurrent", BindingFlags.Instance | BindingFlags.NonPublic); } _clientPositionField?.SetValue(player, pos); _clientPositionCurrentField?.SetValue(player, pos); } catch { } } public static void SetPlayerVisualPosition(PlayerAvatarVisuals visuals, Vector3 pos) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) try { if ((object)_visualPositionField == null) { _visualPositionField = typeof(PlayerAvatarVisuals).GetField("visualPosition", BindingFlags.Instance | BindingFlags.NonPublic); } _visualPositionField?.SetValue(visuals, pos); } catch { } } public static bool IsPlayerDisabled(PlayerAvatar player) { try { if ((object)_isDisabledField == null) { _isDisabledField = typeof(PlayerAvatar).GetField("isDisabled", BindingFlags.Instance | BindingFlags.NonPublic); } return _isDisabledField != null && (bool)(_isDisabledField.GetValue(player) ?? ((object)false)); } catch { return false; } } } public class BoomdayBoyFusion : MonoBehaviour { internal static readonly Color AuraColor = new Color(1f, 0.4f, 0f); private EnemyBirthdayBoy _birthday; private EnemyHealth? _health; private EnemyParent? _self; private Enemy? _enemy; private PhysGrabObject? _selfPhys; private bool _fuseLit; private bool _deathDetonated; private bool _hpDone; private float _fuseTimer; private float _explodeCooldown; private float _balloonTimer; private float _proximityTimer; private float _glowTimer; private readonly List<Vector3> _orderedKeys = new List<Vector3>(); private readonly HashSet<Vector3> _seen = new HashSet<Vector3>(); private void Awake() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) _birthday = ((Component)this).GetComponent<EnemyBirthdayBoy>(); _self = ((Component)this).GetComponentInParent<EnemyParent>(); _health = ((Component)this).GetComponentInParent<EnemyHealth>() ?? ((Component)this).GetComponentInChildren<EnemyHealth>(); _enemy = ((Component)this).GetComponent<Enemy>() ?? ((Component)this).GetComponentInParent<Enemy>(); _selfPhys = ((Component)this).GetComponentInParent<PhysGrabObject>() ?? ((Component)this).GetComponentInChildren<PhysGrabObject>(true); if (SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null) { _health.health = Mathf.Max(1, Mathf.RoundToInt((float)_health.health * Plugin.MutationHealthMultiplier.Value)); } FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); } private void Update() { //IL_0030: 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) _glowTimer -= Time.deltaTime; if (_glowTimer <= 0f) { _glowTimer = 2f; FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); } _balloonTimer -= Time.deltaTime; if (_balloonTimer <= 0f) { _balloonTimer = 0.2f; SyncAndTintBalloons(); } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } EnsureHpDoubled(); if (_deathDetonated || (Object)(object)_birthday == (Object)null) { return; } HostBalloonContacts(); if (_explodeCooldown > 0f) { _explodeCooldown -= Time.deltaTime; } _proximityTimer -= Time.deltaTime; if (!_fuseLit && _explodeCooldown <= 0f && _proximityTimer <= 0f) { _proximityTimer = 0.25f; if (FusionShared.NearestPlayerWithin(((Component)this).transform.position, Plugin.BoomdayFuseRange.Value)) { _fuseLit = true; _fuseTimer = Plugin.BoomdayFuseTime.Value; } } if (_fuseLit) { _fuseTimer -= Time.deltaTime; if (_fuseTimer <= 0f) { ProximityExplode(); } } } private void EnsureHpDoubled() { if (!_hpDone && !((Object)(object)_health == (Object)null)) { _hpDone = true; FusionShared.SetHealthCurrent(_health, _health.health); } } private void SyncAndTintBalloons() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_birthday == (Object)null || _birthday.balloons == null) { return; } foreach (KeyValuePair<Vector3, GameObject> balloon in _birthday.balloons) { if (!((Object)(object)balloon.Value == (Object)null) && _seen.Add(balloon.Key)) { _orderedKeys.Add(balloon.Key); TintBalloon(balloon.Value); } } } private void HostBalloonContacts() { //IL_0049: 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_005a: 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_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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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) if ((Object)(object)_birthday == (Object)null || _birthday.balloons == null || _orderedKeys.Count == 0) { return; } float value = Plugin.BoomdayBalloonTouchRadius.Value; List<Vector3> list = null; foreach (Vector3 orderedKey in _orderedKeys) { if (!_birthday.balloons.TryGetValue(orderedKey, out var value2) || (Object)(object)value2 == (Object)null) { (list ?? (list = new List<Vector3>())).Add(orderedKey); continue; } Vector3 position = value2.transform.position; if (AnyPlayerWithin(position, value)) { ExplodeBalloon(value2, position); (list ?? (list = new List<Vector3>())).Add(orderedKey); } else if (AnyOtherEnemyWithin(position, value)) { PopBalloon(value2, position); (list ?? (list = new List<Vector3>())).Add(orderedKey); } } if (list == null) { return; } foreach (Vector3 item in list) { ForgetBalloon(item); } } private static bool AnyPlayerWithin(Vector3 pos, float radius) { //IL_001e: 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) foreach (PlayerAvatar item in FusionShared.AllPlayers()) { if (!((Object)(object)item == (Object)null) && Vector3.Distance(pos, ((Component)item).transform.position) <= radius) { return true; } } return false; } private bool AnyOtherEnemyWithin(Vector3 pos, float radius) { //IL_0046: 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) EnemyDirector instance = EnemyDirector.instance; if ((Object)(object)instance == (Object)null || instance.enemiesSpawned == null) { return false; } foreach (EnemyParent item in instance.enemiesSpawned) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)_self) && Vector3.Distance(pos, ((Component)item).transform.position) <= radius) { return true; } } return false; } private void ProximityExplode() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) FusionShared.ExplodeAuthoritative(((Component)this).transform.position, 1.3f, Plugin.BoomdayCoreDamage.Value, 0, _selfPhys, _enemy); AggroNearestPlayer(); StartBalloonChain(); _fuseLit = false; _explodeCooldown = Plugin.BoomdayExplodeCooldown.Value; } public void Detonate() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!_deathDetonated) { _deathDetonated = true; FusionShared.ExplodeAuthoritative(((Component)this).transform.position, 1.6f, Plugin.BoomdayCoreDamage.Value, 0, _selfPhys, _enemy); StartBalloonChain(); } } private void AggroNearestPlayer() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)_birthday == (Object)null)) { PlayerAvatar val = FusionShared.NearestPlayer(((Component)this).transform.position, Plugin.BoomdayFuseRange.Value * 3f); if (!((Object)(object)val == (Object)null)) { _birthday.playerTarget = val; _birthday.UpdateState((State)6); } } } catch { } } private void StartBalloonChain() { //IL_0032: 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_0050: 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 ((Object)(object)_birthday == (Object)null || _orderedKeys.Count == 0) { return; } List<GameObject> list = new List<GameObject>(); foreach (Vector3 orderedKey in _orderedKeys) { if (_birthday.balloons != null && _birthday.balloons.TryGetValue(orderedKey, out var value) && (Object)(object)value != (Object)null) { list.Add(value); _birthday.balloons.Remove(orderedKey); } } _orderedKeys.Clear(); _seen.Clear(); Plugin.Instance.StartBalloonChain(list, Plugin.BoomdayBalloonDamage.Value, ((Object)(object)_birthday != (Object)null) ? _birthday.balloonPopEffect : null); } private void ForgetBalloon(Vector3 key) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) _birthday?.balloons?.Remove(key); _orderedKeys.Remove(key); _seen.Remove(key); } private void ExplodeBalloon(GameObject balloon, Vector3 bp) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) FusionShared.ExplodeAuthoritative(bp, 0.7f, Plugin.BoomdayBalloonDamage.Value, 0); if ((Object)(object)_birthday != (Object)null && (Object)(object)_birthday.balloonPopEffect != (Object)null) { Object.Instantiate<GameObject>(_birthday.balloonPopEffect, bp, Quaternion.identity); } Object.Destroy((Object)(object)balloon); } private void PopBalloon(GameObject balloon, Vector3 bp) { //IL_002c: 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) if ((Object)(object)_birthday != (Object)null && (Object)(object)_birthday.balloonPopEffect != (Object)null) { Object.Instantiate<GameObject>(_birthday.balloonPopEffect, bp, Quaternion.identity); } Object.Destroy((Object)(object)balloon); } private void TintBalloon(GameObject balloon) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_003b: 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_0064: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = balloon.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { MaterialPropertyBlock val2 = new MaterialPropertyBlock(); val.GetPropertyBlock(val2); val2.SetColor("_Color", new Color(1f, 0.45f, 0f)); val2.SetColor("_EmissionColor", new Color(1f, 0.35f, 0f) * 1.5f); val.SetPropertyBlock(val2); } } } } public class PoltergeistFusion : MonoBehaviour { internal static readonly Color AuraColor = new Color(0.35f, 0.8f, 1f); private EnemyHealth? _health; private bool _hpDone; private float _throwCooldown; private float _playerFloatCooldown; private float _fieldTimer; private float _glowTimer; private GameObject? _fieldSphere; private void Awake() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) _health = ((Component)this).GetComponentInParent<EnemyHealth>() ?? ((Component)this).GetComponentInChildren<EnemyHealth>(); if (SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null) { _health.health = Mathf.Max(1, Mathf.RoundToInt((float)_health.health * Plugin.MutationHealthMultiplier.Value)); } FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); _throwCooldown = Plugin.PoltergeistThrowInterval.Value; _playerFloatCooldown = Plugin.PoltergeistPlayerFloatInterval.Value; } private void Update() { //IL_0030: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) _glowTimer -= Time.deltaTime; if (_glowTimer <= 0f) { _glowTimer = 2f; FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); } EnsureFieldSphere(); if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } EnsureHpDoubled(); _fieldTimer -= Time.deltaTime; if (_fieldTimer <= 0f) { _fieldTimer = 0.25f; foreach (PhysGrabObject item in FusionShared.PhysObjectsInRadius(((Component)this).transform.position, Plugin.PoltergeistRange.Value)) { if (!((Object)(object)item == (Object)null)) { try { item.OverrideZeroGravity(0.35f); item.OverrideDrag(1f, 0.35f); item.OverrideAngularDrag(1.5f, 0.35f); } catch { } } } } _playerFloatCooldown -= Time.deltaTime; if (_playerFloatCooldown <= 0f) { _playerFloatCooldown = Plugin.PoltergeistPlayerFloatInterval.Value; foreach (PlayerAvatar item2 in FusionShared.PlayersInRadius(((Component)this).transform.position, Plugin.PoltergeistRange.Value)) { if (!((Object)(object)item2 == (Object)null)) { try { item2.ForceImpulse(Vector3.up * Plugin.PoltergeistPlayerFloatForce.Value); } catch { } } } } _throwCooldown -= Time.deltaTime; if (_throwCooldown <= 0f) { _throwCooldown = Plugin.PoltergeistThrowInterval.Value; ThrowValuableAtPlayer(); } } private void EnsureHpDoubled() { if (!_hpDone && !((Object)(object)_health == (Object)null)) { _hpDone = true; FusionShared.SetHealthCurrent(_health, _health.health); } } private void EnsureFieldSphere() { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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) if ((Object)(object)_fieldSphere != (Object)null) { return; } try { EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>(); EnemyFloaterSphereEffect val = ((componentInParent != null) ? ((Component)componentInParent).GetComponentInChildren<EnemyFloaterSphereEffect>(true) : null) ?? ((Component)this).GetComponentInChildren<EnemyFloaterSphereEffect>(true); MeshRenderer val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<MeshRenderer>() : null); Material val3 = (((Object)(object)val2 != (Object)null) ? ((Renderer)val2).sharedMaterial : null); if (!((Object)(object)val3 == (Object)null)) { GameObject val4 = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)val4).name = "MatsuPoltergeistField"; Collider component = val4.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } MeshRenderer component2 = val4.GetComponent<MeshRenderer>(); ((Renderer)component2).sharedMaterial = val3; ((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component2).receiveShadows = false; val4.transform.SetParent(((Component)this).transform, false); val4.transform.localPosition = Vector3.zero; val4.transform.localScale = Vector3.one * (Plugin.PoltergeistRange.Value * 2f); _fieldSphere = val4; } } catch { _fieldSphere = null; } } private void ThrowValuableAtPlayer() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: 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_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_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_01c6: 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_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: 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_0099: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar val = FusionShared.NearestPlayer(((Component)this).transform.position, Plugin.PoltergeistRange.Value * 1.5f); if ((Object)(object)val == (Object)null) { return; } PhysGrabObject val2 = null; float num = float.MaxValue; foreach (PhysGrabObject item in FusionShared.PhysObjectsInRadius(((Component)this).transform.position, Plugin.PoltergeistRange.Value)) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item.rb == (Object)null) && !((Object)(object)((Component)item).GetComponentInParent<ValuableObject>() == (Object)null)) { float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)item).transform.position); if (num2 < num) { num = num2; val2 = item; } } } if ((Object)(object)val2 == (Object)null || (Object)(object)val2.rb == (Object)null) { return; } Rigidbody rb = val2.rb; EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>(); if ((Object)(object)componentInParent != (Object)null) { Collider[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<Collider>(true); Collider[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Collider>(true); Collider[] array = componentsInChildren; foreach (Collider val3 in array) { if ((Object)(object)val3 == (Object)null) { continue; } Collider[] array2 = componentsInChildren2; foreach (Collider val4 in array2) { if ((Object)(object)val4 != (Object)null) { try { Physics.IgnoreCollision(val3, val4, true); } catch { } } } } } try { val2.ResetMass(); } catch { } float num3 = Mathf.Min(20f * rb.mass, 100f); try { val2.ResetIndestructible(); } catch { } Vector3 val5 = ((Component)val).transform.position + Vector3.up * 1f; Vector3 val6 = Vector3.Lerp(((Component)this).transform.forward, val5 - val2.centerPoint, 0.5f); rb.AddForce(val6 * num3, (ForceMode)1); rb.AddTorque(((Component)val2).transform.right * 0.5f, (ForceMode)1); FusionShared.BoostThrownImpact(val2, 5f, 2f); } } public class CleanupCrewFusion : MonoBehaviour { internal static readonly Color AuraColor = new Color(0.4f, 1f, 0.15f); private static FieldInfo? _headStateField; private EnemyBombThrower _thrower; private EnemyHealth? _health; private bool _hpDone; private float _glowTimer; private int _prevHeadState = -1; private void Awake() { _thrower = ((Component)this).GetComponent<EnemyBombThrower>(); _health = ((Component)this).GetComponentInParent<EnemyHealth>() ?? ((Component)this).GetComponentInChildren<EnemyHealth>(); if (SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null) { _health.health = Mathf.Max(1, Mathf.RoundToInt((float)_health.health * Plugin.MutationHealthMultiplier.Value)); } ApplyGlow(); Plugin.GetMeltdownHeadPrefabRef(); } private void Update() { _glowTimer -= Time.deltaTime; if (_glowTimer <= 0f) { _glowTimer = 2f; ApplyGlow(); } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } EnsureHpDoubled(); if (!((Object)(object)_thrower == (Object)null) && !((Object)(object)_thrower.head == (Object)null)) { int num = ReadHeadState(_thrower.head); if (_prevHeadState != -1 && num == 1 && _prevHeadState != 1) { SpawnExtraHeads(); } _prevHeadState = num; } } private void SpawnExtraHeads() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Transform headSpawnTransform = _thrower.headSpawnTransform; if ((Object)(object)headSpawnTransform == (Object)null) { Plugin.Log.LogWarning((object)"[MeltdownCrew] headSpawnTransform is null; can't spawn extras."); return; } Plugin.Log.LogInfo((object)"[MeltdownCrew] body launched its head — spawning 2 extra heads."); Plugin.SpawnMeltdownHead(headSpawnTransform.position, headSpawnTransform.rotation, headSpawnTransform.forward, Plugin.MeltdownSlowSpeed.Value); Plugin.SpawnMeltdownHead(headSpawnTransform.position, headSpawnTransform.rotation, headSpawnTransform.forward, Plugin.MeltdownFastSpeed.Value); } private void EnsureHpDoubled() { if (!_hpDone && !((Object)(object)_health == (Object)null)) { _hpDone = true; FusionShared.SetHealthCurrent(_health, _health.health); } } private void ApplyGlow() { //IL_0006: 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) FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); if ((Object)(object)_thrower != (Object)null && (Object)(object)_thrower.head != (Object)null) { FusionShared.ApplyMutationGlow(((Component)_thrower.head).transform, AuraColor); } } private static int ReadHeadState(EnemyBombThrowerHead head) { try { if (_headStateField == null) { _headStateField = typeof(EnemyBombThrowerHead).GetField("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object obj = _headStateField?.GetValue(head); return (obj != null) ? Convert.ToInt32(obj) : (-1); } catch { return -1; } } } public class MeltdownExtraHead : MonoBehaviour { private PhotonView? _pv; private Rigidbody? _rb; private ParticleScriptExplosion? _explosion; private float _factor = 1f; private bool _launched; private bool _exploding; private float _flightTimer; private float _destroyTimer; private void Awake() { _pv = ((Component)this).GetComponent<PhotonView>(); _rb = ((Component)this).GetComponent<PhysGrabObject>()?.rb ?? ((Component)this).GetComponent<Rigidbody>(); _explosion = ((Component)this).GetComponent<ParticleScriptExplosion>(); Animator component = ((Component)this).GetComponent<Animator>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; } } public void Launch(float factor, Vector3 forward) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) _factor = factor; _flightTimer = Plugin.MeltdownHeadFlightSeconds.Value; _launched = true; if ((Object)(object)_rb != (Object)null) { _rb.isKinematic = false; Vector3 val = Vector3.Lerp(((Vector3)(ref forward)).normalized, Vector3.up, 0.3f); _rb.AddForce(val * 20f, (ForceMode)1); _rb.AddTorque(Vector3.right * 0.25f, (ForceMode)1); } } private void FixedUpdate() { //IL_0053: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0105: 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_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_011c: 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) //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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_00ab: 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_00cf: 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_01aa: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } if (_exploding) { _destroyTimer -= Time.fixedDeltaTime; if (_destroyTimer <= 0f) { DestroySelf(); } } else { if (!_launched || (Object)(object)_rb == (Object)null) { return; } PlayerAvatar val = FusionShared.NearestPlayer(_rb.position, 40f); if ((Object)(object)val != (Object)null) { Vector3 val2 = ((Component)val).transform.position - _rb.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f) { _rb.AddForce(((Vector3)(ref val2)).normalized * Plugin.MeltdownHomingForce.Value * Mathf.Max(0.5f, _factor), (ForceMode)0); } } float num = Plugin.MeltdownBaseSpeed.Value * _factor; Vector3 velocity = _rb.velocity; Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(velocity.x, 0f, velocity.z); if (((Vector3)(ref val3)).magnitude > num) { val3 = ((Vector3)(ref val3)).normalized * num; _rb.velocity = new Vector3(val3.x, velocity.y, val3.z); } _flightTimer -= Time.fixedDeltaTime; if (_flightTimer <= 0f) { _exploding = true; _destroyTimer = 0.3f; if (SemiFunc.IsMultiplayer() && (Object)(object)_pv != (Object)null) { _pv.RPC("ExplodeRPC", (RpcTarget)0, new object[1] { _rb.position }); } else { ExplodeRPC(_rb.position); } } } } [PunRPC] private void ExplodeRPC(Vector3 pos) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) try { ParticleScriptExplosion? explosion = _explosion; if (explosion != null) { explosion.Spawn(pos, 2f, Plugin.MeltdownHeadDamage.Value, 30, 4f, false, false, 1f); } } catch { } Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } } private void DestroySelf() { try { if (SemiFunc.IsMultiplayer() && (Object)(object)_pv != (Object)null && _pv.IsMine) { PhotonNetwork.Destroy(((Component)this).gameObject); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } catch { Object.Destroy((Object)(object)((Component)this).gameObject); } } } public class PlayerTeleportHelper : MonoBehaviour { private PhotonView? _pv; private PlayerAvatar? _avatar; private void Awake() { _pv = ((Component)this).GetComponent<PhotonView>(); _avatar = ((Component)this).GetComponent<PlayerAvatar>(); } public static void Trigger(PlayerAvatar player, Vector3 pos, int damage, int enemyIndex) { //IL_005a: 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) PlayerTeleportHelper component = ((Component)player).GetComponent<PlayerTeleportHelper>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component._pv == (Object)null)) { if (SemiFunc.IsMultiplayer()) { component._pv.RPC("TeleportAndHurtRPC", (RpcTarget)0, new object[3] { pos, damage, enemyIndex }); } else { component.TeleportAndHurtRPC(pos, damage, enemyIndex); } } } [PunRPC] private void TeleportAndHurtRPC(Vector3 pos, int damage, int enemyIndex) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_0030: 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_00de: 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_006a: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)_avatar == (Object)null) { return; } if (SemiFunc.IsMasterClientOrSingleplayer()) { PhysGrabObject playerPhysGrabObject = FusionShared.GetPlayerPhysGrabObject(_avatar); if ((Object)(object)playerPhysGrabObject != (Object)null) { playerPhysGrabObject.Teleport(pos, ((Component)_avatar).transform.rotation); if ((Object)(object)playerPhysGrabObject.rb != (Object)null) { playerPhysGrabObject.rb.velocity = Vector3.zero; playerPhysGrabObject.rb.angularVelocity = Vector3.zero; } } } ((Component)_avatar).transform.position = pos; FusionShared.SetPlayerClientPosition(_avatar, pos); if ((Object)(object)_avatar.playerAvatarVisuals != (Object)null) { ((Component)_avatar.playerAvatarVisuals).transform.position = pos; FusionShared.SetPlayerVisualPosition(_avatar.playerAvatarVisuals, pos); } if (SemiFunc.IsMasterClientOrSingleplayer()) { _avatar.playerHealth.HurtOther(damage, pos, false, enemyIndex, false); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Snatcher] teleport RPC error: {arg}"); } } } [HarmonyPatch(typeof(PlayerAvatar), "Start")] internal static class PlayerAvatar_Start_Patch { private static void Postfix(PlayerAvatar __instance) { try { if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<PlayerTeleportHelper>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<PlayerTeleportHelper>(); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Snatcher] PlayerAvatar_Start_Patch error: {arg}"); } } } public class SnatcherFusion : MonoBehaviour { internal static readonly Color AuraColor = new Color(0.6f, 0f, 0.85f); private static FieldInfo? _playerTargetField; private EnemyHidden _hidden; private EnemyParent? _self; private EnemyHealth? _health; private bool _hpDone; private float _glowTimer; private State _prevState; private bool _stateInitialized; private void Awake() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) _hidden = ((Component)this).GetComponent<EnemyHidden>(); _self = ((Component)this).GetComponentInParent<EnemyParent>(); _health = ((Component)this).GetComponentInParent<EnemyHealth>() ?? ((Component)this).GetComponentInChildren<EnemyHealth>(); if (SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null) { _health.health = Mathf.Max(1, Mathf.RoundToInt((float)_health.health * Plugin.MutationHealthMultiplier.Value)); } FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); } private void Update() { //IL_0030: 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_0062: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Invalid comparison between Unknown and I4 //IL_0114: 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_00b0: 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) _glowTimer -= Time.deltaTime; if (_glowTimer <= 0f) { _glowTimer = 2f; FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } EnsureHpDoubled(); if ((Object)(object)_hidden == (Object)null) { return; } State currentState = _hidden.currentState; if (!_stateInitialized) { _prevState = currentState; _stateInitialized = true; } else { if (currentState == _prevState) { return; } if ((int)currentState == 7) { PlayerAvatar playerTarget = GetPlayerTarget(_hidden); if ((Object)(object)playerTarget != (Object)null && !FusionShared.IsPlayerDisabled(playerTarget) && FusionShared.TryGetSafeRandomPoint(((Component)playerTarget).transform.position, out var point)) { int enemyIndex = (((Object)(object)_self != (Object)null && (Object)(object)EnemyDirector.instance != (Object)null) ? EnemyDirector.instance.enemiesSpawned.IndexOf(_self) : (-1)); PlayerTeleportHelper.Trigger(playerTarget, point, Plugin.SnatcherDamage.Value, enemyIndex); Plugin.Log.LogInfo((object)"[Snatcher] Snatched a player to a random spot."); } } _prevState = currentState; } } private void EnsureHpDoubled() { if (!_hpDone && !((Object)(object)_health == (Object)null)) { _hpDone = true; FusionShared.SetHealthCurrent(_health, _health.health); } } private static PlayerAvatar? GetPlayerTarget(EnemyHidden hidden) { try { if ((object)_playerTargetField == null) { _playerTargetField = typeof(EnemyHidden).GetField("playerTarget", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj = _playerTargetField?.GetValue(hidden); return (PlayerAvatar?)((obj is PlayerAvatar) ? obj : null); } catch { return null; } } } public class PeeperFusion : MonoBehaviour { internal static readonly Color AuraColor = new Color(1f, 0.1f, 0.1f); private static FieldInfo? _targetPlayerField; private EnemyCeilingEye _eye; private EnemyHealth? _health; private bool _hpDone; private float _glowTimer; private PlayerAvatar? _lastTarget; private float _stareTimer; private void Awake() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) _eye = ((Component)this).GetComponent<EnemyCeilingEye>(); _health = ((Component)this).GetComponentInParent<EnemyHealth>() ?? ((Component)this).GetComponentInChildren<EnemyHealth>(); if (SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)_health != (Object)null) { _health.health = Mathf.Max(1, Mathf.RoundToInt((float)_health.health * Plugin.MutationHealthMultiplier.Value)); } FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); } private void Update() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 _glowTimer -= Time.deltaTime; if (_glowTimer <= 0f) { _glowTimer = 2f; FusionShared.ApplyMutationGlow(((Component)this).transform, AuraColor); } EnsureHpDoubled(); if ((Object)(object)_eye == (Object)null) { return; } PlayerAvatar val = (((int)_eye.currentState == 3) ? GetTarget(_eye) : null); if ((Object)(object)val == (Object)null) { _lastTarget = null; _stareTimer = 0f; return; } if ((Object)(object)val != (Object)(object)_lastTarget) { _lastTarget = val; _stareTimer = 0f; } _stareTimer += Time.deltaTime; if (_stareTimer >= Plugin.DeathgazeStareSeconds.Value) { _stareTimer = 0f; FireBeam(val); } } private void EnsureHpDoubled() { if (!_hpDone && !((Object)(object)_health == (Object)null) && SemiFunc.IsMasterClientOrSingleplayer()) { _hpDone = true; FusionShared.SetHealthCurrent(_health, _health.health); } } private void FireBeam(PlayerAvatar target) { try { SemiLaser clownLaserPrefab = Plugin.GetClownLaserPrefab(); if ((Object)(object)clownLaserPrefab == (Object)null) { return; } Transform source = (((Object)(object)_eye.eyeTransform != (Object)null) ? _eye.eyeTransform : ((Component)this).transform); GameObject val = Object.Instantiate<GameObject>(((Component)clownLaserPrefab).gameObject); val.SetActive(true); SemiLaser component = val.GetComponent<SemiLaser>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return; } HurtCollider componentInChildren = val.GetComponentInChildren<HurtCollider>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.enemyHost = ((Component)_eye).GetComponent<Enemy>(); componentInChildren.playerKill = false; componentInChildren.playerDamage = Plugin.DeathgazeBeamDamage.Value; componentInChildren.playerDamageCooldown = Plugin.DeathgazeBeamSeconds.Value + 1f; } EnemyParent componentInParent = ((Component)_eye).GetComponentInParent<EnemyParent>(); Transform ignoreRoot = ((componentInParent != null) ? ((Component)componentInParent).transform : null) ?? ((Component)this).transform; val.AddComponent<PeeperBeam>().Init(component, source, target, Plugin.DeathgazeBeamSeconds.Value, ignoreRoot); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Deathgaze] fire error: {arg}"); } } private static PlayerAvatar? GetTarget(EnemyCeilingEye eye) { try { if ((object)_targetPlayerField == null) { _targetPlayerField = typeof(EnemyCeilingEye).GetField("targetPlayer", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj = _targetPlayerField?.GetValue(eye); return (PlayerAvatar?)((obj is PlayerAvatar) ? obj : null); } catch { return null; } } } public class PeeperBeam : MonoBehaviour { private static readonly int DefaultMask = LayerMask.GetMask(new string[1] { "Default" }); private SemiLaser _laser; private Transform _source; private PlayerAvatar? _target; private float _duration; private float _elapsed; private Transform? _ignoreRoot; public void Init(SemiLaser laser, Transform source, PlayerAvatar target, float duration, Transform? ignoreRoot) { _laser = laser; _source = source; _target = target; _duration = duration; _ignoreRoot = ignoreRoot; } private void LateUpdate() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_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_007c: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a0: 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_00a8: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0136: 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_011f: Unknown result type (might be due to invalid IL or missing references) _elapsed += Time.deltaTime; if ((Object)(object)_laser == (Object)null || (Object)(object)_source == (Object)null || (Object)(object)_target == (Object)null || _elapsed >= _duration) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Vector3 position = _source.position; Vector3 val = ((Component)_target).transform.position + Vector3.up * 1f; Vector3 val2 = val - position; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < 0.01f) { return; } val2 /= magnitude; Vector3 val3 = val; float num = magnitude; RaycastHit[] array = Physics.RaycastAll(position, val2, magnitude, DefaultMask, (QueryTriggerInteraction)1); for (int i = 0; i < array.Length; i++) { RaycastHit val4 = array[i]; if (!((Object)(object)((RaycastHit)(ref val4)).collider == (Object)null) && (!((Object)(object)_ignoreRoot != (Object)null) || !((Component)((RaycastHit)(ref val4)).collider).transform.IsChildOf(_ignoreRoot)) && ((RaycastHit)(ref val4)).distance < num) { num = ((RaycastHit)(ref val4)).distance; val3 = ((RaycastHit)(ref val4)).point; } } _laser.LaserActive(position, val3, true); } } [BepInPlugin("com.matsu.repomutations", "REPO Mutant Enemies", "0.8.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.matsu.repomutations"; public const string Name = "REPO Mutant Enemies"; public const string Version = "0.8.0"; public static ConfigEntry<float> MutationChancePerLevel; public static ConfigEntry<float> MutationMaxChance; public static ConfigEntry<float> MutationHealthMultiplier; public static ConfigEntry<float> MutationAuraRange; public static ConfigEntry<float> MutationAuraIntensity; public static ConfigEntry<float> BoomdayFuseRange; public static ConfigEntry<float> BoomdayFuseTime; public static ConfigEntry<float> BoomdayExplodeCooldown; public static ConfigEntry<int> BoomdayCoreDamage; public static ConfigEntry<int> BoomdayBalloonDamage; public static ConfigEntry<float> BoomdayBalloonTouchRadius; public static ConfigEntry<float> PoltergeistRange; public static ConfigEntry<float> PoltergeistPlayerFloatInterval; public static ConfigEntry<float> PoltergeistPlayerFloatForce; public static ConfigEntry<float> PoltergeistThrowInterval; public static ConfigEntry<float> MeltdownSlowSpeed; public static ConfigEntry<float> MeltdownFastSpeed; public static ConfigEntry<float> MeltdownBaseSpeed; public static ConfigEntry<float> MeltdownHomingForce; public static ConfigEntry<float> MeltdownHeadFlightSeconds; public static ConfigEntry<int> MeltdownHeadDamage; public static ConfigEntry<int> SnatcherDamage; public static ConfigEntry<float> DeathgazeStareSeconds; public static ConfigEntry<float> DeathgazeBeamSeconds; public static ConfigEntry<int> DeathgazeBeamDamage; public static ConfigEntry<KeyCode> DebugSpawnBoomdayKey; public static ConfigEntry<KeyCode> DebugSpawnPoltergeistKey; public static ConfigEntry<KeyCode> DebugSpawnMeltdownKey; public static ConfigEntry<KeyCode> DebugSpawnSnatcherKey; public static ConfigEntry<KeyCode> DebugSpawnDeathgazeKey; internal static float ForceFuseUntil; private Harmony _harmony; private static SemiLaser? _clownLaserPrefab; private static bool _clownLaserSearched; private const string MeltdownHeadPrefabId = "Matsu/MeltdownExtraHead"; private static PrefabRef? _meltdownHeadRef; private static bool _meltdownHeadBuilt; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; MutationChancePerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "ChancePerLevel", 0.01f, "Base mutation chance per level (per mutation type). Chance = level x this + pity, where pity grows by (level x this) for every level that type failed to mutate, and resets to 0 once it does."); MutationMaxChance = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "MaxChance", 1f, "Upper cap (0..1) for the level-scaled + pity mutation chance."); MutationHealthMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "HealthMultiplier", 2f, "Health multiplier applied to every mutated enemy."); MutationAuraRange = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "AuraLightRange", 4f, "Range of the coloured aura light attached to every mutated enemy (works even on invisible enemies)."); MutationAuraIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "AuraLightIntensity", 3f, "Brightness of the coloured aura light."); BoomdayFuseRange = ((BaseUnityPlugin)this).Config.Bind<float>("BoomdayBoy", "FuseRange", 4f, "Player distance that lights the fuse."); BoomdayFuseTime = ((BaseUnityPlugin)this).Config.Bind<float>("BoomdayBoy", "FuseTime", 2.5f, "Seconds from fuse lit to an explosion."); BoomdayExplodeCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("BoomdayBoy", "ExplodeCooldown", 4f, "Seconds before a Boomday Boy can explode again. It survives its own blasts (recurring threat)."); BoomdayCoreDamage = ((BaseUnityPlugin)this).Config.Bind<int>("BoomdayBoy", "CoreDamage", 40, "Explosion damage (proximity & death blasts). Uses the game's real explosion."); BoomdayBalloonDamage = ((BaseUnityPlugin)this).Config.Bind<int>("BoomdayBoy", "BalloonDamage", 20, "Per-balloon explosion damage. Uses the game's real explosion."); BoomdayBalloonTouchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("BoomdayBoy", "BalloonTouchRadius", 1.3f, "A balloon explodes when a player comes this close to it (enemies only pop it, no explosion)."); PoltergeistRange = ((BaseUnityPlugin)this).Config.Bind<float>("Poltergeist", "Range", 7.2f, "Radius of the zero-G field and telekinetic reach."); PoltergeistPlayerFloatInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Poltergeist", "PlayerFloatInterval", 1.4f, "Seconds between the light upward nudges that keep players unsteady in the field."); PoltergeistPlayerFloatForce = ((BaseUnityPlugin)this).Config.Bind<float>("Poltergeist", "PlayerFloatForce", 6f, "Strength of the periodic upward nudge on players inside the field."); PoltergeistThrowInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Poltergeist", "ThrowInterval", 2.2f, "Seconds between telekinetic throws. The thrown valuable's own physics impact deals damage (like the Rugrat)."); MeltdownSlowSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("MeltdownCrew", "SlowHeadSpeed", 0.5f, "Speed factor of the sluggish 2nd head in the volley (1 = normal Cleanup Crew head speed)."); MeltdownFastSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("MeltdownCrew", "FastHeadSpeed", 2f, "Speed factor of the frantic 3rd head in the volley (1 = normal Cleanup Crew head speed)."); MeltdownBaseSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("MeltdownCrew", "BaseHeadSpeed", 4f, "Reference horizontal head speed (m/s) that the slow/fast factors scale. The head's speed is capped at this x factor."); MeltdownHomingForce = ((BaseUnityPlugin)this).Config.Bind<float>("MeltdownCrew", "FastHeadHomingForce", 12f, "Extra homing force applied to the fast head per (factor-1) so it actually reaches its higher speed and tracks the player."); MeltdownHeadFlightSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("MeltdownCrew", "HeadFlightSeconds", 7f, "How long each of the two EXTRA heads chases before it detonates. Set to roughly match the vanilla head's own fuse (~7s) so all three explode together — only their movement SPEED differs (0.5x / 2x)."); MeltdownHeadDamage = ((BaseUnityPlugin)this).Config.Bind<int>("MeltdownCrew", "ExtraHeadDamage", 75, "Explosion damage of each extra head (matches the vanilla Cleanup Crew head by default)."); SnatcherDamage = ((BaseUnityPlugin)this).Config.Bind<int>("Snatcher", "Damage", 20, "Damage dealt the instant a Snatcher (mutated Hidden) whisks you away."); DeathgazeStareSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Deathgaze", "StareSeconds", 7.5f, "Seconds a Deathgaze (mutated Peeper) must hold a player in its stare before it fires a beam."); DeathgazeBeamSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Deathgaze", "BeamSeconds", 2f, "How long each fired beam lasts."); DeathgazeBeamDamage = ((BaseUnityPlugin)this).Config.Bind<int>("Deathgaze", "BeamDamage", 35, "Damage the beam deals (at most once per beam)."); DebugSpawnBoomdayKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Debug", "SpawnBoomdayKey", (KeyCode)290, "Press (host only) to spawn a Boomday Boy in front of your camera."); DebugSpawnPoltergeistKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Debug", "SpawnPoltergeistKey", (KeyCode)291, "Press (host only) to spawn a Poltergeist (mutated Mentalist) in front of your camera."); DebugSpawnMeltdownKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Debug", "SpawnMeltdownKey", (KeyCode)289, "Press (host only) to spawn a Meltdown Crew (mutated Cleanup Crew) in front of your camera."); DebugSpawnSnatcherKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Debug", "SpawnSnatcherKey", (KeyCode)288, "Press (host only) to spawn a Snatcher (mutated Hidden) in front of your camera."); DebugSpawnDeathgazeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Debug", "SpawnDeathgazeKey", (KeyCode)287, "Press (host only) to spawn a Deathgaze (mutated Peeper) in front of your camera."); _harmony = new Harmony("com.matsu.repomutations"); _harmony.PatchAll(); Log.LogInfo((object)string.Format("{0} {1} loaded. Mutation chance = level x {2:P0} + pity. Debug: Boomday Boy (F9), Poltergeist (F10), Meltdown Crew (F8), Snatcher (F7), Deathgaze (F6). Everyone in the lobby must install this mod.", "REPO Mutant Enemies", "0.8.0", MutationChancePerLevel.Value)); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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) if (Input.GetKeyDown(DebugSpawnBoomdayKey.Value)) { DebugSpawn("Birthday", typeof(EnemyBirthdayBoy), "Boomday Boy"); } if (Input.GetKeyDown(DebugSpawnPoltergeistKey.Value)) { DebugSpawn("Floater", typeof(EnemyFloater), "Poltergeist"); } if (Input.GetKeyDown(DebugSpawnMeltdownKey.Value)) { DebugSpawn("Bomb", typeof(EnemyBombThrower), "Meltdown Crew"); } if (Input.GetKeyDown(DebugSpawnSnatcherKey.Value)) { DebugSpawn("Hidden", typeof(EnemyHidden), "Snatcher"); } if (Input.GetKeyDown(DebugSpawnDeathgazeKey.Value)) { DebugSpawn("Peeper", typeof(EnemyCeilingEye), "Deathgaze"); } } private static void DebugSpawn(string nameContains, Type componentType, string label) { //IL_0044: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_00a3: 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) try { if (!SemiFunc.IsMasterClientOrSingleplayer()) { Log.LogWarning((object)"[Debug] Spawn is host-only."); return; } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { Log.LogWarning((object)"[Debug] No main camera; are you in a level?"); return; } Vector3 val = ((Component)main).transform.position + ((Component)main).transform.forward * 3f; EnemySetup val2 = FindEnemySetup(nameContains, componentType); if ((Object)(object)val2 == (Object)null) { Log.LogWarning((object)("[Debug] " + label + " base enemy setup not found.")); return; } ForceFuseUntil = Time.time + 5f; Enemies.SpawnEnemy(val2, val, Quaternion.identity, false); Log.LogInfo((object)$"[Debug] Spawned a {label} at {val}."); } catch (Exception arg) { Log.LogError((object)$"[Debug] spawn error: {arg}"); } } private static EnemySetup? FindEnemySetup(string nameContains, Type componentType) { foreach (EnemySetup allEnemy in Enemies.AllEnemies) { if ((Object)(object)allEnemy != (Object)null && ((Object)allEnemy).name.IndexOf(nameContains, StringComparison.OrdinalIgnoreCase) >= 0) { return allEnemy; } } foreach (EnemySetup allEnemy2 in Enemies.AllEnemies) { if (allEnemy2?.spawnObjects == null) { continue; } foreach (PrefabRef spawnObject in allEnemy2.spawnObjects) { GameObject val = ((PrefabRef<GameObject>)(object)spawnObject)?.Prefab; if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponentInChildren(componentType, true) != (Object)null) { return allEnemy2; } } } return null; } public static SemiLaser? GetClownLaserPrefab() { if (_clownLaserSearched) { return _clownLaserPrefab; } _clownLaserSearched = true; try { EnemySetup val = FindEnemySetup("Beamer", typeof(EnemyBeamer)); if (val?.spawnObjects != null) { foreach (PrefabRef spawnObject in val.spawnObjects) { GameObject val2 = ((PrefabRef<GameObject>)(object)spawnObject)?.Prefab; EnemyBeamer val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponentInChildren<EnemyBeamer>(true) : null); if ((Object)(object)val3 != (Object)null && (Object)(object)val3.laser != (Object)null) { _clownLaserPrefab = val3.laser; break; } } } if ((Object)(object)_clownLaserPrefab == (Object)null) { Log.LogWarning((object)"[Deathgaze] Could not find the Clown/Beamer laser prefab; beams disabled."); } } catch (Exception arg) { Log.LogError((object)$"[Deathgaze] laser prefab lookup error: {arg}"); } return _clownLaserPrefab; } public static PrefabRef? GetMeltdownHeadPrefabRef() { if (_meltdownHeadBuilt) { return _meltdownHeadRef; } PrefabRef meltdownHeadRef = default(PrefabRef); if (NetworkPrefabs.TryGetNetworkPrefabRef("Matsu/MeltdownExtraHead", ref meltdownHeadRef)) { _meltdownHeadBuilt = true; _meltdownHeadRef = meltdownHeadRef; return _meltdownHeadRef; } _meltdownHeadBuilt = true; try { EnemySetup val = FindEnemySetup("Bomb", typeof(EnemyBombThrower)); GameObject val2 = null; if (val?.spawnObjects != null) { foreach (PrefabRef spawnObject in val.spawnObjects) { GameObject val3 = ((PrefabRef<GameObject>)(object)spawnObject)?.Prefab; EnemyBombThrower val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponentInChildren<EnemyBombThrower>(true) : null); if ((Object)(object)val4 != (Object)null && (Object)(object)val4.head != (Object)null) { val2 = ((Component)val4.head).gameObject; break; } } } if ((Object)(object)val2 == (Object)null) { Log.LogWarning((object)"[MeltdownCrew] head prefab not found; extra heads disabled."); return null; } GameObject val5 = Object.Instantiate<GameObject>(val2); ((Object)val5).name = "MatsuMeltdownExtraHead"; Object.DontDestroyOnLoad((Object)(object)val5); val5.SetActive(false); EnemyBombThrowerHead component = val5.GetComponent<EnemyBombThrowerHead>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } val5.AddComponent<MeltdownExtraHead>(); _meltdownHeadRef = NetworkPrefabs.RegisterNetworkPrefab("Matsu/MeltdownExtraHead", val5); if (_meltdownHeadRef == null) { Log.LogWarning((object)"[MeltdownCrew] RegisterNetworkPrefab returned null; extra heads disabled."); } else { Log.LogInfo((object)"[MeltdownCrew] Registered the extra-head network prefab."); } } catch (Exception arg) { Log.LogError((object)$"[MeltdownCrew] head prefab build error: {arg}"); } return _meltdownHeadRef; } public static void SpawnMeltdownHead(Vector3 pos, Quaternion rot, Vector3 forward, float factor) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_008d: Unknown result type (might be due to invalid IL or missing references) try { PrefabRef meltdownHeadPrefabRef = GetMeltdownHeadPrefabRef(); if (meltdownHeadPrefabRef == null) { Log.LogWarning((object)"[MeltdownCrew] no head prefab ref; skipping spawn."); return; } GameObject val = NetworkPrefabs.SpawnNetworkPrefab(meltdownHeadPrefabRef, pos, rot, (byte)0, (object[])null); if ((Object)(object)val == (Object)null) { Log.LogWarning((object)"[MeltdownCrew] SpawnNetworkPrefab returned null."); return; } val.SetActive(true); MeltdownExtraHead component = val.GetComponent<MeltdownExtraHead>(); if ((Object)(object)component == (Object)null) { Log.LogWarning((object)"[MeltdownCrew] spawned head has no driver component."); return; } component.Launch(factor, forward); Log.LogInfo((object)$"[MeltdownCrew] spawned extra head (factor {factor}, active={val.activeSelf}) at {pos}."); } catch (Exception arg) { Log.LogError((object)$"[MeltdownCrew] spawn head error: {arg}"); } } public void StartBalloonChain(List<GameObject> balloons, int damage, GameObject? popEffect) { if (balloons != null && balloons.Count != 0 && SemiFunc.IsMasterClientOrSingleplayer()) { ((MonoBehaviour)this).StartCoroutine(BalloonChainRoutine(balloons, damage, popEffect)); } } private IEnumerator BalloonChainRoutine(List<GameObject> balloons, int damage, GameObject? popEffect) { foreach (GameObject balloon in balloons) { if ((Object)(object)balloon != (Object)null) { Vector3 position = balloon.transform.position; FusionShared.ExplodeAuthoritative(position, 0.7f, damage, 0); if ((Object)(object)popEffect != (Object)null) { Object.Instantiate<GameObject>(popEffect, position, Quaternion.identity); } Object.Destroy((Object)(object)balloon); } yield return (object)new WaitForSeconds(0.1f); } } } [HarmonyPatch(typeof(EnemyParent), "Spawn")] internal static class EnemyParent_Spawn_Patch { private static void Postfix(EnemyParent __instance) { MutationAttach.TryAttach(__instance); } } [HarmonyPatch(typeof(EnemyParent), "SpawnRPC")] internal static class EnemyParent_SpawnRPC_Patch { private static void Postfix(EnemyParent __instance) { MutationAttach.TryAttach(__instance); } } internal static class MutationAttach { private static float _boomdayPity; private static float _poltergeistPity; private static float _cleanupPity; private static float _snatcherPity; private static float _deathgazePity; private static int _boomdayPityLevel = -1; private static int _poltergeistPityLevel = -1; private static int _cleanupPityLevel = -1; private static int _snatcherPityLevel = -1; private static int _deathgazePityLevel = -1; private static bool _boomdayMutatedThisLevel; private static bool _poltergeistMutatedThisLevel; private static bool _cleanupMutatedThisLevel; private static bool _snatcherMutatedThisLevel; private static bool _deathgazeMutatedThisLevel; private static readonly Dictionary<int, bool> _boomdayMutatedIds = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> _poltergeistMutatedIds = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> _cleanupMutatedIds = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> _snatcherMutatedIds = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> _deathgazeMutatedIds = new Dictionary<int, bool>(); public static void TryAttach(EnemyParent __instance) { try { if ((Object)(object)__instance == (Object)null) { return; } bool flag = Time.time <= Plugin.ForceFuseUntil; int key = EnemyId(__instance); EnemyBirthdayBoy componentInChildren = ((Component)__instance).GetComponentInChildren<EnemyBirthdayBoy>(); if ((Object)(object)componentInChildren != (Object)null) { float chance = (flag ? 1f : GetMutationChance(ref _boomdayPity, ref _boomdayPityLevel, ref _boomdayMutatedThisLevel, _boomdayMutatedIds)); bool value; bool flag2 = _boomdayMutatedIds.TryGetValue(key, out value) && value; if ((Object)(object)((Component)componentInChildren).GetComponent<BoomdayBoyFusion>() == (Object)null && (flag2 || ShouldMutate(__instance, chance))) { ((Component)componentInChildren).gameObject.AddComponent<BoomdayBoyFusion>(); _boomdayMutatedThisLevel = true; _boomdayPity = 0f; _boomdayMutatedIds[key] = true; Plugin.Log.LogInfo((object)"[BoomdayBoy] A Birthday Boy became a Boomday Boy."); } return; } EnemyFloater componentInChildren2 = ((Component)__instance).GetComponentInChildren<EnemyFloater>(); if ((Object)(object)componentInChildren2 != (Object)null) { float chance2 = (flag ? 1f : GetMutationChance(ref _poltergeistPity, ref _poltergeistPityLevel, ref _poltergeistMutatedThisLevel, _poltergeistMutatedIds)); bool value2; bool flag3 = _poltergeistMutatedIds.TryGetValue(key, out value2) && value2; if ((Object)(object)((Component)componentInChildren2).GetComponent<PoltergeistFusion>() == (Object)null && (flag3 || ShouldMutate(__instance, chance2))) { ((Component)componentInChildren2).gameObject.AddComponent<PoltergeistFusion>(); _poltergeistMutatedThisLevel = true; _poltergeistPity = 0f; _poltergeistMutatedIds[key] = true; Plugin.Log.LogInfo((object)"[Poltergeist] A Mentalist mutated into a Poltergeist."); } return; } EnemyBombThrower componentInChildren3 = ((Component)__instance).GetComponentInChildren<EnemyBombThrower>(); if ((Object)(object)componentInChildren3 != (Object)null) { float chance3 = (flag ? 1f : GetMutationChance(ref _cleanupPity, ref _cleanupPityLevel, ref _cleanupMutatedThisLevel, _cleanupMutatedIds)); bool value3; bool flag4 = _cleanupMutatedIds.TryGetValue(key, out value3) && value3; if ((Object)(object)((Component)componentInChildren3).GetComponent<CleanupCrewFusion>() == (Object)null && (flag4 || ShouldMutate(__instance, chance3))) { ((Component)componentInChildren3).gameObject.AddComponent<CleanupCrewFusion>(); _cleanupMutatedThisLevel = true; _cleanupPity = 0f; _cleanupMutatedIds[key] = true; Plugin.Log.LogInfo((object)"[MeltdownCrew] A Cleanup Crew mutated into a Meltdown Crew."); } return; } EnemyHidden componentInChildren4 = ((Component)__instance).GetComponentInChildren<EnemyHidden>(); if ((Object)(object)componentInChildren4 != (Object)null) { float chance4 = (flag ? 1f : GetMutationChance(ref _snatcherPity, ref _snatcherPityLevel, ref _snatcherMutatedThisLevel, _snatcherMutatedIds)); bool value4; bool flag5 = _snatcherMutatedIds.TryGetValue(key, out value4) && value4; if ((Object)(object)((Component)componentInChildren4).GetComponent<SnatcherFusion>() == (Object)null && (flag5 || ShouldMutate(__instance, chance4))) { ((Component)componentInChildren4).gameObject.AddComponent<SnatcherFusion>(); _snatcherMutatedThisLevel = true; _snatcherPity = 0f; _snatcherMutatedIds[key] = true; Plugin.Log.LogInfo((object)"[Snatcher] A Hidden mutated into a Snatcher."); } return; } EnemyCeilingEye componentInChildren5 = ((Component)__instance).GetComponentInChildren<EnemyCeilingEye>(); if ((Object)(object)componentInChildren5 != (Object)null) { float chance5 = (flag ? 1f : GetMutationChance(ref _deathgazePity, ref _deathgazePityLevel, ref _deathgazeMutatedThisLevel, _deathgazeMutatedIds)); bool value5; bool flag6 = _deathgazeMutatedIds.TryGetValue(key, out value5) && value5; if ((Object)(object)((Component)componentInChildren5).GetComponent<PeeperFusion>() == (Object)null && (flag6 || ShouldMutate(__instance, chance5))) { ((Component)componentInChildren5).gameObject.AddComponent<PeeperFusion>(); _deathgazeMutatedThisLevel = true; _deathgazePity = 0f; _deathgazeMutatedIds[key] = true; Plugin.Log.LogInfo((object)"[Deathgaze] A Peeper mutated into a Deathgaze."); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Mutation] attach error: {arg}"); } } private static float GetMutationChance(ref float pity, ref int lastLevel, ref bool mutatedThisLevel, Dictionary<int, bool> mutatedIds) { RunManager instance = RunManager.instance; if ((Object)(object)instance == (Object)null) { return 0f; } int num = instance.levelsCompleted + 1; if (lastLevel == -1) { lastLevel = num; } else if (num != lastLevel) { if (mutatedThisLevel) { pity = 0f; } else { pity += (float)lastLevel * Plugin.MutationChancePerLevel.Value; } mutatedThisLevel = false; lastLevel = num; mutatedIds.Clear(); } return Mathf.Clamp((float)num * Plugin.MutationChancePerLevel.Value + pity, 0f, Plugin.MutationMaxChance.Value); } private static int EnemyId(EnemyParent instance) { PhotonView photonView = ((MonoBehaviourPun)instance).photonView; if (!((Object)(object)photonView != (Object)null)) { return ((Object)instance).GetInstanceID(); } return photonView.ViewID; } private static bool ShouldMutate(EnemyParent instance, float chance) { if (chance <= 0f) { return false; } if (chance >= 1f) { return true; } PhotonView photonView = ((MonoBehaviourPun)instance).photonView; if ((Object)(object)photonView == (Object)null) { return Random.value <= chance; } int num = photonView.ViewID * -1640531535; int num2 = (num ^ (num >>> 13)) * -1640531535; return (float)(uint)((num2 ^ (num2 >>> 16)) & 0xFFFFFF) / 16777216f < chance; } } [HarmonyPatch(typeof(EnemyBirthdayBoy), "OnDeath")] internal static class EnemyBirthdayBoy_OnDeath_Patch { private static void Postfix(EnemyBirthdayBoy __instance) { try { if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)(object)__instance == (Object)null)) { BoomdayBoyFusion component = ((Component)__instance).GetComponent<BoomdayBoyFusion>(); if ((Object)(object)component != (Object)null) { component.Detonate(); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"[BoomdayBoy] OnDeath patch error: {arg}"); } } } }