Decompiled source of PissyEnemies v1.1.0

PissyEnemies.dll

Decompiled 2 weeks ago
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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("PissyEnemies")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PissyEnemies")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9d9d3f61-800f-4c7e-987b-5b816a6b0169")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace PissyEnemies;

internal class CustomRager : MonoBehaviour
{
	public string ragingInfoComponent;

	public string ragingInfoEnemy;

	public float ragingInfoVolume;

	public List<AudioClip> ragingInfoClips;

	public int ragingInfoTauntCount;

	private bool eternalTaunt;

	public AudioSource audiosource;

	public AudioSource audiosourceOG;

	private EnemyIdentifier enemyIdentifier;

	private object enemyScript;

	private PropertyInfo enraged;

	private bool canTaunt = true;

	private bool canEnrage = true;

	private List<AudioClip> unusedTaunts;

	private int tauntCountdown;

	private void Awake()
	{
		audiosourceOG = ((Component)this).GetComponent<AudioSource>();
		audiosource = ((Component)this).gameObject.AddComponent<AudioSource>();
		enemyIdentifier = ((Component)this).gameObject.GetComponent<EnemyIdentifier>();
		unusedTaunts = new List<AudioClip>();
	}

	private void Start()
	{
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Expected O, but got Unknown
		audiosource.playOnAwake = false;
		audiosource.outputAudioMixerGroup = MonoSingleton<AudioMixerController>.instance.allGroup;
		audiosource.minDistance = 8f;
		audiosource.spatialBlend = 1f;
		audiosource.clip = ragingInfoClips[0];
		audiosource.volume = ragingInfoVolume;
		audiosource.maxDistance = Plugin.maxDistance.Value;
		audiosource.dopplerLevel = Plugin.doppler.Value;
		ragingInfoClips.ForEach(delegate(AudioClip x)
		{
			unusedTaunts.Add(x);
		});
		try
		{
			enemyScript = ((Component)this).gameObject.GetComponents(typeof(Component)).ToList().Find((Component x) => ((object)x).GetType().Name == ragingInfoComponent);
			enraged = enemyScript.GetType().GetProperty("isEnraged");
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("There's been an error while getting the enemy script component for \"" + ragingInfoEnemy + "\" (" + ragingInfoComponent + ") and enraged property! This is most likely caused by trying to add a CustomRager to an unenragable enemy. To solve this, please check your PissyEnemies.json and correct it.\n" + ex.Message));
			Object.Destroy((Object)(object)this);
		}
		eternalTaunt = ragingInfoTauntCount < 0;
		tauntCountdown = ragingInfoTauntCount;
		UnityAction val = (UnityAction)delegate
		{
			audiosource.Stop();
		};
		enemyIdentifier.onDeath.AddListener(val);
	}

	private void LateUpdate()
	{
		if (!enemyIdentifier.dead)
		{
			bool flag;
			try
			{
				flag = (bool)enraged.GetValue(enemyScript);
			}
			catch
			{
				flag = false;
			}
			if (flag && !canTaunt && !audiosource.isPlaying)
			{
				canTaunt = true;
			}
			else if (audiosource.isPlaying)
			{
				canTaunt = false;
			}
			if (canTaunt)
			{
				EnrageTaunt(ragingInfoClips);
			}
			else if (!flag)
			{
				audiosource.Stop();
			}
			if (tauntCountdown <= 0 && !flag)
			{
				tauntCountdown = ragingInfoTauntCount;
			}
		}
	}

	public void EnrageTaunt(List<AudioClip> clips)
	{
		if (tauntCountdown <= 0 && !eternalTaunt)
		{
			return;
		}
		if (clips.Count > 1)
		{
			if (unusedTaunts.Count == 0)
			{
				ragingInfoClips.ForEach(delegate(AudioClip x)
				{
					unusedTaunts.Add(x);
				});
			}
			int index = Random.Range(0, unusedTaunts.Count);
			audiosource.PlayOneShot(unusedTaunts[index]);
			unusedTaunts.RemoveAt(index);
		}
		else
		{
			audiosource.Play();
		}
		if (!eternalTaunt)
		{
			tauntCountdown--;
		}
	}
}
public class RagingInfo : MonoBehaviour
{
	public string component { get; set; }

	public string enemy { get; set; }

	public List<AudioClip> clips { get; set; }

	public float volume { get; set; }

	public int tauntcount { get; set; }

	public RagingInfo(string component, List<AudioClip> clips, string enemy, string volume, int tauntcount)
	{
		this.component = component;
		this.enemy = enemy;
		this.clips = clips;
		this.volume = (float.TryParse(volume, out var _) ? float.Parse(volume) : Plugin.volume.Value);
		this.tauntcount = tauntcount;
	}

	public RagingInfo(RagingInfo ri)
	{
		component = ri.component;
		clips = ri.clips;
		enemy = ri.enemy;
		volume = ri.volume;
		tauntcount = ri.tauntcount;
	}

	public RagingInfo()
	{
	}
}
[HarmonyPatch(typeof(EnemyIdentifier))]
[HarmonyPatch("Start")]
public static class EnemyIdentifier_Start_Patch
{
	[HarmonyPostfix]
	private static void Postfix(EnemyIdentifier __instance)
	{
		GameObject gameObject = ((Component)__instance).gameObject;
		Debug.Log((object)gameObject);
		List<Component> list = gameObject.GetComponents<Component>().ToList();
		bool flag = false;
		foreach (Component item in list)
		{
			try
			{
				foreach (RagingInfo enemy in Plugin.enemies)
				{
					if (enemy.component.Equals(((object)item).GetType().Name) && enemy.enemy.Equals(((object)(EnemyType)(ref __instance.enemyType)).ToString()))
					{
						CustomRager customRager = ((Component)__instance).gameObject.AddComponent<CustomRager>();
						customRager.ragingInfoComponent = enemy.component;
						customRager.ragingInfoEnemy = enemy.enemy;
						customRager.ragingInfoClips = enemy.clips;
						customRager.ragingInfoVolume = enemy.volume;
						customRager.ragingInfoTauntCount = enemy.tauntcount;
						flag = true;
						break;
					}
				}
			}
			catch
			{
				Debug.Log((object)("Error trying to find enemy component for " + ((object)(EnemyType)(ref __instance.enemyType)).ToString()));
				break;
			}
			if (flag)
			{
				break;
			}
		}
	}
}
[BepInPlugin("simonciott.ultrakill.pissyenemies", "PissyEnemies", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	private const string modGUID = "simonciott.ultrakill.pissyenemies";

	private const string modName = "PissyEnemies";

	private const string modVersion = "1.0.0";

	private const string easteregg = "SONO PARANOICO ED OSSESSIVO FINO ALL'ABIURA DI ME";

	private static readonly Harmony Harmony = new Harmony("simonciott.ultrakill.pissyenemies");

	public static readonly string pissyEnemiesPath;

	public static readonly string pissyEnemiesPathConfig;

	public static readonly string lastResortPath;

	public static readonly List<string> supportedFormats;

	public static List<RagingInfo> enemies;

	public static List<RageData> enemiesData;

	public static bool canRun;

	public static bool isConfigPath;

	public static ConfigEntry<float> maxDistance;

	public static ConfigEntry<float> volume;

	public static ConfigEntry<float> doppler;

	public static string usedPath;

	private void Awake()
	{
		Debug.Log((object)"PissyEnemies is loading...");
		volume = ((BaseUnityPlugin)this).Config.Bind<float>("General", "volume", 1f, "The volume of the audio if the property in the json is null or invalid. Must be between 0 and 1");
		maxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "maxDistance", 120f, "The maximum distance the sound can be hear from");
		doppler = ((BaseUnityPlugin)this).Config.Bind<float>("General", "doppler", 0f, "Enhances the doppler effect. Must be between 0 and 1");
		try
		{
			enemiesData = JsonConvert.DeserializeObject<List<RageData>>(File.ReadAllText(Path.Combine(pissyEnemiesPathConfig, "PissyEnemies.json")));
			usedPath = pissyEnemiesPathConfig;
		}
		catch
		{
			Debug.Log((object)"Config path data failed to load or is missing. Trying to load original path.");
			isConfigPath = false;
			try
			{
				enemiesData = JsonConvert.DeserializeObject<List<RageData>>(File.ReadAllText(Path.Combine(pissyEnemiesPath, "PissyEnemies.json")));
				usedPath = pissyEnemiesPath;
			}
			catch
			{
				Debug.Log((object)"Either paths are invalid. Trying out last resort.");
				try
				{
					enemiesData = JsonConvert.DeserializeObject<List<RageData>>(File.ReadAllText(Path.Combine(lastResortPath, "PissyEnemies.json")));
					usedPath = lastResortPath;
					goto end_IL_00e6;
				}
				catch
				{
					Debug.LogError((object)"All possible data paths are missing. Impossible to load PissyEnemies data.");
					canRun = false;
					goto end_IL_00e6;
				}
				end_IL_00e6:;
			}
		}
		if (canRun)
		{
			for (int i = 0; i < enemiesData.Count; i++)
			{
				((MonoBehaviour)this).StartCoroutine(LoadAudio(enemiesData[i].component, enemiesData[i].enemy, enemiesData[i].clips, enemiesData[i].volume, enemiesData[i].tauntcount, i));
			}
			Harmony.PatchAll();
			Debug.Log((object)"PissyEnemies is loaded! But check the logs if all audio clips load!");
		}
	}

	public static IEnumerator LoadAudio(string name, string enemy, List<string> filenames, string volume, int tauntcount, int index)
	{
		for (int i = 0; i < index; i++)
		{
			yield return null;
		}
		List<AudioClip> clips = new List<AudioClip>();
		foreach (string filename in filenames)
		{
			UnityWebRequest request = GetAudioFromFile(filename, usedPath);
			request.SendWebRequest();
			while (!request.isDone)
			{
				yield return null;
			}
			try
			{
				if (request.isHttpError)
				{
					throw new Exception("http error.");
				}
				AudioClip clip = DownloadHandlerAudioClip.GetContent(request);
				((Object)clip).name = "PissyEnemies_" + name + "_" + Path.GetFileNameWithoutExtension(filename);
				clips.Add(clip);
				Debug.Log((object)(((Object)clip).name + " has been loaded."));
			}
			catch (Exception e)
			{
				Debug.LogError((object)("failed to load " + filename + "!\n" + e.Message));
			}
		}
		enemies.Add(new RagingInfo(name, clips, enemy, volume, tauntcount));
	}

	public static UnityWebRequest GetAudioFromFile(string filename, string dataPath)
	{
		try
		{
			if (!supportedFormats.Any((string x) => x == Path.GetExtension(filename)))
			{
				throw new Exception("file is of unsupported format.");
			}
			string text = Path.Combine("file://", dataPath);
			string[] files = Directory.GetFiles(dataPath, filename, SearchOption.AllDirectories);
			if (files.Length < 1)
			{
				throw new Exception("file doesn't exist.");
			}
			string text2 = files[0];
			return UnityWebRequestMultimedia.GetAudioClip("file://" + text2, (AudioType)0);
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("Failed to get audio file " + filename + "!\n" + ex.Message));
			return null;
		}
	}

	static Plugin()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Expected O, but got Unknown
		string? directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
		char directorySeparatorChar = Path.DirectorySeparatorChar;
		pissyEnemiesPath = Path.Combine(directoryName, "PissyEnemies" + directorySeparatorChar);
		string configPath = Paths.ConfigPath;
		directorySeparatorChar = Path.DirectorySeparatorChar;
		pissyEnemiesPathConfig = Path.Combine(configPath, "PissyEnemies" + directorySeparatorChar);
		string? directoryName2 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
		directorySeparatorChar = Path.DirectorySeparatorChar;
		lastResortPath = directoryName2 + directorySeparatorChar;
		supportedFormats = new string[3] { ".wav", ".mp3", ".ogg" }.ToList();
		enemies = new List<RagingInfo>();
		canRun = true;
		isConfigPath = true;
	}
}
public class RageData
{
	public string component { get; set; }

	public string enemy { get; set; }

	public List<string> clips { get; set; }

	public string volume { get; set; }

	public int tauntcount { get; set; }
}