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 hololive English Promise v1.0.1
PromiseSuit.dll
Decompiled 6 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using ModelReplacement; using ModelReplacement.AvatarBodyUpdater; using ModelReplacement.Scripts.Enemies; using ModelReplacement.Scripts.Player; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCopyright("© 2016 cover corp.")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyVersion("1.0.1.0")] namespace PromiseSuit; public static class MaskedAppearanceCompatibility { private static readonly Type HostType = typeof(BodyReplacementBase).Assembly.GetType("ModelReplacement.Monobehaviors.Enemies.MaskedReplacementBase"); private static readonly FieldInfo ModelField = ((HostType == null) ? null : AccessTools.Field(HostType, "replacementModel")); private static readonly FieldInfo ActiveField = ((HostType == null) ? null : AccessTools.Field(HostType, "IsActive")); private static readonly PropertyInfo AvatarProperty = ((HostType == null) ? null : AccessTools.Property(HostType, "avatar")); private static readonly MethodInfo Replace = ((HostType == null) ? null : AccessTools.Method(HostType, "SetReplacement", new Type[1] { typeof(PlayerControllerB) }, (Type[])null)); private static readonly ManualLogSource Log = Logger.CreateLogSource("Promise masked compatibility"); public static void Install(Harmony harmony) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown if (Replace == null || ModelField == null || AvatarProperty == null) { Log.LogWarning((object)"Masked API entry points unavailable; player replacements remain enabled."); return; } harmony.Patch((MethodBase)Replace, new HarmonyMethod(typeof(MaskedAppearanceCompatibility), "Assign", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(MaskedPlayerEnemy), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(MaskedAppearanceCompatibility), "Spawned", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static bool Owns(PlayerControllerB player, out BodyReplacementBase body) { body = null; if (Object.op_Implicit((Object)(object)player) && ModelReplacementAPI.GetPlayerModelReplacement(player, ref body) && Object.op_Implicit((Object)(object)body)) { return ((object)body).GetType().Assembly == typeof(Plugin).Assembly; } return false; } private static void Spawned(MaskedPlayerEnemy __instance) { if (Object.op_Implicit((Object)(object)__instance) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<MaskedAppearanceRetry>())) { ((Component)__instance).gameObject.AddComponent<MaskedAppearanceRetry>().Enemy = __instance; } } internal static void Retry(MaskedPlayerEnemy enemy) { if (!Object.op_Implicit((Object)(object)enemy) || !Object.op_Implicit((Object)(object)enemy.mimickingPlayer) || !Owns(enemy.mimickingPlayer, out var body) || !Object.op_Implicit((Object)(object)body.replacementModel) || (Object)(object)body.viewState == (Object)null) { return; } Component component = ((Component)enemy).GetComponent(HostType); if (!Object.op_Implicit((Object)(object)component)) { ((Component)enemy).gameObject.AddComponent(HostType); return; } object? value = ModelField.GetValue(component); if (!Object.op_Implicit((Object)((value is GameObject) ? value : null))) { Replace.Invoke(component, new object[1] { enemy.mimickingPlayer }); } } private static bool Assign(object __instance, PlayerControllerB __0) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown if (!Owns(__0, out var body)) { return true; } if (!Object.op_Implicit((Object)(object)body.replacementModel) || (Object)(object)body.viewState == (Object)null) { return false; } object obj = ((__instance is Component) ? __instance : null); MaskedPlayerEnemy val = ((obj != null) ? ((Component)obj).GetComponent<MaskedPlayerEnemy>() : null); if (!Object.op_Implicit((Object)(object)val)) { return true; } GameObject val2 = null; object? value = ModelField.GetValue(__instance); GameObject val3 = (GameObject)((value is GameObject) ? value : null); try { MaskedModelFaceDriver maskedModelFaceDriver = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent<MaskedModelFaceDriver>() : null); if (Object.op_Implicit((Object)(object)maskedModelFaceDriver) && (Object)(object)maskedModelFaceDriver.SourcePlayer == (Object)(object)__0 && (Object)(object)maskedModelFaceDriver.SourceModel == (Object)(object)body.replacementModel) { return false; } val2 = Object.Instantiate<GameObject>(body.replacementModel); ((Object)val2).name = ((Object)body.replacementModel).name + " (Masked)"; val2.transform.localPosition = Vector3.zero; MaskedModelFaceDriver.DetachPlayerControllers(val2); Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>(true); foreach (Renderer obj2 in componentsInChildren) { ((Component)obj2).gameObject.layer = body.viewState.VisibleLayer; obj2.shadowCastingMode = (ShadowCastingMode)1; obj2.enabled = true; } Camera[] componentsInChildren2 = val2.GetComponentsInChildren<Camera>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { ((Behaviour)componentsInChildren2[i]).enabled = false; } NaturalEyeSockets.Ensure(val2).Aim(Vector2.zero); val2.AddComponent<MaskedModelFaceDriver>().Initialize(val, __0, body.replacementModel); MaskedAvatarUpdater val4 = new MaskedAvatarUpdater(); val4.AssignModelReplacement(((Component)val).gameObject, val2); AvatarProperty.SetValue(__instance, val4, null); ModelField.SetValue(__instance, val2); ActiveField?.SetValue(__instance, true); val2.SetActive(true); SkinnedMeshRenderer[] array = (SkinnedMeshRenderer[])(object)new SkinnedMeshRenderer[3] { val.rendererLOD0, val.rendererLOD1, val.rendererLOD2 }; foreach (SkinnedMeshRenderer val5 in array) { if (Object.op_Implicit((Object)(object)val5)) { ((Renderer)val5).enabled = false; ((Renderer)val5).shadowCastingMode = (ShadowCastingMode)0; } } if (Object.op_Implicit((Object)(object)val3) && (Object)(object)val3 != (Object)(object)val2) { Object.Destroy((Object)(object)val3); } return false; } catch (Exception ex) { if (Object.op_Implicit((Object)(object)val2)) { Object.Destroy((Object)(object)val2); } Log.LogWarning((object)("Masked adapter could not initialize; retaining MRAPI fallback: " + ex)); return true; } } } public sealed class MaskedAppearanceRetry : MonoBehaviour { public MaskedPlayerEnemy Enemy; private float next; private void Update() { if (!(Time.unscaledTime < next)) { next = Time.unscaledTime + 1f; if (!Object.op_Implicit((Object)(object)Enemy) || ((EnemyAI)Enemy).isEnemyDead) { ((Behaviour)this).enabled = false; } else { MaskedAppearanceCompatibility.Retry(Enemy); } } } } [DefaultExecutionOrder(9000)] public sealed class MaskedModelFaceDriver : MonoBehaviour { private sealed class Face { public SkinnedMeshRenderer Renderer; public int Blink; public int Left; public int Right; public int Up; public int Down; } public PlayerControllerB SourcePlayer; public GameObject SourceModel; private MaskedPlayerEnemy enemy; private MaskedVanillaBadges.Binding vanillaBadges; private NaturalEyeSockets sockets; private Vector2 gaze; private bool morphGaze; private float nextBlink; private float blinkStart = -10f; private readonly List<Face> faces = new List<Face>(); private static int Shape(Mesh mesh, string name) { for (int i = 0; i < mesh.blendShapeCount; i++) { string blendShapeName = mesh.GetBlendShapeName(i); if (blendShapeName == name || blendShapeName.EndsWith("." + name, StringComparison.Ordinal) || blendShapeName.EndsWith("_" + name, StringComparison.Ordinal)) { return i; } } return -1; } private static void Set(Face face, int index, float value) { if (Object.op_Implicit((Object)(object)face.Renderer) && index >= 0) { face.Renderer.SetBlendShapeWeight(index, value); } } public static void DetachPlayerControllers(GameObject clone) { MaskedCloneIsolation.Detach(clone, typeof(MaskedModelFaceDriver).Namespace); } public void Initialize(MaskedPlayerEnemy masked, PlayerControllerB source, GameObject model) { enemy = masked; SourcePlayer = source; SourceModel = model; vanillaBadges = MaskedVanillaBadges.Bind(((Component)masked).gameObject, (Object)(object)this); sockets = NaturalEyeSockets.Ensure(((Component)this).gameObject); nextBlink = Time.time + (float)Random.Range(2, 5); SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val.sharedMesh) && ((Object)val).name.IndexOf("Ink", StringComparison.OrdinalIgnoreCase) < 0) { Mesh sharedMesh = val.sharedMesh; int num = Shape(sharedMesh, "blink"); if (num < 0) { num = Shape(sharedMesh, "Fac_Eye_Close"); } if (num >= 0) { Face face = new Face { Renderer = val, Blink = num, Left = Shape(sharedMesh, "eyes_look_left"), Right = Shape(sharedMesh, "eyes_look_right"), Up = Shape(sharedMesh, "eyes_look_up"), Down = Shape(sharedMesh, "eyes_look_down") }; morphGaze |= face.Left >= 0 && face.Right >= 0; faces.Add(face); } } } PromiseAdaptiveLighting component = ((Component)this).GetComponent<PromiseAdaptiveLighting>(); if (!Object.op_Implicit((Object)(object)component)) { return; } component.Rebind(); component.BindContext(delegate { //IL_0052: 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_0065: Unknown result type (might be due to invalid IL or missing references) bool factory = Object.op_Implicit((Object)(object)enemy) && !((EnemyAI)enemy).isOutside; int ship; if (Object.op_Implicit((Object)(object)enemy) && Object.op_Implicit((Object)(object)StartOfRound.Instance) && Object.op_Implicit((Object)(object)StartOfRound.Instance.shipInnerRoomBounds)) { Bounds bounds = StartOfRound.Instance.shipInnerRoomBounds.bounds; ship = (((Bounds)(ref bounds)).Contains(((Component)enemy).transform.position) ? 1 : 0); } else { ship = 0; } return new PromiseLightingContext(factory, (byte)ship != 0); }); } private void OnDestroy() { MaskedVanillaBadges.Release(vanillaBadges, (Object)(object)this); } private void LateUpdate() { //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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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) if (!Object.op_Implicit((Object)(object)enemy)) { return; } vanillaBadges?.Hide(); if (!Object.op_Implicit((Object)(object)sockets)) { return; } Vector2 target = Vector2.zero; PlayerControllerB targetPlayer = ((EnemyAI)enemy).targetPlayer; if (!((EnemyAI)enemy).isEnemyDead && Plugin.Eyes.Value && Object.op_Implicit((Object)(object)targetPlayer) && !targetPlayer.isPlayerDead && Object.op_Implicit((Object)(object)sockets.Head)) { target = NaturalEyeMath.Target((Object.op_Implicit((Object)(object)targetPlayer.playerEye) ? targetPlayer.playerEye.position : (((Component)targetPlayer).transform.position + Vector3.up * 1.5f)) - sockets.Head.position, sockets.Forward, sockets.Up); } gaze = NaturalEyeMath.Smooth(gaze, target, Time.deltaTime); sockets.Aim(morphGaze ? Vector2.zero : gaze); if (Time.time >= nextBlink) { blinkStart = Time.time; nextBlink = Time.time + Random.Range(2.5f, 6f); } float num = Time.time - blinkStart; float value = ((!((EnemyAI)enemy).isEnemyDead && Plugin.Blink.Value && num >= 0f && num < 0.18f) ? (Mathf.Sin(num / 0.18f * (float)Math.PI) * 100f) : 0f); foreach (Face face in faces) { Set(face, face.Blink, value); Set(face, face.Left, Mathf.Max(0f, (0f - gaze.x) / 12f) * 20f); Set(face, face.Right, Mathf.Max(0f, gaze.x / 12f) * 20f); Set(face, face.Up, Mathf.Max(0f, (0f - gaze.y) / 7f) * 15f); Set(face, face.Down, Mathf.Max(0f, gaze.y / 9f) * 15f); } } } public static class MaskedCloneIsolation { private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static bool IsOwner(Type type) { Type type2 = type; while (type2 != null) { if (type2.Name == "PlayerControllerB" || type2.Name == "BodyReplacementBase") { return true; } type2 = type2.BaseType; } return false; } private static void Clear(Type type, MonoBehaviour component, string field, object value) { FieldInfo field2 = type.GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null && !field2.IsInitOnly) { field2.SetValue(component, value); } } public static void Detach(GameObject clone, string ownNamespace) { MonoBehaviour[] componentsInChildren = clone.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { if (!Object.op_Implicit((Object)(object)val) || ((object)val).GetType().Namespace != ownNamespace) { continue; } Type type = ((object)val).GetType(); bool flag = false; FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (IsOwner(fieldInfo.FieldType)) { if (!fieldInfo.IsInitOnly) { fieldInfo.SetValue(val, null); } flag = true; } } if (flag || type.Name.EndsWith("ReactionFace", StringComparison.Ordinal) || type.Name.Contains("HeadTracking") || type.Name.EndsWith("Face", StringComparison.Ordinal) || type.Name.Contains("FirstPerson") || type.Name.Contains("RenderDiagnostics") || type.Name.Contains("RuntimeMotionAudit")) { ((Behaviour)val).enabled = false; } if (type.Name.EndsWith("OutfitState", StringComparison.Ordinal)) { Clear(type, val, "HasPlayerBinding", false); Clear(type, val, "Corpse", false); Clear(type, val, "SourceState", null); Clear(type, val, "AutomaticEars", false); type.GetMethod("Rebind", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)?.Invoke(val, null); } } } } public static class MaskedVanillaBadges { public sealed class Binding { internal GameObject Enemy; internal object[] State; public void Hide() { MeshRenderer[] array = (MeshRenderer[])State[1]; foreach (MeshRenderer val in array) { if (Object.op_Implicit((Object)(object)val) && ((Renderer)val).enabled) { ((Renderer)val).enabled = false; } } } } private const string Chest = "ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/"; private const string StateKey = "RaidNight.SuitMods.MaskedVanillaBadges.v1"; private static Dictionary<GameObject, object[]> Active { get { Dictionary<GameObject, object[]> dictionary = AppDomain.CurrentDomain.GetData("RaidNight.SuitMods.MaskedVanillaBadges.v1") as Dictionary<GameObject, object[]>; if (dictionary == null) { dictionary = new Dictionary<GameObject, object[]>(); AppDomain.CurrentDomain.SetData("RaidNight.SuitMods.MaskedVanillaBadges.v1", dictionary); } return dictionary; } } public static Binding Bind(GameObject enemy, Object owner) { if (!Object.op_Implicit((Object)(object)enemy) || !Object.op_Implicit(owner)) { return null; } if (Active.TryGetValue(enemy, out var value)) { value[0] = owner; Binding binding = new Binding(); binding.Enemy = enemy; binding.State = value; binding.Hide(); return binding; } List<MeshRenderer> list = new List<MeshRenderer>(); string[] array = new string[2] { "LevelSticker", "BetaBadge" }; foreach (string text in array) { Transform val = enemy.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/" + text); MeshRenderer val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<MeshRenderer>() : null); if (Object.op_Implicit((Object)(object)val2)) { list.Add(val2); } } bool[] array2 = new bool[list.Count]; for (int j = 0; j < list.Count; j++) { array2[j] = ((Renderer)list[j]).enabled; } object[] array3 = new object[3] { owner, list.ToArray(), array2 }; Binding obj = new Binding { Enemy = enemy, State = array3 }; Active.Add(enemy, array3); obj.Hide(); return obj; } public static void Release(Binding binding, Object owner) { if (binding == null || binding.State[0] != owner || !Active.TryGetValue(binding.Enemy, out var value) || value != binding.State) { return; } Active.Remove(binding.Enemy); MeshRenderer[] array = (MeshRenderer[])binding.State[1]; bool[] array2 = (bool[])binding.State[2]; for (int i = 0; i < array.Length; i++) { if (Object.op_Implicit((Object)(object)array[i])) { ((Renderer)array[i]).enabled = array2[i]; } } } } public static class NaturalEyeMath { public const float YawLimit = 12f; public const float UpLimit = 7f; public const float DownLimit = 9f; public const float SocketLimit = 12f; public const float MorphHorizontal = 20f; public const float MorphVertical = 15f; private static bool Finite(float v) { if (!float.IsNaN(v)) { return !float.IsInfinity(v); } return false; } public static Vector2 Clamp(Vector2 angles) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0020: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0085: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if (!Finite(angles.x) || !Finite(angles.y)) { return Vector2.zero; } float num = ((angles.y < 0f) ? 7f : 9f); angles.x = Mathf.Clamp(angles.x, -12f, 12f); angles.y = Mathf.Clamp(angles.y, -7f, 9f); float num2 = Mathf.Sqrt(angles.x * angles.x / 144f + angles.y * angles.y / (num * num)); if (!(num2 > 1f)) { return angles; } return angles / num2; } public static Vector2 Target(Vector3 local) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_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_00d6: Unknown result type (might be due to invalid IL or missing references) if (!Finite(local.x) || !Finite(local.y) || !Finite(local.z) || ((Vector3)(ref local)).sqrMagnitude < 1E-10f || local.z <= 0f) { return Vector2.zero; } float num = Mathf.Atan2(local.x, local.z) * 57.29578f; float num2 = (0f - Mathf.Atan2(local.y, Mathf.Sqrt(local.x * local.x + local.z * local.z))) * 57.29578f; float num3 = Mathf.Max(Mathf.Abs(num), Mathf.Abs(num2)); float num4 = 1f - Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(60f, 90f, num3)); return Clamp(new Vector2(num, num2)) * num4; } public static Vector2 Smooth(Vector2 current, Vector2 target, float dt) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) current = Clamp(current); target = Clamp(target); if (!Finite(dt) || dt <= 0f) { return current; } return Clamp(Vector2.Lerp(current, target, 1f - Mathf.Exp((0f - Mathf.Min(dt, 0.1f)) * 12f))); } public static Vector2 Target(Vector3 direction, Vector3 forward, Vector3 up) { //IL_0032: 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_001e: 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_0038: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_004a: Unknown result type (might be due to invalid IL or missing references) if (!(((Vector3)(ref forward)).sqrMagnitude < 1E-08f) && !(((Vector3)(ref up)).sqrMagnitude < 1E-08f)) { Vector3 val = Vector3.Cross(up, forward); if (!(((Vector3)(ref val)).sqrMagnitude < 1E-08f)) { return Target(Quaternion.Inverse(Quaternion.LookRotation(forward, up)) * direction); } } return Vector2.zero; } public static void Apply(Transform eye, Quaternion neutral, Vector3 forward, Vector3 up, Vector2 angles) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_006d: 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) //IL_0070: 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) if (Object.op_Implicit((Object)(object)eye) && Object.op_Implicit((Object)(object)eye.parent)) { angles = Clamp(angles); Quaternion val = Quaternion.LookRotation(forward, up); Quaternion val2 = Quaternion.Inverse(eye.parent.rotation) * val; Quaternion val3 = val2 * Quaternion.Euler(angles.y, angles.x, 0f) * Quaternion.Inverse(val2) * neutral; eye.localRotation = Quaternion.RotateTowards(neutral, val3, 12f); } } } [DefaultExecutionOrder(10000)] public sealed class NaturalEyeSockets : MonoBehaviour { public Transform Left; public Transform Right; public Transform Head; public Quaternion LeftNeutral = Quaternion.identity; public Quaternion RightNeutral = Quaternion.identity; public Quaternion HeadToLook = Quaternion.identity; public bool Captured; public Vector3 Forward { get { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //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) //IL_002f: 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_0013: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Head)) { return ((Component)this).transform.forward; } return Head.rotation * HeadToLook * Vector3.forward; } } public Vector3 Up { get { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //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) //IL_002f: 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_0013: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Head)) { return ((Component)this).transform.up; } return Head.rotation * HeadToLook * Vector3.up; } } public static NaturalEyeSockets Ensure(GameObject model) { NaturalEyeSockets naturalEyeSockets = model.GetComponent<NaturalEyeSockets>(); if (!Object.op_Implicit((Object)(object)naturalEyeSockets)) { naturalEyeSockets = model.AddComponent<NaturalEyeSockets>(); } naturalEyeSockets.Capture(); return naturalEyeSockets; } private void Awake() { Capture(); } public void Capture() { //IL_0104: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_018e: 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_01a0: Unknown result type (might be due to invalid IL or missing references) if (Captured) { return; } Animator componentInChildren = ((Component)this).GetComponentInChildren<Animator>(true); if (Object.op_Implicit((Object)(object)componentInChildren) && componentInChildren.isHuman) { Head = componentInChildren.GetBoneTransform((HumanBodyBones)10); Left = componentInChildren.GetBoneTransform((HumanBodyBones)21); Right = componentInChildren.GetBoneTransform((HumanBodyBones)22); } Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == "head.x" || (!Object.op_Implicit((Object)(object)Head) && (((Object)val).name == "DEF-spine.006" || ((Object)val).name == "spine.004"))) { Head = val; } if (((Object)val).name == "Skn_L_Eye") { Left = val; } if (((Object)val).name == "Skn_R_Eye") { Right = val; } } if (Object.op_Implicit((Object)(object)Left)) { LeftNeutral = Left.localRotation; } if (Object.op_Implicit((Object)(object)Right)) { RightNeutral = Right.localRotation; } Transform val2 = null; componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true); foreach (Transform val3 in componentsInChildren) { if (((Object)val3).name.EndsWith("GazeFrame", StringComparison.Ordinal)) { val2 = val3; break; } } if (Object.op_Implicit((Object)(object)Head)) { HeadToLook = Quaternion.Inverse(Head.rotation) * (Object.op_Implicit((Object)(object)val2) ? val2.rotation : ((Component)this).transform.rotation); } Captured = Object.op_Implicit((Object)(object)Head); } private static void Limit(Transform eye, Quaternion neutral) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)eye)) { eye.localRotation = Quaternion.RotateTowards(neutral, eye.localRotation, 12f); } } private void LateUpdate() { //IL_000d: 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) Capture(); Limit(Left, LeftNeutral); Limit(Right, RightNeutral); } public void Aim(Vector2 angles) { //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_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_002b: 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_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) Capture(); NaturalEyeMath.Apply(Left, LeftNeutral, Forward, Up, angles); NaturalEyeMath.Apply(Right, RightNeutral, Forward, Up, angles); } } [Serializable] public struct PromiseLightingContext { public bool InsideFactory; public bool InsideShip; public bool Indoors { get { if (!InsideFactory) { return InsideShip; } return true; } } public float Floor { get { if (!Indoors) { return 0.075f; } return 0f; } } public PromiseLightingContext(bool factory, bool ship) { InsideFactory = factory; InsideShip = ship; } } public sealed class PromiseCorpseLightingContext { private PromiseLightingContext context; private bool trackedItem; public PromiseCorpseLightingContext(PromiseLightingContext death) { context = death; } public PromiseLightingContext Observe(bool bodyInShip, bool hasHolder, PromiseLightingContext holder, bool hasItem, PromiseLightingContext item) { if (hasHolder) { context = holder; trackedItem = true; } else if (hasItem && trackedItem) { context = item; } if (!bodyInShip) { return context; } return new PromiseLightingContext(factory: false, ship: true); } } [DefaultExecutionOrder(600)] public sealed class PromiseAdaptiveLighting : MonoBehaviour { private struct Draw { public Renderer Renderer; public int Slot; public bool Floor; public bool Ink; public Color InkColor; } public Renderer[] receivers; private readonly List<Draw> draws = new List<Draw>(); private MaterialPropertyBlock block; private Func<PromiseLightingContext> contextReader; private bool initialized; private static readonly int FloorId = Shader.PropertyToID("_GflAmbientFloor"); private static readonly int InkId = Shader.PropertyToID("_InkColor"); public PromiseLightingContext Context { get; private set; } public float CurrentFloor => Context.Floor; public int FloorSlots { get; private set; } public int InkSlots { get; private set; } private void Awake() { Rebind(); Refresh(); } private void OnEnable() { if (initialized) { Refresh(); } } public void Rebind() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if (block == null) { block = new MaterialPropertyBlock(); } draws.Clear(); int floorSlots = (InkSlots = 0); FloorSlots = floorSlots; receivers = ((Component)this).GetComponentsInChildren<Renderer>(true); Renderer[] array = receivers; foreach (Renderer val in array) { Material[] sharedMaterials = val.sharedMaterials; for (int i = 0; i < sharedMaterials.Length; i++) { Material val2 = sharedMaterials[i]; if (!Object.op_Implicit((Object)(object)val2)) { continue; } bool flag = val2.HasProperty(FloorId); bool flag2 = val2.HasProperty(InkId); if (flag || flag2) { draws.Add(new Draw { Renderer = val, Slot = i, Floor = flag, Ink = flag2, InkColor = (flag2 ? val2.GetColor(InkId) : Color.black) }); if (flag) { FloorSlots++; } if (flag2) { InkSlots++; } } } } initialized = true; Apply(Context); } public void BindContext(Func<PromiseLightingContext> reader) { contextReader = reader; Refresh(); } public PromiseLightingContext ReadContext() { if (contextReader == null) { return Context; } return contextReader(); } public void InheritContext(PromiseAdaptiveLighting source) { if (Object.op_Implicit((Object)(object)source)) { BindContext(source.ReadContext); } } public void Refresh() { Apply(ReadContext()); } public void Apply(PromiseLightingContext context) { //IL_0088: 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_00be: 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) if (!initialized) { Rebind(); } Context = context; foreach (Draw draw in draws) { if (!Object.op_Implicit((Object)(object)draw.Renderer)) { continue; } block.Clear(); draw.Renderer.GetPropertyBlock(block, draw.Slot); if (draw.Floor) { block.SetFloat(FloorId, context.Floor); } if (draw.Ink) { Color inkColor = draw.InkColor; if (context.Indoors) { ((Color)(ref inkColor))..ctor(0f, 0f, 0f, inkColor.a); } block.SetColor(InkId, inkColor); } draw.Renderer.SetPropertyBlock(block, draw.Slot); } } private void LateUpdate() { Refresh(); } } internal static class PromiseLightingControl { private sealed class Death { internal ulong Owner; internal PromiseLightingContext Context; } private static readonly Dictionary<PlayerControllerB, Death> deaths = new Dictionary<PlayerControllerB, Death>(); private static readonly FieldInfo sourceField = AccessTools.Field(typeof(BodyReplacementBase), "replacementModel"); private static readonly FieldInfo shadowField = AccessTools.Field(typeof(BodyReplacementBase), "replacementModelShadow"); private static readonly FieldInfo viewField = AccessTools.Field(typeof(BodyReplacementBase), "replacementViewModel"); private static PromiseLightingContext Native(PlayerControllerB player) { if (!Object.op_Implicit((Object)(object)player)) { return default(PromiseLightingContext); } return new PromiseLightingContext(player.isInsideFactory, player.isInHangarShipRoom); } internal static void Install(Harmony harmony) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(BodyReplacementBase), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PromiseLightingControl), "Created", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo = AccessTools.Method(typeof(BodyReplacementBase), "LoadRagdollReplacement", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(PromiseLightingControl), "Ragdoll", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerControllerB), "KillPlayer", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PromiseLightingControl), "CaptureDeath", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerControllerB), "SpawnDeadBody", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PromiseLightingControl), "CaptureRemoteDeath", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(StartOfRound), "ReviveDeadPlayers", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PromiseLightingControl), "Clear", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static void CaptureDeath(PlayerControllerB __instance) { if (Object.op_Implicit((Object)(object)__instance) && !__instance.isPlayerDead) { deaths[__instance] = new Death { Owner = ((NetworkBehaviour)__instance).OwnerClientId, Context = Native(__instance) }; } } private static void CaptureRemoteDeath(PlayerControllerB deadPlayerController) { if (Object.op_Implicit((Object)(object)deadPlayerController) && !((NetworkBehaviour)deadPlayerController).IsOwner) { deaths[deadPlayerController] = new Death { Owner = ((NetworkBehaviour)deadPlayerController).OwnerClientId, Context = Native(deadPlayerController) }; } } private static void Created(BodyReplacementBase __instance) { if (__instance is PromiseBody promiseBody && Object.op_Implicit((Object)(object)((BodyReplacementBase)promiseBody).controller)) { FieldInfo[] array = new FieldInfo[3] { sourceField, shadowField, viewField }; for (int i = 0; i < array.Length; i++) { object? obj = array[i]?.GetValue(promiseBody); Bind((GameObject)((obj is GameObject) ? obj : null), ((BodyReplacementBase)promiseBody).controller); } } } internal static void AttachView(GameObject playerObject, GameObject view) { if (Object.op_Implicit((Object)(object)playerObject) && Object.op_Implicit((Object)(object)view) && Object.op_Implicit((Object)(object)view.GetComponent<PromiseAdaptiveLighting>())) { Bind(view, playerObject.GetComponent<PlayerControllerB>()); } } private static void Ragdoll(BodyReplacementBase __instance, GameObject __result) { if (__instance is PromiseBody promiseBody && Object.op_Implicit((Object)(object)((BodyReplacementBase)promiseBody).controller)) { Bind(__result, ((BodyReplacementBase)promiseBody).controller, corpse: true); } } private static void Bind(GameObject model, PlayerControllerB player, bool corpse = false) { if (!Object.op_Implicit((Object)(object)model) || !Object.op_Implicit((Object)(object)player)) { return; } PromiseAdaptiveLighting promiseAdaptiveLighting = model.GetComponent<PromiseAdaptiveLighting>() ?? model.AddComponent<PromiseAdaptiveLighting>(); promiseAdaptiveLighting.Rebind(); ulong owner = ((NetworkBehaviour)player).OwnerClientId; if (!corpse) { promiseAdaptiveLighting.BindContext(() => (!Object.op_Implicit((Object)(object)player) || ((NetworkBehaviour)player).OwnerClientId != owner) ? default(PromiseLightingContext) : Native(player)); return; } Death value; PromiseLightingContext death = ((deaths.TryGetValue(player, out value) && value.Owner == owner) ? value.Context : Native(player)); PromiseCorpseLightingContext corpseContext = new PromiseCorpseLightingContext(death); DeadBodyInfo nativeBody = player.deadBody; promiseAdaptiveLighting.BindContext(delegate { if (!Object.op_Implicit((Object)(object)nativeBody)) { return corpseContext.Observe(bodyInShip: false, hasHolder: false, default(PromiseLightingContext), hasItem: false, default(PromiseLightingContext)); } GrabbableObject grabBodyObject = nativeBody.grabBodyObject; PlayerControllerB val = ((Object.op_Implicit((Object)(object)grabBodyObject) && grabBodyObject.isHeld) ? grabBodyObject.playerHeldBy : null); return corpseContext.Observe(nativeBody.isInShip || nativeBody.parentedToShip, Object.op_Implicit((Object)(object)val), Native(val), Object.op_Implicit((Object)(object)grabBodyObject), Object.op_Implicit((Object)(object)grabBodyObject) ? new PromiseLightingContext(grabBodyObject.isInFactory, grabBodyObject.isInShipRoom) : default(PromiseLightingContext)); }); } internal static void Clear() { deaths.Clear(); } } public enum AttentionKind { Player, Enemy, Item } public struct AttentionCandidate { public int Key; public AttentionKind Kind; public float Distance; public bool Speaking; public bool Eligible; public AttentionCandidate(int key, AttentionKind kind, float distance, bool speaking = true, bool eligible = true) { Key = key; Kind = kind; Distance = distance; Speaking = speaking; Eligible = eligible; } } public sealed class PromiseAttentionSelection { private float lastSpeech; private float selectedAt; public int CurrentKey { get; private set; } public bool HasTarget { get; private set; } public AttentionKind CurrentKind { get; private set; } public void Reset() { HasTarget = false; CurrentKey = 0; lastSpeech = (selectedAt = 0f); } public int Choose(IList<AttentionCandidate> candidates, float now, float pauseHold = 1.2f) { AttentionCandidate attentionCandidate = default(AttentionCandidate); AttentionCandidate c = default(AttentionCandidate); AttentionCandidate c2 = default(AttentionCandidate); bool flag = false; bool flag2 = false; bool flag3 = false; foreach (AttentionCandidate candidate in candidates) { if (!candidate.Eligible || float.IsNaN(candidate.Distance) || float.IsInfinity(candidate.Distance) || candidate.Distance < 0f) { continue; } if (HasTarget && candidate.Key == CurrentKey && candidate.Kind == CurrentKind) { attentionCandidate = candidate; flag = true; } if (candidate.Kind == AttentionKind.Player) { if (candidate.Speaking && (!flag2 || candidate.Distance < c.Distance)) { c = candidate; flag2 = true; } } else if (!flag3 || candidate.Kind < c2.Kind || (candidate.Kind == c2.Kind && candidate.Distance < c2.Distance)) { c2 = candidate; flag3 = true; } } if (flag && attentionCandidate.Kind == AttentionKind.Player && attentionCandidate.Speaking) { lastSpeech = now; } if (flag2) { if (flag && attentionCandidate.Kind == AttentionKind.Player && attentionCandidate.Speaking && (now - selectedAt < 0.65f || c.Distance >= attentionCandidate.Distance * 0.7f)) { return CurrentKey; } return Select(c, now); } if (flag && attentionCandidate.Kind == AttentionKind.Player && now - lastSpeech <= Mathf.Clamp(pauseHold, 0f, 5f)) { return CurrentKey; } if (flag3) { if (flag && attentionCandidate.Kind == c2.Kind && attentionCandidate.Kind != AttentionKind.Player && (now - selectedAt < 1.5f || c2.Distance >= attentionCandidate.Distance * 0.7f)) { return CurrentKey; } return Select(c2, now); } Reset(); return 0; } private int Select(AttentionCandidate c, float now) { if (!HasTarget || c.Key != CurrentKey || c.Kind != CurrentKind) { selectedAt = now; } HasTarget = true; CurrentKey = c.Key; CurrentKind = c.Kind; if (c.Kind == AttentionKind.Player && c.Speaking) { lastSpeech = now; } return CurrentKey; } public static bool InView(Vector3 origin, Vector3 forward, Vector3 point, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_002c: 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_0038: 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_0046: Unknown result type (might be due to invalid IL or missing references) Vector3 val = point - origin; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < 0.0225f || sqrMagnitude > radius * radius) { return false; } Vector3 val2 = Vector3.ProjectOnPlane(val, Vector3.up); Vector3 val3 = Vector3.ProjectOnPlane(forward, Vector3.up); if (Vector3.Angle(val2, val3) <= 65f) { return Mathf.Abs(Mathf.Atan2(val.y, ((Vector3)(ref val2)).magnitude) * 57.29578f) <= 60f; } return false; } public static bool ActiveSpeech(bool speaking, float amplitude) { if (speaking && !float.IsNaN(amplitude) && !float.IsInfinity(amplitude)) { return amplitude >= 0.002f; } return false; } public static bool Visible(Vector3 origin, Vector3 point, int mask, Transform observer, Transform model, Transform target, RaycastHit[] hits) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_001a: 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_001d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = point - origin; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.05f) { return true; } int num = Physics.RaycastNonAlloc(origin, val / magnitude, hits, magnitude, mask, (QueryTriggerInteraction)1); if (num == hits.Length) { return false; } for (int i = 0; i < num; i++) { Transform transform = ((RaycastHit)(ref hits[i])).transform; if (Object.op_Implicit((Object)(object)transform) && (!Object.op_Implicit((Object)(object)observer) || !transform.IsChildOf(observer)) && (!Object.op_Implicit((Object)(object)model) || !transform.IsChildOf(model)) && (!Object.op_Implicit((Object)(object)target) || !transform.IsChildOf(target))) { return false; } } return true; } } public sealed class PromiseAttention { private sealed class ItemRenderer { public GrabbableObject Item; public Renderer Renderer; } private readonly PromiseAttentionSelection selection = new PromiseAttentionSelection(); private readonly List<AttentionCandidate> candidates = new List<AttentionCandidate>(64); private readonly Dictionary<int, Object> objects = new Dictionary<int, Object>(); private readonly RaycastHit[] hits = (RaycastHit[])(object)new RaycastHit[24]; private static EnemyAI[] enemies = (EnemyAI[])(object)new EnemyAI[0]; private static GrabbableObject[] items = (GrabbableObject[])(object)new GrabbableObject[0]; private static float nextSceneScan; private static StartOfRound scene; private static readonly Dictionary<int, ItemRenderer> itemRenderers = new Dictionary<int, ItemRenderer>(); private static readonly HashSet<int> aliveItems = new HashSet<int>(); private static readonly List<int> staleItems = new List<int>(); private Object target; private float nextScan; public void Reset() { selection.Reset(); target = null; nextScan = 0f; } private static void ScanScene(float now) { if ((Object)(object)scene != (Object)(object)StartOfRound.Instance) { scene = StartOfRound.Instance; nextSceneScan = 0f; itemRenderers.Clear(); } if (now < nextSceneScan) { return; } nextSceneScan = now + 1f; enemies = PromiseSceneCache.Enemies(now); items = Object.FindObjectsByType<GrabbableObject>((FindObjectsSortMode)0); aliveItems.Clear(); GrabbableObject[] array = items; foreach (GrabbableObject val in array) { if (Object.op_Implicit((Object)(object)val)) { aliveItems.Add(((Object)val).GetInstanceID()); } } staleItems.Clear(); foreach (KeyValuePair<int, ItemRenderer> itemRenderer in itemRenderers) { if (!aliveItems.Contains(itemRenderer.Key)) { staleItems.Add(itemRenderer.Key); } } foreach (int staleItem in staleItems) { itemRenderers.Remove(staleItem); } } internal static void ClearSceneCache() { scene = null; nextSceneScan = 0f; enemies = (EnemyAI[])(object)new EnemyAI[0]; items = (GrabbableObject[])(object)new GrabbableObject[0]; itemRenderers.Clear(); aliveItems.Clear(); staleItems.Clear(); } private static Vector3 Point(Object value) { //IL_003d: 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_002c: 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_0102: 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_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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_00e6: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = (PlayerControllerB)(object)((value is PlayerControllerB) ? value : null); if (val != null) { if (!Object.op_Implicit((Object)(object)val.playerEye)) { return ((Component)val).transform.position + Vector3.up * 1.6f; } return val.playerEye.position; } EnemyAI val2 = (EnemyAI)(object)((value is EnemyAI) ? value : null); if (val2 != null) { if (!Object.op_Implicit((Object)(object)val2.eye)) { return ((Component)val2).transform.position + Vector3.up; } return val2.eye.position; } GrabbableObject val3 = (GrabbableObject)(object)((value is GrabbableObject) ? value : null); if (val3 != null) { int instanceID = ((Object)val3).GetInstanceID(); if (!itemRenderers.TryGetValue(instanceID, out var value2) || (Object)(object)value2.Item != (Object)(object)val3) { value2 = new ItemRenderer { Item = val3, Renderer = ((Component)val3).GetComponentInChildren<Renderer>() }; itemRenderers[instanceID] = value2; } if (!Object.op_Implicit((Object)(object)value2.Renderer)) { return ((Component)val3).transform.position; } Bounds bounds = value2.Renderer.bounds; return ((Bounds)(ref bounds)).center; } return Vector3.zero; } private void Add(Component value, AttentionKind kind, Vector3 origin, Vector3 forward, float range, bool speaking, PlayerControllerB owner, Transform model) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) Vector3 val = Point((Object)(object)value); if (PromiseAttentionSelection.InView(origin, forward, val, range)) { int mask = (Object.op_Implicit((Object)(object)StartOfRound.Instance) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-5)); if (PromiseAttentionSelection.Visible(origin, val, mask, ((Component)owner).transform, model, value.transform, hits)) { int instanceID = ((Object)value).GetInstanceID(); objects[instanceID] = (Object)(object)value; candidates.Add(new AttentionCandidate(instanceID, kind, Vector3.Distance(origin, val), speaking)); } } } public bool Resolve(PlayerControllerB owner, Transform model, Vector3 origin, Vector3 forward, float now, out Vector3 direction) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) direction = forward; if (!Object.op_Implicit((Object)(object)owner) || owner.isPlayerDead || !owner.isPlayerControlled || !Object.op_Implicit((Object)(object)StartOfRound.Instance)) { Reset(); return false; } if (now >= nextScan) { nextScan = now + 0.1f; candidates.Clear(); objects.Clear(); ScanScene(now); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val == (Object)(object)owner) && val.isPlayerControlled && !val.isPlayerDead && ((Component)val).gameObject.activeInHierarchy) { bool flag = PromiseVoiceActivity.IsSpeaking(val); if (flag || (selection.HasTarget && selection.CurrentKind == AttentionKind.Player && selection.CurrentKey == ((Object)val).GetInstanceID())) { Add((Component)(object)val, AttentionKind.Player, origin, forward, Plugin.TalkingPlayersRange.Value, flag, owner, model); } } } EnemyAI[] array = enemies; foreach (EnemyAI val2 in array) { if (Object.op_Implicit((Object)(object)val2) && !val2.isEnemyDead && ((Behaviour)val2).isActiveAndEnabled) { Add((Component)(object)val2, AttentionKind.Enemy, origin, forward, Plugin.EnemiesRange.Value, speaking: false, owner, model); } } GrabbableObject[] array2 = items; foreach (GrabbableObject val3 in array2) { if (Object.op_Implicit((Object)(object)val3) && !val3.isHeld && !val3.isPocketed && !val3.isHeldByEnemy && ((Behaviour)val3).isActiveAndEnabled) { Add((Component)(object)val3, AttentionKind.Item, origin, forward, Plugin.ItemsRange.Value, speaking: false, owner, model); } } int key = selection.Choose(candidates, now, Plugin.SpeechPauseHold.Value); target = ((selection.HasTarget && objects.TryGetValue(key, out var value)) ? value : null); } if (!Object.op_Implicit(target)) { return false; } Object obj = target; PlayerControllerB val4 = (PlayerControllerB)(object)((obj is PlayerControllerB) ? obj : null); if (val4 == null || (val4.isPlayerControlled && !val4.isPlayerDead)) { Object obj2 = target; EnemyAI val5 = (EnemyAI)(object)((obj2 is EnemyAI) ? obj2 : null); if (val5 == null || !val5.isEnemyDead) { Object obj3 = target; GrabbableObject val6 = (GrabbableObject)(object)((obj3 is GrabbableObject) ? obj3 : null); if (val6 == null || (!val6.isHeld && !val6.isPocketed && !val6.isHeldByEnemy)) { direction = Point(target) - origin; return ((Vector3)(ref direction)).sqrMagnitude > 1E-06f; } } } target = null; selection.Reset(); nextScan = 0f; return false; } } internal static class PromiseVoiceActivity { private static object comms; private static readonly Dictionary<int, float> retry = new Dictionary<int, float>(); private static readonly Dictionary<int, object> states = new Dictionary<int, object>(); internal static bool IsSpeaking(PlayerControllerB player) { object obj = PromiseFace.Read(player, "voicePlayerState") ?? PromiseFace.Read(PromiseFace.Read(player, "currentVoiceChatIngameSettings"), "_playerState"); int instanceID = ((Object)player).GetInstanceID(); if (obj == null && states.TryGetValue(instanceID, out var value)) { obj = value; } if (obj == null && (!retry.TryGetValue(instanceID, out var value2) || Time.unscaledTime >= value2)) { retry[instanceID] = Time.unscaledTime + 1f; comms = PromiseFace.Read(StartOfRound.Instance, "voiceChatModule"); if (comms != null) { string text = (((NetworkBehaviour)player).IsOwner ? (PromiseFace.Read(comms, "LocalPlayerName") as string) : (PromiseFace.Read(player, "voicePlayerName") as string)); if (!string.IsNullOrEmpty(text)) { try { obj = PromiseRuntimeMembers.CallString(comms, "FindPlayer", text); if (obj != null) { states[instanceID] = obj; } } catch { } } } } bool value3; bool flag = PromiseRuntimeMembers.TryRead<bool>(obj, "IsSpeaking", out value3) && value3; if (PromiseRuntimeMembers.TryRead<bool>(obj, "IsConnected", out var value4) && !value4) { return false; } if (!PromiseRuntimeMembers.TryRead<float>(obj, "Amplitude", out var value5)) { return flag; } return PromiseAttentionSelection.ActiveSpeech(flag, value5); } internal static void Clear() { comms = null; retry.Clear(); states.Clear(); } } public static class PromiseClockMath { public static float Minutes(float normalized, float hours) { if (float.IsNaN(normalized) || float.IsInfinity(normalized) || float.IsNaN(hours) || float.IsInfinity(hours) || hours <= 0f) { return 360f; } return Mathf.Clamp(normalized * 60f * hours + 360f, 360f, 1440f); } public static Vector3 Angles(float minutes) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (float.IsNaN(minutes) || float.IsInfinity(minutes)) { minutes = 360f; } return new Vector3(Mathf.Repeat(minutes, 720f) * 0.5f, Mathf.Repeat(minutes, 60f) * 6f, Mathf.Repeat(minutes * 60f, 60f) * 6f); } } [DefaultExecutionOrder(850)] public sealed class PromiseClock : MonoBehaviour { [Serializable] public class Hand { public Transform Bone; public Quaternion Neutral = Quaternion.identity; public Vector3 Axis; public Vector3 Up; public Vector3 RestDirection; } public Hand Hour; public Hand Minute; public Hand Second; public float LastGameMinutes = 360f; public bool HasGameTime; private PromiseOutfitState state; public bool SyncEnabled { get; private set; } public void SetMinutes(float minutes) { //IL_0008: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) LastGameMinutes = minutes; Vector3 val = PromiseClockMath.Angles(minutes); Apply(Hour, val.x); Apply(Minute, val.y); Apply(Second, val.z); } private static void Apply(Hand hand, float clockwiseDegrees) { //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_0024: 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_002f: 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_003a: 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) if (hand != null && Object.op_Implicit((Object)(object)hand.Bone)) { hand.Bone.localRotation = Quaternion.AngleAxis(clockwiseDegrees, hand.Axis) * Quaternion.FromToRotation(hand.RestDirection, hand.Up) * hand.Neutral; } } private static void Restore(Hand hand) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (hand != null && Object.op_Implicit((Object)(object)hand.Bone)) { hand.Bone.localRotation = hand.Neutral; } } public void UpdateClock(float minutes) { if (!Object.op_Implicit((Object)(object)state)) { state = ((Component)this).GetComponent<PromiseOutfitState>(); } LastGameMinutes = minutes; SyncEnabled = Object.op_Implicit((Object)(object)state) && (state.AlternateMask & 4) != 0; if (SyncEnabled) { SetMinutes(minutes); return; } Restore(Hour); Restore(Minute); Restore(Second); } private void LateUpdate() { float minutes = LastGameMinutes; TimeOfDay instance = TimeOfDay.Instance; if (Object.op_Implicit((Object)(object)instance)) { HasGameTime = true; minutes = PromiseClockMath.Minutes(instance.normalizedTimeOfDay, instance.numberOfHours); } UpdateClock(minutes); } } public enum PromiseExpression : byte { Neutral, Frightened, Hurt, Happy, Surprised, VeryHappy, Dead } public struct PromiseExpressionContext { public bool Dead; public bool Critical; public bool EnemyNear; public bool Fear; public bool Chased; public bool Dancing; public bool Unsafe { get { if (!EnemyNear && !Fear) { return Chased; } return true; } } } public sealed class PromiseExpressionSelection { private double hurtUntil = -1.0; private double treasureUntil = -1.0; private bool surprised = true; private int pickups; public void Damage(double now) { hurtUntil = now + 2.0; } public void PickedUp(int value, double now) { if (value > 100) { treasureUntil = now + 3.5; surprised = pickups++ % 2 == 0; } } public void Reset() { hurtUntil = (treasureUntil = -1.0); pickups = 0; surprised = true; } public PromiseExpression Choose(PromiseExpressionContext c, double now) { if (c.Dead) { return PromiseExpression.Dead; } if (c.Critical || now < hurtUntil) { return PromiseExpression.Hurt; } if (c.Unsafe) { return PromiseExpression.Frightened; } if (now < treasureUntil) { if (!surprised) { return PromiseExpression.VeryHappy; } return PromiseExpression.Surprised; } if (c.Dancing) { return PromiseExpression.Happy; } return PromiseExpression.Neutral; } } public struct PromiseExpressionWeight { public string Shape; public float Weight; public bool Eyes; public bool Mouth; public PromiseExpressionWeight(string shape, float weight, bool eyes = false, bool mouth = false) { Shape = "expr_" + shape; Weight = weight; Eyes = eyes; Mouth = mouth; } } public static class PromiseExpressionProfiles { private static readonly PromiseExpressionWeight[][] profiles = new PromiseExpressionWeight[7][] { new PromiseExpressionWeight[0], new PromiseExpressionWeight[4] { B("worry", 0.75f), B("brow_up", 0.25f), E("surprise", 0.85f), M("triangle", 0.6f) }, new PromiseExpressionWeight[4] { B("worry", 0.85f), B("serious", 0.25f), E("focus", 0.45f), M("clench", 0.8f) }, new PromiseExpressionWeight[3] { B("happy_brows", 0.45f), E("smile_eyes", 0.65f), M("smile", 0.85f) }, new PromiseExpressionWeight[3] { B("brow_up", 0.65f), E("surprise", 0.9f), M("o", 0.65f) }, new PromiseExpressionWeight[3] { B("happy_brows", 0.65f), E("smile_eyes", 0.85f), M("laugh", 0.85f) }, new PromiseExpressionWeight[2] { B("worry", 0.7f), M("clench", 0.55f) } }; private static PromiseExpressionWeight B(string n, float w) { return new PromiseExpressionWeight(n, w); } private static PromiseExpressionWeight E(string n, float w) { return new PromiseExpressionWeight(n, w, eyes: true); } private static PromiseExpressionWeight M(string n, float w) { return new PromiseExpressionWeight(n, w, eyes: false, mouth: true); } public static PromiseExpressionWeight[] Weights(PromiseExpression state) { return profiles[(uint)state]; } } public sealed class PromiseExpressionMixer { private sealed class Binding { public SkinnedMeshRenderer Renderer; public int[] Indices; public int Blink; public int Open; public int Round; } private readonly List<string> shapes = new List<string>(); private readonly Dictionary<string, int> slots = new Dictionary<string, int>(); private readonly List<Binding> bindings = new List<Binding>(); private float[] values; private float[] target; private bool[] eyes; private bool[] mouth; public PromiseExpressionMixer(GameObject model) { foreach (PromiseExpression value in Enum.GetValues(typeof(PromiseExpression))) { PromiseExpressionWeight[] array = PromiseExpressionProfiles.Weights(value); for (int i = 0; i < array.Length; i++) { PromiseExpressionWeight promiseExpressionWeight = array[i]; if (!slots.ContainsKey(promiseExpressionWeight.Shape)) { slots[promiseExpressionWeight.Shape] = shapes.Count; shapes.Add(promiseExpressionWeight.Shape); } } } values = new float[shapes.Count]; target = new float[shapes.Count]; eyes = new bool[shapes.Count]; mouth = new bool[shapes.Count]; foreach (PromiseExpression value2 in Enum.GetValues(typeof(PromiseExpression))) { PromiseExpressionWeight[] array = PromiseExpressionProfiles.Weights(value2); for (int i = 0; i < array.Length; i++) { PromiseExpressionWeight promiseExpressionWeight2 = array[i]; int num = slots[promiseExpressionWeight2.Shape]; eyes[num] |= promiseExpressionWeight2.Eyes; mouth[num] |= promiseExpressionWeight2.Mouth; } } SkinnedMeshRenderer[] componentsInChildren = model.GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val.sharedMesh) && !PromiseInkOutline.IsInk(val)) { Binding binding = new Binding { Renderer = val, Indices = new int[shapes.Count], Blink = val.sharedMesh.GetBlendShapeIndex("blink"), Open = val.sharedMesh.GetBlendShapeIndex("speech_open"), Round = val.sharedMesh.GetBlendShapeIndex("speech_round") }; for (int j = 0; j < shapes.Count; j++) { binding.Indices[j] = val.sharedMesh.GetBlendShapeIndex(shapes[j]); } bindings.Add(binding); } } } public void Step(PromiseExpression state, float delta, bool immediate = false) { Array.Clear(target, 0, target.Length); PromiseExpressionWeight[] array = PromiseExpressionProfiles.Weights(state); for (int i = 0; i < array.Length; i++) { PromiseExpressionWeight promiseExpressionWeight = array[i]; target[slots[promiseExpressionWeight.Shape]] = promiseExpressionWeight.Weight; } float num = ((immediate || state == PromiseExpression.Dead) ? 1f : (1f - Mathf.Exp((0f - Mathf.Clamp(delta, 0f, 0.1f)) * 13f))); for (int j = 0; j < values.Length; j++) { values[j] = Mathf.Lerp(values[j], target[j], num); } foreach (Binding binding in bindings) { if (!Object.op_Implicit((Object)(object)binding.Renderer)) { continue; } float num2 = ((binding.Blink < 0) ? 0f : Mathf.Clamp01(binding.Renderer.GetBlendShapeWeight(binding.Blink) / 100f)); float num3 = ((binding.Open < 0) ? 0f : Mathf.Clamp01(binding.Renderer.GetBlendShapeWeight(binding.Open) / 85f)); if (state == PromiseExpression.Dead) { num2 = 1f; num3 = 0f; if (binding.Blink >= 0) { binding.Renderer.SetBlendShapeWeight(binding.Blink, 100f); } if (binding.Open >= 0) { binding.Renderer.SetBlendShapeWeight(binding.Open, 0f); } if (binding.Round >= 0) { binding.Renderer.SetBlendShapeWeight(binding.Round, 0f); } } for (int k = 0; k < values.Length; k++) { if (binding.Indices[k] >= 0) { float num4 = values[k]; if (eyes[k]) { num4 *= 1f - num2; } if (mouth[k]) { num4 *= 1f - num3 * 0.55f; } binding.Renderer.SetBlendShapeWeight(binding.Indices[k], num4 * 100f); } } } } } [DefaultExecutionOrder(280)] public sealed class PromiseDeathFace : MonoBehaviour { private PromiseExpressionMixer mixer; public void Initialize() { mixer = new PromiseExpressionMixer(((Component)this).gameObject); mixer.Step(PromiseExpression.Dead, 0f, immediate: true); } private void LateUpdate() { if (mixer == null) { Initialize(); } mixer.Step(PromiseExpression.Dead, 0f, immediate: true); } } public struct PromiseExpressionRecord { public ulong PlayerId; public ulong Owner; public byte Character; public PromiseExpression Expression; public uint Revision; } public sealed class PromiseExpressionStore { private sealed class Entry { public PromiseExpressionRecord Record; public double At; } private readonly Dictionary<ulong, Entry> records = new Dictionary<ulong, Entry>(); public bool Accept(ulong sender, ulong actualOwner, PromiseExpressionRecord value, double now) { if (sender != actualOwner || value.Owner != actualOwner || value.Character >= PromiseOutfitProtocol.Characters.Length || (int)value.Expression > 6 || double.IsNaN(now) || double.IsInfinity(now)) { return false; } if (records.TryGetValue(value.PlayerId, out var value2) && value2.Record.Owner == actualOwner && (value.Revision < value2.Record.Revision || (value.Revision == value2.Record.Revision && (value.Character != value2.Record.Character || value.Expression != value2.Record.Expression)))) { return false; } records[value.PlayerId] = new Entry { Record = value, At = now }; return true; } public bool TryGet(ulong id, double now, out PromiseExpressionRecord value) { value = default(PromiseExpressionRecord); if (!records.TryGetValue(id, out var value2) || now - value2.At > 5.0 || now < value2.At) { return false; } value = value2.Record; return true; } public uint NextRevision(ulong id, ulong owner) { if (!records.TryGetValue(id, out var value) || value.Record.Owner != owner) { return 1u; } return value.Record.Revision + 1; } public PromiseExpressionRecord[] Snapshot(double now) { List<PromiseExpressionRecord> list = new List<PromiseExpressionRecord>(); foreach (Entry value in records.Values) { if (now >= value.At && now - value.At <= 5.0) { list.Add(value.Record); } } list.Sort((PromiseExpressionRecord a, PromiseExpressionRecord b) => a.PlayerId.CompareTo(b.PlayerId)); return list.ToArray(); } public void RemoveOwner(ulong owner) { List<ulong> list = new List<ulong>(); foreach (KeyValuePair<ulong, Entry> record in records) { if (record.Value.Record.Owner == owner) { list.Add(record.Key); } } foreach (ulong item in list) { records.Remove(item); } } public void Clear() { records.Clear(); } } public static class PromiseFirstPersonMesh { private sealed class Entry { public Mesh Mesh; public int[] BoneIndices; public int[] MaterialSlots; } private static readonly Dictionary<Mesh, Entry> Cache = new Dictionary<Mesh, Entry>(); public static int CachedMeshes => Cache.Count; private static HashSet<Transform> ArmBones(GameObject model) { //IL_0042: 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) Animator componentInChildren = model.GetComponentInChildren<Animator>(true); if (!Object.op_Implicit((Object)(object)componentInChildren) || !componentInChildren.isHuman) { throw new InvalidOperationException("Promise first-person avatar must be humanoid."); } HashSet<Transform> hashSet = new HashSet<Transform>(); HumanBodyBones[] array = new HumanBodyBones[6]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); HumanBodyBones[] array2 = (HumanBodyBones[])(object)array; foreach (HumanBodyBones val in array2) { Transform boneTransform = componentInChildren.GetBoneTransform(val); if (Object.op_Implicit((Object)(object)boneTransform)) { Transform[] componentsInChildren = ((Component)boneTransform).GetComponentsInChildren<Transform>(true); foreach (Transform item in componentsInChildren) { hashSet.Add(item); } } } return hashSet; } public static void Prime(GameObject model) { HashSet<Transform> arms = ArmBones(model); SkinnedMeshRenderer[] componentsInChildren = model.GetComponentsInChildren<SkinnedMeshRenderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Get(componentsInChildren[i], arms); } } public static IEnumerator PrimeIncremental(GameObject model) { HashSet<Transform> arms = ArmBones(model); SkinnedMeshRenderer[] componentsInChildren = model.GetComponentsInChildren<SkinnedMeshRenderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Get(componentsInChildren[i], arms); yield return null; } } private static bool Allowed(BoneWeight weight, bool[] bones) { if ((((BoneWeight)(ref weight)).weight0 <= 0f || bones[((BoneWeight)(ref weight)).boneIndex0]) && (((BoneWeight)(ref weight)).weight1 <= 0f || bones[((BoneWeight)(ref weight)).boneIndex1]) && (((BoneWeight)(ref weight)).weight2 <= 0f || bones[((BoneWeight)(ref weight)).boneIndex2])) { if (!(((BoneWeight)(ref weight)).weight3 <= 0f)) { return bones[((BoneWeight)(ref weight)).boneIndex3]; } return true; } return false; } private static Entry Get(SkinnedMeshRenderer renderer, HashSet<Transform> arms) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Expected O, but got Unknown //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) Mesh sharedMesh = renderer.sharedMesh; if (!Object.op_Implicit((Object)(object)sharedMesh)) { return null; } if (Cache.TryGetValue(sharedMesh, out var value)) { return value; } if (!sharedMesh.isReadable) { throw new InvalidOperationException("Promise first-person source mesh is not readable: " + ((Object)sharedMesh).name); } Transform[] bones = renderer.bones; bool[] array = new bool[bones.Length]; for (int i = 0; i < array.Length; i++) { array[i] = Object.op_Implicit((Object)(object)bones[i]) && arms.Contains(bones[i]); } BoneWeight[] boneWeights = sharedMesh.boneWeights; if (boneWeights.Length != sharedMesh.vertexCount) { throw new InvalidOperationException("Promise arms require four-weight source skinning."); } bool[] array2 = new bool[sharedMesh.vertexCount]; for (int j = 0; j < boneWeights.Length; j++) { array2[j] = Allowed(boneWeights[j], array); } List<int> list = new List<int>(); Dictionary<int, int> dictionary = new Dictionary<int, int>(); List<int[]> list2 = new List<int[]>(); List<int> list3 = new List<int>(); for (int k = 0; k < sharedMesh.subMeshCount; k++) { int[] triangles = sharedMesh.GetTriangles(k); List<int> list4 = new List<int>(); for (int l = 0; l < triangles.Length; l += 3) { if (!array2[triangles[l]] || !array2[triangles[l + 1]] || !array2[triangles[l + 2]]) { continue; } for (int m = 0; m < 3; m++) { int num = triangles[l + m]; if (!dictionary.TryGetValue(num, out var value2)) { value2 = list.Count; dictionary.Add(num, value2); list.Add(num); } list4.Add(value2); } } if (list4.Count > 0) { list3.Add(k); list2.Add(list4.ToArray()); } } if (list.Count == 0) { Cache.Add(sharedMesh, null); return null; } List<int> list5 = new List<int>(); Dictionary<int, int> dictionary2 = new Dictionary<int, int>(); BoneWeight[] array3 = (BoneWeight[])(object)new BoneWeight[list.Count]; for (int n = 0; n < array3.Length; n++) { BoneWeight val = boneWeights[list[n]]; int[] array4 = new int[4] { ((BoneWeight)(ref val)).boneIndex0, ((BoneWeight)(ref val)).boneIndex1, ((BoneWeight)(ref val)).boneIndex2, ((BoneWeight)(ref val)).boneIndex3 }; float[] array5 = new float[4] { ((BoneWeight)(ref val)).weight0, ((BoneWeight)(ref val)).weight1, ((BoneWeight)(ref val)).weight2, ((BoneWeight)(ref val)).weight3 }; for (int num2 = 0; num2 < 4; num2++) { if (array5[num2] <= 0f) { array4[num2] = 0; continue; } if (!dictionary2.TryGetValue(array4[num2], out var value3)) { value3 = list5.Count; dictionary2.Add(array4[num2], value3); list5.Add(array4[num2]); } array4[num2] = value3; } ((BoneWeight)(ref val)).boneIndex0 = array4[0]; ((BoneWeight)(ref val)).boneIndex1 = array4[1]; ((BoneWeight)(ref val)).boneIndex2 = array4[2]; ((BoneWeight)(ref val)).boneIndex3 = array4[3]; array3[n] = val; } Mesh val2 = new Mesh { name = ((Object)sharedMesh).name + "_PromiseFirstPerson", indexFormat = (IndexFormat)(list.Count > 65535) }; val2.vertices = Subset(sharedMesh.vertices, list); if (sharedMesh.normals.Length == sharedMesh.vertexCount) { val2.normals = Subset(sharedMesh.normals, list); } if (sharedMesh.tangents.Length == sharedMesh.vertexCount) { val2.tangents = Subset(sharedMesh.tangents, list); } if (sharedMesh.colors32.Length == sharedMesh.vertexCount) { val2.colors32 = Subset(sharedMesh.colors32, list); } for (int num3 = 0; num3 < 8; num3++) { List<Vector4> list6 = new List<Vector4>(); sharedMesh.GetUVs(num3, list6); if (list6.Count == sharedMesh.vertexCount) { val2.SetUVs(num3, Subset(list6.ToArray(), list)); } } for (int num4 = 0; num4 < sharedMesh.blendShapeCount; num4++) { string blendShapeName = sharedMesh.GetBlendShapeName(num4); if (!blendShapeName.StartsWith("opt_", StringComparison.Ordinal)) { continue; } Vector3[] array6 = (Vector3[])(object)new Vector3[sharedMesh.vertexCount]; sharedMesh.GetBlendShapeFrameVertices(num4, 0, array6, (Vector3[])null, (Vector3[])null); Vector3[] array7 = Subset(array6, list); bool flag = false; Vector3[] array8 = array7; for (int num5 = 0; num5 < array8.Length; num5++) { Vector3 val3 = array8[num5]; if (((Vector3)(ref val3)).sqrMagnitude > 1E-14f) { flag = true; break; } } if (flag) { val2.AddBlendShapeFrame(blendShapeName, sharedMesh.GetBlendShapeFrameWeight(num4, 0), array7, (Vector3[])null, (Vector3[])null); } } val2.boneWeights = array3; val2.bindposes = Subset(sharedMesh.bindposes, list5); val2.subMeshCount = list2.Count; for (int num6 = 0; num6 < list2.Count; num6++) { val2.SetTriangles(list2[num6], num6, false); } val2.RecalculateBounds(); value = new Entry { Mesh = val2, BoneIndices = list5.ToArray(), MaterialSlots = list3.ToArray() }; Cache.Add(sharedMesh, value); return value; } private static T[] Subset<T>(T[] source, List<int> indices) { T[] array = new T[indices.Count]; for (int i = 0; i < indices.Count; i++) { array[i] = source[indices[i]]; } return array; } public static GameObject Convert(GameObject model) { PromiseSourceRotationGrant component = model.GetComponent<PromiseSourceRotationGrant>(); PromiseSourceRotationGrant.Grant[] sourceGrants = (Object.op_Implicit((Object)(object)component) ? component.grants : null); HashSet<Transform> arms = ArmBones(model); SkinnedMeshRenderer[] componentsInChildren = model.GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { Entry entry = Get(val, arms); if (entry == null) { ((Renderer)val).enabled = false; Remove((Object)(object)val); continue; } Transform[] bones = val.bones; Material[] sharedMaterials = ((Renderer)val).sharedMaterials; Transform[] array = (Transform[])(object)new Transform[entry.BoneIndices.Length]; Material[] array2 = (Material[])(object)new Material[entry.MaterialSlots.Length]; for (int j = 0; j < array.Length; j++) { array[j] = bones[entry.BoneIndices[j]]; } for (int k = 0; k < array2.Length; k++) { array2[k] = sharedMaterials[entry.MaterialSlots[k]]; } val.sharedMesh = entry.Mesh; val.bones = array; ((Renderer)val).sharedMaterials = array2; val.quality = (SkinQuality)4; val.updateWhenOffscreen = true; ((Renderer)val).shadowCastingMode = (ShadowCastingMode)0; } StripSimulation(model); PromiseViewModelPose obj = model.GetComponent<PromiseViewModelPose>() ?? model.AddComponent<PromiseViewModelPose>(); obj.SourceGrants = sourceGrants; obj.Initialize(); model.GetComponent<PromiseAdaptiveLighting>()?.Rebind(); model.GetComponent<PromiseOutfitState>()?.Rebind(); return model; } public static void StripSimulation(GameObject model) { Collider[] componentsInChildren = model.GetComponentsInChildren<Collider>(true); foreach (Collider obj in componentsInChildren) { obj.enabled = false; Remove((Object)(object)obj); } MonoBehaviour[] componentsInChildren2 = model.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren2) { if (Object.op_Implicit((Object)(object)val)) { switch (((object)val).GetType().FullName) { case "PromiseSuit.PromiseSecondaryMotion": case "PromiseSuit.PromiseHeadTracking": case "PromiseSuit.PromiseFace": case "PromiseSuit.PromiseToonFrame": case "PromiseSuit.PromiseSourceRotationGrant": case "PromiseSuit.PromiseReactionFace": case "JigglePhysics.JiggleRigBuilder": ((Behaviour)val).enabled = false; Remove((Object)(object)val); break; } } } } private static void Remove(Object component) { if (Application.isPlaying) { Object.Destroy(component); } else { Object.DestroyImmediate(component); } } public static void Clear() { foreach (Entry value in Cache.Values) { if (value != null && Object.op_Implicit((Object)(object)value.Mesh)) { Remove((Object)(object)value.Mesh); } } Cache.Clear(); } } public static class PromiseFirstPersonPatch { public static void Install(Harmony harmony) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown Type type = typeof(BodyReplacementBase).Assembly.GetType("ModelReplacement.Scripts.MeshHelper", throwOnError: true); MethodInfo methodInfo = AccessTools.Method(type, "ConvertModelToViewModel", new Type[1] { typeof(GameObject) }, (Type[])null); if (methodInfo == null) { throw new MissingMethodException(type.FullName, "ConvertModelToViewModel"); } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PromiseFirstPersonPatch), "BeforeConvert", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(BodyReplacementBase), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PromiseFirstPersonPatch), "AfterBodyCreated", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Type type2 = typeof(BodyReplacementBase).Assembly.GetType("ModelReplacement.Scripts.Player.ViewModelUpdater", throwOnError: true); MethodInfo methodInfo2 = AccessTools.Method(type2, "UpdateViewModel", Type.EmptyTypes, (Type[])null); if (methodInfo2 == null) { throw new MissingMethodException(type2.FullName, "UpdateViewModel"); } harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(PromiseFirstPersonPatch), "BeforeViewPose", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(type2, "AssignViewModelReplacement", new Type[2] { typeof(GameObject), typeof(GameObject) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PromiseFirstPersonPatch), "AfterViewAssigned", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static bool BeforeConvert(GameObject __0, ref GameObject __result) { if (!Object.op_Implicit((Object)(object)__0) || !((Object)__0).name.StartsWith("Promise_", StringComparison.Ordinal)) { return true; } __result = PromiseFirstPersonMesh.Convert(__0); return false; } private static void AfterBodyCreated(BodyReplacementBase __instance) { if (!(__instance is PromiseBody)) { return; } object? value = AccessTools.Field(typeof(BodyReplacementBase), "replacementModel").GetValue(__instance); GameObject val = (GameObject)((value is GameObject) ? value : null); object? value2 = AccessTools.Field(typeof(BodyReplacementBase), "replacementModelShadow").GetValue(__instance); GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2)) { PromiseFirstPersonMesh.StripSimulation(val2); val2.AddComponent<PromiseShadowPose>().Initialize(val); } object? value3 = AccessTools.Field(typeof(BodyReplacementBase), "replacementViewModel").GetValue(__instance); GameObject val3 = (GameObject)((value3 is GameObject) ? value3 : null); if (Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)__instance.controller)) { PromiseViewModelPose component = val3.GetComponent<PromiseViewModelPose>(); SkinnedMeshRenderer thisPlayerModelArms = __instance.controller.thisPlayerModelArms; if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)thisPlayerModelArms)) { component.Bind(thisPlayerModelArms, __instance.controller.playerModelArmsMetarig); } } } private static bool BeforeViewPose(ViewModelUpdater __instance) { GameObject replacementViewModel = __instance.replacementViewModel; if (!Object.op_Implicit((Object)(object)replacementViewModel)) { return true; } PromiseViewModelPose component = replacementViewModel.GetComponent<PromiseViewModelPose>(); if (Object.op_Implicit((Object)(object)component)) { return !component.Step(); } return true; } private static void AfterViewAssigned(GameObject __0, GameObject __1) { if (!Object.op_Implicit((Object)(object)__0) || !Object.op_Implicit((Object)(object)__1)) { return; } PromiseOutfitControl.AttachView(__0, __1); PromiseViewModelPose component = __1.GetComponent<PromiseViewModelPose>(); if (Object.op_Implicit((Object)(object)component)) { PlayerControllerB component2 = __0.GetComponent<PlayerControllerB>(); if (Object.op_Implicit((Object)(object)component2)) { component.Bind(component2.thisPlayerModelArms, component2.playerModelArmsMetarig); } } } } public class PromiseFootAlignment : MonoBehaviour { private Transform hip; private Transform leftSole; private Transform rightSole; private Transform playerLeft; private Transform playerRight; private Vector3 leftReference; private Vector3 rightReference; private SkinnedMeshRenderer source; private bool ready; public float LastCorrection { get; private set; } public void Align(SkinnedMeshRenderer player) { //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: 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_01d2: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return; } if (!ready || (Object)(object)source != (Object)(object)player) { source = player; Animator component = ((Component)this).GetComponent<Animator>(); if (!Object.op_Implicit((Object)(object)component) || !component.isHuman) { return; } hip = component.GetBoneTransform((HumanBodyBones)0); Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true); leftSole = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PromiseSole.L")); rightSole = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PromiseSole.R")); Transform val = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "EmployeeSoleReference.L")); Transform val2 = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "EmployeeSoleReference.R")); playerLeft = ((IEnumerable<Transform>)player.bones).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "foot.L")); playerRight = ((IEnumerable<Transform>)player.bones).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "foot.R")); ready = Object.op_Implicit((Object)(object)hip) && Object.op_Implicit((Object)(object)leftSole) && Object.op_Implicit((Object)(object)rightSole) && Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)playerLeft) && Object.op_Implicit((Object)(object)playerRight); if (!ready) { return; } leftReference = val.localPosition; rightReference = val2.localPosition; } float num = Mathf.Min(playerLeft.TransformPoint(leftReference).y, playerRight.TransformPoint(rightReference).y); float num2 = Mathf.Min(leftSole.position.y, rightSole.position.y); LastCorrection = num - num2; if (!float.IsNaN(LastCorrection) && !float.IsInfinity(LastCorrection)) { Transform obj = hip; obj.position += Vector3.up * LastCorrection; } } } public class PromiseHandAlignment : MonoBehaviour { private class Arm { public Transform Upper; public Transform Lower; public Transform Hand; public Transform PlayerUpper; public Transform PlayerLower; public Transform PlayerHand; } private Arm[] arms; private SkinnedMeshRenderer source; public void Align(SkinnedMeshRenderer player) { //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return; } if (arms == null || (Object)(object)source != (Object)(object)player) { Animator component = ((Component)this).GetComponent<Animator>(); if (!Object.op_Implicit((Object)(object)component) || !component.isHuman) { return; } source = player; arms = new Arm[2]; for (int i = 0; i < 2; i++) { bool flag = i == 0; string s = (flag ? "L" : "R"); arms[i] = new Arm { Upper = component.GetBoneTransform((HumanBodyBones)(flag ? 13 : 14)), Lower = component.GetBoneTransform((HumanBodyBones)(flag ? 15 : 16)), Hand = component.GetBoneTransform((HumanBodyBones)(flag ? 17 : 18)), PlayerUpper = ((IEnumerable<Transform>)player.bones).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "arm." + s + "_upper")), PlayerLower = ((IEnumerable<Transform>)player.bones).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "arm." + s + "_lower")), PlayerHand = ((IEnumerable<Transform>)player.bones).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "hand." + s)) }; } } Arm[] array = arms; foreach (Arm arm in array) { if (Object.op_Implicit((Object)(object)arm.Upper) && Object.op_Implicit((Object)(object)arm.Lower) && Object.op_Implicit((Object)(object)arm.Hand) && Object.op_Implicit((Object)(object)arm.PlayerUpper) && Object.op_Implicit((Object)(object)arm.PlayerLower) && Object.op_Implicit((Object)(object)arm.PlayerHand)) { Quaternion rotation = arm.Hand.rotation; Aim(arm.Upper, arm.Lower, arm.PlayerLower.position