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.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using PluginConfig.API;
using PluginConfig.API.Decorators;
using PluginConfig.API.Fields;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("UltrakillVoiceMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UltrakillVoiceMod")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("761705d4-f8d0-4609-9e66-ab9d62fdfdb3")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace UltrakillVoiceMod;
[BepInPlugin("com.NearRaindrop116.ultrakillvoicemod", "Ultrakill Voice Mod", "1.0.0")]
public class VoiceModPlugin : BaseUnityPlugin
{
[CompilerGenerated]
private sealed class <DelayedInitialize>d__8 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public VoiceModPlugin <>4__this;
private string <pluginFolder>5__1;
private string <soundsRoot>5__2;
private string <defaultPath>5__3;
private string <exclusiveRoot>5__4;
private float <timeout>5__5;
private float <timer>5__6;
private string[] <>s__7;
private int <>s__8;
private string <file>5__9;
private string[] <>s__10;
private int <>s__11;
private string <dir>5__12;
private string <enemyKey>5__13;
private string[] <>s__14;
private int <>s__15;
private string <file>5__16;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DelayedInitialize>d__8(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<pluginFolder>5__1 = null;
<soundsRoot>5__2 = null;
<defaultPath>5__3 = null;
<exclusiveRoot>5__4 = null;
<>s__7 = null;
<file>5__9 = null;
<>s__10 = null;
<dir>5__12 = null;
<enemyKey>5__13 = null;
<>s__14 = null;
<file>5__16 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Expected O, but got Unknown
//IL_028d: Unknown result type (might be due to invalid IL or missing references)
//IL_02a7: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<pluginFolder>5__1 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
<soundsRoot>5__2 = Path.Combine(<pluginFolder>5__1, "sounds");
<defaultPath>5__3 = Path.Combine(<soundsRoot>5__2, "default");
<exclusiveRoot>5__4 = Path.Combine(<soundsRoot>5__2, "exclusive");
<timeout>5__5 = 15f;
<timer>5__6 = 0f;
break;
case 1:
<>1__state = -1;
<timer>5__6 += Time.unscaledDeltaTime;
break;
}
if (!Directory.Exists(<defaultPath>5__3) && !Directory.Exists(<exclusiveRoot>5__4))
{
if (<timer>5__6 >= <timeout>5__5)
{
((BaseUnityPlugin)<>4__this).Logger.LogError((object)"Timed out waiting for sound folders to appear.");
return false;
}
<>2__current = null;
<>1__state = 1;
return true;
}
if (Directory.Exists(<defaultPath>5__3))
{
<>s__7 = Directory.GetFiles(<defaultPath>5__3, "*.wav");
for (<>s__8 = 0; <>s__8 < <>s__7.Length; <>s__8++)
{
<file>5__9 = <>s__7[<>s__8];
((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.LoadClip(new WWW("file://" + <file>5__9), KillSounds));
<file>5__9 = null;
}
<>s__7 = null;
}
else
{
((BaseUnityPlugin)<>4__this).Logger.LogWarning((object)"No default folder found.");
}
if (Directory.Exists(<exclusiveRoot>5__4))
{
<>s__10 = Directory.GetDirectories(<exclusiveRoot>5__4);
for (<>s__11 = 0; <>s__11 < <>s__10.Length; <>s__11++)
{
<dir>5__12 = <>s__10[<>s__11];
<enemyKey>5__13 = Path.GetFileName(<dir>5__12).ToLower();
ExclusiveKillSounds[<enemyKey>5__13] = new List<AudioClip>();
<>s__14 = Directory.GetFiles(<dir>5__12, "*.wav");
for (<>s__15 = 0; <>s__15 < <>s__14.Length; <>s__15++)
{
<file>5__16 = <>s__14[<>s__15];
((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.LoadClip(new WWW("file://" + <file>5__16), ExclusiveKillSounds[<enemyKey>5__13]));
<file>5__16 = null;
}
<>s__14 = null;
<enemyKey>5__13 = null;
<dir>5__12 = null;
}
<>s__10 = null;
}
else
{
((BaseUnityPlugin)<>4__this).Logger.LogWarning((object)"No exclusive folder found.");
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <LoadClip>d__9 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public WWW www;
public List<AudioClip> targetList;
public VoiceModPlugin <>4__this;
private AudioClip <clip>5__1;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadClip>d__9(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<clip>5__1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = www;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<clip>5__1 = www.GetAudioClip(false, false);
if ((Object)(object)<clip>5__1 != (Object)null)
{
targetList.Add(<clip>5__1);
}
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
internal static ManualLogSource ModLogger;
internal static AudioClip KillSound;
internal static Dictionary<string, List<AudioClip>> ExclusiveKillSounds = new Dictionary<string, List<AudioClip>>();
internal static List<AudioClip> KillSounds = new List<AudioClip>();
private PluginConfigurator config;
public static FloatField V1Volume;
public static IntField V1Chance;
private void Awake()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Expected O, but got Unknown
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Expected O, but got Unknown
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Expected O, but got Unknown
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Expected O, but got Unknown
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Expected O, but got Unknown
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Expected O, but got Unknown
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Expected O, but got Unknown
ModLogger = ((BaseUnityPlugin)this).Logger;
Harmony val = new Harmony("com.NearRaindrop116.ultrakillvoicemod");
val.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"VoiceModPlugin awake, patching...");
config = PluginConfigurator.Create("Ultrakill Voiceline Mod", "com.NearRaindrop116.ultrakillvoicemod");
config.SetIconWithURL("file://" + Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty, "icon.png"));
ConfigHeader val2 = new ConfigHeader(config.rootPanel, " ", 24);
val2.textSize = 12;
ConfigHeader val3 = new ConfigHeader(config.rootPanel, "--Ultrakill Voiceline Mod--", 24);
ConfigHeader val4 = new ConfigHeader(config.rootPanel, " ", 24);
val4.textSize = 12;
ConfigHeader val5 = new ConfigHeader(config.rootPanel, "Volume at which voicelines are played. 0 - 1 including decimals", 24);
val5.textSize = 12;
V1Volume = new FloatField(config.rootPanel, "Voiceline Volume", "voice_volume", 1f);
V1Volume.minimumValue = 0f;
V1Volume.maximumValue = 1f;
ConfigHeader val6 = new ConfigHeader(config.rootPanel, "Chance to play a voiceline. Ie: a value of 4 has a 1/4 chance to play", 24);
val6.textSize = 12;
V1Chance = new IntField(config.rootPanel, "Voiceline Chance", "voice_chance", 1);
V1Chance.minimumValue = 1;
((BaseUnityPlugin)this).Logger.LogInfo((object)("Current Volume is " + V1Volume.value));
((MonoBehaviour)this).StartCoroutine(DelayedInitialize());
}
[IteratorStateMachine(typeof(<DelayedInitialize>d__8))]
private IEnumerator DelayedInitialize()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DelayedInitialize>d__8(0)
{
<>4__this = this
};
}
[IteratorStateMachine(typeof(<LoadClip>d__9))]
private IEnumerator LoadClip(WWW www, List<AudioClip> targetList)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadClip>d__9(0)
{
<>4__this = this,
www = www,
targetList = targetList
};
}
}
[HarmonyPatch(typeof(EnemyIdentifier), "Death", new Type[] { typeof(bool) })]
public static class EnemyDeathPatch
{
[CompilerGenerated]
private sealed class <StopAndDestroyAfter>d__6 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public AudioSource source;
public float delay;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <StopAndDestroyAfter>d__6(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSeconds(delay);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
source.Stop();
Object.Destroy((Object)(object)((Component)source).gameObject);
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static float lastPlayTime = 0f;
private static float cooldownSeconds = 1f;
private static AudioSource currentKillAudio;
private static float V1_Volume = VoiceModPlugin.V1Volume.value;
private static int V1_Chance = VoiceModPlugin.V1Chance.value;
public static void Prefix(EnemyIdentifier __instance, bool fromExplosion)
{
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Expected O, but got Unknown
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
V1_Volume = VoiceModPlugin.V1Volume.value;
V1_Chance = VoiceModPlugin.V1Chance.value;
if ((Object)(object)__instance == (Object)null || __instance.dead)
{
return;
}
if (VoiceModPlugin.KillSounds == null || VoiceModPlugin.KillSounds.Count == 0)
{
VoiceModPlugin.ModLogger.LogWarning((object)"No kill sounds loaded.");
}
else
{
if (Random.Range(1, V1_Chance + 1) != 1)
{
return;
}
float time = Time.time;
if (time < lastPlayTime + cooldownSeconds)
{
return;
}
if ((Object)(object)currentKillAudio != (Object)null)
{
currentKillAudio.Stop();
Object.Destroy((Object)(object)((Component)currentKillAudio).gameObject);
currentKillAudio = null;
}
lastPlayTime = time;
try
{
Camera main = Camera.main;
Transform val = ((main != null) ? ((Component)main).transform : null);
if ((Object)(object)val == (Object)null)
{
VoiceModPlugin.ModLogger.LogWarning((object)"Could not find player camera to play sound.");
return;
}
GameObject val2 = new GameObject("TempAudio");
val2.transform.position = val.position;
currentKillAudio = val2.AddComponent<AudioSource>();
int index = Random.Range(0, VoiceModPlugin.KillSounds.Count);
AudioClip val3 = VoiceModPlugin.KillSounds[index];
string key = ((Object)__instance).name.ToLower().Replace("(clone)", "").Trim();
AudioClip val4 = null;
if (VoiceModPlugin.ExclusiveKillSounds.TryGetValue(key, out var value) && value.Count > 0 && Random.Range(0, VoiceModPlugin.KillSounds.Count + 1) == 0)
{
val4 = value[Random.Range(0, value.Count)];
}
else
{
if (VoiceModPlugin.KillSounds.Count <= 0)
{
VoiceModPlugin.ModLogger.LogWarning((object)"No kill sound available to play.");
Object.Destroy((Object)(object)val2);
return;
}
val4 = VoiceModPlugin.KillSounds[Random.Range(0, VoiceModPlugin.KillSounds.Count)];
}
VoiceModPlugin.ModLogger.LogInfo((object)("Current Volume is " + VoiceModPlugin.V1Volume.value));
currentKillAudio.clip = val4;
currentKillAudio.spatialBlend = 0f;
currentKillAudio.volume = V1_Volume;
currentKillAudio.loop = false;
((Behaviour)currentKillAudio).enabled = true;
currentKillAudio.Play();
cooldownSeconds = val4.length + 0.1f;
lastPlayTime = Time.time;
StopAndDestroyAfter(currentKillAudio, val3.length + 0.1f);
VoiceModPlugin.ModLogger.LogInfo((object)("Played sound: " + ((Object)val3).name + " for: " + ((Object)__instance).name + " at player position."));
}
catch (Exception arg)
{
VoiceModPlugin.ModLogger.LogError((object)$"Failed to play kill sound: {arg}");
}
}
}
[IteratorStateMachine(typeof(<StopAndDestroyAfter>d__6))]
private static IEnumerator StopAndDestroyAfter(AudioSource source, float delay)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <StopAndDestroyAfter>d__6(0)
{
source = source,
delay = delay
};
}
}