Decompiled source of Drugs v0.0.3

Drugs.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using Drugs.Smoking;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Drugs")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Drugs")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.3")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.3.0")]
namespace Drugs
{
	internal static class ContentCatalog
	{
		internal static readonly string[] Items = new string[11]
		{
			"WeedSeedsF", "WeedSeedsM", "WeedLeaves", "WeedBuds", "RollingPaper", "WeedGround", "WeedJoint", "WeedCrossJoint", "WeedButter", "WeedCookieUncooked",
			"WeedCookie"
		};

		internal static readonly string[] Pickables = new string[2] { "Pickable_WeedBuds", "Pickable_WeedSeeds" };

		internal static readonly RecipeConfig[] Recipes = (RecipeConfig[])(object)new RecipeConfig[6]
		{
			Recipe("RollingPaper", "piece_drugtable", 1, Req("WeedLeaves", 3), Req("Honey", 1)),
			Recipe("WeedGround", "piece_drugtable", 2, Req("WeedBuds", 1)),
			Recipe("WeedJoint", "", 1, Req("RollingPaper", 1), Req("WeedGround", 1)),
			Recipe("WeedCrossJoint", "piece_drugtable", 1, Req("RollingPaper", 2), Req("WeedGround", 2)),
			Recipe("WeedButter", "piece_cauldron", 1, Req("WeedLeaves", 5), Req("WeedBuds", 2), Req("OatMilk", 2)),
			Recipe("WeedCookieUncooked", "piece_preptable", 4, Req("WeedButter", 1), Req("BarleyFlour", 2))
		};

		internal static readonly (string PrefabId, PieceConfig Config)[] Pieces = new(string, PieceConfig)[4]
		{
			("piece_drugtable", Piece("Hammer", "", Req("RoundLog", 5), Req("FineWood", 10), Req("Stone", 10), Req("Iron", 10))),
			("piece_bong", Piece("Hammer", "forge", Req("Crystal", 5))),
			("sapling_weed", Piece("Cultivator", "", Req("WeedSeedsF", 1, recover: false))),
			("sapling_seedweed", Piece("Cultivator", "", Req("WeedSeedsM", 1, recover: false)))
		};

		internal const int SeedPrice = 100;

		internal const int SeedStack = 1;

		internal const float CookieCookSeconds = 50f;

		internal static readonly Dictionary<string, string> Translations = new Dictionary<string, string>
		{
			{ "piece_drugs_bong_wait", "Servirse" },
			{ "piece_drugs_bong_load", "Sirves 1 Cogollo Molido" },
			{ "piece_drugs_bong_hit", "Pegarse una toka" },
			{ "piece_drugs_bong_need", "Necesitas Cogollo Molido" },
			{ "se_drugs_tosiendo", "Tosiendo" },
			{ "se_drugs_tosiendo_desc", "Velocidad de movimiento -10%. Sin regeneración de resistencia. 5 segundos." },
			{ "se_drugs_volao", "Volao" },
			{ "se_drugs_volao_desc", "Resistencia máxima y velocidad de movimiento +5%." },
			{ "se_drugs_cookie_volao_desc", "Resistencia máxima y velocidad de movimiento +5%. Sin Bajón cuando esto se acabe." },
			{ "se_drugs_bajon", "Bajón" },
			{ "se_drugs_bajon_desc", "La comida se agota 25% más rápido. 1 minuto. Fuma de nuevo para cancelarlo." },
			{ "se_drugs_palida", "Pálida" },
			{ "se_drugs_palida_desc", "Sobrecargado y mareado por 5 segundos, luego vómito." },
			{ "msg_drugs_cookie_badtrip", "No puedes comer otra galleta de mota durante una Pálida." }
		};

		private static RequirementConfig Req(string item, int amount, bool recover = true)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			return new RequirementConfig(item, amount, 0, recover);
		}

		private static RecipeConfig Recipe(string item, string station, int amount, params RequirementConfig[] requirements)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			return new RecipeConfig
			{
				Name = "Recipe_Drugs_" + item,
				Item = item,
				Amount = amount,
				CraftingStation = station,
				MinStationLevel = 1,
				Requirements = requirements
			};
		}

		private static PieceConfig Piece(string table, string station, params RequirementConfig[] requirements)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return new PieceConfig
			{
				PieceTable = table,
				CraftingStation = station,
				Requirements = requirements
			};
		}
	}
	internal static class ContentRegistration
	{
		[HarmonyPatch(typeof(Trader), "GetAvailableItems")]
		private static class BogWitchSeeds
		{
			private static void Postfix(Trader __instance, List<TradeItem> __result)
			{
				//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_0090: 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_009f: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Expected O, but got Unknown
				//IL_00ce: Expected O, but got Unknown
				if (!Ready || (((Object)__instance).name != "BogWitch" && ((Object)__instance).name != "BogWitch(Clone)"))
				{
					return;
				}
				string[] array = new string[2] { "WeedSeedsF", "WeedSeedsM" };
				foreach (string id in array)
				{
					ItemDrop component = Prefabs[id].GetComponent<ItemDrop>();
					if (!__result.Any((TradeItem stock) => Object.op_Implicit((Object)(object)stock.m_prefab) && ((Object)stock.m_prefab).name == id))
					{
						__result.Add(new TradeItem
						{
							m_prefab = component,
							m_stack = 1,
							m_price = 100,
							m_tooltip = (component.m_itemData.m_shared.m_description ?? string.Empty),
							m_buyPlayerEffects = new EffectList()
						});
					}
				}
			}
		}

		private const string BundleResourceName = "drugs";

		private static readonly Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>(StringComparer.Ordinal);

		private static AssetBundle bundle;

		internal static bool Ready { get; private set; }

		internal static void Initialize()
		{
			PrefabManager.OnVanillaPrefabsAvailable += Register;
		}

		private static void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Register;
			LoadBundleAndSounds();
			LoadAndValidatePrefabs();
			RegisterItems();
			RegisterPickables();
			RegisterPlants();
			RegisterPieces();
			RegisterRecipesAndConversion();
			SmokingSystem.RegisterEffects(LoadSprite("tosiendo"), LoadSprite("volao"), Prefabs["WeedGround"].GetComponent<ItemDrop>().m_itemData.GetIcon(), LoadSprite("palida"));
			Ready = true;
			SmokingEffects.OnSmoked = SmokingSystem.Smoke;
			int num = ContentCatalog.Items.Length + ContentCatalog.Pickables.Length + ContentCatalog.Pieces.Length;
			Logger.LogInfo((object)$"Registered {num} drugs prefabs, {ContentCatalog.Recipes.Length} recipes, the oven conversion, and smoking/cookie effects.");
		}

		private static void LoadBundleAndSounds()
		{
			Dictionary<string, Shader> dictionary = (from s in Resources.FindObjectsOfTypeAll<Shader>()
				where Object.op_Implicit((Object)(object)s)
				group s by ((Object)s).name).ToDictionary((IGrouping<string, Shader> g) => g.Key, (IGrouping<string, Shader> g) => g.First());
			bundle = AssetUtils.LoadAssetBundleFromResources("drugs", typeof(ContentRegistration).Assembly);
			if (!Object.op_Implicit((Object)(object)bundle))
			{
				throw new InvalidOperationException("Could not load the drugs asset bundle. Rebuild with the Unity drugs bundle embedded.");
			}
			Material[] array = bundle.LoadAllAssets<Material>();
			foreach (Material val in array)
			{
				if (Object.op_Implicit((Object)(object)val.shader) && dictionary.TryGetValue(((Object)val.shader).name, out var value))
				{
					val.shader = value;
				}
			}
			SmokingEffects.BongHitSound = LoadClip("BongHit");
			SmokingEffects.JointHitSound = LoadClip("JointHit");
			SmokingEffects.CoughSound = LoadClip("Cough");
		}

		private static void LoadAndValidatePrefabs()
		{
			foreach (string item2 in ContentCatalog.Items.Concat(ContentCatalog.Pickables).Concat(ContentCatalog.Pieces.Select(((string PrefabId, PieceConfig Config) p) => p.PrefabId)))
			{
				GameObject val = bundle.LoadAsset<GameObject>(item2);
				if (!Object.op_Implicit((Object)(object)val))
				{
					throw new InvalidOperationException("Missing drugs prefab: " + item2 + ". Rebuild the drugs bundle from the current Unity project.");
				}
				Prefabs.Add(item2, val);
				if (!Object.op_Implicit((Object)(object)val.GetComponent<ZNetView>()))
				{
					throw new InvalidOperationException(item2 + " requires a ZNetView.");
				}
			}
			string[] items = ContentCatalog.Items;
			foreach (string text in items)
			{
				if (!Object.op_Implicit((Object)(object)Prefabs[text].GetComponent<ItemDrop>()))
				{
					throw new InvalidOperationException(text + " requires ItemDrop.");
				}
			}
			(string, PieceConfig)[] pieces = ContentCatalog.Pieces;
			for (int num = 0; num < pieces.Length; num++)
			{
				string item = pieces[num].Item1;
				if (!Object.op_Implicit((Object)(object)Prefabs[item].GetComponent<Piece>()))
				{
					throw new InvalidOperationException(item + " requires Piece.");
				}
			}
			if (!Object.op_Implicit((Object)(object)Prefabs["piece_drugtable"].GetComponent<CraftingStation>()))
			{
				throw new InvalidOperationException("piece_drugtable requires CraftingStation.");
			}
			BongInteraction component = Prefabs["piece_bong"].GetComponent<BongInteraction>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.loadedWeed))
			{
				throw new InvalidOperationException("Prepare the bong in Unity and rebuild the bundle; its loaded visual is missing.");
			}
			if (!Object.op_Implicit((Object)(object)Prefabs["WeedCookieUncooked"].transform.Find("attach")))
			{
				throw new InvalidOperationException("WeedCookieUncooked needs an attach child for the oven.");
			}
		}

		private static void RegisterItems()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			string[] items = ContentCatalog.Items;
			foreach (string text in items)
			{
				GameObject val = Prefabs[text];
				SharedData shared = val.GetComponent<ItemDrop>().m_itemData.m_shared;
				if (SmokingSystem.IsSmokeable(text))
				{
					shared.m_itemType = (ItemType)2;
					shared.m_food = (shared.m_foodStamina = (shared.m_foodEitr = 0f));
					shared.m_consumeStatusEffect = null;
				}
				else if (text == "WeedCookie")
				{
					shared.m_itemType = (ItemType)2;
					shared.m_consumeStatusEffect = null;
				}
				else
				{
					shared.m_itemType = (ItemType)1;
					shared.m_consumeStatusEffect = null;
				}
				Sprite val2 = RenderManager.Instance.Render(val, RenderManager.IsometricRotation);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					throw new InvalidOperationException(text + " has no visual to render an icon from.");
				}
				Require(ItemManager.Instance.AddItem(new CustomItem(val, false, new ItemConfig
				{
					Icon = val2
				})), text);
			}
		}

		private static void RegisterPickables()
		{
			//IL_007a: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			string[] pickables = ContentCatalog.Pickables;
			foreach (string text in pickables)
			{
				Pickable component = Prefabs[text].GetComponent<Pickable>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					throw new InvalidOperationException(text + " requires Pickable.");
				}
				string key = ((text == "Pickable_WeedBuds") ? "WeedBuds" : "WeedSeedsM");
				component.m_itemPrefab = Prefabs[key];
				for (int j = 0; j < component.m_extraDrops.m_drops.Count; j++)
				{
					DropData val = component.m_extraDrops.m_drops[j];
					if (Object.op_Implicit((Object)(object)val.m_item) && Prefabs.TryGetValue(((Object)val.m_item).name, out var value))
					{
						val.m_item = value;
					}
					component.m_extraDrops.m_drops[j] = val;
				}
				PrefabManager.Instance.AddPrefab(new CustomPrefab(Prefabs[text], false));
				if ((Object)(object)PrefabManager.Instance.GetPrefab(text) != (Object)(object)Prefabs[text])
				{
					throw new InvalidOperationException("Failed to register " + text);
				}
			}
		}

		private static void RegisterPlants()
		{
			Prefabs["sapling_weed"].GetComponent<Plant>().m_grownPrefabs = (GameObject[])(object)new GameObject[1] { Prefabs["Pickable_WeedBuds"] };
			Prefabs["sapling_seedweed"].GetComponent<Plant>().m_grownPrefabs = (GameObject[])(object)new GameObject[1] { Prefabs["Pickable_WeedSeeds"] };
			FixVanillaEffect(Prefabs["sapling_weed"].GetComponent<Plant>().m_growEffect);
			FixVanillaEffect(Prefabs["sapling_seedweed"].GetComponent<Plant>().m_growEffect);
		}

		private static void RegisterPieces()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			Prefabs["piece_drugtable"].GetComponent<CraftingStation>().m_showBasicRecipies = true;
			(string, PieceConfig)[] pieces = ContentCatalog.Pieces;
			for (int i = 0; i < pieces.Length; i++)
			{
				var (text, val) = pieces[i];
				PiecePrefabRepair.RepairFragmentRoots(Prefabs[text]);
				Sprite val2 = RenderManager.Instance.Render(Prefabs[text], RenderManager.IsometricRotation);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					throw new InvalidOperationException(text + " has no visual to render an icon from.");
				}
				FixVanillaEffect(Prefabs[text].GetComponent<Piece>().m_placeEffect);
				val.Icon = val2;
				Require(PieceManager.Instance.AddPiece(new CustomPiece(Prefabs[text], true, val)), text);
			}
		}

		private static void RegisterRecipesAndConversion()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			RecipeConfig[] recipes = ContentCatalog.Recipes;
			foreach (RecipeConfig val in recipes)
			{
				Require(ItemManager.Instance.AddRecipe(new CustomRecipe(val)), val.Name);
			}
			Require(ItemManager.Instance.AddItemConversion(new CustomItemConversion((ConversionConfig)new CookingConversionConfig
			{
				Station = "piece_oven",
				FromItem = "WeedCookieUncooked",
				ToItem = "WeedCookie",
				CookTime = 50f
			})), "WeedCookie oven conversion");
		}

		private static void Require(bool success, string id)
		{
			if (!success)
			{
				throw new InvalidOperationException("Failed to register " + id);
			}
		}

		private static Sprite LoadSprite(string name)
		{
			Sprite obj = bundle.LoadAsset<Sprite>(name);
			if (!Object.op_Implicit((Object)(object)obj))
			{
				throw new InvalidOperationException("Missing drugs status effect icon: " + name + ". Rebuild the drugs bundle from the current Unity project.");
			}
			return obj;
		}

		private static AudioClip LoadClip(string name)
		{
			AudioClip obj = bundle.LoadAsset<AudioClip>(name);
			if (!Object.op_Implicit((Object)(object)obj))
			{
				throw new InvalidOperationException("Missing drugs audio clip: " + name + ". Rebuild the drugs bundle from the current Unity project.");
			}
			return obj;
		}

		private static void FixVanillaEffect(EffectList effects)
		{
			for (int i = 0; i < effects.m_effectPrefabs.Length; i++)
			{
				EffectData val = effects.m_effectPrefabs[i];
				if (Object.op_Implicit((Object)(object)val.m_prefab))
				{
					GameObject prefab = PrefabManager.Instance.GetPrefab(((Object)val.m_prefab).name);
					if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab != (Object)(object)val.m_prefab)
					{
						val.m_prefab = prefab;
						effects.m_effectPrefabs[i] = val;
					}
				}
			}
		}

		internal static void Shutdown()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Register;
			Ready = false;
			Prefabs.Clear();
			SmokingEffects.BongHitSound = (SmokingEffects.JointHitSound = (SmokingEffects.CoughSound = null));
			if (Object.op_Implicit((Object)(object)bundle))
			{
				bundle.Unload(false);
			}
		}
	}
	[BepInPlugin("com.valkyrie.drugs", "Drugs", "0.0.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class Drugs : BaseUnityPlugin
	{
		public const string PluginGUID = "com.valkyrie.drugs";

		public const string PluginName = "Drugs";

		public const string PluginVersion = "0.0.3";

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		private void OnDestroy()
		{
			SmokingSystem.Shutdown();
		}

		private void Awake()
		{
			SmokingSystem.Initialize();
		}
	}
	internal static class PiecePrefabRepair
	{
		internal static void RepairFragmentRoots(GameObject prefab)
		{
			WearNTear component = prefab.GetComponent<WearNTear>();
			if (Object.op_Implicit((Object)(object)component) && component.m_fragmentRoots != null)
			{
				component.m_fragmentRoots = component.m_fragmentRoots.Where((GameObject root) => Object.op_Implicit((Object)(object)root)).ToArray();
			}
		}
	}
	internal static class PortalSwirl
	{
		[HarmonyPatch(typeof(Hud), "Update")]
		private static class UpdateOverlay
		{
			private static void Postfix(Hud __instance)
			{
				Player localPlayer = Player.m_localPlayer;
				if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || !((Character)localPlayer).GetSEMan().HaveStatusEffect(SmokingSystem.BadTrip))
				{
					Clear();
				}
				else
				{
					if (Object.op_Implicit((Object)(object)overlay))
					{
						return;
					}
					Transform val = (Object.op_Implicit((Object)(object)__instance.m_teleportingProgress) ? __instance.m_teleportingProgress.transform.Find("Swirl") : null);
					if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)__instance.m_loadingScreen))
					{
						if (!warned)
						{
							Logger.LogWarning((object)"Palida: the vanilla portal Swirl was not found on the HUD.");
						}
						warned = true;
						return;
					}
					overlay = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)__instance.m_loadingScreen).transform.parent, false);
					((Object)overlay).name = "Drugs_Palida_PortalSwirl";
					overlay.transform.SetAsLastSibling();
					CanvasGroup val2 = overlay.GetComponent<CanvasGroup>();
					if (!Object.op_Implicit((Object)(object)val2))
					{
						val2 = overlay.AddComponent<CanvasGroup>();
					}
					val2.alpha = 1f;
					val2.blocksRaycasts = false;
					val2.interactable = false;
					overlay.SetActive(true);
				}
			}
		}

		private static GameObject overlay;

		private static bool warned;

		internal static void Clear()
		{
			if (Object.op_Implicit((Object)(object)overlay))
			{
				overlay.SetActive(false);
				Object.Destroy((Object)(object)overlay);
			}
			overlay = null;
		}
	}
	internal static class SmokingSystem
	{
		[HarmonyPatch(typeof(Player), "ConsumeItem")]
		private static class ConsumeWeed
		{
			private static bool Prefix(Player __instance, Inventory inventory, ItemData item, ref bool __result)
			{
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				bool flag = IsCookie(item);
				bool flag2 = item != null && Object.op_Implicit((Object)(object)item.m_dropPrefab) && IsSmokeable(((Object)item.m_dropPrefab).name);
				if (!flag && !flag2)
				{
					return true;
				}
				__result = false;
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || ((Character)__instance).IsDead() || !ContentRegistration.Ready || inventory == null || !inventory.ContainsItem(item))
				{
					return false;
				}
				if (flag)
				{
					if (((Character)__instance).GetSEMan().HaveStatusEffect(BadTrip))
					{
						((Character)__instance).Message((MessageType)2, "$msg_drugs_cookie_badtrip", 0, (Sprite)null, false);
						return false;
					}
					return true;
				}
				if (inventory.RemoveItem(item, 1))
				{
					__result = SmokingEffects.Smoke(__instance);
					if (__result)
					{
						SmokingEffects.PlaySound(SmokingEffects.JointHitSound, ((Component)__instance).transform.position);
					}
				}
				return false;
			}

			private static void Postfix(Player __instance, ItemData item, bool __result, bool __runOriginal)
			{
				if (__runOriginal && __result && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && IsCookie(item))
				{
					EatCookie(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "CanEat")]
		private static class RepeatCookie
		{
			private static bool Prefix(Player __instance, ItemData item, ref bool __result)
			{
				if (!ContentRegistration.Ready || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !IsCookie(item))
				{
					return true;
				}
				if (!__instance.GetFoods().Any((Food food) => IsCookie(food.m_item)))
				{
					return true;
				}
				__result = !((Character)__instance).IsDead() && !((Character)__instance).GetSEMan().HaveStatusEffect(BadTrip);
				return false;
			}
		}

		private struct PhaseSnapshot
		{
			internal SmokingPhase Cough;

			internal SmokingPhase High;

			internal SmokingPhase Hunger;

			internal SmokingPhase BadTrip;
		}

		[HarmonyPatch(typeof(SEMan), "Update")]
		private static class AdvancePhase
		{
			private static void Prefix(SEMan __instance, Character ___m_character, out PhaseSnapshot __state)
			{
				__state = default(PhaseSnapshot);
				if (!((Object)(object)___m_character != (Object)(object)Player.m_localPlayer))
				{
					__state.Cough = __instance.GetStatusEffect(Cough) as SmokingPhase;
					__state.High = __instance.GetStatusEffect(High) as SmokingPhase;
					__state.Hunger = __instance.GetStatusEffect(Hunger) as SmokingPhase;
					__state.BadTrip = __instance.GetStatusEffect(BadTrip) as SmokingPhase;
				}
			}

			private static void Postfix(SEMan __instance, Character ___m_character, PhaseSnapshot __state)
			{
				Player val = (Player)(object)((___m_character is Player) ? ___m_character : null);
				if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !((Character)val).IsDead() && (Advance(__instance, __state.Cough) | Advance(__instance, __state.High) | Advance(__instance, __state.Hunger) | Advance(__instance, __state.BadTrip)))
				{
					RefreshStamina(val);
				}
			}

			private static bool Advance(SEMan effects, SmokingPhase phase)
			{
				if (!Object.op_Implicit((Object)(object)phase) || !((StatusEffect)phase).IsDone() || effects.HaveStatusEffect(((StatusEffect)phase).NameHash()))
				{
					return false;
				}
				if (((StatusEffect)phase).NameHash() == Cough)
				{
					effects.AddStatusEffect(SEMan.s_statusEffectRested, true, 0, 0f, (short)(-1));
				}
				if (((StatusEffect)phase).NameHash() == BadTrip)
				{
					effects.AddStatusEffect(pukeEffect, true, 0, 0f, (short)(-1));
				}
				else if (!string.IsNullOrEmpty(phase.nextEffect))
				{
					effects.AddStatusEffect(StringExtensionMethods.GetStableHashCode(phase.nextEffect), true, 0, 0f, (short)(-1));
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Player), "IsEncumbered")]
		private static class BadTripEncumbrance
		{
			private static void Postfix(Player __instance, ref bool __result)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && ((Character)__instance).GetSEMan().HaveStatusEffect(BadTrip))
				{
					__result = true;
				}
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")]
		private static class CoughRegen
		{
			[HarmonyPriority(0)]
			private static void Postfix(SEMan __instance, ref float __0)
			{
				if (__instance.HaveStatusEffect(Cough))
				{
					__0 = 0f;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
		private static class HighStamina
		{
			private static void Postfix(Player __instance, ref float __1)
			{
				if (((Character)__instance).GetSEMan().HaveStatusEffect(High))
				{
					__1 *= 1.05f;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateFood", new Type[]
		{
			typeof(float),
			typeof(bool)
		})]
		private static class HungerDrain
		{
			private static void Prefix(Player __instance, float dt, bool forceUpdate, ref float ___m_foodUpdateTimer)
			{
				if (!forceUpdate && ((Character)__instance).GetSEMan().HaveStatusEffect(Hunger))
				{
					___m_foodUpdateTimer += dt * Game.m_foodRate * 0.25f;
				}
			}
		}

		internal static readonly int Cough = StringExtensionMethods.GetStableHashCode("Drugs_Tosiendo");

		internal static readonly int High = StringExtensionMethods.GetStableHashCode("Drugs_Volao");

		internal static readonly int Hunger = StringExtensionMethods.GetStableHashCode("Drugs_Bajon");

		internal static readonly int BadTrip = StringExtensionMethods.GetStableHashCode("Drugs_Palida");

		private static readonly MethodInfo FoodValues = AccessTools.Method(typeof(Player), "GetTotalFoodValue", (Type[])null, (Type[])null);

		private static Harmony harmony;

		private static StatusEffect pukeEffect;

		internal static bool IsSmokeable(string id)
		{
			if (!(id == "WeedJoint"))
			{
				return id == "WeedCrossJoint";
			}
			return true;
		}

		private static bool IsCookie(ItemData item)
		{
			if (item != null && Object.op_Implicit((Object)(object)item.m_dropPrefab))
			{
				return ((Object)item.m_dropPrefab).name == "WeedCookie";
			}
			return false;
		}

		internal static void Initialize()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			harmony = new Harmony("com.valkyrie.drugs.smoking");
			harmony.PatchAll(typeof(SmokingSystem).Assembly);
			ContentRegistration.Initialize();
			CustomLocalization localization = Drugs.Localization;
			string text = "Spanish";
			localization.AddTranslation(ref text, ContentCatalog.Translations);
			CustomLocalization localization2 = Drugs.Localization;
			text = "English";
			localization2.AddTranslation(ref text, ContentCatalog.Translations);
		}

		internal static void RegisterEffects(Sprite tosiendoIcon, Sprite volaoIcon, Sprite bajonIcon, Sprite palidaIcon)
		{
			AddPhase("Drugs_Tosiendo", "tosiendo", 5f, 0.9f, "Drugs_Volao", tosiendoIcon);
			AddPhase("Drugs_Volao", "volao", 60f, 1.05f, "Drugs_Bajon", volaoIcon);
			AddPhase("Drugs_Bajon", "bajon", 60f, 1f, null, bajonIcon);
			AddPhase("Drugs_Palida", "palida", 5f, 1f, null, palidaIcon);
			GameObject prefab = PrefabManager.Instance.GetPrefab("Pukeberries");
			pukeEffect = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_consumeStatusEffect : null);
			if (!Object.op_Implicit((Object)(object)pukeEffect))
			{
				throw new InvalidOperationException("The vanilla Pukeberries status effect could not be resolved.");
			}
		}

		private static void AddPhase(string id, string key, float seconds, float speed, string next, Sprite icon)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			SmokingPhase smokingPhase = ScriptableObject.CreateInstance<SmokingPhase>();
			((Object)smokingPhase).name = id;
			((StatusEffect)smokingPhase).m_name = "$se_drugs_" + key;
			((StatusEffect)smokingPhase).m_tooltip = "$se_drugs_" + key + "_desc";
			((StatusEffect)smokingPhase).m_ttl = seconds;
			((StatusEffect)smokingPhase).m_icon = icon;
			smokingPhase.speedMultiplier = speed;
			smokingPhase.nextEffect = next;
			if (!ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)smokingPhase, false)))
			{
				throw new InvalidOperationException("Failed to register " + id);
			}
		}

		internal static void Smoke(Player player)
		{
			SEMan sEMan = ((Character)player).GetSEMan();
			sEMan.RemoveStatusEffect(Cough, false);
			sEMan.RemoveStatusEffect(High, false);
			sEMan.RemoveStatusEffect(Hunger, false);
			sEMan.AddStatusEffect(Cough, true, 0, 0f, (short)(-1));
			RefreshStamina(player);
		}

		private static void EatCookie(Player player)
		{
			SEMan sEMan = ((Character)player).GetSEMan();
			SmokingPhase smokingPhase = sEMan.GetStatusEffect(High) as SmokingPhase;
			int additionalCookies = IntoxicationRules.CountCookie(Object.op_Implicit((Object)(object)smokingPhase), Object.op_Implicit((Object)(object)smokingPhase) ? smokingPhase.additionalCookies : 0);
			sEMan.RemoveStatusEffect(Cough, false);
			sEMan.RemoveStatusEffect(Hunger, false);
			sEMan.AddStatusEffect(SEMan.s_statusEffectRested, true, 0, 0f, (short)(-1));
			if (IntoxicationRules.IsOverdose(additionalCookies))
			{
				sEMan.RemoveStatusEffect(High, false);
				sEMan.AddStatusEffect(BadTrip, true, 0, 0f, (short)(-1));
			}
			else
			{
				sEMan.AddStatusEffect(High, true, 0, 0f, (short)(-1));
				SmokingPhase obj = sEMan.GetStatusEffect(High) as SmokingPhase;
				if (!Object.op_Implicit((Object)(object)obj))
				{
					throw new InvalidOperationException("Volao was not registered.");
				}
				((StatusEffect)obj).m_ttl = 180f;
				obj.nextEffect = null;
				obj.additionalCookies = additionalCookies;
				((StatusEffect)obj).m_tooltip = "$se_drugs_cookie_volao_desc";
				((StatusEffect)obj).ResetTime();
			}
			RefreshStamina(player);
		}

		internal static void RefreshStamina(Player player)
		{
			object[] array = new object[3] { 0f, 0f, 0f };
			FoodValues.Invoke(player, array);
			player.SetMaxStamina((float)array[1], true);
		}

		internal static void Shutdown()
		{
			SmokingEffects.OnSmoked = null;
			PortalSwirl.Clear();
			ContentRegistration.Shutdown();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
}
namespace Drugs.Smoking
{
	[DisallowMultipleComponent]
	public sealed class BongInteraction : MonoBehaviour, Hoverable, Interactable
	{
		public GameObject loadedWeed;

		public string fuelPrefab = "WeedGround";

		public float interactionDistance = 3f;

		private const string LoadedKey = "Drugs_BongLoaded";

		private const string OwnershipRpc = "Drugs_BongOwnership";

		private ZNetView view;

		private Player pendingPlayer;

		private bool expectedLoaded;

		private float deadline;

		private float nextRequest;

		private bool Loaded
		{
			get
			{
				if (Object.op_Implicit((Object)(object)view) && view.IsValid())
				{
					return view.GetZDO().GetBool("Drugs_BongLoaded", false);
				}
				return false;
			}
		}

		private void Awake()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)loadedWeed))
			{
				loadedWeed.SetActive(false);
			}
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				view.Register<long>("Drugs_BongOwnership", (Action<long, long>)RequestOwnership);
			}
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverName()
		{
			return "Bong";
		}

		public string GetHoverText()
		{
			string text = (Object.op_Implicit((Object)(object)pendingPlayer) ? "$piece_drugs_bong_wait" : (Loaded ? "$piece_drugs_bong_hit" : "$piece_drugs_bong_load"));
			return Localization.instance.Localize("Bong\n[<color=yellow><b>$KEY_Use</b></color>] " + text);
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (!hold && !Object.op_Implicit((Object)(object)pendingPlayer))
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
				{
					return Begin(val);
				}
			}
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			if (!IsFuel(item))
			{
				return false;
			}
			if (!Loaded && !Object.op_Implicit((Object)(object)pendingPlayer))
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer)
				{
					Begin(val);
				}
			}
			return true;
		}

		private bool IsFuel(ItemData item)
		{
			if (item != null && Object.op_Implicit((Object)(object)item.m_dropPrefab))
			{
				return ((Object)item.m_dropPrefab).name == fuelPrefab;
			}
			return false;
		}

		private ItemData FindFuel(Player player)
		{
			return ((Humanoid)player).GetInventory().GetAllItems().Find(IsFuel);
		}

		private bool CanUse(Player player)
		{
			//IL_001e: 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)
			if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !((Character)player).InPlaceMode())
			{
				return Vector3.Distance(((Component)player).transform.position, ((Component)this).transform.position) <= interactionDistance;
			}
			return false;
		}

		private bool Begin(Player player)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)view) || !view.IsValid() || !CanUse(player) || SmokingEffects.OnSmoked == null)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return false;
			}
			if (!Loaded && FindFuel(player) == null)
			{
				((Character)player).Message((MessageType)2, "$piece_drugs_bong_need", 0, (Sprite)null, false);
				return false;
			}
			expectedLoaded = Loaded;
			pendingPlayer = player;
			deadline = Time.time + 5f;
			nextRequest = 0f;
			Update();
			return true;
		}

		private void RequestOwnership(long sender, long playerId)
		{
			if (!view.IsOwner() || Object.op_Implicit((Object)(object)pendingPlayer))
			{
				return;
			}
			Player player = Player.GetPlayer(playerId);
			if (CanUse(player))
			{
				ZNetView component = ((Component)player).GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.GetZDO().GetOwner() == sender)
				{
					view.GetZDO().SetOwner(sender);
				}
			}
		}

		private void Update()
		{
			//IL_00f3: 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)
			if (Object.op_Implicit((Object)(object)loadedWeed) && loadedWeed.activeSelf != Loaded)
			{
				loadedWeed.SetActive(Loaded);
			}
			if (!Object.op_Implicit((Object)(object)pendingPlayer))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)view) || !view.IsValid() || Time.time > deadline || !CanUse(pendingPlayer))
			{
				pendingPlayer = null;
				return;
			}
			if (!view.IsOwner())
			{
				if (Time.time >= nextRequest)
				{
					nextRequest = Time.time + 0.5f;
					view.InvokeRPC("Drugs_BongOwnership", new object[1] { pendingPlayer.GetPlayerID() });
				}
				return;
			}
			Player val = pendingPlayer;
			pendingPlayer = null;
			if (Loaded != expectedLoaded || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return;
			}
			if (Loaded)
			{
				if (SmokingEffects.Smoke(val))
				{
					view.GetZDO().Set("Drugs_BongLoaded", false);
					SmokingEffects.PlaySound(SmokingEffects.BongHitSound, ((Component)this).transform.position);
				}
			}
			else
			{
				ItemData val2 = FindFuel(val);
				if (val2 != null && ((Humanoid)val).GetInventory().RemoveItem(val2, 1))
				{
					view.GetZDO().Set("Drugs_BongLoaded", true);
				}
			}
			if (Object.op_Implicit((Object)(object)loadedWeed))
			{
				loadedWeed.SetActive(Loaded);
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				view.Unregister("Drugs_BongOwnership");
			}
		}
	}
	public static class IntoxicationRules
	{
		public const float CoughSeconds = 5f;

		public const float SmokeHighSeconds = 60f;

		public const float CookieHighSeconds = 180f;

		public const float HungerSeconds = 60f;

		public const float BadTripSeconds = 5f;

		public const int AdditionalCookiesForBadTrip = 2;

		public const float CoughSoundDelaySeconds = 3f;

		public static int CountCookie(bool alreadyHigh, int additionalCookies)
		{
			if (!alreadyHigh)
			{
				return 0;
			}
			return additionalCookies + 1;
		}

		public static bool IsOverdose(int additionalCookies)
		{
			return additionalCookies >= 2;
		}
	}
	public static class SmokingEffects
	{
		public const string Cough = "Drugs_Tosiendo";

		public const string High = "Drugs_Volao";

		public const string Hunger = "Drugs_Bajon";

		public const string BadTrip = "Drugs_Palida";

		public static Action<Player> OnSmoked;

		public static AudioClip BongHitSound;

		public static AudioClip JointHitSound;

		public static AudioClip CoughSound;

		public static bool Smoke(Player player)
		{
			if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead() || OnSmoked == null)
			{
				return false;
			}
			OnSmoked(player);
			return true;
		}

		public static void PlaySound(AudioClip clip, Vector3 position)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)clip))
			{
				AudioSource.PlayClipAtPoint(clip, position);
			}
		}
	}
	public class SmokingPhase : StatusEffect
	{
		public string nextEffect;

		[NonSerialized]
		public int additionalCookies;

		[NonSerialized]
		private bool coughSoundPlayed;

		public float speedMultiplier = 1f;

		public override void ModifySpeed(float baseSpeed, ref float speed, Character character, Vector3 direction)
		{
			speed *= speedMultiplier;
		}

		public override void UpdateStatusEffect(float dt)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			((StatusEffect)this).UpdateStatusEffect(dt);
			if (!coughSoundPlayed && !(((Object)this).name != "Drugs_Tosiendo") && !(base.m_time < 3f))
			{
				coughSoundPlayed = true;
				SmokingEffects.PlaySound(SmokingEffects.CoughSound, ((Component)base.m_character).transform.position);
			}
		}
	}
}