Decompiled source of ItemsReworked v1.6.1

BepInEx/plugins/ItemsReworked.dll

Decompiled 9 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using ItemsReworked.Handlers;
using ItemsReworked.Scrap;
using ItemsReworked.Scrap.ItemsReworked.Scrap;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ItemsReworked")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ItemsReworked")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ef20c8e1-b33c-42f7-8c20-02953334a9b9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ItemsReworked
{
	[BepInPlugin("ItemsReworkedPlugin", "ItemsReworkedPlugin", "1.6.1")]
	public class ItemsReworkedPlugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("ItemsReworkedPlugin");

		internal static ManualLogSource mls;

		internal ScrapHandler scrapHandler = new ScrapHandler();

		internal static ConfigEntry<int> NoEffectProbability;

		internal static ConfigEntry<int> IntoxicationEffectProbability;

		internal static ConfigEntry<int> PoisoningEffectProbability;

		internal static ConfigEntry<int> MaxPoison;

		internal static ConfigEntry<int> HealingEffectProbability;

		internal static ConfigEntry<int> MaxHealing;

		internal static ConfigEntry<float> LaserPointerBatteryDrain;

		internal static ConfigEntry<float> GiantsRangeOfView;

		internal static ConfigEntry<float> MinDurationStaminaBoost;

		internal static ConfigEntry<float> MaxDurationStaminaBoost;

		internal static ConfigEntry<int> MinPills;

		internal static ConfigEntry<int> MaxPills;

		internal static ConfigEntry<float> MinDurationJumpBoost;

		internal static ConfigEntry<float> MaxDurationJumpBoost;

		internal static ConfigEntry<int> MinRemoteUses;

		internal static ConfigEntry<int> MaxRemoteUses;

		internal static ConfigEntry<int> RemoteExplosionProbability;

		internal static ConfigEntry<int> RemoteZapProbability;

		internal static ConfigEntry<bool> DetonateMines;

		internal static ConfigEntry<bool> ToggleTurrets;

		internal static ItemsReworkedPlugin Instance { get; private set; }

		private void Awake()
		{
			NoEffectProbability = ((BaseUnityPlugin)this).Config.Bind<int>("Flask", "NoEffectProbability", 20, "Probability of flasks to have of having no effect.");
			IntoxicationEffectProbability = ((BaseUnityPlugin)this).Config.Bind<int>("Flask", "IntoxicationEffectProbability", 50, "Probability of flasks to intoxicate the player.");
			PoisoningEffectProbability = ((BaseUnityPlugin)this).Config.Bind<int>("Flask", "PoisoningEffectProbability", 50, "Probability of flasks to poison the player.");
			MaxPoison = ((BaseUnityPlugin)this).Config.Bind<int>("Flask", "MaxPoison", 1, "Health left after being poisoned. 0 Kills the player.");
			HealingEffectProbability = ((BaseUnityPlugin)this).Config.Bind<int>("Flask", "HealingEffectProbability", 1, "Probability of flasks to heal the player.");
			MaxHealing = ((BaseUnityPlugin)this).Config.Bind<int>("Flask", "MaxHealing", 33, "Max amount of healing a flask can do. (Based on Scrap Value)");
			LaserPointerBatteryDrain = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Pointer", "LaserPointerBatteryDrain", 0.1f, "Additional battery drain for the laser pointer. (Recommendation: 0.02 - 0.2)");
			GiantsRangeOfView = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Pointer", "GiantsRangeOfView", 200f, "Determines how far a giant can follow the laser without losing track of it. (Recommendation: 75 - 300)");
			MinDurationStaminaBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Mug", "MinDuration", 10f, "Min duration of stamina boost. (Based on Scrap Value)");
			MaxDurationStaminaBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Mug", "MaxDuration", 30f, "Max duration of stamina boost. (Based on Scrap Value)");
			MinPills = ((BaseUnityPlugin)this).Config.Bind<int>("Pill Bottle", "MinPills", 2, "Min amount of pills in a Bottle. (Based on Scrap Value)");
			MaxPills = ((BaseUnityPlugin)this).Config.Bind<int>("Pill Bottle", "MaxPills", 33, "Max amount of pills in a Bottle. (Based on Scrap Value)");
			MinDurationJumpBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Soda", "MinDuration", 5f, "Min duration of jump boost. (Based on Scrap Value)");
			MaxDurationJumpBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Soda", "MaxDuration", 30f, "Max duration of jump boost. (Based on Scrap Value)");
			MinRemoteUses = ((BaseUnityPlugin)this).Config.Bind<int>("Remote", "MinDuration", 2, "Min amount of uses for a remote. (Based on Scrap Value)");
			MaxRemoteUses = ((BaseUnityPlugin)this).Config.Bind<int>("Remote", "MaxDuration", 10, "Max amount of uses for a remote. (Based on Scrap Value)");
			RemoteExplosionProbability = ((BaseUnityPlugin)this).Config.Bind<int>("Remote", "RemoteExplosionProbability", 5, "Probability for the Remote to explode and kill the player when used.");
			RemoteZapProbability = ((BaseUnityPlugin)this).Config.Bind<int>("Remote", "RemoteZapProbability", 15, "Probability for the Remote to zap and damage the player when used.");
			DetonateMines = ((BaseUnityPlugin)this).Config.Bind<bool>("Remote", "DetonateMines", true, "Enables the detonation of Mines by using the remote.");
			ToggleTurrets = ((BaseUnityPlugin)this).Config.Bind<bool>("Remote", "ToggleTurrets", true, "Enables the Disabling/Reenabling of Turrets by using the remote.");
			Instance = this;
			mls = Logger.CreateLogSource("Loading Items Reworked Plugin");
			harmony.PatchAll();
			mls.LogInfo((object)"Items Reworked Plugin loaded sucessfully.");
		}
	}
}
namespace ItemsReworked.Patches
{
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatches
	{
		private static ItemsReworkedPlugin pluginInstance => ItemsReworkedPlugin.Instance;

		[HarmonyPatch("GrabObjectServerRpc")]
		[HarmonyPostfix]
		private static void PickUpScrapItem(NetworkObjectReference grabbedObject)
		{
			NetworkObject val = default(NetworkObject);
			((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null);
			GrabbableObject componentInChildren = ((Component)val).gameObject.GetComponentInChildren<GrabbableObject>();
			pluginInstance.scrapHandler.RegisterScrapItem(componentInChildren);
			ItemsReworkedPlugin.mls.LogInfo((object)(((Object)componentInChildren).name + " picked up."));
		}

		[HarmonyPatch("ActivateItem_performed")]
		[HarmonyPrefix]
		private static void UseScrapItem(PlayerControllerB __instance, CallbackContext context, ref GrabbableObject ___currentlyHeldObjectServer)
		{
			if ((Object)(object)___currentlyHeldObjectServer != (Object)null)
			{
				pluginInstance.scrapHandler.UseScrapItem(___currentlyHeldObjectServer, __instance);
			}
		}

		[HarmonyPatch("InspectItem_performed")]
		[HarmonyPrefix]
		private static void InspectItem_performed(PlayerControllerB __instance, CallbackContext context, ref GrabbableObject ___currentlyHeldObjectServer)
		{
			if ((Object)(object)___currentlyHeldObjectServer != (Object)null)
			{
				pluginInstance.scrapHandler.InspectScrapItem(___currentlyHeldObjectServer, __instance);
			}
		}

		[HarmonyPatch("ItemSecondaryUse_performed")]
		[HarmonyPrefix]
		private static void ItemSecondaryUse_performed(PlayerControllerB __instance, CallbackContext context, ref GrabbableObject ___currentlyHeldObjectServer)
		{
			if ((Object)(object)___currentlyHeldObjectServer != (Object)null)
			{
				pluginInstance.scrapHandler.SpecialUse(___currentlyHeldObjectServer, __instance);
			}
		}
	}
}
namespace ItemsReworked.Scrap
{
	public abstract class BaseItem
	{
		public bool inSpecialScenario = false;

		public bool hasSpecialUse = false;

		public abstract void UseItem(PlayerControllerB player, GrabbableObject item);

		public abstract void SpecialUseItem(PlayerControllerB player, GrabbableObject item);

		public abstract void InspectItem(PlayerControllerB player, GrabbableObject item);

		protected IEnumerator DelayedActivation(PlayerControllerB player, GrabbableObject item, float delayInSeconds, Action activationAction)
		{
			yield return (object)new WaitForSeconds(delayInSeconds);
			activationAction();
		}
	}
	internal class LaserPointer : BaseItem
	{
		private bool isTurnedOn = false;

		private Dictionary<ForestGiantAI, Vector3> distractedGiants;

		private ForestGiantAI distractedGiant;

		internal LaserPointer(GrabbableObject laserPointer)
		{
			distractedGiants = new Dictionary<ForestGiantAI, Vector3>();
			distractedGiant = null;
			hasSpecialUse = false;
			isTurnedOn = false;
		}

		public override void InspectItem(PlayerControllerB player, GrabbableObject item)
		{
			HUDManager.Instance.DisplayTip("Laser Pointer", "Giants are easily distracted by its light", false, false, "LC_Tip1");
		}

		public override void UseItem(PlayerControllerB player, GrabbableObject item)
		{
			if ((Object)(object)item != (Object)null && (Object)(object)player != (Object)null)
			{
				if (item.insertedBattery.charge > 0f)
				{
					ToggleLaserPointerPower(!isTurnedOn);
				}
				if (isTurnedOn)
				{
					((MonoBehaviour)player).StartCoroutine(EmitLaserRay(player, item));
				}
			}
			else
			{
				ItemsReworkedPlugin.mls.LogError((object)("Error during using of " + ((Object)item).name));
			}
		}

		public override void SpecialUseItem(PlayerControllerB player, GrabbableObject item)
		{
			throw new NotImplementedException();
		}

		private void ToggleLaserPointerPower(bool enable)
		{
			ItemsReworkedPlugin.mls.LogInfo((object)$"Setting Laser to {enable}");
			if (isTurnedOn != enable)
			{
				isTurnedOn = enable;
			}
			if (!isTurnedOn)
			{
				distractedGiants.Clear();
				distractedGiant = null;
			}
		}

		private IEnumerator EmitLaserRay(PlayerControllerB player, GrabbableObject item)
		{
			RaycastHit hit = default(RaycastHit);
			while (isTurnedOn && item.insertedBattery.charge > 0f && (Object)(object)item != (Object)null)
			{
				Battery insertedBattery = item.insertedBattery;
				insertedBattery.charge -= ItemsReworkedPlugin.LaserPointerBatteryDrain.Value * Time.deltaTime;
				Ray ray = new Ray(((Component)item).transform.position, ((Component)item).transform.forward);
				float maxDistance = 800f;
				if (Physics.Raycast(ray, ref hit, maxDistance, StartOfRound.Instance.walkableSurfacesMask))
				{
					if ((Object)(object)distractedGiant == (Object)null)
					{
						Collider[] hitColliders = Physics.OverlapSphere(((RaycastHit)(ref hit)).point, 50f);
						Collider[] array = hitColliders;
						foreach (Collider hitCollider in array)
						{
							distractedGiant = ((Component)hitCollider).GetComponent<ForestGiantAI>();
							if ((Object)(object)distractedGiant != (Object)null && !distractedGiants.ContainsKey(distractedGiant))
							{
								distractedGiants.Add(distractedGiant, default(Vector3));
							}
						}
					}
					if (distractedGiants.Count > 0)
					{
						DistractGiants(distractedGiants, hit);
					}
				}
				yield return null;
				hit = default(RaycastHit);
			}
			if (item.insertedBattery.charge <= 0f)
			{
				ToggleLaserPointerPower(enable: false);
			}
		}

		private void DistractGiants(Dictionary<ForestGiantAI, Vector3> forestGiants, RaycastHit laser)
		{
			//IL_0031: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			foreach (KeyValuePair<ForestGiantAI, Vector3> forestGiant in forestGiants)
			{
				if (!((EnemyAI)forestGiant.Key).inSpecialAnimation && Vector3.Distance(((Component)forestGiant.Key).transform.position, ((RaycastHit)(ref laser)).transform.position) < ItemsReworkedPlugin.GiantsRangeOfView.Value)
				{
					distractedGiants[forestGiant.Key] = ((RaycastHit)(ref laser)).point;
					forestGiant.Key.lookTarget.position = ((RaycastHit)(ref laser)).point;
					forestGiant.Key.turnCompass.LookAt(((RaycastHit)(ref laser)).point);
					((EnemyAI)forestGiant.Key).SetDestinationToPosition(((RaycastHit)(ref laser)).point, false);
					((EnemyAI)forestGiant.Key).SwitchToBehaviourState(0);
				}
				else
				{
					forestGiant.Key.investigatePosition = distractedGiants[forestGiant.Key];
					((EnemyAI)forestGiant.Key).SetDestinationToPosition(distractedGiants[forestGiant.Key], true);
				}
			}
		}
	}
	internal class RedSodaCan : BaseItem
	{
		private float effectDuration;

		internal RedSodaCan(GrabbableObject redSodaCan)
		{
			effectDuration = CalculateEffectDuration(redSodaCan.scrapValue);
		}

		public override void InspectItem(PlayerControllerB player, GrabbableObject item)
		{
			effectDuration = CalculateEffectDuration(item.scrapValue);
			ItemsReworkedPlugin.mls.LogInfo((object)$"Effect duration: {effectDuration}");
			if (!item.itemUsedUp)
			{
				HUDManager.Instance.DisplayTip("Some kind of energy drink", "What did they say in those advertisements when I was younger... something about a red bull... and wings? I dunno...", false, false, "LC_Tip1");
			}
			else
			{
				HUDManager.Instance.DisplayTip("An empty energy drink", "Wow... the ads were not lying", false, false, "LC_Tip1");
			}
		}

		public override void SpecialUseItem(PlayerControllerB player, GrabbableObject item)
		{
			throw new NotImplementedException();
		}

		public override void UseItem(PlayerControllerB player, GrabbableObject item)
		{
			if (!item.itemUsedUp)
			{
				item.itemUsedUp = true;
				Random random = new Random();
				string text = "Soda" + random.Next(1, 3) + ".mp3";
				AudioHandler.PlaySound(player, "Scrap\\RedSodaCan\\" + text, 3f, 10f, 1f, 1f, 0f, (AudioRolloffMode)1);
				ItemsReworkedPlugin.mls.LogInfo((object)("playing: " + text));
				((MonoBehaviour)player).StartCoroutine(DelayedActivation(player, item, 3f, delegate
				{
					((MonoBehaviour)player).StartCoroutine(Energize(player));
					item.SetScrapValue(item.scrapValue / 2);
				}));
			}
		}

		private float CalculateEffectDuration(int scrapValue)
		{
			float value = ItemsReworkedPlugin.MinDurationJumpBoost.Value;
			float value2 = ItemsReworkedPlugin.MaxDurationJumpBoost.Value;
			float num = (float)(scrapValue - 19) / 71f;
			return Mathf.Lerp(value, value2, num);
		}

		private IEnumerator Energize(PlayerControllerB player)
		{
			float elapsedTime = 0f;
			float originalForce = player.jumpForce;
			while (elapsedTime < effectDuration)
			{
				player.jumpForce = originalForce * 1.5f;
				elapsedTime += Time.deltaTime;
				yield return null;
			}
			ItemsReworkedPlugin.mls.LogInfo((object)"Effect worn off");
			ItemsReworkedPlugin.mls.LogInfo((object)$"Original force: {originalForce}");
			player.jumpForce = originalForce;
		}
	}
	internal class Candy : BaseItem
	{
		public override void InspectItem(PlayerControllerB player, GrabbableObject item)
		{
			throw new NotImplementedException();
		}

		public override void SpecialUseItem(PlayerControllerB player, GrabbableObject item)
		{
			throw new NotImplementedException();
		}

		public override void UseItem(PlayerControllerB player, GrabbableObject item)
		{
			if (!item.itemUsedUp && player.insanityLevel > 1f)
			{
				player.insanityLevel = 0f;
				item.itemUsedUp = true;
				player.currentlyHeldObject.DiscardItemOnClient();
			}
		}
	}
	internal class Flask : BaseItem
	{
		private Random random = new Random();

		private string flaskEffect = "None";

		internal Flask()
		{
			int num = 0;
			int[] array = new int[4]
			{
				ItemsReworkedPlugin.NoEffectProbability.Value,
				0,
				0,
				0
			};
			num += array[0];
			array[1] = ItemsReworkedPlugin.IntoxicationEffectProbability.Value;
			num += array[1];
			array[2] = ItemsReworkedPlugin.PoisoningEffectProbability.Value;
			num += array[2];
			array[3] = ItemsReworkedPlugin.HealingEffectProbability.Value;
			num += array[3];
			if (num == 0)
			{
				flaskEffect = "None";
				return;
			}
			int num2 = random.Next(num);
			int num3 = 0;
			for (int i = 0; i < array.Length; i++)
			{
				num3 += array[i];
				if (num2 < num3)
				{
					switch (i)
					{
					case 0:
						flaskEffect = "NoEffect";
						break;
					case 1:
						flaskEffect = "Intoxication";
						break;
					case 2:
						flaskEffect = "Poisoning";
						break;
					case 3:
						flaskEffect = "Healing";
						break;
					}
					break;
				}
			}
		}

		public override void InspectItem(PlayerControllerB player, GrabbableObject item)
		{
			if (!item.itemUsedUp)
			{
				HUDManager.Instance.DisplayTip("A random flask", "Should I really risk drinking the content?", false, false, "LC_Tip1");
			}
			else
			{
				HUDManager.Instance.DisplayTip("A random flask", "... the taste, was not great.", false, false, "LC_Tip1");
			}
		}

		public override void UseItem(PlayerControllerB player, GrabbableObject item)
		{
			if (item.itemUsedUp)
			{
				return;
			}
			item.itemUsedUp = true;
			((MonoBehaviour)player).StartCoroutine(DelayedActivation(player, item, 3f, delegate
			{
				switch (flaskEffect)
				{
				default:
					NoEffect(player);
					break;
				case "Intoxication":
					ApplyDrunkEffect(player);
					break;
				case "Poisoning":
					((MonoBehaviour)player).StartCoroutine(ApplyPoisonEffect(player));
					break;
				case "Healing":
					((MonoBehaviour)player).StartCoroutine(ApplyHealEffect(player, item.scrapValue));
					break;
				}
			}));
			item.SetScrapValue(3);
		}

		public override void SpecialUseItem(PlayerControllerB player, GrabbableObject item)
		{
			throw new NotImplementedException();
		}

		private void NoEffect(PlayerControllerB player)
		{
			HUDManager.Instance.DisplayTip("Nothing", "Nothing happened...", false, false, "LC_Tip1");
		}

		private void ApplyDrunkEffect(PlayerControllerB player)
		{
			AudioHandler.PlaySound(player, "Scrap\\Flask\\Intoxication.mp3", 3f, 10f, 1f, 1f, 0f, (AudioRolloffMode)1);
			player.drunkness = 1f;
			HUDManager.Instance.DisplayTip("Intoxication", "You feel a bit dizzy.", false, false, "LC_Tip1");
		}

		private IEnumerator ApplyPoisonEffect(PlayerControllerB player)
		{
			HUDManager.Instance.DisplayTip("Poisoning Effect", "You feel a burning sensation.", false, false, "LC_Tip1");
			float elapsedTime = 0f;
			while (player.health > ItemsReworkedPlugin.MaxPoison.Value)
			{
				elapsedTime += Time.deltaTime;
				if (elapsedTime >= 3f)
				{
					player.DamagePlayer(1, false, true, (CauseOfDeath)0, 0, false, default(Vector3));
					elapsedTime = 0f;
					HUDManager.Instance.UpdateHealthUI(player.health, true);
				}
				yield return null;
			}
		}

		private IEnumerator ApplyHealEffect(PlayerControllerB player, int flaskValue)
		{
			HUDManager.Instance.DisplayTip("Healing Effect", "You feel rejuvenated.", false, false, "LC_Tip1");
			int minHealing = 1;
			int maxHealing = ItemsReworkedPlugin.MaxHealing.Value;
			int healing;
			if (flaskValue <= 16)
			{
				healing = minHealing;
			}
			else if (flaskValue >= 44)
			{
				healing = maxHealing;
			}
			else
			{
				float percentage = (float)(flaskValue - 16) / 28f;
				healing = Mathf.RoundToInt(Mathf.Lerp((float)minHealing, (float)maxHealing, percentage));
			}
			int targetHealth = player.health + healing;
			float elapsedTime = 0f;
			while (player.health < targetHealth && player.health < 100)
			{
				elapsedTime += Time.deltaTime;
				if (elapsedTime >= 3f)
				{
					player.health++;
					elapsedTime = 0f;
					player.health = Mathf.Min(player.health, targetHealth);
					HUDManager.Instance.UpdateHealthUI(player.health, false);
				}
				yield return null;
			}
		}
	}
	internal class PillBottle : BaseItem
	{
		private int remainingPills;

		private int pillQuality;

		internal PillBottle(GrabbableObject pillBottle)
		{
			pillQuality = GetPillQuality();
			remainingPills = CalculatePills(pillBottle.scrapValue);
		}

		public override void InspectItem(PlayerControllerB player, GrabbableObject item)
		{
			if (item.itemUsedUp)
			{
				HUDManager.Instance.DisplayTip("An empty pill bottle", "Seems like there are no pills left in this one...", false, false, "LC_Tip1");
			}
			else
			{
				HUDManager.Instance.DisplayTip("A pill bottle", "There are some pills in here...", false, false, "LC_Tip1");
			}
		}

		public override void UseItem(PlayerControllerB player, GrabbableObject item)
		{
			if (item.itemUsedUp || inSpecialScenario || player.health == 100 || player.inTerminalMenu)
			{
				return;
			}
			inSpecialScenario = true;
			string text = "PillPop" + pillQuality + ".mp3";
			AudioHandler.PlaySound(player, "Scrap\\PillBottle\\" + text, 3f, 10f, 1f, 1f, 0f, (AudioRolloffMode)1);
			ItemsReworkedPlugin.mls.LogInfo((object)("playing: " + text));
			((MonoBehaviour)player).StartCoroutine(DelayedActivation(player, item, 2f, delegate
			{
				remainingPills = IngestPills(player, remainingPills);
				item.SetScrapValue(remainingPills);
				if (remainingPills == 0)
				{
					item.SetScrapValue(1);
					item.itemUsedUp = true;
				}
			}));
		}

		private int GetPillQuality()
		{
			Random random = new Random();
			int num = random.Next(-1, 4);
			if (num != 0)
			{
				return num;
			}
			return 1;
		}

		private int CalculatePills(int scrapValue)
		{
			int value = ItemsReworkedPlugin.MinPills.Value;
			int value2 = ItemsReworkedPlugin.MaxPills.Value;
			if (scrapValue <= 16)
			{
				return value;
			}
			if (scrapValue >= 40)
			{
				return value2;
			}
			float num = (float)(scrapValue - 16) / 24f;
			return Mathf.RoundToInt(Mathf.Lerp((float)value, (float)value2, num));
		}

		private int IngestPills(PlayerControllerB player, int pills)
		{
			int num = 100;
			int num2 = 0;
			int num3 = pills * pillQuality;
			if (player.health + num3 > num)
			{
				num2 = player.health + num3 - num / pillQuality;
				((MonoBehaviour)player).StartCoroutine(GradualHealing(player, pills - num2));
			}
			else
			{
				((MonoBehaviour)player).StartCoroutine(GradualHealing(player, pills));
			}
			return num2;
		}

		private IEnumerator GradualHealing(PlayerControllerB player, int pills)
		{
			ItemsReworkedPlugin.mls.LogInfo((object)"CoroutineStarted");
			int targetHealth = player.health + pills * pillQuality;
			float healingDuration = pillQuality switch
			{
				2 => (float)pills * 5f, 
				3 => (float)pills * 3f, 
				_ => (float)pills * 10f, 
			};
			float healingInterval = healingDuration / (float)pills;
			float elapsedTime = 0f;
			float elapsedIntervalTime = 0f;
			while (elapsedTime < healingDuration)
			{
				if (elapsedIntervalTime > healingInterval)
				{
					player.health += pillQuality;
					HUDManager.Instance.UpdateHealthUI(player.health, false);
					elapsedIntervalTime = 0f;
				}
				elapsedTime += Time.deltaTime;
				elapsedIntervalTime += Time.deltaTime;
				yield return null;
			}
			player.health = targetHealth;
			HUDManager.Instance.UpdateHealthUI(player.health, false);
			inSpecialScenario = false;
		}

		public override void SpecialUseItem(PlayerControllerB player, GrabbableObject item)
		{
			throw new NotImplementedException();
		}
	}
	internal class Remote : BaseItem
	{
		private static int uses;

		internal Remote(GrabbableObject remote)
		{
			uses = CalculateUses(remote.scrapValue);
		}

		public override void InspectItem(PlayerControllerB player, GrabbableObject item)
		{
			ItemsReworkedPlugin.mls.LogInfo((object)$"Remaining uses: {uses}.");
		}

		public override void UseItem(PlayerControllerB player, GrabbableObject item)
		{
			if (uses > 0)
			{
				uses--;
				ActivateRemote();
				((MonoBehaviour)player).StartCoroutine(DelayedActivation(player, item, 1.5f, delegate
				{
					RemoteMalfunction(player, item);
				}));
			}
		}

		private int CalculateUses(int scrapValue)
		{
			int value = ItemsReworkedPlugin.MinRemoteUses.Value;
			int value2 = ItemsReworkedPlugin.MaxRemoteUses.Value;
			if (scrapValue <= 20)
			{
				return value;
			}
			if (scrapValue >= 48)
			{
				return value2;
			}
			float num = (float)(scrapValue - 20) / 28f;
			int num2 = Mathf.RoundToInt(Mathf.Lerp((float)value, (float)value2, num));
			if (num2 == 0)
			{
				ItemsReworkedPlugin.mls.LogError((object)"Calculation error in remote uses");
			}
			return num2;
		}

		private static bool ActivateRemote()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			Vector3 position = ((Component)localPlayerController.gameplayCamera).transform.position;
			Vector3 forward = ((Component)localPlayerController.gameplayCamera).transform.forward;
			float num = 20f;
			RaycastHit[] array = Physics.RaycastAll(position, forward, num);
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val = array2[i];
				Landmine component = ((Component)((RaycastHit)(ref val)).collider).GetComponent<Landmine>();
				Turret component2 = ((Component)((RaycastHit)(ref val)).collider).GetComponent<Turret>();
				if (((Object)(object)component2 != (Object)null) & ItemsReworkedPlugin.ToggleTurrets.Value)
				{
					ItemsReworkedPlugin.mls.LogInfo((object)"Toggling Turret");
					component2.ToggleTurretEnabled(!((Behaviour)component2).enabled);
					return true;
				}
				if ((Object)(object)component != (Object)null && ItemsReworkedPlugin.DetonateMines.Value)
				{
					ItemsReworkedPlugin.mls.LogInfo((object)"HIT MINE");
					component.ExplodeMineServerRpc();
					return true;
				}
			}
			return false;
		}

		private static void RemoteMalfunction(PlayerControllerB player, GrabbableObject remote)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			Random random = new Random();
			int num = random.Next(0, 101);
			if (num <= ItemsReworkedPlugin.RemoteExplosionProbability.Value)
			{
				uses = 0;
				Landmine.SpawnExplosion(((Component)remote).transform.position, true, 1f, 1f);
				if (remote.heldByPlayerOnServer)
				{
					Vector3 val = (((Component)player.gameplayCamera).transform.position + ((Component)remote).transform.position) / 2f;
					remote.playerHeldBy.KillPlayer(val, true, (CauseOfDeath)3, 0);
					remote.DestroyObjectInHand(remote.playerHeldBy);
					ItemsReworkedPlugin.Instance.scrapHandler.RemoveScrapItem(remote);
					ItemsReworkedPlugin.mls.LogInfo((object)("Remote exploded in the hand of the player '" + ((Object)player).name + "'"));
				}
				remote.SetScrapValue(1);
			}
			else if (num <= ItemsReworkedPlugin.RemoteZapProbability.Value)
			{
				if (remote.heldByPlayerOnServer)
				{
					AudioHandler.PlaySound(player, "Scrap\\Remote\\Zap.mp3", 3f, 10f, 1f, 1f, 0f, (AudioRolloffMode)1);
					remote.playerHeldBy.DamagePlayer(10, true, true, (CauseOfDeath)11, 0, false, default(Vector3));
					ItemsReworkedPlugin.mls.LogInfo((object)("Remote zapped player '" + ((Object)player).name + "'"));
				}
				uses = 0;
				remote.SetScrapValue(1);
			}
		}

		public override void SpecialUseItem(PlayerControllerB player, GrabbableObject item)
		{
			throw new NotImplementedException();
		}
	}
}
namespace ItemsReworked.Scrap.ItemsReworked.Scrap
{
	internal class Mug : BaseItem
	{
		private float effectDuration;

		internal Mug(GrabbableObject item)
		{
			effectDuration = CalculateEffectDuration(item.scrapValue);
		}

		public override void InspectItem(PlayerControllerB player, GrabbableObject item)
		{
			ItemsReworkedPlugin.mls.LogInfo((object)$"Caffeine effect duration: {effectDuration}");
			if (!item.itemUsedUp)
			{
				HUDManager.Instance.DisplayTip("A cup of coffee", "I wonder who left it here... it's still warm.", false, false, "LC_Tip1");
			}
			else
			{
				HUDManager.Instance.DisplayTip("A cup of coffee", "WHO DRANK IT?", false, false, "LC_Tip1");
			}
		}

		public override void UseItem(PlayerControllerB player, GrabbableObject item)
		{
			if (!item.itemUsedUp && !inSpecialScenario)
			{
				inSpecialScenario = true;
				string text = "Mug.mp3";
				AudioHandler.PlaySound(player, "Scrap\\Mug\\" + text, 3f, 10f, 1f, 1f, 0f, (AudioRolloffMode)1);
				ItemsReworkedPlugin.mls.LogInfo((object)("playing: " + text));
				((MonoBehaviour)player).StartCoroutine(DelayedActivation(player, item, 1.5f, delegate
				{
					((MonoBehaviour)player).StartCoroutine(Caffeinated(player));
					item.itemUsedUp = true;
					item.SetScrapValue(item.scrapValue / 2);
				}));
			}
		}

		private float CalculateEffectDuration(int scrapValue)
		{
			float value = ItemsReworkedPlugin.MinDurationStaminaBoost.Value;
			float value2 = ItemsReworkedPlugin.MaxDurationStaminaBoost.Value;
			float num = (float)(scrapValue - 24) / 44f;
			return Mathf.Lerp(value, value2, num);
		}

		private IEnumerator Caffeinated(PlayerControllerB player)
		{
			float elapsedTime = 0f;
			while (elapsedTime < effectDuration)
			{
				player.sprintMeter = 1f;
				player.isSprinting = true;
				elapsedTime += Time.deltaTime;
				yield return null;
			}
			inSpecialScenario = false;
			ItemsReworkedPlugin.mls.LogInfo((object)"Effect has worn off");
		}

		public override void SpecialUseItem(PlayerControllerB player, GrabbableObject item)
		{
			throw new NotImplementedException();
		}
	}
}
namespace ItemsReworked.Handlers
{
	public class AudioInfo
	{
		public bool IsPlaying { get; set; }

		public AudioSource AudioSource { get; set; }
	}
	public class AudioHandler
	{
		public static Dictionary<PlayerControllerB, AudioInfo> AudioInfoMap = new Dictionary<PlayerControllerB, AudioInfo>();

		public static void PlaySound(PlayerControllerB player, string soundFileName, float minDistance = 3f, float maxDistance = 10f, float volume = 1f, float spacialBlend = 1f, float dopplerLevel = 0f, AudioRolloffMode rolloffMode = 1)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			StopAllSounds();
			if (!AudioInfoMap.TryGetValue(player, out var audioInfo))
			{
				audioInfo = new AudioInfo
				{
					IsPlaying = false,
					AudioSource = ((Component)player).gameObject.AddComponent<AudioSource>()
				};
				audioInfo.AudioSource.spatialBlend = spacialBlend;
				audioInfo.AudioSource.dopplerLevel = dopplerLevel;
				audioInfo.AudioSource.rolloffMode = rolloffMode;
				audioInfo.AudioSource.minDistance = minDistance;
				audioInfo.AudioSource.maxDistance = maxDistance;
				audioInfo.AudioSource.volume = volume;
				AudioInfoMap[player] = audioInfo;
			}
			if (!audioInfo.IsPlaying)
			{
				string text = "file://" + Paths.PluginPath + "\\8-ItemsReworked\\SFX\\" + soundFileName;
				UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(text, (AudioType)13);
				audioClip.SendWebRequest();
				while (!audioClip.isDone)
				{
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip);
				audioInfo.AudioSource.clip = content;
				audioInfo.AudioSource.PlayOneShot(content);
				audioInfo.IsPlaying = true;
				float time = 5f;
				Task.Run(async delegate
				{
					await Task.Delay(TimeSpan.FromSeconds(time));
					audioInfo.AudioSource.Stop();
					audioInfo.IsPlaying = false;
				});
			}
		}

		public static void StopAllSounds()
		{
			foreach (AudioInfo value in AudioInfoMap.Values)
			{
				if (value.IsPlaying)
				{
					value.AudioSource.Stop();
					value.IsPlaying = false;
				}
			}
		}
	}
	public class ScrapHandler
	{
		private Dictionary<int, BaseItem> scrapItemDictionary = new Dictionary<int, BaseItem>();

		public void RegisterScrapItem(GrabbableObject scrapItem)
		{
			if (!scrapItemDictionary.ContainsKey(((Object)scrapItem).GetInstanceID()))
			{
				BaseItem baseItem = CreateScrapItem(scrapItem);
				if (baseItem != null)
				{
					scrapItemDictionary.Add(((Object)scrapItem).GetInstanceID(), baseItem);
					ItemsReworkedPlugin.mls.LogInfo((object)(((Object)scrapItem).name + " registered in ScrapHandler."));
				}
			}
		}

		public void RemoveScrapItem(GrabbableObject scrapItem)
		{
			int instanceID = ((Object)scrapItem).GetInstanceID();
			if (scrapItemDictionary.ContainsKey(instanceID) && scrapItemDictionary.Remove(instanceID))
			{
				ItemsReworkedPlugin.mls.LogInfo((object)(((Object)scrapItem).name + " removed from ScrapHandler."));
			}
			else
			{
				ItemsReworkedPlugin.mls.LogError((object)(((Object)scrapItem).name + " not found in ScrapHandler."));
			}
		}

		public void UseScrapItem(GrabbableObject scrapItem, PlayerControllerB player)
		{
			int instanceID = ((Object)scrapItem).GetInstanceID();
			if (scrapItemDictionary.ContainsKey(instanceID))
			{
				BaseItem baseItem = scrapItemDictionary[instanceID];
				baseItem.UseItem(player, scrapItem);
			}
		}

		public void SpecialUse(GrabbableObject scrapItem, PlayerControllerB player)
		{
			int instanceID = ((Object)scrapItem).GetInstanceID();
			if (scrapItemDictionary.ContainsKey(instanceID) && scrapItemDictionary[instanceID].hasSpecialUse)
			{
				BaseItem baseItem = scrapItemDictionary[instanceID];
				baseItem.SpecialUseItem(player, scrapItem);
			}
		}

		public void InspectScrapItem(GrabbableObject scrapItem, PlayerControllerB player)
		{
			int instanceID = ((Object)scrapItem).GetInstanceID();
			if (scrapItemDictionary.ContainsKey(instanceID))
			{
				BaseItem baseItem = scrapItemDictionary[instanceID];
				baseItem.InspectItem(player, scrapItem);
			}
		}

		private BaseItem CreateScrapItem(GrabbableObject scrapItem)
		{
			switch (((Object)scrapItem).name.Replace("(Clone)", null))
			{
			case "Candy":
				return new Candy();
			case "Flask":
				return new Flask();
			case "Mug":
				return new Mug(scrapItem);
			case "PillBottle":
				return new PillBottle(scrapItem);
			case "RedSodaCan":
				return new RedSodaCan(scrapItem);
			case "Remote":
				return new Remote(scrapItem);
			case "LaserPointer":
				return new LaserPointer(scrapItem);
			default:
				ItemsReworkedPlugin.mls.LogInfo((object)("Unsupported scrap item type " + ((Object)scrapItem).name + " picked up"));
				return null;
			}
		}
	}
}