using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Peak.Afflictions;
using Photon.Pun;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Networking;
using UnityEngine.UI;
using Zorro.Core;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace EntitiesPlus;
public static class AfflictionDialogue
{
public static readonly string[] TimedKeys = new string[26]
{
"PoisonOverTime", "InfiniteStamina", "FasterBoi", "Exhausted", "Glowing", "ColdOverTime", "Chaos", "AdjustStatus", "ClearAllStatus", "PreventPoisonHealing",
"AddBonusStamina", "DrowsyOverTime", "AdjustStatusOverTime", "Sunscreen", "BingBongShield", "ZombieBite", "Invincibility", "LowGravity", "Blind", "Numb",
"ClimbingChalk", "NoHunger", "HealAll", "DoubleJumpAmulet", "RadiateInfiniteStam", "MassSuperJump"
};
public static readonly string[] TimedNames = new string[26]
{
"poison over time", "infinite stamina", "increased speed", "exhaustion", "glowing", "cold changing over time", "chaos", "a status adjustment", "status clearing", "blocked poison recovery",
"bonus stamina", "drowsiness over time", "a status changing over time", "sunscreen", "Bing Bong's shield", "a zombie bite", "invincibility", "low gravity", "blindness", "numbness",
"climbing chalk", "hunger prevention", "healing", "a double-jump amulet", "radiating infinite stamina", "a super jump"
};
private static readonly string[] Advice = new string[15]
{
"Treat your injuries before another difficult climb. Leave yourself some stamina for a safe landing.", "Eat before hunger leaves you too little stamina to climb. Keep some food for the journey ahead.", "Get away from the cold and warm up before climbing farther. Don't let it use up all your spare stamina.", "Get away from the source of poison. It can wear off after a delay, unless another effect is preventing recovery. Rest somewhere safe while it clears.", "The game recorded crab status. I couldn't confirm where it came from. Give yourself room to recover from the other effects before taking another risk.", "Being revived at the statue comes with a cost. You didn't do anything wrong by wanting another chance. Leave room for that curse when managing your other effects.", "Rest somewhere safe while the drowsiness wears off. Avoid another dose before you've recovered, and stay close to a friend.", "Put down items you don't need. Carrying less leaves more stamina available for the climb.", "Move away from the heat and give yourself time to cool down. Wait for the effect to decrease before attempting another difficult climb.", "Avoid the spikes that caught you. Pull out the thorns, or let a friend help, before they take up more of your stamina.",
"Get away from the source of the spores. They can wear off, but don't count on recovering safely after you collapse. Stay with a friend.", "Keep clear of the webs. If you get caught, use the game's escape prompt and get help before other effects overwhelm you.", "Keep clear of the arrows' path. Remove embedded arrows or ask a friend for help before continuing.", "Avoid another source of petrification. With StatueLife, a friend's blowgun can cure your statue before you choose to shatter.", "Keep clear of the flytrap. If it catches you, use the game's escape prompt and call for help before your other effects build up."
};
public static string AdviceFor(string cause)
{
int num = Array.IndexOf(DeathDialogue.StatusKeys, cause);
if (num >= 0)
{
return Advice[num];
}
return cause switch
{
"Fall" => "Make sure to use your stamina wisely. Or this might happen again.",
"Ransom" => "When it appears make sure to halt.",
"Scoutmaster" => "Make sure to follow the rules. Never abandon a friend in need.",
_ => "",
};
}
public static string[] Contributors(float[] values)
{
if (values == null || values.Sum((float v) => Math.Max(0f, v)) <= 0.99f)
{
return new string[0];
}
return (from i in Enumerable.Range(0, Math.Min(values.Length, DeathDialogue.StatusKeys.Length))
where values[i] > 0.001f
orderby values[i] descending
select DeathDialogue.StatusKeys[i]).ToArray();
}
public static string Build(string light, string cause, string[] combined)
{
if (cause == "Combined" && combined != null && combined.Length > 0)
{
string text = string.Join(", ", combined.Select(DeathDialogue.Name).ToArray());
if (light == "Curious Light")
{
return "Oh. Let's see what killed you... " + text + " together. More than one thing this time. Good luck.";
}
if (light == "Mischievous Light")
{
return "One effect wasn't enough. " + text + " together did the job. I do enjoy cooperation.";
}
return "Welcome back. Several effects overwhelmed you together: " + text + ". " + string.Join(" ", combined.Select(AdviceFor).ToArray());
}
if (light == "Curious Light")
{
return DeathDialogue.Curious(cause);
}
if (light == "Mischievous Light")
{
return DeathDialogue.Mischievous(cause);
}
return DeathDialogue.Guiding(cause, AdviceFor(cause));
}
public static string TimedContext(string light, string key)
{
int num = Array.IndexOf(TimedKeys, key);
if (num < 0)
{
return "";
}
string text = TimedNames[num];
if (light == "Curious Light")
{
return "I also noticed " + text + " was active. That doesn't tell me it killed you.";
}
if (light == "Mischievous Light")
{
return text + " was active too. Another detail for you to wonder about. I won't explain my methods.";
}
string text2 = "That alone doesn't mean it caused your death.";
switch (key)
{
case "Blind":
text2 = "It hid your view. Wait somewhere safe until you can see again before taking a risky route.";
break;
case "Exhausted":
text2 = "It was draining your stamina. Give yourself time to recover before a difficult climb.";
break;
case "PoisonOverTime":
text2 = "It was adding poison over time. Get clear of the source and recover somewhere safe.";
break;
case "PreventPoisonHealing":
text2 = "It was blocking natural poison recovery. Don't rely on simply waiting for poison to clear while it remains.";
break;
case "ZombieBite":
text2 = "It can add spores over time. Keep away from another bite and deal with the spores before you collapse.";
break;
case "DrowsyOverTime":
text2 = "Watch the drowsiness meter and rest somewhere safe if it is increasing.";
break;
case "Numb":
text2 = "Don't let the changed feedback convince you that you're safe. Check your condition before another risky move.";
break;
case "Chaos":
text2 = "Its changes can be unpredictable. Check your condition again before committing to a climb.";
break;
case "ColdOverTime":
case "AdjustStatus":
case "AdjustStatusOverTime":
text2 = "Check which way your status meter is changing before committing to another climb.";
break;
}
return "You also had " + text + " active. " + text2;
}
}
public static class DeathDialogue
{
public static readonly string[] StatusKeys = new string[15]
{
"Injury", "Hunger", "Cold", "Poison", "Crab", "Curse", "Drowsy", "Weight", "Hot", "Thorns",
"Spores", "Web", "Arrow", "Petrify", "FlyTrap"
};
public static readonly string[] StatusNames = new string[15]
{
"injury", "hunger", "cold", "poison", "crabs", "curse", "drowsiness", "carried weight", "heat", "thorns",
"spores", "webs", "arrows", "petrification", "a flytrap"
};
private static readonly string[] Taunts = new string[15]
{
"So many injuries. I kept count. Did you?", "An empty stomach and an empty future. How fitting.", "You were shivering. I thought the silence afterward suited you better.", "Poison. Such a patient little accomplice.", "Crabs. You expected something grander, didn't you?", "A curse. Someone wished you ill. Who could that have been?", "You looked tired. I arranged a longer rest.", "You carried so much. I only needed to add a little pressure.", "Too hot? I was just getting comfortable.", "Every thorn found its place. Almost as though someone guided them.",
"Spores. You never noticed how much of the air was mine.", "Caught in a web. I do appreciate someone else's handiwork.", "An arrow found you. Such remarkable aim. Such remarkable luck.", "Stone suits you. Much easier to keep where I want you.", "The flytrap closed. You can blame the plant if that helps."
};
public static string Name(string key)
{
int num = Array.IndexOf(StatusKeys, key);
if (num >= 0)
{
return StatusNames[num];
}
return key;
}
public static string Curious(string cause)
{
return cause switch
{
"Fall" => "Oh. Let's see what killed you... A fall. I'll call that fall damage. Good luck.",
"Ransom" => "Oh. Let's see what killed you... That demanding face. I'll call it RANSOM. Good luck.",
"Scoutmaster" => "Oh. Let's see what killed you... The Scoutmaster threw you. So that is where it started. Good luck.",
"Unknown" => "Oh. You're back. I couldn't tell what killed you this time. Good luck.",
_ => "Oh. Let's see what killed you... " + Name(cause) + ". I'll remember that name. Good luck.",
};
}
public static string Mischievous(string cause)
{
int num = Array.IndexOf(StatusKeys, cause);
if (num >= 0)
{
return Taunts[num];
}
return cause switch
{
"Fall" => "You almost caught that ledge. I almost let you.",
"Ransom" => "RANSOM gave you a deadline. I was counting down too.",
"Scoutmaster" => "The Scoutmaster threw you. Yes. Let's blame him.",
_ => "Welcome back. Right on schedule. All those little accidents...",
};
}
public static string Guiding(string cause, string advice)
{
string text = "Welcome back. " + Name(cause) + " overwhelmed you.";
if (cause == "Fall")
{
text = "Hello. Welcome back. Let's see what killed you... Oh. Fall damage.";
}
if (cause == "Ransom")
{
text = "Welcome back. R4NSOM killed you.";
}
if (cause == "Scoutmaster")
{
text = "Welcome back. The Scoutmaster killed you.";
}
if (cause == "Unknown")
{
return "Hello. Welcome back. I'm glad you're here. I couldn't see exactly what happened this time. Take a breath. Your friends are still out there.";
}
return text + " " + (string.IsNullOrWhiteSpace(advice) ? "Take a breath. You're not alone here." : advice.Trim());
}
}
public sealed class DialoguePages
{
public const float CharactersPerSecond = 16f;
private string[] pages = new string[0];
private int index;
private float started;
public bool Finished => index >= pages.Length;
public string Current
{
get
{
if (pages.Length != 0)
{
return pages[Math.Min(index, pages.Length - 1)];
}
return "";
}
}
public void Start(string text, float now)
{
pages = Regex.Split(text.Trim(), "(?<=[.!?])\\s+");
index = 0;
started = now;
}
public void Tick(float now, bool clicked)
{
if (!Finished && (clicked || now - started >= (float)Current.Length / 16f + 5f))
{
index++;
started = now;
}
}
public string Visible(float now)
{
string current = Current;
return current[..Math.Max(0, Math.Min(current.Length, (int)((now - started) * 16f)))];
}
}
[BepInPlugin("local.entitiesplus", "ENTITIES PLUS", "0.1.5")]
public sealed class Plugin : BaseUnityPlugin
{
private enum Phase
{
Idle,
Warning,
Download,
Hunt,
Success,
Failure,
Death
}
internal static Plugin Instance;
internal static int FallDepth;
private Phase phase;
private Harmony harmony;
private GameObject ui;
private Image background;
private Image glow;
private Image tab;
private RawImage face;
private Text heading;
private Text body;
private Text huntTimer;
private Text huntProgress;
private Text huntPenalty;
private AudioSource music;
private AudioSource deathTunes;
private bool deathTunesWasMuted;
private Texture2D faceTexture;
private Texture2D glowTexture;
private Sprite glowSprite;
private GameObject particleLayer;
private readonly Image[] lightParticles = (Image[])(object)new Image[48];
private readonly float[] particleX = new float[48];
private readonly float[] particlePhase = new float[48];
private readonly float[] particleSpeed = new float[48];
private readonly float[] particleSize = new float[48];
private readonly Dictionary<string, AudioClip> clips = new Dictionary<string, AudioClip>();
private readonly PickupLedger ledger = new PickupLedger();
private readonly DialoguePages pages = new DialoguePages();
private bool cursorOwned;
private bool previousCursorVisible;
private string[] statusContributors = new string[0];
private string[] collapseContributors = new string[0];
private string[] timedEffects = new string[0];
private string[] collapseEffects = new string[0];
private string collapseCause;
private bool collapseRecorded;
private string overloadOrigin;
private readonly FieldInfo afflictionList = AccessTools.Field(typeof(CharacterAfflictions), "afflictionList");
private CursorLockMode previousCursorLock;
private ConfigEntry<float> gapMin;
private ConfigEntry<float> gapMax;
private ConfigEntry<float> volume;
private ConfigEntry<float> reaction;
private ConfigEntry<float> punishment;
private ConfigEntry<float> curiousChance;
private ConfigEntry<float> redChance;
private float nextEncounter;
private float phaseStart;
private float stillTime;
private float huntEnd;
private float nextPoll;
private float readyGround;
private float deathEnd;
private float lastFall = -999f;
private float lastThrow = -999f;
private float lastRansom = -999f;
private float injuryBeforeRansom;
private Vector3 lastPosition;
private Character tracked;
private bool wasDead;
private bool assetsReady;
private bool terminalFailure;
private ushort targetId;
private string targetName;
private string dialogue;
private string lightName;
private int collected;
private Color lightColor;
private string root;
private string logPath;
private readonly FieldInfo airport = AccessTools.Field(typeof(CharacterAfflictions), "m_inAirport");
public static bool DeathShowing
{
get
{
if ((Object)(object)Instance != (Object)null)
{
return Instance.phase == Phase.Death;
}
return false;
}
}
private void Awake()
{
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Expected O, but got Unknown
Instance = this;
root = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
logPath = Path.Combine(root, "EntitiesPlus-diagnostics.log");
gapMin = ((BaseUnityPlugin)this).Config.Bind<float>("RANSOM", "MinimumGapSeconds", 240f, "Minimum random gap; at least 30 seconds.");
gapMax = ((BaseUnityPlugin)this).Config.Bind<float>("RANSOM", "MaximumGapSeconds", 480f, "Maximum random gap.");
reaction = ((BaseUnityPlugin)this).Config.Bind<float>("RANSOM", "ReactionSeconds", 0.4f, "Brief grace before the one-second stillness test.");
punishment = ((BaseUnityPlugin)this).Config.Bind<float>("RANSOM", "FailureInjury", 0.65f, "Injury added on timeout, from 0 to 1.");
volume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "MusicVolume", 0.2f, "Entity music volume, from 0 to 1. Supplied loud track starts quiet.");
curiousChance = ((BaseUnityPlugin)this).Config.Bind<float>("Death", "CuriousChance", 0.08f, "Yellow appearance probability.");
redChance = ((BaseUnityPlugin)this).Config.Bind<float>("Death", "MischievousChance", 0.01f, "Red appearance probability.");
try
{
BuildUI();
music = ((Component)this).gameObject.AddComponent<AudioSource>();
music.playOnAwake = false;
music.spatialBlend = 0f;
music.loop = true;
harmony = new Harmony("local.entitiesplus");
harmony.PatchAll(typeof(Plugin).Assembly);
Schedule();
((MonoBehaviour)this).StartCoroutine(LoadAssets());
Log("ENTITIES PLUS 0.1.5 loaded. Press G during gameplay to summon RANSOM.");
((MonoBehaviour)this).StartCoroutine(PatchReport());
}
catch (Exception e)
{
FailSafe(e);
}
}
internal void Log(string text)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)text);
try
{
File.AppendAllText(logPath, DateTime.UtcNow.ToString("o") + " " + text + Environment.NewLine);
}
catch
{
}
}
private IEnumerator PatchReport()
{
yield return (object)new WaitForSecondsRealtime(10f);
foreach (MethodBase allPatchedMethod in Harmony.GetAllPatchedMethods())
{
if (!(allPatchedMethod.DeclaringType == null) && new string[7] { "CharacterMovement", "CharacterItems", "Player", "Character", "Scoutmaster", "CharacterInput", "CharacterVoiceHandler" }.Contains(allPatchedMethod.DeclaringType.Name))
{
Patches patchInfo = Harmony.GetPatchInfo(allPatchedMethod);
if (patchInfo != null && patchInfo.Owners.Contains("local.entitiesplus"))
{
Log("Hook owners " + allPatchedMethod.DeclaringType.Name + "." + allPatchedMethod.Name + ": " + string.Join(", ", patchInfo.Owners.ToArray()));
}
}
}
}
private IEnumerator LoadAssets()
{
string path = Path.Combine(root, "assets/ransom.png");
try
{
faceTexture = new Texture2D(2, 2);
if (!ImageConversion.LoadImage(faceTexture, File.ReadAllBytes(path)))
{
throw new Exception("Invalid face image");
}
face.texture = (Texture)(object)faceTexture;
}
catch (Exception ex)
{
Log("Face loading failed; encounters disabled: " + ex.Message);
yield break;
}
try
{
string[] array = new string[4] { "ransom", "guiding", "curious", "mischievous" };
foreach (string name in array)
{
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(Path.Combine(root, "assets/" + name + ".wav")).AbsoluteUri, (AudioType)20);
try
{
yield return request.SendWebRequest();
if ((int)request.result != 1)
{
Log("Audio load failed for " + name + ": " + request.error);
yield break;
}
clips[name] = DownloadHandlerAudioClip.GetContent(request);
}
finally
{
((IDisposable)request)?.Dispose();
}
}
}
finally
{
}
assetsReady = true;
Log("Face and all four music tracks loaded.");
}
private void BuildUI()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_0097: 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_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
//IL_01e2: Expected O, but got Unknown
//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0303: Expected O, but got Unknown
//IL_032a: Unknown result type (might be due to invalid IL or missing references)
//IL_0334: Expected O, but got Unknown
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_020a: Unknown result type (might be due to invalid IL or missing references)
//IL_0252: Unknown result type (might be due to invalid IL or missing references)
//IL_0257: Unknown result type (might be due to invalid IL or missing references)
//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
//IL_053e: Unknown result type (might be due to invalid IL or missing references)
//IL_054d: Unknown result type (might be due to invalid IL or missing references)
//IL_055c: Unknown result type (might be due to invalid IL or missing references)
//IL_0588: Unknown result type (might be due to invalid IL or missing references)
//IL_0597: Unknown result type (might be due to invalid IL or missing references)
//IL_05a6: Unknown result type (might be due to invalid IL or missing references)
//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
ui = new GameObject("ENTITIES PLUS overlay", new Type[3]
{
typeof(RectTransform),
typeof(Canvas),
typeof(CanvasScaler)
});
ui.transform.SetParent(((Component)this).transform, false);
Canvas component = ui.GetComponent<Canvas>();
component.renderMode = (RenderMode)0;
component.sortingOrder = 32765;
CanvasScaler component2 = ui.GetComponent<CanvasScaler>();
component2.uiScaleMode = (ScaleMode)1;
component2.referenceResolution = new Vector2(1920f, 1080f);
component2.matchWidthOrHeight = 0.5f;
background = Element<Image>("Screen", ui.transform);
Stretch(((Graphic)background).rectTransform);
tab = Element<Image>("RANSOM task window", ui.transform);
((Graphic)tab).color = new Color(0.025f, 0.005f, 0.005f, 0.95f);
Place(((Graphic)tab).rectTransform, new Vector2(1f, 1f), new Vector2(-290f, -210f), new Vector2(520f, 360f));
face = Element<RawImage>("RANSOM", ui.transform);
((Graphic)face).rectTransform.sizeDelta = new Vector2(350f, 350f);
glow = Element<Image>("Light", ui.transform);
((Graphic)glow).rectTransform.sizeDelta = new Vector2(380f, 380f);
glowTexture = new Texture2D(128, 128, (TextureFormat)4, false);
Color[] array = (Color[])(object)new Color[16384];
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 128; j++)
{
float num = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(63.5f, 63.5f)) / 64f;
ref Color reference = ref array[i * 128 + j];
reference = new Color(1f, 1f, 1f, Mathf.Pow(Mathf.Clamp01(1f - num), 2f));
}
}
glowTexture.SetPixels(array);
glowTexture.Apply();
glowSprite = Sprite.Create(glowTexture, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f));
glow.sprite = glowSprite;
particleLayer = new GameObject("Death light particles", new Type[1] { typeof(RectTransform) });
particleLayer.transform.SetParent(ui.transform, false);
Stretch((RectTransform)particleLayer.transform);
Random random = new Random(47291);
for (int k = 0; k < lightParticles.Length; k++)
{
lightParticles[k] = Element<Image>("Light mote " + k, particleLayer.transform);
lightParticles[k].sprite = glowSprite;
particleX[k] = (float)random.NextDouble();
particlePhase[k] = (float)random.NextDouble();
particleSpeed[k] = 0.025f + (float)random.NextDouble() * 0.035f;
particleSize[k] = 10f + (float)random.NextDouble() * 22f;
}
particleLayer.SetActive(false);
heading = Element<Text>("Title", ui.transform);
body = Element<Text>("Message", ui.transform);
huntTimer = Element<Text>("RANSOM time remaining", ui.transform);
huntProgress = Element<Text>("RANSOM items collected", ui.transform);
huntPenalty = Element<Text>("RANSOM penalty", ui.transform);
Font builtinResource = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
Text[] array2 = (Text[])(object)new Text[5] { heading, body, huntTimer, huntProgress, huntPenalty };
foreach (Text val in array2)
{
val.font = builtinResource;
val.alignment = (TextAnchor)4;
((Graphic)val).color = Color.white;
val.horizontalOverflow = (HorizontalWrapMode)0;
val.verticalOverflow = (VerticalWrapMode)1;
val.supportRichText = false;
}
Place(((Graphic)huntTimer).rectTransform, new Vector2(1f, 1f), new Vector2(-290f, -245f), new Vector2(460f, 65f));
huntTimer.fontSize = 44;
Place(((Graphic)huntProgress).rectTransform, new Vector2(1f, 1f), new Vector2(-290f, -298f), new Vector2(460f, 35f));
huntProgress.fontSize = 28;
Place(((Graphic)huntPenalty).rectTransform, new Vector2(1f, 1f), new Vector2(-290f, -350f), new Vector2(470f, 60f));
huntPenalty.fontSize = 18;
huntPenalty.text = "OR ALL YOUR ITEMS WILL BE DISCARDED\nWITH NO RETURN. YOU WILL TAKE DAMAGE.";
heading.fontSize = 34;
body.fontSize = 30;
ui.SetActive(false);
}
private T Element<T>(string name, Transform parent) where T : Graphic
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
GameObject val = new GameObject(name, new Type[3]
{
typeof(RectTransform),
typeof(CanvasRenderer),
typeof(T)
});
val.transform.SetParent(parent, false);
T component = val.GetComponent<T>();
((Graphic)component).raycastTarget = false;
return component;
}
private static void Stretch(RectTransform rect)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
Vector2 offsetMin = (rect.offsetMax = Vector2.zero);
rect.offsetMin = offsetMin;
}
private static void Place(RectTransform rect, Vector2 anchor, Vector2 position, Vector2 size)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: 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_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
Vector2 anchorMin = (rect.anchorMax = anchor);
rect.anchorMin = anchorMin;
rect.pivot = new Vector2(0.5f, 0.5f);
rect.anchoredPosition = position;
rect.sizeDelta = size;
}
private void Play(string name)
{
music.Stop();
music.clip = clips[name];
music.volume = Mathf.Clamp01(volume.Value);
music.Play();
}
private void StopMusic()
{
if ((Object)(object)music != (Object)null)
{
music.Stop();
}
}
private void Schedule()
{
nextEncounter = Time.time + Random.Range(Mathf.Max(30f, gapMin.Value), Mathf.Max(Mathf.Max(30f, gapMin.Value), gapMax.Value));
}
private void RestoreCursor()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
if (cursorOwned)
{
Cursor.lockState = previousCursorLock;
Cursor.visible = previousCursorVisible;
cursorOwned = false;
}
}
private void RestoreDeathTunes()
{
RestoreCursor();
if ((Object)(object)deathTunes != (Object)null)
{
deathTunes.mute = deathTunesWasMuted;
}
deathTunes = null;
}
private void QuietDeathTunes()
{
try
{
Type type = AccessTools.TypeByName("DeathTunes.DeathTunesPlugin");
PropertyInfo propertyInfo = ((type == null) ? null : AccessTools.Property(type, "AudioSource"));
if (!(propertyInfo == null) && !(propertyInfo.GetGetMethod(nonPublic: true) == null) && propertyInfo.GetGetMethod(nonPublic: true).IsStatic)
{
ref AudioSource reference = ref deathTunes;
object? value = propertyInfo.GetValue(null, null);
reference = (AudioSource)((value is AudioSource) ? value : null);
if ((Object)(object)deathTunes != (Object)null)
{
deathTunesWasMuted = deathTunes.mute;
deathTunes.mute = true;
}
}
}
catch (Exception ex)
{
Log("Optional DeathTunes integration unavailable: " + ex.Message);
}
}
private void Idle()
{
StopMusic();
RestoreDeathTunes();
phase = Phase.Idle;
ledger.Reset(0, 0f, new Guid[0]);
if ((Object)(object)ui != (Object)null)
{
ui.SetActive(false);
}
Schedule();
}
private void Begin(Phase value)
{
phase = value;
phaseStart = Time.time;
ui.SetActive(true);
}
private bool Local(Character c)
{
if ((Object)(object)c != (Object)null && c.IsLocal && (Object)(object)((MonoBehaviourPun)c).photonView != (Object)null && ((MonoBehaviourPun)c).photonView.IsMine && !c.isBot)
{
return (Object)(object)c.data != (Object)null;
}
return false;
}
private bool Airport(Character c)
{
if (airport != null)
{
return (bool)airport.GetValue(c.refs.afflictions);
}
return false;
}
private bool Ready(Character c)
{
if (Local(c) && !c.data.dead && c.data.fullyConscious && !c.data.shouldPetrify)
{
return !Airport(c);
}
return false;
}
private void Update()
{
if (terminalFailure)
{
return;
}
try
{
Tick();
}
catch (Exception e)
{
FailSafe(e);
}
}
private void FailSafe(Exception e)
{
Log("Disabled after error; no additional punishment: " + e);
terminalFailure = true;
StopMusic();
RestoreDeathTunes();
if ((Object)(object)ui != (Object)null)
{
ui.SetActive(false);
}
phase = Phase.Idle;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
private void Tick()
{
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
//IL_0345: Unknown result type (might be due to invalid IL or missing references)
//IL_034a: Unknown result type (might be due to invalid IL or missing references)
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter != (Object)(object)tracked)
{
tracked = localCharacter;
wasDead = (Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null && localCharacter.data.dead;
lastFall = (lastThrow = (lastRansom = -999f));
ResetEvidence();
Idle();
}
if (!Local(localCharacter) || !PhotonNetwork.InRoom)
{
if (phase != Phase.Idle)
{
Idle();
}
return;
}
bool dead = localCharacter.data.dead;
if (!dead && wasDead)
{
ResetEvidence();
lastFall = (lastThrow = (lastRansom = -999f));
}
if (!dead)
{
ObserveConditions(localCharacter);
}
if (dead && !wasDead && assetsReady)
{
StartDeath(localCharacter);
}
wasDead = dead;
if (phase == Phase.Death)
{
if (!dead)
{
Idle();
return;
}
Cursor.lockState = (CursorLockMode)0;
Cursor.visible = true;
bool clicked = Application.isFocused && Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame && ((Object)(object)GUIManager.instance == (Object)null || !GUIManager.instance.windowBlockingInput) && RectTransformUtility.RectangleContainsScreenPoint(((Graphic)body).rectTransform, ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue(), (Camera)null);
if (!pages.Finished)
{
pages.Tick(Time.time, clicked);
if (pages.Finished)
{
deathEnd = Time.time + 2f;
}
}
float num = (pages.Finished ? (deathEnd - Time.time) : 2f);
music.volume = Mathf.Clamp01(volume.Value) * Mathf.Clamp01(num / 2f);
if (num <= 0f)
{
Idle();
}
else
{
Render();
}
}
else if (dead)
{
if (phase != Phase.Idle)
{
Idle();
}
}
else
{
if (!assetsReady)
{
return;
}
if (localCharacter.data.fullyConscious && localCharacter.data.isGrounded)
{
readyGround += Time.deltaTime;
if (readyGround > 5f)
{
lastThrow = -999f;
if (localCharacter.refs.afflictions.GetCurrentStatus((STATUSTYPE)0) <= injuryBeforeRansom)
{
lastRansom = -999f;
}
}
}
else
{
readyGround = 0f;
}
if (phase == Phase.Idle)
{
bool flag = Keyboard.current != null && ((ButtonControl)Keyboard.current.gKey).wasPressedThisFrame;
if ((!flag && !(Time.time >= nextEncounter)) || !Ready(localCharacter) || !Application.isFocused || !((Object)(object)GUIManager.instance != (Object)null) || GUIManager.instance.windowBlockingInput || GUIManager.instance.wheelActive)
{
return;
}
if (!ChooseTarget(localCharacter))
{
nextEncounter = Time.time + 30f;
if (flag)
{
Log("RANSOM summon skipped: no matching pair of collectible items within 80m.");
}
}
else
{
lastPosition = localCharacter.Center;
stillTime = 0f;
Begin(Phase.Warning);
Log(flag ? "RANSOM summoned with G." : "RANSOM warning.");
Render();
}
return;
}
if (phase == Phase.Warning)
{
if (!Ready(localCharacter))
{
Idle();
return;
}
bool flag2 = ((Vector2)(ref localCharacter.input.movementInput)).sqrMagnitude > 0.01f || localCharacter.input.jumpWasPressed || Vector3.Distance(localCharacter.Center, lastPosition) > 0.06f;
lastPosition = localCharacter.Center;
if (Time.time - phaseStart >= Mathf.Clamp(reaction.Value, 0.1f, 2f))
{
if (flag2)
{
Begin(Phase.Download);
Log("RANSOM movement detected.");
}
else
{
stillTime += Time.deltaTime;
if (stillTime >= 1f)
{
Idle();
}
}
}
}
else if (phase == Phase.Download && Time.time - phaseStart >= 1.5f)
{
collected = 0;
huntEnd = Time.time + 60f;
ledger.Reset(targetId, huntEnd, OwnedItemIds(localCharacter));
nextPoll = Time.time;
Begin(Phase.Hunt);
Play("ransom");
Log("RANSOM target: 2 " + targetName);
}
else if (phase == Phase.Hunt)
{
if (Time.time >= huntEnd)
{
Punish(localCharacter);
}
else if (Time.time >= nextPoll)
{
nextPoll = Time.time + 0.1f;
CountPickups(localCharacter);
}
}
else if ((phase == Phase.Success || phase == Phase.Failure) && Time.time - phaseStart >= 2f)
{
Idle();
}
if (phase != Phase.Idle)
{
Render();
}
}
}
private bool ChooseTarget(Character c)
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
Dictionary<ushort, List<Item>> dictionary = new Dictionary<ushort, List<Item>>();
Item[] array = Item.ALL_ITEMS.ToArray();
foreach (Item val in array)
{
if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && val.data != null && !(val.data.guid == Guid.Empty) && (int)val.itemState == 0 && !((Object)(object)val.holderCharacter != (Object)null) && !val.blockInteraction && !(Vector3.Distance(val.Center(), c.Center) > 80f) && val.IsInteractible(c))
{
Item val2 = PickupPrefab(val);
if (!dictionary.TryGetValue(val2.itemID, out var value))
{
value = new List<Item>();
dictionary[val2.itemID] = value;
}
value.Add(val);
}
}
List<List<Item>> list = dictionary.Values.Where((List<Item> g) => g.Select((Item item) => item.data.guid).Distinct().Count() >= 2).ToList();
if (list.Count == 0)
{
return false;
}
List<Item> list2 = list[Random.Range(0, list.Count)];
Item val3 = PickupPrefab(list2[0]);
targetId = val3.itemID;
targetName = val3.GetName() ?? ((Object)val3).name;
return true;
}
private static Item PickupPrefab(Item item)
{
if (!((Object)(object)item.isSecretlyOtherItemPrefab != (Object)null))
{
return item;
}
return item.isSecretlyOtherItemPrefab;
}
private IEnumerable<Guid> OwnedItemIds(Character c)
{
foreach (ItemSlot slot in Slots(c, contents: true))
{
if (slot != null && !slot.IsEmpty() && slot.data != null)
{
yield return slot.data.guid;
}
}
Item held = c.data.currentItem;
if ((Object)(object)held != (Object)null && held.data != null)
{
yield return held.data.guid;
}
}
private IEnumerable<ItemSlot> Slots(Character c, bool contents)
{
Player player = c.player;
if ((Object)(object)player == (Object)null)
{
yield break;
}
if (player.itemSlots != null)
{
try
{
ItemSlot[] itemSlots = player.itemSlots;
for (int i = 0; i < itemSlots.Length; i++)
{
yield return itemSlots[i];
}
}
finally
{
}
}
if (player.tempFullSlot != null)
{
yield return player.tempFullSlot;
}
if (player.backpackSlot == null)
{
yield break;
}
yield return (ItemSlot)(object)player.backpackSlot;
if (!contents || ((ItemSlot)player.backpackSlot).IsEmpty())
{
yield break;
}
BackpackReference fromEquippedBackpack = BackpackReference.GetFromEquippedBackpack(c);
BackpackData data = ((BackpackReference)(ref fromEquippedBackpack)).GetData();
if (data == null || data.itemSlots == null)
{
yield break;
}
try
{
ItemSlot[] itemSlots2 = data.itemSlots;
for (int j = 0; j < itemSlots2.Length; j++)
{
yield return itemSlots2[j];
}
}
finally
{
}
}
internal void CountPickups(Character c)
{
if (phase != Phase.Hunt || !Local(c) || Time.time >= huntEnd)
{
return;
}
foreach (ItemSlot item in Slots(c, contents: true))
{
if (item != null && !item.IsEmpty() && !((Object)(object)item.prefab == (Object)null) && item.data != null)
{
RecordPickup(item.prefab.itemID, item.data.guid);
if (phase != Phase.Hunt)
{
return;
}
}
}
Item currentItem = c.data.currentItem;
if ((Object)(object)currentItem != (Object)null && currentItem.data != null && (Object)(object)currentItem.holderCharacter == (Object)(object)c)
{
RecordPickup(currentItem.itemID, currentItem.data.guid);
}
}
private void RecordPickup(ushort itemId, Guid id)
{
if (phase == Phase.Hunt && ledger.TryPickup(itemId, id, Time.time))
{
collected = ledger.Count;
Log("RANSOM pickup " + collected + "/2; itemID=" + itemId);
if (collected >= 2)
{
StopMusic();
Begin(Phase.Success);
}
}
}
internal void InventorySlotChanged(ItemSlot slot)
{
Character localCharacter = Character.localCharacter;
if (phase == Phase.Hunt && Local(localCharacter) && slot != null && !slot.IsEmpty() && slot.data != null && Slots(localCharacter, contents: true).Any((ItemSlot owned) => object.ReferenceEquals(owned, slot)))
{
RecordPickup(slot.prefab.itemID, slot.data.guid);
}
}
internal void PickupAccepted(CharacterItems items)
{
Character localCharacter = Character.localCharacter;
if (phase == Phase.Hunt && Local(localCharacter) && object.ReferenceEquals(localCharacter.refs.items, items))
{
CountPickups(localCharacter);
}
}
internal void InventorySynced(Player player)
{
Character localCharacter = Character.localCharacter;
if (phase == Phase.Hunt && Local(localCharacter) && object.ReferenceEquals(localCharacter.player, player))
{
CountPickups(localCharacter);
}
}
internal void PickupHookError(Exception error)
{
FailSafe(error);
}
private void Punish(Character c)
{
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
StopMusic();
Begin(Phase.Failure);
Log("RANSOM timed out: removing local inventory, then applying injury.");
if (!Local(c) || c.data.dead)
{
return;
}
ItemSlot[] source = (from s in Slots(c, contents: false)
where s != null && !s.IsEmpty()
select s).ToArray();
((MonoBehaviourPun)c).photonView.RPC("DestroyHeldItemRpc", (RpcTarget)0, new object[0]);
foreach (byte item in source.Select((ItemSlot s) => s.itemSlotID).Distinct())
{
c.player.EmptySlot(Optionable<byte>.Some(item), true);
}
AccessTools.Method(typeof(CharacterAfflictions), "UpdateWeight", (Type[])null, (Type[])null).Invoke(c.refs.afflictions, null);
injuryBeforeRansom = c.refs.afflictions.GetCurrentStatus((STATUSTYPE)0);
if (c.refs.afflictions.AddStatus((STATUSTYPE)0, Mathf.Clamp01(punishment.Value), false, true, true, false))
{
lastRansom = Time.time;
readyGround = 0f;
if (c.refs.afflictions.statusSum > 0.99f)
{
overloadOrigin = "Ransom";
}
}
}
internal void RecordFall(CharacterAfflictions aff, float before)
{
Character localCharacter = Character.localCharacter;
if (!Local(localCharacter) || (Object)(object)localCharacter.refs.afflictions != (Object)(object)aff)
{
return;
}
float num = aff.GetCurrentStatus((STATUSTYPE)0) - before;
if (num > 0f)
{
lastFall = Time.time;
readyGround = 0f;
if (aff.statusSum > 0.99f && aff.statusSum - num <= 0.99f)
{
overloadOrigin = "Fall";
}
}
}
internal void RecordThrow(Scoutmaster scout)
{
Character currentTarget = scout.currentTarget;
if (Local(currentTarget))
{
lastThrow = Time.time;
readyGround = 0f;
Log("Scoutmaster throw chain started.");
}
}
private void ResetEvidence()
{
collapseRecorded = false;
collapseCause = null;
overloadOrigin = null;
statusContributors = (collapseContributors = (timedEffects = (collapseEffects = new string[0])));
}
private void ObserveConditions(Character c)
{
float[] array = new float[DeathDialogue.StatusKeys.Length];
for (int i = 0; i < array.Length; i++)
{
array[i] = c.refs.afflictions.GetCurrentStatus((STATUSTYPE)i);
}
statusContributors = AfflictionDialogue.Contributors(array);
if (statusContributors.Length == 0)
{
overloadOrigin = null;
}
IEnumerable<Affliction> enumerable = ((afflictionList == null) ? null : (afflictionList.GetValue(c.refs.afflictions) as IEnumerable<Affliction>));
timedEffects = ((enumerable == null) ? new string[0] : (from e in enumerable
where e != null
select ((object)e.GetAfflictionType()).ToString()).Distinct().ToArray());
if (c.data.fullyConscious)
{
collapseRecorded = false;
collapseCause = null;
collapseContributors = (collapseEffects = new string[0]);
}
else if (!collapseRecorded)
{
CaptureCollapse(c);
}
}
internal void CaptureCollapse(Character c)
{
if (Local(c) && !c.data.dead && c.data.passedOut && !collapseRecorded)
{
float[] array = new float[DeathDialogue.StatusKeys.Length];
for (int i = 0; i < array.Length; i++)
{
array[i] = c.refs.afflictions.GetCurrentStatus((STATUSTYPE)i);
}
collapseContributors = AfflictionDialogue.Contributors(array);
IEnumerable<Affliction> enumerable = ((afflictionList == null) ? null : (afflictionList.GetValue(c.refs.afflictions) as IEnumerable<Affliction>));
collapseEffects = ((enumerable == null) ? new string[0] : (from e in enumerable
where e != null
select ((object)e.GetAfflictionType()).ToString()).Distinct().ToArray());
collapseCause = ((Time.time - lastThrow < 30f) ? "Scoutmaster" : (overloadOrigin ?? StatusCause(collapseContributors)));
collapseRecorded = true;
}
}
private static string StatusCause(string[] causes)
{
if (causes.Length <= 1)
{
if (causes.Length != 1)
{
return "Unknown";
}
return causes[0];
}
return "Combined";
}
private string Cause(Character c)
{
if (collapseRecorded && collapseCause != "Unknown")
{
return collapseCause;
}
if (Time.time - lastRansom < 120f && lastRansom >= lastFall)
{
return "Ransom";
}
if (Time.time - lastThrow < 30f)
{
return "Scoutmaster";
}
if (Time.time - lastFall < 30f)
{
return "Fall";
}
if (c.data.shouldPetrify)
{
return "Petrify";
}
return StatusCause(statusContributors);
}
private void StartDeath(Character c)
{
//IL_004f: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
string text = Cause(c);
StopMusic();
Begin(Phase.Death);
QuietDeathTunes();
float value = Random.value;
if (value < Mathf.Clamp01(redChance.Value))
{
lightName = "Mischievous Light";
lightColor = new Color(1f, 0.08f, 0.08f);
Play("mischievous");
}
else if (value < Mathf.Clamp01(redChance.Value) + Mathf.Clamp01(curiousChance.Value))
{
lightName = "Curious Light";
lightColor = new Color(1f, 0.85f, 0.15f);
Play("curious");
}
else
{
lightName = "Guiding Light";
lightColor = Color.cyan;
Play("guiding");
}
dialogue = AfflictionDialogue.Build(lightName, text, collapseRecorded ? collapseContributors : statusContributors);
string[] array = (collapseRecorded ? collapseEffects : timedEffects);
foreach (string key in array)
{
string text2 = AfflictionDialogue.TimedContext(lightName, key);
if (text2.Length > 0)
{
dialogue = dialogue + " " + text2;
}
}
pages.Start(dialogue, Time.time);
deathEnd = float.PositiveInfinity;
previousCursorLock = Cursor.lockState;
previousCursorVisible = Cursor.visible;
cursorOwned = true;
Log(lightName + " death encounter; recorded cause=" + text);
}
private void Render()
{
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_0258: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_026c: Unknown result type (might be due to invalid IL or missing references)
//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0320: Unknown result type (might be due to invalid IL or missing references)
//IL_032f: Unknown result type (might be due to invalid IL or missing references)
//IL_033e: Unknown result type (might be due to invalid IL or missing references)
//IL_035d: Unknown result type (might be due to invalid IL or missing references)
//IL_036c: Unknown result type (might be due to invalid IL or missing references)
//IL_037b: Unknown result type (might be due to invalid IL or missing references)
//IL_039b: Unknown result type (might be due to invalid IL or missing references)
//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
//IL_04dc: Unknown result type (might be due to invalid IL or missing references)
//IL_0489: Unknown result type (might be due to invalid IL or missing references)
//IL_0473: Unknown result type (might be due to invalid IL or missing references)
//IL_051a: Unknown result type (might be due to invalid IL or missing references)
//IL_057f: Unknown result type (might be due to invalid IL or missing references)
//IL_05c2: Unknown result type (might be due to invalid IL or missing references)
//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0640: Unknown result type (might be due to invalid IL or missing references)
//IL_06a8: Unknown result type (might be due to invalid IL or missing references)
//IL_0692: Unknown result type (might be due to invalid IL or missing references)
//IL_06ad: Unknown result type (might be due to invalid IL or missing references)
//IL_06ca: Unknown result type (might be due to invalid IL or missing references)
((Component)huntTimer).gameObject.SetActive(phase == Phase.Hunt);
((Component)huntProgress).gameObject.SetActive(phase == Phase.Hunt);
((Component)huntPenalty).gameObject.SetActive(phase == Phase.Hunt);
particleLayer.SetActive(phase == Phase.Death);
((Component)face).gameObject.SetActive(false);
((Component)glow).gameObject.SetActive(false);
((Component)tab).gameObject.SetActive(phase == Phase.Hunt);
heading.text = "";
body.text = "";
Place(((Graphic)heading).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0f, 240f), new Vector2(1200f, 80f));
Place(((Graphic)body).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0f, -230f), new Vector2(1200f, 160f));
((Graphic)body).color = Color.white;
((Graphic)heading).color = Color.white;
body.fontSize = 30;
body.resizeTextForBestFit = false;
if (phase == Phase.Warning)
{
((Graphic)background).color = new Color(0f, 0f, 0f, 0.2f);
((Component)face).gameObject.SetActive(true);
Place(((Graphic)face).rectTransform, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(350f, 350f));
heading.text = "HALT.";
body.text = "DO NOT MOVE";
}
else if (phase == Phase.Download)
{
((Graphic)background).color = new Color(0.5f, 0f, 0f, 0.96f);
((Component)face).gameObject.SetActive(true);
Place(((Graphic)face).rectTransform, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(350f, 350f));
heading.text = "R4NSOM";
body.text = "DOWNLOADING INTO SCOUT... " + Mathf.Min(100, Mathf.FloorToInt((Time.time - phaseStart) / 1.5f * 100f)) + "%";
}
else if (phase == Phase.Hunt)
{
((Graphic)background).color = new Color(0.65f, 0f, 0f, 0.22f);
((Component)face).gameObject.SetActive(true);
Place(((Graphic)face).rectTransform, new Vector2(1f, 1f), new Vector2(-478f, -87f), new Vector2(64f, 64f));
Place(((Graphic)heading).rectTransform, new Vector2(1f, 1f), new Vector2(-275f, -85f), new Vector2(320f, 50f));
heading.text = "R4NSOM";
((Graphic)heading).color = Color.red;
Place(((Graphic)body).rectTransform, new Vector2(1f, 1f), new Vector2(-290f, -167f), new Vector2(460f, 90f));
body.fontSize = 26;
body.resizeTextForBestFit = true;
body.resizeTextMinSize = 16;
body.resizeTextMaxSize = 26;
body.text = "FIND 2 " + targetName.ToUpperInvariant();
huntTimer.text = RansomCountdown.Display(huntEnd, Time.time) + " LEFT";
((Graphic)huntTimer).color = (Color)((huntEnd - Time.time <= 10f) ? new Color(1f, 0.35f, 0.35f) : Color.white);
huntProgress.text = ledger.Count + " / 2 COLLECTED";
}
else if (phase == Phase.Success)
{
((Graphic)background).color = new Color(0f, 0.55f, 0.1f, 0.8f);
heading.text = "YOU DID IT!";
}
else if (phase == Phase.Failure)
{
((Graphic)background).color = new Color(0.6f, 0f, 0f, 0.8f);
heading.text = "TIME'S UP.";
body.text = "YOUR ITEMS ARE GONE.";
}
else if (phase == Phase.Death)
{
float num = Mathf.Clamp01((deathEnd - Time.time) / 2f);
((Graphic)background).color = new Color(0.005f, 0.015f, 0.07f, num);
((Component)glow).gameObject.SetActive(true);
((Graphic)glow).color = new Color(lightColor.r, lightColor.g, lightColor.b, num);
float num2 = 380f + Mathf.Sin(Time.time * 2f) * 25f;
((Graphic)glow).rectTransform.sizeDelta = new Vector2(num2, num2);
RenderLightParticles(num);
heading.text = lightName;
((Graphic)heading).color = new Color(lightColor.r, lightColor.g, lightColor.b, num);
body.text = (pages.Finished ? pages.Current : pages.Visible(Time.time));
Color val = (Color)((lightName == "Guiding Light") ? new Color(0.25f, 0.55f, 1f) : lightColor);
((Graphic)body).color = new Color(val.r, val.g, val.b, num);
}
}
private void RenderLightParticles(float fade)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
Rect rect = ((RectTransform)particleLayer.transform).rect;
float num = Time.time - phaseStart;
bool flag = lightName == "Mischievous Light";
for (int i = 0; i < lightParticles.Length; i++)
{
float num2 = Mathf.Repeat(particlePhase[i] + num * particleSpeed[i] * (flag ? 1.5f : 1f), 1f);
float num3 = Mathf.Sin(num * (flag ? 1.8f : 0.45f) + (float)i * 1.7f) * (flag ? 25f : 45f);
float num4 = (particleX[i] - 0.5f) * ((Rect)(ref rect)).width + num3;
float num5 = (num2 - 0.5f) * ((Rect)(ref rect)).height;
float num6 = particleSize[i] * (flag ? 0.65f : 1f);
Place(((Graphic)lightParticles[i]).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(num4, num5), new Vector2(num6, flag ? (num6 * 1.8f) : num6));
float num7 = Mathf.Sin(num2 * (float)Math.PI);
float num8 = ((Mathf.Abs(num4) < 620f && num5 > -330f && num5 < -130f) ? 0.18f : 1f);
float num9 = 0.65f + 0.35f * Mathf.Sin(num * (flag ? 8f : 2f) + (float)i);
((Graphic)lightParticles[i]).color = new Color(lightColor.r, lightColor.g, lightColor.b, fade * num7 * num9 * num8 * 0.8f);
}
}
private void OnDisable()
{
StopMusic();
RestoreDeathTunes();
phase = Phase.Idle;
if ((Object)(object)ui != (Object)null)
{
ui.SetActive(false);
}
}
private void OnDestroy()
{
OnDisable();
if (harmony != null)
{
harmony.UnpatchSelf();
}
((MonoBehaviour)this).StopAllCoroutines();
foreach (AudioClip value in clips.Values)
{
if ((Object)(object)value != (Object)null)
{
Object.Destroy((Object)(object)value);
}
}
if ((Object)(object)ui != (Object)null)
{
Object.Destroy((Object)(object)ui);
}
if ((Object)(object)faceTexture != (Object)null)
{
Object.Destroy((Object)(object)faceTexture);
}
if ((Object)(object)glowSprite != (Object)null)
{
Object.Destroy((Object)(object)glowSprite);
}
if ((Object)(object)glowTexture != (Object)null)
{
Object.Destroy((Object)(object)glowTexture);
}
if ((Object)(object)music != (Object)null)
{
Object.Destroy((Object)(object)music);
}
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
}
}
[HarmonyPatch(typeof(CharacterMovement), "CheckFallDamage")]
internal static class FallScope
{
private static void Prefix()
{
Plugin.FallDepth++;
}
private static Exception Finalizer(Exception __exception)
{
Plugin.FallDepth = Math.Max(0, Plugin.FallDepth - 1);
return __exception;
}
}
[HarmonyPatch(typeof(CharacterAfflictions), "AddStatus", new Type[]
{
typeof(STATUSTYPE),
typeof(float),
typeof(bool),
typeof(bool),
typeof(bool),
typeof(bool)
})]
internal static class FallEvidence
{
private static void Prefix(CharacterAfflictions __instance, ref float __state)
{
if (Plugin.FallDepth > 0)
{
__state = __instance.GetCurrentStatus((STATUSTYPE)0);
}
}
private static void Postfix(CharacterAfflictions __instance, float __state)
{
if (Plugin.FallDepth > 0 && (Object)(object)Plugin.Instance != (Object)null)
{
Plugin.Instance.RecordFall(__instance, __state);
}
}
}
[HarmonyPatch(typeof(Scoutmaster), "IThrow")]
internal static class ThrowEvidence
{
private static void Postfix(Scoutmaster __instance, ref IEnumerator __result)
{
__result = Track(__instance, __result);
}
private static IEnumerator Track(Scoutmaster scout, IEnumerator original)
{
try
{
while (original.MoveNext())
{
yield return original.Current;
}
}
finally
{
if (original is IDisposable disposable)
{
disposable.Dispose();
}
}
if ((Object)(object)scout != (Object)null && (Object)(object)Plugin.Instance != (Object)null)
{
Plugin.Instance.RecordThrow(scout);
}
}
}
[HarmonyPatch(typeof(Character), "RPCA_PassOut")]
internal static class CollapseEvidence
{
private static void Postfix(Character __instance)
{
if ((Object)(object)Plugin.Instance != (Object)null)
{
Plugin.Instance.CaptureCollapse(__instance);
}
}
}
[HarmonyPatch(typeof(CharacterInput), "Sample")]
internal static class DeathInput
{
private static readonly FieldInfo[] buttons = (from f in typeof(CharacterInput).GetFields(BindingFlags.Instance | BindingFlags.Public)
where f.FieldType == typeof(bool) && f.Name != "pauseWasPressed"
select f).ToArray();
private static void Postfix(CharacterInput __instance)
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
if (Plugin.DeathShowing && !((Object)(object)Character.localCharacter == (Object)null) && object.ReferenceEquals(Character.localCharacter.input, __instance))
{
FieldInfo[] array = buttons;
foreach (FieldInfo fieldInfo in array)
{
fieldInfo.SetValue(__instance, false);
}
__instance.movementInput = Vector2.zero;
__instance.lookInput = Vector2.zero;
__instance.scrollInput = 0f;
}
}
}
[HarmonyPatch(typeof(ItemSlot), "SetItem")]
internal static class RansomSlotPickup
{
private static void Postfix(ItemSlot __instance)
{
if ((Object)(object)Plugin.Instance == (Object)null)
{
return;
}
try
{
Plugin.Instance.InventorySlotChanged(__instance);
}
catch (Exception error)
{
Plugin.Instance.PickupHookError(error);
}
}
}
[HarmonyPatch(typeof(CharacterItems), "OnPickupAccepted")]
internal static class RansomAcceptedPickup
{
private static void Prefix(CharacterItems __instance)
{
Check(__instance);
}
private static void Postfix(CharacterItems __instance)
{
Check(__instance);
}
private static void Check(CharacterItems items)
{
if ((Object)(object)Plugin.Instance == (Object)null)
{
return;
}
try
{
Plugin.Instance.PickupAccepted(items);
}
catch (Exception error)
{
Plugin.Instance.PickupHookError(error);
}
}
}
[HarmonyPatch(typeof(Player), "SyncInventoryRPC")]
internal static class RansomInventorySync
{
private static void Postfix(Player __instance)
{
if ((Object)(object)Plugin.Instance == (Object)null)
{
return;
}
try
{
Plugin.Instance.InventorySynced(__instance);
}
catch (Exception error)
{
Plugin.Instance.PickupHookError(error);
}
}
}
public sealed class PickupLedger
{
private readonly HashSet<Guid> oldItems = new HashSet<Guid>();
private readonly HashSet<Guid> picked = new HashSet<Guid>();
private ushort target;
private float deadline;
public int Count => picked.Count;
public void Reset(ushort item, float end, IEnumerable<Guid> alreadyOwned)
{
target = item;
deadline = end;
oldItems.Clear();
picked.Clear();
foreach (Guid item2 in alreadyOwned)
{
oldItems.Add(item2);
}
}
public bool TryPickup(ushort item, Guid id, float now)
{
if (now >= deadline || Count >= 2 || item != target || id == Guid.Empty || oldItems.Contains(id))
{
return false;
}
return picked.Add(id);
}
}
public static class RansomCountdown
{
public static string Display(float deadline, float now)
{
int num = (int)Math.Ceiling(Math.Max(0f, deadline - now));
return (num / 60).ToString("00") + ":" + (num % 60).ToString("00");
}
}