using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("DefibroFaceExpressions")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DefibroFaceExpressions")] [assembly: AssemblyTitle("DefibroFaceExpressions")] [assembly: AssemblyVersion("1.0.0.0")] namespace DFE { public static class Constants { public static class AssetPaths { public static string AssemblyPath => Assembly.GetExecutingAssembly().Location; public static string AssemblyFolder => Path.GetDirectoryName(AssemblyPath); public static string NewExpressionPath => Path.Join((ReadOnlySpan)Plugin.Instance.ConfigExpressionPath.Value, (ReadOnlySpan)("/" + Plugin.Instance.ConfigExpressionFileName.Value)); } } [BepInPlugin("com.averyocean65.defibrofaceexpressions", "DefibroFaceExpressions", "1.1.0")] public class Plugin : BaseUnityPlugin { private class PluginInfo { public const string GUID = "com.averyocean65.defibrofaceexpressions"; public const string Name = "DefibroFaceExpressions"; public const string Version = "1.1.0"; } public static Plugin Instance; public ConfigEntry ConfigDebugMode; public ConfigEntry ConfigVerboseLogging; public ConfigEntry ConfigCacheTexture; public ConfigEntry ConfigExpressionPath; public ConfigEntry ConfigExpressionFileName; public static ManualLogSource LogSource => ((BaseUnityPlugin)Instance).Logger; private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)Instance)) { Object.Destroy((Object)(object)this); return; } Instance = this; Harmony val = new Harmony("com.averyocean65.defibrofaceexpressions"); val.PatchAll(); ConfigCacheTexture = ((BaseUnityPlugin)this).Config.Bind("Performance", "CacheTexture", true, "Determines whether the texture should be loaded into the game once or re-loaded from disk each time a Defibro spawns."); ConfigExpressionPath = ((BaseUnityPlugin)this).Config.Bind("IO", "ExpressionFolderPath", Constants.AssetPaths.AssemblyFolder, "Where the folder for the expression file is on your file system."); ConfigExpressionFileName = ((BaseUnityPlugin)this).Config.Bind("IO", "ExpressionFileName", "expressions.png", "The name of the expressions file."); ConfigDebugMode = ((BaseUnityPlugin)this).Config.Bind("Developer", "DebugMode", false, "Whether to toggle on the debug mode for DefibroFaceExpressions."); ConfigVerboseLogging = ((BaseUnityPlugin)this).Config.Bind("Developer", "VerboseLogging", false, "Enable or disable verbose logging."); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Looking for: " + Constants.AssetPaths.NewExpressionPath)); } } } namespace DFE.Patches { [HarmonyPatch] public class DefibroPatches { private static Vector2 _lastOffset = new Vector2(10000f, 10000f); private static MethodInfo _setFacialExpression; private static MethodInfo _updateFaceBounce; private static Texture2D _cachedFaceTextureAtlas; private static float _lastExprChangeTime = 0f; private static float[] _facialExpressions = new float[10] { 0.101f, 0.179f, 0.023f, 0.257f, 0.335f, 0.413f, 0.491f, 0.569f, 0.647f, 0.728f }; private static int _facialExprIndex = 0; public static bool _debugMode => Plugin.Instance.ConfigDebugMode.Value; public static bool _logging => Plugin.Instance.ConfigVerboseLogging.Value; private static Texture2D FaceTextureAtlas { get { if (!Plugin.Instance.ConfigCacheTexture.Value) { return LoadTexture(Constants.AssetPaths.NewExpressionPath); } if (!Object.op_Implicit((Object)(object)_cachedFaceTextureAtlas)) { _cachedFaceTextureAtlas = LoadTexture(Constants.AssetPaths.NewExpressionPath); } return _cachedFaceTextureAtlas; } } [HarmonyPrefix] [HarmonyPatch(typeof(ItemReviveItem), "Start")] private static void PatchStart(ItemReviveItem __instance) { if (!Object.op_Implicit((Object)(object)FaceTextureAtlas)) { Plugin.LogSource.LogError((object)("No expressions.png found in " + Constants.AssetPaths.NewExpressionPath)); return; } ((Renderer)__instance.FaceMeshRenderer).material.mainTexture = (Texture)(object)FaceTextureAtlas; _setFacialExpression = AccessTools.Method(typeof(ItemReviveItem), "SetFacialExpression", new Type[1] { typeof(float) }, (Type[])null); _updateFaceBounce = AccessTools.Method(typeof(ItemReviveItem), "UpdateFaceBounce", (Type[])null, (Type[])null); } [HarmonyPostfix] [HarmonyPatch(typeof(ItemReviveItem), "UpdateFaceBounce")] private static void PatchUpdateFaceBounce(ItemReviveItem __instance) { //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (_logging) { Vector2 mainTextureOffset = ((Renderer)__instance.FaceMeshRenderer).material.mainTextureOffset; if (!(Mathf.Abs(mainTextureOffset.x - _lastOffset.x) < 0.01f)) { _lastOffset = mainTextureOffset; Plugin.LogSource.LogInfo((object)$"Offset: [{mainTextureOffset.x}; {mainTextureOffset.y}]"); } } } private static void SwitchThroughFacialExpressions(ItemReviveItem instance) { if (Mathf.Abs(Time.time - _lastExprChangeTime) > 2f) { _lastExprChangeTime = Time.time; _facialExprIndex++; if (_facialExprIndex >= _facialExpressions.Length) { _facialExprIndex = 0; } } _setFacialExpression.Invoke(instance, new object[1] { _facialExpressions[_facialExprIndex] }); } [HarmonyPrefix] [HarmonyPatch(typeof(ItemReviveItem), "FacialExpressionLogic")] private static bool PatchFacialExpression(ItemReviveItem __instance) { if (_debugMode) { SwitchThroughFacialExpressions(__instance); } return !_debugMode; } private static Texture2D LoadTexture(string filePath) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown Texture2D val = new Texture2D(256, 32); byte[] array = File.ReadAllBytes(filePath); ImageConversion.LoadImage(val, array); return val; } } }