Decompiled source of EngineerGaussShotgun v0.3.0

BepInEx/plugins/EngiAlternateSkills.dll

Decompiled 2 months 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 System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using EntityStates;
using Microsoft.CodeAnalysis;
using On.RoR2;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.Skills;
using RoR2.UI;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;

[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("EngiAlternateSkills")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+27393ff00ec0c7866d1a398d7c63ef9cb2e620e4")]
[assembly: AssemblyProduct("EngiAlternateSkills")]
[assembly: AssemblyTitle("EngiAlternateSkills")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace EngiGaussShotgun
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.example.EngiGaussShotgun", "Engineer Gauss Shotgun", "1.0.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class EngiGaussShotgunPlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <DeferredSurvivorBankLoad>d__46 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public EngiGaussShotgunPlugin <>4__this;

			private uint <commandoEventId>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DeferredSurvivorBankLoad>d__46(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					goto IL_0046;
				case 1:
					<>1__state = -1;
					goto IL_0046;
				case 2:
					{
						<>1__state = -1;
						<commandoEventId>5__1 = AkSoundEngine.GetIDFromString("Play_commando_R");
						((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"[GaussShotgun] Commando bank loaded - Play_commando_R ID: {<commandoEventId>5__1}");
						return false;
					}
					IL_0046:
					if ((Object)(object)Stage.instance == (Object)null)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"[GaussShotgun] Stage loaded, forcing Commando soundbank load...");
					AkBankManager.LoadBank("char_Commando", true, true);
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 2;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <LoadRequiredPrefabs>d__52 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public EngiGaussShotgunPlugin <>4__this;

			private string[] <>s__1;

			private int <>s__2;

			private string <prefabPath>5__3;

			private AsyncOperationHandle<GameObject> <loadOp>5__4;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadRequiredPrefabs>d__52(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				<>s__1 = null;
				<prefabPath>5__3 = null;
				<loadOp>5__4 = default(AsyncOperationHandle<GameObject>);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0061: 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_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_012b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0135: Expected O, but got Unknown
				//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>s__1 = requiredPrefabs;
					<>s__2 = 0;
					goto IL_010b;
				case 1:
					<>1__state = -1;
					if ((Object)(object)<loadOp>5__4.Result == (Object)null)
					{
						((BaseUnityPlugin)<>4__this).Logger.LogWarning((object)("[GaussShotgun] Failed to load required prefab: " + <prefabPath>5__3));
					}
					else
					{
						((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("[GaussShotgun] Loaded prefab: " + <prefabPath>5__3));
					}
					<loadOp>5__4 = default(AsyncOperationHandle<GameObject>);
					<prefabPath>5__3 = null;
					<>s__2++;
					goto IL_010b;
				case 2:
					{
						<>1__state = -1;
						return false;
					}
					IL_010b:
					if (<>s__2 < <>s__1.Length)
					{
						<prefabPath>5__3 = <>s__1[<>s__2];
						<loadOp>5__4 = Addressables.LoadAssetAsync<GameObject>((object)<prefabPath>5__3);
						<>2__current = <loadOp>5__4;
						<>1__state = 1;
						return true;
					}
					<>s__1 = null;
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 2;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <VerifyBanksNextFrame>d__54 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string context;

			public EngiGaussShotgunPlugin <>4__this;

			private uint <idCommandoR>5__1;

			private uint <idBanditM1>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <VerifyBanksNextFrame>d__54(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<idCommandoR>5__1 = AkSoundEngine.GetIDFromString("Play_commando_R");
					<idBanditM1>5__2 = AkSoundEngine.GetIDFromString("Play_bandit_M1_shot");
					if (BankDebugEnabled)
					{
						((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"[GaussShotgun] VerifyBanks ({context}): Play_commando_R={<idCommandoR>5__1} Play_bandit_M1_shot={<idBanditM1>5__2}");
					}
					if (<idCommandoR>5__1 != 0 && <idBanditM1>5__2 != 0)
					{
						banksVerified = true;
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static AssetBundle? assetBundle = null;

		private ConfigEntry<int>? stockConfig;

		private ConfigEntry<float>? damageConfig;

		private ConfigEntry<float>? reloadTimeConfig;

		private ConfigEntry<bool>? debugAllPelletImpactSoundConfig;

		private ConfigEntry<string>? reloadStartSoundConfig;

		private ConfigEntry<string>? reloadPerRoundSoundConfig;

		private ConfigEntry<bool>? reloadPlayPerRoundSoundConfig;

		private ConfigEntry<bool>? bankDebugConfig;

		private ConfigEntry<bool>? forceSurvivorBanksConfig;

		private static bool BankDebugEnabled;

		private static bool banksVerified;

		private static bool ForceSurvivorBanks;

		private static readonly Color GaussGreenColor = new Color(0.682f, 1f, 0.663f, 1f);

		private static Texture? gaussRampTexture;

		public static SkillDef? gaussShotgunSkillDef;

		private Sprite? gaussShotgunIcon;

		private static GameObject? customCrosshairPrefab;

		private static readonly string[] survivorBanks = new string[2] { "char_Commando", "char_bandit2" };

		private static readonly string[] requiredPrefabs = new string[2] { "RoR2/Base/Bandit2/Bandit2Body.prefab", "RoR2/Base/Commando/CommandoBody.prefab" };

		public static PluginInfo? PInfo { get; private set; }

		public static bool DebugAllPelletImpactSound { get; private set; }

		public static float ReloadPerRoundBaseTime { get; private set; }

		public static string ReloadStartSoundEvent { get; private set; } = "Play_engi_M1_chargeStock";


		public static string ReloadPerRoundSoundEvent { get; private set; } = "Play_item_use_fireballDashRecharge";


		public static bool ReloadPerRoundSoundEnabled { get; private set; } = true;


		private void Awake()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			PInfo = ((BaseUnityPlugin)this).Info;
			LoadConfig();
			LoadAssets();
			((MonoBehaviour)this).StartCoroutine(DeferredSurvivorBankLoad());
			Stage.onStageStartGlobal += OnStageStartGlobal;
			GenericSkill.SetSkillOverride += new hook_SetSkillOverride(GenericSkill_SetSkillOverride);
			SetupGaussShotgun();
			SetupCustomCrosshair();
			CreateCustomEffects();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Engineer Gauss Shotgun loaded successfully!");
		}

		private void LoadConfig()
		{
			stockConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Gauss Shotgun", "Max Stock", 8, "Maximum ammo capacity for Gauss Shotgun");
			damageConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Gauss Shotgun", "Damage Per Pellet", 0.6f, "Damage coefficient per pellet (fires 8 pellets total)");
			reloadTimeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Gauss Shotgun", "Reload Time", 3f, "Time to reload one shot");
			debugAllPelletImpactSoundConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Play Impact Sound Every Pellet", false, "If true, plays the impact event for every pellet hit instead of only first per shot.");
			reloadStartSoundConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "Reload Start Sound", "Play_engi_M1_chargeStock", "Sound event played when reload sequence begins.");
			reloadPerRoundSoundConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "Reload Per Round Sound", "Play_item_use_fireballDashRecharge", "Short subtle tick sound for each round added asynchronously.");
			reloadPlayPerRoundSoundConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "Enable Per Round Reload Sound", true, "Enable/disable per-round tick sound.");
			bankDebugConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableBankDebug", true, "If true, logs one-time resolution of cross-survivor weapon events.");
			forceSurvivorBanksConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "ForceLoadSurvivorBanks", true, "Force load Commando/Bandit survivor soundbanks so their events (e.g. Play_commando_R) are always available even if that survivor is not present.");
			SyncStaticDebugFlags();
			debugAllPelletImpactSoundConfig.SettingChanged += delegate
			{
				SyncStaticDebugFlags();
			};
		}

		private void SyncStaticDebugFlags()
		{
			DebugAllPelletImpactSound = debugAllPelletImpactSoundConfig?.Value ?? false;
			ReloadPerRoundBaseTime = reloadTimeConfig?.Value ?? 3f;
			ReloadStartSoundEvent = reloadStartSoundConfig?.Value ?? ReloadStartSoundEvent;
			ReloadPerRoundSoundEvent = reloadPerRoundSoundConfig?.Value ?? ReloadPerRoundSoundEvent;
			ReloadPerRoundSoundEnabled = reloadPlayPerRoundSoundConfig?.Value ?? ReloadPerRoundSoundEnabled;
			BankDebugEnabled = bankDebugConfig.Value;
			ForceSurvivorBanks = forceSurvivorBanksConfig.Value;
		}

		private void LoadAssets()
		{
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: 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_0094: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
				assetBundle = AssetBundle.LoadFromFile(Path.Combine(directoryName, "engineerassets"));
				if ((Object)(object)assetBundle == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Failed to load engineer asset bundle; custom visuals will be missing.");
					return;
				}
				gaussShotgunIcon = assetBundle.LoadAsset<Sprite>("GaussShotgun");
				if ((Object)(object)gaussShotgunIcon == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"GaussShotgun sprite missing from bundle; using default cyan fallback.");
					Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
					Color32[] array = (Color32[])(object)new Color32[4096];
					for (int i = 0; i < array.Length; i++)
					{
						array[i] = new Color32((byte)0, byte.MaxValue, byte.MaxValue, byte.MaxValue);
					}
					val.SetPixels32(array);
					val.Apply();
					gaussShotgunIcon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Error loading assets: " + ex.Message));
				Texture2D val2 = new Texture2D(64, 64, (TextureFormat)4, false);
				Color32[] array2 = (Color32[])(object)new Color32[4096];
				for (int j = 0; j < array2.Length; j++)
				{
					array2[j] = new Color32((byte)0, byte.MaxValue, byte.MaxValue, byte.MaxValue);
				}
				val2.SetPixels32(array2);
				val2.Apply();
				gaussShotgunIcon = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), 100f);
			}
		}

		[IteratorStateMachine(typeof(<DeferredSurvivorBankLoad>d__46))]
		private IEnumerator DeferredSurvivorBankLoad()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DeferredSurvivorBankLoad>d__46(0)
			{
				<>4__this = this
			};
		}

		private void OnStageStartGlobal(Stage stage)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[GaussShotgun] Stage " + ((Object)stage).name + " started, loading Commando soundbank..."));
			AkBankManager.LoadBank("char_Commando", true, true);
			uint iDFromString = AkSoundEngine.GetIDFromString("Play_commando_R");
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"[GaussShotgun] Commando bank status - Play_commando_R ID: {iDFromString}");
		}

		private void CreateCustomEffects()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_00bc: 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_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			if (GaussShotgunFire.customEffectsCreated)
			{
				return;
			}
			try
			{
				Texture val = gaussRampTexture;
				if ((Object)(object)val == (Object)null)
				{
					val = (gaussRampTexture = Addressables.LoadAssetAsync<Texture>((object)"RoR2/Base/Common/ColorRamps/texRampEngi.png").WaitForCompletion());
					if ((Object)(object)val == (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)"[GaussShotgun] Failed to load texRampEngi texture; custom effects will keep default remap.");
					}
				}
				GameObject val2 = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Common/VFX/Muzzleflash1.prefab").WaitForCompletion();
				GameObject val3 = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Commando/HitsparkCommando.prefab").WaitForCompletion();
				if ((Object)(object)val2 != (Object)null)
				{
					GaussShotgunFire.customMuzzleEffectPrefab = PrefabAPI.InstantiateClone(val2, "EngiGaussMuzzleFlash", false);
					GaussShotgunFire.customMuzzleEffectPrefab.SetActive(false);
					ApplyGaussVisualTheme(GaussShotgunFire.customMuzzleEffectPrefab, val, GaussGreenColor, tintLights: true);
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[GaussShotgun] Applied gauss green tint to muzzle flash.");
					EffectComponent val4 = GaussShotgunFire.customMuzzleEffectPrefab.GetComponent<EffectComponent>();
					if ((Object)(object)val4 == (Object)null)
					{
						val4 = GaussShotgunFire.customMuzzleEffectPrefab.AddComponent<EffectComponent>();
						val4.applyScale = true;
						val4.parentToReferencedTransform = false;
						val4.positionAtReferencedTransform = true;
						val4.soundName = "";
					}
					val4.effectIndex = (EffectIndex)(-1);
					VFXAttributes component = GaussShotgunFire.customMuzzleEffectPrefab.GetComponent<VFXAttributes>();
					if ((Object)(object)component == (Object)null)
					{
						component = GaussShotgunFire.customMuzzleEffectPrefab.AddComponent<VFXAttributes>();
						component.vfxIntensity = (VFXIntensity)0;
						component.vfxPriority = (VFXPriority)0;
					}
					ContentAddition.AddEffect(GaussShotgunFire.customMuzzleEffectPrefab);
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[GaussShotgun] Custom muzzle flash registered with game");
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"[GaussShotgun] Failed to load base muzzle flash prefab");
				}
				if ((Object)(object)val3 != (Object)null)
				{
					GaussShotgunFire.customHitEffectPrefab = PrefabAPI.InstantiateClone(val3, "EngiGaussHitSpark", false);
					GaussShotgunFire.customHitEffectPrefab.SetActive(false);
					ApplyGaussVisualTheme(GaussShotgunFire.customHitEffectPrefab, val, GaussGreenColor, tintLights: false);
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[GaussShotgun] Applied gauss green tint to hit spark.");
					EffectComponent val5 = GaussShotgunFire.customHitEffectPrefab.GetComponent<EffectComponent>();
					if ((Object)(object)val5 == (Object)null)
					{
						val5 = GaussShotgunFire.customHitEffectPrefab.AddComponent<EffectComponent>();
						val5.applyScale = false;
						val5.parentToReferencedTransform = false;
						val5.positionAtReferencedTransform = true;
						val5.soundName = "";
					}
					val5.effectIndex = (EffectIndex)(-1);
					VFXAttributes component2 = GaussShotgunFire.customHitEffectPrefab.GetComponent<VFXAttributes>();
					if ((Object)(object)component2 == (Object)null)
					{
						component2 = GaussShotgunFire.customHitEffectPrefab.AddComponent<VFXAttributes>();
						component2.vfxIntensity = (VFXIntensity)0;
						component2.vfxPriority = (VFXPriority)0;
					}
					ContentAddition.AddEffect(GaussShotgunFire.customHitEffectPrefab);
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[GaussShotgun] Custom hit spark registered with game");
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"[GaussShotgun] Failed to load base hit spark prefab");
				}
				GaussShotgunFire.customEffectsCreated = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[GaussShotgun] ===== Custom green effects creation complete =====");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[GaussShotgun] Failed to create custom effects: " + ex.Message + "\n" + ex.StackTrace));
			}
		}

		private static void ApplyGaussVisualTheme(GameObject effectRoot, Texture? rampTexture, Color tintColor, bool tintLights)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Expected O, but got Unknown
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)effectRoot))
			{
				return;
			}
			if (tintLights)
			{
				Light[] componentsInChildren = effectRoot.GetComponentsInChildren<Light>(true);
				foreach (Light val in componentsInChildren)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.color = tintColor;
					}
				}
			}
			Renderer[] componentsInChildren2 = effectRoot.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Material[] sharedMaterials = val2.sharedMaterials;
				bool flag = false;
				for (int k = 0; k < sharedMaterials.Length; k++)
				{
					Material val3 = sharedMaterials[k];
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					Material val4 = new Material(val3)
					{
						name = (((Object)val3).name.EndsWith("_GaussClone", StringComparison.Ordinal) ? ((Object)val3).name : (((Object)val3).name + "_GaussClone"))
					};
					if ((Object)(object)rampTexture != (Object)null)
					{
						if (val4.HasProperty("_RemapTex"))
						{
							val4.SetTexture("_RemapTex", rampTexture);
						}
						if (val4.HasProperty("_Remap"))
						{
							val4.SetTexture("_Remap", rampTexture);
						}
					}
					if (val4.HasProperty("_TintColor"))
					{
						Color color = val4.GetColor("_TintColor");
						val4.SetColor("_TintColor", new Color(tintColor.r, tintColor.g, tintColor.b, color.a));
					}
					if (val4.HasProperty("_Color"))
					{
						Color color2 = val4.GetColor("_Color");
						val4.SetColor("_Color", new Color(tintColor.r, tintColor.g, tintColor.b, color2.a));
					}
					sharedMaterials[k] = val4;
					flag = true;
				}
				if (flag)
				{
					val2.sharedMaterials = sharedMaterials;
				}
				ParticleSystemRenderer val5 = (ParticleSystemRenderer)(object)((val2 is ParticleSystemRenderer) ? val2 : null);
				if (val5 == null || !((Object)(object)val5.trailMaterial != (Object)null))
				{
					continue;
				}
				Material trailMaterial = val5.trailMaterial;
				Material val6 = new Material(trailMaterial)
				{
					name = (((Object)trailMaterial).name.EndsWith("_GaussClone", StringComparison.Ordinal) ? ((Object)trailMaterial).name : (((Object)trailMaterial).name + "_GaussClone"))
				};
				if ((Object)(object)rampTexture != (Object)null)
				{
					if (val6.HasProperty("_RemapTex"))
					{
						val6.SetTexture("_RemapTex", rampTexture);
					}
					if (val6.HasProperty("_Remap"))
					{
						val6.SetTexture("_Remap", rampTexture);
					}
				}
				if (val6.HasProperty("_TintColor"))
				{
					Color color3 = val6.GetColor("_TintColor");
					val6.SetColor("_TintColor", new Color(tintColor.r, tintColor.g, tintColor.b, color3.a));
				}
				if (val6.HasProperty("_Color"))
				{
					Color color4 = val6.GetColor("_Color");
					val6.SetColor("_Color", new Color(tintColor.r, tintColor.g, tintColor.b, color4.a));
				}
				val5.trailMaterial = val6;
			}
		}

		[IteratorStateMachine(typeof(<LoadRequiredPrefabs>d__52))]
		private IEnumerator LoadRequiredPrefabs()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadRequiredPrefabs>d__52(0)
			{
				<>4__this = this
			};
		}

		private void EnsureSurvivorBanksLoaded(string context)
		{
			if (!ForceSurvivorBanks && context != "DeferredStart")
			{
				return;
			}
			string[] array = survivorBanks;
			foreach (string text in array)
			{
				AkBankManager.LoadBank(text, true, true);
				if (BankDebugEnabled)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[GaussShotgun] Directly loading bank '" + text + "' (context=" + context + ")"));
				}
				if (AkSoundEngine.GetIDFromString("Play_commando_R") == 0 && BankDebugEnabled)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[GaussShotgun] Bank " + text + " loaded but Play_commando_R still not available!"));
				}
			}
			if (!banksVerified)
			{
				((MonoBehaviour)this).StartCoroutine(VerifyBanksNextFrame(context));
			}
		}

		[IteratorStateMachine(typeof(<VerifyBanksNextFrame>d__54))]
		private IEnumerator VerifyBanksNextFrame(string context)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <VerifyBanksNextFrame>d__54(0)
			{
				<>4__this = this,
				context = context
			};
		}

		private void OnDestroy()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			Stage.onStageStartGlobal -= OnStageStartGlobal;
			GenericSkill.SetSkillOverride -= new hook_SetSkillOverride(GenericSkill_SetSkillOverride);
		}

		private void GenericSkill_SetSkillOverride(orig_SetSkillOverride orig, GenericSkill self, object source, SkillDef skillDef, SkillOverridePriority priority)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			if (self.skillDef is GaussShotgunSkillDef && (Object)(object)self.characterBody != (Object)null)
			{
				GaussShotgunStockTracker gaussShotgunStockTracker = ((Component)self.characterBody).GetComponent<GaussShotgunStockTracker>();
				if ((Object)(object)gaussShotgunStockTracker == (Object)null)
				{
					gaussShotgunStockTracker = ((Component)self.characterBody).gameObject.AddComponent<GaussShotgunStockTracker>();
					Debug.Log((object)"[GaussShotgun] Created GaussShotgunStockTracker in SetSkillOverride hook");
				}
				gaussShotgunStockTracker.savedStock = self.stock;
				gaussShotgunStockTracker.savedRechargeStopwatch = self.rechargeStopwatch;
				Debug.Log((object)$"[GaussShotgun] SetSkillOverride hook - Saved stock={self.stock}, rechargeStopwatch={self.rechargeStopwatch:F2} BEFORE override (skillDef={skillDef?.skillName})");
			}
			orig.Invoke(self, source, skillDef, priority);
		}

		private void SetupCustomCrosshair()
		{
			try
			{
				if ((Object)(object)assetBundle != (Object)null)
				{
					customCrosshairPrefab = PrefabAPI.InstantiateClone(assetBundle.LoadAsset<GameObject>("GaussCrosshair"), "GaussShotgunCrosshair", false);
					if ((Object)(object)customCrosshairPrefab != (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded custom crosshair prefab from asset bundle");
						Sprite val = assetBundle.LoadAsset<Sprite>("StockHexIcon");
						if ((Object)(object)val != (Object)null)
						{
							CreateStockDisplay(val);
						}
						if ((Object)(object)gaussShotgunSkillDef != (Object)null)
						{
							GaussShotgunSkillDef.crosshairOverride = customCrosshairPrefab;
							((BaseUnityPlugin)this).Logger.LogInfo((object)"Crosshair override set on skill def");
						}
					}
					else
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not load GaussCrosshair from asset bundle");
					}
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Asset bundle not loaded, cannot setup custom crosshair");
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom crosshair setup complete");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Error setting up custom crosshair: " + ex.Message));
			}
		}

		private void CreateStockDisplay(Sprite stockSprite)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Expected O, but got Unknown
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)customCrosshairPrefab == (Object)null || (Object)(object)stockSprite == (Object)null)
			{
				return;
			}
			try
			{
				CrosshairController component = customCrosshairPrefab.GetComponent<CrosshairController>();
				if ((Object)(object)component == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"No CrosshairController on prefab!");
					return;
				}
				GameObject val = new GameObject("StockContainer");
				val.transform.SetParent(customCrosshairPrefab.transform, false);
				RectTransform val2 = val.AddComponent<RectTransform>();
				val2.anchorMin = new Vector2(0.5f, 0f);
				val2.anchorMax = new Vector2(0.5f, 0f);
				val2.pivot = new Vector2(0.5f, 1f);
				val2.anchoredPosition = new Vector2(0f, -20f);
				val2.sizeDelta = new Vector2(200f, 30f);
				HorizontalLayoutGroup val3 = val.AddComponent<HorizontalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)val3).spacing = 4f;
				((LayoutGroup)val3).childAlignment = (TextAnchor)4;
				((HorizontalOrVerticalLayoutGroup)val3).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)val3).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)val3).childControlWidth = false;
				((HorizontalOrVerticalLayoutGroup)val3).childControlHeight = false;
				SkillStockSpriteDisplay[] skillStockSpriteDisplays = component.skillStockSpriteDisplays;
				int num = stockConfig?.Value ?? gaussShotgunSkillDef?.baseMaxStock ?? 8;
				int num2 = Mathf.Min(num, 10);
				SkillStockSpriteDisplay[] array = (SkillStockSpriteDisplay[])(object)new SkillStockSpriteDisplay[skillStockSpriteDisplays.Length + num2];
				for (int i = 0; i < skillStockSpriteDisplays.Length; i++)
				{
					array[i] = skillStockSpriteDisplays[i];
					if (array[i].maximumStockCountToBeValid > 0 && array[i].maximumStockCountToBeValid < num)
					{
						array[i].maximumStockCountToBeValid = num;
					}
				}
				for (int j = 0; j < num2; j++)
				{
					GameObject val4 = new GameObject($"StockIcon{j + 1}");
					val4.transform.SetParent(val.transform, false);
					RectTransform val5 = val4.AddComponent<RectTransform>();
					val5.sizeDelta = new Vector2(20f, 20f);
					Image val6 = val4.AddComponent<Image>();
					val6.sprite = stockSprite;
					((Graphic)val6).color = Color.white;
					array[skillStockSpriteDisplays.Length + j] = new SkillStockSpriteDisplay
					{
						target = val4,
						skillSlot = (SkillSlot)0,
						requiredSkillDef = gaussShotgunSkillDef,
						minimumStockCountToBeValid = j + 1,
						maximumStockCountToBeValid = num
					};
				}
				component.skillStockSpriteDisplays = array;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Created stock display with {num2} icons");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Error creating stock display: " + ex.Message));
			}
		}

		private void SetupGaussShotgun()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_003e: 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_011a: 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_0144: Expected O, but got Unknown
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Engi/EngiBody.prefab").WaitForCompletion();
			SkillLocator component = val.GetComponent<SkillLocator>();
			SkillFamily skillFamily = component.primary.skillFamily;
			GaussShotgunSkillDef gaussShotgunSkillDef = ScriptableObject.CreateInstance<GaussShotgunSkillDef>();
			((SkillDef)gaussShotgunSkillDef).activationState = new SerializableEntityStateType(typeof(GaussShotgunFire));
			((SkillDef)gaussShotgunSkillDef).baseMaxStock = stockConfig?.Value ?? 4;
			((SkillDef)gaussShotgunSkillDef).rechargeStock = 1;
			((SkillDef)gaussShotgunSkillDef).baseRechargeInterval = ReloadPerRoundBaseTime;
			((SkillDef)gaussShotgunSkillDef).skillDescriptionToken = "ENGI_GAUSS_SHOTGUN_DESCRIPTION";
			((SkillDef)gaussShotgunSkillDef).skillName = "GaussShotgun";
			((SkillDef)gaussShotgunSkillDef).skillNameToken = "ENGI_GAUSS_SHOTGUN_NAME";
			((SkillDef)gaussShotgunSkillDef).activationStateMachineName = "Weapon";
			((SkillDef)gaussShotgunSkillDef).beginSkillCooldownOnSkillEnd = false;
			((SkillDef)gaussShotgunSkillDef).fullRestockOnAssign = true;
			((SkillDef)gaussShotgunSkillDef).interruptPriority = (InterruptPriority)1;
			((SkillDef)gaussShotgunSkillDef).isCombatSkill = true;
			((SkillDef)gaussShotgunSkillDef).cancelSprintingOnActivation = true;
			((SkillDef)gaussShotgunSkillDef).canceledFromSprinting = false;
			((SkillDef)gaussShotgunSkillDef).mustKeyPress = false;
			((SkillDef)gaussShotgunSkillDef).icon = gaussShotgunIcon;
			((SkillDef)gaussShotgunSkillDef).requiredStock = 1;
			((SkillDef)gaussShotgunSkillDef).stockToConsume = 0;
			((SkillDef)gaussShotgunSkillDef).attackSpeedBuffsRestockSpeed = true;
			ContentAddition.AddSkillDef((SkillDef)(object)gaussShotgunSkillDef);
			Array.Resize(ref skillFamily.variants, skillFamily.variants.Length + 1);
			Variant[] variants = skillFamily.variants;
			int num = skillFamily.variants.Length - 1;
			Variant val2 = new Variant
			{
				skillDef = (SkillDef)(object)gaussShotgunSkillDef,
				unlockableDef = null
			};
			((Variant)(ref val2)).viewableNode = new Node(((SkillDef)gaussShotgunSkillDef).skillNameToken, false, (Node)null);
			variants[num] = val2;
			EngiGaussShotgunPlugin.gaussShotgunSkillDef = (SkillDef?)(object)gaussShotgunSkillDef;
			LanguageAPI.Add("ENGI_GAUSS_SHOTGUN_NAME", "Gauss Shotgun");
			LanguageAPI.Add("ENGI_GAUSS_SHOTGUN_DESCRIPTION", $"Fire a close-range blast of pellets, dealing <style=cIsDamage>8x{(int)((damageConfig?.Value ?? 0.6f) * 100f)}% damage</style>. " + $"Holds {stockConfig?.Value ?? 4} total rounds.");
		}
	}
	public class GaussShotgunSkillDef : SkillDef
	{
		public class InstanceData : BaseSkillInstanceData
		{
			public int stockToRestore;
		}

		public static GameObject? crosshairOverride;

		public override float GetRechargeInterval(GenericSkill skillSlot)
		{
			if ((Object)(object)((skillSlot != null) ? skillSlot.characterBody : null) != (Object)null)
			{
				return base.baseRechargeInterval / skillSlot.characterBody.attackSpeed;
			}
			return base.baseRechargeInterval;
		}

		public override BaseSkillInstanceData OnAssigned(GenericSkill skillSlot)
		{
			Debug.Log((object)$"[GaussShotgun] OnAssigned called - skillSlot.stock={skillSlot.stock}, rechargeStopwatch={skillSlot.rechargeStopwatch:F2}");
			if ((Object)(object)crosshairOverride != (Object)null)
			{
				CharacterBody component = ((Component)skillSlot).GetComponent<CharacterBody>();
				if ((Object)(object)component != (Object)null)
				{
					CrosshairUtils.RequestOverrideForBody(component, crosshairOverride, (OverridePriority)1);
				}
			}
			CharacterBody characterBody = skillSlot.characterBody;
			int num = -1;
			float num2 = -1f;
			Debug.Log((object)$"[GaussShotgun] OnAssigned - charBody={(Object)(object)characterBody != (Object)null}");
			if ((Object)(object)characterBody != (Object)null)
			{
				GaussShotgunStockTracker component2 = ((Component)characterBody).GetComponent<GaussShotgunStockTracker>();
				Debug.Log((object)$"[GaussShotgun] OnAssigned - stockTracker={(Object)(object)component2 != (Object)null}");
				if ((Object)(object)component2 != (Object)null)
				{
					Debug.Log((object)$"[GaussShotgun] OnAssigned - stockTracker.savedStock={component2.savedStock}, savedRechargeStopwatch={component2.savedRechargeStopwatch:F2}");
					if (component2.savedStock >= 0)
					{
						num = component2.savedStock;
						num2 = component2.savedRechargeStopwatch;
						component2.savedStock = -1;
						component2.savedRechargeStopwatch = 0f;
						Debug.Log((object)$"[GaussShotgun] Found saved stock: {num}, recharge: {num2:F2}, will restore after base call");
					}
					else
					{
						Debug.Log((object)$"[GaussShotgun] savedStock is negative ({component2.savedStock}), not restoring");
					}
				}
				else
				{
					Debug.LogWarning((object)"[GaussShotgun] OnAssigned: No GaussShotgunStockTracker found on character body!");
				}
			}
			else
			{
				Debug.LogError((object)"[GaussShotgun] OnAssigned: CharacterBody is NULL!");
			}
			Debug.Log((object)$"[GaussShotgun] Calling base.OnAssigned() - stock before base call: {skillSlot.stock}");
			BaseSkillInstanceData result = ((SkillDef)this).OnAssigned(skillSlot);
			Debug.Log((object)$"[GaussShotgun] After base.OnAssigned() - stock is now: {skillSlot.stock}, rechargeStopwatch: {skillSlot.rechargeStopwatch:F2}");
			if (num >= 0)
			{
				Debug.Log((object)$"[GaussShotgun] Overriding stock from {skillSlot.stock} to {num}");
				skillSlot.stock = num;
				skillSlot.rechargeStopwatch = num2;
				Debug.Log((object)$"[GaussShotgun] Restored stock to {num} and rechargeStopwatch to {num2:F2} on reassign (overriding fullRestockOnAssign) - final stock: {skillSlot.stock}, recharge: {skillSlot.rechargeStopwatch:F2}");
				if ((Object)(object)characterBody != (Object)null && num < skillSlot.maxStock)
				{
					GaussReloadController gaussReloadController = ((Component)characterBody).GetComponent<GaussReloadController>();
					if ((Object)(object)gaussReloadController == (Object)null)
					{
						gaussReloadController = ((Component)characterBody).gameObject.AddComponent<GaussReloadController>();
						Debug.Log((object)"[GaussShotgun] Created GaussReloadController on reassign");
					}
					gaussReloadController.RestoreReloadState(skillSlot, characterBody, num2);
					Debug.Log((object)$"[GaussShotgun] Restarted GaussReloadController with restored stopwatch {num2:F2}");
				}
			}
			else
			{
				Debug.Log((object)$"[GaussShotgun] No stock to restore, keeping default stock: {skillSlot.stock}");
			}
			return result;
		}

		public override void OnUnassigned(GenericSkill skillSlot)
		{
			Debug.Log((object)"[GaussShotgun] OnUnassigned called - stock saving was already handled by SetSkillOverride hook");
			((SkillDef)this).OnUnassigned(skillSlot);
		}

		public override void OnFixedUpdate(GenericSkill skillSlot, float deltaTime)
		{
			CharacterBody characterBody = skillSlot.characterBody;
			if (Object.op_Implicit((Object)(object)characterBody))
			{
				GaussReloadController gaussReloadController = ((Component)characterBody).GetComponent<GaussReloadController>();
				if (!Object.op_Implicit((Object)(object)gaussReloadController))
				{
					gaussReloadController = ((Component)characterBody).gameObject.AddComponent<GaussReloadController>();
				}
				if (skillSlot.stock < skillSlot.maxStock)
				{
					gaussReloadController.BeginReload(skillSlot, characterBody, characterBody.attackSpeed);
				}
				else
				{
					gaussReloadController.StopReload(skillSlot);
				}
			}
		}

		public override bool CanExecute(GenericSkill skillSlot)
		{
			if (skillSlot.stock > 0)
			{
				return ((SkillDef)this).CanExecute(skillSlot);
			}
			return false;
		}
	}
	public class GaussShotgunFire : BaseState
	{
		public static float baseMaxDuration = 0.1f;

		public static float baseMinDuration = 0.1f;

		private float maxDuration;

		private float minDuration;

		private bool buttonReleased;

		private bool shotFired;

		private string muzzleString = "MuzzleRight";

		private string muzzleString2 = "MuzzleLeft";

		public static GameObject? muzzleEffectPrefab;

		public static GameObject? tracerEffectPrefab;

		public static GameObject? hitEffectPrefab;

		public static GameObject? customMuzzleEffectPrefab;

		public static GameObject? customHitEffectPrefab;

		public static bool customEffectsCreated = false;

		public static readonly string enemyImpactEvent = "Play_commando_R";

		public static readonly string worldImpactEvent = "Play_commando_R";

		private bool hasPlayedImpactThisShot = false;

		public override void OnEnter()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			((BaseState)this).OnEnter();
			maxDuration = baseMaxDuration / base.attackSpeedStat;
			minDuration = baseMinDuration / base.attackSpeedStat;
			if (!Object.op_Implicit((Object)(object)muzzleEffectPrefab))
			{
				muzzleEffectPrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Common/VFX/Muzzleflash1.prefab").WaitForCompletion();
			}
			if (!Object.op_Implicit((Object)(object)tracerEffectPrefab))
			{
				tracerEffectPrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Engi/TracerEngiTurret.prefab").WaitForCompletion();
			}
			if (!Object.op_Implicit((Object)(object)hitEffectPrefab))
			{
				hitEffectPrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Commando/HitsparkCommando.prefab").WaitForCompletion();
			}
			GameObject val = customMuzzleEffectPrefab ?? muzzleEffectPrefab;
			if (Object.op_Implicit((Object)(object)hitEffectPrefab))
			{
				EffectComponent component = hitEffectPrefab.GetComponent<EffectComponent>();
				if (!Object.op_Implicit((Object)(object)component) || string.IsNullOrEmpty(component.soundName))
				{
					Debug.Log((object)"[GaussShotgun] hitEffectPrefab has no EffectComponent soundName; will rely on manual impact sounds.");
				}
				else
				{
					Debug.Log((object)("[GaussShotgun] hitEffectPrefab soundName='" + component.soundName + "'"));
				}
			}
			Util.PlaySound("Play_engi_M1_shoot", ((EntityState)this).gameObject);
			Util.PlaySound(worldImpactEvent, ((EntityState)this).gameObject);
			((EntityState)this).PlayAnimation("Gesture Right Cannon, Additive", "FireGrenadeRight", "FireGrenadeRight.playbackRate", maxDuration, 0f);
			((EntityState)this).PlayAnimation("Gesture Left Cannon, Additive", "FireGrenadeLeft", "FireGrenadeLeft.playbackRate", maxDuration, 0f);
			if ((Object)(object)val != (Object)null)
			{
				EffectManager.SimpleMuzzleFlash(val, ((EntityState)this).gameObject, muzzleString, false);
				EffectManager.SimpleMuzzleFlash(val, ((EntityState)this).gameObject, muzzleString2, false);
			}
			if (((EntityState)this).isAuthority)
			{
				FireShotgun();
			}
			if (!Object.op_Implicit((Object)(object)((EntityState)this).gameObject.GetComponent<AkGameObj>()))
			{
				((EntityState)this).gameObject.AddComponent<AkGameObj>();
				Debug.Log((object)"[GaussShotgun] Added AkGameObj to ensure Wwise events post correctly.");
			}
		}

		private void FireShotgun()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Ray aimRay = ((BaseState)this).GetAimRay();
			float perPelletDamageCoeff = 0.6f;
			((BaseState)this).AddRecoil(-4.5f, -1f, -1f, 4f);
			((EntityState)this).characterBody.AddSpreadBloom(0.3f);
			hasPlayedImpactThisShot = false;
			GameObject hitToUse = customHitEffectPrefab ?? hitEffectPrefab;
			FireFromMuzzle(muzzleString);
			FireFromMuzzle(muzzleString2);
			shotFired = true;
			void FireFromMuzzle(string muzzle)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: 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_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: 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_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: 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_00fb: 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_0111: 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_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_0135: Unknown result type (might be due to invalid IL or missing references)
				//IL_0137: Unknown result type (might be due to invalid IL or missing references)
				//IL_013c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0144: Unknown result type (might be due to invalid IL or missing references)
				//IL_014e: Expected O, but got Unknown
				//IL_014f: Expected O, but got Unknown
				//IL_0190: Unknown result type (might be due to invalid IL or missing references)
				BulletAttack val = new BulletAttack
				{
					owner = ((EntityState)this).gameObject,
					weapon = ((EntityState)this).gameObject,
					origin = ((Ray)(ref aimRay)).origin,
					aimVector = ((Ray)(ref aimRay)).direction,
					maxDistance = 80f,
					bulletCount = 8u,
					damage = perPelletDamageCoeff * base.damageStat,
					isCrit = Util.CheckRoll(base.critStat, ((EntityState)this).characterBody.master),
					force = 9f,
					procCoefficient = 0.45f,
					procChainMask = default(ProcChainMask),
					radius = 0.15f,
					falloffModel = (FalloffModel)1,
					smartCollision = true,
					stopperMask = CommonMasks.bullet,
					hitMask = CommonMasks.bullet,
					muzzleName = muzzle,
					HitEffectNormal = true,
					minSpread = 0f,
					maxSpread = 3.5f,
					spreadPitchScale = 1f,
					spreadYawScale = 1f,
					cheapMultiBullet = false,
					allowTrajectoryAimAssist = false,
					queryTriggerInteraction = (QueryTriggerInteraction)0,
					hitCallback = (HitCallback)delegate(BulletAttack bulletAttack, ref BulletHit hitInfo)
					{
						bool result = BulletAttack.defaultHitCallback.Invoke(bulletAttack, ref hitInfo);
						if (!hasPlayedImpactThisShot && EngiGaussShotgunPlugin.DebugAllPelletImpactSound)
						{
							if (Object.op_Implicit((Object)(object)hitInfo.hitHurtBox))
							{
								Util.PlaySound(enemyImpactEvent, ((Component)hitInfo.hitHurtBox.healthComponent).gameObject);
							}
							else
							{
								Util.PlaySound(worldImpactEvent, ((EntityState)this).gameObject);
							}
						}
						else if (!hasPlayedImpactThisShot)
						{
							hasPlayedImpactThisShot = true;
							if (Object.op_Implicit((Object)(object)hitInfo.hitHurtBox))
							{
								Util.PlaySound(enemyImpactEvent, ((Component)hitInfo.hitHurtBox.healthComponent).gameObject);
							}
							else
							{
								Util.PlaySound(worldImpactEvent, ((EntityState)this).gameObject);
							}
						}
						return result;
					}
				};
				if ((Object)(object)tracerEffectPrefab != (Object)null)
				{
					val.tracerEffectPrefab = tracerEffectPrefab;
				}
				if ((Object)(object)hitToUse != (Object)null)
				{
					val.hitEffectPrefab = hitToUse;
				}
				val.damageType.damageSource = (DamageSource)1;
				val.Fire();
				Debug.Log((object)string.Format("[GaussShotgun] Fired muzzle={0} dmgPerPellet={1:F2} count={2} hitFx={3}", muzzle, perPelletDamageCoeff * base.damageStat, val.bulletCount, Object.op_Implicit((Object)(object)hitEffectPrefab) ? ((Object)hitEffectPrefab).name : "NULL"));
			}
		}

		public override void OnExit()
		{
			if (!buttonReleased && Object.op_Implicit((Object)(object)((EntityState)this).characterBody))
			{
				((EntityState)this).characterBody.SetSpreadBloom(0f, false);
			}
			((EntityState)this).OnExit();
		}

		public override void FixedUpdate()
		{
			if (shotFired)
			{
				GenericSkill val = ((EntityState)this).skillLocator?.primary;
				if ((Object)(object)val != (Object)null)
				{
					val.DeductStock(1);
					GaussReloadController gaussReloadController = ((Component)((EntityState)this).characterBody).GetComponent<GaussReloadController>();
					if (!Object.op_Implicit((Object)(object)gaussReloadController))
					{
						gaussReloadController = ((Component)((EntityState)this).characterBody).gameObject.AddComponent<GaussReloadController>();
					}
					gaussReloadController.BeginReload(val, ((EntityState)this).characterBody, base.attackSpeedStat);
				}
				shotFired = false;
			}
			((EntityState)this).FixedUpdate();
			buttonReleased |= !((EntityState)this).inputBank.skill1.down;
			if (((EntityState)this).fixedAge >= maxDuration && ((EntityState)this).isAuthority)
			{
				((EntityState)this).outer.SetNextStateToMain();
			}
		}

		public override InterruptPriority GetMinimumInterruptPriority()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (buttonReleased && ((EntityState)this).fixedAge >= minDuration)
			{
				return (InterruptPriority)0;
			}
			return (InterruptPriority)2;
		}
	}
	public class GaussShotgunReload : BaseState
	{
		public static GameObject? reloadEffectPrefab;

		public override void OnEnter()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			((BaseState)this).OnEnter();
			if (!((EntityState)this).isAuthority)
			{
				((EntityState)this).outer.SetNextStateToMain();
				return;
			}
			if (!Object.op_Implicit((Object)(object)reloadEffectPrefab))
			{
				reloadEffectPrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Common/Muzzleflash.prefab").WaitForCompletion();
			}
			if (Object.op_Implicit((Object)(object)reloadEffectPrefab))
			{
				EffectManager.SimpleMuzzleFlash(reloadEffectPrefab, ((EntityState)this).gameObject, "MuzzleCenter", false);
			}
			GaussReloadController gaussReloadController = ((Component)((EntityState)this).characterBody).GetComponent<GaussReloadController>();
			if (!Object.op_Implicit((Object)(object)gaussReloadController))
			{
				gaussReloadController = ((Component)((EntityState)this).characterBody).gameObject.AddComponent<GaussReloadController>();
			}
			gaussReloadController.BeginReload(((EntityState)this).skillLocator.primary, ((EntityState)this).characterBody, base.attackSpeedStat);
			((EntityState)this).outer.SetNextStateToMain();
		}

		public override InterruptPriority GetMinimumInterruptPriority()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return (InterruptPriority)0;
		}
	}
	public class GaussShotgunStockTracker : MonoBehaviour
	{
		public int savedStock = -1;

		public float savedRechargeStopwatch = 0f;
	}
	public class GaussReloadController : MonoBehaviour
	{
		private GenericSkill? skill;

		private CharacterBody? body;

		private float perRoundInterval;

		private float intervalStopwatch;

		private bool reloading;

		private bool skipFirstRoundSound;

		private int targetMax;

		public void RestoreReloadState(GenericSkill primary, CharacterBody cb, float restoredStopwatch)
		{
			if (!((Object)(object)primary == (Object)null) && !((Object)(object)cb == (Object)null))
			{
				skill = primary;
				body = cb;
				targetMax = skill.maxStock;
				GaussShotgunSkillDef gaussShotgunSkillDef = skill.skillDef as GaussShotgunSkillDef;
				perRoundInterval = (((Object)(object)gaussShotgunSkillDef != (Object)null) ? ((SkillDef)gaussShotgunSkillDef).GetRechargeInterval(skill) : skill.baseRechargeInterval);
				intervalStopwatch = restoredStopwatch;
				if (skill.stock < targetMax)
				{
					reloading = true;
					skipFirstRoundSound = true;
					Debug.Log((object)$"[GaussReloadController] RestoreReloadState: reloading={reloading}, intervalStopwatch={intervalStopwatch:F2}, perRoundInterval={perRoundInterval:F2}");
				}
			}
		}

		public void BeginReload(GenericSkill primary, CharacterBody cb, float atkSpeed)
		{
			if ((Object)(object)primary == (Object)null || (Object)(object)cb == (Object)null)
			{
				return;
			}
			if ((Object)(object)skill != (Object)(object)primary)
			{
				skill = primary;
				targetMax = skill.maxStock;
			}
			body = cb;
			if (skill.stock >= targetMax)
			{
				StopReload(primary);
				return;
			}
			float num = perRoundInterval;
			GaussShotgunSkillDef gaussShotgunSkillDef = skill.skillDef as GaussShotgunSkillDef;
			float num2 = (((Object)(object)gaussShotgunSkillDef != (Object)null) ? ((SkillDef)gaussShotgunSkillDef).GetRechargeInterval(skill) : skill.baseRechargeInterval);
			perRoundInterval = num2;
			if (num > 0f && intervalStopwatch > 0f)
			{
				float num3 = Mathf.Clamp01(intervalStopwatch / num);
				intervalStopwatch = num3 * perRoundInterval;
			}
			else
			{
				intervalStopwatch = Mathf.Min(intervalStopwatch, perRoundInterval);
			}
			if (!reloading)
			{
				reloading = true;
				skipFirstRoundSound = skill.stock == 0;
				if (!skipFirstRoundSound && (Object)(object)body != (Object)null && ((NetworkBehaviour)body).hasAuthority)
				{
					Util.PlaySound(EngiGaussShotgunPlugin.ReloadStartSoundEvent, ((Component)body).gameObject);
				}
			}
		}

		public void StopReload(GenericSkill? requestingSkill = null)
		{
			if (!((Object)(object)requestingSkill != (Object)null) || !((Object)(object)skill != (Object)null) || !((Object)(object)requestingSkill != (Object)(object)skill))
			{
				reloading = false;
				intervalStopwatch = 0f;
				skipFirstRoundSound = false;
				if ((Object)(object)skill != (Object)null)
				{
					skill.rechargeStopwatch = 0f;
				}
			}
		}

		private void FixedUpdate()
		{
			if (!reloading || (Object)(object)skill == (Object)null || (Object)(object)body == (Object)null)
			{
				return;
			}
			targetMax = skill.maxStock;
			if (skill.stock >= targetMax)
			{
				StopReload(skill);
				return;
			}
			float num = perRoundInterval;
			GaussShotgunSkillDef gaussShotgunSkillDef = skill.skillDef as GaussShotgunSkillDef;
			float num2 = (((Object)(object)gaussShotgunSkillDef != (Object)null) ? ((SkillDef)gaussShotgunSkillDef).GetRechargeInterval(skill) : skill.baseRechargeInterval);
			perRoundInterval = num2;
			if (num > 0f && !Mathf.Approximately(num, perRoundInterval))
			{
				float num3 = Mathf.Clamp01(intervalStopwatch / num);
				intervalStopwatch = num3 * perRoundInterval;
			}
			intervalStopwatch += Time.fixedDeltaTime;
			if (intervalStopwatch > perRoundInterval)
			{
				intervalStopwatch = perRoundInterval;
			}
			skill.rechargeStopwatch = intervalStopwatch;
			skill.RecalculateValues();
			if (intervalStopwatch >= perRoundInterval)
			{
				intervalStopwatch = 0f;
				if (NetworkServer.active)
				{
					skill.AddOneStock();
				}
				if (!skipFirstRoundSound && EngiGaussShotgunPlugin.ReloadPerRoundSoundEnabled && (Object)(object)body != (Object)null && ((NetworkBehaviour)body).hasAuthority)
				{
					Util.PlaySound(EngiGaussShotgunPlugin.ReloadPerRoundSoundEvent, ((Component)body).gameObject);
				}
				skipFirstRoundSound = false;
				if (skill.stock >= targetMax)
				{
					StopReload(skill);
				}
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}