Decompiled source of BloodbugMode v1.0.3

BloodbugMode.dll

Decompiled 9 hours 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.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DarkMachine.AI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Rewired;
using TrinketAndBindingFramework;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Rendering;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.UI;

[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("BloodbugMode")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3+8d24d5c310cd5f8a91eddbda211de5ea4b5f16bd")]
[assembly: AssemblyProduct("BloodbugMode")]
[assembly: AssemblyTitle("BloodbugMode")]
[assembly: InternalsVisibleTo("BloodbugMode.SelfTest")]
[assembly: AssemblyVersion("1.0.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BloodbugMode
{
	internal static class Balance
	{
		public const float Scale = 0.4f;

		public const float WalkSpeed = 0.7f;

		public const float ThrowStrength = 0.5f;

		public const float CarryStrength = 0.5f;

		public const float LightBodyKnockback = 1.6f;

		public const float WetDrainMultiplier = 2f;

		public const float WetSeconds = 15f;

		public const float InjurySpeed = 12.5f;

		public const float InjuryStaminaLoss = 0.25f;

		public const float InjurySeconds = 60f;

		public const int MaxInjuries = 3;

		public const float CruiseSpeed = 8f;

		public const float BurstSpeed = 14f;

		public const float Inertia = 0.85f;

		public const float Wobble = 0.85f;

		public const float HungryBelow = 0.3f;

		public const float StarvingSpeed = 0.75f;

		public const float MaxStamina = 75f;

		public const float HoverDrain = 7f;

		public const float CruiseDrain = 12f;

		public const float BurstDrain = 16f;

		public const float GroundRegen = 17f;

		public const float PerchRegen = 14f;

		public const float FoodStamina = 40f;

		public const float RoachStamina = 25f;

		public const float PlatinumRoachStamina = 32f;

		public const float RubyRoachStamina = 40f;

		public const float MoonRocksDrain = 0.75f;

		public const float PillSeconds = 35f;

		public const float FloatSeconds = 5f;

		public const float CrashSpeed = 10f;

		public const float CrashBaseDamage = 0.5f;

		public const float CrashDamagePerSpeed = 0.2f;

		public const float FallDistance = 2f;

		public const float ChargeDamage = 3f;

		public const float ChargeStamina = 20f;

		public const float ChargeCooldown = 2.5f;

		public const float FeedStaminaRate = 30f;

		public const float FeedHealRate = 0.3f;

		public const float BloodPerDenizen = 70f;

		public const float ScoreMultiplierBonus = 0.35f;

		public const float BugViewSharpTo = 10f;

		public const float NearClip = 0.375f;

		public const float HearingNear = 4f;

		public const float HearingFar = 16f;

		public const float HearingCutoff = 1200f;

		public const float HearingResonance = 1.5f;
	}
	internal static class BloodbugContent
	{
		public const string PerkId = "Perk_Senkodev_BloodbugForm";

		public const string LightBodyId = "Perk_Senkodev_BloodbugLightBody";

		public const string WetWingsId = "Perk_Senkodev_BloodbugWetWings";

		public const string WingInjuryId = "Perk_Senkodev_BloodbugWingInjury";

		public const string BindingId = "Senkodev_Bloodbug";

		public const string TrinketName = "Trinket_Senkodev_Bloodbug";

		public const string DatabaseId = "senkodev-bloodbugmode";

		public const string FormBuffId = "senkodev-bloodbugform";

		private const string CardArtPerkId = "Perk_Binding_HalfInventory";

		private static WKAssetDatabase database;

		public static Perk Perk { get; private set; }

		public static Sprite Icon { get; private set; }

		public static Sprite Pixel { get; private set; }

		public static Perk LightBody { get; private set; }

		public static Perk WetWings { get; private set; }

		public static Perk WingInjury { get; private set; }

		public static void RegisterBinding()
		{
			Create();
			TrinketRegistry.RegisterBinding("Senkodev_Bloodbug", "Bloodbug Mode", Description(), "", 1, 0.35f, 0f, Icon, (Func<List<Item_Object>>)null, (Func<List<Perk>>)(() => new List<Perk> { Perk }), 0);
			TrinketRegistry.RegisterMutexHub("Senkodev_Bloodbug", new string[1] { "Binding_RoachMode" });
		}

		public static void Register()
		{
			if (!((Object)(object)CL_AssetManager.baseDatabase == (Object)null))
			{
				CL_AssetManager.AddNewDatabase("senkodev-bloodbugmode", database);
				if (GameAssets.Load())
				{
					UseGameCardArt();
				}
			}
		}

		private static string Description()
		{
			return "You were unfortunate enough to become a <color=red>Bloodbug</color>.\nFly on limited stamina, rest on walls and charge at denizens.\nEnable Half Inventory and Survival Mode for the full Bloodbug experience!";
		}

		public static void ApplyBiteKey()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			string text = ((object)Plugin.BiteKey.Value/*cast due to .constrained prefix*/).ToString();
			string text2 = (Plugin.AllowClimbing.Value ? "hammers, pitons, rebars or computers" : "hammers, pitons, rebars, handholds or computers");
			Perk.description = "(+) You can fly and rest on walls and ceilings.\n(+) Press " + text + " to charge at a denizen, hold " + text + " to feed on it.\n(+) Bloodbugs leave you alone.\n(-) You are short-sighted, color blind and hard of hearing.\n(-) You are small, slow on foot and crashing into things hurts.\n(-) No using " + text2 + ".";
			ENT_Player playerObject = ENT_Player.playerObject;
			Perk val = (((Object)(object)playerObject != (Object)null) ? playerObject.GetPerk("Perk_Senkodev_BloodbugForm") : null);
			if ((Object)(object)val != (Object)null)
			{
				val.description = Perk.description;
			}
		}

		private static void Create()
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0109: Expected O, but got Unknown
			Icon = ModFiles.LoadSprite("binding_icon.png", "Binding_Icon_Bloodbug");
			Pixel = ModFiles.WhitePixel();
			Perk = NewPerk("Perk_Senkodev_BloodbugForm", "Bloodbug Mode", (PerkType)9, Icon);
			ApplyBiteKey();
			Perk.flavorText = "bzzzzzz";
			Perk.tags = new List<string> { "binding" };
			Perk.playerTag = new List<string> { "Senkodev_BloodbugKin" };
			Perk.modules = new List<PerkModule> { (PerkModule)(object)new BloodbugModule() };
			Perk.useBuff = true;
			Perk.buff = new BuffContainer
			{
				id = "senkodev-bloodbugform",
				desc = "",
				loseOverTime = false,
				loseRate = 0f,
				buffs = new List<Buff>
				{
					new Buff
					{
						id = "addPlayerScale",
						maxAmount = -0.6f
					}
				}
			};
			LightBody = NewPerk("Perk_Senkodev_BloodbugLightBody", "Light Body", (PerkType)2, ModFiles.LoadSprite("debuff_light_body.png", "Debuff_Icon_LightBody"));
			WetWings = NewPerk("Perk_Senkodev_BloodbugWetWings", "Wet Wings", (PerkType)2, ModFiles.LoadSprite("debuff_wet_wings.png", "Debuff_Icon_WetWings"));
			WingInjury = NewPerk("Perk_Senkodev_BloodbugWingInjury", "Wing Injury", (PerkType)2, ModFiles.LoadSprite("debuff_wing_injury.png", "Debuff_Icon_WingInjury"));
			WingInjury.canStack = true;
			database = ModFiles.Keep<WKAssetDatabase>(ScriptableObject.CreateInstance<WKAssetDatabase>());
			((Object)database).name = "senkodev-bloodbugmode";
			database.id = "senkodev-bloodbugmode";
			database.perkAssets.AddRange((IEnumerable<Perk>)(object)new Perk[4] { Perk, LightBody, WetWings, WingInjury });
			LightBody.description = "(-) You weigh next to nothing.\nBlows, blasts, fans and steam throw you " + Percent(0.6f) + "% further.";
			WetWings.description = "(-) Your wings are soaked.\nFlying costs " + Percent(1f) + "% more stamina until they dry out.";
			WingInjury.description = "(-) A hard crash has torn one of your wings.\nEach injury takes " + Percent(0.25f) + "% off your flight stamina until it heals.";
			WingInjury.stackMax = 3;
		}

		private static Perk NewPerk(string id, string title, PerkType type, Sprite icon)
		{
			//IL_003d: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00c2: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			Perk obj = ModFiles.Keep<Perk>(ScriptableObject.CreateInstance<Perk>());
			((Object)obj).name = id;
			obj.id = id;
			obj.title = title;
			obj.description = "";
			obj.flavorText = "";
			obj.icon = icon;
			obj.perkType = type;
			obj.sortingCategory = -10;
			obj.spawnPool = (PerkPool)2;
			obj.spawnInEndless = false;
			obj.competitive = false;
			obj.removeOnCleanse = false;
			obj.canStack = false;
			obj.stackMax = 1;
			obj.multiplierCurve = AnimationCurve.Constant(0f, 1f, 1f);
			obj.useBuff = false;
			obj.buff = new BuffContainer
			{
				id = "",
				desc = "",
				buffs = new List<Buff>()
			};
			obj.useBaseBuff = false;
			obj.baseBuff = new BuffContainer
			{
				id = "",
				desc = "",
				buffs = new List<Buff>()
			};
			obj.tags = new List<string>();
			obj.flags = new List<string>();
			obj.playerTag = new List<string>();
			obj.modules = new List<PerkModule>();
			obj.unlockProgressionID = "";
			return obj;
		}

		private static void UseGameCardArt()
		{
			Perk val = CL_AssetManager.GetBaseAssetDatabase().perkAssets.Find((Perk perk) => perk.id == "Perk_Binding_HalfInventory");
			if (!((Object)(object)val == (Object)null))
			{
				Perk[] array = (Perk[])(object)new Perk[4] { Perk, LightBody, WetWings, WingInjury };
				foreach (Perk obj in array)
				{
					obj.perkCard = val.perkCard;
					obj.perkFrame = val.perkFrame;
					obj.iconMat = val.iconMat;
				}
			}
		}

		private static string Percent(float fraction)
		{
			return Mathf.RoundToInt(fraction * 100f).ToString();
		}
	}
	internal static class BugHands
	{
		private const string Id = "senkodev-bloodbug-hands";

		private const int CellSize = 128;

		private const int Columns = 10;

		private const string PointerPrefix = "interact-";

		private static Cosmetic_HandItem cosmetic;

		private static bool failed;

		public static Cosmetic_HandItem Cosmetic
		{
			get
			{
				if ((Object)(object)cosmetic == (Object)null && !failed)
				{
					try
					{
						cosmetic = Build();
					}
					catch (Exception arg)
					{
						Plugin.Log.LogError((object)$"failed to build the bug hands: {arg}");
					}
					failed = (Object)(object)cosmetic == (Object)null;
				}
				return cosmetic;
			}
		}

		private static Cosmetic_HandItem Build()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0046: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Expected O, but got Unknown
			string[] array = Encoding.UTF8.GetString(ModFiles.Read("bug_hands.txt")).Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, ModFiles.Read("bug_hands.png"));
			Cosmetic_HandItem_Data val2 = new Cosmetic_HandItem_Data
			{
				id = "senkodev-bloodbug-hands",
				cosmeticName = "Bloodbug",
				author = "senkodev",
				description = "",
				unlock = "",
				globalMaterialBase = "",
				flags = new List<string>(),
				emotes = new List<HandEmote>(),
				palettes = new List<ColorPalette>(),
				allowedSpecialtyPoses = new List<string>(),
				globalSecondary = new List<SecondaryTextures>(),
				swapSprites = new List<SwapSprite>(),
				interactSwaps = new List<InteractSwap>()
			};
			Dictionary<string, List<SwapSprite>> dictionary = new Dictionary<string, List<SwapSprite>>();
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				int x = i % 10 * 128;
				int y = ((Texture)val).height - (i / 10 + 1) * 128;
				Sprite val3 = CutSprite(val, x, y, text);
				if (text.StartsWith("interact-"))
				{
					val2.interactSwaps.Add(new InteractSwap
					{
						spriteName = text,
						replacementSpriteName = text,
						replacementSprite = val3
					});
					continue;
				}
				SwapSprite item = new SwapSprite
				{
					spriteName = text,
					replacementSpriteNames = new List<string> { text },
					replacementSprites = new List<Sprite> { val3 },
					secondaryTextures = new List<SecondaryTextures>(),
					materialBase = ""
				};
				val2.swapSprites.Add(item);
				dictionary[text] = new List<SwapSprite> { item };
			}
			Object.Destroy((Object)(object)val);
			Cosmetic_HandItem obj = ModFiles.Keep<Cosmetic_HandItem>(ScriptableObject.CreateInstance<Cosmetic_HandItem>());
			((Object)obj).name = "Cosmetic_Hand_Senkodev_Bloodbug";
			obj.cosmeticData = val2;
			((Cosmetic_Base)obj).cosmeticInfo = new Cosmetic_Info
			{
				id = "senkodev-bloodbug-hands",
				cosmeticName = val2.cosmeticName,
				tag = "hand",
				author = val2.author,
				description = "",
				unlock = "",
				flags = val2.flags
			};
			SetPrivate(obj, "materialDict", new Dictionary<string, Material>());
			SetPrivate(obj, "hands", new Dictionary<int, HandMaterials>());
			SetPrivate(obj, "swapDict", dictionary);
			SetPrivate(obj, "spriteNames", new Dictionary<Sprite, string>());
			EnsureReturnList();
			Plugin.Log.LogInfo((object)$"bug hands: {val2.swapSprites.Count} poses, {val2.interactSwaps.Count} pointers");
			return obj;
		}

		private static Sprite CutSprite(Texture2D atlas, int x, int y, string name)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			Texture2D obj = ModFiles.Keep<Texture2D>(new Texture2D(128, 128, (TextureFormat)4, false));
			((Object)obj).name = "Bloodbug_" + name;
			obj.SetPixels(atlas.GetPixels(x, y, 128, 128));
			((Texture)obj).filterMode = (FilterMode)0;
			((Texture)obj).wrapMode = (TextureWrapMode)1;
			obj.Apply(false, true);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(0f, 0f, 128f, 128f);
			Sprite obj2 = ModFiles.Keep<Sprite>(Sprite.Create(obj, val, new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0));
			((Object)obj2).name = name;
			return obj2;
		}

		private static void EnsureReturnList()
		{
			FieldInfo fieldInfo = RequireField("returnSprites");
			if (fieldInfo.GetValue(null) == null)
			{
				fieldInfo.SetValue(null, (IList)Activator.CreateInstance(fieldInfo.FieldType));
			}
		}

		private static void SetPrivate(Cosmetic_HandItem target, string name, object value)
		{
			RequireField(name).SetValue(target, value);
		}

		private static FieldInfo RequireField(string name)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(Cosmetic_HandItem), name);
			if (fieldInfo == null)
			{
				throw new MissingFieldException("Cosmetic_HandItem", name);
			}
			return fieldInfo;
		}
	}
	internal static class GameAssets
	{
		public const string MoonRocksId = "Perk_Trinket_MoonRock";

		private const string BloodbugPrefabName = "Denizen_Bloodbug";

		private const string HealedClipName = "player_injury_healed";

		private const string LemonRoachName = "Denizen_Roach_Lemon";

		private static readonly string[] HurtSets = new string[3] { "hurt", "hurt-falling", "hurt-heat" };

		private static readonly string[] DeathSets = new string[1] { "death" };

		private static readonly Dictionary<string, List<AudioClip>> sounds = new Dictionary<string, List<AudioClip>>();

		private static AudioClip healedClip;

		private static int healedClipSearches;

		private static bool loaded;

		public static GameObject BloodbugPrefab { get; private set; }

		public static AudioClip BuzzClip { get; private set; }

		public static AudioClipHandlerOverride Voice { get; private set; }

		public static AudioClip RoachEatClip { get; private set; }

		public static float RoachEatVolume { get; private set; } = 1f;

		public static AudioClip HealedClip
		{
			get
			{
				if ((Object)(object)healedClip != (Object)null || healedClipSearches >= 3)
				{
					return healedClip;
				}
				healedClipSearches++;
				AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>();
				foreach (AudioClip val in array)
				{
					if (((Object)val).name == "player_injury_healed")
					{
						healedClip = val;
						return val;
					}
				}
				Plugin.Log.LogWarning((object)"player_injury_healed isn't loaded");
				return null;
			}
		}

		public static bool Load()
		{
			if (loaded)
			{
				return false;
			}
			loaded = true;
			BloodbugPrefab = FindBloodbugPrefab(CL_AssetManager.GetBaseAssetDatabase());
			if ((Object)(object)BloodbugPrefab != (Object)null)
			{
				AudioSource component = BloodbugPrefab.GetComponent<AudioSource>();
				BuzzClip = (((Object)(object)component != (Object)null) ? component.clip : null);
				Voice = CreateVoice(BloodbugPrefab.GetComponent<UT_AudioClipHandler>());
			}
			GameObject assetGameObject = CL_AssetManager.GetAssetGameObject("Denizen_Roach_Lemon", "");
			Item_Object val = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null);
			HandItem_Buff val2 = (HandItem_Buff)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val2 != (Object)null)
			{
				RoachEatClip = val2.audioClip;
				RoachEatVolume = val2.audioVolume;
			}
			Plugin.Log.LogInfo((object)("game assets: prefab=" + Name((Object)(object)BloodbugPrefab) + ", buzz=" + Name((Object)(object)BuzzClip) + ", " + $"voice={(((Object)(object)Voice != (Object)null) ? Voice.setOverrides.Count : 0)} sets, roach eating={Name((Object)(object)RoachEatClip)}"));
			return true;
		}

		public static AudioClip Sound(string set)
		{
			if (sounds.TryGetValue(set, out var value))
			{
				return value[Random.Range(0, value.Count)];
			}
			return null;
		}

		private static GameObject FindBloodbugPrefab(WKAssetDatabase game)
		{
			GameObject val = null;
			foreach (GameObject denizenPrefab in game.denizenPrefabs)
			{
				if (!((Object)(object)denizenPrefab == (Object)null) && ((Object)denizenPrefab).name.StartsWith("Denizen_Bloodbug") && !((Object)(object)denizenPrefab.GetComponentInChildren<Animator>(true) == (Object)null) && ((Object)(object)val == (Object)null || ((Object)denizenPrefab).name == "Denizen_Bloodbug"))
				{
					val = denizenPrefab;
				}
			}
			return val;
		}

		private static AudioClipHandlerOverride CreateVoice(UT_AudioClipHandler bloodbug)
		{
			if ((Object)(object)bloodbug == (Object)null)
			{
				return null;
			}
			foreach (AudioGroup group in bloodbug.groups)
			{
				foreach (AudioSet audioSet in group.audioSets)
				{
					if (audioSet.clips.Count > 0)
					{
						sounds[audioSet.name] = audioSet.clips;
					}
				}
			}
			sounds.TryGetValue("hurt", out var value);
			if (!sounds.TryGetValue("die", out var value2))
			{
				sounds.TryGetValue("death", out value2);
			}
			AudioClipHandlerOverride val = ModFiles.Keep<AudioClipHandlerOverride>(ScriptableObject.CreateInstance<AudioClipHandlerOverride>());
			((Object)val).name = "Bloodbug_Voice";
			val.setOverrides = new List<AudioSetOverride>();
			AddOverrides(val, HurtSets, value);
			AddOverrides(val, DeathSets, value2);
			if (val.setOverrides.Count <= 0)
			{
				return null;
			}
			return val;
		}

		private static void AddOverrides(AudioClipHandlerOverride voice, string[] playerSets, List<AudioClip> clips)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if (clips != null)
			{
				foreach (string setName in playerSets)
				{
					voice.setOverrides.Add(new AudioSetOverride
					{
						groupName = "player",
						setName = setName,
						clips = clips
					});
				}
			}
		}

		private static string Name(Object asset)
		{
			if (!(asset != (Object)null))
			{
				return "none";
			}
			return asset.name;
		}
	}
	internal static class ModFiles
	{
		private static readonly string Folder = Path.GetDirectoryName(typeof(ModFiles).Assembly.Location);

		public static byte[] Read(string fileName)
		{
			return File.ReadAllBytes(Path.Combine(Folder, fileName));
		}

		public static Sprite LoadSprite(string fileName, string spriteName)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = ModFiles.Keep<Texture2D>(new Texture2D(2, 2, (TextureFormat)4, false));
			((Object)val).name = spriteName;
			ImageConversion.LoadImage(val, Read(fileName));
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height);
			Sprite obj = ModFiles.Keep<Sprite>(Sprite.Create(val, val2, new Vector2(0.5f, 0.5f), 100f));
			((Object)obj).name = spriteName;
			return obj;
		}

		public static Sprite WhitePixel()
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_001c: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			Texture2D obj = ModFiles.Keep<Texture2D>(new Texture2D(1, 1, (TextureFormat)4, false));
			((Object)obj).name = "Bloodbug_Pixel";
			obj.SetPixel(0, 0, Color.white);
			obj.Apply();
			((Texture)obj).filterMode = (FilterMode)0;
			return ModFiles.Keep<Sprite>(Sprite.Create(obj, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 1f));
		}

		public static T Keep<T>(T asset) where T : Object
		{
			((Object)asset).hideFlags = (HideFlags)32;
			return asset;
		}
	}
	internal class BodyOutline
	{
		private class Body
		{
			public Denizen denizen;

			public Renderer[] renderers;
		}

		private const float DepthPush = 0.06f;

		private const float Width = 2f;

		private const float MaxDistance = 25f;

		private static readonly Color EdibleColor = Color32.op_Implicit(new Color32((byte)193, (byte)48, (byte)48, byte.MaxValue));

		private static readonly Color InReachColor = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)150, (byte)150, byte.MaxValue));

		private static readonly Vector2[] Offsets = (Vector2[])(object)new Vector2[8]
		{
			new Vector2(1f, 0f),
			new Vector2(-1f, 0f),
			new Vector2(0f, 1f),
			new Vector2(0f, -1f),
			new Vector2(0.7f, 0.7f),
			new Vector2(-0.7f, 0.7f),
			new Vector2(0.7f, -0.7f),
			new Vector2(-0.7f, -0.7f)
		};

		private static readonly List<Body> bodies = new List<Body>();

		private readonly Camera camera;

		private readonly BloodbugController bug;

		private readonly CommandBuffer buffer;

		private readonly Material edible;

		private readonly Material inReach;

		private bool shown;

		private bool attached;

		public static int Count => bodies.Count;

		private BodyOutline(Camera camera, BloodbugController bug, Shader shader)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			this.camera = camera;
			this.bug = bug;
			edible = FlatMaterial(shader, EdibleColor);
			inReach = FlatMaterial(shader, InReachColor);
			buffer = new CommandBuffer
			{
				name = "Bloodbug prey outline"
			};
		}

		public static BodyOutline Create(Camera camera, BloodbugController bug)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			Shader val = Shader.Find("Hidden/Internal-Colored");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Hidden/Internal-Colored shader not found");
				return null;
			}
			TrackDead(Object.FindObjectsByType<Denizen>((FindObjectsSortMode)0));
			BodyOutline bodyOutline = new BodyOutline(camera, bug, val);
			Camera.onPreRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(bodyOutline.Draw));
			return bodyOutline;
		}

		public static void Track(Denizen denizen)
		{
			if (!bodies.Exists((Body body) => (Object)(object)body.denizen == (Object)(object)denizen))
			{
				bodies.Add(new Body
				{
					denizen = denizen
				});
			}
		}

		public static void TrackDead(IEnumerable<Denizen> denizens)
		{
			foreach (Denizen denizen in denizens)
			{
				if (((GameEntity)denizen).dead)
				{
					Track(denizen);
				}
			}
		}

		public static void Forget()
		{
			bodies.Clear();
		}

		public void Destroy()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(Draw));
			Detach();
			buffer.Release();
			Object.Destroy((Object)(object)edible);
			Object.Destroy((Object)(object)inReach);
		}

		public void Show(bool wanted)
		{
			shown = wanted;
			if (!wanted)
			{
				Detach();
			}
		}

		private void Draw(Camera rendering)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rendering != (Object)(object)camera || !shown)
			{
				return;
			}
			buffer.Clear();
			Matrix4x4 worldToCameraMatrix = camera.worldToCameraMatrix;
			Matrix4x4 projectionMatrix = camera.projectionMatrix;
			Vector2 pixel = default(Vector2);
			((Vector2)(ref pixel))..ctor(4f / (float)camera.pixelWidth, 4f / (float)camera.pixelHeight);
			Vector3 position = ((Component)camera).transform.position;
			bool flag = false;
			for (int num = bodies.Count - 1; num >= 0; num--)
			{
				Body body = bodies[num];
				if ((Object)(object)body.denizen == (Object)null || bug.BloodLeft((GameEntity)(object)body.denizen) <= 0f)
				{
					bodies.RemoveAt(num);
				}
				else
				{
					float num2 = Vector3.Distance(((Component)body.denizen).transform.position, position);
					if (!(num2 > 25f) && ((Component)body.denizen).gameObject.activeInHierarchy)
					{
						if (body.renderers == null)
						{
							body.renderers = ((Component)body.denizen).GetComponentsInChildren<Renderer>(true);
						}
						bool flag2 = (Object)(object)body.denizen == (Object)(object)bug.Prey || num2 <= 1.6f;
						Renderer[] renderers = body.renderers;
						foreach (Renderer renderer in renderers)
						{
							if (CanDraw(renderer))
							{
								DrawShifted(renderer, flag2 ? inReach : edible, worldToCameraMatrix, projectionMatrix, pixel);
								flag = true;
							}
						}
					}
				}
			}
			if (!flag)
			{
				Detach();
				return;
			}
			buffer.SetViewProjectionMatrices(worldToCameraMatrix, projectionMatrix);
			if (!attached)
			{
				camera.AddCommandBuffer((CameraEvent)12, buffer);
				attached = true;
			}
		}

		private void DrawShifted(Renderer renderer, Material material, Matrix4x4 view, Matrix4x4 projection, Vector2 pixel)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = renderer.bounds;
			float num = Mathf.Max(Vector3.Dot(((Bounds)(ref bounds)).center - ((Component)camera).transform.position, ((Component)camera).transform.forward), camera.nearClipPlane * 2f);
			float depth = 0.12f * camera.nearClipPlane / (num * num);
			Vector2[] offsets = Offsets;
			foreach (Vector2 val in offsets)
			{
				buffer.SetViewProjectionMatrices(view, Shift(projection, val.x * pixel.x, val.y * pixel.y, depth));
				for (int j = 0; j < renderer.sharedMaterials.Length; j++)
				{
					buffer.DrawRenderer(renderer, material, j);
				}
			}
		}

		private static bool CanDraw(Renderer renderer)
		{
			if ((Object)(object)renderer != (Object)null && renderer.enabled && ((Component)renderer).gameObject.activeInHierarchy)
			{
				if (!(renderer is SkinnedMeshRenderer))
				{
					return renderer is MeshRenderer;
				}
				return true;
			}
			return false;
		}

		private void Detach()
		{
			if (attached && (Object)(object)camera != (Object)null)
			{
				camera.RemoveCommandBuffer((CameraEvent)12, buffer);
			}
			attached = false;
		}

		private static Matrix4x4 Shift(Matrix4x4 projection, float x, float y, float depth)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Vector4 row = ((Matrix4x4)(ref projection)).GetRow(3);
			((Matrix4x4)(ref projection)).SetRow(0, ((Matrix4x4)(ref projection)).GetRow(0) + row * x);
			((Matrix4x4)(ref projection)).SetRow(1, ((Matrix4x4)(ref projection)).GetRow(1) + row * y);
			((Matrix4x4)(ref projection)).SetRow(2, ((Matrix4x4)(ref projection)).GetRow(2) + row * depth);
			return projection;
		}

		private static Material FlatMaterial(Shader shader, Color color)
		{
			//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_000e: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			Material val = new Material(shader)
			{
				hideFlags = (HideFlags)61,
				color = color
			};
			val.SetInt("_SrcBlend", 1);
			val.SetInt("_DstBlend", 0);
			val.SetInt("_Cull", 0);
			val.SetInt("_ZWrite", 0);
			val.SetInt("_ZTest", 4);
			return val;
		}
	}
	internal class FlightMeter
	{
		private const float Width = 190f;

		private const float Height = 24f;

		private const float IconSize = 24f;

		private const float BarHeight = 14f;

		private const float Border = 2f;

		private static readonly Color Backing = new Color(0f, 0f, 0f, 0.75f);

		private static readonly Color Flying = Color32.op_Implicit(new Color32((byte)193, (byte)48, (byte)48, byte.MaxValue));

		private static readonly Color Recovering = Color32.op_Implicit(new Color32((byte)240, (byte)97, (byte)97, byte.MaxValue));

		private static readonly Color Spent = Color32.op_Implicit(new Color32((byte)107, (byte)107, (byte)107, byte.MaxValue));

		private static readonly Color Pilled = new Color(0f, 0.48f, 1f);

		private GameObject root;

		private RectTransform fill;

		private Image fillImage;

		private float punch;

		public static FlightMeter Create(Transform parent)
		{
			//IL_0024: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			FlightMeter flightMeter = new FlightMeter();
			flightMeter.root = NewElement("BloodbugFlightMeter", parent, out var rect);
			rect.sizeDelta = new Vector2(190f, 24f);
			RectTransform rect2;
			Image obj = NewImage("Icon", (Transform)(object)rect, BloodbugContent.Icon, Color.white, out rect2);
			RectTransform obj2 = rect2;
			RectTransform obj3 = rect2;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 0.5f);
			obj3.anchorMax = val;
			obj2.anchorMin = val;
			rect2.pivot = new Vector2(0f, 0.5f);
			rect2.anchoredPosition = Vector2.zero;
			rect2.sizeDelta = new Vector2(24f, 24f);
			obj.preserveAspect = true;
			NewImage("Backing", (Transform)(object)rect, BloodbugContent.Pixel, Backing, out var rect3);
			rect3.anchorMin = new Vector2(0f, 0.5f);
			rect3.anchorMax = new Vector2(1f, 0.5f);
			rect3.pivot = new Vector2(0.5f, 0.5f);
			rect3.offsetMin = new Vector2(30f, -7f);
			rect3.offsetMax = new Vector2(0f, 7f);
			flightMeter.fillImage = NewImage("Fill", (Transform)(object)rect3, BloodbugContent.Pixel, Flying, out flightMeter.fill);
			flightMeter.fill.anchorMin = Vector2.zero;
			flightMeter.fill.anchorMax = Vector2.one;
			flightMeter.fill.offsetMin = new Vector2(2f, 2f);
			flightMeter.fill.offsetMax = new Vector2(-2f, -2f);
			return flightMeter;
		}

		public void Set(float fraction, BloodbugController.FlightState state, bool tooLowToFly, bool onPills, bool feeding)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			fraction = Mathf.Clamp01(fraction);
			fill.anchorMax = new Vector2(fraction, 1f);
			fill.offsetMax = new Vector2(-2f * fraction, -2f);
			((Graphic)fillImage).color = ColorFor(fraction, state, tooLowToFly, onPills, feeding);
			punch = Mathf.Lerp(punch, 0f, Time.unscaledDeltaTime * 8f);
			root.transform.localScale = Vector3.one * (1f + punch);
		}

		public void Punch()
		{
			punch = 0.25f;
		}

		public void SetVisible(bool visible)
		{
			root.SetActive(visible);
		}

		public void Destroy()
		{
			Object.Destroy((Object)(object)root);
		}

		private static Color ColorFor(float fraction, BloodbugController.FlightState state, bool tooLowToFly, bool onPills, bool feeding)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (onPills)
			{
				return Pulse(Pilled, 1.5f, 0.25f);
			}
			if (feeding)
			{
				return Pulse(Recovering, 3f, 0.4f);
			}
			if (tooLowToFly)
			{
				return Spent;
			}
			if (state != BloodbugController.FlightState.Flying)
			{
				return Recovering;
			}
			if (!(fraction < 0.25f))
			{
				return Flying;
			}
			return Pulse(Flying, 4f, 0.6f);
		}

		private static Color Pulse(Color color, float rate, float amount)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			return Color.Lerp(color, Color.white, Mathf.PingPong(Time.unscaledTime * rate, 1f) * amount);
		}

		private static GameObject NewElement(string name, Transform parent, out RectTransform rect)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.layer = ((Component)parent).gameObject.layer;
			rect = (RectTransform)val.transform;
			((Transform)rect).SetParent(parent, false);
			return val;
		}

		private static Image NewImage(string name, Transform parent, Sprite sprite, Color color, out RectTransform rect)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Image obj = NewElement(name, parent, out rect).AddComponent<Image>();
			obj.sprite = sprite;
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}
	}
	internal class FlyCamera
	{
		private const string FinalCameraName = "FXCam";

		private const int LensLayer = 31;

		private const int BlurLayer = 30;

		private const float Priority = 1000f;

		private const float MaxDistortion = 85f;

		private const float MaxDistortionScale = 1.25f;

		private const float MaxVignette = 0.3f;

		private const float MaxExtraView = 1.3f;

		private const float MaxFieldOfView = 150f;

		private const float FocalLength = 50f;

		private const float MinAperture = 0.7f;

		private const float MaxAperture = 12f;

		private static readonly Vector3 ProtanRed = new Vector3(56.7f, 43.3f, 0f);

		private static readonly Vector3 ProtanGreen = new Vector3(55.8f, 44.2f, 0f);

		private static readonly Vector3 ProtanBlue = new Vector3(0f, 24.2f, 75.8f);

		private readonly PostProcessLayer finalLayer;

		private readonly PostProcessLayer worldLayer;

		private readonly LayerMask finalMask;

		private readonly LayerMask worldMask;

		private readonly bool worldWasEnabled;

		private PostProcessVolume lensVolume;

		private PostProcessVolume blurVolume;

		private LensDistortion distortion;

		private ColorGrading grading;

		private Vignette vignette;

		private DepthOfField depthOfField;

		private bool shown;

		private FlyCamera(PostProcessLayer finalLayer, PostProcessLayer worldLayer)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			this.finalLayer = finalLayer;
			this.worldLayer = worldLayer;
			finalMask = finalLayer.volumeLayer;
			if ((Object)(object)worldLayer != (Object)null)
			{
				worldMask = worldLayer.volumeLayer;
				worldWasEnabled = ((Behaviour)worldLayer).enabled;
			}
		}

		public static FlyCamera Create(ENT_Player player)
		{
			Camera val = FindFinalCamera(player);
			PostProcessLayer val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PostProcessLayer>() : null);
			if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).enabled)
			{
				Plugin.Log.LogWarning((object)"could not apply post-processing on the final camera");
				return null;
			}
			PostProcessLayer val3 = null;
			if ((Object)(object)player.cam != (Object)(object)val)
			{
				val3 = ((Component)player.cam).GetComponent<PostProcessLayer>();
			}
			if ((Object)(object)val3 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"could not apply post-processing on the final camera");
			}
			FlyCamera flyCamera = new FlyCamera(val2, val3);
			flyCamera.CreateVolumes();
			Plugin.Log.LogInfo((object)("bug view: lens on " + ((Object)val).name + ", blur on " + (((Object)(object)val3 != (Object)null) ? ((Object)val3).name : "nothing")));
			return flyCamera;
		}

		public void Show(bool wanted)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)lensVolume == (Object)null || (Object)(object)finalLayer == (Object)null)
			{
				return;
			}
			if (wanted)
			{
				ApplyConfig();
			}
			if (wanted != shown)
			{
				shown = wanted;
				((Behaviour)lensVolume).enabled = wanted;
				finalLayer.volumeLayer = (wanted ? LayerMask.op_Implicit(LayerMask.op_Implicit(finalMask) & -1073741825) : finalMask);
				if (!wanted)
				{
					SetBlur(on: false);
				}
			}
		}

		public float Widen(float fieldOfView)
		{
			float value = Plugin.BugViewFisheye.Value;
			if (!shown || value <= 0f)
			{
				return fieldOfView;
			}
			float num = MathF.PI / 180f * Mathf.Min(160f, 1.6f * Mathf.Max(value * 85f, 1f));
			float num2 = 2f * Mathf.Tan(num * 0.5f);
			float num3 = Mathf.Lerp(1f, 1.25f, value);
			float num4 = 0.5f / num3;
			float num5 = Mathf.Tan(num4 * num) / (num4 * num2) / num3;
			num5 /= Mathf.Lerp(1f, 1.3f, value);
			return Mathf.Min(2f * Mathf.Atan(Mathf.Tan(fieldOfView * 0.5f * (MathF.PI / 180f)) / num5) * 57.29578f, 150f);
		}

		public void Destroy()
		{
			Show(wanted: false);
			if ((Object)(object)lensVolume != (Object)null)
			{
				RuntimeUtilities.DestroyVolume(lensVolume, true, true);
				lensVolume = null;
			}
			if ((Object)(object)blurVolume != (Object)null)
			{
				RuntimeUtilities.DestroyVolume(blurVolume, true, true);
				blurVolume = null;
			}
		}

		private static Camera FindFinalCamera(ENT_Player player)
		{
			Camera[] componentsInChildren = ((Component)((Component)player).transform.root).GetComponentsInChildren<Camera>(true);
			foreach (Camera val in componentsInChildren)
			{
				if (((Object)val).name == "FXCam" && (Object)(object)val.targetTexture == (Object)null)
				{
					return val;
				}
			}
			componentsInChildren = Camera.allCameras;
			foreach (Camera val2 in componentsInChildren)
			{
				if (((Object)val2).name == "FXCam" && (Object)(object)val2.targetTexture == (Object)null)
				{
					return val2;
				}
			}
			return null;
		}

		private void CreateVolumes()
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			distortion = ScriptableObject.CreateInstance<LensDistortion>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)distortion).enabled).Override(true);
			grading = ScriptableObject.CreateInstance<ColorGrading>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)grading).enabled).Override(true);
			((ParameterOverride<GradingMode>)(object)grading.gradingMode).Override((GradingMode)0);
			vignette = ScriptableObject.CreateInstance<Vignette>();
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)vignette).enabled).Override(true);
			((ParameterOverride<VignetteMode>)(object)vignette.mode).Override((VignetteMode)0);
			((ParameterOverride<Color>)(object)vignette.color).Override(Color.black);
			((ParameterOverride<float>)(object)vignette.smoothness).Override(0.45f);
			((ParameterOverride<float>)(object)vignette.roundness).Override(1f);
			lensVolume = PostProcessManager.instance.QuickVolume(31, 1000f, (PostProcessEffectSettings[])(object)new PostProcessEffectSettings[3]
			{
				(PostProcessEffectSettings)distortion,
				(PostProcessEffectSettings)grading,
				(PostProcessEffectSettings)vignette
			});
			((Object)lensVolume).name = "Bloodbug lens";
			((Behaviour)lensVolume).enabled = false;
			if (!((Object)(object)worldLayer == (Object)null))
			{
				depthOfField = ScriptableObject.CreateInstance<DepthOfField>();
				((ParameterOverride<bool>)(object)((PostProcessEffectSettings)depthOfField).enabled).Override(true);
				((ParameterOverride<float>)(object)depthOfField.focalLength).Override(50f);
				blurVolume = PostProcessManager.instance.QuickVolume(30, 1000f, (PostProcessEffectSettings[])(object)new PostProcessEffectSettings[1] { (PostProcessEffectSettings)depthOfField });
				((Object)blurVolume).name = "Bloodbug blur";
				((Behaviour)blurVolume).enabled = false;
			}
		}

		private void ApplyConfig()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: 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)
			float value = Plugin.BugViewFisheye.Value;
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)distortion).enabled).Override(value > 0f);
			((ParameterOverride<float>)(object)distortion.intensity).Override(value * 85f);
			((ParameterOverride<float>)(object)distortion.scale).Override(Mathf.Lerp(1f, 1.25f, value));
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)vignette).enabled).Override(value > 0f);
			((ParameterOverride<float>)(object)vignette.intensity).Override(value * 0.3f);
			float value2 = Plugin.BugViewNoRed.Value;
			Vector3 val = Vector3.Lerp(new Vector3(100f, 0f, 0f), ProtanRed, value2);
			Vector3 val2 = Vector3.Lerp(new Vector3(0f, 100f, 0f), ProtanGreen, value2);
			Vector3 val3 = Vector3.Lerp(new Vector3(0f, 0f, 100f), ProtanBlue, value2);
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)grading).enabled).Override(value2 > 0f);
			((ParameterOverride<float>)(object)grading.mixerRedOutRedIn).Override(val.x);
			((ParameterOverride<float>)(object)grading.mixerRedOutGreenIn).Override(val.y);
			((ParameterOverride<float>)(object)grading.mixerRedOutBlueIn).Override(val.z);
			((ParameterOverride<float>)(object)grading.mixerGreenOutRedIn).Override(val2.x);
			((ParameterOverride<float>)(object)grading.mixerGreenOutGreenIn).Override(val2.y);
			((ParameterOverride<float>)(object)grading.mixerGreenOutBlueIn).Override(val2.z);
			((ParameterOverride<float>)(object)grading.mixerBlueOutRedIn).Override(val3.x);
			((ParameterOverride<float>)(object)grading.mixerBlueOutGreenIn).Override(val3.y);
			((ParameterOverride<float>)(object)grading.mixerBlueOutBlueIn).Override(val3.z);
			float value3 = Plugin.BugViewBlur.Value;
			SetBlur(value3 > 0f);
			if ((Object)(object)depthOfField != (Object)null && value3 > 0f)
			{
				((ParameterOverride<float>)(object)depthOfField.focusDistance).Override(10f);
				((ParameterOverride<float>)(object)depthOfField.aperture).Override(Mathf.Lerp(12f, 0.7f, value3));
				((ParameterOverride<KernelSize>)(object)depthOfField.kernelSize).Override((KernelSize)((value3 > 0.66f) ? 3 : ((!(value3 > 0.33f)) ? 1 : 2)));
			}
		}

		private void SetBlur(bool on)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)blurVolume == (Object)null) && !((Object)(object)worldLayer == (Object)null) && ((Behaviour)blurVolume).enabled != on)
			{
				((Behaviour)blurVolume).enabled = on;
				worldLayer.volumeLayer = (on ? LayerMask.op_Implicit(1073741824) : worldMask);
				((Behaviour)worldLayer).enabled = on || worldWasEnabled;
			}
		}
	}
	internal static class NearHearing
	{
		private struct Saved
		{
			public AudioSource source;

			public AudioRolloffMode mode;

			public float min;

			public float max;

			public AudioLowPassFilter muffle;
		}

		private const float OwnSoundRadius = 0.75f;

		private static readonly List<Saved> changed = new List<Saved>();

		private static readonly Dictionary<AudioSource, AudioLowPassFilter> pooled = new Dictionary<AudioSource, AudioLowPassFilter>();

		public static bool On { get; private set; }

		public static void Turn(bool on)
		{
			if (on != On)
			{
				On = on;
				if (on)
				{
					Adjust(Object.FindObjectsByType<AudioSource>((FindObjectsSortMode)0));
				}
				else
				{
					Restore();
				}
			}
		}

		public static void Pooled(AudioSource source)
		{
			if (!pooled.ContainsKey(source))
			{
				pooled.Add(source, Muffle(source, on: false));
			}
		}

		public static void Played(AudioSource source, Vector3 position, Transform from, float spatial)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)source == (Object)null) && pooled.TryGetValue(source, out var value))
			{
				((Behaviour)value).enabled = On && spatial > 0f && !IsOwn(position, from);
			}
		}

		public static float Fade(Vector3 position)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position2 = ((Component)ENT_Player.playerObject.cam).transform.position;
			return 1f - Mathf.InverseLerp(4f, 16f, Vector3.Distance(position, position2));
		}

		public static bool IsOwn(Vector3 position, Transform from)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)ENT_Player.playerObject).transform;
			if ((Object)(object)from != (Object)null)
			{
				if (!((Object)(object)from == (Object)(object)transform))
				{
					return from.IsChildOf(transform);
				}
				return true;
			}
			return Vector3.Distance(position, transform.position) < 0.75f;
		}

		public static void Adjust(IEnumerable<AudioSource> sources)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)ENT_Player.playerObject).transform;
			foreach (AudioSource source in sources)
			{
				if (!pooled.ContainsKey(source) && !(source.spatialBlend <= 0f) && !((Component)source).transform.IsChildOf(transform))
				{
					changed.Add(new Saved
					{
						source = source,
						mode = source.rolloffMode,
						min = source.minDistance,
						max = source.maxDistance,
						muffle = Muffle(source, on: true)
					});
					source.rolloffMode = (AudioRolloffMode)1;
					source.minDistance = Mathf.Min(source.minDistance, 4f);
					source.maxDistance = Mathf.Min(source.maxDistance, 16f);
				}
			}
		}

		private static AudioLowPassFilter Muffle(AudioSource source, bool on)
		{
			AudioLowPassFilter val = ((Component)source).GetComponent<AudioLowPassFilter>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)source).gameObject.AddComponent<AudioLowPassFilter>();
			}
			val.cutoffFrequency = 1200f;
			val.lowpassResonanceQ = 1.5f;
			((Behaviour)val).enabled = on;
			return val;
		}

		public static void Forget()
		{
			changed.Clear();
			pooled.Clear();
			On = false;
		}

		private static void Restore()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			for (int num = changed.Count - 1; num >= 0; num--)
			{
				Saved saved = changed[num];
				if (!((Object)(object)saved.source == (Object)null))
				{
					saved.source.rolloffMode = saved.mode;
					saved.source.minDistance = saved.min;
					saved.source.maxDistance = saved.max;
					if ((Object)(object)saved.muffle != (Object)null)
					{
						((Behaviour)saved.muffle).enabled = false;
					}
				}
			}
			changed.Clear();
			foreach (AudioLowPassFilter value in pooled.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					((Behaviour)value).enabled = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(DEN_BasicDenizen), "Start")]
	internal static class DenizenStartPatch
	{
		private static void Postfix(DEN_BasicDenizen __instance)
		{
			if (BloodbugKin.IsBloodbug((GameEntity)(object)__instance))
			{
				BloodbugKin.IgnorePlayer(__instance.targetComponent);
			}
			if (NearHearing.On)
			{
				NearHearing.Adjust(((Component)__instance).GetComponentsInChildren<AudioSource>(true));
			}
		}
	}
	[HarmonyPatch]
	internal static class DenizenDeathPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(Denizen).Assembly);
			foreach (Type type in typesFromAssembly)
			{
				if (!typeof(Denizen).IsAssignableFrom(type))
				{
					continue;
				}
				foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type))
				{
					if ((declaredMethod.Name == "Damage" || (declaredMethod.Name == "Kill" && declaredMethod.GetParameters().Length == 2)) && !declaredMethod.IsAbstract && !declaredMethod.IsStatic)
					{
						yield return declaredMethod;
					}
				}
			}
		}

		private static void Postfix(Denizen __instance)
		{
			if (((GameEntity)__instance).dead && BloodbugController.Exists)
			{
				BodyOutline.Track(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(DEN_Roach), "AI")]
	internal static class RoachCrushPatch
	{
		private static void Prefix(DEN_Roach __instance, out bool __state)
		{
			__state = __instance.canSquish && BloodbugController.IsBloodbug(ENT_Player.playerObject);
			if (__state)
			{
				__instance.canSquish = false;
			}
		}

		private static void Finalizer(DEN_Roach __instance, bool __state)
		{
			if (__state)
			{
				__instance.canSquish = true;
			}
		}
	}
	internal static class BloodbugKin
	{
		public const string Tag = "Senkodev_BloodbugKin";

		public static bool IsBloodbug(GameEntity entity)
		{
			if (!((Object)entity).name.StartsWith("Denizen_Bloodbug", StringComparison.OrdinalIgnoreCase))
			{
				if (entity.objectType != null)
				{
					return entity.objectType.IndexOf("bloodbug", StringComparison.OrdinalIgnoreCase) >= 0;
				}
				return false;
			}
			return true;
		}

		public static void Provoke(GameEntity entity)
		{
			DEN_BasicDenizen val = (DEN_BasicDenizen)(object)((entity is DEN_BasicDenizen) ? entity : null);
			if (val != null && IsBloodbug((GameEntity)(object)val))
			{
				List<string> list = new List<string>(val.targetComponent.targetIgnoreTags);
				if (list.Remove("Senkodev_BloodbugKin"))
				{
					val.targetComponent.targetIgnoreTags = list.ToArray();
				}
			}
		}

		public static void IgnorePlayer(AITargetComponent targeting)
		{
			List<string> list = new List<string>(targeting.targetIgnoreTags);
			if (!list.Contains("Senkodev_BloodbugKin"))
			{
				list.Add("Senkodev_BloodbugKin");
				targeting.targetIgnoreTags = list.ToArray();
			}
		}
	}
	[HarmonyPatch]
	internal static class BlockedShotPatch
	{
		private static readonly string[] Methods = new string[3] { "Use", "StartShoot", "Shoot" };

		private static IEnumerable<MethodBase> TargetMethods()
		{
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(HandItem_Shoot).Assembly);
			foreach (Type type in typesFromAssembly)
			{
				if (!typeof(HandItem_Shoot).IsAssignableFrom(type))
				{
					continue;
				}
				string[] methods = Methods;
				foreach (string text in methods)
				{
					MethodInfo methodInfo = AccessTools.DeclaredMethod(type, text, Type.EmptyTypes, (Type[])null);
					if (methodInfo != null && !methodInfo.IsAbstract)
					{
						yield return methodInfo;
					}
				}
			}
		}

		private static bool Prefix(HandItem_Shoot __instance)
		{
			int num;
			if (BloodbugItems.IsRebar(((HandItem)__instance).item) || BloodbugItems.IsPiton(((HandItem)__instance).item))
			{
				num = (BloodbugController.IsBloodbug(((Hand_Base)__instance).hand.GetPlayer()) ? 1 : 0);
				if (num != 0)
				{
					BloodbugItems.Refuse((HandItem)(object)__instance);
				}
			}
			else
			{
				num = 0;
			}
			return num == 0;
		}
	}
	[HarmonyPatch(typeof(HandItem_Piton), "Use")]
	internal static class PitonUsePatch
	{
		private static bool Prefix(HandItem_Piton __instance)
		{
			bool num = BloodbugController.IsBloodbug(((Hand_Base)__instance).hand.GetPlayer());
			if (num)
			{
				BloodbugItems.Refuse((HandItem)(object)__instance);
			}
			return !num;
		}
	}
	[HarmonyPatch(typeof(HandItem_Piton), "PitonHit")]
	internal static class PitonHitPatch
	{
		private static bool Prefix(HandItem_Piton __instance)
		{
			return !BloodbugController.IsBloodbug(((Hand_Base)__instance).hand.GetPlayer());
		}
	}
	[HarmonyPatch(typeof(Inventory), "DropItemIntoWorld")]
	internal static class ItemDropPatch
	{
		private static void Prefix(Item item, out float? __state)
		{
			__state = null;
			if (BloodbugController.IsBloodbug(ENT_Player.playerObject))
			{
				float scale = (BloodbugItems.IsRebar(item) ? 0f : 0.5f);
				__state = item.dropVel;
				item.dropVel = BloodbugItems.ScaledDropVel(item.dropVel, scale);
			}
		}

		private static void Finalizer(Item item, float? __state)
		{
			if (__state.HasValue)
			{
				item.dropVel = __state.Value;
			}
		}
	}
	[HarmonyPatch(typeof(HandItem_Shoot), "CreateProjectile")]
	internal static class ThrowStrengthPatch
	{
		private static void Prefix(HandItem_Shoot __instance, out float? __state)
		{
			__state = null;
			if (BloodbugItems.IsThrown(__instance) && BloodbugController.IsBloodbug(((Hand_Base)__instance).hand.GetPlayer()))
			{
				__state = __instance.shootSpeed;
				__instance.shootSpeed *= 0.5f;
			}
		}

		private static void Finalizer(HandItem_Shoot __instance, float? __state)
		{
			if (__state.HasValue)
			{
				__instance.shootSpeed = __state.Value;
			}
		}
	}
	[HarmonyPatch(typeof(Item_Object), "CanPickup")]
	internal static class HammerPickupPatch
	{
		private static void Postfix(Item_Object __instance, ref bool __result)
		{
			if (__result && __instance.itemData != null && BloodbugItems.IsBanned(__instance.itemData) && BloodbugController.IsBloodbug(ENT_Player.playerObject))
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItemToInventoryScreen")]
	internal static class HammerBagPatch
	{
		private static bool Prefix(Item item)
		{
			if (!BloodbugItems.IsHammer(item) || !BloodbugController.IsBloodbug(ENT_Player.playerObject))
			{
				return true;
			}
			if (ConsoleSpawnPatch.Spawning)
			{
				BloodbugItems.Allow(item);
				return true;
			}
			item.ClearDropObject();
			return false;
		}
	}
	[HarmonyPatch(typeof(CL_GameManager), "SpawnItem")]
	internal static class ConsoleSpawnPatch
	{
		internal static bool Spawning;

		private static void Prefix()
		{
			Spawning = true;
		}

		private static void Finalizer()
		{
			Spawning = false;
		}
	}
	[HarmonyPatch(typeof(HandItem_Melee), "Use")]
	internal static class HammerUsePatch
	{
		private static bool Prefix(HandItem_Melee __instance)
		{
			bool num = BloodbugItems.BlocksSwing(__instance);
			if (num)
			{
				BloodbugItems.Refuse((HandItem)(object)__instance);
			}
			return !num;
		}
	}
	[HarmonyPatch(typeof(HandItem_Melee), "StartUse")]
	internal static class HammerSwingPatch
	{
		private static bool Prefix(HandItem_Melee __instance)
		{
			return !BloodbugItems.BlocksSwing(__instance);
		}
	}
	[HarmonyPatch(typeof(HandItem_Melee), "Hit")]
	internal static class HammerHitPatch
	{
		private static bool Prefix(HandItem_Melee __instance)
		{
			return !BloodbugItems.BlocksSwing(__instance);
		}
	}
	[HarmonyPatch(typeof(HandItem), "Use")]
	internal static class RoachEatPatch
	{
		private static void Prefix(HandItem __instance)
		{
			if (__instance.used || !BloodbugItems.IsEdibleRoach(__instance))
			{
				return;
			}
			ENT_Player player = ((Hand_Base)__instance).hand.GetPlayer();
			if (!BloodbugController.IsBloodbug(player))
			{
				return;
			}
			Animator val = (((Object)(object)__instance.anim != (Object)null) ? __instance.anim : ((Component)__instance).GetComponent<Animator>());
			if (!((Object)(object)val == (Object)null))
			{
				__instance.used = true;
				val.SetTrigger("Use");
				if ((Object)(object)GameAssets.RoachEatClip != (Object)null)
				{
					AudioManager.PlaySound(GameAssets.RoachEatClip, ((Component)player).transform, GameAssets.RoachEatVolume, 1f, 0f, false, 1f, (AudioMixerGroup)null, "");
				}
			}
		}
	}
	[HarmonyPatch(typeof(HandItem), "Activate")]
	internal static class RoachSwallowPatch
	{
		private static void Postfix(HandItem __instance)
		{
			if (__instance.used && BloodbugItems.IsEdibleRoach(__instance))
			{
				BloodbugController.For(((Hand_Base)__instance).hand.GetPlayer())?.EatRoach(__instance.item);
			}
		}
	}
	[HarmonyPatch(typeof(HandItem_Buff), "Activate")]
	internal static class BuffItemActivatePatch
	{
		private static void Postfix(HandItem_Buff __instance)
		{
			ENT_Player localPlayer = CL_GameManager.gMan.localPlayer;
			BloodbugItems.MarkBuff(__instance, localPlayer);
			if (__instance.onEatType != "food")
			{
				BloodbugController.For(localPlayer)?.Eat(BloodbugItems.Meals(__instance));
			}
		}
	}
	[HarmonyPatch(typeof(M_Gamemode), "Finish")]
	internal static class GamemodeFinishPatch
	{
		private static void Prefix(M_Gamemode __instance, out bool? __state)
		{
			__state = null;
			if (Leaderboards.IsBloodbugRun && !AlreadySkipsScoring(__instance))
			{
				__state = WK_Leaderboard_Core.disableLeaderboards;
				WK_Leaderboard_Core.disableLeaderboards = true;
				Plugin.Log.LogInfo((object)"bloodbug run, not submitting to leaderboards");
			}
		}

		private static void Postfix(M_Gamemode __instance, bool hasFinished, bool? __state)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (__state.HasValue && hasFinished && __instance.winCredits > 0 && CL_GameManager.GetRoaches(true) < __instance.winCreditMaximum && !__instance.IsCompetitive())
			{
				CL_ProgressionManager.ShowUnlockPopup(__instance.roachEndSprite, "WIN BONUS", $"{__instance.winCredits} Facility Credits Added", DarkMachineCrayons.gold * 0.5f, (AudioClip)null, false);
				CL_GameManager.AddRoaches(__instance.winCredits, true);
			}
		}

		private static void Finalizer(bool? __state)
		{
			if (__state.HasValue)
			{
				WK_Leaderboard_Core.disableLeaderboards = __state.Value;
			}
		}

		private static bool AlreadySkipsScoring(M_Gamemode gamemode)
		{
			if ((gamemode.allowCheatedScores || !CommandConsole.hasCheated) && (gamemode.allowCheatedScores || CL_GameManager.AreAchievementsAllowed()) && !WorldLoader.customSeed && CL_GameManager.gMan.allowScores)
			{
				return !gamemode.allowLeaderboardScoring;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SteamManager), "UploadGamemodeResults")]
	internal static class SteamUploadPatch
	{
		private static bool Prefix()
		{
			return !Leaderboards.IsBloodbugRun;
		}
	}
	internal static class Leaderboards
	{
		private static bool flown;

		public static bool IsBloodbugRun
		{
			get
			{
				ENT_Player playerObject = ENT_Player.playerObject;
				if (!flown)
				{
					if ((Object)(object)playerObject != (Object)null)
					{
						return playerObject.HasPerk("Perk_Senkodev_BloodbugForm");
					}
					return false;
				}
				return true;
			}
		}

		public static void MarkRun()
		{
			flown = true;
		}

		public static void NewRun()
		{
			flown = false;
		}
	}
	[HarmonyPatch(typeof(ENT_Player), "Start")]
	internal static class PlayerStartPatch
	{
		private static void Postfix()
		{
			Leaderboards.NewRun();
		}
	}
	[HarmonyPatch(typeof(ENT_Player), "Movement")]
	internal static class PlayerMovementPatch
	{
		private static void Prefix(ENT_Player __instance)
		{
			BloodbugController.For(__instance)?.BeforeMovement();
		}

		private static void Postfix(ENT_Player __instance)
		{
			BloodbugController.For(__instance)?.AfterMovement();
		}
	}
	[HarmonyPatch(typeof(ENT_Player), "OnControllerColliderHit")]
	internal static class PlayerColliderHitPatch
	{
		private static void Prefix(ENT_Player __instance, ControllerColliderHit hit)
		{
			BloodbugController.For(__instance)?.OnSurfaceHit(hit);
		}
	}
	[HarmonyPatch(typeof(ENT_Player), "AddForce", new Type[]
	{
		typeof(Vector3),
		typeof(string)
	})]
	internal static class PlayerAddForcePatch
	{
		private static void Prefix(ENT_Player __instance, ref Vector3 v, string source)
		{
			//IL_0002: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			v *= BloodbugController.KnockbackMultiplier(__instance, source);
		}
	}
	[HarmonyPatch(typeof(UT_ForceZone), "FixedUpdate")]
	internal static class ForceZonePatch
	{
		private static void Prefix()
		{
			BloodbugController.activeForceZones++;
		}

		private static void Finalizer()
		{
			BloodbugController.activeForceZones--;
		}
	}
	[HarmonyPatch(typeof(ENT_Player), "GetCurrentMaxFallDistance")]
	internal static class FallDistancePatch
	{
		private static void Postfix(ENT_Player __instance, ref float __result)
		{
			if (BloodbugController.IsBloodbug(__instance))
			{
				__result *= 2f;
			}
		}
	}
	[HarmonyPatch(typeof(ENT_Player), "GrabPropUpdate")]
	internal static class PropCarryPatch
	{
		private static void Prefix(ENT_Player __instance, int hand, out (Rigidbody body, float mass) __state)
		{
			__state = default((Rigidbody, float));
			CL_Prop grabTarget = __instance.hands[hand].grabTarget;
			if (!((Object)(object)grabTarget == (Object)null) && !grabTarget.stuck && !BloodbugItems.IsPlank(grabTarget) && BloodbugController.IsBloodbug(__instance))
			{
				Rigidbody rigidbody = grabTarget.GetRigidbody();
				__state = (body: rigidbody, mass: rigidbody.mass);
				rigidbody.mass /= 0.5f;
			}
		}

		private static void Finalizer((Rigidbody body, float mass) __state)
		{
			if ((Object)(object)__state.body != (Object)null)
			{
				__state.body.mass = __state.mass;
			}
		}
	}
	[HarmonyPatch(typeof(Cosmetic_HandItem), "SpriteSwap")]
	internal static class BugHandsPalettePatch
	{
		private static void Postfix(Cosmetic_HandItem __instance, GameObject root)
		{
			if ((Object)(object)__instance != (Object)(object)BugHands.Cosmetic)
			{
				return;
			}
			SpriteRenderer[] componentsInChildren = root.GetComponentsInChildren<SpriteRenderer>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material sharedMaterial = ((Renderer)componentsInChildren[i]).sharedMaterial;
				if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasFloat("_PaletteBaseBlend"))
				{
					sharedMaterial.SetFloat("_PaletteBaseBlend", 0f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ENT_Player), "SetCameraFov")]
	internal static class CameraFovPatch
	{
		private static void Postfix(ENT_Player __instance)
		{
			BloodbugController bloodbugController = BloodbugController.For(__instance);
			if (!((Object)(object)bloodbugController == (Object)null))
			{
				float fieldOfView = bloodbugController.WidenView(__instance.cam.fieldOfView);
				__instance.cam.fieldOfView = fieldOfView;
				__instance.inventoryCam.fieldOfView = fieldOfView;
			}
		}
	}
	[HarmonyPatch(typeof(AudioManager), "GetPooledAudioSource")]
	internal static class PooledSoundPatch
	{
		internal static AudioSource Last;

		private static void Postfix(AudioSource __result)
		{
			Last = __result;
			if ((Object)(object)__result != (Object)null)
			{
				NearHearing.Pooled(__result);
			}
		}
	}
	[HarmonyPatch(typeof(AudioManager), "PlaySound", new Type[]
	{
		typeof(AudioClip),
		typeof(Vector3),
		typeof(float),
		typeof(float),
		typeof(float),
		typeof(bool),
		typeof(float),
		typeof(AudioMixerGroup),
		typeof(string)
	})]
	internal static class SoundAtPlacePatch
	{
		private static void Prefix(Vector3 position, ref float volume, float spatial)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (NearHearing.On && spatial > 0f)
			{
				volume *= NearHearing.Fade(position);
			}
		}

		private static void Postfix(Vector3 position, float spatial)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			NearHearing.Played(PooledSoundPatch.Last, position, null, spatial);
		}
	}
	[HarmonyPatch(typeof(AudioManager), "PlaySound", new Type[]
	{
		typeof(AudioClip),
		typeof(Transform),
		typeof(float),
		typeof(float),
		typeof(float),
		typeof(bool),
		typeof(float),
		typeof(AudioMixerGroup),
		typeof(string)
	})]
	internal static class SoundOnThingPatch
	{
		private static void Prefix(Transform from, ref float volume, float spatial)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (NearHearing.On && spatial > 0f)
			{
				volume *= NearHearing.Fade(from.position);
			}
		}

		private static void Postfix(Transform from, float spatial)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			NearHearing.Played(PooledSoundPatch.Last, from.position, from, spatial);
		}
	}
	[HarmonyPatch(typeof(M_Level), "Awake")]
	internal static class LevelAwakePatch
	{
		private static void Postfix(M_Level __instance)
		{
			MotherKin.ScanLevel(__instance);
			if (BloodbugController.Exists)
			{
				BodyOutline.TrackDead(((Component)__instance).GetComponentsInChildren<Denizen>(true));
			}
			if (NearHearing.On)
			{
				NearHearing.Adjust(((Component)__instance).GetComponentsInChildren<AudioSource>(true));
			}
		}
	}
	[HarmonyPatch(typeof(SSM_PerkChecker), "Check")]
	internal static class MotherPerkCheckPatch
	{
		private static void Postfix(SSM_PerkChecker __instance, ref float __result)
		{
			if (MotherKin.IsMotherCheck(__instance) && MotherKin.AppliesTo(ENT_Player.GetPlayer()))
			{
				__result = __instance.trueValue;
			}
		}
	}
	[HarmonyPatch(typeof(Localization), "GetLine")]
	internal static class MotherLinePatch
	{
		private static void Postfix(string group, string key, ref string __result)
		{
			if (MotherKin.TryGetLine(group, key, out var line) && MotherKin.AppliesToRun)
			{
				__result = line;
			}
		}
	}
	[HarmonyPatch(typeof(CL_AchievementManager), "SetAchievementValue", new Type[]
	{
		typeof(string),
		typeof(bool)
	})]
	internal static class RoachAchievementPatch
	{
		private static bool Prefix(string name)
		{
			if (!(name != "ACH_ROACHMODE"))
			{
				return !MotherKin.AppliesToRun;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(UT_LocationDataCollector), "LogData")]
	internal static class EndingVisitPatch
	{
		private static void Prefix(UT_LocationDataCollector __instance, out bool __state)
		{
			__state = __instance.locationName == "roachending" && MotherKin.AppliesToRun;
			if (__state)
			{
				__instance.locationName = "senkodev-bloodbugending";
			}
		}

		private static void Finalizer(UT_LocationDataCollector __instance, bool __state)
		{
			if (__state)
			{
				__instance.locationName = "roachending";
			}
		}
	}
	[HarmonyPatch(typeof(UT_GameStateController), "SetGamemode")]
	internal static class EndingSetGamemodePatch
	{
		private static void Prefix(ref M_Gamemode gamemode)
		{
			if (MotherKin.IsGameRoachEnding(gamemode) && MotherKin.AppliesToRun)
			{
				gamemode = MotherKin.EndingFor(gamemode);
			}
		}
	}
	[HarmonyPatch(typeof(UT_GameStateController), "LoadGamemode")]
	internal static class EndingLoadGamemodePatch
	{
		private static void Prefix(ref M_Gamemode gm)
		{
			if (MotherKin.IsGameRoachEnding(gm) && MotherKin.AppliesToRun)
			{
				gm = MotherKin.EndingFor(gm);
			}
		}
	}
	[HarmonyPatch(typeof(CL_AssetManager), "InitializeAssetManager")]
	internal static class AssetManagerReadyPatch
	{
		private static void Postfix()
		{
			BloodbugContent.Register();
		}
	}
	[HarmonyPatch(typeof(CL_Handhold), "CanInteract")]
	internal static class HandholdCanInteractPatch
	{
		private static void Postfix(CL_Handhold __instance, Interaction info, ref bool __result)
		{
			if (__result && BloodbugController.BlocksClimbing(info.player, __instance))
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(Hand), "GrabHold")]
	internal static class HandGrabHoldPatch
	{
		private static bool Prefix(Hand __instance, Transform target)
		{
			return !BloodbugController.BlocksClimbing(__instance.GetPlayer(), ((Component)target).GetComponent<CL_Handhold>());
		}
	}
	[HarmonyPatch(typeof(OS_Computer_Interface), "ActivateComputer")]
	internal static class ComputerUsePatch
	{
		private static bool Prefix()
		{
			return !BloodbugController.IsBloodbug(ENT_Player.playerObject);
		}
	}
	public class BloodbugController : MonoBehaviour
	{
		private enum Charge
		{
			None,
			WindingUp,
			Dashing
		}

		public enum FlightState
		{
			Inactive,
			Grounded,
			Flying,
			Perched,
			Falling,
			Resting
		}

		internal const float FeedReach = 1.6f;

		private const float ChargeWindup = 0.5f;

		private const float ChargeSpeed = 20f;

		private const float ChargeDuration = 0.45f;

		private const float ChargeKnockback = 3f;

		private const float FeedDamageRate = 0.5f;

		private const float StrikeReach = 0.6f;

		private const float StrikeRadius = 0.7f;

		private const float ReboundSpeed = 4f;

		private const float FeedTickSeconds = 0.5f;

		internal static Func<bool> BiteOverride;

		private static readonly Collider[] overlaps = (Collider[])(object)new Collider[48];

		private static KeyCode lastCheckedKey = (KeyCode)0;

		private readonly Dictionary<int, float> bloodLeft = new Dictionary<int, float>();

		private Charge charge;

		private float chargeTimer;

		private float chargeCooldown;

		private Vector3 dashDirection;

		private bool biteHeld;

		private bool bitePressed;

		private GameEntity prey;

		private float feedTick;

		private PerkModule_HungerMeter hunger;

		private static BloodbugController current;

		private ENT_Player player;

		private bool active;

		private bool leaving;

		private int surfaceMask;

		internal const string FoodEatType = "food";

		private const float MaxInjuryLoss = 0.9f;

		private const float MinTakeoffStamina = 10f;

		private const float RecoverStamina = 25f;

		internal static int activeForceZones;

		private float wetTimer;

		private float injuryTimer;

		private Perk wetWings;

		private Perk injury;

		private Perk moonRocks;

		private const float SputterBelow = 0.2f;

		private const float BankSpeed = 6f;

		private const float BankAngle = 10f;

		private const float HealedVolume = 0.6f;

		private readonly HandCosmeticSwap bugHands = new HandCosmeticSwap();

		private FlightMeter meter;

		private AudioSource buzz;

		private BodyOutline outline;

		private FlyCamera eye;

		private bool hasVoice;

		private bool outlineFailed;

		private bool eyeFailed;

		private float bank;

		private float climberNearClip;

		private const float AutoTakeoffDelay = 0.2f;

		private const float JumpTakeoffDelay = 0.04f;

		private const float HoverBrake = 2.5f;

		private const float AirRegen = 3f;

		private const float InjectorSpeedBonus = 0.5f;

		private bool jumpPressed;

		private float airborneTime;

		private float thrust;

		private bool touchedFloor;

		private Vector3 velocityBeforeMove;

		private Vector3 wobbleSeed;

		private const float CrashCooldown = 0.6f;

		private const float CrashStun = 0.4f;

		private const float CrashBounce = 0.4f;

		private const float CrashStaminaLoss = 15f;

		private float stunTimer;

		private float crashCooldown;

		private float pendingCrashDamage;

		private const float PerchIntent = 0.3f;

		private const float PerchReach = 0.5f;

		private const float PerchSkin = 0.05f;

		private const float PerchSettleSpeed = 1f;

		private const float PerchCooldown = 0.4f;

		private const float KnockOffSpeed = 5f;

		private const float CrawlSpeed = 0.75f;

		private const float PushOffSpeed = 4f;

		private float perchCooldown;

		private Vector3 perchNormal;

		private Transform perchSurface;

		private const float ClingGrip = 12f;

		private const float WaterEscapeSeconds = 0.6f;

		private const float RideDepth = 0.04f;

		private const float HeadUnderMargin = 0.05f;

		private const float SurfacingSpeed = 1.6f;

		private const float SinkingSpeed = 0.6f;

		private const float FloatStiffness = 5f;

		private const float FloatDamping = 8f;

		private const float BobHeight = 0.015f;

		private const float BobRate = 2.2f;

		private const float MaxSoak = 3f;

		private float soakedSeconds;

		private float waterEscape;

		public bool IsCharging => charge != Charge.None;

		public bool IsFeeding => (Object)(object)prey != (Object)null;

		internal GameEntity Prey => prey;

		public FlightState State { get; private set; }

		public static bool Exists => (Object)(object)current != (Object)null;

		public float Stamina { get; private set; }

		public bool OnPills { get; private set; }

		public float MaxStamina
		{
			get
			{
				float num = Mathf.Min(0.25f * (float)Injuries, 0.9f);
				return 75f * (1f - num);
			}
		}

		public int Injuries { get; private set; }

		public bool HasWetWings => wetTimer > 0f;

		public bool IsStunned => stunTimer > 0f;

		public Vector3 PerchNormal => perchNormal;

		public bool IsClinging { get; private set; }

		public bool IsAfloat { get; private set; }

		internal float BloodLeft(GameEntity entity)
		{
			if (entity is DEN_Drone || entity is DEN_Turret || entity is DEN_GantryTurret)
			{
				return 0f;
			}
			if (!bloodLeft.TryGetValue(((Object)entity).GetInstanceID(), out var value))
			{
				return 70f;
			}
			return value;
		}

		internal unsafe static string GameBindingFor(KeyCode key)
		{
			//IL_0000: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key == 0)
			{
				return null;
			}
			foreach (ControllerMap allMap in ReInput.players.GetPlayer(0).controllers.maps.GetAllMaps((ControllerType)0))
			{
				foreach (ActionElementMap allMap2 in allMap.AllMaps)
				{
					InputAction action = ReInput.mapping.GetAction(allMap2.actionId);
					if (((object)allMap2.keyCode/*cast due to .constrained prefix*/).ToString() == ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString() && action != null && action.name != "Fly")
					{
						return action.name;
					}
				}
			}
			return null;
		}

		private void ReadBiteKey()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			bool flag = ((BiteOverride != null) ? BiteOverride() : Input.GetKey(Plugin.BiteKey.Value)) && !player.IsInputLocked();
			if (flag && !biteHeld)
			{
				bitePressed = true;
			}
			biteHeld = flag;
		}

		private void WarnIfBiteKeyTaken()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			KeyCode value = Plugin.BiteKey.Value;
			if (value != lastCheckedKey)
			{
				lastCheckedKey = value;
				string text = GameBindingFor(value);
				if (text != null)
				{
					Plugin.Log.LogWarning((object)$"bite key {value} is also the game's {text} key");
					CL_UIManager.instance.highscoreHeader.ShowText($"Bloodbug bite key {value} is also the game's {text} key. Change BiteKey in the mod's config.");
				}
			}
		}

		private void UpdateBite(ref Vector3 vel, float dt)
		{
			//IL_016a: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			chargeCooldown -= dt;
			bool flag = bitePressed;
			bitePressed = false;
			GameEntity previousPrey = prey;
			prey = null;
			if (IsStunned || State == FlightState.Resting)
			{
				EndCharge(0f);
				return;
			}
			if (PlayerAccess.Grappled(player))
			{
				EndCharge(0f);
				if (flag)
				{
					Sting();
				}
				return;
			}
			if (biteHeld && charge == Charge.None)
			{
				GameEntity val = FindPrey();
				if ((Object)(object)val != (Object)null)
				{
					Feed(val, previousPrey, dt);
					return;
				}
			}
			switch (charge)
			{
			case Charge.None:
			{
				bool flag2 = OnPills || Stamina >= 20f;
				if (flag && State == FlightState.Flying && chargeCooldown <= 0f && flag2)
				{
					charge = Charge.WindingUp;
					chargeTimer = 0f;
					PlayBloodbugSound("attack-start", 0.5f);
				}
				break;
			}
			case Charge.WindingUp:
				chargeTimer += dt;
				if (State != FlightState.Flying)
				{
					EndCharge(0f);
				}
				else if (chargeTimer >= 0.5f)
				{
					charge = Charge.Dashing;
					chargeTimer = 0.45f;
					dashDirection = ((Component)player.cam).transform.forward;
					if (!OnPills)
					{
						Stamina = Mathf.Max(Stamina - 20f, 0f);
					}
					PlayBloodbugSound("attack-activate", 0.6f);
				}
				break;
			case Charge.Dashing:
			{
				chargeTimer -= dt;
				Damageable val2 = ((State == FlightState.Flying) ? FindChargeTarget() : null);
				if (val2 != null)
				{
					Strike(ref vel, val2);
				}
				else if (State != FlightState.Flying || chargeTimer <= 0f)
				{
					vel = Vector3.ClampMagnitude(vel, 8f / 175f);
					EndCharge(2.5f);
				}
				break;
			}
			}
		}

		private void Sting()
		{
			((GameEntity)player).ClearGrapple();
			chargeCooldown = 2.5f;
			PlayBloodbugSound("attack-activate", 0.6f);
			CL_CameraControl.Shake(0.05f);
			player.SplatterScreenBlood(1);
		}

		private void EndCharge(float cooldown)
		{
			if (charge != Charge.None)
			{
				charge = Charge.None;
				chargeCooldown = cooldown;
			}
		}

		private void Strike(ref Vector3 vel, Damageable target)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			DamageInfo val = DamageInfo.CreateDamageInfo(3f, (GameEntity)(object)player, "bloodbug");
			val.position = player.GetControllerPosition();
			val.direction = dashDirection;
			DamageInfo val2 = val;
			if (val2.tags == null)
			{
				val2.tags = new List<string>();
			}
			GameEntity val3 = (GameEntity)(object)((target is GameEntity) ? target : null);
			if (val3 != null)
			{
				BloodbugKin.Provoke(val3);
				val3.AddForce((dashDirection + Vector3.up * 0.3f) * 3f, "denizen");
			}
			target.Damage(val);
			vel = -dashDirection * (4f / 175f);
			crashCooldown = 0.6f;
			perchCooldown = 0.4f;
			PlayBloodbugSound("hurt-impact", 0.5f);
			CL_CameraControl.Shake(0.08f);
			player.SplatterScreenBlood(1);
			EndCharge(2.5f);
		}

		private void Feed(GameEntity target, GameEntity previousPrey, float dt)
		{
			float num = BloodLeft(target);
			if (num <= 0f)
			{
				return;
			}
			prey = target;
			if ((Object)(object)previousPrey != (Object)(object)target)
			{
				feedTick = 0f;
				PlayBloodbugSound("attack-start", 0.35f);
				player.SplatterScreenBlood(1);
			}
			float num2 = Mathf.Min(30f * dt, num);
			bloodLeft[((Object)target).GetInstanceID()] = num - num2;
			Stamina = Mathf.Min(Stamina + num2, MaxStamina);
			((GameEntity)player).Heal(0.3f * dt);
			FillHunger(num2 / 70f);
			feedTick -= dt;
			if (!(feedTick > 0f))
			{
				feedTick = 0.5f;
				CL_CameraControl.Shake(0.01f);
				if (!target.dead)
				{
					BloodbugKin.Provoke(target);
					target.Damage(DamageInfo.CreateDamageInfo(0.25f, (GameEntity)(object)player, "bloodbug"));
				}
			}
		}

		internal void EatRoach(Item roach)
		{
			float num = BloodbugItems.RoachStamina(roach);
			Stamina = Mathf.Min(Stamina + num, MaxStamina);
			FillHunger(num / 70f);
		}

		private void FillHunger(float share)
		{
			if (hunger != null)
			{
				hunger.hungerMeter = Mathf.Min(hunger.hungerMeter + share * hunger.hungerMax, hunger.hungerMax);
			}
		}

		private float HungerSpeed()
		{
			if (hunger == null)
			{
				return 1f;
			}
			float num = hunger.hungerMeter / hunger.hungerMax;
			return Mathf.Lerp(0.75f, 1f, num / 0.3f);
		}

		private PerkModule_HungerMeter FindHunger()
		{
			foreach (Perk perk in player.perks)
			{
				foreach (PerkModule module in perk.modules)
				{
					PerkModule_HungerMeter val = (PerkModule_HungerMeter)(object)((module is PerkModule_HungerMeter) ? module : null);
					if (val != null)
					{
						return val;
					}
				}
			}
			return null;
		}

		private GameEntity FindPrey()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)player.cam).transform;
			int num = Physics.OverlapSphereNonAlloc(transform.position + transform.forward * 0.8f, 1f, overlaps, -1, (QueryTriggerInteraction)2);
			GameEntity result = null;
			float num2 = float.MaxValue;
			for (int i = 0; i < num; i++)
			{
				GameEntity obj = EntityOf(overlaps[i]);
				Denizen val = (Denizen)(object)((obj is Denizen) ? obj : null);
				if (val != null)
				{
					Vector3 val2 = overlaps[i].ClosestPoint(transform.position) - transform.position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num2)
					{
						result = (GameEntity)(object)val;
						num2 = sqrMagnitude;
					}
				}
			}
			return result;
		}

		private Damageable FindChargeTarget()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			int num = Physics.OverlapSphereNonAlloc(player.GetControllerPosition() + dashDirection * 0.6f, 0.7f, overlaps, -1, (QueryTriggerInteraction)2);
			for (int i = 0; i < num; i++)
			{
				GameEntity val = EntityOf(overlaps[i]);
				if ((Object)(object)val != (Object)null && !val.dead && val.damageable)
				{
					return (Damageable)(object)val;
				}
			}
			for (int j = 0; j < num; j++)
			{
				UT_Damage componentInParent = ((Component)overlaps[j]).GetComponentInParent<UT_Damage>();
				if ((Object)(object)componentInParent != (Object)null && componentInParent.canDamage && !((Component)componentInParent).transform.IsChildOf(((Component)player).transform))
				{
					return (Damageable)(object)componentInParent;
				}
			}
			return null;
		}

		private GameEntity EntityOf(Collider collider)
		{
			GameEntity val = GameEntity.GetGameEntity(((Component)collider).gameObject);
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)collider).GetComponentInParent<GameEntity>();
			}
			if (!((Object)(object)val == (Object)(object)player))
			{
				return val;
			}
			return null;
		}

		public static BloodbugController For(ENT_Player player)
		{
			if (!((Object)(object)current != (Object)null) || !((Object)(object)current.player == (Object)(object)player))
			{
				return null;
			}
			return current;
		}

		public static bool IsBloodbug(ENT_Player player)
		{
			BloodbugController bloodbugController = For(player);
			if ((Object)(object)bloodbugController != (Object)null)
			{
				return bloodbugController.active;
			}
			return false;
		}

		public static bool BlocksClimbing(ENT_Player player, CL_Handhold handhold)
		{
			if (IsBloodbug(player) && !Plugin.AllowClimbing.Value)
			{
				return !BloodbugItems.IsRemoteMarker((Component)(object)handhold);
			}
			return false;
		}

		internal void Leave()
		{
			leaving = true;
		}

		private void Awake()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			current = this;
			player = ((Component)this).GetComponent<ENT_Player>();
			wobbleSeed = new Vector3(Random.Range(0f, 100f), Random.Range(0f, 100f), Random.Range(0f, 100f));
			for (int i = 0; i < 32; i++)
			{
				if (i != ((Component)this).gameObject.layer && !Physics.GetIgnoreLayerCollision(((Component)this).gameObject.layer, i))
				{
					surfaceMask |= 1 << i;
				}
			}
		}

		private void Update()
		{
			if (leaving)
			{
				if (active)
				{
					Deactivate(keepDebuffs: false);
				}
				else
				{
					RemoveDebuffs();
				}
				Object.Destroy((Object)(object)this);
				return;
			}
			if (!((GameEntity)player).dead && !active)
			{
				Activate();
			}
			else if (((GameEntity)player).dead && active)
			{
				Deactivate(keepDebuffs: true);
			}
			if (active)
			{
				if (InputManager.GetButton("Jump").Down)
				{
					jumpPressed = true;