using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BossVSIntro")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Boss VS Intro")]
[assembly: AssemblyTitle("BossVSIntro")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 BossVSIntro
{
[BepInPlugin("com.scout.bossvsintro", "Boss VS Intro", "1.2.0")]
public class BossVSIntroPlugin : BaseUnityPlugin
{
public const string PluginGuid = "com.scout.bossvsintro";
public const string PluginName = "Boss VS Intro";
public const string PluginVersion = "1.2.0";
internal static BossVSIntroPlugin Instance;
internal static ManualLogSource Log;
internal static string ImagesRoot;
internal static string SoundsRoot;
internal static string PluginDir;
private void Awake()
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
PluginDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
ImagesRoot = Path.Combine(PluginDir, "Images");
SoundsRoot = Path.Combine(PluginDir, "Sounds");
new Harmony("com.scout.bossvsintro").PatchAll();
Log.LogInfo((object)"Boss VS Intro v1.2.0 loaded.");
BossVSIntroPatch.BeginPreloadSounds();
}
}
internal static class VSConfig
{
public static float introCooldown = 5f;
public static float slideInDuration = 0.45f;
public static float vsPopDuration = 0.35f;
public static float vsStartScale = 3.5f;
public static float vsHeightFraction = 0.35f;
public static float shakeDuration = 0.4f;
public static float shakeAmplitude = 38f;
public static float holdDuration = 1f;
public static float slideOutDuration = 0.4f;
public static float centerGap = -1920f;
public static string triggerSoundFile = "Trigger.wav";
public static float soundVolume = 1f;
public static float vsDelay = 1f;
public static string playerFileName = "Player.png";
public static string vsFileName = "VS.png";
public static string bossFolderName = "Bosses";
public static string bossFallbackName = "Default.png";
}
public class VSRunner : MonoBehaviour
{
}
[HarmonyPatch(typeof(BossHealthBarTemplate))]
public class BossVSIntroPatch
{
private static bool introPlaying;
private static float lastIntroTime = -9999f;
private static Canvas introCanvas;
private static AudioSource introAudio;
private static readonly Dictionary<string, Sprite> spriteCache = new Dictionary<string, Sprite>();
private static AudioClip triggerClip;
private static MonoBehaviour runner;
private static MonoBehaviour Runner
{
get
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
if ((Object)(object)runner == (Object)null)
{
GameObject val = new GameObject("BossVSIntroRunner");
Object.DontDestroyOnLoad((Object)(object)val);
runner = (MonoBehaviour)(object)val.AddComponent<VSRunner>();
}
return runner;
}
}
[HarmonyPostfix]
[HarmonyPatch("Initialize", new Type[]
{
typeof(BossHealthBar),
typeof(SliderLayer[])
})]
private static void InitializePostfix(BossHealthBarTemplate __instance, BossHealthBar bossBar, SliderLayer[] colorLayers)
{
BossVSIntroPlugin.Log.LogInfo((object)("[VS] Initialize fired for: " + bossBar?.bossName));
if (!((Object)(object)__instance == (Object)null) && !((Object)(object)bossBar == (Object)null) && !string.IsNullOrEmpty(bossBar.bossName))
{
if (introPlaying)
{
BossVSIntroPlugin.Log.LogWarning((object)"[VS] Bailed: introPlaying is STUCK true — last splash never finished.");
return;
}
if (Time.unscaledTime - lastIntroTime < VSConfig.introCooldown)
{
BossVSIntroPlugin.Log.LogWarning((object)$"[VS] Bailed: on cooldown ({Time.unscaledTime - lastIntroTime:F1}s since last < {VSConfig.introCooldown}s).");
return;
}
BossVSIntroPlugin.Log.LogInfo((object)"[VS] All guards passed — starting splash coroutine.");
Runner.StartCoroutine(PlayVSIntro(bossBar.bossName));
}
}
public static void BeginPreloadSounds()
{
Runner.StartCoroutine(PreloadSounds());
}
private static IEnumerator PreloadSounds()
{
yield return LoadClip(Path.Combine(BossVSIntroPlugin.SoundsRoot, VSConfig.triggerSoundFile), delegate(AudioClip c)
{
triggerClip = c;
});
}
private static IEnumerator LoadClip(string fullPath, Action<AudioClip> onLoaded)
{
if (!File.Exists(fullPath))
{
BossVSIntroPlugin.Log.LogWarning((object)("Sound not found (splash will be silent for this one): " + fullPath));
onLoaded(null);
yield break;
}
AudioType type = GuessAudioType(fullPath);
UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip("file://" + fullPath, type);
try
{
yield return req.SendWebRequest();
if ((int)req.result != 1)
{
BossVSIntroPlugin.Log.LogError((object)("Failed to load sound '" + fullPath + "': " + req.error));
onLoaded(null);
yield break;
}
onLoaded(DownloadHandlerAudioClip.GetContent(req));
}
finally
{
((IDisposable)req)?.Dispose();
}
}
private static AudioType GuessAudioType(string path)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
string text = Path.GetExtension(path).ToLowerInvariant();
string text2 = text;
if (!(text2 == ".ogg"))
{
if (text2 == ".mp3")
{
return (AudioType)13;
}
return (AudioType)20;
}
return (AudioType)14;
}
private static void PlaySound(AudioClip clip)
{
if (!((Object)(object)clip == (Object)null) && !((Object)(object)introAudio == (Object)null))
{
introAudio.PlayOneShot(clip, VSConfig.soundVolume);
}
}
private static string Sanitize(string name)
{
StringBuilder stringBuilder = new StringBuilder();
string text = name.ToUpperInvariant();
foreach (char c in text)
{
if (char.IsLetterOrDigit(c))
{
stringBuilder.Append(c);
}
else if (c == ' ' || c == '-' || c == '_')
{
stringBuilder.Append('_');
}
}
return stringBuilder.ToString();
}
private static Sprite LoadSprite(string fullPath)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
if (spriteCache.TryGetValue(fullPath, out var value))
{
return value;
}
if (!File.Exists(fullPath))
{
return null;
}
try
{
byte[] array = File.ReadAllBytes(fullPath);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
ImageConversion.LoadImage(val, array);
((Texture)val).filterMode = (FilterMode)1;
((Texture)val).wrapMode = (TextureWrapMode)1;
Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
spriteCache[fullPath] = val2;
return val2;
}
catch (Exception ex)
{
BossVSIntroPlugin.Log.LogError((object)("Failed to load image '" + fullPath + "': " + ex.Message));
return null;
}
}
private static Canvas GetOrCreateCanvas()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
if ((Object)(object)introCanvas != (Object)null)
{
return introCanvas;
}
GameObject val = new GameObject("BossVSIntroCanvas");
Object.DontDestroyOnLoad((Object)(object)val);
introCanvas = val.AddComponent<Canvas>();
introCanvas.renderMode = (RenderMode)0;
introCanvas.sortingOrder = 32767;
CanvasScaler val2 = val.AddComponent<CanvasScaler>();
val2.uiScaleMode = (ScaleMode)0;
val2.scaleFactor = 1f;
val.AddComponent<GraphicRaycaster>();
introAudio = val.AddComponent<AudioSource>();
introAudio.playOnAwake = false;
introAudio.spatialBlend = 0f;
introAudio.ignoreListenerPause = true;
return introCanvas;
}
private static Image MakeImage(Transform parent, Sprite sprite, string name, float targetHeight)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name);
val.transform.SetParent(parent, false);
Image val2 = val.AddComponent<Image>();
val2.sprite = sprite;
((Graphic)val2).raycastTarget = false;
val2.preserveAspect = true;
RectTransform rectTransform = ((Graphic)val2).rectTransform;
rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
rectTransform.pivot = new Vector2(0.5f, 0.5f);
float num = (float)((Texture)sprite.texture).width / (float)((Texture)sprite.texture).height;
rectTransform.sizeDelta = new Vector2(targetHeight * num, targetHeight);
rectTransform.anchoredPosition = Vector2.zero;
((Transform)rectTransform).localScale = Vector3.one;
return val2;
}
private static float EaseOutCubic(float x)
{
return 1f - Mathf.Pow(1f - x, 3f);
}
private static float EaseInCubic(float x)
{
return x * x * x;
}
private static IEnumerator PlayVSIntro(string bossName)
{
introPlaying = true;
string playerPath = Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.playerFileName);
string vsPath = Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.vsFileName);
string bossPath = Path.Combine(path3: Sanitize(bossName) + ".png", path1: BossVSIntroPlugin.ImagesRoot, path2: VSConfig.bossFolderName);
string bossFallback = Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.bossFolderName, VSConfig.bossFallbackName);
Sprite playerSprite = LoadSprite(playerPath);
Sprite vsSprite = LoadSprite(vsPath);
Sprite bossSprite = LoadSprite(bossPath) ?? LoadSprite(bossFallback);
if ((Object)(object)playerSprite == (Object)null)
{
BossVSIntroPlugin.Log.LogWarning((object)("Missing player image: " + playerPath));
}
if ((Object)(object)vsSprite == (Object)null)
{
BossVSIntroPlugin.Log.LogWarning((object)("Missing VS image: " + vsPath));
}
if ((Object)(object)bossSprite == (Object)null)
{
BossVSIntroPlugin.Log.LogWarning((object)("Missing boss image (and no Default.png): " + bossPath));
}
if ((Object)(object)playerSprite == (Object)null || (Object)(object)vsSprite == (Object)null || (Object)(object)bossSprite == (Object)null)
{
introPlaying = false;
yield break;
}
lastIntroTime = Time.unscaledTime;
float previousTimeScale = Time.timeScale;
Time.timeScale = 0f;
Image playerImg = null;
Image bossImg = null;
Image vsImg = null;
IEnumerator anim = AnimateCard(playerSprite, bossSprite, vsSprite, delegate(Image img)
{
playerImg = img;
}, delegate(Image img)
{
bossImg = img;
}, delegate(Image img)
{
vsImg = img;
});
while (true)
{
object current;
try
{
if (!anim.MoveNext())
{
break;
}
current = anim.Current;
goto IL_0295;
}
catch (Exception ex)
{
Exception e = ex;
BossVSIntroPlugin.Log.LogError((object)$"[VS] Splash threw, bailing safely: {e}");
}
break;
IL_0295:
yield return current;
}
if ((Object)(object)playerImg != (Object)null)
{
Object.Destroy((Object)(object)((Component)playerImg).gameObject);
}
if ((Object)(object)bossImg != (Object)null)
{
Object.Destroy((Object)(object)((Component)bossImg).gameObject);
}
if ((Object)(object)vsImg != (Object)null)
{
Object.Destroy((Object)(object)((Component)vsImg).gameObject);
}
Time.timeScale = previousTimeScale;
introPlaying = false;
}
private static IEnumerator AnimateCard(Sprite playerSprite, Sprite bossSprite, Sprite vsSprite, Action<Image> outPlayer, Action<Image> outBoss, Action<Image> outVs)
{
Canvas canvas = GetOrCreateCanvas();
PlaySound(triggerClip);
float screenW = Screen.width;
float screenH = Screen.height;
Image playerImg = MakeImage(((Component)canvas).transform, playerSprite, "VS_Player", screenH);
Image bossImg = MakeImage(((Component)canvas).transform, bossSprite, "VS_Boss", screenH);
Image vsImg = MakeImage(((Component)canvas).transform, vsSprite, "VS_Badge", screenH * VSConfig.vsHeightFraction);
outPlayer(playerImg);
outBoss(bossImg);
outVs(vsImg);
RectTransform playerRT = ((Graphic)playerImg).rectTransform;
RectTransform bossRT = ((Graphic)bossImg).rectTransform;
RectTransform vsRT = ((Graphic)vsImg).rectTransform;
float halfGap = VSConfig.centerGap * 0.5f;
float playerHalfW = playerRT.sizeDelta.x * 0.5f;
float bossHalfW = bossRT.sizeDelta.x * 0.5f;
Vector2 playerStart = new Vector2(0f - screenW, 0f);
Vector2 bossStart = new Vector2(screenW, 0f);
Vector2 playerEnd = new Vector2(0f - (playerHalfW + halfGap), 0f);
Vector2 bossEnd = new Vector2(bossHalfW + halfGap, 0f);
playerRT.anchoredPosition = playerStart;
bossRT.anchoredPosition = bossStart;
vsRT.anchoredPosition = Vector2.zero;
((Transform)playerRT).SetAsLastSibling();
((Transform)bossRT).SetAsLastSibling();
((Transform)vsRT).SetAsLastSibling();
((Component)vsImg).gameObject.SetActive(false);
float t = 0f;
while (t < VSConfig.slideInDuration)
{
t += Time.unscaledDeltaTime;
float k = EaseOutCubic(Mathf.Clamp01(t / VSConfig.slideInDuration));
playerRT.anchoredPosition = Vector2.LerpUnclamped(playerStart, playerEnd, k);
bossRT.anchoredPosition = Vector2.LerpUnclamped(bossStart, bossEnd, k);
yield return null;
}
playerRT.anchoredPosition = playerEnd;
bossRT.anchoredPosition = bossEnd;
t = 0f;
while (t < VSConfig.vsDelay)
{
t += Time.unscaledDeltaTime;
yield return null;
}
((Component)vsImg).gameObject.SetActive(true);
float impactDuration = Mathf.Max(VSConfig.vsPopDuration, VSConfig.shakeDuration);
t = 0f;
while (t < impactDuration)
{
t += Time.unscaledDeltaTime;
float kv = EaseOutCubic(Mathf.Clamp01(t / VSConfig.vsPopDuration));
((Transform)vsRT).localScale = Vector3.one * Mathf.LerpUnclamped(VSConfig.vsStartScale, 1f, kv);
float decay = 1f - Mathf.Clamp01(t / VSConfig.shakeDuration);
float amp = VSConfig.shakeAmplitude * decay;
playerRT.anchoredPosition = playerEnd + new Vector2(Random.Range(0f - amp, amp), Random.Range(0f - amp, amp));
bossRT.anchoredPosition = bossEnd + new Vector2(Random.Range(0f - amp, amp), Random.Range(0f - amp, amp));
yield return null;
}
((Transform)vsRT).localScale = Vector3.one;
playerRT.anchoredPosition = playerEnd;
bossRT.anchoredPosition = bossEnd;
t = 0f;
while (t < VSConfig.holdDuration)
{
t += Time.unscaledDeltaTime;
yield return null;
}
Vector2 vsUpEnd = new Vector2(0f, screenH);
t = 0f;
while (t < VSConfig.slideOutDuration)
{
t += Time.unscaledDeltaTime;
float k2 = EaseInCubic(Mathf.Clamp01(t / VSConfig.slideOutDuration));
playerRT.anchoredPosition = Vector2.LerpUnclamped(playerEnd, playerStart, k2);
bossRT.anchoredPosition = Vector2.LerpUnclamped(bossEnd, bossStart, k2);
vsRT.anchoredPosition = Vector2.LerpUnclamped(Vector2.zero, vsUpEnd, k2);
yield return null;
}
}
}
}