Decompiled source of ShrunkenSurvivor v1.1.0

ShrunkenSurvivor.dll

Decompiled 20 hours ago
using System;
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 System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HG.BlendableTypes;
using Microsoft.CodeAnalysis;
using On.RoR2;
using On.RoR2.Projectile;
using RoR2;
using RoR2.Projectile;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShrunkenSurvivor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("ShrunkenSurvivor")]
[assembly: AssemblyTitle("ShrunkenSurvivor")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[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 ShrunkenSurvivor
{
	[BepInPlugin("dileppy.shrunkensurvivor", "ShrunkenSurvivor", "1.1.0")]
	public class ShrunkenSurvivorPlugin : BaseUnityPlugin
	{
		public enum SizeTier
		{
			Small,
			ExtraSmall,
			ExtremelySmall
		}

		private struct TierValues
		{
			public float size;

			public float move;

			public float jump;

			public float damage;

			public float attackSpeed;

			public TierValues(float s, float m, float j, float d, float a)
			{
				size = s;
				move = m;
				jump = j;
				damage = d;
				attackSpeed = a;
			}
		}

		private class ShrunkenMarker : MonoBehaviour
		{
			public Vector3 baseScale;
		}

		public const string PluginGUID = "dileppy.shrunkensurvivor";

		public const string PluginName = "ShrunkenSurvivor";

		public const string PluginVersion = "1.1.0";

		private const string BiggerBulletsGUID = "dileppy.biggerbullets";

		private static bool biggerBulletsPresent;

		private static readonly Dictionary<SizeTier, TierValues> Defaults = new Dictionary<SizeTier, TierValues>
		{
			{
				SizeTier.Small,
				new TierValues(0.7f, 0.85f, 0.85f, 0.75f, 1.25f)
			},
			{
				SizeTier.ExtraSmall,
				new TierValues(0.5f, 0.7f, 0.7f, 0.55f, 1.6f)
			},
			{
				SizeTier.ExtremelySmall,
				new TierValues(0.3f, 0.55f, 0.55f, 0.4f, 2f)
			}
		};

		public static ConfigEntry<SizeTier> Tier;

		public static ConfigEntry<bool> ShrinkProjectiles;

		public static ConfigEntry<bool> UseCustomValues;

		public static ConfigEntry<float> CustomSize;

		public static ConfigEntry<float> CustomMove;

		public static ConfigEntry<float> CustomJump;

		public static ConfigEntry<float> CustomDamage;

		public static ConfigEntry<float> CustomAttackSpeed;

		public static ConfigEntry<bool> DebugLogging;

		public static ConfigEntry<bool> GiantWeapon;

		public static ConfigEntry<float> WeaponScale;

		public static ConfigEntry<float> CameraPullIn;

		public static ConfigEntry<bool> BonusRewards;

		public static ConfigEntry<bool> CompensateEvasion;

		public static ConfigEntry<bool> SurvivorSounds;

		public static ConfigEntry<float> SoundVolume;

		private static readonly Dictionary<SizeTier, float> RewardBonus = new Dictionary<SizeTier, float>
		{
			{
				SizeTier.Small,
				1.15f
			},
			{
				SizeTier.ExtraSmall,
				1.35f
			},
			{
				SizeTier.ExtremelySmall,
				1.6f
			}
		};

		private static readonly Dictionary<SizeTier, float> EvasionHealthComp = new Dictionary<SizeTier, float>
		{
			{
				SizeTier.Small,
				0.9f
			},
			{
				SizeTier.ExtraSmall,
				0.8f
			},
			{
				SizeTier.ExtremelySmall,
				0.7f
			}
		};

		private void Awake()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Expected O, but got Unknown
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Expected O, but got Unknown
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Expected O, but got Unknown
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Expected O, but got Unknown
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Expected O, but got Unknown
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Expected O, but got Unknown
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Expected O, but got Unknown
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Expected O, but got Unknown
			Tier = ((BaseUnityPlugin)this).Config.Bind<SizeTier>("General", "SizeTier", SizeTier.Small, "How shrunken you are. Small = 70% size, ExtraSmall = 50%, ExtremelySmall = 30%. Each tier scales the challenge: smaller = slower, weaker jumps, much less damage, but a faster fire rate to partially compensate.");
			ShrinkProjectiles = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShrinkProjectiles", true, "Also physically shrink your projectiles to match your size.");
			UseCustomValues = ((BaseUnityPlugin)this).Config.Bind<bool>("Custom", "UseCustomValues", false, "Ignore the tier presets and use the Custom* values below instead.");
			CustomSize = ((BaseUnityPlugin)this).Config.Bind<float>("Custom", "CustomSize", 0.5f, new ConfigDescription("Model size multiplier", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			CustomMove = ((BaseUnityPlugin)this).Config.Bind<float>("Custom", "CustomMove", 0.7f, new ConfigDescription("Move speed multiplier", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			CustomJump = ((BaseUnityPlugin)this).Config.Bind<float>("Custom", "CustomJump", 0.7f, new ConfigDescription("Jump power multiplier", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			CustomDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Custom", "CustomDamage", 0.55f, new ConfigDescription("Damage multiplier", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			CustomAttackSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Custom", "CustomAttackSpeed", 1.6f, new ConfigDescription("Attack speed multiplier", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "DebugLogging", false, "Log applied multipliers to the console for verification.");
			GiantWeapon = ((BaseUnityPlugin)this).Config.Bind<bool>("Fun", "GiantWeapon", true, "Scale the survivor's weapon UP relative to their shrunken body, so your tiny character lugs a comically oversized gun. Works best on Commando/Bandit/Railgunner-style survivors; best-effort on others.");
			WeaponScale = ((BaseUnityPlugin)this).Config.Bind<float>("Fun", "WeaponScale", 1.6f, new ConfigDescription("How oversized the weapon is relative to the shrunken body.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>()));
			CameraPullIn = ((BaseUnityPlugin)this).Config.Bind<float>("Fun", "CameraPullIn", 0.6f, new ConfigDescription("How much the camera moves down toward your tiny survivor (0 = normal camera, 1 = fully scaled to your size). Makes enemies TOWER over you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			BonusRewards = ((BaseUnityPlugin)this).Config.Bind<bool>("Challenge", "BonusRewards", true, "Earn bonus gold and XP for playing shrunken: +15% (Small), +35% (ExtraSmall), +60% (ExtremelySmall). Risk, meet reward.");
			CompensateEvasion = ((BaseUnityPlugin)this).Config.Bind<bool>("Challenge", "CompensateEvasion", false, "Being tiny makes enemies miss you more. Enable this to trim max HP per tier (-10%/-20%/-30%) so the challenge stays honest.");
			SurvivorSounds = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "SurvivorSounds", true, "Play persona-matched effort sounds when your tiny survivor jumps, lands, and takes hits. Each survivor has a sound personality (soldier grunts, agile breaths, machine servos, beast growls, arcane hums).");
			SoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "SoundVolume", 0.6f, new ConfigDescription("Volume of the survivor sounds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			CharacterBody.Start += new hook_Start(CharacterBody_Start);
			CharacterBody.RecalculateStats += new hook_RecalculateStats(CharacterBody_RecalculateStats);
			ProjectileController.Start += new hook_Start(ProjectileController_Start);
			DeathRewards.OnKilledServer += new hook_OnKilledServer(DeathRewards_OnKilledServer);
			HealthComponent.TakeDamage += new hook_TakeDamage(HealthComponent_TakeDamage);
			SoundBank.Load(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), ((BaseUnityPlugin)this).Logger);
			biggerBulletsPresent = Chainloader.PluginInfos.ContainsKey("dileppy.biggerbullets");
			if (biggerBulletsPresent)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"ShrunkenSurvivor: BiggerBullets detected - deferring all bullet sizing to it. Tune bullet size in BiggerBullets' config for the full tiny-survivor-giant-bullets experience.");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} loaded. Tier={2}", "ShrunkenSurvivor", "1.1.0", Tier.Value));
		}

		private void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			CharacterBody.Start -= new hook_Start(CharacterBody_Start);
			CharacterBody.RecalculateStats -= new hook_RecalculateStats(CharacterBody_RecalculateStats);
			ProjectileController.Start -= new hook_Start(ProjectileController_Start);
		}

		private static TierValues Current()
		{
			if (UseCustomValues.Value)
			{
				return new TierValues(CustomSize.Value, CustomMove.Value, CustomJump.Value, CustomDamage.Value, CustomAttackSpeed.Value);
			}
			return Defaults[Tier.Value];
		}

		private static bool IsPlayer(CharacterBody body)
		{
			if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.master))
			{
				return Object.op_Implicit((Object)(object)body.master.playerCharacterMasterController);
			}
			return false;
		}

		private static void ApplyAbsoluteScale(GameObject go, float factor)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)go))
			{
				return;
			}
			Scene scene = go.scene;
			if (((Scene)(ref scene)).IsValid())
			{
				ShrunkenMarker shrunkenMarker = go.GetComponent<ShrunkenMarker>();
				if (!Object.op_Implicit((Object)(object)shrunkenMarker))
				{
					shrunkenMarker = go.AddComponent<ShrunkenMarker>();
					shrunkenMarker.baseScale = go.transform.localScale;
				}
				go.transform.localScale = shrunkenMarker.baseScale * factor;
			}
		}

		private void CharacterBody_Start(orig_Start orig, CharacterBody self)
		{
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: 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_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			if (!IsPlayer(self))
			{
				return;
			}
			try
			{
				TierValues tierValues = Current();
				ModelLocator modelLocator = self.modelLocator;
				if (Object.op_Implicit((Object)(object)modelLocator) && Object.op_Implicit((Object)(object)modelLocator.modelTransform))
				{
					ApplyAbsoluteScale(((Component)modelLocator.modelTransform).gameObject, tierValues.size);
					if (GiantWeapon.Value && WeaponScale.Value > 1.001f)
					{
						string[] array = new string[15]
						{
							"gun", "weapon", "pistol", "rifle", "musket", "launcher", "crossbow", "bow", "sword", "blade",
							"hammer", "cleaver", "knife", "railgun", "shotgun"
						};
						Transform[] componentsInChildren = ((Component)modelLocator.modelTransform).GetComponentsInChildren<Transform>(true);
						foreach (Transform val in componentsInChildren)
						{
							string text = ((Object)val).name.ToLowerInvariant();
							string[] array2 = array;
							foreach (string value in array2)
							{
								if (text.Contains(value))
								{
									ApplyAbsoluteScale(((Component)val).gameObject, WeaponScale.Value);
									if (DebugLogging.Value)
									{
										((BaseUnityPlugin)this).Logger.LogInfo((object)("ShrunkenSurvivor: giant-weapon scaled bone '" + ((Object)val).name + "'"));
									}
									break;
								}
							}
						}
					}
					if (DebugLogging.Value)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"ShrunkenSurvivor: shrank {self.GetDisplayName()} model to {tierValues.size:P0}");
					}
				}
				if (CameraPullIn.Value > 0.001f)
				{
					CameraTargetParams component = ((Component)self).GetComponent<CameraTargetParams>();
					if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.cameraParams))
					{
						float num = Mathf.Lerp(1f, tierValues.size, CameraPullIn.Value);
						CharacterCameraParams val2 = Object.Instantiate<CharacterCameraParams>(component.cameraParams);
						val2.data.idealLocalCameraPos = BlendableVector3.op_Implicit(component.cameraParams.data.idealLocalCameraPos.value * num);
						val2.data.pivotVerticalOffset = BlendableFloat.op_Implicit(component.cameraParams.data.pivotVerticalOffset.value * num);
						component.cameraParams = val2;
						if (DebugLogging.Value)
						{
							((BaseUnityPlugin)this).Logger.LogInfo((object)$"ShrunkenSurvivor: camera pulled in to {num:P0}");
						}
					}
				}
				SurvivorAudio.Attach(self, ((BaseUnityPlugin)this).Logger);
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"ShrunkenSurvivor: failed to shrink model: {arg}");
			}
		}

		private void CharacterBody_RecalculateStats(orig_RecalculateStats orig, CharacterBody self)
		{
			orig.Invoke(self);
			if (IsPlayer(self))
			{
				TierValues tierValues = Current();
				self.moveSpeed *= tierValues.move;
				self.jumpPower *= tierValues.jump;
				self.damage *= tierValues.damage;
				self.attackSpeed *= tierValues.attackSpeed;
				if (CompensateEvasion.Value && !UseCustomValues.Value)
				{
					self.maxHealth *= EvasionHealthComp[Tier.Value];
				}
			}
		}

		private void DeathRewards_OnKilledServer(orig_OnKilledServer orig, DeathRewards self, DamageReport damageReport)
		{
			if (BonusRewards.Value && !UseCustomValues.Value && damageReport != null && Object.op_Implicit((Object)(object)damageReport.attackerBody) && IsPlayer(damageReport.attackerBody))
			{
				float num = RewardBonus[Tier.Value];
				self.goldReward = (uint)((float)self.goldReward * num);
				self.expReward = (uint)((float)self.expReward * num);
			}
			orig.Invoke(self, damageReport);
		}

		private void HealthComponent_TakeDamage(orig_TakeDamage orig, HealthComponent self, DamageInfo damageInfo)
		{
			orig.Invoke(self, damageInfo);
			if (SurvivorSounds.Value && damageInfo != null && damageInfo.damage > 0f && Object.op_Implicit((Object)(object)self.body) && IsPlayer(self.body))
			{
				SurvivorAudio component = ((Component)self.body).GetComponent<SurvivorAudio>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.PlayHurt();
				}
			}
		}

		private void ProjectileController_Start(orig_Start orig, ProjectileController self)
		{
			orig.Invoke(self);
			if (!ShrinkProjectiles.Value || biggerBulletsPresent || !Object.op_Implicit((Object)(object)self.owner))
			{
				return;
			}
			CharacterBody component = self.owner.GetComponent<CharacterBody>();
			if (!Object.op_Implicit((Object)(object)component) || !IsPlayer(component))
			{
				return;
			}
			try
			{
				TierValues tierValues = Current();
				ApplyAbsoluteScale(((Component)self).gameObject, tierValues.size);
				if (Object.op_Implicit((Object)(object)self.ghost))
				{
					ApplyAbsoluteScale(((Component)self.ghost).gameObject, tierValues.size);
				}
				if (DebugLogging.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"ShrunkenSurvivor: shrank projectile {((Object)((Component)self).gameObject).name} to {tierValues.size:P0}");
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"ShrunkenSurvivor: failed to shrink projectile: {arg}");
			}
		}
	}
	internal static class SoundBank
	{
		private static readonly Dictionary<string, List<AudioClip>> clips = new Dictionary<string, List<AudioClip>>();

		private static readonly (string match, string persona, float pitch)[] Personas = new(string, string, float)[19]
		{
			("CommandoBody", "grunt", 1f),
			("Bandit2Body", "grunt", 0.92f),
			("EngiBody", "grunt", 0.95f),
			("LoaderBody", "grunt", 0.78f),
			("CaptainBody", "grunt", 0.85f),
			("OperatorBody", "grunt", 1.05f),
			("HuntressBody", "light", 1.2f),
			("MercBody", "light", 1.05f),
			("RailgunnerBody", "light", 1.12f),
			("SeekerBody", "light", 1.25f),
			("ToolbotBody", "robot", 0.9f),
			("TreebotBody", "robot", 0.75f),
			("ChefBody", "robot", 1.15f),
			("CrocoBody", "beast", 1f),
			("VoidSurvivorBody", "beast", 0.65f),
			("ChirrBody", "beast", 1.4f),
			("MageBody", "arcane", 1.15f),
			("HereticBody", "arcane", 0.85f),
			("FalseSonBody", "arcane", 0.6f)
		};

		public static bool Loaded { get; private set; }

		public static (string persona, float pitch) PersonaFor(string bodyName)
		{
			(string, string, float)[] personas = Personas;
			for (int i = 0; i < personas.Length; i++)
			{
				(string, string, float) tuple = personas[i];
				if (bodyName.StartsWith(tuple.Item1, StringComparison.OrdinalIgnoreCase))
				{
					return (persona: tuple.Item2, pitch: tuple.Item3);
				}
			}
			return (persona: "grunt", pitch: 1f);
		}

		public static void Load(string pluginDir, ManualLogSource log)
		{
			try
			{
				string path = Path.Combine(pluginDir, "sounds");
				if (!Directory.Exists(path))
				{
					log.LogWarning((object)"ShrunkenSurvivor: sounds folder not found - survivor sounds disabled.");
					return;
				}
				string[] files = Directory.GetFiles(path, "*.wav");
				foreach (string path2 in files)
				{
					AudioClip val = LoadWav(path2);
					if (!((Object)(object)val == (Object)null))
					{
						string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path2);
						int num = fileNameWithoutExtension.LastIndexOf('_');
						string key = ((num > 0) ? fileNameWithoutExtension.Substring(0, num) : fileNameWithoutExtension);
						if (!clips.TryGetValue(key, out var value))
						{
							value = new List<AudioClip>();
							clips[key] = value;
						}
						value.Add(val);
					}
				}
				Loaded = clips.Count > 0;
				log.LogInfo((object)$"ShrunkenSurvivor: loaded {clips.Count} sound groups.");
			}
			catch (Exception arg)
			{
				log.LogError((object)$"ShrunkenSurvivor: sound load failed: {arg}");
			}
		}

		public static AudioClip Pick(string persona, string evt)
		{
			if (clips.TryGetValue(persona + "_" + evt, out var value) && value.Count > 0)
			{
				return value[Random.Range(0, value.Count)];
			}
			return null;
		}

		private static AudioClip LoadWav(string path)
		{
			byte[] array = File.ReadAllBytes(path);
			if (array.Length < 44)
			{
				return null;
			}
			int num = BitConverter.ToInt16(array, 22);
			int num2 = BitConverter.ToInt32(array, 24);
			int num3;
			for (int i = 12; i + 8 < array.Length; i += 8 + num3)
			{
				string text = Encoding.ASCII.GetString(array, i, 4);
				num3 = BitConverter.ToInt32(array, i + 4);
				if (text == "data")
				{
					int num4 = num3 / 2;
					float[] array2 = new float[num4];
					for (int j = 0; j < num4; j++)
					{
						array2[j] = (float)BitConverter.ToInt16(array, i + 8 + j * 2) / 32768f;
					}
					AudioClip obj = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num4 / num, num, num2, false);
					obj.SetData(array2, 0);
					return obj;
				}
			}
			return null;
		}
	}
	internal class SurvivorAudio : MonoBehaviour
	{
		private CharacterBody body;

		private AudioSource source;

		private string persona;

		private float basePitch;

		private bool wasGrounded = true;

		private float lastHurt;

		public static void Attach(CharacterBody b, ManualLogSource log)
		{
			if (ShrunkenSurvivorPlugin.SurvivorSounds.Value && SoundBank.Loaded && !Object.op_Implicit((Object)(object)((Component)b).GetComponent<SurvivorAudio>()))
			{
				SurvivorAudio survivorAudio = ((Component)b).gameObject.AddComponent<SurvivorAudio>();
				survivorAudio.body = b;
				SurvivorAudio survivorAudio2 = survivorAudio;
				(string, float) tuple = SoundBank.PersonaFor(((Object)b).name);
				survivorAudio.persona = tuple.Item1;
				survivorAudio2.basePitch = tuple.Item2;
				survivorAudio.source = ((Component)b).gameObject.AddComponent<AudioSource>();
				survivorAudio.source.spatialBlend = 0f;
				survivorAudio.source.playOnAwake = false;
				log.LogInfo((object)$"ShrunkenSurvivor: audio persona '{survivorAudio.persona}' (pitch {survivorAudio.basePitch:F2}) attached to {((Object)b).name}");
			}
		}

		private void Play(string evt, float volumeScale = 1f)
		{
			AudioClip val = SoundBank.Pick(persona, evt);
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)source))
			{
				source.pitch = basePitch * Random.Range(0.93f, 1.07f);
				source.PlayOneShot(val, ShrunkenSurvivorPlugin.SoundVolume.Value * volumeScale);
			}
		}

		public void PlayHurt()
		{
			if (!(Time.time - lastHurt < 0.6f))
			{
				lastHurt = Time.time;
				Play("hurt");
			}
		}

		private void Update()
		{
			if (Object.op_Implicit((Object)(object)body) && !((Object)(object)body.characterMotor == (Object)null))
			{
				bool isGrounded = body.characterMotor.isGrounded;
				if (wasGrounded && !isGrounded && body.characterMotor.velocity.y > 1f)
				{
					Play("jump");
				}
				else if (!wasGrounded && isGrounded)
				{
					Play("land", 0.8f);
				}
				wasGrounded = isGrounded;
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "ShrunkenSurvivor";

		public const string PLUGIN_NAME = "ShrunkenSurvivor";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}