Decompiled source of GlitnirSounds v0.1.4

GlitnirMusicZones.dll

Decompiled 3 days 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.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("GlitnirMusicZones")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GlitnirMusicZones")]
[assembly: AssemblyTitle("GlitnirMusicZones")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GlitnirMusicZones
{
	internal static class DefaultConfig
	{
		public const string YAML = "# ╔══════════════════════════════════════════════════════════════════╗\r\n# ║           GLITNIR MUSIC ZONES — music_config.yaml               ║\r\n# ╚══════════════════════════════════════════════════════════════════╝\r\n# Use URLs diretas de MP3 (sem expiração). Recomendado: GitHub Releases\r\n# ou cdn.pixabay.com. Evite links do Discord (expiram em horas).\r\n#\r\n# Após salvar o arquivo, a config recarrega automaticamente no jogo.\r\n\r\n# ─── MENU PRINCIPAL ────────────────────────────────────────────────\r\nmenu:\r\n  enabled: false\r\n  volume: 0.0500\r\n  url: \"https://cdn.pixabay.com/download/audio/2025/07/24/audio_9d4a9c72f8.mp3?filename=wesleysert-glitnir-valhhala-1-379314.mp3\"\r\n\r\n# ─── BIOMAS ────────────────────────────────────────────────────────\r\n# Biomas disponíveis: Meadows, BlackForest, Swamp, Mountain, Plains,\r\n#                     Mistlands, AshLands, DeepNorth, Ocean\r\n# mode:   custom  = toca a url configurada (silencia vanilla)\r\n#         vanilla = deixa a música do jogo tocar normalmente\r\n#         mute    = silêncio total (nem mod nem vanilla)\r\nbiomes:\r\n  enabled: true\r\n  volume: 0.0500\r\n  tracks:\r\n    Meadows:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_d304cbd8a2.mp3?filename=morgnar-neve-540465.mp3\"\r\n    BlackForest:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_62456d9582.mp3?filename=morgnar-mire-of-ancients-538620.mp3\"\r\n    Swamp:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_47a47ff6c2.mp3?filename=morgnar-pantano-540510.mp3\"\r\n    Mountain:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_e6186facfc.mp3?filename=morgnar-mist-over-runestones-540508.mp3\"\r\n    Plains:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_0f67273299.mp3?filename=morgnar-planicie-540517.mp3\"\r\n    Mistlands:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_e6186facfc.mp3?filename=morgnar-mist-over-runestones-540508.mp3\"\r\n    AshLands:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_d97092169a.mp3?filename=morgnar-ashlands-540519.mp3\"\r\n    DeepNorth:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_2fe0daf552.mp3?filename=morgnar-deepnorth-540531.mp3\"\r\n    Ocean:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_2fe0daf552.mp3?filename=morgnar-deepnorth-540531.mp3\"\r\n\r\n# ─── LOCATIONS (Pontos de interesse do ZoneSystem) ─────────────────\r\n# location:      nome exato da Location (ex: StartTemple, Crypt2)\r\n# radius:        raio em unidades (0 = usa o radius global abaixo)\r\n# dungeon_only:  true = só toca dentro da dungeon (faixa Y)\r\n# dungeon_y_min/max: faixa Y da dungeon (-1 = usa o global)\r\nlocations:\r\n  enabled: false\r\n  volume: 0.65\r\n  radius: 90.0\r\n  dungeon_y_min: 4500.0\r\n  dungeon_y_max: 5500.0\r\n  tracks:\r\n    - enabled: false\r\n      location: StartTemple\r\n      radius: 60.0\r\n      dungeon_only: false\r\n      dungeon_y_min: -1\r\n      dungeon_y_max: -1\r\n      url: \"\"\r\n\r\n    - enabled: false\r\n      location: Vendor_BlackForest\r\n      radius: 0.0\r\n      dungeon_only: false\r\n      dungeon_y_min: 4500.0\r\n      dungeon_y_max: -1\r\n      url: \"\"\r\n\r\n    - enabled: false\r\n      location: Crypt2\r\n      radius: 90.0\r\n      dungeon_only: false\r\n      dungeon_y_min: 4500.0\r\n      dungeon_y_max: 5500.0\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      location: Crypt3\r\n      radius: 90.0\r\n      dungeon_only: true\r\n      dungeon_y_min: 4500\r\n      dungeon_y_max: 5500\r\n      url: \"\"\r\n\r\n    - enabled: false\r\n      location: MountainCave01\r\n      radius: 90.0\r\n      dungeon_only: false\r\n      dungeon_y_min: 4500\r\n      dungeon_y_max: 5500\r\n      url: \"\"\r\n\r\n# ─── TERRITORIES (Zonas por coordenada XZ) ─────────────────────────\r\n# Use para vilas ou regiões sem Location no ZoneSystem.\r\n# x/z:    coordenadas do centro no mapa do Valheim\r\n# mode:   custom  = toca a url configurada (silencia vanilla)\r\n#         vanilla = deixa a música do jogo tocar normalmente\r\n#         mute    = silêncio total (nem mod nem vanilla)\r\nterritories:\r\n  enabled: true\r\n  tracks:\r\n    - enabled: true\r\n      name: BosquePrmadico\r\n      x: 25186.0\r\n      z: 4411.0\r\n      radius: 700.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_d304cbd8a2.mp3?filename=morgnar-neve-540465.mp3\"\r\n\r\n    - enabled: true\r\n      name: Vila Prado\r\n      x: -245.0\r\n      z: 336.0\r\n      radius: 200.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_e0d6b4179f.mp3?filename=morgnar-harbor-hearth-village-1-538622.mp3\"\r\n\r\n    - enabled: true\r\n      name: Skjalfhame\r\n      x: -37714.0\r\n      z: 9799.0\r\n      radius: 100.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_6ab79d7f51.mp3?filename=morgnar-vila-540514.mp3\"\r\n\r\n    - enabled: true\r\n      name: Hrotghar\r\n      x: 3337.0\r\n      z: -6096.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_6ab79d7f51.mp3?filename=morgnar-vila-540514.mp3\"\r\n\r\n    - enabled: true\r\n      name: Winterhold\r\n      x: 17938.0\r\n      z: 14584.0\r\n      radius: 70.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_6ab79d7f51.mp3?filename=morgnar-vila-540514.mp3\"\r\n\r\n    - enabled: true\r\n      name: Vila da Floresta Negra\r\n      x: -1997.0\r\n      z: -5333.0\r\n      radius: 50.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_6ab79d7f51.mp3?filename=morgnar-vila-540514.mp3\"\r\n\r\n    - enabled: true\r\n      name: Vila do Pantano\r\n      x: 4917.0\r\n      z: -2571.0\r\n      radius: 200.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_e0d6b4179f.mp3?filename=morgnar-harbor-hearth-village-1-538622.mp3\"\r\n\r\n    - enabled: true\r\n      name: Vila da Montanha\r\n      x: 6508.0\r\n      z: 3735.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_e0d6b4179f.mp3?filename=morgnar-harbor-hearth-village-1-538622.mp3\"\r\n\r\n    - enabled: true\r\n      name: Varghard - Reino dos Humanos\r\n      x: 13695.0\r\n      z: 19496.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Eryndel - Reino dos Elfos\r\n      x: 21474.0\r\n      z: 12080.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Drakthar - Reino dos Orcs\r\n      x: -7346.0\r\n      z: 20523.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Coliseu\r\n      x: 1745.0\r\n      z: 21713.0\r\n      radius: 500.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Brumello - Reino dos Halflings\r\n      x: -15671.0\r\n      z: 15840.0\r\n      radius: 500.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Cabaré do Sjar\r\n      x: 14691.0\r\n      z: 17973.0\r\n      radius: 50.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Forte Falkreath\r\n      x: -22106.0\r\n      z: 9622.0\r\n      radius: 100.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_c2d6bad590.mp3?filename=morgnar-falkreath-citadel-541114.mp3\"\r\n\r\n    - enabled: false\r\n      name: Parkour\r\n      x: 6508.0\r\n      z: 3735.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_4d4bef9969.mp3?filename=morgnar-mead-hall-waltz-541115.mp3\"\r\n\r\n    - enabled: true\r\n      name: Jorrvaskr\r\n      x: 11411.0\r\n      z: 19191.0\r\n      radius: 70.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_a9a5df53e2.mp3?filename=morgnar-harbor-hearth-village-538619.mp3\"\r\n\r\n    - enabled: true\r\n      name: Calindel\r\n      x: 8590.0\r\n      z: 20394.0\r\n      radius: 70.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_a9a5df53e2.mp3?filename=morgnar-harbor-hearth-village-538619.mp3\"\r\n\r\n# ─── BOSSES ────────────────────────────────────────────────────────\r\n# Prefab name do boss sem '(Clone)'. Toca enquanto o boss estiver vivo no raio.\r\n# Bosses vanilla: Eikthyr, gd_king, Bonemass, Dragon, GoblinKing, SeekerQueen, Fader\r\nbosses:\r\n  enabled: true\r\n  volume: 0.0500\r\n  radius: 120.0\r\n  tracks:\r\n    Eikthyr:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    gd_king:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    Bonemass:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    Dragon:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    GoblinKing:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    SeekerQueen:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    Fader:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    brutoGLIT:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n\r\n# ─── CRIATURAS ─────────────────────────────────────────────────────\r\n# Toca enquanto houver ao menos uma criatura viva no raio.\r\ncreatures:\r\n  enabled: true\r\n  volume: 0.0500\r\n  radius: 30.0\r\n  tracks:\r\n    Troll:\r\n      enabled: false\r\n      url: \"\"\r\n    GoblinBrute:\r\n      enabled: false\r\n      url: \"\"\r\n    BlobTar:\r\n      enabled: false\r\n      url: \"\"\r\n    Seeker:\r\n      enabled: false\r\n      url: \"\"\r\n    Leech:\r\n      enabled: false\r\n      url: \"\"\r\n";
	}
	internal static class MusicManPatches
	{
		private static readonly FieldRef<MusicMan, AudioSource> _musicSourceRef = AccessTools.FieldRefAccess<MusicMan, AudioSource>("m_musicSource");

		private static float _lastKnownVolume = 1f;

		private static AudioSource MusicManSource
		{
			get
			{
				if ((Object)(object)MusicMan.instance == (Object)null)
				{
					return null;
				}
				try
				{
					return _musicSourceRef.Invoke(MusicMan.instance);
				}
				catch
				{
					return null;
				}
			}
		}

		public static float RealMusicVolume => _lastKnownVolume;

		public static AudioMixerGroup GetMusicGroup()
		{
			AudioSource musicManSource = MusicManSource;
			return (musicManSource != null) ? musicManSource.outputAudioMixerGroup : null;
		}

		internal static void SetInitialVolume(float v)
		{
			if (v > 0f)
			{
				_lastKnownVolume = v;
			}
		}

		private static void PrefixUpdate()
		{
			float masterMusicVolume = MusicMan.m_masterMusicVolume;
			if (masterMusicVolume > 0f)
			{
				_lastKnownVolume = masterMusicVolume;
			}
		}

		private static void PostfixUpdate()
		{
			if (Plugin.VanillaMuted)
			{
				MusicMan.m_masterMusicVolume = 0f;
				AudioSource musicManSource = MusicManSource;
				if ((Object)(object)musicManSource != (Object)null && musicManSource.isPlaying)
				{
					musicManSource.Stop();
				}
			}
		}

		private static bool PrefixStartMusic()
		{
			if (!Plugin.VanillaMuted)
			{
				return true;
			}
			AudioSource musicManSource = MusicManSource;
			if (musicManSource != null)
			{
				musicManSource.Stop();
			}
			return false;
		}

		private static bool PrefixQueue()
		{
			return !Plugin.VanillaMuted;
		}

		public static void ApplyAll(Harmony harmony)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			Type typeFromHandle = typeof(MusicManPatches);
			HarmonyMethod val = new HarmonyMethod(typeFromHandle.GetMethod("PrefixStartMusic", BindingFlags.Static | BindingFlags.NonPublic));
			HarmonyMethod val2 = new HarmonyMethod(typeFromHandle.GetMethod("PrefixQueue", BindingFlags.Static | BindingFlags.NonPublic));
			HarmonyMethod val3 = new HarmonyMethod(typeFromHandle.GetMethod("PrefixUpdate", BindingFlags.Static | BindingFlags.NonPublic));
			HarmonyMethod val4 = new HarmonyMethod(typeFromHandle.GetMethod("PostfixUpdate", BindingFlags.Static | BindingFlags.NonPublic));
			MethodInfo methodInfo = null;
			MethodInfo[] methods = typeof(MusicMan).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo2 in methods)
			{
				if (methodInfo2.Name == "StartMusic")
				{
					harmony.Patch((MethodBase)methodInfo2, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else if (methodInfo2.Name == "Queue")
				{
					harmony.Patch((MethodBase)methodInfo2, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else if (methodInfo2.Name == "Update")
				{
					methodInfo = methodInfo2;
				}
			}
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, val3, val4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}
	}
	public class YamlConfig
	{
		public YamlMenu menu { get; set; } = new YamlMenu();

		public YamlBiomes biomes { get; set; } = new YamlBiomes();

		public YamlLocations locations { get; set; } = new YamlLocations();

		public YamlTerritories territories { get; set; } = new YamlTerritories();

		public YamlBosses bosses { get; set; } = new YamlBosses();

		public YamlCreatures creatures { get; set; } = new YamlCreatures();
	}
	public class YamlMenu
	{
		public bool enabled { get; set; } = true;

		public float volume { get; set; } = 0.3f;

		public string url { get; set; } = "";
	}
	public class YamlBiomes
	{
		public bool enabled { get; set; } = true;

		public float volume { get; set; } = 0.6f;

		public Dictionary<string, YamlTrack> tracks { get; set; } = new Dictionary<string, YamlTrack>();
	}
	public class YamlLocations
	{
		public bool enabled { get; set; } = true;

		public float volume { get; set; } = 0.65f;

		public float radius { get; set; } = 90f;

		public float dungeon_y_min { get; set; } = 4500f;

		public float dungeon_y_max { get; set; } = 5500f;

		public List<YamlLocationTrack> tracks { get; set; } = new List<YamlLocationTrack>();
	}
	public class YamlTerritories
	{
		public bool enabled { get; set; } = true;

		public List<YamlTerritoryTrack> tracks { get; set; } = new List<YamlTerritoryTrack>();
	}
	public class YamlBosses
	{
		public bool enabled { get; set; } = true;

		public float volume { get; set; } = 0.7f;

		public float radius { get; set; } = 120f;

		public Dictionary<string, YamlTrack> tracks { get; set; } = new Dictionary<string, YamlTrack>();
	}
	public class YamlCreatures
	{
		public bool enabled { get; set; } = true;

		public float volume { get; set; } = 0.55f;

		public float radius { get; set; } = 30f;

		public Dictionary<string, YamlTrack> tracks { get; set; } = new Dictionary<string, YamlTrack>();
	}
	public class YamlTrack
	{
		public bool enabled { get; set; } = true;

		public string mode { get; set; } = "custom";

		public string url { get; set; } = "";
	}
	public class YamlLocationTrack
	{
		public bool enabled { get; set; } = true;

		public string location { get; set; } = "";

		public float radius { get; set; } = 0f;

		public bool dungeon_only { get; set; } = false;

		public float dungeon_y_min { get; set; } = -1f;

		public float dungeon_y_max { get; set; } = -1f;

		public string url { get; set; } = "";
	}
	public class YamlTerritoryTrack
	{
		public bool enabled { get; set; } = true;

		public string name { get; set; } = "";

		public float x { get; set; } = 0f;

		public float z { get; set; } = 0f;

		public float radius { get; set; } = 60f;

		public float volume { get; set; } = 0.65f;

		public string mode { get; set; } = "custom";

		public string url { get; set; } = "";
	}
	public enum TerritoryMode
	{
		Custom,
		Vanilla,
		Mute
	}
	[BepInPlugin("glitnir.musiczones", "Glitnir Music Zones", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private enum MusicState
		{
			None,
			Menu,
			Biome,
			Location,
			Territory,
			Boss,
			Creature
		}

		internal class LocationEntry
		{
			public string location;

			public float radius;

			public float dungeonYMin;

			public float dungeonYMax;

			public bool dungeonOnly;

			public bool enabled;

			public string url;

			public bool IsActive => enabled && !string.IsNullOrWhiteSpace(url) && !string.IsNullOrWhiteSpace(location);
		}

		internal class TerritoryEntry
		{
			public string name;

			public float x;

			public float z;

			public float radius;

			public float volume;

			public bool enabled;

			public TerritoryMode mode;

			public string url;

			public bool IsActive => enabled && (mode != TerritoryMode.Custom || !string.IsNullOrWhiteSpace(url));
		}

		internal class MusicEntry
		{
			public bool enabled;

			public string url;

			public TerritoryMode mode;

			public bool IsActive => enabled && (mode != TerritoryMode.Custom || !string.IsNullOrWhiteSpace(url));

			public MusicEntry(bool enabled, string url, TerritoryMode mode = TerritoryMode.Custom)
			{
				this.enabled = enabled;
				this.url = url ?? "";
				this.mode = mode;
			}
		}

		private static GameObject musicObject;

		private static AudioSource audioSource;

		private string currentClipUrl = "";

		private readonly Dictionary<string, AudioClip> clipCache = new Dictionary<string, AudioClip>();

		private readonly HashSet<string> preloadingUrls = new HashSet<string>();

		private const int MaxCachedClips = 12;

		private readonly Queue<string> _cacheInsertionOrder = new Queue<string>();

		private Coroutine fadeCoroutine = null;

		private bool isFading = false;

		private float fadeDuration = 1f;

		private FileSystemWatcher configWatcher;

		private bool reloadPending = false;

		private float _reloadCooldown = 0f;

		private DateTime _watcherEventTime = DateTime.MinValue;

		private const float WatcherSettleDelay = 0.3f;

		private Harmony harmony;

		private MusicEntry menuEntry;

		private float menuVolume = 0.3f;

		private bool menuEnabled = true;

		private bool biomesEnabled = true;

		private float biomeVolume = 0.6f;

		private Dictionary<Biome, MusicEntry> biomeMap = new Dictionary<Biome, MusicEntry>();

		private bool locEnabled = true;

		private float locVolume = 0.65f;

		private float locRadius = 90f;

		private float locDungeonYMin = 4500f;

		private float locDungeonYMax = 5500f;

		private List<LocationEntry> locList = new List<LocationEntry>();

		private bool terrEnabled = true;

		private List<TerritoryEntry> terrList = new List<TerritoryEntry>();

		private bool bossEnabled = true;

		private float bossVolume = 0.7f;

		private float bossRadius = 120f;

		private Dictionary<string, MusicEntry> bossMap = new Dictionary<string, MusicEntry>();

		private bool creatEnabled = true;

		private float creatVolume = 0.55f;

		private float creatRadius = 30f;

		private Dictionary<string, MusicEntry> creatMap = new Dictionary<string, MusicEntry>();

		private MusicState currentState = MusicState.None;

		private string currentUrl = "";

		private float currentCfgVolume = 1f;

		private AudioClip menuClip = null;

		private bool menuClipReady = false;

		private bool worldLoaded = false;

		private float checkInterval = 2f;

		private float checkTimer = 0f;

		private Vector3 _lastCheckPos = Vector3.zero;

		private readonly Dictionary<string, Vector3> _locPosCache = new Dictionary<string, Vector3>();

		private float _locCacheTimer = 0f;

		private const float PreloadAheadMultiplier = 1.5f;

		private readonly List<Character> _charBuffer = new List<Character>();

		public static bool VanillaMuted { get; private set; }

		private string ConfigPath => Path.Combine(Paths.ConfigPath, "glitnir.musiczones", "music_config.yaml");

		private float FinalVolume(float cfgVolume)
		{
			return cfgVolume * MusicManPatches.RealMusicVolume;
		}

		private void MuteVanilla()
		{
			if (!VanillaMuted)
			{
				VanillaMuted = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Vanilla silenciada.");
			}
		}

		private void UnmuteVanilla()
		{
			if (VanillaMuted)
			{
				VanillaMuted = false;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Vanilla restaurada.");
			}
		}

		private void Awake()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir Music Zones] v1.0.0 iniciando...");
			harmony = new Harmony("glitnir.musiczones");
			try
			{
				MusicManPatches.ApplyAll(harmony);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Patches Harmony aplicados com sucesso.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[Glitnir] Falha ao aplicar patches: " + ex.Message));
			}
			EnsureDefaultConfig();
			LoadConfig();
			CreateMusicPlayer();
			StartConfigWatcher();
			if ((Object)(object)MusicMan.instance != (Object)null && MusicMan.m_masterMusicVolume > 0f)
			{
				MusicManPatches.SetInitialVolume(MusicMan.m_masterMusicVolume);
			}
			((MonoBehaviour)this).StartCoroutine(PreloadMenuMusic());
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			configWatcher?.Dispose();
			UnmuteVanilla();
			ClearCache();
		}

		private void Update()
		{
			if (_reloadCooldown > 0f)
			{
				_reloadCooldown -= Time.deltaTime;
			}
			if (reloadPending && _reloadCooldown <= 0f && (DateTime.UtcNow - _watcherEventTime).TotalSeconds >= 0.30000001192092896)
			{
				reloadPending = false;
				_reloadCooldown = 1f;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Config alterada — recarregando...");
				LoadConfig();
				currentUrl = "";
				currentState = MusicState.None;
			}
			if ((Object)(object)audioSource != (Object)null && audioSource.isPlaying && !isFading)
			{
				audioSource.volume = FinalVolume(currentCfgVolume);
			}
			bool flag = (Object)(object)ZNet.instance != (Object)null;
			if (flag && !worldLoaded && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				worldLoaded = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Mundo carregado — parando música do menu.");
				StopOurMusic();
				menuClip = null;
				menuClipReady = false;
			}
			if (!flag && worldLoaded)
			{
				worldLoaded = false;
				UnmuteVanilla();
				ClearCache();
				_locPosCache.Clear();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Voltou ao menu.");
				((MonoBehaviour)this).StartCoroutine(PreloadMenuMusic());
			}
			if (!flag)
			{
				if (!menuEnabled || menuEntry == null || !menuEntry.IsActive)
				{
					if (VanillaMuted)
					{
						UnmuteVanilla();
					}
				}
				else if (menuClipReady && currentState != MusicState.Menu)
				{
					PlayCachedClip(menuClip, FinalVolume(menuVolume), MusicState.Menu, menuEntry.url, menuVolume);
				}
			}
			else if (worldLoaded)
			{
				checkTimer -= Time.deltaTime;
				if (!(checkTimer > 0f))
				{
					checkTimer = checkInterval;
					UpdateInGameMusic();
				}
			}
		}

		private void UpdateInGameMusic()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			float num = Vector3.Distance(position, _lastCheckPos);
			checkInterval = ((num < 3f) ? 4f : 2f);
			_lastCheckPos = position;
			_locCacheTimer += checkInterval;
			if (_locCacheTimer > 30f)
			{
				_locPosCache.Clear();
				_locCacheTimer = 0f;
			}
			TryPreloadNearby(position);
			if (bossEnabled || creatEnabled)
			{
				string text = null;
				string text2 = null;
				float num2 = Math.Max(bossRadius, creatRadius);
				_charBuffer.Clear();
				foreach (Character allCharacter in Character.GetAllCharacters())
				{
					if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsDead())
					{
						if (Vector3.Distance(position, ((Component)allCharacter).transform.position) <= num2)
						{
							_charBuffer.Add(allCharacter);
						}
						if (_charBuffer.Count >= 64)
						{
							break;
						}
					}
				}
				foreach (Character item in _charBuffer)
				{
					float num3 = Vector3.Distance(position, ((Component)item).transform.position);
					string key = ((Object)item).name.Replace("(Clone)", "").Trim();
					if (bossEnabled && text == null && num3 <= bossRadius && bossMap.TryGetValue(key, out var value) && value.IsActive)
					{
						text = value.url;
					}
					if (creatEnabled && text2 == null && num3 <= creatRadius && creatMap.TryGetValue(key, out var value2) && value2.IsActive)
					{
						text2 = value2.url;
					}
					if (text != null && text2 != null)
					{
						break;
					}
				}
				if (text != null)
				{
					TryPreload(text);
					SwitchMusic(text, bossVolume, MusicState.Boss);
					return;
				}
				if (text2 != null)
				{
					TryPreload(text2);
					SwitchMusic(text2, creatVolume, MusicState.Creature);
					return;
				}
			}
			if (locEnabled)
			{
				string locationMusic = GetLocationMusic(position);
				if (!string.IsNullOrEmpty(locationMusic))
				{
					TryPreload(locationMusic);
					SwitchMusic(locationMusic, locVolume, MusicState.Location);
					return;
				}
			}
			if (terrEnabled && GetTerritoryMatch(position, out var url, out var volume, out var mode))
			{
				switch (mode)
				{
				case TerritoryMode.Custom:
					TryPreload(url);
					SwitchMusic(url, volume, MusicState.Territory);
					return;
				case TerritoryMode.Mute:
					if (currentState != MusicState.Territory || currentUrl != "__mute__")
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] [Territory/Mute] Silenciando tudo.");
						MuteVanilla();
						if (fadeCoroutine != null)
						{
							((MonoBehaviour)this).StopCoroutine(fadeCoroutine);
						}
						isFading = false;
						if (audioSource.isPlaying)
						{
							fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeOutAndStop());
						}
						currentState = MusicState.Territory;
						currentUrl = "__mute__";
					}
					return;
				case TerritoryMode.Vanilla:
					if (currentState != MusicState.Territory || currentUrl != "__vanilla__")
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] [Territory/Vanilla] Restaurando música vanilla.");
						if (fadeCoroutine != null)
						{
							((MonoBehaviour)this).StopCoroutine(fadeCoroutine);
						}
						isFading = false;
						fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeOutAndStop(andUnmute: true));
						currentState = MusicState.Territory;
						currentUrl = "__vanilla__";
					}
					return;
				}
			}
			if (biomesEnabled)
			{
				Biome key2 = (Biome)((WorldGenerator.instance != null) ? ((int)WorldGenerator.instance.GetBiome(position.x, position.z, 0.02f, false)) : 0);
				if (biomeMap.TryGetValue(key2, out var value3) && value3.IsActive)
				{
					switch (value3.mode)
					{
					case TerritoryMode.Custom:
						TryPreload(value3.url);
						SwitchMusic(value3.url, biomeVolume, MusicState.Biome);
						return;
					case TerritoryMode.Mute:
						if (currentState != MusicState.Biome || currentUrl != "__mute__biome__")
						{
							((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] [Biome/Mute] Silenciando tudo.");
							MuteVanilla();
							if (fadeCoroutine != null)
							{
								((MonoBehaviour)this).StopCoroutine(fadeCoroutine);
							}
							isFading = false;
							if (audioSource.isPlaying)
							{
								fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeOutAndStop());
							}
							currentState = MusicState.Biome;
							currentUrl = "__mute__biome__";
						}
						return;
					case TerritoryMode.Vanilla:
						if (currentState != MusicState.Biome || currentUrl != "__vanilla__biome__")
						{
							((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] [Biome/Vanilla] Restaurando música vanilla.");
							if (fadeCoroutine != null)
							{
								((MonoBehaviour)this).StopCoroutine(fadeCoroutine);
							}
							isFading = false;
							fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeOutAndStop(andUnmute: true));
							currentState = MusicState.Biome;
							currentUrl = "__vanilla__biome__";
						}
						return;
					}
				}
			}
			if (currentState != MusicState.None)
			{
				if (fadeCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(fadeCoroutine);
				}
				fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeOutAndStop(andUnmute: true));
				currentState = MusicState.None;
				currentUrl = "";
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Sem zona ativa — vanilla tocando.");
			}
		}

		private void TryPreloadNearby(Vector3 pos)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			foreach (TerritoryEntry terr in terrList)
			{
				if (terr.IsActive && terr.mode == TerritoryMode.Custom)
				{
					float num = Vector3.Distance(new Vector3(pos.x, 0f, pos.z), new Vector3(terr.x, 0f, terr.z));
					if (num <= terr.radius * 1.5f)
					{
						TryPreload(terr.url);
					}
				}
			}
			if (biomesEnabled && WorldGenerator.instance != null)
			{
				float num2 = 64f;
				Vector3[] array = (Vector3[])(object)new Vector3[5]
				{
					pos,
					new Vector3(pos.x + num2, pos.y, pos.z),
					new Vector3(pos.x - num2, pos.y, pos.z),
					new Vector3(pos.x, pos.y, pos.z + num2),
					new Vector3(pos.x, pos.y, pos.z - num2)
				};
				Vector3[] array2 = array;
				foreach (Vector3 val in array2)
				{
					Biome biome = WorldGenerator.instance.GetBiome(val.x, val.z, 0.02f, false);
					if (biomeMap.TryGetValue(biome, out var value) && value.IsActive)
					{
						TryPreload(value.url);
					}
				}
			}
			if (locEnabled)
			{
				foreach (LocationEntry loc in locList)
				{
					if (loc.IsActive && _locPosCache.TryGetValue(loc.location, out var value2))
					{
						float num3 = ((loc.radius > 0f) ? loc.radius : locRadius);
						float num4 = Vector3.Distance(new Vector3(pos.x, 0f, pos.z), new Vector3(value2.x, 0f, value2.z));
						if (num4 <= num3 * 1.5f)
						{
							TryPreload(loc.url);
						}
					}
				}
			}
			if ((!bossEnabled && !creatEnabled) || _charBuffer.Count <= 0)
			{
				return;
			}
			foreach (Character item in _charBuffer)
			{
				if (!((Object)(object)item == (Object)null))
				{
					string key = ((Object)item).name.Replace("(Clone)", "").Trim();
					if (bossEnabled && bossMap.TryGetValue(key, out var value3) && value3.IsActive)
					{
						TryPreload(value3.url);
					}
					if (creatEnabled && creatMap.TryGetValue(key, out var value4) && value4.IsActive)
					{
						TryPreload(value4.url);
					}
				}
			}
		}

		private string GetLocationMusic(Vector3 origin)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return null;
			}
			LocationInstance val = default(LocationInstance);
			foreach (LocationEntry loc in locList)
			{
				if (!loc.IsActive)
				{
					continue;
				}
				float num = ((loc.dungeonYMin >= 0f) ? loc.dungeonYMin : locDungeonYMin);
				float num2 = ((loc.dungeonYMax >= 0f) ? loc.dungeonYMax : locDungeonYMax);
				bool flag = origin.y >= num && origin.y <= num2;
				if (loc.dungeonOnly)
				{
					if (!flag)
					{
						continue;
					}
					return loc.url;
				}
				if (!_locPosCache.TryGetValue(loc.location, out var value))
				{
					if (!ZoneSystem.instance.FindClosestLocation(loc.location, origin, ref val))
					{
						continue;
					}
					value = val.m_position;
					_locPosCache[loc.location] = value;
				}
				float num3 = ((loc.radius > 0f) ? loc.radius : locRadius);
				float num4 = (float)Math.Sqrt(Math.Pow(origin.x - value.x, 2.0) + Math.Pow(origin.z - value.z, 2.0));
				if (!(num4 <= num3))
				{
					continue;
				}
				return loc.url;
			}
			return null;
		}

		private bool GetTerritoryMatch(Vector3 origin, out string url, out float volume, out TerritoryMode mode)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			foreach (TerritoryEntry terr in terrList)
			{
				if (terr.IsActive)
				{
					float num = Vector3.Distance(new Vector3(origin.x, 0f, origin.z), new Vector3(terr.x, 0f, terr.z));
					if (num <= terr.radius)
					{
						url = terr.url;
						volume = terr.volume;
						mode = terr.mode;
						return true;
					}
				}
			}
			url = null;
			volume = 0f;
			mode = TerritoryMode.Custom;
			return false;
		}

		private void TryPreload(string url)
		{
			if (!string.IsNullOrWhiteSpace(url) && !clipCache.ContainsKey(url) && !preloadingUrls.Contains(url))
			{
				((MonoBehaviour)this).StartCoroutine(PreloadClip(url));
			}
		}

		private void AddToCache(string url, AudioClip clip)
		{
			if ((Object)(object)clip == (Object)null)
			{
				clipCache[url] = null;
				return;
			}
			bool flag = !clipCache.ContainsKey(url);
			clipCache[url] = clip;
			if (flag)
			{
				_cacheInsertionOrder.Enqueue(url);
			}
			int num = 0;
			int count = _cacheInsertionOrder.Count;
			while (_cacheInsertionOrder.Count > 12 && num < count)
			{
				num++;
				string text = _cacheInsertionOrder.Peek();
				if (text == currentClipUrl)
				{
					break;
				}
				_cacheInsertionOrder.Dequeue();
				if (clipCache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Glitnir] Cache LRU: liberando '{text.Split(new char[1] { '/' }).Last()}' ({clipCache.Count - 1} clips)");
				}
				clipCache.Remove(text);
			}
		}

		private IEnumerator PreloadClip(string url)
		{
			preloadingUrls.Add(url);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[Glitnir] Pré-carregando: " + url));
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(url, (AudioType)13);
			try
			{
				((DownloadHandlerAudioClip)req.downloadHandler).compressed = false;
				req.timeout = 20;
				yield return req.SendWebRequest();
				if ((int)req.result != 1)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Glitnir] Falha no pré-carregamento (URL inválida/expirada?): " + req.error + " — " + url));
					clipCache[url] = null;
					preloadingUrls.Remove(url);
					yield break;
				}
				AudioClip clip = DownloadHandlerAudioClip.GetContent(req);
				preloadingUrls.Remove(url);
				if ((Object)(object)clip != (Object)null)
				{
					AddToCache(url, clip);
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Glitnir] Cache: {((Object)clip).name} ({clipCache.Count} clips em RAM)");
				}
			}
			finally
			{
				((IDisposable)req)?.Dispose();
			}
		}

		private void SwitchMusic(string url, float cfgVolume, MusicState state)
		{
			if (!(currentUrl == url))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Glitnir] [{state}] → {url}");
				currentState = state;
				currentUrl = url;
				currentCfgVolume = cfgVolume;
				MuteVanilla();
				if (fadeCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(fadeCoroutine);
				}
				isFading = false;
				if (clipCache.TryGetValue(url, out var value) && (Object)(object)value != (Object)null)
				{
					fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeSwitchCached(value, url, cfgVolume));
				}
				else
				{
					fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeSwitch(url, cfgVolume));
				}
			}
		}

		private IEnumerator FadeSwitchCached(AudioClip nextClip, string url, float cfgVolume)
		{
			isFading = true;
			try
			{
				float startVol = audioSource.volume;
				float t = 0f;
				while (t < fadeDuration)
				{
					t += Time.deltaTime;
					audioSource.volume = Mathf.Lerp(startVol, 0f, t / fadeDuration);
					yield return null;
				}
				audioSource.Stop();
				currentClipUrl = url;
				audioSource.clip = nextClip;
				audioSource.volume = 0f;
				audioSource.Play();
				t = 0f;
				while (t < fadeDuration)
				{
					t += Time.deltaTime;
					audioSource.volume = Mathf.Lerp(0f, FinalVolume(cfgVolume), t / fadeDuration);
					yield return null;
				}
				audioSource.volume = FinalVolume(cfgVolume);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Glitnir] Tocando do cache (vol={audioSource.volume:F2}).");
			}
			finally
			{
				isFading = false;
			}
		}

		private IEnumerator FadeSwitch(string url, float cfgVolume)
		{
			isFading = true;
			try
			{
				float waitLimit = fadeDuration + 15f;
				float waited = 0f;
				float startVol = audioSource.volume;
				float t = 0f;
				while (t < fadeDuration || (preloadingUrls.Contains(url) && waited < waitLimit))
				{
					float dt = Time.deltaTime;
					t += dt;
					waited += dt;
					if (t <= fadeDuration)
					{
						audioSource.volume = Mathf.Lerp(startVol, 0f, t / fadeDuration);
					}
					else
					{
						audioSource.volume = 0f;
					}
					if (!preloadingUrls.Contains(url) && t >= fadeDuration)
					{
						break;
					}
					yield return null;
				}
				audioSource.Stop();
				ReleaseCurrentClip();
				if (clipCache.TryGetValue(url, out var cached) && (Object)(object)cached != (Object)null)
				{
					currentClipUrl = url;
					audioSource.clip = cached;
					audioSource.volume = 0f;
					audioSource.Play();
					t = 0f;
					while (t < fadeDuration)
					{
						t += Time.deltaTime;
						audioSource.volume = Mathf.Lerp(0f, FinalVolume(cfgVolume), t / fadeDuration);
						yield return null;
					}
					audioSource.volume = FinalVolume(cfgVolume);
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Glitnir] Tocando do cache (vol={audioSource.volume:F2}).");
				}
				else
				{
					yield return ((MonoBehaviour)this).StartCoroutine(LoadAndFadeIn(url, cfgVolume));
				}
			}
			finally
			{
				isFading = false;
			}
		}

		private IEnumerator FadeOutAndStop(bool andUnmute = false)
		{
			isFading = true;
			try
			{
				float startVol = audioSource.volume;
				float t = 0f;
				while (t < fadeDuration)
				{
					t += Time.deltaTime;
					audioSource.volume = Mathf.Lerp(startVol, 0f, t / fadeDuration);
					yield return null;
				}
				audioSource.Stop();
				ReleaseCurrentClip();
				if (andUnmute)
				{
					UnmuteVanilla();
				}
			}
			finally
			{
				isFading = false;
			}
		}

		private IEnumerator LoadAndFadeIn(string url, float cfgVolume)
		{
			if (string.IsNullOrWhiteSpace(url))
			{
				yield break;
			}
			if (clipCache.TryGetValue(url, out var preloaded) && (Object)(object)preloaded != (Object)null)
			{
				currentClipUrl = url;
				audioSource.clip = preloaded;
				audioSource.volume = 0f;
				audioSource.Play();
				float t2 = 0f;
				while (t2 < fadeDuration)
				{
					t2 += Time.deltaTime;
					audioSource.volume = Mathf.Lerp(0f, FinalVolume(cfgVolume), t2 / fadeDuration);
					yield return null;
				}
				audioSource.volume = FinalVolume(cfgVolume);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Glitnir] Tocando (vol={audioSource.volume:F2}).");
				yield break;
			}
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(url, (AudioType)13);
			try
			{
				((DownloadHandlerAudioClip)req.downloadHandler).compressed = false;
				req.timeout = 15;
				yield return req.SendWebRequest();
				if ((int)req.result != 1)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Glitnir] Falha ao carregar (URL inválida/expirada?): " + req.error + " — " + url));
					clipCache[url] = null;
					yield break;
				}
				AudioClip clip = DownloadHandlerAudioClip.GetContent(req);
				if ((Object)(object)clip == (Object)null || currentUrl != url)
				{
					if ((Object)(object)clip != (Object)null)
					{
						Object.Destroy((Object)(object)clip);
					}
					yield break;
				}
				AddToCache(url, clip);
				preloadingUrls.Remove(url);
				ReleaseCurrentClip();
				audioSource.clip = clip;
				audioSource.volume = 0f;
				audioSource.Play();
				currentClipUrl = url;
				float t3 = 0f;
				while (t3 < fadeDuration)
				{
					t3 += Time.deltaTime;
					audioSource.volume = Mathf.Lerp(0f, FinalVolume(cfgVolume), t3 / fadeDuration);
					yield return null;
				}
				audioSource.volume = FinalVolume(cfgVolume);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Glitnir] Tocando (vol={audioSource.volume:F2}).");
			}
			finally
			{
				((IDisposable)req)?.Dispose();
			}
		}

		private void PlayCachedClip(AudioClip clip, float finalVolume, MusicState state, string url, float cfgVolume)
		{
			if (!(currentUrl == url))
			{
				currentState = state;
				currentUrl = url;
				currentClipUrl = url;
				currentCfgVolume = cfgVolume;
				MuteVanilla();
				audioSource.Stop();
				audioSource.clip = clip;
				audioSource.volume = finalVolume;
				audioSource.Play();
			}
		}

		private IEnumerator PreloadMenuMusic()
		{
			if (menuEntry == null || !menuEnabled || !menuEntry.IsActive)
			{
				yield break;
			}
			if (clipCache.TryGetValue(menuEntry.url, out var cached))
			{
				if ((Object)(object)cached != (Object)null)
				{
					menuClip = cached;
					menuClipReady = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Menu: usando clip do cache.");
				}
				yield break;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Pré-carregando música do menu...");
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(menuEntry.url, (AudioType)13);
			try
			{
				((DownloadHandlerAudioClip)req.downloadHandler).compressed = false;
				req.timeout = 15;
				yield return req.SendWebRequest();
				if ((int)req.result != 1)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[Glitnir] Falha no menu: " + req.error));
					clipCache[menuEntry.url] = null;
					yield break;
				}
				AudioClip clip = DownloadHandlerAudioClip.GetContent(req);
				if ((Object)(object)clip != (Object)null)
				{
					AddToCache(menuEntry.url, clip);
					menuClip = clip;
					menuClipReady = true;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[Glitnir] Menu " + (menuClipReady ? "pronto." : "clip nulo!")));
			}
			finally
			{
				((IDisposable)req)?.Dispose();
			}
		}

		private void StopOurMusic()
		{
			if (fadeCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(fadeCoroutine);
			}
			isFading = false;
			audioSource.Stop();
			ReleaseCurrentClip();
			currentState = MusicState.None;
			currentUrl = "";
		}

		private void ReleaseCurrentClip()
		{
			if (!string.IsNullOrEmpty(currentClipUrl))
			{
				if (!clipCache.ContainsKey(currentClipUrl) && (Object)(object)audioSource.clip != (Object)null)
				{
					Object.Destroy((Object)(object)audioSource.clip);
				}
				audioSource.clip = null;
				currentClipUrl = "";
			}
		}

		private void ClearCache()
		{
			menuClip = null;
			menuClipReady = false;
			foreach (AudioClip value in clipCache.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			clipCache.Clear();
			preloadingUrls.Clear();
			_cacheInsertionOrder.Clear();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Cache de clips liberado.");
		}

		private void CreateMusicPlayer()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			if (!((Object)(object)musicObject != (Object)null) || !((Object)(object)audioSource != (Object)null))
			{
				if ((Object)(object)musicObject == (Object)null)
				{
					musicObject = new GameObject("Glitnir Music Player");
					Object.DontDestroyOnLoad((Object)(object)musicObject);
				}
				audioSource = musicObject.GetComponent<AudioSource>() ?? musicObject.AddComponent<AudioSource>();
				audioSource.loop = true;
				audioSource.spatialBlend = 0f;
				audioSource.volume = 1f;
				TryConnectToMusicMixer();
			}
		}

		private void TryConnectToMusicMixer()
		{
			AudioMixerGroup musicGroup = MusicManPatches.GetMusicGroup();
			if ((Object)(object)musicGroup != (Object)null)
			{
				audioSource.outputAudioMixerGroup = musicGroup;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] AudioSource conectado ao mixer de música do jogo.");
			}
			else
			{
				((MonoBehaviour)this).StartCoroutine(RetryConnectMixer());
			}
		}

		private IEnumerator RetryConnectMixer()
		{
			float elapsed = 0f;
			while (elapsed < 10f)
			{
				yield return (object)new WaitForSeconds(0.5f);
				elapsed += 0.5f;
				AudioMixerGroup group = MusicManPatches.GetMusicGroup();
				if ((Object)(object)group != (Object)null)
				{
					audioSource.outputAudioMixerGroup = group;
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] AudioSource conectado ao mixer de música do jogo (retry).");
					yield break;
				}
			}
			((BaseUnityPlugin)this).Logger.LogError((object)"[Glitnir] Não foi possível conectar ao AudioMixerGroup do MusicMan — o slider 'Volume da música' pode não afetar o volume do mod!");
		}

		private void StartConfigWatcher()
		{
			try
			{
				string directoryName = Path.GetDirectoryName(ConfigPath);
				string fileName = Path.GetFileName(ConfigPath);
				if (Directory.Exists(directoryName))
				{
					configWatcher = new FileSystemWatcher(directoryName, fileName)
					{
						NotifyFilter = NotifyFilters.LastWrite,
						EnableRaisingEvents = true
					};
					configWatcher.Changed += delegate
					{
						_watcherEventTime = DateTime.UtcNow;
						reloadPending = true;
					};
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Watcher de config ativo.");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[Glitnir] Watcher não iniciado: " + ex.Message));
			}
		}

		private void LoadConfig()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			if (!File.Exists(ConfigPath))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[Glitnir] Config não encontrada: " + ConfigPath));
				return;
			}
			try
			{
				string text = File.ReadAllText(ConfigPath);
				IDeserializer val = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(UnderscoredNamingConvention.Instance).IgnoreUnmatchedProperties().Build();
				YamlConfig yamlConfig = val.Deserialize<YamlConfig>(text);
				if (yamlConfig == null)
				{
					throw new Exception("YAML resultou em objeto nulo.");
				}
				bool enabled = yamlConfig.menu.enabled;
				float volume = yamlConfig.menu.volume;
				MusicEntry musicEntry = new MusicEntry(enabled: true, yamlConfig.menu.url);
				bool enabled2 = yamlConfig.biomes.enabled;
				float volume2 = yamlConfig.biomes.volume;
				Dictionary<Biome, MusicEntry> dictionary = new Dictionary<Biome, MusicEntry>();
				foreach (KeyValuePair<string, YamlTrack> track in yamlConfig.biomes.tracks)
				{
					if (Enum.TryParse<Biome>(track.Key, out Biome result))
					{
						TerritoryMode mode = TerritoryMode.Custom;
						if (!string.IsNullOrWhiteSpace(track.Value.mode))
						{
							string text2 = track.Value.mode.Trim().ToLowerInvariant();
							string text3 = text2;
							mode = ((text3 == "vanilla") ? TerritoryMode.Vanilla : ((text3 == "mute") ? TerritoryMode.Mute : TerritoryMode.Custom));
						}
						dictionary[result] = new MusicEntry(track.Value.enabled, track.Value.url, mode);
					}
				}
				bool enabled3 = yamlConfig.locations.enabled;
				float volume3 = yamlConfig.locations.volume;
				float radius = yamlConfig.locations.radius;
				float dungeon_y_min = yamlConfig.locations.dungeon_y_min;
				float dungeon_y_max = yamlConfig.locations.dungeon_y_max;
				List<LocationEntry> list = new List<LocationEntry>();
				foreach (YamlLocationTrack track2 in yamlConfig.locations.tracks)
				{
					list.Add(new LocationEntry
					{
						location = track2.location,
						radius = track2.radius,
						dungeonYMin = track2.dungeon_y_min,
						dungeonYMax = track2.dungeon_y_max,
						dungeonOnly = track2.dungeon_only,
						enabled = track2.enabled,
						url = track2.url
					});
				}
				bool enabled4 = yamlConfig.territories.enabled;
				List<TerritoryEntry> list2 = new List<TerritoryEntry>();
				foreach (YamlTerritoryTrack track3 in yamlConfig.territories.tracks)
				{
					TerritoryMode mode2 = TerritoryMode.Custom;
					if (!string.IsNullOrWhiteSpace(track3.mode))
					{
						string text4 = track3.mode.Trim().ToLowerInvariant();
						string text5 = text4;
						mode2 = ((text5 == "vanilla") ? TerritoryMode.Vanilla : ((text5 == "mute") ? TerritoryMode.Mute : TerritoryMode.Custom));
					}
					list2.Add(new TerritoryEntry
					{
						name = track3.name,
						x = track3.x,
						z = track3.z,
						radius = track3.radius,
						volume = track3.volume,
						enabled = track3.enabled,
						mode = mode2,
						url = track3.url
					});
				}
				bool enabled5 = yamlConfig.bosses.enabled;
				float volume4 = yamlConfig.bosses.volume;
				float radius2 = yamlConfig.bosses.radius;
				Dictionary<string, MusicEntry> dictionary2 = new Dictionary<string, MusicEntry>();
				foreach (KeyValuePair<string, YamlTrack> track4 in yamlConfig.bosses.tracks)
				{
					dictionary2[track4.Key] = new MusicEntry(track4.Value.enabled, track4.Value.url);
				}
				bool enabled6 = yamlConfig.creatures.enabled;
				float volume5 = yamlConfig.creatures.volume;
				float radius3 = yamlConfig.creatures.radius;
				Dictionary<string, MusicEntry> dictionary3 = new Dictionary<string, MusicEntry>();
				foreach (KeyValuePair<string, YamlTrack> track5 in yamlConfig.creatures.tracks)
				{
					dictionary3[track5.Key] = new MusicEntry(track5.Value.enabled, track5.Value.url);
				}
				ClearCache();
				_locPosCache.Clear();
				menuEnabled = enabled;
				menuVolume = volume;
				menuEntry = musicEntry;
				biomesEnabled = enabled2;
				biomeVolume = volume2;
				biomeMap = dictionary;
				locEnabled = enabled3;
				locVolume = volume3;
				locRadius = radius;
				locDungeonYMin = dungeon_y_min;
				locDungeonYMax = dungeon_y_max;
				locList = list;
				terrEnabled = enabled4;
				terrList = list2;
				bossEnabled = enabled5;
				bossVolume = volume4;
				bossRadius = radius2;
				bossMap = dictionary2;
				creatEnabled = enabled6;
				creatVolume = volume5;
				creatRadius = radius3;
				creatMap = dictionary3;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[Glitnir] Config carregada: " + $"{biomeMap.Count} biomas, {locList.Count} locations, " + $"{terrList.Count} territories, {bossMap.Count} bosses, {creatMap.Count} criaturas."));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[Glitnir] Erro ao ler config: " + ex.Message));
				((BaseUnityPlugin)this).Logger.LogError((object)("[Glitnir] Verifique o arquivo: " + ConfigPath));
			}
		}

		private void EnsureDefaultConfig()
		{
			if (!File.Exists(ConfigPath))
			{
				Directory.CreateDirectory(Path.GetDirectoryName(ConfigPath));
				File.WriteAllText(ConfigPath, "# ╔══════════════════════════════════════════════════════════════════╗\r\n# ║           GLITNIR MUSIC ZONES — music_config.yaml               ║\r\n# ╚══════════════════════════════════════════════════════════════════╝\r\n# Use URLs diretas de MP3 (sem expiração). Recomendado: GitHub Releases\r\n# ou cdn.pixabay.com. Evite links do Discord (expiram em horas).\r\n#\r\n# Após salvar o arquivo, a config recarrega automaticamente no jogo.\r\n\r\n# ─── MENU PRINCIPAL ────────────────────────────────────────────────\r\nmenu:\r\n  enabled: false\r\n  volume: 0.0500\r\n  url: \"https://cdn.pixabay.com/download/audio/2025/07/24/audio_9d4a9c72f8.mp3?filename=wesleysert-glitnir-valhhala-1-379314.mp3\"\r\n\r\n# ─── BIOMAS ────────────────────────────────────────────────────────\r\n# Biomas disponíveis: Meadows, BlackForest, Swamp, Mountain, Plains,\r\n#                     Mistlands, AshLands, DeepNorth, Ocean\r\n# mode:   custom  = toca a url configurada (silencia vanilla)\r\n#         vanilla = deixa a música do jogo tocar normalmente\r\n#         mute    = silêncio total (nem mod nem vanilla)\r\nbiomes:\r\n  enabled: true\r\n  volume: 0.0500\r\n  tracks:\r\n    Meadows:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_d304cbd8a2.mp3?filename=morgnar-neve-540465.mp3\"\r\n    BlackForest:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_62456d9582.mp3?filename=morgnar-mire-of-ancients-538620.mp3\"\r\n    Swamp:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_47a47ff6c2.mp3?filename=morgnar-pantano-540510.mp3\"\r\n    Mountain:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_e6186facfc.mp3?filename=morgnar-mist-over-runestones-540508.mp3\"\r\n    Plains:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_0f67273299.mp3?filename=morgnar-planicie-540517.mp3\"\r\n    Mistlands:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_e6186facfc.mp3?filename=morgnar-mist-over-runestones-540508.mp3\"\r\n    AshLands:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_d97092169a.mp3?filename=morgnar-ashlands-540519.mp3\"\r\n    DeepNorth:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_2fe0daf552.mp3?filename=morgnar-deepnorth-540531.mp3\"\r\n    Ocean:\r\n      enabled: true\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_2fe0daf552.mp3?filename=morgnar-deepnorth-540531.mp3\"\r\n\r\n# ─── LOCATIONS (Pontos de interesse do ZoneSystem) ─────────────────\r\n# location:      nome exato da Location (ex: StartTemple, Crypt2)\r\n# radius:        raio em unidades (0 = usa o radius global abaixo)\r\n# dungeon_only:  true = só toca dentro da dungeon (faixa Y)\r\n# dungeon_y_min/max: faixa Y da dungeon (-1 = usa o global)\r\nlocations:\r\n  enabled: false\r\n  volume: 0.65\r\n  radius: 90.0\r\n  dungeon_y_min: 4500.0\r\n  dungeon_y_max: 5500.0\r\n  tracks:\r\n    - enabled: false\r\n      location: StartTemple\r\n      radius: 60.0\r\n      dungeon_only: false\r\n      dungeon_y_min: -1\r\n      dungeon_y_max: -1\r\n      url: \"\"\r\n\r\n    - enabled: false\r\n      location: Vendor_BlackForest\r\n      radius: 0.0\r\n      dungeon_only: false\r\n      dungeon_y_min: 4500.0\r\n      dungeon_y_max: -1\r\n      url: \"\"\r\n\r\n    - enabled: false\r\n      location: Crypt2\r\n      radius: 90.0\r\n      dungeon_only: false\r\n      dungeon_y_min: 4500.0\r\n      dungeon_y_max: 5500.0\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      location: Crypt3\r\n      radius: 90.0\r\n      dungeon_only: true\r\n      dungeon_y_min: 4500\r\n      dungeon_y_max: 5500\r\n      url: \"\"\r\n\r\n    - enabled: false\r\n      location: MountainCave01\r\n      radius: 90.0\r\n      dungeon_only: false\r\n      dungeon_y_min: 4500\r\n      dungeon_y_max: 5500\r\n      url: \"\"\r\n\r\n# ─── TERRITORIES (Zonas por coordenada XZ) ─────────────────────────\r\n# Use para vilas ou regiões sem Location no ZoneSystem.\r\n# x/z:    coordenadas do centro no mapa do Valheim\r\n# mode:   custom  = toca a url configurada (silencia vanilla)\r\n#         vanilla = deixa a música do jogo tocar normalmente\r\n#         mute    = silêncio total (nem mod nem vanilla)\r\nterritories:\r\n  enabled: true\r\n  tracks:\r\n    - enabled: true\r\n      name: BosquePrmadico\r\n      x: 25186.0\r\n      z: 4411.0\r\n      radius: 700.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_d304cbd8a2.mp3?filename=morgnar-neve-540465.mp3\"\r\n\r\n    - enabled: true\r\n      name: Vila Prado\r\n      x: -245.0\r\n      z: 336.0\r\n      radius: 200.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_e0d6b4179f.mp3?filename=morgnar-harbor-hearth-village-1-538622.mp3\"\r\n\r\n    - enabled: true\r\n      name: Skjalfhame\r\n      x: -37714.0\r\n      z: 9799.0\r\n      radius: 100.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_6ab79d7f51.mp3?filename=morgnar-vila-540514.mp3\"\r\n\r\n    - enabled: true\r\n      name: Hrotghar\r\n      x: 3337.0\r\n      z: -6096.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_6ab79d7f51.mp3?filename=morgnar-vila-540514.mp3\"\r\n\r\n    - enabled: true\r\n      name: Winterhold\r\n      x: 17938.0\r\n      z: 14584.0\r\n      radius: 70.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_6ab79d7f51.mp3?filename=morgnar-vila-540514.mp3\"\r\n\r\n    - enabled: true\r\n      name: Vila da Floresta Negra\r\n      x: -1997.0\r\n      z: -5333.0\r\n      radius: 50.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_6ab79d7f51.mp3?filename=morgnar-vila-540514.mp3\"\r\n\r\n    - enabled: true\r\n      name: Vila do Pantano\r\n      x: 4917.0\r\n      z: -2571.0\r\n      radius: 200.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_e0d6b4179f.mp3?filename=morgnar-harbor-hearth-village-1-538622.mp3\"\r\n\r\n    - enabled: true\r\n      name: Vila da Montanha\r\n      x: 6508.0\r\n      z: 3735.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_e0d6b4179f.mp3?filename=morgnar-harbor-hearth-village-1-538622.mp3\"\r\n\r\n    - enabled: true\r\n      name: Varghard - Reino dos Humanos\r\n      x: 13695.0\r\n      z: 19496.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Eryndel - Reino dos Elfos\r\n      x: 21474.0\r\n      z: 12080.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Drakthar - Reino dos Orcs\r\n      x: -7346.0\r\n      z: 20523.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Coliseu\r\n      x: 1745.0\r\n      z: 21713.0\r\n      radius: 500.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Brumello - Reino dos Halflings\r\n      x: -15671.0\r\n      z: 15840.0\r\n      radius: 500.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Cabaré do Sjar\r\n      x: 14691.0\r\n      z: 17973.0\r\n      radius: 50.0\r\n      volume: 0.0500\r\n      mode: mute\r\n      url: \"\"\r\n\r\n    - enabled: true\r\n      name: Forte Falkreath\r\n      x: -22106.0\r\n      z: 9622.0\r\n      radius: 100.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_c2d6bad590.mp3?filename=morgnar-falkreath-citadel-541114.mp3\"\r\n\r\n    - enabled: false\r\n      name: Parkour\r\n      x: 6508.0\r\n      z: 3735.0\r\n      radius: 400.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/25/audio_4d4bef9969.mp3?filename=morgnar-mead-hall-waltz-541115.mp3\"\r\n\r\n    - enabled: true\r\n      name: Jorrvaskr\r\n      x: 11411.0\r\n      z: 19191.0\r\n      radius: 70.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_a9a5df53e2.mp3?filename=morgnar-harbor-hearth-village-538619.mp3\"\r\n\r\n    - enabled: true\r\n      name: Calindel\r\n      x: 8590.0\r\n      z: 20394.0\r\n      radius: 70.0\r\n      volume: 0.0500\r\n      mode: custom\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_a9a5df53e2.mp3?filename=morgnar-harbor-hearth-village-538619.mp3\"\r\n\r\n# ─── BOSSES ────────────────────────────────────────────────────────\r\n# Prefab name do boss sem '(Clone)'. Toca enquanto o boss estiver vivo no raio.\r\n# Bosses vanilla: Eikthyr, gd_king, Bonemass, Dragon, GoblinKing, SeekerQueen, Fader\r\nbosses:\r\n  enabled: true\r\n  volume: 0.0500\r\n  radius: 120.0\r\n  tracks:\r\n    Eikthyr:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    gd_king:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    Bonemass:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    Dragon:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    GoblinKing:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    SeekerQueen:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    Fader:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n    brutoGLIT:\r\n      enabled: true\r\n      url: \"https://cdn.pixabay.com/download/audio/2026/05/22/audio_1a619af2ce.mp3?filename=morgnar-stag-of-thunder-538616.mp3\"\r\n\r\n# ─── CRIATURAS ─────────────────────────────────────────────────────\r\n# Toca enquanto houver ao menos uma criatura viva no raio.\r\ncreatures:\r\n  enabled: true\r\n  volume: 0.0500\r\n  radius: 30.0\r\n  tracks:\r\n    Troll:\r\n      enabled: false\r\n      url: \"\"\r\n    GoblinBrute:\r\n      enabled: false\r\n      url: \"\"\r\n    BlobTar:\r\n      enabled: false\r\n      url: \"\"\r\n    Seeker:\r\n      enabled: false\r\n      url: \"\"\r\n    Leech:\r\n      enabled: false\r\n      url: \"\"\r\n");
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[Glitnir] Config padrão criada em: " + ConfigPath));
			}
		}
	}
}