using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Sodalite.ModPanel;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("NGA")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Persistent player progression! Raid, stash loot, and deploy with seemless scene/loadout saving.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("NGA.SosigFaces")]
[assembly: AssemblyTitle("BepInEx Plugin Title")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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;
}
}
}
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
{
}
}
}
namespace NGA
{
[BepInPlugin("NGA.SosigFaces", "SosigFaces", "0.0.1")]
[BepInDependency("nrgill28.Sodalite", "1.0.0")]
[BepInProcess("h3vr.exe")]
public class SosigFaces : BaseUnityPlugin
{
[HarmonyPatch(typeof(PlayerSosigBody))]
[HarmonyPatch("Start")]
public class PlayerSosigBodyAwake : MonoBehaviour
{
private static void Postfix(PlayerSosigBody __instance)
{
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
if (CheckPlayerSkip())
{
return;
}
Logger.LogWarning((object)"Trying Player Sosig Start");
Transform sosig_Head = __instance.Sosig_Head;
if ((Object)(object)sosig_Head == (Object)null)
{
Logger.LogWarning((object)"Player Head not found!");
return;
}
Logger.LogMessage((object)"Doing player face");
if (!IM.OD.TryGetValue("NGA_PlayerFaceThing", out var value))
{
Logger.LogWarning((object)"NGA_FaceThing not found in IM.OD!");
return;
}
GameObject val = Object.Instantiate<GameObject>(((AnvilAsset)value).GetGameObject(), Vector3.zero, Quaternion.identity);
Logger.LogMessage((object)"Made face");
val.transform.SetParent(sosig_Head, false);
Logger.LogMessage((object)"Set face");
val.transform.localPosition = Vector3.zero;
val.transform.localRotation = Quaternion.identity;
FaceLipSync faceLipSync = val.gameObject.AddComponent<FaceLipSync>();
}
}
[HarmonyPatch(typeof(Sosig))]
[HarmonyPatch("ProcessDamage")]
[HarmonyPatch(new Type[]
{
typeof(float),
typeof(float),
typeof(float),
typeof(float),
typeof(Vector3),
typeof(SosigLink)
})]
public class SosigProcessDamage : MonoBehaviour
{
private static void Postfix(Sosig __instance, float damage_p, float damage_c, float damage_b, float damage_t, Vector3 point, SosigLink link)
{
if (!CheckSosigSkip())
{
((Component)__instance).GetComponent<EnemyFaceController>().SetState("Damaged");
}
}
}
[HarmonyPatch(typeof(Sosig))]
[HarmonyPatch("SosigDies")]
public class SosigSosigDies : MonoBehaviour
{
private static void Postfix(Sosig __instance, DamageClass damClass, SosigDeathType deathType)
{
if (!CheckSosigSkip())
{
((Component)__instance).GetComponent<EnemyFaceController>().SetState("Dead");
}
}
}
[HarmonyPatch(typeof(Sosig))]
[HarmonyPatch("BrainUpdate")]
public class SosigBrainUpdate : MonoBehaviour
{
private static void Postfix(Sosig __instance)
{
//IL_000f: 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_0016: 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)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected I4, but got Unknown
if (!CheckSosigSkip())
{
bool flag = false;
SosigOrder currentOrder = __instance.CurrentOrder;
SosigOrder val = currentOrder;
switch ((int)val)
{
case 0:
case 1:
case 3:
case 4:
case 6:
case 8:
case 9:
case 10:
flag = false;
break;
default:
flag = true;
break;
}
string state = (flag ? "Assaulting" : "Idle");
((Component)__instance).GetComponent<EnemyFaceController>().SetState(state);
}
}
}
[HarmonyPatch(typeof(Sosig))]
[HarmonyPatch("Start")]
public class SosigAwake : MonoBehaviour
{
private static void Postfix(Sosig __instance)
{
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
if (CheckSosigSkip())
{
return;
}
bool flag = false;
foreach (SosigLink link in __instance.Links)
{
Transform transform = ((Component)link).transform;
if (((Object)((Component)link).transform).name != "Sosig_Torso")
{
continue;
}
if ((Object)(object)((Component)link).transform == (Object)(object)GM.CurrentPlayerBody.Torso)
{
flag = true;
}
Transform val = transform.Find("Head");
if ((Object)(object)val == (Object)null)
{
Logger.LogWarning((object)"Head not found!");
break;
}
if (flag)
{
Logger.LogError((object)"Doing player face when i shouldnt");
continue;
}
if (!IM.OD.TryGetValue("NGA_FaceThing", out var value))
{
Logger.LogError((object)"NGA_FaceThing not found in IM.OD!");
break;
}
GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)value).GetGameObject(), Vector3.zero, Quaternion.identity);
val2.transform.SetParent(val, false);
val2.transform.localPosition = Vector3.zero;
val2.transform.localRotation = Quaternion.identity;
EnemyFaceController enemyFaceController = ((Component)__instance).gameObject.AddComponent<EnemyFaceController>();
enemyFaceController.Init(val2);
}
}
}
private class FaceThingComponent : MonoBehaviour
{
public GameObject attached_face = null;
}
public class EnemyFaceController : MonoBehaviour
{
private Material faceMaterial;
private Texture2D idleFace;
private Texture2D assaultFace;
private Coroutine damageCoroutine;
public GameObject attached_face = null;
private bool dead = false;
private bool damaged = false;
public void Init(GameObject face)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
attached_face = face;
Transform val = attached_face.transform.Find("default");
if ((Object)(object)val != (Object)null)
{
Renderer component = ((Component)val).GetComponent<Renderer>();
if ((Object)(object)component != (Object)null)
{
faceMaterial = new Material(component.material);
component.material = faceMaterial;
}
else
{
Logger.LogError((object)"Renderer component not found on the 'default' object.");
}
}
else
{
Logger.LogError((object)"'Face' object not found among children.");
}
SetRandomIdleFace();
}
public void SetRandomIdleFace()
{
if (!((Object)(object)faceMaterial == (Object)null))
{
idleFace = GetRandomTexture(IdleFaces);
faceMaterial.mainTexture = (Texture)(object)idleFace;
assaultFace = GetRandomTexture(AssaultingFaces);
}
}
public void SetState(string state)
{
if ((Object)(object)faceMaterial == (Object)null || dead)
{
return;
}
switch (state)
{
case "Dead":
if (damageCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(damageCoroutine);
}
faceMaterial.mainTexture = (Texture)(object)GetRandomTexture(DeadFaces);
dead = true;
break;
case "Idle":
if (!damaged && !((Object)(object)faceMaterial.mainTexture == (Object)(object)idleFace))
{
faceMaterial.mainTexture = (Texture)(object)idleFace;
}
break;
case "Assaulting":
if (!damaged && !((Object)(object)faceMaterial.mainTexture == (Object)(object)assaultFace))
{
faceMaterial.mainTexture = (Texture)(object)assaultFace;
}
break;
case "Damaged":
if (!damaged)
{
if (damageCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(damageCoroutine);
}
faceMaterial.mainTexture = (Texture)(object)GetRandomTexture(DamagedFaces);
damageCoroutine = ((MonoBehaviour)this).StartCoroutine(DamageTimeout());
}
break;
}
}
private IEnumerator DamageTimeout()
{
damaged = true;
yield return (object)new WaitForSeconds(2f);
faceMaterial.mainTexture = (Texture)(object)idleFace;
damaged = false;
}
private Texture2D GetRandomTexture(List<Texture2D> textures)
{
if (textures.Count == 0)
{
Logger.LogError((object)"No textures available for the requested state.");
return null;
}
return textures[Random.Range(0, textures.Count)];
}
}
public class FaceLipSync : MonoBehaviour
{
public AudioSource audioSource;
public Material mouthMaterial;
public string folderPath;
public string closedMouthFileName = "mouthClosed.png";
public string partiallyOpenMouthFileName = "mouthPartiallyOpen.png";
public string openMouthFileName = "mouthOpen.png";
public string smileMouthFileName = "mouthSmile.png";
public string wideOpenMouthFileName = "mouthWideOpen.png";
public string frownMouthFileName = "mouthFrown.png";
private Texture2D closedMouthTexture;
private Texture2D partiallyOpenMouthTexture;
private Texture2D openMouthTexture;
private Texture2D smileMouthTexture;
private Texture2D wideOpenMouthTexture;
private Texture2D frownMouthTexture;
private string microphoneName;
private float lastActiveTime;
private float lastChosenMouth = Time.time;
private void Awake()
{
if ((Object)(object)audioSource == (Object)null)
{
audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
}
if ((Object)(object)mouthMaterial == (Object)null)
{
Transform val = ((Component)this).transform.Find("mouth");
if ((Object)(object)val != (Object)null)
{
Renderer component = ((Component)val).GetComponent<Renderer>();
if ((Object)(object)component != (Object)null)
{
mouthMaterial = component.material;
}
else
{
Logger.LogError((object)"Renderer component not found on the 'mouth' object.");
}
}
else
{
Logger.LogError((object)"'mouth' object not found among children.");
}
}
LoadTextures();
InitializeMicrophone();
}
private void LoadTextures()
{
Logger.LogMessage((object)"LoadTextures");
folderPath = Paths.PluginPath + "\\NGA-SosigFarce\\";
Logger.LogMessage((object)("Folder path:" + folderPath + "."));
Logger.LogMessage((object)("Sample file path:" + folderPath + closedMouthFileName + "."));
closedMouthTexture = LoadTexture(folderPath + closedMouthFileName);
partiallyOpenMouthTexture = LoadTexture(folderPath + partiallyOpenMouthFileName);
openMouthTexture = LoadTexture(folderPath + openMouthFileName);
smileMouthTexture = LoadTexture(folderPath + smileMouthFileName);
wideOpenMouthTexture = LoadTexture(folderPath + wideOpenMouthFileName);
frownMouthTexture = LoadTexture(folderPath + frownMouthFileName);
}
private Texture2D LoadTexture(string path)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
byte[] array = File.ReadAllBytes(path);
Texture2D val = new Texture2D(2, 2);
val.LoadImage(array);
return val;
}
private void InitializeMicrophone()
{
string[] devices = Microphone.devices;
foreach (string text in devices)
{
Logger.LogMessage((object)("Microphone detected: " + text));
}
if (Microphone.devices.Length != 0)
{
microphoneName = Microphone.devices[0];
audioSource.clip = Microphone.Start(microphoneName, true, 1, 44100);
audioSource.loop = true;
while (Microphone.GetPosition(microphoneName) <= 0)
{
}
audioSource.Play();
}
else
{
Logger.LogError((object)"No microphones detected at all!");
}
}
private void Update()
{
if ((Object)(object)mouthMaterial == (Object)null)
{
return;
}
if (Microphone.IsRecording(microphoneName))
{
float[] array = new float[64];
audioSource.GetOutputData(array, 0);
float num = 0f;
float num2 = 0f;
int num3 = 0;
for (int i = 1; i < array.Length; i++)
{
num += Mathf.Abs(array[i]);
if (array[i - 1] < 0f && array[i] > 0f)
{
num3++;
}
}
num /= (float)array.Length;
num2 = num3;
Texture2D val = closedMouthTexture;
val = ((num < mouthClosedV.Value) ? closedMouthTexture : ((num < smileFrownV.Value) ? ((!(num2 < (float)pitchSwap.Value)) ? smileMouthTexture : frownMouthTexture) : ((num < partialOpenV.Value) ? partiallyOpenMouthTexture : ((!(num < normalOpenv.Value)) ? wideOpenMouthTexture : openMouthTexture))));
lastActiveTime = Time.time;
if (Time.time - lastChosenMouth > talkDuration.Value)
{
lastChosenMouth = Time.time;
mouthMaterial.mainTexture = (Texture)(object)val;
}
}
if (Time.time - lastActiveTime > silenceDuration.Value)
{
mouthMaterial.mainTexture = (Texture)(object)closedMouthTexture;
}
}
}
private static ConfigEntry<bool> GameEnabled;
private static ConfigEntry<bool> SosigHaveFaces;
private static ConfigEntry<bool> PlayerHasFace;
private static ConfigEntry<float> mouthClosedV;
private static ConfigEntry<float> smileFrownV;
private static ConfigEntry<float> partialOpenV;
private static ConfigEntry<float> normalOpenv;
private static ConfigEntry<float> talkDuration;
private static ConfigEntry<float> silenceDuration;
private static ConfigEntry<int> pitchSwap;
public static List<Texture2D> IdleFaces = new List<Texture2D>();
public static List<Texture2D> AssaultingFaces = new List<Texture2D>();
public static List<Texture2D> DamagedFaces = new List<Texture2D>();
public static List<Texture2D> DeadFaces = new List<Texture2D>();
internal static ManualLogSource Logger { get; private set; }
private void Awake()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
Harmony val = new Harmony("NGA.SosigFaces");
Logger.LogMessage((object)"New harmony");
LoadTextures();
SetUpConfigFields();
Logger.LogMessage((object)"Setted the fields");
val.PatchAll();
Logger.LogMessage((object)"Hello, world! Sent from NGA.SosigFaces 0.0.1");
}
public static void LoadTextures()
{
string path = Paths.PluginPath + "\\NGA-SosigFarce\\";
IdleFaces = LoadTexturesFromFolder(Path.Combine(path, "Idle"));
AssaultingFaces = LoadTexturesFromFolder(Path.Combine(path, "Assaulting"));
DamagedFaces = LoadTexturesFromFolder(Path.Combine(path, "Damaged"));
DeadFaces = LoadTexturesFromFolder(Path.Combine(path, "Dead"));
}
private static List<Texture2D> LoadTexturesFromFolder(string folderPath)
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
List<Texture2D> list = new List<Texture2D>();
string[] files = Directory.GetFiles(folderPath, "*.png");
Logger.LogWarning((object)("Number pngs in " + folderPath + " is " + files.Length));
string[] array = files;
foreach (string path in array)
{
byte[] array2 = File.ReadAllBytes(path);
Texture2D val = new Texture2D(2, 2);
val.LoadImage(array2);
list.Add(val);
Logger.LogWarning((object)"Added sosig face texture!");
}
return list;
}
private void SetUpConfigFields()
{
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Expected O, but got Unknown
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Expected O, but got Unknown
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Expected O, but got Unknown
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Expected O, but got Unknown
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Expected O, but got Unknown
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Expected O, but got Unknown
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Expected O, but got Unknown
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Expected O, but got Unknown
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_01a6: Expected O, but got Unknown
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Expected O, but got Unknown
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Expected O, but got Unknown
//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Expected O, but got Unknown
//IL_020d: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Expected O, but got Unknown
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_0222: Expected O, but got Unknown
GameEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Overall", "ON/OFF.", true, "Turn mod On / Off");
SosigHaveFaces = ((BaseUnityPlugin)this).Config.Bind<bool>("Overall", "Sosig Faces ON/OFF.", true, "Sosigs have faces");
PlayerHasFace = ((BaseUnityPlugin)this).Config.Bind<bool>("Overall", "Player Face ON/OFF.", true, "Player has face");
mouthClosedV = ((BaseUnityPlugin)this).Config.Bind<float>("Volume", "Mouth closed", 0.001f, new ConfigDescription("Mouth closed for values below this.", (AcceptableValueBase)new AcceptableValueFloatRangeStep(0.0001f, 1f, 0.001f), new object[0]));
smileFrownV = ((BaseUnityPlugin)this).Config.Bind<float>("Volume", "Smile Frown", 0.07f, new ConfigDescription("Smile Frown for values below this.", (AcceptableValueBase)new AcceptableValueFloatRangeStep(0.0001f, 1f, 0.001f), new object[0]));
partialOpenV = ((BaseUnityPlugin)this).Config.Bind<float>("Volume", "Partial Open", 0.02f, new ConfigDescription("Partial Open for values below this..", (AcceptableValueBase)new AcceptableValueFloatRangeStep(0.0001f, 1f, 0.001f), new object[0]));
normalOpenv = ((BaseUnityPlugin)this).Config.Bind<float>("Volume", "Normal open", 0.03f, new ConfigDescription("Mouth open normal for values below this.", (AcceptableValueBase)new AcceptableValueFloatRangeStep(0.0001f, 1f, 0.001f), new object[0]));
talkDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Animation", "Mouth Change", 0.15f, new ConfigDescription("How long before the mouth next updates", (AcceptableValueBase)new AcceptableValueFloatRangeStep(0.0001f, 1f, 0.001f), new object[0]));
silenceDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Animation", "Silence Change", 0.5f, new ConfigDescription("How long before the mouth closes", (AcceptableValueBase)new AcceptableValueFloatRangeStep(0.0001f, 1f, 0.001f), new object[0]));
pitchSwap = ((BaseUnityPlugin)this).Config.Bind<int>("Animation", "Pitch Frown or Smile", 1, new ConfigDescription("Pitch needed to swap between smile and frown at same volume.", (AcceptableValueBase)new AcceptableValueIntRangeStep(0, 100, 1), new object[0]));
}
private static bool CheckSkip()
{
return !GameEnabled.Value;
}
private static bool CheckSosigSkip()
{
return !GameEnabled.Value || !SosigHaveFaces.Value;
}
private static bool CheckPlayerSkip()
{
return !GameEnabled.Value || !PlayerHasFace.Value;
}
}
}