Decompiled source of ShrinkingZone v1.0.3

ShrinkingZoneMod.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using ExitGames.Client.Photon;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnboundLib;
using UnboundLib.GameModes;
using UnboundLib.Networking;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShrinkingZoneMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ShrinkingZoneMod")]
[assembly: AssemblyTitle("ShrinkingZoneMod")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ShrinkingZoneMod
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("yourname.rounds.shrinkingzone", "Shrinking Zone", "1.0.1")]
	public class ShrinkingZonePlugin : BaseUnityPlugin
	{
		public const string ModId = "yourname.rounds.shrinkingzone";

		public const string ModName = "Shrinking Zone";

		public const string Version = "1.0.1";

		public static float StartRadius = 50f;

		public static float FinalRadius = 8f;

		public static float ShrinkStartDelay = 5f;

		public static float ShrinkDuration = 25f;

		public static float DamagePercentPerSecond = 0.1f;

		public static float DamageTickInterval = 0.5f;

		public static float DamageGracePeriod = 10f;

		private void Awake()
		{
			GameModeManager.AddHook("PointStart", (Func<IGameModeHandler, IEnumerator>)OnRoundStart);
			GameModeManager.AddHook("PointEnd", (Func<IGameModeHandler, IEnumerator>)OnRoundEnd);
		}

		private IEnumerator OnRoundStart(IGameModeHandler gm)
		{
			if ((Object)(object)PlayerManager.instance != (Object)null)
			{
				foreach (Player p in PlayerManager.instance.players)
				{
					if ((Object)(object)p != (Object)null)
					{
						Debug.LogWarning($"[ShrinkingZoneMod] Player at spawn: {((Component)p).transform.position}");
					}
				}
			}
			ZoneController.SpawnZone(Vector2.zero, StartRadius, FinalRadius, ShrinkStartDelay, ShrinkDuration, DamagePercentPerSecond, DamageTickInterval, DamageGracePeriod);
			yield break;
		}

		private IEnumerator OnRoundEnd(IGameModeHandler gm)
		{
			ZoneController.DespawnZone();
			yield break;
		}
	}
	public class ZoneController : MonoBehaviour
	{
		private static ZoneController _active;

		public Vector2 Center;

		public float StartRadius;

		public float FinalRadius;

		public float ShrinkDelay;

		public float ShrinkDuration;

		public float DamagePercentPerSecond;

		public float TickInterval;

		public float DamageGracePeriod;

		private float _currentRadius;

		private float _timer;

		private LineRenderer _ring;

		private readonly Dictionary<Player, float> _tickTimers = new Dictionary<Player, float>();

		private const float SyncInterval = 0.2f;

		private float _syncTimer;

		private const string ShrinkSoundFileName = "ring_collapse.wav";

		private const string DamageTickSoundFileName = "damage_tick.wav";

		private static AudioClip _shrinkSoundClip;

		private static AudioClip _damageTickSoundClip;

		private static bool _shrinkSoundLoadAttempted;

		private static bool _damageTickSoundLoadAttempted;

		private AudioSource _audioSource;

		private AudioSource _tickAudioSource;

		public static void SpawnZone(Vector2 center, float startRadius, float finalRadius, float shrinkDelay, float shrinkDuration, float damagePercentPerSecond, float tickInterval, float damageGracePeriod = 0f)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_001a: 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)
			DespawnZone();
			GameObject val = new GameObject("ShrinkingZone");
			ZoneController zoneController = val.AddComponent<ZoneController>();
			zoneController.Center = center;
			zoneController.StartRadius = startRadius;
			zoneController.FinalRadius = finalRadius;
			zoneController.ShrinkDelay = shrinkDelay;
			zoneController.ShrinkDuration = shrinkDuration;
			zoneController.DamagePercentPerSecond = damagePercentPerSecond;
			zoneController.TickInterval = tickInterval;
			zoneController.DamageGracePeriod = damageGracePeriod;
			_active = zoneController;
		}

		public static void DespawnZone()
		{
			if ((Object)(object)_active != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_active).gameObject);
				_active = null;
			}
		}

		private void Awake()
		{
			_currentRadius = StartRadius;
			_timer = 0f;
			_syncTimer = 0f;
			SetupRingVisual();
			SetupAudio();
		}

		private void SetupAudio()
		{
			_audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			_audioSource.loop = true;
			_audioSource.playOnAwake = false;
			_audioSource.spatialBlend = 0f;
			_tickAudioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			_tickAudioSource.loop = false;
			_tickAudioSource.playOnAwake = false;
			_tickAudioSource.spatialBlend = 0f;
			if ((Object)(object)_shrinkSoundClip == (Object)null && !_shrinkSoundLoadAttempted)
			{
				_shrinkSoundLoadAttempted = true;
				((MonoBehaviour)this).StartCoroutine(LoadAudioClip("ring_collapse.wav", delegate(AudioClip clip)
				{
					_shrinkSoundClip = clip;
				}));
			}
			if ((Object)(object)_damageTickSoundClip == (Object)null && !_damageTickSoundLoadAttempted)
			{
				_damageTickSoundLoadAttempted = true;
				((MonoBehaviour)this).StartCoroutine(LoadAudioClip("damage_tick.wav", delegate(AudioClip clip)
				{
					_damageTickSoundClip = clip;
				}));
			}
		}

		private IEnumerator LoadAudioClip(string fileName, Action<AudioClip> onLoaded)
		{
			string pluginDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string filePath = Path.Combine(pluginDir ?? "", fileName);
			if (!File.Exists(filePath))
			{
				Debug.LogWarning("[ShrinkingZoneMod] Sound file not found at: " + filePath + " -- this sound will be silent. Make sure " + fileName + " is placed next to ShrinkingZoneMod.dll.");
				yield break;
			}
			AudioType audioType = GetAudioTypeFromExtension(filePath);
			string uri = "file://" + filePath.Replace("\\", "/");
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(uri, audioType);
			try
			{
				yield return req.SendWebRequest();
				if (req.isNetworkError || req.isHttpError)
				{
					Debug.LogWarning("[ShrinkingZoneMod] Failed to load sound file " + fileName + ": " + req.error);
					yield break;
				}
				onLoaded(DownloadHandlerAudioClip.GetContent(req));
				Debug.LogWarning("[ShrinkingZoneMod] Loaded sound: " + fileName);
			}
			finally
			{
				((IDisposable)req)?.Dispose();
			}
		}

		private static AudioType GetAudioTypeFromExtension(string path)
		{
			//IL_003c: 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_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)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			return (AudioType)(Path.GetExtension(path).ToLowerInvariant() switch
			{
				".wav" => 20, 
				".ogg" => 14, 
				".mp3" => 13, 
				_ => 0, 
			});
		}

		private void SetupRingVisual()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			_ring = ((Component)this).gameObject.AddComponent<LineRenderer>();
			_ring.loop = true;
			_ring.positionCount = 64;
			_ring.widthMultiplier = 0.6f;
			_ring.useWorldSpace = true;
			((Renderer)_ring).material = new Material(Shader.Find("Sprites/Default"));
			_ring.startColor = new Color(1f, 0.2f, 0.2f, 0.8f);
			_ring.endColor = new Color(1f, 0.2f, 0.2f, 0.8f);
			DrawRing();
		}

		private void DrawRing()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			for (int i = 0; i < _ring.positionCount; i++)
			{
				float num = (float)i / (float)_ring.positionCount * MathF.PI * 2f;
				((Vector3)(ref val))..ctor(Center.x + Mathf.Cos(num) * _currentRadius, Center.y + Mathf.Sin(num) * _currentRadius, 0f);
				_ring.SetPosition(i, val);
			}
		}

		private void UpdateShrinkSound()
		{
			if ((Object)(object)_audioSource == (Object)null || (Object)(object)_shrinkSoundClip == (Object)null)
			{
				return;
			}
			if (_timer >= ShrinkDelay && _timer < ShrinkDelay + ShrinkDuration)
			{
				if ((Object)(object)_audioSource.clip != (Object)(object)_shrinkSoundClip)
				{
					_audioSource.clip = _shrinkSoundClip;
				}
				if (!_audioSource.isPlaying)
				{
					_audioSource.Play();
				}
			}
			else if (_audioSource.isPlaying)
			{
				_audioSource.Stop();
			}
		}

		private void Update()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.IsMasterClient)
			{
				_timer += Time.deltaTime;
				if (_timer >= ShrinkDelay)
				{
					float num = Mathf.Clamp01((_timer - ShrinkDelay) / ShrinkDuration);
					_currentRadius = Mathf.Lerp(StartRadius, FinalRadius, num);
				}
				_syncTimer += Time.deltaTime;
				if (_syncTimer >= 0.2f)
				{
					_syncTimer = 0f;
					NetworkingManager.RPC(typeof(ZoneController), "RPCA_SyncZoneState", RaiseEventOptions.Default, SendOptions.SendReliable, new object[4] { Center.x, Center.y, _currentRadius, _timer });
				}
			}
			DrawRing();
			UpdateShrinkSound();
			if ((Object)(object)PlayerManager.instance == (Object)null || _timer < DamageGracePeriod)
			{
				return;
			}
			foreach (Player player in PlayerManager.instance.players)
			{
				if ((Object)(object)player == (Object)null)
				{
					continue;
				}
				Vector2 val = Vector2.op_Implicit(((Component)player).transform.position);
				if (!(Vector2.Distance(val, Center) > _currentRadius))
				{
					_tickTimers.Remove(player);
					continue;
				}
				Debug.LogWarning($"[ShrinkingZoneMod] {((Object)player).name} is outside zone (dist={Vector2.Distance(val, Center):F1}, radius={_currentRadius:F1}).");
				if (!_tickTimers.ContainsKey(player))
				{
					_tickTimers[player] = 0f;
				}
				_tickTimers[player] += Time.deltaTime;
				if (_tickTimers[player] >= TickInterval)
				{
					_tickTimers[player] -= TickInterval;
					ApplyZoneDamage(player, DamagePercentPerSecond * TickInterval);
				}
			}
		}

		private void ApplyZoneDamage(Player player, float percentOfMaxHealth)
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			PhotonView component = ((Component)player).GetComponent<PhotonView>();
			if ((Object)(object)component != (Object)null && !component.IsMine)
			{
				Debug.LogWarning("[ShrinkingZoneMod] Skipping damage for " + ((Object)player).name + ": not locally owned (view.IsMine == false).");
				return;
			}
			float maxHealth = player.data.maxHealth;
			if (maxHealth <= 0f)
			{
				Debug.LogWarning($"[ShrinkingZoneMod] Skipping damage for {((Object)player).name}: maxHealth <= 0 ({maxHealth}).");
				return;
			}
			float num = maxHealth * percentOfMaxHealth;
			HealthHandler componentInChildren = ((Component)player).GetComponentInChildren<HealthHandler>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				Debug.LogWarning("[ShrinkingZoneMod] No HealthHandler found on " + ((Object)player).name + " or its children -- damage cannot be applied.");
				return;
			}
			Debug.LogWarning($"[ShrinkingZoneMod] Applying {num:F1} zone damage to {((Object)player).name} (maxHealth={maxHealth}).");
			Vector2 val = Vector2.op_Implicit(((Component)player).transform.position) - Center;
			Vector2 val2 = ((Vector2)(ref val)).normalized;
			if (val2 == Vector2.zero)
			{
				val2 = Vector2.up;
			}
			Vector2 val3 = val2 * num;
			((Damagable)componentInChildren).CallTakeDamage(val3, Vector2.op_Implicit(((Component)player).transform.position), (GameObject)null, (Player)null, true);
			if ((Object)(object)_tickAudioSource != (Object)null && (Object)(object)_damageTickSoundClip != (Object)null)
			{
				Debug.LogWarning($"[ShrinkingZoneMod] Playing damage tick sound. audioSource.enabled={((Behaviour)_tickAudioSource).enabled}, gameObject.activeInHierarchy={((Component)this).gameObject.activeInHierarchy}, clip.length={_damageTickSoundClip.length:F2}, clip.loadState={_damageTickSoundClip.loadState}.");
				_tickAudioSource.PlayOneShot(_damageTickSoundClip);
			}
			else
			{
				Debug.LogWarning($"[ShrinkingZoneMod] Damage tick sound NOT played -- audioSource null? {(Object)(object)_tickAudioSource == (Object)null}, clip null? {(Object)(object)_damageTickSoundClip == (Object)null}.");
			}
		}

		[UnboundRPC]
		private static void RPCA_SyncZoneState(float centerX, float centerY, float radius, float timer)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_active == (Object)null))
			{
				_active.Center = new Vector2(centerX, centerY);
				_active._currentRadius = radius;
				_active._timer = timer;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_ring != (Object)null)
			{
				Object.Destroy((Object)(object)_ring);
			}
		}
	}
}