Decompiled source of TF2Minigun Mod v1.1.0

TF2Minigun.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using CzajnikXD.TF2MinigunMod.Behaviours;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("CzajnikXD")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("TF2Minigun")]
[assembly: AssemblyTitle("TF2Minigun")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[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 CzajnikXD.TF2MinigunMod
{
	[BepInPlugin("com.czajnikxd.repo.tf2minigunmod", "TF2 Minigun Mod", "1.1.0")]
	public class TF2MinigunPlugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("com.czajnikxd.repo.tf2minigunmod");

		private void Awake()
		{
			harmony.PatchAll(Assembly.GetExecutingAssembly());
			foreach (MethodBase patchedMethod in harmony.GetPatchedMethods())
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Patched: " + patchedMethod.DeclaringType.Name + "." + patchedMethod.Name));
			}
		}
	}
}
namespace CzajnikXD.TF2MinigunMod.Patches
{
	[HarmonyPatch(typeof(ItemGun), "ShootLogic")]
	internal static class ItemGun_ShootLogic_Patch
	{
		private static bool Prefix(ItemGun __instance)
		{
			return (Object)(object)((Component)__instance).GetComponent<MinigunContinuousFireLogic>() == (Object)null;
		}
	}
	[HarmonyPatch(typeof(ItemGun), "Misfire")]
	internal static class ItemGun_Misfire_Patch
	{
		private static bool Prefix(ItemGun __instance)
		{
			return (Object)(object)((Component)__instance).GetComponent<MinigunContinuousFireLogic>() == (Object)null;
		}
	}
}
namespace CzajnikXD.TF2MinigunMod.Behaviours
{
	[RequireComponent(typeof(PhotonView))]
	public class MinigunContinuousFireLogic : MonoBehaviour
	{
		public enum MinigunState
		{
			Idle,
			WindingUp,
			Spinning,
			Shooting,
			ShootingEmpty,
			WindingDown
		}

		private ItemGun itemGun;

		private ItemBattery itemBattery;

		private PhysGrabObject physGrabObject;

		private PhotonView photonView;

		public MinigunState currentState;

		public float windUpDuration = 0.87f;

		public float windDownDuration = 0.87f;

		public KeyCode fireKey = (KeyCode)101;

		[Header("Sounds (game Sound class)")]
		public Sound soundWindUp;

		public Sound soundWindDown;

		public Sound soundSpinLoop;

		public Sound soundShootLoop;

		public Sound soundEmptyClick;

		[Tooltip("Volume units per second. Loop volume is capped by the Sound's Volume.")]
		public float loopFadeIn = 6f;

		public float loopFadeOut = 6f;

		[Header("Debug")]
		public bool debugLogging = true;

		private bool loggedShootResult;

		private AudioSource windUpHandle;

		private AudioSource windDownHandle;

		private bool spinLoopOn;

		private bool shootLoopOn;

		private bool localTriggerHeld;

		private bool triggerHeld;

		private float stateTimer;

		private float shotTimer;

		private bool loopSourcesDone;

		private void Awake()
		{
			itemGun = ((Component)this).GetComponent<ItemGun>();
			itemBattery = ((Component)this).GetComponent<ItemBattery>();
			physGrabObject = ((Component)this).GetComponent<PhysGrabObject>();
			photonView = ((Component)this).GetComponent<PhotonView>();
			if (!Object.op_Implicit((Object)(object)itemGun) || !Object.op_Implicit((Object)(object)itemBattery) || !Object.op_Implicit((Object)(object)physGrabObject))
			{
				Debug.LogError((object)"[MinigunLogic] Missing ItemGun / ItemBattery / PhysGrabObject on prefab root. Disabling.");
				((Behaviour)this).enabled = false;
			}
			else
			{
				TryCreateLoopSources();
			}
		}

		private void TryCreateLoopSources()
		{
			if (!loopSourcesDone && !((Object)(object)AudioManager.instance == (Object)null))
			{
				loopSourcesDone = true;
				EnsureLoopSource(soundSpinLoop, "MinigunLoop_Spin");
				EnsureLoopSource(soundShootLoop, "MinigunLoop_Shoot");
				WarnIfLoopBroken(soundSpinLoop, "spinLoop");
				WarnIfLoopBroken(soundShootLoop, "shootLoop");
			}
		}

		private void EnsureLoopSource(Sound s, string objectName)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Invalid comparison between Unknown and I4
			if (!HasClips(s) || Object.op_Implicit((Object)(object)s.Source))
			{
				return;
			}
			GameObject val = new GameObject(objectName);
			val.transform.SetParent(((Component)this).transform, false);
			AudioSource val2 = val.AddComponent<AudioSource>();
			val2.playOnAwake = false;
			val2.loop = true;
			AudioSource val3 = TemplateFor(s.Type);
			if (Object.op_Implicit((Object)(object)val3))
			{
				val2.outputAudioMixerGroup = val3.outputAudioMixerGroup;
				val2.rolloffMode = val3.rolloffMode;
				val2.minDistance = val3.minDistance;
				val2.maxDistance = val3.maxDistance;
				if ((int)val3.rolloffMode == 2)
				{
					val2.SetCustomCurve((AudioSourceCurveType)0, val3.GetCustomCurve((AudioSourceCurveType)0));
				}
			}
			else
			{
				val2.rolloffMode = (AudioRolloffMode)1;
				val2.minDistance = 3f;
				val2.maxDistance = 25f;
			}
			s.Source = val2;
		}

		private static AudioSource TemplateFor(AudioType type)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected I4, but got Unknown
			AudioManager instance = AudioManager.instance;
			GameObject val = instance.AudioDefault;
			switch (type - 1)
			{
			case 0:
				val = instance.AudioHighFalloff;
				break;
			case 1:
				val = instance.AudioFootstep;
				break;
			case 2:
				val = instance.AudioMaterialImpact;
				break;
			case 3:
				val = instance.AudioCutscene;
				break;
			case 4:
				val = instance.AudioAmbienceBreaker;
				break;
			case 5:
				val = instance.AudioLowFalloff;
				break;
			case 6:
				val = instance.AudioGlobal;
				break;
			case 7:
				val = instance.AudioHigherFalloff;
				break;
			case 8:
				val = instance.AudioAttack;
				break;
			case 9:
				val = instance.AudioPersistent;
				break;
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return val.GetComponent<AudioSource>();
		}

		private static bool HasClips(Sound s)
		{
			if (s != null && s.Sounds != null)
			{
				return s.Sounds.Length != 0;
			}
			return false;
		}

		private static bool LoopReady(Sound s)
		{
			if (HasClips(s))
			{
				return Object.op_Implicit((Object)(object)s.Source);
			}
			return false;
		}

		private static void WarnIfLoopBroken(Sound s, string label)
		{
			if (HasClips(s) && !Object.op_Implicit((Object)(object)s.Source))
			{
				Debug.LogWarning((object)("[MinigunLogic] Sound '" + label + "' has clips but no Source (AudioSource) assigned; the loop is skipped."));
			}
			else if (!HasClips(s))
			{
				Debug.LogWarning((object)("[MinigunLogic] Sound '" + label + "' has no clips; the loop is skipped."));
			}
		}

		private void Update()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			if (physGrabObject.grabbed && physGrabObject.grabbedLocal && PlayerController.instance.InputDisableTimer <= 0f)
			{
				flag = Input.GetKey(fireKey);
			}
			if (flag != localTriggerHeld)
			{
				localTriggerHeld = flag;
				BroadcastTrigger(flag);
			}
			bool flag2 = triggerHeld && physGrabObject.grabbed;
			float deltaTime = Time.deltaTime;
			stateTimer += deltaTime;
			shotTimer -= deltaTime;
			MinigunState minigunState = currentState;
			switch (currentState)
			{
			case MinigunState.Idle:
				if (flag2)
				{
					minigunState = MinigunState.WindingUp;
				}
				break;
			case MinigunState.WindingUp:
				if (!flag2)
				{
					minigunState = MinigunState.WindingDown;
				}
				else if (stateTimer >= windUpDuration)
				{
					minigunState = MinigunState.Spinning;
				}
				break;
			case MinigunState.Spinning:
				minigunState = (flag2 ? (IsEmpty() ? MinigunState.ShootingEmpty : MinigunState.Shooting) : MinigunState.WindingDown);
				break;
			case MinigunState.Shooting:
				if (!flag2)
				{
					minigunState = MinigunState.WindingDown;
				}
				else if (IsEmpty())
				{
					minigunState = MinigunState.ShootingEmpty;
				}
				else if (shotTimer <= 0f && SemiFunc.IsMasterClientOrSingleplayer())
				{
					if (itemGun.Shoot())
					{
						shotTimer = Mathf.Max(itemGun.shootCooldown, 0.02f);
					}
					if (!loggedShootResult)
					{
						loggedShootResult = true;
					}
				}
				break;
			case MinigunState.ShootingEmpty:
				if (!flag2)
				{
					minigunState = MinigunState.WindingDown;
				}
				else if (!IsEmpty())
				{
					minigunState = MinigunState.Shooting;
				}
				else if (shotTimer <= 0f)
				{
					PlayOneShot(soundEmptyClick);
					shotTimer = Mathf.Max(itemGun.shootCooldown, 0.2f);
				}
				break;
			case MinigunState.WindingDown:
				if (flag2)
				{
					minigunState = MinigunState.WindingUp;
				}
				else if (stateTimer >= windDownDuration)
				{
					minigunState = MinigunState.Idle;
				}
				break;
			}
			if (minigunState != currentState)
			{
				currentState = minigunState;
				stateTimer = 0f;
				loggedShootResult = false;
				OnStateEnter(minigunState);
			}
			TryCreateLoopSources();
			if (LoopReady(soundSpinLoop))
			{
				soundSpinLoop.PlayLoop(spinLoopOn, loopFadeIn, loopFadeOut, 1f, 1f);
			}
			if (LoopReady(soundShootLoop))
			{
				soundShootLoop.PlayLoop(shootLoopOn, loopFadeIn, loopFadeOut, 1f, 1f);
			}
		}

		private bool IsEmpty()
		{
			return itemBattery.batteryLifeInt <= 0;
		}

		private void BroadcastTrigger(bool held)
		{
			if (SemiFunc.IsMultiplayer())
			{
				if (photonView.ViewID != 0)
				{
					photonView.RPC("SetTriggerHeldRPC", (RpcTarget)0, new object[1] { held });
				}
			}
			else
			{
				SetTriggerHeldRPC(held);
			}
		}

		[PunRPC]
		private void SetTriggerHeldRPC(bool held)
		{
			triggerHeld = held;
		}

		[Conditional("DEBUG")]
		private void Dbg(string msg)
		{
			if (debugLogging)
			{
				Debug.Log((object)("[MinigunLogic] " + msg));
			}
		}

		private void OnStateEnter(MinigunState state)
		{
			switch (state)
			{
			case MinigunState.WindingUp:
				StopHandle(ref windDownHandle);
				StopHandle(ref windUpHandle);
				windUpHandle = PlayOneShot(soundWindUp);
				spinLoopOn = true;
				shootLoopOn = false;
				break;
			case MinigunState.Spinning:
				spinLoopOn = true;
				shootLoopOn = false;
				break;
			case MinigunState.Shooting:
				spinLoopOn = true;
				shootLoopOn = true;
				break;
			case MinigunState.ShootingEmpty:
				spinLoopOn = true;
				shootLoopOn = false;
				shotTimer = 0f;
				break;
			case MinigunState.WindingDown:
				StopHandle(ref windUpHandle);
				StopHandle(ref windDownHandle);
				windDownHandle = PlayOneShot(soundWindDown);
				spinLoopOn = false;
				shootLoopOn = false;
				break;
			case MinigunState.Idle:
				spinLoopOn = false;
				shootLoopOn = false;
				break;
			}
		}

		private AudioSource PlayOneShot(Sound s)
		{
			if (!HasClips(s))
			{
				return null;
			}
			return s.Play(((Component)this).transform, 1f, 1f, 1f, 1f);
		}

		private static void StopHandle(ref AudioSource handle)
		{
			if (Object.op_Implicit((Object)(object)handle))
			{
				handle.Stop();
			}
			handle = null;
		}

		private static void StopLoopNow(Sound s)
		{
			if (s != null && Object.op_Implicit((Object)(object)s.Source) && s.Source.isPlaying)
			{
				s.Source.Stop();
			}
		}

		private void OnDisable()
		{
			StopHandle(ref windUpHandle);
			StopHandle(ref windDownHandle);
			StopLoopNow(soundSpinLoop);
			StopLoopNow(soundShootLoop);
			spinLoopOn = false;
			shootLoopOn = false;
			currentState = MinigunState.Idle;
			localTriggerHeld = false;
			triggerHeld = false;
		}
	}
}