Decompiled source of PeakImposter v1.0.4
BepInEx/plugins/PeakImposter/PeakImposter.dll
Decompiled a day 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.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Peak; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Zorro.Core.Runtime")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PeakImposter")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.4.0")] [assembly: AssemblyInformationalVersion("1.0.4")] [assembly: AssemblyProduct("PeakImposter")] [assembly: AssemblyTitle("PeakImposter")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.4.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 PeakImposter { public static class DaggerUtil { public const string FallbackPrefabName = "RitualDagger"; private static bool _resolved; private static string _prefabName; private static ushort _itemId; public static string PrefabName { get { Resolve(); return _prefabName; } } public static ushort ItemId { get { Resolve(); return _itemId; } } public static bool Resolved { get { Resolve(); return _prefabName != null; } } public static void Invalidate() { _resolved = false; _prefabName = null; _itemId = 0; } private static void Resolve() { if (_resolved) { return; } ItemDatabase instance; try { instance = SingletonAsset<ItemDatabase>.Instance; } catch (Exception ex) { Plugin.Log.LogWarning((object)("ItemDatabase not available yet: " + ex.Message)); return; } if ((Object)(object)instance == (Object)null || instance.itemLookup == null || instance.itemLookup.Count == 0) { return; } _resolved = true; foreach (KeyValuePair<ushort, Item> item in instance.itemLookup) { Item value = item.Value; if (!((Object)(object)value == (Object)null) && !((Object)(object)((Component)value).GetComponentInChildren<RitualDaggerFeedBehavior>(true) == (Object)null)) { _prefabName = ((Object)((Component)value).gameObject).name; _itemId = item.Key; Plugin.Log.LogInfo((object)$"Ritual dagger found: '{_prefabName}' (itemID {_itemId})"); return; } } Item val = default(Item); if (ItemDatabase.TryGetItem("RitualDagger", ref val) && (Object)(object)val != (Object)null) { _prefabName = ((Object)((Component)val).gameObject).name; _itemId = val.itemID; Plugin.Log.LogWarning((object)("Ritual dagger only found by fallback name: '" + _prefabName + "'")); } else { Plugin.Log.LogError((object)"Ritual dagger not found in the ItemDatabase!"); } } public static bool IsDagger(Item item) { if ((Object)(object)item == (Object)null) { return false; } if (Resolved && item.itemID == _itemId) { return true; } return (Object)(object)((Component)item).GetComponentInChildren<RitualDaggerFeedBehavior>(true) != (Object)null; } public static bool IsDagger(ushort itemId) { if (Resolved) { return itemId == _itemId; } return false; } public static bool PlayerHasDagger(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (player.itemSlots != null) { ItemSlot[] itemSlots = player.itemSlots; foreach (ItemSlot val in itemSlots) { if (val != null && !val.IsEmpty() && IsDagger(val.prefab)) { return true; } } } if (player.tempFullSlot != null && !player.tempFullSlot.IsEmpty() && IsDagger(player.tempFullSlot.prefab)) { return true; } Character character = player.character; if ((Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && (Object)(object)character.data.currentItem != (Object)null && IsDagger(character.data.currentItem)) { return true; } return false; } } public class ImposterManager : MonoBehaviour, IOnEventCallback { private readonly Dictionary<int, int> _killsByActor = new Dictionary<int, int>(); private Coroutine _assignRoutine; private Coroutine _grantRoutine; private bool _rolesAssignedThisRun; private bool _callbacksRegistered; private float _lastCampfireHandled = -999f; private bool _rerollRunning; private Coroutine _rerollRoutine; private int _sheriffActor = -1; private const int RerollMinAlive = 2; private int _sheriffShotsLeft; private int _roleSceneHandle = -1; private readonly HashSet<int> _impostersThisRun = new HashSet<int>(); private readonly HashSet<int> _sheriffsThisRun = new HashSet<int>(); private readonly Dictionary<int, int> _correctCallsByActor = new Dictionary<int, int>(); public static ImposterManager Instance { get; private set; } public string ToastText { get; private set; } = ""; public float ToastUntil { get; private set; } public void Toast(string text, float seconds = 4f) { ToastText = text; ToastUntil = Time.time + seconds; } private void Awake() { Instance = this; } private void Update() { if (!_callbacksRegistered) { try { if (PhotonNetwork.NetworkingClient == null) { return; } PhotonNetwork.AddCallbackTarget((object)this); _callbacksRegistered = true; Plugin.Log.LogInfo((object)"Photon callbacks registered."); } catch (Exception ex) { Plugin.Log.LogDebug((object)("Photon not ready yet: " + ex.Message)); } } if (Plugin.Cfg.DebugMode.Value) { HandleDebugKeys(); } } private void OnDestroy() { if (_callbacksRegistered) { try { PhotonNetwork.RemoveCallbackTarget((object)this); } catch { } } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } public void OnRunStarted() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); int num = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle); if (!PhotonNetwork.IsMasterClient && ImposterState.Active && _roleSceneHandle == num) { Plugin.Log.LogInfo((object)"Role arrived before this client's own run start - keeping it."); } else { ImposterState.Reset(); } _killsByActor.Clear(); _impostersThisRun.Clear(); _sheriffsThisRun.Clear(); _correctCallsByActor.Clear(); _rolesAssignedThisRun = false; _lastCampfireHandled = -999f; StopReroll(); DaggerUtil.Invalidate(); SheriffBook.Invalidate(); if (!Plugin.Cfg.Enabled.Value) { Plugin.Log.LogInfo((object)"Imposter mode is disabled in the config."); return; } if (_assignRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_assignRoutine); } if (PhotonNetwork.IsMasterClient) { _assignRoutine = ((MonoBehaviour)this).StartCoroutine(InitialAssignRoutine()); } else { Plugin.Log.LogInfo((object)"Run started - waiting for the host to assign roles."); } } public void OnReturnedToAirport() { ImposterState.Reset(); _killsByActor.Clear(); _impostersThisRun.Clear(); _sheriffsThisRun.Clear(); _correctCallsByActor.Clear(); _rolesAssignedThisRun = false; StopReroll(); } private void StopReroll() { if (_rerollRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_rerollRoutine); } _rerollRoutine = null; _rerollRunning = false; } private IEnumerator InitialAssignRoutine() { float deadline = Time.realtimeSinceStartup + Plugin.Cfg.AssignTimeout.Value; yield return (object)new WaitForSecondsRealtime(2f); while (Time.realtimeSinceStartup < deadline) { int num = ((PhotonNetwork.CurrentRoom == null) ? 1 : PhotonNetwork.CurrentRoom.PlayerCount); if (PlayerHandler.GetAllPlayerCharacters().Count >= num) { break; } yield return (object)new WaitForSecondsRealtime(0.5f); } yield return (object)new WaitForSecondsRealtime(Plugin.Cfg.AssignDelay.Value); AssignRoles(isReroll: false); } private bool AssignRoles(bool isReroll) { if (!PhotonNetwork.IsMasterClient) { return false; } Character val = default(Character); List<int> list = (from a in ImposterNet.GetActivePlayerActors() where PlayerHandler.TryGetCharacter(a, ref val) select a).ToList(); List<int> list2 = list.Where(IsAlive).ToList(); int num = (isReroll ? 2 : Plugin.Cfg.MinPlayers.Value); if (list2.Count < num) { Plugin.Log.LogWarning((object)$"Not enough living players ({list2.Count}) for imposter mode."); if (!isReroll) { ImposterNet.SendAbort(Loc.T("toast.minplayers", Plugin.Cfg.MinPlayers.Value, list2.Count)); } return false; } ImposterState.ProtectionSeconds = Plugin.Cfg.ProtectionSeconds.Value; ImposterState.CooldownSeconds = Plugin.Cfg.CooldownSeconds.Value; ImposterState.InfiniteDagger = Plugin.Cfg.InfiniteDagger.Value; ImposterState.SilentKill = Plugin.Cfg.SilentKill.Value; ImposterState.HideFeedIndicator = Plugin.Cfg.HideFeedIndicator.Value; ImposterState.OnlyImposterCanKill = Plugin.Cfg.OnlyImposterCanKill.Value; float num2 = (isReroll ? Plugin.Cfg.RerollProtectionSeconds.Value : Plugin.Cfg.ProtectionSeconds.Value); float protectionEndRunTime = ImposterState.RunTime + num2; HashSet<int> previous = new HashSet<int>(ImposterState.ImposterActors); List<int> list3 = list2; if (isReroll && Plugin.Cfg.NeverSameImposterTwice.Value) { List<int> list4 = list2.Where((int a) => !previous.Contains(a)).ToList(); if (list4.Count >= Plugin.Cfg.ImposterCount.Value) { list3 = list4; } } int count = Mathf.Clamp(Plugin.Cfg.ImposterCount.Value, 1, Mathf.Max(1, list3.Count - 1)); int[] array = list3.OrderBy((int _) => Random.value).Take(count).ToArray(); ImposterState.ImposterActors.Clear(); int[] array2 = array; foreach (int item in array2) { ImposterState.ImposterActors.Add(item); _impostersThisRun.Add(item); } ImposterState.ProtectionEndRunTime = protectionEndRunTime; Plugin.Log.LogInfo((object)((isReroll ? "New imposters: " : "Imposters chosen: ") + string.Join(", ", array.Select(NameOf).ToArray()))); _sheriffActor = -1; if (Plugin.Cfg.EnableSheriff.Value && list2.Count >= Plugin.Cfg.SheriffMinPlayers.Value) { List<int> list5 = list2.Where((int a) => !ImposterState.ImposterActors.Contains(a)).ToList(); if (list5.Count > 0) { _sheriffActor = list5[Random.Range(0, list5.Count)]; _sheriffsThisRun.Add(_sheriffActor); Plugin.Log.LogInfo((object)("Sheriff: " + NameOf(_sheriffActor))); } } _sheriffShotsLeft = Plugin.Cfg.SheriffShots.Value; int num4 = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); foreach (int item2 in list) { bool num5 = ImposterState.ImposterActors.Contains(item2); Role role = (num5 ? Role.Imposter : ((item2 != _sheriffActor) ? Role.Crew : Role.Sheriff)); int[] array3 = (num5 ? array : new int[0]); int num6 = ((role == Role.Sheriff) ? _sheriffShotsLeft : 0); if (item2 == num4) { ImposterState.SheriffShotsLeft = num6; ImposterState.SheriffAimSeconds = Plugin.Cfg.SheriffAimSeconds.Value; ApplyRole(role, array3, isReroll); } else { ImposterNet.SendRole(item2, role, array3, protectionEndRunTime, isReroll, num6, Plugin.Cfg.SheriffAimSeconds.Value); } } _rolesAssignedThisRun = true; if (Plugin.Cfg.GiveDaggerOnStart.Value) { if (_grantRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_grantRoutine); } _grantRoutine = ((MonoBehaviour)this).StartCoroutine(GrantDaggersRoutine(array)); } return true; } private static bool IsAlive(int actor) { Character val = default(Character); if (PlayerHandler.TryGetCharacter(actor, ref val) && (Object)(object)val != (Object)null && (Object)(object)val.data != (Object)null) { return !val.data.dead; } return false; } private static int CountAliveActors() { return ImposterNet.GetActivePlayerActors().Count(IsAlive); } private static string NameOf(int actor) { if (ImposterState.IsDebugFake(actor)) { return ImposterState.DebugFakeName(actor); } Character val = default(Character); if (PlayerHandler.TryGetCharacter(actor, ref val) && (Object)(object)val != (Object)null) { return val.characterName; } Player val2 = ((PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.GetPlayer(actor, false) : null); if (val2 == null) { return "Scout #" + actor; } return val2.NickName; } private static bool HasRealFreeSlot(Player player) { if ((Object)(object)player == (Object)null || player.itemSlots == null) { return false; } for (int i = 0; i < player.itemSlots.Length; i++) { if (player.itemSlots[i] != null && player.itemSlots[i].IsEmpty()) { return true; } } return false; } private IEnumerator GrantDaggersRoutine(int[] actors) { float dbDeadline = Time.time + 20f; while (!DaggerUtil.Resolved && Time.time < dbDeadline) { yield return (object)new WaitForSeconds(0.5f); } if (!DaggerUtil.Resolved) { Plugin.Log.LogError((object)"Dagger not found in the ItemDatabase - cannot hand it out."); foreach (int actor in actors) { SendToast(actor, "toast.dagger.failed", 8f); } yield break; } yield return (object)new WaitForSeconds(Plugin.Cfg.DaggerSpawnDelay.Value); List<int> pending = new List<int>(actors); HashSet<int> warned = new HashSet<int>(); float deadline = Time.time + Plugin.Cfg.DaggerGrantTimeout.Value; Player val = default(Player); ItemSlot val2 = default(ItemSlot); while (pending.Count > 0 && Time.time < deadline) { if (Plugin.Cfg.GiveDaggerAfterProtection.Value && ImposterState.ProtectionActive) { yield return (object)new WaitForSeconds(1f); continue; } for (int num = pending.Count - 1; num >= 0; num--) { int num2 = pending[num]; if (!ImposterState.ImposterActors.Contains(num2)) { pending.RemoveAt(num); } else if (PlayerHandler.TryGetPlayer(num2, ref val) && !((Object)(object)val == (Object)null)) { Character character = val.character; if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null) && !character.data.dead) { if (DaggerUtil.PlayerHasDagger(val)) { Plugin.Log.LogInfo((object)(NameOf(num2) + " already has a dagger - not handing out a second one.")); SetWaiting(num2, waiting: false); pending.RemoveAt(num); } else if (!HasRealFreeSlot(val)) { if (warned.Add(num2)) { SetWaiting(num2, waiting: true); SendToast(num2, "toast.dagger.waiting", 10f); } } else if (val.AddItem(DaggerUtil.ItemId, (ItemInstanceData)null, ref val2)) { try { character.refs.items.RefreshAllCharacterCarryWeight(); } catch { } SetWaiting(num2, waiting: false); SendToast(num2, "toast.dagger.given", 6f); Plugin.Log.LogInfo((object)("Dagger handed to " + NameOf(num2) + ".")); pending.RemoveAt(num); } } } } yield return (object)new WaitForSeconds(1f); } foreach (int item in pending) { Plugin.Log.LogWarning((object)("Handing the dagger to " + NameOf(item) + " timed out.")); SendToast(item, "toast.dagger.failed", 8f); SetWaiting(item, waiting: false); } } public void HandleBookRequest(int sheriffActor) { if (!PhotonNetwork.IsMasterClient || sheriffActor != _sheriffActor || _sheriffShotsLeft <= 0) { return; } if (!SheriffBook.Resolved) { Plugin.Log.LogError((object)"No guidebook in the ItemDatabase - cannot hand out the ledger."); SendToast(sheriffActor, "toast.book.failed", 8f); } else { Player val = default(Player); if (!PlayerHandler.TryGetPlayer(sheriffActor, ref val) || (Object)(object)val == (Object)null) { return; } Character character = val.character; if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || character.data.dead) { return; } ItemSlot val2 = default(ItemSlot); if (!HasRealFreeSlot(val)) { SendToast(sheriffActor, "toast.book.waiting", 8f); } else if (val.AddItem(SheriffBook.ItemId, (ItemInstanceData)null, ref val2) && val2 != null && val2.data != null) { try { character.refs.items.RefreshAllCharacterCarryWeight(); } catch { } ManualLogSource log = Plugin.Log; string[] obj2 = new string[7] { "Ledger handed to ", NameOf(sheriffActor), " (slot ", val2.itemSlotID.ToString(), ", Guid ", null, null }; Guid guid = val2.data.guid; obj2[5] = guid.ToString(); obj2[6] = ")."; log.LogInfo((object)string.Concat(obj2)); GrantBookTo(sheriffActor, val2.itemSlotID, val2.data.guid); } } } private void GrantBookTo(int actor, byte slotId, Guid ledgerId) { if (PhotonNetwork.LocalPlayer != null && actor == PhotonNetwork.LocalPlayer.ActorNumber) { if ((Object)(object)SheriffAbility.Instance != (Object)null) { SheriffAbility.Instance.OnBookGranted(slotId, ledgerId); } } else { ImposterNet.SendBookGranted(actor, slotId, ledgerId); } } private void SendToast(int actor, string locKey, float seconds) { if (PhotonNetwork.LocalPlayer != null && actor == PhotonNetwork.LocalPlayer.ActorNumber) { Toast(Loc.T(locKey), seconds); } else { ImposterNet.SendToast(actor, locKey, seconds); } } private void SetWaiting(int actor, bool waiting) { if (PhotonNetwork.LocalPlayer != null && actor == PhotonNetwork.LocalPlayer.ActorNumber) { ImposterState.WaitingForDaggerSlot = waiting; } else { ImposterNet.SendWaiting(actor, waiting); } } private void SetCeasefire(bool on) { if (on) { if (_grantRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_grantRoutine); } _grantRoutine = null; foreach (int imposterActor in ImposterState.ImposterActors) { if (!ImposterState.IsDebugFake(imposterActor)) { SetWaiting(imposterActor, waiting: false); } } } ApplyCeasefire(on); ImposterNet.SendCeasefire(on); } private void HandleCeasefire(EventData photonEvent) { if (photonEvent.CustomData is object[] array && array.Length >= 1) { ApplyCeasefire((bool)array[0]); } } private void ApplyCeasefire(bool on) { if (ImposterState.Ceasefire != on) { ImposterState.Ceasefire = on; Plugin.Log.LogInfo((object)(on ? "Ceasefire until the re-roll." : "Ceasefire over.")); if (on && ImposterState.IsImposter) { ImposterState.WaitingForDaggerSlot = false; ((MonoBehaviour)this).StartCoroutine(RemoveOwnDagger()); Toast(Loc.T("toast.ceasefire.imposter"), 6f); } } } private IEnumerator RemoveOwnDagger() { Character c = Character.localCharacter; if ((Object)(object)c == (Object)null || (Object)(object)c.player == (Object)null) { yield break; } if ((Object)(object)c.data != (Object)null && (Object)(object)c.data.currentItem != (Object)null && DaggerUtil.IsDagger(c.data.currentItem)) { c.refs.items.EquipSlot(Optionable<byte>.None); yield return (object)new WaitForSeconds(0.5f); } ItemSlot[] itemSlots = c.player.itemSlots; for (byte b = 0; b < itemSlots.Length; b++) { ItemSlot val = itemSlots[b]; if (val != null && !val.IsEmpty() && !((Object)(object)val.prefab == (Object)null) && DaggerUtil.IsDagger(val.prefab)) { c.player.EmptySlot(Optionable<byte>.Some(b), true); Plugin.Log.LogInfo((object)("Removed own dagger from slot " + b + ".")); } } } public void OnCampfireLit(bool advancesBiome, Vector3 campfirePosition) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if (!advancesBiome || !PhotonNetwork.IsMasterClient || !_rolesAssignedThisRun || _rerollRunning || Time.time - _lastCampfireHandled < 10f) { return; } _lastCampfireHandled = Time.time; List<Character> list = Character.AllCharacters.Where((Character c) => (Object)(object)c != (Object)null && (Object)(object)c.data != (Object)null && !c.data.dead && (Object)(object)((MonoBehaviourPun)c).photonView != (Object)null && ((MonoBehaviourPun)c).photonView.Owner != null).ToList(); bool flag = list.Count > 0 && ImposterState.ImposterActors.Count > 0 && list.All((Character c) => ImposterState.ImposterActors.Contains(((MonoBehaviourPun)c).photonView.Owner.ActorNumber)); SpawnConsolationItems(campfirePosition, !flag); if (flag) { Plugin.Log.LogInfo((object)"Imposter was the sole survivor - reward goes to them."); foreach (Character item in list) { Reward(((MonoBehaviourPun)item).photonView.Owner.ActorNumber); } } else if (Plugin.Cfg.RewardSurvivingScouts.Value) { Plugin.Log.LogInfo((object)"Scouts made it through the biome - reward goes to them."); foreach (Character item2 in list) { int actorNumber = ((MonoBehaviourPun)item2).photonView.Owner.ActorNumber; if (!ImposterState.ImposterActors.Contains(actorNumber)) { Reward(actorNumber); } } } if (Plugin.Cfg.RerollAtCampfire.Value) { if (Plugin.Cfg.CeasefireAtCampfire.Value) { SetCeasefire(on: true); } _rerollRoutine = ((MonoBehaviour)this).StartCoroutine(RerollRoutine()); } } private unsafe void SpawnConsolationItems(Vector3 center, bool scoutsSurvived) { //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Cfg.ConsolationItems.Value || !PhotonNetwork.IsMasterClient) { return; } int num = Mathf.Clamp(((PhotonNetwork.CurrentRoom == null) ? 1 : PhotonNetwork.CurrentRoom.PlayerCount) * Plugin.Cfg.ConsolationItemsPerPlayer.Value, 0, 24); if (num <= 0) { return; } SpawnPool val = ToSpawnPool(Plugin.Cfg.ConsolationItemPool.Value); Rarity val2 = (scoutsSurvived ? Plugin.Cfg.ConsolationMinRarityOnSuccess.Value : Plugin.Cfg.ConsolationMinRarityOnWipe.Value); List<GameObject> list; try { list = (((int)val2 > 0) ? PickByRarity(val, val2, num) : null) ?? LootData.GetRandomItems(val, num, true, (GameObject)null); } catch (Exception ex) { Plugin.Log.LogError((object)("Consolation items: loot table not readable - " + ex.Message)); return; } if (list == null) { return; } Plugin.Log.LogInfo((object)("Consolation items: " + (scoutsSurvived ? "scouts survived" : "imposter wiped the group") + ", minimum rarity " + ((object)(*(Rarity*)(&val2))/*cast due to .constrained prefix*/).ToString() + ".")); int num2 = 0; foreach (GameObject item in list) { if (!((Object)(object)item == (Object)null)) { float num3 = Random.value * MathF.PI * 2f; float num4 = Random.Range(1.4f, 3.2f); Vector3 val3 = center + new Vector3(Mathf.Cos(num3) * num4, 1.3f, Mathf.Sin(num3) * num4); try { PhotonNetwork.Instantiate("0_Items/" + ((Object)item).name, val3, Quaternion.identity, (byte)0, (object[])null); num2++; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Consolation item '" + ((Object)item).name + "' could not be spawned: " + ex2.Message)); } } } if (num2 > 0) { Plugin.Log.LogInfo((object)$"Spawned {num2} consolation items at the campfire."); ImposterNet.SendToastAll("toast.consolation", 7f); } if (scoutsSurvived && Plugin.Cfg.BonusItemOnSuccess.Value) { SpawnBonusItem(center); } } private static SpawnPool ToSpawnPool(LootPool pool) { return (SpawnPool)(pool switch { LootPool.AllItems => 134217728, LootPool.RespawnChest => 131072, LootPool.AncientLuggage => 32768, _ => 33554432, }); } private unsafe void SpawnBonusItem(Vector3 center) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) SpawnPool pool = ToSpawnPool(Plugin.Cfg.BonusItemPool.Value); Rarity val = Plugin.Cfg.BonusItemMinRarity.Value; while ((int)val >= 0) { List<GameObject> list; try { list = PickByRarity(pool, val, 1); } catch (Exception ex) { Plugin.Log.LogError((object)("Bonus item: loot table not readable - " + ex.Message)); return; } if (list == null || list.Count == 0 || (Object)(object)list[0] == (Object)null) { if ((int)val == 0) { break; } val = (Rarity)(val - 1); continue; } GameObject val2 = list[0]; Vector3 val3 = center + new Vector3(0f, 1.6f, 0f); try { PhotonNetwork.Instantiate("0_Items/" + ((Object)val2).name, val3, Quaternion.identity, (byte)0, (object[])null); Plugin.Log.LogInfo((object)("Spawned bonus item '" + ((Object)val2).name + "' (" + ((object)(*(Rarity*)(&val))/*cast due to .constrained prefix*/).ToString() + ") at the campfire.")); ImposterNet.SendToastAll("toast.bonus", 7f); return; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Bonus item '" + ((Object)val2).name + "' could not be spawned: " + ex2.Message)); return; } } Plugin.Log.LogWarning((object)("No bonus item found - pool " + ((object)(*(SpawnPool*)(&pool))/*cast due to .constrained prefix*/).ToString() + " is empty.")); } private unsafe static List<GameObject> PickByRarity(SpawnPool pool, Rarity minRarity, int count) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) List<Item> list = (from item in LootData.GetAllItemsInPool(pool) where (Object)(object)item != (Object)null select item).Where(delegate(Item item) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) LootData component = ((Component)item).GetComponent<LootData>(); return (Object)(object)component != (Object)null && component.Rarity >= minRarity && component.IsValidToSpawn(); }).ToList(); if (list.Count == 0) { Plugin.Log.LogWarning((object)("No items of rarity " + ((object)(*(Rarity*)(&minRarity))/*cast due to .constrained prefix*/).ToString() + " or higher in the pool - falling back to the default selection.")); return null; } List<GameObject> list2 = new List<GameObject>(); for (int num = 0; num < count; num++) { list2.Add(((Component)list[Random.Range(0, list.Count)]).gameObject); } return list2; } private void Reward(int actor) { if (PhotonNetwork.LocalPlayer != null && actor == PhotonNetwork.LocalPlayer.ActorNumber) { ApplyReward(); } else { ImposterNet.SendReward(actor); } } private IEnumerator RerollRoutine() { _rerollRunning = true; try { yield return (object)new WaitForSeconds(Plugin.Cfg.RerollDelay.Value); bool flag = PhotonNetwork.CurrentRoom == null || PhotonNetwork.CurrentRoom.PlayerCount <= 1; if (ImposterState.DebugDummies.Count > 0 && !flag) { Plugin.Log.LogWarning((object)"DEBUG: other players joined - dummies discarded, doing a real re-roll."); ImposterState.DebugDummies.Clear(); } if (ImposterState.DebugDummies.Count > 0) { ImposterNet.SendRerollAnnounce(); yield return (object)new WaitForSeconds(Plugin.Cfg.RerollAnnounceLead.Value); SimulateAssignment(isReroll: true); yield break; } float deadline = Time.time + Plugin.Cfg.RerollWaitForRevives.Value; while (Time.time < deadline && CountAliveActors() < Plugin.Cfg.MinPlayers.Value) { yield return (object)new WaitForSeconds(2f); } bool postponedLogged = false; while (true) { if (!_rolesAssignedThisRun) { yield break; } if (CountAliveActors() < 2) { if (!postponedLogged) { Plugin.Log.LogWarning((object)"Only one player alive - re-roll postponed until someone is revived."); postponedLogged = true; } yield return (object)new WaitForSeconds(2f); } else { ImposterNet.SendRerollAnnounce(); yield return (object)new WaitForSeconds(Plugin.Cfg.RerollAnnounceLead.Value); if (AssignRoles(isReroll: true)) { break; } } } SetCeasefire(on: false); } finally { ImposterManager imposterManager = this; imposterManager._rerollRunning = false; imposterManager._rerollRoutine = null; } } private void ApplyReward() { Character localCharacter = Character.localCharacter; if (!((Object)(object)localCharacter == (Object)null) && localCharacter.refs != null && !((Object)(object)localCharacter.refs.afflictions == (Object)null)) { localCharacter.refs.afflictions.ClearAllStatus(true, true); localCharacter.refs.afflictions.UpdateWeight(); localCharacter.AddStamina(1f); ImposterUI.ShowAnnouncement(Loc.T("reward.title"), Loc.T("reward.sub"), positive: true); Plugin.Log.LogInfo((object)"Sole survivor reward applied."); } } public void OnEvent(EventData photonEvent) { switch (photonEvent.Code) { case 171: HandleRole(photonEvent); break; case 172: HandleKillReport(photonEvent); break; case 173: HandleReveal(photonEvent); break; case 174: HandleAbort(photonEvent.CustomData as string); break; case 175: HandleRerollAnnounce(); break; case 176: ApplyReward(); break; case 177: HandleToast(photonEvent); break; case 178: HandleWaiting(photonEvent); break; case 179: HandleAccuse(photonEvent); break; case 180: HandleExecute(photonEvent); break; case 181: HandleAccuseResult(photonEvent); break; case 182: HandleBookRequest(photonEvent.Sender); break; case 183: HandleBookGranted(photonEvent); break; case 170: HandleCeasefire(photonEvent); break; } } private void HandleRole(EventData photonEvent) { if (!ImposterNet.TryReadRole(photonEvent.CustomData, out var role, out var imposters, out var isReroll)) { Plugin.Log.LogError((object)"Could not read the role event."); } else { ApplyRole(role, imposters, isReroll); } } private void ApplyRole(Role role, int[] imposters, bool isReroll) { //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: 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) if (!isReroll && ImposterState.Active && ImposterState.LocalRole == role) { Plugin.Log.LogWarning((object)"Role was already set - ignoring duplicate event."); return; } bool isImposter = ImposterState.IsImposter; bool isSheriff = ImposterState.IsSheriff; if (isReroll) { ImposterState.ResetForReroll(); } ImposterState.Ceasefire = false; ImposterState.Active = true; ImposterState.LocalRole = role; ImposterState.LastKillTime = -99999f; ImposterState.FellowImposters.Clear(); if (role == Role.Imposter && imposters != null) { int num = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); int[] array = imposters; foreach (int num2 in array) { if (num2 != num && !ImposterState.FellowImposters.Contains(num2)) { ImposterState.FellowImposters.Add(num2); } } } if (!PhotonNetwork.IsMasterClient) { ImposterState.ImposterActors.Clear(); if (role == Role.Imposter) { int[] array = imposters; foreach (int item in array) { ImposterState.ImposterActors.Add(item); } } } if (isImposter && role != Role.Imposter && Plugin.Cfg.TakeDaggerBackOnReroll.Value) { ((MonoBehaviour)this).StartCoroutine(RemoveOwnDagger()); } if (isSheriff && role != Role.Sheriff && (Object)(object)SheriffAbility.Instance != (Object)null) { SheriffAbility.Instance.Stow(); } Scene activeScene = SceneManager.GetActiveScene(); _roleSceneHandle = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle); Plugin.Log.LogInfo((object)("Role received: " + role.ToString() + (isReroll ? " (re-roll)" : ""))); ((MonoBehaviour)this).StartCoroutine(ShowRoleCardWhenReady(role, imposters, isReroll)); } private IEnumerator ShowRoleCardWhenReady(Role role, int[] imposters, bool isReroll) { bool withIntro = !isReroll || Plugin.Cfg.IntroOnReroll.Value; ImposterUI.RoleCardPending = true; try { float guard = Time.realtimeSinceStartup + 60f; while ((LoadingScreenHandler.loading || (Object)(object)Character.localCharacter == (Object)null) && Time.realtimeSinceStartup < guard) { yield return null; } if (ImposterState.LocalRole == role) { Character localCharacter = Character.localCharacter; if (withIntro && (Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null && localCharacter.data.dead) { withIntro = false; } ImposterUI.ShowRoleCard(role, imposters, withIntro, isReroll); } } finally { ImposterUI.RoleCardPending = false; } } private void HandleRerollAnnounce() { ImposterUI.ShowAnnouncement(Loc.T("reroll.title"), Loc.T("reroll.sub"), positive: false); } private void HandleToast(EventData photonEvent) { if (photonEvent.CustomData is object[] array && array.Length >= 2) { Toast(Loc.T((array[0] as string) ?? ""), (float)array[1]); } } private void HandleWaiting(EventData photonEvent) { if (photonEvent.CustomData is object[] array && array.Length >= 1) { ImposterState.WaitingForDaggerSlot = (bool)array[0]; } } private void HandleAccuse(EventData photonEvent) { if (photonEvent.CustomData is object[] array && array.Length >= 1) { SubmitAccusation(photonEvent.Sender, (int)array[0]); } } public void SubmitAccusation(int sheriff, int target) { if (!PhotonNetwork.IsMasterClient) { return; } if (sheriff != _sheriffActor) { Plugin.Log.LogWarning((object)("Accusation from actor " + sheriff + ", who is not the sheriff - ignored.")); } else { if (_sheriffShotsLeft <= 0) { return; } _sheriffShotsLeft--; bool flag = ImposterState.ImposterActors.Contains(target); Plugin.Log.LogInfo((object)("Sheriff " + NameOf(sheriff) + " accuses " + NameOf(target) + " -> " + (flag ? "imposter" : "innocent"))); SendAccuseResultTo(sheriff, flag, _sheriffShotsLeft); if (flag) { if (!_correctCallsByActor.ContainsKey(sheriff)) { _correctCallsByActor[sheriff] = 0; } _correctCallsByActor[sheriff]++; Execute(target, 0); if (Plugin.Cfg.SheriffAnnounceHit.Value) { ImposterNet.SendToastAll("sheriff.announce", 8f); } } else if (Plugin.Cfg.SheriffDiesOnMisfire.Value) { Execute(sheriff, 1); } } } private void Execute(int actor, byte reason) { if (ImposterState.IsDebugFake(actor)) { ImposterState.DebugDummies.Remove(actor); Plugin.Log.LogInfo((object)("DEBUG: " + NameOf(actor) + " executed (reason " + reason + ").")); } else if (PhotonNetwork.LocalPlayer != null && actor == PhotonNetwork.LocalPlayer.ActorNumber) { ApplyExecution(reason); } else { ImposterNet.SendExecute(actor, reason); } } private void SendAccuseResultTo(int actor, bool guilty, int shotsLeft) { if (PhotonNetwork.LocalPlayer != null && actor == PhotonNetwork.LocalPlayer.ActorNumber) { ApplyAccuseResult(guilty, shotsLeft); } else { ImposterNet.SendAccuseResult(actor, guilty, shotsLeft); } } private void HandleBookGranted(EventData photonEvent) { if (photonEvent.CustomData is object[] array && array.Length >= 2 && Guid.TryParse(array[1] as string, out var result) && (Object)(object)SheriffAbility.Instance != (Object)null) { SheriffAbility.Instance.OnBookGranted((byte)array[0], result); } } private void HandleExecute(EventData photonEvent) { byte reason = (byte)((photonEvent.CustomData is object[] array && array.Length != 0) ? ((byte)array[0]) : 0); ApplyExecution(reason); } private void ApplyExecution(byte reason) { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { return; } Toast(Loc.T((reason == 0) ? "sheriff.executed" : "sheriff.misfire.death"), 8f); Plugin.Log.LogInfo((object)("Executed by the sheriff (reason " + reason + ").")); try { localCharacter.DieInstantly(); } catch (Exception ex) { Plugin.Log.LogError((object)("Execution failed: " + ex.Message)); } } private void HandleAccuseResult(EventData photonEvent) { if (photonEvent.CustomData is object[] array && array.Length >= 2) { ApplyAccuseResult((bool)array[0], (int)array[1]); } } private void ApplyAccuseResult(bool guilty, int shotsLeft) { ImposterState.SheriffShotsLeft = shotsLeft; if ((Object)(object)SheriffAbility.Instance != (Object)null) { SheriffAbility.Instance.Cancel(); } if (guilty) { ImposterUI.ShowAnnouncement(Loc.T("sheriff.hit.title"), Loc.T("sheriff.hit.sub"), positive: true); } else if (!Plugin.Cfg.SheriffDiesOnMisfire.Value) { Toast(Loc.T("sheriff.misfire"), 6f); } } private void HandleKillReport(EventData photonEvent) { int victim = ((photonEvent.CustomData is object[] array && array.Length != 0) ? ((int)array[0]) : (-1)); CountKill(photonEvent.Sender, victim); } private void CountKill(int killer, int victim) { if (PhotonNetwork.IsMasterClient) { if (!_killsByActor.ContainsKey(killer)) { _killsByActor[killer] = 0; } _killsByActor[killer]++; Plugin.Log.LogInfo((object)("Kill reported: " + NameOf(killer) + " -> " + NameOf(victim))); } } private void HandleReveal(EventData photonEvent) { if (ImposterNet.TryReadReveal(photonEvent.CustomData, out var outcome, out var imposterEntries, out var sheriffEntries)) { string text = Loc.T(outcome switch { 1 => "reveal.crewwon", 0 => "reveal.imposterwon", _ => "reveal.nobodywon", }); string text2 = Loc.T("reveal.imposters", (imposterEntries.Length != 0) ? string.Join(", ", imposterEntries) : "-"); text2 = text2 + "\n" + ((sheriffEntries.Length != 0) ? Loc.T("reveal.sheriffs", string.Join(", ", sheriffEntries)) : Loc.T("reveal.nosheriff")); ImposterState.Active = false; ImposterUI.ShowReveal(text, text2, outcome == 0); Plugin.Log.LogInfo((object)("Reveal shown: " + text)); } } private void HandleAbort(string reason) { ImposterState.Reset(); if (!string.IsNullOrEmpty(reason)) { Plugin.Log.LogInfo((object)("Imposter mode aborted: " + reason)); Toast(reason, 8f); } } public void RegisterLocalKill(Character victim) { ImposterState.LastKillTime = Time.time; ImposterState.LocalKills++; int num = -1; if ((Object)(object)victim != (Object)null && (Object)(object)((MonoBehaviourPun)victim).photonView != (Object)null && ((MonoBehaviourPun)victim).photonView.Owner != null) { num = ((MonoBehaviourPun)victim).photonView.Owner.ActorNumber; } if (PhotonNetwork.IsMasterClient && PhotonNetwork.LocalPlayer != null) { CountKill(PhotonNetwork.LocalPlayer.ActorNumber, num); } else { ImposterNet.ReportKill(num); } Toast(Loc.T("toast.kill", ImposterState.FormatTime(ImposterState.CooldownSeconds)), 6f); Plugin.Log.LogInfo((object)("Local kill registered (victim actor " + num + ").")); } public void OnGameEnded() { if (!PhotonNetwork.IsMasterClient || !_rolesAssignedThisRun) { return; } bool flag = false; bool flag2 = false; foreach (Character allCharacter in Character.AllCharacters) { if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)((MonoBehaviourPun)allCharacter).photonView == (Object)null) && ((MonoBehaviourPun)allCharacter).photonView.Owner != null && Character.CheckWinCondition(allCharacter)) { if (ImposterState.ImposterActors.Contains(((MonoBehaviourPun)allCharacter).photonView.Owner.ActorNumber)) { flag = true; } else { flag2 = true; } } } byte outcome = (byte)(flag2 ? 1 : ((!flag) ? 2 : 0)); string[] array = (from a in _impostersThisRun.OrderByDescending(CountKills) select NameOf(a) + " (" + CountKills(a) + ")").ToArray(); string[] array2 = (from a in _sheriffsThisRun.OrderByDescending(CountCalls) select NameOf(a) + " (" + CountCalls(a) + ")").ToArray(); Plugin.Log.LogInfo((object)("Run ended, outcome " + outcome + " | Imposter: " + string.Join(", ", array) + " | Sheriffs: " + string.Join(", ", array2))); ImposterNet.SendReveal(outcome, array, array2); } private int CountKills(int actor) { if (!_killsByActor.TryGetValue(actor, out var value)) { return 0; } return value; } private int CountCalls(int actor) { if (!_correctCallsByActor.TryGetValue(actor, out var value)) { return 0; } return value; } private void SimulateAssignment(bool isReroll) { if (!PhotonNetwork.IsMasterClient || PhotonNetwork.LocalPlayer == null) { return; } if (PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.PlayerCount > 1) { Plugin.Log.LogWarning((object)("DEBUG: dummy simulation only works while alone in the lobby - " + PhotonNetwork.CurrentRoom.PlayerCount + " players present.")); Toast(Loc.T("debug.dummies.alone"), 5f); return; } int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; if (!isReroll || ImposterState.DebugDummies.Count == 0) { ImposterState.DebugDummies.Clear(); int num = Mathf.Clamp(Plugin.Cfg.DebugDummyCount.Value, 1, 11); for (int i = 1; i <= num; i++) { ImposterState.DebugDummies.Add(-100 - i); } } List<int> list = new List<int>(ImposterState.DebugDummies); List<int> list2 = new List<int> { actorNumber }; list2.AddRange(list); DebugRole value = Plugin.Cfg.DebugForceRole.Value; int num2 = Mathf.Clamp(Plugin.Cfg.ImposterCount.Value, 1, Mathf.Max(1, list2.Count - 1)); List<int> imposters; switch (value) { case DebugRole.Imposter: imposters = new List<int> { actorNumber }; imposters.AddRange(list.OrderBy((int _) => Random.value).Take(num2 - 1)); break; case DebugRole.Random: imposters = list2.OrderBy((int _) => Random.value).Take(num2).ToList(); break; default: imposters = list.OrderBy((int _) => Random.value).Take(num2).ToList(); break; } int num3 = -1; bool flag = Plugin.Cfg.EnableSheriff.Value && list2.Count >= Plugin.Cfg.SheriffMinPlayers.Value; List<int> list3 = list2.Where((int a) => !imposters.Contains(a)).ToList(); if (value == DebugRole.Sheriff) { if (flag) { num3 = actorNumber; } else { Plugin.Log.LogWarning((object)("DEBUG: sheriff forced, but EnableSheriff is off or " + list2.Count + " players < SheriffMinPlayers - you become a scout.")); } } else if (flag) { if (value == DebugRole.Scout) { list3.Remove(actorNumber); } if (list3.Count > 0) { num3 = list3[Random.Range(0, list3.Count)]; } } ImposterState.ProtectionSeconds = Plugin.Cfg.ProtectionSeconds.Value; ImposterState.CooldownSeconds = Plugin.Cfg.CooldownSeconds.Value; ImposterState.InfiniteDagger = Plugin.Cfg.InfiniteDagger.Value; ImposterState.SilentKill = Plugin.Cfg.SilentKill.Value; ImposterState.HideFeedIndicator = Plugin.Cfg.HideFeedIndicator.Value; ImposterState.OnlyImposterCanKill = Plugin.Cfg.OnlyImposterCanKill.Value; ImposterState.ProtectionEndRunTime = ImposterState.RunTime + (isReroll ? Plugin.Cfg.RerollProtectionSeconds.Value : Plugin.Cfg.ProtectionSeconds.Value); ImposterState.ImposterActors.Clear(); foreach (int item in imposters) { ImposterState.ImposterActors.Add(item); _impostersThisRun.Add(item); } _sheriffActor = num3; if (num3 >= 0 || ImposterState.IsDebugFake(num3)) { _sheriffsThisRun.Add(num3); } _sheriffShotsLeft = Plugin.Cfg.SheriffShots.Value; _rolesAssignedThisRun = true; Role role = (imposters.Contains(actorNumber) ? Role.Imposter : ((num3 != actorNumber) ? Role.Crew : Role.Sheriff)); ImposterState.SheriffShotsLeft = ((role == Role.Sheriff) ? _sheriffShotsLeft : 0); ImposterState.SheriffAimSeconds = Plugin.Cfg.SheriffAimSeconds.Value; Plugin.Log.LogInfo((object)("DEBUG simulation" + (isReroll ? " (re-roll)" : "") + ": " + list2.Count + " players | imposters: " + string.Join(", ", imposters.Select(NameOf).ToArray()) + " | Sheriff: " + ((num3 == -1) ? "-" : NameOf(num3)) + " | you: " + role)); Toast(Loc.T("debug.dummies", list2.Count, Loc.T(role switch { Role.Sheriff => "role.sheriff", Role.Imposter => "role.imposter", _ => "role.crew", })), 6f); if (!isReroll) { ImposterState.Active = false; } ApplyRole(role, (role == Role.Imposter) ? imposters.ToArray() : new int[0], isReroll); if (role == Role.Imposter && Plugin.Cfg.GiveDaggerOnStart.Value) { if (_grantRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_grantRoutine); } _grantRoutine = ((MonoBehaviour)this).StartCoroutine(GrantDaggersRoutine(new int[1] { actorNumber })); } } private unsafe static bool Pressed(Keyboard kb, Key key) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) KeyControl val = kb[key]; if (val == null || !((ButtonControl)val).wasPressedThisFrame) { return false; } Plugin.Log.LogInfo((object)("Debug key " + ((object)(*(Key*)(&key))/*cast due to .constrained prefix*/).ToString() + " pressed.")); return true; } private void HandleDebugKeys() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { return; } if (Pressed(current, Plugin.Cfg.DebugKeyImposter.Value)) { ImposterState.Active = true; ImposterState.LocalRole = Role.Imposter; ImposterState.ProtectionEndRunTime = ImposterState.RunTime + Plugin.Cfg.ProtectionSeconds.Value; ImposterState.LastKillTime = -99999f; if (PhotonNetwork.LocalPlayer != null) { ImposterState.ImposterActors.Add(PhotonNetwork.LocalPlayer.ActorNumber); _impostersThisRun.Add(PhotonNetwork.LocalPlayer.ActorNumber); } _rolesAssignedThisRun = true; ImposterUI.ShowRoleCard(Role.Imposter, ImposterState.ImposterActors.ToArray(), withIntro: true); Toast(Loc.T("debug.imposter")); if (PhotonNetwork.IsMasterClient && DaggerUtil.Resolved && PhotonNetwork.LocalPlayer != null) { ((MonoBehaviour)this).StartCoroutine(GrantDaggersRoutine(new int[1] { PhotonNetwork.LocalPlayer.ActorNumber })); } } if (Pressed(current, Plugin.Cfg.DebugKeyDummies.Value) && PhotonNetwork.IsMasterClient) { SimulateAssignment(isReroll: false); } if (Pressed(current, Plugin.Cfg.DebugKeySheriff.Value)) { ImposterState.Active = true; ImposterState.LocalRole = Role.Sheriff; ImposterState.SheriffShotsLeft = Plugin.Cfg.SheriffShots.Value; ImposterState.SheriffAimSeconds = Plugin.Cfg.SheriffAimSeconds.Value; if (PhotonNetwork.LocalPlayer != null) { _sheriffActor = PhotonNetwork.LocalPlayer.ActorNumber; _sheriffsThisRun.Add(_sheriffActor); } _sheriffShotsLeft = ImposterState.SheriffShotsLeft; _rolesAssignedThisRun = true; ImposterUI.ShowRoleCard(Role.Sheriff, new int[0], withIntro: true); Toast(Loc.T("debug.sheriff")); } if (Pressed(current, Plugin.Cfg.DebugKeySkip.Value)) { ImposterState.ProtectionEndRunTime = 0f; ImposterState.LastKillTime = -99999f; Toast(Loc.T("debug.protection")); } if (Pressed(current, Plugin.Cfg.DebugKeyKill.Value)) { Toast(Loc.T("debug.kill")); try { Character.Die(); } catch (Exception ex) { Plugin.Log.LogError((object)("Instakill failed: " + ex.Message)); } } if (Pressed(current, Plugin.Cfg.DebugKeyReroll.Value) && PhotonNetwork.IsMasterClient) { Toast(Loc.T("debug.reroll")); Vector3 campfirePosition = (((Object)(object)Character.localCharacter != (Object)null) ? Character.localCharacter.Center : Vector3.zero); OnCampfireLit(advancesBiome: true, campfirePosition); } } } public static class ImposterNet { public const byte EvtRole = 171; public const byte EvtKill = 172; public const byte EvtReveal = 173; public const byte EvtAbort = 174; public const byte EvtReroll = 175; public const byte EvtReward = 176; public const byte EvtToast = 177; public const byte EvtWaiting = 178; public const byte EvtAccuse = 179; public const byte EvtExecute = 180; public const byte EvtAccuseResult = 181; public const byte EvtBookRequest = 182; public const byte EvtBookGranted = 183; public const byte EvtCeasefire = 170; private static readonly SendOptions Reliable = SendOptions.SendReliable; public const byte OutcomeImposter = 0; public const byte OutcomeScouts = 1; public const byte OutcomeNobody = 2; private static void Raise(byte code, object content, RaiseEventOptions options) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom) { PhotonNetwork.RaiseEvent(code, content, options, Reliable); } } public static void SendRole(int targetActor, Role role, int[] imposterActors, float protectionEndRunTime, bool isReroll, int sheriffShots, float sheriffAimSeconds) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown object[] content = new object[12] { (byte)role, protectionEndRunTime, ImposterState.ProtectionSeconds, ImposterState.CooldownSeconds, ImposterState.InfiniteDagger, ImposterState.SilentKill, ImposterState.HideFeedIndicator, ImposterState.OnlyImposterCanKill, imposterActors ?? new int[0], isReroll, sheriffShots, sheriffAimSeconds }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { targetActor }; Raise(171, content, val); } public static bool TryReadRole(object data, out Role role, out int[] imposters, out bool isReroll) { role = Role.Unknown; imposters = new int[0]; isReroll = false; if (!(data is object[] array) || array.Length < 12) { return false; } role = (Role)(byte)array[0]; ImposterState.ProtectionEndRunTime = (float)array[1]; ImposterState.ProtectionSeconds = (float)array[2]; ImposterState.CooldownSeconds = (float)array[3]; ImposterState.InfiniteDagger = (bool)array[4]; ImposterState.SilentKill = (bool)array[5]; ImposterState.HideFeedIndicator = (bool)array[6]; ImposterState.OnlyImposterCanKill = (bool)array[7]; imposters = (array[8] as int[]) ?? new int[0]; isReroll = (bool)array[9]; ImposterState.SheriffShotsLeft = (int)array[10]; ImposterState.SheriffAimSeconds = (float)array[11]; return true; } public static void ReportKill(int victimActor) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown Raise(172, new object[1] { victimActor }, new RaiseEventOptions { Receivers = (ReceiverGroup)2 }); } public static void SendAccuse(int targetActor) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown Raise(179, new object[1] { targetActor }, new RaiseEventOptions { Receivers = (ReceiverGroup)2 }); } public static void SendExecute(int targetActor, byte reason) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown object[] content = new object[1] { reason }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { targetActor }; Raise(180, content, val); } public static void SendBookRequest() { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown Raise(182, new object[0], new RaiseEventOptions { Receivers = (ReceiverGroup)2 }); } public static void SendBookGranted(int targetActor, byte slotId, Guid ledgerId) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown object[] content = new object[2] { slotId, ledgerId.ToString() }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { targetActor }; Raise(183, content, val); } public static void SendAccuseResult(int targetActor, bool guilty, int shotsLeft) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown object[] content = new object[2] { guilty, shotsLeft }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { targetActor }; Raise(181, content, val); } public static void SendRerollAnnounce() { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown Raise(175, new object[0], new RaiseEventOptions { Receivers = (ReceiverGroup)1 }); } public static void SendCeasefire(bool on) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown Raise(170, new object[1] { on }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }); } public static void SendReward(int targetActor) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown object[] content = new object[0]; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { targetActor }; Raise(176, content, val); } public static void SendToast(int targetActor, string locKey, float seconds) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown object[] content = new object[2] { locKey, seconds }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { targetActor }; Raise(177, content, val); } public static void SendToastAll(string locKey, float seconds) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown Raise(177, new object[2] { locKey, seconds }, new RaiseEventOptions { Receivers = (ReceiverGroup)1 }); } public static void SendWaiting(int targetActor, bool waiting) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown object[] content = new object[1] { waiting }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { targetActor }; Raise(178, content, val); } public static void SendReveal(byte outcome, string[] imposterEntries, string[] sheriffEntries) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown Raise(173, new object[3] { outcome, imposterEntries ?? new string[0], sheriffEntries ?? new string[0] }, new RaiseEventOptions { Receivers = (ReceiverGroup)1 }); } public static bool TryReadReveal(object data, out byte outcome, out string[] imposterEntries, out string[] sheriffEntries) { outcome = 2; imposterEntries = new string[0]; sheriffEntries = new string[0]; if (!(data is object[] array) || array.Length < 3) { return false; } outcome = (byte)array[0]; imposterEntries = (array[1] as string[]) ?? new string[0]; sheriffEntries = (array[2] as string[]) ?? new string[0]; return true; } public static void SendAbort(string reason) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown Raise(174, reason, new RaiseEventOptions { Receivers = (ReceiverGroup)1 }); } public static List<int> GetActivePlayerActors() { List<int> list = new List<int>(); if (!PhotonNetwork.InRoom) { return list; } Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if (val != null && !val.IsInactive) { list.Add(val.ActorNumber); } } return list; } } public enum Role : byte { Unknown, Crew, Imposter, Sheriff } public static class ImposterState { public static bool Active; public static Role LocalRole = Role.Unknown; public static readonly HashSet<int> ImposterActors = new HashSet<int>(); public static float ProtectionEndRunTime; public static bool Ceasefire; public static float ProtectionSeconds = 180f; public static float CooldownSeconds = 60f; public static bool InfiniteDagger = true; public static bool SilentKill = true; public static bool HideFeedIndicator = true; public static bool OnlyImposterCanKill = true; public static float LastKillTime = -99999f; public static int LocalKills; public static bool WaitingForDaggerSlot; public static int SheriffShotsLeft; public static float SheriffAimSeconds = 1.5f; public static readonly List<int> FellowImposters = new List<int>(); public const int DebugFakeBase = -100; public static readonly List<int> DebugDummies = new List<int>(); public static bool IsImposter => LocalRole == Role.Imposter; public static bool IsSheriff => LocalRole == Role.Sheriff; public static float RunTime { get { RunManager instance = RunManager.Instance; if (!((Object)(object)instance != (Object)null)) { return 0f; } return instance.TimeSinceRunStarted; } } public static bool ProtectionActive { get { if (Active) { if (!Ceasefire) { return RunTime < ProtectionEndRunTime; } return true; } return false; } } public static float ProtectionRemaining => Mathf.Max(0f, ProtectionEndRunTime - RunTime); public static float CooldownRemaining => Mathf.Max(0f, LastKillTime + CooldownSeconds - Time.time); public static bool CanStab { get { if (Active && IsImposter && !ProtectionActive) { return CooldownRemaining <= 0f; } return false; } } public static bool IsDebugFake(int actor) { return actor < -100; } public static string DebugFakeName(int actor) { return "Dummy " + (-100 - actor); } public static void Reset() { Active = false; LocalRole = Role.Unknown; ImposterActors.Clear(); ProtectionEndRunTime = 0f; Ceasefire = false; LastKillTime = -99999f; LocalKills = 0; WaitingForDaggerSlot = false; SheriffShotsLeft = 0; FellowImposters.Clear(); DebugDummies.Clear(); } public static void ResetForReroll() { LocalRole = Role.Unknown; LastKillTime = -99999f; WaitingForDaggerSlot = false; FellowImposters.Clear(); } public static string FormatTime(float seconds) { if (seconds < 0f) { seconds = 0f; } int num = Mathf.CeilToInt(seconds); return $"{num / 60}:{num % 60:00}"; } } public enum HudCorner { TopLeft, TopRight } public enum RevealSide { Left, Right } public class ImposterUI : MonoBehaviour { public static bool RoleCardPending; private static readonly Color ImposterRed = Color32.op_Implicit(new Color32((byte)232, (byte)72, (byte)72, byte.MaxValue)); private static readonly Color CrewGreen = Color32.op_Implicit(new Color32((byte)118, (byte)209, (byte)128, byte.MaxValue)); private static readonly Color Warm = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)214, (byte)120, byte.MaxValue)); private static readonly Color SheriffBlue = Color32.op_Implicit(new Color32((byte)108, (byte)176, (byte)240, byte.MaxValue)); private GameObject _root; private RectTransform _badge; private TextMeshProUGUI _badgeRole; private TextMeshProUGUI _badgeStatus; private TextMeshProUGUI _badgeKills; private TextMeshProUGUI _badgeFellows; private RectTransform _announce; private TextMeshProUGUI _announceTitle; private TextMeshProUGUI _announceSub; private float _announceUntil; private RectTransform _toast; private TextMeshProUGUI _toastText; private RectTransform _reveal; private Image _revealBackdrop; private TextMeshProUGUI _revealTitle; private TextMeshProUGUI _revealBody; private float _revealUntil; private TMP_FontAsset _font; private HudCorner _builtCorner; private float _builtScale; private bool _builtBold; private float _builtOutline; private RevealSide _builtRevealSide; public static ImposterUI Instance { get; private set; } public static void ShowRoleCard(Role role, int[] imposters, bool withIntro, bool isReroll = false) { if (!((Object)(object)Instance == (Object)null)) { Compose(role, imposters, out var title, out var sub); if (!withIntro || !Plugin.Cfg.UseIntroSequence.Value || !((Object)(object)IntroSequence.Instance != (Object)null) || !IntroSequence.Instance.Play(role, imposters, title, sub, isReroll)) { ShowPlainRoleCard(role, title, sub); } } } public static void ShowPlainRoleCard(Role role, string title, string sub) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance == (Object)null)) { Instance.Announce(title, sub, RoleColor(role), Plugin.Cfg.RoleCardSeconds.Value); } } public static Color RoleColor(Role role) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) return (Color)(role switch { Role.Imposter => ImposterRed, Role.Sheriff => SheriffBlue, _ => CrewGreen, }); } public static string FellowNames() { if (!Plugin.Cfg.ShowFellowImposters.Value) { return null; } if (!ImposterState.IsImposter || ImposterState.FellowImposters.Count == 0) { return null; } List<string> list = new List<string>(); foreach (int fellowImposter in ImposterState.FellowImposters) { list.Add(ActorName(fellowImposter)); } return string.Join(", ", list.ToArray()); } private static string ActorName(int actor) { if (ImposterState.IsDebugFake(actor)) { return ImposterState.DebugFakeName(actor); } Character val = default(Character); if (PlayerHandler.TryGetCharacter(actor, ref val) && (Object)(object)val != (Object)null) { return val.characterName; } Room currentRoom = PhotonNetwork.CurrentRoom; Player val2 = ((currentRoom != null) ? currentRoom.GetPlayer(actor, false) : null); if (val2 == null) { return "Scout #" + actor; } return val2.NickName; } private static void Compose(Role role, int[] imposters, out string title, out string sub) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (role == Role.Sheriff) { title = Loc.T("card.sheriff.title"); sub = Loc.T("card.sheriff.sub", ImposterState.SheriffShotsLeft, Plugin.Cfg.SheriffKey.Value); if (Plugin.Cfg.SheriffDiesOnMisfire.Value) { sub = sub + "\n" + Loc.T("card.sheriff.warn"); } return; } bool flag = role == Role.Imposter; title = Loc.T(flag ? "card.imposter.title" : "card.crew.title"); if (!flag) { sub = Loc.T("card.crew.sub"); return; } sub = ((imposters != null && imposters.Length > 1) ? Loc.T("card.imposter.sub.multi", imposters.Length) : Loc.T("card.imposter.sub")); string text = FellowNames(); if (text != null) { sub = sub + "\n" + Loc.T("card.imposter.fellows", text); } sub = sub + "\n" + Loc.T(Plugin.Cfg.GiveDaggerAfterProtection.Value ? "card.imposter.hint.later" : "card.imposter.hint", ImposterState.FormatTime(ImposterState.ProtectionRemaining), ImposterState.FormatTime(ImposterState.CooldownSeconds)); } public static void ShowAnnouncement(string title, string sub, bool positive) { //IL_001f: 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) if (!((Object)(object)Instance == (Object)null)) { Instance.Announce(title, sub, positive ? CrewGreen : Warm, Plugin.Cfg.RoleCardSeconds.Value); } } public static void ShowReveal(string title, string body, bool imposterWon) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance == (Object)null)) { Instance.EnsureBuilt(); if (!((Object)(object)Instance._revealTitle == (Object)null)) { ((TMP_Text)Instance._revealTitle).text = title; ((Graphic)Instance._revealTitle).color = (imposterWon ? ImposterRed : CrewGreen); ((TMP_Text)Instance._revealBody).text = body; Instance._revealUntil = Time.time + Plugin.Cfg.RevealSeconds.Value; ((Component)Instance._reveal).gameObject.SetActive(true); } } } private void Announce(string title, string sub, Color color, float seconds) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) EnsureBuilt(); if (!((Object)(object)_announceTitle == (Object)null)) { ((TMP_Text)_announceTitle).text = title; ((Graphic)_announceTitle).color = color; ((TMP_Text)_announceSub).text = sub; _announceUntil = Time.time + seconds; ((Component)_announce).gameObject.SetActive(true); } } private void Awake() { Instance = this; } private void OnDestroy() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } public static TMP_FontAsset GameFont() { GUIManager instance = GUIManager.instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.interactPromptText != (Object)null && (Object)(object)((TMP_Text)instance.interactPromptText).font != (Object)null) { return ((TMP_Text)instance.interactPromptText).font; } if ((Object)(object)instance.heroText != (Object)null && (Object)(object)((TMP_Text)instance.heroText).font != (Object)null) { return ((TMP_Text)instance.heroText).font; } } return TMP_Settings.defaultFontAsset; } private bool SettingsChanged() { if (_builtCorner == Plugin.Cfg.HudCorner.Value && Mathf.Approximately(_builtScale, Plugin.Cfg.HudScale.Value) && _builtBold == Plugin.Cfg.HudBold.Value && Mathf.Approximately(_builtOutline, Plugin.Cfg.HudOutline.Value)) { return _builtRevealSide != Plugin.Cfg.RevealSide.Value; } return true; } private void EnsureBuilt() { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null && SettingsChanged()) { Object.Destroy((Object)(object)_root); _root = null; } if ((Object)(object)_root != (Object)null) { TMP_FontAsset val = GameFont(); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)_font) { _font = val; TextMeshProUGUI[] array = (TextMeshProUGUI[])(object)new TextMeshProUGUI[9] { _badgeRole, _badgeStatus, _badgeKills, _badgeFellows, _announceTitle, _announceSub, _toastText, _revealTitle, _revealBody }; foreach (TextMeshProUGUI t in array) { StyleText(t); } } } else { _font = GameFont(); _builtCorner = Plugin.Cfg.HudCorner.Value; _builtScale = Plugin.Cfg.HudScale.Value; _builtBold = Plugin.Cfg.HudBold.Value; _builtOutline = Plugin.Cfg.HudOutline.Value; _builtRevealSide = Plugin.Cfg.RevealSide.Value; float builtScale = _builtScale; _root = new GameObject("PeakImposterHUD"); ((Object)_root).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)_root); Canvas obj = _root.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 30000; CanvasScaler obj2 = _root.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.screenMatchMode = (ScreenMatchMode)0; obj2.matchWidthOrHeight = 0.5f; BuildBadge(builtScale); BuildAnnounce(builtScale); BuildToast(builtScale); BuildReveal(builtScale); } } private RectTransform MakeContainer(string name, Vector2 anchor, Vector2 offset, Vector2 size) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(_root.transform, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = anchor; component.anchorMax = anchor; component.pivot = anchor; component.anchoredPosition = offset; component.sizeDelta = size; return component; } private TextMeshProUGUI MakeLine(RectTransform parent, string name, float y, float height, float fontSize, TextAlignmentOptions align) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0098: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val.transform.SetParent((Transform)(object)parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.offsetMin = new Vector2(0f, 0f); component.offsetMax = new Vector2(0f, 0f); component.anchoredPosition = new Vector2(0f, 0f - y); component.sizeDelta = new Vector2(0f, height); TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component2).fontSize = fontSize; ((TMP_Text)component2).alignment = align; ((Graphic)component2).color = Color.white; ((Graphic)component2).raycastTarget = false; ((TMP_Text)component2).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)component2).overflowMode = (TextOverflowModes)0; StyleText(component2); return component2; } private void StyleText(TextMeshProUGUI t) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null) { return; } if ((Object)(object)_font != (Object)null) { ((TMP_Text)t).font = _font; } ((TMP_Text)t).fontStyle = (FontStyles)(Plugin.Cfg.HudBold.Value ? 1 : 0); float value = Plugin.Cfg.HudOutline.Value; if (value <= 0f) { return; } try { ((TMP_Text)t).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)220); ((TMP_Text)t).outlineWidth = value; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Text outline not supported: " + ex.Message)); } } private void BuildBadge(float s) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) bool flag = _builtCorner == HudCorner.TopRight; Vector2 anchor = default(Vector2); ((Vector2)(ref anchor))..ctor(flag ? 1f : 0f, 1f); _badge = MakeContainer("Badge", anchor, new Vector2(flag ? (-34f) : 34f, -30f), new Vector2(560f * s, 170f * s)); TextAlignmentOptions align = (TextAlignmentOptions)(flag ? 260 : 257); _badgeRole = MakeLine(_badge, "Role", 0f, 46f * s, 30f * s, align); _badgeStatus = MakeLine(_badge, "Status", 44f * s, 36f * s, 23f * s, align); _badgeKills = MakeLine(_badge, "Kills", 80f * s, 30f * s, 18f * s, align); _badgeFellows = MakeLine(_badge, "Fellows", 108f * s, 30f * s, 18f * s, align); ((Graphic)_badgeFellows).color = ImposterRed; ((Component)_badge).gameObject.SetActive(false); } private void BuildAnnounce(float s) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) _announce = MakeContainer("Announce", new Vector2(0.5f, 1f), new Vector2(0f, -200f), new Vector2(1180f * s, 230f * s)); _announceTitle = MakeLine(_announce, "Title", 0f, 60f * s, 40f * s, (TextAlignmentOptions)258); _announceSub = MakeLine(_announce, "Sub", 66f * s, 150f * s, 22f * s, (TextAlignmentOptions)258); ((Component)_announce).gameObject.SetActive(false); } private void BuildToast(float s) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) _toast = MakeContainer("Toast", new Vector2(0.5f, 0f), new Vector2(0f, 210f), new Vector2(1180f * s, 90f * s)); _toastText = MakeLine(_toast, "Text", 0f, 90f * s, 23f * s, (TextAlignmentOptions)258); ((Graphic)_toastText).color = Warm; ((Component)_toast).gameObject.SetActive(false); } private void BuildReveal(float s) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) bool flag = _builtRevealSide == RevealSide.Right; Vector2 anchor = default(Vector2); ((Vector2)(ref anchor))..ctor(flag ? 1f : 0f, 0.5f); _reveal = MakeContainer("Reveal", anchor, new Vector2(flag ? (-40f) : 40f, 0f), new Vector2(540f * s, 260f * s)); GameObject val = new GameObject("Backdrop", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent((Transform)(object)_reveal, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(-18f, -14f); component.offsetMax = new Vector2(18f, 14f); _revealBackdrop = val.GetComponent<Image>(); ((Graphic)_revealBackdrop).raycastTarget = false; TextAlignmentOptions align = (TextAlignmentOptions)(flag ? 260 : 257); _revealTitle = MakeLine(_reveal, "Title", 0f, 52f * s, 30f * s, align); _revealBody = MakeLine(_reveal, "Body", 56f * s, 200f * s, 20f * s, align); ((Component)_reveal).gameObject.SetActive(false); } private void UpdateReveal() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if (!((Component)_reveal).gameObject.activeSelf) { return; } if (Time.time > _revealUntil) { ((Component)_reveal).gameObject.SetActive(false); return; } float num = Mathf.Clamp01(_revealUntil - Time.time); ((TMP_Text)_revealTitle).alpha = num; ((TMP_Text)_revealBody).alpha = num; float value = Plugin.Cfg.RevealBackgroundAlpha.Value; ((Behaviour)_revealBackdrop).enabled = value > 0f; if (((Behaviour)_revealBackdrop).enabled) { ((Graphic)_revealBackdrop).color = new Color(0f, 0f, 0f, value * num); } } private void LateUpdate() { if (!Plugin.Cfg.ShowHud.Value) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } return; } if (IntroSequence.IsPlaying || RoleCardPending || LoadingScreenHandler.loading) { if ((Object)(object)_root != (Object)null && _root.activeSelf) { _root.SetActive(false); } return; } EnsureBuilt(); if (!((Object)(object)_root == (Object)null)) { if (!_root.activeSelf) { _root.SetActive(true); } UpdateBadge(); UpdateAnnounce(); UpdateToast(); UpdateReveal(); } } private void UpdateBadge() { //IL_00d4: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) bool flag = ImposterState.Active && ImposterState.LocalRole != Role.Unknown && (Object)(object)Character.localCharacter != (Object)null; if (flag && ImposterState.LocalRole == Role.Crew && !Plugin.Cfg.ShowRoleBadgeForCrew.Value) { flag = false; } if (!flag) { if (((Component)_badge).gameObject.activeSelf) { ((Component)_badge).gameObject.SetActive(false); } return; } if (!((Component)_badge).gameObject.activeSelf) { ((Component)_badge).gameObject.SetActive(true); } bool isImposter = ImposterState.IsImposter; bool isSheriff = ImposterState.IsSheriff; ((TMP_Text)_badgeRole).text = Loc.T(isImposter ? "role.imposter" : (isSheriff ? "role.sheriff" : "role.crew")); ((Graphic)_badgeRole).color = (isImposter ? ImposterRed : (isSheriff ? SheriffBlue : CrewGreen)); string text; Color color; if (ImposterState.Ceasefire) { text = Loc.T("hud.ceasefire"); color = CrewGreen; } else if (ImposterState.ProtectionActive) { text = Loc.T("hud.protection", ImposterState.FormatTime(ImposterState.ProtectionRemaining)); color = CrewGreen; } else if (isSheriff && SheriffBook.OwnLedgerSlot() >= 0) { text = Loc.T("hud.sheriff.stow"); color = Warm; } else if (isSheriff) { bool flag2 = ImposterState.SheriffShotsLeft > 0; text = (flag2 ? Loc.T("hud.sheriff.ready", ImposterState.SheriffShotsLeft, Plugin.Cfg.SheriffKey.Value) : Loc.T("hud.sheriff.spent")); color = (flag2 ? SheriffBlue : Color.white); } else if (!isImposter) { text = ""; color = Color.white; } else if (ImposterState.WaitingForDaggerSlot) { text = Loc.T("hud.nodagger"); color = Warm; } else if (ImposterState.CooldownRemaining > 0f) { text = Loc.T("hud.cooldown", ImposterState.FormatTime(ImposterState.CooldownRemaining)); color = Warm; } else { text = Loc.T("hud.ready"); color = ImposterRed; } ((TMP_Text)_badgeStatus).text = text; ((Graphic)_badgeStatus).color = color; ((Component)_badgeStatus).gameObject.SetActive(!string.IsNullOrEmpty(text)); bool flag3 = isImposter && ImposterState.LocalKills > 0; ((Component)_badgeKills).gameObject.SetActive(flag3); if (flag3) { ((TMP_Text)_badgeKills).text = Loc.T("hud.kills", ImposterState.LocalKills); } string text2 = FellowNames(); ((Component)_badgeFellows).gameObject.SetActive(text2 != null); if (text2 != null) { ((TMP_Text)_badgeFellows).text = Loc.T("hud.fellows", text2); } } private void UpdateAnnounce() { if (((Component)_announce).gameObject.activeSelf) { if (Time.time > _announceUntil) { ((Component)_announce).gameObject.SetActive(false); return; } float alpha = Mathf.Clamp01(_announceUntil - Time.time); ((TMP_Text)_announceTitle).alpha = alpha; ((TMP_Text)_announceSub).alpha = alpha; } } private void UpdateToast() { ImposterManager instance = ImposterManager.Instance; if (!((Object)(object)instance != (Object)null) || !(Time.time <= instance.ToastUntil) || string.IsNullOrEmpty(instance.ToastText)) { if (((Component)_toast).gameObject.activeSelf) { ((Component)_toast).gameObject.SetActive(false); } return; } if (!((Component)_toast).gameObject.activeSelf) { ((Component)_toast).gameObject.SetActive(true); } ((TMP_Text)_toastText).text = instance.ToastText; ((TMP_Text)_toastText).alpha = Mathf.Clamp01(instance.ToastUntil - Time.time); } } public class IntroSequence : MonoBehaviour { private class CardTag : MonoBehaviour { public int Actor; } private sealed class CardEntry { public readonly int Actor; public readonly string Name; public readonly RenderTexture Photo; public CardEntry(int actor, string name, RenderTexture photo) { Actor = actor; Name = name; Photo = photo; } } private static readonly Color ImposterRed = Color32.op_Implicit(new Color32((byte)232, (byte)72, (byte)72, byte.MaxValue)); private static readonly Color CrewGreen = Color32.op_Implicit(new Color32((byte)118, (byte)209, (byte)128, byte.MaxValue)); private static readonly Color SheriffBlue = Color32.op_Implicit(new Color32((byte)108, (byte)176, (byte)240, byte.MaxValue)); private static readonly Color Ink = Color32.op_Implicit(new Color32((byte)233, (byte)224, (byte)205, byte.MaxValue)); private GameObject _root; private CanvasGroup _group; private RectTransform _cardRow; private TextMeshProUGUI _roleTitle; private TextMeshProUGUI _roleSub; private readonly List<GameObject> _cards = new List<GameObject>(); private readonly List<Canvas> _hiddenCanvases = new List<Canvas>(); private Dictionary<int, RenderTexture> _textures; private Coroutine _running; public static IntroSequence Instance { get; private set; } public static bool IsPlaying { get; private set; } private void Awake() { Instance = this; } private void OnDestroy() { RestoreGameUi(); PortraitStudio.Release(_textures); if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } IsPlaying = false; } public bool Play(Role role, int[] imposters, string title, string sub, bool isReroll = false) { if (!PortraitStudio.IsAvailable) { return false; } if (!PhotonNetwork.InRoom) { return false; } if (_running != null) { ((MonoBehaviour)this).StopCoroutine(_running); } _running = ((MonoBehaviour)this).StartCoroutine(Run(role, title, sub, isReroll)); return true; } public void Stop() { if (_running != null) { ((MonoBehaviour)this).StopCoroutine(_running); } _running = null; IsPlaying = false; RestoreGameUi(); if ((Object)(object)_group != (Object)null) { _group.alpha = 0f; } if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } } private void HideGameUi() { RestoreGameUi(); if (!Plugin.Cfg.HideGameUiDuringIntro.Value) { return; } Canvas[] array; try { array = Object.FindObjectsByType<Canvas>((FindObjectsInactive)0, (FindObjectsSortMode)0); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not hide the game UI: " + ex.Message)); return; } Canvas[] array2 = array; foreach (Canvas val in array2) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled && !((Object)((Component)val).transform.root).name.StartsWith("PeakImposter")) { ((Behaviour)val).enabled = false; _hiddenCanvases.Add(val); } } } private void RestoreGameUi() { foreach (Canvas hiddenCanvase in _hiddenCanvases) { if ((Object)(object)hiddenCanvase != (Object)null) { ((Behaviour)hiddenCanvase).enabled = true; } } _hiddenCanvases.Clear(); } private IEnumerator Run(Role role, string title, string sub, bool isReroll) { IsPlaying = true; float guard = Time.realtimeSinceStartup + 30f; while (LoadingScreenHandler.loading && Time.realtimeSinceStartup < guard) { yield return null; } yield return (object)new WaitForSeconds(Plugin.Cfg.IntroDelaySeconds.Value); HideGameUi(); try { List<Player> players = new List<Player>(); Player[] playerList = PhotonNetwork.PlayerList; Character val2 = default(Character); foreach (Player val in playerList) { if (val != null && !val.IsInactive && (!isReroll || !PlayerHandler.TryGetCharacter(val.ActorNumber, ref val2) || !((Object)(object)val2 != (Object)null) || !((Object)(object)val2.data != (Object)null) || !val2.data.dead)) { players.Add(val); } } Dictionary<int, RenderTexture> shots = null; yield return PortraitStudio.Capture(players, delegate(Dictionary<int, RenderTexture> result) { shots = result; }); if (shots == null) { RestoreGameUi(); IsPlaying = false; _running = null; ImposterUI.ShowPlainRoleCard(role, title, sub); yield break; } PortraitStudio.Release(_textures); _textures = shots; Build(); List<CardEntry> list = new List<CardEntry>(); foreach (Player item in players) { if (item != null && shots.TryGetValue(item.ActorNumber, out var value)) { list.Add(new CardEntry(item.ActorNumber, NameOf(item), value)); } } int key = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); if (shots.TryGetValue(key, out var value2)) { foreach (int debugDummy in ImposterState.DebugDummies) { list.Add(new CardEntry(debugDummy, ImposterState.DebugFakeName(debugDummy), value2)); } } BuildCards(list); int localActor = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); Color color = (Color)(role switch { Role.Sheriff => SheriffBlue, Role.Imposter => ImposterRed, _ => CrewGreen, }); ((TMP_Text)_roleTitle).text = title; ((Graphic)_roleTitle).color = color; ((TMP_Text)_roleSub).text = sub; _root.SetActive(true); yield return Fade(_group, 0f, 1f, 0.4f); yield return (object)new WaitForSeconds(Plugin.Cfg.IntroGroupSeconds.Value); HashSet<int> hashSet = new HashSet<int>(); if (role == Role.Imposter && Plugin.Cfg.ShowFellowImposters.Value) { foreach (int fellowImposter in ImposterState.FellowImposters) { hashSet.Add(fellowImposter); } } List<CanvasGroup> others = new List<CanvasGroup>(); List<RectTransform> list2 = new List<RectTransform>(); RectTransform mine = null; foreach (GameObject card in _cards) { int actor = card.GetComponent<CardTag>().Actor; if (actor == localActor) { mine = card.GetComponent<RectTransform>(); } else if (hashSet.Contains(actor)) { list2.Add(card.GetComponent<RectTransform>()); } else { others.Add(card.GetComponent<CanvasGroup>()); } } List<RectTransform> kept = new List<RectTransform>(); if ((Object)(object)mine != (Object)null) { kept.Add(mine); } for (int num = 0; num < list2.Count; num++) { if (num % 2 == 0) { kept.Add(list2[num]); } else { kept.Insert(0, list2[num]); } } Dictionary<RectTransform, Vector2> starts = new Dictionary<RectTransform, Vector2>(); Dictionary<RectTransform, Vector2> targets = new Dictionary<RectTransform, Vector2>(); float num2 = 0f; foreach (RectTransform item2 in kept) { num2 += item2.sizeDelta.x * (((Object)(object)item2 == (Object)(object)mine) ? 1.35f : 1f); } num2 += 40f * (float)Mathf.Max(0, kept.Count - 1); float num3 = (0f - num2) * 0.5f; foreach (RectTransform item3 in kept) { float num4 = item3.sizeDelta.x * (((Object)(object)item3 == (Object)(object)mine) ? 1.35f : 1f); starts[item3] = item3.anchoredPosition; targets[item3] = new Vector2(num3 + num4 * 0.5f, 0f); num3 += num4 + 40f; } List<TextMeshProUGUI> tags = new List<TextMeshProUGUI>(); TextMeshProUGUI val5 = default(TextMeshProUGUI); foreach (RectTransform item4 in list2) { TextMeshProUGUI val3 = MakeText((Transform)(object)item4, "FellowTag", 22f, (TextAlignmentOptions)1026); RectTransform rectTransform = ((TMP_Text)val3).rectTransform; rectTransform.anchorMin = new Vector2(0.5f, 1f); rectTransform.anchorMax = new Vector2(0.5f, 1f); rectTransform.pivot = new Vector2(0.5f, 0f); rectTransform.anchoredPosition = new Vector2(0f, 6f); rectTransform.sizeDelta = new Vector2(item4.sizeDelta.x + 40f, 32f); ((TMP_Text)val3).text = Loc.T("intro.fellow"); ((Graphic)val3).color = ImposterRed; ((TMP_Text)val3).alpha = 0f; tags.Add(val3); Transform val4 = ((Transform)item4).Find("Name"); if ((Object)(object)val4 != (Object)null && ((Component)val4).TryGetComponent<TextMeshProUGUI>(ref val5)) { ((Graphic)val5).color = ImposterRed; } } float t = 0f; float move = 0.6f; while (t < move) { t += Time.deltaTime; float num5 = Mathf.SmoothStep(0f, 1f, t / move); foreach (CanvasGroup item5 in others) { item5.alpha = 1f - num5; } foreach (TextMeshProUGUI item6 in tags) { ((TMP_Text)item6).alpha = num5; } foreach (RectTransform item7 in kept) { item7.anchoredPosition = Vector2.Lerp(starts[item7], targets[item7], num5); if ((Object)(object)item7 == (Object)(object)mine) { ((Transform)item7).localScale = Vector3.one * Mathf.Lerp(1f, 1.35f, num5); } } yield return null; } foreach (CanvasGroup item8 in others) { ((Component)item8).gameObject.SetActive(false); } yield return FadeText(1f, 0.35f); yield return (object)new WaitForSeconds(Plugin.Cfg.IntroRoleSeconds.Value); yield return Fade(_group, 1f, 0f, 0.5f); _root.SetActive(false); } finally { IntroSequence introSequence = this; introSequence.RestoreGameUi(); IsPlaying = false; introSequence._running = null; } } private IEnumerator Fade(CanvasGroup group, float from, float to, float duration) { float t = 0f; while (t < duration) { t += Time.deltaTime; group.alpha = Mathf.Lerp(from, to, t / duration); yield return null; } group.alpha = to; } private IEnumerator FadeText(float to, float duration) { float t = 0f; while (t < duration) { t += Ti