using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Zen.Config;
using Zen.Controls;
using Zen.Lib;
using Zen.Logging;
using ZenCombat.Compatibility;
using ZenCombat.Section;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenCombat")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenCombat")]
[assembly: AssemblyCopyright("Copyright \ufffd 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ZenCombat
{
[BepInPlugin("ZenDragon.ZenCombat", "ZenCombat", "0.4.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[SynchronizationMode(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class Plugin : ZenMod<Plugin>
{
public const string PluginName = "ZenCombat";
public const string PluginVersion = "0.4.0";
public const string PluginGUID = "ZenDragon.ZenCombat";
protected override void Setup()
{
((ZenMod)this).RequireGamepadRemap = RemapDodge.Configs.RemapDodgeButton.Value;
((ZenMod)this).RegisterInputs += RemapDodge.RemapGamepad;
((ZenMod)this).RegisterInputs += Mounts.SetupInputs;
((ZenMod)this).ConfigSync += Bows.Setup;
}
protected override void TitleScene(bool isFirstBoot)
{
}
protected override void WorldStart()
{
}
protected override void Shutdown()
{
}
}
}
namespace ZenCombat.Section
{
[HarmonyPatch]
internal static class Bows
{
private static class Configs
{
public static readonly ConfigEntry<bool> EnableWoodArrow;
public static readonly ConfigEntry<float> WoodArrowDamage;
public static readonly ConfigEntry<float> ProjectileLaunchAngle;
public static readonly ConfigEntry<float> BowDrawMovementSpeed;
public static readonly ConfigEntry<float> BowDrawSpeed;
static Configs()
{
EnableWoodArrow = Config.Define<bool>(true, "Bows", "Enable WoodArrow", false, "Allow wood arrows? They are a bit OP because they are so cheap and lethal.\r\nWhen enabled it does not make firing an arrow a risky proposition and they \r\nundermine any reason to invest in more expensive ammunition.\r\n[restart required]");
WoodArrowDamage = Config.Define<float>(true, "Bows", "WoodArrow Damage", 1f, Config.AcceptRange<float>(0.1f, 22f), "How much damage should wood arrows do if they are enabled?\r\nThey are very OP by default for being a basic crude arrow. (Vanilla: 22)\r\n[restart required]");
ProjectileLaunchAngle = Config.Define<float>(true, "Bows", "Projectile Launch Angle", -2f, Config.AcceptRange<float>(-10f, 10f), "Angle that the projectile is launched at. To offset the default undershot in Vanilla. (Vanilla: 0)");
BowDrawMovementSpeed = Config.Define<float>(true, "Bows", "Movement Speed", 0.5f, Config.AcceptRange<float>(0f, 1f), "Percent of normal movement speed when bow is drawn, 0.5 = 50%, move half speed when drawing bow. (Vanilla: 1)\r\nNOTE: If CombatOverhaulRewrite is installed it is recommended to set this to 1 otherwise the two mods will compound this value.");
BowDrawSpeed = Config.Define<float>(true, "Bows", "Bow Draw Speed", 0.5f, Config.AcceptRange<float>(0f, 1f), "Adjust bow draw speed to a percent of vanilla bow draw speed at high levels. 0.5 = half of vanilla speed. (Vanilla: 1)\r\nThis affects how fast the bow can be drawn at higher levels and is especailly influential when Bow skill level is maxed.\r\nReducing this value will make the bow draw slower, increasing it will make it draw faster.");
}
}
internal static void Setup()
{
SetupArrows();
}
private static void SetupArrows()
{
Log.Info((object)"Setting up arrows", (ushort)0);
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("ArrowWood");
ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
if ((Object)(object)val == (Object)null)
{
Log.Error((object)"Unable to find wood arrow in ObjectDB", (ushort)0);
return;
}
val.m_itemData.m_shared.m_damages.m_pierce = Configs.WoodArrowDamage.Value;
Recipe val2 = default(Recipe);
if (ItemDataExt.TryGetRecipe(val, ref val2))
{
val2.m_enabled = Configs.EnableWoodArrow.Value;
}
else
{
Log.Error((object)"Unable to find wood arrow recipe", (ushort)0);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Attack), "Start")]
private static void Attack_Start(Attack __instance)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Invalid comparison between Unknown and I4
Humanoid character = __instance.m_character;
Player val = (Player)(object)((character is Player) ? character : null);
if (val != null && PlayerExt.Is(val, (Character)(object)Player.m_localPlayer))
{
ItemData currentWeapon = ((Humanoid)val).GetCurrentWeapon();
if (currentWeapon != null && (int)currentWeapon.m_shared.m_skillType == 8)
{
Log.Info((object)$"Weapon: {ItemDataExt.GetName(currentWeapon)} LaunchAngle: {__instance.m_launchAngle}", (ushort)0);
__instance.m_launchAngle = Configs.ProjectileLaunchAngle.Value;
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Player), "GetJogSpeedFactor")]
private static void Player_GetJogSpeedFactor(Player __instance, ref float __result)
{
__result *= ((((Humanoid)__instance).m_attackDrawTime > 0f) ? Configs.BowDrawMovementSpeed.Value : 1f);
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(Humanoid), "GetAttackDrawPercentage")]
private static IEnumerable<CodeInstruction> Humanoid_GetAttackDrawPercentage(IEnumerable<CodeInstruction> codes)
{
MethodInfo methodInfo = AccessTools.Method(typeof(Mathf), "Lerp", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = AccessTools.Method(typeof(Bows), "BowDrawLerp_Intercept", (Type[])null, (Type[])null);
return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
}
private static float BowDrawLerp_Intercept(float a, float b, float t)
{
float num = ((Configs.BowDrawSpeed.Value > 0f) ? Configs.BowDrawSpeed.Value : (b / a));
float num2 = Mathf.Min(a, b / num);
return Mathf.Lerp(a, num2, t);
}
}
[HarmonyPatch]
internal static class DamageUI
{
private static class Configs
{
public static readonly ConfigEntry<bool> SoftDamageScreenFlash;
public static readonly ConfigEntry<bool> HideDamageText0;
public static readonly ConfigEntry<DamageTextVisibilityMode> DamageTextVisibility;
public static readonly ConfigEntry<float> DamageTextDistance;
public static readonly ConfigEntry<float> DamageTextDuration;
public static readonly ConfigEntry<int> DamageTextFontFar;
public static readonly ConfigEntry<int> DamageTextFontNear;
static Configs()
{
SoftDamageScreenFlash = Config.Define<bool>(true, "UI", "Softer Damage Screen Flash", true, "Override the vanilla red screen damage flash with a softer less blinding style.");
HideDamageText0 = Config.Define<bool>(true, "UI", "Damage Text - Hide 0", true, "Hide damage text when it's just value 0 (Vanilla: false)");
DamageTextVisibility = Config.Define<DamageTextVisibilityMode>(true, "UI", "Damage Text - Visibility", DamageTextVisibilityMode.Self, "In multiplayer, damage text visibility mode: (Vanilla: All)\r\nAll - View all damage numbers and info text from everyone.\r\nSelf - Only show your own damage numbers + Info texts.\r\nInfo - Only show info texts, no damage numbers.\r\nNone - Hide all texts, show nothing.");
DamageTextDistance = Config.Define<float>(true, "UI", "Damage Text - Distance", 60f, Config.AcceptRange<float>(15f, 100f), "Max distance to show damage texts. (Vanilla: 30)\r\nIf you want to hide damage texts use the Visibility setting instead.");
DamageTextDistance.SettingChanged += delegate
{
SetupDamageText();
};
DamageTextDuration = Config.Define<float>(true, "UI", "Damage Text - Duration", 1.5f, Config.AcceptRange<float>(0.5f, 5f), "Number of seconds to display damage texts (Vanilla: 1.5)\r\nIf you want to hide damage texts use the Visibility setting instead.");
DamageTextDuration.SettingChanged += delegate
{
SetupDamageText();
};
DamageTextFontFar = Config.Define<int>(true, "UI", "Damage Text - Font Far", 8, Config.AcceptRange<int>(2, 100), "Font size when the text is far from the camera (Vanilla: 8)\r\nIf you want to hide damage texts use the Visibility setting instead.");
DamageTextFontFar.SettingChanged += delegate
{
SetupDamageText();
};
DamageTextFontNear = Config.Define<int>(true, "UI", "Damage Text - Font Near", 16, Config.AcceptRange<int>(2, 100), "Font size when the text is near the camera (Vanilla: 16)\r\nIf you want to hide damage texts use the Visibility setting instead.");
DamageTextFontNear.SettingChanged += delegate
{
SetupDamageText();
};
}
}
private enum DamageTextVisibilityMode
{
All,
Self,
Info,
None
}
[HarmonyPatch]
private static class DamageTextDisplay
{
private static HitData? _hitData;
[HarmonyPostfix]
[HarmonyPatch(typeof(DamageText), "Awake")]
private static void DamageText_Awake(DamageText __instance)
{
SetupDamageText();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DamageText), "AddInworldText")]
private static void DamageText_AddInWorldText(ref bool __runOriginal, TextType type, bool mySelf)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Invalid comparison between Unknown and I4
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Invalid comparison between Unknown and I4
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Invalid comparison between Unknown and I4
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Invalid comparison between Unknown and I4
HitData? hitData = _hitData;
Character val = ((hitData != null) ? hitData.GetAttacker() : null);
int num;
if (!((Object)(object)Player.m_localPlayer == (Object)(object)val))
{
if (((Character)Player.m_localPlayer).IsRiding())
{
IDoodadController doodadController = Player.m_localPlayer.GetDoodadController();
num = (((Object)(object)val == (Object)(object)((doodadController != null) ? doodadController.GetControlledComponent() : null)) ? 1 : 0);
}
else
{
num = 0;
}
}
else
{
num = 1;
}
bool flag = (byte)num != 0;
bool flag2 = (int)type == 4;
bool num2 = mySelf && (int)type == 7;
bool flag3 = mySelf && (int)type <= 3;
bool flag4 = num2 || (flag && (int)type >= 3);
Log.Info((object)$"Attacker: {((val != null) ? val.GetHoverName() : null)} isAttacker:{flag}", (ushort)0);
__runOriginal = Configs.DamageTextVisibility.Value switch
{
DamageTextVisibilityMode.All => true,
DamageTextVisibilityMode.Self => flag || flag4 || flag2 || flag3,
DamageTextVisibilityMode.Info => flag4 || flag2,
DamageTextVisibilityMode.None => false,
_ => throw new ArgumentOutOfRangeException(),
};
_hitData = null;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(HitData), "SetAttacker")]
private static void HitData_SetAttacker(HitData __instance, Character? attacker)
{
_hitData = __instance;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DamageText), "ShowText", new Type[]
{
typeof(TextType),
typeof(Vector3),
typeof(float),
typeof(bool)
})]
private static void DamageText_ShowText(TextType type, float dmg, ref bool __runOriginal)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
if ((int)type == 0 && Configs.HideDamageText0.Value)
{
__runOriginal = dmg >= 0.1f;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DamageText), "ShowText", new Type[]
{
typeof(TextType),
typeof(Vector3),
typeof(string),
typeof(bool)
})]
private static void DamageText_ShowText(TextType type, ref string text)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Invalid comparison between Unknown and I4
if (float.TryParse(text, out var result) && result < 0.1f && (int)type == 3)
{
text = "$inventory_immune";
}
Log.Info((object)$"Damage text type: {type} text: {text}", (ushort)0);
}
}
private static void SetupDamageText()
{
if (Object.op_Implicit((Object)(object)DamageText.instance))
{
DamageText.instance.m_maxTextDistance = Configs.DamageTextDistance.Value;
DamageText.instance.m_textDuration = Configs.DamageTextDuration.Value;
DamageText.instance.m_largeFontSize = Configs.DamageTextFontNear.Value;
DamageText.instance.m_smallFontSize = Configs.DamageTextFontFar.Value;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Hud), "Awake")]
private static void Hud_Awake()
{
if (Configs.SoftDamageScreenFlash.Value)
{
Hud.instance.m_damageScreen.sprite = AssetIO.LoadSprite("damage_flash.png", (Assembly)null);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Hud), "DamageFlash")]
private static void Hud_DamageFlash(ref bool __runOriginal)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if (Configs.SoftDamageScreenFlash.Value)
{
__runOriginal = false;
Image damageScreen = Hud.instance.m_damageScreen;
((Graphic)damageScreen).color = new Color(1f, 0f, 0f, 0.8f);
((Component)damageScreen).gameObject.SetActive(true);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Hud), "UpdateDamageFlash")]
private static void Hud_UpdateDamageFlash(ref bool __runOriginal, float dt)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: 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)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
if (Configs.SoftDamageScreenFlash.Value)
{
__runOriginal = false;
Image damageScreen = Hud.instance.m_damageScreen;
Color color = ((Graphic)damageScreen).color;
color.a = Mathf.MoveTowards(color.a, 0f, dt * 0.5f);
((Graphic)damageScreen).color = color;
((Component)damageScreen).gameObject.SetActive(color.a > 0f);
}
}
}
[HarmonyPatch]
public static class Knockback
{
private static class Configs
{
private const string SECTION_KNOCKBACK = "Knockback";
public static readonly ConfigEntry<float> AttackMelee;
public static readonly ConfigEntry<float> AttackArea;
public static readonly ConfigEntry<float> AttackRanged;
private static readonly ConfigEntry<StringList> AttackAnim;
public static readonly Dictionary<string, float> AttackAnimValues;
public static readonly ConfigEntry<float> Recoil;
static Configs()
{
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Expected O, but got Unknown
//IL_00af: Expected O, but got Unknown
AttackMelee = Config.Define<float>(true, "Knockback", "Melee Attack", 0.4f, Config.AcceptRange<float>(0f, 2f), "The percent of vanilla pushback force to apply for melee attacks (Vanilla: 100%)\r\nMelee attacks are defined as horizontal and vertical attacks.\r\nBy default this is set to lower than 100% to make it feel weighty.\r\nOtherwise things get flinged around far to easily and feels weightless.\r\nNOTE: This is applied to both player and monster attacks.");
AttackArea = Config.Define<float>(true, "Knockback", "Area Attack", 0.5f, Config.AcceptRange<float>(0f, 2f), "The percent of vanilla pushback force to apply with Area attacks (Vanilla: 100%)\r\nBy default this is set to lower than 100% to make it feel weighty.\r\nOtherwise things get flinged around far to easily and feels weightless.\r\nNOTE: This is applied to both player and monster attacks.");
AttackRanged = Config.Define<float>(true, "Knockback", "Ranged Attack", 0.5f, Config.AcceptRange<float>(0f, 2f), "The percent of vanilla pushback force to apply with ranged attacks (Vanilla: 100%)\r\nBy default this is set to lower than 100% to make it feel weighty.\r\nOtherwise things get flinged around far to easily and feels weightless.\r\nNOTE: This is applied to both player and monster attacks.");
StringList val = new StringList();
((List<string>)val).Add("atgeir_secondary:1.0");
AttackAnim = Config.Define<StringList>(true, "Knockback", "Animation", val, "Comma separated list of animation names and the percent of pushback to apply for that animation.\r\nIf defined this will override the attack type specified from the other configs in this section.\r\nYou can view the animation names of different attacks by turning on debug mode in this mod's config options.\r\nWhen you attack you will see the animation name on the screen and in the log.");
AttackAnimValues = new Dictionary<string, float>();
Recoil = Config.Define<float>(true, "Knockback", "Recoil", 1f, Config.AcceptRange<float>(0f, 2f), "The recoil strength of certain weapons. (Vanilla: 100%)");
AttackAnim.SettingChanged += delegate
{
AttackAnimValues.Clear();
CultureInfo provider = new CultureInfo("en-US");
foreach (var (text, s) in IEnumerableExt.AsTuple<string, string>(AttackAnim.Value.ToDictionary(':')))
{
AttackAnimValues.Add(text.ToLower(), float.TryParse(s, NumberStyles.Float, provider, out var result) ? result : 1f);
}
};
}
}
private static float GetKnockback(Attack attack, float defaultValue)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
float value;
float num = (Configs.AttackAnimValues.TryGetValue(attack.m_attackAnimation.ToLower(), out value) ? value : defaultValue);
Log.Info((object)$"Attack: {attack.m_attackType}, Animation: {attack.m_attackAnimation}, Force: {num}", (ushort)0);
return num;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
[HarmonyPriority(700)]
private static void Attack_OnAttackTrigger(Attack __instance)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
__instance.m_recoilPushback *= Configs.Recoil.Value;
if (Log.IsEnabled)
{
((Character)Player.m_localPlayer).Message((MessageType)2, $"Attack: {__instance.m_attackType} - {__instance.m_attackAnimation}", 0, (Sprite)null);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Attack), "ProjectileAttackTriggered")]
[HarmonyPriority(700)]
private static void Pushback_Attack_ProjectileAttackTriggered(Attack __instance)
{
__instance.m_forceMultiplier *= GetKnockback(__instance, Configs.AttackRanged.Value);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Attack), "DoAreaAttack")]
[HarmonyPriority(700)]
private static void Pushback_Attack_DoAreaAttack(Attack __instance)
{
__instance.m_forceMultiplier *= GetKnockback(__instance, Configs.AttackArea.Value);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
[HarmonyPriority(700)]
private static void Pushback_Attack_DoMeleeAttack(Attack __instance)
{
__instance.m_forceMultiplier *= GetKnockback(__instance, Configs.AttackMelee.Value);
}
}
[HarmonyPatch]
internal static class Melee
{
private static class Configs
{
public static readonly ConfigEntry<bool> EnableSlopeCombat;
public static readonly ConfigEntry<bool> BlockTowardsLookDir;
public static readonly ConfigEntry<bool> NoStunParryRangedAttack;
static Configs()
{
NoStunParryRangedAttack = Config.Define<bool>(true, "Melee", "Parry Ranged Attacker - No Stun", true, "Parrying a ranged attack does not stun the attacker. That's just silly. (Vanilla : false)");
EnableSlopeCombat = Config.Define<bool>(true, "Melee", "Enable Slope Combat", true, "Attack targets on slopes above or below you.");
BlockTowardsLookDir = Config.Define<bool>(false, "Melee", "Block Towards Look Direction", true, "When the vanilla setting 'Attack towards look direction' is enabled this makes it also apply those rules for blocking. (Vanilla : false)");
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
private static void Attack_DoMeleeAttack(Attack __instance)
{
Humanoid character = __instance.m_character;
Player val = (Player)(object)((character is Player) ? character : null);
if (val != null && PlayerExt.Is(val, (Character)(object)Player.m_localPlayer) && Configs.EnableSlopeCombat.Value)
{
__instance.m_maxYAngle = 180f;
__instance.m_attackOffset = 0f;
__instance.m_attackHeight = 1f;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Player), "AlwaysRotateCamera")]
private static void Player_AlwaysRotateCamera(Character __instance, ref bool __result)
{
if (Configs.BlockTowardsLookDir.Value)
{
Player val = (Player)(object)((__instance is Player) ? __instance : null);
if (val != null && PlayerExt.Is(val, (Character)(object)Player.m_localPlayer) && ((Character)val).IsBlocking() && val.m_attackTowardsPlayerLookDir)
{
__result = false;
}
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(Humanoid), "BlockAttack")]
private static IEnumerable<CodeInstruction> Humanoid_BlockAttack(IEnumerable<CodeInstruction> instructions)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Expected O, but got Unknown
FieldInfo fieldInfo = AccessTools.Field(typeof(Character), "m_staggerWhenBlocked");
return new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[3]
{
new CodeMatch((OpCode?)OpCodes.Ldarg_2, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ldfld, (object)fieldInfo, (string)null),
new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null)
}).ThrowIfInvalid("Unable to match IL for disabling stagger when parry ranged attack").Advance(1)
.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
{
new CodeInstruction(OpCodes.Ldarg_1, (object)null)
})
.SetInstruction(CodeInstruction.Call(typeof(Melee), "Humanoid_BlockAttack_StaggerIntercept", (Type[])null, (Type[])null))
.InstructionEnumeration();
}
private static bool Humanoid_BlockAttack_StaggerIntercept(Character attacker, HitData hitData)
{
if (!Configs.NoStunParryRangedAttack.Value)
{
return attacker.m_staggerWhenBlocked;
}
if (attacker.m_staggerWhenBlocked)
{
return !hitData.m_ranged;
}
return false;
}
}
[HarmonyPatch]
internal static class AutoShield
{
private static class Configs
{
public static readonly ConfigEntry<bool> Autoequip;
static Configs()
{
Autoequip = Config.Define<bool>(false, "AutoShield", "Autoequip Recent Shield", true, "Automatically equip the recent shield when equipping main 1h weapon.\r\nPlus extra logic to make the torch behave nicely with auto shield.\r\nIntuitivly toggle weapons and shields and torches without needing to think about it to much.");
}
}
private const string RecentShieldDataKey = "ZenCombat|RecentShield";
private static ItemData? RecentShield
{
get
{
if (!Configs.Autoequip.Value)
{
return null;
}
string[] array = GeneralExtensions.GetValueSafe<string, string>(Player.m_localPlayer.m_customData, "ZenCombat|RecentShield")?.Split(new char[1] { '\t' });
(string PrefabName, int Variant, int Quality) saved = ((array != null && array.Length == 3) ? (array[0], int.Parse(array[1]), int.Parse(array[2])) : default((string, int, int)));
return ((IEnumerable<ItemData>)(from item in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems()
orderby item.m_quality descending
select item)).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => ItemDataExt.GetPrefabName(item) == saved.PrefabName && item.m_variant == saved.Variant && item.m_quality >= saved.Quality && item.m_worldLevel >= Game.m_worldLevel));
}
set
{
Dictionary<string, string> customData = Player.m_localPlayer.m_customData;
if (value == null)
{
customData.Remove("ZenCombat|RecentShield");
}
else
{
customData["ZenCombat|RecentShield"] = $"{ItemDataExt.GetPrefabName(value)}\t{value.m_variant}\t{value.m_quality}";
}
}
}
private static ItemData? GetBeltTorch(Humanoid humanoid)
{
if (!ItemDataExt.IsItemType(humanoid.m_hiddenLeftItem, (ItemType)15))
{
if (!ItemDataExt.IsItemType(humanoid.m_hiddenRightItem, (ItemType)15))
{
return null;
}
return humanoid.m_hiddenRightItem;
}
return humanoid.m_hiddenLeftItem;
}
private static void DebugItemPositions(Humanoid humanoid, ItemData item)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
if (Log.IsEnabled)
{
string value = new string('=', 73);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine(value);
stringBuilder.AppendFormat("{0,15} | {1,25} | {2,25} |\n", "POSITION", "TYPE", "NAME");
stringBuilder.AppendLine(value);
stringBuilder.AppendFormat("{0,15} | {1,25} | {2,25} |\n", "Equipping", ItemDataExt.GetItemType(item), ItemDataExt.GetName(item));
object arg = ItemDataExt.GetItemType(humanoid.LeftItem);
ItemData leftItem = humanoid.LeftItem;
stringBuilder.AppendFormat("{0,15} | {1,25} | {2,25} |\n", "Active Left", arg, (leftItem != null) ? ItemDataExt.GetName(leftItem) : null);
object arg2 = ItemDataExt.GetItemType(humanoid.m_hiddenLeftItem);
ItemData hiddenLeftItem = humanoid.m_hiddenLeftItem;
stringBuilder.AppendFormat("{0,15} | {1,25} | {2,25} |\n", "Hidden Left", arg2, (hiddenLeftItem != null) ? ItemDataExt.GetName(hiddenLeftItem) : null);
object arg3 = ItemDataExt.GetItemType(humanoid.RightItem);
ItemData rightItem = humanoid.RightItem;
stringBuilder.AppendFormat("{0,15} | {1,25} | {2,25} |\n", "Active Right", arg3, (rightItem != null) ? ItemDataExt.GetName(rightItem) : null);
object arg4 = ItemDataExt.GetItemType(humanoid.m_hiddenRightItem);
ItemData hiddenRightItem = humanoid.m_hiddenRightItem;
stringBuilder.AppendFormat("{0,15} | {1,25} | {2,25} |\n", "Hidden Right", arg4, (hiddenRightItem != null) ? ItemDataExt.GetName(hiddenRightItem) : null);
stringBuilder.AppendLine(value);
Log.Info((object)("\n" + stringBuilder), (ushort)0);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Humanoid), "EquipItem")]
private static void Humanoid_EquipItem_Prefix(Humanoid __instance, ItemData? item)
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Invalid comparison between Unknown and I4
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Invalid comparison between Unknown and I4
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Invalid comparison between Unknown and I4
Humanoid __instance2 = __instance;
if (!Configs.Autoequip.Value || item == null || (Object)(object)__instance2 != (Object)(object)Player.m_localPlayer || ((Character)__instance2).IsDead())
{
return;
}
DebugItemPositions(__instance2, item);
ItemData beltTorch = GetBeltTorch(__instance2);
ItemType itemType = ItemDataExt.GetItemType(item);
if ((int)itemType != 3)
{
if ((int)itemType != 5)
{
if ((int)itemType == 15 && ItemDataExt.IsItemType(__instance2.RightItem, (ItemType)3))
{
if (ItemDataExt.IsItemType(__instance2.LeftItem, (ItemType)5))
{
__instance2.UnequipItem(__instance2.LeftItem, false);
}
else if (ItemDataExt.IsItemType(__instance2.LeftItem, (ItemType)15) && __instance2.LeftItem != item)
{
__instance2.m_leftItem.m_equipped = false;
__instance2.m_leftItem = item;
__instance2.m_leftItem.m_equipped = true;
}
}
}
else if (beltTorch != null && IsHandAvail())
{
__instance2.m_rightItem = beltTorch;
__instance2.m_rightItem.m_equipped = true;
__instance2.m_hiddenLeftItem = null;
__instance2.m_hiddenRightItem = null;
}
}
else if (ItemDataExt.IsItemType(__instance2.RightItem, (ItemType)15))
{
__instance2.UnequipItem(__instance2.LeftItem, false);
}
else if (beltTorch != null && IsHandAvail())
{
__instance2.m_leftItem = beltTorch;
__instance2.m_leftItem.m_equipped = true;
__instance2.m_hiddenLeftItem = null;
__instance2.m_hiddenRightItem = null;
}
else if (ItemDataExt.IsItemType(__instance2.LeftItem, (ItemType)15))
{
if (__instance2.RightItem != null)
{
__instance2.m_rightItem.m_equipped = false;
}
__instance2.m_rightItem = __instance2.LeftItem;
__instance2.m_leftItem = null;
}
__instance2.SetupEquipment();
bool IsHandAvail()
{
if (__instance2.LeftItem != null)
{
return __instance2.RightItem == null;
}
return true;
}
}
private static void UpdateEquipped()
{
foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
{
allItem.m_equipped = ((Humanoid)Player.m_localPlayer).IsItemEquiped(allItem);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Humanoid), "EquipItem")]
private static void Humanoid_EquipItem_Postfix(Humanoid __instance, ItemData? item)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Invalid comparison between Unknown and I4
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Invalid comparison between Unknown and I4
if (!Configs.Autoequip.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || ((Character)__instance).IsDead())
{
return;
}
ItemType? val = item?.m_shared.m_itemType;
if (val.HasValue)
{
ItemType valueOrDefault = val.GetValueOrDefault();
if ((int)valueOrDefault != 3)
{
if ((int)valueOrDefault == 5)
{
RecentShield = item;
}
}
else if (__instance.LeftItem == null)
{
__instance.EquipItem(RecentShield, false);
}
}
Timing.EndOfFrame((MonoBehaviour)(object)__instance, (Action)UpdateEquipped);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
private static void Humanoid_UnequipItem(Humanoid __instance, ItemData? item)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Invalid comparison between Unknown and I4
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Invalid comparison between Unknown and I4
if (!Configs.Autoequip.Value || item == null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || ((Character)__instance).IsDead())
{
return;
}
ItemType itemType = item.m_shared.m_itemType;
if ((int)itemType != 3)
{
if ((int)itemType == 15 && ItemDataExt.IsItemType(__instance.RightItem, (ItemType)3))
{
__instance.EquipItem(RecentShield, false);
}
return;
}
if (ItemDataExt.IsItemType(__instance.LeftItem, (ItemType)15))
{
__instance.m_rightItem = __instance.m_leftItem;
__instance.m_leftItem = null;
__instance.SetupEquipment();
}
if (ItemDataExt.IsItemType(__instance.LeftItem, (ItemType)5) && !Object.op_Implicit((Object)(object)item.m_lastProjectile))
{
__instance.UnequipItem(__instance.LeftItem, false);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Player), "UseHotbarItem")]
private static void Player_UseHotbarItem(int index)
{
if (Configs.Autoequip.Value && ((Humanoid)Player.m_localPlayer).GetInventory().GetItemAt(index - 1, 0) == RecentShield)
{
RecentShield = null;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")]
private static void InventoryGui_OnRightClickItem(InventoryGrid grid, ItemData item)
{
if (Configs.Autoequip.Value && grid.GetInventory() == ((Humanoid)Player.m_localPlayer).GetInventory() && item == RecentShield)
{
RecentShield = null;
}
}
}
[HarmonyPatch]
internal static class Mounts
{
private enum Condition
{
NotAllowed,
NotEncumbered,
Allowed
}
private static class Configs
{
private const string SECTION_MOUNTS = "Mounts";
public static readonly ConfigEntry<float> AttackPrimaryStaminaDrain = Config.Define<float>(true, "Mounts", "Stamina Drain - Primary Attack", 10f, Config.AcceptRange<float>(0f, 250f), "Stamina drain of mounts when they perform their primary attack.");
public static readonly ConfigEntry<float> AttackSecondaryStaminaDrain = Config.Define<float>(true, "Mounts", "Stamina Drain - Secondary Attack", 25f, Config.AcceptRange<float>(0f, 250f), "Stamina drain of mounts when they perform their secondary attack.");
public static readonly ConfigEntry<Condition> CanJump = Config.Define<Condition>(true, "Mounts", "Can Jump", Condition.NotAllowed, "When enabled the player can directly control the mount's jump (Vanilla: false)\r\nNote: The mount must be sprinting before they can jump. \r\nThe vanilla animations are not designed for jumping mounts, they look odd.\r\nI think it looks bad and it breaks the gameplay somewhat, so it's disabled by default.");
public static readonly ConfigEntry<Condition> CanAttack = Config.Define<Condition>(true, "Mounts", "Can Attack", Condition.Allowed, "When enabled the player can directly control the mount's attack (Vanilla: false)\r\nControls:\r\n- Main Attack: Primary attack (if mount has an attack)\r\n- Secondary Attack:(if mount has 2 attacks)\r\n- Third Attack: Attack + Hold Block (if mount has 3 attacks)\r\nNOTE: Third attack stamina cost is the average of primary + secondary attacks");
public static readonly ConfigEntry<bool> DismountRoll = Config.Define<bool>(false, "Mounts", "Dismount Roll", true, "Press and hold in a direction while pressing the dismount key/button to do a rolling dismount.\r\nHold the dismount button without pressing in a direction to dismount without rolling.");
public static readonly ConfigEntry<KeyCode> DismountKey = Config.Define<KeyCode>(false, "Mounts", "Dismount Key", (KeyCode)308, $"Dedicated dismount button so that you can always dismount easily and intentionally when using other mods.\r\nGamepad is assigned {(object)(GamepadInput)6}\r\nNOTE: Set to None to disable this button and use vanilla behavior.\r\n[restart required for changes to take effect]");
}
[HarmonyPatch]
private static class SaddleAction
{
private struct InputState
{
public bool Jump;
public bool Attack;
public bool SecondaryAttack;
public Vector3 MoveDir;
}
private static InputState _input;
public static bool CheckForJumpOrAttack(bool jump, bool attack, bool secondaryAttack, bool dodge)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
_input.Jump = jump;
_input.Attack = attack;
_input.SecondaryAttack = secondaryAttack;
if ((int)Configs.DismountKey.Value == 0 || ((Character)Player.m_localPlayer).IsAttachedToShip())
{
return jump || attack || secondaryAttack || dodge;
}
bool flag = !UI.IsOpen && ZInput.GetButton(ActionString.op_Implicit(Dismount));
if (flag && Configs.DismountRoll.Value)
{
if (((Vector3)(ref _input.MoveDir)).magnitude > 0.1f)
{
DismountRoll(_input.MoveDir);
}
else if (ZInput.GetButtonPressedTimer(ActionString.op_Implicit(Dismount)) < 0.5f)
{
return false;
}
}
return flag;
}
private static void DismountRoll(Vector3 inputDir)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
Vector3 roll = ((Component)GameCamera.instance).transform.TransformDirection(inputDir);
Log.Info((object)$"Dismount: {roll}", (ushort)0);
Timing.NextFrame((MonoBehaviour)(object)Player.m_localPlayer, (Action)delegate
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
Player.m_localPlayer.m_queuedDodgeTimer = 0.5f;
Player.m_localPlayer.m_queuedDodgeDir = roll;
});
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Player), "SetDoodadControlls")]
private static void Player_SetDoodadControls(Vector3 moveDir)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
_input.MoveDir = moveDir;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Sadle), "FixedUpdate")]
private static void Saddle_FixedUpdate(Sadle __instance)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Invalid comparison between Unknown and I4
Humanoid val = (Humanoid)((BaseAI)__instance.m_monsterAI).m_character;
if (!Object.op_Implicit((Object)(object)val) || !__instance.m_character.IsTamed() || !__instance.IsLocalUser() || !((Character)val).IsOnGround() || ((Character)val).IsDead() || ((Character)val).InAttack() || ((Character)val).InDodge() || ((Character)val).IsKnockedBack() || ((Character)val).IsStaggering())
{
return;
}
bool flag = __instance.m_character.IsSwimming();
if (_input.Jump && IsAllowed(Configs.CanJump.Value))
{
float num = 2f * __instance.m_runStaminaDrain;
if ((int)__instance.m_speed == 2 && _input.Jump && __instance.HaveStamina(num) && !flag)
{
__instance.UseStamina(num);
__instance.m_character.Jump(false);
}
}
if ((_input.Attack || _input.SecondaryAttack) && IsAllowed(Configs.CanAttack.Value))
{
float value = Configs.AttackPrimaryStaminaDrain.Value;
float value2 = Configs.AttackSecondaryStaminaDrain.Value;
float num2 = (value + value2) / 2f;
List<ItemData> allItems = val.GetInventory().GetAllItems();
if (_input.Attack && allItems.Count > 0)
{
bool flag2 = ZInput.GetButton("Block") || ZInput.GetButton("JoyBlock");
float num3 = value;
ItemData val2 = allItems[0];
if (allItems.Count > 2 && flag2 && !flag)
{
val2 = allItems[2];
num3 = num2;
}
val.EquipItem(val2, true);
if (__instance.HaveStamina(num3) && __instance.m_monsterAI.DoAttack((Character)null, false))
{
__instance.UseStamina(num3);
}
}
else if (_input.SecondaryAttack && allItems.Count > 1 && !flag)
{
val.EquipItem(allItems[1], true);
if (__instance.HaveStamina(value2) && __instance.m_monsterAI.DoAttack((Character)null, false))
{
__instance.UseStamina(value2);
}
}
}
_input = default(InputState);
}
}
private static readonly ActionString Dismount = new ActionString("Dismount", "Dismount", true);
public static void SetupInputs()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
if ((int)Configs.DismountKey.Value != 0)
{
Dismount.AddButton(Configs.DismountKey.Value, false, false, false, 0f, 0f);
Dismount.AddButton((GamepadInput)6, false, false, false, 0f, 0f);
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(Player), "SetControls")]
private static IEnumerable<CodeInstruction> Player_SetControls_Transpile(IEnumerable<CodeInstruction> instructions)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Expected O, but got Unknown
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Expected O, but got Unknown
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Expected O, but got Unknown
return new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[8]
{
new CodeMatch((OpCode?)OpCodes.Ldarg_S, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ldarg_2, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Or, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ldarg_S, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Or, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ldarg_S, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Or, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null)
}).ThrowIfInvalid("Unable to find IL match").Advance(2)
.SetAndAdvance(OpCodes.Nop, (object)null)
.Advance(1)
.SetAndAdvance(OpCodes.Nop, (object)null)
.Advance(1)
.SetInstruction(CodeInstruction.Call(typeof(SaddleAction), "CheckForJumpOrAttack", (Type[])null, (Type[])null))
.InstructionEnumeration();
}
private static bool IsAllowed(Condition condition)
{
return condition switch
{
Condition.NotAllowed => false,
Condition.NotEncumbered => !IsEncumbered(),
Condition.Allowed => true,
_ => throw new ArgumentOutOfRangeException("condition", condition, "Invalid condition rule"),
};
}
private static bool IsEncumbered()
{
if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !((Character)Player.m_localPlayer).IsEncumbered())
{
return false;
}
((Character)Player.m_localPlayer).Message((MessageType)2, "$se_encumbered_repeat", 0, (Sprite)null);
return true;
}
}
[HarmonyPatch]
internal static class RemapDodge
{
internal static class Configs
{
public static readonly ConfigEntry<bool> RemapDodgeButton;
public static readonly ConfigEntry<KeyCode> KeyboardDodgeButton;
static Configs()
{
RemapDodgeButton = Config.Define<bool>(false, "Dodge", "Separate Jump/Dodge Buttons", true, "Dodge becomes a separate button from jump, you no longer need to hold block to dodge.\r\nKeyboard: Define the custom key using the config option below.\r\nGamepad: A or B depending on selected controller layout. (Interact is moved to X)\r\nNote: When using gamepad you need to restart the game for all control mapping to take effect.");
RemapDodgeButton.SettingChanged += delegate
{
((ZenMod)ZenMod<Plugin>.Instance).RefreshInputs();
};
KeyboardDodgeButton = Config.Define<KeyCode>(false, "Dodge", "Keyboard Dodge Button", (KeyCode)308, "Keyboard: Dedicated dodge button for keyboard.");
}
}
[HarmonyPatch]
private static class HandleKeyboardDodgeButton
{
[HarmonyPatch(typeof(Player), "SetControls")]
private static class PlayerSetControls
{
[UsedImplicitly]
private static void Prefix(Player __instance, ref bool jump)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
if (Configs.RemapDodgeButton.Value && !ZInput.IsGamepadActive() && !((Character)__instance).IsSitting() && !jump && (!__instance.IsDodging() || Quickstep.IsDoubleTap()) && ZInput.GetKey(Configs.KeyboardDodgeButton.Value, true))
{
jump = true;
_isDodging = true;
}
}
[UsedImplicitly]
private static void Postfix()
{
_isDodging = false;
}
}
private static bool _isDodging;
[HarmonyPrefix]
[HarmonyPatch(typeof(Character), "Jump")]
private static void Character_Jump(Player __instance, ref bool __runOriginal)
{
if (Configs.RemapDodgeButton.Value && !ZInput.IsGamepadActive() && _isDodging)
{
__runOriginal = false;
InvokeDodge(__instance);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Player), "Dodge")]
private static void Player_Dodge(Player __instance, Vector3 dodgeDir, ref bool __runOriginal)
{
if (Configs.RemapDodgeButton.Value && !ZInput.IsGamepadActive() && !_isDodging)
{
__runOriginal = false;
((Character)__instance).Jump(false);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(KeyHints), "Awake")]
private static void KeyHints_Awake(KeyHints __instance)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
if (Configs.RemapDodgeButton.Value)
{
Transform obj = __instance.m_combatHints.transform.Find("Keyboard/Dodge");
TextMeshProUGUI component = ((Component)obj.Find("key_bkg/Key")).GetComponent<TextMeshProUGUI>();
KeyCode value = Configs.KeyboardDodgeButton.Value;
((TMP_Text)component).text = ((object)(KeyCode)(ref value)).ToString();
((Component)obj.GetChild(2)).gameObject.SetActive(false);
((Component)obj.GetChild(3)).gameObject.SetActive(false);
}
}
}
[CompilerGenerated]
private sealed class <Transpile_KeyHints_SetGamePadBindings>d__9 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
{
private int <>1__state;
private CodeInstruction <>2__current;
private int <>l__initialThreadId;
private IEnumerable<CodeInstruction> instructions;
public IEnumerable<CodeInstruction> <>3__instructions;
private IEnumerator<CodeInstruction> <>7__wrap1;
CodeInstruction IEnumerator<CodeInstruction>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Transpile_KeyHints_SetGamePadBindings>d__9(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<>7__wrap1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
try
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>7__wrap1 = instructions.GetEnumerator();
<>1__state = -3;
break;
case 1:
<>1__state = -3;
break;
}
if (<>7__wrap1.MoveNext())
{
CodeInstruction current = <>7__wrap1.Current;
if (current.opcode == OpCodes.Ldstr && current.operand as string == "$hud_buildmenu <mspace=0.6em>$KEY_Use</mspace>")
{
current.operand = "$hud_buildmenu <mspace=0.6em>$KEY_BuildMenu</mspace>";
}
<>2__current = current;
<>1__state = 1;
return true;
}
<>m__Finally1();
<>7__wrap1 = null;
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<>7__wrap1 != null)
{
<>7__wrap1.Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
{
<Transpile_KeyHints_SetGamePadBindings>d__9 <Transpile_KeyHints_SetGamePadBindings>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<Transpile_KeyHints_SetGamePadBindings>d__ = this;
}
else
{
<Transpile_KeyHints_SetGamePadBindings>d__ = new <Transpile_KeyHints_SetGamePadBindings>d__9(0);
}
<Transpile_KeyHints_SetGamePadBindings>d__.instructions = <>3__instructions;
return <Transpile_KeyHints_SetGamePadBindings>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
}
}
[CompilerGenerated]
private sealed class <Transpile_Player_UpdateBuildGuiInput>d__8 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
{
private int <>1__state;
private CodeInstruction <>2__current;
private int <>l__initialThreadId;
private IEnumerable<CodeInstruction> instructions;
public IEnumerable<CodeInstruction> <>3__instructions;
private IEnumerator<CodeInstruction> <>7__wrap1;
CodeInstruction IEnumerator<CodeInstruction>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Transpile_Player_UpdateBuildGuiInput>d__8(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<>7__wrap1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
try
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>7__wrap1 = instructions.GetEnumerator();
<>1__state = -3;
break;
case 1:
<>1__state = -3;
break;
}
if (<>7__wrap1.MoveNext())
{
CodeInstruction current = <>7__wrap1.Current;
if (current.opcode == OpCodes.Ldstr && current.operand as string == "JoyUse")
{
current.operand = "JoyBuildMenu";
}
<>2__current = current;
<>1__state = 1;
return true;
}
<>m__Finally1();
<>7__wrap1 = null;
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<>7__wrap1 != null)
{
<>7__wrap1.Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
{
<Transpile_Player_UpdateBuildGuiInput>d__8 <Transpile_Player_UpdateBuildGuiInput>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<Transpile_Player_UpdateBuildGuiInput>d__ = this;
}
else
{
<Transpile_Player_UpdateBuildGuiInput>d__ = new <Transpile_Player_UpdateBuildGuiInput>d__8(0);
}
<Transpile_Player_UpdateBuildGuiInput>d__.instructions = <>3__instructions;
return <Transpile_Player_UpdateBuildGuiInput>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
}
}
private static bool IsDodging(this Player player)
{
if (!(player.m_queuedDodgeTimer > 0f))
{
return ((Character)player).InDodge();
}
return true;
}
private static void InvokeDodge(Player player)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
Vector3 moveDir = ((Character)player).m_moveDir;
if (((Vector3)(ref moveDir)).magnitude >= 0.1f)
{
player.Dodge(((Vector3)(ref moveDir)).normalized);
}
}
internal static void RemapGamepad()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
if (Configs.RemapDodgeButton.Value)
{
GamepadInput val;
if ((int)ZInput.InputLayout == 0)
{
val = (GamepadInput)5;
ZInputExt.RemapTo(ZInput.instance.GetButtonDef("JoyUse"), (GamepadInput)7, (bool?)null, (bool?)null, (bool?)null, (float?)null, (float?)null);
}
else
{
val = (GamepadInput)6;
}
ZInputExt.RemapTo(ZInput.instance.GetButtonDef("JoyDodge"), val, (bool?)false, (bool?)null, (bool?)null, (float?)null, (float?)null);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(KeyHints), "SetGamePadBindings")]
private static void KeyHints_SetGamePadBindings()
{
if (Configs.RemapDodgeButton.Value)
{
TextMeshProUGUI dodgeKey = KeyHints.instance.m_dodgeKey;
Localization.instance.RemoveTextFromCache((TMP_Text)(object)dodgeKey);
((TMP_Text)dodgeKey).text = "$settings_dodge <mspace=0.6em>$KEY_JoyDodge</mspace>";
Localization.instance.Localize(((TMP_Text)dodgeKey).transform);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Player), "FixedUpdate")]
private static void RemapDodge_CheckForInput_Player_FixedUpdate(Player __instance)
{
if (Configs.RemapDodgeButton.Value && ZInput.IsGamepadActive() && ZInput.GetButton("JoyDodge") && !UI.IsOpen && PlayerExt.Is(__instance, (Character)(object)Player.m_localPlayer) && (!__instance.IsDodging() || Quickstep.IsDoubleTap()))
{
InvokeDodge(__instance);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Player), "Dodge")]
private static void RemapDodge_FixClassicJump_Player_Dodge(Player __instance, ref bool __runOriginal)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
if (Configs.RemapDodgeButton.Value && (int)ZInput.InputLayout == 0 && ZInput.IsGamepadActive() && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ZInput.GetButton("JoyButtonB"))
{
__runOriginal = false;
((Character)__instance).Jump(false);
}
}
[IteratorStateMachine(typeof(<Transpile_Player_UpdateBuildGuiInput>d__8))]
[HarmonyTranspiler]
[HarmonyPatch(typeof(Player), "UpdateBuildGuiInput")]
public static IEnumerable<CodeInstruction> Transpile_Player_UpdateBuildGuiInput(IEnumerable<CodeInstruction> instructions)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Transpile_Player_UpdateBuildGuiInput>d__8(-2)
{
<>3__instructions = instructions
};
}
[IteratorStateMachine(typeof(<Transpile_KeyHints_SetGamePadBindings>d__9))]
[HarmonyTranspiler]
[HarmonyPatch(typeof(KeyHints), "SetGamePadBindings")]
public static IEnumerable<CodeInstruction> Transpile_KeyHints_SetGamePadBindings(IEnumerable<CodeInstruction> instructions)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Transpile_KeyHints_SetGamePadBindings>d__9(-2)
{
<>3__instructions = instructions
};
}
}
}
namespace ZenCombat.Compatibility
{
internal static class Quickstep
{
private const string QuickstepPluginID = "shudnal.Quickstep";
private static bool? _isLoaded;
private static bool IsLoaded
{
get
{
bool valueOrDefault = _isLoaded.GetValueOrDefault();
if (!_isLoaded.HasValue)
{
valueOrDefault = Chainloader.PluginInfos.ContainsKey("shudnal.Quickstep");
_isLoaded = valueOrDefault;
return valueOrDefault;
}
return valueOrDefault;
}
}
public static bool IsDoubleTap()
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
if (!IsLoaded)
{
return false;
}
if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
return false;
}
bool flag = (ZInput.IsGamepadActive() ? ZInput.GetButtonDown("JoyDodge") : ZInput.GetKeyDown(RemapDodge.Configs.KeyboardDodgeButton.Value, true));
return ((Character)Player.m_localPlayer).InDodge() && flag;
}
}
}