using System;
using System.Collections.Generic;
using System.Diagnostics;
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 BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Zen.Config;
using Zen.Lib;
using Zen.Logging;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenPath")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenPath")]
[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 ZenPath
{
public static class Configs
{
public static readonly ConfigEntry<float> StaminaDrainPath;
public static readonly ConfigEntry<float> StaminaDrainPaved;
public static readonly ConfigEntry<bool> ShowStatusIcon;
public static readonly ConfigEntry<string> LabelPath;
public static readonly ConfigEntry<string> LabelPaved;
static Configs()
{
StaminaDrainPath = Config.Define<float>(true, "General", "Stamina Usage Path", 0.5f, Config.AcceptRange<float>(0f, 1f), "The percent stamina drain when running on dirt, wood, or metal");
StaminaDrainPaved = Config.Define<float>(true, "General", "Stamina Usage Paved", 0f, Config.AcceptRange<float>(0f, 1f), "The percent stamina drain when running on a paved surface or stone.");
ShowStatusIcon = Config.Define<bool>(true, "General", "Show Status Icon", true, "Display the status effect icon when in buff is active");
LabelPath = Config.Define<string>(false, "Translation", "Label Path", "Path", "Text to display when runninng on a dirt, wooden, or metal surface");
LabelPaved = Config.Define<string>(false, "Translation", "Label Paved", "$piece_pavedroad", "Text to display when runninng on a paved road or stone surface");
}
}
public static class HeightmapExt
{
public static Color GetPaintMask(this Heightmap heightmap, Vector3 worldPos)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
worldPos.x -= 0.5f;
worldPos.z -= 0.5f;
int num = default(int);
int num2 = default(int);
heightmap.WorldToVertex(worldPos, ref num, ref num2);
return heightmap.GetPaintMask(num, num2);
}
public static bool IsPaintMaskOf(this Color color, Color mask)
{
//IL_0000: 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_0014: 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)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
if (color.r >= mask.r * 0.5f && color.g >= mask.g * 0.5f)
{
return color.b >= mask.b * 0.5f;
}
return false;
}
public static bool IsDirt(this Heightmap heightmap, Vector3 worldPos)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
return heightmap.GetPaintMask(worldPos).IsPaintMaskOf(Heightmap.m_paintMaskDirt);
}
public static bool IsPaved(this Heightmap heightmap, Vector3 worldPos)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
return heightmap.GetPaintMask(worldPos).IsPaintMaskOf(Heightmap.m_paintMaskPaved);
}
}
[HarmonyPatch]
public static class PathDetect
{
public static MotionType MotionType { get; private set; }
public static GroundMaterial GroundMaterial { get; private set; }
public static PathType PathType { get; private set; }
public static bool IsRunning
{
get
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//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)
//IL_0008: Invalid comparison between Unknown and I4
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Invalid comparison between Unknown and I4
MotionType motionType = MotionType;
if ((int)motionType == 2 || (int)motionType == 8)
{
return true;
}
return false;
}
}
public static bool IsOnPath => PathType != PathType.None;
private static Player LocalPlayer => Player.m_localPlayer;
private static PathType GetPathType(Collider? collider, Vector3 worldPos)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//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)
//IL_0009: Invalid comparison between Unknown and I4
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Invalid comparison between Unknown and I4
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Invalid comparison between Unknown and I4
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Invalid comparison between Unknown and I4
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Invalid comparison between Unknown and I4
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Invalid comparison between Unknown and I4
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected I4, but got Unknown
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Invalid comparison between Unknown and I4
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Invalid comparison between Unknown and I4
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Invalid comparison between Unknown and I4
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Invalid comparison between Unknown and I4
//IL_0099: 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_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
GroundMaterial groundMaterial = GroundMaterial;
if ((int)groundMaterial <= 64)
{
if ((int)groundMaterial <= 16)
{
switch ((int)groundMaterial)
{
default:
if ((int)groundMaterial == 16)
{
break;
}
goto IL_007d;
case 0:
case 2:
break;
case 8:
goto IL_0079;
case 4:
return PathType.PavedPath;
case 1:
case 3:
case 5:
case 6:
case 7:
goto IL_007d;
}
goto IL_0077;
}
if ((int)groundMaterial != 32 && (int)groundMaterial == 64)
{
}
}
else if ((int)groundMaterial <= 256)
{
if ((int)groundMaterial != 128 && (int)groundMaterial == 256)
{
goto IL_0079;
}
}
else if ((int)groundMaterial == 512 || (int)groundMaterial == 2048)
{
goto IL_0077;
}
goto IL_007d;
IL_0077:
return PathType.None;
IL_0079:
return PathType.SimplePath;
IL_007d:
if (!Object.op_Implicit((Object)(object)collider))
{
return PathType.None;
}
Heightmap component = ((Component)collider).GetComponent<Heightmap>();
if (!Object.op_Implicit((Object)(object)component))
{
return PathType.None;
}
Color paintMask = component.GetPaintMask(worldPos);
if (paintMask.IsPaintMaskOf(Heightmap.m_paintMaskDirt))
{
return PathType.SimplePath;
}
if (paintMask.IsPaintMaskOf(Heightmap.m_paintMaskPaved))
{
return PathType.PavedPath;
}
return PathType.None;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FootStep), "OnFoot", new Type[] { typeof(Transform) })]
private static void FootStep_OnFoot(FootStep __instance)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
Log.Info((object)$"GroundType: {GroundMaterial}, MotionType: {MotionType}, PathType: {PathType}", (ushort)0);
PathEffect.UpdateStep();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FootStep), "GetMotionType")]
private static void FootStep_GetMotionType(Character character, ref MotionType __result)
{
if (PlayerExt.Is(LocalPlayer, character))
{
MotionType = __result;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FootStep), "GetGroundMaterial")]
private static void FootStep_GetGroundMaterial(Character character, Vector3 point, ref GroundMaterial __result)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if (PlayerExt.Is(LocalPlayer, character))
{
GroundMaterial = __result;
PathType = GetPathType(character.GetLastGroundCollider(), point);
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(FootStep), "GetGroundMaterial")]
private static IEnumerable<CodeInstruction> Transpile_FootStep_GetGroundMaterial_Ashlands(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
Label jumpTarget = CodeInstructionExtensions.WithLabels(instructions.First((CodeInstruction code) => code.opcode == OpCodes.Ldc_I4_4), new Label[1] { generator.DefineLabel() }).labels.Last();
foreach (CodeInstruction instruction in instructions)
{
if (instruction.opcode == OpCodes.Switch)
{
List<Label> list = ((Label[])instruction.operand).ToList();
list.Add(jumpTarget);
yield return new CodeInstruction(OpCodes.Switch, (object)list.ToArray());
}
else
{
yield return instruction;
}
}
}
}
public enum PathType
{
None,
SimplePath,
PavedPath
}
[BepInPlugin("ZenDragon.ZenPath", "ZenPath", "0.2.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class Plugin : ZenMod<Plugin>
{
public const string PluginName = "ZenPath";
public const string PluginVersion = "0.2.3";
public const string PluginGUID = "ZenDragon.ZenPath";
protected override void Setup()
{
}
protected override void TitleScene(bool isFirstBoot)
{
}
protected override void WorldStart()
{
PathEffect.Init();
}
private void Update()
{
PathEffect.CheckPath();
}
protected override void Shutdown()
{
PathEffect.Cleanup();
}
}
public static class PathEffect
{
private class Effect : StatusEffect
{
private readonly Sprite _icon = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("CorpseRun")).m_icon;
private PathType _pathType;
private Effect()
{
((Object)this).name = "SE_ZenPath";
}
public override void ModifyRunStaminaDrain(float baseDrain, ref float drain, Vector3 dir)
{
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
if (PathDetect.IsOnPath)
{
_pathType = PathDetect.PathType;
float value;
switch (_pathType)
{
case PathType.SimplePath:
value = Configs.StaminaDrainPath.Value;
base.m_name = StringExt.Localize(Configs.LabelPath.Value);
break;
case PathType.PavedPath:
value = Configs.StaminaDrainPaved.Value;
base.m_name = StringExt.Localize(Configs.LabelPaved.Value);
break;
case PathType.None:
Log.Info((object)"No path detected, not applying stamina drain", (ushort)0);
return;
default:
throw new ArgumentOutOfRangeException("_pathType");
}
drain = baseDrain * Math.Max(value, 0.001f);
base.m_tooltip = StringExt.Localize($"$se_runstamina {value * 100f}%");
base.m_icon = (Configs.ShowStatusIcon.Value ? _icon : null);
if (PlayerExt.IsReady(LocalPlayer) && PathDetect.IsRunning)
{
Log.Info((object)$"Stamina Drain: {value}\tPathType: {_pathType} : {PathDetect.GroundMaterial}", (ushort)0);
}
}
}
}
private static Effect _buff;
private const float Cooldown = 1f;
private static float _activationTime;
private static Player LocalPlayer => Player.m_localPlayer;
private static bool IsExpired => Time.time >= _activationTime + 1f;
private static bool IsRunningOnPath
{
get
{
if (PathDetect.IsRunning)
{
return PathDetect.IsOnPath;
}
return false;
}
}
public static void Init()
{
_buff = ScriptableObject.CreateInstance<Effect>();
ObjectDB.instance.m_StatusEffects.Add((StatusEffect)(object)_buff);
}
public static void Cleanup()
{
if (Object.op_Implicit((Object)(object)ObjectDB.instance))
{
ObjectDB.instance.m_StatusEffects.Remove((StatusEffect)(object)_buff);
}
}
public static void UpdateStep()
{
if (PlayerExt.IsReady(LocalPlayer) && IsRunningOnPath)
{
ApplyBuff();
}
}
private static void ApplyBuff()
{
if (IsExpired)
{
((Character)LocalPlayer).GetSEMan().AddStatusEffect((StatusEffect)(object)_buff, false, 0, 0f);
}
_activationTime = Time.time;
}
private static void RemoveBuff()
{
if (Object.op_Implicit((Object)(object)_buff) && PlayerExt.IsReady(LocalPlayer))
{
((Character)LocalPlayer).GetSEMan().RemoveStatusEffect((StatusEffect)(object)_buff, false);
}
}
public static void CheckPath()
{
if (IsExpired && !IsRunningOnPath)
{
RemoveBuff();
}
}
}
}