Decompiled source of JohnFister v1.1.1
JohnFister.dll
Decompiled an hour ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JohnFister.Body; using JohnFister.Core; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Utilities; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("JohnFister")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("JohnFister")] [assembly: AssemblyTitle("JohnFister")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] namespace JohnFister { internal static class Assets { private static string dir; private static readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>(); private static Shader unlit; private static bool preloaded; private static Texture2D white; internal static string Dir { get { if (dir != null) { return dir; } string pluginDir = FisterPlugin.PluginDir; string text = (dir = Path.Combine(pluginDir, "assets")); if (!File.Exists(Path.Combine(text, "body.txt"))) { try { string text2 = Directory.GetFiles(pluginDir, "body.txt", SearchOption.AllDirectories).FirstOrDefault(); if (text2 != null) { dir = Path.GetDirectoryName(text2); FisterPlugin.Log.LogWarning((object)("assets are not in " + text + "; using " + dir)); } else { FisterPlugin.Log.LogError((object)("John Fister's assets are missing: no body.txt under " + pluginDir + ". Reinstall the mod (the package's assets folder must sit next to JohnFister.dll).")); } } catch (Exception ex) { FisterPlugin.Log.LogError((object)("asset search failed: " + ex.Message)); } } return dir; } } internal static Texture2D White { get { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)white == (Object)null) { white = new Texture2D(4, 4, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[16]; for (int i = 0; i < 16; i++) { array[i] = Color.white; } white.SetPixels(array); white.Apply(); Object.DontDestroyOnLoad((Object)(object)white); } return white; } } internal static Shader Unlit { get { if ((Object)(object)unlit == (Object)null) { unlit = ((IEnumerable<Shader>)Resources.FindObjectsOfTypeAll<Shader>()).FirstOrDefault((Func<Shader, bool>)((Shader s) => (Object)(object)s != (Object)null && ((Object)s).name == "Particles/Standard Unlit")); if ((Object)(object)unlit == (Object)null) { unlit = Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Unlit/Texture") ?? Shader.Find("Sprites/Default"); FisterPlugin.Log.LogWarning((object)("Particles/Standard Unlit is not loaded; John is drawn with " + (((Object)(object)unlit != (Object)null) ? ((Object)unlit).name : "NO SHADER"))); } } return unlit; } } internal static string Find(string sub, string file) { string text = Path.Combine(Path.Combine(Dir, sub), file); if (File.Exists(text)) { return text; } string text2 = Path.Combine(Dir, file); if (File.Exists(text2)) { return text2; } try { return Directory.GetFiles(FisterPlugin.PluginDir, file, SearchOption.AllDirectories).FirstOrDefault() ?? text; } catch (Exception) { return text; } } internal static Texture2D Tex(string name) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (textures.TryGetValue(name, out var value) && (Object)(object)value != (Object)null) { return value; } string text = Find("tex", name + ".png"); value = new Texture2D(2, 2, (TextureFormat)4, true); if (File.Exists(text)) { ImageConversion.LoadImage(value, File.ReadAllBytes(text)); } else { FisterPlugin.Log.LogError((object)("missing texture " + text)); } ((Object)value).name = "fister_" + name; ((Texture)value).wrapMode = (TextureWrapMode)1; ((Texture)value).filterMode = (FilterMode)1; Object.DontDestroyOnLoad((Object)(object)value); textures[name] = value; return value; } internal static void PreloadAll() { if (preloaded) { return; } preloaded = true; try { string path = Path.Combine(Dir, "tex"); if (Directory.Exists(path)) { string[] files = Directory.GetFiles(path, "*.png"); for (int i = 0; i < files.Length; i++) { Tex(Path.GetFileNameWithoutExtension(files[i])); } } string path2 = Path.Combine(Dir, "sfx"); if (Directory.Exists(path2)) { string[] files = Directory.GetFiles(path2, "*.wav"); for (int i = 0; i < files.Length; i++) { FisterAudio.Clip(Path.GetFileNameWithoutExtension(files[i])); } } _ = Unlit; Fx.Prewarm(); } catch (Exception ex) { FisterPlugin.Log.LogWarning((object)("preload: " + ex.Message)); } } internal static Material Material(Texture tex, int cull, bool transparent = false, bool additive = false) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(Unlit); val.mainTexture = tex; val.SetColor("_Color", Color.white); val.SetFloat("_Cull", (float)cull); if (transparent) { val.SetFloat("_Mode", 2f); val.SetFloat("_SrcBlend", 5f); val.SetFloat("_DstBlend", additive ? 1f : 10f); val.SetFloat("_ZWrite", 0f); val.renderQueue = 3000; } else { val.SetFloat("_Mode", 0f); val.SetFloat("_SrcBlend", 1f); val.SetFloat("_DstBlend", 0f); val.SetFloat("_ZWrite", 1f); val.renderQueue = 2000; } Object.DontDestroyOnLoad((Object)(object)val); return val; } } internal sealed class ContactProbe : MonoBehaviour { internal readonly List<Vector3> normals = new List<Vector3>(8); internal readonly List<Vector3> points = new List<Vector3>(8); private int frame = -1; private void Record(Collision c) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c.collider == (Object)null || c.collider.isTrigger) { return; } _ = frame; _ = Time.frameCount; int contactCount = c.contactCount; for (int i = 0; i < contactCount; i++) { if (normals.Count >= 8) { break; } ContactPoint contact = c.GetContact(i); normals.Add(((ContactPoint)(ref contact)).normal); points.Add(((ContactPoint)(ref contact)).point); } } private void OnCollisionEnter(Collision c) { Record(c); } private void OnCollisionStay(Collision c) { Record(c); } internal void Consume(List<Vector3> outNormals, List<Vector3> outPoints) { outNormals.Clear(); outPoints.Clear(); outNormals.AddRange(normals); outPoints.AddRange(points); normals.Clear(); points.Clear(); } } internal sealed class CooldownRing : MonoBehaviour { private static readonly Color ParryColor = new Color(8f / 51f, 0.5921569f, 1f); private static readonly Color GrabColor = new Color(1f, 0.83137256f, 0.23137255f); private const float FlashSeconds = 0.56f; private const int Segments = 28; private float parryFlash = -1f; private float grabFlash = -1f; private float lastParry; private float lastGrab; private float parryMax = 3f; private float grabMax = 2f; private void Update() { if (FisterMode.Active && !((Object)(object)FisterController.Instance == (Object)null)) { Sim sim = FisterController.Instance.player.sim; float num = sim.ParryCooldown(); float num2 = sim.GrabCooldown(); if (num > lastParry + 0.01f) { parryMax = Mathf.Max(0.1f, num); } if (num2 > lastGrab + 0.01f) { grabMax = Mathf.Max(0.1f, num2); } if (lastParry > 0f && num <= 0f) { parryFlash = 0f; } if (lastGrab > 0f && num2 <= 0f) { grabFlash = 0f; } lastParry = num; lastGrab = num2; float unscaledDeltaTime = Time.unscaledDeltaTime; if (parryFlash >= 0f && (parryFlash += unscaledDeltaTime) > 0.56f) { parryFlash = -1f; } if (grabFlash >= 0f && (grabFlash += unscaledDeltaTime) > 0.56f) { grabFlash = -1f; } } } private static float FlashAlpha(float t) { float num = t / 0.56f; if (num < 0.14f) { return Mathf.Lerp(0f, 0.82f, num / 0.14f); } if (num < 0.46f) { return Mathf.Lerp(0.82f, 0.24f, (num - 0.14f) / 0.32f); } return Mathf.Lerp(0.24f, 0f, (num - 0.46f) / 0.54f); } private void OnGUI() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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) if ((int)Event.current.type == 7 && FisterMode.Active && !((Object)(object)FisterController.Instance == (Object)null)) { OptionsManager instance = MonoSingleton<OptionsManager>.Instance; NewMovement instance2 = MonoSingleton<NewMovement>.Instance; if ((!((Object)(object)instance != (Object)null) || !instance.paused) && !((Object)(object)instance2 == (Object)null) && !instance2.dead && !instance2.levelOver) { float num = Screen.height; float r = num * 0.028f; float thick = Mathf.Max(2f, Mathf.Round(num * 0.0035f)); Vector2 c = new Vector2((float)Screen.width * 0.5f, num * 0.5f); Arc(c, r, thick, 180f, lastParry, parryMax, parryFlash, ParryColor); Arc(c, r, thick, 0f, lastGrab, grabMax, grabFlash, GrabColor); } } } private static void Arc(Vector2 c, float r, float thick, float centreDeg, float cooldown, float max, float flash, Color colour) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) bool flag = cooldown > 0f; if (flag || !(flash < 0f)) { float num = (flag ? (1f - Mathf.Clamp01(cooldown / max)) : 1f); bool num2 = centreDeg > 90f; float num3 = (num2 ? (centreDeg - 55f) : (centreDeg + 55f)); float num4 = (num2 ? 1f : (-1f)); float num5 = (float)Math.PI * 2f * r * (11f / 36f) / 28f + 0.6f; Color color = GUI.color; for (int i = 0; i < 28; i++) { float num6 = ((float)i + 0.5f) / 28f; float num7 = (flag ? ((num6 <= num) ? 0.9f : 0.22f) : FlashAlpha(flash)); Color color2 = ((flag && num6 > num) ? new Color(0f, 0f, 0f, num7) : new Color(colour.r, colour.g, colour.b, num7)); float num8 = num3 + num4 * 110f * num6; float num9 = num8 * ((float)Math.PI / 180f); Vector2 val = c + new Vector2(Mathf.Cos(num9), Mathf.Sin(num9)) * r; GUI.color = color2; Matrix4x4 matrix = GUI.matrix; GUIUtility.RotateAroundPivot(num8 + 90f, val); GUI.DrawTexture(new Rect(val.x - num5 / 2f, val.y - thick / 2f, num5, thick), (Texture)(object)Assets.White); GUI.matrix = matrix; } GUI.color = color; } } } internal static class Defense { internal static Vector3? pendingDirection; internal static Sim Sim => FisterController.Instance?.player.sim; internal static bool Parrying { get { if (FisterMode.Active && Sim != null) { return Sim.IsParrying(); } return false; } } internal static bool Invulnerable { get { if (FisterMode.Active && Sim != null) { return Sim.IsInvulnerable(); } return false; } } internal static void MarkParry() { Sim.MarkParrySuccessful(0); FisterController.Instance.player.combat.HandleEvents(MonoSingleton<NewMovement>.Instance); } internal static void ParryProjectile(Projectile p) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) Punch val = (((Object)(object)MonoSingleton<FistControl>.Instance != (Object)null) ? MonoSingleton<FistControl>.Instance.currentPunch : null); if ((Object)(object)val != (Object)null) { if ((Object)(object)val.fc == (Object)null) { val.fc = MonoSingleton<FistControl>.Instance; } if ((Object)(object)val.anim == (Object)null) { val.anim = ((Component)val).GetComponent<Animator>(); } val.ParryProjectile(p); } else { p.friendly = true; p.parried = true; p.homingType = (HomingType)0; p.speed = Mathf.Max(p.speed * 2f, 100f); MonoSingleton<NewMovement>.Instance.Parry((EnemyIdentifier)null, ""); } NewMovement instance = MonoSingleton<NewMovement>.Instance; CameraController cc = instance.cc; Vector3 johnAim = Quaternion.Euler(0f - cc.rotationX, cc.rotationY, 0f) * Vector3.forward; ParryReturn.Aim(p, ((Component)instance).transform.position + Vector3.up * 1.4f, johnAim); } internal static void Counter(EnemyIdentifier eid, Vector3 attackForward) { //IL_0023: 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) if (!((Object)(object)eid == (Object)null) && !eid.dead) { float num = 100f; Vec3 vec = FisterWorld.BodyCentre(eid).Sub(Units.BodyCentreFromFeet(FisterPlayer.Feet(MonoSingleton<NewMovement>.Instance))); Vec3 vec2 = new Vec3(vec.x, vec.y, 0f).Normalized(); if (vec2.Length() < 0.5f) { vec2 = Units.DirToSim(-attackForward); } vec2.z = 0.3f; FisterWorld.Launch(eid, vec2.Normalized().Mul(Mathf.Min(60f, num)), 2f, 3f); } } } [HarmonyPatch(typeof(Projectile), "Collided")] internal static class ProjectileParryPatch { private static bool Prefix(Projectile __instance, Collider other) { //IL_008a: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) if (!FisterMode.Active || __instance.friendly || __instance.hittingPlayer || !((Component)other).gameObject.CompareTag("Player")) { return true; } if (Defense.Parrying && !__instance.unparryable && !__instance.undeflectable) { Defense.ParryProjectile(__instance); Defense.MarkParry(); return false; } if (Defense.Invulnerable || Defense.Parrying) { return false; } Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>(); Vector3 value; if ((Object)(object)component != (Object)null) { Vector3 velocity = component.velocity; if (((Vector3)(ref velocity)).sqrMagnitude > 0.01f) { velocity = component.velocity; value = ((Vector3)(ref velocity)).normalized; goto IL_009f; } } value = ((Component)__instance).transform.forward; goto IL_009f; IL_009f: Defense.pendingDirection = value; return true; } } [HarmonyPatch(typeof(SwingCheck2), "CheckCollision")] internal static class MeleeParryPatch { private static bool Prefix(SwingCheck2 __instance, Collider other) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!FisterMode.Active || !((Component)other).gameObject.CompareTag("Player") || __instance.hitColliders.Contains(other)) { return true; } if (Defense.Parrying) { __instance.hitColliders.Add(other); EnemyIdentifier eid = __instance.eid; Defense.Counter(eid, ((Component)__instance).transform.forward); MonoSingleton<NewMovement>.Instance.Parry(eid, ""); Defense.MarkParry(); return false; } if (Defense.Invulnerable) { return false; } Defense.pendingDirection = ((Component)__instance).transform.forward; return true; } } [HarmonyPatch(typeof(NewMovement), "GetHurt")] internal static class GetHurtPatch { private static bool Prefix(NewMovement __instance, int damage, bool invincible, bool instablack, bool ignoreInvincibility) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (!FisterMode.Active || SelfDamageGuard.Active || __instance.dead) { return true; } bool flag = instablack || damage >= 999; if (!flag && (Defense.Parrying || Defense.Invulnerable)) { if (Defense.Parrying) { Defense.MarkParry(); } Defense.pendingDirection = null; return false; } if (damage > 0 && !flag && (!invincible || ((Component)__instance).gameObject.layer != 15 || ignoreInvincibility)) { float num = Mathf.Clamp01((float)damage * 2f / 50f); Vector3 val = (Vector3)(((??)Defense.pendingDirection) ?? (-((Component)__instance).transform.forward)); Vector3 val2 = new Vector3(val.x, 0f, val.z); Vec3 vec = Units.DirToSim(((Vector3)(ref val2)).normalized).Mul(2f + 4f * num); vec.z = 1f; Defense.Sim.OnHitByAttack(num, vec); } Defense.pendingDirection = null; return true; } } [HarmonyPatch(typeof(NewMovement), "LaunchFromPoint")] internal static class NoLaunchFromPoint { private static bool Prefix() { return !FisterMode.Active; } } [HarmonyPatch(typeof(NewMovement), "Slamdown")] internal static class NoSlamdown { private static bool Prefix() { return !FisterMode.Active; } } [HarmonyPatch(typeof(Enemy), "FixedUpdate")] internal static class EnemyFixedPatch { private static bool Prefix(Enemy __instance) { if (FisterWorld.Victims.Count != 0) { return !FisterWorld.IsVictim((Component)(object)__instance); } return true; } } [HarmonyPatch(typeof(Zombie), "FixedUpdate")] internal static class ZombieFixedPatch { private static bool Prefix(Zombie __instance) { if (FisterWorld.Victims.Count != 0) { return !FisterWorld.IsVictim((Component)(object)__instance); } return true; } } [HarmonyPatch(typeof(Machine), "FixedUpdate")] internal static class MachineFixedPatch { private static bool Prefix(Machine __instance) { if (FisterWorld.Victims.Count != 0) { return !FisterWorld.IsVictim((Component)(object)__instance); } return true; } } [HarmonyPatch(typeof(Drone), "FixedUpdate")] internal static class DroneFixedPatch { private static bool Prefix(Drone __instance) { if (FisterWorld.Victims.Count != 0) { return !FisterWorld.IsVictim((Component)(object)__instance); } return true; } } internal static class FisterAudio { internal const float Master = 0.5f; private static readonly Dictionary<string, AudioClip> clips = new Dictionary<string, AudioClip>(); private static readonly List<AudioSource> pool = new List<AudioSource>(); private static GameObject host; private static readonly Dictionary<string, AudioSource> loops = new Dictionary<string, AudioSource>(); private static Action<string, float> Played; internal static float UserVolume => 0.5f * FisterConfig.Volume.Value; internal static void ObservePlays(Action<string, float> a) { Played = (Action<string, float>)Delegate.Combine(Played, a); } internal static AudioClip Clip(string name) { if (clips.TryGetValue(name, out var value) && (Object)(object)value != (Object)null) { return value; } string text = Assets.Find("sfx", name + ".wav"); value = (File.Exists(text) ? LoadWav(text, name) : null); if ((Object)(object)value == (Object)null) { FisterPlugin.Log.LogWarning((object)("missing sound " + text)); } clips[name] = value; return value; } private static AudioClip LoadWav(string path, string name) { byte[] array = File.ReadAllBytes(path); int num = 1; int num2 = 44100; int num3 = 16; int num4 = -1; int num5 = 0; int num6; for (int i = 12; i + 8 <= array.Length; i += 8 + num6 + (num6 & 1)) { string text = Encoding.ASCII.GetString(array, i, 4); num6 = BitConverter.ToInt32(array, i + 4); if (text == "fmt ") { num = BitConverter.ToInt16(array, i + 10); num2 = BitConverter.ToInt32(array, i + 12); num3 = BitConverter.ToInt16(array, i + 22); } else if (text == "data") { num4 = i + 8; num5 = Mathf.Min(num6, array.Length - num4); break; } } if (num4 < 0 || num3 != 16) { return null; } int num7 = num5 / 2; float[] array2 = new float[num7]; for (int j = 0; j < num7; j++) { array2[j] = (float)BitConverter.ToInt16(array, num4 + j * 2) / 32768f; } AudioClip obj = AudioClip.Create("fister_" + name, num7 / num, num, num2, false); obj.SetData(array2, 0); Object.DontDestroyOnLoad((Object)(object)obj); return obj; } private static void EnsureHost() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)host == (Object)null) { host = new GameObject("FisterAudio"); Object.DontDestroyOnLoad((Object)(object)host); pool.Clear(); loops.Clear(); } } private static AudioSource NewSource() { AudioSource val = host.AddComponent<AudioSource>(); val.playOnAwake = false; val.spatialBlend = 0f; AudioMixerController instance = MonoSingleton<AudioMixerController>.Instance; if ((Object)(object)instance != (Object)null) { val.outputAudioMixerGroup = instance.allGroup; } return val; } internal static void Play(string name, Vector3 at, float volume, float pitch = 1f) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) AudioClip val = Clip(name); if ((Object)(object)val == (Object)null) { return; } EnsureHost(); AudioSource val2 = null; foreach (AudioSource item in pool) { if ((Object)(object)item != (Object)null && !item.isPlaying) { val2 = item; break; } } if ((Object)(object)val2 == (Object)null) { if (pool.Count >= 24) { return; } val2 = NewSource(); pool.Add(val2); } AudioMixerController instance = MonoSingleton<AudioMixerController>.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)val2.outputAudioMixerGroup == (Object)null) { val2.outputAudioMixerGroup = instance.allGroup; } float num = 1f; NewMovement instance2 = MonoSingleton<NewMovement>.Instance; if ((Object)(object)instance2 != (Object)null) { float num2 = Vector3.Distance(((Component)instance2).transform.position, at) / 1.1798415f; num = Mathf.Clamp(1f - (num2 - 20f) / 100f, 0.3f, 1f); } float num3 = Mathf.Clamp01(volume * UserVolume * num); val2.pitch = pitch; val2.PlayOneShot(val, num3); Played?.Invoke(name, num3); } internal static void Loop(string name, float volume, float pitch) { EnsureHost(); loops.TryGetValue(name, out var value); if (volume <= 0.001f) { if ((Object)(object)value != (Object)null && value.isPlaying) { value.Stop(); } return; } if ((Object)(object)value == (Object)null) { value = NewSource(); value.loop = true; value.clip = Clip(name); loops[name] = value; } if (!((Object)(object)value.clip == (Object)null)) { value.volume = Mathf.Clamp01(volume * UserVolume); value.pitch = pitch; if (!value.isPlaying) { value.Play(); Played?.Invoke(name + "(loop)", value.volume); } } } internal static void StopLoops() { foreach (AudioSource value in loops.Values) { if ((Object)(object)value != (Object)null) { value.Stop(); } } } } internal static class FisterCamera { internal const float PivotAboveHead = 1.25f; internal const float HeadAboveFeet = 2.3f; internal const float ScreenFraction = 0.2f; internal static Vector3 FollowFeet; internal static bool HasFollow; internal static Vector3 Shake; internal static float FovPush; private static bool overriding; private static float smoothedDistance; private static Camera mainCam; private static bool hooked; private static bool moved; private static Vector3 savedLocalPos; private static Quaternion savedLocalRot; private static ParticleSystemRenderer[] heat; private static float[] heatMax; private static int heatScene = -1; internal static float HeatWaveMaxSize = 0.06f; internal static Vector3 Pivot { get; private set; } internal static Vector3 ViewPosition { get; private set; } internal static Quaternion ViewRotation { get; private set; } internal static float Distance { get; private set; } internal static float BodyAlpha { get; private set; } = 1f; internal static float DistanceFor(float verticalFov) { return Mathf.Clamp(2.6f / (0.4f * Mathf.Tan(verticalFov * 0.5f * ((float)Math.PI / 180f))), 4f, 12f); } internal static void Apply(CameraController cc) { //IL_0039: 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_0049: 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_005a: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) Camera cam = cc.cam; if ((Object)(object)cam == (Object)null) { return; } RestoreTransform(); if (!FisterMode.Active || !HasFollow) { if (overriding) { cam.ResetWorldToCameraMatrix(); overriding = false; } return; } Quaternion val = cc.gravityRotation * Quaternion.AngleAxis(cc.rotationY, Vector3.up) * Quaternion.AngleAxis(0f - cc.rotationX, Vector3.right); Vector3 val2 = cc.gravityRotation * Vector3.up; int num = LayerMask.op_Implicit(LayerMaskDefaults.Get((LMD)1)); float nearClipPlane = cam.nearClipPlane; float num2 = nearClipPlane * Mathf.Tan(cam.fieldOfView * 0.5f * ((float)Math.PI / 180f)); float num3 = Mathf.Max(0.25f, Mathf.Sqrt(nearClipPlane * nearClipPlane + num2 * num2 * (1f + cam.aspect * cam.aspect)) + 0.05f); Vector3 val3 = FollowFeet + val2 * 2.7136354f; Vector3 val4 = val3 + val2 * 1.4748019f; float num4 = 1.4748019f; RaycastHit val5 = default(RaycastHit); if (Physics.SphereCast(val3, num3, val2, ref val5, num4, num, (QueryTriggerInteraction)1)) { val4 = val3 + val2 * Mathf.Max(0f, ((RaycastHit)(ref val5)).distance - 0.05f); } float num5 = DistanceFor(cam.fieldOfView) * 1.1798415f; Vector3 val6 = val * Vector3.back; float num6 = num5; RaycastHit val7 = default(RaycastHit); if (Physics.SphereCast(val4, num3, val6, ref val7, num5, num, (QueryTriggerInteraction)1)) { num6 = Mathf.Max(0.15f, ((RaycastHit)(ref val7)).distance - 0.05f); } float num7 = Mathf.Min(Time.unscaledDeltaTime, 0.1f); if (smoothedDistance <= 0f || num6 < smoothedDistance) { smoothedDistance = num6; } else { smoothedDistance = Mathf.Min(num6, Mathf.Lerp(smoothedDistance, num6, 1f - Mathf.Exp(-3f * num7))); } float num8 = smoothedDistance; BodyAlpha = Mathf.Lerp(0.35f, 1f, Mathf.InverseLerp(0.8f, 2.6f, num8)); Vector3 val8 = val4 + val6 * num8 + Shake; Pivot = val4; ViewPosition = val8; ViewRotation = val; Distance = num8; Matrix4x4 val9 = Matrix4x4.Scale(new Vector3(1f, 1f, -1f)); Matrix4x4 val10 = Matrix4x4.TRS(val8, val, Vector3.one); cam.worldToCameraMatrix = val9 * ((Matrix4x4)(ref val10)).inverse; overriding = true; mainCam = cam; Hook(); } private static void Hook() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown if (!hooked) { hooked = true; Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnPreCull)); Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRender)); } } private static void OnPreCull(Camera cam) { //IL_0033: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)cam == (Object)null) && !((Object)(object)cam != (Object)(object)mainCam) && overriding && !moved && FisterMode.Active) { Transform transform = ((Component)cam).transform; savedLocalPos = transform.localPosition; savedLocalRot = transform.localRotation; transform.SetPositionAndRotation(ViewPosition, ViewRotation); moved = true; TameHeatWaves(tame: true); } } private static void OnPostRender(Camera cam) { if ((Object)(object)cam == (Object)(object)mainCam) { RestoreTransform(); } } private static void TameHeatWaves(bool tame) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) try { Scene val = SceneManager.GetActiveScene(); int handle = ((Scene)(ref val)).handle; if (tame && (heat == null || heatScene != handle)) { heatScene = handle; List<ParticleSystemRenderer> list = new List<ParticleSystemRenderer>(); ParticleSystemRenderer[] array = Resources.FindObjectsOfTypeAll<ParticleSystemRenderer>(); foreach (ParticleSystemRenderer val2 in array) { if ((Object)(object)val2 != (Object)null) { val = ((Component)val2).gameObject.scene; if (((Scene)(ref val)).IsValid() && (Object)(object)((Renderer)val2).sharedMaterial != (Object)null && (Object)(object)((Renderer)val2).sharedMaterial.shader != (Object)null && ((Object)((Renderer)val2).sharedMaterial.shader).name.Contains("HeatWave")) { list.Add(val2); } } } heat = list.ToArray(); heatMax = new float[heat.Length]; for (int j = 0; j < heat.Length; j++) { heatMax[j] = heat[j].maxParticleSize; } } if (heat == null) { return; } for (int k = 0; k < heat.Length; k++) { if ((Object)(object)heat[k] != (Object)null) { heat[k].maxParticleSize = (tame ? Mathf.Min(heatMax[k], HeatWaveMaxSize) : heatMax[k]); } } } catch (Exception) { heat = null; } } internal static void RestoreTransform() { //IL_002b: 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 (moved) { moved = false; TameHeatWaves(tame: false); if ((Object)(object)mainCam != (Object)null) { ((Component)mainCam).transform.localPosition = savedLocalPos; ((Component)mainCam).transform.localRotation = savedLocalRot; } } } } [HarmonyPatch(typeof(CameraController), "LateUpdate")] internal static class CameraLateUpdatePatch { private static void Postfix(CameraController __instance) { if ((Object)(object)FisterController.Instance != (Object)null && FisterMode.Active) { FisterController.Instance.OnCameraLateUpdate(__instance); } else { FisterCamera.Apply(__instance); } } } internal sealed class FisterCombat { private struct Hit { internal EnemyIdentifier ent; internal float distance; internal Vec3 centre; } private readonly FisterPlayer owner; private float pendingImpactDamage; private double pendingImpactAt; private static Action<Event> EventObserved; private bool diveHitAnyone; private EnemyIdentifier airKickHomingTarget; private EnemyIdentifier airKickLockTarget; private EnemyIdentifier grabbed; private float lastAirKickScale = 1f; private readonly HashSet<EnemyIdentifier> railingHit = new HashSet<EnemyIdentifier>(); private readonly HashSet<EnemyIdentifier> ascentHit = new HashSet<EnemyIdentifier>(); private readonly HashSet<EnemyIdentifier> grabStandIn = new HashSet<EnemyIdentifier>(); private readonly Dictionary<EnemyIdentifier, double[]> taps = new Dictionary<EnemyIdentifier, double[]>(); private static Action<EnemyIdentifier, Vec3> ThrowObserved; private readonly List<EnemyIdentifier> sweepBuffer = new List<EnemyIdentifier>(32); private int airKickChain; private float lastKickHitTime = -10f; private bool landedSinceKick = true; private Sim sim => owner.sim; internal EnemyIdentifier AirKickLockTarget => airKickLockTarget; private float Yaw => owner.yaw; internal int AirKickChain => airKickChain; internal FisterCombat(FisterPlayer owner) { this.owner = owner; } internal void Reset() { pendingImpactDamage = 0f; ResetTargets(); } internal void HandleEvents(NewMovement nm) { List<Event> list = new List<Event>(sim.Events()); sim.Events().Clear(); for (int i = 0; i < list.Count; i++) { Event obj = list[i]; try { HandleEvent(nm, obj); } catch (Exception ex) { FisterPlugin.Log.LogError((object)("event " + obj.type.ToString() + " handler failed: " + ex)); } list.AddRange(sim.Events()); sim.Events().Clear(); } } internal static void ObserveEvents(Action<Event> a) { EventObserved = (Action<Event>)Delegate.Combine(EventObserved, a); } private void HandleEvent(NewMovement nm, Event e) { //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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) EventObserved?.Invoke(e); Fx instance = Fx.Instance; Vector3 at = Units.PosToUnity(e.position); Vector3 val = FisterPlayer.Feet(nm); switch (e.type) { case EventType.ChargeReady: FisterAudio.Play("reload", val, 0.4f); FisterController.Instance.anim.TriggerChargeReady(); break; case EventType.PunchThrown: FisterAudio.Play("punch", val, 1f); FisterController.Instance.anim.TriggerPunch(e.strength, owner.pitch); ResolvePunch(nm, e); break; case EventType.RocketPunchLaunch: ResetAscent(); instance?.GroundHop(val, 0.6f); break; case EventType.DiveStart: diveHitAnyone = false; break; case EventType.DiveImpact: case EventType.DiveObstacle: ResolveDive(nm, e, at); break; case EventType.AirKickStart: airKickHomingTarget = (e.flag ? airKickLockTarget : null); break; case EventType.AirKickWhiff: { float num2 = FMath.Clamp(lastAirKickScale, 0.5f, 1.5f); instance?.AirKickWhiff(at, num2); FisterController.Instance.anim.TriggerImpactFrame(0.04f + 0.025f * num2); Shake(0.25f * num2); break; } case EventType.RailingStart: ResetRailing(); FisterAudio.Play("overcharge-dash-screech", val, 1.2f); break; case EventType.RailingBounce: { sim.ScaleLaunch(Tuning.RailingBounce.Value); float num = (e.flag ? 2.35f : FMath.Clamp(e.value / 1.1f / 88f, 1f, 2.25f)); instance?.RailingBounce(at, num); FisterAudio.Play("crack", at, 1f, 0.9f); Shake(0.2f * num); if (e.flag) { SelfKill(nm); } break; } case EventType.RailingMegaBoost: instance?.MegaBoost(val + Vector3.up * 1.1798415f); FisterAudio.Play("railing-sonic-boom", val, 1f); break; case EventType.GroundPunchHop: sim.ScaleLaunch(Tuning.GroundHop.Value); instance?.GroundHop(val, 1f); ResolveGroundHop(nm, e); break; case EventType.ParryStart: ParryReceivers(nm); break; case EventType.ParrySuccess: if (e.kind == 3) { pendingImpactDamage = 0f; sim.ScaleLaunch(Tuning.WallParry.Value); } else if (e.kind == 1) { sim.ScaleLaunch(Tuning.ParryJump.Value); owner.StartParryJumpFlight(); } else if (e.kind == 2 && sim.IsOverchargeDashing()) { sim.ScaleLaunch(Tuning.RailingReverse.Value); } else if (e.kind == 2) { sim.ScaleLaunch(Tuning.GroundParry.Value); } FisterAudio.Play("parry-success", val, 1.8f); FisterController.Instance.anim.TriggerImpactFrame(0.1f); instance?.Parry(val + Vector3.up * 1.1798415f); instance?.Flash(new Color(53f / 85f, 43f / 51f, 1f), 0.35f); break; case EventType.GrabStart: ClearGrabStandIns(); FisterAudio.Play("grab-lunge", val, 0.45f); break; case EventType.GrabMiss: case EventType.GrabCancel: ReleaseGrabbed(breakSim: false); break; case EventType.GrabThrow: ResolveThrow(nm, e); break; case EventType.PiledriverImpact: ResolvePiledriver(nm, e, at); break; case EventType.OverchargeExplode: ResolveOverchargeExplode(nm, e); break; case EventType.RagdollImpact: instance?.Impact(at, Mathf.Min(1f, e.value / 15f)); FisterAudio.Play("crack", at, Mathf.Min(1f, 0.3f + e.value / 20f)); if (sim.parryLateWindow > 0f) { pendingImpactDamage += e.value; pendingImpactAt = owner.clock; } else { SelfDamage(nm, e.value); } break; case EventType.SelfDamage: SelfDamage(nm, e.value); break; case EventType.Ragdoll: ReleaseGrabbed(breakSim: false); break; case EventType.AirKickStop: case EventType.RailingStop: case EventType.ParryEndlag: case EventType.SlideStart: case EventType.SlideStop: case EventType.AirTech: case EventType.Flip: case EventType.OverchargeWarning: case EventType.Recover: break; } } private void ParryReceivers(NewMovement nm) { //IL_000d: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) CameraController cc = nm.cc; Vector3 val = ((Component)nm).transform.position + ((Component)nm).transform.up * 1.4f; Vector3 val2 = Quaternion.Euler(0f - cc.rotationX, cc.rotationY, 0f) * Vector3.forward; Collider[] array = Physics.OverlapCapsule(val, val + val2 * 5f * 1.1798415f, 1.5f, -1, (QueryTriggerInteraction)2); foreach (Collider val3 in array) { ParryReceiver val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<ParryReceiver>() : null); if (!((Object)(object)val4 == (Object)null) && ((Behaviour)val4).enabled) { if (val4.parryHeal) { nm.Parry((EnemyIdentifier)null, ""); } else { MonoSingleton<TimeController>.Instance.ParryFlash(); } val4.Parry(); sim.MarkParrySuccessful(0); FisterPlugin.Log.LogInfo((object)("parried " + ((Object)val3).name)); break; } } } internal static void Shake(float intensity) { if (FisterConfig.ScreenShake.Value) { FisterController.Instance?.AddShake(intensity); } } internal static void ObserveThrows(Action<EnemyIdentifier, Vec3> a) { ThrowObserved = (Action<EnemyIdentifier, Vec3>)Delegate.Combine(ThrowObserved, a); } private void ResetTargets() { diveHitAnyone = false; airKickHomingTarget = (airKickLockTarget = null); grabbed = null; railingHit.Clear(); ascentHit.Clear(); taps.Clear(); } private void ClearGrabStandIns() { grabStandIn.Clear(); } private void ResetAscent() { ascentHit.Clear(); } private void ResetRailing() { railingHit.Clear(); } private void ApplyPunchToTarget(EnemyIdentifier target, Vec3 direction, float velocity, float strength, bool critical) { bool flag = FisterWorld.IsRagdolled(target); bool flag2 = FisterWorld.IsHardKnocked(target); float num = FisterWorld.Health(target); float num2 = Mathf.Max(0.01f, FisterWorld.MaxHealth(target)); float num3 = num2 * 0.2f; if (strength >= 0.95f && num > 0f && !target.isBoss && !FisterWorld.IsKillProtected(target) && (num <= num3 || (flag2 && num <= num2 * 0.5f))) { FisterWorld.KillAndLaunch(target, direction.Mul(velocity)); return; } float hardKnockdown = 0f; if (strength >= 0.95f && flag2) { if (!critical) { velocity *= 10f; } hardKnockdown = 2f; } if (flag) { Vec3 vec = new Vec3(direction.x * velocity, direction.y * velocity, 0.5f * velocity); if (strength < 0.6f) { vec = vec.Mul(0.5f); } FisterWorld.Launch(target, vec, hardKnockdown, 0f); } else if (strength < 0.6f) { double clock = owner.clock; if (!taps.TryGetValue(target, out var value) || clock - value[2] > 0.65 || clock - value[1] > 1.8) { value = new double[3] { 0.0, clock, clock }; taps[target] = value; } value[2] = clock; value[0] += 1.0; if (value[0] >= 4.0) { value[0] = 0.0; FisterWorld.Launch(target, direction.Mul(velocity * 0.5f), 0f, 1f); } else { FisterWorld.Stagger(target, strength, direction.Mul(velocity * 0.5f)); } } else { FisterWorld.Launch(target, direction.Mul(velocity), hardKnockdown, 4f); } } private void ResolvePunch(NewMovement nm, Event e) { //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_058b: Unknown result type (might be due to invalid IL or missing references) //IL_055f: Unknown result type (might be due to invalid IL or missing references) //IL_0594: Unknown result type (might be due to invalid IL or missing references) //IL_0598: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) //IL_050f: Unknown result type (might be due to invalid IL or missing references) //IL_05c1: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Unknown result type (might be due to invalid IL or missing references) float strength = e.strength; int kind = e.kind; bool critical = e.critical; bool flag = kind == 2; Vec3 position = e.position; Vec3 vec = FMath.YawForward(Yaw); Vec3 direction = e.direction; Vec3 vec2 = sim.Velocity(); float num = 15f + strength * 25f; float num2 = (critical ? 10f : 1f); float num3 = Mathf.Max(0f, vec.Dot(vec2)); float num4 = 1f + num3 / 20f * 0.5f; float num5 = (flag ? 18f : 5f); float arcCos = FMath.Cos((flag ? 0.9424779f : ((float)Math.PI * 3f / 4f)) / 2f); List<Hit> list = new List<Hit>(); foreach (EnemyIdentifier item in FisterWorld.Targets(position, num5 + 12f)) { float hitRadius = (FisterWorld.IsRagdolled(item) ? 1f : 0.5f); Vec3 vec3 = FisterWorld.BodyCentre(item); float bodyAllowance = Mathf.Max(0f, BodyHalfHeight(item) - 1.3f); float hitDistance; bool flag2 = PunchReaches(position, vec, vec3, bodyAllowance, hitRadius, num5, arcCos, flag, out hitDistance); if (!flag2 && FisterWorld.IsHeavy(item)) { Vec3 vec4 = FisterWorld.NearestBodyPoint(item, position); if (PunchReaches(position, vec, vec4, 0f, hitRadius, num5, arcCos, flag, out hitDistance)) { flag2 = true; vec3 = vec4; } } if (flag2 && FisterWorld.ClearLine(position, vec3, item)) { list.Add(new Hit { ent = item, distance = hitDistance, centre = vec3 }); } } list.Sort((Hit a, Hit b) => a.distance.CompareTo(b.distance)); if (flag && list.Count > 1) { list.RemoveRange(1, list.Count - 1); } int num6 = 0; foreach (Hit item2 in list) { float num7 = Mathf.Max(0.2f, 1f - 0.2f * (float)num6); float velocity = num * num2 * num4 * num7; num6++; FisterWorld.PunchContact(item2.ent, strength, critical || flag); bool flag3 = false; if (e.flag) { Vec3 vec5 = item2.centre.Sub(position); float num8 = vec5.x * vec.x + vec5.y * vec.y; float num9 = FMath.Hypot(vec5.x - vec.x * num8, vec5.y - vec.y * num8); float num10 = vec5.z - 0.08f; if (num8 <= 4.25f && num9 <= 0.95f && num10 >= -0.75f && num10 <= 2.85f) { flag3 = true; if (FisterWorld.IsClearlyAirborne(item2.ent)) { FisterWorld.KillAndLaunch(item2.ent, new Vec3(0f, 0f, 111.111115f)); FisterAudio.Play("successful-100-punch", FisterPlayer.Feet(nm), 1f); } else if (kind == 3) { float num11 = (critical ? 0.45f : 0.3f); float num12 = (critical ? 6f : 3f); FisterWorld.Launch(item2.ent, new Vec3(vec2.x * num11, vec2.y * num11, Mathf.Max(0f, vec2.z) + num12), 0f, 3f); } else { ApplyPunchToTarget(item2.ent, new Vec3(direction.x * 0.3f, direction.y * 0.3f, direction.z), velocity, strength, critical); } } } if (!flag3) { ApplyPunchToTarget(item2.ent, direction, velocity, strength, critical); } } float s = FMath.Clamp01(strength); foreach (Hit item3 in list) { Vec3 vec6 = item3.centre.Sub(position).Normalized(); if (vec6.Length() < 0.5f) { vec6 = vec; } Fx.Instance?.PunchHit(Units.PosToUnity(item3.centre), Units.DirToUnity(vec6), s); } if (num6 > 0 && strength > 0f && strength < 0.6f) { Shake(0.05f + 0.08f * Mathf.Min(1f, strength / 0.6f)); } if (num6 > 0 && critical) { Fx.Instance?.CriticalIcon(); FisterAudio.Play("criticalhit", FisterPlayer.Feet(nm), 1f); } float volume = Mathf.Max((0.5f + 0.5f * strength) * 0.6f, Mathf.Min(1f, 0.3f + 0.45f * strength)); if (num6 > 0) { FisterAudio.Play("crack", FisterPlayer.Feet(nm), volume); if (strength >= 1f) { sim.GrantInstantPunchCharge(); } return; } Vector3 val = Units.PosToUnity(position); RaycastHit val2 = default(RaycastHit); if (kind == 3 || !Physics.Raycast(val, Units.DirToUnity(direction), ref val2, 5.8992076f, LayerMask.op_Implicit(LayerMaskDefaults.Get((LMD)1)), (QueryTriggerInteraction)1)) { return; } FisterAudio.Play("crack", ((RaycastHit)(ref val2)).point, volume); Fx.Instance?.WallPunch(((RaycastHit)(ref val2)).point, strength); Breakable componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Breakable>(); if ((Object)(object)componentInParent != (Object)null && (componentInParent.weak || strength >= 0.6f) && !componentInParent.unbreakable && !componentInParent.precisionOnly && !componentInParent.specialCaseOnly) { componentInParent.Break(); return; } Glass componentInParent2 = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Glass>(); if (strength >= 0.6f && (Object)(object)componentInParent2 != (Object)null && !componentInParent2.broken) { componentInParent2.Shatter(); } else { sim.ApplyWallPunchRecoil(strength); } } private static bool PunchReaches(Vec3 origin, Vec3 forward, Vec3 centre, float bodyAllowance, float hitRadius, float range, float arcCos, bool criticalDash, out float hitDistance) { Vec3 vec = centre.Sub(origin); float num = vec.Length(); float num2 = vec.x * forward.x + vec.y * forward.y; float num3 = FMath.Hypot(vec.x - forward.x * num2, vec.y - forward.y * num2); hitDistance = (criticalDash ? num2 : num); if (criticalDash) { float num4 = 2.2f + (hitRadius - 0.5f) + bodyAllowance; if (num2 > 0f && num2 <= range + bodyAllowance && Mathf.Abs(vec.z) <= 2.5f + bodyAllowance) { return num3 <= num4; } return false; } bool num5 = num > 0.001f && num <= range + (hitRadius - 0.5f) + bodyAllowance && num2 / num > arcCos; bool flag = num2 >= -0.2f && num2 <= range + bodyAllowance && num3 <= 1.3299999f + bodyAllowance && Mathf.Abs(vec.z) <= 2f + bodyAllowance; return num5 || flag; } private static float BodyHalfHeight(EnemyIdentifier eid) { //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_000c: 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) Vector3 val = FisterWorld.CentreUnity(eid); return Mathf.Clamp(Mathf.Max(0.5f, val.y - ((Component)eid).transform.position.y) / 1.1798415f, 0.4f, 6f); } private bool ResolveShockwave(Vec3 centre, float charge) { float num = 5f + 7f * charge; bool result = false; foreach (EnemyIdentifier item in FisterWorld.Targets(centre, num + 4f)) { Vec3 vec = FisterWorld.BodyCentre(item).Sub(centre); if (Mathf.Abs(vec.z) > 4f + BodyHalfHeight(item)) { continue; } float num2 = FMath.Hypot(vec.x, vec.y); if (!(num2 >= num)) { result = true; if (num2 < 0.75f) { FisterWorld.KillAndLaunch(item, new Vec3(0f, 0f, 10f)); continue; } float num3 = 16.25f * (1f - num2 / num); Vec3 vec2 = new Vec3(vec.x, vec.y, 0f).Normalized(); FisterWorld.Launch(item, new Vec3(vec2.x * num3, vec2.y * num3, num3 * 0.18f), 2f, 4f); } } return result; } private void ResolveDive(NewMovement nm, Event e, Vector3 at) { //IL_0116: 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) float num = e.value * 0.6f; bool flag = diveHitAnyone; foreach (EnemyIdentifier item in FisterWorld.Targets(e.position, 6f)) { Vec3 vec = FisterWorld.BodyCentre(item); if (FMath.Hypot(vec.x - e.position.x, vec.y - e.position.y) <= 2f && Mathf.Abs(vec.z - e.position.z) <= 4f + BodyHalfHeight(item)) { if (item.isBoss || !FisterWorld.CanLaunch(item)) { FisterWorld.StandInImpact(item, new Vec3(0f, 0f, 40f)); } else { FisterWorld.KillAndLaunch(item, new Vec3(0f, 0f, 12f)); } flag = true; } } flag = ResolveShockwave(e.position, num) || flag; Fx.Instance?.DiveLand(at, num); FisterAudio.Play("crack", at, 0.8f + 0.4f * num); Shake(0.3f + 0.4f * num); sim.ResolveDiveImpact(flag); if (flag) { sim.GrantInstantPunchCharge(); } } private void ResolveGroundHop(NewMovement nm, Event e) { foreach (EnemyIdentifier item in FisterWorld.Targets(e.position, 3.5f)) { if (!FisterWorld.IsRagdolled(item)) { float num = FisterWorld.BodyCentre(item).Sub(e.position).Length(); if (num < 3.5f) { float z = 12f * (1f - num / 3.5f); FisterWorld.Push(item, new Vec3(0f, 0f, z)); } } } } private void ResolveOverchargeExplode(NewMovement nm, Event e) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_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_0031: Unknown result type (might be due to invalid IL or missing references) Vector3 val = FisterPlayer.Feet(nm); Fx.Instance?.Explode(val + Vector3.up * 1.1798415f); FisterAudio.Play("explode", val, 1f); Shake(1f); foreach (EnemyIdentifier item in FisterWorld.Targets(e.position, 8f)) { Vec3 vec = FisterWorld.BodyCentre(item).Sub(e.position); float num = vec.Length(); if (!(num >= 8f)) { float num2 = 1f - num / 8f; Vec3 vec2 = new Vec3(vec.x, vec.y, 0f).Normalized(); float num3 = 800f * (0.3f + 0.7f * num2) / 72f; FisterWorld.Launch(item, new Vec3(vec2.x * num3, vec2.y * num3, 300f * num2 / 72f), 3f, 0f); } } SelfKill(nm); } private void ResolveThrow(NewMovement nm, Event e) { if ((Object)(object)grabbed != (Object)null && !e.flag) { FisterWorld.SetGrabbed(grabbed, grabbed: false); Vec3 vec = e.direction.Mul(e.value * Tuning.Throw.Value); FisterWorld.Launch(grabbed, vec, 2.2f, 2f, roomScaled: false, thrown: true); ThrowObserved?.Invoke(grabbed, vec); grabbed = null; } } private void ResolvePiledriver(NewMovement nm, Event e, Vector3 at) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)grabbed != (Object)null) { FisterWorld.SetGrabbed(grabbed, grabbed: false); FisterWorld.KillAndLaunch(grabbed, new Vec3(0f, 0f, 6f)); } grabbed = null; ResolveShockwave(e.position, e.value); sim.GrantInstantPunchCharge(); Fx.Instance?.DiveLand(at, e.value); FisterAudio.Play("crack", at, 1.2f); Shake(0.3f + 0.4f * e.value); } internal void ReleaseGrabbed(bool breakSim) { if ((Object)(object)grabbed != (Object)null) { FisterWorld.SetGrabbed(grabbed, grabbed: false); } grabbed = null; if (breakSim) { sim.OnGrabBroken(); } } private static float DistanceToSegment(Vec3 pt, Vec3 a, Vec3 b, float halfHeight) { Vec3 vec = b.Sub(a); float num = vec.Dot(vec); float s = ((num > 1E-08f) ? FMath.Clamp01(pt.Sub(a).Dot(vec) / num) : 0f); Vec3 vec2 = a.Add(vec.Mul(s)); float num2 = pt.z - vec2.z; num2 = ((num2 > 0f) ? Mathf.Max(0f, num2 - halfHeight) : Mathf.Min(0f, num2 + halfHeight)); return Mathf.Sqrt((pt.x - vec2.x) * (pt.x - vec2.x) + (pt.y - vec2.y) * (pt.y - vec2.y) + num2 * num2); } internal void TickCombat(NewMovement nm) { //IL_0d82: Unknown result type (might be due to invalid IL or missing references) //IL_0a2b: Unknown result type (might be due to invalid IL or missing references) //IL_0a30: Unknown result type (might be due to invalid IL or missing references) //IL_0a78: Unknown result type (might be due to invalid IL or missing references) //IL_0b99: Unknown result type (might be due to invalid IL or missing references) //IL_0a97: Unknown result type (might be due to invalid IL or missing references) //IL_08f1: Unknown result type (might be due to invalid IL or missing references) //IL_0925: Unknown result type (might be due to invalid IL or missing references) //IL_0bee: Unknown result type (might be due to invalid IL or missing references) //IL_06bb: Unknown result type (might be due to invalid IL or missing references) //IL_0773: Unknown result type (might be due to invalid IL or missing references) //IL_0799: Unknown result type (might be due to invalid IL or missing references) if (sim.IsGrounded()) { landedSinceKick = true; } if (pendingImpactDamage > 0f && owner.clock - pendingImpactAt >= (double)sim.parryLateWindow) { float fisterHp = pendingImpactDamage; pendingImpactDamage = 0f; SelfDamage(nm, fisterHp); } bool flag = sim.IsGrabbing(); bool flag2 = sim.IsHoldingGrabbed() || (sim.IsPiledriving() && (Object)(object)grabbed != (Object)null); bool flag3 = sim.IsRocketPunchDiving(); bool flag4 = sim.IsAirKickDashing(); bool flag5 = sim.IsOverchargeDashing(); bool flag6 = sim.IsRocketPunchAscending() && sim.RocketAscentTimer() >= 0.05f; bool flag7 = sim.Charge() >= 1f && sim.IsAirborneForFullChargePunch(); if (!flag7) { sim.SetAirKickLockCandidate(onTarget: false); } if (!flag && !flag2 && !flag3 && !flag4 && !flag5 && !flag6 && !flag7) { return; } Vec3 position = owner.lastEnv.position; Vec3 vec = sim.Velocity(); Vec3 vec2 = FMath.YawForward(Yaw); Vec3 vec3 = position.Add(vec.Mul(1f / 60f * owner.TravelScale())); float radiusFister = vec.Length() * (1f / 60f) + 8f; if (flag2) { if ((Object)(object)grabbed == (Object)null || (grabbed.dead && !FisterWorld.Victims.ContainsKey(grabbed))) { ReleaseGrabbed(breakSim: true); } else { Vec3 goalSim = new Vec3(position.x + vec2.x * 0.8f, position.y + vec2.y * 0.8f, position.z + 1.5f); FisterWorld.Hold(grabbed, goalSim, vec); } } if (flag && (Object)(object)grabbed == (Object)null) { EnemyIdentifier val = null; float num = 1E+09f; foreach (EnemyIdentifier item in FisterWorld.Targets(position, 8f)) { Vec3 vec4 = FisterWorld.BodyCentre(item); Vec3 vec5 = vec4.Sub(position); int num2; float num3; if (!sim.GrabStartedAirborne()) { num2 = (FisterWorld.IsRagdolled(item) ? 1 : 0); if (num2 == 0) { num3 = 4f; goto IL_0293; } } else { num2 = 1; } num3 = 4.75f; goto IL_0293; IL_0293: float num4 = num3; float a = ((num2 != 0) ? ((float)Math.PI * 23f / 36f) : ((float)Math.PI / 2f)) / 2f; float num5 = ((num2 != 0) ? 6f : 3f) + Mathf.Max(0f, BodyHalfHeight(item) - 1.3f); float num6 = ((num2 != 0) ? vec5.Length() : FMath.Hypot(vec5.x, vec5.y)); if (!(num6 > num4) && !(num6 < 0.001f) && !(Mathf.Abs(vec5.z) > num5)) { float num7 = FMath.Hypot(vec5.x, vec5.y); if (!(((num7 > 0.001f) ? ((vec5.x * vec2.x + vec5.y * vec2.y) / num7) : 1f) < FMath.Cos(a)) && !(num6 >= num) && FisterWorld.ClearLine(position, vec4)) { val = item; num = num6; } } } if ((Object)(object)val != (Object)null && FisterWorld.Grab(val)) { sim.OnGrabCaught(); grabbed = val; } else if ((Object)(object)val != (Object)null && !grabStandIn.Contains(val)) { grabStandIn.Add(val); FisterWorld.StandInImpact(val, vec2.Mul(15f)); } } if (flag3) { foreach (EnemyIdentifier item2 in FisterWorld.Targets(position, radiusFister, sweepBuffer)) { if (DistanceToSegment(FisterWorld.BodyCentre(item2), position, vec3, 0.65f + BodyHalfHeight(item2)) <= 1f) { if (!FisterWorld.CanLaunch(item2) || item2.isBoss) { FisterWorld.StandInImpact(item2, vec); } else { FisterWorld.KillAndLaunch(item2, new Vec3(vec.x * 0.3f, vec.y * 0.3f, 8f)); } diveHitAnyone = true; } } } if (flag4) { lastAirKickScale = sim.AirKickImpactScale(); EnemyIdentifier val2 = airKickHomingTarget; if ((Object)(object)val2 != (Object)null) { bool valid = (Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeInHierarchy && (!val2.dead || FisterWorld.Victims.ContainsKey(val2)) && FisterWorld.ClearLine(position, FisterWorld.BodyCentre(val2)); sim.SetAirKickHomingTarget(valid, FisterWorld.BodyCentre(val2)); } EnemyIdentifier val3 = null; float num8 = 1E+09f; foreach (EnemyIdentifier item3 in FisterWorld.Targets(position, radiusFister, sweepBuffer)) { Vec3 vec6 = FisterWorld.BodyCentre(item3); if (DistanceToSegment(vec6, position, vec3, 0.65f + Mathf.Max(0f, BodyHalfHeight(item3) - 1.3f)) > 2.65f) { bool flag8 = false; if (FisterWorld.IsHeavy(item3)) { Vec3[] array = new Vec3[3] { position, vec3, position.Add(vec3).Mul(0.5f) }; foreach (Vec3 fromSim in array) { if (DistanceToSegment(FisterWorld.NearestBodyPoint(item3, fromSim), position, vec3, 0.65f) <= 2.65f) { flag8 = true; break; } } } if (!flag8) { continue; } } float num9 = vec6.Sub(position).Length(); if (num9 < num8) { val3 = item3; num8 = num9; } } if ((Object)(object)val3 == (Object)null) { for (int j = 0; j < ParryReturn.Live.Count; j++) { Projectile val4 = ParryReturn.Live[j]; if (!((Object)(object)val4 == (Object)null) && !val4.friendly && !val4.parried && !val4.unparryable && !val4.undeflectable && !val4.playerBullet && !(DistanceToSegment(Units.PosToSim(((Component)val4).transform.position), position, vec3, 0.65f) > 2.65f)) { Vec3 vec7 = sim.AirKickDirection(); Vec3 vec8 = sim.Velocity(); Defense.ParryProjectile(val4); sim.StopAirKickDash(); Vec3 vec9 = new Vec3(vec7.x, vec7.y, 0f).Normalized(); sim.SetVelocity(new Vec3((0f - vec9.x) * 4f, (0f - vec9.y) * 4f, vec8.z * 0.15f)); sim.MarkParrySuccessful(0); FisterAudio.Play("successful-100-punch", FisterPlayer.Feet(nm), 1f); Fx.Instance?.AirKickHit(((Component)val4).transform.position, 1f); FisterPlugin.Log.LogInfo((object)("air kick redirected " + ((Object)val4).name)); return; } } } if ((Object)(object)val3 != (Object)null) { float num10 = sim.AirKickImpactScale(); if (FisterWorld.IsHardKnocked(val3)) { num10 = Mathf.Max(num10, 1f); } Vec3 vec10 = sim.AirKickDirection(); float time = Time.time; bool flag9 = airKickChain > 0 && (!landedSinceKick || time - lastKickHitTime <= FisterConfig.AirKickChainWindow.Value); airKickChain = ((!flag9) ? 1 : (airKickChain + 1)); lastKickHitTime = time; landedSinceKick = false; FisterWorld.AirKickContact(val3, num10, airKickChain); float num11 = 28800f * num10 / 72f * FisterConfig.AirKickLaunch.Value; float num12 = 40f * Tuning.EnemyLaunch.Value; Vec3 velSim = vec10.Normalized().Mul(Mathf.Max(num11, num12 * 1.1f)); FisterWorld.Launch(val3, velSim, 2f, 4f, roomScaled: false); sim.OnAirKickHit(); FisterAudio.Play("criticalhit", FisterPlayer.Feet(nm), 1f); float num13 = FMath.Clamp(num10, 0.5f, 1.5f); Fx.Instance?.AirKickHit(FisterWorld.CentreUnity(val3), num13); FisterController.Instance.anim.TriggerImpactFrame(0.04f + 0.025f * num10); Shake(0.3f * num13); airKickHomingTarget = null; } } if (flag5) { Vec3 vec11 = sim.OverchargeDashDirection(); float num14 = sim.OverchargeDashLaunchChargeTime(); float t = Sim.RailingTuningProgress(num14); foreach (EnemyIdentifier item4 in FisterWorld.Targets(position, radiusFister, sweepBuffer)) { if (!sim.IsOverchargeDashing() || railingHit.Contains(item4)) { continue; } Vec3 vec12 = FisterWorld.BodyCentre(item4); if (DistanceToSegment(vec12, position, vec3, 0.85f + Mathf.Max(0f, BodyHalfHeight(item4) - 1.3f)) > 2.4f || !FisterWorld.ClearLine(position, vec12)) { continue; } railingHit.Add(item4); Vector3 at = Units.PosToUnity(vec12); if (num14 >= 10f && !item4.isBoss) { FisterWorld.KillAndLaunch(item4, new Vec3(vec11.x * 230f, vec11.y * 230f, 70f)); FisterAudio.Play("disintegrated", FisterPlayer.Feet(nm), 2f); Fx.Instance?.RailingHit(at, 2.35f); sim.OnRailingHit(flatten: true); sim.GrantInstantPunchCharge(); continue; } if (sim.IsOverchargeDashMegaBoosted()) { Vec3 velSim2 = vec11.Mul(400f); FisterWorld.Launch(item4, velSim2, 2f, 4f); } else { float num15 = FMath.Lerp(75f, 230f, t); float z = FMath.Lerp(20f, 70f, t); float hardKnockdown = ((num14 > 3f) ? FMath.Lerp(2f, 4.5f, t) : 0f); FisterWorld.Damage(item4, FMath.Lerp(40f, 170f, t)); FisterWorld.Launch(item4, new Vec3(vec11.x * num15, vec11.y * num15, z), hardKnockdown, FMath.Lerp(1f, 2.4f, t) * 2f); } FisterAudio.Play("criticalhit", FisterPlayer.Feet(nm), 1f); float st = (sim.IsOverchargeDashMegaBoosted() ? 2.35f : FMath.Clamp(sim.OverchargeDashSpeed() / 88f, 1f, 2.25f)); Fx.Instance?.RailingHit(at, st); sim.OnRailingHit(flatten: false); sim.GrantInstantPunchCharge(); } } if (flag6) { float num16 = sim.RocketAscentCharge(); foreach (EnemyIdentifier item5 in FisterWorld.Targets(position, radiusFister, sweepBuffer)) { if (!ascentHit.Contains(item5) && !(DistanceToSegment(FisterWorld.BodyCentre(item5), position, vec3, 0.65f + Mathf.Max(0f, BodyHalfHeight(item5) - 1.3f)) > 1.5f)) { ascentHit.Add(item5); if (FisterWorld.IsClearlyAirborne(item5) && !item5.isBoss) { FisterWorld.KillAndLaunch(item5, new Vec3(0f, 0f, 111.111115f)); continue; } float num17 = vec.Length(); float s = 1500f * (0.5f + num16) * (0.5f + 0.5f * num17 / 35f) / 72f; Vec3 vec13 = vec.Normalized(); vec13.z = Mathf.Max(vec13.z, 0.5f); vec13 = vec13.Normalized().Mul(s); FisterWorld.Damage(item5, 15f + 20f * num16); FisterWorld.Launch(item5, vec13, 2f, 3.75f); FisterAudio.Play("crack", FisterWorld.CentreUnity(item5), 1f); } } } if (!flag7) { return; } Vec3 vec14 = FMath.AimDirection(Yaw, owner.pitch); Vec3 vec15 = new Vec3(position.x, position.y, position.z + 0.9f); EnemyIdentifier val5 = null; float num18 = 192f; foreach (EnemyIdentifier item6 in FisterWorld.Targets(position, 192f)) { Vec3 vec16 = FisterWorld.BodyCentre(item6); float num19 = vec16.Sub(vec15).Dot(vec14); if (!(num19 <= 0f) && !(num19 >= num18)) { Vec3 o = vec15.Add(vec14.Mul(num19)); float num20 = 1.2f + (FisterWorld.IsRagdolled(item6) ? 0.6f : 0f) + Mathf.Max(0f, BodyHalfHeight(item6) - 1.3f); if (vec16.Sub(o).Length() <= num20 && FisterWorld.ClearLine(vec15, vec16)) { val5 = item6; num18 = num19; } } } sim.SetAirKickLockCandidate((Object)(object)val5 != (Object)null && (Object)(object)val5 == (Object)(object)airKickLockTarget); airKickLockTarget = val5; } internal static void SelfDamage(NewMovement nm, float fisterHp) { int num = Mathf.RoundToInt(fisterHp * 100f / 200f); if (num <= 0 || nm.dead) { return; } SelfDamageGuard.Active = true; try { nm.GetHurt(num, false, 1f, false, false, 0.35f, false); } finally { SelfDamageGuard.Active = false; } } internal static void SelfKill(NewMovement nm) { if (!FisterConfig.LethalSelfMoves.Value) { FisterController.Instance.player.sim.EnterRagdoll(3f, hardKnockdown: true); return; } SelfDamageGuard.Active = true; try { nm.GetHurt(1000, false, 1f, false, false, 0.35f, true); } finally { SelfDamageGuard.Active = false; } } } internal static class SelfDamageGuard { internal static bool Active; } internal static class FisterConfig { internal static ConfigEntry<bool> StartEnabled; internal static ConfigEntry<Key> ToggleKey; internal static ConfigEntry<float> Volume; internal static ConfigEntry<bool> ScreenShake; internal static ConfigEntry<bool> LethalSelfMoves; internal static ConfigEntry<float> DamageScale; internal static ConfigEntry<bool> WhiffKnockdowns; internal static ConfigEntry<bool> InstantChargeOnKill; internal static ConfigEntry<bool> RagdollOnHit; internal static ConfigEntry<float> PunchDamage; internal static ConfigEntry<float> JabDamageFraction; internal static ConfigEntry<float> HeavyPunchFraction; internal static ConfigEntry<float> BossPunchFraction; internal static ConfigEntry<float> CriticalPunchMultiplier; internal static ConfigEntry<bool> HitStop; internal static ConfigEntry<float> SurfaceParryBuffer; internal static ConfigEntry<float> SurfaceParryLate; internal static ConfigEntry<float> AirKickDamage; internal static ConfigEntry<float> AirKickHeavyFraction; internal static ConfigEntry<float> AirKickBossFraction; internal static ConfigEntry<float> AirKickLaunch; internal static ConfigEntry<float> AirKickChainBonus; internal static ConfigEntry<float> AirKickChainWindow; internal static ConfigEntry<float> BossDamageScale; internal static ConfigEntry<float> KillProtectHealth; internal static ConfigEntry<int> AirKickChainMax; internal static ConfigEntry<bool> LiveRagdollTint; internal static ConfigEntry<int> ConfigVersion; internal static void Bind(ConfigFile cfg) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Expected O, but got Unknown //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Expected O, but got Unknown //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Expected O, but got Unknown //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Expected O, but got Unknown //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Expected O, but got Unknown //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Expected O, but got Unknown //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Expected O, but got Unknown //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Expected O, but got Unknown //IL_0492: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Expected O, but got Unknown //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Expected O, but got Unknown StartEnabled = cfg.Bind<bool>("General", "StartAsJohnFister", true, "Play as John Fister when a level starts. Toggle in game with the toggle key."); ToggleKey = cfg.Bind<Key>("General", "ToggleKey", (Key)100, "Switches between John Fister and V1 (restores V1's controls, health, weapons and camera)."); Volume = cfg.Bind<float>("Audio", "Volume", 1f, new ConfigDescription("John Fister's sounds, on top of the game's SFX volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); ScreenShake = cfg.Bind<bool>("Camera", "ScreenShake", true, "Fister's own hit shake. The game's screen shake setting also scales it."); LethalSelfMoves = cfg.Bind<bool>("Combat", "LethalSelfMoves", true, "As in Fister: the 10 s overcharge self-destruct, a mega-boosted railing into a wall and a parried dive or railing kill John. Off: a long hard knockdown instead."); DamageScale = cfg.Bind<float>("Combat", "DamageScale", 0.15f, new ConfigDescription("Collision damage: enemy health taken per Fister damage point when a launched body hits a wall, the floor or another enemy (Fister's damage is for a 200 HP brawler; 0.15 maps a full-charge punch into a wall, ~140 Fister damage, to 21).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>())); PunchDamage = cfg.Bind<float>("Combat", "PunchDamage", 3.5f, new ConfigDescription("Direct damage of a full-charge punch on contact (ULTRAKILL health; V1's feedbacker deals 1; a Filth has 0.5, a Stray 1.5, a Schism 5). Added to the collision damage. Lighter punches deal less (see JabDamageFraction).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); JabDamageFraction = cfg.Bind<float>("Combat", "JabDamageFraction", 0.08f, new ConfigDescription("Share of the full punch's contact damage a tap jab deals; charged punches climb from here to 1 with the square of the charge.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); HeavyPunchFraction = cfg.Bind<float>("Combat", "HeavyPunchFraction", 0.1f, new ConfigDescription("Heavy enemies (Swordsmachine, Cerberus, Hideous Mass, Mindflayer, Gutterman... anything too big to launch): a full punch takes at least this share of their full health.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); BossPunchFraction = cfg.Bind<float>("Combat", "BossPunchFraction", 0f, new ConfigDescription("Bosses: a full punch takes at least this share of their full health.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); CriticalPunchMultiplier = cfg.Bind<float>("Combat", "CriticalPunchMultiplier", 3f, new ConfigDescription("Contact damage multiplier of the critical fist (the 7 s charge).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); AirKickDamage = cfg.Bind<float>("Combat", "AirKickDamage", 7f, new ConfigDescription("Contact damage of an air kick that connects (2x a full punch; a fast kick deals up to 1.5x this; chained kicks add AirKickChainBonus each).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); AirKickHeavyFraction = cfg.Bind<float>("Combat", "AirKickHeavyFraction", 0.15f, new ConfigDescription("Heavy enemies: least share of their health an air kick takes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); AirKickBossFraction = cfg.Bind<float>("Combat", "AirKickBossFraction", 0f, new ConfigDescription("Bosses: least share of their health an air kick takes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); AirKickLaunch = cfg.Bind<float>("Combat", "AirKickLaunch", 0.6f, new ConfigDescription("Air kick launch speed (x Fister's; not reduced by EnemyLaunch, and never slower than a full punch's launch).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>())); AirKickChainBonus = cfg.Bind<float>("Combat", "AirKickChainBonus", 1f, new ConfigDescription("Air-kick chain: each consecutive air-kick hit adds this much damage. Kicks chain while John has not landed since the last kick hit, or within AirKickChainWindow seconds of it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>())); AirKickChainWindow = cfg.Bind<float>("Combat", "AirKickChainWindow", 1.5f, new ConfigDescription("Seconds after an air-kick hit within which the next kick hit still counts as a chain (even after landing).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); AirKickChainMax = cfg.Bind<int>("Combat", "AirKickChainMax", 5, new ConfigDescription("Most chain bonuses that stack (the 6th and later kicks in a chain deal base + 5 x bonus).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>())); BossDamageScale = cfg.Bind<float>("Combat", "BossDamageScale", 1f, new ConfigDescription("Multiplier on all of John's damage to bosses.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f), Array.Empty<object>())); KillProtectHealth = cfg.Bind<float>("Combat", "KillProtectHealth", 10f, new ConfigDescription("Enemies with more health than this, and every boss, never take an instant kill (finisher, airborne uppercut, dive, piledriver, throw kill): they take a full punch's damage instead, and no single other hit deals more than two full punches.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>())); LiveRagdollTint = cfg.Bind<bool>("Combat", "LiveRagdollTint", true, "Enemies John launches or ragdolls glow orange while they are alive (as Fister tints a hard-knocked-down player); the tint goes when they get up or die."); HitStop = cfg.Bind<bool>("Combat", "HitStop", true, "ULTRAKILL's own hit-stop, camera kick and punch impact on every connecting punch."); WhiffKnockdowns = cfg.Bind<bool>("Combat", "WhiffKnockdowns", false, "Fister's whiff punishments: an air kick that ends on a wall or the ground, or a dive that hits nobody, knocks John down. Off by default."); InstantChargeOnKill = cfg.Bind<bool>("Combat", "InstantChargeOnKill", true, "Any kill credited to John gives the instant full charge (a port rule; in Fister only landed full punches, parries, air-kick and railing hits, connecting dives and throws do)."); RagdollOnHit = cfg.Bind<bool>("Combat", "RagdollOnHit", true, "Enemies John launches, grabs or throws go limp (their own ragdoll, limbs flopping) and get back up when they settle. Enemies without a jointed rig fly as a rigid body either way."); SurfaceParryBuffer = cfg.Bind<float>("Parry timing", "SurfaceParryBuffer", 0.3f, new ConfigDescription("How early (seconds) a parry may be pressed before hitting a wall or the floor while ragdolled or in the air and still rebound. Fister: 0.16 (in flight), 0.25 (ragdolled).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); SurfaceParryLate = cfg.Bind<float>("Parry timing", "SurfaceParryLate", 0.1f, new ConfigDescription("How late (seconds) a parry may come after hitting a wall or the floor and still rebound off it (a port addition; Fister: 0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>())); Tuning.BindAll(cfg); ConfigVersion = cfg.Bind<int>("General", "ConfigVersion", 0, "Settings format version (managed by the mod; do not edit)."); Migrate(cfg); } private static void MoveToNewDefault(ConfigEntry<float> e, float oldDefault) { if (Mathf.Approximately(e.Value, oldDefault)) { e.Value = (float)((ConfigEntryBase)e).DefaultValue; } } private static void Migrate(ConfigFile cfg) { if (ConfigVersion.Value < 104) { if (Mathf.Approximately(DamageScale.Value, 0.1f)) { DamageScale.Value = (float)((ConfigEntryBase)DamageScale).DefaultValue; } if (Mathf.Approximately(Tuning.EnemyLaunch.Value, 0.5f)) { Tuning.EnemyLaunch.Value = (float)((ConfigEntryBase)Tuning.EnemyLaunch).DefaultValue; } MoveToNewDefault(Tuning.WallParry, 0.6f); MoveToNewDefault(Tuning.RailingBounce, 0.4f); MoveToNewDefault(Tuning.GroundParry, 0.8f); ConfigVersion.Value = 104; } if (ConfigVersion.Value < 105) { MoveToNewDefault(Tuning.WallParry, 0.5f); MoveToNewDefault(Tuning.GroundParry, 0.6f); ConfigVersion.Value = 105; } if (ConfigVersion.Value < 106) { DropOrphans(cfg, (ConfigDefinition d) => d.Section == "Parry brake" || (d.Section == "Room scale" && (d.Key == "ParryMaxSpeed" || d.Key == "ParryBrakeTime" || d.Key == "ParryDriftSpeed"))); ConfigVersion.Value = 106; } if (ConfigVersion.Value < 110) { MoveToNewDefault(PunchDamage, 5f); MoveToNewDefault(HeavyPunchFraction, 0.3f); MoveToNewDefault(BossPunchFraction, 0.1f); MoveToNewDefault(AirKickDamage, 7.5f); MoveToNewDefault(AirKickHeavyFraction, 0.45f); MoveToNewDefault(AirKickBossFraction, 0.15f); ConfigVersion.Value = 110; } } private static void DropOrphans(ConfigFile cfg, Func<ConfigDefinition, bool> which) { try { Dictionary<ConfigDefinition, string> value = Traverse.Create((object)cfg).Property("OrphanedEntries", (object[])null).GetValue<Dictionary<ConfigDefinition, string>>(); if (value == null) { return; } foreach (ConfigDefinition item in new List<ConfigDefinition>(value.Keys)) { if (which(item)) { value.Remove(item); } } cfg.Save(); } catch (Exception ex) { FisterPlugin.Log.LogWarning((object)("settings cleanup: " + ex.Message)); } } } internal sealed class FisterController : MonoBehaviour { internal static FisterController Instance; internal readonly FisterPlayer player = new FisterPlayer(); internal readonly PoseAnimator anim = new PoseAnimator(); internal BodyRenderer body; internal Pose lastPose; internal bool wanted; private float animTime; private float shake; private float airTime; private int lastHp = -1; private bool grabWasDown; private bool itemPress; private Vector3 lastHand; private string lastGatedScene; private string failure; private float failureUntil; internal NewMovement Player => MonoSingleton<NewMovement>.Instance; private void Awake() { Instance = this; wanted = FisterConfig.StartEnabled.Value; Fx.Instance = ((Component)this).gameObject.AddComponent<Fx>(); ((Component)this).gameObject.AddComponent<CooldownRing>(); } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { FisterPlugin.Log.LogInfo((object)("scene loaded: " + ((Scene)(ref scene)).name)); player.Reset(); anim.Reset(); FisterInput.Invalidate(); FisterAudio.StopLoops(); FisterWorld.ReleaseAll(); ParryReturn.Clear(); lastHp = -1; } private void FixedUpdate() { FisterCamera.RestoreTransform(); FisterWorld.FixedTick(); ParryReturn.FixedTick(); } internal void AddShake(float intensity) { shake = Mathf.Max(shake, intensity); } private void Update() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) FisterCamera.RestoreTransform(); Keyboard current = Keyboard.current; if (current != null && ((ButtonControl)current[FisterConfig.ToggleKey.Value]).wasPressedThisFrame) { wanted = !wanted; } NewMovement val = Player; bool flag = (Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled && (Object)(object)val.rb != (Object)null; bool active = FisterMode.Active; bool flag2 = flag && val.levelOver; string currentScene = SceneHelper.CurrentScene; int num; switch (currentScene) { default: num = ((currentScene == "Credits") ? 1 : 0); break; case "Intro": case "Tutorial": case "Main Menu": case "Bootstrap": num = 1; break; } bool flag3 = (byte)num != 0; if (flag3 && currentScene != lastGatedScene) { lastGatedScene = currentScene; FisterPlugin.Log.LogInfo((object)("John Fister stays off in " + currentScene + " (V1's own sequence)")); } flag2 = flag2 || flag3; if (flag2 && FisterMode.Active) { FisterPlugin.Log.LogInfo((object)"level over: handing the end sequence to V1 until the next level"); } try { FisterMode.Sync(flag ? val : null, wanted && !flag2); } catch (Exception ex) { Fail("switching modes failed", ex); try { FisterMode.Sync(flag ? val : null, wants: false); } catch (Exception ex2) { FisterPlugin.Log.LogError((object)("restoring V1 failed: " + ex2)); } } if (FisterMode.Active && !active) { Assets.PreloadAll(); player.Reset(); anim.Reset(); } if (!FisterMode.Active) { if (body != null) { body.Visible = false; } FisterCamera.HasFollow = false; FisterAudio.StopLoops(); } else { SampleInput(val); UpdateFeedback(val); } } private void SampleInput(NewMovement nm) { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) CameraController cc = nm.cc; OptionsManager instance = MonoSingleton<OptionsManager>.Instance; FisterInput.State state = (((Object)(object)instance != (Object)null && (instance.paused || instance.frozen)) ? default(FisterInput.State) : FisterInput.Read()); if (state.grab && !grabWasDown && !state.fist && (Object)(object)cc != (Object)null) { Vector3 head = ((Component)nm).transform.position + ((Component)nm).transform.up * 1.4f; Vector3 aim = Quaternion.Euler(0f - cc.rotationX, cc.rotationY, 0f) * Vector3.forward; itemPress = FisterItems.TryUse(head, aim, lastHand); } grabWasDown = state.grab; if (itemPress) { if (state.grab) { state.grab = false; } else { itemPress = false; } } player.buttons.Update(state.fist, state.parry, state.grab, Time.timeAsDouble); player.move = state.move; if ((Object)(object)cc != (Object)null) { player.yaw = Units.SimYaw(cc.rotationY); player.pitch = cc.rotationX * ((float)Math.PI / 180f); } } private void UpdateFeedback(NewMovement nm) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) Sim sim = player.sim; if (!sim.IsGrounded()) { airTime += Time.deltaTime; } else { if (airTime >= 0.28f) { FisterAudio.Play("footstep", FisterPlayer.Feet(nm), 0.5f); } airTime = 0f; } if (lastHp >= 0 && lastHp - nm.hp >= 1) { anim.TriggerDamageFlash(); FisterAudio.Play("damage-taken", FisterPlayer.Feet(nm), 0.8f); } lastHp = nm.hp; FisterSounds.UpdateLoops(sim); } internal void OnCameraLateUpdate(CameraController cc) { NewMovement val = Player; if (!FisterMode.Active || (Object)(object)val == (Object)null) { FisterCamera.HasFollow = false; return; } try { if (body == null) { body = new BodyRenderer("JohnFisterBody"); } body.Visible = true; PlaceBodyAndCamera(cc, val); } catch (Exception ex) { Fail("drawing John failed", ex); if (body != null) { body.Visible = false; } FisterCamera.HasFollow = false; FisterCamera.Apply(cc); } } internal void Fail(string what, Exception ex) { FisterPlugin.Log.LogError((object)("John Fister: " + what + "; switching back to V1 (F7 tries again). " + ex)); wanted = false; failure = "John Fister: " + what + " (" + ex.GetType().Name + ": " + ex.Message + "). Playing as V1; see BepInEx/LogOutput.log."; failureUntil = Time.unscaledTime + 12f; } private void OnGUI() { //IL_0015: 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) if (failure != null && Time.unscaledTime < failureUntil) { GUI.color = Color.white; GUI.Label(new Rect(20f, 20f, (float)Screen.width - 40f, 60f), failure); } } private void PlaceBodyAndCamera(CameraController cc, NewMovement nm) { //IL_0012: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result