using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FaceCam")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.2.0")]
[assembly: AssemblyInformationalVersion("1.3.2+cee7aad9de0937e60ff1e8c5228ddd0d3d068c1f")]
[assembly: AssemblyProduct("FaceCam")]
[assembly: AssemblyTitle("FaceCam")]
[assembly: AssemblyVersion("1.3.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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 FaceCam
{
[BepInPlugin("com.slopgaming.facecam", "FaceCam", "1.3.2")]
public class FaceCamPlugin : BaseUnityPlugin
{
public enum Corner
{
TopLeft,
TopRight,
BottomLeft,
BottomRight
}
private struct Threat
{
public string Name;
public Vector3 Point;
public float Distance;
}
public const string PluginGuid = "com.slopgaming.facecam";
public const string PluginName = "FaceCam";
public const string PluginVersion = "1.3.2";
private ConfigEntry<KeyboardShortcut> toggleKey;
private ConfigEntry<bool> enabledOnStart;
private ConfigEntry<bool> hideWhenNoThreat;
private ConfigEntry<float> maxTrackDistance;
private ConfigEntry<bool> trackMass;
private ConfigEntry<bool> trackFaces;
private ConfigEntry<bool> trackHunter;
private ConfigEntry<bool> trackRemains;
private ConfigEntry<bool> trackRatKing;
private ConfigEntry<Corner> corner;
private ConfigEntry<float> viewportSize;
private ConfigEntry<float> margin;
private ConfigEntry<float> borderThickness;
private ConfigEntry<Color> borderColor;
private ConfigEntry<bool> showName;
private ConfigEntry<bool> showDistance;
private ConfigEntry<float> fieldOfView;
private ConfigEntry<float> aimSmoothing;
private ConfigEntry<int> resolutionScale;
private ConfigEntry<float> shakeDistance;
private ConfigEntry<float> shakeAngle;
private ConfigEntry<float> shakePixels;
private ConfigEntry<float> shakeSpeed;
private bool active;
private Camera cam;
private RenderTexture rt;
private Canvas hudCanvas;
private RectTransform hudRoot;
private Image border;
private RawImage feed;
private RectTransform tagRoot;
private TextMeshProUGUI tagText;
private Threat current;
private bool hasThreat;
private Quaternion aimRotation;
private bool aimInitialized;
private Vector2 shakeOffset;
private static readonly FieldInfo FaceIsPrimary = typeof(DEN_Face).GetField("isPrimary", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo GameDead = typeof(CL_GameManager).GetField("dead", BindingFlags.Static | BindingFlags.NonPublic);
private static readonly FieldInfo GameLoading = typeof(CL_GameManager).GetField("loading", BindingFlags.Instance | BindingFlags.NonPublic);
internal static ManualLogSource Log;
private static FaceCamPlugin instance;
private float nextLiveFontCheck;
private bool liveFontApplied;
internal static bool Rendering
{
get
{
if ((Object)(object)instance != (Object)null && (Object)(object)instance.cam != (Object)null)
{
return ((Behaviour)instance.cam).enabled;
}
return false;
}
}
private void Awake()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_018b: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Expected O, but got Unknown
//IL_0209: Unknown result type (might be due to invalid IL or missing references)
//IL_028e: Unknown result type (might be due to invalid IL or missing references)
//IL_0298: Expected O, but got Unknown
//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
//IL_02ef: Expected O, but got Unknown
//IL_03af: Unknown result type (might be due to invalid IL or missing references)
//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Key that turns the FaceCam viewport on and off.");
enabledOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnabledOnStart", false, "Whether the FaceCam starts switched on when the game launches.");
hideWhenNoThreat = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HideWhenNoThreat", true, "Hide the viewport while no tracked threat exists (or all are out of range).");
maxTrackDistance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxTrackDistance", 250f, "Threats further away than this (metres) are ignored.");
trackMass = ((BaseUnityPlugin)this).Config.Bind<bool>("Threats", "TrackMass", true, "Track the Mass (rising goo below you).");
trackFaces = ((BaseUnityPlugin)this).Config.Bind<bool>("Threats", "TrackFaces", true, "Track Faces. Each Face is tracked separately and labelled.");
trackHunter = ((BaseUnityPlugin)this).Config.Bind<bool>("Threats", "TrackHunter", true, "Track the Hunter.");
trackRemains = ((BaseUnityPlugin)this).Config.Bind<bool>("Threats", "TrackRemains", true, "Track active Remains (the climbing bodies).");
trackRatKing = ((BaseUnityPlugin)this).Config.Bind<bool>("Threats", "TrackRatKing", true, "Track the Rat King.");
corner = ((BaseUnityPlugin)this).Config.Bind<Corner>("Viewport", "Corner", Corner.BottomRight, "Screen corner the viewport sits in.");
viewportSize = ((BaseUnityPlugin)this).Config.Bind<float>("Viewport", "Size", 0.28f, new ConfigDescription("Side length of the square viewport as a fraction of screen height.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.9f), Array.Empty<object>()));
margin = ((BaseUnityPlugin)this).Config.Bind<float>("Viewport", "Margin", 24f, "Gap in pixels between the viewport and the screen edges.");
borderThickness = ((BaseUnityPlugin)this).Config.Bind<float>("Viewport", "BorderThickness", 3f, "Border thickness in pixels.");
borderColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Viewport", "BorderColor", new Color(0.85f, 0.85f, 0.85f, 0.9f), "Border colour (RGBA).");
showName = ((BaseUnityPlugin)this).Config.Bind<bool>("Viewport", "ShowName", true, "Show a name tag with the tracked threat's name.");
showDistance = ((BaseUnityPlugin)this).Config.Bind<bool>("Viewport", "ShowDistance", false, "Add the distance to the threat to the name tag.");
fieldOfView = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FieldOfView", 60f, new ConfigDescription("Field of view of the FaceCam.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 120f), Array.Empty<object>()));
aimSmoothing = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "AimSmoothing", 10f, "How quickly the camera turns towards the threat. Higher is snappier; 0 snaps instantly.");
resolutionScale = ((BaseUnityPlugin)this).Config.Bind<int>("Camera", "ResolutionScale", 1, new ConfigDescription("Divides the render texture resolution (1 = full, 2 = half). Raise for performance.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>()));
shakeDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Shake", "ShakeDistance", 10f, "The viewport starts to shake when the threat is closer than this (metres). 0 disables shake.");
shakeAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Shake", "ShakeAngle", 1.2f, "Maximum camera wobble in degrees at point blank.");
shakePixels = ((BaseUnityPlugin)this).Config.Bind<float>("Shake", "ShakePixels", 4f, "Maximum viewport jitter in pixels at point blank.");
shakeSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Shake", "ShakeSpeed", 18f, "Shake frequency.");
active = enabledOnStart.Value;
Log = ((BaseUnityPlugin)this).Logger;
instance = this;
new Harmony("com.slopgaming.facecam").PatchAll(typeof(RemainsVisibilityPatch));
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. Toggle with {2}. Starts {3}.", "FaceCam", "1.3.2", toggleKey.Value, active ? "on" : "off"));
}
private void Update()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
KeyboardShortcut value = toggleKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
active = !active;
((BaseUnityPlugin)this).Logger.LogInfo((object)("FaceCam " + (active ? "on" : "off")));
}
ENT_Player playerObject = ENT_Player.playerObject;
if (!active || (Object)(object)playerObject == (Object)null || (Object)(object)playerObject.cam == (Object)null || !InPlayableState())
{
Hide();
return;
}
CL_GameManager gMan = CL_GameManager.gMan;
bool flag = (Object)(object)gMan != (Object)null && gMan.isPaused;
if (!flag)
{
Vector3 position = ((Component)playerObject.cam).transform.position;
hasThreat = FindClosestThreat(playerObject, position, out current);
}
if (!hasThreat && hideWhenNoThreat.Value)
{
Hide();
return;
}
if (!EnsureHud(playerObject))
{
Hide();
return;
}
LayoutHud();
EnsureCamera(playerObject.cam);
if (!flag)
{
UpdateCameraPose(((Component)playerObject.cam).transform.position);
}
UpdateTag();
((Component)hudRoot).gameObject.SetActive(true);
((Behaviour)cam).enabled = !flag;
}
private static bool InPlayableState()
{
CL_GameManager gMan = CL_GameManager.gMan;
if ((Object)(object)gMan == (Object)null)
{
return false;
}
if (CL_GameManager.runHasEnded)
{
return false;
}
if (GameDead != null && (bool)GameDead.GetValue(null))
{
return false;
}
if (GameLoading != null && (bool)GameLoading.GetValue(gMan))
{
return false;
}
return true;
}
private void Hide()
{
aimInitialized = false;
if ((Object)(object)cam != (Object)null)
{
((Behaviour)cam).enabled = false;
}
if ((Object)(object)hudRoot != (Object)null)
{
((Component)hudRoot).gameObject.SetActive(false);
}
}
private bool FindClosestThreat(ENT_Player player, Vector3 eye, out Threat best)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
Threat closest = default(Threat);
float bestDist = maxTrackDistance.Value;
bool found = false;
if (trackMass.Value && (Object)(object)DEN_DeathFloor.instance != (Object)null && ((Behaviour)DEN_DeathFloor.instance).isActiveAndEnabled)
{
float height = DEN_DeathFloor.GetHeight();
if (height > -10000f)
{
Vector3 position = ((Component)player).transform.position;
Consider("The Mass", new Vector3(position.x, height, position.z));
}
}
if (trackFaces.Value && DEN_Face.faceInstances != null)
{
List<DEN_Face> faceInstances = DEN_Face.faceInstances;
int num = 2;
for (int i = 0; i < faceInstances.Count; i++)
{
DEN_Face val = faceInstances[i];
if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled)
{
Consider((FaceIsPrimary != null && (bool)FaceIsPrimary.GetValue(val)) ? "Face" : $"Face #{num++}", ((Component)val).transform.position);
}
}
}
if (trackHunter.Value && DEN_Hunter.activeHunters != null)
{
List<DEN_Hunter> activeHunters = DEN_Hunter.activeHunters;
for (int j = 0; j < activeHunters.Count; j++)
{
DEN_Hunter val2 = activeHunters[j];
if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).isActiveAndEnabled)
{
Transform val3 = (((Object)(object)val2.headObject != (Object)null) ? val2.headObject : ((Component)val2).transform);
Consider((activeHunters.Count > 1) ? $"Hunter #{j + 1}" : "Hunter", val3.position);
}
}
}
if (trackRatKing.Value && DEN_RatKing.activeRatKings != null)
{
List<DEN_RatKing> activeRatKings = DEN_RatKing.activeRatKings;
for (int k = 0; k < activeRatKings.Count; k++)
{
DEN_RatKing val4 = activeRatKings[k];
if (!((Object)(object)val4 == (Object)null) && ((Behaviour)val4).isActiveAndEnabled)
{
Consider((activeRatKings.Count > 1) ? $"Rat King #{k + 1}" : "Rat King", ((Component)val4).transform.position);
}
}
}
if (trackRemains.Value && GameEntity.entities != null)
{
List<GameEntity> entities = GameEntity.entities;
for (int l = 0; l < entities.Count; l++)
{
GameEntity obj = entities[l];
DEN_Remains_Active val5 = (DEN_Remains_Active)(object)((obj is DEN_Remains_Active) ? obj : null);
if (val5 != null && !((Object)(object)val5 == (Object)null) && val5.active && ((Behaviour)val5).isActiveAndEnabled)
{
Vector3 val6;
if (!((Object)(object)val5.capsuleCollider != (Object)null))
{
val6 = ((Component)val5).transform.position;
}
else
{
Bounds bounds = ((Collider)val5.capsuleCollider).bounds;
val6 = ((Bounds)(ref bounds)).center;
}
Vector3 point = val6;
Consider("Remains", point);
}
}
}
best = closest;
return found;
void Consider(string name, Vector3 val7)
{
//IL_0001: 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_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
float num2 = Vector3.Distance(eye, val7);
if (num2 < bestDist)
{
bestDist = num2;
closest = new Threat
{
Name = name,
Point = val7,
Distance = num2
};
found = true;
}
}
}
private void UpdateCameraPose(Vector3 eye)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: 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_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: 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_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: 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)
((Component)cam).transform.position = eye;
cam.fieldOfView = fieldOfView.Value;
if (hasThreat)
{
Vector3 val = current.Point - eye;
if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
{
Vector3 val2 = Vector3.up;
if (Mathf.Abs(Vector3.Dot(((Vector3)(ref val)).normalized, val2)) > 0.98f)
{
val2 = Vector3.forward;
}
Quaternion val3 = Quaternion.LookRotation(val, val2);
if (!aimInitialized || aimSmoothing.Value <= 0f)
{
aimRotation = val3;
}
else
{
aimRotation = Quaternion.Slerp(aimRotation, val3, 1f - Mathf.Exp((0f - aimSmoothing.Value) * Time.unscaledDeltaTime));
}
aimInitialized = true;
}
}
float num = 0f;
if (hasThreat && shakeDistance.Value > 0f && current.Distance < shakeDistance.Value)
{
num = 1f - current.Distance / shakeDistance.Value;
}
Quaternion val4 = Quaternion.identity;
shakeOffset = Vector2.zero;
if (num > 0f)
{
float num2 = Time.unscaledTime * shakeSpeed.Value;
float num3 = Mathf.PerlinNoise(num2, 0.1f) * 2f - 1f;
float num4 = Mathf.PerlinNoise(0.7f, num2) * 2f - 1f;
float num5 = Mathf.PerlinNoise(num2, 3.3f) * 2f - 1f;
float num6 = shakeAngle.Value * num;
val4 = Quaternion.Euler(num3 * num6, num4 * num6, num5 * num6 * 0.5f);
shakeOffset = new Vector2(num3, num4) * shakePixels.Value * num;
}
((Component)cam).transform.rotation = aimRotation * val4;
}
private void EnsureCamera(Camera playerCam)
{
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Expected O, but got Unknown
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Expected O, but got Unknown
int num = Mathf.Max(1, resolutionScale.Value);
int num2 = Mathf.Max(16, Mathf.RoundToInt(SidePixels() / (float)num));
if ((Object)(object)rt == (Object)null || ((Texture)rt).width != num2)
{
if ((Object)(object)rt != (Object)null)
{
if ((Object)(object)cam != (Object)null)
{
cam.targetTexture = null;
}
rt.Release();
Object.Destroy((Object)(object)rt);
}
rt = new RenderTexture(num2, num2, 24, OpaqueFormat())
{
name = "FaceCamRT"
};
rt.Create();
if ((Object)(object)feed != (Object)null)
{
feed.texture = (Texture)(object)rt;
}
}
if ((Object)(object)cam == (Object)null)
{
GameObject val = new GameObject("FaceCam_Camera");
Object.DontDestroyOnLoad((Object)(object)val);
cam = val.AddComponent<Camera>();
cam.CopyFrom(playerCam);
cam.depth = playerCam.depth - 1f;
((Behaviour)cam).enabled = false;
}
cam.cullingMask = playerCam.cullingMask;
cam.clearFlags = playerCam.clearFlags;
cam.backgroundColor = playerCam.backgroundColor;
cam.nearClipPlane = playerCam.nearClipPlane;
cam.farClipPlane = playerCam.farClipPlane;
cam.aspect = 1f;
cam.targetTexture = rt;
}
private static RenderTextureFormat OpaqueFormat()
{
if (!SystemInfo.SupportsRenderTextureFormat((RenderTextureFormat)22))
{
return (RenderTextureFormat)4;
}
return (RenderTextureFormat)22;
}
private float SidePixels()
{
return (float)Screen.height * viewportSize.Value;
}
private bool EnsureHud(ENT_Player player)
{
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Expected O, but got Unknown
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Expected O, but got Unknown
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
//IL_028b: Unknown result type (might be due to invalid IL or missing references)
//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
//IL_0329: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)hudRoot != (Object)null && (Object)(object)hudCanvas != (Object)null)
{
return true;
}
Image val = null;
if (player.hands != null)
{
Hand[] hands = player.hands;
foreach (Hand val2 in hands)
{
if (val2 != null && (Object)(object)val2.uiInteract != (Object)null)
{
val = val2.uiInteract;
break;
}
}
}
if ((Object)(object)val == (Object)null || (Object)(object)((Graphic)val).canvas == (Object)null)
{
return false;
}
hudCanvas = ((Graphic)val).canvas.rootCanvas;
Transform transform = ((Component)hudCanvas).transform;
Transform val3 = ((Component)val).transform;
while ((Object)(object)val3.parent != (Object)null && (Object)(object)val3.parent != (Object)(object)transform)
{
val3 = val3.parent;
}
int num = (((Object)(object)val3.parent == (Object)(object)transform) ? val3.GetSiblingIndex() : 0);
CL_GameManager gMan = CL_GameManager.gMan;
if ((Object)(object)gMan != (Object)null && (Object)(object)gMan.pauseMenu != (Object)null && gMan.pauseMenu.transform.IsChildOf(transform))
{
Transform val4 = gMan.pauseMenu.transform;
while ((Object)(object)val4.parent != (Object)null && (Object)(object)val4.parent != (Object)(object)transform)
{
val4 = val4.parent;
}
if ((Object)(object)val4.parent == (Object)(object)transform)
{
num = Mathf.Min(num, val4.GetSiblingIndex());
}
}
GameObject val5 = new GameObject("FaceCam_HUD", new Type[1] { typeof(RectTransform) });
hudRoot = (RectTransform)val5.transform;
((Transform)hudRoot).SetParent(transform, false);
((Transform)hudRoot).SetSiblingIndex(num);
val5.layer = ((Component)val3).gameObject.layer;
border = NewChild<Image>("Border", (Transform)(object)hudRoot);
((Graphic)border).raycastTarget = false;
Stretch(((Graphic)border).rectTransform, 0f);
feed = NewChild<RawImage>("Feed", (Transform)(object)hudRoot);
((Graphic)feed).raycastTarget = false;
feed.texture = (Texture)(object)rt;
Image val6 = NewChild<Image>("NameTag", (Transform)(object)((Graphic)feed).rectTransform);
((Graphic)val6).raycastTarget = false;
((Graphic)val6).color = new Color(0f, 0f, 0f, 0.55f);
tagRoot = ((Graphic)val6).rectTransform;
tagRoot.anchorMin = new Vector2(0f, 0f);
tagRoot.anchorMax = new Vector2(1f, 0f);
tagRoot.pivot = new Vector2(0.5f, 0f);
tagRoot.anchoredPosition = Vector2.zero;
tagText = NewChild<TextMeshProUGUI>("Text", (Transform)(object)tagRoot);
((Graphic)tagText).raycastTarget = false;
((TMP_Text)tagText).alignment = (TextAlignmentOptions)514;
((TMP_Text)tagText).textWrappingMode = (TextWrappingModes)0;
((TMP_Text)tagText).overflowMode = (TextOverflowModes)1;
((Graphic)tagText).color = Color.white;
Stretch(((TMP_Text)tagText).rectTransform, 0f);
ApplySubtitleFont(tagText);
liveFontApplied = false;
((BaseUnityPlugin)this).Logger.LogInfo((object)$"FaceCam HUD attached to canvas '{((Object)hudCanvas).name}' at index {num} (before '{((Object)val3).name}').");
return true;
}
private void ApplySubtitleFont(TextMeshProUGUI text)
{
CL_UIManager val = CL_UIManager.instance;
TMP_Text val2 = (((Object)(object)val != (Object)null && (Object)(object)val.subtitleObject != (Object)null) ? val.subtitleObject.text : null);
if ((Object)(object)val2 != (Object)null && (Object)(object)val2.font != (Object)null)
{
CopyFont(val2, (TMP_Text)(object)text, "subtitle template");
}
else
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"Subtitle font not found; the name tag uses the default TMP font.");
}
}
private void TryApplyLiveSubtitleFont()
{
if (liveFontApplied || Time.unscaledTime < nextLiveFontCheck)
{
return;
}
nextLiveFontCheck = Time.unscaledTime + 1f;
CL_UIManager val = CL_UIManager.instance;
if ((Object)(object)val == (Object)null || (Object)(object)val.subtitleParent == (Object)null)
{
return;
}
UI_Subtitle[] componentsInChildren = ((Component)val.subtitleParent).GetComponentsInChildren<UI_Subtitle>(false);
foreach (UI_Subtitle val2 in componentsInChildren)
{
if (!((Object)(object)val2.text == (Object)null) && !((Object)(object)val2.text.font == (Object)null) && !string.IsNullOrEmpty(val2.text.text))
{
CopyFont(val2.text, (TMP_Text)(object)tagText, "live subtitle");
liveFontApplied = true;
break;
}
}
}
private void CopyFont(TMP_Text from, TMP_Text to, string source)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
to.font = from.font;
to.fontSharedMaterial = from.fontSharedMaterial;
to.fontStyle = from.fontStyle;
to.characterSpacing = from.characterSpacing;
ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
string[] obj = new string[7]
{
"Name tag font from ",
source,
": '",
((Object)from.font).name,
"', material '",
null,
null
};
Material fontSharedMaterial = from.fontSharedMaterial;
obj[5] = ((fontSharedMaterial != null) ? ((Object)fontSharedMaterial).name : null);
obj[6] = "'.";
logger.LogInfo((object)string.Concat(obj));
}
private static T NewChild<T>(string name, Transform parent) where T : Component
{
//IL_0014: 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_002a: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) })
{
layer = ((Component)parent).gameObject.layer
};
val.transform.SetParent(parent, false);
return val.AddComponent<T>();
}
private static void Stretch(RectTransform r, float inset)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: 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_0028: Unknown result type (might be due to invalid IL or missing references)
r.anchorMin = Vector2.zero;
r.anchorMax = Vector2.one;
r.offsetMin = new Vector2(inset, inset);
r.offsetMax = new Vector2(0f - inset, 0f - inset);
}
private void LayoutHud()
{
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
float num = ((hudCanvas.scaleFactor > 0f) ? hudCanvas.scaleFactor : 1f);
float num2 = SidePixels() / num;
float num3 = margin.Value / num;
float num4 = borderThickness.Value / num;
bool flag = corner.Value == Corner.TopLeft || corner.Value == Corner.BottomLeft;
bool flag2 = corner.Value == Corner.TopLeft || corner.Value == Corner.TopRight;
Vector2 val = default(Vector2);
((Vector2)(ref val))..ctor(flag ? 0f : 1f, flag2 ? 1f : 0f);
hudRoot.anchorMin = val;
hudRoot.anchorMax = val;
hudRoot.pivot = val;
hudRoot.sizeDelta = new Vector2(num2 + 2f * num4, num2 + 2f * num4);
hudRoot.anchoredPosition = new Vector2(flag ? num3 : (0f - num3), flag2 ? (0f - num3) : num3) + shakeOffset / num;
((Graphic)border).color = borderColor.Value;
Stretch(((Graphic)feed).rectTransform, num4);
float num5 = num2 * 0.12f;
tagRoot.sizeDelta = new Vector2(0f, num5);
((TMP_Text)tagText).fontSize = num5 * 0.62f;
}
private void UpdateTag()
{
TryApplyLiveSubtitleFont();
bool flag = (showName.Value || showDistance.Value) && hasThreat;
((Component)tagRoot).gameObject.SetActive(flag);
if (flag)
{
string text = (showName.Value ? current.Name : "");
if (showDistance.Value)
{
text = (showName.Value ? $"{text} {current.Distance:0}m" : $"{current.Distance:0}m");
}
if (((TMP_Text)tagText).text != text)
{
((TMP_Text)tagText).text = text;
}
}
}
private void OnDestroy()
{
if ((Object)(object)cam != (Object)null)
{
Object.Destroy((Object)(object)((Component)cam).gameObject);
}
if ((Object)(object)hudRoot != (Object)null)
{
Object.Destroy((Object)(object)((Component)hudRoot).gameObject);
}
if ((Object)(object)rt != (Object)null)
{
rt.Release();
Object.Destroy((Object)(object)rt);
}
}
}
[HarmonyPatch(typeof(DEN_Remains_Active), "Update")]
internal static class RemainsVisibilityPatch
{
private static readonly MethodInfo IsVisibleGetter = AccessTools.PropertyGetter(typeof(Renderer), "isVisible");
private static readonly MethodInfo Replacement = AccessTools.Method(typeof(RemainsVisibilityPatch), "SeenByPlayer", (Type[])null, (Type[])null);
private static readonly Plane[] Planes = (Plane[])(object)new Plane[6];
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
int replaced = 0;
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, IsVisibleGetter))
{
replaced++;
instruction.opcode = OpCodes.Call;
instruction.operand = Replacement;
}
yield return instruction;
}
if (replaced == 0)
{
FaceCamPlugin.Log.LogWarning((object)"Remains patch: isVisible call not found; Remains may freeze while on FaceCam.");
}
}
private static bool SeenByPlayer(Renderer renderer)
{
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
if (!renderer.isVisible)
{
return false;
}
if (!FaceCamPlugin.Rendering)
{
return true;
}
ENT_Player playerObject = ENT_Player.playerObject;
Camera val = (((Object)(object)playerObject != (Object)null) ? playerObject.cam : null);
if ((Object)(object)val == (Object)null)
{
return true;
}
GeometryUtility.CalculateFrustumPlanes(val, Planes);
return GeometryUtility.TestPlanesAABB(Planes, renderer.bounds);
}
}
}