Wink.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
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 = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("Vippy")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+32312975ceabdd634b835c7a8ffa6f3f51b54f2d")]
[assembly: AssemblyProduct("Wink")]
[assembly: AssemblyTitle("Wink")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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]
	[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 Wink
{
	internal static class BuildInfo
	{
		public const string Version = "1.0.0";
	}
	internal static class WinkState
	{
		internal static EyeSettings? Closed;

		internal static void EnsureClosed(List<ExpressionSettings> expressions)
		{
			if (Closed != null || expressions == null)
			{
				return;
			}
			float num = float.NegativeInfinity;
			EyeSettings val = null;
			foreach (ExpressionSettings expression in expressions)
			{
				if (expression == null)
				{
					continue;
				}
				EyeSettings[] array = (EyeSettings[])(object)new EyeSettings[2] { expression.leftEye, expression.rightEye };
				foreach (EyeSettings val2 in array)
				{
					if (val2 != null && val2.upperLidClosedPercent > num)
					{
						num = val2.upperLidClosedPercent;
						val = val2;
					}
				}
			}
			if (val != null)
			{
				Closed = Copy(val);
			}
		}

		private static EyeSettings Copy(EyeSettings s)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			return new EyeSettings
			{
				upperLidAngle = s.upperLidAngle,
				upperLidClosedPercent = s.upperLidClosedPercent,
				upperLidClosedPercentJitterAmount = s.upperLidClosedPercentJitterAmount,
				upperLidClosedPercentJitterSpeed = s.upperLidClosedPercentJitterSpeed,
				lowerLidAngle = s.lowerLidAngle,
				lowerLidClosedPercent = s.lowerLidClosedPercent,
				lowerLidClosedPercentJitterAmount = s.lowerLidClosedPercentJitterAmount,
				lowerLidClosedPercentJitterSpeed = s.lowerLidClosedPercentJitterSpeed,
				pupilSize = s.pupilSize,
				pupilSizeJitterAmount = s.pupilSizeJitterAmount,
				pupilSizeJitterSpeed = s.pupilSizeJitterSpeed,
				pupilPositionJitter = s.pupilPositionJitter,
				pupilPositionJitterAmount = s.pupilPositionJitterAmount,
				pupilOffsetRotationX = s.pupilOffsetRotationX,
				pupilOffsetRotationY = s.pupilOffsetRotationY
			};
		}
	}
	internal enum WinkStyle
	{
		Normal,
		Seductive
	}
	internal static class WinkAnim
	{
		private class Anim
		{
			public float Timer;

			public float Dur;

			public WinkStyle Style;

			public float Amount;
		}

		private static readonly Dictionary<PlayerExpression, Anim> _anims = new Dictionary<PlayerExpression, Anim>();

		private static readonly List<PlayerExpression> _dead = new List<PlayerExpression>();

		public static void Start(PlayerExpression pe, WinkStyle style)
		{
			foreach (PlayerExpression key in _anims.Keys)
			{
				if ((Object)(object)key == (Object)null)
				{
					_dead.Add(key);
				}
			}
			foreach (PlayerExpression item in _dead)
			{
				_anims.Remove(item);
			}
			_dead.Clear();
			float num = Mathf.Max(0.05f, (style == WinkStyle.Seductive) ? WinkConfig.SeductiveDuration.Value : WinkConfig.NormalDuration.Value);
			_anims[pe] = new Anim
			{
				Timer = num,
				Dur = num,
				Style = style
			};
		}

		public static void Tick(PlayerExpression pe)
		{
			if (_anims.TryGetValue(pe, out Anim value))
			{
				value.Timer -= Time.deltaTime;
				if (value.Timer <= 0f)
				{
					_anims.Remove(pe);
				}
				else
				{
					value.Amount = Mathf.Sin(MathF.PI * (1f - value.Timer / value.Dur));
				}
			}
		}

		public static bool TryGet(PlayerExpression pe, out float amount, out WinkStyle style)
		{
			if (_anims.TryGetValue(pe, out Anim value))
			{
				amount = value.Amount;
				style = value.Style;
				return true;
			}
			amount = 0f;
			style = WinkStyle.Normal;
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerExpression), "Start")]
	internal static class WinkSetupPatch
	{
		private static bool _logged;

		[HarmonyPostfix]
		public static void Postfix(PlayerExpression __instance)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			List<ExpressionSettings> expressions = __instance.expressions;
			if (expressions != null)
			{
				WinkState.EnsureClosed(expressions);
				if (!_logged)
				{
					_logged = true;
					WinkPlugin.Log.LogInfo((object)$"[Wink] {expressions.Count} expressions, wink on {WinkConfig.WinkKey.Value}");
				}
				float value = WinkConfig.EyelidSpeed.Value;
				SetSpeed(__instance.leftUpperLidClosedAngle, value);
				SetSpeed(__instance.leftLowerLidClosedAngle, value);
				SetSpeed(__instance.rightUpperLidClosedAngle, value);
				SetSpeed(__instance.rightLowerLidClosedAngle, value);
			}
		}

		private static void SetSpeed(SpringFloat? spring, float spd)
		{
			if (spring != null)
			{
				spring.speed = spd;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerExpression), "Update")]
	internal static class WinkUpdatePatch
	{
		private const float HeldFaceMinWeight = 5f;

		private const float KeepAliveTimer = 0.1f;

		[HarmonyPostfix]
		public static void Postfix(PlayerExpression __instance)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			List<ExpressionSettings> expressions = __instance.expressions;
			if (expressions == null || expressions.Count == 0)
			{
				return;
			}
			PlayerAvatarVisuals playerVisuals = __instance.playerVisuals;
			if (__instance.isLocal && (Object)(object)playerVisuals != (Object)null && !playerVisuals.isMenuAvatar && (Object)(object)__instance.playerAvatar != (Object)null && (Object)(object)__instance == (Object)(object)__instance.playerAvatar.playerExpression && (Object)(object)MenuManager.instance != (Object)null && !Object.op_Implicit((Object)(object)MenuManager.instance.currentMenuPage) && Input.GetKeyDown(WinkConfig.WinkKey.Value))
			{
				WinkStyle style = ((WinkConfig.Style.Value == "Seductive") ? WinkStyle.Seductive : WinkStyle.Normal);
				WinkAnim.Start(__instance, style);
				PlayerExpressionsUI instance = PlayerExpressionsUI.instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.ShrinkReset();
					if ((Object)(object)instance.playerExpression != (Object)null)
					{
						WinkAnim.Start(instance.playerExpression, style);
					}
				}
				if (!__instance.onlyVisualRepresentation)
				{
					WinkNet.Send(__instance.playerAvatar, style);
				}
			}
			WinkAnim.Tick(__instance);
			if (!WinkAnim.TryGet(__instance, out var amount, out var style2))
			{
				return;
			}
			expressions[0].timer = Mathf.Max(expressions[0].timer, 0.1f);
			float num = 0f;
			for (int i = 1; i < expressions.Count; i++)
			{
				if (i != 4)
				{
					num += expressions[i].weight;
				}
			}
			if (num < 5f)
			{
				expressions[0].weight = 100f;
			}
			if ((Object)(object)playerVisuals != (Object)null && style2 == WinkStyle.Seductive)
			{
				playerVisuals.HeadTiltOverride(WinkConfig.HeadTilt.Value * amount);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerExpression), "BlendEyeSettings")]
	internal static class WinkBlendPatch
	{
		[HarmonyPostfix]
		public static void Postfix(PlayerExpression __instance, bool isLeft, EyeSettings __result)
		{
			if (!WinkAnim.TryGet(__instance, out var amount, out var style) || amount <= 0f)
			{
				return;
			}
			EyeSettings closed = WinkState.Closed;
			if (closed == null || __result == null)
			{
				return;
			}
			List<ExpressionSettings> expressions = __instance.expressions;
			int num = 4;
			if (expressions == null || num >= expressions.Count)
			{
				return;
			}
			float num2 = 0f;
			for (int i = 0; i < expressions.Count; i++)
			{
				num2 += expressions[i].weight;
			}
			float num3 = expressions[num]?.weight ?? 0f;
			if (num3 > 0.5f && num2 > 0.001f)
			{
				float num4 = num2 - num3;
				EyeSettings val = (isLeft ? expressions[num].leftEye : expressions[num].rightEye);
				if (num4 > 0.5f && val != null)
				{
					__result.upperLidClosedPercent = (__result.upperLidClosedPercent * num2 - val.upperLidClosedPercent * num3) / num4;
					__result.lowerLidClosedPercent = (__result.lowerLidClosedPercent * num2 - val.lowerLidClosedPercent * num3) / num4;
					__result.upperLidAngle = (__result.upperLidAngle * num2 - val.upperLidAngle * num3) / num4;
					__result.lowerLidAngle = (__result.lowerLidAngle * num2 - val.lowerLidAngle * num3) / num4;
					__result.pupilSize = (__result.pupilSize * num2 - val.pupilSize * num3) / num4;
				}
			}
			bool flag = isLeft == WinkConfig.WinkLeftEye.Value;
			bool flag2 = style == WinkStyle.Seductive;
			float num5 = (flag ? amount : (flag2 ? (amount * WinkConfig.SultryLid.Value) : 0f));
			float num6 = (flag ? amount : 0f);
			__result.upperLidClosedPercent = Mathf.Lerp(__result.upperLidClosedPercent, closed.upperLidClosedPercent, num5);
			__result.lowerLidClosedPercent = Mathf.Lerp(__result.lowerLidClosedPercent, closed.lowerLidClosedPercent, num5);
			__result.upperLidAngle = Mathf.Lerp(__result.upperLidAngle, closed.upperLidAngle, num6);
			__result.lowerLidAngle = Mathf.Lerp(__result.lowerLidAngle, closed.lowerLidAngle, num6);
			__result.pupilSize = Mathf.Lerp(__result.pupilSize, closed.pupilSize, num6);
		}
	}
	[HarmonyPatch(typeof(PunManager), "Awake")]
	internal static class PunManagerWinkPatch
	{
		[HarmonyPostfix]
		public static void Postfix(PunManager __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<WinkNet>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<WinkNet>();
			}
		}
	}
	[BepInPlugin("Vippy.Wink", "Wink", "1.0.0")]
	public class WinkPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			WinkConfig.Init(((BaseUnityPlugin)this).Config);
			new Harmony("Vippy.Wink").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Wink v1.0.0 loaded");
		}
	}
	internal class WinkNet : MonoBehaviour
	{
		private const float BlinkSeconds = 0.3f;

		private static float _blinkStopAt;

		public static void Send(PlayerAvatar avatar, WinkStyle style)
		{
			if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom.PlayerCount > 1)
			{
				PunManager.instance.photonView.RPC("WinkRPC", (RpcTarget)1, new object[2]
				{
					SemiFunc.PhotonViewIDPlayerAvatarLocal(),
					(int)style
				});
				if (WinkConfig.BlinkForOthers.Value)
				{
					avatar.PlayerExpressionSet(4, 100f);
					_blinkStopAt = Time.time + 0.3f;
				}
			}
		}

		[PunRPC]
		public void WinkRPC(int _avatarViewID, int _style, PhotonMessageInfo _info = default(PhotonMessageInfo))
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(_avatarViewID);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.playerExpression == (Object)null) && _info.Sender != null && !((Object)(object)val.photonView == (Object)null) && val.photonView.Owner == _info.Sender)
			{
				WinkAnim.Start(val.playerExpression, (_style == 1) ? WinkStyle.Seductive : WinkStyle.Normal);
			}
		}

		private void Update()
		{
			if (_blinkStopAt > 0f && Time.time >= _blinkStopAt)
			{
				_blinkStopAt = 0f;
				if ((Object)(object)PlayerAvatar.instance != (Object)null)
				{
					PlayerAvatar.instance.PlayerExpressionStop(4);
				}
			}
		}
	}
	internal static class WinkConfig
	{
		public const int BlinkSlot = 4;

		public const string StyleNormal = "Normal";

		public const string StyleSeductive = "Seductive";

		public static ConfigEntry<KeyCode> WinkKey;

		public static ConfigEntry<string> Style;

		public static ConfigEntry<bool> BlinkForOthers;

		public static ConfigEntry<bool> WinkLeftEye;

		public static ConfigEntry<float> NormalDuration;

		public static ConfigEntry<float> SeductiveDuration;

		public static ConfigEntry<float> EyelidSpeed;

		public static ConfigEntry<float> SultryLid;

		public static ConfigEntry<float> HeadTilt;

		public static void Init(ConfigFile config)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			WinkKey = config.Bind<KeyCode>("Wink", "Wink key", (KeyCode)52, "Wink. Pick which wink it does with the 'Wink style' setting. The inventory keys (1-3) and the six expression keys (5-0) stay vanilla.");
			Style = config.Bind<string>("Wink", "Wink style", "Normal", new ConfigDescription("Normal is a quick close-and-reopen. Seductive is slower - the other eye goes half-lidded and the head tilts.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Normal", "Seductive" }), Array.Empty<object>()));
			BlinkForOthers = config.Bind<bool>("Wink", "Blink for unmodded players", true, "Also flash the vanilla closed-eyes face for a split second so players WITHOUT the mod see a quick blink instead of nothing. Players with the mod always see the real one-eyed wink.");
			WinkLeftEye = config.Bind<bool>("Wink", "Wink the left eye", false, "Close the LEFT eye instead of the right.");
			NormalDuration = config.Bind<float>("Wink", "Normal wink duration", 0.35f, new ConfigDescription("Seconds for the normal wink's close-and-reopen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.15f, 1f), Array.Empty<object>()));
			SeductiveDuration = config.Bind<float>("Wink", "Seductive wink duration", 0.7f, new ConfigDescription("Seconds for the seductive wink's close-and-reopen. Higher = slower, more deliberate.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 2f), Array.Empty<object>()));
			EyelidSpeed = config.Bind<float>("Wink", "Eyelid speed", 18f, new ConfigDescription("Eyelid spring smoothing (vanilla 20). Lower is softer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 60f), Array.Empty<object>()));
			SultryLid = config.Bind<float>("Wink", "Sultry lid", 0.4f, new ConfigDescription("Seductive wink only: how far the OTHER eye half-closes (bedroom eyes). 0 = wide open.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.85f), Array.Empty<object>()));
			HeadTilt = config.Bind<float>("Wink", "Head tilt", 10f, new ConfigDescription("Seductive wink only: head tilt in degrees (sign flips direction). 0 = none.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-25f, 25f), Array.Empty<object>()));
		}
	}
}