local b=settings.MusicFadeoutTime function PlaySound(b)if b==nil then return end local y=Instance.new("\083\111\117\110\100")y.Looped=true y.SoundId=b.SoundId y.Volume=musicon and b.Volume or 0 local V=Instance.new("\078\117\109\098\101\114\086\097\108\117\101",y)V.Name="\079\114\105\103\105\110\097\108\086\111\108\117\109\101"V.Value=b.Volume y.Pitch=b.Pitch y.Name="\066\071\077"y.Parent=script y:Play()end function FadeOutSound(y)local V=y.Volume local S=math.ceil(30*b)if S<1 then S=1 end for b=1,S,1 do if y then y.Volume=y.Volume-V/S wait(.033333333333333)end end if y then y:Stop()y:Destroy()end end if settings.UseGlobalBackgroundMusic==true and settings.UseMusicZones==false then if#music[globali]==1 then PlaySound(music[1][1])return elseif#music[globali]==0 then return end end local y={}math.randomseed(tick())local V local S function CheckIfRecent(b)for y,V in pairs(y)do if V==b then return true end end return false end function SelectRandomMusic(b)if b==nil or#b==0 then return end local V={}local S for b=1,#b,1 do if not CheckIfRecent(b)then table.insert(V,b)end end local X=V[math.random(1,#V)]table.insert(y,X)if#y>math.ceil(#b/2)then table.remove(y,1)end return b[X]end function IsInZone(b)if torso and torso.Parent~=nil then local y=torso.Position for b,V in pairs(b.Parts)do if V.Coordinates then local b=V.Coordinates if y.x>b.lx and(y.x<b.mx and(y.y>b.ly and(y.y<b.my and(y.z>b.lz and y.z<b.mz))))then return true end elseif V.Part then local b=V.Part:clone()b.Anchored=true b.Parent=workspace.CurrentCamera or workspace b.CanCollide=true local y=b:GetTouchingParts()b:Destroy()for b,y in pairs(y)do if y==torso then return true end end end end return false end end function CalculateCurrentZone()local b=-math.huge local S=V local X if V then if IsInZone(V)then X=V b=V.Priority end end for y,V in pairs(zones)do if V.Priority>b and IsInZone(V)then b=V.Priority X=V end end V=X if V~=S and(V~=nil or settings.UseGlobalBackgroundMusic==true)then y={}end return V,S end function RunCycle()local y=script:FindFirstChild("\066\071\077")if settings.UseMusicZones==true then local b,V=CalculateCurrentZone()if b~=V and(b~=S and y)then if b==nil and(settings.UseGlobalBackgroundMusic==true or settings.MusicOnlyPlaysWithinZones==true)or b~=nil then FadeOutSound(y)return end elseif b and y==nil then PlaySound(SelectRandomMusic(b.Music))S=b return elseif b==nil and(V and(settings.MusicOnlyPlaysWithinZones==false and(settings.UseGlobalBackgroundMusic==false and y==nil)))then PlaySound(SelectRandomMusic(V.Music))S=V return elseif S and(settings.MusicOnlyPlaysWithinZones==false and(settings.UseGlobalBackgroundMusic==false and y==nil))then PlaySound(SelectRandomMusic(S.Music))return elseif settings.UseGlobalBackgroundMusic==true and y==nil then PlaySound(SelectRandomMusic(music[globali]))S=nil return end elseif y==nil and settings.UseGlobalBackgroundMusic==true then PlaySound(SelectRandomMusic(music[globali]))return end if y and(settings.UseGlobalBackgroundMusic==true and(S==nil and#music[globali]>1))or S and#S.Music>1 then local V=y.TimeLength local S=y.TimePosition if V~=0 and V-S<b+.5 then FadeOutSound(y)end end end while wait(.5)do RunCycle()end
--now, get to playing the music

local FadeoutTime = settings.MusicFadeoutTime

function PlaySound(sounddata)
	if sounddata == nil then
		return
	end
	local sound = Instance.new("Sound")
	sound.Looped = true
	sound.SoundId = sounddata.SoundId
	sound.Volume = musicon and sounddata.Volume or 0
	local v = Instance.new("NumberValue", sound)
	v.Name = "OriginalVolume"
	v.Value = sounddata.Volume
	sound.Pitch = sounddata.Pitch
	sound.Name = "BGM"
	sound.Parent = script
	sound:Play()
end

function FadeOutSound(sound)
	local basevol = sound.Volume
	local count = math.ceil(30 * FadeoutTime)
	if count < 1 then
		count = 1
	end
	for i = 1, count do
		if sound then
			sound.Volume = sound.Volume - (basevol / count)
			wait(1 / 30)
		end
	end
	if sound then
		sound:Stop()
		sound:Destroy()
	end
end

if settings.UseGlobalBackgroundMusic == true and settings.UseMusicZones == false then
	if #music[globali] == 1 then --global BGM with just 1 song? ez pz
		PlaySound(music[1][1])
		return
	elseif #music[globali] == 0 then --there's no music to play...?
		return
	end
end

local recentindices = {} --keeps track of recently selected indicies, so as not to play repeat music tracks
math.randomseed(tick())
local currentzone
local zoneplayingmusic

function CheckIfRecent(i)
	for _, v in pairs(recentindices) do
		if v == i then
			return true
		end
	end
	return false
end

function SelectRandomMusic(musiclist) --select a random number, excluding ones that were already used recently
	if musiclist == nil or #musiclist == 0 then
		return
	end
	local possiblenumbers = {}
	local selectedindex
	for i = 1, #musiclist do
		if not CheckIfRecent(i) then
			table.insert(possiblenumbers, i)
		end
	end
	local selectedindex = possiblenumbers[math.random(1, #possiblenumbers)]
	table.insert(recentindices, selectedindex)
	if #recentindices > math.ceil(#musiclist / 2) then
		table.remove(recentindices, 1)
	end
	return musiclist[selectedindex]
end

function IsInZone(zonedata)
	if torso and torso.Parent ~= nil then
		local p = torso.Position
		for _, data in pairs(zonedata["Parts"]) do
			if data["Coordinates"] then
				local t = data["Coordinates"]
				if p.x > t.lx and p.x < t.mx and p.y > t.ly and p.y < t.my and p.z > t.lz and p.z < t.mz then --is the character within all the coordinates of the zone?
					return true
				end
			elseif data["Part"] then --complex part? create a clone of the part and check if it's touching the character's torso
				local part = data["Part"]:clone()
				part.Anchored = true
				part.Parent = workspace.CurrentCamera or workspace
				part.CanCollide = true
				local touching = part:GetTouchingParts()
				part:Destroy()
				for _, v in pairs(touching) do
					if v == torso then
						return true
					end
				end
			end
		end
		return false
	end
end

function CalculateCurrentZone()
	local priority = -math.huge
	local oldzone = currentzone
	local selectedzone
	if currentzone then
		if IsInZone(currentzone) then
			selectedzone = currentzone
			priority = currentzone["Priority"]
		end
	end
	for _, zone in pairs(zones) do
		if zone["Priority"] > priority and IsInZone(zone) then
			priority = zone["Priority"]
			selectedzone = zone
		end
	end
	currentzone = selectedzone
	if currentzone ~= oldzone and (currentzone ~= nil or settings.UseGlobalBackgroundMusic == true) then
		recentindices = {}
	end
	return currentzone, oldzone
end

function RunCycle() --the main cycle which will continuously run, checking which zones (if any) the character is in and playing new music when necessary
	local bgm = script:FindFirstChild("BGM")
	if settings.UseMusicZones == true then
		local zone, oldzone = CalculateCurrentZone()
		if zone ~= oldzone and zone ~= zoneplayingmusic and bgm then
			if
				(
					zone == nil
					and (settings.UseGlobalBackgroundMusic == true or settings.MusicOnlyPlaysWithinZones == true)
				) or zone ~= nil
			then
				FadeOutSound(bgm)
				return
			end
		elseif zone and bgm == nil then
			PlaySound(SelectRandomMusic(zone["Music"]))
			zoneplayingmusic = zone
			return
		elseif
			zone == nil
			and oldzone
			and settings.MusicOnlyPlaysWithinZones == false
			and settings.UseGlobalBackgroundMusic == false
			and bgm == nil
		then
			PlaySound(SelectRandomMusic(oldzone["Music"]))
			zoneplayingmusic = oldzone
			return
		elseif
			zoneplayingmusic
			and settings.MusicOnlyPlaysWithinZones == false
			and settings.UseGlobalBackgroundMusic == false
			and bgm == nil
		then
			PlaySound(SelectRandomMusic(zoneplayingmusic["Music"]))
			return
		elseif settings.UseGlobalBackgroundMusic == true and bgm == nil then
			PlaySound(SelectRandomMusic(music[globali]))
			zoneplayingmusic = nil
			return
		end
	elseif bgm == nil and settings.UseGlobalBackgroundMusic == true then
		PlaySound(SelectRandomMusic(music[globali]))
		return
	end

	if
		bgm and (settings.UseGlobalBackgroundMusic == true and zoneplayingmusic == nil and #music[globali] > 1)
		or (zoneplayingmusic and #zoneplayingmusic["Music"] > 1)
	then
		local length = bgm.TimeLength
		local pos = bgm.TimePosition
		if length ~= 0 and length - pos < FadeoutTime + 0.5 then
			FadeOutSound(bgm)
		end
	end
end

while wait(0.5) do
	RunCycle()
end
