Decompiled source of AkechiBracken v1.2.0

AkechiBracken.dll

Decompiled 8 months ago
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 AkechiBracken.Core;
using AkechiBracken.Patches;
using AkechiBracken.Scripts;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
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("AkechiBracken")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AkechiBracken")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2f4869f2-4749-4b64-9b84-22f15eae6e4d")]
[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 AkechiBracken.Scripts
{
	public class AkechiController : MonoBehaviour
	{
		private FlowermanAI FlowermanAI { get; set; }

		private GameObject DefaultAkechiObject { get; set; }

		private GameObject AggressiveAkechiObject { get; set; }

		private GameObject DeadAkechiObject { get; set; }

		private bool IsDead { get; set; }

		private AudioClip[] CrackNeckAudioClips { get; set; }

		private int CrackNeckRandomIdx { get; set; }

		private void Start()
		{
			FlowermanAI = ((Component)this).GetComponent<FlowermanAI>();
			HideFlowermanModel();
			CreateAkechiModels();
			ReplaceFlowermanSFX();
			UpdateScanNodeData();
		}

		private void Update()
		{
			if (((EnemyAI)FlowermanAI).isEnemyDead)
			{
				if (!IsDead)
				{
					KillAkechi();
				}
			}
			else if (FlowermanAI.isInAngerMode)
			{
				EnterAttackState();
			}
			else
			{
				ExitAttackState();
			}
		}

		private void HideFlowermanModel()
		{
			Renderer[] componentsInChildren = ((Component)((Component)FlowermanAI).transform.Find("FlowermanModel")).GetComponentsInChildren<Renderer>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
		}

		private void CreateAkechiModels()
		{
			GameObject asset = Assets.GetAsset<GameObject>("AkechiBracken_Default_Prefab");
			DefaultAkechiObject = Object.Instantiate<GameObject>(asset, ((Component)this).gameObject.transform);
			((Object)DefaultAkechiObject).name = "Default Akechi";
			GameObject asset2 = Assets.GetAsset<GameObject>("AkechiBracken_Aggressive_Prefab");
			AggressiveAkechiObject = Object.Instantiate<GameObject>(asset2, ((Component)this).gameObject.transform);
			((Object)AggressiveAkechiObject).name = "Aggressive Akechi";
			GameObject asset3 = Assets.GetAsset<GameObject>("AkechiBracken_Death_Prefab");
			DeadAkechiObject = Object.Instantiate<GameObject>(asset3, ((Component)this).gameObject.transform);
			((Object)DeadAkechiObject).name = "Dead Akechi";
		}

		private void ReplaceFlowermanSFX()
		{
			if (ConfigManager.UseMusic.Value)
			{
				FlowermanAI.creatureAngerVoice.clip = Assets.GetAsset<AudioClip>("AkechiBracken_Aggressive_SFX");
			}
			if (ConfigManager.UseVoicelines.Value)
			{
				CrackNeckAudioClips = (AudioClip[])(object)new AudioClip[4];
				CrackNeckAudioClips[0] = Assets.GetAsset<AudioClip>("AkechiBracken_CrackNeck1_SFX");
				CrackNeckAudioClips[1] = Assets.GetAsset<AudioClip>("AkechiBracken_CrackNeck2_SFX");
				CrackNeckAudioClips[2] = Assets.GetAsset<AudioClip>("AkechiBracken_CrackNeck3_SFX");
				CrackNeckAudioClips[3] = Assets.GetAsset<AudioClip>("AkechiBracken_CrackNeck4_SFX");
				CrackNeckRandomIdx = Random.Range(0, CrackNeckAudioClips.Length - 1);
				FlowermanAI.crackNeckSFX = CrackNeckAudioClips[CrackNeckRandomIdx];
				FlowermanAI.crackNeckAudio.clip = CrackNeckAudioClips[CrackNeckRandomIdx];
				((EnemyAI)FlowermanAI).enemyBehaviourStates[0].VoiceClip = Assets.GetAsset<AudioClip>("AkechiBracken_Ambient_SFX");
				((EnemyAI)FlowermanAI).enemyBehaviourStates[1].VoiceClip = Assets.GetAsset<AudioClip>("AkechiBracken_Voice_SFX");
				((EnemyAI)FlowermanAI).enemyType.hitEnemyVoiceSFX = Assets.GetAsset<AudioClip>("AkechiBracken_Hit_SFX");
				((EnemyAI)FlowermanAI).enemyType.stunSFX = Assets.GetAsset<AudioClip>("AkechiBracken_Stunned_SFX");
			}
			if (ConfigManager.UseDeathSound.Value)
			{
				((EnemyAI)FlowermanAI).dieSFX = Assets.GetAsset<AudioClip>("AkechiBracken_Death_SFX");
			}
		}

		private void UpdateScanNodeData()
		{
			((Component)FlowermanAI).GetComponentInChildren<ScanNodeProperties>().headerText = "Goro Akechi";
		}

		private void EnterAttackState()
		{
			DefaultAkechiObject.SetActive(false);
			AggressiveAkechiObject.SetActive(true);
		}

		private void ExitAttackState()
		{
			DefaultAkechiObject.SetActive(true);
			AggressiveAkechiObject.SetActive(false);
		}

		private void KillAkechi()
		{
			DefaultAkechiObject.SetActive(false);
			AggressiveAkechiObject.SetActive(false);
			DeadAkechiObject.SetActive(true);
			DeadAkechiObject.GetComponentInChildren<ParticleSystem>().Play();
			((EnemyAI)FlowermanAI).enemyType.hitBodySFX = null;
			((EnemyAI)FlowermanAI).enemyType.hitEnemyVoiceSFX = null;
			IsDead = true;
		}
	}
}
namespace AkechiBracken.Patches
{
	[HarmonyPatch]
	internal class EnemyPatches
	{
		[HarmonyPatch(typeof(FlowermanAI), "Start")]
		[HarmonyPostfix]
		public static void CreateAkechiModel(FlowermanAI __instance)
		{
			((Component)__instance).gameObject.AddComponent<AkechiController>();
		}
	}
	[HarmonyPatch]
	internal class TerminalPatches
	{
		[HarmonyPatch(typeof(Terminal), "Awake")]
		[HarmonyPostfix]
		public static void EditTerminal(Terminal __instance)
		{
			__instance.enemyFiles[1].creatureName = "Goro Akechi";
			__instance.enemyFiles[1].displayText = "Shut up, shut up, shut up! Teammates!? Friends!? To hell with that! Why am I inferior to you...!? I was extremely particular about my life, my grades, my public image, so someone would want me around! I am an ace detective... a celebrity! But you... You're just some criminal trash living in an attic! So how!? How does someone like you have things I don't!? How can such a worthless piece of trash be more special than me!?";
			int num = -1;
			for (int i = 0; i < __instance.terminalNodes.allKeywords.Length - 1; i++)
			{
				if (__instance.terminalNodes.allKeywords[i].word == "brackens")
				{
					num = i;
					break;
				}
			}
			if (num >= 0)
			{
				__instance.terminalNodes.allKeywords[num].word = "goro akechi";
			}
			else
			{
				Logger.LogWarning("AkechiBracken - Warning: Could not locate terminal keyword to swap 'Brackens' for 'Goro Akechi'! Terminal may not work correctly when parsing as a result.");
			}
		}
	}
}
namespace AkechiBracken.Core
{
	internal static class PluginInfo
	{
		public const string GUID = "Balaneo.AkechiBracken";

		public const string NAME = "Akechi Bracken";

		public const string VERSION = "1.0.0.0";

		public const string ASSET_BUNDLE_NAME = "akechibracken";
	}
	internal static class ConfigManager
	{
		public static ConfigEntry<bool> UseSkinVariants { get; private set; }

		public static ConfigEntry<bool> UseVoicelines { get; private set; }

		public static ConfigEntry<bool> UseMusic { get; private set; }

		public static ConfigEntry<bool> UseDeathSound { get; private set; }

		private static ConfigFile Config => AkechiBrackenBase.ModConfig;

		public static void InitializeConfig()
		{
			UseVoicelines = Config.Bind<bool>("Sound", "Use Akechi Voicelines", true, "Controls whether or not to replace the bracken's kill sound with Akechi voicelines");
			UseMusic = Config.Bind<bool>("Sound", "Use UI Music", true, "Controls whether or not to replace the bracken's agressive sound with Akechis boss fight music");
			UseDeathSound = Config.Bind<bool>("Sound", "Use Death Sound", true, "Controls whether or not to play a sound on the bracken's death");
		}
	}
	internal static class Logger
	{
		public static void LogInfo(object message)
		{
			AkechiBrackenBase.LogSource.LogInfo(message);
		}

		public static void LogWarning(object message)
		{
			AkechiBrackenBase.LogSource.LogWarning(message);
		}

		public static void LogError(object message)
		{
			AkechiBrackenBase.LogSource.LogError(message);
		}
	}
	[BepInPlugin("Balaneo.AkechiBracken", "Akechi Bracken", "1.0.0.0")]
	public class AkechiBrackenBase : BaseUnityPlugin
	{
		private static AkechiBrackenBase _instance;

		private readonly Harmony Harmony = new Harmony("Balaneo.AkechiBracken");

		internal static AkechiBrackenBase Instance
		{
			get
			{
				return _instance;
			}
			set
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Expected O, but got Unknown
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Expected O, but got Unknown
				if ((Object)_instance == (Object)null)
				{
					_instance = value;
				}
				else
				{
					Object.Destroy((Object)value);
				}
			}
		}

		public static ManualLogSource LogSource => ((BaseUnityPlugin)Instance).Logger;

		public static ConfigFile ModConfig => ((BaseUnityPlugin)Instance).Config;

		private void Awake()
		{
			Instance = this;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Initializing config...");
			ConfigManager.InitializeConfig();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading asset bundle...");
			Assets.PopulateAssets();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Goro Akechi has arrived!");
			Harmony.PatchAll(typeof(AkechiBrackenBase));
			Harmony.PatchAll(typeof(EnemyPatches));
			Harmony.PatchAll(typeof(TerminalPatches));
		}
	}
	internal static class Assets
	{
		public static AssetBundle AssetBundle { get; private set; }

		private static Dictionary<string, Object> AssetList { get; set; }

		private static string AssemblyName => Assembly.GetExecutingAssembly().FullName.Split(new char[1] { ',' })[0];

		public static void PopulateAssets()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			if ((Object)AssetBundle != (Object)null)
			{
				Logger.LogWarning("Attempted to load the asset bundle but the bundle was not null!");
				return;
			}
			string name = AssemblyName + ".Bundles.akechibracken";
			using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
			{
				AssetBundle = AssetBundle.LoadFromStream(stream);
			}
			if ((Object)AssetBundle == (Object)null)
			{
				Logger.LogError("Asset bundle at " + AssemblyName + ".akechibracken failed to load!");
			}
			AssetList = new Dictionary<string, Object>();
			Object[] array = AssetBundle.LoadAllAssets();
			Object[] array2 = array;
			foreach (Object val in array2)
			{
				AssetList.Add(val.name, val);
			}
		}

		public static T GetAsset<T>(string name) where T : Object
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			if (!AssetList.TryGetValue(name, out var value))
			{
				Logger.LogError("Attempted to load asset of name " + name + " but no asset of that name exists!");
				return default(T);
			}
			T val = (T)(object)((value is T) ? value : null);
			if ((Object)val == (Object)null)
			{
				Logger.LogError("Attempted to load an asset of type " + typeof(T).Name + " but asset of name " + name + " does not match this type!");
				return default(T);
			}
			return val;
		}
	}
}