Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Casualheim v1.2.8
Casualheim.dll
Decompiled 8 months agousing 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 { public class MaxHealthSetting { public string name; public ConfigEntry<int> percent; public static Dictionary<string, MaxHealthSetting> Settings = new Dictionary<string, MaxHealthSetting>(); public MaxHealthSetting(string name) { this.name = name; } public static void CreateMapping(string id, string name, int default_percent) { MaxHealthSetting maxHealthSetting = new MaxHealthSetting(name); maxHealthSetting.percent = ((BaseUnityPlugin)ThisPlugin.instance).Config.Bind<int>("Mob Health", "Percent " + id + " health", default_percent, "Percent of normal health that " + name + " will have."); Settings.Add(id.ToLower(), maxHealthSetting); } } [BepInPlugin("Casualheim", "Casualheim", "1.2.8")] [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.2.8"; 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<float> TrophyDropChanceMult; public static ConfigEntry<float> TrophyLevelDropChanceMult; 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<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> EitrBoostMultiplier; public static ConfigEntry<float> EitrRegenBoostMultiplier; public static ConfigEntry<float> SpeedBoostMultiplier; public static ConfigEntry<float> JumpHeightMultiplier; public static ConfigEntry<float> FallWindowMultiplier; public static ConfigEntry<bool> EnableShipHelp; public static ConfigEntry<float> ShipStabilization; public static ConfigEntry<float> RudderForceMult; public static ConfigEntry<float> SailForceMult; 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(ShipHelpPatch)); harmony_instance.PatchAll(typeof(TrophyDropPatch)); 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 CreateMaxHealthUnitMapping(string id, string display_name) { } public static void MaxHealthDictsInit() { MaxHealthSetting.CreateMapping("Goblin", "Fuling", 100); MaxHealthSetting.CreateMapping("GoblinBrute", "Fuling berserker", 75); MaxHealthSetting.CreateMapping("GoblinShaman", "Fuling shaman", 100); MaxHealthSetting.CreateMapping("Lox", "Lox", 75); MaxHealthSetting.CreateMapping("Deathsquito", "Deathsquito", 100); MaxHealthSetting.CreateMapping("BlobTar", "Growth", 100); MaxHealthSetting.CreateMapping("Seeker", "Seeker", 100); MaxHealthSetting.CreateMapping("SeekerBrood", "Seeker brood", 100); MaxHealthSetting.CreateMapping("SeekerBrute", "Seeker soldier", 67); MaxHealthSetting.CreateMapping("Gjall", "Gjall", 67); MaxHealthSetting.CreateMapping("Tick", "Tick", 100); MaxHealthSetting.CreateMapping("Dverger", "Dvergr rogue", 100); MaxHealthSetting.CreateMapping("DvergerMage", "Dvergr mage", 100); MaxHealthSetting.CreateMapping("DvergerMageFire", "Fire Dvergr mage", 100); MaxHealthSetting.CreateMapping("DvergerMageIce", "Ice Dvergr mage", 100); MaxHealthSetting.CreateMapping("DvergerMageSupport", "Support Dvergr mage", 100); MaxHealthSetting.CreateMapping("FallenValkyrie", "Fallen Valkyrie", 67); MaxHealthSetting.CreateMapping("Morgen", "Morgen", 50); MaxHealthSetting.CreateMapping("BonemawSerpent", "Bonemaw Serpent", 67); MaxHealthSetting.CreateMapping("Asksvin", "Asksvin", 100); MaxHealthSetting.CreateMapping("Volture", "Volture", 100); MaxHealthSetting.CreateMapping("piece_Charred_Balista", "Skugg", 100); MaxHealthSetting.CreateMapping("BlobLava", "Skugg", 100); MaxHealthSetting.CreateMapping("Charred_Melee_Dyrnwyn", "Lord Reto", 100); MaxHealthSetting.CreateMapping("DvergerAshlands", "Ashlands Dvergr", 100); MaxHealthSetting.CreateMapping("Charred_Melee", "Charred Warrior", 67); MaxHealthSetting.CreateMapping("Charred_Archer", "Charred Marksman", 100); MaxHealthSetting.CreateMapping("Charred_Mage", "Charred Warlock", 67); MaxHealthSetting.CreateMapping("Charred_Twitcher", "Charred Twitcher", 85); 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)."); TrophyDropChanceMult = ((BaseUnityPlugin)instance).Config.Bind<float>("General", "Trophy drop chance multiplier", 2f, "Multiplies the drop chance for the trophies (1.0 for no change)."); TrophyLevelDropChanceMult = ((BaseUnityPlugin)instance).Config.Bind<float>("General", "Trophy drop chance multiplier per level", 2f, "Multiplies the drop chance for the trophies further for every creature star (1.0 for no change)."); 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."); 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)."); EitrBoostMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Eitr boost strength multiplier", 1f, "Changes the strength of the eitr boost (0 for disable)."); EitrRegenBoostMultiplier = ((BaseUnityPlugin)instance).Config.Bind<float>("Leveling", "Eitr regen boost strength multiplier", 1f, "Changes the strength of the eitr 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)."); EnableShipHelp = ((BaseUnityPlugin)instance).Config.Bind<bool>("Ship Help", "Enable tweaks for easier sailing", true, "Enables/Disables the sailing assistance system"); ShipStabilization = ((BaseUnityPlugin)instance).Config.Bind<float>("Ship Help", "Ship stabilization assistance multiplier", 6f, "Changes the amount of ship stabilization (1.0 is vanilla)."); SailForceMult = ((BaseUnityPlugin)instance).Config.Bind<float>("Ship Help", "Ship sail force multiplier", 6f, "Changes the amount of force sails generate (1.0 is vanilla)."); RudderForceMult = ((BaseUnityPlugin)instance).Config.Bind<float>("Ship Help", "Ship rudder force multiplier", 4f, "Changes the amount of force rudder generates (0 for disable)."); } } public static class Util { public class CallStackPrinter { public HashSet<string> unique_callers = new HashSet<string>(); public string caller_name; public CallStackPrinter(string caller_name) { this.caller_name = caller_name; } public void print_callstack(bool force_print = false) { 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 (force_print || !unique_callers.Contains(text)) { unique_callers.Add(text); Debug.Log((object)""); Debug.Log((object)("in " + caller_name)); 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; } zloc_hash = last_zone_location_hash; zdo.Set("zloc_checked", true); zdo.Set("zloc_hash", zloc_hash); if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)("Casualheim | DETERMINISICALLY found zloc hash for " + ((object)obj).GetType()?.ToString() + " :: " + zloc_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; } zloc_hash = loc_2_zloc_dict[((object)loc).GetHashCode()]; zdo.Set("zloc_checked", true); zdo.Set("zloc_hash", zloc_hash); if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)("Casualheim | HEURISTICALLY found zloc hash for " + ((object)obj).GetType()?.ToString() + " :: " + 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 buildCheck, ref Vector3 point) { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !buildCheck || !__instance.m_noBuild || !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); } WeakReference<ConfigEntry<int>> value = null; ConfigEntry<int> target = null; if (text == "human") { return; } if (!ThisPlugin.MaxHealthPercentDict.TryGetValue(text, out value)) { if (!MaxHealthSetting.Settings.ContainsKey(text)) { return; } target = MaxHealthSetting.Settings[text].percent; } if ((target != null || value != null) && (target != null || value.TryGetTarget(out target))) { health *= (float)target.Value / 100f; } } } [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] public class ShipHelpPatch { [HarmonyPostfix] [HarmonyPatch(typeof(Ship), "GetSailForce")] public static void ShipGetSailForcePostfixPatch(Ship __instance, ref Vector3 __result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (ThisPlugin.EnableShipHelp.Value) { __result *= ThisPlugin.SailForceMult.Value; } } [HarmonyPrefix] [HarmonyPatch(typeof(Ship), "Start")] public static void ShipStartPatch(Ship __instance) { if (ThisPlugin.EnableShipHelp.Value) { __instance.m_sailForceOffset *= 1f / ThisPlugin.ShipStabilization.Value; __instance.m_backwardForce *= ThisPlugin.RudderForceMult.Value; if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)("Casualheim.ShipStartPatch :: tm_sailForceOffset = " + __instance.m_sailForceOffset)); Debug.Log((object)("Casualheim.ShipStartPatch :: m_backwardForce = " + __instance.m_backwardForce)); } } } } [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; } } } [HarmonyPatch] public class TrophyDropPatch { [HarmonyPrefix] [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] public static void GenerateDropListPatch(ref CharacterDrop __instance) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 ItemDrop val = default(ItemDrop); foreach (Drop drop in __instance.m_drops) { if (!drop.m_prefab.TryGetComponent<ItemDrop>(ref val)) { continue; } SharedData shared = val.m_itemData.m_shared; if (shared != null && (int)shared.m_itemType == 13) { float num = drop.m_chance * ThisPlugin.TrophyDropChanceMult.Value; for (int i = 0; i < __instance.m_character.GetLevel(); i++) { num *= ThisPlugin.TrophyLevelDropChanceMult.Value; } num = Math.Min(num, 1f); drop.m_chance = num; } } } } } 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 Dictionary<int, float> eitr_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), "SetMaxEitr")] public static void PlayerSetMaxEitrPatch(Player __instance, ref float eitr) { if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value && ThisPlugin.EitrBoostMultiplier.Value != 0f && Util.TryGetPlayerZDO(ref __instance, out var zdo)) { float num = GetLevelEffectStrength(ref zdo, 1.5f) * ThisPlugin.EitrBoostMultiplier.Value; eitr *= num; } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] public static void PlayerUpdateStatsPatch_Prefix(Player __instance) { if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableLeveling.Value) { stamina_values[((object)__instance).GetHashCode()] = __instance.m_stamina; eitr_values[((object)__instance).GetHashCode()] = __instance.m_eitr; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] public static void PlayerUpdateStatsPatch_Postfix(Player __instance) { if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableLeveling.Value) { return; } int hashCode = ((object)__instance).GetHashCode(); if (!Util.TryGetPlayerZDO(ref __instance, out var zdo)) { return; } if (stamina_values.ContainsKey(hashCode) && ThisPlugin.StaminaRegenBoostMultiplier.Value > 0.001f) { 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); } } if (eitr_values.ContainsKey(hashCode) && ThisPlugin.EitrRegenBoostMultiplier.Value > 0.001f) { float num3 = GetLevelEffectStrength(ref zdo, 2f) * ThisPlugin.EitrRegenBoostMultiplier.Value; float num4 = __instance.m_eitr - eitr_values[hashCode]; if (num4 > 0f) { __instance.m_eitr = Mathf.Min(((Character)__instance).GetMaxEitr(), num4 * (num3 - 1f) + __instance.m_eitr); } } } [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 struct PlayerAttackControls { public bool atk; public bool atkHold; public bool secAtk; public bool secAtkHold; } public static class State { public static Dictionary<int, AttackCancel> last_attack_cancel_dict = new Dictionary<int, AttackCancel>(); public static Dictionary<int, float> last_started_attack_time = new Dictionary<int, float>(); public static Dictionary<int, float> last_started_emote_time = new Dictionary<int, float>(); public static Dictionary<int, float> last_ended_emote_time = new Dictionary<int, float>(); 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, PlayerAttackControls> player_controls = new Dictionary<int, PlayerAttackControls>(); public static Dictionary<int, bool> player_attack_stop = new Dictionary<int, bool>(); public static Dictionary<int, float> player_no_attack_promise = new Dictionary<int, float>(); 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; } if (name == "csca!stop") { if (((Humanoid)target).m_currentAttack != null) { ((Humanoid)target).m_currentAttack.Stop(); } return false; } 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(); 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; float num; 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(); num = value.time; flag = fixedTime - num > 1f; } else { num = 0f; } if (State.last_attack_cancel_dict.ContainsKey(hashCode) && !State.last_attack_cancel_dict[hashCode].done) { float num2 = fixedTime - State.last_attack_cancel_dict[hashCode].time; if (num2 < 0.1f) { if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)("Casualheim.PlayerInAttackCancelPatch | attack canceled recently :: " + num2 + "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; } Attack currentAttack = ((Humanoid)__instance).m_currentAttack; bool flag3 = currentAttack.IsDone(); bool flag4 = currentAttack.m_projectileBursts > 1; bool flag5 = currentAttack.m_projectileBursts == currentAttack.m_projectileBurstsFired; StackFrame[] frames = new StackTrace(fNeedFileInfo: true).GetFrames(); bool flag6 = false; bool flag7 = 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")) { flag6 = true; attack_min_time = 0f; break; } if (realDeclaringType == typeof(Humanoid) && name.Contains("UpdateBlock")) { bool flag8 = false; if (!State.block_state_dict.ContainsKey(hashCode)) { flag8 = true; } if (!flag8) { BlockInputState blockInputState = State.block_state_dict[hashCode]; if (blockInputState.attack_start_time < blockInputState.block_start_time) { flag8 = true; } } if (flag8) { flag6 = true; flag7 = true; attack_min_time = 0.1f; } break; } if (realDeclaringType == typeof(Player) && name.Contains("UpdateDodge")) { float num3 = __instance.m_dodgeStaminaUsage - __instance.m_dodgeStaminaUsage * ((Character)__instance).GetEquipmentMovementModifier() + __instance.m_dodgeStaminaUsage * ((Character)__instance).GetEquipmentDodgeStaminaModifier(); ((Character)__instance).m_seman.ModifyDodgeStaminaUsage(num3, ref num3, true); if (((Character)__instance).HaveStamina(num3)) { flag6 = true; attack_min_time = 0.1f; } break; } } PlayerAttackControls value3; bool flag9 = State.player_controls.TryGetValue(hashCode, out value3); if (!flag6) { if (!State.player_attack_stop.TryGetValue(hashCode, out var value4)) { value4 = false; } if (!value4 && flag9) { if (!currentAttack.m_attackDone && (value3.atkHold || value3.secAtkHold) && flag4 && !flag5) { __result = true; return; } float value5 = ((!State.last_started_attack_time.TryGetValue(hashCode, out value5)) ? 10f : (fixedTime - value5)); if ((double)value5 > 0.2 && flag4 && ((!value3.atk && !value3.atkHold && !value3.secAtk && !value3.secAtkHold) || flag5)) { if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)"Casualheim.PlayerInAttackCancelPatch | stopping channeling attack gracefully"); } State.player_attack_stop[hashCode] = true; ((Character)__instance).m_nview.InvokeRPC(ZNetView.Everybody, "SetTrigger", new object[1] { "csca!stop" }); ((Humanoid)__instance).m_previousAttack = null; return; } } } if (!flag6) { return; } if (flag4 && !flag5) { if (!State.player_attack_stop.TryGetValue(hashCode, out var value6)) { value6 = false; } if (!value6) { if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)"Casualheim.PlayerInAttackCancelPatch | trying to \"cancel\" channeling attack"); } State.last_attack_cancel_dict[hashCode] = new AttackCancel { time = fixedTime, atk = ((object)currentAttack).GetHashCode(), done = true }; State.player_attack_stop[hashCode] = true; ((Character)__instance).m_nview.InvokeRPC(ZNetView.Everybody, "SetTrigger", new object[1] { "csca!stop" }); ((Humanoid)__instance).m_previousAttack = null; __result = false; return; } } if ((flag3 || flag2) && !flag) { if (!flag9 || value3.atk || value3.atkHold || value3.secAtk || value3.secAtkHold || !(fixedTime - num > 0.25f)) { return; } if (!State.player_no_attack_promise.TryGetValue(hashCode, out var value7)) { value7 = -1f; } if (fixedTime - value7 > 1f) { if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)"Casualheim.PlayerInAttackCancelPatch | making a promise of not attacking"); } State.player_no_attack_promise[hashCode] = fixedTime; } } ((Humanoid)__instance).ClearActionQueue(); __result = !CancelAttack(ref __instance, attack_min_time); __instance.m_cachedAttack = __result; if (!__result && flag7) { ((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(Player), "StartEmote")] public static bool PlayerStartEmotePatch(Player __instance) { if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableAttackMod.Value) { return true; } bool num = ((Humanoid)__instance).m_currentAttack == null || ((Humanoid)__instance).m_currentAttack.IsDone(); float num2 = -10f; int hashCode = ((object)__instance).GetHashCode(); float fixedTime = Time.fixedTime; if (State.last_started_attack_time.ContainsKey(hashCode)) { num2 = State.last_started_attack_time[hashCode]; } if (!num || fixedTime - num2 < 0.25f) { return false; } if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)"Casualheim | not cancelling StartEmote() !!!"); } State.last_started_emote_time[hashCode] = fixedTime; return true; } [HarmonyPrefix] [HarmonyPatch(typeof(Humanoid), "StartAttack")] public static bool HumanoidStartAttackCancelPatch_Prefix(Humanoid __instance, ref bool __result) { //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Invalid comparison between Unknown and I4 if (!ThisPlugin.PluginEnabled.Value || !ThisPlugin.EnableAttackMod.Value) { return true; } if (((object)__instance).GetType() != typeof(Player)) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); int hashCode = ((object)val).GetHashCode(); float fixedTime = Time.fixedTime; if (!State.player_no_attack_promise.TryGetValue(hashCode, out var value)) { value = -1f; } if (fixedTime - value < 1f) { if (ThisPlugin.DebugOutput.Value) { Debug.Log((object)("cannot start attack because of a promise ::\n\tpromise time :: " + value + "\n\tdelta :: " + (fixedTime - value))); } __result = false; return false; } if (State.last_ended_emote_time.ContainsKey(hashCode) && fixedTime - State.last_ended_emote_time[hashCode] < 0.25f) { __result = false; return false; } if (((Character)val).InEmote() || (State.last_started_emote_time.ContainsKey(hashCode) && fixedTime - State.last_started_emote_time[hashCode] < 0.25f)) { ((Character)val).StopEmote(); State.last_ended_emote_time[hashCode] = fixedTime; __result = false; return false; } 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 ..."); } State.last_started_attack_time[hashCode] = fixedTime; State.player_attack_stop[hashCode] = false; AnimatorControllerParameter[] parameters = ((Character)__instance).m_zanim.m_animator.parameters; foreach (AnimatorControllerParameter val2 in parameters) { if ((int)val2.type == 9) { ((Character)__instance).m_zanim.m_animator.ResetTrigger(val2.name); } } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(Humanoid), "StartAttack")] public static void HumanoidStartAttackCancelPatch_Postfix(Humanoid __instance, ref bool __result, ref bool secondaryAttack) { if (ThisPlugin.PluginEnabled.Value && ThisPlugin.EnableAttackMod.Value && __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 }; } bool flag3 = false; 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; flag3 = true; } if (!flag3 && !State.last_attack_cancel_dict.ContainsKey(hashCode)) { flag3 = true; } if (!flag3 && Time.fixedTime - State.last_attack_cancel_dict[hashCode].time >= 0.1f) { flag3 = true; } if (!flag3 && ThisPlugin.DebugOutput.Value) { Debug.Log((object)"Casualheim.PlayerSetControlsPatch | stopping attack input due recent cancelled attack"); } if (!flag3) { attack = false; attackHold = false; secondaryAttack = false; secondaryAttackHold = false; } State.player_controls[hashCode] = new PlayerAttackControls { atk = attack, atkHold = attackHold, secAtk = secondaryAttack, secAtkHold = secondaryAttackHold }; } } }