Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of Flatline IL2CPP v1.0.2
Mods/Flatline-IL2Cpp.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using Flatline; using HarmonyLib; using Il2CppFishNet; using Il2CppFishNet.Managing; using Il2CppFishNet.Managing.Object; using Il2CppFishNet.Object; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.Audio; using Il2CppScheduleOne.AvatarFramework; using Il2CppScheduleOne.Building.Doors; using Il2CppScheduleOne.Combat; using Il2CppScheduleOne.Core.Audio; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.Core.Weather; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Dialogue; using Il2CppScheduleOne.Doors; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.Equipping; using Il2CppScheduleOne.FX; using Il2CppScheduleOne.GameTime; using Il2CppScheduleOne.Interaction; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Map; using Il2CppScheduleOne.Money; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.NPCs.CharacterClasses; using Il2CppScheduleOne.ObjectScripts; using Il2CppScheduleOne.Persistence; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.PlayerScripts.Health; using Il2CppScheduleOne.Product; using Il2CppScheduleOne.Property; using Il2CppScheduleOne.Temperature; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.MainMenu; using Il2CppScheduleOne.UI.Phone; using Il2CppScheduleOne.UI.Phone.Messages; using Il2CppScheduleOne.VoiceOver; using Il2CppScheduleOne.Weather; using Il2CppSystem; using Il2CppSystem.Collections; using Il2CppSystem.Collections.Generic; using Il2CppTMPro; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Support; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(global::Flatline.Flatline), "Flatline", "1.0.2", "XOWithSauce", "https://github.com/XOWithSauce/schedule-flatline")] [assembly: MelonColor] [assembly: MelonOptionalDependencies(new string[] { "FishNet.Runtime", "Il2Cpp" })] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)] [assembly: VerifyLoaderVersion("0.7.2", true)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("XOWithSauce")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright XOWithSauce 2026 Source MIT")] [assembly: AssemblyDescription("Schedule I Flatline Mod")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("Flatline")] [assembly: AssemblyTitle("Flatline-IL2Cpp")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/XOWithSauce/schedule-flatline")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Flatline { public static class BedRotSimulator { public static bool isBedrotting = false; public static bool isInitialized = false; public static bool isEvaluatingBedState = false; public static readonly float energyRegenPerMinute = FlatlinePlayer.DefaultEnergyConsumption + 0.003f; public static readonly float healthRegenPerMinuteTarget = FlatlinePlayer.DefaultHealthRegeneration * 5f; public static readonly float healthRegenT = FlatlinePlayer.SystematicHomeostasisSpeed * 10f; public static IEnumerator InitBedRotModule() { yield return (object)new WaitUntil(Func<bool>.op_Implicit((Func<bool>)(() => NetworkManager._instances != null && NetworkManager._instances.Count > 0))); NetworkManager instance = NetworkManager._instances[0]; yield return (object)new WaitUntil(Func<bool>.op_Implicit((Func<bool>)(() => instance.Initialized))); PrepareBedRotInteractable(); DebugModule.Log("Bed prefab changed succesfully", "InitBedRotModule"); isInitialized = true; } public static void ResetBedRotModule() { isBedrotting = false; isEvaluatingBedState = false; } public static void PrepareBedRotInteractable() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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) PrefabObjects spawnablePrefabs = Object.FindObjectOfType<NetworkManager>(true).SpawnablePrefabs; for (int i = 0; i < spawnablePrefabs.GetObjectCount(); i++) { NetworkObject val = spawnablePrefabs.GetObject(true, i); if (((val != null) ? ((Object)((Component)val).gameObject).name : null).Contains("SingleBed")) { ((Component)val).GetComponent<Bed>(); GameObject val2 = new GameObject("BedRotIntObj"); val2.transform.parent = ((Component)val).transform; ((Object)val2.gameObject).name = "BedRotIntObj"; val2.transform.position = new Vector3(0f, 0.264f, 0.8f); BoxCollider val3 = val2.AddComponent<BoxCollider>(); ((Collider)val3).isTrigger = true; InteractableObject val4 = val2.AddComponent<InteractableObject>(); val4.message = "Rot in the bed"; val4.SetInteractableState((EInteractableState)0); val2.SetActive(true); ((Collider)val3).enabled = true; ((Behaviour)val4).enabled = true; } } } public static void BedRotInteracted(InteractableObject intObj, Bed bed) { if (!isBedrotting) { isBedrotting = true; Flatline.coros.Add(MelonCoroutines.Start(BedRotSimulatorRunner(intObj, bed))); } } public static void BedRotInteractableHovered(InteractableObject intObj, Bed bed) { if (!isEvaluatingBedState) { isEvaluatingBedState = true; Flatline.coros.Add(MelonCoroutines.Start(EvaluateBedState(intObj, bed))); } } public static IEnumerator EvaluateBedState(InteractableObject intObj, Bed bed) { if (Player.Local.IsSkating) { intObj.SetInteractableState((EInteractableState)1); intObj.message = "Can't bedrot while skateboarding"; } else if ((Object)(object)bed.AssignedEmployee != (Object)null) { intObj.SetInteractableState((EInteractableState)1); intObj.message = "Can't bedrot in an employee's bed"; } else if (NetworkSingleton<TimeManager>.Instance.IsCurrentTimeWithinRange(359, 700)) { intObj.SetInteractableState((EInteractableState)1); intObj.message = "Can't bedrot at late night"; } else { intObj.SetInteractableState((EInteractableState)0); intObj.message = "Rot in the bed"; } yield return Flatline.Wait1; if (Flatline.registered) { isEvaluatingBedState = false; } } public static IEnumerator BedRotSimulatorRunner(InteractableObject intObj, Bed bed) { ((Behaviour)intObj).enabled = false; ((Behaviour)bed.intObj).enabled = false; PlayerSingleton<PlayerCamera>.Instance.SetCanLook(false); PlayerSingleton<PlayerMovement>.Instance.CanMove = false; ((Behaviour)PlayerSingleton<PlayerMovement>.Instance).enabled = false; ((Collider)Player.Local.CapCol).enabled = false; Transform playerTrRoot = ((Component)Player.Local).transform.root; playerTrRoot.parent = ((Component)bed).transform; Vector3 originalStandPoint = playerTrRoot.localPosition; Quaternion originalRotation = playerTrRoot.localRotation; Vector3 targetLocalPosition = new Vector3(0.009f, 0.24f, 0.012f); Quaternion targetRotation = Quaternion.Euler(270f, 0f, 0f); float animationDuration = 3f; float elapsed = 0f; while (elapsed < animationDuration && Flatline.registered) { float num = elapsed / animationDuration; playerTrRoot.localPosition = Vector3.Lerp(originalStandPoint, targetLocalPosition, num); playerTrRoot.localRotation = Quaternion.Slerp(originalRotation, targetRotation, num); elapsed += Time.deltaTime; yield return null; } playerTrRoot.localPosition = targetLocalPosition; playerTrRoot.localRotation = targetRotation; PlayerSingleton<PlayerCamera>.Instance.SetCanLook(true); float maxY = 20f; while (Flatline.registered) { yield return Flatline.WaitFrame; if (Quaternion.Angle(playerTrRoot.localRotation, targetRotation) > maxY) { playerTrRoot.localRotation = Quaternion.Slerp(playerTrRoot.localRotation, targetRotation, 0.05f); } if ((!PlayerSingleton<Phone>.Instance.IsOpen && (Input.GetKey((KeyCode)32) || Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)97) || Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)100))) || FlatlinePlayer.isPassedOut || FlatlinePlayer.isQueuedForDeath) { break; } } PlayerSingleton<PlayerCamera>.Instance.SetCanLook(false); elapsed = 0f; Quaternion currentRotation = playerTrRoot.localRotation; while (elapsed < animationDuration && Flatline.registered) { float num2 = elapsed / animationDuration; playerTrRoot.localPosition = Vector3.Lerp(targetLocalPosition, originalStandPoint, num2); playerTrRoot.localRotation = Quaternion.Slerp(currentRotation, originalRotation, num2); elapsed += Time.deltaTime; yield return null; } playerTrRoot.localPosition = originalStandPoint; playerTrRoot.localRotation = originalRotation; playerTrRoot.parent = null; ((Collider)Player.Local.CapCol).enabled = true; PlayerSingleton<PlayerCamera>.Instance.SetCanLook(true); ((Behaviour)PlayerSingleton<PlayerMovement>.Instance).enabled = true; PlayerSingleton<PlayerMovement>.Instance.CanMove = true; ((Behaviour)intObj).enabled = true; ((Behaviour)bed.intObj).enabled = true; isBedrotting = false; AfterBedrotEnd(); } public static void MinPassBedrotting() { if (!Flatline.registered || Flatline.isSaving || !isBedrotting || FlatlinePlayer.isQueuedForDeath || Flatline.haltExecution) { return; } if (Flatline.loadedPlayerData.State.Energy < 1f) { FlatlinePlayer.SetEnergy(Mathf.Clamp01(Flatline.loadedPlayerData.State.Energy + energyRegenPerMinute)); } if (Flatline.loadedPlayerData.State.healthData.CurrentHP < Flatline.loadedPlayerData.State.healthData.MaxHP) { if (FlatlinePlayer.HealthRegenPerMinute < healthRegenPerMinuteTarget) { FlatlinePlayer.HealthRegenPerMinute = Mathf.Lerp(FlatlinePlayer.HealthRegenPerMinute, healthRegenPerMinuteTarget, healthRegenT); } if (Random.Range(0f, 1f) > 0.9f) { Player.Local.Health.CurrentHealth = Mathf.Clamp(Player.Local.Health.CurrentHealth + 1f, 0f, Flatline.loadedPlayerData.State.healthData.MaxHP); if (Flatline.loadedPlayerData.State.Energy < 1f) { Mathf.Clamp01(Flatline.loadedPlayerData.State.Energy + energyRegenPerMinute * 8f); } } } if (Flatline.loadedPlayerData.State.Hunger < 1f && Flatline.loadedPlayerData.State.Hunger > 0.1f && FlatlinePlayer.FoodConsumptionPerMinute > FlatlinePlayer.DefaultFoodConsumption / 2f) { FlatlinePlayer.FoodConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.FoodConsumptionPerMinute, FlatlinePlayer.DefaultFoodConsumption / 2f, FlatlinePlayer.SystematicHomeostasisSpeed * 1.55f); } if (Flatline.loadedPlayerData.State.Thirst < 1f && Flatline.loadedPlayerData.State.Thirst > 0.1f && FlatlinePlayer.ThirstConsumptionPerMinute > FlatlinePlayer.DefaultThirstConsumption / 2f) { FlatlinePlayer.ThirstConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.ThirstConsumptionPerMinute, FlatlinePlayer.DefaultThirstConsumption / 2f, FlatlinePlayer.SystematicHomeostasisSpeed * 1.55f); } } public static void AfterBedrotEnd() { if (FlatlinePlayer.HealthRegenPerMinute > FlatlinePlayer.DefaultHealthRegeneration) { FlatlinePlayer.HealthRegenPerMinute = Mathf.Lerp(FlatlinePlayer.HealthRegenPerMinute, FlatlinePlayer.DefaultHealthRegeneration, 0.5f); } if (FlatlinePlayer.FoodConsumptionPerMinute < FlatlinePlayer.DefaultFoodConsumption) { FlatlinePlayer.FoodConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.FoodConsumptionPerMinute, FlatlinePlayer.DefaultFoodConsumption, 0.5f); } if (FlatlinePlayer.ThirstConsumptionPerMinute < FlatlinePlayer.DefaultThirstConsumption) { FlatlinePlayer.ThirstConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.ThirstConsumptionPerMinute, FlatlinePlayer.DefaultThirstConsumption, 0.5f); } } } [HarmonyPatch(typeof(Bed), "Awake")] public static class Bed_Awake_Patch { [HarmonyPrefix] public static bool Prefix(Bed __instance) { Transform val = ((Component)__instance).transform.Find("BedRotIntObj"); if ((Object)(object)val == (Object)null) { return true; } InteractableObject bedRotInt = ((Component)val).gameObject.GetComponent<InteractableObject>(); bedRotInt.onInteractStart.AddListener(UnityAction.op_Implicit((Action)OnBedRotInteraction)); bedRotInt.onHovered.AddListener(UnityAction.op_Implicit((Action)OnBedRotHovered)); return true; void OnBedRotHovered() { if (Flatline.registered) { BedRotSimulator.BedRotInteractableHovered(bedRotInt, __instance); } } void OnBedRotInteraction() { if (Flatline.registered) { BedRotSimulator.BedRotInteracted(bedRotInt, __instance); } } } } public static class DepressionSimulator { public static GameObject disabledOverlay; public static void InitiateDepressionSimulatorModule() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00ef: Unknown result type (might be due to invalid IL or missing references) disabledOverlay = new GameObject("DisableOverlay"); disabledOverlay.transform.SetParent(((Component)PlayerSingleton<MessagesApp>.Instance).transform, false); RectTransform obj = disabledOverlay.AddComponent<RectTransform>(); obj.sizeDelta = new Vector2(800f, 1200f); ((Transform)obj).localScale = Vector3.one; ((Transform)obj).localPosition = Vector3.zero; ((Transform)obj).localRotation = Quaternion.identity; ((Graphic)disabledOverlay.AddComponent<Image>()).color = new Color(0.1f, 0.1f, 0.1f, 0.93f); GameObject val = new GameObject("Text"); val.transform.SetParent(disabledOverlay.transform); val.transform.localScale = Vector3.one; val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.AddComponent<RectTransform>().sizeDelta = new Vector2(600f, 1200f); TextMeshProUGUI obj2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)obj2).text = "You are too depressed right now"; ((TMP_Text)obj2).alignment = (TextAlignmentOptions)514; ((TMP_Text)obj2).fontSize = 52f; disabledOverlay.SetActive(false); DebugModule.Log("Initiated depression simulator", "InitiateDepressionSimulatorModule"); } public static void ResetDepressionSimulatorModule() { disabledOverlay = null; } public static bool ShouldSkip() { if (Player.PlayerList.Count > 1 && !Player.Local.Health.IsAlive) { return true; } if (NetworkSingleton<TimeManager>.Instance.CurrentTime < 659 && NetworkSingleton<TimeManager>.Instance.CurrentTime > 400) { return true; } if (Flatline.isSaving) { return true; } if (Flatline.haltExecution) { return true; } return false; } public static IEnumerator DepressionBlandWorld(Depression depression) { while (true) { yield return Flatline.Wait10; if (!Flatline.registered || !depression.data.Active || (FlatlinePlayer.isQueuedForDeath && Flatline.currentConfig.PermanentDeath)) { break; } if (ShouldSkip() || depression.isTemporaryCurePresent) { continue; } float num = Mathf.Lerp(0.95f, 0.75f, depression.data.Severity / 0.3f); if (Random.Range(0f, 1f) < num) { continue; } float duration = Mathf.Lerp(Depression.minBlandEffectDuration, Depression.maxBlandEffectDuration, depression.data.Severity / 0.3f); float current = 0f; Singleton<PostProcessingManager>.Instance.SaturationController.AddOverride(-56f, 25, "Depression"); do { yield return Flatline.Wait1; if (!Flatline.registered) { yield break; } current += 1f; } while (!(current >= duration) && depression.data.Active && !depression.isTemporaryCurePresent); Singleton<PostProcessingManager>.Instance.SaturationController.RemoveOverride("Depression"); } } public static IEnumerator DepressionMessagerDisabler(Depression depression) { while (true) { yield return Flatline.Wait10; if (!Flatline.registered || !depression.data.Active || (FlatlinePlayer.isQueuedForDeath && Flatline.currentConfig.PermanentDeath)) { break; } if (ShouldSkip() || depression.isTemporaryCurePresent) { continue; } float num = Mathf.Lerp(0.95f, 0.75f, depression.data.Severity / 0.3f); if (Random.Range(0f, 1f) < num) { continue; } float duration = Mathf.Lerp(Depression.minDisablerEffectDuration, Depression.maxDisablerEffectDuration, depression.data.Severity / 0.3f); float current = 0f; disabledOverlay.SetActive(true); do { yield return Flatline.Wait1; if (!Flatline.registered) { yield break; } current += 1f; } while (!(current >= duration) && depression.data.Active && !depression.isTemporaryCurePresent); disabledOverlay.SetActive(false); } } public static IEnumerator DepressionDoorDisabler(Depression depression) { while (true) { yield return Flatline.Wait10; if (!Flatline.registered || !depression.data.Active || (FlatlinePlayer.isQueuedForDeath && Flatline.currentConfig.PermanentDeath)) { break; } if (ShouldSkip() || (int)Player.Local.CrimeData.CurrentPursuitLevel != 0 || depression.isTemporaryCurePresent) { continue; } float num = Mathf.Clamp01(((float)depression.data.Progression / 5f + depression.data.Severity / 0.3f) / 2f); float num2 = Mathf.Lerp(0.95f, 0.75f, num); if (Random.Range(0f, 1f) < num2 || !((Object)(object)Player.Local.CurrentProperty != (Object)null) || !Player.Local.CurrentProperty.IsOwned) { continue; } if (PropertyTemperatureController.propertyDoors.TryGetValue(Player.Local.CurrentProperty.propertyCode, out var doors)) { PropertyDoorController[] array = doors; foreach (PropertyDoorController val in array) { if (!((DoorController)val).IsOpen) { ((DoorController)val).PlayerAccess = (EDoorAccess)1; ((DoorController)val).noAccessErrorMessage = "You are too depressed right now"; } } float duration = Mathf.Lerp(Depression.minDisablerEffectDuration, Depression.maxDisablerEffectDuration, num); float current = 0f; do { yield return Flatline.Wait1; if (!Flatline.registered) { yield break; } current += 1f; } while (!(current >= duration) && depression.data.Active && !depression.isTemporaryCurePresent); array = doors; foreach (PropertyDoorController val2 in array) { if ((int)((DoorController)val2).PlayerAccess == 1 && ((DoorController)val2).noAccessErrorMessage == "You are too depressed right now") { ((DoorController)val2).PlayerAccess = (EDoorAccess)0; ((DoorController)val2).noAccessErrorMessage = ""; } } } doors = null; } } } public static class AudioLoader { public static AudioClip ToAudioClip(byte[] fileBytes, string name = "wav") { int num = 0; int num2 = 16000; ushort num3 = 1; int dataSize = fileBytes.Length; bool flag = true; byte[] array = new byte[4]; Array.Copy(fileBytes, 0, array, 0, 4); if (!Encoding.ASCII.GetString(array).Equals("RIFF")) { flag = false; } if (flag) { int num4 = BitConverter.ToInt32(fileBytes, 16); BitConverter.ToUInt16(fileBytes, 20); num3 = BitConverter.ToUInt16(fileBytes, 22); num2 = BitConverter.ToInt32(fileBytes, 24); BitConverter.ToUInt16(fileBytes, 34); num = 20 + num4 + 4; dataSize = BitConverter.ToInt32(fileBytes, num); } float[] array2 = Convert16BitByteArrayToAudioClipData(fileBytes, num, dataSize); AudioClip obj = AudioClip.Create(name, array2.Length / num3, (int)num3, num2, false); obj.SetData(Il2CppStructArray<float>.op_Implicit(array2), 0); return obj; } private static float[] Convert16BitByteArrayToAudioClipData(byte[] source, int headerOffset, int dataSize) { int num = dataSize; if (headerOffset != 0) { num = BitConverter.ToInt32(source, headerOffset); headerOffset += 4; } int num2 = 2; int num3 = num / num2; float[] array = new float[num3]; short num4 = short.MaxValue; int num5 = 0; for (int i = 0; i < num3; i++) { num5 = i * num2 + headerOffset; array[i] = (float)BitConverter.ToInt16(source, num5) / (float)num4; } return array; } } [Serializable] public class FlatlinePlayerData { public FlatlinePlayerState State = new FlatlinePlayerState(); public List<DiseaseData> DiseaseData = new List<DiseaseData>(); public FlatlinePlayerData() { } public FlatlinePlayerData(FlatlinePlayerData original) { State = new FlatlinePlayerState(original.State); DiseaseData = new List<DiseaseData>(); foreach (DiseaseData diseaseDatum in original.DiseaseData) { DiseaseData.Add(new DiseaseData(diseaseDatum)); } } } [Serializable] public class FlatlinePlayerState { public Dictionary<string, ConsumptionData> consumptionDatas = new Dictionary<string, ConsumptionData>(); public HealthData healthData = new HealthData(); public float Thirst = 1f; public float Hunger = 1f; public float Energy = 1f; public float Temperature = 1f; public FlatlinePlayerState() { } public FlatlinePlayerState(FlatlinePlayerState original) { Thirst = original.Thirst; Hunger = original.Hunger; Energy = original.Energy; Temperature = original.Temperature; foreach (KeyValuePair<string, ConsumptionData> consumptionData in original.consumptionDatas) { consumptionDatas.Add(consumptionData.Key, new ConsumptionData(consumptionData.Value)); } healthData = new HealthData(original.healthData); } } [Serializable] public class ConsumptionData { public float overtimeLungDamage; public float overtimeLiverDamage; public float currentAmountInSystem; public ConsumptionData() { } public ConsumptionData(ConsumptionData original) { overtimeLungDamage = original.overtimeLungDamage; overtimeLiverDamage = original.overtimeLiverDamage; currentAmountInSystem = original.currentAmountInSystem; } } [Serializable] public class HealthData { public float MaxHP = 100f; public float CurrentHP = 100f; public float MoveSpeedScale = 1f; public float Predisposition; public float Gluttony; public int TimesSmoked; public bool IsLegBoneBroken; public int daysSinceFlu; public HealthData() { } public HealthData(HealthData original) { MaxHP = original.MaxHP; CurrentHP = original.CurrentHP; MoveSpeedScale = original.MoveSpeedScale; Predisposition = original.Predisposition; Gluttony = original.Gluttony; TimesSmoked = original.TimesSmoked; IsLegBoneBroken = original.IsLegBoneBroken; daysSinceFlu = original.daysSinceFlu; } } [Serializable] public class DiseaseData { public string DiseaseID = ""; public bool Active; public int MinsSinceDiseaseStart; public int Progression = 1; public float Severity; public float HealState; [JsonProperty(/*Could not decode attribute arguments.*/)] public Dictionary<string, float> DiseaseStates; public DiseaseData() { } public DiseaseData(DiseaseData original) { DiseaseID = original.DiseaseID; Active = original.Active; MinsSinceDiseaseStart = original.MinsSinceDiseaseStart; Progression = original.Progression; Severity = original.Severity; HealState = original.HealState; if (original.DiseaseStates != null) { DiseaseStates = new Dictionary<string, float>(original.DiseaseStates); } } } public class FlatlineModConfig { public bool PermanentDeath = true; public bool DrugSideEffects = true; public bool PropertyTemperatureChanges = true; public bool WorldTemperatureChanges = true; public bool FahrenheitTemp; public bool DiseasesEnabled = true; public bool BleedingEnabled = true; public bool BoneBreakEnabled = true; public bool CancerEnabled = true; public bool DepressionEnabled = true; public bool FeverEnabled = true; public bool WaterRequired = true; public bool FoodRequired = true; public bool EnergyRequired = true; public bool TemperatureRequired = true; public float WaterConsumption = 0.00087958f; public float FoodConsumption = 0.0015f; public float EnergyConsumption = 0.0007f; public float TemperatureConsumption = 0.00022f; } public static class ConfigLoader { private static readonly string BASE_USERDATA_NAME = "XO_WithSauce-Flatline"; private static readonly string TS_PACKAGE_NAME = "XO_WithSauce-Flatline_"; private static readonly string packagePathUserData = Path.Combine(MelonEnvironment.UserDataDirectory, TS_PACKAGE_NAME + "IL2CPP", BASE_USERDATA_NAME); private static readonly string manualPathUserData = Path.Combine(MelonEnvironment.UserDataDirectory, BASE_USERDATA_NAME); private static readonly string pathPlayerData = Path.Combine(packagePathUserData, "PlayerData"); private static readonly string pathModImageResources = Path.Combine(packagePathUserData, "ModResources", "Images"); private static readonly string pathModAudioResources = Path.Combine(packagePathUserData, "ModResources", "Audio"); private static readonly string pathManualPlayerData = Path.Combine(manualPathUserData, "PlayerData"); private static readonly string pathManualModImageResources = Path.Combine(manualPathUserData, "ModResources", "Images"); private static readonly string pathManualModAudioResources = Path.Combine(manualPathUserData, "ModResources", "Audio"); public static readonly List<string> imageResources = new List<string> { "bleed", "bonebreak", "cancer", "depression", "energy", "fever", "meat", "temperature", "water" }; public static readonly List<string> audioResources = new List<string> { "malecough", "malesneeze", "femalecough", "femalesneeze", "bonebreak", "flatline", "singleheartbeat" }; public static object playerDataLock = new object(); public static Dictionary<string, Sprite> loadedSprites = new Dictionary<string, Sprite>(); public static Dictionary<string, AudioClip> loadedAudios = new Dictionary<string, AudioClip>(); public static FlatlinePlayerData LoadPlayerData() { string organisationName = Singleton<LoadManager>.Instance.ActiveSaveInfo.OrganisationName; int saveSlotNumber = Singleton<LoadManager>.Instance.ActiveSaveInfo.SaveSlotNumber; string path = $"{saveSlotNumber}_{SanitizeAndFormatName(organisationName)}"; string text = ""; if (Directory.Exists(pathPlayerData)) { text = pathPlayerData; } else { if (!Directory.Exists(pathManualPlayerData)) { MelonLogger.Error("Failed to locate Flatline PlayerData from the UserData folder!"); return null; } text = pathManualPlayerData; } FlatlinePlayerData flatlinePlayerData; if (File.Exists(Path.Combine(text, path))) { try { flatlinePlayerData = JsonConvert.DeserializeObject<FlatlinePlayerData>(File.ReadAllText(Path.Combine(text, path))); } catch (Exception ex) { flatlinePlayerData = new FlatlinePlayerData(); MelonLogger.Warning("Failed to read flatline player data: " + ex); } } else { flatlinePlayerData = new FlatlinePlayerData(); flatlinePlayerData.State.healthData.Predisposition = Random.Range(0.0005f, 0.02f); Save(flatlinePlayerData); } return flatlinePlayerData; } public static void Save(FlatlinePlayerData playerData) { lock (playerDataLock) { FlatlinePlayerData flatlinePlayerData = new FlatlinePlayerData(playerData); try { string organisationName = Singleton<LoadManager>.Instance.ActiveSaveInfo.OrganisationName; int saveSlotNumber = Singleton<LoadManager>.Instance.ActiveSaveInfo.SaveSlotNumber; string path = $"{saveSlotNumber}_{SanitizeAndFormatName(organisationName)}"; string text = ""; text = (Directory.Exists(pathPlayerData) ? pathPlayerData : ((!Directory.Exists(pathManualPlayerData)) ? pathPlayerData : pathManualPlayerData)); string path2 = Path.Combine(text, path); string contents = JsonConvert.SerializeObject((object)flatlinePlayerData, (Formatting)1); Directory.CreateDirectory(Path.GetDirectoryName(path2)); File.WriteAllText(path2, contents); } catch (Exception ex) { MelonLogger.Warning("Failed to save Flatline player data: " + ex); } } } public static void RemoveSaveAssociatedData(string orgName, int slotNum) { string path = $"{slotNum}_{SanitizeAndFormatName(orgName)}"; string text = ""; if (Directory.Exists(pathPlayerData)) { text = pathPlayerData; } else { if (!Directory.Exists(pathManualPlayerData)) { MelonLogger.Error("Failed to locate Flatline PlayerData from the UserData folder!"); return; } text = pathManualPlayerData; } if (File.Exists(Path.Combine(text, path))) { try { File.Delete(Path.Combine(text, path)); } catch (Exception ex) { MelonLogger.Warning("Failed to remove save associated flatline player data: " + ex); } } } public static void LoadModResources() { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) string text = ""; string text2 = ""; if (Directory.Exists(packagePathUserData)) { text = pathModImageResources; text2 = pathModAudioResources; } else { if (!Directory.Exists(manualPathUserData)) { MelonLogger.Error("Failed to locate Flatline mod resources from UserData!"); return; } text = pathManualModImageResources; text2 = pathManualModAudioResources; } if (Directory.Exists(text)) { foreach (string imageResource in imageResources) { string path = Path.Combine(text, imageResource + ".png"); if (File.Exists(path)) { byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x34); ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)); ((Object)val).name = imageResource; ((Texture)val).anisoLevel = 1; val.Apply(); Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f); ((Object)val2).hideFlags = (HideFlags)(((Object)val2).hideFlags | 0x34); loadedSprites.Add(imageResource, val2); } else { MelonLogger.Error("Flatline mod expected to find file '" + imageResource + "' but it's missing!"); } } } else { MelonLogger.Error("Flatline mod expected to find directory '" + text + "' but it's missing!"); } if (Directory.Exists(text2)) { foreach (string audioResource in audioResources) { string path2 = Path.Combine(text2, audioResource + ".wav"); if (File.Exists(path2)) { AudioClip val3 = AudioLoader.ToAudioClip(File.ReadAllBytes(path2)); ((Object)val3).hideFlags = (HideFlags)(((Object)val3).hideFlags | 0x34); loadedAudios.Add(audioResource, val3); } else { MelonLogger.Error("Flatline mod expected to find file '" + audioResource + "' but it's missing!"); } } return; } MelonLogger.Error("Flatline mod expected to find directory '" + text2 + "' but it's missing!"); } public static string SanitizeAndFormatName(string orgName) { string text = orgName; if (text != null) { text = text.Replace(" ", "_").ToLower(); text = text.Replace(",", ""); text = text.Replace(".", ""); text = text.Replace("<", ""); text = text.Replace(">", ""); text = text.Replace(":", ""); text = text.Replace("\"", ""); text = text.Replace("/", ""); text = text.Replace("\\", ""); text = text.Replace("|", ""); text = text.Replace("?", ""); text = text.Replace("*", ""); } return text + ".json"; } } public class Bleeding : Disease { public static readonly float passiveDiseaseHealingMax = 0.0055f; public static readonly float passiveDiseaseHealingMin = 0.0001f; public float MaximumMaxHPReduction = 100f; private float maxHPReduced; public Bleeding(DiseaseData data) { base.data = data; base.data.DiseaseID = "bleed"; base.minsRequiredForProgression = 240; onDiseaseStarted = BleedingStarted; MaximumMaxHPReduction = Mathf.Lerp(40f, 150f, base.data.Severity / 0.3f); if (base.data.DiseaseStates == null) { base.data.DiseaseStates = new Dictionary<string, float>(); } if (base.data.DiseaseStates.ContainsKey("maxHPReduced")) { maxHPReduced = base.data.DiseaseStates["maxHPReduced"]; } else { base.data.DiseaseStates.Add("maxHPReduced", 0f); } } private void BleedingStarted() { PlayerDiseaseDamage.isBleedingStemmed = false; if (!PlayerDiseaseDamage.bleedPressureIntObj.activeSelf) { PlayerDiseaseDamage.bleedPressureIntObj.SetActive(true); } Flatline.coros.Add(MelonCoroutines.Start(RunBleedDamage())); } private IEnumerator RunBleedDamage() { while (true) { float num; if (data.Progression >= 3) { yield return Flatline.Wait05; num = 0.5f; } else { yield return Flatline.Wait1; num = 1f; } if (!Flatline.registered || !data.Active || data.Progression >= 5) { break; } if (Flatline.haltExecution || Flatline.isSaving || FlatlinePlayer.isPassedOut || NetworkSingleton<TimeManager>.Instance.IsSleepInProgress) { continue; } if (FlatlinePlayer.isQueuedForDeath || maxHPReduced >= MaximumMaxHPReduction) { break; } if (data.HealState > 0.9f || PlayerDiseaseDamage.isBleedingStemmed) { continue; } float num2 = (float)base.minsRequiredForProgression * (1f + data.Severity); float num3 = num2 * 5f / 1440f; float num4 = num2 * 1f / 1440f; float num5 = num3 - num4; float num6 = MaximumMaxHPReduction / 1440f * num5 / num; float num7 = Mathf.Lerp(Mathf.Approximately(data.HealState, 0f) ? 0.015f : data.HealState, 0.001f, (float)data.Progression / 5f - 0.2f); num6 = Mathf.Clamp01(Mathf.Lerp(num6, 0f, num7)) * (float)data.Progression; DebugModule.Log("Calc bleed reduction: " + num6, "RunBleedDamage"); if (Random.Range(0f, 1f) > 0.33f) { Player.Local.Health.PlayBloodMist(); } if (Flatline.loadedPlayerData.State.healthData.MaxHP - num6 < Flatline.loadedPlayerData.State.healthData.CurrentHP) { float num8 = Flatline.loadedPlayerData.State.healthData.CurrentHP - (Flatline.loadedPlayerData.State.healthData.MaxHP - num6); if (Player.Local.Health.CurrentHealth - num8 <= 0f) { FlatlineUIModule.causeOfDeath = "Bleeding"; } Player.Local.Health.TakeDamage(num8, Random.Range(0, 10) == 0, false); FlatlinePlayer.AppendDamageSource($"Bleeding damage (-{num8}HP)"); } else { DebugModule.Log("Bleed amount not smaller than current hp", "RunBleedDamage"); } maxHPReduced += num6; Flatline.loadedPlayerData.State.healthData.MaxHP = Mathf.Clamp(Flatline.loadedPlayerData.State.healthData.MaxHP - num6, 0f, 100f); } } public override void DiseaseEffect() { float num = data.MinsSinceDiseaseStart; if (!PlayerDiseaseDamage.bleedPressureIntObj.activeSelf) { PlayerDiseaseDamage.bleedPressureIntObj.SetActive(true); } if (PlayerDiseaseDamage.isBleedingStemmed) { num *= 0.33f; } if (Mathf.Round(num * (1f + data.Severity)) / (float)base.minsRequiredForProgression >= (float)data.Progression) { data.Progression++; } if (data.Progression >= 5 && maxHPReduced >= MaximumMaxHPReduction && !PlayerDiseaseDamage.isBleedingStemmed) { DebugModule.Log("Player died of bleeding", "DiseaseEffect"); FlatlineUIModule.causeOfDeath = "Bleeding"; Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.PrePlayerDied())); data.Active = false; return; } if (data.Progression >= 4 && Flatline.loadedPlayerData.State.Thirst > 0.15f) { Flatline.loadedPlayerData.State.Thirst -= 0.0015f; } data.HealState += Random.Range(passiveDiseaseHealingMin, passiveDiseaseHealingMax); if (maxHPReduced >= MaximumMaxHPReduction) { data.HealState += Random.Range(passiveDiseaseHealingMin * 3f, passiveDiseaseHealingMax * 3f); } float num2 = Mathf.Lerp(12f, 50f, Mathf.Clamp01(data.HealState)); float num3 = Mathf.Lerp(1f, 3f, Mathf.Clamp01((float)data.Progression / 5f)); if (PlayerDiseaseDamage.isBleedingStemmed) { data.HealState += passiveDiseaseHealingMax * num2; DebugModule.Log($"Stem heal: {data.HealState} +{passiveDiseaseHealingMax * num2}", "DiseaseEffect"); } else { data.HealState = Mathf.Clamp01(data.HealState - passiveDiseaseHealingMax * num3); DebugModule.Log($"No stem: {data.HealState} -{passiveDiseaseHealingMax * num3}", "DiseaseEffect"); } DebugModule.Log("Bleeding Max HP reduction total so far: " + maxHPReduced, "DiseaseEffect"); } public override void DiseaseHealed() { if (PlayerDiseaseDamage.bleedPressureIntObj.activeSelf) { PlayerDiseaseDamage.bleedPressureIntObj.SetActive(false); } PlayerDiseaseDamage.isBleedingStemmed = false; DebugModule.Log("Healed bleeding succesfully", "DiseaseHealed"); } public override void UpdateDiseaseData() { if (data.DiseaseStates == null) { data.DiseaseStates = new Dictionary<string, float>(); } if (data.DiseaseStates.ContainsKey("maxHPReduced")) { data.DiseaseStates["maxHPReduced"] = maxHPReduced; } else { data.DiseaseStates.Add("maxHPReduced", maxHPReduced); } } } public class BoneBreak : Disease { public static readonly float passiveDiseaseHealingMax = 0.001f; public static readonly float passiveDiseaseHealingMin = 0.0001f; public static readonly float healingReductionWhileSprinting = 0.008f; public static readonly float baseMoveSpeedReduction = 0.03f; public static readonly float minMoveSpeedScaleValue = 0.65f; private bool hasDisabledJump; public BoneBreak(DiseaseData data) { base.data = data; base.data.DiseaseID = "bonebreak"; base.minsRequiredForProgression = 4320; } public override void DiseaseEffect() { if (Mathf.Round((float)data.MinsSinceDiseaseStart * (1f + data.Severity)) / (float)base.minsRequiredForProgression >= (float)data.Progression) { data.Progression++; } if (data.Progression >= 5) { DebugModule.Log("Player died of a broken bone", "DiseaseEffect"); FlatlineUIModule.causeOfDeath = "Broken bone"; Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.PrePlayerDied())); data.Active = false; return; } data.HealState += Random.Range(passiveDiseaseHealingMin, passiveDiseaseHealingMax); if (PlayerSingleton<PlayerMovement>.Instance.IsSprinting) { data.HealState = Mathf.Clamp01(data.HealState - healingReductionWhileSprinting * (float)data.Progression); } if (BedRotSimulator.isBedrotting) { data.HealState += Random.Range(passiveDiseaseHealingMin, passiveDiseaseHealingMax); } if (data.Progression >= 1) { float num = Mathf.Lerp(minMoveSpeedScaleValue, 1f, data.HealState); if (Flatline.loadedPlayerData.State.healthData.MoveSpeedScale > num) { float num2 = Mathf.Lerp(baseMoveSpeedReduction * (float)data.Progression * (1f + data.Severity), 0f, data.HealState); float moveSpeedScale = Mathf.Clamp(Flatline.loadedPlayerData.State.healthData.MoveSpeedScale - num2, minMoveSpeedScaleValue, 1f); Flatline.loadedPlayerData.State.healthData.MoveSpeedScale = moveSpeedScale; } } if (data.Progression < 3 || !(data.HealState < 0.5f) || !Flatline.loadedPlayerData.State.healthData.IsLegBoneBroken) { return; } if (PlayerSingleton<PlayerMovement>.Instance.CanJump && !hasDisabledJump) { if (Random.Range(0f, 1f) > 0.95f) { PlayerSingleton<PlayerMovement>.Instance.CanJump = false; hasDisabledJump = true; } } else if (!PlayerSingleton<PlayerMovement>.Instance.CanJump && hasDisabledJump) { PlayerSingleton<PlayerMovement>.Instance.CanJump = true; hasDisabledJump = false; } } public override void DiseaseHealed() { Flatline.loadedPlayerData.State.healthData.IsLegBoneBroken = false; DebugModule.Log("Healed bone break succesfully", "DiseaseHealed"); } public override void UpdateDiseaseData() { } } public class Cancer : Disease { public static readonly float MaximumMaxHPReduction = 100f; public Cancer(DiseaseData data) { base.data = data; base.data.DiseaseID = "cancer"; base.minsRequiredForProgression = 10080; } public override void DiseaseEffect() { float num = Mathf.Round((float)data.MinsSinceDiseaseStart * (1f + data.Severity)); float num2 = (float)base.minsRequiredForProgression * (1f + data.Severity); if (num / (float)base.minsRequiredForProgression >= (float)data.Progression) { data.Progression++; } if (data.Progression >= 5) { DebugModule.Log("Player died of cancer", "DiseaseEffect"); FlatlineUIModule.causeOfDeath = "Cancer"; Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.PrePlayerDied())); data.Active = false; return; } if (data.Progression >= 3) { float num3 = num2 * 5f / 1440f; float num4 = num2 * 3f / 1440f; float num5 = num3 - num4; float num6 = MaximumMaxHPReduction / 1440f * num5 / 10f; DebugModule.Log("Cancer Max HP reduction: " + num6, "DiseaseEffect"); if (Flatline.loadedPlayerData.State.healthData.MaxHP - num6 < Flatline.loadedPlayerData.State.healthData.CurrentHP) { float num7 = Flatline.loadedPlayerData.State.healthData.CurrentHP - (Flatline.loadedPlayerData.State.healthData.MaxHP - num6); if (Player.Local.Health.CurrentHealth - num7 <= 0f) { FlatlineUIModule.causeOfDeath = "Cancer"; } Player.Local.Health.TakeDamage(num7, true, false); FlatlinePlayer.AppendDamageSource($"Cancer damage (-{num7}HP)"); } Flatline.loadedPlayerData.State.healthData.MaxHP = Mathf.Clamp(Flatline.loadedPlayerData.State.healthData.MaxHP - num6, 0f, 100f); } if (!FlatlinePlayer.flatlinePlayerAudio.isPlaying) { AudioClip val = null; val = ((Player.Local.Avatar.CurrentSettings.Gender > 0.5f) ? ((!(Random.Range(0f, 1f) > 0.5f)) ? ConfigLoader.loadedAudios["femalesneeze"] : ConfigLoader.loadedAudios["femalecough"]) : ((!(Random.Range(0f, 1f) > 0.5f)) ? ConfigLoader.loadedAudios["malesneeze"] : ConfigLoader.loadedAudios["malecough"])); if (data.Progression == 2 && Random.Range(0f, 1f) > 0.99f) { FlatlinePlayer.flatlinePlayerAudio.PlayOneShot(val); } else if (data.Progression >= 3 && Random.Range(0f, 1f) > 0.95f) { FlatlinePlayer.flatlinePlayerAudio.PlayOneShot(val); } } } public override void DiseaseHealed() { DebugModule.Log("Healed cancer succesfully", "DiseaseHealed"); } public override void UpdateDiseaseData() { } } public class Depression : Disease { public static readonly float passiveDiseaseHealingMax = 0.0025f; public static readonly float passiveDiseaseHealingMin = 0.0001f; public static readonly float baseEnergyConsumptionIncrease = 0.002f; public static readonly float baseFoodConsumptionIncrease = 0.0008f; public static readonly int maxTemporaryCureMins = 120; public static readonly float maxBlandEffectDuration = 180f; public static readonly float minBlandEffectDuration = 80f; public static readonly float maxDisablerEffectDuration = 120f; public static readonly float minDisablerEffectDuration = 50f; private static int minsSpentBedrotting = 0; public bool isTemporaryCurePresent; private int minsSinceTemporaryCureStarted; public static readonly List<string> temporaryDepressionCures = new List<string> { "weed", "shroom", "cocaine", "meth" }; public Depression(DiseaseData data) { base.data = data; base.data.DiseaseID = "depression"; base.minsRequiredForProgression = 4320; onDiseaseStarted = RunDepressionCoros; } private void RunDepressionCoros() { Flatline.coros.Add(MelonCoroutines.Start(DepressionSimulator.DepressionBlandWorld(this))); Flatline.coros.Add(MelonCoroutines.Start(DepressionSimulator.DepressionDoorDisabler(this))); Flatline.coros.Add(MelonCoroutines.Start(DepressionSimulator.DepressionMessagerDisabler(this))); } public override void DiseaseEffect() { if (Mathf.Round((float)data.MinsSinceDiseaseStart * (1f + data.Severity)) / (float)base.minsRequiredForProgression >= (float)data.Progression) { data.Progression++; } if (data.Progression >= 5) { DebugModule.Log("Player died of depression", "DiseaseEffect"); FlatlineUIModule.causeOfDeath = "Depression"; Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.PrePlayerDied())); data.Active = false; return; } if (BedRotSimulator.isBedrotting) { minsSpentBedrotting += 10; float num = Mathf.Lerp(0f, 1f, Mathf.Clamp01((float)minsSpentBedrotting / 1440f)); if (num > data.HealState) { data.HealState = num; } else { data.HealState += num / 10f; } } data.HealState += Random.Range(passiveDiseaseHealingMin, passiveDiseaseHealingMax); if (isTemporaryCurePresent) { minsSinceTemporaryCureStarted += 10; if (minsSinceTemporaryCureStarted >= maxTemporaryCureMins) { isTemporaryCurePresent = false; } } if (Flatline.loadedPlayerData.State.healthData.TimesSmoked > 0 && Flatline.loadedPlayerData.State.consumptionDatas.Count > 0) { Dictionary<string, ConsumptionData> dictionary = new Dictionary<string, ConsumptionData>(Flatline.loadedPlayerData.State.consumptionDatas); float num2 = 0f; int num3 = 0; foreach (KeyValuePair<string, ConsumptionData> item in dictionary) { if (temporaryDepressionCures.Contains(item.Key)) { num2 += item.Value.currentAmountInSystem; if (num2 > 0.15f && !isTemporaryCurePresent) { isTemporaryCurePresent = true; minsSinceTemporaryCureStarted = 0; } num3++; } } if (num3 > 0) { num2 = Mathf.Clamp01(num2 / (float)num3); float num4 = passiveDiseaseHealingMax * (1f + num2); float num5 = Random.Range(passiveDiseaseHealingMin * (1f + num2), num4); num5 = Mathf.Lerp(num5, num4, num2); data.HealState += Mathf.Clamp(num5, 0f, 0.01f); } } if (!BedRotSimulator.isBedrotting) { float num6 = Mathf.Lerp(3f, 5f, (float)data.Progression / 5f - 0.2f); float num7 = Mathf.Clamp(baseEnergyConsumptionIncrease * (float)data.Progression * (1f + data.Severity), 0f, 0.01f); float num8 = Mathf.Clamp(baseFoodConsumptionIncrease * (float)data.Progression * (1f + data.Severity), 0f, 0.0052f); FlatlinePlayer.EnergyConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.EnergyConsumptionPerMinute, FlatlinePlayer.EnergyConsumptionPerMinute + num7, MaximumSystematicPropertyChangePerTick * num6); FlatlinePlayer.FoodConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.FoodConsumptionPerMinute, FlatlinePlayer.FoodConsumptionPerMinute + num8, MaximumSystematicPropertyChangePerTick * num6); } } public override void DiseaseHealed() { if (FlatlinePlayer.FoodConsumptionPerMinute > FlatlinePlayer.DefaultFoodConsumption) { FlatlinePlayer.FoodConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.FoodConsumptionPerMinute, FlatlinePlayer.DefaultFoodConsumption, 0.5f); } if (FlatlinePlayer.EnergyConsumptionPerMinute > FlatlinePlayer.DefaultEnergyConsumption) { FlatlinePlayer.EnergyConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.EnergyConsumptionPerMinute, FlatlinePlayer.DefaultEnergyConsumption, 0.5f); } DebugModule.Log("Healed depression succesfully", "DiseaseHealed"); } public override void UpdateDiseaseData() { } } public class Fever : Disease { public static readonly float baseEnergyConsumptionIncrease = 7E-05f; public static readonly float baseTemperatureConsumptionIncrease = 0.00025f; public static readonly float baseThirstConsumptionIncrease = 0.00012f; public static readonly float passiveDiseaseHealingMax = 0.0055f; public static readonly float passiveDiseaseHealingMin = 0.0003f; public static readonly float MaximumMaxHPReduction = 33f; private int minsSinceLastFeverShiver; private int minsUntilNextFeverShiver = 120; public Fever(DiseaseData data) { base.data = data; base.data.DiseaseID = "fever"; base.minsRequiredForProgression = 1080; onDiseaseStarted = FeverStarted; } private void FeverStarted() { Player.Local.Avatar.Effects.SetSicklySkinColor(true); Player.Local.Avatar.EmotionManager.AddEmotionOverride("Concerned", "Sickly", 0f, 5); } public override void DiseaseEffect() { minsSinceLastFeverShiver += 10; DebugModule.Log("Mins until next fever jitter " + (minsUntilNextFeverShiver - minsSinceLastFeverShiver), "DiseaseEffect"); float num = Mathf.Round((float)data.MinsSinceDiseaseStart * (1f + data.Severity)); float num2 = (float)base.minsRequiredForProgression * (1f + data.Severity); if (num / (float)base.minsRequiredForProgression >= (float)data.Progression) { data.Progression++; } if (data.Progression >= 5) { DebugModule.Log("Player died of fever", "DiseaseEffect"); FlatlineUIModule.causeOfDeath = "Fever"; Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.PrePlayerDied())); data.Active = false; return; } data.HealState += Random.Range(passiveDiseaseHealingMin, passiveDiseaseHealingMax); if (BedRotSimulator.isBedrotting) { data.HealState += Random.Range(passiveDiseaseHealingMin * 5f, passiveDiseaseHealingMax * 5f); } if (PlayerSingleton<PlayerMovement>.Instance.IsSprinting) { data.HealState = Mathf.Clamp01(data.HealState - Random.Range(passiveDiseaseHealingMin, passiveDiseaseHealingMax * 2f)); } if (!FlatlinePlayer.flatlinePlayerAudio.isPlaying) { AudioClip val = null; val = ((Player.Local.Avatar.CurrentSettings.Gender > 0.5f) ? ((!(Random.Range(0f, 1f) > 0.5f)) ? ConfigLoader.loadedAudios["femalesneeze"] : ConfigLoader.loadedAudios["femalecough"]) : ((!(Random.Range(0f, 1f) > 0.5f)) ? ConfigLoader.loadedAudios["malesneeze"] : ConfigLoader.loadedAudios["malecough"])); if (data.Progression == 1 && Random.Range(0f, 1f) > 0.96f) { FlatlinePlayer.flatlinePlayerAudio.PlayOneShot(val); } else if (data.Progression == 2 && Random.Range(0f, 1f) > 0.94f) { FlatlinePlayer.flatlinePlayerAudio.PlayOneShot(val); } else if (data.Progression == 3 && Random.Range(0f, 1f) > 0.92f) { FlatlinePlayer.flatlinePlayerAudio.PlayOneShot(val); } else if (data.Progression >= 4 && Random.Range(0f, 1f) > 0.87f) { FlatlinePlayer.flatlinePlayerAudio.PlayOneShot(val); } } if (data.Progression >= 1) { float num3 = Mathf.Clamp(FlatlinePlayer.EnergyConsumptionPerMinute + Mathf.Clamp(baseEnergyConsumptionIncrease * (float)data.Progression * (1f + data.Severity), 0f, 0.0009f), 0f, FlatlinePlayer.DefaultEnergyConsumption * 3f); FlatlinePlayer.EnergyConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.EnergyConsumptionPerMinute, num3, MaximumSystematicPropertyChangePerTick * 2f); float num4 = Mathf.Clamp(FlatlinePlayer.TemperatureConsumption + Mathf.Clamp(baseTemperatureConsumptionIncrease * (float)data.Progression * (1f + data.Severity), 0f, 0.0015f), 0f, FlatlinePlayer.TemperatureConsumptionPerMinutePerDegreeDiff * 3f); FlatlinePlayer.TemperatureConsumption = Mathf.Lerp(FlatlinePlayer.TemperatureConsumption, num4, MaximumSystematicPropertyChangePerTick * 3f); float num5 = Mathf.Clamp(FlatlinePlayer.ThirstConsumptionPerMinute + Mathf.Clamp(baseThirstConsumptionIncrease * (float)data.Progression * (1f + data.Severity), 0f, 0.0015f), 0f, FlatlinePlayer.DefaultThirstConsumption * 3f); FlatlinePlayer.ThirstConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.ThirstConsumptionPerMinute, num5, MaximumSystematicPropertyChangePerTick * 3f); } if (data.Progression >= 2 && data.HealState < 0.8f && Flatline.loadedPlayerData.State.healthData.MaxHP > 100f - MaximumMaxHPReduction) { float num6 = num2 * 5f / 1440f; float num7 = num2 * 2f / 1440f; float num8 = num6 - num7; float num9 = MaximumMaxHPReduction / 1440f * num8 / 10f; num9 = Mathf.Clamp01(Mathf.Lerp(num9, 0f, data.HealState)); DebugModule.Log("Fever Max HP reduction: " + num9, "DiseaseEffect"); if (Flatline.loadedPlayerData.State.healthData.MaxHP - num9 < Flatline.loadedPlayerData.State.healthData.CurrentHP) { float num10 = Flatline.loadedPlayerData.State.healthData.CurrentHP - (Flatline.loadedPlayerData.State.healthData.MaxHP - num9); if (Player.Local.Health.CurrentHealth - num10 <= 0f) { FlatlineUIModule.causeOfDeath = "Fever"; } Player.Local.Health.TakeDamage(num10, false, false); FlatlinePlayer.AppendDamageSource($"Fever damage (-{num10}HP)"); } Flatline.loadedPlayerData.State.healthData.MaxHP = Mathf.Clamp(Flatline.loadedPlayerData.State.healthData.MaxHP - num9, 10f, 100f); } if (minsSinceLastFeverShiver >= minsUntilNextFeverShiver) { Flatline.coros.Add(MelonCoroutines.Start(BlurShort())); minsSinceLastFeverShiver = 0; switch (data.Progression) { case 1: minsUntilNextFeverShiver = Random.Range(100, 200); break; case 2: minsUntilNextFeverShiver = Random.Range(80, 180); break; case 3: minsUntilNextFeverShiver = Random.Range(70, 120); break; case 4: minsUntilNextFeverShiver = Random.Range(50, 100); break; default: minsUntilNextFeverShiver = Random.Range(80, 360); break; } } } public IEnumerator BlurShort() { if (!Flatline.registered || FlatlinePlayer.isPassedOut || FlatlinePlayer.isQueuedForDeath) { yield break; } DebugModule.Log("Start blur", "BlurShort"); Mathf.Lerp(2f, 5f, (float)data.Progression / 5f); PlayerSingleton<PlayerCamera>.Instance.FoVChangeSmoother.AddOverride(-8f, 5, "fever"); PlayerSingleton<PlayerCamera>.Instance.SmoothLookSmoother.AddOverride(0.8f, 5, "fever"); if (data.Progression > 3) { Player.Local.Disoriented = true; } Player.Local.Seizure = true; Singleton<PostProcessingManager>.Instance.SetBlur(1f); yield return Flatline.Wait5; if (Flatline.registered) { Player.Local.Seizure = false; if (data.Progression > 3 && Player.Local.Disoriented) { Player.Local.Disoriented = false; } Singleton<PostProcessingManager>.Instance.SetBlur(0f); PlayerSingleton<PlayerCamera>.Instance.FoVChangeSmoother.RemoveOverride("fever"); PlayerSingleton<PlayerCamera>.Instance.SmoothLookSmoother.RemoveOverride("fever"); DebugModule.Log("End blur", "BlurShort"); } } public override void DiseaseHealed() { if (FlatlinePlayer.EnergyConsumptionPerMinute > FlatlinePlayer.DefaultEnergyConsumption) { FlatlinePlayer.EnergyConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.EnergyConsumptionPerMinute, FlatlinePlayer.DefaultFoodConsumption, 0.5f); } if (FlatlinePlayer.ThirstConsumptionPerMinute > FlatlinePlayer.DefaultThirstConsumption) { FlatlinePlayer.ThirstConsumptionPerMinute = Mathf.Lerp(FlatlinePlayer.ThirstConsumptionPerMinute, FlatlinePlayer.DefaultThirstConsumption, 0.5f); } if (FlatlinePlayer.TemperatureConsumption > FlatlinePlayer.TemperatureConsumptionPerMinutePerDegreeDiff) { FlatlinePlayer.TemperatureConsumption = Mathf.Lerp(FlatlinePlayer.TemperatureConsumption, FlatlinePlayer.TemperatureConsumptionPerMinutePerDegreeDiff, 0.5f); } Player.Local.Avatar.Effects.SetSicklySkinColor(false); Player.Local.Avatar.EmotionManager.RemoveEmotionOverride("Sickly"); DebugModule.Log("Healed fever succesfully", "DiseaseHealed"); } public override void UpdateDiseaseData() { } } public abstract class Disease { public readonly float ParasympatheticHealing = 0.0002f; public readonly float MaximumSystematicPropertyChangePerTick = 1f / 144f; public DiseaseData data; public object diseaseCoroutine; public Action onDiseaseStarted; public int minsRequiredForProgression { get; set; } public abstract void DiseaseEffect(); public abstract void DiseaseHealed(); public abstract void UpdateDiseaseData(); public IEnumerator DiseaseEvaluator() { FlatlineUIModule.diseaseIcons[data.DiseaseID].SetActive(true); if (onDiseaseStarted != null) { onDiseaseStarted(); } while (data.Active) { yield return Flatline.Wait10; if (FlatlinePlayer.isQueuedForDeath && !Flatline.currentConfig.PermanentDeath && Player.PlayerList.Count > 1) { continue; } if (!Flatline.registered || FlatlinePlayer.isQueuedForDeath) { yield break; } if (!Flatline.isSaving && !FlatlinePlayer.isPassedOut && !NetworkSingleton<TimeManager>.Instance.IsSleepInProgress && !Flatline.haltExecution && (Player.PlayerList.Count <= 1 || Player.Local.Health.IsAlive) && (NetworkSingleton<TimeManager>.Instance.CurrentTime >= 659 || NetworkSingleton<TimeManager>.Instance.CurrentTime <= 400)) { if (data.DiseaseID != "cancer" && Flatline.loadedPlayerData.State.Hunger > 0.9f) { data.HealState += ParasympatheticHealing; } if (data.HealState >= 1f) { break; } if (HospitalHealing.hospitalChoiceInitialized) { UpdateChoiceState((NPC)(object)HospitalHealing.lisaNPC, HospitalHealing.lisaCureChoices); UpdateChoiceState((NPC)(object)HospitalHealing.ireneNPC, HospitalHealing.ireneCureChoices); } data.MinsSinceDiseaseStart += 10; DiseaseEffect(); } } data.Active = false; FlatlineUIModule.diseaseIcons[data.DiseaseID].SetActive(false); DiseaseHealed(); if (HospitalHealing.hospitalChoiceInitialized) { UpdateChoiceState((NPC)(object)HospitalHealing.lisaNPC, HospitalHealing.lisaCureChoices); UpdateChoiceState((NPC)(object)HospitalHealing.ireneNPC, HospitalHealing.ireneCureChoices); } diseaseCoroutine = null; } private void UpdateChoiceState(NPC npc, Dictionary<string, DialogueChoice> choices) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)npc != (Object)null && choices.TryGetValue(data.DiseaseID, out var value)) { value.Enabled = Vector3.Distance(npc.CenterPoint, HospitalHealing.hospitalDoorPoint) <= 7f && data.Active && data.HealState < 1f; } } } public static class PlayerConsumeDamage { public enum EConsumeType { None, Weed, Meth, Cocaine, Shroom, Paracetamol, Addy, Chili } public static readonly List<string> trackedKeys = new List<string> { "cocaine", "meth", "shroom", "weed", "paracetamol", "addy", "chili" }; public static readonly int CocaineLifeTimeHrs = 8; public static readonly float cocaineSystemicAmountPerDose = 0.08f; public static readonly float cocaineConsumeLungDamage = 0.004f; public static readonly int MethLifeTimeHrs = 12; public static readonly float methSystemicAmountPerDose = 0.11f; public static readonly float methConsumeLungDamage = 0.0005f; public static readonly int ShroomsLifeTimeHrs = 6; public static readonly float shroomSystemicAmountPerDose = 0.06f; public static readonly float weedConsumeLungDamage = 0.009f; public static readonly float paracetamolLiverDamage = 0.005f; public static readonly int ParacetamolLifeTimeHrs = 18; public static readonly int AddyLifeTimeHrs = 14; public static readonly int ChiliLifeTimeHrs = 50; public static readonly Dictionary<string, int> lifeTimeHours = new Dictionary<string, int> { { "cocaine", CocaineLifeTimeHrs }, { "meth", MethLifeTimeHrs }, { "shroom", ShroomsLifeTimeHrs }, { "paracetamol", ParacetamolLifeTimeHrs }, { "addy", AddyLifeTimeHrs }, { "chili", ChiliLifeTimeHrs } }; public static bool ProductEffectRunning = false; public static bool IsWeedEffectRunning = false; public static bool IsShroomEffectRunning = false; public static bool IsMethEffectRunning = false; public static bool IsCocaineEffectRunning = false; public static AudioSource heartBeatSource = null; public static bool heartPumpOverrideActive = false; public static void InitConsumeDamageModule() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("FlatlineHeartAudio"); val.transform.parent = ((Component)PlayerSingleton<PlayerCamera>.Instance).transform; val.transform.localPosition = Vector3.zero; heartBeatSource = val.AddComponent<AudioSource>(); heartBeatSource.volume = 0.7f; heartBeatSource.loop = false; val.SetActive(true); ((Behaviour)heartBeatSource).enabled = true; } public static void ResetConsumeDamageModule() { ProductEffectRunning = false; IsWeedEffectRunning = false; IsShroomEffectRunning = false; IsMethEffectRunning = false; IsCocaineEffectRunning = false; heartBeatSource = null; heartPumpOverrideActive = false; } public static EConsumeType TypeFromID(string id) { return id switch { "weed" => EConsumeType.Weed, "meth" => EConsumeType.Meth, "cocaine" => EConsumeType.Cocaine, "shroom" => EConsumeType.Shroom, "paracetamol" => EConsumeType.Paracetamol, "addy" => EConsumeType.Addy, "chili" => EConsumeType.Chili, _ => EConsumeType.None, }; } public static void OnProductConsumed(EConsumeType type, EQuality quality = (EQuality)0, bool useQuality = false) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!Flatline.currentConfig.DrugSideEffects || type == EConsumeType.None) { return; } float num = 1f; float num2 = 1f; if (useQuality) { int num3 = Enum.GetNames(typeof(EQuality)).Length - 1; num = Mathf.Lerp(1f, 2f, (float)quality / (float)num3); num2 = Mathf.Lerp(2f, 1f, (float)quality / (float)num3); Flatline.coros.Add(MelonCoroutines.Start(WaitRandomAfterConsume(type, quality))); } string key = type.ToString().ToLower(); if (!Flatline.loadedPlayerData.State.consumptionDatas.ContainsKey(key)) { Flatline.loadedPlayerData.State.consumptionDatas.Add(key, new ConsumptionData()); } switch (type) { case EConsumeType.Weed: Flatline.loadedPlayerData.State.consumptionDatas[key].overtimeLungDamage += weedConsumeLungDamage * num2; Flatline.loadedPlayerData.State.healthData.TimesSmoked++; break; case EConsumeType.Meth: Flatline.loadedPlayerData.State.consumptionDatas[key].overtimeLungDamage += methConsumeLungDamage * num2; Flatline.loadedPlayerData.State.consumptionDatas[key].currentAmountInSystem += methSystemicAmountPerDose * num; Flatline.loadedPlayerData.State.healthData.TimesSmoked++; Flatline.coros.Add(MelonCoroutines.Start(CurrentProductMonitor())); Flatline.coros.Add(MelonCoroutines.Start(StimulantEffectChanger())); Flatline.coros.Add(MelonCoroutines.Start(HeartPumpOverride("meth"))); break; case EConsumeType.Cocaine: Flatline.loadedPlayerData.State.consumptionDatas[key].overtimeLungDamage += cocaineConsumeLungDamage * num2; Flatline.loadedPlayerData.State.consumptionDatas[key].currentAmountInSystem += cocaineSystemicAmountPerDose * num; Flatline.coros.Add(MelonCoroutines.Start(CurrentProductMonitor())); Flatline.coros.Add(MelonCoroutines.Start(StimulantEffectChanger())); Flatline.coros.Add(MelonCoroutines.Start(HeartPumpOverride("cocaine"))); break; case EConsumeType.Shroom: Flatline.loadedPlayerData.State.consumptionDatas[key].currentAmountInSystem += shroomSystemicAmountPerDose * num; Flatline.coros.Add(MelonCoroutines.Start(CurrentProductMonitor())); Flatline.coros.Add(MelonCoroutines.Start(ShroomEffectChanger())); break; case EConsumeType.Paracetamol: { Flatline.loadedPlayerData.State.consumptionDatas[key].currentAmountInSystem += IngestibleParacetamol.SystemicAmountPerDose; Flatline.loadedPlayerData.State.consumptionDatas[key].overtimeLiverDamage += paracetamolLiverDamage; float maxHP = Flatline.loadedPlayerData.State.healthData.MaxHP; if (!Mathf.Approximately(maxHP, 100f)) { Flatline.loadedPlayerData.State.healthData.MaxHP = Mathf.Clamp(maxHP + IngestibleParacetamol.MaxHPRegen, 1f, 100f); } break; } case EConsumeType.Addy: Flatline.loadedPlayerData.State.consumptionDatas[key].currentAmountInSystem += IngestibleAddy.SystemicAmountPerDose; break; case EConsumeType.Chili: Flatline.loadedPlayerData.State.consumptionDatas[key].currentAmountInSystem += IngestibleChili.SystemicAmountPerDose; break; } DebugModule.Log("Changed consumption values succesfully", "OnProductConsumed"); } public static IEnumerator WaitRandomAfterConsume(EConsumeType type, EQuality quality) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) int randomWaitMins = Random.Range(3, 6); for (int i = 0; i < randomWaitMins; i++) { yield return Flatline.Wait60; if (!Flatline.registered || FlatlinePlayer.isQueuedForDeath || Flatline.haltExecution) { yield break; } } if (Flatline.isSaving) { yield return (object)new WaitUntil(Func<bool>.op_Implicit((Func<bool>)(() => !Flatline.isSaving))); } if (!Flatline.registered || FlatlinePlayer.isQueuedForDeath || Flatline.haltExecution) { yield break; } DebugModule.Log("Evaluate after effects for drug", "WaitRandomAfterConsume"); if ((type == EConsumeType.Meth || type == EConsumeType.Cocaine) && (int)quality < 4 && Random.Range(0f, 1f) > 0.8f) { Player.Local.Avatar.Effects.TriggerSick(false); if (Flatline.loadedPlayerData.State.Hunger > 0.1f) { FlatlinePlayer.SetFood(Mathf.Clamp01(Flatline.loadedPlayerData.State.Hunger * 0.95f)); } if (Flatline.loadedPlayerData.State.Thirst > 0.1f) { FlatlinePlayer.SetWater(Mathf.Clamp01(Flatline.loadedPlayerData.State.Thirst * 0.92f)); } } else if (type == EConsumeType.Weed && (int)quality >= 2 && Random.Range(0f, 1f) > 0.2f) { if (Flatline.loadedPlayerData.State.Hunger > 0.1f) { FlatlinePlayer.SetFood(Mathf.Clamp01(Flatline.loadedPlayerData.State.Hunger * 0.75f)); } if (Flatline.loadedPlayerData.State.Thirst > 0.1f) { FlatlinePlayer.SetWater(Mathf.Clamp01(Flatline.loadedPlayerData.State.Thirst * 0.75f)); } } PlayerDiseaseDamage.CalculateDepressionAfterConsumeProbability(type, quality); } public static void OnHourPass() { if (Flatline.registered && !FlatlinePlayer.isQueuedForDeath && !Flatline.haltExecution && (NetworkSingleton<TimeManager>.Instance.CurrentTime >= 659 || NetworkSingleton<TimeManager>.Instance.CurrentTime <= 400)) { Flatline.coros.Add(MelonCoroutines.Start(SystemicDecay())); } } public static IEnumerator SystemicDecay() { if (Flatline.isSaving) { yield return (object)new WaitUntil(Func<bool>.op_Implicit((Func<bool>)(() => !Flatline.isSaving))); } foreach (string item in new List<string>(Flatline.loadedPlayerData.State.consumptionDatas.Keys)) { float currentAmountInSystem = Flatline.loadedPlayerData.State.consumptionDatas[item].currentAmountInSystem; if (currentAmountInSystem > 0f) { int lifeTimeHrs = lifeTimeHours[item]; float num = DecayHalfLife(currentAmountInSystem, lifeTimeHrs); if (num < 0.0001f) { num = 0f; } Flatline.loadedPlayerData.State.consumptionDatas[item].currentAmountInSystem = num; } } if (Flatline.loadedPlayerData.State.consumptionDatas.Any((KeyValuePair<string, ConsumptionData> x) => x.Value.currentAmountInSystem >= 1f)) { KeyValuePair<string, ConsumptionData> keyValuePair = Flatline.loadedPlayerData.State.consumptionDatas.First((KeyValuePair<string, ConsumptionData> x) => x.Value.currentAmountInSystem >= 1f); DebugModule.Log("Player consumed lethal dose of: " + keyValuePair.Key, "SystemicDecay"); FlatlineUIModule.causeOfDeath = "Lethal dose of " + keyValuePair.Key; Player.Local.Avatar.Effects.TriggerSick(false); Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.PrePlayerDied())); if (Player.PlayerList.Count > 1) { Flatline.loadedPlayerData.State.consumptionDatas[keyValuePair.Key].currentAmountInSystem = 0f; } } else if (Flatline.loadedPlayerData.State.consumptionDatas.Any((KeyValuePair<string, ConsumptionData> x) => x.Value.overtimeLiverDamage >= 1f)) { KeyValuePair<string, ConsumptionData> keyValuePair2 = Flatline.loadedPlayerData.State.consumptionDatas.First((KeyValuePair<string, ConsumptionData> x) => x.Value.overtimeLiverDamage >= 1f); DebugModule.Log("Players liver failed due to: " + keyValuePair2.Key, "SystemicDecay"); FlatlineUIModule.causeOfDeath = "Liver failure from consumption of " + keyValuePair2.Key; Player.Local.Avatar.Effects.TriggerSick(false); Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.PrePlayerDied())); if (Player.PlayerList.Count > 1) { Flatline.loadedPlayerData.State.consumptionDatas[keyValuePair2.Key].overtimeLiverDamage = 0f; } } else if (Flatline.loadedPlayerData.State.consumptionDatas.Any((KeyValuePair<string, ConsumptionData> x) => x.Value.overtimeLungDamage >= 1f)) { KeyValuePair<string, ConsumptionData> keyValuePair3 = Flatline.loadedPlayerData.State.consumptionDatas.First((KeyValuePair<string, ConsumptionData> x) => x.Value.overtimeLungDamage >= 1f); DebugModule.Log("Players lungs failed due to: " + keyValuePair3.Key, "SystemicDecay"); FlatlineUIModule.causeOfDeath = "Pulmonary embolism from smoking " + keyValuePair3.Key; Player.Local.Avatar.Effects.TriggerSick(false); Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.PrePlayerDied())); if (Player.PlayerList.Count > 1) { Flatline.loadedPlayerData.State.consumptionDatas[keyValuePair3.Key].overtimeLungDamage = 0f; } } } public static float DecayHalfLife(float current, int lifeTimeHrs) { return Mathf.Clamp(current * Mathf.Pow(0.5f, 1f / (float)lifeTimeHrs), 0f, 2f); } public static IEnumerator CurrentProductMonitor() { if (ProductEffectRunning) { yield break; } ProductEffectRunning = true; yield return Flatline.Wait025; ProductItemInstance current = Player.Local.ConsumedProduct; if (current != null) { yield return (object)new WaitUntil(Func<bool>.op_Implicit((Func<bool>)(() => CanContinue()))); } DebugModule.Log("Current product has ended, disable", "CurrentProductMonitor"); ProductEffectRunning = false; IsWeedEffectRunning = false; IsShroomEffectRunning = false; IsMethEffectRunning = false; IsCocaineEffectRunning = false; bool CanContinue() { if (Flatline.registered && !FlatlinePlayer.isQueuedForDeath && Player.Local.ConsumedProduct != null && Player.Local.ConsumedProduct == current) { return Flatline.haltExecution; } return true; } } public static IEnumerator ShroomEffectChanger() { if (IsShroomEffectRunning) { yield break; } IsShroomEffectRunning = true; float amplitudeMax = 0.5f; float amplitudeMin = 0.19f; float blendMax = 0.4f; float blendMin = 0.016f; float noiseScaleMax = 50f; float noiseScaleMin = 15f; float num = 0f; if (Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue("shroom", out var value)) { num = Mathf.Clamp01(value.currentAmountInSystem); } float targetAmp = Mathf.Lerp(amplitudeMin, amplitudeMax, num) * Random.Range(0.95f, 1.05f); float targetBld = Mathf.Lerp(blendMin, blendMax, num) * Random.Range(0.95f, 1.05f); float targetNoi = Mathf.Lerp(noiseScaleMin, noiseScaleMax, num) * Random.Range(0.95f, 1.05f); MaterialProperties activeProperties = Singleton<PostProcessingManager>.Instance.GetActivePsychedelicEffectProperties(); MaterialProperties source = activeProperties.Clone(); PsychedelicFullScreenData psychedelicEffectDataPreset = Singleton<PostProcessingManager>.Instance.GetPsychedelicEffectDataPreset("Active"); MaterialProperties targetMaterialProperties = psychedelicEffectDataPreset.ConvertToMaterialProperties(); targetMaterialProperties.Blend = targetBld; targetMaterialProperties.NoiseScale = targetNoi; targetMaterialProperties.Amplitude = targetAmp; Singleton<EnvironmentFX>.Instance.SetEnvironmentScrollingActive(true); Singleton<PostProcessingManager>.Instance.SetPsychedelicEffectActive(true); float easeInTime = 2f; float currentEase = 0f; while (currentEase < easeInTime) { if (!Flatline.registered) { yield break; } currentEase += Time.deltaTime; float num2 = currentEase / easeInTime; activeProperties.Blend = Mathf.Lerp(source.Blend, targetMaterialProperties.Blend, num2); Singleton<EnvironmentFX>.Instance.SetEnvironmentScrollingSpeedByPercentage(Mathf.Lerp(0f, 1f, num2)); yield return null; } Singleton<PostProcessingManager>.Instance.SetPsychedelicEffectProperties(targetMaterialProperties); float sleepTime = 5f; float sleepCurrent = 0f; bool shouldBreak = false; while (!shouldBreak) { while (sleepCurrent < sleepTime) { sleepCurrent += Time.deltaTime; if (!Flatline.registered) { yield break; } if (!ProductEffectRunning || !IsShroomEffectRunning) { shouldBreak = true; break; } yield return null; } sleepCurrent = 0f; if (shouldBreak) { break; } if (Flatline.isSaving || !Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue("shroom", out var value2)) { continue; } float num3 = Mathf.Clamp01(value2.currentAmountInSystem); if (num3 > 0.75f && Random.Range(0f, 1f) > 0.98f) { Player.Local.Avatar.Effects.TriggerSick(false); FlatlinePlayer.SetFood(Mathf.Clamp01(Flatline.loadedPlayerData.State.Hunger - 0.05f)); FlatlinePlayer.SetWater(Mathf.Clamp01(Flatline.loadedPlayerData.State.Thirst - 0.02f)); } targetAmp = Mathf.Lerp(amplitudeMin, amplitudeMax, num3); targetBld = Mathf.Lerp(blendMin, blendMax, num3); targetNoi = Mathf.Lerp(noiseScaleMin, noiseScaleMax, num3); MaterialProperties temp = Singleton<PostProcessingManager>.Instance.GetActivePsychedelicEffectProperties().Clone(); targetAmp = Mathf.Clamp(targetAmp, temp.Amplitude - amplitudeMax / 10f, temp.Amplitude + amplitudeMax / 10f); targetBld = Mathf.Clamp(targetBld, temp.Blend - blendMax / 10f, temp.Blend + blendMax / 10f); targetNoi = Mathf.Clamp(targetNoi, temp.NoiseScale - noiseScaleMax / 10f, temp.NoiseScale + noiseScaleMax / 10f); float num4 = Random.Range(0f, 1f); float num5 = Random.Range(0f, 1f); float num6 = Random.Range(0f, 1f); bool useBlend = false; bool useNoise = false; bool useAmplitude = false; List<int> list = new List<int> { 0, 1, 2 }; int num7 = list.Count; while (num7 > 1) { num7--; int index = Random.Range(0, num7 + 1); int value3 = list[index]; list[index] = list[num7]; list[num7] = value3; } for (int i = 0; i < 2; i++) { if (list[i] == 0 && (double)num4 > 0.33) { useBlend = true; } if (list[i] == 1 && (double)num5 > 0.33) { useNoise = true; } if (list[i] == 2 && (double)num6 > 0.33) { useAmplitude = true; } } if (!(useBlend || useNoise || useAmplitude)) { continue; } currentEase = 0f; while (currentEase < easeInTime) { if (!Flatline.registered) { yield break; } if (!ProductEffectRunning || !IsShroomEffectRunning) { shouldBreak = true; break; } currentEase += Time.deltaTime; float num8 = currentEase / easeInTime; float num9 = Mathf.SmoothStep(0f, 1f, num8); if (useBlend) { activeProperties.Blend = Mathf.Lerp(temp.Blend, targetBld, num9); } if (useNoise) { activeProperties.NoiseScale = Mathf.Lerp(temp.NoiseScale, targetNoi, num9); } if (useAmplitude) { activeProperties.Amplitude = Mathf.Lerp(temp.Amplitude, targetAmp, num9); } yield return null; } if (shouldBreak) { break; } targetMaterialProperties = activeProperties.Clone(); Singleton<PostProcessingManager>.Instance.SetPsychedelicEffectProperties(targetMaterialProperties); sleepTime = Random.Range(5f, 10f); easeInTime = Random.Range(2f, 6f); } DebugModule.Log("Shroom effect changer ended", "ShroomEffectChanger"); IsShroomEffectRunning = false; } public static IEnumerator StimulantEffectChanger() { if (IsCocaineEffectRunning || IsMethEffectRunning) { yield break; } IsCocaineEffectRunning = true; IsMethEffectRunning = true; yield return Flatline.Wait2; if (!Flatline.registered) { yield break; } float sleepTime = 2f; float sleepCurrent = 0f; bool shouldBreak = false; while (!shouldBreak) { while (sleepCurrent < sleepTime) { sleepCurrent += Time.deltaTime; if (!Flatline.registered) { yield break; } if (!ProductEffectRunning || !IsMethEffectRunning || !IsCocaineEffectRunning) { shouldBreak = true; break; } yield return null; } sleepCurrent = 0f; if (shouldBreak) { break; } float num = 0f; if (Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue("meth", out var value) && value.currentAmountInSystem > 0.001f) { num = value.currentAmountInSystem; } if (Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue("cocaine", out var value2) && value2.currentAmountInSystem > 0.001f && value2.currentAmountInSystem > num) { num = value2.currentAmountInSystem; } num = Mathf.Clamp01(num); if (num > 0.75f && Random.Range(0f, 1f) > 0.98f) { Player.Local.Avatar.Effects.TriggerSick(false); FlatlinePlayer.SetFood(Mathf.Clamp01(Flatline.loadedPlayerData.State.Hunger - 0.05f)); FlatlinePlayer.SetWater(Mathf.Clamp01(Flatline.loadedPlayerData.State.Thirst - 0.02f)); } float num2 = Mathf.Lerp(0.9f, 0.75f, num); if (Random.Range(0f, 1f) < num2) { continue; } float num3 = Mathf.Lerp(1.15f, 2f, num); float rotAmount = Random.Range(2f, 6f) * num3; rotAmount = ((Random.Range(0, 2) == 0) ? (0f - rotAmount) : rotAmount); for (int i = 0; i < Random.Range(4, 8); i++) { yield return Flatline.Wait05; if (!Flatline.registered) { yield break; } if (!ProductEffectRunning || !IsMethEffectRunning || !IsCocaineEffectRunning) { shouldBreak = true; break; } if (Random.Range(0f, 1f) > 0.55f) { float num4 = 0.5f; float num5 = 0f; Quaternion rotation = ((Component)Player.Local).transform.root.rotation; while (num5 < num4) { if (!Flatline.registered) { yield break; } if (!ProductEffectRunning || !IsMethEffectRunning || !IsCocaineEffectRunning) { shouldBreak = true; break; } num5 += Time.deltaTime; float num6 = num5 / num4; ((Component)Player.Local).transform.root.rotation = Quaternion.Lerp(rotation, Quaternion.Euler(0f, rotation.y + rotAmount, 0f), num6); } if (shouldBreak) { break; } } if (i % 2 != 0) { continue; } PlayerInventory instance = PlayerSingleton<PlayerInventory>.Instance; if (GameInput.IsTyping || Singleton<PauseMenu>.Instance.IsPaused || !instance.HotbarEnabled) { continue; } int num7 = Random.Range(0, 8); if (num7 != instance.EquippedSlotIndex) { if (instance.EquippedSlotIndex != -1) { instance.IndexAllSlots(instance.EquippedSlotIndex).Unequip(); } instance.PreviousEquippedSlotIndex = instance.EquippedSlotIndex; instance.EquippedSlotIndex = num7; instance.Equip(instance.IndexAllSlots(num7)); PlayerSingleton<ViewmodelSway>.Instance.RefreshViewmodel(); } } if (shouldBreak) { break; } } IsCocaineEffectRunning = false; IsMethEffectRunning = false; DebugModule.Log("Stimulant effect changer ended", "StimulantEffectChanger"); } public static IEnumerator HeartPumpOverride(string consumedID) { if (heartPumpOverrideActive) { yield break; } heartPumpOverrideActive = true; DebugModule.Log("Starting heart pump override", "HeartPumpOverride"); if (!Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue(consumedID, out var data)) { DebugModule.Log("No match for id in consumption data", "HeartPumpOverride"); heartPumpOverrideActive = false; yield break; } if (!CanContinue(data)) { heartPumpOverrideActive = false; yield break; } float maxTotalElapsed = 120f; float totalElapsed = 0f; int maxBeatsPerMinute = 200; int minBeatsPerMinute = 70; int num = Mathf.RoundToInt(Mathf.Lerp((float)minBeatsPerMinute, (float)maxBeatsPerMinute, Mathf.Clamp01(data.currentAmountInSystem))); DebugModule.Log("Setting bpm to " + num, "HeartPumpOverride"); float elapsedSinceLast = 0f; float num2 = (float)num / 60f; float secondsForBeat = 1f / num2; while (true) { if (!Flatline.registered) { yield break; } if (!CanContinue(data) || totalElapsed >= maxTotalElapsed) { break; } yield return Flatline.Wait01; totalElapsed += 0.1f; elapsedSinceLast += 0.1f; if (elapsedSinceLast >= secondsForBeat) { if ((Object)(object)heartBeatSource != (Object)null && !heartBeatSource.isPlaying) { heartBeatSource.PlayOneShot(ConfigLoader.loadedAudios["singleheartbeat"]); } if (Mathf.RoundToInt(totalElapsed) % 5 == 0) { num = Mathf.RoundToInt(Mathf.Lerp((float)minBeatsPerMinute, (float)maxBeatsPerMinute, Mathf.Clamp01(data.currentAmountInSystem))); num2 = (float)num / 60f; secondsForBeat = 1f / num2; } } } DebugModule.Log("Finished heart pump override", "HeartPumpOverride"); heartPumpOverrideActive = false; static bool CanContinue(ConsumptionData consumptionData) { if (PlayerSingleton<PlayerCamera>.Instance.HeartbeatSoundController._sound._audioSource.volume == 0f && Mathf.Clamp01(consumptionData.currentAmountInSystem) > 0.55f && !FlatlinePlayer.isQueuedForDeath && !FlatlinePlayer.isPassedOut) { return ProductEffectRunning; } return false; } } } [HarmonyPatch(typeof(ShroomInstance), "DoPsychedlicEffectBlend")] public static class ShroomInstance_DoPsychedlicEffectBlend_Patch { [HarmonyPrefix] public static bool Prefix(ShroomInstance __instance, ref IEnumerator __result, MaterialProperties targetMaterialProperties, float targetValuePercentage, float duration) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (!Flatline.currentConfig.DrugSideEffects) { return true; } if (targetValuePercentage > 0f) { MonoEnumeratorWrapper val = new MonoEnumeratorWrapper(EmptyCoroutine()); __result = ((Il2CppObjectBase)val).Cast<IEnumerator>(); return false; } return true; } public static IEnumerator EmptyCoroutine() { yield break; } } public static class PlayerDiseaseDamage { private enum ImpactLocation { Legs, Torso, Head } public static List<Disease> allDiseases = new List<Disease>(); public static readonly List<string> diseaseNames = new List<string> { "cancer", "fever", "bonebreak", "bleed", "depression" }; public static GameObject bleedPressureIntObj; public static bool isBleedingStemmed = false; public static void InitPlayerDiseaseDamage() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) bleedPressureIntObj = new GameObject("ApplyPressureInt"); bleedPressureIntObj.layer = LayerMask.NameToLayer("Task"); bleedPressureIntObj.transform.parent = ((Component)Player.Local).transform.root; bleedPressureIntObj.transform.localScale = Vector3.one; bleedPressureIntObj.transform.localRotation = Quaternion.identity; bleedPressureIntObj.transform.localPosition = new Vector3(0f, 0.1f, 0.1f); bleedPressureIntObj.AddComponent<BoxCollider>().size = new Vector3(0.2f, 0.2f, 0.2f); InteractableObject obj = bleedPressureIntObj.AddComponent<InteractableObject>(); obj.message = "Stem bleeding"; obj.MaxInteractionRange = 2f; obj.interactionType = (EInteractionType)0; obj.onInteractStart.AddListener(UnityAction.op_Implicit((Action)SetIsBleedingStemmedTrue)); obj.onInteractEnd.AddListener(UnityAction.op_Implicit((Action)SetIsBleedingStemmedFalse)); bleedPressureIntObj.SetActive(false); static void SetIsBleedingStemmedFalse() { DebugModule.Log("Disable bleeding stemmed", "InitPlayerDiseaseDamage"); isBleedingStemmed = false; } static void SetIsBleedingStemmedTrue() { DebugModule.Log("Set bleeding stemmed", "InitPlayerDiseaseDamage"); isBleedingStemmed = true; } } public static void ResetPlayerDiseaseDamage() { bleedPressureIntObj = null; isBleedingStemmed = false; } public static void ApplyLoadedDiseases() { if (!Flatline.currentConfig.DiseasesEnabled) { return; } foreach (DiseaseData diseaseDatum in Flatline.loadedPlayerData.DiseaseData) { switch (diseaseDatum.DiseaseID) { case "cancer": { Cancer item5 = new Cancer(diseaseDatum); allDiseases.Add(item5); break; } case "fever": { Fever item4 = new Fever(diseaseDatum); allDiseases.Add(item4); break; } case "bonebreak": { BoneBreak item3 = new BoneBreak(diseaseDatum); allDiseases.Add(item3); break; } case "bleed": { Bleeding item2 = new Bleeding(diseaseDatum); allDiseases.Add(item2); break; } case "depression": { Depression item = new Depression(diseaseDatum); allDiseases.Add(item); break; } default: DebugModule.Log("Unknown disease id: " + diseaseDatum.DiseaseID, "ApplyLoadedDiseases"); break; } } bool flag = false; foreach (Disease allDisease in allDiseases) { if (allDisease.data.Active && allDisease.data.HealState < 1f) { allDisease.diseaseCoroutine = MelonCoroutines.Start(allDisease.DiseaseEvaluator()); } if (allDisease.data.DiseaseID == "bonebreak") { flag = true; } } if (Flatline.loadedPlayerData.State.healthData.IsLegBoneBroken && !flag) { DebugModule.Log("Player leg bone cant be broken since there is no active disease, setting false", "ApplyLoadedDiseases"); Flatline.loadedPlayerData.State.healthData.IsLegBoneBroken = false; } } public static void UpdateDiseaseData() { Flatline.loadedPlayerData.DiseaseData.Clear(); foreach (Disease allDisease in allDiseases) { if (allDisease.data.Active) { allDisease.UpdateDiseaseData(); Flatline.loadedPlayerData.DiseaseData.Add(allDisease.data); } } } public static T AddNewDisease<T>(float severity) where T : Disease { if (!Flatline.currentConfig.DiseasesEnabled) { return null; } if (typeof(T) == typeof(Bleeding) && !Flatline.currentConfig.BleedingEnabled) { return null; } if (typeof(T) == typeof(BoneBreak) && !Flatline.currentConfig.BoneBreakEnabled) { return null; } if (typeof(T) == typeof(Cancer) && !Flatline.currentConfig.CancerEnabled) { return null; } if (typeof(T) == typeof(Depression) && !Flatline.currentConfig.DepressionEnabled) { return null; } if (typeof(T) == typeof(Fever) && !Flatline.currentConfig.FeverEnabled) { return null; } float num = Mathf.Clamp(severity, 0f, 0.3f); foreach (Disease allDisease in allDiseases) { if (allDisease.GetType() == typeof(T) && allDisease.data.Active) { DebugModule.Log("Disease of type " + typeof(T).Name + " is already active, can't add duplicate", "AddNewDisease"); if (allDisease.GetType() == typeof(Bleeding) && allDisease.data.Severity < num) { DebugModule.Log("Upgrading bleeding to worse severity on reapply", "AddNewDisease"); allDisease.data.Severity = num; allDisease.data.HealState *= 0.75f; (allDisease as Bleeding).MaximumMaxHPReduction = Mathf.Lerp(40f, 150f, num / 0.3f); } return null; } } DiseaseData diseaseData = new DiseaseData(); diseaseData.Active = true; diseaseData.Severity = num; T val = (T)Activator.CreateInstance(typeof(T), diseaseData); allDiseases.Add(val); val.diseaseCoroutine = MelonCoroutines.Start(val.DiseaseEvaluator()); DebugModule.Log("Succesfully added new disease: " + typeof(T).Name, "AddNewDisease"); return val; } public static void OnHourPass() { if (!Flatline.haltExecution && !NetworkSingleton<TimeManager>.Instance.IsSleepInProgress && (NetworkSingleton<TimeManager>.Instance.CurrentTime >= 659 || NetworkSingleton<TimeManager>.Instance.CurrentTime <= 400)) { CalculateFeverProbability(); } } public static void OnSleepEnd() { if (!Flatline.haltExecution) { CalculateCancerProbability(); CalculateDepressionPassiveProbability(); } } public static void CalculateDepressionPassiveProbability() { float num = Mathf.Clamp01((float)NetworkSingleton<TimeManager>.Instance.ElapsedDays / 100f); int num2 = ((FlatlinePlayer.minsInsideProperty == 0) ? 1 : FlatlinePlayer.minsInsideProperty); int num3 = ((FlatlinePlayer.minsOutsideProperty == 0) ? 1 : FlatlinePlayer.minsOutsideProperty); float num4 = 0f; if (num2 >= num3) { int num5 = num2 - num3; if ((float)num5 > 480f) { num4 += 0.09f; } else if ((float)num5 > 360f) { num4 += 0.06f; } else if ((float)num5 > 240f) { num4 += 0.03f; } } int num6 = 0; float num7 = 0f; if (Flatline.loadedPlayerData.State.consumptionDatas.Count > 0) { foreach (KeyValuePair<string, ConsumptionData> consumptionData in Flatline.loadedPlayerData.State.consumptionDatas) { if (Depression.temporaryDepressionCures.Contains(consumptionData.Key)) { num7 += consumptionData.Value.currentAmountInSystem; num6++; } } } float num8 = 0f; if (num6 > 0) { num7 /= (float)num6; num8 = Mathf.Lerp(0f, 0.03f, num7); } num8 += Mathf.Clamp((float)Flatline.loadedPlayerData.State.healthData.TimesSmoked / 100f, 0f, 0.33f); num8 = Mathf.Clamp01(num8); float num9 = 0f; if (Flatline.loadedPlayerData.State.Thirst <= 0.65f) { num9 += 0.002f; } if (Flatline.loadedPlayerData.State.Hunger <= 0.65f) { num9 += 0.002f; } if (Flatline.loadedPlayerData.State.Temperature <= 0.65f) { num9 += 0.002f; } if (NetworkSingleton<MoneyManager>.Instance.cashBalance < 5000f) { num9 += 0.002f; } float gender = Player.Local.Avatar.CurrentSettings.Gender; float num10 = 0f; num10 = ((!(gender > 0.5f)) ? Random.Range(0.003f, 0.004f) : Random.Range(0.005f, 0.007f)); float num11 = (float)FlatlinePlayer.minsWithSunnyWeather / 1440f; float num12 = Mathf.Lerp(0.25f, 0f, num11); float num13 = (num + num4 + num7 + num9 + num10 + num12) / 6f; DebugModule.Log($"Mins with sun: {FlatlinePlayer.minsWithSunnyWeather} ({num12})", "CalculateDepressionPassiveProbability"); DebugModule.Log("Depression chance subtotal: " + num13, "CalculateDepressionPassiveProbability"); if (Random.Range(0f, 1f) < num13) { DebugModule.Log("Depression consumption chance hits", "CalculateDepressionPassiveProbability"); AddNewDisease<Depression>(Random.Range(0.001f, 0.3f)); } FlatlinePlayer.minsOutsideProperty = 0; FlatlinePlayer.minsInsideProperty = 0; FlatlinePlayer.minsWithSunnyWeather = 0; } public static void CalculateDepressionAfterConsumeProbability(PlayerConsumeDamage.EConsumeType type, EQuality quality) { //IL_017d: Unknown result type (might be due to invalid IL or missing references) if (type != PlayerConsumeDamage.EConsumeType.Weed && type != PlayerConsumeDamage.EConsumeType.Meth && type != PlayerConsumeDamage.EConsumeType.Cocaine && type != PlayerConsumeDamage.EConsumeType.Shroom) { return; } float num = 0f; switch (type) { case PlayerConsumeDamage.EConsumeType.Weed: { if (Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue("weed", out var value3) && value3.currentAmountInSystem < 0.3f) { num = Random.Range(0.002f, 0.019f); } break; } case PlayerConsumeDamage.EConsumeType.Shroom: { if (Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue("shroom", out var value2) && value2.currentAmountInSystem > 0.08f) { num = Random.Range(0.002f, 0.025f); } break; } case PlayerConsumeDamage.EConsumeType.Meth: { if (Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue("meth", out var value4) && value4.currentAmountInSystem < 0.35f) { num = Random.Range(0.03f, 0.095f); } break; } case PlayerConsumeDamage.EConsumeType.Cocaine: { if (Flatline.loadedPlayerData.State.consumptionDatas.TryGetValue("cocaine", out var value) && value.currentAmountInSystem < 0.35f) { num = Random.Range(0.03f, 0.125f); } break; } } if (num == 0f) { num = 0.05f; } float num2 = num; float num3 = 1f + Flatline.loadedPlayerData.State.healthData.Predisposition; int num4 = Enum.GetNames(typeof(EQuality)).Length - 1; float num5 = Mathf.Lerp(0.95f, 1.08f, (float)quality / (float)num4); float num6 = Mathf.Clamp01(num2 * num3 * num5); DebugModule.Log("Depression subtotal consumption: " + num6, "CalculateDepressionAfterConsumeProbability"); if (Random.Range(0f, 1f) < num6) { DebugModule.Log("Depression consumption chance hits", "CalculateDepressionAfterConsumeProbability"); AddNewDisease<Depression>(Random.Range(0.001f, 0.3f)); } } public static void CalculateFallBoneBreakProbability(float fallDamage) { float num = 0f; if (fallDamage >= 20f && fallDamage <= 25f) { num += 0.2f; } else if (fallDamage > 20f && fallDamage <= 28f) { num += 0.35f; } else if (fallDamage > 28f && fallDamage <= 38f) { num += 0.65f; } else if (fallDamage > 38f) { num += 0.75f; } float weight = Player.Local.Avatar.CurrentSettings.Weight; if (weight <= 0.25f) { num += 0.005f; } else if (weight > 0.25f && weight <= 0.4f) { num += 0.015f; } else if (weight > 0.4f && weight <= 0.65f) { num += 0.03f; } else if (weight > 0.65f) { num += 0.07f; } bool flag = false; bool flag2 = false; if (!(fallDamage <= 0.12f)) { if (Player.Local.Health.CurrentHealth - fallDamage <= 0f) { FlatlineUIModule.causeOfDeath = "Fall damage"; flag2 = true; } if (!flag2 && !FlatlinePlayer.isFPRagdollActive && !Player.Local.IsRagdolled && fallDamage > 20f) { flag = true; Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.FPRagdoll(waitSleepEnd: false, null, 0))); } Player.Local.Health.TakeDamage(fallDamage, true, false); FlatlinePlayer.AppendDamageSource($"Fall damage (-{Mathf.RoundToInt(fallDamage)}HP)"); } if (!(fallDamage <= 0.18f) && Random.Range(0f, 1f) < num) { if (!flag && !flag2 && !FlatlinePlayer.isFPRagdollActive && !Player.Local.IsRagdolled) { Flatline.coros.Add(MelonCoroutines.Start(FlatlinePlayer.FPRagdoll(waitSleepEnd: false, null, 0))); } if (!FlatlinePlayer.flatlinePlayerAudio.isPlaying) { FlatlinePlayer.flatlinePlayerAudio.PlayOneShot(ConfigLoader.loadedAudios["bonebreak"]); } if (!flag2) { AddNewDisease<BoneBreak>(Random.Range(0.01f, 0.3f)); Flatline.loadedPlayerData.State.healthData.IsLegBoneBroken = true; } DebugModule.Log("Fall damage bone break chance hits", "CalculateFallBoneBreakProbability"); } } public static void CalculateImpact(Impact impact) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invali