using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ComputerysModdingUtilities;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("CombatSounds")]
[assembly: AssemblyDescription("STRAFTAT: pick your own hit, head hit and kill sounds, client-side.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: StraftatMod(true)]
[assembly: AssemblyVersion("1.0.1.0")]
namespace CombatSounds;
[BepInPlugin("dorsth.straftat.combatsounds", "CombatSounds", "1.0.1")]
public sealed class CombatSoundsPlugin : BaseUnityPlugin
{
public const string Guid = "dorsth.straftat.combatsounds";
public const string Name = "CombatSounds";
public const string Version = "1.0.1";
internal static ManualLogSource Log;
internal static SoundSlot Hit;
internal static SoundSlot HeadHit;
internal static SoundSlot Kill;
private void Awake()
{
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Log.LogMessage((object)"Dorsth was here");
string text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
if (string.Equals(Path.GetFullPath(text).TrimEnd('\\', '/'), Path.GetFullPath(Paths.PluginPath).TrimEnd('\\', '/'), StringComparison.OrdinalIgnoreCase))
{
text = Path.Combine(text, "CombatSounds");
}
Hit = new SoundSlot(((BaseUnityPlugin)this).Config, "Hit Sound", Path.Combine(text, "HitSounds"), "Sound when you hit a player.");
HeadHit = new SoundSlot(((BaseUnityPlugin)this).Config, "Head Hit Sound", Path.Combine(text, "HeadHitSounds"), "Sound when you hit a player in the head. Same as Hit = your hit sound, at this volume.", Hit);
Kill = new SoundSlot(((BaseUnityPlugin)this).Config, "Kill Sound", Path.Combine(text, "KillSounds"), "Sound when you kill a player. Plays on top of the hit sound.");
try
{
Hooks.Install(new Harmony("dorsth.straftat.combatsounds"));
}
catch (Exception ex)
{
Log.LogError((object)("Couldn't hook the game's hit sounds, so the mod is off. (" + ex.Message + ")"));
}
}
}
internal sealed class SoundSlot
{
private const string Default = "Default";
private const string None = "None";
private const string SameAsHit = "Same as Hit";
private static GameObject _speaker;
private readonly ConfigEntry<string> _choice;
private readonly ConfigEntry<int> _volume;
private readonly Dictionary<string, string> _files = new Dictionary<string, string>();
private readonly string _name;
private readonly SoundSlot _hit;
private AudioSource _source;
private AudioClip _clip;
private AudioClip _louder;
private AudioClip _louderOf;
private string _sound;
private bool _none;
private bool _following;
private int _loadId;
private int _louderVolume;
private float _nextPreview;
private SoundSlot Pick
{
get
{
if (!_following)
{
return this;
}
return _hit;
}
}
internal bool ReplacesGameSound
{
get
{
SoundSlot pick = Pick;
if (!((Object)(object)pick._clip != (Object)null))
{
return pick._none;
}
return true;
}
}
internal bool HasSound => (Object)(object)Pick._clip != (Object)null;
internal SoundSlot(ConfigFile config, string name, string folder, string description, SoundSlot hit = null)
{
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Expected O, but got Unknown
//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
//IL_01db: Expected O, but got Unknown
_name = name;
_hit = hit;
List<string> list = new List<string>
{
(hit != null) ? "Same as Hit" : "Default",
"None"
};
try
{
Directory.CreateDirectory(folder);
string[] files = Directory.GetFiles(folder);
Array.Sort(files, (IComparer<string>?)StringComparer.OrdinalIgnoreCase);
string[] array = files;
foreach (string text in array)
{
string text2 = Path.GetExtension(text).ToLowerInvariant();
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
if ((!(text2 != ".wav") || !(text2 != ".ogg") || !(text2 != ".mp3")) && !list.Contains(fileNameWithoutExtension))
{
list.Add(fileNameWithoutExtension);
_files[fileNameWithoutExtension] = text;
}
}
}
catch (Exception ex)
{
CombatSoundsPlugin.Log.LogWarning((object)("Couldn't read " + folder + ": " + ex.Message));
}
string text3 = (folder.StartsWith(Paths.GameRootPath, StringComparison.OrdinalIgnoreCase) ? folder.Substring(Paths.GameRootPath.Length).TrimStart('\\', '/') : folder);
_choice = config.Bind<string>("Sounds", name, list[0], new ConfigDescription(description + ((hit != null) ? "" : " Default = the game's own sound.") + " None = no sound. To add your own, put .wav, .ogg or .mp3 files in " + text3 + " and restart the game.", (AcceptableValueBase)(object)new AcceptableValueList<string>(list.ToArray()), Array.Empty<object>()));
_volume = config.Bind<int>("Sounds", name + " Volume", 100, new ConfigDescription("Volume of the " + name.ToLowerInvariant() + ". 100 = normal, 200 = twice as loud.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
_choice.SettingChanged += delegate
{
Load(preview: true);
};
_volume.SettingChanged += delegate
{
if (!(Time.unscaledTime < _nextPreview))
{
_nextPreview = Time.unscaledTime + 0.3f;
Play();
}
};
Load(preview: false);
}
internal bool SameSound(SoundSlot other)
{
if (other != null)
{
return string.Equals(Pick._sound, other.Pick._sound, StringComparison.OrdinalIgnoreCase);
}
return false;
}
internal void Play()
{
AudioClip clip = Pick._clip;
if (!((Object)(object)clip == (Object)null))
{
if ((Object)(object)_source == (Object)null)
{
_source = NewSource();
}
int value = _volume.Value;
_source.clip = ((value > 100) ? Louder(clip, value) : clip);
_source.volume = ((value > 100) ? 1f : ((float)value / 100f));
_source.Play();
}
}
internal void Stop()
{
if ((Object)(object)_source != (Object)null)
{
_source.Stop();
}
}
private static AudioSource NewSource()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
if ((Object)(object)_speaker == (Object)null)
{
_speaker = new GameObject("CombatSounds")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)(object)_speaker);
}
AudioSource obj = _speaker.AddComponent<AudioSource>();
obj.playOnAwake = false;
obj.spatialBlend = 0f;
obj.priority = 0;
bool flag = (obj.bypassReverbZones = true);
bool bypassEffects = (obj.bypassListenerEffects = flag);
obj.bypassEffects = bypassEffects;
return obj;
}
private AudioClip Louder(AudioClip clip, int volume)
{
if (_louderVolume == volume && (Object)(object)_louderOf == (Object)(object)clip)
{
return _louder ?? clip;
}
_louderVolume = volume;
_louderOf = clip;
DropLouder();
try
{
float[] array = new float[clip.samples * clip.channels];
if (!clip.GetData(array, 0))
{
return clip;
}
float num = (float)volume / 100f;
for (int i = 0; i < array.Length; i++)
{
array[i] = Mathf.Clamp(array[i] * num, -1f, 1f);
}
_louder = AudioClip.Create(((Object)clip).name + " (louder)", clip.samples, clip.channels, clip.frequency, false);
_louder.SetData(array, 0);
return _louder;
}
catch (Exception ex)
{
CombatSoundsPlugin.Log.LogWarning((object)("Couldn't make " + ((Object)clip).name + " louder, so it plays at 100. (" + ex.Message + ")"));
DropLouder();
return clip;
}
}
private void DropLouder()
{
if ((Object)(object)_louder != (Object)null)
{
Object.Destroy((Object)(object)_louder);
}
_louder = null;
}
private void Load(bool preview)
{
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
int id = ++_loadId;
string choice = _choice.Value;
_none = choice == "None";
_following = _hit != null && choice == "Same as Hit";
if ((Object)(object)_clip != (Object)null)
{
Object.Destroy((Object)(object)_clip);
}
_clip = null;
_sound = null;
DropLouder();
_louderVolume = 0;
if (!_files.TryGetValue(choice, out var file))
{
if (preview && _following)
{
Play();
}
return;
}
string text = Path.GetExtension(file).ToLowerInvariant();
AudioType val = (AudioType)((text == ".ogg") ? 14 : ((text == ".mp3") ? 13 : 20));
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(file), val);
((AsyncOperation)request.SendWebRequest()).completed += delegate
{
try
{
AudioClip val2 = (string.IsNullOrEmpty(request.error) ? DownloadHandlerAudioClip.GetContent(request) : null);
if (id != _loadId)
{
if ((Object)(object)val2 != (Object)null)
{
Object.Destroy((Object)(object)val2);
}
}
else if ((Object)(object)val2 == (Object)null || val2.samples == 0)
{
CombatSoundsPlugin.Log.LogWarning((object)("Couldn't load " + Path.GetFileName(file) + " (" + (request.error ?? "not a sound Unity can play") + "), so the game's own " + _name.ToLowerInvariant() + " plays."));
}
else
{
((Object)val2).name = choice;
_clip = val2;
_sound = choice;
if (preview)
{
Play();
}
}
}
catch (Exception ex)
{
CombatSoundsPlugin.Log.LogWarning((object)("Couldn't load " + Path.GetFileName(file) + ": " + ex.Message));
}
finally
{
request.Dispose();
}
};
}
}
internal static class Hooks
{
private static int _frame = -1;
private static SoundSlot _hit;
private static SoundSlot _kill;
private static int _headLayerFrame = -1;
private static bool _errorLogged;
internal static void Install(Harmony harmony)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Expected O, but got Unknown
harmony.Patch((MethodBase)AccessTools.Method(typeof(Settings), "IncreaseBodyshotsAmount", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Hooks), "HitPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)AccessTools.Method(typeof(Settings), "IncreaseHeadshotsAmount", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Hooks), "HeadHitPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)AccessTools.Method(typeof(Settings), "IncreaseKillsAmount", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Hooks), "KillPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
HarmonyMethod val = new HarmonyMethod(typeof(Hooks), "GameSoundPrefix", (Type[])null);
Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(Weapon).Assembly);
foreach (Type type in typesFromAssembly)
{
if (typeof(Weapon).IsAssignableFrom(type))
{
MethodInfo methodInfo = AccessTools.DeclaredMethod(type, "LocalSound", new Type[1] { typeof(int) }, (Type[])null);
if (methodInfo != null)
{
harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
}
}
private static void HitPostfix()
{
Play(CombatSoundsPlugin.Hit, kill: false);
}
private static void HeadHitPostfix()
{
Play(CombatSoundsPlugin.HeadHit, kill: false);
}
private static void KillPostfix()
{
Play(CombatSoundsPlugin.Kill, kill: true);
}
private static void Play(SoundSlot slot, bool kill)
{
try
{
if (!slot.HasSound)
{
return;
}
int frameCount = Time.frameCount;
if (frameCount != _frame)
{
_frame = frameCount;
_hit = (_kill = null);
}
if (kill)
{
if (_kill == null)
{
_kill = slot;
if (!slot.SameSound(_hit))
{
slot.Play();
}
}
}
else if (_hit != slot && _hit != CombatSoundsPlugin.HeadHit)
{
if (_hit != null)
{
_hit.Stop();
}
_hit = slot;
if (!slot.SameSound(_kill))
{
slot.Play();
}
}
}
catch (Exception ex)
{
if (!_errorLogged)
{
_errorLogged = true;
CombatSoundsPlugin.Log.LogError((object)("Error (further errors are not logged): " + ex));
}
}
}
private static bool GameSoundPrefix(int __0)
{
switch (__0)
{
case 0:
_headLayerFrame = Time.frameCount;
return !CombatSoundsPlugin.HeadHit.ReplacesGameSound;
case 1:
{
bool num = _headLayerFrame == Time.frameCount;
_headLayerFrame = -1;
return !(num ? CombatSoundsPlugin.HeadHit : CombatSoundsPlugin.Hit).ReplacesGameSound;
}
case 2:
return !CombatSoundsPlugin.Kill.ReplacesGameSound;
default:
return true;
}
}
}