Decompiled source of ETHICAL Auras v0.2.1

ETHICAL-Auras.dll

Decompiled 5 months ago
using System;
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 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("ETHICAL-Auras")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ETHICAL-Auras")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d86f2d5e-231e-4f05-92fa-59b0c76e056c")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ETHICAL_Auras;

[BepInPlugin("com.talitore.ethical-auras", "ETHICAL Auras", "0.1.0")]
public class EthicalAurasPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "com.talitore.ethical-auras";

	public const string PluginName = "ETHICAL Auras";

	public const string PluginVersion = "0.1.0";

	private static ManualLogSource Log;

	private Harmony harmony;

	private AssetBundle ethicalAurasBundle;

	public static ConfigEntry<string> TrackedBuffsConfig;

	public static List<string> TrackedBuffNames = new List<string>();

	public static ConfigEntry<bool> EnableAudioAlertsConfig;

	public static ConfigEntry<bool> LoopAudioAlertConfig;

	public static ConfigEntry<string> SelectedAudioClipNameConfig;

	private bool isMenuVisible = false;

	private Vector2 menuScrollPosition = Vector2.zero;

	private string searchText = "";

	private List<StatusEffect> allStatusEffects = new List<StatusEffect>();

	private Dictionary<string, bool> statusEffectSelectionState = new Dictionary<string, bool>();

	private Dictionary<string, bool> initialSelectionState = new Dictionary<string, bool>();

	public static ConfigEntry<bool> EnableZoneAwarenessConfig;

	public static ConfigEntry<bool> MeadowsZoneConfig;

	public static ConfigEntry<bool> BlackForestZoneConfig;

	public static ConfigEntry<bool> SwampZoneConfig;

	public static ConfigEntry<bool> MountainZoneConfig;

	public static ConfigEntry<bool> PlainsZoneConfig;

	public static ConfigEntry<bool> MistlandsZoneConfig;

	public static ConfigEntry<bool> OceanZoneConfig;

	public static ConfigEntry<bool> AshlandsZoneConfig;

	public static ConfigEntry<bool> DeepNorthZoneConfig;

	public static ConfigEntry<float> IconSizeConfig;

	public static ConfigEntry<string> IconPositionConfig;

	public static ConfigEntry<float> IconSpacingConfig;

	private List<StatusEffect> currentlyMissingBuffs = new List<StatusEffect>();

	private AudioClip missingBuffAudioClip;

	private float iconFlashTimer = 0f;

	private const float ICON_FLASH_SPEED = 2f;

	private const float ICON_SIZE = 40f;

	private const float ICON_PADDING = 5f;

	private bool statusEffectsInitialized = false;

	private float playerLoadDelay = 3f;

	private bool hasStartedChecking = false;

	private void Awake()
	{
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Expected O, but got Unknown
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Expected O, but got Unknown
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Expected O, but got Unknown
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Expected O, but got Unknown
		//IL_0490: Unknown result type (might be due to invalid IL or missing references)
		//IL_049a: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"Plugin com.talitore.ethical-auras (ETHICAL Auras) is loading!");
		TrackedBuffsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TrackedBuffs", "Rested,CampFire,Potion_poisonresist", "List of buffs being tracked. Use the 'Open Buff Selection Menu' button to modify this list.");
		((BaseUnityPlugin)this).Config.Bind<string>("General", "BuffMenuNote", "Note: Click the checkbox below to open the buff selection menu where you can choose which buffs to track because real buttons are a pain", "This is a note for users");
		((BaseUnityPlugin)this).Config.Bind<bool>("General", "OpenBuffMenu", false, "Click to open the buff selection menu");
		((BaseUnityPlugin)this).Config.SettingChanged += delegate(object sender, SettingChangedEventArgs args)
		{
			if (args.ChangedSetting.Definition.Key == "OpenBuffMenu")
			{
				isMenuVisible = true;
				((BaseUnityPlugin)this).Config["General", "OpenBuffMenu"].BoxedValue = false;
			}
		};
		EnableAudioAlertsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("AudioAlerts", "EnableAudioAlerts", false, "Enable or disable audio alerts for missing buffs.");
		LoopAudioAlertConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("AudioAlerts", "LoopAudioAlert", true, "Enable or disable looping for the audio alert. If false, the sound plays once per missing buff.");
		SelectedAudioClipNameConfig = ((BaseUnityPlugin)this).Config.Bind<string>("AudioAlerts", "SelectedAudioClipName", "scream", new ConfigDescription("The name of the audio clip to play. Send me (talitore) clips to be added.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "scream", "creatine" }), Array.Empty<object>()));
		IconSizeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "IconSize", 40f, new ConfigDescription("Size of the buff icons in pixels", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 200f), Array.Empty<object>()));
		IconPositionConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "IconPosition", "TopCenter", new ConfigDescription("Position of the buff icons on screen", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[9] { "TopLeft", "TopCenter", "TopRight", "MiddleLeft", "MiddleCenter", "MiddleRight", "BottomLeft", "BottomCenter", "BottomRight" }), Array.Empty<object>()));
		IconSpacingConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "IconSpacing", 5f, new ConfigDescription("Spacing between buff icons in pixels", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
		IconSizeConfig.SettingChanged += delegate
		{
			Log.LogInfo((object)$"Icon size changed to: {IconSizeConfig.Value}");
		};
		IconPositionConfig.SettingChanged += delegate
		{
			Log.LogInfo((object)("Icon position changed to: " + IconPositionConfig.Value));
		};
		IconSpacingConfig.SettingChanged += delegate
		{
			Log.LogInfo((object)$"Icon spacing changed to: {IconSpacingConfig.Value}");
		};
		ParseTrackedBuffs();
		TrackedBuffsConfig.SettingChanged += delegate
		{
			ParseTrackedBuffs();
		};
		EnableAudioAlertsConfig.SettingChanged += delegate
		{
			Log.LogInfo((object)("Audio alerts " + (EnableAudioAlertsConfig.Value ? "enabled" : "disabled") + "."));
		};
		LoopAudioAlertConfig.SettingChanged += delegate
		{
			Log.LogInfo((object)("Audio alert looping " + (LoopAudioAlertConfig.Value ? "enabled" : "disabled") + "."));
		};
		SelectedAudioClipNameConfig.SettingChanged += delegate
		{
			Log.LogInfo((object)("Selected audio clip name changed to: " + SelectedAudioClipNameConfig.Value + ". Reloading clip."));
			LoadSelectedAudioClip(ethicalAurasBundle);
		};
		EnableZoneAwarenessConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwareness", "EnableZoneAwareness", true, "Enable or disable zone-specific buff tracking.");
		EnableZoneAwarenessConfig.SettingChanged += delegate
		{
			Log.LogInfo((object)("Zone awareness " + (EnableZoneAwarenessConfig.Value ? "enabled" : "disabled") + "."));
		};
		MeadowsZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "MeadowsZone", false, "Track buffs in Meadows biome.");
		BlackForestZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "BlackForestZone", false, "Track buffs in Black Forest biome.");
		SwampZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "SwampZone", false, "Track buffs in Swamp biome.");
		MountainZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "MountainZone", false, "Track buffs in Mountain biome.");
		PlainsZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "PlainsZone", false, "Track buffs in Plains biome.");
		MistlandsZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "MistlandsZone", false, "Track buffs in Mistlands biome.");
		OceanZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "OceanZone", false, "Track buffs in Ocean biome.");
		AshlandsZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "AshlandsZone", false, "Track buffs in Ashlands biome.");
		DeepNorthZoneConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ZoneAwarenessZones", "DeepNorthZone", false, "Track buffs in Deep North biome.");
		harmony = new Harmony("com.talitore.ethical-auras");
		harmony.PatchAll();
		Assembly executingAssembly = Assembly.GetExecutingAssembly();
		string text = "ETHICAL_Auras.ethical_auras";
		Stream manifestResourceStream = executingAssembly.GetManifestResourceStream(text);
		if (manifestResourceStream == null)
		{
			Log.LogError((object)("Failed to load embedded resource stream: " + text + ". Make sure the resource exists and is marked as an Embedded Resource."));
			return;
		}
		ethicalAurasBundle = AssetBundle.LoadFromStream(manifestResourceStream);
		manifestResourceStream.Close();
		if ((Object)(object)ethicalAurasBundle == (Object)null)
		{
			Log.LogError((object)("Failed to load AssetBundle from stream: " + text + "."));
			return;
		}
		LoadSelectedAudioClip(ethicalAurasBundle);
		Log.LogInfo((object)("Plugin com.talitore.ethical-auras (ETHICAL Auras) has loaded. Currently tracking: " + string.Join(", ", TrackedBuffNames)));
		Log.LogInfo((object)string.Format("Audio alerts: {0}, Loop: {1}, Clip: {2}", EnableAudioAlertsConfig.Value ? "Enabled" : "Disabled", LoopAudioAlertConfig.Value, SelectedAudioClipNameConfig.Value));
	}

	private void Start()
	{
	}

	private void LoadSelectedAudioClip(AssetBundle bundle)
	{
		if ((Object)(object)bundle == (Object)null)
		{
			Log.LogError((object)"AssetBundle is null. Cannot load audio clip.");
			missingBuffAudioClip = null;
			return;
		}
		string value = SelectedAudioClipNameConfig.Value;
		if (string.IsNullOrEmpty(value))
		{
			Log.LogWarning((object)"Selected audio clip name is empty. No audio clip will be loaded.");
			missingBuffAudioClip = null;
			return;
		}
		AudioClip val = bundle.LoadAsset<AudioClip>(value);
		if ((Object)(object)val == (Object)null)
		{
			Log.LogError((object)("Failed to load AudioClip '" + value + "' from AssetBundle. Ensure the clip exists in the bundle."));
			missingBuffAudioClip = null;
		}
		else
		{
			missingBuffAudioClip = val;
			Log.LogInfo((object)("Successfully loaded '" + value + "' audio clip from asset bundle."));
		}
	}

	private void ParseTrackedBuffs()
	{
		string text = TrackedBuffsConfig.Value ?? "";
		TrackedBuffNames = (from buffName in text.Split(new char[1] { ',' })
			select buffName.Trim() into buffName
			where !string.IsNullOrEmpty(buffName)
			select buffName).ToList();
		if (Log != null)
		{
			Log.LogInfo((object)"Tracked buffs configuration reloaded.");
			if (TrackedBuffNames.Any())
			{
				Log.LogInfo((object)("Currently configured to track: " + string.Join(", ", TrackedBuffNames)));
			}
			else
			{
				Log.LogInfo((object)"No buffs are currently configured for tracking.");
			}
		}
	}

	private bool IsCurrentZoneEnabled()
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Invalid comparison between Unknown and I4
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Invalid comparison between Unknown and I4
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected I4, but got Unknown
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Invalid comparison between Unknown and I4
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Invalid comparison between Unknown and I4
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Invalid comparison between Unknown and I4
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Invalid comparison between Unknown and I4
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Invalid comparison between Unknown and I4
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Invalid comparison between Unknown and I4
		if (!EnableZoneAwarenessConfig.Value)
		{
			return true;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		Biome currentBiome = localPlayer.GetCurrentBiome();
		Biome val = currentBiome;
		Biome val2 = val;
		if ((int)val2 <= 16)
		{
			switch (val2 - 1)
			{
			default:
				if ((int)val2 != 8)
				{
					if ((int)val2 != 16)
					{
						break;
					}
					return PlainsZoneConfig.Value;
				}
				return BlackForestZoneConfig.Value;
			case 0:
				return MeadowsZoneConfig.Value;
			case 1:
				return SwampZoneConfig.Value;
			case 3:
				return MountainZoneConfig.Value;
			case 2:
				break;
			}
		}
		else if ((int)val2 <= 64)
		{
			if ((int)val2 == 32)
			{
				return AshlandsZoneConfig.Value;
			}
			if ((int)val2 == 64)
			{
				return DeepNorthZoneConfig.Value;
			}
		}
		else
		{
			if ((int)val2 == 256)
			{
				return OceanZoneConfig.Value;
			}
			if ((int)val2 == 512)
			{
				return MistlandsZoneConfig.Value;
			}
		}
		return true;
	}

	private void Update()
	{
		if (!statusEffectsInitialized && (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_StatusEffects != null && ObjectDB.instance.m_StatusEffects.Count > 0)
		{
			InitializeStatusEffectList();
			statusEffectsInitialized = true;
		}
		if (!IsCurrentZoneEnabled())
		{
			if (!currentlyMissingBuffs.Any())
			{
				return;
			}
			currentlyMissingBuffs.Clear();
			GameObject val = GameObject.Find("TempLoopingAlertSound");
			if ((Object)(object)val != (Object)null)
			{
				AudioSource component = val.GetComponent<AudioSource>();
				if ((Object)(object)component != (Object)null && component.isPlaying)
				{
					component.Stop();
				}
			}
			return;
		}
		if (!hasStartedChecking)
		{
			playerLoadDelay -= Time.deltaTime;
			if (playerLoadDelay <= 0f)
			{
				hasStartedChecking = true;
			}
			return;
		}
		CheckActiveBuffs();
		if (EnableAudioAlertsConfig.Value && currentlyMissingBuffs.Count == 0)
		{
			GameObject val2 = GameObject.Find("TempLoopingAlertSound");
			if ((Object)(object)val2 != (Object)null)
			{
				AudioSource component2 = val2.GetComponent<AudioSource>();
				if ((Object)(object)component2 != (Object)null && component2.isPlaying && component2.loop)
				{
					component2.Stop();
					Log.LogInfo((object)"All tracked buffs are active. Stopped looping alert sound.");
				}
			}
		}
		if (EnableAudioAlertsConfig.Value)
		{
			return;
		}
		GameObject val3 = GameObject.Find("TempLoopingAlertSound");
		if ((Object)(object)val3 != (Object)null)
		{
			AudioSource component3 = val3.GetComponent<AudioSource>();
			if ((Object)(object)component3 != (Object)null && component3.isPlaying)
			{
				component3.Stop();
				Log.LogInfo((object)"Audio alerts globally disabled. Stopped active alert sound.");
			}
		}
	}

	private void CheckActiveBuffs()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).GetSEMan() == null)
		{
			if (currentlyMissingBuffs.Any())
			{
				currentlyMissingBuffs.Clear();
			}
			return;
		}
		SEMan sEMan = ((Character)localPlayer).GetSEMan();
		List<StatusEffect> list = new List<StatusEffect>();
		foreach (string trackedBuffName in TrackedBuffNames)
		{
			if (!sEMan.HaveStatusEffect(StringExtensionMethods.GetStableHashCode(trackedBuffName)))
			{
				StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode(trackedBuffName));
				if ((Object)(object)statusEffect != (Object)null && (Object)(object)statusEffect.m_icon != (Object)null)
				{
					list.Add(statusEffect);
				}
				else if ((Object)(object)statusEffect == (Object)null)
				{
					Log.LogWarning((object)("Could not find StatusEffect for tracked buff name: " + trackedBuffName));
				}
			}
		}
		if (EnableAudioAlertsConfig.Value)
		{
			List<string> list2 = list.Select((StatusEffect se) => ((Object)se).name).ToList();
			List<string> list3 = currentlyMissingBuffs.Select((StatusEffect se) => ((Object)se).name).ToList();
			foreach (StatusEffect item in list)
			{
				if (!list3.Contains(((Object)item).name))
				{
					PlayMissingBuffSoundLogic(item.m_name, ((Component)localPlayer).transform);
				}
			}
		}
		currentlyMissingBuffs = list;
	}

	private void PlayMissingBuffSoundLogic(string buffName, Transform anchor)
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)missingBuffAudioClip == (Object)null)
		{
			return;
		}
		if ((Object)(object)AudioMan.instance != (Object)null && (Object)(object)anchor != (Object)null)
		{
			GameObject val = GameObject.Find("TempLoopingAlertSound");
			AudioSource val2;
			if ((Object)(object)val == (Object)null)
			{
				val = new GameObject("TempLoopingAlertSound");
				val2 = val.AddComponent<AudioSource>();
				val2.spatialBlend = 0f;
			}
			else
			{
				val2 = val.GetComponent<AudioSource>();
				if ((Object)(object)val2 != (Object)null)
				{
					val2.spatialBlend = 0f;
				}
			}
			val.transform.position = anchor.position;
			if ((Object)(object)missingBuffAudioClip != (Object)null)
			{
				if (!val2.isPlaying || (Object)(object)val2.clip != (Object)(object)missingBuffAudioClip)
				{
					val2.clip = missingBuffAudioClip;
					val2.loop = LoopAudioAlertConfig.Value;
					if (SelectedAudioClipNameConfig.Value == "scream" && ((Object)missingBuffAudioClip).name.ToLowerInvariant().Contains("scream"))
					{
						val2.time = 0.5f;
						Log.LogInfo((object)"Starting 'scream' clip from 0.5s offset.");
					}
					else
					{
						val2.time = 0f;
					}
					val2.Play();
					Log.LogInfo((object)("Started " + (LoopAudioAlertConfig.Value ? "looping" : "playing one-shot") + " '" + SelectedAudioClipNameConfig.Value + "' sound for missing buff: " + buffName));
				}
			}
			else
			{
				Log.LogWarning((object)("missingBuffAudioClip became null unexpectedly before playing for buff: " + buffName + ". This should not happen."));
			}
			return;
		}
		if ((Object)(object)AudioMan.instance == (Object)null)
		{
			Log.LogWarning((object)("AudioMan.instance is null. Cannot play missing buff sound for " + buffName + "."));
		}
		if ((Object)(object)anchor == (Object)null)
		{
			Log.LogWarning((object)("Player transform is null. Cannot play missing buff sound for " + buffName + " at player location."));
		}
		GameObject val3 = GameObject.Find("TempLoopingAlertSound");
		if ((Object)(object)val3 != (Object)null)
		{
			AudioSource component = val3.GetComponent<AudioSource>();
			if ((Object)(object)component != (Object)null && component.isPlaying && component.loop)
			{
				component.Stop();
				Log.LogInfo((object)"Stopped looping alert sound as conditions are no longer met (AudioMan or anchor is null).");
			}
		}
	}

	private void OnGUI()
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0439: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_0403: Unknown result type (might be due to invalid IL or missing references)
		//IL_0407: Unknown result type (might be due to invalid IL or missing references)
		if (isMenuVisible)
		{
			DrawStatusEffectMenu();
		}
		if (!currentlyMissingBuffs.Any() || isMenuVisible)
		{
			return;
		}
		iconFlashTimer += Time.deltaTime * 2f;
		float num = Mathf.PingPong(iconFlashTimer, 1f);
		Color color = GUI.color;
		GUI.color = new Color(color.r, color.g, color.b, num);
		float value = IconSizeConfig.Value;
		float value2 = IconSpacingConfig.Value;
		float num2 = (float)currentlyMissingBuffs.Count * (value + value2) - value2;
		float num3 = 0f;
		float num4 = 0f;
		switch (IconPositionConfig.Value)
		{
		case "TopLeft":
			num3 = 10f;
			num4 = 10f;
			break;
		case "TopCenter":
			num3 = ((float)Screen.width - num2) / 2f;
			num4 = 10f;
			break;
		case "TopRight":
			num3 = (float)Screen.width - num2 - 10f;
			num4 = 10f;
			break;
		case "MiddleLeft":
			num3 = 10f;
			num4 = ((float)Screen.height - value) / 2f;
			break;
		case "MiddleCenter":
			num3 = ((float)Screen.width - num2) / 2f;
			num4 = ((float)Screen.height - value) / 2f;
			break;
		case "MiddleRight":
			num3 = (float)Screen.width - num2 - 10f;
			num4 = ((float)Screen.height - value) / 2f;
			break;
		case "BottomLeft":
			num3 = 10f;
			num4 = (float)Screen.height - value - 10f;
			break;
		case "BottomCenter":
			num3 = ((float)Screen.width - num2) / 2f;
			num4 = (float)Screen.height - value - 10f;
			break;
		case "BottomRight":
			num3 = (float)Screen.width - num2 - 10f;
			num4 = (float)Screen.height - value - 10f;
			break;
		}
		Rect val = default(Rect);
		Rect val2 = default(Rect);
		foreach (StatusEffect currentlyMissingBuff in currentlyMissingBuffs)
		{
			Sprite icon = currentlyMissingBuff.m_icon;
			if ((Object)(object)icon != (Object)null && (Object)(object)icon.texture != (Object)null)
			{
				Texture2D texture = icon.texture;
				Rect textureRect = icon.textureRect;
				((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height);
				((Rect)(ref val2))..ctor(num3, num4, value, value);
				GUI.DrawTextureWithTexCoords(val2, (Texture)(object)texture, val, true);
				num3 += value + value2;
			}
		}
		GUI.color = color;
	}

	private void DrawStatusEffectMenu()
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		float num = 400f;
		float num2 = 600f;
		float num3 = ((float)Screen.width - num) / 2f + (float)Screen.width / 3f;
		float num4 = ((float)Screen.height - num2) / 2f;
		GUI.Window(12345, new Rect(num3, num4, num, num2), new WindowFunction(DrawMenuContents), "Status Effect Selection");
	}

	private void DrawMenuContents(int windowID)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Expected O, but got Unknown
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		GUI.DragWindow(new Rect(0f, 0f, 400f, 20f));
		float num = 10f;
		float num2 = num;
		float num3 = 40f;
		float num4 = 10f;
		int num5 = 4;
		GUI.SetNextControlName("SearchBox");
		searchText = GUI.TextField(new Rect(num, num2, 380f, 25f), searchText);
		num2 += 35f;
		menuScrollPosition = GUI.BeginScrollView(new Rect(num, num2, 380f, 500f), menuScrollPosition, new Rect(0f, 0f, 360f, (float)Mathf.CeilToInt((float)allStatusEffects.Count / (float)num5) * (num3 + num4 + 20f)));
		List<StatusEffect> list = allStatusEffects.Where((StatusEffect se) => string.IsNullOrEmpty(searchText) || se.m_name.ToLower().Contains(searchText.ToLower())).ToList();
		float num6 = 0f;
		Rect val = default(Rect);
		Rect val2 = default(Rect);
		foreach (StatusEffect item in list)
		{
			if (num6 + num3 > 360f)
			{
				num6 = 0f;
				num2 += num3 + num4 + 20f;
			}
			((Rect)(ref val))..ctor(num6, num2, num3, num3 + 20f);
			GUI.Box(val, "");
			if ((Object)(object)item.m_icon != (Object)null)
			{
				Sprite icon = item.m_icon;
				Texture2D texture = icon.texture;
				Rect textureRect = icon.textureRect;
				((Rect)(ref val2))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height);
				GUI.DrawTextureWithTexCoords(new Rect(num6, num2, num3, num3), (Texture)(object)texture, val2, true);
			}
			GUI.Label(new Rect(num6, num2 + num3, num3, 20f), item.m_name, new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)1,
				fontSize = 10
			});
			bool flag = statusEffectSelectionState[((Object)item).name];
			bool flag2 = GUI.Toggle(new Rect(num6, num2, num3, num3), flag, "");
			if (flag2 != flag)
			{
				statusEffectSelectionState[((Object)item).name] = flag2;
			}
			num6 += num3 + num4;
		}
		GUI.EndScrollView();
		float num7 = 180f;
		float num8 = 20f;
		float num9 = 540f;
		if (GUI.Button(new Rect(num, num9, num7, 30f), "Apply Changes"))
		{
			UpdateTrackedBuffsList();
			isMenuVisible = false;
		}
		if (GUI.Button(new Rect(num + num7 + num8, num9, num7, 30f), "Cancel"))
		{
			statusEffectSelectionState = new Dictionary<string, bool>(initialSelectionState);
			isMenuVisible = false;
		}
	}

	private void UpdateTrackedBuffsList()
	{
		TrackedBuffNames = (from kvp in statusEffectSelectionState
			where kvp.Value
			select kvp.Key).ToList();
		TrackedBuffsConfig.Value = string.Join(",", TrackedBuffNames);
		Log.LogInfo((object)("Updated tracked buffs: " + TrackedBuffsConfig.Value));
	}

	private void InitializeStatusEffectList()
	{
		allStatusEffects.Clear();
		statusEffectSelectionState.Clear();
		initialSelectionState.Clear();
		if ((Object)(object)ObjectDB.instance == (Object)null)
		{
			Log.LogWarning((object)"ObjectDB.instance is null. Cannot initialize status effects list.");
			return;
		}
		Log.LogInfo((object)$"Found {ObjectDB.instance.m_StatusEffects.Count} total status effects in ObjectDB");
		foreach (StatusEffect statusEffect in ObjectDB.instance.m_StatusEffects)
		{
			if ((Object)(object)statusEffect != (Object)null && (Object)(object)statusEffect.m_icon != (Object)null)
			{
				allStatusEffects.Add(statusEffect);
				bool value = TrackedBuffNames.Contains(((Object)statusEffect).name);
				statusEffectSelectionState[((Object)statusEffect).name] = value;
				initialSelectionState[((Object)statusEffect).name] = value;
				Log.LogDebug((object)("Added status effect: " + ((Object)statusEffect).name));
			}
		}
		allStatusEffects = allStatusEffects.OrderBy((StatusEffect se) => se.m_name).ToList();
		Log.LogInfo((object)$"Initialized {allStatusEffects.Count} status effects with icons");
	}

	private static void DrawTrackedBuffsConfig(ConfigEntryBase configEntry)
	{
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Label("Currently Tracked Buffs:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
		foreach (string trackedBuffName in TrackedBuffNames)
		{
			GUILayout.Label("• " + trackedBuffName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
		}
		GUILayout.Space(10f);
		if (GUILayout.Button("Open Buff Selection Menu", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
		{
			EthicalAurasPlugin ethicalAurasPlugin = Object.FindObjectOfType<EthicalAurasPlugin>();
			if ((Object)(object)ethicalAurasPlugin != (Object)null)
			{
				ethicalAurasPlugin.isMenuVisible = true;
			}
		}
		GUILayout.EndVertical();
	}

	private void OnDestroy()
	{
		Log.LogInfo((object)"Plugin com.talitore.ethical-auras (ETHICAL Auras) is unloading.");
	}
}
public static class ZSFXHelper
{
	public static void PlayOneShotZSFX(AudioClip clip, Vector3 position, float volume = 1f, float pitch = 1f)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)clip == (Object)null))
		{
			GameObject val = new GameObject("TempZSFX_" + ((Object)clip).name);
			val.transform.position = position;
			AudioSource val2 = val.AddComponent<AudioSource>();
			ZSFX val3 = val.AddComponent<ZSFX>();
			val2.spatialBlend = 1f;
			val2.minDistance = 1f;
			val2.maxDistance = 30f;
			val2.rolloffMode = (AudioRolloffMode)0;
			val2.loop = false;
			val2.playOnAwake = false;
			val3.m_audioClips = (AudioClip[])(object)new AudioClip[1] { clip };
			val3.m_minVol = (val3.m_maxVol = volume);
			val3.m_minPitch = (val3.m_maxPitch = pitch);
			val3.m_playOnAwake = false;
			val3.Awake();
			val3.Play();
			Object.Destroy((Object)(object)val, clip.length + 0.5f);
		}
	}
}