Decompiled source of Drinkable v1.1.0

Drinkable.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CSync.Extensions;
using CSync.Lib;
using Frailty;
using Frailty.Manager;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
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("Drinkable")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("Drinkable")]
[assembly: AssemblyTitle("Drinkable")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DrinkableSoda
{
	internal static class Assets
	{
		private static readonly Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>();

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

		private static readonly Dictionary<string, Texture2D> cans = new Dictionary<string, Texture2D>();

		internal static byte[] Read(string name)
		{
			using Stream stream = typeof(Assets).Assembly.GetManifestResourceStream("DrinkableSoda." + name);
			if (stream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		internal static Sprite Icon(string name)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_005e: 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)
			if (sprites.TryGetValue(name, out var value))
			{
				return value;
			}
			value = null;
			try
			{
				byte[] array = Read("Icons." + name + ".png");
				if (array != null)
				{
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
					ImageConversion.LoadImage(val, array);
					((Texture)val).wrapMode = (TextureWrapMode)1;
					value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
					((Object)value).name = name;
				}
				else
				{
					Plugin.Log.LogWarning((object)("Missing icon " + name));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Icon " + name + ": " + ex.Message));
			}
			sprites[name] = value;
			return value;
		}

		internal static Texture2D CanTexture(string key)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			if (cans.TryGetValue(key, out var value))
			{
				return value;
			}
			value = null;
			try
			{
				byte[] array = Read("Cans." + key + ".png");
				if (array != null)
				{
					value = new Texture2D(2, 2, (TextureFormat)4, true);
					ImageConversion.LoadImage(value, array, false);
					((Object)value).name = "DrinkableSoda_" + key;
					((Texture)value).wrapMode = (TextureWrapMode)1;
					((Texture)value).filterMode = (FilterMode)1;
					((Texture)value).anisoLevel = 4;
					value.Apply(true, true);
				}
				else
				{
					Plugin.Log.LogWarning((object)("Missing can texture " + key));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Can " + key + ": " + ex.Message));
			}
			cans[key] = value;
			return value;
		}

		internal static Texture2D MachineTexture(string name)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			string text = "Machine." + name;
			if (cans.TryGetValue(text, out var value))
			{
				return value;
			}
			value = null;
			try
			{
				byte[] array = Read(text + ".png");
				if (array != null)
				{
					value = new Texture2D(2, 2, (TextureFormat)4, true);
					ImageConversion.LoadImage(value, array, false);
					((Object)value).name = "SodaMachine_" + name;
					((Texture)value).wrapMode = (TextureWrapMode)1;
					((Texture)value).anisoLevel = 4;
					value.Apply(true, true);
				}
				else
				{
					Plugin.Log.LogWarning((object)("Missing machine texture " + name));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Machine texture " + name + ": " + ex.Message));
			}
			cans[text] = value;
			return value;
		}

		internal static Sprite CanIcon(string key)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			string text = key + "_icon";
			if (sprites.TryGetValue(text, out var value))
			{
				return value;
			}
			value = null;
			try
			{
				byte[] array = Read("Cans." + text + ".png");
				if (array != null)
				{
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
					ImageConversion.LoadImage(val, array);
					((Texture)val).wrapMode = (TextureWrapMode)1;
					value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
					((Object)value).name = text;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Icon " + text + ": " + ex.Message));
			}
			sprites[text] = value;
			return value;
		}

		internal static AudioClip Sound(string name)
		{
			if (clips.TryGetValue(name, out var value))
			{
				return value;
			}
			value = null;
			try
			{
				byte[] array = Read("Sounds." + name + ".wav");
				if (array != null)
				{
					value = LoadWav(name, array);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Sound " + name + ": " + ex.Message));
			}
			clips[name] = value;
			return value;
		}

		private static AudioClip LoadWav(string name, byte[] d)
		{
			int num = 1;
			int num2 = 44100;
			int num3 = 16;
			int num4 = -1;
			int num5 = 0;
			int num6;
			for (int i = 12; i + 8 <= d.Length; i += 8 + num6 + (num6 & 1))
			{
				string text = Encoding.ASCII.GetString(d, i, 4);
				num6 = BitConverter.ToInt32(d, i + 4);
				if (text == "fmt ")
				{
					num = BitConverter.ToInt16(d, i + 10);
					num2 = BitConverter.ToInt32(d, i + 12);
					num3 = BitConverter.ToInt16(d, i + 22);
				}
				else if (text == "data")
				{
					num4 = i + 8;
					num5 = Math.Min(num6, d.Length - num4);
					break;
				}
			}
			if (num4 < 0 || num3 != 16)
			{
				throw new Exception("unsupported wav");
			}
			int num7 = num5 / 2;
			float[] array = new float[num7];
			for (int j = 0; j < num7; j++)
			{
				array[j] = (float)BitConverter.ToInt16(d, num4 + j * 2) / 32768f;
			}
			AudioClip obj = AudioClip.Create(name, num7 / num, num, num2, false);
			obj.SetData(array, 0);
			return obj;
		}
	}
	internal static class BuffInfo
	{
		internal static readonly Color Gold = new Color(1f, 0.72f, 0.11f);

		internal static readonly Color Cyan = new Color(0f, 0.86f, 1f);

		internal static readonly Color Green = new Color(0.35f, 1f, 0.45f);

		internal static readonly Color Pink = new Color(1f, 0.55f, 0.75f);

		internal static readonly Color Purple = new Color(0.75f, 0.5f, 1f);

		internal static readonly Color Red = new Color(1f, 0f, 0.216f);

		internal static readonly Color Ice = new Color(0.6f, 0.78f, 1f);

		internal static string Title(BuffKind k)
		{
			return k switch
			{
				BuffKind.SugarRush => "Sugar Rush", 
				BuffKind.WebRush => "Sugar Rush+", 
				BuffKind.SugarCrash => "Sugar Crash", 
				BuffKind.Hydration => "Hydration", 
				BuffKind.Dehydration => "Dehydration", 
				BuffKind.Regeneration => "Regeneration", 
				BuffKind.SugarMend => "Sugar Mend", 
				BuffKind.Brawn => "Brawn", 
				BuffKind.Swift => "Swift", 
				BuffKind.Spring => "Spring", 
				BuffKind.SecondWind => "Second Wind", 
				BuffKind.Endurance => "Endurance", 
				BuffKind.Hyponatremia => "Hyponatremia", 
				BuffKind.Equilibrium => "Equilibrium", 
				BuffKind.BorrowedTime => "Borrowed Time", 
				BuffKind.Equivalence => "Equivalence", 
				BuffKind.SharpSight => "Sharp Sight", 
				BuffKind.Exquisite => "Exquisite", 
				BuffKind.CheeseSense => "Cheese Sense", 
				BuffKind.Grounded => "Grounded", 
				BuffKind.Numb => "Numb", 
				_ => k.ToString(), 
			};
		}

		internal static string Description(BuffKind k)
		{
			switch (k)
			{
			case BuffKind.SugarRush:
				return "You move a bit faster and jump a bit higher. A Sugar Crash may follow.";
			case BuffKind.WebRush:
				return "A stronger, longer Sugar Rush: faster and higher jumps. A longer Sugar Crash may follow.";
			case BuffKind.SugarCrash:
				return "Your stamina refills slower.";
			case BuffKind.Hydration:
				return "While you drink, your stamina refills much faster.";
			case BuffKind.Dehydration:
				return "Salty! While you drink, your stamina drains.";
			case BuffKind.Regeneration:
				return "You slowly heal over time.";
			case BuffKind.SugarMend:
				return "You slowly heal over time and your stamina refills faster.";
			case BuffKind.Brawn:
				return "Carried weight slows you down and tires you less. Melee hits deal much more damage.";
			case BuffKind.Swift:
				return "You walk and run faster.";
			case BuffKind.Spring:
				return "You jump higher.";
			case BuffKind.SecondWind:
				return "Your stamina refills faster.";
			case BuffKind.Endurance:
				return "Sprinting drains less stamina.";
			case BuffKind.Hyponatremia:
				return "Too much Mystery Soda. You run slower, jump lower and sprinting costs more stamina.";
			case BuffKind.Equilibrium:
				if (!FrailtyBridge.Installed)
				{
					return "You take less damage. Getting hit can give Borrowed Time.";
				}
				return "You take less damage and new injuries last shorter. Getting hit can give Borrowed Time and Equivalence.";
			case BuffKind.BorrowedTime:
				return "You were hit: you run faster and sprinting costs no stamina for a moment.";
			case BuffKind.Equivalence:
				return "For a moment your injuries and debuffs do nothing. Their time still runs out.";
			case BuffKind.SharpSight:
				return "You see wider, and dark places are easier to see in.";
			case BuffKind.Exquisite:
				return "You move faster, jump higher, climb faster and your stamina refills faster.";
			case BuffKind.CheeseSense:
				return "Inside the facility, arrows at the top of your screen point to the nearest scrap and the nearest exit.";
			case BuffKind.Grounded:
				return "You don't sink in quicksand and lightning doesn't hit you.";
			case BuffKind.Numb:
				return "The pills dull the pain: you take less damage.";
			default:
				return "";
			}
		}

		internal static Color Color(BuffKind k)
		{
			//IL_0056: 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)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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)
			switch (k)
			{
			case BuffKind.SugarCrash:
			case BuffKind.Dehydration:
			case BuffKind.Hyponatremia:
				return Red;
			case BuffKind.Hydration:
			case BuffKind.Equilibrium:
			case BuffKind.Equivalence:
				return Cyan;
			case BuffKind.Regeneration:
			case BuffKind.SugarMend:
				return Green;
			case BuffKind.SharpSight:
				return Pink;
			case BuffKind.Numb:
				return Ice;
			case BuffKind.Exquisite:
			case BuffKind.CheeseSense:
				return Purple;
			default:
				return Gold;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class BuffPatches
	{
		private static bool applied;

		private static float savedSpeed;

		private static float newSpeed;

		private static float savedJump;

		private static float newJump;

		private static float savedClimb;

		private static float newClimb;

		private static float savedCarry;

		private static float newCarry;

		private static float staminaBefore = -1f;

		private static float lateCarrySaved;

		private static float lateCarryNew;

		private static bool lateCarry;

		private static float fovApplied;

		private static readonly HashSet<string> logged = new HashSet<string>();

		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		[HarmonyPriority(200)]
		private static void UpdatePrefix(PlayerControllerB __instance)
		{
			applied = false;
			if (!Local.Is(__instance) || SodaConfig.Instance == null)
			{
				return;
			}
			try
			{
				Buffs.Tick(__instance);
				if (fovApplied != 0f && (Object)(object)__instance.gameplayCamera != (Object)null)
				{
					Camera gameplayCamera = __instance.gameplayCamera;
					gameplayCamera.fieldOfView -= fovApplied;
				}
				float num = Buffs.SpeedMul();
				float num2 = Buffs.JumpMul();
				float num3 = Buffs.ClimbMul();
				float num4 = Buffs.CarryReduce();
				if (num != 1f || num2 != 1f || num3 != 1f || num4 != 0f)
				{
					savedSpeed = __instance.movementSpeed;
					newSpeed = savedSpeed * num;
					__instance.movementSpeed = newSpeed;
					savedJump = __instance.jumpForce;
					newJump = savedJump * Mathf.Sqrt(Mathf.Max(0.01f, num2));
					__instance.jumpForce = newJump;
					if (num2 < 1f && __instance.fallValueUncapped > newJump)
					{
						__instance.fallValueUncapped = newJump;
					}
					savedClimb = __instance.climbSpeed;
					newClimb = savedClimb * num3;
					__instance.climbSpeed = newClimb;
					savedCarry = __instance.carryWeight;
					newCarry = 1f + Mathf.Max(0f, savedCarry - 1f) * (1f - num4);
					__instance.carryWeight = newCarry;
					applied = true;
				}
			}
			catch (Exception e)
			{
				Once("update", e);
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyFinalizer]
		private static void UpdateFinalizer(PlayerControllerB __instance)
		{
			if (!Local.Is(__instance))
			{
				return;
			}
			if (applied)
			{
				applied = false;
				__instance.movementSpeed = Restore(__instance.movementSpeed, savedSpeed, newSpeed);
				__instance.jumpForce = Restore(__instance.jumpForce, savedJump, newJump);
				__instance.climbSpeed = Restore(__instance.climbSpeed, savedClimb, newClimb);
				__instance.carryWeight = Restore(__instance.carryWeight, savedCarry, newCarry);
			}
			try
			{
				float num = Buffs.FovAdd();
				fovApplied = Mathf.MoveTowards(fovApplied, num, 30f * Time.deltaTime);
				if (fovApplied != 0f && (Object)(object)__instance.gameplayCamera != (Object)null)
				{
					Camera gameplayCamera = __instance.gameplayCamera;
					gameplayCamera.fieldOfView += fovApplied;
				}
				Visuals.Update(__instance);
			}
			catch (Exception e)
			{
				Once("visuals", e);
			}
		}

		private static float Restore(float now, float saved, float changed)
		{
			if (!Mathf.Approximately(now, changed))
			{
				return now + (saved - changed);
			}
			return saved;
		}

		[HarmonyPatch("LateUpdate")]
		[HarmonyPrefix]
		[HarmonyPriority(200)]
		private static void LatePrefix(PlayerControllerB __instance)
		{
			staminaBefore = -1f;
			lateCarry = false;
			if (Local.Is(__instance) && SodaConfig.Instance != null && Buffs.All != null)
			{
				staminaBefore = __instance.sprintMeter;
				float num = Buffs.CarryReduce();
				if (num > 0f)
				{
					lateCarrySaved = __instance.carryWeight;
					lateCarryNew = 1f + Mathf.Max(0f, lateCarrySaved - 1f) * (1f - num);
					__instance.carryWeight = lateCarryNew;
					lateCarry = true;
				}
			}
		}

		[HarmonyPatch("LateUpdate")]
		[HarmonyPostfix]
		[HarmonyPriority(600)]
		private static void LatePostfix(PlayerControllerB __instance)
		{
			if (lateCarry)
			{
				__instance.carryWeight = Restore(__instance.carryWeight, lateCarrySaved, lateCarryNew);
				lateCarry = false;
			}
			if (staminaBefore < 0f)
			{
				return;
			}
			try
			{
				float num = __instance.sprintMeter - staminaBefore;
				if (num > 0f)
				{
					__instance.sprintMeter = Mathf.Clamp01(staminaBefore + num * Buffs.RefillMul());
				}
				else if (num < 0f)
				{
					__instance.sprintMeter = Mathf.Clamp01(staminaBefore + num * Buffs.DrainMul());
				}
				if (Buffs.Has(BuffKind.Dehydration))
				{
					__instance.sprintMeter = Mathf.Clamp01(__instance.sprintMeter - SodaConfig.Instance.DehydrationDrain.Value * Time.deltaTime);
				}
			}
			catch (Exception e)
			{
				Once("stamina", e);
			}
			staminaBefore = -1f;
		}

		[HarmonyPatch("DamagePlayer")]
		[HarmonyPrefix]
		[HarmonyPriority(600)]
		private static bool Damage(PlayerControllerB __instance, ref int damageNumber, bool fallDamage)
		{
			if (!Local.Is(__instance) || SodaConfig.Instance == null)
			{
				return true;
			}
			if (Lightning.Striking && Buffs.Has(BuffKind.Grounded))
			{
				return false;
			}
			float num = Buffs.DamageMul();
			if (num < 1f && damageNumber > 0)
			{
				damageNumber = Mathf.Max(1, Mathf.RoundToInt((float)damageNumber * num));
			}
			if (!FrailtyBridge.Installed && damageNumber > 0 && !fallDamage && Buffs.Has(BuffKind.Equilibrium) && SodaConfig.Instance.BorrowedTime.Value > 0f && !__instance.isPlayerDead && __instance.AllowPlayerDeath())
			{
				Buffs.Add(BuffKind.BorrowedTime, SodaConfig.Instance.BorrowedTime.Value);
			}
			return true;
		}

		[HarmonyPatch("KillPlayer")]
		[HarmonyPrefix]
		[HarmonyPriority(600)]
		private static bool Kill(PlayerControllerB __instance)
		{
			if (Local.Is(__instance) && Lightning.Striking)
			{
				return !Buffs.Has(BuffKind.Grounded);
			}
			return true;
		}

		[HarmonyPatch("CheckConditionsForSinkingInQuicksand")]
		[HarmonyPostfix]
		private static void Quicksand(PlayerControllerB __instance, ref bool __result)
		{
			if (__result && Local.Is(__instance) && Buffs.Has(BuffKind.Grounded))
			{
				__result = false;
			}
		}

		internal static void Once(string key, Exception e)
		{
			if (logged.Add(key))
			{
				Plugin.Log.LogError((object)(key + ": " + e));
			}
		}
	}
	[HarmonyPatch(typeof(StormyWeather), "LightningStrike")]
	internal static class Lightning
	{
		internal static bool Striking;

		[HarmonyPrefix]
		private static void Prefix()
		{
			Striking = true;
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			Striking = false;
		}
	}
	[HarmonyPatch]
	internal static class MeleePatches
	{
		private static readonly FieldRef<Shovel, PlayerControllerB> shovelHolder = AccessTools.FieldRefAccess<Shovel, PlayerControllerB>("previousPlayerHeldBy");

		[HarmonyPatch(typeof(Shovel), "HitShovel")]
		[HarmonyPrefix]
		private static void ShovelPrefix(Shovel __instance, out int __state)
		{
			__state = int.MinValue;
			PlayerControllerB p = shovelHolder.Invoke(__instance) ?? ((GrabbableObject)__instance).playerHeldBy;
			float num = Buffs.MeleeMul();
			if (num > 1f && Local.Is(p))
			{
				__state = __instance.shovelHitForce;
				__instance.shovelHitForce = Mathf.Max(1, Mathf.RoundToInt((float)__state * num));
			}
		}

		[HarmonyPatch(typeof(Shovel), "HitShovel")]
		[HarmonyFinalizer]
		private static void ShovelFinalizer(Shovel __instance, int __state)
		{
			if (__state != int.MinValue)
			{
				__instance.shovelHitForce = __state;
			}
		}

		[HarmonyPatch(typeof(KnifeItem), "HitKnife")]
		[HarmonyPrefix]
		private static void KnifePrefix(KnifeItem __instance, out int __state)
		{
			__state = int.MinValue;
			PlayerControllerB p = __instance.previousPlayerHeldBy ?? ((GrabbableObject)__instance).playerHeldBy;
			float num = Buffs.MeleeMul();
			if (num > 1f && Local.Is(p))
			{
				__state = __instance.knifeHitForce;
				__instance.knifeHitForce = Mathf.Max(1, Mathf.RoundToInt((float)__state * num));
			}
		}

		[HarmonyPatch(typeof(KnifeItem), "HitKnife")]
		[HarmonyFinalizer]
		private static void KnifeFinalizer(KnifeItem __instance, int __state)
		{
			if (__state != int.MinValue)
			{
				__instance.knifeHitForce = __state;
			}
		}
	}
	public enum BuffKind
	{
		SugarRush,
		WebRush,
		SugarCrash,
		Hydration,
		Dehydration,
		Regeneration,
		SugarMend,
		Brawn,
		Swift,
		Spring,
		SecondWind,
		Endurance,
		Hyponatremia,
		Equilibrium,
		BorrowedTime,
		Equivalence,
		SharpSight,
		Exquisite,
		CheeseSense,
		Grounded,
		Numb
	}
	public class Buff
	{
		public BuffKind kind;

		public float end;

		public float length;

		public float healLeft;

		public float healPending;

		public float crashAfter;

		public float Left => Mathf.Max(0f, end - Time.time);
	}
	public static class Buffs
	{
		private static readonly Dictionary<BuffKind, Buff> active = new Dictionary<BuffKind, Buff>();

		private static readonly List<Buff> expired = new List<Buff>();

		private static int healedSinceSync;

		public static IEnumerable<Buff> All => active.Values;

		private static SodaConfig C => SodaConfig.Instance;

		public static bool Has(BuffKind k)
		{
			return active.ContainsKey(k);
		}

		public static Buff Get(BuffKind k)
		{
			if (!active.TryGetValue(k, out var value))
			{
				return null;
			}
			return value;
		}

		public static Buff Add(BuffKind k, float seconds)
		{
			if (seconds <= 0f)
			{
				return null;
			}
			if ((k == BuffKind.SugarCrash || k == BuffKind.Hyponatremia) && Has(BuffKind.Equilibrium) && FrailtyBridge.Installed)
			{
				seconds *= Mathf.Clamp01(C.EquiDebuffTime.Value / 100f);
			}
			if (!active.TryGetValue(k, out var value))
			{
				value = new Buff
				{
					kind = k,
					end = Time.time + seconds,
					length = seconds
				};
				active[k] = value;
			}
			else if (value.Left < seconds)
			{
				value.end = Time.time + seconds;
				value.length = seconds;
			}
			return value;
		}

		public static void Remove(BuffKind k)
		{
			active.Remove(k);
		}

		public static void Clear()
		{
			active.Clear();
		}

		public static bool IsDebuff(BuffKind k)
		{
			if (k != BuffKind.SugarCrash && k != BuffKind.Hyponatremia)
			{
				return k == BuffKind.Dehydration;
			}
			return true;
		}

		public static void ClearDebuffs()
		{
			Remove(BuffKind.SugarCrash);
			Remove(BuffKind.Hyponatremia);
			Remove(BuffKind.Dehydration);
		}

		internal static void Tick(PlayerControllerB player)
		{
			if (active.Count == 0)
			{
				return;
			}
			if (player.isPlayerDead)
			{
				Clear();
				return;
			}
			float deltaTime = Time.deltaTime;
			expired.Clear();
			foreach (Buff value in active.Values)
			{
				if (value.healLeft > 0f)
				{
					Heal(player, value, deltaTime);
				}
				if (Time.time >= value.end)
				{
					expired.Add(value);
				}
			}
			foreach (Buff item in expired)
			{
				active.Remove(item.kind);
				if ((item.kind == BuffKind.SugarRush || item.kind == BuffKind.WebRush) && item.crashAfter > 0f && C.SugarCrash.Value && !Has(BuffKind.SugarRush) && !Has(BuffKind.WebRush))
				{
					Add(BuffKind.SugarCrash, item.crashAfter);
				}
			}
		}

		private static void Heal(PlayerControllerB player, Buff b, float dt)
		{
			float num = b.healLeft / Mathf.Max(0.05f, b.Left);
			float num2 = Mathf.Min(b.healLeft, num * dt);
			b.healLeft -= num2;
			b.healPending += num2;
			if (b.healPending < 1f)
			{
				return;
			}
			int num3 = Mathf.FloorToInt(b.healPending);
			b.healPending -= num3;
			if (player.health >= 100)
			{
				return;
			}
			player.health = Mathf.Min(100, player.health + num3);
			HUDManager.Instance.UpdateHealthUI(player.health, false);
			if (player.health >= 20 && player.criticallyInjured)
			{
				player.MakeCriticallyInjured(false);
			}
			healedSinceSync += num3;
			if (healedSinceSync >= 5 || player.health >= 100 || b.healLeft < 1f)
			{
				healedSinceSync = 0;
				if (FrailtyBridge.Installed)
				{
					FrailtyBridge.SyncHealth(player);
				}
			}
		}

		public static float SpeedMul()
		{
			float num = 1f;
			if (Has(BuffKind.SugarRush))
			{
				num *= 1f + C.RushSpeed.Value / 100f;
			}
			if (Has(BuffKind.WebRush))
			{
				num *= 1f + C.WebSpeed.Value / 100f;
			}
			if (Has(BuffKind.Swift))
			{
				num *= 1f + C.GenericSpeed.Value / 100f;
			}
			if (Has(BuffKind.Exquisite))
			{
				num *= 1f + C.ExqSpeed.Value / 100f;
			}
			if (Has(BuffKind.BorrowedTime))
			{
				num *= 1f + C.BorrowedSpeed.Value / 100f;
			}
			if (Has(BuffKind.Hyponatremia))
			{
				num *= 1f - C.HypoSlow.Value / 100f;
			}
			return num;
		}

		public static float JumpMul()
		{
			float num = 1f;
			if (Has(BuffKind.SugarRush))
			{
				num *= 1f + C.RushJump.Value / 100f;
			}
			if (Has(BuffKind.WebRush))
			{
				num *= 1f + C.WebJump.Value / 100f;
			}
			if (Has(BuffKind.Spring))
			{
				num *= 1f + C.GenericJump.Value / 100f;
			}
			if (Has(BuffKind.Exquisite))
			{
				num *= 1f + C.ExqJump.Value / 100f;
			}
			if (Has(BuffKind.Hyponatremia))
			{
				num *= 1f - C.HypoSlow.Value / 100f;
			}
			return num;
		}

		public static float ClimbMul()
		{
			if (!Has(BuffKind.Exquisite))
			{
				return 1f;
			}
			return 1f + C.ExqClimb.Value / 100f;
		}

		public static float RefillMul()
		{
			float num = 1f;
			if (Has(BuffKind.Hydration))
			{
				num *= C.HydrationRefill.Value;
			}
			if (Has(BuffKind.SugarMend))
			{
				num *= 1f + C.MendRefill.Value / 100f;
			}
			if (Has(BuffKind.SecondWind))
			{
				num *= 1f + C.GenericRefill.Value / 100f;
			}
			if (Has(BuffKind.Exquisite))
			{
				num *= 1f + C.ExqRefill.Value / 100f;
			}
			if (Has(BuffKind.SugarCrash))
			{
				num *= 1f - C.CrashRefill.Value / 100f;
			}
			return num;
		}

		public static float DrainMul()
		{
			if (Has(BuffKind.BorrowedTime))
			{
				return 0f;
			}
			float num = 1f;
			if (Has(BuffKind.Endurance))
			{
				num *= 1f - C.GenericEndurance.Value / 100f;
			}
			if (Has(BuffKind.Hyponatremia))
			{
				num *= 1f + C.HypoDrain.Value / 100f;
			}
			return num;
		}

		public static float CarryReduce()
		{
			if (!Has(BuffKind.Brawn))
			{
				return 0f;
			}
			return Mathf.Clamp01(C.BrawnCarry.Value / 100f);
		}

		public static float DamageMul()
		{
			float num = 1f;
			if (Has(BuffKind.Equilibrium))
			{
				num *= 1f - Mathf.Clamp01(C.EquiReduction.Value / 100f);
			}
			if (Has(BuffKind.Numb))
			{
				num *= 1f - Mathf.Clamp01(C.NumbReduction.Value / 100f);
			}
			return num;
		}

		public static float MeleeMul()
		{
			if (!Has(BuffKind.Brawn))
			{
				return 1f;
			}
			return C.BrawnMelee.Value;
		}

		public static float FovAdd()
		{
			if (!Has(BuffKind.SharpSight))
			{
				return 0f;
			}
			return C.SharpFov.Value;
		}
	}
	[HarmonyPatch]
	internal static class CustomDrinks
	{
		private static readonly Dictionary<DrinkId, Item> items = new Dictionary<DrinkId, Item>();

		private static GameObject holder;

		private static bool made;

		private static readonly FieldInfo hashField = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static Material BaseMaterial;

		private static int baseMin = -1;

		private static int baseMax = -1;

		internal static IEnumerable<Item> All => items.Values;

		internal static Item ItemFor(DrinkDef def)
		{
			if (def == null || !items.TryGetValue(def.id, out var value))
			{
				return null;
			}
			return value;
		}

		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		[HarmonyPostfix]
		private static void Make()
		{
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Expected O, but got Unknown
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Expected O, but got Unknown
			if (made)
			{
				return;
			}
			made = true;
			try
			{
				NetworkManager singleton = NetworkManager.Singleton;
				if ((Object)(object)singleton == (Object)null || singleton.NetworkConfig == null || singleton.NetworkConfig.Prefabs == null)
				{
					Plugin.Log.LogError((object)"Our drinks: no network manager yet.");
					return;
				}
				GameObject val = null;
				foreach (NetworkPrefab prefab in singleton.NetworkConfig.Prefabs.Prefabs)
				{
					GrabbableObject val2 = (((Object)(object)prefab?.Prefab != (Object)null) ? prefab.Prefab.GetComponent<GrabbableObject>() : null);
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2.itemProperties != (Object)null && val2.itemProperties.itemName == "Red soda")
					{
						val = prefab.Prefab;
						break;
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogError((object)"Our drinks: the Red soda wasn't found, so Bolt Cola and the others can't be made.");
					return;
				}
				Item itemProperties = val.GetComponent<GrabbableObject>().itemProperties;
				baseMin = itemProperties.minValue;
				baseMax = itemProperties.maxValue;
				Sprite val3 = Assets.CanIcon("RedSoda");
				if ((Object)(object)val3 != (Object)null)
				{
					itemProperties.itemIcon = val3;
				}
				Renderer componentInChildren = val.GetComponentInChildren<Renderer>(true);
				if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.sharedMaterial != (Object)null)
				{
					BaseMaterial = componentInChildren.sharedMaterial;
				}
				holder = new GameObject("DrinkableSodaPrefabs");
				holder.SetActive(false);
				((Object)holder).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)holder);
				foreach (DrinkDef item in DrinkDefs.All.Where((DrinkDef d) => d.Custom))
				{
					GameObject val4 = Object.Instantiate<GameObject>(val, holder.transform);
					((Object)val4).name = "DrinkableSoda_" + item.key;
					((Object)val4).hideFlags = (HideFlags)61;
					hashField?.SetValue(val4.GetComponent<NetworkObject>(), Hash("DrinkableSoda." + item.key));
					Item val5 = Object.Instantiate<Item>(itemProperties);
					((Object)val5).name = "DrinkableSoda_" + item.key;
					val5.itemName = item.itemName;
					val5.spawnPrefab = val4;
					val5.isScrap = true;
					Sprite val6 = Assets.CanIcon(item.key);
					if ((Object)(object)val6 != (Object)null)
					{
						val5.itemIcon = val6;
					}
					val4.GetComponent<GrabbableObject>().itemProperties = val5;
					ScanNodeProperties[] componentsInChildren = val4.GetComponentsInChildren<ScanNodeProperties>(true);
					for (int num = 0; num < componentsInChildren.Length; num++)
					{
						componentsInChildren[num].headerText = item.itemName;
					}
					Texture2D val7 = Assets.CanTexture(item.key);
					if ((Object)(object)val7 != (Object)null)
					{
						Renderer[] componentsInChildren2 = val4.GetComponentsInChildren<Renderer>(true);
						foreach (Renderer val8 in componentsInChildren2)
						{
							Material[] sharedMaterials = val8.sharedMaterials;
							bool flag = false;
							for (int num2 = 0; num2 < sharedMaterials.Length; num2++)
							{
								if (!((Object)(object)sharedMaterials[num2] == (Object)null))
								{
									Material val9 = new Material(sharedMaterials[num2])
									{
										name = "DrinkableSoda_" + item.key
									};
									if (val9.HasProperty("_BaseColorMap"))
									{
										val9.SetTexture("_BaseColorMap", (Texture)(object)val7);
									}
									if (val9.HasProperty("_MainTex"))
									{
										val9.SetTexture("_MainTex", (Texture)(object)val7);
									}
									sharedMaterials[num2] = val9;
									flag = true;
								}
							}
							if (flag)
							{
								val8.sharedMaterials = sharedMaterials;
							}
						}
					}
					singleton.AddNetworkPrefab(val4);
					items[item.id] = val5;
				}
				Plugin.Log.LogInfo((object)string.Format("Made {0} drinks: {1}.", items.Count, string.Join(", ", items.Values.Select((Item i) => i.itemName))));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Our drinks: " + ex));
			}
		}

		private static uint Hash(string s)
		{
			using MD5 mD = MD5.Create();
			return BitConverter.ToUInt32(mD.ComputeHash(Encoding.UTF8.GetBytes(s)), 0);
		}

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPrefix]
		[HarmonyPriority(600)]
		private static void AddToItemList(StartOfRound __instance)
		{
			try
			{
				List<Item> list = __instance.allItemsList?.itemsList;
				if (list == null)
				{
					return;
				}
				foreach (DrinkDef item in DrinkDefs.All.Where((DrinkDef d) => d.Custom))
				{
					Item val = ItemFor(item);
					if ((Object)(object)val != (Object)null && !list.Contains(val))
					{
						list.Add(val);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Our drinks (item list): " + ex));
			}
		}

		internal static float ScrapWeight(DrinkDef def)
		{
			return Mathf.Sqrt(30f / (float)Mathf.Max(10, def.price()));
		}

		[HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")]
		[HarmonyPrefix]
		private static void AddToScrap(RoundManager __instance)
		{
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Expected O, but got Unknown
			try
			{
				SelectableLevel currentLevel = __instance.currentLevel;
				if ((Object)(object)currentLevel == (Object)null || currentLevel.spawnableScrap == null)
				{
					return;
				}
				SodaConfig instance = SodaConfig.Instance;
				currentLevel.spawnableScrap.RemoveAll((SpawnableItemWithRarity s) => s != null && (Object)(object)s.spawnableItem != (Object)null && items.ContainsValue(s.spawnableItem));
				if (!instance.ScrapSpawn.Value || currentLevel.levelID == 3)
				{
					return;
				}
				foreach (DrinkDef item in DrinkDefs.All.Where((DrinkDef d) => d.Custom && d.enabled()))
				{
					Item val = ItemFor(item);
					if (!((Object)(object)val == (Object)null))
					{
						int num = Mathf.Max(0, Mathf.RoundToInt((float)instance.ScrapRarity.Value * ScrapWeight(item)));
						float num2 = Mathf.Sqrt((float)Mathf.Max(10, item.price()) / 30f);
						if (baseMin > 0 && baseMax > 0)
						{
							val.minValue = Mathf.Max(1, Mathf.RoundToInt((float)baseMin * num2));
							val.maxValue = Mathf.Max(val.minValue + 1, Mathf.RoundToInt((float)baseMax * num2));
						}
						if (num > 0)
						{
							currentLevel.spawnableScrap.Add(new SpawnableItemWithRarity(val, num));
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Our drinks (scrap): " + ex.Message));
			}
		}
	}
	internal static class Diagnostics
	{
		private static readonly HashSet<string> seen = new HashSet<string>();

		private static int scanFrame = -1;

		private static int scanCount;

		internal static void TryPatch(Harmony harmony)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0077: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			if (SodaConfig.Instance == null || !SodaConfig.Instance.LogTypeSearches.Value)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(AccessTools), "TypeByName", new Type[1] { typeof(string) }, (Type[])null);
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Diagnostics), "Prefix", (Type[])null), new HarmonyMethod(typeof(Diagnostics), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(AccessTools), "GetTypesFromAssembly", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Diagnostics), "ScanPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				Plugin.Log.LogWarning((object)"Debug: logging slow type searches (turn off in config when done).");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Type search logging: " + ex.Message));
			}
		}

		private static void Prefix(out float __state)
		{
			__state = Time.realtimeSinceStartup;
		}

		private static void Postfix(string name, Type __result, float __state)
		{
			float num = (Time.realtimeSinceStartup - __state) * 1000f;
			if (name != null && (!(__result != null) || !(num < 15f)) && seen.Add(name))
			{
				Plugin.Log.LogWarning((object)string.Format("Slow type search: \"{0}\" {1} ({2:0} ms). Asked by:\n{3}", name, (__result == null) ? "not found" : "found", num, Environment.StackTrace));
			}
		}

		private static void ScanPrefix()
		{
			int frameCount = Time.frameCount;
			if (frameCount != scanFrame)
			{
				scanFrame = frameCount;
				scanCount = 0;
			}
			if (++scanCount == 40)
			{
				string stackTrace = Environment.StackTrace;
				if (seen.Add("scan:" + stackTrace.GetHashCode()))
				{
					Plugin.Log.LogWarning((object)("Slow type search: a mod is reading every type of every mod. Asked by:\n" + stackTrace));
				}
			}
		}
	}
	public enum DrinkId
	{
		RedSoda,
		Pills,
		Alt,
		Generic,
		Web,
		Jim,
		Sakura,
		Morv,
		Cheese,
		Harvest,
		Vanilla
	}
	public class DrinkDef
	{
		public DrinkId id;

		public string itemName;

		public bool pill;

		public string key;

		public Func<bool> enabled;

		public Func<int> price;

		public Func<int> machineBase;

		public bool special;

		public bool Custom => key != null;

		public int MaxUses
		{
			get
			{
				if (!pill)
				{
					return 1;
				}
				return Mathf.Max(1, SodaConfig.Instance.PillUses.Value);
			}
		}

		public string Tip(int usesLeft)
		{
			if (!pill)
			{
				return "Drink : [LMB]";
			}
			return $"Take a pill ({usesLeft} left) : [LMB]";
		}
	}
	internal static class DrinkDefs
	{
		internal static readonly List<DrinkDef> All = new List<DrinkDef>();

		private static SodaConfig C => SodaConfig.Instance;

		internal static void Init()
		{
			All.Clear();
			Add(DrinkId.RedSoda, "Red soda", pill: false, null, () => C.OnRedSoda.Value, () => C.PriceRedSoda.Value);
			Add(DrinkId.Pills, "Pill bottle", pill: true, null, () => C.OnPills.Value && !FrailtyBridge.MedicalInstalled, () => C.PricePills.Value);
			Add(DrinkId.Alt, "Peach Soda", pill: false, "PeachSoda", () => C.OnAlt.Value, () => C.PriceAlt.Value);
			Add(DrinkId.Generic, "Mystery Soda", pill: false, "MysterySoda", () => C.OnGeneric.Value, () => C.PriceGeneric.Value);
			Add(DrinkId.Web, "Bolt Cola", pill: false, "BoltCola", () => C.OnWeb.Value, () => C.PriceWeb.Value);
			Add(DrinkId.Jim, "Sparkle Soda", pill: false, "SparkleSoda", () => C.OnJim.Value, () => C.PriceJim.Value);
			Add(DrinkId.Sakura, "ACE Soda", pill: false, "AceSoda", () => C.OnSakura.Value, () => C.PriceSakura.Value);
			Add(DrinkId.Morv, "Climate Soda", pill: false, "ClimateSoda", () => C.OnMorv.Value, () => C.PriceMorv.Value);
			Add(DrinkId.Cheese, "Cheesy Soda", pill: false, "CheesySoda", () => C.OnCheese.Value, () => C.PriceCheese.Value);
			Add(DrinkId.Harvest, "Kosher Soda", pill: false, "KosherSoda", () => C.OnHarvest.Value, () => C.PriceHarvest.Value);
			Add(DrinkId.Vanilla, "Vanilla Soda", pill: false, "VanillaSoda", () => C.OnVanilla.Value, () => C.PriceVanilla.Value);
			Special(DrinkId.Morv, () => C.MachineBaseMorv.Value);
			Special(DrinkId.Cheese, () => C.MachineBaseCheese.Value);
			Special(DrinkId.Harvest, () => C.MachineBaseHarvest.Value);
		}

		private static void Add(DrinkId id, string name, bool pill, string key, Func<bool> on, Func<int> price)
		{
			All.Add(new DrinkDef
			{
				id = id,
				itemName = name,
				pill = pill,
				key = key,
				enabled = on,
				price = price
			});
		}

		private static void Special(DrinkId id, Func<int> machineBase)
		{
			DrinkDef drinkDef = Get(id);
			drinkDef.special = true;
			drinkDef.machineBase = machineBase;
		}

		internal static DrinkDef Get(DrinkId id)
		{
			return All.Find((DrinkDef d) => d.id == id);
		}

		internal static DrinkDef Find(Item item)
		{
			if ((Object)(object)item == (Object)null || string.IsNullOrEmpty(item.itemName))
			{
				return null;
			}
			string b = item.itemName.Trim();
			foreach (DrinkDef item2 in All)
			{
				if (string.Equals(item2.itemName, b, StringComparison.OrdinalIgnoreCase))
				{
					return item2;
				}
			}
			return null;
		}
	}
	public class Drinkable : MonoBehaviour
	{
		public DrinkDef def;

		public GrabbableObject item;

		public int used;

		private ScanNodeProperties scan;

		private string scanHeader;

		private int scanNodeType = -1;

		private string scanSub;

		public bool Empty => used >= def.MaxUses;

		public int UsesLeft => Mathf.Max(0, def.MaxUses - used);

		public bool FromStore
		{
			get
			{
				if ((Object)(object)item != (Object)null)
				{
					return item.scrapValue <= 0;
				}
				return false;
			}
		}

		internal static Drinkable For(GrabbableObject g)
		{
			if ((Object)(object)g == (Object)null)
			{
				return null;
			}
			Drinkable component = ((Component)g).GetComponent<Drinkable>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			DrinkDef drinkDef = DrinkDefs.Find(g.itemProperties);
			if (drinkDef == null)
			{
				return null;
			}
			component = ((Component)g).gameObject.AddComponent<Drinkable>();
			component.def = drinkDef;
			component.item = g;
			component.scan = ((Component)g).GetComponentInChildren<ScanNodeProperties>(true);
			if ((Object)(object)component.scan != (Object)null)
			{
				if (component.scan.headerText != null && component.scan.headerText.Contains("???"))
				{
					component.scan.headerText = "Cheese soda";
				}
				component.scanHeader = component.scan.headerText;
			}
			Net.ApplyPending(component);
			component.RefreshScan();
			return component;
		}

		internal void SetUsed(int value)
		{
			used = Mathf.Max(0, value);
			RefreshScan();
			if ((Object)(object)item != (Object)null && (Object)(object)item.playerHeldBy != (Object)null && (Object)(object)item.playerHeldBy == (Object)(object)GameNetworkManager.Instance?.localPlayerController && (Object)(object)item.playerHeldBy.currentlyHeldObjectServer == (Object)(object)item)
			{
				Drinking.SetTips(this);
			}
		}

		internal void RefreshScan()
		{
			if ((Object)(object)scan == (Object)null)
			{
				return;
			}
			if (scanNodeType < 0)
			{
				scanNodeType = scan.nodeType;
			}
			if (FromStore)
			{
				if (scan.nodeType != 0)
				{
					scan.nodeType = 0;
					scanSub = scan.subText;
				}
				scan.subText = "";
			}
			else if (scan.nodeType != scanNodeType)
			{
				scan.nodeType = scanNodeType;
				if (scanSub != null && string.IsNullOrEmpty(scan.subText))
				{
					scan.subText = scanSub;
				}
			}
			string text = scanHeader ?? def.itemName;
			if (Empty)
			{
				scan.headerText = "Empty " + text;
			}
			else if (def.pill)
			{
				scan.headerText = text + " (" + UsesLeft + ((UsesLeft == 1) ? " use left)" : " uses left)");
			}
			else
			{
				scan.headerText = text;
			}
		}
	}
	internal static class Drinking
	{
		internal static bool Busy;

		private static SodaConfig C => SodaConfig.Instance;

		internal static float DrinkTime(DrinkDef d)
		{
			if (!d.pill)
			{
				return 3.2f;
			}
			return 1.6f;
		}

		internal static void SetTips(Drinkable d)
		{
			try
			{
				string[] array = ((!d.def.enabled() || d.Empty) ? new string[0] : new string[1] { d.def.Tip(d.UsesLeft) });
				HUDManager.Instance.ChangeControlTipMultiple(array, true, d.item.itemProperties);
			}
			catch
			{
			}
		}

		internal static bool TryUse(GrabbableObject item)
		{
			Drinkable drinkable = Drinkable.For(item);
			if ((Object)(object)drinkable == (Object)null || !drinkable.def.enabled())
			{
				return false;
			}
			if (Busy || drinkable.Empty)
			{
				return true;
			}
			PlayerControllerB playerHeldBy = item.playerHeldBy;
			if ((Object)(object)playerHeldBy == (Object)null || (Object)(object)playerHeldBy != (Object)(object)GameNetworkManager.Instance.localPlayerController || playerHeldBy.isPlayerDead)
			{
				return true;
			}
			((MonoBehaviour)Plugin.Instance).StartCoroutine(Drink(playerHeldBy, drinkable));
			return true;
		}

		private static IEnumerator Drink(PlayerControllerB player, Drinkable d)
		{
			Busy = true;
			GrabbableObject item = d.item;
			float time = DrinkTime(d.def);
			player.activatingItem = true;
			player.playerBodyAnimator.SetBool("useTZPItem", true);
			Sfx.Play(player, d.def.pill);
			Net.SendDrink(item, d.def.pill);
			if (C.NoiseRange.Value > 0f)
			{
				RoundManager.Instance.PlayAudibleNoise(((Component)item).transform.position, C.NoiseRange.Value, 0.5f, 0, item.isInElevator && StartOfRound.Instance.hangarDoorsClosed, 0);
			}
			BuffKind? during = (d.def.pill ? ((BuffKind?)null) : new BuffKind?((d.def.id == DrinkId.Harvest) ? BuffKind.Dehydration : BuffKind.Hydration));
			if (during.HasValue)
			{
				Buffs.Add(during.Value, time);
			}
			bool cancelled = false;
			float t = 0f;
			while (t < time)
			{
				yield return null;
				t += Time.deltaTime;
				if ((Object)(object)player == (Object)null || player.isPlayerDead || (Object)(object)item == (Object)null || (Object)(object)item.playerHeldBy != (Object)(object)player || item.isPocketed || (Object)(object)player.currentlyHeldObjectServer != (Object)(object)item)
				{
					cancelled = true;
					break;
				}
			}
			if ((Object)(object)player != (Object)null)
			{
				player.playerBodyAnimator.SetBool("useTZPItem", false);
				player.activatingItem = false;
			}
			if (during.HasValue)
			{
				Buffs.Remove(during.Value);
			}
			Busy = false;
			if (cancelled || (Object)(object)player == (Object)null || player.isPlayerDead)
			{
				Sfx.Stop(player);
				yield break;
			}
			try
			{
				Effects.Apply(player, d.def);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Drink effects: " + ex));
			}
			Consume(player, d);
		}

		private static void Consume(PlayerControllerB player, Drinkable d)
		{
			int num = d.used + 1;
			if (num >= d.def.MaxUses && d.FromStore)
			{
				player.DespawnHeldObject();
				return;
			}
			int value = d.item.scrapValue;
			if (num >= d.def.MaxUses && !d.FromStore)
			{
				value = Mathf.Max(1, Mathf.RoundToInt((float)d.item.scrapValue * Mathf.Clamp01(C.EmptyValuePercent.Value / 100f)));
			}
			Net.SendState(d.item, num, value);
		}
	}
	internal static class Sfx
	{
		internal static void Play(PlayerControllerB player, bool pill)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player.itemAudio == (Object)null))
			{
				AudioClip val = Assets.Sound(pill ? "Pill_Shake" : "Soda_Drink_tight");
				if (!((Object)(object)val == (Object)null))
				{
					player.itemAudio.PlayOneShot(val, 1f);
					WalkieTalkie.TransmitOneShotAudio(player.itemAudio, val, 1f);
				}
			}
		}

		internal static void Stop(PlayerControllerB player)
		{
		}
	}
	internal static class Effects
	{
		private static SodaConfig C => SodaConfig.Instance;

		internal static void Apply(PlayerControllerB player, DrinkDef d)
		{
			switch (d.id)
			{
			case DrinkId.RedSoda:
				Buffs.Add(BuffKind.SugarRush, C.RushTime.Value).crashAfter = C.CrashTime.Value;
				Buffs.Remove(BuffKind.SugarCrash);
				break;
			case DrinkId.Web:
				Buffs.Add(BuffKind.WebRush, C.WebTime.Value).crashAfter = C.WebCrashTime.Value;
				Buffs.Remove(BuffKind.SugarCrash);
				break;
			case DrinkId.Pills:
				if (FrailtyBridge.Installed)
				{
					FrailtyBridge.CurePillInjuries();
				}
				CureVanillaTzp(player);
				Buffs.Add(BuffKind.Numb, C.NumbTime.Value);
				if (C.PillHeal.Value > 0f)
				{
					Heal(BuffKind.Regeneration, C.PillHeal.Value, C.PillHealTime.Value);
				}
				break;
			case DrinkId.Alt:
				Heal(BuffKind.SugarMend, C.MendHeal.Value, C.MendTime.Value);
				break;
			case DrinkId.Generic:
			{
				if (Buffs.Has(BuffKind.Swift) || Buffs.Has(BuffKind.Spring) || Buffs.Has(BuffKind.SecondWind) || Buffs.Has(BuffKind.Endurance))
				{
					Buffs.Add(BuffKind.Hyponatremia, C.HypoTime.Value);
				}
				float value = Random.value;
				float num = Mathf.Clamp01(C.GenericCureChance.Value);
				if (value < num)
				{
					CureAll(player);
					break;
				}
				Buffs.Add(Mathf.Clamp((int)((value - num) / Mathf.Max(0.0001f, 1f - num) * 4f), 0, 3) switch
				{
					2 => BuffKind.SecondWind, 
					1 => BuffKind.Spring, 
					0 => BuffKind.Swift, 
					_ => BuffKind.Endurance, 
				}, C.GenericTime.Value);
				break;
			}
			case DrinkId.Jim:
				Buffs.Add(BuffKind.Brawn, C.BrawnTime.Value);
				break;
			case DrinkId.Sakura:
				Buffs.Add(BuffKind.SharpSight, C.SharpTime.Value);
				break;
			case DrinkId.Vanilla:
				Buffs.Add(BuffKind.Exquisite, C.ExqTime.Value);
				break;
			case DrinkId.Cheese:
				Buffs.Add(BuffKind.CheeseSense, C.CheeseTime.Value);
				break;
			case DrinkId.Morv:
				Buffs.Add(BuffKind.Grounded, C.GroundedTime.Value);
				break;
			case DrinkId.Harvest:
				Buffs.Add(BuffKind.Equilibrium, C.EquiTime.Value);
				break;
			}
		}

		private static void Heal(BuffKind kind, float hp, float seconds)
		{
			float num = Buffs.Get(kind)?.healLeft ?? 0f;
			Buff buff = Buffs.Add(kind, seconds);
			if (buff != null)
			{
				buff.healLeft = num + hp;
			}
		}

		internal static void CureAll(PlayerControllerB player)
		{
			if (FrailtyBridge.Installed)
			{
				FrailtyBridge.CureAll();
			}
			Buffs.ClearDebuffs();
			CureVanillaTzp(player);
		}

		internal static void CureVanillaTzp(PlayerControllerB player)
		{
			player.drunkness = 0f;
			player.drunknessInertia = 0f;
		}
	}
	internal static class EladsTint
	{
		private const string EladsGuid = "me.eladnlg.customhud";

		private static FieldInfo healthBar;

		private static FieldInfo healthGroup;

		private static FieldInfo staminaBar;

		private static FieldInfo warnColor;

		private static FieldInfo colorLerp;

		private static bool tzpPlus;

		private static object lastHud;

		private static Color originalHealth;

		private static float staminaAmount;

		private static float healthAmount;

		private static Color staminaColor = BuffInfo.Gold;

		private static readonly BuffKind[] staminaBuffs = new BuffKind[10]
		{
			BuffKind.Exquisite,
			BuffKind.BorrowedTime,
			BuffKind.Hydration,
			BuffKind.SecondWind,
			BuffKind.Endurance,
			BuffKind.Swift,
			BuffKind.WebRush,
			BuffKind.SugarRush,
			BuffKind.SugarMend,
			BuffKind.Brawn
		};

		internal static void TryPatch(Harmony harmony)
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			try
			{
				if (!Chainloader.PluginInfos.TryGetValue("me.eladnlg.customhud", out var value) || (Object)(object)value.Instance == (Object)null)
				{
					return;
				}
				Type type = ((object)value.Instance).GetType().Assembly.GetType("CustomHUD_Mono");
				if (!(type == null))
				{
					healthBar = AccessTools.Field(type, "healthBar");
					healthGroup = AccessTools.Field(type, "healthGroup");
					staminaBar = AccessTools.Field(type, "staminaBar");
					warnColor = AccessTools.Field(type, "staminaWarnColor");
					colorLerp = AccessTools.Field(type, "colorLerp");
					MethodInfo methodInfo = AccessTools.Method(type, "UpdateFromPlayer", (Type[])null, (Type[])null);
					if (!(methodInfo == null) && !(healthBar == null) && !(staminaBar == null))
					{
						tzpPlus = Chainloader.PluginInfos.ContainsKey("Miles.TZPPlus");
						HarmonyMethod val = new HarmonyMethod(typeof(EladsTint), "Postfix", (Type[])null);
						val.priority = 400;
						val.after = new string[1] { "Miles.TZPPlus" };
						harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Plugin.Log.LogInfo((object)"EladsHUD+ found: its bars change color with drink buffs.");
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("EladsHUD+ bar colors: " + ex.Message));
			}
		}

		private static void Postfix(object __instance)
		{
			//IL_0067: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: 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_01f3: 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)
			try
			{
				SodaConfig instance = SodaConfig.Instance;
				if (instance == null)
				{
					return;
				}
				float deltaTime = Time.deltaTime;
				BuffKind? buffKind = null;
				if (instance.TintStamina.Value)
				{
					BuffKind[] array = staminaBuffs;
					foreach (BuffKind buffKind2 in array)
					{
						if (Buffs.Has(buffKind2))
						{
							buffKind = buffKind2;
							break;
						}
					}
				}
				if (buffKind.HasValue)
				{
					staminaColor = Color.Lerp(staminaColor, BuffInfo.Color(buffKind.Value), 4f * deltaTime);
				}
				staminaAmount = Mathf.MoveTowards(staminaAmount, buffKind.HasValue ? 1f : 0f, 2f * deltaTime);
				if (staminaAmount > 0f)
				{
					object? value = staminaBar.GetValue(__instance);
					Image val = (Image)((value is Image) ? value : null);
					if (val != null && (Object)(object)val != (Object)null)
					{
						Color val2 = (Color)((warnColor != null) ? ((Color)warnColor.GetValue(__instance)) : Color.red);
						float num = ((colorLerp != null) ? Convert.ToSingle(colorLerp.GetValue(__instance)) : 0f);
						((Graphic)val).color = Color.Lerp(((Graphic)val).color, Color.Lerp(staminaColor, val2, num), staminaAmount);
					}
				}
				object? value2 = healthBar.GetValue(__instance);
				Image val3 = (Image)((value2 is Image) ? value2 : null);
				if (val3 == null || (Object)(object)val3 == (Object)null)
				{
					return;
				}
				if (__instance != lastHud)
				{
					lastHud = __instance;
					originalHealth = ((Graphic)val3).color;
				}
				bool flag = instance.TintHealth.Value && (Buffs.Has(BuffKind.Regeneration) || Buffs.Has(BuffKind.SugarMend));
				healthAmount = Mathf.MoveTowards(healthAmount, flag ? 1f : 0f, 2f * deltaTime);
				Color val4 = (tzpPlus ? ((Graphic)val3).color : originalHealth);
				((Graphic)val3).color = Color.Lerp(val4, BuffInfo.Green, healthAmount);
				if (healthAmount > 0f && healthGroup != null)
				{
					object? value3 = healthGroup.GetValue(__instance);
					CanvasGroup val5 = (CanvasGroup)((value3 is CanvasGroup) ? value3 : null);
					if (val5 != null && (Object)(object)val5 != (Object)null)
					{
						val5.alpha = Mathf.Max(val5.alpha, healthAmount);
					}
				}
			}
			catch
			{
			}
		}
	}
	internal static class FrailtyBridge
	{
		private static bool? installed;

		private static Transform conditionRow;

		private static bool rowSearched;

		internal static bool Installed
		{
			get
			{
				bool? flag = installed;
				if (!flag.HasValue)
				{
					bool? flag2 = (installed = Chainloader.PluginInfos.ContainsKey("Chaos.Frailty"));
					return flag2.Value;
				}
				return flag == true;
			}
		}

		internal static bool MedicalInstalled => Chainloader.PluginInfos.ContainsKey("Miles.FrailtyMedical");

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void Hook()
		{
			SodaConfig C = SodaConfig.Instance;
			FrailtyApi.NewDebuffTimeScale.Add(() => (!Buffs.Has(BuffKind.Equilibrium)) ? 1f : Mathf.Clamp01(C.EquiDebuffTime.Value / 100f));
			FrailtyApi.SuppressEffects.Add(() => Buffs.Has(BuffKind.Equivalence));
			FrailtyApi.LocalPlayerHurt += delegate(PlayerControllerB player, int taken, CauseOfDeath cause, bool fall)
			{
				if (Buffs.Has(BuffKind.Equilibrium))
				{
					if (!fall && C.BorrowedTime.Value > 0f)
					{
						Buffs.Add(BuffKind.BorrowedTime, C.BorrowedTime.Value);
					}
					if (C.EquivalenceTime.Value > 0f && Random.value < C.EquivalenceChance.Value)
					{
						Buffs.Add(BuffKind.Equivalence, C.EquivalenceTime.Value);
					}
				}
			};
			Plugin.Log.LogInfo((object)"FrailtyPlus found: Equilibrium and Cure All work with its injuries.");
		}

		internal static int VisibleConditionIcons()
		{
			try
			{
				if ((Object)(object)conditionRow == (Object)null && !rowSearched)
				{
					rowSearched = true;
					PluginInfo value;
					object? obj = (((Chainloader.PluginInfos.TryGetValue("Chaos.Frailty", out value) && (Object)(object)value.Instance != (Object)null) ? ((object)value.Instance).GetType().Assembly.GetType("Frailty.Patches.HUDPatch") : null)?.GetField("conditionHud", BindingFlags.Static | BindingFlags.Public))?.GetValue(null);
					GameObject val = (GameObject)((obj is GameObject) ? obj : null);
					conditionRow = (((Object)(object)val != (Object)null) ? val.transform : null);
				}
				if ((Object)(object)conditionRow == (Object)null)
				{
					rowSearched = false;
					return 0;
				}
				int num = 0;
				for (int i = 0; i < conditionRow.childCount; i++)
				{
					if (((Component)conditionRow.GetChild(i)).gameObject.activeSelf)
					{
						num++;
					}
				}
				return num;
			}
			catch
			{
				return 0;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void CureAll()
		{
			FrailtyApi.CureAll();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void CurePillInjuries()
		{
			ConditionType[] array = new ConditionType[5];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			FrailtyApi.Cure((ConditionType[])(object)array);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void SyncHealth(PlayerControllerB player)
		{
			HealthSync.Send(player);
		}
	}
	public class SodaMachine : MonoBehaviour
	{
		internal enum Status
		{
			Free,
			Buy,
			NoMoney,
			NotSold,
			SoldOut,
			OutOfStock
		}

		internal static readonly List<SodaMachine> All = new List<SodaMachine>();

		internal const int ButtonCount = 10;

		private NetworkObject netObj;

		private PlaceableShipObject placeable;

		private AutoParentToShip parent;

		private readonly InteractTrigger[] buttons = (InteractTrigger[])(object)new InteractTrigger[10];

		private AudioSource audioSource;

		private Transform dispensePoint;

		private MachineModel model;

		private float busyUntil;

		private int selected = -1;

		private float selectedUntil;

		private const float SelectTime = 8f;

		private int litButton = -1;

		private float litUntil;

		private bool litGreen;

		private readonly Material[] lampShown = (Material[])(object)new Material[10];

		private string shownText;

		private float nextTips;

		private static Sprite hoverIcon;

		private static AudioClip placeSfx;

		private static readonly Color DisplayGreen = new Color(0.49f, 1f, 0.54f);

		private static readonly Color DisplayRed = new Color(1f, 0.33f, 0.28f);

		private AudioSource motor;

		private const float FlapOpen = 70f;

		private bool Busy => Time.time < busyUntil;

		private bool Picked
		{
			get
			{
				if (selected >= 0)
				{
					return Time.time < selectedUntil;
				}
				return false;
			}
		}

		private static PlayerControllerB Me
		{
			get
			{
				if (!((Object)(object)GameNetworkManager.Instance != (Object)null))
				{
					return null;
				}
				return GameNetworkManager.Instance.localPlayerController;
			}
		}

		internal ulong Id
		{
			get
			{
				if (!((Object)(object)netObj != (Object)null))
				{
					return 0uL;
				}
				return netObj.NetworkObjectId;
			}
		}

		internal IEnumerable<Collider> OwnColliders => ((Component)this).GetComponentsInChildren<Collider>(true);

		internal static void BuildPrefab(GameObject root)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 size = MachineModel.Size;
			root.AddComponent<AutoParentToShip>();
			SetupAudio(root.AddComponent<AudioSource>());
			root.AddComponent<SodaMachine>();
			GameObject val = new GameObject("Placement");
			val.transform.SetParent(root.transform, false);
			val.transform.localPosition = new Vector3(0f, size.y * 0.5f, 0f);
			val.layer = Layer("PlaceableShipObjects", 26);
			val.tag = "PlaceableObject";
			BoxCollider val2 = val.AddComponent<BoxCollider>();
			val2.size = size;
			SetupAudio(val.AddComponent<AudioSource>());
			PlaceableShipObject obj = val.AddComponent<PlaceableShipObject>();
			obj.parentObject = root.GetComponent<AutoParentToShip>();
			obj.placeObjectCollider = (Collider)(object)val2;
			obj.yOffset = size.y * 0.5f;
			obj.AllowPlacementOnCounters = false;
			obj.AllowPlacementOnWalls = false;
			obj.unlockableID = -1;
			GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)3);
			Mesh sharedMesh = obj2.GetComponent<MeshFilter>().sharedMesh;
			Object.DestroyImmediate((Object)(object)obj2);
			GameObject val3 = new GameObject("Shape");
			val3.transform.SetParent(root.transform, false);
			val3.transform.localPosition = new Vector3(0f, size.y * 0.5f, 0f);
			val3.transform.localScale = size;
			val3.AddComponent<MeshFilter>().sharedMesh = sharedMesh;
			obj.mainMesh = val3.GetComponent<MeshFilter>();
			GameObject val4 = new GameObject("Body");
			val4.transform.SetParent(root.transform, false);
			val4.transform.localPosition = new Vector3(0f, size.y * 0.5f, 0f);
			val4.layer = Layer("Room", 8);
			val4.AddComponent<BoxCollider>().size = size;
			for (int i = 0; i < 10; i++)
			{
				GameObject val5 = new GameObject("Button" + i);
				val5.transform.SetParent(root.transform, false);
				val5.layer = Layer("InteractableObject", 9);
				val5.tag = "InteractTrigger";
				BoxCollider obj3 = val5.AddComponent<BoxCollider>();
				((Collider)obj3).isTrigger = true;
				obj3.size = new Vector3(0.26f, 0.1f, 0.2f);
				InteractTrigger obj4 = val5.AddComponent<InteractTrigger>();
				obj4.hoverTip = "Pick : [E]";
				obj4.disabledHoverTip = "";
				obj4.interactable = true;
				obj4.oneHandedItemAllowed = true;
				obj4.twoHandedItemAllowed = true;
				obj4.holdInteraction = false;
				obj4.interactCooldown = true;
				obj4.cooldownTime = 0.3f;
				obj4.disableTriggerMesh = false;
				InitEvents(obj4);
			}
			new GameObject("Dispense").transform.SetParent(root.transform, false);
		}

		private static int Layer(string name, int fallback)
		{
			int num = LayerMask.NameToLayer(name);
			if (num < 0)
			{
				return fallback;
			}
			return num;
		}

		private static void SetupAudio(AudioSource a)
		{
			a.playOnAwake = false;
			a.spatialBlend = 1f;
			a.rolloffMode = (AudioRolloffMode)1;
			a.minDistance = 2f;
			a.maxDistance = 18f;
		}

		private static void InitEvents(InteractTrigger it)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			it.onInteract = (InteractEvent)(((object)it.onInteract) ?? ((object)new InteractEvent()));
			it.onInteractEarly = (InteractEvent)(((object)it.onInteractEarly) ?? ((object)new InteractEvent()));
			it.onInteractEarlyOtherClients = (InteractEvent)(((object)it.onInteractEarlyOtherClients) ?? ((object)new InteractEvent()));
			it.onStopInteract = (InteractEvent)(((object)it.onStopInteract) ?? ((object)new InteractEvent()));
			it.onCancelAnimation = (InteractEvent)(((object)it.onCancelAnimation) ?? ((object)new InteractEvent()));
			it.holdingInteractEvent = (InteractEventFloat)(((object)it.holdingInteractEvent) ?? ((object)new InteractEventFloat()));
		}

		private void Awake()
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			netObj = ((Component)this).GetComponent<NetworkObject>();
			parent = ((Component)this).GetComponent<AutoParentToShip>();
			audioSource = ((Component)this).GetComponent<AudioSource>();
			placeable = ((Component)this).GetComponentInChildren<PlaceableShipObject>(true);
			dispensePoint = ((Component)this).transform.Find("Dispense");
			for (int i = 0; i < 10; i++)
			{
				Transform val = ((Component)this).transform.Find("Button" + i);
				buttons[i] = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<InteractTrigger>() : null);
				if (!((Object)(object)buttons[i] == (Object)null))
				{
					InitEvents(buttons[i]);
					int index = i;
					((UnityEvent<PlayerControllerB>)(object)buttons[i].onInteract).AddListener((UnityAction<PlayerControllerB>)delegate(PlayerControllerB p)
					{
						OnButton(index, p);
					});
				}
			}
			try
			{
				model = MachineModel.Build(((Component)this).transform);
				Plugin.Log.LogInfo((object)"Soda Machine spawned.");
				float num = 0.5f;
				for (int num2 = 0; num2 < 10; num2++)
				{
					if (!((Object)(object)buttons[num2] == (Object)null))
					{
						Bounds val2 = model.ButtonRect(num2, 10);
						((Component)buttons[num2]).transform.localPosition = new Vector3(((Bounds)(ref val2)).center.x, ((Bounds)(ref val2)).center.y, num + 0.06f);
						((Component)buttons[num2]).GetComponent<BoxCollider>().size = new Vector3(Mathf.Max(0.15f, ((Bounds)(ref val2)).size.x), Mathf.Max(0.05f, ((Bounds)(ref val2)).size.y), 0.2f);
					}
				}
				if ((Object)(object)dispensePoint != (Object)null)
				{
					dispensePoint.localPosition = model.dispense;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Soda Machine model: " + ex));
			}
			int id = MachineSetup.Id;
			if (id >= 0)
			{
				if ((Object)(object)placeable != (Object)null && placeable.unlockableID < 0)
				{
					placeable.unlockableID = id;
				}
				if ((Object)(object)parent != (Object)null && parent.unlockableID < 0)
				{
					parent.unlockableID = id;
				}
			}
		}

		private void Start()
		{
			All.Add(this);
			BorrowVanillaBits();
			if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer)
			{
				((MonoBehaviour)this).StartCoroutine(PlaceIfNew());
			}
		}

		private void OnDestroy()
		{
			All.Remove(this);
		}

		private void BorrowVanillaBits()
		{
			try
			{
				InteractTrigger[] array;
				if ((Object)(object)hoverIcon == (Object)null)
				{
					array = Object.FindObjectsOfType<InteractTrigger>();
					foreach (InteractTrigger val in array)
					{
						if ((Object)(object)val != (Object)null && !buttons.Contains(val) && (Object)(object)val.hoverIcon != (Object)null)
						{
							hoverIcon = val.hoverIcon;
							break;
						}
					}
				}
				if ((Object)(object)placeSfx == (Object)null)
				{
					PlaceableShipObject[] array2 = Object.FindObjectsOfType<PlaceableShipObject>();
					foreach (PlaceableShipObject val2 in array2)
					{
						if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)placeable && (Object)(object)val2.placeObjectSFX != (Object)null && ((Object)val2.placeObjectSFX).name == "MoveShipObjectBig")
						{
							placeSfx = val2.placeObjectSFX;
							break;
						}
					}
				}
				if ((Object)(object)placeSfx == (Object)null)
				{
					placeSfx = MachineSounds.Get("MoveShipObjectBig");
				}
				if ((Object)(object)placeSfx == (Object)null)
				{
					PlaceableShipObject[] array2 = Object.FindObjectsOfType<PlaceableShipObject>();
					foreach (PlaceableShipObject val3 in array2)
					{
						if ((Object)(object)val3 != (Object)null && (Object)(object)val3 != (Object)(object)placeable && (Object)(object)val3.placeObjectSFX != (Object)null)
						{
							placeSfx = val3.placeObjectSFX;
							break;
						}
					}
				}
				array = buttons;
				foreach (InteractTrigger val4 in array)
				{
					if ((Object)(object)val4 != (Object)null)
					{
						val4.hoverIcon = hoverIcon;
					}
				}
				if ((Object)(object)placeable != (Object)null)
				{
					placeable.placeObjectSFX = placeSfx;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Soda Machine: " + ex.Message));
			}
		}

		internal static Status StatusOf(int button, PlayerControllerB me)
		{
			if ((Object)(object)me != (Object)null && MachineNet.LeftToday(me) > 0)
			{
				return Status.Free;
			}
			DrinkDef drinkDef = MachineNet.DefAt(button);
			Item val = MachineNet.ItemAt(button);
			if (drinkDef == null || (Object)(object)val == (Object)null || (Object)(object)val.spawnPrefab == (Object)null || !drinkDef.enabled())
			{
				return Status.SoldOut;
			}
			if (!SodaConfig.Instance.MachineSells.Value)
			{
				return Status.NotSold;
			}
			if (MachineNet.StockLeft(button) <= 0)
			{
				return Status.OutOfStock;
			}
			Terminal term = MachineNet.Term;
			if (!((Object)(object)term != (Object)null) || term.groupCredits < MachineNet.PriceOf(drinkDef))
			{
				return Status.NoMoney;
			}
			return Status.Buy;
		}

		private void Update()
		{
			PlayerControllerB me = Me;
			if (!((Object)(object)me == (Object)null))
			{
				if (!Picked)
				{
					selected = -1;
				}
				Status st = (Picked ? StatusOf(selected, me) : Status.SoldOut);
				UpdateLamps(st);
				UpdateDisplay(me, st);
				if (Time.time >= nextTips)
				{
					nextTips = Time.time + 0.2f;
					UpdateTips(me);
				}
			}
		}

		private void UpdateLamps(Status st)
		{
			if (model == null || model.leds.Count == 0)
			{
				return;
			}
			bool flag = Mathf.Repeat(Time.time * 4f, 1f) < 0.55f;
			bool flag2 = st == Status.Free || st == Status.Buy;
			for (int i = 0; i < 10 && i < model.leds.Count; i++)
			{
				Material val = model.ledOff;
				if (i == litButton && Time.time < litUntil)
				{
					val = (litGreen ? model.ledOn : model.ledRed);
				}
				else if (i == selected && flag)
				{
					val = (flag2 ? model.ledOn : model.ledRed);
				}
				if ((Object)(object)val != (Object)null && (Object)(object)lampShown[i] != (Object)(object)val && (Object)(object)model.leds[i] != (Object)null)
				{
					model.leds[i].sharedMaterial = val;
					lampShown[i] = val;
				}
			}
		}

		private void UpdateDisplay(PlayerControllerB me, Status st)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			TextMeshPro val = ((model != null) ? model.display : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			bool flag = false;
			string text;
			if (Busy)
			{
				text = "ENJOY!";
			}
			else if (Picked)
			{
				DrinkDef drinkDef = MachineNet.DefAt(selected);
				string text2 = ((st == Status.Free) ? "RANDOM DRINK" : ((drinkDef != null) ? drinkDef.itemName.ToUpperInvariant() : ""));
				string text3;
				switch (st)
				{
				case Status.Free:
					text3 = "FREE";
					break;
				case Status.Buy:
					text3 = "$" + MachineNet.PriceOf(drinkDef);
					break;
				case Status.NoMoney:
					text3 = "$" + MachineNet.PriceOf(drinkDef);
					flag = true;
					break;
				case Status.NotSold:
					text3 = "TOMORROW";
					flag = true;
					break;
				default:
					text3 = "SOLD OUT";
					flag = true;
					break;
				}
				text = "<size=45%>" + text2 + "</size>\n" + text3;
			}
			else
			{
				text = ((MachineNet.LeftToday(me) > 0) ? "FREE" : "");
			}
			text += (flag ? "#r" : "#g");
			if (!(text == shownText))
			{
				shownText = text;
				((Graphic)val).color = (flag ? DisplayRed : DisplayGreen);
				((TMP_Text)val).text = text.Substring(0, text.Length - 2);
			}
		}

		private void UpdateTips(PlayerControllerB me)
		{
			for (int i = 0; i < 10; i++)
			{
				InteractTrigger val = buttons[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (Busy)
				{
					val.interactable = false;
					val.disabledHoverTip = "Dispensing...";
					continue;
				}
				val.interactable = true;
				DrinkDef drinkDef = MachineNet.DefAt(i);
				string text = ((drinkDef != null) ? drinkDef.itemName : "Soda");
				Status status = StatusOf(i, me);
				int num = ((drinkDef != null) ? MachineNet.PriceOf(drinkDef) : 0);
				int num2 = MachineNet.StockLeft(i);
				string arg = ((num2 < 100 && SodaConfig.Instance.MachineShowStock.Value) ? $", {num2} left" : "");
				if (i == selected)
				{
					switch (status)
					{
					case Status.Free:
						val.hoverTip = "Get your free random drink : [E]";
						break;
					case Status.Buy:
						val.hoverTip = $"Buy {text} (${num}{arg}) : [E]";
						break;
					case Status.NoMoney:
						val.hoverTip = $"{text} ${num}: not enough credits";
						break;
					case Status.NotSold:
						val.hoverTip = "Free drink used: come back tomorrow";
						break;
					case Status.OutOfStock:
						val.hoverTip = text + " is sold out for today";
						break;
					default:
						val.hoverTip = text + " is turned off";
						break;
					}
				}
				else
				{
					switch (status)
					{
					case Status.Free:
						val.hoverTip = "Free random drink : [E]";
						break;
					case Status.Buy:
					case Status.NoMoney:
						val.hoverTip = $"{text} (${num}{arg}) : [E]";
						break;
					case Status.NotSold:
						val.hoverTip = text + " (come back tomorrow) : [E]";
						break;
					case Status.OutOfStock:
						val.hoverTip = text + " (sold out) : [E]";
						break;
					default:
						val.hoverTip = text + " (turned off) : [E]";
						break;
					}
				}
			}
		}

		private void OnButton(int index, PlayerControllerB player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Me || (Object)(object)netObj == (Object)null || !netObj.IsSpawned || Busy)
			{
				return;
			}
			if (index == selected && Picked)
			{
				Status status = StatusOf(index, player);
				if (status == Status.Free || status == Status.Buy)
				{
					selected = -1;
					MachineNet.SendUse(this, player, index, status == Status.Free);
					return;
				}
				selectedUntil = Time.time + 8f;
				Click(0.5f);
				Deny();
				DrinkDef drinkDef = MachineNet.DefAt(index);
				string text = status switch
				{
					Status.OutOfStock => (drinkDef?.itemName ?? "That drink") + " is sold out for today. More tomorrow!", 
					Status.NotSold => "You had your free drink today. Come back tomorrow!", 
					Status.NoMoney => $"Not enough credits: {drinkDef?.itemName} costs ${MachineNet.PriceOf(drinkDef)}.", 
					_ => (drinkDef?.itemName ?? "That drink") + " is turned off in the config.", 
				};
				HUDManager instance = HUDManager.Instance;
				if (instance != null)
				{
					instance.DisplayTip("Soda Machine", text, true, false, "LC_Tip1");
				}
				nextTips = 0f;
			}
			else
			{
				selected = index;
				selectedUntil = Time.time + 8f;
				nextTips = 0f;
				Click(0.6f);
			}
		}

		private void Play(AudioClip clip, float volume, float pitch = 1f)
		{
			if (!((Object)(object)clip == (Object)null) && !((Object)(object)audioSource == (Object)null))
			{
				if (Mathf.Approximately(pitch, 1f))
				{
					audioSource.PlayOneShot(clip, volume);
					return;
				}
				AudioSource obj = Motor();
				obj.pitch = pitch;
				obj.PlayOneShot(clip, volume);
			}
		}

		private AudioSource Motor()
		{
			if ((Object)(object)motor == (Object)null)
			{
				motor = ((Component)this).gameObject.AddComponent<AudioSource>();
				SetupAudio(motor);
				if ((Object)(object)audioSource != (Object)null)
				{
					motor.outputAudioMixerGroup = audioSource.outputAudioMixerGroup;
				}
			}
			return motor;
		}

		private void Click(float volume)
		{
			Play(MachineSounds.Button(), volume);
		}

		private void Deny()
		{
			Play(MachineSounds.Deny(), 0.7f);
		}

		internal void PlayPress(int button, bool dispensing, bool paid)
		{
			busyUntil = (dispensing ? (Time.time + 3f) : 0f);
			litButton = button;
			litGreen = dispensing;
			litUntil = Time.time + (dispensing ? 1.6f : 0.8f);
			nextTips = 0f;
			try
			{
				Click(0.9f);
				if (!dispensing)
				{
					Deny();
					return;
				}
				if (paid)
				{
					Play(MachineSounds.Get("PurchaseSFX"), 0.8f);
				}
				((MonoBehaviour)this).StopCoroutine("Vend");
				((MonoBehaviour)this).StartCoroutine("Vend");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Soda Machine press: " + ex.Message));
			}
		}

		private IEnumerator Vend()
		{
			yield return (object)new WaitForSeconds(0.1f);
			AudioSource m = Motor();
			AudioClip val = MachineSounds.Get("MicrowaveWhir");
			if ((Object)(object)val != (Object)null)
			{
				m.clip = val;
				m.pitch = 1.35f;
				m.volume = 0.55f;
				m.time = Mathf.Min(0.4f, val.length * 0.2f);
				m.Play();
			}
			yield return (object)new WaitForSeconds(0.5f);
			Play(MachineSounds.Get("DropCan", "DropMetalObject3"), 0.9f);
			yield return (object)new WaitForSeconds(0.15f);
			if (m.isPlaying)
			{
				m.Stop();
			}
			m.pitch = 1f;
			Play(MachineSounds.Get("MetalHatchOpen", "CupboardOpen"), 0.6f);
			yield return Swing(0f, 70f, 0.15f);
			yield return (object)new WaitForSeconds(1.05f);
			yield return Swing(70f, 0f, 0.3f);
			Play(MachineSounds.Get("ExtensionLadderLidOpen", "DoorClose", "CupboardOpen"), 0.6f, 1.1f);
		}

		private IEnumerator Swing(float from, float to, float time)
		{
			Transform hinge = ((model != null) ? model.flap : null);
			if (!((Object)(object)hinge == (Object)null))
			{
				for (float t = 0f; t < time; t += Time.deltaTime)
				{
					float num = Mathf.SmoothStep(0f, 1f, t / time);
					hinge.localRotation = Quaternion.Euler(Mathf.Lerp(from, to, num), 0f, 0f);
					yield return null;
				}
				hinge.localRotation = Quaternion.Euler(to, 0f, 0f);
			}
		}

		internal void SetBusy(bool value)
		{
			busyUntil = (value ? (Time.time + 3f) : 0f);
		}

		internal void ServerDispense(Item item)
		{
			((MonoBehaviour)this).StartCoroutine(DispenseLater(item));
		}

		private IEnumerator DispenseLater(Item item)
		{
			busyUntil = Time.time + 3f;
			yield return (object)new WaitForSeconds(1f);
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				Vector3 val = (((Object)(object)dispensePoint != (Object)null) ? dispensePoint.position : (((Component)this).transform.position + ((Component)this).transform.forward + Vector3.up * 0.4f));
				GrabbableObject component = Object.Instantiate<GameObject>(item.spawnPrefab, val, Quaternion.identity, instance.elevatorTransform).GetComponent<GrabbableObject>();
				component.fallTime = 0f;
				component.scrapValue = 0;
				component.isInElevator = true;
				component.isInShipRoom = true;
				((NetworkBehaviour)component).NetworkObject.Spawn(false);
				MachineNet.SendDispensed(this, ((NetworkBehaviour)component).NetworkObjectId);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Soda Machine: couldn't dispense " + item?.itemName + ": " + ex));
			}
			busyUntil = 0f;
		}

		private IEnumerator PlaceIfNew()
		{
			yield return null;
			yield return null;
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)placeable == (Object)null || placeable.unlockableID < 0)
			{
				yield break;
			}
			UnlockableItem val = instance.unlockablesList.unlockables[placeable.unlockableID];
			if (val.inStorage || (MachineNet.AutoPlacedBefore() && (val.hasBeenMoved || val.placedPosition != Vector3.zero)))
			{
				yield break;
			}
			if (MachinePlacement.TryFind(this, out var placement, out var yaw))
			{
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(0f, yaw, 0f);
				ShipBuildModeManager instance2 = ShipBuildModeManager.Instance;
				if ((Object)(object)instance2 != (Object)null)
				{
					instance2.PlaceShipObjectClientRpc(placement, val2, NetworkObjectReference.op_Implicit(netObj), -1);
				}
				MachineNet.MarkAutoPlaced();
				Plugin.Log.LogInfo((object)$"Soda Machine placed at {placement} (facing {yaw:0}).");
			}
			else
			{
				Plugin.Log.LogInfo((object)"Soda Machine: no free spot found, it stays where it spawned (press B to move it).");
			}
		}
	}
	internal static class MachinePlacement
	{
		private const int WallMask = 2305;

		private const int BlockMask = 134220033;

		private static readonly Vector2[] Spots = (Vector2[])(object)new Vector2[3]
		{
			new Vector2(3.3f, 1f),
			new Vector2(3.3f, -1f),
			new Vector2(-0.8f, 1f)
		};

		private const float RoomMidZ = -6.67f;

		private const float ChestY = 1f;

		internal static bool TryFind(SodaMachine machine, out Vector3 placement, out float yaw)
		{
			//IL_0001: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: 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_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: 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_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			placement = default(Vector3);
			yaw = 0f;
			StartOfRound instance = StartOfRound.Instance;
			Transform val = (((Object)(object)instance != (Object)null) ? instance.elevatorTransform : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			List<Collider> list = machine.OwnColliders.Where((Collider c) => c.enabled).ToList();
			foreach (Collider item in list)
			{
				item.enabled = false;
			}
			try
			{
				Vector3 size = MachineModel.Size;
				bool flag = false;
				Vector3 val2 = default(Vector3);
				float num = 0f;
				Vector2[] spots = Spots;
				RaycastHit val6 = default(RaycastHit);
				RaycastHit val7 = default(RaycastHit);
				foreach (Vector2 val3 in spots)
				{
					Vector3 val4 = val.TransformDirection(new Vector3(0f, 0f, val3.y));
					Vector3 normalized = ((Vector3)(ref val4)).normalized;
					val4 = val.TransformDirection(Vector3.right);
					Vector3 normalized2 = ((Vector3)(ref val4)).normalized;
					Vector3 val5 = val.TransformPoint(new Vector3(val3.x, 1f, -6.67f));
					float num3 = float.MaxValue;
					float[] array = new float[3]
					{
						(0f - size.x) * 0.5f,
						0f,
						size.x * 0.5f
					};
					foreach (float num5 in array)
					{
						float[] array2 = new float[2] { -0.5f, 0.6f };
						foreach (float num7 in array2)
						{
							if (Physics.Raycast(val5 + normalized2 * num5 + Vector3.up * num7, normalized, ref val6, 6f, 2305, (QueryTriggerInteraction)1))
							{
								num3 = Mathf.Min(num3, ((RaycastHit)(ref val6)).distance);
							}
						}
					}
					if (num3 == float.MaxValue || num3 < size.z + 0.6f)
					{
						Plugin.Log.LogInfo((object)$"Soda Machine: spot {val3} has no room (wall at {num3:0.00} m).");
					}
					else if (Physics.Raycast(val5 + normalized * (num3 - 0.04f - size.z * 0.5f) + Vector3.up * 0.5f, Vector3.down, ref val7, 3f, 2305, (QueryTriggerInteraction)1))
					{
						Vector3 val8 = ((RaycastHit)(ref val7)).point + Vector3.up * (size.y * 0.5f + 0.02f);
						Quaternion val9 = Quaternion.LookRotation(-normalized, Vector3.up);
						float y = ((Quaternion)(ref val9)).eulerAngles.y;
						if (!flag)
						{
							flag = true;
							val2 = val8;
							num = y;
						}
						if (!Physics.CheckBox(val8, size * 0.5f * 0.9f, Quaternion.Euler(0f, y, 0f), 134220033, (QueryTriggerInteraction)1))
						{
							placement = val8;
							yaw = y;
							Plugin.Log.LogInfo((object)$"Soda Machine: spot {val3} (ship {val.InverseTransformPoint(val8)}), wall {num3:0.00} m away.");
							return true;
						}
						Plugin.Log.LogInfo((object)$"Soda Machine: spot {val3} is taken.");
					}
				}
				if (flag)
				{
					placement = val2;
					yaw = num;
					Plugin.Log.LogInfo((object)"Soda Machine: every spot looked taken, using the first one.");
					return true;
				}
				return false;
			}
			finally
			{
				foreach (Collider item2 in list)
				{
					if ((Object)(object)item2 != (Object)null)
					{
						item2.enabled = true;
					}
				}
			}
		}
	}
	internal static class MachineNet
	{
		internal enum Result
		{
			Free,
			Bought,
			NoMoney,
			NoFree,
			SoldOut,
			NotSold,
			OutOfStock
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnUse;

			public static HandleNamedMessageDelegate <1>__OnPress;

			public static HandleNamedMessageDelegate <2>__OnItem;

			public static HandleNamedMessageDelegate <3>__OnClaims;

			public static HandleNamedMessageDelegate <4>__OnClaimRequest;
		}

		private const string UseMsg = "Miles.DrinkableSoda.MachineUse";

		private const string PressMsg = "Miles.DrinkableSoda.MachinePress";

		private const string ItemMsg = "Miles.DrinkableSoda.MachineItem";

		private const string ClaimsMsg = "Miles.DrinkableSoda.MachineClaims";

		private const string ClaimReqMsg = "Miles.DrinkableSoda.MachineClaimReq";

		private const string SaveKey = "Miles.DrinkableSoda.MachineClaims";

		private static NetworkManager registeredOn;

		private static readonly Dictionary<string, int> claims = new Dictionary<string, int>();

		private static int claimsDay = -1;

		private static string claimsFile;

		private static int stockDay = -2;

		private const string StockKey = "Miles.DrinkableSoda.MachineStock";

		private static readonly int[] stock = new int[10];

		private static bool stockReady;

		private const string PlacedKey = "Miles.DrinkableSoda.MachinePlaced";

		private const int PlacedVersion = 2;

		private static readonly DrinkId[] ButtonOrder = new DrinkId[10]
		{
			DrinkId.RedSoda,
			DrinkId.Web,
			DrinkId.Alt,
			DrinkId.Jim,
			DrinkId.Sakura,
			DrinkId.Vanilla,
			DrinkId.Cheese,
			DrinkId.Morv,
			DrinkId.Harvest,
			DrinkId.Generic
		};

		private static Terminal term;

		private static NetworkManager NM => NetworkManager.Singleton;

		internal static bool Limited
		{
			get
			{
				if (SodaConfig.Instance != null)
				{
					return SodaConfig.Instance.MachineStock.Value;
				}
				return false;
			}
		}

		internal static Terminal Term
		{
			get
			{
				if ((Object)(object)term == (Object)null)
				{
					term = (((Object)(object)Shop.Current != (Object)null) ? Shop.Current : Object.FindObjectOfType<Terminal>());
				}
				return term;
			}
		}

		internal static int StockLeft(int button)
		{
			if (!Limited)
			{
				return int.MaxValue;
			}
			if ((Object)(object)NM != (Object)null && NM.IsServer)
			{
				EnsureDay();
			}
			if (button < 0 || button >= stock.Length)
			{
				return 0;
			}
			return stock[button];
		}

		private static int SpecialStock(int max, float odds)
		{
			max = Mathf.Max(0, max);
			odds = Mathf.Clamp(odds, 0.01f, 1f);
			float num = 0f;
			float num2 = 1f;
			int num3 = 0;
			while (num3 <= max)
			{
				num += num2;
				num3++;
				num2 *= odds;
			}
			float num4 = Random.value * num;
			num2 = 1f;
			int num5 = 0;
			while (num5 <= max)
			{
				num4 -= num2;
				if (num4 <= 0f)
				{
					return num5;
				}
				num5++;
				num2 *= odds;
			}
			return max;
		}

		private static void Restock()
		{
			SodaConfig instance = SodaConfig.Instance;
			int num = Mathf.Max(0, Mathf.Min(instance.MachineStockMin.Value, instance.MachineStockMax.Value));
			int num2 = Mathf.Max(num, Mathf.Max(instance.MachineStockMin.Value, instance.MachineStockMax.Value));
			for (int i = 0; i < stock.Length; i++)
			{
				DrinkDef drinkDef = DefAt(i);
				if (drinkDef != null && drinkDef.special)
				{
					stock[i] = SpecialStock(instance.MachineRareStock.Value, instance.MachineRareChance.Value);
				}
				else
				{
					stock[i] = Random.Range(num, num2 + 1);
				}
			}
			stockReady = true;
			Plugin.Log.LogInfo((object)("Soda Machine restocked: " + string.Join(", ", stock)));
		}

		internal unsafe static void Register()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager nM = NM;
			if ((Object)(object)nM == (Object)null || nM.CustomMessagingManager == null || (Object)(object)registeredOn == (Object)(object)nM)
			{
				return;
			}
			registeredOn = nM;
			claims.Clear();
			claimsDay = -1;
			claimsFile = null;
			CustomMessagingManager customMessagingManager = nM.CustomMessagingManager;
			object obj = <>O.<0>__OnUse;
			if (obj == null)
			{
				HandleNamedMessageDelegate val = OnUse;
				<>O.<0>__OnUse = val;
				obj = (object)val;
			}
			customMessagingManager.RegisterNamedMessageHandler("Miles.DrinkableSoda.MachineUse", (HandleNamedMessageDelegate)obj);
			object obj2 = <>O.<1>__OnPress;
			if (obj2 == null)
			{
				HandleNamedMessageDelegate val2 = OnPress;
				<>O.<1>__OnPress = val2;
				obj2 = (object)val2;
			}
			customMessagingManager.RegisterNamedMessageHandler("Miles.DrinkableSoda.MachinePress", (HandleNamedMessageDelegate)obj2);
			object obj3 = <>O.<2>__OnItem;
			if (obj3 == null)
			{
				HandleNamedMessageDelegate val3 = OnItem;
				<>O.<2>__OnItem = val3;
				obj3 = (object)val3;
			}
			customMessagingManager.RegisterNamedMessageHandler("Miles.DrinkableSoda.MachineItem", (HandleNamedMessageDelegate)obj3);
			object obj4 = <>O.<3>__OnClaims;
			if (obj4 == null)
			{
				HandleNamedMessageDelegate val4 = OnClaims;
				<>O.<3>__OnClaims = val4;
				obj4 = (object)val4;
			}
			customMessagingManager.RegisterNamedMessageHandler("Miles.DrinkableSoda.MachineClaims", (HandleNamedMessageDelegate)obj4);
			object obj5 = <>O.<4>__OnClaimRequest;
			if (obj5 == null)
			{
				HandleNamedMessageDelegate val5 = OnClaimRequest;
				<>O.<4>__OnClaimRequest = val5;
				obj5 = (object)val5;
			}
			customMessagingManager.RegisterNamedMessageHandler("Miles.DrinkableSoda.MachineClaimReq", (HandleNamedMessageDelegate)obj5);
			if (nM.IsServer)