using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PizzaTowerEscapeMusic.Scripting;
using PizzaTowerEscapeMusic.Scripting.Conditions;
using PizzaTowerEscapeMusic.Scripting.ScriptEvents;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PizzaTowerEscapeMusic")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Plays music from Pizza Tower when the early ship leave alert appears")]
[assembly: AssemblyFileVersion("2.0.2.0")]
[assembly: AssemblyInformationalVersion("2.0.2")]
[assembly: AssemblyProduct("PizzaTowerEscapeMusic")]
[assembly: AssemblyTitle("PizzaTowerEscapeMusic")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 PizzaTowerEscapeMusic
{
public class Configuration
{
private readonly ConfigFile config;
internal ConfigEntry<float> volumeMaster;
internal ConfigEntry<string> scriptingScript;
public Configuration(ConfigFile config)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: 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
this.config = config;
RemoveObsoleteEntries();
scriptingScript = config.Bind<string>("Scripting", "Script", "Default", new ConfigDescription("The name of the JSON script file that will be loaded", (AcceptableValueBase)null, Array.Empty<object>()));
volumeMaster = config.Bind<float>("Volume", "Master", 0.5f, new ConfigDescription("The volume of the music as a whole, all volumes are scaled by this value", (AcceptableValueBase)null, Array.Empty<object>()));
}
private void RemoveObsoleteEntry(string section, string key)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
ConfigDefinition val = new ConfigDefinition(section, key);
config.Bind<string>(val, "", (ConfigDescription)null);
config.Remove(val);
}
private void RemoveObsoleteEntries()
{
RemoveObsoleteEntry("Volume", "InsideFacility");
RemoveObsoleteEntry("Volume", "OutsideFacility");
RemoveObsoleteEntry("Volume", "InsideShip");
RemoveObsoleteEntry("Volume", "CrouchingScale");
RemoveObsoleteEntry("Music", "InsideFacility");
RemoveObsoleteEntry("Music", "OutsideFacility");
RemoveObsoleteEntry("Music", "HeavyWeather");
}
}
public class GameEventListener : MonoBehaviour
{
private ManualLogSource logger;
public Action OnSoundManagerCreated = delegate
{
};
public Action OnSoundManagerDestroyed = delegate
{
};
public Action OnDungeonDoneGenerating = delegate
{
};
public Action OnShipLanded = delegate
{
};
public Action OnShipTakeOff = delegate
{
};
public Action OnShipReturnToOrbit = delegate
{
};
public Action OnShipLeavingAlertCalled = delegate
{
};
public Action OnPlayerDamaged = delegate
{
};
public Action OnPlayerDeath = delegate
{
};
public Action OnPlayerEnteredFacility = delegate
{
};
public Action OnPlayerExitedFacility = delegate
{
};
public Action OnPlayerEnteredShip = delegate
{
};
public Action OnPlayerExitedShip = delegate
{
};
public Action OnApparatusTaken = delegate
{
};
public Action<SelectableLevel?> OnCurrentMoonChanged = delegate
{
};
private readonly Dictionary<string, object?> previousValues = new Dictionary<string, object>();
private LungProp? dockedApparatus;
private void Awake()
{
logger = Logger.CreateLogSource("PizzaTowerEscapeMusic GameEventListener");
OnShipLanded = (Action)Delegate.Combine(OnShipLanded, new Action(FindDockedApparatus));
}
private void FindDockedApparatus()
{
logger.LogDebug((object)"Checking for docked Apparatus...");
LungProp[] array = Object.FindObjectsOfType<LungProp>();
foreach (LungProp val in array)
{
if (val.isLungDocked)
{
logger.LogDebug((object)"Found docked Apparatus");
dockedApparatus = val;
return;
}
}
logger.LogDebug((object)"Could not find docked Apparatus");
}
private void Update()
{
CheckSoundManager();
CheckDungeonDoneGenerating();
CheckShipLanded();
CheckShipReturnToOrbit();
CheckShipLeavingAlertCalled();
CheckPlayerDamaged();
CheckPlayerDeath();
CheckPlayerInsideFacility();
CheckPlayerInsideShip();
CheckApparatusTaken();
CheckCurrentMoonChanged();
}
private T? UpdateCached<T>(string key, T? currentValue, T? defaultValue)
{
if (!previousValues.TryGetValue(key, out object value))
{
value = defaultValue;
}
previousValues[key] = currentValue;
return (T)value;
}
private void CheckSoundManager()
{
bool flag = (Object)(object)SoundManager.Instance != (Object)null;
if (UpdateCached("SoundManager", flag, defaultValue: false) != flag)
{
if (flag)
{
logger.LogDebug((object)"Sound Manager created");
OnSoundManagerCreated();
}
else
{
logger.LogDebug((object)"Sound Manager destroyed");
OnSoundManagerDestroyed();
}
}
}
private void CheckDungeonDoneGenerating()
{
bool flag = (Object)(object)RoundManager.Instance != (Object)null && RoundManager.Instance.dungeonCompletedGenerating;
bool flag2 = UpdateCached("DungeonDoneGenerating", flag, defaultValue: false);
if (flag != flag2 && flag)
{
logger.LogDebug((object)"Dungeon done generating");
OnDungeonDoneGenerating();
}
}
private void CheckShipLanded()
{
bool flag = (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipHasLanded;
bool flag2 = UpdateCached("ShipLanded", flag, defaultValue: true);
if (flag != flag2 && !((Object)(object)StartOfRound.Instance == (Object)null))
{
if (flag)
{
logger.LogDebug((object)"Ship has landed");
OnShipLanded();
}
else
{
logger.LogDebug((object)"Ship has taken off");
OnShipTakeOff();
}
}
}
private void CheckShipReturnToOrbit()
{
bool flag = (Object)(object)StartOfRound.Instance == (Object)null || (!StartOfRound.Instance.shipHasLanded && !StartOfRound.Instance.shipIsLeaving);
bool flag2 = UpdateCached("ShipReturnToOrbit", flag, defaultValue: true);
if (flag != flag2 && flag)
{
logger.LogDebug((object)"Ship returned to orbit");
OnShipReturnToOrbit();
}
}
private void CheckShipLeavingAlertCalled()
{
bool flag = (Object)(object)TimeOfDay.Instance != (Object)null && TimeOfDay.Instance.shipLeavingAlertCalled;
bool flag2 = UpdateCached("ShipLeavingAlertCalled", flag, defaultValue: false);
if (flag != flag2 && flag)
{
logger.LogDebug((object)"Ship leaving alert called");
OnShipLeavingAlertCalled();
}
}
private void CheckPlayerDamaged()
{
if (!((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null))
{
int health = GameNetworkManager.Instance.localPlayerController.health;
int num = UpdateCached("PlayerDamaged", health, 100);
if (health < num)
{
logger.LogDebug((object)$"Player took damage (Health: {GameNetworkManager.Instance.localPlayerController.health})");
OnPlayerDamaged();
}
}
}
private void CheckPlayerDeath()
{
bool flag = (Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null && GameNetworkManager.Instance.localPlayerController.isPlayerDead;
bool flag2 = UpdateCached("PlayerDeath", flag, defaultValue: false);
if (flag != flag2 && flag)
{
logger.LogDebug((object)"Player has died");
OnPlayerDeath();
}
}
private void CheckPlayerInsideFacility()
{
bool flag = (Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null && GameNetworkManager.Instance.localPlayerController.isInsideFactory;
bool flag2 = UpdateCached("PlayerInsideFacility", flag, defaultValue: false);
if (flag != flag2)
{
if (flag)
{
logger.LogDebug((object)"Player entered facility");
OnPlayerEnteredFacility();
}
else
{
logger.LogDebug((object)"Player exited facility");
OnPlayerExitedFacility();
}
}
}
private void CheckPlayerInsideShip()
{
bool flag = (Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null && GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom;
bool flag2 = UpdateCached("PlayerInsideShip", flag, defaultValue: false);
if (flag != flag2)
{
if (flag)
{
logger.LogDebug((object)"Player entered ship");
OnPlayerEnteredShip();
}
else
{
logger.LogDebug((object)"Player exited ship");
OnPlayerExitedShip();
}
}
}
private void CheckApparatusTaken()
{
bool flag = (Object)(object)dockedApparatus != (Object)null && !dockedApparatus.isLungDocked;
bool flag2 = UpdateCached("ApparatusTaken", flag, defaultValue: false);
if (flag != flag2 && flag)
{
dockedApparatus = null;
logger.LogDebug((object)"Apparatus was taken");
OnApparatusTaken();
}
}
private void CheckCurrentMoonChanged()
{
SelectableLevel val = TimeOfDay.Instance?.currentLevel;
SelectableLevel val2 = UpdateCached<SelectableLevel>("CurrentMoon", val, null);
if (!((Object)(object)val == (Object)(object)val2))
{
logger.LogDebug((object)("Level has changed to " + val?.PlanetName));
OnCurrentMoonChanged(val);
}
}
}
public class MusicManager : MonoBehaviour
{
private class MusicInstance
{
public ScriptEvent_PlayMusic musicEvent;
public AudioSource audioSource;
public Script.VolumeGroup volumeGroup;
private bool isStopping;
private float volume;
public float FadeSpeed { get; private set; }
public MusicInstance(ScriptEvent_PlayMusic musicEvent, AudioSource audioSource, AudioClip? musicClip)
{
this.musicEvent = musicEvent;
this.audioSource = audioSource;
audioSource.clip = musicClip;
audioSource.loop = musicEvent.loop;
audioSource.Play();
musicInstances.Add(this);
if (musicEvent.tag != null)
{
if (!musicInstancesByTag.TryGetValue(musicEvent.tag, out List<MusicInstance> value))
{
value = new List<MusicInstance>(1);
musicInstancesByTag.Add(musicEvent.tag, value);
Debug.Log((object)("musicInstancesByTag didn't have a list for tag " + musicEvent.tag + ", creating one now"));
}
Debug.Log((object)"Added music instance to musicInstancesByTag");
value.Add(this);
}
volumeGroup = Plugin.ScriptManager.TryGetVolumeGroup(musicEvent.tag);
volume = volumeGroup.GetVolume();
}
public void Update(float deltaTime)
{
float num = (isStopping ? 0f : volumeGroup.GetVolume());
float num2 = (isStopping ? volumeGroup.stoppingVolumeLerpSpeed : volumeGroup.volumeLerpSpeed);
volume = Mathf.Lerp(volume, num, num2 * deltaTime);
audioSource.volume = volume * Plugin.Configuration.volumeMaster.Value;
if (!audioSource.isPlaying || (isStopping && audioSource.volume < 0.005f))
{
StopCompletely();
}
}
public void FadeStop()
{
if (!isStopping)
{
isStopping = true;
FadeSpeed = volumeGroup.stoppingVolumeLerpSpeed;
}
}
public void StopCompletely()
{
audioSource.Stop();
audioSourcePool.Push(audioSource);
musicInstances.Remove(this);
if (musicEvent.tag != null && musicInstancesByTag.TryGetValue(musicEvent.tag, out List<MusicInstance> value))
{
value.Remove(this);
}
}
}
private ManualLogSource logger;
private static readonly List<MusicInstance> musicInstances = new List<MusicInstance>();
private static readonly Dictionary<string, List<MusicInstance>> musicInstancesByTag = new Dictionary<string, List<MusicInstance>>();
private static readonly Stack<AudioSource> audioSourcePool = new Stack<AudioSource>();
private readonly Dictionary<string, AudioClip> loadedMusic = new Dictionary<string, AudioClip>();
private void Awake()
{
logger = Logger.CreateLogSource("PizzaTowerEscapeMusic MusicManager");
}
private void Update()
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
return;
}
for (int num = musicInstances.Count - 1; num >= 0; num--)
{
musicInstances[num].Update(Time.deltaTime);
}
bool flag = false;
foreach (MusicInstance musicInstance in musicInstances)
{
if (musicInstance.musicEvent.silenceGameMusic)
{
flag = true;
break;
}
}
if (flag)
{
if (SoundManager.Instance.playingOutsideMusic && GetIsMusicPlaying())
{
SoundManager.Instance.playingOutsideMusic = false;
logger.LogInfo((object)"Silenced the outside music because alternate music is playing");
}
if (TimeOfDay.Instance.TimeOfDayMusic.isPlaying && GetIsMusicPlaying())
{
TimeOfDay.Instance.TimeOfDayMusic.Stop();
logger.LogInfo((object)"Silenced the time of day music because alternate music is playing");
}
}
}
public bool GetIsMusicPlaying(string? tag = null)
{
if (tag == null)
{
return musicInstances.Count > 0;
}
if (musicInstancesByTag.TryGetValue(tag, out List<MusicInstance> value))
{
logger.LogDebug((object)$"GetIsMusicPlaying says there's {value.Count} music instance(s) with the tag \"{tag}\"");
return value.Count > 0;
}
logger.LogDebug((object)("GetIsMusicPlaying says there was no music instance list for tag \"" + tag + "\""));
return false;
}
public void PlayMusic(ScriptEvent_PlayMusic musicEvent)
{
logger.LogDebug((object)("PlayMusic called\nTag: " + musicEvent.tag + $"\nOverlap handling: {musicEvent.overlapHandling}" + $"\nAny music playing?: {GetIsMusicPlaying()}" + $"\nAny music playing with tag?: {GetIsMusicPlaying(musicEvent.tag)}"));
if (musicEvent.overlapHandling == ScriptEvent_PlayMusic.OverlapHandling.IgnoreAll && GetIsMusicPlaying())
{
logger.LogDebug((object)"PlayMusic canceled because other music was playing");
return;
}
if (musicEvent.overlapHandling == ScriptEvent_PlayMusic.OverlapHandling.IgnoreTag && GetIsMusicPlaying(musicEvent.tag))
{
logger.LogDebug((object)("PlayMusic canceled because other music with the tag \"" + musicEvent.tag + "\" was playing"));
return;
}
switch (musicEvent.overlapHandling)
{
case ScriptEvent_PlayMusic.OverlapHandling.OverrideAll:
StopMusic();
break;
case ScriptEvent_PlayMusic.OverlapHandling.OverrideTag:
StopMusic(musicEvent.tag);
break;
case ScriptEvent_PlayMusic.OverlapHandling.OverrideFadeAll:
FadeStopMusic();
break;
case ScriptEvent_PlayMusic.OverlapHandling.OverrideFadeTag:
FadeStopMusic(musicEvent.tag);
break;
}
string text = musicEvent.musicNames[Random.Range(0, musicEvent.musicNames.Length)];
loadedMusic.TryGetValue(text, out AudioClip value);
if ((Object)(object)value != (Object)null)
{
new MusicInstance(musicEvent, GetAudioSource(), value);
logger.LogInfo((object)("Playing music (" + text + ")"));
}
else
{
logger.LogWarning((object)("Music (" + text + ") is null, cannot play. Maybe it wasn't loaded correctly?"));
}
}
public void StopMusic(string? targetTag = null)
{
foreach (MusicInstance item in new List<MusicInstance>(musicInstances))
{
if (targetTag == null || !(item.musicEvent.tag != targetTag))
{
item.StopCompletely();
}
}
}
public void FadeStopMusic(string? targetTag = null)
{
foreach (MusicInstance item in new List<MusicInstance>(musicInstances))
{
if (targetTag == null || !(item.musicEvent.tag != targetTag))
{
item.FadeStop();
}
}
}
private AudioSource GetAudioSource()
{
if (!audioSourcePool.TryPop(out AudioSource result))
{
return ((Component)this).gameObject.AddComponent<AudioSource>();
}
return result;
}
public async void LoadNecessaryMusicClips()
{
if (Plugin.ScriptManager.loadedScript == null)
{
logger.LogError((object)"Script has not loaded, cannot load its music!");
return;
}
UnloadMusicClips();
ScriptEvent[] scriptEvents = Plugin.ScriptManager.loadedScript.scriptEvents;
for (int i = 0; i < scriptEvents.Length; i++)
{
if (!(scriptEvents[i] is ScriptEvent_PlayMusic scriptEvent_PlayMusic))
{
continue;
}
string[] musicNames = scriptEvent_PlayMusic.musicNames;
foreach (string musicName in musicNames)
{
if (!loadedMusic.ContainsKey(musicName))
{
AudioClip val = await LoadMusicClip(musicName);
if (!((Object)(object)val == (Object)null))
{
loadedMusic.Add(musicName, val);
}
}
}
}
logger.LogInfo((object)"Music clips done loading");
}
public void UnloadMusicClips()
{
foreach (AudioClip value in loadedMusic.Values)
{
value.UnloadAudioData();
}
loadedMusic.Clear();
logger.LogInfo((object)"All music clips unloaded");
}
private async Task<AudioClip?> LoadMusicClip(string musicFileName)
{
string path = "file:///" + GetMusicPath(musicFileName);
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)20);
try
{
request.SendWebRequest();
while (!request.isDone)
{
await Task.Delay(50);
}
if ((int)request.result == 1)
{
logger.LogInfo((object)("Loaded music (" + musicFileName + ") from file"));
AudioClip content = DownloadHandlerAudioClip.GetContent(request);
((Object)content).name = musicFileName;
return content;
}
logger.LogError((object)("Failed to load music (" + musicFileName + ") from file:\n- Path: " + path + "\n- Error: " + request.error));
return null;
}
finally
{
((IDisposable)request)?.Dispose();
}
}
private string GetMusicPath(string musicFileName)
{
string text = Paths.PluginPath + "/BGN-PizzaTowerEscapeMusic_Custom/Music/" + musicFileName + ".wav";
if (File.Exists(text))
{
return text;
}
return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/DefaultMusic/" + musicFileName + ".wav";
}
}
[BepInPlugin("bgn.pizzatowerescapemusic", "PizzaTowerEscapeMusic", "2.0.2")]
[BepInProcess("Lethal Company.exe")]
public class Plugin : BaseUnityPlugin
{
private const string GUID = "bgn.pizzatowerescapemusic";
private GameEventListener gameEventListener;
public static Configuration Configuration { get; private set; }
public static ScriptManager ScriptManager { get; private set; }
public static MusicManager MusicManager { get; private set; }
private void Awake()
{
Configuration = new Configuration(((BaseUnityPlugin)this).Config);
MusicManager = ((Component)this).gameObject.AddComponent<MusicManager>();
gameEventListener = ((Component)this).gameObject.AddComponent<GameEventListener>();
GameEventListener obj = gameEventListener;
obj.OnSoundManagerCreated = (Action)Delegate.Combine(obj.OnSoundManagerCreated, new Action(MusicManager.LoadNecessaryMusicClips));
GameEventListener obj2 = gameEventListener;
obj2.OnSoundManagerDestroyed = (Action)Delegate.Combine(obj2.OnSoundManagerDestroyed, (Action)delegate
{
MusicManager.StopMusic();
});
GameEventListener obj3 = gameEventListener;
obj3.OnSoundManagerDestroyed = (Action)Delegate.Combine(obj3.OnSoundManagerDestroyed, new Action(MusicManager.UnloadMusicClips));
ScriptManager = new ScriptManager(Configuration.scriptingScript.Value, gameEventListener);
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin bgn.pizzatowerescapemusic is loaded!");
}
private void Update()
{
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "PizzaTowerEscapeMusic";
public const string PLUGIN_NAME = "PizzaTowerEscapeMusic";
public const string PLUGIN_VERSION = "2.0.2";
}
}
namespace PizzaTowerEscapeMusic.Scripting
{
public class Script
{
public class VolumeRule
{
public string comment = string.Empty;
[JsonRequired]
public float volume;
public Condition? condition;
}
public class VolumeModifier
{
public string comment = string.Empty;
[JsonRequired]
public float volumeScale;
public Condition? condition;
}
public class VolumeGroup
{
public string comment = string.Empty;
public string tag = string.Empty;
public float volumeLerpSpeed = 1f;
public float stoppingVolumeLerpSpeed = 1f;
[JsonRequired]
public VolumeRule[] volumeRules = Array.Empty<VolumeRule>();
public VolumeModifier[] volumeModifiers = Array.Empty<VolumeModifier>();
public float GetVolume()
{
float num = 1f;
VolumeRule[] array = volumeRules;
foreach (VolumeRule volumeRule in array)
{
if (volumeRule.condition == null || volumeRule.condition.Check())
{
num = volumeRule.volume;
break;
}
}
VolumeModifier[] array2 = volumeModifiers;
foreach (VolumeModifier volumeModifier in array2)
{
if (volumeModifier.condition == null || volumeModifier.condition.Check())
{
num *= volumeModifier.volumeScale;
}
}
return num;
}
}
public string comment = string.Empty;
public VolumeGroup[] volumeGroups = Array.Empty<VolumeGroup>();
[JsonRequired]
public ScriptEvent[] scriptEvents = Array.Empty<ScriptEvent>();
}
public class ScriptManager
{
private readonly ManualLogSource logger;
public readonly Script? loadedScript;
private readonly Dictionary<ScriptEvent.GameEventType, List<ScriptEvent>> loadedScriptEvents = new Dictionary<ScriptEvent.GameEventType, List<ScriptEvent>>();
private readonly Dictionary<string, Script.VolumeGroup> loadedScriptVolumeGroups = new Dictionary<string, Script.VolumeGroup>();
private static readonly Script.VolumeGroup defaultVolumeGroup = new Script.VolumeGroup();
public ScriptManager(string scriptName, GameEventListener gameEventListener)
{
logger = Logger.CreateLogSource("PizzaTowerEscapeMusic ScriptManager");
loadedScript = DeserializeScript(scriptName);
if (loadedScript == null)
{
return;
}
ScriptEvent[] scriptEvents = loadedScript.scriptEvents;
foreach (ScriptEvent scriptEvent in scriptEvents)
{
if (!loadedScriptEvents.TryGetValue(scriptEvent.gameEventType, out List<ScriptEvent> value))
{
value = new List<ScriptEvent>(1);
loadedScriptEvents.Add(scriptEvent.gameEventType, value);
}
value.Add(scriptEvent);
}
Script.VolumeGroup[] volumeGroups = loadedScript.volumeGroups;
foreach (Script.VolumeGroup volumeGroup in volumeGroups)
{
if (!loadedScriptVolumeGroups.TryAdd(volumeGroup.tag, volumeGroup))
{
logger.LogError((object)("Volume group tag " + volumeGroup.tag + " was already declaired, you cannot have two volume groups with the same tag"));
}
}
gameEventListener.OnShipLanded = (Action)Delegate.Combine(gameEventListener.OnShipLanded, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.ShipLanded);
});
gameEventListener.OnShipTakeOff = (Action)Delegate.Combine(gameEventListener.OnShipTakeOff, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.ShipTakeOff);
});
gameEventListener.OnShipLeavingAlertCalled = (Action)Delegate.Combine(gameEventListener.OnShipLeavingAlertCalled, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.ShipLeavingAlertCalled);
});
gameEventListener.OnPlayerDamaged = (Action)Delegate.Combine(gameEventListener.OnPlayerDamaged, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.PlayerDamaged);
});
gameEventListener.OnPlayerDeath = (Action)Delegate.Combine(gameEventListener.OnPlayerDeath, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.PlayerDied);
});
gameEventListener.OnPlayerEnteredFacility = (Action)Delegate.Combine(gameEventListener.OnPlayerEnteredFacility, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.PlayerEnteredFacility);
});
gameEventListener.OnPlayerExitedFacility = (Action)Delegate.Combine(gameEventListener.OnPlayerExitedFacility, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.PlayerExitedFacility);
});
gameEventListener.OnPlayerEnteredShip = (Action)Delegate.Combine(gameEventListener.OnPlayerEnteredShip, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.PlayerEnteredShip);
});
gameEventListener.OnPlayerExitedShip = (Action)Delegate.Combine(gameEventListener.OnPlayerExitedShip, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.PlayerExitedShip);
});
gameEventListener.OnApparatusTaken = (Action)Delegate.Combine(gameEventListener.OnApparatusTaken, (Action)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.ApparatusTaken);
});
gameEventListener.OnCurrentMoonChanged = (Action<SelectableLevel>)Delegate.Combine(gameEventListener.OnCurrentMoonChanged, (Action<SelectableLevel>)delegate
{
CheckScriptEvents(ScriptEvent.GameEventType.CurrentMoonChanged);
});
logger.LogInfo((object)("Script (" + scriptName + ") loaded"));
}
public Script.VolumeGroup TryGetVolumeGroup(string? tag)
{
if (tag == null || !loadedScriptVolumeGroups.ContainsKey(tag))
{
return defaultVolumeGroup;
}
return loadedScriptVolumeGroups[tag];
}
private void CheckScriptEvents(ScriptEvent.GameEventType eventType)
{
if (!loadedScriptEvents.TryGetValue(eventType, out List<ScriptEvent> value))
{
return;
}
foreach (ScriptEvent item in value)
{
if (item.CheckConditions())
{
logger.LogDebug((object)("Conditions for a script event have been met!\n Script Event Type: " + item.scriptEventType + $"\n Game Event Type: {item.gameEventType}" + "\n Comment: " + item.comment));
item.Run();
}
}
}
private Script? DeserializeScript(string name)
{
string scriptPath = GetScriptPath(name);
if (!File.Exists(scriptPath))
{
logger.LogError((object)("Script \"" + name + "\" does not exist! Make sure you spelt it right the config, and make sure its file extention is \".json\""));
return null;
}
string text = File.ReadAllText(scriptPath);
try
{
return JsonConvert.DeserializeObject<Script>(text);
}
catch (Exception ex)
{
logger.LogError((object)("Failed to deserialize script \"" + name + "\":\n" + ex.Message));
return null;
}
}
private string GetScriptPath(string fileName)
{
string text = Paths.PluginPath + "/BGN-PizzaTowerEscapeMusic_Custom/Scripts/" + fileName + ".json";
if (File.Exists(text))
{
return text;
}
return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/DefaultScripts/" + fileName + ".json";
}
}
}
namespace PizzaTowerEscapeMusic.Scripting.ScriptEvents
{
public class ScriptEventConverter : JsonConverter<ScriptEvent>
{
public override bool CanWrite => false;
public override ScriptEvent ReadJson(JsonReader reader, Type objectType, ScriptEvent? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JObject val = JObject.Load(reader);
JToken val2 = default(JToken);
if (!val.TryGetValue("scriptEventType", ref val2))
{
throw new Exception("scriptEventType type is null!");
}
string text = Extensions.Value<string>((IEnumerable<JToken>)val2);
ScriptEvent scriptEvent;
if (!(text == "PlayMusic"))
{
if (!(text == "StopMusic"))
{
throw new Exception($"Condition type \"{val2}\" does not exist");
}
scriptEvent = new ScriptEvent_StopMusic();
}
else
{
scriptEvent = new ScriptEvent_PlayMusic();
}
ScriptEvent scriptEvent2 = scriptEvent;
serializer.Populate(((JToken)val).CreateReader(), (object)scriptEvent2);
return scriptEvent2;
}
public override void WriteJson(JsonWriter writer, ScriptEvent? value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
[JsonConverter(typeof(ScriptEventConverter))]
public abstract class ScriptEvent
{
public enum GameEventType
{
ShipLanded,
ShipTakeOff,
ShipLeavingAlertCalled,
PlayerDamaged,
PlayerDied,
PlayerEnteredFacility,
PlayerExitedFacility,
PlayerEnteredShip,
PlayerExitedShip,
ApparatusTaken,
CurrentMoonChanged
}
public string comment = string.Empty;
[JsonRequired]
public string scriptEventType = string.Empty;
[JsonRequired]
public GameEventType gameEventType;
public Condition[] conditions = Array.Empty<Condition>();
public bool CheckConditions()
{
return !conditions.Any((Condition c) => !c.Check());
}
public abstract void Run();
}
public class ScriptEvent_PlayMusic : ScriptEvent
{
public enum OverlapHandling
{
IgnoreAll,
IgnoreTag,
OverrideAll,
OverrideTag,
OverrideFadeAll,
OverrideFadeTag,
Overlap
}
public bool loop;
public bool silenceGameMusic = true;
[JsonRequired]
public OverlapHandling overlapHandling;
public string? tag;
[JsonRequired]
public string[] musicNames = Array.Empty<string>();
public override void Run()
{
if (musicNames.Length != 0)
{
Plugin.MusicManager.PlayMusic(this);
}
}
}
public class ScriptEvent_StopMusic : ScriptEvent
{
public string[]? targetTags;
public bool instant;
public override void Run()
{
if (targetTags != null)
{
string[] array = targetTags;
foreach (string targetTag in array)
{
if (instant)
{
Plugin.MusicManager.StopMusic(targetTag);
}
else
{
Plugin.MusicManager.FadeStopMusic(targetTag);
}
}
}
else if (instant)
{
Plugin.MusicManager.StopMusic();
}
else
{
Plugin.MusicManager.FadeStopMusic();
}
}
}
}
namespace PizzaTowerEscapeMusic.Scripting.Conditions
{
public class ConditionConverter : JsonConverter<Condition>
{
public override bool CanWrite => false;
public override Condition ReadJson(JsonReader reader, Type objectType, Condition? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JObject val = JObject.Load(reader);
JToken val2 = default(JToken);
if (!val.TryGetValue("conditionType", ref val2))
{
throw new Exception("Condition type is null!");
}
Condition condition = Extensions.Value<string>((IEnumerable<JToken>)val2) switch
{
"And" => new Condition_And(),
"Or" => new Condition_Or(),
"Not" => new Condition_Not(),
"Weather" => new Condition_Weather(),
"PlayerLocation" => new Condition_PlayerLocation(),
"PlayerAlive" => new Condition_PlayerAlive(),
"PlayerHealth" => new Condition_PlayerHealth(),
"PlayerCrouching" => new Condition_PlayerCrouching(),
"ShipLanded" => new Condition_ShipLanded(),
"ShipLeavingAlertCalled" => new Condition_ShipLeavingAlertCalled(),
"MusicWithTagPlaying" => new Condition_MusicWithTagPlaying(),
"CurrentMoon" => new Condition_CurrentMoon(),
_ => throw new Exception($"Condition type \"{val2}\" does not exist"),
};
serializer.Populate(((JToken)val).CreateReader(), (object)condition);
return condition;
}
public override void WriteJson(JsonWriter writer, Condition? value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
[JsonConverter(typeof(ConditionConverter))]
public abstract class Condition
{
[JsonRequired]
public string conditionType = string.Empty;
public abstract bool Check();
}
public class Condition_And : Condition
{
[JsonRequired]
public Condition[] conditions = Array.Empty<Condition>();
public override bool Check()
{
return !conditions.Any((Condition c) => !c.Check());
}
}
public class Condition_Or : Condition
{
[JsonRequired]
public Condition[] conditions = Array.Empty<Condition>();
public override bool Check()
{
return conditions.Any((Condition c) => c.Check());
}
}
public class Condition_Not : Condition
{
[JsonRequired]
public Condition? condition;
public override bool Check()
{
if (condition == null)
{
return true;
}
return !condition.Check();
}
}
public class Condition_Weather : Condition
{
[JsonRequired]
public LevelWeatherType weather;
public override bool Check()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)TimeOfDay.Instance == (Object)null)
{
return false;
}
return TimeOfDay.Instance.currentLevelWeather == weather;
}
}
public class Condition_PlayerLocation : Condition
{
public enum Location
{
Ship,
Facility
}
[JsonRequired]
public Location location;
public override bool Check()
{
if ((Object)(object)GameNetworkManager.Instance == (Object)null)
{
return false;
}
if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
{
return false;
}
return location switch
{
Location.Ship => GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom,
Location.Facility => GameNetworkManager.Instance.localPlayerController.isInsideFactory,
_ => false,
};
}
}
public class Condition_PlayerAlive : Condition
{
public override bool Check()
{
if ((Object)(object)GameNetworkManager.Instance == (Object)null)
{
return false;
}
if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
{
return false;
}
return !GameNetworkManager.Instance.localPlayerController.isPlayerDead;
}
}
public class Condition_PlayerHealth : Condition
{
public enum ComparisonType
{
Equals,
NotEquals,
GreaterThan,
LessThan,
GreaterThanOrEquals,
LessThanOrEquals
}
[JsonRequired]
public ComparisonType comparisonType;
[JsonRequired]
public int value;
public override bool Check()
{
if ((Object)(object)GameNetworkManager.Instance == (Object)null)
{
return false;
}
if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
{
return false;
}
int health = GameNetworkManager.Instance.localPlayerController.health;
return comparisonType switch
{
ComparisonType.Equals => health == value,
ComparisonType.NotEquals => health != value,
ComparisonType.GreaterThan => health > value,
ComparisonType.LessThan => health < value,
ComparisonType.GreaterThanOrEquals => health >= value,
ComparisonType.LessThanOrEquals => health <= value,
_ => false,
};
}
}
public class Condition_PlayerCrouching : Condition
{
public override bool Check()
{
if ((Object)(object)GameNetworkManager.Instance == (Object)null)
{
return false;
}
if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
{
return false;
}
return GameNetworkManager.Instance.localPlayerController.isCrouching;
}
}
public class Condition_ShipLanded : Condition
{
public override bool Check()
{
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
return false;
}
return StartOfRound.Instance.shipHasLanded;
}
}
public class Condition_ShipLeavingAlertCalled : Condition
{
public override bool Check()
{
if ((Object)(object)TimeOfDay.Instance == (Object)null)
{
return false;
}
return TimeOfDay.Instance.shipLeavingAlertCalled;
}
}
public class Condition_MusicWithTagPlaying : Condition
{
[JsonRequired]
public string tag = string.Empty;
public override bool Check()
{
return Plugin.MusicManager.GetIsMusicPlaying(tag);
}
}
public class Condition_CurrentMoon : Condition
{
public enum Moons
{
Gordion = 3,
Experimentation = 0,
Assurance = 1,
Vow = 2,
Offense = 7,
March = 4,
Rend = 5,
Dine = 6,
Titan = 8
}
[JsonRequired]
public Moons moon;
public override bool Check()
{
if ((Object)(object)TimeOfDay.Instance == (Object)null)
{
return false;
}
return TimeOfDay.Instance.currentLevel.levelID == (int)moon;
}
}
}