Decompiled source of Casualheim v1.1.2

Casualheim.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BetterUI.Patches;
using Casualheim.attack_cancel;
using Casualheim.gui;
using Casualheim.leveling;
using Casualheim.patches;
using HarmonyLib;
using MonoMod.Utils;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Casualheim")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Casualheim")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("260c10ac-6c86-41da-be4b-e5891db32a21")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Casualheim
{
	[BepInPlugin("Casualheim", "Casualheim", "1.1.2")]
	[BepInProcess("valheim.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ThisPlugin : BaseUnityPlugin
	{
		public static Harmony harmony_instance = null;

		public const string PluginName = "Casualheim";

		public const string PluginAuthor = "k-Knight";

		public const string PluginVersion = "1.1.2";

		public const string PluginGUID = "Casualheim";

		public static ConfigEntry<bool> PluginEnabled;

		public static ConfigEntry<bool> DebugOutput;

		public static ConfigEntry<int> NumberOfPlayersMax;

		public static ConfigEntry<bool> AllowClearedBuilding;

		public static ConfigEntry<float> ChopMineDamageMultiplier;

		public static ConfigEntry<bool> EasierSkillCurveEnabled;

		public static ConfigEntry<float> RequiredExpMultiplier;

		public static ConfigEntry<bool> EnableDeathPenaltyMod;

		public static ConfigEntry<float> DeathPenaltyMultiplier;

		public static ConfigEntry<bool> EnableSkillLevelProgressLoss;

		public static ConfigEntry<float> EnemyLevelChanceMultiplier;

		public static ConfigEntry<bool> EnableAttackMod;

		public static ConfigEntry<int> PercentAttackMovement;

		public static ConfigEntry<int> PercentAttackRotation;

		public static ConfigEntry<bool> PreventDodgeSpamming;

		public static ConfigEntry<bool> EnableEnemyHealthMod;

		public static ConfigEntry<int> PercentCharredTwitcher;

		public static ConfigEntry<int> PercentCharredArcher;

		public static ConfigEntry<int> PercentCharredMelee;

		public static ConfigEntry<int> PercentCharredMage;

		public static ConfigEntry<int> PercentCharredTwitcherSummoned;

		public static ConfigEntry<int> PercentFallenValkyrie;

		public static ConfigEntry<int> PercentBonemawSerpent;

		public static ConfigEntry<int> PercentMorgen;

		public static ConfigEntry<int> PercentVolture;

		public static ConfigEntry<int> PercentPieceCharredBalista;

		public static ConfigEntry<int> PercentBlobLava;

		public static ConfigEntry<int> PercentDvergerAshlands;

		public static ConfigEntry<bool> EnableBossHealthRegenMod;

		public static ConfigEntry<int> RegenerationMultiplier;

		public static ConfigEntry<int> PercentRegenEikthyr;

		public static ConfigEntry<int> PercentRegenElder;

		public static ConfigEntry<int> PercentRegenBonemass;

		public static ConfigEntry<int> PercentRegenModer;

		public static ConfigEntry<int> PercentRegenYagluth;

		public static ConfigEntry<int> PercentRegenQueen;

		public static ConfigEntry<int> PercentRegenFader;

		public static ConfigEntry<int> PercentHealthEikthyr;

		public static ConfigEntry<int> PercentHealthElder;

		public static ConfigEntry<int> PercentHealthBonemass;

		public static ConfigEntry<int> PercentHealthModer;

		public static ConfigEntry<int> PercentHealthYagluth;

		public static ConfigEntry<int> PercentHealthQueen;

		public static ConfigEntry<int> PercentHealthFader;

		public static ConfigEntry<bool> EnableLeveling;

		public static ConfigEntry<float> HealthBoostMultiplier;

		public static ConfigEntry<float> HealthRegenBoostMultiplier;

		public static ConfigEntry<float> StaminaBoostMultiplier;

		public static ConfigEntry<float> StaminaRegenBoostMultiplier;

		public static ConfigEntry<float> SpeedBoostMultiplier;

		public static ConfigEntry<float> JumpHeightMultiplier;

		public static ConfigEntry<float> FallWindowMultiplier;

		public static Dictionary<string, WeakReference<ConfigEntry<int>>> MaxHealthPercentDict = new Dictionary<string, WeakReference<ConfigEntry<int>>>();

		public static Dictionary<string, WeakReference<ConfigEntry<int>>> HealthRegenPercentDict = new Dictionary<string, WeakReference<ConfigEntry<int>>>();

		private static ThisPlugin thisInstance;

		public static ThisPlugin instance => thisInstance;

		public static bool ModIsLoaded(string GUID)
		{
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				if (pluginInfo.Value.Metadata.GUID.Equals(GUID))
				{
					return true;
				}
			}
			return false;
		}

		public void Awake()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			thisInstance = this;
			MaxHealthDictsInit();
			LoadSettings();
			if (!PluginEnabled.Value)
			{
				return;
			}
			harmony_instance = new Harmony("Casualheim");
			harmony_instance.PatchAll(typeof(AllowClearedBuildingPatch));
			harmony_instance.PatchAll(typeof(AttackSlowdownPatch));
			harmony_instance.PatchAll(typeof(DeathPenaltyPatch));
			harmony_instance.PatchAll(typeof(EnemyLevelChancePatch));
			harmony_instance.PatchAll(typeof(MaxHealthPatch));
			harmony_instance.PatchAll(typeof(RegenPatch));
			harmony_instance.PatchAll(typeof(SkillCurvePatch));
			harmony_instance.PatchAll(typeof(MiningChoppingPatch));
			harmony_instance.PatchAll(typeof(AttackCancelPatch));
			harmony_instance.PatchAll(typeof(AttackPreventLogicPatch));
			harmony_instance.PatchAll(typeof(LevelPatch));
			harmony_instance.PatchAll(typeof(StatModificationPatch));
			if (ModIsLoaded("MK_BetterUI"))
			{
				if (DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim | found optional BetterUI dependency, patching ...");
				}
				harmony_instance.PatchAll(typeof(DisableBetterUIXPPatch));
			}
			harmony_instance.PatchAll(typeof(LevelIndicatorPatch));
		}

		public void OnDestroy()
		{
			if (harmony_instance != null)
			{
				harmony_instance.UnpatchSelf();
			}
		}

		public static void MaxHealthDictsInit()
		{
			MaxHealthPercentDict.Add("charred_twitcher", new WeakReference<ConfigEntry<int>>(PercentCharredTwitcher));
			MaxHealthPercentDict.Add("charred_archer", new WeakReference<ConfigEntry<int>>(PercentCharredArcher));
			MaxHealthPercentDict.Add("charred_melee", new WeakReference<ConfigEntry<int>>(PercentCharredMelee));
			MaxHealthPercentDict.Add("charred_mage", new WeakReference<ConfigEntry<int>>(PercentCharredMage));
			MaxHealthPercentDict.Add("charred_twitcher_summoned", new WeakReference<ConfigEntry<int>>(PercentCharredTwitcherSummoned));
			MaxHealthPercentDict.Add("fallenvalkyrie", new WeakReference<ConfigEntry<int>>(PercentFallenValkyrie));
			MaxHealthPercentDict.Add("bonemawserpent", new WeakReference<ConfigEntry<int>>(PercentBonemawSerpent));
			MaxHealthPercentDict.Add("morgen", new WeakReference<ConfigEntry<int>>(PercentMorgen));
			MaxHealthPercentDict.Add("volture", new WeakReference<ConfigEntry<int>>(PercentVolture));
			MaxHealthPercentDict.Add("piece_charred_balista", new WeakReference<ConfigEntry<int>>(PercentPieceCharredBalista));
			MaxHealthPercentDict.Add("bloblava", new WeakReference<ConfigEntry<int>>(PercentBlobLava));
			MaxHealthPercentDict.Add("dvergerashlands", new WeakReference<ConfigEntry<int>>(PercentDvergerAshlands));
			MaxHealthPercentDict.Add("eikthyr", new WeakReference<ConfigEntry<int>>(PercentHealthEikthyr));
			MaxHealthPercentDict.Add("gdking", new WeakReference<ConfigEntry<int>>(PercentHealthElder));
			MaxHealthPercentDict.Add("bonemass", new WeakReference<ConfigEntry<int>>(PercentHealthBonemass));
			MaxHealthPercentDict.Add("dragon", new WeakReference<ConfigEntry<int>>(PercentHealthModer));
			MaxHealthPercentDict.Add("goblinking", new WeakReference<ConfigEntry<int>>(PercentHealthYagluth));
			MaxHealthPercentDict.Add("seekerqueen", new WeakReference<ConfigEntry<int>>(PercentHealthQueen));
			MaxHealthPercentDict.Add("fader", new WeakReference<ConfigEntry<int>>(PercentHealthFader));
			HealthRegenPercentDict.Add("eikthyr", new WeakReference<ConfigEntry<int>>(PercentRegenEikthyr));
			HealthRegenPercentDict.Add("gdking", new WeakReference<ConfigEntry<int>>(PercentRegenElder));
			HealthRegenPercentDict.Add("bonemass", new WeakReference<ConfigEntry<int>>(PercentRegenBonemass));
			HealthRegenPercentDict.Add("dragon", new WeakReference<ConfigEntry<int>>(PercentRegenModer));
			HealthRegenPercentDict.Add("goblinking", new WeakReference<ConfigEntry<int>>(PercentRegenYagluth));
			HealthRegenPercentDict.Add("seekerqueen", new WeakReference<ConfigEntry<int>>(PercentRegenQueen));
			HealthRegenPercentDict.Add("fader", new WeakReference<ConfigEntry<int>>(PercentRegenFader));
		}

		public static void LoadSettings()
		{
			PluginEnabled = ((BaseUnityPlugin)instance).Config.Bind<bool>("General", "Enabled", true, "Enable/disable this pulgin.");
			DebugOutput = ((BaseUnityPlugin)instance).Config.Bind<bool>("General", "Debug", false, "Enable/disable debug logging.");
			NumberOfPlayersMax = ((BaseUnityPlugin)instance).Config.Bind<int>("General", "Number of players max", 4, "Maximum number of active players to modify boss health and regen.");
			EnemyLevelChanceMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("General", "Enemy level chance multiplier", 3f, "My how much the chance of leveling up enemy (stars) is multiplied (1.0 for default values).");
			AllowClearedBuilding = ((BaseUnityPlugin)instance).Config.Bind<bool>("General", "Allow cleared dungeon building", true, "Allow building in dungeons/locations when all enemies are dead. May require a new world (kinda).");
			ChopMineDamageMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("General", "Multiplier for chop/mine damage", 2f, "Multiplies the damage of chopping and mining (0 for disable).");
			EasierSkillCurveEnabled = ((BaseUnityPlugin)instance).Config.Bind<bool>("Skills", "Enable easier skill curve", true, "Enables/Disables easier skill curve.");
			RequiredExpMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Skills", "Required exp multiplier", 1f, "This changes the speed of arithmetic progression in required experience to reach next skill level.");
			EnableDeathPenaltyMod = ((BaseUnityPlugin)instance).Config.Bind<bool>("Skills", "Enable death penalty changes", true, "Enables/Disables modifications of death penalty.");
			DeathPenaltyMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Skills", "Death penalty multiplier", 0f, "This changes the amount of skill loss by multiplying it with this value.");
			EnableSkillLevelProgressLoss = ((BaseUnityPlugin)instance).Config.Bind<bool>("Skills", "Enable skill level progress loss", false, "Whether to reset the accumulated experience on the current skill level.");
			EnableAttackMod = ((BaseUnityPlugin)instance).Config.Bind<bool>("Attacks", "Enable attack changes", true, "Enables/Disables attack cancellation and other related things.");
			PercentAttackMovement = ((BaseUnityPlugin)instance).Config.Bind<int>("Attacks", "Percent attack movement speed", 20, "Percent of normal movement speed that remains while attacking (20% is game's default).");
			PercentAttackRotation = ((BaseUnityPlugin)instance).Config.Bind<int>("Attacks", "Percent attack rotation speed", 20, "Percent of normal rotation speed that remains while attacking (20% is game's default).");
			PreventDodgeSpamming = ((BaseUnityPlugin)instance).Config.Bind<bool>("Attacks", "Prevent dodge spamming", false, "Prevent dodge spamming if player continiously holds down the dodge key.");
			EnableEnemyHealthMod = ((BaseUnityPlugin)instance).Config.Bind<bool>("Mob Health", "Enable enemy health change", true, "Enables/Disables the change of enemies' max health.");
			PercentCharredTwitcher = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent Charred Twitcher health", 100, "Percent of normal health that Charred Twitcher will have.");
			PercentCharredArcher = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent CharredArcher health", 100, "Percent of normal health that Charred Marksman will have.");
			PercentCharredMelee = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent CharredMelee health", 66, "Percent of normal health that Charred Warrior will have.");
			PercentCharredMage = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent CharredMage health", 66, "Percent of normal health that Charred Warlock will have.");
			PercentCharredTwitcherSummoned = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent CharredTwitcherSummoned health", 100, "Percent of normal health that Summoned Twitcher will have.");
			PercentFallenValkyrie = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent FallenValkyrie health", 50, "Percent of normal health that Fallen Valkyrie will have.");
			PercentBonemawSerpent = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent BonemawSerpent health", 50, "Percent of normal health that Bonemaw Serpent will have.");
			PercentMorgen = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent Morgen health", 50, "Percent of normal health that Morgen will have.");
			PercentVolture = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent Volture health", 100, "Percent of normal health that Volture will have.");
			PercentPieceCharredBalista = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent PieceCharredBalista health", 100, "Percent of normal health that Skugg will have.");
			PercentBlobLava = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent BlobLava health", 100, "Percent of normal health that Lava Blob will have.");
			PercentDvergerAshlands = ((BaseUnityPlugin)instance).Config.Bind<int>("Mob Health", "Percent DvergerAshlands health", 100, "Percent of normal health that Ashlands Dvergr will have.");
			EnableBossHealthRegenMod = ((BaseUnityPlugin)instance).Config.Bind<bool>("Boss Health", "Enable boss health change", true, "Enables/Disables the change of boss max health and regen.");
			PercentRegenEikthyr = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent regen Eikthyr", 0, "Percent of normal Eikthyr health regen.");
			PercentRegenElder = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent regen Elder", 0, "Percent of normal Elder health regen.");
			PercentRegenBonemass = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent regen Bonemass", 0, "Percent of normal Bonemass health regen.");
			PercentRegenModer = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent regen Moder", 0, "Percent of normal Moder health regen.");
			PercentRegenYagluth = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent regen Yagluth", 0, "Percent of normal Yagluth health regen.");
			PercentRegenQueen = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent regen Queen", 0, "Percent of normal Queen health regen.");
			PercentRegenFader = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent regen Fader", 0, "Percent of normal Fader health regen.");
			PercentHealthEikthyr = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent health Eikthyr", 150, "Percent of normal Eikthyr max health.");
			PercentHealthElder = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent health Elder", 100, "Percent of normal Elder max health.");
			PercentHealthBonemass = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent health Bonemass", 100, "Percent of normal Bonemass max health.");
			PercentHealthModer = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent health Moder", 100, "Percent of normal Moder max health.");
			PercentHealthYagluth = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent health Yagluth", 100, "Percent of normal Yagluth max health.");
			PercentHealthQueen = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent health Queen", 100, "Percent of normal Queen max health.");
			PercentHealthFader = ((BaseUnityPlugin)instance).Config.Bind<int>("Boss Health", "Percent health Fader", 60, "Percent of normal Fader max health.");
			EnableLeveling = ((BaseUnityPlugin)instance).Config.Bind<bool>("Leveling", "Enable leveling system", true, "Enables/Disables the leveling system");
			HealthBoostMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Health boost strength multiplier", 1f, "Changes the strength of the health boost (0 for disable).");
			HealthRegenBoostMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Health regen boost strength multiplier", 1f, "Changes the strength of the health regeneration boost (0 for disable).");
			StaminaBoostMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Stamina boost strength multiplier", 1f, "Changes the strength of the stamina boost (0 for disable).");
			StaminaRegenBoostMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Stamina regen boost strength multiplier", 1f, "Changes the strength of the stamina regeneration boost (0 for disable).");
			SpeedBoostMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Speed boost strength multiplier", 1f, "Changes the strength of the movement speed boost (0 for disable).");
			JumpHeightMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Jump height boost strength multiplier", 1f, "Changes the strength of the jump height boost (0 for disable).");
			FallWindowMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Allowed fall window increase multiplier", 1f, "Changes the strength of allowed fall window increase where player does not receive fall damage (0 for disable).");
		}
	}
	public static class Util
	{
		public static HashSet<string> unique_callers = new HashSet<string>();

		public static void print_callstack(string caller_method)
		{
			StackFrame[] frames = new StackTrace(fNeedFileInfo: true).GetFrames();
			string text = "\n";
			for (int i = 1; i < frames.Length; i++)
			{
				text = text + "    " + new string(' ', i * 2) + frames[i].GetMethod().ToString() + "\n";
			}
			if (!unique_callers.Contains(text))
			{
				unique_callers.Add(text);
				Debug.Log((object)"");
				Debug.Log((object)("in " + caller_method + "()"));
				Debug.Log((object)text);
			}
		}

		public static bool check_caller(string caller_method)
		{
			StackFrame[] frames = new StackTrace(fNeedFileInfo: true).GetFrames();
			for (int i = 2; i < frames.Length; i++)
			{
				if (frames[i].GetMethod().Name == caller_method)
				{
					return true;
				}
			}
			return false;
		}

		public static bool check_caller(Type caller_type, string caller_name_part)
		{
			StackFrame[] frames = new StackTrace(fNeedFileInfo: true).GetFrames();
			for (int i = 2; i < frames.Length; i++)
			{
				MethodBase method = frames[i].GetMethod();
				if (ReflectionHelper.GetRealDeclaringType((MemberInfo)method) == caller_type && method.Name.Contains(caller_name_part))
				{
					return true;
				}
			}
			return false;
		}

		public static bool GetLocation<T>(ref T obj, out Location loc) where T : MonoBehaviour
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			loc = Location.GetLocation(((Component)obj).transform.position, true);
			if ((Object)(object)loc == (Object)null)
			{
				return false;
			}
			return true;
		}

		public static bool GetSyncThings<T>(ref T obj, out ZNetView nview, out ZDO zdo) where T : MonoBehaviour
		{
			zdo = null;
			nview = null;
			if (typeof(CreatureSpawner).IsAssignableFrom(((object)obj).GetType()))
			{
				object obj2 = obj;
				nview = ((CreatureSpawner)((obj2 is CreatureSpawner) ? obj2 : null)).m_nview;
			}
			else if (typeof(SpawnArea).IsAssignableFrom(((object)obj).GetType()))
			{
				object obj3 = obj;
				nview = ((SpawnArea)((obj3 is SpawnArea) ? obj3 : null)).m_nview;
			}
			else if (typeof(Character).IsAssignableFrom(((object)obj).GetType()))
			{
				object obj4 = obj;
				nview = ((Character)((obj4 is Character) ? obj4 : null)).m_nview;
			}
			if ((Object)(object)nview == (Object)null)
			{
				return false;
			}
			zdo = nview.GetZDO();
			if (zdo == null)
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)("Casualheim | !!!   !!!   no ZDO for " + ((object)obj).GetType()?.ToString() + "   !!!   !!!"));
				}
				return false;
			}
			return true;
		}

		public static bool TryGetPlayerZDO(ref Character character, out Player player, out ZDO zdo)
		{
			player = null;
			zdo = null;
			if (((object)character).GetType() != typeof(Player))
			{
				return false;
			}
			Character obj = character;
			player = (Player)(object)((obj is Player) ? obj : null);
			return TryGetPlayerZDO(ref player, out zdo);
		}

		public static bool TryGetPlayerZDO(ref Player player, out ZDO zdo)
		{
			zdo = ((Character)player).m_nview.GetZDO();
			if (zdo == null)
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim.StatModificationPatch | zdo of a player is null !!!");
				}
				return false;
			}
			return true;
		}
	}
}
namespace Casualheim.patches
{
	[HarmonyPatch]
	public class AllowClearedBuildingPatch
	{
		public static int last_zone_location_hash = -1;

		public static int last_creature_spawner_hash = -1;

		public static int last_character_drop_hash = -1;

		public static Dictionary<int, int> loc_2_zloc_dict = new Dictionary<int, int>();

		public static bool AssignLocHashDeterministic<T>(ref T obj, out ZDO zdo, out int zloc_hash) where T : MonoBehaviour
		{
			zloc_hash = 0;
			zdo = null;
			if (!Util.check_caller("DMD<ZoneSystem::SpawnLocation>"))
			{
				return false;
			}
			if (!Util.GetSyncThings(ref obj, out var nview, out zdo))
			{
				return false;
			}
			if (!nview.IsOwner())
			{
				return false;
			}
			if (zdo.GetBool("zloc_checked", false))
			{
				zloc_hash = zdo.GetInt("zloc_hash", 0);
				return true;
			}
			if (ThisPlugin.DebugOutput.Value)
			{
				Debug.Log((object)("Casualheim | DETERMINISICALLY found zloc hash for " + ((object)obj).GetType()?.ToString() + " :: " + zloc_hash));
			}
			zdo.Set("zloc_checked", true);
			zdo.Set("zloc_hash", last_zone_location_hash);
			zloc_hash = last_zone_location_hash;
			return true;
		}

		public static bool AssignLocHashHeuristic<T>(ref T obj, ref ZDO zdo, out int zloc_hash) where T : MonoBehaviour
		{
			zloc_hash = 0;
			if (zdo.GetBool("zloc_checked", false))
			{
				zloc_hash = zdo.GetInt("zloc_hash", 0);
				return true;
			}
			Util.GetLocation(ref obj, out var loc);
			if ((Object)(object)loc == (Object)null)
			{
				return false;
			}
			if (!loc_2_zloc_dict.ContainsKey(((object)loc).GetHashCode()))
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim | CreatureSpawner.Spawn location is not in the dictrionary !!!");
				}
				return false;
			}
			if (ThisPlugin.DebugOutput.Value)
			{
				Debug.Log((object)("Casualheim | HEURISTICALLY found zloc hash for " + ((object)obj).GetType()?.ToString() + " :: " + zloc_hash));
			}
			zloc_hash = loc_2_zloc_dict[((object)loc).GetHashCode()];
			zdo.Set("zloc_checked", true);
			zdo.Set("zloc_hash", zloc_hash);
			return true;
		}

		public static void BeforeSpawnerUnitSpawn<T>(ref T obj) where T : MonoBehaviour
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.AllowClearedBuilding.Value)
			{
				return;
			}
			last_creature_spawner_hash = 0;
			if (Util.GetSyncThings(ref obj, out var nview, out var zdo))
			{
				last_creature_spawner_hash = zdo.GetInt("zloc_hash", 0);
				if (last_creature_spawner_hash == 0 && nview.IsOwner() && AssignLocHashHeuristic(ref obj, ref zdo, out var zloc_hash))
				{
					last_creature_spawner_hash = zloc_hash;
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Location), "IsInside")]
		public static void LocationIsInsidePatch(ref Location __instance, ref bool __result, ref bool buildCheck, ref Vector3 point)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || !buildCheck || !__instance.m_noBuild || !__result || !ThisPlugin.PluginEnabled.Value || !ThisPlugin.AllowClearedBuilding.Value)
			{
				return;
			}
			if (!loc_2_zloc_dict.ContainsKey(((object)__instance).GetHashCode()))
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim | Location.IsInside location is not in the dictrionary !!!");
				}
				return;
			}
			bool flag = true;
			int num = loc_2_zloc_dict[((object)__instance).GetHashCode()];
			if (ZoneSystem.m_instance.GetLocation(num) == null)
			{
				return;
			}
			foreach (CreatureSpawner creatureSpawner in CreatureSpawner.m_creatureSpawners)
			{
				if ((Object)(object)creatureSpawner == (Object)null || (Object)(object)creatureSpawner.m_nview == (Object)null)
				{
					continue;
				}
				ZDO zDO = creatureSpawner.m_nview.GetZDO();
				if (zDO == null)
				{
					continue;
				}
				int @int = zDO.GetInt("zloc_hash", 0);
				ZDOID connectionZDOID = zDO.GetConnectionZDOID((ConnectionType)3);
				if (num == @int && creatureSpawner.SpawnedCreatureStillExists(connectionZDOID))
				{
					flag = false;
					if (ThisPlugin.DebugOutput.Value)
					{
						Debug.Log((object)("Casualheim | creaturespawner [" + ((object)creatureSpawner).GetHashCode() + "] says char still exists for zloc [" + num + "] !"));
					}
					break;
				}
			}
			if (!flag)
			{
				return;
			}
			foreach (Character s_character in Character.s_characters)
			{
				if ((Object)(object)s_character == (Object)null || (Object)(object)s_character.m_nview == (Object)null)
				{
					continue;
				}
				ZDO zDO2 = s_character.m_nview.GetZDO();
				if (zDO2 == null)
				{
					continue;
				}
				int int2 = zDO2.GetInt("zloc_hash", 0);
				if (num == int2)
				{
					flag = false;
					if (ThisPlugin.DebugOutput.Value)
					{
						Debug.Log((object)("Casualheim | found char " + s_character.m_name.ToLower() + " that is still alive for zloc [" + num + "] !"));
					}
					break;
				}
			}
			if (flag)
			{
				__instance.m_noBuild = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Location), "Awake")]
		public static void LocatioAwakenPatch(ref Location __instance)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.AllowClearedBuilding.Value && Util.check_caller("DMD<ZoneSystem::SpawnLocation>"))
			{
				loc_2_zloc_dict.Add(((object)__instance).GetHashCode(), last_zone_location_hash);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(CharacterDrop), "OnDeath")]
		public static void CharacterDropOnDeathPatch(ref CharacterDrop __instance)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.AllowClearedBuilding.Value)
			{
				return;
			}
			last_character_drop_hash = 0;
			if (!((Object)(object)__instance.m_character == (Object)null) && !((Object)(object)__instance.m_character.m_nview == (Object)null))
			{
				ZDO zDO = __instance.m_character.m_nview.GetZDO();
				if (zDO != null)
				{
					last_character_drop_hash = zDO.GetInt("zloc_hash", 0);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZoneSystem), "SpawnLocation")]
		public static void ZoneSystemSpawnLocationPatch(ref ZoneLocation location)
		{
			last_zone_location_hash = 0;
			last_zone_location_hash = location.Hash;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Character), "Awake")]
		public static void CharacterAwakePatch(ref Character __instance)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.AllowClearedBuilding.Value)
			{
				return;
			}
			bool flag = false;
			bool flag2 = false;
			if (Util.check_caller("DMD<CreatureSpawner::Spawn>"))
			{
				flag = true;
			}
			else if (Util.check_caller("DMD<CharacterDrop::OnDeath>"))
			{
				flag2 = true;
			}
			if ((!flag && !flag2) || (Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsOwner())
			{
				return;
			}
			ZDO zDO = __instance.m_nview.GetZDO();
			if (zDO != null)
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)("Casualheim | setting zloc_hash [" + (flag ? last_creature_spawner_hash : (flag2 ? last_character_drop_hash : (-1))) + "] for char :: " + __instance.m_name.ToLower()));
				}
				if (flag)
				{
					zDO.Set("zloc_hash", last_creature_spawner_hash);
				}
				else if (flag2)
				{
					zDO.Set("zloc_hash", last_character_drop_hash);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(CreatureSpawner), "Awake")]
		public static void CreatureSpawnerAwakePatch(ref CreatureSpawner __instance)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.AllowClearedBuilding.Value)
			{
				AllowClearedBuildingPatch.AssignLocHashDeterministic<CreatureSpawner>(ref __instance, out ZDO _, out int _);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SpawnArea), "Awake")]
		public static void SpawnAreaAwakePatch(ref SpawnArea __instance)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.AllowClearedBuilding.Value)
			{
				AllowClearedBuildingPatch.AssignLocHashDeterministic<SpawnArea>(ref __instance, out ZDO _, out int _);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(CreatureSpawner), "Spawn")]
		public static void CreatureSpawnerSpawnPatch(ref CreatureSpawner __instance)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.AllowClearedBuilding.Value)
			{
				AllowClearedBuildingPatch.BeforeSpawnerUnitSpawn<CreatureSpawner>(ref __instance);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SpawnArea), "SpawnOne")]
		public static void SpawnAreaSpawnOnePatch(ref SpawnArea __instance)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.AllowClearedBuilding.Value)
			{
				AllowClearedBuildingPatch.BeforeSpawnerUnitSpawn<SpawnArea>(ref __instance);
			}
		}
	}
	[HarmonyPatch(typeof(Skills), "LowerAllSkills")]
	public class DeathPenaltyPatch
	{
		public static bool Prefix(ref Skills __instance, ref float factor)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableDeathPenaltyMod.Value)
			{
				return true;
			}
			factor *= ThisPlugin.DeathPenaltyMultiplier.Value;
			foreach (KeyValuePair<SkillType, Skill> skillDatum in __instance.m_skillData)
			{
				if ((double)factor >= 0.01)
				{
					float num = skillDatum.Value.m_level * factor;
					Skill value = skillDatum.Value;
					value.m_level -= num;
				}
				if (ThisPlugin.EnableSkillLevelProgressLoss.Value)
				{
					skillDatum.Value.m_accumulator = 0f;
				}
			}
			((Character)__instance.m_player).Message((MessageType)1, "$msg_skills_lowered", 0, (Sprite)null);
			return false;
		}
	}
	[HarmonyPatch]
	public class EnemyLevelChancePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(SpawnArea), "GetLevelUpChance")]
		public static void SpawnAreaLevelUpChancePatch(ref SpawnArea __instance, ref float __result)
		{
			if (ThisPlugin.PluginEnabled.Value)
			{
				__result *= ThisPlugin.EnemyLevelChanceMultiplier.Value;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SpawnSystem), "GetLevelUpChance", new Type[] { typeof(float) })]
		public static void SpawnSystemLevelUpChancePatch(ref float __result)
		{
			if (ThisPlugin.PluginEnabled.Value)
			{
				__result *= ThisPlugin.EnemyLevelChanceMultiplier.Value;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TriggerSpawner), "Awake")]
		public static void TriggerSpawnerLevelUpChancePatch(ref TriggerSpawner __instance)
		{
			if (ThisPlugin.PluginEnabled.Value)
			{
				TriggerSpawner obj = __instance;
				obj.m_levelupChance *= ThisPlugin.EnemyLevelChanceMultiplier.Value;
			}
		}
	}
	[HarmonyPatch(typeof(Character), "SetMaxHealth")]
	public class MaxHealthPatch
	{
		public static void Prefix(Character __instance, ref float health)
		{
			if (!ThisPlugin.PluginEnabled.Value || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (__instance.IsBoss() && (Player.GetAllPlayers().Count > ThisPlugin.NumberOfPlayersMax.Value || !ThisPlugin.EnableBossHealthRegenMod.Value)) || (!__instance.IsBoss() && !ThisPlugin.EnableEnemyHealthMod.Value))
			{
				return;
			}
			string text = __instance.m_name.ToLower();
			if (text.StartsWith("$enemy_"))
			{
				text = text.Substring("$enemy_".Length);
			}
			ConfigEntry<int> target;
			if (!ThisPlugin.MaxHealthPercentDict.TryGetValue(text, out var value))
			{
				if (ThisPlugin.DebugOutput.Value && text != "human")
				{
					Debug.Log((object)("Casualheim | !!! unmatched enemy normal max health " + text + " :: " + health));
				}
			}
			else if (value.TryGetTarget(out target))
			{
				health *= (float)target.Value / 100f;
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)("Casualheim.MaxHealthPatch :: " + text + " :: " + health));
				}
			}
		}
	}
	[HarmonyPatch]
	public class MiningChoppingPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(DamageTypes), "GetTotalDamage")]
		public static bool DamageTypesGetTotalDamagePatch(ref DamageTypes __instance, ref float __result)
		{
			float value = ThisPlugin.ChopMineDamageMultiplier.Value;
			if ((double)value < 0.001)
			{
				return true;
			}
			__result = __instance.m_damage + __instance.m_blunt + __instance.m_slash + __instance.m_pierce + __instance.m_chop * value + __instance.m_pickaxe * value + __instance.m_fire + __instance.m_frost + __instance.m_lightning + __instance.m_poison + __instance.m_spirit;
			return false;
		}
	}
	[HarmonyPatch(typeof(Skill), "GetNextLevelRequirement")]
	public class SkillCurvePatch
	{
		public static bool Prefix(Skill __instance, ref float __result)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EasierSkillCurveEnabled.Value)
			{
				return true;
			}
			__result = Mathf.Floor(__instance.m_level + 1f) * ThisPlugin.RequiredExpMultiplier.Value;
			return false;
		}
	}
	[HarmonyPatch(typeof(Character), "Heal")]
	public class RegenPatch
	{
		public static void Prefix(Character __instance, ref float hp)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableBossHealthRegenMod.Value || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (__instance.IsBoss() && Player.GetAllPlayers().Count > ThisPlugin.NumberOfPlayersMax.Value))
			{
				return;
			}
			string text = __instance.m_name.ToLower();
			if (text.StartsWith("$enemy_"))
			{
				text = text.Substring("$enemy_".Length);
			}
			if (ThisPlugin.HealthRegenPercentDict.TryGetValue(text, out var value) && value.TryGetTarget(out var target))
			{
				hp *= (float)target.Value / 100f;
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)("Casualheim.RegenPatch :: " + text + " :: " + __instance.GetHealth() + " / " + __instance.GetMaxHealth() + "(+" + hp + ")"));
				}
			}
		}
	}
	[HarmonyPatch]
	public class AttackSlowdownPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Humanoid), "GetAttackSpeedFactorMovement")]
		public static void AttackMovementSpeedPatch(Humanoid __instance, ref float __result)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableAttackMod.Value && __result < 0.99f && ((object)__instance).GetType() == typeof(Player) && ThisPlugin.PluginEnabled.Value)
			{
				__result = (float)ThisPlugin.PercentAttackMovement.Value / 100f;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Humanoid), "GetAttackSpeedFactorRotation")]
		public static void AttackRotationSpeedPatch(Humanoid __instance, ref float __result)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableAttackMod.Value && __result < 0.99f && ((object)__instance).GetType() == typeof(Player) && ThisPlugin.PluginEnabled.Value)
			{
				__result = (float)ThisPlugin.PercentAttackRotation.Value / 100f;
			}
		}
	}
}
namespace Casualheim.leveling
{
	[HarmonyPatch]
	public class DisableBetterUIXPPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(XP), "Awake")]
		public static bool DisableXPAwake()
		{
			if (!ThisPlugin.EnableLeveling.Value)
			{
				return true;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(XP), "RaiseXP")]
		public static bool DisableXPRaiseXP()
		{
			if (!ThisPlugin.EnableLeveling.Value)
			{
				return true;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(XP), "UpdateLevelProgressPercentage")]
		public static bool DisableXPUpdateLevelProgressPercentage()
		{
			if (!ThisPlugin.EnableLeveling.Value)
			{
				return true;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(XP), "GetNextLevelRequirement")]
		public static bool DisableXPGetNextLevelRequirement(ref float __result)
		{
			if (!ThisPlugin.EnableLeveling.Value)
			{
				return true;
			}
			__result = 1f;
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(XPBar), "Create")]
		public static bool DisableXPBarCreate()
		{
			if (!ThisPlugin.EnableLeveling.Value)
			{
				return true;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(XPBar), "UpdateLevelProgressPercentage")]
		public static bool DisableXPBarUpdateLevelProgressPercentage()
		{
			if (!ThisPlugin.EnableLeveling.Value)
			{
				return true;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(XPBar), "UpdatePosition")]
		public static bool DisableXPBarUpdatePosition()
		{
			if (!ThisPlugin.EnableLeveling.Value)
			{
				return true;
			}
			return false;
		}
	}
	public static class Level
	{
		public static Player player;

		public static float total_exp;

		public static int level = -1;

		public static float next_level_progress;

		public static float curr_level_required_xp = 0f;

		public static float next_level_required_xp = 1f;

		public static void Initialize(ref Player player)
		{
			Level.player = player;
			level = -1;
			Update();
		}

		public static void Update()
		{
			//IL_0052: 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)
			if (!((Object)(object)player == (Object)null))
			{
				int num = level;
				UpdateTotalExp();
				UpdateLevel();
				UpdateLevelProgress();
				LevelIndicatorPatch.Update(level, next_level_progress);
				if (num != -1 && num < level)
				{
					player.m_skillLevelupEffects.Create(((Character)player).m_head.position, ((Character)player).m_head.rotation, ((Character)player).m_head, 1.5f, -1);
					((Character)player).Message((MessageType)2, $"<size=60><color=#ffffffff>New Level</color></size>\n<size=30>Reached level {level} </size>", 0, (Sprite)null);
				}
			}
		}

		public static void UpdateTotalExp()
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			float num = 0f;
			int num2 = 0;
			foreach (Skill value in player.m_skills.m_skillData.Values)
			{
				num2++;
				num += value.m_level;
			}
			total_exp = num / ((float)num2 * 100f) * 5050f;
		}

		public static void UpdateLevel()
		{
			if ((Object)(object)player == (Object)null)
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim.Level | local player is null !!!");
				}
				return;
			}
			level = (int)Math.Floor(Math.Round((-1.0 + Math.Sqrt(8.0 * (double)total_exp + 1.0)) / 2.0, 1));
			curr_level_required_xp = GetNextLevelRequirement(level - 1);
			next_level_required_xp = GetNextLevelRequirement(level);
			if (!ThisPlugin.PluginEnabled.Value)
			{
				return;
			}
			if (!((Character)player).m_nview.IsOwner())
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim.Level | we are not the owner of the local player !!!");
				}
				return;
			}
			ZDO zDO = ((Character)player).m_nview.GetZDO();
			if (zDO == null)
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim.Level | zdo of local player is null !!!");
				}
				return;
			}
			if (ThisPlugin.DebugOutput.Value)
			{
				Debug.Log((object)("Casualheim.Level | current level for local player is :: " + level));
			}
			zDO.Set("betterui_level", level);
		}

		public static void UpdateLevelProgress()
		{
			next_level_progress = (total_exp - curr_level_required_xp) / (next_level_required_xp - curr_level_required_xp);
		}

		public static float GetNextLevelRequirement(int lvl)
		{
			return ((float)lvl + 1f) * (2f + (float)lvl) / 2f;
		}
	}
	[HarmonyPatch]
	public class LevelPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Skills), "LowerAllSkills")]
		public static void SkillstLowerAllSkillsPatch()
		{
			if (ThisPlugin.EnableLeveling.Value)
			{
				Level.Update();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Skills), "CheatRaiseSkill")]
		public static void SkillsCheatRaiseSkillPatch()
		{
			if (ThisPlugin.EnableLeveling.Value)
			{
				Level.Update();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Skill), "Raise")]
		public static void SkillRaisePatch()
		{
			if (ThisPlugin.EnableLeveling.Value)
			{
				Level.Update();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "Update")]
		public static void HudUpdatePatch()
		{
			if (ThisPlugin.EnableLeveling.Value)
			{
				Player player = Player.m_localPlayer;
				if ((Object)(object)player != (Object)null && ((Object)(object)Level.player == (Object)null || ((object)Level.player).GetHashCode() != ((object)player).GetHashCode()))
				{
					Level.Initialize(ref player);
				}
			}
		}
	}
	[HarmonyPatch]
	public class StatModificationPatch
	{
		public static Dictionary<int, float> stamina_values = new Dictionary<int, float>();

		public static float GetLevelEffectStrength(ref ZDO zdo, float strength_at_100)
		{
			return (float)zdo.GetInt("betterui_level", 0) / 100f / (1f / (strength_at_100 - 1f)) + 1f;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Character), "SetMaxHealth")]
		public static void CharacterSetMaxHealthPatch(ref Character __instance, ref float health)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value && ThisPlugin.HealthBoostMultiplier.Value != 0f && Util.TryGetPlayerZDO(ref __instance, out var _, out var zdo))
			{
				float num = GetLevelEffectStrength(ref zdo, 1.5f) * ThisPlugin.HealthBoostMultiplier.Value;
				health *= num;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Character), "Heal")]
		public static void CharacterHealPatch(Character __instance, ref float hp)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value && ThisPlugin.HealthRegenBoostMultiplier.Value != 0f && Util.TryGetPlayerZDO(ref __instance, out var _, out var zdo))
			{
				float num = GetLevelEffectStrength(ref zdo, 1.5f) * ThisPlugin.HealthRegenBoostMultiplier.Value;
				hp *= num;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "SetMaxStamina")]
		public static void PlayerSetMaxStaminaPatch(Player __instance, ref float stamina)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value && ThisPlugin.StaminaBoostMultiplier.Value != 0f && Util.TryGetPlayerZDO(ref __instance, out var zdo))
			{
				float num = GetLevelEffectStrength(ref zdo, 1.25f) * ThisPlugin.StaminaBoostMultiplier.Value;
				stamina *= num;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })]
		public static void PlayerUpdateStatsPatch_Prefix(Player __instance)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value && ThisPlugin.StaminaRegenBoostMultiplier.Value != 0f)
			{
				stamina_values[((object)__instance).GetHashCode()] = __instance.m_stamina;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })]
		public static void PlayerUpdateStatsPatch_Postfix(Player __instance)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableLeveling.Value || ThisPlugin.StaminaRegenBoostMultiplier.Value == 0f)
			{
				return;
			}
			int hashCode = ((object)__instance).GetHashCode();
			ZDO zdo;
			if (!stamina_values.ContainsKey(hashCode))
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)("Casualheim.StatModificationPatch | stamina_values has no record for player " + ((Character)__instance).m_name + " !!!"));
				}
			}
			else if (Util.TryGetPlayerZDO(ref __instance, out zdo))
			{
				float num = GetLevelEffectStrength(ref zdo, 2f) * ThisPlugin.StaminaRegenBoostMultiplier.Value;
				float num2 = __instance.m_stamina - stamina_values[hashCode];
				if (!(num2 <= 0f))
				{
					__instance.m_stamina = Mathf.Min(((Character)__instance).GetMaxStamina(), num2 * (num - 1f) + __instance.m_stamina);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "GetJogSpeedFactor")]
		public static void PlayerGetJogSpeedFactorPatch(Player __instance, ref float __result)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value && ThisPlugin.SpeedBoostMultiplier.Value != 0f && Util.TryGetPlayerZDO(ref __instance, out var zdo))
			{
				float num = GetLevelEffectStrength(ref zdo, 1.25f) * ThisPlugin.SpeedBoostMultiplier.Value;
				__result *= num;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "GetRunSpeedFactor")]
		public static void PlayerGetRunSpeedFactorPatch(Player __instance, ref float __result)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value && ThisPlugin.SpeedBoostMultiplier.Value != 0f && Util.TryGetPlayerZDO(ref __instance, out var zdo))
			{
				float num = GetLevelEffectStrength(ref zdo, 1.25f) * ThisPlugin.SpeedBoostMultiplier.Value;
				__result *= num;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Character), "UpdateWalking")]
		public static void CharacterUpdateWalkingPatch(Character __instance)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value && ThisPlugin.SpeedBoostMultiplier.Value != 0f && Util.TryGetPlayerZDO(ref __instance, out var player, out var zdo))
			{
				float num = GetLevelEffectStrength(ref zdo, 1.25f) * ThisPlugin.SpeedBoostMultiplier.Value;
				float num2 = player.m_skills.GetSkillFactor((SkillType)101) * 0.5f + 1f;
				float num3 = 1f + ((Character)player).GetEquipmentMovementModifier();
				((Character)player).m_crouchSpeed = 2f * num * num2 * num3;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Character), "UpdateGroundContact")]
		public static void CharacteUpdateGroundContactPatch_Prefix(Character __instance)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!ThisPlugin.PluginEnabled.Value || !__instance.m_groundContact || !Util.TryGetPlayerZDO(ref __instance, out var player, out var zdo))
			{
				return;
			}
			float num = ((Character)player).m_maxAirAltitude - ((Component)player).transform.position.y;
			if (!(num <= 0f))
			{
				float num2 = player.m_skills.GetSkillFactor((SkillType)100) * 0.3f;
				Player obj = player;
				((Character)obj).m_maxAirAltitude = ((Character)obj).m_maxAirAltitude - num * num2;
				if (ThisPlugin.FallWindowMultiplier.Value != 0f)
				{
					float num3 = (GetLevelEffectStrength(ref zdo, 3f) - 1f) * ThisPlugin.FallWindowMultiplier.Value;
					((Character)player).m_maxAirAltitude = Math.Max(((Character)player).m_maxAirAltitude - num3, ((Component)player).transform.position.y);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Skills), "GetSkillFactor")]
		public static void SkillsGetSkillFactorPatch(ref Skills __instance, ref float __result, ref SkillType skillType)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.JumpHeightMultiplier.Value != 0f && !((Object)(object)__instance.m_player == (Object)null) && (int)skillType == 100 && Util.TryGetPlayerZDO(ref __instance.m_player, out var zdo) && Util.check_caller(typeof(Character), "Jump"))
			{
				float num = GetLevelEffectStrength(ref zdo, 1.4f) * ThisPlugin.JumpHeightMultiplier.Value;
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)("Casualheim.StatModificationPatch | icreasing jump force " + num + " times"));
				}
				__result *= num;
			}
		}
	}
}
namespace Casualheim.gui
{
	[HarmonyPatch]
	public class LevelIndicatorPatch
	{
		public const float max_bar_length = 97f;

		public static TextMeshProUGUI level_indicator_text;

		public static RectTransform level_indicator_bar;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryGui), "Awake")]
		public static void InventoryGuiAwakePatch()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableLeveling.Value)
			{
				return;
			}
			level_indicator_text = null;
			level_indicator_bar = null;
			Transform obj = InventoryGui.m_instance.m_inventoryRoot.Find("Info");
			Transform obj2 = ((obj is RectTransform) ? obj : null);
			Transform obj3 = obj2.Find("TitlePanel");
			RectTransform val = (RectTransform)(object)((obj3 is RectTransform) ? obj3 : null);
			Transform obj4 = obj2.Find("Texts");
			RectTransform val2 = (RectTransform)(object)((obj4 is RectTransform) ? obj4 : null);
			Transform obj5 = obj2.Find("Skills");
			RectTransform val3 = (RectTransform)(object)((obj5 is RectTransform) ? obj5 : null);
			Transform obj6 = obj2.Find("Trophies");
			RectTransform val4 = (RectTransform)(object)((obj6 is RectTransform) ? obj6 : null);
			Transform obj7 = obj2.Find("PVP");
			Transform obj8 = ((obj7 is RectTransform) ? obj7 : null);
			Transform obj9 = ((Transform)val).Find("charactername");
			RectTransform val5 = (RectTransform)(object)((obj9 is RectTransform) ? obj9 : null);
			Transform obj10 = ((Transform)val).Find("BraidLineHorisontalMedium (1)");
			RectTransform val6 = (RectTransform)(object)((obj10 is RectTransform) ? obj10 : null);
			Transform obj11 = ((Transform)val).Find("BraidLineHorisontalMedium (2)");
			Transform obj12 = ((obj11 is RectTransform) ? obj11 : null);
			val6.anchoredPosition = new Vector2(val6.anchoredPosition.x, -13f);
			((RectTransform)obj12).anchoredPosition = new Vector2(((RectTransform)obj12).anchoredPosition.x, -13f);
			val2.anchoredPosition = new Vector2(val2.anchoredPosition.x, -24f);
			val3.anchoredPosition = new Vector2(val3.anchoredPosition.x, -24f);
			val4.anchoredPosition = new Vector2(val4.anchoredPosition.x, -24f);
			((RectTransform)obj8).anchoredPosition = new Vector2(((RectTransform)obj8).anchoredPosition.x, -24f);
			GameObject val7 = null;
			GameObject val8 = null;
			GuiBar[] array = Resources.FindObjectsOfTypeAll(typeof(GuiBar)) as GuiBar[];
			foreach (GuiBar val9 in array)
			{
				if (((Object)val9).name.Equals("levelbar"))
				{
					val7 = ((Component)val9).gameObject;
					break;
				}
			}
			ButtonSfx[] array2 = Resources.FindObjectsOfTypeAll(typeof(ButtonSfx)) as ButtonSfx[];
			foreach (ButtonSfx val10 in array2)
			{
				if (((Object)val10).name.Equals("Craft"))
				{
					val8 = ((Component)val10).gameObject;
					break;
				}
			}
			Transform obj13 = ((Transform)val).Find("cslh_lvl_indicator");
			RectTransform val11 = (RectTransform)(object)((obj13 is RectTransform) ? obj13 : null);
			if ((Object)(object)val11 != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val11).gameObject);
			}
			GameObject val12 = Object.Instantiate<GameObject>(val8, (Transform)(object)val);
			Component component = val12.GetComponent(typeof(RectTransform));
			val11 = (RectTransform)(object)((component is RectTransform) ? component : null);
			Object.Destroy((Object)(object)((Component)((Transform)val11).Find("Text")).gameObject);
			Object.Destroy((Object)(object)((Component)((Transform)val11).Find("Selected")).gameObject);
			Object.Destroy((Object)(object)((Component)((Transform)val11).Find("gamepad_hint")).gameObject);
			Object.Destroy((Object)(object)val12.GetComponent(typeof(ButtonSfx)));
			Object.Destroy((Object)(object)val12.GetComponent(typeof(UIGamePad)));
			Object.Destroy((Object)(object)val12.GetComponent(typeof(ButtonTextColor)));
			GameObject obj14 = Object.Instantiate<GameObject>(val7, ((Component)val11).transform);
			Component component2 = obj14.GetComponent(typeof(RectTransform));
			RectTransform val13 = (RectTransform)(object)((component2 is RectTransform) ? component2 : null);
			Debug.Log((object)val13);
			Object.Destroy((Object)(object)((Component)((Transform)val13).Find("bkg")).gameObject);
			Object.Destroy((Object)(object)((Component)((Transform)val13).Find("bonustext")).gameObject);
			Object.Destroy((Object)(object)obj14.GetComponent(typeof(GuiBar)));
			((Transform)val11).localPosition = new Vector3(0f, 0f, 0f);
			val11.anchoredPosition = new Vector2(val11.anchoredPosition.x, val11.anchoredPosition.y - 26f);
			val11.sizeDelta = new Vector2(100f, 22f);
			((Object)val12).name = "cslh_lvl_indicator";
			val13.anchoredPosition = new Vector2(0f, 0f);
			val13.sizeDelta = new Vector2(98.5f, 20f);
			((Object)obj14).name = "cslh_lvl_bar_container";
			Transform obj15 = ((Transform)val13).Find("bar");
			Transform obj16 = ((obj15 is RectTransform) ? obj15 : null);
			val13.anchoredPosition = new Vector2(0f, 0f);
			((RectTransform)obj16).sizeDelta = new Vector2(97f, 0f);
			((Object)((Component)obj16).gameObject).name = "cslh_lvl_bar";
			Transform obj17 = ((Transform)val13).Find("leveltext");
			Transform obj18 = ((obj17 is RectTransform) ? obj17 : null);
			GameObject val14 = Object.Instantiate<GameObject>(((Component)val5).gameObject, (Transform)(object)val13);
			Component component3 = val14.GetComponent(typeof(TextMeshProUGUI));
			TextMeshProUGUI val15 = (TextMeshProUGUI)(object)((component3 is TextMeshProUGUI) ? component3 : null);
			Component component4 = val14.GetComponent(typeof(RectTransform));
			RectTransform val16 = (RectTransform)(object)((component4 is RectTransform) ? component4 : null);
			Vector2 anchoredPosition = ((RectTransform)obj18).anchoredPosition;
			Vector2 offsetMax = ((RectTransform)obj18).offsetMax;
			Vector2 offsetMin = ((RectTransform)obj18).offsetMin;
			Vector2 sizeDelta = ((RectTransform)obj18).sizeDelta;
			val16.anchoredPosition = anchoredPosition;
			val16.offsetMax = offsetMax;
			val16.offsetMin = offsetMin;
			val16.sizeDelta = sizeDelta;
			Object.Destroy((Object)(object)((Component)obj18).gameObject);
			((Object)val14).name = "cslh_lvl_text";
			((Graphic)val15).color = new Color(1f, 0.8667f, 0.6784f, 1f);
			((TMP_Text)val15).fontSizeMax = 20f;
			level_indicator_text = val15;
			level_indicator_bar = (RectTransform)(object)obj16;
		}

		public static void Update(int level, float progress)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)level_indicator_text == (Object)null) && !((Object)(object)level_indicator_bar == (Object)null))
			{
				if (progress < 0f)
				{
					progress = 0f;
				}
				if (progress > 1f)
				{
					progress = 1f;
				}
				((TMP_Text)level_indicator_text).text = "Level  " + level;
				level_indicator_bar.sizeDelta = new Vector2(97f * progress, level_indicator_bar.sizeDelta.y);
			}
		}
	}
}
namespace Casualheim.attack_cancel
{
	public struct BlockInputState
	{
		public float block_start_time;

		public float attack_start_time;

		public float dodge_end_time;

		public bool block_state;

		public bool attack_state;

		public bool dodge_state;
	}
	public struct AttackCancel
	{
		public float time;

		public int atk;

		public bool done;
	}
	public struct DamageDone
	{
		public int atk;

		public float time;
	}
	public static class State
	{
		public static Dictionary<int, AttackCancel> last_attack_cancel_dict = new Dictionary<int, AttackCancel>();

		public static Dictionary<int, BlockInputState> block_state_dict = new Dictionary<int, BlockInputState>();

		public static Dictionary<int, DamageDone> player_attack_damage_done_dict = new Dictionary<int, DamageDone>();

		public static Dictionary<int, int> player_in_attack_frame_cached = new Dictionary<int, int>();

		public static Dictionary<int, bool> player_started_secondary = new Dictionary<int, bool>();

		public static Dictionary<int, WeakReference<Player>> zanim_player_dict = new Dictionary<int, WeakReference<Player>>();
	}
	[HarmonyPatch]
	public class AttackPreventLogicPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Attack), "Update")]
		[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
		[HarmonyPatch(typeof(Attack), "ConsumeItem")]
		[HarmonyPatch(typeof(Attack), "UseAmmo")]
		[HarmonyPatch(typeof(Attack), "FireProjectileBurst")]
		[HarmonyPatch(typeof(Attack), "DoNonAttack")]
		[HarmonyPatch(typeof(Attack), "DoAreaAttack")]
		[HarmonyPatch(typeof(Attack), "AddHitPoint")]
		[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
		[HarmonyPatch(typeof(Attack), "SpawnOnHit")]
		[HarmonyPatch(typeof(Attack), "TryAttach")]
		[HarmonyPatch(typeof(Attack), "UpdateAttach")]
		public static bool PreventLogic(ref Attack __instance)
		{
			if (__instance.m_abortAttack && ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableAttackMod.Value)
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class AttackCancelPatch
	{
		public static bool ApplyAnimSpeedup(ref Player p)
		{
			ItemData currentWeapon = ((Humanoid)p).GetCurrentWeapon();
			if (currentWeapon != null && currentWeapon.m_shared != null && currentWeapon.m_shared.m_name != null)
			{
				string name = currentWeapon.m_shared.m_name;
				if (name.Contains("spear"))
				{
					return false;
				}
				if (name.Contains("pickaxe"))
				{
					return false;
				}
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "Awake")]
		public static void PlayerAwakePatch(ref Player __instance)
		{
			if ((Object)(object)((Character)__instance).m_zanim == (Object)null)
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim.PlayerAwakePatch | player m_zanim is null !!!");
				}
			}
			else
			{
				int hashCode = ((object)__instance).GetHashCode();
				State.player_in_attack_frame_cached[hashCode] = MonoUpdaters.UpdateCount;
				State.player_started_secondary[hashCode] = false;
				State.zanim_player_dict.Add(((object)((Character)__instance).m_zanim).GetHashCode(), new WeakReference<Player>(__instance));
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZSyncAnimation), "RPC_SetTrigger")]
		public static bool ZSyncAnimationRPC_SetTriggerPatch(ref ZSyncAnimation __instance, ref string name)
		{
			if (!name.StartsWith("csca!"))
			{
				return true;
			}
			int hashCode = ((object)__instance).GetHashCode();
			if (!State.zanim_player_dict.ContainsKey(hashCode))
			{
				return true;
			}
			if (!State.zanim_player_dict[hashCode].TryGetTarget(out var target))
			{
				return true;
			}
			Animator animator = ((Character)target).m_animator;
			((Character)target).m_animEvent.m_pauseTimer = -1f;
			if (ApplyAnimSpeedup(ref target))
			{
				animator.speed = 1000f;
			}
			else
			{
				animator.speed = 1f;
			}
			animator.ForceStateNormalizedTime(0.99f);
			return false;
		}

		public static void SkipCurrentAttackAnimation(ref Player p)
		{
			if (((Character)p).GetNextAnimHash() != Humanoid.s_animatorTagAttack && ((Character)p).GetCurrentAnimHash() != Humanoid.s_animatorTagAttack)
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim.SkipCurrentAttackAnimation | no animation is an attack animation !!!");
				}
			}
			else
			{
				((Character)p).m_nview.InvokeRPC(ZNetView.Everybody, "SetTrigger", new object[1] { "csca!" });
			}
		}

		public static bool CancelAttack(ref Player p, float attack_min_time)
		{
			if (((Humanoid)p).m_currentAttack == null)
			{
				return false;
			}
			Attack currentAttack = ((Humanoid)p).m_currentAttack;
			int hashCode = ((object)p).GetHashCode();
			int hashCode2 = ((object)currentAttack).GetHashCode();
			float time = currentAttack.m_time;
			bool num = State.last_attack_cancel_dict.ContainsKey(hashCode);
			bool flag = num && State.last_attack_cancel_dict[hashCode].atk == hashCode2;
			bool done = false;
			if (num && flag)
			{
				done = State.last_attack_cancel_dict[hashCode].done;
				return true;
			}
			if (time <= attack_min_time)
			{
				return false;
			}
			if (ThisPlugin.DebugOutput.Value)
			{
				Debug.Log((object)"Casualheim.CancelAttack | cancelling");
			}
			currentAttack.Abort();
			SkipCurrentAttackAnimation(ref p);
			currentAttack.m_zanim.SetTrigger("attack_abort");
			currentAttack.m_zanim.SetTrigger("detach");
			((Humanoid)p).m_previousAttack = null;
			State.last_attack_cancel_dict[hashCode] = new AttackCancel
			{
				time = Time.fixedTime,
				atk = hashCode2,
				done = done
			};
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Humanoid), "OnAttackTrigger")]
		public static void HumanoidOnAttackTriggerPatch(Humanoid __instance)
		{
			if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableAttackMod.Value && !(((object)__instance).GetType() != typeof(Player)) && __instance.m_currentAttack != null)
			{
				Humanoid obj = ((__instance is Player) ? __instance : null);
				Attack currentAttack = obj.m_currentAttack;
				int hashCode = ((object)obj).GetHashCode();
				int hashCode2 = ((object)currentAttack).GetHashCode();
				if (!State.player_attack_damage_done_dict.ContainsKey(hashCode))
				{
					State.player_attack_damage_done_dict.Add(hashCode, new DamageDone
					{
						atk = hashCode2,
						time = Time.fixedTime
					});
				}
				else
				{
					State.player_attack_damage_done_dict[hashCode] = new DamageDone
					{
						atk = hashCode2,
						time = Time.fixedTime
					};
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "Dodge")]
		public static bool PlayerDodgePatch(Player __instance, ref Vector3 dodgeDir)
		{
			//IL_002f: 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)
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.PreventDodgeSpamming.Value)
			{
				return true;
			}
			if (!((Character)__instance).InDodge())
			{
				__instance.m_queuedDodgeTimer = 0.5f;
			}
			__instance.m_queuedDodgeDir = dodgeDir;
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "UpdateDodge")]
		public static bool PlayerUpdateDodgePatch(Player __instance, ref float dt)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableAttackMod.Value)
			{
				return true;
			}
			if (((Character)__instance).InDodge())
			{
				return true;
			}
			int hashCode = ((object)__instance).GetHashCode();
			if (!State.block_state_dict.ContainsKey(hashCode) || Time.fixedTime - State.block_state_dict[hashCode].block_start_time > 0.1f)
			{
				return true;
			}
			__instance.m_queuedDodgeTimer -= dt;
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "InAttack")]
		public static void PlayerInAttackCancelPatch(Player __instance, ref bool __result)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableAttackMod.Value)
			{
				return;
			}
			int hashCode = ((object)__instance).GetHashCode();
			float fixedTime = Time.fixedTime;
			if (State.player_in_attack_frame_cached[hashCode] == MonoUpdaters.UpdateCount)
			{
				return;
			}
			bool flag = false;
			bool flag2 = false;
			if (State.player_attack_damage_done_dict.TryGetValue(hashCode, out var value) && ((Humanoid)__instance).m_currentAttack != null)
			{
				flag2 = value.atk == ((object)((Humanoid)__instance).m_currentAttack).GetHashCode();
				flag = fixedTime - value.time > 1.5f;
			}
			if (State.last_attack_cancel_dict.ContainsKey(hashCode) && !State.last_attack_cancel_dict[hashCode].done)
			{
				float num = fixedTime - State.last_attack_cancel_dict[hashCode].time;
				if (num < 0.1f)
				{
					if (ThisPlugin.DebugOutput.Value)
					{
						Debug.Log((object)("Casualheim | (in attack) attack canceled recently :: " + num + "s  ---  " + MonoUpdaters.UpdateCount));
					}
					SkipCurrentAttackAnimation(ref __instance);
					__result = false;
					__instance.m_cachedAttack = __result;
					State.player_in_attack_frame_cached[hashCode] = MonoUpdaters.UpdateCount;
					return;
				}
				AttackCancel value2 = State.last_attack_cancel_dict[hashCode];
				value2.done = true;
				State.last_attack_cancel_dict[hashCode] = value2;
			}
			if (((Humanoid)__instance).m_currentAttack == null)
			{
				return;
			}
			bool flag3 = ((Humanoid)__instance).m_currentAttack == null || ((Humanoid)__instance).m_currentAttack.IsDone();
			StackFrame[] frames = new StackTrace(fNeedFileInfo: true).GetFrames();
			bool flag4 = false;
			bool flag5 = false;
			float attack_min_time = 0f;
			for (int i = 1; i < frames.Length; i++)
			{
				MethodBase method = frames[i].GetMethod();
				if (method == null)
				{
					continue;
				}
				Type realDeclaringType = ReflectionHelper.GetRealDeclaringType((MemberInfo)method);
				string name = method.Name;
				if (realDeclaringType == null || name == null)
				{
					continue;
				}
				if (realDeclaringType == typeof(Character) && name.Contains("Jump"))
				{
					flag4 = true;
					attack_min_time = 0f;
					break;
				}
				if (realDeclaringType == typeof(Humanoid) && name.Contains("UpdateBlock"))
				{
					bool flag6 = false;
					if (!State.block_state_dict.ContainsKey(hashCode))
					{
						flag6 = true;
					}
					if (!flag6)
					{
						BlockInputState blockInputState = State.block_state_dict[hashCode];
						if (blockInputState.attack_start_time < blockInputState.block_start_time)
						{
							flag6 = true;
						}
					}
					if (flag6)
					{
						flag4 = true;
						flag5 = true;
						attack_min_time = 0.1f;
					}
					break;
				}
				if (realDeclaringType == typeof(Player) && name.Contains("UpdateDodge"))
				{
					float num2 = __instance.m_dodgeStaminaUsage - __instance.m_dodgeStaminaUsage * ((Character)__instance).GetEquipmentMovementModifier() + __instance.m_dodgeStaminaUsage * ((Character)__instance).GetEquipmentDodgeStaminaModifier();
					((Character)__instance).m_seman.ModifyDodgeStaminaUsage(num2, ref num2, true);
					if (((Character)__instance).HaveStamina(num2))
					{
						flag4 = true;
						attack_min_time = 0.1f;
					}
					break;
				}
			}
			if ((!flag2 || flag || flag5) && flag4 && (!flag3 || flag))
			{
				((Humanoid)__instance).ClearActionQueue();
				__result = !CancelAttack(ref __instance, attack_min_time);
				__instance.m_cachedAttack = __result;
				if (!__result && flag5)
				{
					((Character)__instance).m_nview.GetZDO().Set(ZDOVars.s_isBlockingHash, true);
					((Character)__instance).m_zanim.SetBool(Humanoid.s_blocking, true);
				}
				State.player_in_attack_frame_cached[hashCode] = MonoUpdaters.UpdateCount;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		public static bool HumanoidStartAttackCancelPatch_Prefix(Humanoid __instance, ref bool __result)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableAttackMod.Value)
			{
				return true;
			}
			if (((object)__instance).GetType() != typeof(Player))
			{
				return true;
			}
			int hashCode = ((object)((__instance is Player) ? __instance : null)).GetHashCode();
			float fixedTime = Time.fixedTime;
			if (State.last_attack_cancel_dict.ContainsKey(hashCode))
			{
				float num = fixedTime - State.last_attack_cancel_dict[hashCode].time;
				if (num < 0.5f)
				{
					if (ThisPlugin.DebugOutput.Value)
					{
						Debug.Log((object)("Casualheim.HumanoidStartAttackCancelPatch | attack canceled recently :: " + num + "s"));
					}
					__result = false;
					return false;
				}
			}
			else if (State.block_state_dict.ContainsKey(hashCode))
			{
				BlockInputState blockInputState = State.block_state_dict[hashCode];
				if ((blockInputState.block_state && blockInputState.block_start_time > blockInputState.attack_start_time) || blockInputState.dodge_state || fixedTime - blockInputState.dodge_end_time < 0.15f || !blockInputState.attack_state)
				{
					if (ThisPlugin.DebugOutput.Value)
					{
						Debug.Log((object)"Casualheim.HumanoidStartAttackCancelPatch | block/dodge");
					}
					__result = false;
					return false;
				}
			}
			if (ThisPlugin.DebugOutput.Value)
			{
				Debug.Log((object)"Casualheim.HumanoidStartAttackCancelPatch | starting attack ...");
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		public static void HumanoidStartAttackCancelPatch_Postfix(Humanoid __instance, ref bool __result, ref bool secondaryAttack)
		{
			if (__result && ((Character)__instance).IsPlayer())
			{
				State.player_started_secondary[((object)((__instance is Player) ? __instance : null)).GetHashCode()] = secondaryAttack;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "SetControls")]
		public static void PlayerSetControlsPatch(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold, ref bool dodge)
		{
			if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableAttackMod.Value)
			{
				return;
			}
			int hashCode = ((object)__instance).GetHashCode();
			bool flag = block | blockHold;
			bool flag2 = (attack | attackHold | secondaryAttack | secondaryAttackHold) || ((Humanoid)__instance).m_attackDrawTime > 0.01f;
			bool inDodge = __instance.m_inDodge;
			float fixedTime = Time.fixedTime;
			float num;
			float num2;
			float num3;
			if (!State.block_state_dict.ContainsKey(hashCode))
			{
				num = (flag ? fixedTime : (-2f));
				num2 = (inDodge ? fixedTime : (-2f));
				num3 = (flag2 ? fixedTime : (-1f));
				State.block_state_dict.Add(hashCode, new BlockInputState
				{
					block_state = flag,
					block_start_time = num,
					attack_state = flag2,
					attack_start_time = num3,
					dodge_state = inDodge,
					dodge_end_time = num2
				});
			}
			else
			{
				BlockInputState blockInputState = State.block_state_dict[hashCode];
				num = ((!blockInputState.block_state && flag) ? fixedTime : blockInputState.block_start_time);
				num3 = ((!blockInputState.attack_state && flag2) ? fixedTime : blockInputState.attack_start_time);
				num2 = ((!inDodge) ? blockInputState.dodge_end_time : fixedTime);
				State.block_state_dict[hashCode] = new BlockInputState
				{
					block_state = flag,
					block_start_time = num,
					attack_state = flag2,
					attack_start_time = num3,
					dodge_state = inDodge,
					dodge_end_time = num2
				};
			}
			if ((flag && num > num3) || inDodge || fixedTime - num2 < 0.15f)
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim.PlayerSetControlsPatch | stopping attack input due to block/dodge");
				}
				attack = false;
				attackHold = false;
				secondaryAttack = false;
				secondaryAttackHold = false;
			}
			else if (State.last_attack_cancel_dict.ContainsKey(hashCode) && !(Time.fixedTime - State.last_attack_cancel_dict[hashCode].time >= 0.1f))
			{
				if (ThisPlugin.DebugOutput.Value)
				{
					Debug.Log((object)"Casualheim.PlayerSetControlsPatch | stopping attack input due recent cancelled attack");
				}
				attack = false;
				attackHold = false;
				secondaryAttack = false;
				secondaryAttackHold = false;
			}
		}
	}
}