Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Better First Person v1.1.2
BetterFirstPerson.dll
Decompiled 12 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using On.EntityStates; using On.RoR2; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using TMPro; using Unity.Collections; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace BetterFirstPerson; internal static class EmotesSupport { private const string EmotesGuid = "com.weliveinasociety.CustomEmotesAPI"; private const BindingFlags Static = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags Instance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static bool looked; private static MemberInfo localMapper; private static MemberInfo clipName; private static Type clipOwner; public static bool IsLocalEmotePlaying() { if (!looked) { Look(); } if (localMapper == null) { return false; } try { object obj = Read(localMapper, null); if (obj != null) { Object val = (Object)((obj is Object) ? obj : null); if (val == null || Object.op_Implicit(val)) { Type type = obj.GetType(); if (clipName == null || clipOwner != type) { clipOwner = type; clipName = Member(type, "currentClipName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (clipName == null) { return false; } } string text = Read(clipName, obj) as string; return !string.IsNullOrEmpty(text) && text != "none"; } } return false; } catch (Exception) { return false; } } private static void Look() { looked = true; try { if (Chainloader.PluginInfos.TryGetValue("com.weliveinasociety.CustomEmotesAPI", out var value) && Object.op_Implicit((Object)(object)value.Instance)) { Type type = ((object)value.Instance).GetType().Assembly.GetType("EmotesAPI.CustomEmotesAPI", throwOnError: false); if (type != null) { localMapper = Member(type, "localMapper", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("CustomEmotesAPI found but not readable: " + ex.Message)); } } private static MemberInfo Member(Type type, string name, BindingFlags flags) { FieldInfo field = type.GetField(name, flags); if (field != null) { return field; } return type.GetProperty(name, flags); } private static object Read(MemberInfo member, object target) { if (member is FieldInfo fieldInfo) { return fieldInfo.GetValue(target); } if (member is PropertyInfo propertyInfo) { return propertyInfo.GetValue(target, null); } return null; } } internal static class FieldOfView { private const float MaxWidening = 1.41f; private static float TanHalf(float fov) { return Mathf.Tan(fov * 0.5f * ((float)Math.PI / 180f)); } public static float VerticalToHorizontal(float verticalFov, float aspect) { return 2f * Mathf.Atan(TanHalf(verticalFov) * aspect) * 57.29578f; } public static float Compute(CameraRigController rig, float gameFov, float aspect, out float baseFov) { //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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_006f: Unknown result type (might be due to invalid IL or missing references) baseFov = (Object.op_Implicit((Object)(object)rig) ? rig.baseFov : 60f); CameraTargetParams val = (Object.op_Implicit((Object)(object)rig) ? rig.targetParams : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.cameraParams)) { CharacterCameraParamsData basic = CharacterCameraParamsData.basic; CharacterCameraParamsData.Blend(ref val.cameraParams.data, ref basic, 1f); if (basic.fov.value > 1f) { baseFov = basic.fov.value; } } float num = TanHalf(Mathf.Clamp(Settings.FieldOfView.Value, 30f, 170f)) / Mathf.Max(aspect, 0.01f); if (gameFov < 1f || baseFov < 1f) { return 2f * Mathf.Atan(num) * 57.29578f; } float num2 = TanHalf(gameFov) / TanHalf(baseFov); if (num2 > 1f) { float num3 = Mathf.Clamp01(Settings.SprintFovEffect.Value); num2 = 1f + (Mathf.Min(num2, 1.41f) - 1f) * num3; } return Mathf.Clamp(2f * Mathf.Atan(num * num2) * 57.29578f, 1f, 170f); } } internal static class FirstPersonController { private static bool wanted; private static CharacterBody lastBody; private static CharacterBody failedBody; private static float lastSteerTime = -1f; public static FirstPersonSession Session { get; private set; } public static void Install() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown PlayerCharacterMasterController.Update += new hook_Update(PlayerUpdate); CameraRigController.SetCameraState += new hook_SetCameraState(SetCameraState); GenericCharacterMain.HandleMovements += new hook_HandleMovements(HandleMovements); CharacterModel.UpdateMaterials += new hook_UpdateMaterials(UpdateMaterials); CharacterModel.UpdateOverlays += new hook_UpdateOverlays(UpdateOverlays); GenericSkill.OnExecute += new hook_OnExecute(SkillExecuted); Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(PreCull)); Run.onRunDestroyGlobal += delegate { EndSession(); }; Application.quitting += FirstPersonVisuals.OnQuit; } private static void PlayerUpdate(orig_Update orig, PlayerCharacterMasterController self) { //IL_0160: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); NetworkUser networkUser = self.networkUser; LocalUser val = (Object.op_Implicit((Object)(object)networkUser) ? networkUser.localUser : null); if (val == null || val != LocalUserManager.GetFirstLocalUser()) { return; } CameraRigController cameraRigController = networkUser.cameraRigController; if (!Object.op_Implicit((Object)(object)cameraRigController)) { return; } CharacterMaster master = self.master; CharacterBody val2 = (Object.op_Implicit((Object)(object)master) ? master.GetBody() : null); if (Object.op_Implicit((Object)(object)val2) && val2 != lastBody) { if (lastBody != null && !Settings.RememberFirstPerson.Value) { wanted = false; } lastBody = val2; failedBody = null; } if (ToggleKeyPressed() && !PauseManager.isPaused && !IsTyping(val)) { wanted = ((Object.op_Implicit((Object)(object)val2) && CanRun(val2, cameraRigController)) ? (Session == null) : (!wanted)); failedBody = null; } bool flag = wanted && Object.op_Implicit((Object)(object)val2) && val2 != failedBody && CanRun(val2, cameraRigController); FirstPersonSession firstPersonSession = Session; if (firstPersonSession != null && (!flag || firstPersonSession.Body != val2 || firstPersonSession.Rig != cameraRigController)) { EndSession(); firstPersonSession = null; } if (firstPersonSession == null && flag) { firstPersonSession = StartSession(val2, cameraRigController); if (firstPersonSession == null) { failedBody = val2; } } if (firstPersonSession != null) { InputBankTest inputBank = val2.inputBank; if (Object.op_Implicit((Object)(object)inputBank)) { inputBank.aimDirection = firstPersonSession.ViewForward; } if (Settings.BodyRotation.Value == BodyTurning.Smart) { val2.SetAimTimer(0.2f); } } } private static bool CanRun(CharacterBody body, CameraRigController rig) { HealthComponent healthComponent = body.healthComponent; if (!Object.op_Implicit((Object)(object)healthComponent) || !healthComponent.alive) { return false; } if (rig.target != ((Component)body).gameObject || rig.hasOverride) { return false; } VehicleSeat currentVehicle = body.currentVehicle; if (Object.op_Implicit((Object)(object)currentVehicle) && (currentVehicle.hidePassenger || currentVehicle.isSurvivorPod)) { return false; } if (Settings.ThirdPersonWhileEmoting.Value && EmotesSupport.IsLocalEmotePlaying()) { return false; } return true; } private static bool ToggleKeyPressed() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Settings.ToggleKey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; if ((int)mainKey == 0 || !UnityInput.Current.GetKeyDown(mainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!UnityInput.Current.GetKey(modifier)) { return false; } } return true; } private static bool IsTyping(LocalUser localUser) { EventSystem eventSystem = (EventSystem)(object)localUser.eventSystem; GameObject val = (Object.op_Implicit((Object)(object)eventSystem) ? eventSystem.currentSelectedGameObject : null); if (!Object.op_Implicit((Object)(object)val)) { return false; } TMP_InputField component = val.GetComponent<TMP_InputField>(); if (Object.op_Implicit((Object)(object)component) && component.isFocused) { return true; } InputField component2 = val.GetComponent<InputField>(); if (Object.op_Implicit((Object)(object)component2)) { return component2.isFocused; } return false; } private static FirstPersonSession StartSession(CharacterBody body, CameraRigController rig) { try { Session = FirstPersonSession.Start(body, rig); } catch (Exception ex) { Plugin.Log.LogError((object)("First person could not start: " + ex)); Session = null; } return Session; } public static void EndSession() { FirstPersonSession session = Session; Session = null; if (session == null) { return; } try { session.End(); } catch (Exception ex) { Plugin.Log.LogError((object)("Leaving first person failed: " + ex)); } } private static void Fail(Exception exception) { Plugin.Log.LogError((object)("First person stopped after an error, press the key to try again: " + exception)); failedBody = ((Session != null) ? Session.Body : null); EndSession(); } private static void SetCameraState(orig_SetCameraState orig, CameraRigController self, CameraState cameraState) { //IL_0002: 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) orig.Invoke(self, cameraState); FirstPersonSession session = Session; if (session == null || session.Rig != self) { return; } try { session.AfterRigCameraState(cameraState.fov); } catch (Exception exception) { Fail(exception); } } private static void PreCull(Camera camera) { FirstPersonSession session = Session; if (session == null || session.Camera != camera) { return; } try { session.OnPreCull(); } catch (Exception exception) { Fail(exception); } } private static void UpdateMaterials(orig_UpdateMaterials orig, CharacterModel self) { orig.Invoke(self); if (Session != null) { FirstPersonVisuals.AfterModelMaterialsUpdated(self); } } private static void UpdateOverlays(orig_UpdateOverlays orig, CharacterModel self) { orig.Invoke(self); FirstPersonSession session = Session; if (session != null && self == session.CharacterModel && Settings.HideOwnBursts.Value) { FirstPersonVisuals.StripOverlays(self); } } private static void SkillExecuted(orig_OnExecute orig, GenericSkill self) { orig.Invoke(self); FirstPersonSession session = Session; if (session != null && self.characterBody == session.Body) { FirstPersonVisuals.OnSkillExecuted(self); } } private static void HandleMovements(orig_HandleMovements orig, GenericCharacterMain self) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); FirstPersonSession session = Session; if (session == null || Settings.BodyRotation.Value != BodyTurning.FollowCamera || !session.OwnsStateMachine(((EntityState)self).outer)) { return; } CharacterBody body = session.Body; CharacterDirection val = (Object.op_Implicit((Object)(object)body) ? body.characterDirection : null); InputBankTest val2 = (Object.op_Implicit((Object)(object)body) ? body.inputBank : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2)) { Vector3 aimDirection = val2.aimDirection; aimDirection.y = 0f; if (!(((Vector3)(ref aimDirection)).sqrMagnitude < 0.0001f)) { val.moveVector = ((Vector3)(ref aimDirection)).normalized; lastSteerTime = Time.fixedTime; } } } internal static bool SnapBodyYaw(FirstPersonSession session, float yaw) { if (Settings.BodyRotation.Value != BodyTurning.FollowCamera) { return false; } if (Time.fixedTime - lastSteerTime > Time.fixedDeltaTime * 2f) { return false; } CharacterDirection val = (Object.op_Implicit((Object)(object)session.Body) ? session.Body.characterDirection : null); if (!Object.op_Implicit((Object)(object)val)) { return false; } val.yaw = yaw; return true; } } internal sealed class FirstPersonSession { private static readonly HashSet<int> logged = new HashSet<int>(); public readonly CharacterBody Body; public readonly GameObject BodyObject; public readonly CameraRigController Rig; public readonly Camera Camera; public readonly Transform Model; public readonly CharacterModel CharacterModel; public readonly ChildLocator Locator; public readonly HeadAnchor Head; public readonly string BodyName; public readonly SurvivorSettings Survivor; public readonly int HideLayer; private readonly EntityStateMachine[] stateMachines; private readonly WeaponPose weaponPose; private readonly Transform cameraTransform; private readonly bool cameraIsChild; private readonly Vector3 cameraLocalPosition; private readonly Quaternion cameraLocalRotation; private readonly float originalNearClip; private readonly bool hideLayerWasDrawn; private readonly bool originalFading; private readonly Transform aimOrigin; private readonly Vector3 aimOriginLocalPosition; private readonly AimAnimator aimAnimator; private bool aimDiagnosticBroken; private float lastGameFov; private bool fovLogged; private Vector3 steadyOffset; private bool steadyValid; private float steadyTime; public Vector3 ViewForward => cameraTransform.forward; private FirstPersonSession(CharacterBody body, CameraRigController rig, Camera camera, Transform model, HeadAnchor head, string bodyName, SurvivorSettings survivor) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) Body = body; BodyObject = ((Component)body).gameObject; Rig = rig; Camera = camera; Model = model; CharacterModel = ((Component)model).GetComponent<CharacterModel>(); Locator = ((Component)model).GetComponent<ChildLocator>(); Head = head; BodyName = bodyName; Survivor = survivor; stateMachines = ((Component)body).GetComponents<EntityStateMachine>(); cameraTransform = ((Component)camera).transform; cameraIsChild = (Object)(object)cameraTransform != (Object)(object)((Component)rig).transform; cameraLocalPosition = cameraTransform.localPosition; cameraLocalRotation = cameraTransform.localRotation; originalNearClip = camera.nearClipPlane; originalFading = rig.enableFading; aimOrigin = body.aimOriginTransform; aimOriginLocalPosition = (Object.op_Implicit((Object)(object)aimOrigin) ? aimOrigin.localPosition : Vector3.zero); HideLayer = FindHideLayer(); hideLayerWasDrawn = HideLayer >= 0 && (camera.cullingMask & (1 << HideLayer)) != 0; weaponPose = WeaponPose.Build(model, head.Transform, Locator, head.Radius); aimAnimator = ((Component)model).GetComponent<AimAnimator>(); } public static FirstPersonSession Start(CharacterBody body, CameraRigController rig) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) Camera sceneCam = rig.sceneCam; ModelLocator component = ((Component)body).GetComponent<ModelLocator>(); Transform val = (Object.op_Implicit((Object)(object)component) ? component.modelTransform : null); if (!Object.op_Implicit((Object)(object)sceneCam) || !Object.op_Implicit((Object)(object)val)) { return null; } string text = BodyCatalog.GetBodyName(body.bodyIndex); if (string.IsNullOrEmpty(text)) { text = ((Object)body).name.Replace("(Clone)", ""); } SurvivorSettings survivorSettings = Settings.ForSurvivor(text); HeadAnchor headAnchor = HeadFinder.Find(body, val, survivorSettings?.HeadPath.Value); if (headAnchor == null) { Plugin.Log.LogWarning((object)("No head found on " + text + ": set its Head Path in the survivor settings")); return null; } FirstPersonSession firstPersonSession = new FirstPersonSession(body, rig, sceneCam, val, headAnchor, text, survivorSettings); firstPersonSession.Begin(); return firstPersonSession; } private void Begin() { Rig.enableFading = false; if (hideLayerWasDrawn) { Camera camera = Camera; camera.cullingMask &= ~(1 << HideLayer); } if (logged.Add(((Object)Body).GetInstanceID())) { Plugin.Log.LogInfo((object)("First person on " + BodyName + ": eyes at " + Head.Source + ", head size " + Head.Radius.ToString("0.000") + " m, head bone " + (Object.op_Implicit((Object)(object)Head.Bone) ? ("'" + ((Object)Head.Bone).name + "'") : "none") + ", " + Head.Eyes.Length + " eye bones; weapon lowering moves " + weaponPose.Description + ((HideLayer >= 0) ? ("; faded parts go to layer " + HideLayer) : ""))); } FirstPersonVisuals.Begin(this); } public void End() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) try { FirstPersonVisuals.End(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Restoring the weapon and items failed: " + ex.Message)); } try { weaponPose.Release(); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Restoring the arms failed: " + ex2.Message)); } if (Object.op_Implicit((Object)(object)aimOrigin)) { aimOrigin.localPosition = aimOriginLocalPosition; } if (Object.op_Implicit((Object)(object)Camera)) { Camera.nearClipPlane = originalNearClip; if (hideLayerWasDrawn) { Camera camera = Camera; camera.cullingMask |= 1 << HideLayer; } if (lastGameFov > 1f) { Camera.fieldOfView = lastGameFov; } if (cameraIsChild) { cameraTransform.localPosition = cameraLocalPosition; cameraTransform.localRotation = cameraLocalRotation; } } if (Object.op_Implicit((Object)(object)Rig)) { Rig.enableFading = originalFading; } } public bool OwnsStateMachine(EntityStateMachine stateMachine) { EntityStateMachine[] array = stateMachines; for (int i = 0; i < array.Length; i++) { if (array[i] == stateMachine) { return true; } } return false; } public void AfterRigCameraState(float gameFov) { //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) lastGameFov = gameFov; float baseFov; float num = FieldOfView.Compute(Rig, gameFov, Camera.aspect, out baseFov); Camera.fieldOfView = num; Camera.nearClipPlane = Settings.NearClip.Value; if (!fovLogged) { fovLogged = true; Plugin.Log.LogInfo((object)("First person FOV: game " + gameFov.ToString("0.0") + " (base " + baseFov.ToString("0.0") + "), aspect " + Camera.aspect.ToString("0.000") + ", applied vertical " + num.ToString("0.0") + " = horizontal " + FieldOfView.VerticalToHorizontal(num, Camera.aspect).ToString("0.0"))); } float y = cameraTransform.eulerAngles.y; bool num2 = FirstPersonController.SnapBodyYaw(this, y); InputBankTest val = (Object.op_Implicit((Object)(object)Body) ? Body.inputBank : null); if (Object.op_Implicit((Object)(object)val)) { val.aimDirection = cameraTransform.forward; } float sway = (num2 ? Settings.WeaponSway.Value : 0f); weaponPose.Apply((Survivor != null) ? Survivor.WeaponLowering.Value : 0f, y, sway); RecordAim(); PlaceCamera(); } private void RecordAim() { if (aimDiagnosticBroken || !Object.op_Implicit((Object)(object)aimAnimator) || !((Behaviour)aimAnimator).enabled) { return; } try { RecordAimFrom(aimAnimator); } catch (Exception) { aimDiagnosticBroken = true; } } [MethodImpl(MethodImplOptions.NoInlining)] private void RecordAimFrom(AimAnimator animator) { FirstPersonVisuals.RecordAim(animator.currentLocalAngles.yaw, weaponPose.SwayDegrees); } public void OnPreCull() { PlaceCamera(); FirstPersonVisuals.OnPreCull(Camera); } private void PlaceCamera() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_00d2: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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) //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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0186: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Head.Transform)) { return; } Vector3 eulerAngles = cameraTransform.eulerAngles; float y = eulerAngles.y; float num = Mathf.DeltaAngle(0f, eulerAngles.x); Vector3 center = Head.Center; float radius = Head.Radius; Vector3 val = Quaternion.Euler(0f, y, 0f) * Vector3.forward; float num2 = Mathf.Max(0f, Settings.LookDownPush.Value) * Mathf.Clamp01((num - 15f) / 55f); float num3 = Mathf.Max(0f, Settings.ForwardOffset.Value); float num4 = radius * num3; if (num3 > 0f && Head.Eyes.Length != 0) { num4 = Mathf.Max(num4, Head.EyesAhead(center, val) + 0.03f); } float num5 = num4 + radius * num2; float num6 = ((Survivor != null) ? (Survivor.CameraHeight.Value * 0.01f) : 0f); Vector3 val2 = Steady(center, y, radius) + val * num5 + Vector3.up * num6; Vector3 val3 = val2 - center; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude > 0.0001f) { float num7 = Camera.nearClipPlane + 0.02f; Vector3 val4 = val3 / magnitude; float num8 = magnitude + num7; LayerIndex world = LayerIndex.world; RaycastHit val5 = default(RaycastHit); if (Physics.Raycast(center, val4, ref val5, num8, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1)) { val2 = center + val4 * Mathf.Max(0f, ((RaycastHit)(ref val5)).distance - num7); } } cameraTransform.position = val2; if (Object.op_Implicit((Object)(object)aimOrigin) && Body.aimOriginTransform == aimOrigin) { aimOrigin.position = val2; } } private Vector3 Steady(Vector3 center, float yaw, float radius) { //IL_001c: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Model)) { steadyValid = false; return center; } Vector3 position = Model.position; Quaternion val = Quaternion.Euler(0f, yaw, 0f); Vector3 val2 = Quaternion.Inverse(val) * (center - position); float num = Mathf.Clamp01(Settings.Stabilization.Value); float time = Time.time; float num2 = (steadyValid ? (time - steadyTime) : 0f); if (!steadyValid || num <= 0f) { steadyOffset = val2; } else { if (num2 > 0f) { steadyOffset = Vector3.Lerp(steadyOffset, val2, 1f - Mathf.Exp((0f - num2) / (0.3f * num))); } Vector3 val3 = steadyOffset - val2; float num3 = radius * num; val3.x = Mathf.Clamp(val3.x, -0.8f * num3, 0.8f * num3); val3.y = Mathf.Clamp(val3.y, -0.4f * num3, 0.8f * num3); val3.z = Mathf.Clamp(val3.z, -0.25f * num3, 1.25f * num3); steadyOffset = val2 + val3; } steadyValid = true; steadyTime = time; if (num2 > 0f) { FirstPersonVisuals.RecordSway(val2, steadyOffset, num2); } return position + val * steadyOffset; } private static int FindHideLayer() { int intVal = LayerIndex.noDraw.intVal; if (intVal >= 0 && intVal < 32) { return intVal; } for (int num = 31; num >= 8; num--) { if (string.IsNullOrEmpty(LayerMask.LayerToName(num))) { return num; } } return -1; } } internal static class FirstPersonVisuals { private sealed class FadeRenderer { public Renderer renderer; public SkinnedMeshRenderer skinned; public MeshFilter meshFilter; public bool measurable; public bool dither; public bool layerSafe; public int subMeshCount = 1; public bool applied; public bool hidden; public int originalLayer; } private sealed class FadeGroup { public string name; public bool isItem; public bool headgear; public bool fx; public bool wasDrawn; public bool awaitingMeasure; public ItemDisplay itemDisplay; public readonly List<FadeRenderer> renderers = new List<FadeRenderer>(); public float coverage; public float boxCoverage; public bool measured; public float alpha = 1f; public float time; public float coverageSum; public float coverageMax; public float fadedTime; public readonly float[] histogram = new float[10]; } private sealed class PendingReadback { public readonly FadeGroup[] mapping = new FadeGroup[8]; public int tiles; public int height; public int generation; public int frame; public bool busy; public Action<AsyncGPUReadbackRequest> callback; } private enum MeasureMode { Render, Box } private const int TileWidth = 64; private const int MaxTiles = 8; private const float ItemThresholdScale = 0.5f; private const float BodyFadeStart = 0.8f; private const float BodyFadeFull = 0.95f; private const float FadeOutTime = 0.1f; private const float FadeInTime = 0.25f; private const string FullBodyLayerName = "FullBody, Override"; private const float SkillHideOutTime = 0.05f; private const float SkillAnimationDelay = 0.5f; private static readonly List<FadeGroup> weaponGroups = new List<FadeGroup>(); private static readonly List<FadeRenderer> followers = new List<FadeRenderer>(); private static readonly List<FadeRenderer> headgear = new List<FadeRenderer>(); private static readonly List<FadeGroup> items = new List<FadeGroup>(); private static readonly Dictionary<ItemDisplay, FadeGroup> itemGroups = new Dictionary<ItemDisplay, FadeGroup>(); private static readonly Dictionary<SkinnedMeshRenderer, bool> boundsOverrides = new Dictionary<SkinnedMeshRenderer, bool>(); private static readonly HashSet<int> describedBodies = new HashSet<int>(); private static readonly List<ItemDisplay> displayBuffer = new List<ItemDisplay>(); private static readonly MaterialPropertyBlock block = new MaterialPropertyBlock(); private static readonly int fadeId = Shader.PropertyToID("_Fade"); private static readonly PendingReadback[] readbacks = CreateReadbacks(6); private static readonly Vector3[] corners = (Vector3[])(object)new Vector3[8]; private static readonly Vector2[] points = (Vector2[])(object)new Vector2[24]; private static readonly Vector2[] hull = (Vector2[])(object)new Vector2[48]; private static readonly Vector2[] clipA = (Vector2[])(object)new Vector2[64]; private static readonly Vector2[] clipB = (Vector2[])(object)new Vector2[64]; private static FirstPersonSession session; private static CharacterBody body; private static CharacterModel model; private static Transform modelTransform; private static Animator animator; private static AnimatorCullingMode animatorCulling; private static Camera camera; private static string bodyName = ""; private static FadeGroup bodyGroup; private static int classifyFrame = -1; private static int lastFrame = -1; private static float nextItemRefresh; private static float nextStatsLog; private static int generation; private static bool failed; private static int hideLayer = -1; private static MeasureMode mode = MeasureMode.Render; private static bool renderResourcesTried; private static bool renderVerified; private static int checkVisibleFrames; private static Material coverageMaterial; private static RenderTexture coverageTexture; private static CommandBuffer commandBuffer; private static int tileHeight; private static int readbackCursor; private static int weaponCursor; private static int itemCursor; private static Vector3 boxCameraPosition; private static Quaternion boxToCamera; private static float boxTanH; private static float boxTanV; private static float boxNear; private static bool swayValid; private static float swayTime; private static float swayHead; private static float swayCamera; private static Vector3 lastHeadOffset; private static Vector3 lastCameraOffset; private static float modelAlpha = 1f; private static int fullBodyLayer = -1; private static bool fullBodyPlaying; private static bool skillHide; private static GenericSkill lastSkill; private static float lastSkillTime = -10f; private static bool skillStarted; private static int skillHides; private static float skillHiddenTime; private static int burstsHidden; private static readonly HashSet<int> strippedOverlays = new HashSet<int>(); private static bool overlaysBroken; private static bool aimValid; private static float lastAimYaw; private static int aimFrames; private static int aimJumps; private static float aimTime; private static float aimSum; private static float aimMax; private static float swayMax; public static void Begin(FirstPersonSession newSession) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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) End(); failed = false; session = newSession; body = session.Body; camera = session.Camera; bodyName = session.BodyName; hideLayer = session.HideLayer; modelTransform = session.Model; model = session.CharacterModel; if (!Object.op_Implicit((Object)(object)model) || model.baseRendererInfos == null) { model = null; return; } RendererInfo[] baseRendererInfos = model.baseRendererInfos; for (int i = 0; i < baseRendererInfos.Length; i++) { Renderer renderer = baseRendererInfos[i].renderer; SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val != null) { OverrideBoundsUpdate(val); } } animator = ((Component)modelTransform).GetComponent<Animator>(); if (Object.op_Implicit((Object)(object)animator)) { animatorCulling = animator.cullingMode; animator.cullingMode = (AnimatorCullingMode)0; fullBodyLayer = animator.GetLayerIndex("FullBody, Override"); } classifyFrame = Time.frameCount + 1; checkVisibleFrames = 0; } public static void End() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) LogStats(final: true); generation++; try { RestoreAll(); foreach (KeyValuePair<SkinnedMeshRenderer, bool> boundsOverride in boundsOverrides) { if (Object.op_Implicit((Object)(object)boundsOverride.Key)) { boundsOverride.Key.updateWhenOffscreen = boundsOverride.Value; } } if (Object.op_Implicit((Object)(object)animator)) { animator.cullingMode = animatorCulling; } if (Object.op_Implicit((Object)(object)model) && strippedOverlays.Count > 0) { RefreshOverlays(model); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Restoring first person visuals failed: " + ex.Message)); } boundsOverrides.Clear(); weaponGroups.Clear(); followers.Clear(); headgear.Clear(); items.Clear(); itemGroups.Clear(); bodyGroup = null; session = null; body = null; model = null; modelTransform = null; animator = null; camera = null; classifyFrame = -1; lastFrame = -1; swayValid = false; swayTime = 0f; swayHead = 0f; swayCamera = 0f; aimValid = false; aimFrames = 0; aimJumps = 0; aimTime = 0f; aimSum = 0f; aimMax = 0f; swayMax = 0f; modelAlpha = 1f; fullBodyLayer = -1; fullBodyPlaying = false; skillHide = false; lastSkill = null; lastSkillTime = -10f; skillStarted = false; skillHides = 0; skillHiddenTime = 0f; burstsHidden = 0; strippedOverlays.Clear(); } public static void OnQuit() { LogStats(final: true); } private static void RestoreAll() { foreach (FadeGroup weaponGroup in weaponGroups) { RestoreGroup(weaponGroup); } foreach (FadeRenderer follower in followers) { if (follower.applied && Object.op_Implicit((Object)(object)follower.renderer)) { Restore(follower); } } foreach (FadeRenderer item in headgear) { if (item.applied && Object.op_Implicit((Object)(object)item.renderer)) { Restore(item); } } if (bodyGroup != null) { RestoreGroup(bodyGroup); } foreach (FadeGroup item2 in items) { RestoreGroup(item2); } } private static void Fail(Exception exception) { Plugin.Log.LogError((object)("First person visuals stopped until first person is entered again: " + exception)); failed = true; try { RestoreAll(); } catch { } } public static void OnPreCull(Camera cam) { if (cam != camera || failed || lastFrame == Time.frameCount) { return; } lastFrame = Time.frameCount; try { if (!Object.op_Implicit((Object)(object)model)) { return; } if (classifyFrame >= 0) { if (Time.frameCount < classifyFrame) { return; } classifyFrame = -1; Classify(); } UpdateFade(cam); } catch (Exception exception) { Fail(exception); } } public static void AfterModelMaterialsUpdated(CharacterModel updated) { if (updated != model || failed) { return; } foreach (FadeGroup weaponGroup in weaponGroups) { ReapplyFade(weaponGroup); } if (bodyGroup != null) { ReapplyFade(bodyGroup); } foreach (FadeGroup item in items) { ReapplyFade(item); } foreach (FadeRenderer item2 in headgear) { if (item2.applied && item2.dither && Object.op_Implicit((Object)(object)item2.renderer)) { SetFade(item2, 0f); } } } public static void RecordSway(Vector3 headOffset, Vector3 cameraOffset, float deltaTime) { //IL_005f: 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) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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) if (swayValid && deltaTime > 0f && deltaTime < 0.25f) { float num = swayHead; Vector3 val = headOffset - lastHeadOffset; swayHead = num + ((Vector3)(ref val)).magnitude; float num2 = swayCamera; val = cameraOffset - lastCameraOffset; swayCamera = num2 + ((Vector3)(ref val)).magnitude; swayTime += deltaTime; } lastHeadOffset = headOffset; lastCameraOffset = cameraOffset; swayValid = true; } public static void RecordAim(float aimYaw, float sway) { float deltaTime = Time.deltaTime; if (!(deltaTime <= 0f) && !(deltaTime > 0.25f)) { if (aimValid && Mathf.Abs(Mathf.DeltaAngle(lastAimYaw, aimYaw)) > 1f) { aimJumps++; } lastAimYaw = aimYaw; aimValid = true; aimFrames++; aimTime += deltaTime; aimSum += Mathf.Abs(aimYaw) * deltaTime; aimMax = Mathf.Max(aimMax, Mathf.Abs(aimYaw)); swayMax = Mathf.Max(swayMax, Mathf.Abs(sway)); } } private static void UpdateFade(Camera cam) { float deltaTime = Time.deltaTime; if (Time.time >= nextItemRefresh) { nextItemRefresh = Time.time + 0.5f; RefreshItemDisplays(); } bool value = Settings.FadeWeapon.Value; if (value && (mode == MeasureMode.Box || !renderVerified)) { PrepareBox(cam); foreach (FadeGroup weaponGroup in weaponGroups) { weaponGroup.boxCoverage = BoxCoverage(weaponGroup); } if (mode == MeasureMode.Box) { if (bodyGroup != null) { bodyGroup.boxCoverage = 0f; } foreach (FadeGroup item in items) { item.boxCoverage = BoxCoverage(item); } } else { SelfCheck(); } } UpdateSkillHide(deltaTime); float value2 = Settings.FadeStart.Value; float num = Mathf.Max(value2 + 0.01f, Settings.FadeFull.Value); float num2 = 1f; foreach (FadeGroup weaponGroup2 in weaponGroups) { WatchSwitchOn(weaponGroup2, value); float num3 = (weaponGroup2.fx ? 0.5f : 1f); UpdateGroup(weaponGroup2, value, value2 * num3, num * num3, deltaTime); if (!weaponGroup2.fx) { num2 = Mathf.Min(num2, weaponGroup2.alpha); } } foreach (FadeRenderer follower in followers) { if (Object.op_Implicit((Object)(object)follower.renderer)) { Apply(follower, num2); } } foreach (FadeRenderer item2 in headgear) { if (Object.op_Implicit((Object)(object)item2.renderer)) { Apply(item2, 0f); } } if (bodyGroup != null) { UpdateGroup(bodyGroup, value && mode == MeasureMode.Render, 0.8f, 0.95f, deltaTime); } foreach (FadeGroup item3 in items) { UpdateGroup(item3, value, value2 * 0.5f, num * 0.5f, deltaTime); } if (value && mode == MeasureMode.Render) { RequestCoverage(cam); } if (Time.time >= nextStatsLog) { nextStatsLog = Time.time + 60f; LogStats(final: false); } } private static void UpdateGroup(FadeGroup group, bool enabled, float start, float full, float deltaTime) { if (group.headgear) { group.alpha = 0f; { foreach (FadeRenderer renderer in group.renderers) { if (Object.op_Implicit((Object)(object)renderer.renderer)) { Apply(renderer, 0f); } } return; } } float num = ((!enabled) ? 0f : ((mode == MeasureMode.Box) ? group.boxCoverage : (group.measured ? group.coverage : 0f))); float num2 = ((num <= start) ? 1f : ((num >= full) ? 0f : (1f - (num - start) / (full - start)))); if (group.awaitingMeasure) { if (!enabled || mode != MeasureMode.Render || group.measured) { group.awaitingMeasure = false; group.alpha = num2; } else { num2 = 0f; group.alpha = 0f; } } float num3 = ((num2 < group.alpha) ? 0.1f : 0.25f); group.alpha = Mathf.MoveTowards(group.alpha, num2, deltaTime / num3); if (enabled) { group.time += deltaTime; group.coverageSum += num * deltaTime; if (num > group.coverageMax) { group.coverageMax = num; } group.histogram[Mathf.Clamp((int)(num * 10f), 0, 9)] += deltaTime; if (group.alpha < 0.99f) { group.fadedTime += deltaTime; } } foreach (FadeRenderer renderer2 in group.renderers) { if (Object.op_Implicit((Object)(object)renderer2.renderer)) { Apply(renderer2, group.alpha); } } } private static void WatchSwitchOn(FadeGroup group, bool enabled) { bool flag = HasDrawable(group); if (flag && !group.wasDrawn) { group.fx = IsEffectGroup(group); if (group.fx && enabled && mode == MeasureMode.Render) { group.awaitingMeasure = true; group.measured = false; group.alpha = 0f; } } group.wasDrawn = flag; } private static float ModelFade() { if (!Object.op_Implicit((Object)(object)model)) { return 1f; } return model.fade; } private static void Apply(FadeRenderer fr, float alpha) { alpha *= modelAlpha; if (alpha >= 0.999f) { if (fr.applied) { Restore(fr); } return; } if (fr.dither) { SetFade(fr, ModelFade() * alpha); } SetHidden(fr, alpha <= (fr.dither ? 0.02f : 0.5f)); fr.applied = true; } private static void Restore(FadeRenderer fr) { if (fr.dither) { SetFade(fr, ModelFade()); } SetHidden(fr, hide: false); fr.applied = false; } private static void SetFade(FadeRenderer fr, float fade) { fr.renderer.GetPropertyBlock(block); block.SetFloat(fadeId, fade); fr.renderer.SetPropertyBlock(block); } private static void SetHidden(FadeRenderer fr, bool hide) { if (hide == fr.hidden) { return; } fr.hidden = hide; if (fr.measurable && fr.layerSafe && hideLayer >= 0) { GameObject gameObject = ((Component)fr.renderer).gameObject; if (hide) { fr.originalLayer = gameObject.layer; gameObject.layer = hideLayer; } else if (gameObject.layer == hideLayer) { gameObject.layer = fr.originalLayer; } } else { fr.renderer.forceRenderingOff = hide; } } private static void RestoreGroup(FadeGroup group) { foreach (FadeRenderer renderer in group.renderers) { if (renderer.applied && Object.op_Implicit((Object)(object)renderer.renderer)) { Restore(renderer); } } group.alpha = 1f; } private static void ReapplyFade(FadeGroup group) { foreach (FadeRenderer renderer in group.renderers) { if (renderer.applied && renderer.dither && Object.op_Implicit((Object)(object)renderer.renderer)) { SetFade(renderer, ModelFade() * group.alpha * modelAlpha); } } } private static void UpdateSkillHide(float deltaTime) { bool flag = FullBodyAnimationPlaying(); int num; if (flag && (!fullBodyPlaying || skillStarted)) { bool flag2 = Object.op_Implicit((Object)(object)lastSkill) && Time.time - lastSkillTime < 0.5f; bool flag3 = flag2 && IsPrimary(lastSkill); if (!fullBodyPlaying) { num = ((!flag3) ? 1 : 0); } else { if (skillHide) { num = 1; goto IL_006e; } if (!flag2) { num = 0; goto IL_0081; } num = ((!flag3) ? 1 : 0); } if (num != 0) { goto IL_006e; } goto IL_0081; } if (!flag) { skillHide = false; } goto IL_0091; IL_006e: if (!skillHide) { skillHides++; } goto IL_0081; IL_0081: skillHide = (byte)num != 0; goto IL_0091; IL_0091: fullBodyPlaying = flag; skillStarted = false; float num2 = ((skillHide && Settings.HideBodyDuringSkills.Value) ? 0f : 1f); modelAlpha = Mathf.MoveTowards(modelAlpha, num2, deltaTime / ((num2 < modelAlpha) ? 0.05f : 0.25f)); if (modelAlpha < 0.999f) { skillHiddenTime += deltaTime; } } private static bool FullBodyAnimationPlaying() { if (fullBodyLayer < 0 || !Object.op_Implicit((Object)(object)animator) || !((Behaviour)animator).isActiveAndEnabled || fullBodyLayer >= animator.layerCount) { return false; } if (animator.GetLayerWeight(fullBodyLayer) < 0.5f) { return false; } if (animator.GetCurrentAnimatorClipInfoCount(fullBodyLayer) > 0) { return true; } if (animator.IsInTransition(fullBodyLayer)) { return animator.GetNextAnimatorClipInfoCount(fullBodyLayer) > 0; } return false; } private static bool IsPrimary(GenericSkill skill) { SkillLocator val = (Object.op_Implicit((Object)(object)body) ? body.skillLocator : null); if (Object.op_Implicit((Object)(object)val)) { return skill == val.primary; } return false; } public static void OnSkillExecuted(GenericSkill skill) { lastSkill = skill; lastSkillTime = Time.time; skillStarted = true; } public static void CountBurst() { burstsHidden++; } public static void StripOverlays(CharacterModel target) { if (overlaysBroken) { return; } try { StripOverlaysFrom(target); } catch (Exception ex) { overlaysBroken = true; Plugin.Log.LogWarning((object)("Leaving flashes out of the own model stopped working: " + ex.Message)); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void StripOverlaysFrom(CharacterModel target) { Material[] currentOverlays = target.currentOverlays; int num = ((currentOverlays != null) ? Mathf.Min(target.activeOverlayCount, currentOverlays.Length) : 0); if (num <= 0) { return; } List<TemporaryOverlayInstance> temporaryOverlays = target.temporaryOverlays; int num2 = 0; for (int i = 0; i < num; i++) { Material val = currentOverlays[i]; if (Object.op_Implicit((Object)(object)val) && (val.IsKeywordEnabled("VERTEXOFFSET") || IsTemporary(temporaryOverlays, val))) { strippedOverlays.Add(((Object)val).GetInstanceID()); } else { currentOverlays[num2++] = val; } } for (int j = num2; j < num; j++) { currentOverlays[j] = null; } target.activeOverlayCount = num2; } private static bool IsTemporary(List<TemporaryOverlayInstance> temporary, Material material) { if (temporary == null) { return false; } foreach (TemporaryOverlayInstance item in temporary) { if (item != null && item.materialInstance == material) { return true; } } return false; } private static void RefreshOverlays(CharacterModel target) { if (overlaysBroken) { return; } try { ForceOverlayUpdate(target); } catch (Exception) { overlaysBroken = true; } } [MethodImpl(MethodImplOptions.NoInlining)] private static void ForceOverlayUpdate(CharacterModel target) { target.forceUpdate = true; } private static void Classify() { //IL_002e: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0186: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0282: 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_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) Transform transform = session.Head.Transform; Vector3 val = (Object.op_Implicit((Object)(object)transform) ? session.Head.Center : modelTransform.position); Vector3 val2 = (Object.op_Implicit((Object)(object)body) ? body.corePosition : val); List<Renderer> list = new List<Renderer>(); RendererInfo[] baseRendererInfos = model.baseRendererInfos; foreach (RendererInfo val3 in baseRendererInfos) { if (Object.op_Implicit((Object)(object)val3.renderer) && !list.Contains(val3.renderer)) { list.Add(val3.renderer); } } HashSet<Renderer> hashSet = new HashSet<Renderer>(); Vector3 val4 = (Object.op_Implicit((Object)(object)body) ? (body.footPosition + Vector3.up * 0.1f) : val2); string text = "pose bounds"; foreach (Renderer item in list) { if (item is SkinnedMeshRenderer) { Bounds bounds = item.bounds; ((Bounds)(ref bounds)).Expand(0.1f); if (((Bounds)(ref bounds)).Contains(val) && ((Bounds)(ref bounds)).Contains(val2) && ((Bounds)(ref bounds)).Contains(val4)) { hashSet.Add(item); } } } if (hashSet.Count == 0) { text = "pose bounds without feet"; foreach (Renderer item2 in list) { if (item2 is SkinnedMeshRenderer) { Bounds bounds2 = item2.bounds; ((Bounds)(ref bounds2)).Expand(0.1f); if (((Bounds)(ref bounds2)).Contains(val) && ((Bounds)(ref bounds2)).Contains(val2)) { hashSet.Add(item2); } } } } float num = Mathf.Max(0.15f, 0.4f * (Object.op_Implicit((Object)(object)body) ? body.radius : 0.5f)); float num2 = Mathf.Lerp(val2.y, val4.y, 0.5f); int num3 = 0; foreach (Renderer item3 in list) { if (!(item3 is SkinnedMeshRenderer) || hashSet.Contains(item3)) { continue; } Bounds bounds3 = item3.bounds; Vector3 val5 = ((Bounds)(ref bounds3)).center - val2; val5.y = 0f; if (!(((Bounds)(ref bounds3)).size.y < 0.8f * Mathf.Max(((Bounds)(ref bounds3)).size.x, ((Bounds)(ref bounds3)).size.z))) { ((Bounds)(ref bounds3)).Expand(0.1f); if (((Bounds)(ref bounds3)).Contains(val2) && !(((Vector3)(ref val5)).magnitude > num) && (!(((Bounds)(ref bounds3)).min.y > num2) || ((Bounds)(ref bounds3)).Contains(val))) { hashSet.Add(item3); num3++; } } } if (num3 > 0) { text = text + " and " + num3 + " worn around the body"; } if (hashSet.Count == 0 && Object.op_Implicit((Object)(object)transform)) { text = "head bone"; foreach (Renderer item4 in list) { SkinnedMeshRenderer val6 = (SkinnedMeshRenderer)(object)((item4 is SkinnedMeshRenderer) ? item4 : null); if (val6 != null && UsesBone(val6, transform)) { hashSet.Add(item4); } } } if (hashSet.Count == 0) { text = "largest mesh"; Renderer val7 = null; float num4 = 0f; foreach (Renderer item5 in list) { if (item5 is SkinnedMeshRenderer) { Bounds bounds4 = item5.bounds; Vector3 size = ((Bounds)(ref bounds4)).size; float num5 = size.x * size.y * size.z; if (!Object.op_Implicit((Object)(object)val7) || num5 > num4) { val7 = item5; num4 = num5; } } } if (Object.op_Implicit((Object)(object)val7)) { hashSet.Add(val7); } } StringBuilder stringBuilder = new StringBuilder("First person visuals for " + bodyName + ", body by " + text + ":"); bodyGroup = new FadeGroup { name = "body" }; foreach (Renderer item6 in list) { if (hashSet.Contains(item6)) { FadeRenderer fadeRenderer = MakeFadeRenderer(item6); bodyGroup.renderers.Add(fadeRenderer); stringBuilder.Append(" '").Append(((Object)item6).name).Append('\'') .Append(Describe(fadeRenderer)); } } if (bodyGroup.renderers.Count == 0) { bodyGroup = null; } stringBuilder.Append("; weapon:"); int num6 = 0; Dictionary<Transform, FadeGroup> dictionary = new Dictionary<Transform, FadeGroup>(); foreach (Renderer item7 in list) { if (hashSet.Contains(item7)) { continue; } FadeRenderer fadeRenderer2 = MakeFadeRenderer(item7); num6++; if (IsHeadgear(item7)) { headgear.Add(fadeRenderer2); stringBuilder.Append(" '").Append(((Object)item7).name).Append("' (headgear, hidden)"); continue; } if (!fadeRenderer2.measurable) { followers.Add(fadeRenderer2); stringBuilder.Append(" '").Append(((Object)item7).name).Append('\'') .Append(Describe(fadeRenderer2)); continue; } Transform parent = ((Component)item7).transform.parent; bool flag = !Object.op_Implicit((Object)(object)fadeRenderer2.skinned) && Object.op_Implicit((Object)(object)parent) && (Object)(object)parent != (Object)(object)modelTransform; if (!flag || !dictionary.TryGetValue(parent, out var value)) { value = new FadeGroup { name = ((Object)item7).name }; weaponGroups.Add(value); if (flag) { dictionary[parent] = value; } } else if (value.renderers.Count == 1) { value.name = ((Object)parent).name; } value.renderers.Add(fadeRenderer2); } foreach (FadeGroup weaponGroup in weaponGroups) { weaponGroup.fx = IsEffectGroup(weaponGroup); stringBuilder.Append(" '").Append(weaponGroup.name).Append('\''); if (weaponGroup.renderers.Count > 1) { stringBuilder.Append(" ["); for (int j = 0; j < weaponGroup.renderers.Count; j++) { stringBuilder.Append((j == 0) ? "" : ", ").Append(((Object)weaponGroup.renderers[j].renderer).name); } stringBuilder.Append(']'); } stringBuilder.Append(Describe(weaponGroup.renderers[0])); if (weaponGroup.fx) { stringBuilder.Append(" (glow)"); } if (!HasDrawable(weaponGroup)) { stringBuilder.Append(" (off)"); } } if (num6 == 0) { stringBuilder.Append(" none"); } RefreshItemDisplays(); nextItemRefresh = Time.time + 0.5f; nextStatsLog = Time.time + 60f; stringBuilder.Append("; coverage by ").Append((mode == MeasureMode.Render) ? "rendering" : "bounding boxes"); if (hideLayer >= 0) { stringBuilder.Append(", hidden on layer ").Append(hideLayer); } if (Object.op_Implicit((Object)(object)body) && describedBodies.Add(((Object)body).GetInstanceID())) { Plugin.Log.LogInfo((object)stringBuilder.ToString()); } } private static bool IsHeadgear(Renderer renderer) { //IL_0064: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) HeadAnchor headAnchor = ((session != null) ? session.Head : null); if (headAnchor == null || !Object.op_Implicit((Object)(object)headAnchor.Transform) || !Object.op_Implicit((Object)(object)renderer)) { return false; } if (Object.op_Implicit((Object)(object)headAnchor.Bone) && ((Component)renderer).transform.IsChildOf(headAnchor.Bone)) { return true; } if (!(renderer is SkinnedMeshRenderer) && !(renderer is MeshRenderer)) { return false; } Bounds bounds = renderer.bounds; float radius = headAnchor.Radius; Vector3 val = ((Bounds)(ref bounds)).extents; if (((Vector3)(ref val)).magnitude < 2.5f * radius) { val = ((Bounds)(ref bounds)).center - headAnchor.Center; return ((Vector3)(ref val)).magnitude < 1.5f * radius; } return false; } private static bool IsEffectGroup(FadeGroup group) { foreach (FadeRenderer renderer in group.renderers) { if (renderer.dither || !Object.op_Implicit((Object)(object)renderer.renderer)) { return false; } Material[] sharedMaterials = renderer.renderer.sharedMaterials; if (sharedMaterials.Length == 0) { return false; } Material[] array = sharedMaterials; foreach (Material val in array) { if (!Object.op_Implicit((Object)(object)val) || val.renderQueue <= 2500) { return false; } } } return group.renderers.Count > 0; } private static string Describe(FadeRenderer fr) { if (!fr.measurable) { return " (follows)"; } string text = (fr.dither ? " (dither" : " (no dither"); if (!fr.layerSafe) { return text + ", collider)"; } return text + ")"; } private static bool UsesBone(SkinnedMeshRenderer skinned, Transform head) { Transform parent = head.parent; Transform[] bones = skinned.bones; foreach (Transform val in bones) { if (Object.op_Implicit((Object)(object)val) && ((Object)(object)val == (Object)(object)head || (Object)(object)val == (Object)(object)parent)) { return true; } } return false; } private static FadeRenderer MakeFadeRenderer(Renderer renderer) { FadeRenderer fadeRenderer = new FadeRenderer { renderer = renderer, skinned = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null) }; Mesh val = null; if (Object.op_Implicit((Object)(object)fadeRenderer.skinned)) { OverrideBoundsUpdate(fadeRenderer.skinned); val = fadeRenderer.skinned.sharedMesh; } else if (renderer is MeshRenderer) { fadeRenderer.meshFilter = ((Component)renderer).GetComponent<MeshFilter>(); val = (Object.op_Implicit((Object)(object)fadeRenderer.meshFilter) ? fadeRenderer.meshFilter.sharedMesh : null); } if (Object.op_Implicit((Object)(object)val)) { fadeRenderer.measurable = true; fadeRenderer.subMeshCount = Mathf.Max(1, val.subMeshCount); fadeRenderer.dither = MaterialsDither(renderer); fadeRenderer.layerSafe = !Object.op_Implicit((Object)(object)((Component)renderer).GetComponent<Collider>()); } return fadeRenderer; } private static bool MaterialsDither(Renderer renderer) { Material[] sharedMaterials = renderer.sharedMaterials; if (sharedMaterials.Length == 0) { return false; } Material[] array = sharedMaterials; foreach (Material val in array) { if (!Object.op_Implicit((Object)(object)val) || !val.HasProperty(fadeId) || !val.IsKeywordEnabled("DITHER")) { return false; } if (val.HasProperty("_FadeOn") && val.GetInt("_FadeOn") == 0) { return false; } } return true; } private static void OverrideBoundsUpdate(SkinnedMeshRenderer skinned) { if (Object.op_Implicit((Object)(object)skinned) && !boundsOverrides.ContainsKey(skinned)) { boundsOverrides[skinned] = skinned.updateWhenOffscreen; skinned.updateWhenOffscreen = true; } } private static void RefreshItemDisplays() { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)model)) { return; } for (int num = items.Count - 1; num >= 0; num--) { FadeGroup fadeGroup = items[num]; if (!Object.op_Implicit((Object)(object)fadeGroup.itemDisplay)) { foreach (FadeRenderer renderer in fadeGroup.renderers) { if (renderer.skinned != null) { boundsOverrides.Remove(renderer.skinned); } } itemGroups.Remove(fadeGroup.itemDisplay); items.RemoveAt(num); } } displayBuffer.Clear(); ((Component)model).GetComponentsInChildren<ItemDisplay>(true, displayBuffer); foreach (ItemDisplay item in displayBuffer) { if (!Object.op_Implicit((Object)(object)item) || item.rendererInfos == null || itemGroups.ContainsKey(item)) { continue; } FadeGroup fadeGroup2 = new FadeGroup { name = ((Object)item).name.Replace("(Clone)", ""), isItem = true, itemDisplay = item }; bool flag = true; RendererInfo[] rendererInfos = item.rendererInfos; foreach (RendererInfo val in rendererInfos) { if (Object.op_Implicit((Object)(object)val.renderer)) { fadeGroup2.renderers.Add(MakeFadeRenderer(val.renderer)); flag &= IsHeadgear(val.renderer); } } fadeGroup2.headgear = flag && fadeGroup2.renderers.Count > 0; itemGroups[item] = fadeGroup2; items.Add(fadeGroup2); } displayBuffer.Clear(); } private static PendingReadback[] CreateReadbacks(int count) { PendingReadback[] array = new PendingReadback[count]; for (int i = 0; i < count; i++) { PendingReadback pending = new PendingReadback(); pending.callback = delegate(AsyncGPUReadbackRequest request) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) OnReadback(request, pending); }; array[i] = pending; } return array; } private static bool IsDrawn(Renderer renderer) { if (Object.op_Implicit((Object)(object)renderer) && renderer.enabled) { return ((Component)renderer).gameObject.activeInHierarchy; } return false; } private static bool HasDrawable(FadeGroup group) { foreach (FadeRenderer renderer in group.renderers) { if (renderer.measurable && IsDrawn(renderer.renderer)) { return true; } } return false; } private static Shader FindLoadedShader() { string[] obj = new string[3] { "Hidden/InternalErrorShader", "Hidden/Internal-Colored", "Unlit/Color" }; Shader[] array = Resources.FindObjectsOfTypeAll<Shader>(); string[] array2 = obj; foreach (string text in array2) { Shader[] array3 = array; foreach (Shader val in array3) { if (Object.op_Implicit((Object)(object)val) && ((Object)val).name == text && val.isSupported) { return val; } } } return null; } private static bool EnsureRenderResources(Camera cam) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //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_0133: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)coverageMaterial)) { if (renderResourcesTried) { mode = MeasureMode.Box; return false; } renderResourcesTried = true; Shader val = null; try { if (SystemInfo.supportsAsyncGPUReadback) { val = FindLoadedShader(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Looking up a shader for screen coverage failed: " + ex.Message)); } if (!Object.op_Implicit((Object)(object)val)) { mode = MeasureMode.Box; Plugin.Log.LogWarning((object)("Rendered screen coverage is not available (async readback " + SystemInfo.supportsAsyncGPUReadback + "), using bounding boxes")); return false; } coverageMaterial = new Material(val) { name = "BetterFirstPerson coverage", hideFlags = (HideFlags)61 }; SetIfPresent(coverageMaterial, "_Color", 1f); SetIfPresent(coverageMaterial, "_SrcBlend", 1f); SetIfPresent(coverageMaterial, "_DstBlend", 0f); SetIfPresent(coverageMaterial, "_ZWrite", 1f); SetIfPresent(coverageMaterial, "_ZTest", 4f); SetIfPresent(coverageMaterial, "_Cull", 2f); commandBuffer = new CommandBuffer { name = "BetterFirstPerson coverage" }; Plugin.Log.LogInfo((object)("Screen coverage is drawn with " + ((Object)val).name)); } int num = Mathf.Clamp(Mathf.RoundToInt(64f / Mathf.Max(0.2f, cam.aspect)), 8, 160); if (!Object.op_Implicit((Object)(object)coverageTexture) || !coverageTexture.IsCreated() || num != tileHeight) { if (Object.op_Implicit((Object)(object)coverageTexture)) { coverageTexture.Release(); Object.Destroy((Object)(object)coverageTexture); } tileHeight = num; coverageTexture = new RenderTexture(512, tileHeight, 16, (RenderTextureFormat)0, (RenderTextureReadWrite)1) { name = "BetterFirstPerson coverage", hideFlags = (HideFlags)61 }; coverageTexture.Create(); } return true; } private static void SetIfPresent(Material material, string property, float value) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(property)) { if (property == "_Color") { material.SetColor(property, Color.white); } else { material.SetFloat(property, value); } } } private static void AddTile(PendingReadback slot, ref int tiles, FadeGroup group) { if (tiles < 8 && !group.headgear) { if (HasDrawable(group)) { slot.mapping[tiles++] = group; } else { group.coverage = 0f; } } } private static void RequestCoverage(Camera cam) { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) if (!EnsureRenderResources(cam)) { return; } PendingReadback pendingReadback = readbacks[readbackCursor]; if (pendingReadback.busy) { if (Time.frameCount - pendingReadback.frame < 120) { return; } pendingReadback.busy = false; } int tiles = 0; int count = weaponGroups.Count; int i; for (i = 0; i < count; i++) { if (tiles >= 7) { break; } AddTile(pendingReadback, ref tiles, weaponGroups[(weaponCursor + i) % count]); } if (count > 0) { weaponCursor = (weaponCursor + i) % count; } if (bodyGroup != null) { AddTile(pendingReadback, ref tiles, bodyGroup); } int count2 = items.Count; for (i = 0; i < count2; i++) { if (tiles >= 8) { break; } AddTile(pendingReadback, ref tiles, items[(itemCursor + i) % count2]); } if (count2 > 0) { itemCursor = (itemCursor + i) % count2; } if (tiles == 0) { return; } commandBuffer.Clear(); commandBuffer.SetRenderTarget(RenderTargetIdentifier.op_Implicit((Texture)(object)coverageTexture)); commandBuffer.ClearRenderTarget(true, true, Color.clear); commandBuffer.SetViewProjectionMatrices(cam.worldToCameraMatrix, cam.projectionMatrix); for (int j = 0; j < tiles; j++) { commandBuffer.SetViewport(new Rect((float)(j * 64), 0f, 64f, (float)tileHeight)); foreach (FadeRenderer renderer in pendingReadback.mapping[j].renderers) { if (renderer.measurable && IsDrawn(renderer.renderer)) { for (int k = 0; k < renderer.subMeshCount; k++) { commandBuffer.DrawRenderer(renderer.renderer, coverageMaterial, k, 0); } commandBuffer.SetInvertCulling(true); for (int l = 0; l < renderer.subMeshCount; l++) { commandBuffer.DrawRenderer(renderer.renderer, coverageMaterial, l, 0); } commandBuffer.SetInvertCulling(false); } } } RenderTexture active = RenderTexture.active; Graphics.ExecuteCommandBuffer(commandBuffer); RenderTexture.active = active; pendingReadback.tiles = tiles; pendingReadback.height = tileHeight; pendingReadback.generation = generation; pendingReadback.frame = Time.frameCount; pendingReadback.busy = true; readbackCursor = (readbackCursor + 1) % readbacks.Length; AsyncGPUReadback.Request((Texture)(object)coverageTexture, 0, pendingReadback.callback); } private static void OnReadback(AsyncGPUReadbackRequest request, PendingReadback pending) { //IL_0025: 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) pending.busy = false; try { if (((AsyncGPUReadbackRequest)(ref request)).hasError || pending.generation != generation) { return; } NativeArray<uint> data = ((AsyncGPUReadbackRequest)(ref request)).GetData<uint>(0); int num = 512; int height = pending.height; if (data.Length < num * height) { return; } float num2 = 64 * height; for (int i = 0; i < pending.tiles; i++) { int num3 = 0; for (int j = 0; j < height; j++) { int k = j * num + i * 64; for (int num4 = k + 64; k < num4; k++) { if (data[k] != 0) { num3++; } } } FadeGroup obj = pending.mapping[i]; obj.coverage = (float)num3 / num2; obj.measured = true; } } catch (Exception ex) { if (mode == MeasureMode.Render) { mode = MeasureMode.Box; Plugin.Log.LogWarning((object)("Reading rendered screen coverage failed, using bounding boxes: " + ex.Message)); } } finally { Array.Clear(pending.mapping, 0, 8); } } private static void SelfCheck() { if (renderVerified) { return; } bool flag = bodyGroup != null && bodyGroup.measured && bodyGroup.coverage > 0f; float num = 0f; foreach (FadeGroup weaponGroup in weaponGroups) { num = Mathf.Max(num, weaponGroup.boxCoverage); flag |= weaponGroup.measured && weaponGroup.coverage > 0f; } foreach (FadeGroup item in items) { flag |= item.measured && item.coverage > 0f; } if (flag) { renderVerified = true; Plugin.Log.LogInfo((object)("Rendered screen coverage works (checked against boxes for " + checkVisibleFrames + " frames)")); } else if (!(num < 0.05f)) { checkVisibleFrames++; if (checkVisibleFrames >= 600) { mode = MeasureMode.Box; Plugin.Log.LogWarning((object)"Rendered screen coverage stayed empty while parts were on screen, using bounding boxes instead"); } } } private static void PrepareBox(Camera cam) { //IL_0007: 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_0011: 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_001b: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)cam).transform; boxCameraPosition = transform.position; boxToCamera = Quaternion.Inverse(transform.rotation); boxTanV = Mathf.Tan(cam.fieldOfView * 0.5f * ((float)Math.PI / 180f)); boxTanH = boxTanV * cam.aspect; boxNear = cam.nearClipPlane; } private static float BoxCoverage(FadeGroup group) { //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_003f: Unknown result type (might be due to invalid IL or missing references) float num = 0f; foreach (FadeRenderer renderer in group.renderers) { if (renderer.measurable && IsDrawn(renderer.renderer)) { Bounds bounds = renderer.renderer.bounds; if (!((Bounds)(ref bounds)).Contains(boxCameraPosition)) { num = Mathf.Max(num, Coverage(renderer)); } } } return num; } private static float Coverage(FadeRenderer fr) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0076: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) if (!FillBox(fr)) { return 0f; } for (int i = 0; i < 8; i++) { corners[i] = boxToCamera * (corners[i] - boxCameraPosition); } int num = 0; for (int j = 0; j < 8; j++) { if (corners[j].z >= boxNear) { points[num++] = Project(corners[j]); } } for (int k = 0; k < 8; k++) { for (int num2 = 1; num2 < 8; num2 <<= 1) { if ((k & num2) == 0) { int num3 = k | num2; float z = corners[k].z; float z2 = corners[num3].z; if (z >= boxNear != z2 >= boxNear) { Vector3 point = Vector3.LerpUnclamped(corners[k], corners[num3], (boxNear - z) / (z2 - z)); point.z = boxNear; points[num++] = Project(point); } } } } if (num < 3) { return 0f; } int num4 = ConvexHull(num); if (num4 >= 3) { return ClippedArea(num4); } return 0f; } private static bool FillBox(FadeRenderer fr) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_011d: 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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_0147: Unknown result type (might be due to invalid IL or missing references) Renderer renderer = fr.renderer; if (Object.op_Implicit((Object)(object)fr.meshFilter) && Object.op_Implicit((Object)(object)fr.meshFilter.sharedMesh)) { FillCorners(fr.meshFilter.sharedMesh.bounds, ((Component)renderer).transform); return true; } Bounds bounds = renderer.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).sqrMagnitude < 1E-06f) { return false; } if (Object.op_Implicit((Object)(object)fr.skinned)) { FillCorners(((Renderer)fr.skinned).localBounds, Object.op_Implicit((Object)(object)fr.skinned.rootBone) ? fr.skinned.rootBone : ((Component)renderer).transform); Vector3 val = corners[0]; Vector3 val2 = corners[0]; for (int i = 1; i < 8; i++) { val = Vector3.Min(val, corners[i]); val2 = Vector3.Max(val2, corners[i]); } Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(0.05f, 0.05f, 0.05f); if (Vector3.Max(((Bounds)(ref bounds)).min, val - val3) == ((Bounds)(ref bounds)).min && Vector3.Min(((Bounds)(ref bounds)).max, val2 + val3) == ((Bounds)(ref bounds)).max) { return true; } } FillCorners(bounds, null); return true; } private static void FillCorners(Bounds bounds, Transform transform) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_002a: 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_0031: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0084: Unknown result type (might be due to invalid IL or missing references) Vector3 center = ((Bounds)(ref bounds)).center; Vector3 extents = ((Bounds)(ref bounds)).extents; Vector3 val = default(Vector3); for (int i = 0; i < 8; i++) { ((Vector3)(ref val))..ctor(center.x + (((i & 1) != 0) ? extents.x : (0f - extents.x)), center.y + (((i & 2) != 0) ? extents.y : (0f - extents.y)), center.z + (((i & 4) != 0) ? extents.z : (0f - extents.z))); corners[i] = (Object.op_Implicit((Object)(object)transform) ? transform.TransformPoint(val) : val); } } private static Vector2 Project(Vector3 point) { //IL_000a: 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_0029: 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_003e: Unknown result type (might be due to invalid IL or missing references) return new Vector2(0.5f + 0.5f * point.x / (point.z * boxTanH), 0.5f + 0.5f * point.y / (point.z * boxTanV)); } private static float Cross(Vector2 origin, Vector2 a, Vector2 b) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) return (a.x - origin.x) * (b.y - origin.y) - (a.y - origin.y) * (b.x - origin.x); } private static int ConvexHull(int count) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) for (int i = 1; i < count; i++) { Vector2 val = points[i]; int num = i - 1; while (num >= 0 && (points[num].x > val.x || (points[num].x == val.x && points[num].y > val.y))) { points[num + 1] = points[num]; num--; } points[num + 1] = val; } int num2 = 0; for (int j = 0; j < count; j++) { while (num2 >= 2 && Cross(hull[num2 - 2], hull[num2 - 1], points[j]) <= 0f) { num2--; } hull[num2++] = points[j]; } int num3 = count - 2; int num4 = num2 + 1; while (num3 >= 0) { while (num2 >= num4 && Cross(hull[num2 - 2], hull[num2 - 1], points[num3]) <= 0f) { num2--; } hull[num2++] = points[num3]; num3--; } return num2 - 1; } private static float ClippedArea(int count) { //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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) Array.Copy(hull, clipA, count); count = ClipEdge(clipA, count, clipB, alongX: true, 0f, keepGreater: true); count = ClipEdge(clipB, count, clipA, alongX: true, 1f, keepGreater: false); count = ClipEdge(clipA, count, clipB, alongX: false, 0f, keepGreater: true); count = ClipEdge(clipB, count, clipA, alongX: false, 1f, keepGreater: false); if (count < 3) { return 0f; } float num = 0f; for (int i = 0; i < count; i++) { Vector2 val = clipA[i]; Vector2 val2 = clipA[(i + 1) % count]; num += val.x * val2.y - val2.x * val.y; } return Mathf.Abs(num) * 0.5f; } private static int ClipEdge(Vector2[] input, int count, Vector2[] output, bool alongX, float bound, bool keepGreater) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0023: 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) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_008b: 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_003d: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0076: 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) if (count == 0) { return 0; } int result = 0; Vector2 val = input[count - 1]; bool flag = Inside(val, alongX, bound, keepGreater); for (int i = 0; i < count; i++) { Vector2 val2 = input[i]; bool num = Inside(val2, alongX, bound, keepGreater); if (num != flag) { float num2 = (alongX ? val.x : val.y); float num3 = (alongX ? val2.x : val2.y); output[result++] = Vector2.LerpUnclamped(val, val2, (bound - num2) / (num3 - num2)); } if (num) { output[result++] = val2; } val = val2; flag = num; } return result; } private static bool Inside(Vector2 point, bool alongX, float bound, bool keepGreater) { //IL_000b: 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) float num = (alongX ? point.x : point.y); if (!keepGreater) { return num <= bound; } return num >= bound; } private static void LogStats(bool final) { if (weaponGroups.Count == 0 && items.Count == 0 && bodyGroup == null && swayTime < 1f && aimTime < 1f && skillHides == 0 && burstsHidden == 0) { return; } StringBuilder stringBuilder = new StringBuilder("Screen coverage " + (final ? "summary" : "so far") + " for " + bodyName + " (" + ((mode == MeasureMode.Render) ? "rendered" : "bounding boxes") + ", fade from " + Settings.FadeStart.Value.ToString("0.00") + " to " + Settings.FadeFull.Value.ToString("0.00") + ", items at half, body from " + 0.8f.ToString("0.00") + "):"); bool flag = false; foreach (FadeGroup weaponGroup in weaponGroups) { flag |= AppendStats(stringBuilder, weaponGroup); } if (bodyGroup != null) { flag |= AppendStats(stringBuilder, bodyGroup); } foreach (FadeGroup item in items) { if (item.coverageMax >= 0.02f) { flag |= AppendStats(stringBuilder, item); } } if (swayTime >= 1f) { stringBuilder.Append("\n head movement relative to the body ").Append((100f * swayHead / swayTime).ToString("0")).Append(" cm/s, reaching the camera ") .Append((100f * swayCamera / swayTime).ToString("0")) .Append(" cm/s (stabilization ") .Append(Settings.Stabilization.Value.ToString("0.00")) .Append(')'); flag = true; } if (aimTime >= 1f && aimFrames > 0) { stringBuilder.Append("\n arms aimed to the side of the body: avg ").Append((aimSum / aimTime).ToString("0.0")).Append(" deg, max ") .Append(aimMax.ToString("0.0")) .Append(" deg, jumps over 1 deg in ") .Append((100f * (float)aimJumps / (float)aimFrames).ToString("0.0")) .Append("% of frames; sway up to ") .Append(swayMax.ToString("0.0")) .Append(" deg (weapon sway ") .Append(Settings.WeaponSway.Value.ToString("0.00")) .Append(')'); flag = true; } if (skillHides > 0 || burstsHidden > 0 || strippedOverlays.Count > 0) { stringBuilder.Append("\n model hidden for skills that move the whole body ").Append(skillHides).Append(" times, ") .Append(skillHiddenTime.ToString("0.0")) .Append(" s (") .Append((fullBodyLayer >= 0) ? ("full body layer " + fullBodyLayer) : "no full body layer") .Append("); bursts at the body hidden: ") .Append(burstsHidden) .Append("; flashes left out of the model: ") .Append(strippedOverlays.Count); flag = true; } if (flag) { Plugin.Log.LogInfo((object)stringBuilder.ToString()); } } private static bool AppendStats(StringBuilder sb, FadeGroup group) { if (group.time < 1f) { return false; } sb.Append("\n ").Append(group.isItem ? "item '" : ((group == bodyGroup) ? "" : "part '")).Append(group.name) .Append((group.isItem || group != bodyGroup) ? "'" : "") .Append(": avg ") .Append((group.coverageSum / group.time).ToString("0.00")) .Append(" max ") .Append(group.coverageMax.ToString("0.00")) .Append(", faded ") .Append((100f * group.fadedTime / group.time).ToString("0")) .Append("% of ") .Append(group.time.ToString("0")) .Append(" s") .Append(", % of time per tenth of the screen:"); float[] histogram = group.histogram; foreach (float num in histogram) { sb.Append(' ').Append((100f * num / group.time).ToString("0")); } return true; } } internal sealed class HeadAnchor { public Transform Transform; public Vector3 LocalCenter; public float LocalRadius; public float FallbackRadius; public string Source; public Transform Bone; public Transform[] Eyes = (Transform[])(object)new Transform[0]; public Vector3 Center => Transform.TransformPoint(LocalCenter); public float Radius { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid