Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Drugs v0.0.3
Drugs.dll
Decompiled 3 days agousing 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); } } } }