Decompiled source of LCTheWeightOfLifeMod v1.0.0

LCTheWeightOfLifeMod.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using HarmonyLib.Tools;
using LCTheWeightOfLifeMod;
using LethalConfig;
using LethalConfig.ConfigItems;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
public class MusicManager : MonoBehaviour
{
	private static ManualLogSource Logger = Plugin.Logger;

	public AudioSource musicSource;

	public AudioSource musicSourceOutro;

	public DataContainer modData;

	private bool fadeOut = false;

	public float fadeSlowdown;

	private bool fadeOutFast = false;

	public float fadeSlowdownFast;

	private float currentFadeSlowdown;

	private void Start()
	{
		Logger.LogDebug((object)"TheWeightOfLife MusicManager Start!!");
	}

	private void Update()
	{
		if (!musicSource.isPlaying)
		{
			return;
		}
		if (fadeOut || fadeOutFast)
		{
			AudioSource obj = musicSource;
			obj.volume -= Time.deltaTime / currentFadeSlowdown;
			if (musicSource.volume < 0.05f)
			{
				Logger.LogDebug((object)"stopping song");
				musicSource.Stop();
				fadeOut = false;
				fadeOutFast = false;
			}
		}
		else if (StartOfRound.Instance.localPlayerController.hasBegunSpectating && Plugin.Config.spectatorMusic.Value && (Object)(object)StartOfRound.Instance.localPlayerController.spectatedPlayerScript != (Object)(object)modData.lastSpectatedPlayer)
		{
			modData.lastSpectatedPlayer = StartOfRound.Instance.localPlayerController.spectatedPlayerScript;
			if ((Object)(object)modData.lastSpectatedPlayer == (Object)null || (Object)(object)modData.lastSpectatedPlayer != (Object)(object)modData.finalRemainingPlayer)
			{
				musicSource.spatialBlend = 1f;
			}
			else
			{
				musicSource.spatialBlend = 0f;
			}
			Logger.LogDebug((object)$"spectate swap set spatialBlend to {musicSource.spatialBlend}");
		}
	}

	public void SetMusic(Transform parentObject, float spatialBlendLevel, bool isDeadPlayer, bool startSong = true)
	{
		float volumeLevel = (isDeadPlayer ? ((float)Plugin.Config.spectatorVolume.Value / 100f) : ((float)Plugin.Config.volume.Value / 100f));
		SetMusic(parentObject, spatialBlendLevel, volumeLevel, startSong);
	}

	public void SetMusic(Transform parentObject, float spatialBlendLevel, float volumeLevel, bool startSong = true)
	{
		((Component)this).gameObject.transform.SetParent(parentObject, false);
		musicSource.spatialBlend = spatialBlendLevel;
		SetNewVolume(volumeLevel);
		if (startSong && !musicSource.isPlaying)
		{
			fadeOut = false;
			fadeOutFast = false;
			musicSource.Play();
			SoundManager val = Object.FindObjectOfType<SoundManager>();
			if ((Object)(object)val != (Object)null && val.musicSource.isPlaying)
			{
				Logger.LogDebug((object)"interjecting SoundManager musicSource on Play()");
				val.musicSource.Stop();
			}
		}
		Logger.LogDebug((object)$"Play(): {startSong} | parentObject: {((Object)parentObject).name} | spatialBlend: {musicSource.spatialBlend}");
	}

	public void SkipToOutro()
	{
		if (musicSource.isPlaying && musicSource.time < 250f)
		{
			Logger.LogDebug((object)"skipping to end of song");
			SetFadeOut();
			musicSourceOutro.PlayOneShot(modData.musicOutro);
		}
	}

	public void SetFadeOut(bool fast = true)
	{
		if (!musicSource.isPlaying)
		{
			Logger.LogDebug((object)"no music playing to fade, returning");
			return;
		}
		fadeOutFast = fast;
		fadeOut = !fast;
		currentFadeSlowdown = (fadeOut ? fadeSlowdown : fadeSlowdownFast);
		Logger.LogDebug((object)$"fast: {fast} | currentFadeSlowdown: {currentFadeSlowdown}");
	}

	public void SetNewVolume(float newVolume)
	{
		if (fadeOut)
		{
			Logger.LogDebug((object)"currently fading out, not updating volume");
			return;
		}
		if (fadeOutFast)
		{
			Logger.LogDebug((object)"currently fading to outro, not updating body volume");
			musicSourceOutro.volume = newVolume;
		}
		else
		{
			musicSource.volume = newVolume;
			musicSourceOutro.volume = newVolume;
		}
		Logger.LogDebug((object)$"set new volume: {musicSource.volume} | {musicSourceOutro.volume}");
	}
}
[CreateAssetMenu(menuName = "LCTheWeightOfLifeMod/DataContainer")]
public class DataContainer : ScriptableObject
{
	public GameObject spawnMusicPrefab;

	public AudioClip musicOutro;

	public PlayerControllerB finalRemainingPlayer;

	public PlayerControllerB lastSpectatedPlayer;

	public bool finalPlayerLocal;
}
public class CTWOL : MonoBehaviour
{
	private static ManualLogSource Logger = Plugin.Logger;

	public DataContainer modData;

	private GameObject musicObject;

	private MusicManager musicManager;

	private void Start()
	{
		Logger.LogDebug((object)"CTWOL Start()");
		SpawnMusicPrefab();
	}

	public void SpawnMusicPrefab()
	{
		if ((Object)(object)musicObject == (Object)null)
		{
			musicObject = Object.Instantiate<GameObject>(modData.spawnMusicPrefab, ((Component)StartOfRound.Instance).transform.parent, false);
			musicManager = musicObject.GetComponent<MusicManager>();
			Logger.LogDebug((object)$"{musicObject} and {musicManager} on {((Object)musicObject.transform.parent).name}");
		}
	}

	public void SetLastSurvivingPlayer()
	{
		PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
		foreach (PlayerControllerB val in allPlayerScripts)
		{
			if (!val.isPlayerDead)
			{
				modData.finalRemainingPlayer = val;
				Logger.LogDebug((object)("found lastSurvivor " + ((Object)modData.finalRemainingPlayer).name));
				SetMusicPipeline();
				break;
			}
		}
	}

	private void SetMusicPipeline()
	{
		if (!((Object)(object)modData.finalRemainingPlayer != (Object)null) || !CanSongStart())
		{
			return;
		}
		IsFinalPlayerLocal();
		Logger.LogDebug((object)$"survivor: {Plugin.Config.survivorMusic.Value} | spectator: {Plugin.Config.spectatorMusic.Value}");
		if (modData.finalPlayerLocal)
		{
			if (Plugin.Config.hudWarning.Value)
			{
				HUDManager.Instance.DisplayTip("Everyone Is Dead", "You are the final remaining player!", true, false, "LC_Tip1");
			}
			if (Plugin.Config.survivorMusic.Value)
			{
				musicManager.SetMusic(((Component)modData.finalRemainingPlayer).gameObject.transform, 0f, (float)Plugin.Config.volume.Value / 100f);
			}
		}
		else if (Plugin.Config.spectatorMusic.Value)
		{
			musicManager.SetMusic(((Component)modData.finalRemainingPlayer).gameObject.transform, 0f, (float)Plugin.Config.spectatorVolume.Value / 100f);
		}
	}

	public void OnShipLeave()
	{
		if (Plugin.Config.stopOrFade.Value)
		{
			musicManager.SkipToOutro();
		}
		else
		{
			musicManager.SetFadeOut(fast: false);
		}
		if (!StartOfRound.Instance.localPlayerController.isPlayerDead || (StartOfRound.Instance.localPlayerController.isPlayerDead && Plugin.Config.spectatorMusic.Value))
		{
			musicManager.SetMusic(((Component)StartOfRound.Instance).transform, 0f, StartOfRound.Instance.localPlayerController.isPlayerDead, startSong: false);
			modData.finalRemainingPlayer = null;
		}
	}

	public void StopMusic()
	{
		Logger.LogDebug((object)"Stop();");
		if (musicManager.musicSource.isPlaying)
		{
			musicManager.musicSource.Stop();
		}
		musicManager.SetMusic(((Component)StartOfRound.Instance).transform, 0f, StartOfRound.Instance.localPlayerController.isPlayerDead, startSong: false);
		modData.finalRemainingPlayer = null;
	}

	private bool CanSongStart()
	{
		bool flag = false;
		if (!Plugin.Config.startInFacility.Value || (Plugin.Config.startInFacility.Value && modData.finalRemainingPlayer.isInsideFactory))
		{
			flag = true;
		}
		Logger.LogDebug((object)$"config: {Plugin.Config.startInFacility.Value} | CanSongStart(): {flag}");
		return flag;
	}

	public bool IsMusicPlaying()
	{
		return musicManager.musicSource.isPlaying;
	}

	private void IsFinalPlayerLocal()
	{
		modData.finalPlayerLocal = (Object)(object)modData.finalRemainingPlayer == (Object)(object)StartOfRound.Instance.localPlayerController;
		Logger.LogDebug((object)$"finalPlayerLocal: {modData.finalPlayerLocal}");
	}
}
public class HarmonyPatches
{
	[HarmonyPatch]
	public class SpawnPrefab
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "Start")]
		public static void StartPostfix()
		{
			if (Plugin.LoadSuccessful)
			{
				managerScript = Object.Instantiate<GameObject>(Plugin.CTWOLAssetBundle.LoadAsset<GameObject>("Assets/LCTheWeightOfLifeMod/Prefabs/CTWOLManagerObject.prefab"), Plugin.SearchForSimonTendoManagers().transform, false).GetComponent<CTWOL>();
			}
		}
	}

	[HarmonyPatch]
	public class ResetPrefab
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "ShipLeave")]
		public static void ShipLeavePostfix()
		{
			if (Plugin.LoadSuccessful)
			{
				managerScript.OnShipLeave();
			}
		}
	}

	[HarmonyPatch]
	public class StartMusic
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayerClientRpc")]
		public static void KillPlayerClientRpcPostfix()
		{
			if (!Plugin.LoadSuccessful)
			{
				return;
			}
			if (StartOfRound.Instance.allPlayersDead && !StartOfRound.Instance.shipIsLeaving)
			{
				managerScript.StopMusic();
				return;
			}
			Logger.LogDebug((object)$"remaining players for needed amount: {Plugin.Config.teamSize.Value - 1 - (StartOfRound.Instance.connectedPlayersAmount + 1 - StartOfRound.Instance.livingPlayers)}");
			if (StartOfRound.Instance.connectedPlayersAmount >= Plugin.Config.teamSize.Value - 1 && StartOfRound.Instance.livingPlayers == 1)
			{
				managerScript.SetLastSurvivingPlayer();
			}
		}
	}

	[HarmonyPatch]
	public class InterruptMusic
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(SoundManager), "PlayRandomOutsideMusic")]
		public static bool PlayRandomOutsideMusicPrefix()
		{
			if (Plugin.LoadSuccessful)
			{
				return !managerScript.IsMusicPlaying();
			}
			return true;
		}
	}

	private static ManualLogSource Logger = Plugin.Logger;

	private static CTWOL managerScript;
}
namespace LCTheWeightOfLifeMod;

[BepInPlugin("LCTheWeightOfLifeMod", "LCTheWeightOfLifeMod", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public class Config
	{
		public static ConfigEntry<int> teamSize;

		public static ConfigEntry<bool> startInFacility;

		public static ConfigEntry<bool> stopOrFade;

		public static ConfigEntry<bool> hudWarning;

		public static ConfigEntry<bool> survivorMusic;

		public static ConfigEntry<int> volume;

		public static ConfigEntry<bool> spectatorMusic;

		public static ConfigEntry<int> spectatorVolume;

		public Config(ConfigFile cfg)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			teamSize = cfg.Bind<int>("Customization", "Minimum Team Size", 3, new ConfigDescription("Set how many total people need to be in the lobby to play Carrying The Weight Of Life once only a single player remains.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 50), Array.Empty<object>()));
			startInFacility = cfg.Bind<bool>("Customization", "Start In Facility", true, "Set whether Carrying The Weight Of Life can only start playing if the final remaining player is inside the facility (true), or if the music can start playing outside too (false).");
			stopOrFade = cfg.Bind<bool>("Customization", "Outro Upon Leaving", true, "Set whether Carrying The Weight Of Life jumps to the outro as soon as the final remaining player pulls the ship's lever (true), or if the song fades out (false).");
			hudWarning = cfg.Bind<bool>("Customization", "Display Warning Message", false, "Set whether you will get an extra on-screen message as soon as you are the final remaining player (true), or if only Carrying The Weight Of Life will start playing (false).");
			survivorMusic = cfg.Bind<bool>("Final Survivor", "Survivor Hears Music", true, "Set whether Carrying The Weight Of Life starts playing the moment all your teammates have died (true), or if no music plays while you are the final remaining player (false).");
			volume = cfg.Bind<int>("Final Survivor", "Survivor Volume", 80, new ConfigDescription("If [Survivor Hears Music] is set to true, set how loud the volume of Carrying The Weight Of Life is if you are the final remaining player.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			spectatorMusic = cfg.Bind<bool>("Spectators", "Spectator Hears Music", false, "Set whether you can hear Carrying The Weight Of Life from the final remaining player while spectating (true), or if you can only hear it as the final remaining player (false).");
			spectatorVolume = cfg.Bind<int>("Spectators", "Spectator Volume", 25, new ConfigDescription("If [Spectator Hears Music] is set to true, set how loud the volume of Carrying The Weight Of Life is if you are a spectator.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		}
	}

	internal static ManualLogSource Logger;

	public static AssetBundle CTWOLAssetBundle;

	public static bool LoadSuccessful;

	public static Config MyConfig { get; internal set; }

	private void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		Logger = ((BaseUnityPlugin)this).Logger;
		Logger.LogInfo((object)"Plugin LCTheWeightOfLifeMod is loaded!");
		Harmony val = new Harmony("LCTheWeightOfLifeMod");
		val.PatchAll();
		HarmonyFileLog.Enabled = false;
		MyConfig = new Config(((BaseUnityPlugin)this).Config);
		CTWOLAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "pineapple"));
		if ((Object)(object)CTWOLAssetBundle != (Object)null)
		{
			Logger.LogInfo((object)"Loaded TheWeightOfLife asset bundle");
			LoadSuccessful = true;
			DisplayConfigs();
			if (CheckForPlugin("LethalConfig"))
			{
				AddLethalConfig();
			}
		}
		else
		{
			Logger.LogError((object)"Failed to load TheWeightOfLife asset bundle");
		}
	}

	private static void DisplayConfigs()
	{
		Logger.LogInfo((object)$"Config [Minimum Team Size] is set to a value of {Config.teamSize.Value}");
		if (Config.startInFacility.Value)
		{
			Logger.LogInfo((object)"Config [Start In Facility] is set to TRUE. Carrying The Weight Of Life can only start playing if the final remaining player is inside the facility.");
		}
		else
		{
			Logger.LogInfo((object)"Config [Start In Facility] is set to FALSE. Carrying The Weight Of Life starts playing regardless of where the final remaining player is at that moment.");
		}
		if (Config.stopOrFade.Value)
		{
			Logger.LogInfo((object)"Config [Outro Upon Leaving] is set to TRUE. As soon as the final remaining player departs, Carrying The Weight Of Life's outro will play.");
		}
		else
		{
			Logger.LogInfo((object)"Config [Outro Upon Leaving] is set to FALSE. As soon as the final remaining player departs, Carrying The Weight Of Life will fade out.");
		}
		if (Config.hudWarning.Value)
		{
			Logger.LogInfo((object)"Config [Display Warning Message] is set to TRUE. As soon as you are the final remaining player, you will get an extra on-screen message.");
		}
		else
		{
			Logger.LogInfo((object)"Config [Display Warning Message] is set to FALSE. As soon as you are the final remaining player, you will only hear Carrying The Weight Of Life.");
		}
		if (!Config.survivorMusic.Value && !Config.spectatorMusic.Value)
		{
			Logger.LogInfo((object)"Configs [Survivor Hears Music] and [Spectator Hears Music] are both set to FALSE. Did you want something a bit meatier?");
			return;
		}
		if (Config.survivorMusic.Value)
		{
			Logger.LogInfo((object)"Config [Survivor Hears Music] is set to TRUE. You will hear Carrying The Weight Of Life the moment all your teammates have died.");
		}
		else
		{
			Logger.LogInfo((object)"Config [Survivor Hears Music] is set to FALSE. You will not hear Carrying The Weight Of Life if you are the final remaining living player.");
		}
		if (Config.survivorMusic.Value)
		{
			Logger.LogInfo((object)$"Config [Survivor Volume] is set to a value of {Config.volume.Value}.");
		}
		if (Config.spectatorMusic.Value)
		{
			Logger.LogInfo((object)"Config [Spectator Hears Music] is set to TRUE. You will be able to hear Carrying The Weight Of Life, even if you are not the final remaining player");
		}
		else
		{
			Logger.LogInfo((object)"Config [Spectator Hears Music] is set to FALSE. You will only hear Carrying The Weight Of Life if you are the final remaining player.");
		}
		if (Config.spectatorMusic.Value)
		{
			Logger.LogInfo((object)$"Config [Spectator Volume] is set to a value of {Config.spectatorVolume.Value}.");
		}
	}

	private static bool CheckForPlugin(string pluginName, bool printDebug = true)
	{
		foreach (PluginInfo value in Chainloader.PluginInfos.Values)
		{
			if (value.Metadata.Name == pluginName)
			{
				if (printDebug)
				{
					Logger.LogDebug((object)("Successfully found " + pluginName));
				}
				return true;
			}
		}
		if (printDebug)
		{
			Logger.LogDebug((object)("Failed to find " + pluginName));
		}
		return false;
	}

	private static void AddLethalConfig()
	{
		RegisterToLethalConfig();
		Config.survivorMusic.SettingChanged += delegate
		{
			CTWOL cTWOL2 = Object.FindObjectOfType<CTWOL>();
			if ((Object)(object)cTWOL2 != (Object)null && !StartOfRound.Instance.localPlayerController.isPlayerDead)
			{
				cTWOL2.StopMusic();
			}
		};
		Config.volume.SettingChanged += delegate
		{
			MusicManager musicManager2 = Object.FindObjectOfType<MusicManager>();
			if ((Object)(object)musicManager2 != (Object)null && !StartOfRound.Instance.localPlayerController.isPlayerDead)
			{
				musicManager2.SetNewVolume((float)Config.volume.Value / 100f);
			}
		};
		Config.spectatorMusic.SettingChanged += delegate
		{
			CTWOL cTWOL = Object.FindObjectOfType<CTWOL>();
			if ((Object)(object)cTWOL != (Object)null && StartOfRound.Instance.localPlayerController.isPlayerDead)
			{
				cTWOL.StopMusic();
			}
		};
		Config.spectatorVolume.SettingChanged += delegate
		{
			MusicManager musicManager = Object.FindObjectOfType<MusicManager>();
			if ((Object)(object)musicManager != (Object)null && StartOfRound.Instance.localPlayerController.isPlayerDead)
			{
				musicManager.SetNewVolume((float)Config.spectatorVolume.Value / 100f);
			}
		};
	}

	private static void RegisterToLethalConfig()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Expected O, but got Unknown
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Expected O, but got Unknown
		LethalConfigManager.SetModIcon(CTWOLAssetBundle.LoadAsset<Sprite>("Assets/LCTheWeightOfLifeMod/Sprites/icon.png"));
		LethalConfigManager.SetModDescription("Play this high-energy Xenoblade Chronicles 3 song as soon as only one teammate is left alive!");
		LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(Config.teamSize, false));
		LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(Config.startInFacility, false));
		LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(Config.stopOrFade, false));
		LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(Config.hudWarning, false));
		LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(Config.survivorMusic, false));
		LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(Config.volume, false));
		LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(Config.spectatorMusic, false));
		LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(Config.spectatorVolume, false));
	}

	public static GameObject SearchForSimonTendoManagers()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		GameObject[] array = Object.FindObjectsOfType<GameObject>();
		GameObject[] array2 = array;
		GameObject result;
		foreach (GameObject val in array2)
		{
			if (((Object)val).name == "SimonTendoManagers")
			{
				result = val;
				Logger.LogDebug((object)("Found existing " + ((Object)val).name + ", using as parent."));
				return result;
			}
		}
		result = new GameObject("SimonTendoManagers");
		result.transform.SetParent(((Component)StartOfRound.Instance).gameObject.transform.parent);
		Logger.LogDebug((object)("Did not find existing Object, instantiating new " + ((Object)result).name));
		return result;
	}
}