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;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using Microsoft.CodeAnalysis;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MoreEmotesPatch + BetterEmotes Support")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MoreEmotesPatch + BetterEmotes Support")]
[assembly: AssemblyCopyright("Copyright © RtPoogle 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f985f2ab-4c3b-4066-aa78-fe8865941283")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
internal IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}
namespace MoreEmotesPatch
{
internal static class Extensions
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
internal class HarmonyPatchCategory : Attribute
{
public string Category { get; }
public HarmonyPatchCategory(string category)
{
Category = category;
base..ctor();
}
}
public static int CurrentTime => (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
public static T _get<T>(Type type, string pof)
{
return (T)AccessTools.Property(type, pof).GetValue(null);
}
public static bool StopAnyEmotes(PlayerControllerB __instance)
{
__instance.performingEmote = false;
__instance.StopPerformingEmoteServerRpc();
__instance.timeSinceStartingEmote = 0f;
return false;
}
public static void PatchCategory(this Harmony harmony, string category)
{
CollectionExtensions.DoIf<PatchClassProcessor>((IEnumerable<PatchClassProcessor>)((IEnumerable<Type>)AccessTools.GetTypesFromAssembly(new StackTrace().GetFrame(1).GetMethod().ReflectedType.Assembly)).Select((Func<Type, PatchClassProcessor>)harmony.CreateClassProcessor).ToArray(), (Func<PatchClassProcessor, bool>)((PatchClassProcessor patchClass) => ((HarmonyPatchCategory)patchClass.containerType.GetCustomAttribute(typeof(HarmonyPatchCategory), inherit: true))?.Category == category), (Action<PatchClassProcessor>)delegate(PatchClassProcessor patchClass)
{
patchClass.Patch();
});
}
public static void PatchAllUncategorized(this Harmony harmony)
{
CollectionExtensions.DoIf<PatchClassProcessor>((IEnumerable<PatchClassProcessor>)((IEnumerable<Type>)AccessTools.GetTypesFromAssembly(new StackTrace().GetFrame(1).GetMethod().ReflectedType.Assembly)).Select((Func<Type, PatchClassProcessor>)harmony.CreateClassProcessor).ToArray(), (Func<PatchClassProcessor, bool>)((PatchClassProcessor patchClass) => string.IsNullOrEmpty(((HarmonyPatchCategory)patchClass.containerType.GetCustomAttribute(typeof(HarmonyPatchCategory), inherit: true))?.Category)), (Action<PatchClassProcessor>)delegate(PatchClassProcessor patchClass)
{
patchClass.Patch();
});
}
}
internal class Log
{
private static bool Dbg;
private static ManualLogSource Src;
public Log(ManualLogSource logSrc, bool debug = false)
{
Src = logSrc;
Dbg = debug;
}
public static void Info(object message)
{
ManualLogSource src = Src;
if (src != null)
{
src.LogInfo(message);
}
}
public static void Warn(object message)
{
ManualLogSource src = Src;
if (src != null)
{
src.LogWarning(message);
}
}
public static void Error(object message)
{
ManualLogSource src = Src;
if (src != null)
{
src.LogError(message);
}
}
public static void Debug(object message)
{
if (Dbg)
{
ManualLogSource src = Src;
if (src != null)
{
src.LogDebug(message);
}
}
}
}
[BepInPlugin("xyz.poogle.moreemotespatch", "More Emotes Patch", "1.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class MoreEmotesPatchPlugin : BaseUnityPlugin
{
private enum InitType
{
None,
BetterEmotes,
MoreEmotes,
Both
}
private static InitType init_mode = InitType.None;
private readonly Harmony harmony = new Harmony("xyz.poogle.moreemotespatch");
public const string GUID = "xyz.poogle.moreemotespatch";
public const string NAME = "More Emotes Patch";
public const string VER = "1.1.0";
internal static ConfigEntry<int> maxEmoteTime;
internal static Type BE_emoteDefs = AccessTools.TypeByName("BetterEmote.Utils.EmoteDefs");
internal static Type BE_emotes = AccessTools.TypeByName("BetterEmote.Utils.Emote");
internal static Type BE_doubleEmotes = AccessTools.TypeByName("BetterEmote.Utils.DoubleEmote");
internal static Type BE_altEmotes = AccessTools.TypeByName("BetterEmote.Utils.AltEmote");
internal static Type ME_emotePatch = AccessTools.TypeByName("MoreEmotes.Patch.EmotePatch");
internal static Type ME_emotes = AccessTools.TypeByName("MoreEmotes.Patch.Emotes");
private void Awake()
{
//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)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
//IL_0057: Expected O, but got Unknown
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Expected O, but got Unknown
new Log(Logger.CreateLogSource("xyz.poogle.moreemotespatch"), debug: true);
maxEmoteTime = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxEmoteTime", 30, "The max time for any emote to last before auto cancelled in seconds.\n(0 will never cancel.)");
ConfigEntry<int> obj = maxEmoteTime;
IntSliderOptions val = new IntSliderOptions
{
RequiresRestart = false
};
((BaseRangeOptions<int>)val).Min = 0;
((BaseRangeOptions<int>)val).Max = 120;
LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(obj, val));
if (BE_emoteDefs != null && BE_emotes != null && BE_doubleEmotes != null && BE_altEmotes != null)
{
Log.Warn("Found BetterEmotes for patching!");
if (Harmony.HasAnyPatches("BetterEmotes"))
{
init_mode |= InitType.BetterEmotes;
BE_Patches.InitPatches(harmony);
}
else
{
Log.Warn("BetterEmotes doesn't have a harmony instance to patch.");
}
}
if (ME_emotes != null && ME_emotePatch != null)
{
Log.Warn("Using legacy MoreEmotes patch, you should switch to BetterEmotes!");
if (Harmony.HasAnyPatches("MoreEmotes"))
{
init_mode |= InitType.MoreEmotes;
ME_Patches.InitPatches(harmony);
}
else
{
Log.Warn("MoreEmotes doesn't have a harmony instance to patch.");
}
}
if (init_mode != 0)
{
Log.Info($"We have initialized with patches: {init_mode}");
}
else
{
Log.Error("Could not initialize as no compatible mod was found.");
}
}
}
internal class Common_Patches
{
[HarmonyPatch(typeof(PlayerControllerB))]
[HarmonyPatch("CheckConditionsForEmote")]
public static class PlayerControllerB_CheckConditionsForEmote_Patch
{
[HarmonyPriority(0)]
public static void Postfix(PlayerControllerB __instance, ref bool __result)
{
__result = !__instance.inSpecialInteractAnimation && !__instance.isPlayerDead && !__instance.isCrouching && !__instance.isClimbingLadder && !__instance.inTerminalMenu;
}
}
}
internal class BE_Patches
{
[HarmonyPatch(typeof(PlayerControllerB))]
[HarmonyPatch("PerformEmote")]
[Extensions.HarmonyPatchCategory("BetterEmotes")]
public static class PlayerControllerB_PerformEmote_Patch
{
[HarmonyPriority(800)]
public static bool Prefix(PlayerControllerB __instance, int emoteID)
{
int integer = __instance.playerBodyAnimator.GetInteger("emoteNumber");
if (__instance.performingEmote)
{
if (BE_Doubles.Contains(emoteID))
{
if (integer == emoteID + BE_Offset)
{
return Extensions.StopAnyEmotes(__instance);
}
return true;
}
if (integer == emoteID)
{
return Extensions.StopAnyEmotes(__instance);
}
}
LastEmoteTime = Extensions.CurrentTime;
return true;
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
[HarmonyPatch("Update")]
[Extensions.HarmonyPatchCategory("BetterEmotes")]
public static class PlayerControllerB_Update_Patch
{
[HarmonyPriority(800)]
public static bool Prefix(PlayerControllerB __instance)
{
if (MoreEmotesPatchPlugin.maxEmoteTime.Value > 0 && __instance.performingEmote)
{
if (__instance.playerBodyAnimator.GetInteger("emoteNumber") != (int)Enum.Parse(MoreEmotesPatchPlugin.BE_emotes, "Sign") && LastEmoteTime != -1 && Extensions.CurrentTime - LastEmoteTime > MoreEmotesPatchPlugin.maxEmoteTime.Value)
{
Extensions.StopAnyEmotes(__instance);
}
if (!__instance.CheckConditionsForEmote())
{
Extensions.StopAnyEmotes(__instance);
}
}
return true;
}
}
private static int LastEmoteTime = -1;
internal static int BE_Offset = ((int[])Enum.GetValues(MoreEmotesPatchPlugin.BE_doubleEmotes))[0] - (int)AccessTools.Method(MoreEmotesPatchPlugin.BE_emoteDefs, "normalizeEmoteNumber", (Type[])null, (Type[])null).Invoke(null, new object[1] { ((int[])Enum.GetValues(MoreEmotesPatchPlugin.BE_doubleEmotes))[0] });
internal static int[] BE_Doubles = (from x in CollectionExtensions.AddRangeToArray<int>((int[])Enum.GetValues(MoreEmotesPatchPlugin.BE_doubleEmotes), (int[])Enum.GetValues(MoreEmotesPatchPlugin.BE_altEmotes))
select x - BE_Offset).ToArray();
internal static void InitPatches(Harmony harmony)
{
harmony.PatchAllUncategorized();
harmony.PatchCategory("BetterEmotes");
}
}
internal class ME_Patches
{
[HarmonyPatch]
[Extensions.HarmonyPatchCategory("MoreEmotes")]
public static class MoreEmotes_EmotePatch_CheckEmoteInput_Patch
{
private static MethodBase TargetMethod()
{
return MoreEmotesPatchPlugin.ME_emotePatch.GetMethod("CheckEmoteInput", AccessTools.all);
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator il)
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Expected O, but got Unknown
Log.Info("Patching CheckEmoteInput!");
MethodInfo methodInfo = AccessTools.Method(typeof(InputControlExtensions), "IsPressed", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = AccessTools.PropertyGetter(typeof(ButtonControl), "wasPressedThisFrame");
List<CodeInstruction> list = new List<CodeInstruction>(instructions);
for (int i = 0; i < list.Count - 1; i++)
{
if (list[i].opcode == OpCodes.Ldc_R4 && (float)list[i].operand == 0f && CodeInstructionExtensions.Calls(list[i + 1], methodInfo))
{
list[i] = new CodeInstruction(OpCodes.Castclass, (object)typeof(ButtonControl));
list[i + 1] = new CodeInstruction(OpCodes.Callvirt, (object)methodInfo2);
Log.Info("Patched CheckEmoteInput!");
return list;
}
}
Log.Error("Could not find IL to transpile, bailing patch!");
return list;
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
[HarmonyPatch("PerformEmote")]
[Extensions.HarmonyPatchCategory("MoreEmotes")]
public static class PlayerControllerB_PerformEmote_Patch
{
[HarmonyPriority(800)]
public static bool Prefix(PlayerControllerB __instance, int emoteID)
{
int integer = __instance.playerBodyAnimator.GetInteger("emoteNumber");
if (__instance.performingEmote)
{
if (MO_Doubles.Contains(emoteID))
{
if (integer == emoteID + MO_Offset)
{
return Extensions.StopAnyEmotes(__instance);
}
return true;
}
if (integer == emoteID)
{
return Extensions.StopAnyEmotes(__instance);
}
}
LastEmoteTime = Extensions.CurrentTime;
return true;
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
[HarmonyPatch("Update")]
[Extensions.HarmonyPatchCategory("MoreEmotes")]
public static class PlayerControllerB_Update_Patch
{
[HarmonyPriority(800)]
public static bool Prefix(PlayerControllerB __instance)
{
if (MoreEmotesPatchPlugin.maxEmoteTime.Value > 0 && __instance.performingEmote)
{
if (__instance.playerBodyAnimator.GetInteger("emoteNumber") != (int)Enum.Parse(MoreEmotesPatchPlugin.ME_emotes, "Sign") && LastEmoteTime != -1 && Extensions.CurrentTime - LastEmoteTime > MoreEmotesPatchPlugin.maxEmoteTime.Value)
{
Extensions.StopAnyEmotes(__instance);
}
if (!__instance.CheckConditionsForEmote())
{
Extensions.StopAnyEmotes(__instance);
}
}
return true;
}
}
private static int LastEmoteTime = -1;
internal static int MO_Offset = Extensions._get<int>(MoreEmotesPatchPlugin.ME_emotePatch, "_AlternateEmoteIDOffset");
internal static int[] MO_Doubles = (from x in (int[])Enum.GetValues(MoreEmotesPatchPlugin.ME_emotes)
where x - MO_Offset > 0
select x - MO_Offset).ToArray();
internal static void InitPatches(Harmony harmony)
{
harmony.PatchAllUncategorized();
harmony.PatchCategory("MoreEmotes");
}
}
}