Decompiled source of BetterShotgun v1.4.2

BepInEx/plugins/BetterShotgun.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Hypick.BetterShotgun.NetcodePatcher;
using LethalCompanyInputUtils.Api;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Hypick.BetterShotgun")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.4.2.0")]
[assembly: AssemblyInformationalVersion("1.4.2+e83b16fce6e800144c50ae54885cc0f78d0adfbf")]
[assembly: AssemblyProduct("BetterShotgun")]
[assembly: AssemblyTitle("Hypick.BetterShotgun")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Hypick
{
	[BepInPlugin("Hypick.BetterShotgun", "BetterShotgun", "1.4.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static PluginConfig Config;

		private readonly Harmony _harmony = new Harmony("Hypick.BetterShotgun");

		private static Keybinds InputActionsInstance = new Keybinds();

		private static AnimationClip ShotgunInspectAnimation;

		private static AudioClip ShotgunInspectSFX;

		private bool _isLoaded;

		private static Plugin Instance { get; set; }

		public static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger;

		private List<Item> AllItems => Resources.FindObjectsOfTypeAll<Item>().Concat(Object.FindObjectsByType<Item>((FindObjectsInactive)1, (FindObjectsSortMode)1)).ToList();

		private Item Shotgun => ((IEnumerable<Item>)AllItems).FirstOrDefault((Func<Item, bool>)((Item item) => ((Object)item).name == "Shotgun"));

		private Item ShotgunShell => ((IEnumerable<Item>)AllItems).FirstOrDefault((Func<Item, bool>)((Item item) => ((Object)item).name == "GunAmmo"));

		public Plugin()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			Instance = this;
		}

		private void Awake()
		{
			Config = new PluginConfig(((BaseUnityPlugin)this).Config);
			SceneManager.sceneLoaded += OnSceneLoaded;
			Log.LogInfo((object)"Applying patches...");
			_harmony.PatchAll();
			Log.LogInfo((object)"Patches applied");
			SetupKeybindCallbacks();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Hypick.BetterShotgun is fully loaded!");
		}

		public void SetupKeybindCallbacks()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			InputActionSetupExtensions.AddBinding(InputActionsInstance.ReloadKey, "<keyboard>/" + Config.ReloadKeybind, (string)null, (string)null, (string)null);
			if (Config.ReloadKeybind.Replace("<keyboard>/", "") != "e")
			{
				Log.LogInfo((object)("Start ReloadKeybind with key " + InputActionRebindingExtensions.GetBindingDisplayString(InputActionsInstance.ReloadKey, (DisplayStringOptions)0, (string)null)));
				InputActionsInstance.ReloadKey.performed += OnReloadKeyPressed;
			}
		}

		public void OnReloadKeyPressed(CallbackContext context)
		{
			if (!((CallbackContext)(ref context)).performed || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
			{
				return;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if (!((NetworkBehaviour)localPlayerController).IsOwner)
			{
				return;
			}
			GrabbableObject val = localPlayerController.ItemSlots[localPlayerController.currentItemSlot];
			if ((Object)(object)val != (Object)null)
			{
				ShotgunItem val2 = (ShotgunItem)(object)((val is ShotgunItem) ? val : null);
				if (val2 != null && !val2.isReloading)
				{
					val2.StartReloadGun();
				}
			}
		}

		public void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (!_isLoaded && !(((Scene)(ref scene)).name != "MainMenu"))
			{
				_isLoaded = true;
				RegisterItem(Shotgun, "Shotgun", Config.ShotgunMaxDiscount, Config.ShotgunMinValue, Config.ShotgunMaxValue, Config.ShotgunWeight, Config.ShotgunPrice, Config.ShotgunRarity);
				RegisterItem(ShotgunShell, "Shell", Config.ShellMaxDiscount, Config.ShellMinValue, Config.ShellMaxValue, 0, Config.ShellPrice, Config.ShellRarity);
			}
		}

		private static void RegisterItem(Item item, string name, int maxDiscount, int minValue, int maxValue, int weight, int price, int rarity)
		{
			item.itemName = name;
			item.highestSalePercentage = maxDiscount;
			item.minValue = Mathf.Max(minValue, 0) * 100 / 40;
			item.maxValue = Mathf.Max(maxValue, item.minValue) * 100 / 40;
			item.weight = ((weight <= 9) ? ((float)(weight + 100) / 100f) : ((float)(weight + 99) / 100f));
			if (price != -1)
			{
				Items.RegisterShopItem(item, price);
				Log.LogInfo((object)(item.itemName + " added to the store"));
			}
			if (rarity != -1)
			{
				Items.RegisterScrap(item, rarity, (LevelTypes)(-1));
				Log.LogInfo((object)(item.itemName + " added as scrap"));
			}
			Log.LogInfo((object)("Loaded " + item.itemName));
		}
	}
	public static class Category
	{
		public const string Shotgun = "1 >> Shotgun << 1";

		public const string ShotgunTweaks = "3 >> Shotgun Tweaks << 3";

		public const string Shell = "2 >> Shell << 2";
	}
	public class PluginConfig
	{
		public int ShotgunPrice { get; }

		public int ShotgunMaxDiscount { get; }

		public int ShotgunMinValue { get; }

		public int ShotgunMaxValue { get; }

		public int ShotgunWeight { get; }

		public int ShotgunRarity { get; }

		public bool MisfireOff { get; }

		public bool InfiniteAmmo { get; }

		public string ReloadKeybind { get; }

		public bool ShowAmmoCount { get; }

		public bool AmmoCheckAnimation { get; }

		public bool ReloadNoLimit { get; }

		public bool DisableFriendlyFire { get; }

		public bool SkipReloadAnimation { get; }

		public int ShellPrice { get; }

		public int ShellMaxDiscount { get; }

		public int ShellMinValue { get; }

		public int ShellMaxValue { get; }

		public int ShellRarity { get; }

		public PluginConfig(ConfigFile cfg)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			ShotgunPrice = cfg.Bind<int>("1 >> Shotgun << 1", "Price", 700, "Cost of a shotgun in a store. (-1 = remove from sale)").Value;
			ShotgunMaxDiscount = cfg.Bind<int>("1 >> Shotgun << 1", "MaxDiscount", 80, new ConfigDescription("Maximum discount percentage in store (vanilla = 80)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 90), Array.Empty<object>())).Value;
			ShotgunMinValue = cfg.Bind<int>("1 >> Shotgun << 1", "MinValueScrap", 40, "Minimum scrap value (must be >= 0) (In the game, the value is scaled down, so it is calculated using the formula value * 100 / 40)").Value;
			ShotgunMaxValue = cfg.Bind<int>("1 >> Shotgun << 1", "MaxValueScrap", 70, "Maximum scrap value (must be >= min value) (In the game, the value is scaled down, so it is calculated using the formula value * 100 / 40)").Value;
			ShotgunWeight = cfg.Bind<int>("1 >> Shotgun << 1", "Weight", 16, new ConfigDescription("[BETA] Scrap weight", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())).Value;
			ShotgunRarity = cfg.Bind<int>("1 >> Shotgun << 1", "Rarity", -1, "Rarity of shotgun spawn on moons (higher = more common). A shotgun will also appear in gifts. (-1 = disable)").Value;
			MisfireOff = cfg.Bind<bool>("3 >> Shotgun Tweaks << 3", "MisfireOff", true, "If set to true, disables shotgun misfire (vanilla = false)").Value;
			InfiniteAmmo = cfg.Bind<bool>("3 >> Shotgun Tweaks << 3", "InfiniteAmmo", false, "If set to true, the shotgun will have infinite ammo").Value;
			ReloadKeybind = cfg.Bind<string>("3 >> Shotgun Tweaks << 3", "ReloadKeybind", "R", "Changes the reload key to the one you specify (vanilla = E)").Value;
			ShowAmmoCount = cfg.Bind<bool>("3 >> Shotgun Tweaks << 3", "ShowAmmoCount", true, "If set to true, the number of cartridges in the shotgun will be displayed in the upper right text").Value;
			AmmoCheckAnimation = cfg.Bind<bool>("3 >> Shotgun Tweaks << 3", "AmmoCheckAnimation", false, "[BETA] Enables animation of checking cartridges in a shotgun on the reload key (Does not work with InfiniteAmmo = true)").Value;
			ReloadNoLimit = cfg.Bind<bool>("3 >> Shotgun Tweaks << 3", "ReloadNoLimit", false, "The shotgun can be loaded with an infinite number of cartridges").Value;
			DisableFriendlyFire = cfg.Bind<bool>("3 >> Shotgun Tweaks << 3", "DisableFriendlyFire", false, "Turns off friendly fire").Value;
			SkipReloadAnimation = cfg.Bind<bool>("3 >> Shotgun Tweaks << 3", "SkipReloadAnimation", false, "Skips shotgun reload animation").Value;
			ShellPrice = cfg.Bind<int>("2 >> Shell << 2", "Price", 50, "Cost of a shotgun shell in a store. (-1 = remove from sale)").Value;
			ShellMaxDiscount = cfg.Bind<int>("2 >> Shell << 2", "MaxDiscount", 80, new ConfigDescription("Maximum discount percentage in store (vanilla = 80)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 90), Array.Empty<object>())).Value;
			ShellMinValue = cfg.Bind<int>("2 >> Shell << 2", "MinValueScrap", 15, "Minimum scrap value (must be >= 0) (In the game, the value is scaled down, so it is calculated using the formula value * 100 / 40)").Value;
			ShellMaxValue = cfg.Bind<int>("2 >> Shell << 2", "MaxValueScrap", 25, "Maximum scrap value (must be >= min value) (In the game, the value is scaled down, so it is calculated using the formula value * 100 / 40)").Value;
			ShellRarity = cfg.Bind<int>("2 >> Shell << 2", "Rarity", 2, "Rarity of shotgun shell spawns on moons (higher = more common). Shell will also appear in gifts. (-1 = disable)").Value;
		}
	}
	public class Keybinds : LcInputActions
	{
		public InputAction ReloadKey => ((LcInputActions)this).Asset["Reload"];

		public override void CreateInputActions(in InputActionMapBuilder builder)
		{
			builder.NewActionBinding().WithActionId("Reload").WithActionType((InputActionType)1)
				.WithBindingName("ReloadShotgunKey")
				.Finish();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Hypick.BetterShotgun";

		public const string PLUGIN_NAME = "BetterShotgun";

		public const string PLUGIN_VERSION = "1.4.2";
	}
}
namespace Hypick.Patches
{
	[HarmonyPatch(typeof(ShotgunItem))]
	internal class ShotgunItemPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		public static void Update(ShotgunItem __instance)
		{
			if (Plugin.Config.MisfireOff && !__instance.safetyOn)
			{
				__instance.hasHitGroundWithSafetyOff = true;
				__instance.misfireTimer = float.MaxValue;
			}
		}

		[HarmonyPatch("ItemActivate")]
		[HarmonyPrefix]
		public static void ItemActivate(ShotgunItem __instance)
		{
			if (Plugin.Config.InfiniteAmmo)
			{
				__instance.shellsLoaded = int.MaxValue;
			}
		}

		[HarmonyPatch("SetControlTipsForItem")]
		[HarmonyPrefix]
		public static void SetControlTipsForItem(ShotgunItem __instance)
		{
			((GrabbableObject)__instance).itemProperties.toolTips[1] = GetCustomTooltip(__instance);
		}

		[HarmonyPatch("SetSafetyControlTip")]
		[HarmonyPrefix]
		public static void SetSafetyControlTip(ShotgunItem __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				HUDManager.Instance.ChangeControlTip(2, GetCustomTooltip(__instance), false);
			}
		}

		[HarmonyPatch("ReloadGunEffectsClientRpc")]
		[HarmonyPatch("ShootGun")]
		[HarmonyPostfix]
		public static void UpdateControlTipsForItem(ShotgunItem __instance)
		{
			if (Plugin.Config.ShowAmmoCount)
			{
				__instance.SetSafetyControlTip();
			}
		}

		private static string GetCustomTooltip(ShotgunItem item)
		{
			string text = (Plugin.Config.AmmoCheckAnimation ? "Reload / Check" : "Reload");
			if (!Plugin.Config.ShowAmmoCount)
			{
				return text + ": [" + Plugin.Config.ReloadKeybind.ToUpper() + "]";
			}
			string arg = (Plugin.Config.ReloadNoLimit ? "∞" : "2");
			string text2 = (Plugin.Config.InfiniteAmmo ? "∞" : $"{item.shellsLoaded}/{arg}");
			return text + " (" + text2 + "): [" + Plugin.Config.ReloadKeybind.ToUpper() + "]";
		}

		[HarmonyPatch("ShootGun")]
		[HarmonyPrefix]
		[HarmonyPriority(600)]
		public static void ShootGunPrefix(ShotgunItem __instance, out int __state)
		{
			__state = __instance.shellsLoaded;
		}

		[HarmonyPatch("ShootGun")]
		[HarmonyPostfix]
		public static void ShootGunPostfix(ShotgunItem __instance, ref int __state)
		{
			__instance.shellsLoaded = Mathf.Max(0, __state - 1);
			__instance.SetSafetyControlTip();
		}

		[HarmonyPatch("reloadGunAnimation")]
		[HarmonyPrefix]
		public static bool ReloadGunAnimation(ShotgunItem __instance, ref IEnumerator __result)
		{
			__result = ReloadGunAnimationCustom(__instance);
			return false;
		}

		[HarmonyPatch("ShootGun")]
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			bool found = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (Plugin.Config.DisableFriendlyFire && !found && ((object)instruction).ToString().Contains("playerHeldBy"))
				{
					found = true;
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ShotgunItemPatch), "CheckFriendly", (Type[])null, (Type[])null));
					yield return new CodeInstruction(OpCodes.Stloc_0, (object)null);
				}
				yield return instruction;
			}
		}

		private static bool CheckFriendly(ShotgunItem __instance)
		{
			return (Object)(object)((GrabbableObject)__instance).playerHeldBy != (Object)null;
		}

		[HarmonyPatch("ItemInteractLeftRight")]
		[HarmonyPrefix]
		public static bool ItemInteractLeftRight(ShotgunItem __instance, bool right)
		{
			if (Plugin.Config.ReloadKeybind.ToLower() != "e" && right)
			{
				return false;
			}
			if (!Plugin.Config.ReloadNoLimit || !right || __instance.isReloading)
			{
				return true;
			}
			__instance.StartReloadGun();
			return false;
		}

		[HarmonyPatch("StartReloadGun")]
		[HarmonyPrefix]
		public static bool StartReloadGun(ShotgunItem __instance)
		{
			if ((Plugin.Config.AmmoCheckAnimation && !__instance.ReloadedGun()) || (Plugin.Config.AmmoCheckAnimation && !Plugin.Config.ReloadNoLimit && !Plugin.Config.InfiniteAmmo && __instance.shellsLoaded >= 2))
			{
				if (__instance.gunCoroutine != null)
				{
					((MonoBehaviour)__instance).StopCoroutine(__instance.gunCoroutine);
				}
				__instance.gunCoroutine = ((MonoBehaviour)__instance).StartCoroutine(CheckAmmoAnimation(__instance));
				return false;
			}
			if (Plugin.Config.InfiniteAmmo && __instance.ReloadedGun())
			{
				return false;
			}
			return ((NetworkBehaviour)__instance).IsOwner;
		}

		private static IEnumerator CheckAmmoAnimation(ShotgunItem __instance)
		{
			__instance.isReloading = true;
			((GrabbableObject)__instance).playerHeldBy.playerBodyAnimator.SetBool("ReloadShotgun", true);
			((Renderer)__instance.shotgunShellLeft).enabled = __instance.shellsLoaded > 0;
			((Renderer)__instance.shotgunShellRight).enabled = __instance.shellsLoaded > 1;
			yield return (object)new WaitForSeconds(0.3f);
			__instance.gunAnimator.SetBool("Reloading", true);
			__instance.ReloadGunEffectsServerRpc(true);
			yield return (object)new WaitForSeconds(2.35f);
			__instance.gunAnimator.SetBool("Reloading", false);
			((GrabbableObject)__instance).playerHeldBy.playerBodyAnimator.SetBool("ReloadShotgun", false);
			__instance.isReloading = false;
			__instance.ReloadGunEffectsServerRpc(false);
		}

		private static IEnumerator ReloadGunAnimationCustom(ShotgunItem __instance)
		{
			if (!Plugin.Config.SkipReloadAnimation)
			{
				__instance.isReloading = true;
				if (__instance.shellsLoaded <= 0)
				{
					((GrabbableObject)__instance).playerHeldBy.playerBodyAnimator.SetBool("ReloadShotgun", true);
					((Renderer)__instance.shotgunShellLeft).enabled = false;
					((Renderer)__instance.shotgunShellRight).enabled = false;
				}
				else
				{
					((GrabbableObject)__instance).playerHeldBy.playerBodyAnimator.SetBool("ReloadShotgun2", true);
					((Renderer)__instance.shotgunShellRight).enabled = false;
				}
				yield return (object)new WaitForSeconds(0.3f);
				__instance.gunAudio.PlayOneShot(__instance.gunReloadSFX);
				__instance.gunAnimator.SetBool("Reloading", true);
				__instance.ReloadGunEffectsServerRpc(true);
				yield return (object)new WaitForSeconds(0.95f);
				((Renderer)__instance.shotgunShellInHand).enabled = true;
				__instance.shotgunShellInHandTransform.SetParent(((GrabbableObject)__instance).playerHeldBy.leftHandItemTarget);
				__instance.shotgunShellInHandTransform.localPosition = new Vector3(-0.0555f, 0.1469f, -0.0655f);
				__instance.shotgunShellInHandTransform.localEulerAngles = new Vector3(-1.956f, 143.856f, -16.427f);
				yield return (object)new WaitForSeconds(0.95f);
				((GrabbableObject)__instance).playerHeldBy.DestroyItemInSlotAndSync(__instance.ammoSlotToUse);
				__instance.ammoSlotToUse = -1;
				if (Plugin.Config.ReloadNoLimit)
				{
					__instance.shellsLoaded++;
				}
				else
				{
					__instance.shellsLoaded = Mathf.Clamp(__instance.shellsLoaded + 1, 0, 2);
				}
				((Renderer)__instance.shotgunShellLeft).enabled = true;
				if (__instance.shellsLoaded >= 2)
				{
					((Renderer)__instance.shotgunShellRight).enabled = true;
				}
				((Renderer)__instance.shotgunShellInHand).enabled = false;
				__instance.shotgunShellInHandTransform.SetParent(((Component)__instance).transform);
				yield return (object)new WaitForSeconds(0.45f);
				__instance.gunAudio.PlayOneShot(__instance.gunReloadFinishSFX);
				__instance.gunAnimator.SetBool("Reloading", false);
				((GrabbableObject)__instance).playerHeldBy.playerBodyAnimator.SetBool("ReloadShotgun", false);
				((GrabbableObject)__instance).playerHeldBy.playerBodyAnimator.SetBool("ReloadShotgun2", false);
				__instance.isReloading = false;
				__instance.ReloadGunEffectsServerRpc(false);
			}
			else
			{
				Plugin.Log.LogInfo((object)"Skip reload animation");
				__instance.isReloading = true;
				((GrabbableObject)__instance).playerHeldBy.DestroyItemInSlotAndSync(__instance.ammoSlotToUse);
				__instance.ammoSlotToUse = -1;
				if (Plugin.Config.ReloadNoLimit)
				{
					__instance.shellsLoaded++;
				}
				else
				{
					__instance.shellsLoaded = Mathf.Clamp(__instance.shellsLoaded + 1, 0, 2);
				}
				((Renderer)__instance.shotgunShellLeft).enabled = true;
				if (__instance.shellsLoaded >= 2)
				{
					((Renderer)__instance.shotgunShellRight).enabled = true;
				}
				((Renderer)__instance.shotgunShellInHand).enabled = false;
				__instance.shotgunShellInHandTransform.SetParent(((Component)__instance).transform);
				__instance.isReloading = false;
				__instance.SetSafetyControlTip();
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace Hypick.BetterShotgun.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}