Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Glitnir Fader Ending v0.2.2
GlitnirFaderEnding.dll
Decompiled 2 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; using UnityEngine.UI; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("GlitnirFaderEnding")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("GlitnirFaderEnding")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3e8757f3-4e74-4e03-9abb-82f3a0280cc2")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace Glitnir.FaderEnding; [BepInPlugin("glitnir.faderending", "Glitnir Fader Ending", "0.2.2")] [BepInDependency("com.jotunn.jotunn", "2.29.0")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class GlitnirFaderEndingPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(Character), "OnDeath")] private static class Character_OnDeath_Patch { [HarmonyPrefix] private static void Prefix(Character __instance) { if ((Object)(object)Instance != (Object)null) { Instance.TryHandleBossDeath(__instance); } } } [HarmonyPatch(typeof(Player), "TakeInput")] private static class Player_TakeInput_Patch { [HarmonyPrefix] private static bool Prefix(Player __instance, ref bool __result) { if (!LockPlayerInput.Value || !EndingOverlay.IsActive) { return true; } if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { __result = false; return false; } return true; } } [CompilerGenerated] private sealed class <HandleVictoryAuthoritativeLocal>d__64 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public long killerPlayerId; public string killerName; public Vector3 bossDeathPosition; public List<KeyValuePair<GameObject, int>> drops; public GlitnirFaderEndingPlugin <>4__this; private Player <targetPlayer>5__1; private float <delay>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HandleVictoryAuthoritativeLocal>d__64(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <targetPlayer>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(Mathf.Max(0f, TeleportDelaySeconds.Value)); <>1__state = 1; return true; case 1: <>1__state = -1; <targetPlayer>5__1 = Player.m_localPlayer; if ((Object)(object)<targetPlayer>5__1 == (Object)null) { return false; } if (killerPlayerId != 0L && <targetPlayer>5__1.GetPlayerID() != killerPlayerId) { LogDebug("Instância local não é o jogador vencedor."); return false; } <>4__this.ApplyAuthoritativeVictoryToPlayer(<targetPlayer>5__1, bossDeathPosition, drops); if (!EndingEnabled.Value) { break; } <delay>5__2 = Mathf.Max(0f, DelayBeforeEndingVideoSeconds.Value); if (<delay>5__2 > 0f) { <>2__current = (object)new WaitForSeconds(<delay>5__2); <>1__state = 2; return true; } goto IL_012b; case 2: { <>1__state = -1; goto IL_012b; } IL_012b: <>4__this.BroadcastVictoryToClients(<targetPlayer>5__1.GetPlayerID()); break; } LogDebug($"Vitória aplicada localmente para {killerName} ({killerPlayerId}) com teleporte em ({TeleportX.Value}, {TeleportY.Value}, {TeleportZ.Value})."); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <HandleVictoryAuthoritativeServer>d__63 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public long killerPlayerId; public string killerName; public Vector3 bossDeathPosition; public List<KeyValuePair<GameObject, int>> drops; public GlitnirFaderEndingPlugin <>4__this; private Player <targetPlayer>5__1; private float <delay>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HandleVictoryAuthoritativeServer>d__63(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <targetPlayer>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(Mathf.Max(0f, TeleportDelaySeconds.Value)); <>1__state = 1; return true; case 1: <>1__state = -1; <targetPlayer>5__1 = FindPlayerById(killerPlayerId); if ((Object)(object)<targetPlayer>5__1 == (Object)null) { LogWarning($"Não foi possível encontrar o jogador vencedor no servidor. PlayerID={killerPlayerId}"); return false; } <>4__this.ApplyAuthoritativeVictoryToPlayer(<targetPlayer>5__1, bossDeathPosition, drops); if (!EndingEnabled.Value) { break; } <delay>5__2 = Mathf.Max(0f, DelayBeforeEndingVideoSeconds.Value); if (<delay>5__2 > 0f) { <>2__current = (object)new WaitForSeconds(<delay>5__2); <>1__state = 2; return true; } goto IL_0117; case 2: { <>1__state = -1; goto IL_0117; } IL_0117: <>4__this.BroadcastVictoryToClients(killerPlayerId); break; } LogDebug($"Vitória aplicada no servidor para {killerName} ({killerPlayerId}) com teleporte em ({TeleportX.Value}, {TeleportY.Value}, {TeleportZ.Value})."); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "glitnir.faderending"; public const string PluginName = "Glitnir Fader Ending"; public const string PluginVersion = "0.2.2"; internal const string RpcVictory = "glitnir.faderending.victory"; internal static GlitnirFaderEndingPlugin Instance; internal static Harmony HarmonyInstance; private bool _rpcRegistered; private const string SectionGeneral = "General"; private const string SectionTrigger = "Trigger"; private const string SectionTeleport = "Teleport"; private const string SectionLoot = "Loot"; private const string SectionEnding = "Ending"; private const string SectionVideo = "Video"; private const string SectionFinalize = "Finalize"; internal static ConfigEntry<bool> ModEnabled; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<string> BossPrefabName; internal static ConfigEntry<bool> MatchPrefabNameExactly; internal static ConfigEntry<bool> RequirePlayerAsKiller; internal static ConfigEntry<bool> TeleportEnabled; internal static ConfigEntry<float> TeleportX; internal static ConfigEntry<float> TeleportY; internal static ConfigEntry<float> TeleportZ; internal static ConfigEntry<float> TeleportYaw; internal static ConfigEntry<float> TeleportDelaySeconds; internal static ConfigEntry<bool> ResetVelocityAfterTeleport; internal static ConfigEntry<bool> LootToInventoryEnabled; internal static ConfigEntry<string> OverflowModeConfig; internal static ConfigEntry<bool> DisableVanillaWorldDrops; internal static ConfigEntry<bool> ShowLootDebugLog; internal static ConfigEntry<bool> EndingEnabled; internal static ConfigEntry<bool> LockPlayerInput; internal static ConfigEntry<bool> AllowSkip; internal static ConfigEntry<string> SkipKey; internal static ConfigEntry<float> FadeInSeconds; internal static ConfigEntry<float> FadeOutSeconds; internal static ConfigEntry<bool> MuteGameAudioWhileEnding; internal static ConfigEntry<float> DelayBeforeEndingVideoSeconds; internal static ConfigEntry<float> MinimumSkipDelaySeconds; internal static ConfigEntry<bool> VideoEnabled; internal static ConfigEntry<bool> UseEmbeddedVideo; internal static ConfigEntry<string> EmbeddedVideoResourceName; internal static ConfigEntry<string> EmbeddedVideoOutputFileName; internal static ConfigEntry<string> VideoPath; internal static ConfigEntry<bool> LoopVideo; internal static ConfigEntry<float> VideoVolume; internal static ConfigEntry<bool> MuteVideoAudio; internal static ConfigEntry<float> HoldOnLastFrameSeconds; internal static ConfigEntry<float> MaxVideoDurationSeconds; internal static ConfigEntry<bool> AutoCloseEnding; internal static ConfigEntry<bool> KeepPlayerLockedUntilEnd; internal static ConfigEntry<bool> IgnoreDuplicateVictoryEvents; private static readonly FieldInfo LastHitField = AccessTools.Field(typeof(Character), "m_lastHit"); private static readonly FieldInfo DropsEnabledField = AccessTools.Field(typeof(CharacterDrop), "m_dropsEnabled"); private void Awake() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown Instance = this; BindConfig(); HarmonyInstance = new Harmony("glitnir.faderending"); HarmonyInstance.PatchAll(Assembly.GetExecutingAssembly()); SynchronizationManager.OnConfigurationSynchronized += delegate(object _, ConfigurationSynchronizationEventArgs args) { if (DebugLogging != null && DebugLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[DEBUG] Config sync recebido. Initial={args.InitialSynchronization} | Teleport=({TeleportX.Value}, {TeleportY.Value}, {TeleportZ.Value})"); } }; LogInfo("Glitnir Fader Ending 0.2.2 carregado."); } private void Update() { EnsureRpcRegistered(); } private void OnDestroy() { if (HarmonyInstance != null) { HarmonyInstance.UnpatchSelf(); } } private ConfigEntry<T> BindSynced<T>(string section, string key, T defaultValue, string description, AcceptableValueBase acceptable = null) { return ConfigFileExtensions.BindConfigInOrder<T>(((BaseUnityPlugin)this).Config, section, key, defaultValue, description, true, true, true, acceptable, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } private ConfigEntry<T> BindLocal<T>(string section, string key, T defaultValue, string description, AcceptableValueBase acceptable = null) { return ConfigFileExtensions.BindConfigInOrder<T>(((BaseUnityPlugin)this).Config, section, key, defaultValue, description, false, true, true, acceptable, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } private void BindConfig() { ModEnabled = BindSynced("General", "ModEnabled", defaultValue: true, "Liga ou desliga completamente o mod."); DebugLogging = BindLocal("General", "DebugLogging", defaultValue: false, "Ativa logs extras no console local."); BossPrefabName = BindSynced("Trigger", "BossPrefabName", "Fader", "Nome do prefab do boss que dispara a sequência."); MatchPrefabNameExactly = BindSynced("Trigger", "MatchPrefabNameExactly", defaultValue: true, "Se true, compara o nome do prefab exatamente. Se false, usa Contains."); RequirePlayerAsKiller = BindSynced("Trigger", "RequirePlayerAsKiller", defaultValue: true, "Se true, a sequência só dispara se o golpe final vier de um Player."); TeleportEnabled = BindSynced("Teleport", "TeleportEnabled", defaultValue: true, "Teleporta o jogador vencedor para um ponto seguro."); TeleportX = BindSynced("Teleport", "TeleportX", 0f, "Coordenada X do teleporte."); TeleportY = BindSynced("Teleport", "TeleportY", 100f, "Coordenada Y do teleporte."); TeleportZ = BindSynced("Teleport", "TeleportZ", 0f, "Coordenada Z do teleporte."); TeleportYaw = BindSynced("Teleport", "TeleportYaw", 180f, "Rotação Y do jogador após o teleporte.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 360f)); TeleportDelaySeconds = BindSynced("Teleport", "TeleportDelaySeconds", 0.25f, "Delay entre a morte do boss e o teleporte.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f)); ResetVelocityAfterTeleport = BindSynced("Teleport", "ResetVelocityAfterTeleport", defaultValue: true, "Zera a velocidade do rigidbody do jogador depois do teleporte."); LootToInventoryEnabled = BindSynced("Loot", "LootToInventoryEnabled", defaultValue: true, "Envia os drops do Fader direto para o inventário do vencedor."); OverflowModeConfig = BindSynced("Loot", "OverflowModeConfig", "SpawnAtTeleportLocation", "Quando não couber no inventário: SpawnAtTeleportLocation | SpawnAtPlayer | SpawnAtBossDeath | Discard"); DisableVanillaWorldDrops = BindSynced("Loot", "DisableVanillaWorldDrops", defaultValue: true, "Desliga o drop vanilla no chão para evitar duplicação."); ShowLootDebugLog = BindLocal("Loot", "ShowLootDebugLog", defaultValue: false, "Log local detalhado do processamento dos drops."); EndingEnabled = BindSynced("Ending", "EndingEnabled", defaultValue: true, "Mostra a sequência final após matar o boss."); LockPlayerInput = BindSynced("Ending", "LockPlayerInput", defaultValue: true, "Bloqueia input do jogador enquanto a sequência final estiver ativa."); AllowSkip = BindLocal("Ending", "AllowSkip", defaultValue: true, "Permite pular a sequência final no cliente local."); SkipKey = BindLocal("Ending", "SkipKey", "Escape", "Tecla local para pular a sequência final."); FadeInSeconds = BindSynced("Ending", "FadeInSeconds", 1.5f, "Tempo de fade-in da tela.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f)); FadeOutSeconds = BindSynced("Ending", "FadeOutSeconds", 1.25f, "Tempo de fade-out da tela.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f)); MuteGameAudioWhileEnding = BindSynced("Ending", "MuteGameAudioWhileEnding", defaultValue: true, "Zera o áudio do jogo enquanto o vídeo final estiver rodando."); DelayBeforeEndingVideoSeconds = BindSynced("Ending", "DelayBeforeEndingVideoSeconds", 2f, "Tempo de espera após o teleporte antes de abrir o vídeo.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f)); MinimumSkipDelaySeconds = BindSynced("Ending", "MinimumSkipDelaySeconds", 3f, "Tempo mínimo antes de permitir pular o vídeo com Esc.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f)); VideoEnabled = BindSynced("Video", "VideoEnabled", defaultValue: true, "Liga o vídeo final."); UseEmbeddedVideo = BindSynced("Video", "UseEmbeddedVideo", defaultValue: true, "Se true, usa o vídeo embutido dentro da DLL."); EmbeddedVideoResourceName = BindSynced("Video", "EmbeddedVideoResourceName", "", "Nome exato do recurso embutido. Pode ficar vazio para autodetectar."); EmbeddedVideoOutputFileName = BindSynced("Video", "EmbeddedVideoOutputFileName", "glitnir_fader_video_embedded.mp4", "Nome do arquivo temporário extraído do recurso embutido."); VideoPath = BindSynced("Video", "VideoPath", "glitnir_fader_video.mp4", "Caminho do vídeo externo. Só é usado quando UseEmbeddedVideo = false."); LoopVideo = BindSynced("Video", "LoopVideo", defaultValue: false, "Se true, o vídeo fica em loop até o jogador pular."); VideoVolume = BindLocal("Video", "VideoVolume", 1f, "Volume local do vídeo.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)); MuteVideoAudio = BindSynced("Video", "MuteVideoAudio", defaultValue: false, "Se true, o vídeo toca sem áudio."); HoldOnLastFrameSeconds = BindSynced("Video", "HoldOnLastFrameSeconds", 1f, "Quanto tempo segura o último frame antes de fechar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f)); MaxVideoDurationSeconds = BindSynced("Video", "MaxVideoDurationSeconds", 600f, "Proteção para não ficar preso se o vídeo não reportar o fim corretamente.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 7200f)); AutoCloseEnding = BindSynced("Finalize", "AutoCloseEnding", defaultValue: true, "Fecha a UI ao fim do vídeo."); KeepPlayerLockedUntilEnd = BindSynced("Finalize", "KeepPlayerLockedUntilEnd", defaultValue: true, "Mantém input bloqueado até o fim total da sequência."); IgnoreDuplicateVictoryEvents = BindSynced("Finalize", "IgnoreDuplicateVictoryEvents", defaultValue: true, "Ignora RPCs duplicados do mesmo evento."); } private void EnsureRpcRegistered() { if (!_rpcRegistered && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register<ZPackage>("glitnir.faderending.victory", (Action<long, ZPackage>)OnVictoryRpc); _rpcRegistered = true; LogDebug("ZRoutedRpc registrado."); } } private void OnVictoryRpc(long sender, ZPackage pkg) { try { if (!EndingEnabled.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return; } long num = pkg.ReadLong(); if (Player.m_localPlayer.GetPlayerID() == num) { if (IgnoreDuplicateVictoryEvents.Value && EndingOverlay.IsActive) { LogDebug("RPC duplicado ignorado porque a sequência final já está ativa."); } else { EndingOverlay.Show(); } } } catch (Exception arg) { LogError($"Falha ao processar RPC de vitória: {arg}"); } } internal void TryHandleBossDeath(Character victim) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) try { if (!ModEnabled.Value || (Object)(object)victim == (Object)null || victim.IsPlayer() || !IsConfiguredBoss(victim)) { return; } if (!IsAuthoritativeForDeathHandling(victim)) { LogDebug("Instância não autoritativa para tratar morte do boss. Ignorando."); return; } CharacterDrop component = ((Component)victim).GetComponent<CharacterDrop>(); if ((Object)(object)component == (Object)null) { LogWarning("Fader morreu, mas CharacterDrop não foi encontrado."); return; } string killerName; long num = TryGetKillerPlayerId(victim, out killerName); if (RequirePlayerAsKiller.Value && num == 0) { LogWarning("Fader morreu, mas não foi possível identificar um Player como golpe final."); return; } List<KeyValuePair<GameObject, int>> drops = new List<KeyValuePair<GameObject, int>>(); if (LootToInventoryEnabled.Value) { drops = component.GenerateDropList(); if (DisableVanillaWorldDrops.Value && DropsEnabledField != null) { DropsEnabledField.SetValue(component, false); } } Vector3 position = ((Component)victim).transform.position; if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ((MonoBehaviour)this).StartCoroutine(HandleVictoryAuthoritativeServer(num, killerName, position, drops)); } else { ((MonoBehaviour)this).StartCoroutine(HandleVictoryAuthoritativeLocal(num, killerName, position, drops)); } } catch (Exception arg) { LogError($"Erro ao tratar morte do boss: {arg}"); } } [IteratorStateMachine(typeof(<HandleVictoryAuthoritativeServer>d__63))] private IEnumerator HandleVictoryAuthoritativeServer(long killerPlayerId, string killerName, Vector3 bossDeathPosition, List<KeyValuePair<GameObject, int>> drops) { //IL_001c: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <HandleVictoryAuthoritativeServer>d__63(0) { <>4__this = this, killerPlayerId = killerPlayerId, killerName = killerName, bossDeathPosition = bossDeathPosition, drops = drops }; } [IteratorStateMachine(typeof(<HandleVictoryAuthoritativeLocal>d__64))] private IEnumerator HandleVictoryAuthoritativeLocal(long killerPlayerId, string killerName, Vector3 bossDeathPosition, List<KeyValuePair<GameObject, int>> drops) { //IL_001c: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <HandleVictoryAuthoritativeLocal>d__64(0) { <>4__this = this, killerPlayerId = killerPlayerId, killerName = killerName, bossDeathPosition = bossDeathPosition, drops = drops }; } private void ApplyAuthoritativeVictoryToPlayer(Player targetPlayer, Vector3 bossDeathPosition, List<KeyValuePair<GameObject, int>> drops) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)targetPlayer == (Object)null) { return; } if (TeleportEnabled.Value) { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(TeleportX.Value, TeleportY.Value, TeleportZ.Value); Quaternion val2 = Quaternion.Euler(0f, TeleportYaw.Value, 0f); ((Character)targetPlayer).TeleportTo(val, val2, true); if (ResetVelocityAfterTeleport.Value) { Rigidbody component = ((Component)targetPlayer).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.velocity = Vector3.zero; component.angularVelocity = Vector3.zero; } } LogDebug($"Teleport aplicado para {targetPlayer.GetPlayerName()} em {val}"); } if (LootToInventoryEnabled.Value && drops != null && drops.Count > 0) { GiveDropsToInventory(targetPlayer, drops, bossDeathPosition); } } private void GiveDropsToInventory(Player player, List<KeyValuePair<GameObject, int>> drops, Vector3 bossDeathPosition) { //IL_01c8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>(); foreach (KeyValuePair<GameObject, int> drop in drops) { GameObject key = drop.Key; int value = drop.Value; if ((Object)(object)key == (Object)null || value <= 0) { continue; } ItemDrop component = key.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { LogWarning("Prefab sem ItemDrop: " + NormalizePrefabName(key)); continue; } int num = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize); int num2 = value; while (num2 > 0) { int num3 = Mathf.Min(num, num2); GameObject val = Object.Instantiate<GameObject>(key); ((Object)val).hideFlags = (HideFlags)61; ItemDrop component2 = val.GetComponent<ItemDrop>(); if ((Object)(object)component2 == (Object)null) { Object.Destroy((Object)(object)val); break; } component2.m_itemData.m_stack = num3; if (!inventory.AddItem(component2.m_itemData)) { list.Add(new KeyValuePair<GameObject, int>(key, num3)); } Object.Destroy((Object)(object)val); num2 -= num3; } if (ShowLootDebugLog.Value) { LogDebug($"Drop processado: {NormalizePrefabName(key)} x{value}"); } } if (list.Count > 0) { HandleOverflowDrops(list, player, bossDeathPosition); } } private void HandleOverflowDrops(List<KeyValuePair<GameObject, int>> overflow, Player player, Vector3 bossDeathPosition) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) string text = (OverflowModeConfig.Value ?? "SpawnAtTeleportLocation").Trim(); Vector3 val = bossDeathPosition; if (text.Equals("Discard", StringComparison.OrdinalIgnoreCase)) { LogWarning("Drops excedentes foram descartados por configuração."); return; } if (text.Equals("SpawnAtPlayer", StringComparison.OrdinalIgnoreCase)) { val = ((Component)player).transform.position; } else if (text.Equals("SpawnAtTeleportLocation", StringComparison.OrdinalIgnoreCase)) { ((Vector3)(ref val))..ctor(TeleportX.Value, TeleportY.Value, TeleportZ.Value); } SpawnOverflowDrops(overflow, val); LogWarning($"Alguns drops não couberam no inventário e foram spawnados em {val}."); } private void SpawnOverflowDrops(List<KeyValuePair<GameObject, int>> overflow, Vector3 spawnPosition) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<GameObject, int> item in overflow) { GameObject key = item.Key; int value = item.Value; if ((Object)(object)key == (Object)null || value <= 0) { continue; } ItemDrop component = key.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { continue; } int num = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize); int num2 = value; while (num2 > 0) { int num3 = Mathf.Min(num, num2); Vector3 val = Random.insideUnitSphere * 0.5f; val.y = Mathf.Abs(val.y); GameObject val2 = Object.Instantiate<GameObject>(key, spawnPosition + Vector3.up + val, Quaternion.identity); ItemDrop component2 = val2.GetComponent<ItemDrop>(); if ((Object)(object)component2 != (Object)null) { component2.m_itemData.m_stack = num3; } num2 -= num3; } } } private void BroadcastVictoryToClients(long winnerPlayerId) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (ZRoutedRpc.instance == null) { LogWarning("ZRoutedRpc.instance ainda não está pronto. Vitória não foi transmitida."); return; } ZPackage val = new ZPackage(); val.Write(winnerPlayerId); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "glitnir.faderending.victory", new object[1] { val }); LogDebug($"RPC de vitória enviado para o player {winnerPlayerId}."); } private static long TryGetKillerPlayerId(Character victim, out string killerName) { killerName = string.Empty; try { HitData val = (HitData)((LastHitField != null) ? /*isinst with value type is only supported in some contexts*/: null); if (val == null) { return 0L; } Character attacker = val.GetAttacker(); Player val2 = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val2 == (Object)null) { return 0L; } killerName = val2.GetPlayerName(); return val2.GetPlayerID(); } catch (Exception ex) { LogWarning("Falha ao obter killer via m_lastHit: " + ex.Message); return 0L; } } private static bool IsAuthoritativeForDeathHandling(Character victim) { ZNetView component = ((Component)victim).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null) { return true; } if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return true; } return component.IsOwner(); } private static bool IsConfiguredBoss(Character victim) { string text = (BossPrefabName.Value ?? "Fader").Trim(); string text2 = NormalizePrefabName(((Component)victim).gameObject); if (MatchPrefabNameExactly.Value) { return string.Equals(text2, text, StringComparison.OrdinalIgnoreCase); } return text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0; } private static Player FindPlayerById(long playerId) { if (playerId == 0) { return null; } try { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (methodInfo.Name != "GetAllPlayers") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 0) { object obj = methodInfo.Invoke(null, null); if (!(obj is IEnumerable enumerable)) { continue; } foreach (object item in enumerable) { Player val = (Player)((item is Player) ? item : null); if ((Object)(object)val != (Object)null && val.GetPlayerID() == playerId) { return val; } } } else { if (parameters.Length != 1 || !typeof(List<Player>).IsAssignableFrom(parameters[0].ParameterType)) { continue; } List<Player> list = new List<Player>(); methodInfo.Invoke(null, new object[1] { list }); foreach (Player item2 in list) { if ((Object)(object)item2 != (Object)null && item2.GetPlayerID() == playerId) { return item2; } } } } } catch (Exception ex) { LogWarning("Falha ao localizar jogador por ID: " + ex.Message); } return null; } internal static string NormalizePrefabName(GameObject go) { if ((Object)(object)go == (Object)null) { return string.Empty; } return NormalizePrefabName(((Object)go).name); } internal static string NormalizePrefabName(string name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } string text = name.Trim(); if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } internal static string GetPreparedVideoPath() { if (UseEmbeddedVideo.Value) { return ExtractEmbeddedVideoToCache(); } return GetResolvedExternalVideoPath(); } internal static string GetResolvedExternalVideoPath() { string text = ((VideoPath.Value != null) ? VideoPath.Value.Trim() : string.Empty); if (string.IsNullOrWhiteSpace(text)) { return string.Empty; } if (Path.IsPathRooted(text)) { return text; } return Path.Combine(Paths.ConfigPath, text); } internal static string ExtractEmbeddedVideoToCache() { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = ResolveEmbeddedVideoResourceName(executingAssembly); if (string.IsNullOrWhiteSpace(text)) { LogWarning("Nenhum vídeo embutido foi encontrado no assembly."); return string.Empty; } string text2 = Path.Combine(Paths.PluginPath, "GlitnirFaderEndingCache"); Directory.CreateDirectory(text2); string text3 = ((EmbeddedVideoOutputFileName.Value != null) ? EmbeddedVideoOutputFileName.Value.Trim() : string.Empty); if (string.IsNullOrWhiteSpace(text3)) { string text4 = Path.GetExtension(text); if (string.IsNullOrWhiteSpace(text4)) { text4 = ".mp4"; } text3 = "glitnir_fader_video_embedded" + text4; } text3 = SanitizeFileName(text3); string text5 = Path.Combine(text2, text3); using (Stream stream = executingAssembly.GetManifestResourceStream(text)) { if (stream == null) { LogWarning("Não foi possível abrir o recurso embutido: " + text); return string.Empty; } bool flag = true; if (File.Exists(text5)) { FileInfo fileInfo = new FileInfo(text5); if (stream.CanSeek && fileInfo.Length == stream.Length) { flag = false; } } if (flag) { if (stream.CanSeek) { stream.Position = 0L; } using (FileStream destination = new FileStream(text5, FileMode.Create, FileAccess.Write, FileShare.Read)) { stream.CopyTo(destination); } LogDebug("Vídeo embutido extraído para: " + text5); } } return text5; } catch (Exception arg) { LogError($"Falha ao extrair vídeo embutido: {arg}"); return string.Empty; } } private static string ResolveEmbeddedVideoResourceName(Assembly asm) { string configured = ((EmbeddedVideoResourceName.Value != null) ? EmbeddedVideoResourceName.Value.Trim() : string.Empty); string[] manifestResourceNames = asm.GetManifestResourceNames(); if (!string.IsNullOrWhiteSpace(configured)) { string text = manifestResourceNames.FirstOrDefault((string n) => string.Equals(n, configured, StringComparison.Ordinal)); if (!string.IsNullOrWhiteSpace(text)) { return text; } string text2 = manifestResourceNames.FirstOrDefault((string n) => n.EndsWith(configured, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } } string text3 = manifestResourceNames.FirstOrDefault((string n) => n.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase) || n.EndsWith(".webm", StringComparison.OrdinalIgnoreCase) || n.EndsWith(".mov", StringComparison.OrdinalIgnoreCase)); return text3 ?? string.Empty; } private static string SanitizeFileName(string fileName) { char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { fileName = fileName.Replace(oldChar, '_'); } return fileName; } internal static void LogInfo(string msg) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg); } } internal static void LogWarning(string msg) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)msg); } } internal static void LogError(string msg) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogError((object)msg); } } internal static void LogDebug(string msg) { if ((Object)(object)Instance != (Object)null && DebugLogging != null && DebugLogging.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("[DEBUG] " + msg)); } } } internal sealed class EndingOverlay : MonoBehaviour { [CompilerGenerated] private sealed class <FadeCanvas>d__22 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float from; public float to; public float duration; public EndingOverlay <>4__this; private float <elapsed>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FadeCanvas>d__22(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <elapsed>5__1 = 0f; <>4__this._canvasGroup.alpha = from; break; case 1: <>1__state = -1; break; } if (<elapsed>5__1 < duration) { <elapsed>5__1 += Time.unscaledDeltaTime; <>4__this._canvasGroup.alpha = Mathf.Lerp(from, to, <elapsed>5__1 / duration); <>2__current = null; <>1__state = 1; return true; } <>4__this._canvasGroup.alpha = to; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RunSequence>d__19 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public EndingOverlay <>4__this; private float <prepareTimeout>5__1; private float <watchdog>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RunSequence>d__19(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Expected O, but got Unknown //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.FadeCanvas(0f, 1f, Mathf.Max(0.01f, GlitnirFaderEndingPlugin.FadeInSeconds.Value))); <>1__state = 1; return true; case 1: <>1__state = -1; if (GlitnirFaderEndingPlugin.VideoEnabled.Value && (Object)(object)<>4__this._videoPlayer != (Object)null && !string.IsNullOrWhiteSpace(<>4__this._videoPlayer.url)) { <prepareTimeout>5__1 = 10f; goto IL_0116; } goto IL_0189; case 2: <>1__state = -1; goto IL_0116; case 3: <>1__state = -1; goto IL_0253; case 4: <>1__state = -1; goto IL_029e; case 5: <>1__state = -1; <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.FadeCanvas(1f, 0f, Mathf.Max(0.01f, GlitnirFaderEndingPlugin.FadeOutSeconds.Value))); <>1__state = 6; return true; case 6: { <>1__state = -1; <>4__this.RestoreGameAudioMute(); <>4__this._isActive = false; <>4__this.SetOverlayState(visible: false, instantAlphaReset: true); return false; } IL_0189: if (<>4__this._videoPreparedSuccessfully) { <watchdog>5__2 = Mathf.Max(1f, GlitnirFaderEndingPlugin.MaxVideoDurationSeconds.Value); goto IL_0253; } <>2__current = (object)new WaitForSecondsRealtime(Mathf.Max(0.1f, GlitnirFaderEndingPlugin.HoldOnLastFrameSeconds.Value)); <>1__state = 4; return true; IL_029e: if ((Object)(object)<>4__this._videoPlayer != (Object)null && <>4__this._videoPlayer.isPlaying) { <>4__this._videoPlayer.Stop(); } <>2__current = (object)new WaitForSecondsRealtime(Mathf.Max(0f, GlitnirFaderEndingPlugin.HoldOnLastFrameSeconds.Value)); <>1__state = 5; return true; IL_0116: if (!<>4__this._videoPlayer.isPrepared && <prepareTimeout>5__1 > 0f) { <prepareTimeout>5__1 -= Time.unscaledDeltaTime; <>2__current = null; <>1__state = 2; return true; } <>4__this._videoPreparedSuccessfully = <>4__this._videoPlayer.isPrepared; if (<>4__this._videoPreparedSuccessfully) { <>4__this._videoPlayer.Play(); } else { GlitnirFaderEndingPlugin.LogWarning("O vídeo não ficou pronto a tempo. Encerrando sequência com fade."); } goto IL_0189; IL_0253: if (!<>4__this._skipRequested) { <watchdog>5__2 -= Time.unscaledDeltaTime; if (<watchdog>5__2 <= 0f) { GlitnirFaderEndingPlugin.LogWarning("Tempo máximo do vídeo atingido. Encerrando sequência."); } else if (GlitnirFaderEndingPlugin.LoopVideo.Value || <>4__this._videoPlayer.isPlaying || <>4__this._videoPlayer.frame <= 0) { <>2__current = null; <>1__state = 3; return true; } } goto IL_029e; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static EndingOverlay Instance; private bool _isActive; private bool _skipRequested; private bool _videoPreparedSuccessfully; private bool _audioMutedByOverlay; private float _previousGameAudioVolume = 1f; private float _sequenceStartTime; private Canvas _canvas; private CanvasGroup _canvasGroup; private RawImage _background; private VideoPlayer _videoPlayer; private RenderTexture _renderTexture; internal static bool IsActive => (Object)(object)Instance != (Object)null && Instance._isActive; internal static void EnsureRuntimeObject() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)Instance != (Object)null)) { GameObject val = new GameObject("GlitnirFaderEndingOverlay"); Object.DontDestroyOnLoad((Object)(object)val); Instance = val.AddComponent<EndingOverlay>(); Instance.BuildUi(); Instance.SetOverlayState(visible: false, instantAlphaReset: true); } } internal static void Show() { EnsureRuntimeObject(); Instance.Begin(); } private void BuildUi() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) _canvas = ((Component)this).gameObject.AddComponent<Canvas>(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 9999; ((Behaviour)_canvas).enabled = false; ((Component)this).gameObject.AddComponent<GraphicRaycaster>(); _canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>(); _canvasGroup.alpha = 0f; _canvasGroup.interactable = false; _canvasGroup.blocksRaycasts = false; GameObject val = new GameObject("Background"); val.transform.SetParent(((Component)this).transform, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; _background = val.AddComponent<RawImage>(); ((Graphic)_background).color = Color.black; _videoPlayer = ((Component)this).gameObject.AddComponent<VideoPlayer>(); _videoPlayer.playOnAwake = false; _videoPlayer.isLooping = false; _videoPlayer.renderMode = (VideoRenderMode)2; _videoPlayer.audioOutputMode = (VideoAudioOutputMode)2; _videoPlayer.skipOnDrop = true; } private void Begin() { ((MonoBehaviour)this).StopAllCoroutines(); _skipRequested = false; _isActive = true; _videoPreparedSuccessfully = false; _sequenceStartTime = Time.unscaledTime; SetOverlayState(visible: true, instantAlphaReset: false); ApplyGameAudioMute(); ConfigureVideo(); ((MonoBehaviour)this).StartCoroutine(RunSequence()); } private void ConfigureVideo() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_00d7: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) if (!GlitnirFaderEndingPlugin.VideoEnabled.Value) { _background.texture = null; ((Graphic)_background).color = Color.black; _videoPreparedSuccessfully = false; return; } string preparedVideoPath = GlitnirFaderEndingPlugin.GetPreparedVideoPath(); if (string.IsNullOrWhiteSpace(preparedVideoPath) || !File.Exists(preparedVideoPath)) { GlitnirFaderEndingPlugin.LogWarning("Vídeo não encontrado: " + preparedVideoPath); _background.texture = null; ((Graphic)_background).color = Color.black; _videoPreparedSuccessfully = false; return; } if ((Object)(object)_renderTexture != (Object)null) { _renderTexture.Release(); Object.Destroy((Object)(object)_renderTexture); } _renderTexture = new RenderTexture(1920, 1080, 0); _videoPlayer.targetTexture = _renderTexture; _background.texture = (Texture)(object)_renderTexture; ((Graphic)_background).color = Color.white; _videoPlayer.url = preparedVideoPath; _videoPlayer.isLooping = GlitnirFaderEndingPlugin.LoopVideo.Value; _videoPlayer.SetDirectAudioMute((ushort)0, GlitnirFaderEndingPlugin.MuteVideoAudio.Value); _videoPlayer.SetDirectAudioVolume((ushort)0, Mathf.Clamp01(GlitnirFaderEndingPlugin.VideoVolume.Value)); _videoPlayer.Prepare(); } [IteratorStateMachine(typeof(<RunSequence>d__19))] private IEnumerator RunSequence() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RunSequence>d__19(0) { <>4__this = this }; } private void ApplyGameAudioMute() { if (GlitnirFaderEndingPlugin.MuteGameAudioWhileEnding.Value) { _previousGameAudioVolume = AudioListener.volume; AudioListener.volume = 0f; _audioMutedByOverlay = true; } } private void RestoreGameAudioMute() { if (_audioMutedByOverlay) { AudioListener.volume = _previousGameAudioVolume; _audioMutedByOverlay = false; } } [IteratorStateMachine(typeof(<FadeCanvas>d__22))] private IEnumerator FadeCanvas(float from, float to, float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FadeCanvas>d__22(0) { <>4__this = this, from = from, to = to, duration = duration }; } private void SetOverlayState(bool visible, bool instantAlphaReset) { if ((Object)(object)_canvas != (Object)null) { ((Behaviour)_canvas).enabled = visible; } if ((Object)(object)_canvasGroup != (Object)null) { _canvasGroup.interactable = visible; _canvasGroup.blocksRaycasts = visible; if (instantAlphaReset) { _canvasGroup.alpha = (visible ? 1f : 0f); } } } private void Update() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (_isActive && GlitnirFaderEndingPlugin.AllowSkip.Value) { float num = Time.unscaledTime - _sequenceStartTime; if (!(num < Mathf.Max(0f, GlitnirFaderEndingPlugin.MinimumSkipDelaySeconds.Value)) && TryGetSkipKey(out var key) && Input.GetKeyDown(key)) { _skipRequested = true; } } } private bool TryGetSkipKey(out KeyCode key) { return Enum.TryParse<KeyCode>(GlitnirFaderEndingPlugin.SkipKey.Value, ignoreCase: true, out key); } private void OnDestroy() { RestoreGameAudioMute(); } }