using 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.Versioning;
using System.Security;
using System.Security.Permissions;
using BaboonAPI.Hooks.Initializer;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using TootTallyCore;
using TootTallyCore.Utils.Helpers;
using TootTallyCore.Utils.TootTallyGlobals;
using TootTallyCore.Utils.TootTallyModules;
using TootTallySettings;
using TootTallySettings.TootTallySettingsObjects;
using UnityEngine;
using UnityEngine.Events;
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("TootTallyHitSounds")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Hitsounds module for TootTallyCore")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4")]
[assembly: AssemblyProduct("TootTallyHitSounds")]
[assembly: AssemblyTitle("TootTallyHitSounds")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace TootTallyHitSounds
{
internal class CustomHitSoundSettingPage : TootTallySettingPage
{
private static ColorBlock _pageBtnColors;
private TootTallySettingSlider _hitVolumeSlider;
private TootTallySettingSlider _missVolumeSlider;
private TootTallySettingDropdown _hitSoundsDropdown;
private TootTallySettingDropdown _missSoundsDropdown;
private TootTallySettingToggle _toggleSyncWithNotes;
private TootTallySettingToggle _toggleSyncWithSong;
public CustomHitSoundSettingPage()
: base("HitSounds", "HitSounds", 40f, new Color(0f, 0f, 0f, 0f), _pageBtnColors)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
_hitVolumeSlider = ((TootTallySettingPage)this).AddSlider("HitSound Volume", 0f, 1f, Plugin.Instance.HitSoundVolume, false);
_hitSoundsDropdown = CreateDropdownFromFolder("HitSounds", Plugin.Instance.HitSoundName, "None");
_missVolumeSlider = ((TootTallySettingPage)this).AddSlider("MissSound Volume", 0f, 1f, Plugin.Instance.MissSoundVolume, false);
_missSoundsDropdown = CreateDropdownFromFolder("MissSounds", Plugin.Instance.MissSoundName, "None");
_toggleSyncWithNotes = ((TootTallySettingPage)this).AddToggle("Sync With Notes", Plugin.Instance.SyncWithNotes, (UnityAction<bool>)delegate(bool v)
{
Plugin.Instance.SyncWithSong.Value = !v;
_toggleSyncWithSong.toggle.SetIsOnWithoutNotify(!v);
});
_toggleSyncWithSong = ((TootTallySettingPage)this).AddToggle("Sync With Song", Plugin.Instance.SyncWithSong, (UnityAction<bool>)delegate(bool v)
{
Plugin.Instance.SyncWithNotes.Value = !v;
_toggleSyncWithNotes.toggle.SetIsOnWithoutNotify(!v);
});
((TootTallySettingPage)this).AddToggle("Add Audio Latency To Sync", Plugin.Instance.AddAudioLatencyToSync, (UnityAction<bool>)null);
((TootTallySettingPage)this).AddButton("Test HitSound", (Action)TestHitSound);
((TootTallySettingPage)this).AddButton("Test MissSound", (Action)TestMissSound);
}
public override void Initialize()
{
((TootTallySettingPage)this).Initialize();
((UnityEvent<float>)(object)_hitVolumeSlider.slider.onValueChanged).AddListener((UnityAction<float>)OnHitVolumeChange);
((UnityEvent<float>)(object)_missVolumeSlider.slider.onValueChanged).AddListener((UnityAction<float>)OnMissVolumeChange);
((UnityEvent<int>)(object)_hitSoundsDropdown.dropdown.onValueChanged).AddListener((UnityAction<int>)OnHitSoundChange);
((UnityEvent<int>)(object)_missSoundsDropdown.dropdown.onValueChanged).AddListener((UnityAction<int>)OnMissSoundChange);
}
private void TestHitSound()
{
if (Plugin.HitSoundPatches.isHitClipLoaded)
{
Plugin.HitSoundPatches.testHitSound.Play();
}
}
private void TestMissSound()
{
if (Plugin.HitSoundPatches.isMissClipLoaded)
{
Plugin.HitSoundPatches.testMissSound.Play();
}
}
private void OnHitSoundChange(int _)
{
Plugin.HitSoundPatches.isHitClipLoaded = false;
if (Plugin.Instance.HitSoundName.Value != "None")
{
((MonoBehaviour)Plugin.Instance).StartCoroutine((IEnumerator)Plugin.HitSoundPatches.TryLoadingAudioClipLocal("HitSounds", Plugin.Instance.HitSoundName.Value + ".wav", delegate(AudioClip clip)
{
Plugin.HitSoundPatches.testHitSound.clip = clip;
Plugin.HitSoundPatches.isHitClipLoaded = true;
}));
}
}
private void OnMissSoundChange(int _)
{
Plugin.HitSoundPatches.isMissClipLoaded = false;
if (Plugin.Instance.MissSoundName.Value != "None")
{
((MonoBehaviour)Plugin.Instance).StartCoroutine((IEnumerator)Plugin.HitSoundPatches.TryLoadingAudioClipLocal("MissSounds", Plugin.Instance.MissSoundName.Value + ".wav", delegate(AudioClip clip)
{
Plugin.HitSoundPatches.testMissSound.clip = clip;
Plugin.HitSoundPatches.isMissClipLoaded = true;
}));
}
}
private void OnHitVolumeChange(float value)
{
Plugin.HitSoundPatches.testHitSound.volume = value;
}
private void OnMissVolumeChange(float value)
{
Plugin.HitSoundPatches.testMissSound.volume = value;
}
private TootTallySettingDropdown CreateDropdownFromFolder(string folderName, ConfigEntry<string> config, string defaultValue)
{
List<string> folderNames = new List<string> { defaultValue };
string path = Path.Combine(Paths.BepInExRootPath, folderName);
if (Directory.Exists(path))
{
List<string> list = Directory.GetFiles(path).ToList();
list.ForEach(delegate(string d)
{
if (Path.GetExtension(d).ToLower().Contains("wav"))
{
folderNames.Add(Path.GetFileNameWithoutExtension(d));
}
});
}
((TootTallySettingPage)this).AddLabel(folderName, folderName, 24f, (FontStyles)0, (TextAlignmentOptions)1025);
return ((TootTallySettingPage)this).AddDropdown(folderName + "Dropdown", config, folderNames.ToArray());
}
static CustomHitSoundSettingPage()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
ColorBlock pageBtnColors = default(ColorBlock);
((ColorBlock)(ref pageBtnColors)).colorMultiplier = 1f;
((ColorBlock)(ref pageBtnColors)).fadeDuration = 0.2f;
((ColorBlock)(ref pageBtnColors)).disabledColor = Color.gray;
((ColorBlock)(ref pageBtnColors)).normalColor = new Color(0.6f, 0.6f, 0.6f);
((ColorBlock)(ref pageBtnColors)).pressedColor = new Color(0.2f, 0.2f, 0.2f);
((ColorBlock)(ref pageBtnColors)).highlightedColor = new Color(0.8f, 0.8f, 0.8f);
((ColorBlock)(ref pageBtnColors)).selectedColor = new Color(0.6f, 0.6f, 0.6f);
_pageBtnColors = pageBtnColors;
}
}
[BepInPlugin("TootTallyHitSounds", "TootTallyHitSounds", "1.0.4")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin, ITootTallyModule
{
public static class HitSoundPatches
{
private static bool _lastIsActive;
private static AudioSource _hitSound;
private static AudioSource _missSound;
private static float _hitVolume;
private static float _missVolume;
public static bool isHitClipLoaded;
public static bool isMissClipLoaded;
public static AudioSource testHitSound;
public static AudioSource testMissSound;
private static bool _isSlider;
private static int _lastIndex;
private static double _trackTime;
private static int _lastSample;
private static float _nextTiming;
private static bool _isStarted;
private static int _lastMult;
private static bool _lastChamp;
[HarmonyPatch(typeof(HomeController), "Start")]
[HarmonyPostfix]
public static void LoadTestSounds(HomeController __instance)
{
testHitSound = ((Component)__instance).gameObject.AddComponent<AudioSource>();
testHitSound.volume = Instance.HitSoundVolume.Value;
isHitClipLoaded = false;
if (Instance.HitSoundName.Value != "None")
{
((MonoBehaviour)Instance).StartCoroutine((IEnumerator)TryLoadingAudioClipLocal("HitSounds", Instance.HitSoundName.Value + ".wav", delegate(AudioClip clip)
{
testHitSound.clip = clip;
isHitClipLoaded = true;
}));
}
testMissSound = ((Component)__instance).gameObject.AddComponent<AudioSource>();
testMissSound.volume = Instance.HitSoundVolume.Value;
isMissClipLoaded = false;
if (Instance.MissSoundName.Value != "None")
{
((MonoBehaviour)Instance).StartCoroutine((IEnumerator)TryLoadingAudioClipLocal("MissSounds", Instance.MissSoundName.Value + ".wav", delegate(AudioClip clip)
{
testMissSound.clip = clip;
isMissClipLoaded = true;
}));
}
}
[HarmonyPatch(typeof(GameController), "Start")]
[HarmonyPostfix]
public static void LoadHitSound(GameController __instance)
{
isHitClipLoaded = false;
if (!(Instance.HitSoundName.Value == "None"))
{
_isStarted = false;
_lastChamp = false;
_lastMult = 0;
_lastIsActive = false;
_isSlider = false;
_lastIndex = -1;
_trackTime = 0.0;
_nextTiming = ((__instance.leveldata.Count > 0) ? B2s(__instance.leveldata[0][0], __instance.tempo) : 0f);
_hitSound = ((Component)__instance).gameObject.AddComponent<AudioSource>();
_hitSound.volume = (_hitVolume = Instance.HitSoundVolume.Value * GlobalVariables.localsettings.maxvolume);
((MonoBehaviour)Instance).StartCoroutine((IEnumerator)TryLoadingAudioClipLocal("HitSounds", Instance.HitSoundName.Value + ".wav", delegate(AudioClip clip)
{
LogInfo("Hit Sounds " + Instance.HitSoundName.Value + " Loaded.");
_hitSound.clip = clip;
isHitClipLoaded = true;
}));
}
}
[HarmonyPatch(typeof(GameController), "Start")]
[HarmonyPostfix]
public static void LoadMissSound(GameController __instance)
{
isMissClipLoaded = false;
if (!(Instance.MissSoundName.Value == "None"))
{
_missSound = ((Component)__instance).gameObject.AddComponent<AudioSource>();
_missSound.volume = (_hitVolume = Instance.MissSoundVolume.Value * GlobalVariables.localsettings.maxvolume);
((MonoBehaviour)Instance).StartCoroutine((IEnumerator)TryLoadingAudioClipLocal("MissSounds", Instance.MissSoundName.Value + ".wav", delegate(AudioClip clip)
{
LogInfo("Miss Sounds " + Instance.MissSoundName.Value + " Loaded.");
_missSound.clip = clip;
isMissClipLoaded = true;
}));
}
}
[HarmonyPatch(typeof(GameController), "playsong")]
[HarmonyPostfix]
public static void OnPlaySong()
{
_isStarted = true;
}
[HarmonyPatch(typeof(GameController), "grabNoteRefs")]
[HarmonyPrefix]
public static void GetIsSlider(GameController __instance)
{
if (__instance.currentnoteindex + 1 < __instance.leveldata.Count)
{
_isSlider = Mathf.Abs(__instance.leveldata[__instance.currentnoteindex + 1][0] - (__instance.leveldata[__instance.currentnoteindex][0] + __instance.leveldata[__instance.currentnoteindex][1])) < 0.05f;
_nextTiming = B2s(__instance.leveldata[__instance.currentnoteindex + 1][0], __instance.tempo);
}
}
[HarmonyPatch(typeof(GameController), "Update")]
[HarmonyPostfix]
public static void PlaySoundOnNewNoteActive(GameController __instance)
{
if (!((Object)(object)_hitSound == (Object)null) && isHitClipLoaded && _isStarted && _isStarted && !__instance.paused && !__instance.quitting && !__instance.retrying)
{
_trackTime += Time.deltaTime * TootTallyGlobalVariables.gameSpeedMultiplier;
if (_lastSample != __instance.musictrack.timeSamples)
{
_trackTime = __instance.musictrack.time - (Instance.AddAudioLatencyToSync.Value ? __instance.latency_offset : 0f);
_lastSample = __instance.musictrack.timeSamples;
}
if (ShouldPlayHitSound(__instance))
{
_lastIndex = __instance.currentnoteindex;
PlaySound(ref _hitVolume, ref _hitSound, Instance.HitSoundVolume.Value);
}
FadeOutVolume(ref _hitVolume, ref _hitSound, Instance.HitSoundVolume.Value);
FadeOutVolume(ref _missVolume, ref _missSound, Instance.MissSoundVolume.Value);
_lastIsActive = __instance.noteactive;
}
}
[HarmonyPatch(typeof(GameController), "getScoreAverage")]
[HarmonyPostfix]
public static void OnNoteScoringPostfix(GameController __instance)
{
if (!((Object)(object)_missSound == (Object)null) && isMissClipLoaded && _isStarted)
{
if (ShouldPlayMissSount(__instance.multiplier, __instance.rainbowcontroller.champmode))
{
PlaySound(ref _missVolume, ref _missSound, Instance.MissSoundVolume.Value);
}
_lastMult = __instance.multiplier;
_lastChamp = __instance.rainbowcontroller.champmode;
}
}
public static float B2s(float time, float bpm)
{
return time / bpm * 60f;
}
public static bool ShouldPlayHitSound(GameController __instance)
{
if (Instance.SyncWithNotes.Value)
{
return __instance.noteactive && !_lastIsActive && !_isSlider;
}
return _trackTime > (double)_nextTiming && _lastIndex != __instance.currentnoteindex && !_isSlider;
}
public static bool ShouldPlayMissSount(int multiplier, bool champ)
{
return (_lastMult >= 10 && multiplier == 0) || (_lastChamp && !champ);
}
public static void PlaySound(ref float volume, ref AudioSource audioSource, float maxVolume)
{
volume = maxVolume * GlobalVariables.localsettings.maxvolume;
audioSource.time = 0f;
audioSource.Play();
}
public static void FadeOutVolume(ref float volume, ref AudioSource audioSource, float maxVolume)
{
if (volume < 0f)
{
volume = 0f;
audioSource.Stop();
}
else if (volume > 0f)
{
volume -= Time.unscaledDeltaTime / 2f * maxVolume * GlobalVariables.localsettings.maxvolume;
audioSource.volume = Mathf.Clamp(volume, 0f, 1f);
}
}
public static IEnumerator<UnityWebRequestAsyncOperation> TryLoadingAudioClipLocal(string folderName, string fileName, Action<AudioClip> callback)
{
string assetDir = Path.Combine(Paths.BepInExRootPath, folderName, fileName);
UnityWebRequest webRequest = UnityWebRequestMultimedia.GetAudioClip("file://" + assetDir, (AudioType)20);
yield return webRequest.SendWebRequest();
if (!webRequest.isHttpError && !webRequest.isNetworkError)
{
callback(DownloadHandlerAudioClip.GetContent(webRequest));
}
}
}
public static Plugin Instance;
private const string CONFIG_NAME = "TootTallyHitSounds.cfg";
public const string DEFAULT_HITSOUND = "None";
public const string DEFAULT_MISSSOUND = "None";
private Harmony _harmony;
public static TootTallySettingPage settingPage;
public ConfigEntry<bool> ModuleConfigEnabled { get; set; }
public bool IsConfigInitialized { get; set; }
public string Name
{
get
{
return "TootTallyHitSounds";
}
set
{
Name = value;
}
}
public ConfigEntry<float> HitSoundVolume { get; set; }
public ConfigEntry<float> MissSoundVolume { get; set; }
public ConfigEntry<string> HitSoundName { get; set; }
public ConfigEntry<string> MissSoundName { get; set; }
public ConfigEntry<bool> SyncWithNotes { get; set; }
public ConfigEntry<bool> SyncWithSong { get; set; }
public ConfigEntry<bool> AddAudioLatencyToSync { get; set; }
public static void LogInfo(string msg)
{
((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg);
}
public static void LogError(string msg)
{
((BaseUnityPlugin)Instance).Logger.LogError((object)msg);
}
private void Awake()
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
if (!((Object)(object)Instance != (Object)null))
{
Instance = this;
_harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
GameInitializationEvent.Register(((BaseUnityPlugin)this).Info, (Action)TryInitialize);
}
}
private void TryInitialize()
{
ModuleConfigEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Modules", "HitSounds", true, "Add HitSounds when notes become active.");
TootTallyModuleManager.AddModule((ITootTallyModule)(object)this);
Plugin.Instance.AddModuleToSettingPage((ITootTallyModule)(object)this);
}
public void LoadModule()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
string text = Path.Combine(Paths.BepInExRootPath, "config/");
ConfigFile val = new ConfigFile(text + "TootTallyHitSounds.cfg", true)
{
SaveOnConfigSet = true
};
HitSoundVolume = val.Bind<float>("General", "HitSoundVolume", 1f, "Volume of the hitsounds.");
MissSoundVolume = val.Bind<float>("General", "MissSoundVolume", 1f, "Volume of the misssounds.");
HitSoundName = val.Bind<string>("General", "HitSoundName", "None", "Name of the hitsound wav file.");
MissSoundName = val.Bind<string>("General", "MissSoundName", "None", "Name of the misssound wav file.");
SyncWithNotes = val.Bind<bool>("General", "SyncWithNotes", false, "Useful for charters to make sure your map is on time. Use with 0ms audio latency for best results.");
SyncWithSong = val.Bind<bool>("General", "SyncWithSong", true, "Better for players since the clicking sound will (most of the time) match the music's timing.");
AddAudioLatencyToSync = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AddAudioLatencyToSync", false, "Adds the audio offset to tracktime for hitsound syncing.");
TryMigrateSoundsFolder("HitSounds");
TryMigrateSoundsFolder("MissSounds");
settingPage = TootTallySettingsManager.AddNewPage((TootTallySettingPage)(object)new CustomHitSoundSettingPage());
Plugin.TryAddThunderstoreIconToPageButton(((BaseUnityPlugin)Instance).Info.Location, Name, settingPage);
_harmony.PatchAll(typeof(HitSoundPatches));
LogInfo("Module loaded!");
}
private static void TryMigrateSoundsFolder(string folderName)
{
string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location), folderName);
string text2 = Path.Combine(Paths.BepInExRootPath, folderName);
FileHelper.TryMigrateFolder(text, text2, false);
}
public void UnloadModule()
{
_harmony.UnpatchSelf();
settingPage.Remove();
LogInfo("Module unloaded!");
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "TootTallyHitSounds";
public const string PLUGIN_NAME = "TootTallyHitSounds";
public const string PLUGIN_VERSION = "1.0.4";
}
}