Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RamRoyalFlush v0.2.21
BepInEx/plugins/RamRoyalFlush/RamRoyalFlush.dll
Decompiled 6 days 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using SoftReferenceableAssets; using UnityEngine; using UnityEngine.Audio; [assembly: AssemblyFileVersion("0.2.21.0")] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.2.20.0")] namespace RamRoyalFlush; internal sealed class AudioSequenceRules { private bool requested; private bool waitForCompletion; private bool expired; internal bool CompletionSeen { get; private set; } internal bool Played { get; private set; } internal void Complete() { CompletionSeen = true; } internal void Request(bool fartEnabled) { if (!requested) { requested = true; waitForCompletion = fartEnabled; } } internal bool TryStart(bool fartActive, bool paused) { if (expired || Played || !requested || paused || fartActive || (waitForCompletion && !CompletionSeen)) { return false; } Played = true; return true; } internal void Expire() { expired = true; } } public sealed class CompletionAudio : MonoBehaviour { internal enum Readiness { Waiting, Ready, Failed, Cancelled } private static readonly Dictionary<string, CompletionAudio> pending = new Dictionary<string, CompletionAudio>(); private readonly AudioSequenceRules order = new AudioSequenceRules(); private string key; private AudioSource fart; private double fartEnd; private double drainSeconds; private double stoppedAt = -1.0; private int lastSample; private bool finishedLogged; private double expires; private Player player; private GameObject presentation; private bool localBarrier; private bool expectedFart; private bool observedPlaying; private bool cancelled; private bool interruptedPlayback; internal static void BeginLocal(string key, bool fartEnabled) { CompletionAudio completionAudio = Get(key); completionAudio.localBarrier = true; completionAudio.expectedFart = fartEnabled; } internal static bool WantsFart(string key, bool configured) { CompletionAudio completionAudio = Get(key); if (!completionAudio.cancelled && (completionAudio.localBarrier ? completionAudio.expectedFart : configured)) { return !completionAudio.order.Played; } return false; } internal static bool IsCancelled(string key) { if (pending.TryGetValue(key, out var value) && Object.op_Implicit((Object)(object)value)) { return value.cancelled; } return false; } internal static void BindPresentation(string key, GameObject go) { CompletionAudio completionAudio = Get(key); if (completionAudio.cancelled) { Object.Destroy((Object)(object)go); } else { completionAudio.presentation = go; } } internal static Readiness Status(string key) { if (!pending.TryGetValue(key, out var value) || !Object.op_Implicit((Object)(object)value)) { return Readiness.Failed; } if (value.cancelled) { return Readiness.Cancelled; } if (AudioListener.pause) { return Readiness.Waiting; } if (!value.expectedFart) { return Readiness.Ready; } if (!value.order.CompletionSeen) { return Readiness.Waiting; } if (!Object.op_Implicit((Object)(object)value.fart)) { return Readiness.Failed; } return value.PlaybackStatus(); } private Readiness PlaybackStatus() { double dspTime = AudioSettings.dspTime; bool flag = Object.op_Implicit((Object)(object)fart) && fart.isPlaying; if (Object.op_Implicit((Object)(object)fart)) { lastSample = Math.Max(lastSample, fart.timeSamples); } if (observedPlaying && !flag && dspTime < fartEnd - Math.Max(0.02, drainSeconds)) { interruptedPlayback = true; } if (interruptedPlayback) { return Readiness.Failed; } observedPlaying |= flag; if (flag || dspTime < fartEnd) { return Readiness.Waiting; } if (!observedPlaying) { return Readiness.Failed; } if (stoppedAt < 0.0) { stoppedAt = dspTime; } if (dspTime < Math.Max(fartEnd, stoppedAt) + drainSeconds) { return Readiness.Waiting; } if (!finishedLogged) { finishedLogged = true; Plugin.Log.LogInfo((object)("RRFlush fart naturally finished: key=" + key + "; dsp=" + dspTime + "; clipEndDSP=" + fartEnd + "; stoppedDSP=" + stoppedAt + "; outputDrainSeconds=" + drainSeconds + "; lastObservedSample=" + lastSample + "; playing=False; seated exit may now begin.")); } return Readiness.Ready; } internal static void Cancel(string key) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated()) { CompletionAudio completionAudio = Get(key); completionAudio.cancelled = true; completionAudio.order.Expire(); if (Object.op_Implicit((Object)(object)completionAudio.fart)) { completionAudio.fart.Stop(); } if (Object.op_Implicit((Object)(object)completionAudio.presentation)) { Object.Destroy((Object)(object)completionAudio.presentation); } } } internal static string Key(int seat, long token) { return seat + ":" + token; } private static CompletionAudio Get(string key) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (pending.TryGetValue(key, out var value) && Object.op_Implicit((Object)(object)value)) { return value; } GameObject val = new GameObject("RamRoyalFlush_audio_sequence"); value = val.AddComponent<CompletionAudio>(); value.key = key; value.expires = AudioSettings.dspTime + 10.0; pending[key] = value; return value; } internal static bool ScreamStarted(string key) { if (pending.TryGetValue(key, out var value) && Object.op_Implicit((Object)(object)value)) { return value.order.Played; } return false; } internal static void Complete(string key, AudioSource source) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated()) { return; } CompletionAudio completionAudio = Get(key); if (completionAudio.cancelled || completionAudio.order.CompletionSeen) { return; } completionAudio.fart = source; completionAudio.observedPlaying = Object.op_Implicit((Object)(object)source) && source.isPlaying; if (Object.op_Implicit((Object)(object)source) && Object.op_Implicit((Object)(object)source.clip)) { int num = default(int); int num2 = default(int); AudioSettings.GetDSPBufferSize(ref num, ref num2); int outputSampleRate = AudioSettings.outputSampleRate; if (num < 0 || num2 < 0 || outputSampleRate <= 0) { completionAudio.interruptedPlayback = true; Plugin.Log.LogWarning((object)"Audio output timing unavailable; completion cannot verify full playback; food/launch withheld."); } else { completionAudio.drainSeconds = (double)num * (double)num2 / (double)outputSampleRate; } completionAudio.fartEnd = AudioSettings.dspTime + (double)source.clip.samples / (double)source.clip.frequency / Math.Max(0.01, source.pitch); completionAudio.lastSample = source.timeSamples; completionAudio.expires = Math.Max(completionAudio.expires, completionAudio.fartEnd + completionAudio.drainSeconds + 5.0); } completionAudio.order.Complete(); Plugin.Log.LogInfo((object)("RRFlush fart cue: key=" + key + "; started=" + Object.op_Implicit((Object)(object)source) + "; startDSP=" + AudioSettings.dspTime + "; endDSP=" + completionAudio.fartEnd + "; outputDrainSeconds=" + completionAudio.drainSeconds + "; firstSample=" + completionAudio.lastSample)); completionAudio.Tick(); } internal static void Request(string key, Player player, bool fartEnabled) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated()) { CompletionAudio completionAudio = Get(key); completionAudio.player = player; completionAudio.order.Request(completionAudio.localBarrier ? completionAudio.expectedFart : fartEnabled); completionAudio.Tick(); } } private void Update() { Tick(); } internal void Tick() { if (AudioListener.pause) { return; } if (Object.op_Implicit((Object)(object)fart) && fart.isPlaying) { observedPlaying = true; } if (AudioSettings.dspTime >= expires) { if (Object.op_Implicit((Object)(object)player) && !order.Played) { Plugin.Log.LogWarning((object)("RRLaunch scream skipped: completion audio not verified before timeout; flight unchanged. key=" + key)); } Close(); return; } bool fartActive = Object.op_Implicit((Object)(object)fart) && (fart.isPlaying || AudioSettings.dspTime < fartEnd || PlaybackStatus() == Readiness.Waiting); if (!Object.op_Implicit((Object)(object)player) || !order.TryStart(fartActive, paused: false)) { return; } try { Plugin.Log.LogInfo((object)("RRLaunch scream cue: key=" + key + "; dsp=" + AudioSettings.dspTime + "; fartEnded=True")); LaunchScream.Play(player); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Launch scream unavailable; flight unchanged: " + ex)); } } private void Close() { order.Expire(); if (key != null && pending.TryGetValue(key, out var value) && (Object)(object)value == (Object)(object)this) { pending.Remove(key); } Object.Destroy((Object)(object)((Component)this).gameObject); } private void OnDestroy() { order.Expire(); if (key != null && pending.TryGetValue(key, out var value) && (Object)(object)value == (Object)(object)this) { pending.Remove(key); } } internal static void Dispose() { foreach (CompletionAudio item in new List<CompletionAudio>(pending.Values)) { if (Object.op_Implicit((Object)(object)item)) { item.Close(); } } pending.Clear(); } } internal static class CompletionPresentation { private const string CloudShaderID = "0f5a6e59b3eb19f3ba0b7e7955445af0"; private const string CloudShaderName = "Particles/Standard Unlit2"; private static AudioClip fart; private static Material gas; private static Texture2D texture; private static int active; private static bool mixerWarning; private static SoftReference<Shader> cloudShader; private static bool shaderHeld; internal static void Play(Vector3 position, bool surprise, string audioKey) { //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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) AudioSource played = null; try { if (CompletionAudio.IsCancelled(audioKey) || (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated()) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || active >= 4 || Vector3.Distance(((Component)Player.m_localPlayer).transform.position, position) > 30f) { return; } bool sound = CompletionAudio.WantsFart(audioKey, Plugin.FartSound.Value); if (sound || Plugin.GreenCloud.Value) { GameObject go = new GameObject("RamRoyalFlush_completion"); CompletionAudio.BindPresentation(audioKey, go); go.transform.position = position + Vector3.up * 0.45f; active++; go.AddComponent<PresentationLifetime>(); Object.Destroy((Object)(object)go, Mathf.Max(5f, 9.398436f)); EffectPlayback.Run(sound, Plugin.GreenCloud.Value, delegate { played = Sound(go); CompletionAudio.Complete(audioKey, played); }, delegate { go.AddComponent<ThreeGasBursts>().Initialize(surprise, sound, audioKey); }, delegate(string effect, Exception ex) { Plugin.Log.LogWarning((object)(effect + " failed; other effect remains independent; gameplay already completed: " + ex)); }); if (surprise) { Plugin.Log.LogInfo((object)"RRFlush Easter egg rolled (5%); original SHITTER'S FULL! voice asset pending."); } } } finally { CompletionAudio.Complete(audioKey, played); } } private static AudioSource Sound(GameObject go) { AudioMixer val = (Object.op_Implicit((Object)(object)AudioMan.instance) ? AudioMan.instance.m_masterMixer : null); AudioMixerGroup val2 = null; if (Object.op_Implicit((Object)(object)val)) { AudioMixerGroup[] array = val.FindMatchingGroups(""); foreach (AudioMixerGroup val3 in array) { if (Object.op_Implicit((Object)(object)val3) && string.Equals(((Object)val3).name, "SFX", StringComparison.OrdinalIgnoreCase)) { val2 = val3; break; } } } if (!Object.op_Implicit((Object)(object)val2)) { if (!mixerWarning) { mixerWarning = true; Plugin.Log.LogWarning((object)"SFX mixer group unavailable: fart audio skipped, no unrouted fallback."); } return null; } if (!Object.op_Implicit((Object)(object)fart)) { float[] array2 = FartRecording.Create(); AudioClip val4 = AudioClip.Create("RamRoyalFlush_Justin_recording", array2.Length, 1, 44100, false); MethodInfo method = typeof(AudioClip).GetMethod("SetData", new Type[2] { typeof(float[]), typeof(int) }); try { if (method == null || !(bool)method.Invoke(val4, new object[2] { array2, 0 })) { throw new InvalidOperationException("Could not load recorded fart PCM through verified float[] API."); } fart = val4; } catch { if (Object.op_Implicit((Object)(object)val4)) { Object.Destroy((Object)(object)val4); } throw; } } AudioSource val5 = go.AddComponent<AudioSource>(); val5.playOnAwake = false; val5.clip = fart; val5.outputAudioMixerGroup = val2; val5.volume = 1f; val5.spatialBlend = 1f; val5.dopplerLevel = 0f; val5.minDistance = 1.5f; val5.maxDistance = 22f; val5.rolloffMode = (AudioRolloffMode)1; val5.timeSamples = 0; val5.loop = false; val5.Play(); return val5; } internal static ParticleSystem Cloud(GameObject go, bool surprise) { //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Expected O, but got Unknown //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_0495: Unknown result type (might be due to invalid IL or missing references) //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)gas)) { AssetID val = default(AssetID); if (!AssetID.TryParse("0f5a6e59b3eb19f3ba0b7e7955445af0", ref val)) { throw new InvalidOperationException("Invalid verified cloud shader ID."); } if (!shaderHeld) { cloudShader = new SoftReference<Shader>(val); shaderHeld = true; cloudShader.Load(); } Shader asset = cloudShader.Asset; if (!Object.op_Implicit((Object)(object)asset) || ((Object)asset).name != "Particles/Standard Unlit2" || !asset.isSupported) { cloudShader.Release(); shaderHeld = false; throw new InvalidOperationException("Verified Valheim cloud shader unavailable/unsupported; expected Particles/Standard Unlit2, actual=" + (Object.op_Implicit((Object)(object)asset) ? ((Object)asset).name : "null")); } gas = new Material(asset); if (gas.HasProperty("_Mode")) { gas.SetFloat("_Mode", 2f); } gas.SetOverrideTag("RenderType", "Transparent"); gas.DisableKeyword("_ALPHATEST_ON"); gas.DisableKeyword("_ALPHAPREMULTIPLY_ON"); gas.DisableKeyword("_ALPHAMODULATE_ON"); gas.EnableKeyword("_ALPHABLEND_ON"); if (gas.HasProperty("_SrcBlend")) { gas.SetInt("_SrcBlend", 5); } if (gas.HasProperty("_DstBlend")) { gas.SetInt("_DstBlend", 10); } if (gas.HasProperty("_BlendOp")) { gas.SetInt("_BlendOp", 0); } if (gas.HasProperty("_ZWrite")) { gas.SetInt("_ZWrite", 0); } if (gas.HasProperty("_Color")) { gas.SetColor("_Color", Color.white); } gas.renderQueue = 3000; texture = new Texture2D(32, 32, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[1024]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = Mathf.Sqrt(Mathf.Pow(((float)j - 15.5f) / 15.5f, 2f) + Mathf.Pow(((float)i - 15.5f) / 15.5f, 2f)); ref Color reference = ref array[i * 32 + j]; reference = new Color(1f, 1f, 1f, Mathf.Pow(Mathf.Max(0f, 1f - num), 2f)); } } texture.SetPixels(array); texture.Apply(); gas.mainTexture = (Texture)(object)texture; Plugin.Log.LogInfo((object)("RRFlush cloud shader resolved: " + ((Object)asset).name + "; alpha blending configured.")); } ParticleSystem val2 = go.AddComponent<ParticleSystem>(); val2.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = val2.main; ((MainModule)(ref main)).playOnAwake = false; ((MainModule)(ref main)).loop = false; ((MainModule)(ref main)).duration = 0.4f; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(1.7f, 3.1f); ((MainModule)(ref main)).startSpeed = new MinMaxCurve(0.6f, surprise ? 3.3f : 1.65f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.975f, surprise ? 3.9f : 1.95f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.26f, 0.65f, 0.06f, 0.62f)); ((MainModule)(ref main)).maxParticles = (surprise ? 270 : 108); ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(-0.0375f); EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).enabled = false; ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.33f; ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val3 = new Gradient(); val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(new Color(0.26f, 0.65f, 0.06f), 0f), new GradientColorKey(new Color(0.15f, 0.4f, 0.04f), 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[3] { new GradientAlphaKey(0.65f, 0f), new GradientAlphaKey(0.4f, 0.45f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val3); ((Renderer)((Component)val2).GetComponent<ParticleSystemRenderer>()).sharedMaterial = gas; val2.Play(); val2.Emit(surprise ? 90 : 36); go.AddComponent<CloudSpawnCheck>().Initialize(val2); return val2; } internal static void Released() { active = Math.Max(0, active - 1); } internal static void Dispose() { if (Object.op_Implicit((Object)(object)fart)) { Object.Destroy((Object)(object)fart); } if (Object.op_Implicit((Object)(object)gas)) { Object.Destroy((Object)(object)gas); } if (Object.op_Implicit((Object)(object)texture)) { Object.Destroy((Object)(object)texture); } if (shaderHeld) { cloudShader.Release(); shaderHeld = false; } } } public sealed class PresentationLifetime : MonoBehaviour { private void OnDestroy() { CompletionPresentation.Released(); } } public sealed class ThreeGasBursts : MonoBehaviour { private GasBurstSchedule schedule; private ParticleSystem particles; private bool surprise; private string key; internal void Initialize(bool large, bool sound, string audioKey) { surprise = large; key = audioKey; schedule = new GasBurstSchedule(AudioSettings.dspTime, sound); Update(); } private void Update() { if (CompletionAudio.IsCancelled(key)) { Object.Destroy((Object)(object)this); } else { if (AudioListener.pause) { return; } int num = schedule.Poll(AudioSettings.dspTime); if (num == 0) { return; } try { if (num == 1) { particles = CompletionPresentation.Cloud(((Component)this).gameObject, surprise); } else if (Object.op_Implicit((Object)(object)particles)) { particles.Emit(surprise ? 90 : 36); ((Component)this).gameObject.AddComponent<CloudSpawnCheck>().Initialize(particles); } Plugin.Log.LogInfo((object)("RRFlush gas burst=" + num + "; key=" + key + "; dsp=" + AudioSettings.dspTime)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Gas burst unavailable; audio/exit independent: " + ex)); Object.Destroy((Object)(object)this); } if (num == 3) { Object.Destroy((Object)(object)this); } } } } public sealed class CloudSpawnCheck : MonoBehaviour { private ParticleSystem particles; private int frames; internal void Initialize(ParticleSystem value) { particles = value; } private void LateUpdate() { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)particles)) { Object.Destroy((Object)(object)this); } else if (particles.particleCount != 0 || ++frames >= 4) { ParticleSystemRenderer component = ((Component)particles).GetComponent<ParticleSystemRenderer>(); bool flag = particles.particleCount > 0 && Object.op_Implicit((Object)(object)component) && ((Renderer)component).enabled && Object.op_Implicit((Object)(object)((Renderer)component).sharedMaterial) && Object.op_Implicit((Object)(object)((Renderer)component).sharedMaterial.shader) && ((Renderer)component).sharedMaterial.shader.isSupported; string text = "RRFlush cloud spawn check: particles=" + particles.particleCount + "; rendererReady=" + flag + "; position=" + ((Component)this).transform.position; if (flag) { Plugin.Log.LogInfo((object)text); } else { Plugin.Log.LogWarning((object)(text + "; cloud runtime verification FAILED.")); } Object.Destroy((Object)(object)this); } } } internal static class ConfigRetirement { internal static bool Apply(ConfigFile config) { string configFilePath = config.ConfigFilePath; if (!File.Exists(configFilePath)) { return false; } byte[] array = File.ReadAllBytes(configFilePath); int num = 0; Encoding encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); if (Prefix(array, new byte[4] { 255, 254, 0, 0 })) { num = 4; encoding = new UTF32Encoding(bigEndian: false, byteOrderMark: false, throwOnInvalidCharacters: true); } else if (Prefix(array, new byte[4] { 0, 0, 254, 255 })) { num = 4; encoding = new UTF32Encoding(bigEndian: true, byteOrderMark: false, throwOnInvalidCharacters: true); } else if (Prefix(array, new byte[2] { 255, 254 })) { num = 2; encoding = new UnicodeEncoding(bigEndian: false, byteOrderMark: false, throwOnInvalidBytes: true); } else if (Prefix(array, new byte[2] { 254, 255 })) { num = 2; encoding = new UnicodeEncoding(bigEndian: true, byteOrderMark: false, throwOnInvalidBytes: true); } else if (Prefix(array, new byte[3] { 239, 187, 191 })) { num = 3; } string input = encoding.GetString(array, num, array.Length - num); StringBuilder stringBuilder = new StringBuilder(); bool flag = false; bool flag2 = false; foreach (Match item in Regex.Matches(input, "[^\\r\\n]*(?:\\r\\n|\\n|\\r|$)")) { if (item.Length != 0) { string text = item.Value.Trim(); if (text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal)) { string a = text.Substring(1, text.Length - 2).Trim(); flag = string.Equals(a, "Crafting", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "Gameplay", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "Presentation", StringComparison.OrdinalIgnoreCase); flag2 = flag2 || flag; } if (!flag) { stringBuilder.Append(item.Value); } } } if (!flag2) { return false; } byte[] bytes = encoding.GetBytes(stringBuilder.ToString()); byte[] array2 = new byte[num + bytes.Length]; Array.Copy(array, array2, num); Array.Copy(bytes, 0, array2, num, bytes.Length); string text2 = Hash(array); string text3 = Path.Combine(Path.GetDirectoryName(configFilePath), "RamRoyalFlush-ConfigBackups"); Directory.CreateDirectory(text3); string text4 = Path.Combine(text3, "legacy-" + text2.Substring(0, 16) + ".bak"); if (!File.Exists(text4)) { using FileStream fileStream = new FileStream(text4, FileMode.CreateNew, FileAccess.Write, FileShare.None); fileStream.Write(array, 0, array.Length); fileStream.Flush(flushToDisk: true); } if (Hash(File.ReadAllBytes(text4)) != text2) { throw new IOException("Legacy config backup verification failed; original retained."); } string text5 = configFilePath + ".migration-" + Guid.NewGuid().ToString("N") + ".tmp"; try { using (FileStream fileStream2 = new FileStream(text5, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { fileStream2.Write(array2, 0, array2.Length); fileStream2.Flush(flushToDisk: true); } if (Hash(File.ReadAllBytes(configFilePath)) != text2) { throw new IOException("Config changed during migration; replacement cancelled."); } File.Replace(text5, configFilePath, null); if (Hash(File.ReadAllBytes(configFilePath)) != Hash(array2)) { throw new IOException("Migrated config verification failed; verified backup retained at " + text4); } } finally { if (File.Exists(text5)) { File.Delete(text5); } } return true; } private static bool Prefix(byte[] data, byte[] prefix) { if (data.Length < prefix.Length) { return false; } for (int i = 0; i < prefix.Length; i++) { if (data[i] != prefix[i]) { return false; } } return true; } private static string Hash(byte[] data) { using SHA256 sHA = SHA256.Create(); return BitConverter.ToString(sHA.ComputeHash(data)).Replace("-", ""); } } [HarmonyPatch(typeof(Player), "AttachStop")] internal static class DismountSynchronization { [HarmonyPrefix] private static void Prefix(Player __instance, out ExitMonitor __state) { __state = (((Object)(object)__instance == (Object)(object)Player.m_localPlayer) ? ((Component)__instance).GetComponent<ExitMonitor>() : null); if (Object.op_Implicit((Object)(object)__state) && !__state.BeforeNativeDetach(__instance)) { __state = null; } } [HarmonyPostfix] private static void Postfix(Player __instance, ExitMonitor __state) { if (Object.op_Implicit((Object)(object)__state)) { __state.AfterNativeDetach(__instance); } } } internal static class EffectPlayback { internal static void Run(bool sound, bool cloud, Action playSound, Action playCloud, Action<string, Exception> report) { if (sound) { try { playSound(); } catch (Exception arg) { report("Fart audio", arg); } } if (cloud) { try { playCloud(); } catch (Exception arg2) { report("Green cloud", arg2); } } } } internal sealed class EffectsConfiguration : IDisposable { private readonly ConfigFile config; private bool migrating; private bool disposed; internal readonly ConfigEntry<bool> FartSound; internal readonly ConfigEntry<bool> GreenCloud; internal readonly ConfigEntry<bool> FlightDamage; internal readonly ConfigEntry<float> EjectionForce; internal readonly ConfigEntry<float> LaunchAngle; internal EffectsConfiguration(ConfigFile file) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown config = file; bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { if (ConfigRetirement.Apply(config)) { config.Reload(); } FartSound = config.Bind<bool>("Effects", "FartSound", true, "Fart Sound: spatial main fart and Victory Toot."); GreenCloud = config.Bind<bool>("Effects", "GreenCloud", true, "Green Cloud: three synchronized main bursts and small victory puff."); FlightDamage = config.Bind<bool>("Effects", "FlightDamage", true, "Flight Damage: ON keeps Royal Flush impact and native landing damage. OFF suppresses only this launch's custom impacts and native fall hit; other damage remains. Sampled when launching."); EjectionForce = config.Bind<float>("Effects", "EjectionForce", 0f, new ConfigDescription("Ejection Force: 0 disables launch. Smooth upper-end boost preserves gentle low power; 100 requests 290.576 m/s (650 mph). Native collisions/fall damage apply.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0])); LaunchAngle = config.Bind<float>("Effects", "LaunchAngle", 13f, new ConfigDescription("Launch Angle: 10-90 degrees above horizontal throne-forward; default 13.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 90f), new object[0])); config.Save(); config.ConfigReloaded += OnReload; } finally { config.SaveOnConfigSet = saveOnConfigSet; } } private void OnReload(object sender, EventArgs args) { if (disposed || migrating) { return; } migrating = true; bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { if (ConfigRetirement.Apply(config)) { config.Reload(); config.Save(); } } finally { config.SaveOnConfigSet = saveOnConfigSet; migrating = false; } } public void Dispose() { if (!disposed) { disposed = true; config.ConfigReloaded -= OnReload; } } } internal static class EjectionGeometry { internal static float Angle(float angle) { if (!float.IsNaN(angle) && !float.IsInfinity(angle)) { return Math.Max(10f, Math.Min(90f, angle)); } return 13f; } internal static float Speed(float force) { force = PresentationRules.Force(force); double num = (double)force / 100.0; double num2 = 290.576 / (100.0 * Math.Sqrt(2.0)) - 1.0; return (float)((double)force * Math.Sqrt(2.0) * (1.0 + num2 * num * num * num * num)); } internal static Vector3 Velocity(Vector3 forward, float force, float angle = 13f) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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) force = PresentationRules.Force(force); forward.y = 0f; if (force == 0f || float.IsNaN(forward.x) || float.IsNaN(forward.z) || float.IsInfinity(forward.x) || float.IsInfinity(forward.z) || ((Vector3)(ref forward)).sqrMagnitude < 0.0001f) { return Vector3.zero; } double num = (double)Angle(angle) * Math.PI / 180.0; float num2 = Speed(force); return ((Vector3)(ref forward)).normalized * (num2 * (float)Math.Cos(num)) + Vector3.up * (num2 * (float)Math.Sin(num)); } } internal static class ExitGeometry { internal const float Clearance = 0.05f; internal const float MaximumReach = 2.5f; internal const float FloorTolerance = 0.65f; internal static float FrontDistance(Vector3 anchor, Vector3 forward, Vector3 center, Vector3 extents, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) float val = Vector3.Dot(center - anchor, forward) + Math.Abs(forward.x) * extents.x + Math.Abs(forward.y) * extents.y + Math.Abs(forward.z) * extents.z; return Math.Max(0.5f, val) + radius + 0.15f; } internal static bool CapsuleAtFloor(Vector3 floor, Vector3 normal, float referenceY, Vector3 centerOffset, float height, float radius, out Vector3 pivot, out Vector3 bottom, out Vector3 top) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00d3: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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) pivot = (bottom = (top = Vector3.zero)); if (!Finite(floor) || !Finite(normal) || !Finite(centerOffset) || !Finite(referenceY) || !Finite(height) || !Finite(radius) || radius <= 0f || height < 2f * radius || normal.y < 0.75f || Math.Abs(floor.y - referenceY) > 0.65f) { return false; } Vector3 val = floor + Vector3.up * (height * 0.5f + 0.05f); pivot = val - centerOffset; float num = height * 0.5f - radius; bottom = val - Vector3.up * num; top = val + Vector3.up * num; return true; } internal static bool InReach(Vector3 anchor, Vector3 destination) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (!Finite(anchor) || !Finite(destination)) { return false; } float num = destination.x - anchor.x; float num2 = destination.z - anchor.z; return num * num + num2 * num2 <= 6.25f; } private static bool Finite(Vector3 v) { if (Finite(v.x) && Finite(v.y)) { return Finite(v.z); } return false; } private static bool Finite(float v) { if (!float.IsNaN(v)) { return !float.IsInfinity(v); } return false; } } public sealed class ExitMonitor : MonoBehaviour { private Player player; private RoyalFlushSeat seat; private Transform attachment; private Action release; private long token; private bool requested; private bool completion; private bool detached; private bool done; private bool resolved; private Vector3 planned; private float nextRetry; private float started; private int fixedFrames; private int lateFrames; private ExitOutcome outcome; private string contacts = "none"; private float contactTime = -1f; internal void Begin(Player p, RoyalFlushSeat s, long id, Vector3 offset, Action onRelease) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) player = p; seat = s; attachment = ((Chair)s).m_attachPoint; token = id; release = onRelease; planned = attachment.TransformPoint(offset); Trace("before-attach"); } internal void Attached() { Trace("after-attach"); } internal void RequestExit(bool successful) { if (done || resolved) { return; } if (requested) { completion = false; if (outcome != null) { outcome.Cancel(); } } else { requested = true; completion = successful; TryDetach(); } } private void TryDetach() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer) { Finish(commit: false); return; } if (!((Character)player).IsAttached() || (Object)(object)player.GetAttachPoint() != (Object)(object)attachment) { completion = false; ObserveDetach(); return; } if (!Object.op_Implicit((Object)(object)seat) || !ExitPlacement.RefreshCapturedOffset(player, seat)) { completion = false; Trace("exit-blocked-food-preserved"); ((Character)player).Message((MessageType)2, "Exit blocked. Food preserved. Clear the front; Ctrl/jump still cancel.", 0, (Sprite)null, false); nextRetry = Time.unscaledTime + 0.25f; return; } if (!ExitPlacement.ReadCapturedOffset(player, out var offset)) { completion = false; return; } planned = attachment.TransformPoint(offset); Trace("before-native-detach"); ((Character)player).AttachStop(); if (((Character)player).IsAttached() && (Object)(object)player.GetAttachPoint() == (Object)(object)attachment) { completion = false; nextRetry = Time.unscaledTime + 0.25f; } else { ObserveDetach(); } } internal bool BeforeNativeDetach(Player p) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (done || detached || !Object.op_Implicit((Object)(object)p) || (Object)(object)p != (Object)(object)player || (Object)(object)p != (Object)(object)Player.m_localPlayer || !((Character)p).IsAttached() || !Object.op_Implicit((Object)(object)attachment) || (Object)(object)p.GetAttachPoint() != (Object)(object)attachment) { return false; } if (!ExitPlacement.ReadCapturedOffset(p, out var offset)) { return false; } planned = attachment.TransformPoint(offset); if (!requested) { completion = false; requested = true; } return true; } internal void AfterNativeDetach(Player p) { if (!done && !detached && Object.op_Implicit((Object)(object)p) && !((Object)(object)p != (Object)(object)player) && !((Object)(object)p != (Object)(object)Player.m_localPlayer) && !((Character)p).IsAttached() && !Object.op_Implicit((Object)(object)p.GetAttachPoint()) && !((Character)p).IsDead() && !((Character)p).IsTeleporting()) { Trace("after-native-detach"); Physics.SyncTransforms(); Trace("after-dismount-sync"); ObserveDetach(); } } private void ObserveDetach() { if (!detached) { detached = true; started = Time.unscaledTime; outcome = new ExitOutcome(started, completion); fixedFrames = (lateFrames = 0); Trace("observation-start"); } } private void Update() { if (done) { return; } if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead() || ((Character)player).IsTeleporting()) { if (!resolved) { Finish(commit: false); } Cleanup(); return; } if (resolved && Time.unscaledTime - started >= 3f) { Trace("observation-end"); Cleanup(); return; } if (!detached && (!((Character)player).IsAttached() || (Object)(object)player.GetAttachPoint() != (Object)(object)attachment)) { completion = false; requested = true; Trace("native-cancellation-observed"); ObserveDetach(); } if (requested && !detached && Time.unscaledTime >= nextRetry) { if (Object.op_Implicit((Object)(object)seat) && ExitPlacement.TryFind(player, seat, out var _)) { TryDetach(); } nextRetry = Time.unscaledTime + 0.25f; } if (detached && !resolved) { Sample(fixedSample: false); } } private void FixedUpdate() { if (!done && Object.op_Implicit((Object)(object)player) && detached) { fixedFrames++; if (fixedFrames == 1 || fixedFrames == 2 || fixedFrames == 4 || fixedFrames == 8 || fixedFrames == 16 || fixedFrames == 32 || fixedFrames == 64 || fixedFrames == 128) { Trace("fixed-" + fixedFrames); } if (!resolved && fixedFrames > 1) { Sample(fixedSample: true); } } } private void LateUpdate() { if (!done && Object.op_Implicit((Object)(object)player) && detached) { lateFrames++; if (lateFrames == 1 || lateFrames == 2 || lateFrames == 4 || lateFrames == 8 || lateFrames == 16 || lateFrames == 32 || lateFrames == 64 || lateFrames == 128) { Trace("late-" + lateFrames); } } } private void Sample(bool fixedSample) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)seat) || !seat.CompletionAuthorized()) { outcome.Cancel(); } Rigidbody component = ((Component)player).GetComponent<Rigidbody>(); bool attached = ((Character)player).IsAttached() || Object.op_Implicit((Object)(object)player.GetAttachPoint()); string detail; bool flag = ExitPlacement.StandingClear(player, out detail); bool flag2 = Object.op_Implicit((Object)(object)component) && component.useGravity && Vector3.Distance(((Component)player).transform.position, planned) < 0.2f && Vector3.Distance(component.position, ((Component)player).transform.position) < 0.1f && ExitPlacement.ColliderAligned(player); switch (outcome.Sample(Time.unscaledTime, !((Character)player).IsDead() && !((Character)player).IsTeleporting(), attached, flag && flag2, fixedSample)) { case ExitOutcome.Result.Commit: Finish(commit: true); break; case ExitOutcome.Result.Preserve: Finish(commit: false); break; } } private void OnCollisionStay(Collision collision) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!done && Object.op_Implicit((Object)(object)player)) { StringBuilder stringBuilder = new StringBuilder(); ContactPoint[] array = collision.contacts; for (int i = 0; i < array.Length && i < 4; i++) { stringBuilder.Append(Object.op_Implicit((Object)(object)((ContactPoint)(ref array[i])).otherCollider) ? ((Object)((ContactPoint)(ref array[i])).otherCollider).name : "null").Append(':').Append(V(((ContactPoint)(ref array[i])).normal)) .Append(" sep=") .Append(((ContactPoint)(ref array[i])).separation.ToString("F3", CultureInfo.InvariantCulture)) .Append(';'); } contacts = stringBuilder.ToString(); contactTime = Time.unscaledTime; } } private void Trace(string stage) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_015b: 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_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)player)) { Rigidbody component = ((Component)player).GetComponent<Rigidbody>(); CapsuleCollider collider = ((Character)player).GetCollider(); string detail; bool flag = ExitPlacement.StandingClear(player, out detail); Vector3 v = (Object.op_Implicit((Object)(object)attachment) ? attachment.InverseTransformPoint(((Component)player).transform.position) : Vector3.zero); ExitPlacement.ReadCapturedOffset(player, out var offset); ManualLogSource log = Plugin.Log; object[] array = new object[46] { "RRExit token=", token, " stage=", stage, " t=", Time.unscaledTime.ToString("F3", CultureInfo.InvariantCulture), " plan=", V(planned), " transform=", V(((Component)player).transform.position), " local=", V(v), " capturedOffset=", V(offset), " attach=", Object.op_Implicit((Object)(object)attachment) ? V(attachment.position) : "missing", " forward=", V(((Component)player).transform.forward), " body=", Object.op_Implicit((Object)(object)component) ? V(component.position) : "missing", " velocity=", Object.op_Implicit((Object)(object)component) ? V(component.linearVelocity) : "missing", " gravity=", Object.op_Implicit((Object)(object)component) && component.useGravity, " bodyRotation=", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; object obj; if (!Object.op_Implicit((Object)(object)component)) { obj = "missing"; } else { Quaternion rotation = component.rotation; obj = V(((Quaternion)(ref rotation)).eulerAngles); } array[25] = obj; array[26] = " interpolation="; array[27] = (Object.op_Implicit((Object)(object)component) ? ((object)component.interpolation).ToString() : "missing"); array[28] = " autoSync="; array[29] = Physics.autoSyncTransforms; array[30] = " attached="; array[31] = ((Character)player).IsAttached(); array[32] = " samePoint="; array[33] = (Object)(object)player.GetAttachPoint() == (Object)(object)attachment; array[34] = " sitting="; array[35] = ((Character)player).IsSitting(); array[36] = " colliderCenter="; object obj2; if (!Object.op_Implicit((Object)(object)collider)) { obj2 = "missing"; } else { Bounds bounds = ((Collider)collider).bounds; obj2 = V(((Bounds)(ref bounds)).center); } array[37] = obj2; array[38] = " standingClear="; array[39] = flag; array[40] = " overlaps="; array[41] = detail; array[42] = " contacts="; array[43] = contacts; array[44] = " contactAge="; array[45] = ((contactTime < 0f) ? "none" : (Time.unscaledTime - contactTime).ToString("F3", CultureInfo.InvariantCulture)); log.LogInfo((object)string.Concat(array)); } } private static string V(Vector3 v) { return string.Format(CultureInfo.InvariantCulture, "({0:F3},{1:F3},{2:F3})", v.x, v.y, v.z); } private void Finish(bool commit) { //IL_00a4: 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) if (done || resolved) { return; } resolved = true; Trace(commit ? "verified-exit-commit" : "exit-food-preserved"); try { if (commit) { int count = player.GetFoods().Count; Plugin.ClearLocalFood(player); if (count <= 0 || player.GetFoods().Count != 0 || !Object.op_Implicit((Object)(object)seat) || !seat.CompletionCommitted(token)) { return; } try { float force = SafeEjection.TryLaunch(player, ((Chair)seat).m_attachPoint.forward); if (PresentationRules.DangerousLaunch(force)) { seat.NotifyLaunchScream(token, ((Character)player).GetZDOID(), force); } return; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Launch or scream notification failed; verified food/dismount not retried: " + ex)); return; } } if (Object.op_Implicit((Object)(object)seat)) { seat.AbortCompletion(token); } if (Object.op_Implicit((Object)(object)player)) { ((Character)player).Message((MessageType)2, "Interaction cancelled or exit unverified. Food preserved.", 0, (Sprite)null, false); } } catch (Exception ex2) { Plugin.Log.LogError((object)("Food completion failed; no automatic retry: " + ex2)); } finally { if (!detached) { Cleanup(); } } } private void Cleanup() { if (!done) { done = true; if (release != null) { release(); } Object.Destroy((Object)(object)this); } } private void OnDestroy() { if (!done) { done = true; if (release != null) { release(); } } } } internal sealed class ExitOutcome { internal enum Result { Wait, Commit, Preserve } private readonly double started; private bool authorized; private bool finished; private int consecutive; internal ExitOutcome(double now, bool completion) { started = now; authorized = completion; } internal void Cancel() { authorized = false; } internal Result Sample(double now, bool valid, bool attached, bool clear, bool fixedSample) { if (finished) { return Result.Wait; } if (!valid || double.IsNaN(now) || double.IsInfinity(now) || now < started || now - started > 3.0) { finished = true; return Result.Preserve; } if (attached || !clear) { consecutive = 0; } else if (fixedSample) { consecutive++; } if (!attached && clear && consecutive >= 3 && now - started >= 0.15) { finished = true; if (!authorized) { return Result.Preserve; } return Result.Commit; } return Result.Wait; } } internal static class ExitPlacement { private static readonly FieldInfo CapturedOffset = typeof(Player).GetField("m_detachOffset", BindingFlags.Instance | BindingFlags.NonPublic); internal static bool ApiAvailable { get { if (CapturedOffset != null && !CapturedOffset.IsStatic) { return CapturedOffset.FieldType == typeof(Vector3); } return false; } } internal static bool TryFind(Player player, RoyalFlushSeat seat, out Vector3 offset) { //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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: 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_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_021f: 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_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: 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_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0411: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) offset = Vector3.zero; if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)seat) || !Object.op_Implicit((Object)(object)((Chair)seat).m_attachPoint) || !ApiAvailable) { return false; } CapsuleCollider collider = ((Character)player).GetCollider(); if (!Object.op_Implicit((Object)(object)collider) || collider.direction != 1 || Vector3.Dot(((Component)collider).transform.up, Vector3.up) < 0.99f || Vector3.Dot(((Chair)seat).m_attachPoint.up, Vector3.up) < 0.99f) { return false; } Vector3 lossyScale = ((Component)collider).transform.lossyScale; float num = collider.radius * Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.z)); float height = Mathf.Max(collider.height * Mathf.Abs(lossyScale.y), num * 2f); Vector3 val = ((Component)collider).transform.TransformPoint(collider.center) - ((Component)player).transform.position; Vector3 centerOffset = ((Chair)seat).m_attachPoint.rotation * Quaternion.Inverse(((Component)player).transform.rotation) * val; Vector3 val2 = Vector3.ProjectOnPlane(((Chair)seat).m_attachPoint.forward, Vector3.up); Vector3 normalized = ((Vector3)(ref val2)).normalized; if (((Vector3)(ref normalized)).sqrMagnitude < 0.99f) { return false; } Vector3 val3 = Vector3.Cross(Vector3.up, normalized); Vector3 position = ((Chair)seat).m_attachPoint.position; float num2 = 0.5f + num + 0.15f; Collider[] componentsInChildren = ((Component)seat).GetComponentsInChildren<Collider>(); foreach (Collider val4 in componentsInChildren) { if (val4.enabled && !val4.isTrigger) { Bounds bounds = val4.bounds; num2 = Mathf.Max(num2, ExitGeometry.FrontDistance(position, normalized, ((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents, num)); } } float[] array = new float[3] { 0f, 0.45f, -0.45f }; Vector3 val5 = default(Vector3); for (int j = 0; j < 2; j++) { float[] array2 = array; foreach (float num3 in array2) { Vector3 destination = position + normalized * (num2 + (float)j * 0.3f) + val3 * num3; if (!ExitGeometry.InReach(position, destination)) { continue; } ((Vector3)(ref val5))..ctor(destination.x, ((Component)seat).transform.position.y + 0.6f, destination.z); RaycastHit[] array3 = Physics.RaycastAll(val5, Vector3.down, 1.25f, -5, (QueryTriggerInteraction)1); Array.Sort(array3, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit val6 = default(RaycastHit); RaycastHit[] array4 = array3; for (int num4 = 0; num4 < array4.Length; num4++) { RaycastHit val7 = array4[num4]; if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val7)).collider) && !((Component)((RaycastHit)(ref val7)).collider).transform.IsChildOf(((Component)player).transform)) { val6 = val7; break; } } if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref val6)).collider) || ((Component)((RaycastHit)(ref val6)).collider).transform.IsChildOf(((Component)seat).transform) || Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val6)).collider).GetComponentInParent<Character>()) || Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val6)).collider).GetComponentInParent<ItemDrop>()) || Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val6)).collider).GetComponentInParent<Chair>()) || Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val6)).collider).GetComponentInParent<Container>()) || Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val6)).collider).GetComponentInParent<CraftingStation>()) || (Object.op_Implicit((Object)(object)((RaycastHit)(ref val6)).rigidbody) && !((RaycastHit)(ref val6)).rigidbody.isKinematic) || !ExitGeometry.CapsuleAtFloor(((RaycastHit)(ref val6)).point, ((RaycastHit)(ref val6)).normal, ((Component)seat).transform.position.y, centerOffset, height, num, out var pivot, out var bottom, out var top) || !ExitGeometry.InReach(position, pivot)) { continue; } bool flag = false; Collider[] array5 = Physics.OverlapCapsule(bottom, top, num + 0.02f, -5, (QueryTriggerInteraction)1); foreach (Collider val8 in array5) { if (Object.op_Implicit((Object)(object)val8) && !((Component)val8).transform.IsChildOf(((Component)player).transform)) { flag = true; break; } } if (!flag) { offset = ((Chair)seat).m_attachPoint.InverseTransformPoint(pivot); return true; } } } return false; } internal static bool RefreshCapturedOffset(Player player, RoyalFlushSeat seat) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || !((Character)player).IsAttached() || (Object)(object)player.GetAttachPoint() != (Object)(object)((Chair)seat).m_attachPoint) { return false; } if (!TryFind(player, seat, out var offset)) { return false; } CapturedOffset.SetValue(player, offset); return true; } internal static bool ReadCapturedOffset(Player player, out Vector3 offset) { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) offset = Vector3.zero; if (!Object.op_Implicit((Object)(object)player) || !ApiAvailable) { return false; } offset = (Vector3)CapturedOffset.GetValue(player); return true; } internal static bool ColliderAligned(Player player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) CapsuleCollider val = (Object.op_Implicit((Object)(object)player) ? ((Character)player).GetCollider() : null); if (Object.op_Implicit((Object)(object)val) && ((Collider)val).enabled) { Bounds bounds = ((Collider)val).bounds; return Vector3.Distance(((Bounds)(ref bounds)).center, ((Component)val).transform.TransformPoint(val.center)) < 0.1f; } return false; } internal static bool StandingClear(Player player, out string detail) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) detail = "none"; CapsuleCollider val = (Object.op_Implicit((Object)(object)player) ? ((Character)player).GetCollider() : null); if (!Object.op_Implicit((Object)(object)val) || !((Collider)val).enabled || val.direction != 1) { detail = "invalid-capsule"; return false; } Vector3 lossyScale = ((Component)val).transform.lossyScale; float num = val.radius * Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.z)); float num2 = Mathf.Max(val.height * Mathf.Abs(lossyScale.y), num * 2f); Vector3 val2 = ((Component)val).transform.TransformPoint(val.center); Vector3 val3 = ((Component)val).transform.up * (num2 * 0.5f - num); bool flag = true; Collider[] array = Physics.OverlapCapsule(val2 - val3, val2 + val3, num, -5, (QueryTriggerInteraction)1); Vector3 val5 = default(Vector3); float num3 = default(float); foreach (Collider val4 in array) { if (Object.op_Implicit((Object)(object)val4) && !((Component)val4).transform.IsChildOf(((Component)player).transform) && Physics.ComputePenetration((Collider)(object)val, ((Component)val).transform.position, ((Component)val).transform.rotation, val4, ((Component)val4).transform.position, ((Component)val4).transform.rotation, ref val5, ref num3) && !(num3 <= 0.015f)) { flag = false; if (detail.Length < 700) { object obj = detail; detail = string.Concat(obj, ";", ((Object)val4).name, "#", ((Object)val4).GetInstanceID(), " depth=", num3.ToString("F3", CultureInfo.InvariantCulture)); } } } Vector3 val6 = val2 - Vector3.up * (num2 * 0.5f); bool flag2 = false; RaycastHit[] array2 = Physics.RaycastAll(val6 + Vector3.up * 0.1f, Vector3.down, 0.25f, -5, (QueryTriggerInteraction)1); for (int j = 0; j < array2.Length; j++) { RaycastHit val7 = array2[j]; if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val7)).collider) && !((Component)((RaycastHit)(ref val7)).collider).transform.IsChildOf(((Component)player).transform) && !(((RaycastHit)(ref val7)).normal.y < 0.75f) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val7)).collider).GetComponentInParent<Character>()) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val7)).collider).GetComponentInParent<Chair>()) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val7)).collider).GetComponentInParent<ItemDrop>()) && (!Object.op_Implicit((Object)(object)((RaycastHit)(ref val7)).rigidbody) || ((RaycastHit)(ref val7)).rigidbody.isKinematic)) { flag2 = true; break; } } if (!flag2) { detail += ";unsupported"; } if (flag) { return flag2; } return false; } } internal static class FartRecording { internal const int Rate = 44100; internal const int Frames = 266736; internal const int LeadingSilentFrames = 0; internal static float[] Create() { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("RamRoyalFlush.JustinFart"); if (stream == null || stream.Length != 1066944) { throw new InvalidDataException("Embedded Justin fart PCM missing or invalid."); } using BinaryReader binaryReader = new BinaryReader(stream); float[] array = new float[266736]; for (int i = 0; i < array.Length; i++) { array[i] = binaryReader.ReadSingle(); if (float.IsNaN(array[i]) || float.IsInfinity(array[i]) || Math.Abs(array[i]) > 0.921f) { throw new InvalidDataException("Embedded recorded PCM exceeds approved headroom."); } } return array; } } internal static class FatalImpactPresentation { private static AudioClip clip; private static Material blood; private static Texture2D texture; private static SoftReference<Shader> shaderRef; private static bool shaderHeld; private static readonly List<GameObject> live = new List<GameObject>(); internal static void Play(Vector3 point) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated()) { return; } GameObject val = new GameObject("RamRoyalFlush_fatal_impact"); val.transform.position = point; live.Add(val); val.AddComponent<FatalImpactLifetime>(); LaunchScream.StopForFatalImpact(); AudioSource val2 = null; ParticleSystem val3 = null; try { val2 = Sound(val); } catch (Exception ex) { Plugin.Log.LogError((object)("Fatal splat unavailable; gore remains independent: " + ex)); } try { val3 = Blood(val); } catch (Exception ex2) { Plugin.Log.LogError((object)("Fatal gore unavailable; splat remains independent: " + ex2)); } try { if (Object.op_Implicit((Object)(object)val2)) { val2.Play(); } } catch (Exception ex3) { Plugin.Log.LogError((object)("Fatal splat playback failed: " + ex3)); } try { if (Object.op_Implicit((Object)(object)val3)) { val3.Play(); val3.Emit(110); val.AddComponent<FatalImpactSpawnCheck>().Initialize(val3); } } catch (Exception ex4) { Plugin.Log.LogError((object)("Fatal gore emission failed: " + ex4)); } Object.Destroy((Object)(object)val, 3f); Plugin.Log.LogInfo((object)string.Concat("RRFatalImpact sound/gore triggered together at=", point, "; standalone lifetime3s; no gain; client-local.")); } private static AudioSource Sound(GameObject root) { AudioMixer val = (Object.op_Implicit((Object)(object)AudioMan.instance) ? AudioMan.instance.m_masterMixer : null); AudioMixerGroup val2 = null; if (Object.op_Implicit((Object)(object)val)) { AudioMixerGroup[] array = val.FindMatchingGroups(""); foreach (AudioMixerGroup val3 in array) { if (Object.op_Implicit((Object)(object)val3) && string.Equals(((Object)val3).name, "SFX", StringComparison.OrdinalIgnoreCase)) { val2 = val3; break; } } } if (!Object.op_Implicit((Object)(object)val2)) { throw new InvalidOperationException("SFX mixer unavailable; no unrouted fallback."); } if (!Object.op_Implicit((Object)(object)clip)) { float[] array2 = FatalImpactRecording.Create(); AudioClip val4 = AudioClip.Create("RamRoyalFlush_blood_splats_1", array2.Length, 1, 44100, false); try { MethodInfo method = typeof(AudioClip).GetMethod("SetData", new Type[2] { typeof(float[]), typeof(int) }); if (method == null || !(bool)method.Invoke(val4, new object[2] { array2, 0 })) { throw new InvalidOperationException("Fatal PCM upload failed."); } clip = val4; } catch { Object.Destroy((Object)(object)val4); throw; } } AudioSource val5 = root.AddComponent<AudioSource>(); val5.playOnAwake = false; val5.loop = false; val5.clip = clip; val5.outputAudioMixerGroup = val2; val5.volume = 1f; val5.pitch = 1f; val5.dopplerLevel = 0f; val5.spatialBlend = 0f; return val5; } private static ParticleSystem Blood(GameObject root) { //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0366: 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_038b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)blood)) { AssetID val = default(AssetID); if (!AssetID.TryParse("0f5a6e59b3eb19f3ba0b7e7955445af0", ref val)) { throw new InvalidOperationException("Blood shader ID invalid."); } if (!shaderHeld) { shaderRef = new SoftReference<Shader>(val); shaderHeld = true; shaderRef.Load(); } Shader asset = shaderRef.Asset; if (!Object.op_Implicit((Object)(object)asset) || ((Object)asset).name != "Particles/Standard Unlit2" || !asset.isSupported) { throw new InvalidOperationException("Verified particle shader unavailable."); } blood = new Material(asset); blood.SetOverrideTag("RenderType", "Transparent"); blood.DisableKeyword("_ALPHATEST_ON"); blood.DisableKeyword("_ALPHAPREMULTIPLY_ON"); blood.DisableKeyword("_ALPHAMODULATE_ON"); blood.EnableKeyword("_ALPHABLEND_ON"); if (blood.HasProperty("_Mode")) { blood.SetFloat("_Mode", 2f); } if (blood.HasProperty("_SrcBlend")) { blood.SetInt("_SrcBlend", 5); } if (blood.HasProperty("_DstBlend")) { blood.SetInt("_DstBlend", 10); } if (blood.HasProperty("_BlendOp")) { blood.SetInt("_BlendOp", 0); } if (blood.HasProperty("_ZWrite")) { blood.SetInt("_ZWrite", 0); } if (blood.HasProperty("_Color")) { blood.SetColor("_Color", Color.white); } blood.renderQueue = 3000; texture = new Texture2D(32, 32, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[1024]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = Mathf.Sqrt(Mathf.Pow(((float)j - 15.5f) / 15.5f, 2f) + Mathf.Pow(((float)i - 15.5f) / 15.5f, 2f)); ref Color reference = ref array[i * 32 + j]; reference = new Color(1f, 1f, 1f, Mathf.Pow(Mathf.Max(0f, 1f - num), 2f)); } } texture.SetPixels(array); texture.Apply(); blood.mainTexture = (Texture)(object)texture; } ParticleSystem val2 = root.AddComponent<ParticleSystem>(); val2.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = val2.main; ((MainModule)(ref main)).playOnAwake = false; ((MainModule)(ref main)).loop = false; ((MainModule)(ref main)).duration = 0.1f; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.4f, 1.2f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.1f, 0.45f); ((MainModule)(ref main)).startSpeed = new MinMaxCurve(3f, 9f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.75f, 0.015f, 0.01f, 0.95f)); ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0.8f); ((MainModule)(ref main)).maxParticles = 110; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.3f; EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).enabled = false; ((Renderer)((Component)val2).GetComponent<ParticleSystemRenderer>()).sharedMaterial = blood; return val2; } internal static void Released(GameObject go) { live.Remove(go); } internal static void Dispose() { FatalImpactReceipt.Dispose(); GameObject[] array = live.ToArray(); foreach (GameObject val in array) { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } } live.Clear(); if (Object.op_Implicit((Object)(object)clip)) { Object.Destroy((Object)(object)clip); } if (Object.op_Implicit((Object)(object)blood)) { Object.Destroy((Object)(object)blood); } if (Object.op_Implicit((Object)(object)texture)) { Object.Destroy((Object)(object)texture); } if (shaderHeld) { shaderRef.Release(); shaderHeld = false; } } } public sealed class FatalImpactLifetime : MonoBehaviour { private void OnDestroy() { FatalImpactPresentation.Released(((Component)this).gameObject); } } public sealed class FatalImpactSpawnCheck : MonoBehaviour { private ParticleSystem particles; private int frames; internal void Initialize(ParticleSystem value) { particles = value; } private void LateUpdate() { if (!Object.op_Implicit((Object)(object)particles) || particles.particleCount != 0 || ++frames >= 4) { ParticleSystemRenderer val = (Object.op_Implicit((Object)(object)particles) ? ((Component)particles).GetComponent<ParticleSystemRenderer>() : null); if (Object.op_Implicit((Object)(object)particles) && particles.particleCount > 0 && Object.op_Implicit((Object)(object)val) && ((Renderer)val).enabled && Object.op_Implicit((Object)(object)((Renderer)val).sharedMaterial) && Object.op_Implicit((Object)(object)((Renderer)val).sharedMaterial.shader) && ((Renderer)val).sharedMaterial.shader.isSupported) { Plugin.Log.LogInfo((object)("RRFatalImpact gore renderer ready; particles=" + particles.particleCount)); } else { Plugin.Log.LogWarning((object)"RRFatalImpact gore runtime verification FAILED."); } Object.Destroy((Object)(object)this); } } } public sealed class FatalImpactReceipt : MonoBehaviour { private static readonly List<FatalImpactReceipt> pending = new List<FatalImpactReceipt>(); private Player player; private Action callback; private Vector3 point; private float before; private float expires; private bool requestOpen; private bool armed; private bool finished; private string cause = "collision"; internal static FatalImpactReceipt Begin(Player p, Vector3 point, float before) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) FatalImpactReceipt[] array = pending.ToArray(); foreach (FatalImpactReceipt fatalImpactReceipt in array) { if (Object.op_Implicit((Object)(object)fatalImpactReceipt) && (Object)(object)fatalImpactReceipt.player == (Object)(object)p && !fatalImpactReceipt.finished) { if (fatalImpactReceipt.requestOpen || (fatalImpactReceipt.armed && ((Character)p).GetHealth() <= 0f)) { return null; } fatalImpactReceipt.Close(); } } GameObject val = new GameObject("RamRoyalFlush_fatal_receipt"); FatalImpactReceipt fatalImpactReceipt2 = val.AddComponent<FatalImpactReceipt>(); fatalImpactReceipt2.player = p; fatalImpactReceipt2.point = point; fatalImpactReceipt2.before = before; fatalImpactReceipt2.requestOpen = true; fatalImpactReceipt2.expires = Time.unscaledTime + 3f; fatalImpactReceipt2.callback = fatalImpactReceipt2.OnNativeDeath; ((Character)p).m_onDeath = (Action)Delegate.Combine(((Character)p).m_onDeath, fatalImpactReceipt2.callback); pending.Add(fatalImpactReceipt2); return fatalImpactReceipt2; } internal static FatalImpactReceipt BeginNativeFall(Player p, Vector3 point, float before) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) FatalImpactReceipt fatalImpactReceipt = Begin(p, point, before); if (Object.op_Implicit((Object)(object)fatalImpactReceipt)) { fatalImpactReceipt.cause = "native fall"; } return fatalImpactReceipt; } internal void EndRequest() { if (!finished) { requestOpen = false; try { armed = Object.op_Implicit((Object)(object)player) && before > 0f && ((Character)player).GetHealth() <= 0f; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Fatal impact confirmation unavailable: " + ex)); } if (!armed) { Close(); } } } private void OnNativeDeath() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (finished) { return; } try { if (Object.op_Implicit((Object)(object)player) && ((Character)player).IsDead() && before > 0f && (requestOpen || armed)) { finished = true; Plugin.Log.LogInfo((object)("RRFatalImpact confirmed by native death callback; cause=" + cause + "; position=" + point)); try { FatalImpactPresentation.Play(point); } catch (Exception ex) { Plugin.Log.LogError((object)("Confirmed fatal presentation failed: " + ex)); } Close(); } } catch (Exception ex2) { Plugin.Log.LogError((object)("Fatal death observer failed without changing death: " + ex2)); Close(); } } private void Update() { if (!finished) { if (!requestOpen && Object.op_Implicit((Object)(object)player) && ((Character)player).GetHealth() > 0f) { Close(); } else if (!Object.op_Implicit((Object)(object)player) || Time.unscaledTime >= expires) { Plugin.Log.LogWarning((object)"Fatal impact not confirmed by native death; no speculative splat/gore."); Close(); } } } private void Close() { finished = true; if (!object.ReferenceEquals(player, null) && callback != null) { Player obj = player; ((Character)obj).m_onDeath = (Action)Delegate.Remove(((Character)obj).m_onDeath, callback); callback = null; } pending.Remove(this); Object.Destroy((Object)(object)((Component)this).gameObject); } private void OnDestroy() { if (!object.ReferenceEquals(player, null) && callback != null) { Player obj = player; ((Character)obj).m_onDeath = (Action)Delegate.Remove(((Character)obj).m_onDeath, callback); callback = null; } pending.Remove(this); } internal static void Dispose() { FatalImpactReceipt[] array = pending.ToArray(); foreach (FatalImpactReceipt fatalImpactReceipt in array) { if (Object.op_Implicit((Object)(object)fatalImpactReceipt)) { fatalImpactReceipt.Close(); } } pending.Clear(); } } internal static class FatalImpactRecording { internal const int Frames = 40421; internal const int Rate = 44100; internal static float[] Create() { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("RamRoyalFlush.FatalImpact"); if (stream == null || stream.Length != 161684) { throw new InvalidDataException("Fatal splat PCM missing/invalid."); } using BinaryReader binaryReader = new BinaryReader(stream); float[] array = new float[40421]; for (int i = 0; i < array.Length; i++) { array[i] = binaryReader.ReadSingle(); if (float.IsNaN(array[i]) || float.IsInfinity(array[i]) || Math.Abs(array[i]) > 1f) { throw new InvalidDataException("Fatal splat PCM invalid/clipped."); } } return array; } } internal static class FixedGameplay { internal const int WoodCost = 10; internal const int FineWoodCost = 2; internal const float InteractionDurationSeconds = 4f; internal const bool CompletionMessagesEnabled = true; internal const string CompletionMessages = "You feel strangely lighter. Odin looks away in disgust.|You have made an offering to the All-Farter.|The gods have witnessed your shame.|Valhalla trembles. Your bowels are empty.|A great burden has been lifted.|You feel empty inside."; } internal sealed class InteractionSession { internal enum Phase { Idle, Pending, Seated, Completed, Cancelled } internal enum Result { None, Cancel, Complete } private double requested; private double started; private double lastTick; private double duration; internal Phase State { get; private set; } internal long Token { get; private set; } internal bool WaitingForSeating { get; private set; } internal bool Request(long token, double now) { if (token == 0 || !Finite(now) || State == Phase.Pending || State == Phase.Seated) { return false; } Token = token; requested = (lastTick = now); State = Phase.Pending; return true; } internal bool Grant(long token, double seconds, double now) { if (State != Phase.Pending || token != Token || !Finite(now) || now < requested || now - requested >= 5.0 || !Finite(seconds) || seconds < 1.0 || seconds > 15.0) { return false; } started = (lastTick = now); duration = Math.Min(seconds, 0.5); State = Phase.Seated; return true; } internal Result Tick(double now, bool validPlayer, bool stillSeated, bool leaseHeld, bool nativeSitting = true) { if (State != Phase.Pending && State != Phase.Seated) { return Result.None; } if (!Finite(now) || now < lastTick || !validPlayer || (State == Phase.Pending && now - requested >= 5.0) || (State == Phase.Seated && (!stillSeated || now - lastTick > 2.5))) { Cancel(); return Result.Cancel; } lastTick = now; if (State == Phase.Seated && now - started >= duration) { if (!leaseHeld) { Cancel(); return Result.Cancel; } if (now - started > 3.0 || (!nativeSitting && now - started >= 3.0)) { Cancel(); return Result.Cancel; } WaitingForSeating = !nativeSitting; if (WaitingForSeating) { return Result.None; } State = Phase.Completed; return Result.Complete; } return Result.None; } internal void Cancel() { WaitingForSeating = false; State = Phase.Cancelled; } private static bool Finite(double n) { if (!double.IsNaN(n)) { return !double.IsInfinity(n); } return false; } } internal static class LeaseRules { internal static bool Available(long now, long occupant, long expires) { if (occupant != 0) { return expires <= now; } return true; } internal static bool Held(long now, long uid, long token, long occupant, long savedToken, long expires) { if (uid != 0 && token != 0 && uid == occupant && token == savedToken) { return expires > now; } return false; } } public sealed class LaunchCollisionMonitor : MonoBehaviour { private static LaunchCollisionMonitor current; private Player player; private Rigidbody body; private LaunchCollisionScope scope; private Vector3 origin; private float began; private int frames; private int contacts; private bool ended; private bool modeWarning; private readonly LaunchImpactRules impacts = new LaunchImpactRules(); private Vector3 preStepVelocity; private Vector3 impactPoint; private Vector3 impactNormal; private Vector3 impactRelative; private string impactObject; private bool landingLogged; private bool flightDamageEnabled; private bool damageSuppressionLogged; private bool endingOnLanding; private bool flightStarted; private bool victoryConsumed; private readonly LaunchLandingSequence landingSequence = new LaunchLandingSequence(); private double supportAt = double.NegativeInfinity; private Vector3 supportNormal; private Vector3 supportPoint; private Collider supportCollider; private Rigidbody supportBody; internal void RecordLaunch() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)body)) { preStepVelocity = body.linearVelocity; flightStarted = true; } } internal static bool IsActiveFor(Player p) { if (Object.op_Implicit((Object)(object)current) && (Object)(object)current.player == (Object)(object)p) { return current.CanImpact(); } return false; } internal static LaunchCollisionMonitor DamageContextFor(Player p) { if (!IsActiveFor(p)) { return null; } return current; } internal static void InterruptForJump(Player p) { if (IsActiveFor(p)) { current.End("deliberate new jump"); } } internal bool ProtectsNativeFallInCall(Player p) { if ((Object)(object)p == (Object)(object)player && !flightDamageEnabled) { if (ended) { return endingOnLanding; } return true; } return false; } internal static LaunchCollisionMonitor Begin(Player p, Rigidbody rb, bool damageEnabled = true) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) EndActive("new launch"); LaunchCollisionMonitor launchCollisionMonitor = ((Component)p).gameObject.AddComponent<LaunchCollisionMonitor>(); launchCollisionMonitor.player = p; launchCollisionMonitor.body = rb; launchCollisionMonitor.origin = rb.position; launchCollisionMonitor.began = Time.unscaledTime; launchCollisionMonitor.flightDamageEnabled = damageEnabled; try { launchCollisionMonitor.scope = new LaunchCollisionScope(() => rb.collisionDetectionMode, delegate(CollisionDetectionMode mode) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)rb)) { rb.collisionDetectionMode = mode; } }); current = launchCollisionMonitor; Plugin.Log.LogInfo((object)string.Concat("RRLaunch CCD begin: original=", launchCollisionMonitor.scope.Original, "; active=", rb.collisionDetectionMode, "; kinematic=", rb.isKinematic, "; detectCollisions=", rb.detectCollisions, "; fixedDt=", Time.fixedDeltaTime, "; flightDamage=", damageEnabled)); return launchCollisionMonitor; } catch { launchCollisionMonitor.End("setup failure"); throw; } } internal static void EndActive(string reason) { if (Object.op_Implicit((Object)(object)current)) { current.End(reason); } } internal void End(string reason, bool destroy = true) { //IL_0073: 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_011a: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) if (ended) { if (reason != "landed") { endingOnLanding = false; } return; } endingOnLanding = reason == "landed"; impacts.Stop(); try { if (scope != null) { scope.Dispose(); } } finally { ended = true; if (Object.op_Implicit((Object)(object)body) && scope != null && body.collisionDetectionMode != scope.Original) { Plugin.Log.LogError((object)string.Concat("RRLaunch original collision mode restoration FAILED: expected=", scope.Original, "; actual=", body.collisionDetectionMode)); } if (Object.op_Implicit((Object)(object)body)) { ManualLogSource log = Plugin.Log; object[] array = new object[10] { "RRLaunch end: reason=", reason, "; original=", (scope != null) ? ((object)scope.Original).ToString() : "unavailable", "; restored=", body.collisionDetectionMode, "; horizontalDistance=", null, null, null }; Vector3 val = Vector3.ProjectOnPlane(body.position - origin, Vector3.up); array[7] = ((Vector3)(ref val)).magnitude.ToString("F3"); array[8] = "; elapsed="; array[9] = (Time.unscaledTime - began).ToString("F3"); log.LogInfo((object)string.Concat(array)); } if ((Object)(object)current == (Object)(object)this) { current = null; } if (destroy) { Object.Destroy((Object)(object)this); } } } private void FixedUpdate() { //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Invalid comparison between Unknown and I4 //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0381: 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_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) if (ended) { return; } ZNetView val = (Object.op_Implicit((Object)(object)player) ? ((Component)player).GetComponent<ZNetView>() : null); if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)val) || !val.IsValid() || !val.IsOwner() || ((Character)player).IsDead() || ((Character)player).IsTeleporting() || ((Character)player).IsAttached() || ((Character)player).IsSwimming() || body.isKinematic || !body.useGravity || !body.detectCollisions || !flightStarted) { End("interruption/death/ownership"); return; } bool nativeGrounded = Time.unscaledTime - began > 0.15f && ((Character)player).IsOnGround(); FlushImpact(nativeGrounded); if (ended) { return; } if (!Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead()) {