-- EASING --
local path = GAMESTATE:GetCurrentSong():GetSongDir()..'lua/'
loadfile(path..'easing.lua')()

LIST_ACTORS = true

_darkness = {} _darkmask = {}
checked = false

local linear, inQuad, outQuad, inOutQuad, outInQuad, inCubic, outCubic, inOutCubic, outInCubic, inQuart,outQuart, inOutQuart, outInQuart, inQuint, outQuint, inOutQuint, outInQuint, inSine, outSine, inOutSine,outInSine, inExpo, outExpo, inOutExpo, outInExpo, inCirc, outCirc, inOutCirc, outInCirc, inElastic,outElastic, inOutElastic, outInElastic, inBack, outBack, inOutBack, outInBack, inBounce, outBounce,inOutBounce, outInBounce = ease.linear, ease.inQuad, ease.outQuad, ease.inOutQuad, ease.outInQuad,ease.inCubic, ease.outCubic, ease.inOutCubic, ease.outInCubic, ease.inQuart, ease.outQuart,ease.inOutQuart, ease.outInQuart, ease.inQuint, ease.outQuint, ease.inOutQuint, ease.outInQuint,ease.inSine, ease.outSine, ease.inOutSine, ease.outInSine, ease.inExpo, ease.outExpo, ease.inOutExpo,ease.outInExpo, ease.inCirc, ease.outCirc, ease.inOutCirc, ease.outInCirc, ease.inElastic,ease.outElastic, ease.inOutElastic, ease.outInElastic, ease.inBack, ease.outBack, ease.inOutBack,ease.outInBack, ease.inBounce, ease.outBounce, ease.inOutBounce, ease.outInBounce

	sw = SCREEN_WIDTH
	sh = SCREEN_HEIGHT --shortcuts
	
	scx = sw/2
	scy = sh/2
	
local po = {GAMESTATE:GetPlayerState(0):GetPlayerOptions'ModsLevel_Song', GAMESTATE:GetPlayerState(1):GetPlayerOptions'ModsLevel_Song'}
function mod_do(str,pn)
	--if pn then if GAMESTATE:IsPlayerEnabled(pn-1) then handle_mods(str,pn) end
	--else for pn=1,2 do if GAMESTATE:IsPlayerEnabled(pn-1) then handle_mods(str,pn) end end end
	
    if pn then
        po[pn]:FromString(str)
    else
        po[1]:FromString(str)
        po[2]:FromString(str)
    end
end

_numplayers = 0
local _diff = {0,0}
if GAMESTATE:IsHumanPlayer(PLAYER_1) then
	local stepsr = (GAMESTATE:GetCurrentSteps(PLAYER_1):GetDifficulty())
	if stepsr == "Difficulty_Beginner" then _diff[1] = 0 end
	if stepsr == "Difficulty_Easy" then _diff[1] = 1 end
	if stepsr == "Difficulty_Medium" then _diff[1] = 2 end
	if stepsr == "Difficulty_Hard" then _diff[1] = 3 end
	if stepsr == "Difficulty_Challenge" then _diff[1] = 4 end
	_numplayers = _numplayers+1
end
if GAMESTATE:IsHumanPlayer(PLAYER_2) then
	local stepsr = (GAMESTATE:GetCurrentSteps(PLAYER_2):GetDifficulty())
	if stepsr == "Difficulty_Beginner" then _diff[2] = 0 end
	if stepsr == "Difficulty_Easy" then _diff[2] = 1 end
	if stepsr == "Difficulty_Medium" then _diff[2] = 2 end
	if stepsr == "Difficulty_Hard" then _diff[2] = 3 end
	if stepsr == "Difficulty_Challenge" then _diff[2] = 4 end
	_numplayers = _numplayers+1
end

--print("tech num players: ".._numplayers)

-- thank u ky dashiel
local poptions = {GAMESTATE:GetPlayerState(0):GetPlayerOptions('ModsLevel_Song'), GAMESTATE:GetPlayerState(1):GetPlayerOptions('ModsLevel_Song')}
_isusingreverse = {false, false}
_miniscale = {1,1}
for pn = 1, 2 do
	if poptions[pn] then
		_isusingreverse[pn] = poptions[pn]:Reverse() ~= 0
		_miniscale[pn] = (200 - poptions[pn]:Mini()) * 0.005
	end
end

			sw,sh = SCREEN_WIDTH,SCREEN_HEIGHT
			
			curmod = 1
			m_current = {{},{}}
			m_lastframe = {{},{}}
			m_startv = {{},{}}
			m_startt = {{},{}}
			m_endv = {{},{}}
			m_len = {{},{}}
			m_ease = {{},{}}
			m_opt1 = {{},{}}
			m_opt2 = {{},{}}
			m_tweening = {{},{}}
			modnames = {}
			m_isreal = {} --REAL mods that are part of the engine
			
			function definemod(name,initv,real)
				if not initv then initv = 0 end
				if real == nil then real = true end
				table.insert(modnames,name)
				m_isreal[name] = real
				for pn=1,2 do
					m_tweening[pn][name] = false
					m_current[pn][name] = initv
					m_lastframe[pn][name] = -1
					m_startv[pn][name] = initv
					m_endv[pn][name] = initv
					m_startt[pn][name] = 0
					m_len[pn][name] = 0
					m_opt1[pn][name] = 0
					m_opt2[pn][name] = 0
					m_ease[pn][name] = linear
				end
			end
			
			--regular ass mods
			definemod('bgdim',.2,false)
			definemod('starsrot',90,false)
			definemod('starsalp1',1,false)
			definemod('starsalp2',0,false)
			definemod('bgkick',1,false)
			for i=1,7 do
				definemod('bgx'..i,0,false)
				definemod('bgy'..i,0,false)
				definemod('bgrot'..i,0,false)
				definemod('bgzoom'..i,0,false)
				definemod('bgalpha'..i,0,false)
			end
			definemod('drunk')
			definemod('tipsy')
			definemod('stealth')
			definemod('sudden')
			definemod('suddenoffset')
			definemod('brake')
			definemod('beat')
			definemod('tiny')
			definemod('dark')
			definemod('flip')
			definemod('invert')
			definemod('centered')
			definemod('split')
			definemod('cross')
			definemod('alternate')
			definemod('reverse')
			definemod('confusionoffset')
			definemod('darknessx',0,false)
			definemod('darknessy',0,false)
			definemod('darknessalpha',0,false)
			definemod('static',0,false)
			for i=0,7 do
				definemod('dark'..i)
				definemod('tiny'..i)
				definemod('confusionoffset'..i)
			end
			
			--tweens as mods lol
			definemod('x',0,false)
			definemod('y',0,false)
			definemod('z',0,false)
			definemod('rotationx',0,false)
			definemod('rotationy',0,false)
			definemod('rotationz',0,false)
			definemod('zoomx',1,false)
			definemod('zoomy',1,false)
			definemod('zoomz',1,false)
			definemod('zoom',1,false)
			
			mods, ma, ca, mfsb = {}, {}, 1, GAMESTATE:GetSongBeat();
			function mod_do(str,pn) if pn then GAMESTATE:ApplyGameCommand('mod,'..str,pn) else GAMESTATE:ApplyGameCommand('mod,'..str) end end
			local me, m2 = function (t)
				local beat,len,ease,str1,mod = unpack(t)
				for pn=1,2 do
					--print(_diff[pn],t.min)
					if not t.min and not t.only or t.only and _diff[pn] == t.only or t.min and _diff[pn] >= t.min then
						if not t.plr or pn == t.plr then
							table.insert(mods,{beat,len,ease,str1,mod,startVal=t.startVal,opt1=t.opt1,opt2=t.opt2,plr=t.plr})
						end
					end
				end
			end, function (beat,fun,per) table.insert(ma,{beat,fun,per}) end
			
			capturedOrig = false
			origx = {SCREEN_WIDTH*0.25,SCREEN_WIDTH*0.75}
			origy = {SCREEN_HEIGHT*0.5,SCREEN_HEIGHT*0.5}
			origz = {0,0}
			
			function sm2(t)
				local b,l,e,v,mo = unpack(t)
				me{b-.05,.1,linear,v[2],mo,min=t.min,plr=t.plr,only=t.only,opt1=t.opt1,opt2=t.opt2}
				me{b+.05,l-.05,e,v[1],mo,min=t.min,plr=t.plr,only=t.only,opt1=t.opt1,opt2=t.opt2}
			end
			
			function set(t)
				local b,v1,mo = unpack(t)
				me{b,0,linear,v1,mo,min=t.min,plr=t.plr,only=t.only}
			end
			
			_anyplayers = false
			_firstplayer = -1
			
			m2(0,function()
				for pn=1,2 do
					local a = SCREENMAN:GetTopScreen():GetChild('PlayerP'..pn)
					
					local darkSize = math.min((SCREEN_WIDTH*.5)/320,SCREEN_HEIGHT/480)
					
					if a then
						origx[pn] = a:GetX()
						origy[pn] = a:GetY()
						origz[pn] = a:GetZ()
						
						_anyplayers = true
						if _firstplayer == -1 then
							_firstplayer = pn
						end
						
						--print('P'..pn..' x = '.._plr[pn]:GetX())
						_darkness[pn]:x(a:GetX())
						_darkness[pn]:y(SCREEN_CENTER_Y)
						_darkness[pn]:basezoomx(darkSize)
						_darkness[pn]:basezoomy(darkSize)
						_darkmask[pn]:x(a:GetX())
						_darkmask[pn]:y(SCREEN_CENTER_Y)
						_darkmask[pn]:basezoomx(darkSize)
						_darkmask[pn]:basezoomy(darkSize)
					end
					
				end
				if _firstplayer == -1 then
					_firstplayer = 1
				end
				capturedOrig = true
			end,true)
			
			
			--thanks mr thatkid!!!
			local log0_5 = 1/math.log(0.5)
			--Save this so we do one less math.log & division every call, maybe.
			
			function SM5Tiny(amt)
				--takes a nitg tiny% and returns a sm5 tiny%
				--return amt --in nitg, just return base val
				return (math.log(1-0.5*(amt*0.01))*log0_5)*100
			end 
			
			
			me{135.5,1,linear,90,'stealth',min=2}
			me{136.5,4,linear,100,'stealth',min=2}
			set{135.5,100,'beat'}
			set{142.5,0,'beat'}
			me{141,1,linear,0,'stealth',min=2}
			me{16+135.5,1,linear,90,'stealth',min=2}
			me{16+136.5,2,linear,100,'stealth',min=2}
			set{16+135.5,100,'beat'}
			set{16+140.5,0,'beat'}
			me{155.5,1,linear,0,'stealth',min=2}
			set{135.5,100,'beat'}
			
			me{191.5,.5,linear,50,'stealth'}
			me{192,4,outCubic,0,'stealth'}
			
			me{351.5,1,linear,100,'stealth',min=2}
			me{355.5,1,linear,0,'stealth',min=2}
			set{351.5,100,'beat'}
			set{356.5,0,'beat'}
			
			local angs = {90,0,180,-90}
			function only2cols(t)
				local b,l,e,f1,f2,t1,t2 = unpack(t)
				local c = {{f1,t1},{f2,t2}}
				for i=1,#c do
					if c[i][1] ~= c[i][2] then
						--print(b,c[i][1],c[i][2],math.rad(angs[c[i][2]+1]-angs[c[i][1]+1])*100)
						me{b,l,e,math.rad(angs[c[i][2]+1]-angs[c[i][1]+1])*100,'confusionoffset'..c[i][1]+1,min=t.min,only=t.only,plr=t.plr}
						me{b+l,0,linear,0,'confusionoffset'..c[i][1]+1,min=t.min,only=t.only,plr=t.plr}
						me{b+l,0,linear,100,'dark'..c[i][1]+1,min=t.min,only=t.only,plr=t.plr}
						me{b+l,0,linear,0,'dark'..c[i][2]+1,min=t.min,only=t.only,plr=t.plr}
					end
				end
			end
			
			me{236,4,linear,1,'darknessalpha'}
			me{240,8,outQuad,.1,'static',startVal=1}
			me{240,8,outExpo,1,'darknessx'}
			me{240,8,outExpo,1,'darknessy'}
			me{272,8,inOutCubic,0,'darknessalpha'}
			me{272,8,inOutCubic,0,'static'}
			
			me{238,2,inQuad,1000 * SCREEN_HEIGHT/480,'z'}
			me{240,8,outExpo,0,'z'}
			
			set{240,12.5,'flip',min=3}
			set{240,37.5,'invert',min=3}
			set{240,100,'dark2',min=3}
			set{240,100,'dark3',min=3}
			
			only2cols{250,2,outQuart,0,3,1,2}
			only2cols{254,2,outQuart,1,2,0,3}
			only2cols{258,2,outQuart,0,3,1,2}
			only2cols{262,2,outQuart,1,2,1,3}
			only2cols{266,2,outQuart,1,3,0,2}
			only2cols{270,2,outQuart,0,2,0,3}
			
			me{273,2,inOutCubic,0,'flip'}
			me{273,2,inOutCubic,0,'invert'}
			for i=0,3 do
				me{273,2,inOutCubic,0,'dark'..i}
			end
			
			me{279,2,inOutCubic,25,'flip'}
			me{279,2,inOutCubic,-25,'invert'}
			me{279,2,inOutCubic,SM5Tiny(-100),'tiny2'}
			me{279,2,inOutCubic,SM5Tiny(-100),'tiny3'}
			me{279,2,inOutCubic,100,'dark2'}
			
			me{294,4,inOutCubic,314.15,'confusionoffset3'}
			me{294,2,outCubic,SM5Tiny(-200),'tiny3'}
			me{296,2,outCubic,SM5Tiny(-100),'tiny3'}
			
			me{280,2,inOutCubic,4,'cross',only=2}
			me{280,2,inOutCubic,10,'cross',only=4}
			
			me{298,0,linear,0,'dark2'}
			me{298,0,linear,100,'dark3'}
			me{298,0,linear,0,'confusionoffset3'}
			
			me{276,4,inOutCubic,100,'centered'}
			me{276,4,inOutCubic,-112,'y'}
			
			me{311,1,linear,100,'centered'}
			me{311,1,linear,0,'y'}
			me{311,1,linear,0,'flip'}
			me{311,1,linear,0,'invert'}
			me{311,1,linear,100,'cross'}
			me{311,1,linear,SM5Tiny(0),'tiny2'}
			me{311,1,linear,SM5Tiny(0),'tiny3'}
			me{311,1,linear,0,'dark2'}
			me{311,1,linear,0,'dark3'}
			
			for pn=1,2 do
				local reverseamt = _isusingreverse[pn] and 100 or 0
				me{317,2,inOutCubic,reverseamt+100,'reverse',plr=pn}
				me{324,3,inOutCirc,reverseamt,'reverse',plr=pn}
			end
			
			me{324,3,inOutCirc,0,'cross'}
			me{324,3,inOutCirc,0,'centered'}
			
			
			local f = 1
			for i=0,2 do
				me{232+.333*i,.3,outCubic,0,startVal=10*f,'rotationz',min=3}
				me{232+.333*i,.3,outCubic,0,startVal=20*f,'x',min=3}
				f=-f
			end
			for i=0,2 do
				me{233+i,.8,outCubic,0,startVal=10*f,'rotationz',min=3}
				me{233+i,.8,outCubic,0,startVal=20*f,'x',min=3}
				f=-f
			end
			set{278,100,'suddenoffset'}
			me{278,2,linear,100,'sudden'}
			me{311,1,linear,0,'sudden'}
			
			gimmick = {
				{276.500,3,1},
				{276.667,2,1},
				{276.833,1,1},
				{277.000,0,1},
				{277.167,1,1},
				{277.333,2,1},
				{277.500,3,1},
				{277.750,0,1},
				{278.000,2,1},
				{278.500,1,1},
				{279.250,3,1},
				{280.000,0,1},
				{280.833,3,1},
				{281.667,0,1},
				{282.000,2,1},
				{282.500,0,1},
				{283.333,3,1},
				{284.167,0,1},
				{285.000,3,1},
				{285.667,0,1},
				{286.000,2,1},
				{286.333,0,1},
				{287.000,3,1},
				{287.750,0,1},
				{288.000,3,1},
				{288.750,0,1},
				{289.500,3,1},
				{290.000,2,1},
				{290.333,3,1},
				{291.000,0,1},
				{291.667,3,1},
				{292.167,0,1},
				{292.667,3,1},
				{293.333,0,1},
				{293.833,3,1},
				{294.000,2,1},
				{294.750,3,1},
				{295.500,0,1},
				{296.000,3,1},
				{296.833,0,1},
				{297.667,3,1},
				{298.000,1,1},
				{298.500,3,1},
				{299.333,0,1},
				{300.167,3,1},
				{301.000,0,1},
				{301.667,3,1},
				{302.000,1,1},
				{302.333,3,1},
				{303.000,0,1},
				{303.750,3,1},
				{304.000,0,1},
				{304.750,3,1},
				{305.500,0,1},
				{306.000,1,1},
				{306.333,0,1},
				{307.000,3,1},
				{307.667,0,1},
				{308.167,3,1},
				{308.667,0,1},
				{309.333,3,1},
				{309.833,0,1},
				{310.000,1,1},
			}
			
			local f2 = 1
			for i=1,#gimmick do
				local v = gimmick[i]
				local len = 1
				if i < #gimmick then
					len = gimmick[i+1][1]-v[1]
				end
				
				if v[1] < 280 then
					me{v[1],len,linear,0,'tiny',startVal=-50}
				else
					local dir = 0
					if v[2] == 0 or v[2] == 3 then
						dir = v[2] == 0 and -1 or 1
						sm2{v[1],1,outExpo,{0,5*dir},'rotationz',min=2,intime=0.05}
						sm2{v[1],1,outExpo,{0,30*dir},'x',min=2,intime=0.05}
					end
					if v[2] == 1 or v[2] == 2 then
						sm2{v[1],2,outExpo,{0,60},'tipsy',intime=0.05}
						sm2{v[1],2,outExpo,{0,60*f2},'drunk',intime=0.05}
						sm2{v[1],2,outExpo,{0,SM5Tiny(-150)},'tiny',intime=0.05}
					end
				end
				f2 = -f2
			end
			
			
			
			--bg stuff pass
			me{28,8,inOutCubic,0,'starsrot'}
			me{55,4,linear,.3,'static'}
			me{59,1,linear,0,'static'}
			
			definemod('pixel',0,false)
			
			--me{2,4,linear,8,'pixel'}
			
			me{51,8,linear,4,'pixel'}
			me{59,1,linear,0,'pixel'}
			
			
			--set{58,1,'bgalpha1'}
			set{56,.7,'bgzoom1'}
			me{56,4,linear,1,'bgalpha1',startVal=0}
			
			--me{60,4,linear,.8,'bgalpha1'}
			for i=0,15 do
				set{60+i*.25,.4,'bgalpha1'}
				set{60.125+i*.25,1,'bgalpha1'}
			end
			
			sm2{76,2,outExpo,{1,1.5},'bgkick'}
			sm2{78,2,outExpo,{1,1.5},'bgkick'}
			sm2{80,2,outExpo,{1,1.5},'bgkick'}
			
			for i=96,155.5 do
				sm2{i,1,outExpo,{1,1.05},'bgkick'}
			end
			
			
			
			me{60,4,linear,.55,'bgzoom1'}
			me{64,1,outCubic,.2,'bgzoom1'}
			me{64,1,outCubic,0,'bgalpha1'}
			
			set{63,1,'bgalpha7'}
			me{63,2,inOutCubic,.6,'bgzoom7'}
			
			set{91,1,'bgalpha4'}
			set{91,150,'bgx4'}
			me{91,2,inOutCubic,.5,'bgzoom4'}
			
			me{91,2,inOutCubic,.5,'bgzoom7'}
			me{91,2,inOutCubic,-150,'bgx7'}
			
			me{95,2,inOutCubic,0,'bgzoom4'}
			me{95,2,inOutCubic,0,'bgzoom7'}
			
			set{91,1,'bgalpha2'}
			me{95,2,inOutCubic,.6,'bgzoom2'}
			
			set{135.5,.6,'bgzoom7'}
			set{135.5,0,'bgx7'}
			me{135.5,1,linear,1,'bgalpha7',startVal=0}
			me{143.5,1,linear,0,'bgalpha7'}
			me{151.5,1,linear,1,'bgalpha7'}
			--me{155.5,1,linear,0,'bgalpha7'}
			me{155,2,inOutCubic,0,'bgzoom7'}
			me{155,2,inOutCubic,0,'bgzoom2'}
			
			set{155.5,40,'bgx4'}
			set{155.5,1,'bgalpha5'}
			me{159,2,inOutCubic,.6,'bgzoom5'}
			set{156.5,1,'bgalpha4'}
			me{163,2,inOutCubic,-200,'bgx5'}
			
			for i=0,6 do
				if i~= 3 then
					me{163+8*i,2,inOutCubic,.5,'bgzoom4'}
					me{163+8*i,2,inOutCubic,.3,'bgzoom5'}
					me{163+8*i,2,inOutCubic,40,'bgx4'}
					me{163+8*i,2,inOutCubic,-200,'bgx5'}
					if i ~= 6 then
						me{167+8*i,2,inOutCubic,.3,'bgzoom4'}
						me{167+8*i,2,inOutCubic,.5,'bgzoom5'}
						me{167+8*i,2,inOutCubic,200,'bgx4'}
						me{167+8*i,2,inOutCubic,-40,'bgx5'}
					end
				end
			end
			
			for i=208,215 do
				sm2{i,1,outExpo,{1,1.05},'bgkick'}
			end
			for i=216,219.5,.5 do
				sm2{i,.5,outExpo,{1,1.05},'bgkick'}
			end
			sm2{220,1,outExpo,{1,1.05},'bgkick'}
			
			sm2{192,8,outExpo,{.5,.7},'bgzoom5'}
			me{191,1,inExpo,180,'bgrot5'}
			me{192,4,outExpo,0,'bgrot5',startVal=-180}
			
			me{215,2,inOutCubic,0,'bgzoom4'}
			me{215,2,inOutCubic,0,'bgzoom5'}
			
			set{215,1,'bgalpha1'}
			set{215,0,'bgx1'}
			me{215,2,inOutCubic,.6,'bgzoom1'}
			me{223,2,inOutCubic,0,'bgzoom1'}
			
			set{224,50,'drunk',only=4}
			
			set{225,0,'drunk',only=4}
			set{225,50,'tipsy',only=4}
			
			set{226,-50,'drunk',only=4}
			set{226,0,'tipsy',only=4}
			
			set{227,0,'drunk',only=4}
			set{227,-50,'tipsy',only=4}
			
			set{228,50,'drunk',only=4}
			set{228,50,'tipsy',only=4}
			set{229,-50,'drunk',only=4}
			set{229,50,'tipsy',only=4}
			set{230,50,'drunk',only=4}
			set{230,-50,'tipsy',only=4}
			
			me{231,2,outExpo,0,'drunk',only=4}
			me{231,2,outExpo,0,'tipsy',only=4}
			
			for i=0,7 do
				me{224+i,.8,outCubic,0,'brake',startVal=50,min=3}
			end
			
			set{240,0,'bgdim'}
			set{240,1,'starsalp2'}
			me{311,1,linear,0,'starsalp2'}
			
			set{240,.5,'bgalpha6'}
			set{240,1,'bgzoom6'}
			
			me{276,4,inOutCubic,.5,'bgzoom6'}
			me{276,4,inOutCubic,.5,'bgalpha6'}
			me{276,4,inOutCubic,-150,'bgx6'}
			
			set{276,.5,'bgalpha3'}
			set{276,150,'bgx3'}
			me{276,4,inOutCubic,.5,'bgzoom3'}
			
			function st(b,l)
				me{b-l,l,outCubic,.5,'static'}
				me{b,l,outCubic,0,'static'}
			end
			function px(b,l)
				me{b-l,l,outCubic,10,'pixel'}
				me{b,l,outCubic,0,'pixel'}
			end
			
			px(311.5,1)
			px(327.5,1)
			px(343.5,1)
			px(359.5,1)
			
			me{311,1,linear,.3,'bgdim'}
			me{311,1,linear,0,'bgalpha3'}
			me{311,1,linear,0,'bgalpha6'}
			set{311,0,'bgx7'}
			set{311,.6,'bgzoom7'}
			me{311,1,linear,1,'bgalpha7',startVal=0}
			
			me{327,1,linear,0,'bgalpha7'}
			set{327,0,'bgx5'}
			set{327,.6,'bgzoom5'}
			me{327,1,linear,1,'bgalpha5',startVal=0}
			
			me{343,1,linear,0,'bgalpha5'}
			set{343,0,'bgx2'}
			set{343,.6,'bgzoom2'}
			me{343,1,linear,1,'bgalpha2',startVal=0}
			me{351.5,1,linear,1,'bgalpha7'}
			me{355.5,1,linear,0,'bgalpha7'}
			
			me{359,1,linear,0,'bgalpha2'}
			me{359,1,linear,1,'bgalpha7'}
			
			me{367,1,linear,0,'bgalpha7'}
			set{367,0,'bgx6'}
			set{367,.6,'bgzoom6'}
			me{367,1,linear,1,'bgalpha6',startVal=0}
			me{371,1,linear,0,'bgalpha6'}
			set{371,0,'bgx1'}
			set{371,.6,'bgzoom1'}
			me{371,1,linear,1,'bgalpha1',startVal=0}
			me{371,1,linear,.5,'bgdim'}
			
			me{375,2,inOutCirc,.5,'bgzoom1'}
			me{377,7,inQuad,.2,'bgzoom1'}
			me{377,7,linear,0,'bgalpha1'}
			
			me{384,8,linear,0,'starsalp1'}
			
			
			function cmp(a,b)
				return a[1] < b[1]
			end
			if table.getn(ma) > 1 then
				table.sort(ma, cmp)
			end
			if table.getn(mods) > 1 then
				table.sort(mods, cmp)
			end

local ac = Def.ActorFrame{
	
	Def.Actor{
		OnCommand=function(s)
			s:queuecommand('Loop')
		end,
		LoopCommand=function(self)
			local beat = GAMESTATE:GetSongBeat()
			if beat > mfsb+0.1 then
				
				while curmod <= #mods and beat > mods[curmod][1] do
					local v = mods[curmod]
					
					local mn = v[5]
					local dur = v[2]
					if v.timing and v.timing == 'end' then
						dur = v[2]-v[1]
					end
					
					print('launch attack '..v[4]..' '..mn..' at beat '..v[1])
					
					if v.plr and not v.pn then v.pn = v.plr end
					
					for pn=1,2 do
						if not v.pn or pn == v.pn then
							m_startt[pn][mn] = v[1]
							m_len[pn][mn] = dur
							m_ease[pn][mn] = v[3]
							if v.startVal then
								m_startv[pn][mn] = v.startVal
							else
								m_startv[pn][mn] = m_current[pn][mn]
							end
							if v.add then
								m_endv[pn][mn] = m_current[pn][mn]+v[4]
							else
								m_endv[pn][mn] = v[4]
							end
							m_opt1[pn][mn] = v.opt1
							m_opt2[pn][mn] = v.opt2
							m_tweening[pn][mn] = true
						end
					end
					
					curmod = curmod+1
				end
				
				for pn=1,2 do
					for _,v in pairs(modnames) do
						if m_tweening[pn][v] then
							local curtime = beat - m_startt[pn][v]
							local duration = m_len[pn][v]
							local startstrength = m_startv[pn][v]
							local diff = m_endv[pn][v] - startstrength
							local curve = m_ease[pn][v]
							local strength = curve(curtime, startstrength, diff, duration, m_opt1[pn][v], m_opt2[pn][v])
							m_current[pn][v] = strength
							if beat > m_startt[pn][v]+duration then
								m_tweening[pn][v] = false
							end
						else
							m_current[pn][v] = m_endv[pn][v]
						end
					end
				end
				
				--ONLY apply mods if there were changes THIS frame
				for pn=1,2 do
					local mstr = ''
					for _,v in pairs(modnames) do
						if m_isreal[v] and m_lastframe[pn][v] ~= m_current[pn][v] then
							mstr = mstr..'*10000 '..m_current[pn][v]..' '..v..','
							m_lastframe[pn][v] = m_current[pn][v]
						end
					end
					if mstr ~= '' then
						mod_do(mstr,pn)
					end
				end
				
				if capturedOrig then
					for pn=1,2 do
						local a = SCREENMAN:GetTopScreen():GetChild('PlayerP'..pn)
						if a then
						
							a:x(origx[pn]+m_current[pn].x*SCREEN_HEIGHT/480)
							if _isusingreverse[pn] then
								a:y(origy[pn]-m_current[pn].y*SCREEN_HEIGHT/480)
							else
								a:y(origy[pn]+m_current[pn].y*SCREEN_HEIGHT/480)
							end
							a:z(origz[pn]+m_current[pn].z)
							if _isusingreverse[pn] then
								a:rotationx(-m_current[pn].rotationx)
							else
								a:rotationx(m_current[pn].rotationx)
							end
							a:rotationy(m_current[pn].rotationy)
							a:rotationz(m_current[pn].rotationz)
							a:basezoomx(m_current[pn].zoomx*m_current[pn].zoom)
							a:basezoomy(m_current[pn].zoomy*m_current[pn].zoom)
							a:zoomz(m_current[pn].zoomz*m_current[pn].zoom)

						end
					end
				
					if _anyplayers then
						_darkcover:diffusealpha(m_current[_firstplayer].darknessalpha)
					end
					
					for pn=1,2 do
						local a = SCREENMAN:GetTopScreen():GetChild('PlayerP'..pn)
						if a then
							_darkness[pn]:zoomx(m_current[pn].darknessx)
							_darkness[pn]:zoomy(m_current[pn].darknessy)
							_darkness[pn]:diffusealpha(m_current[pn].darknessalpha)
							
							_darkmask[pn]:zoomx(m_current[pn].darknessx)
							_darkmask[pn]:zoomy(m_current[pn].darknessy)
						else
							_darkmask[pn]:visible(false)
						end
					end
					
					--print(_static)
					--print(m_current[_firstplayer])
					--print(m_current[_firstplayer].static)
					_static:diffusealpha(m_current[_firstplayer].static)
					
					for i=1,2 do
						local a = _stars[i]
						if a then
							a:rotationz(m_current[_firstplayer].starsrot)
							a:diffuse(1,1,1,m_current[_firstplayer]['starsalp'..i])
						end
					end
					
					local dim = 1-m_current[_firstplayer].bgdim
					for i=1,7 do
						local a = _bgs[i]
						if a then
							local offs = (i/7)*2*math.pi
							if i == 7 then
								offs = (2/7)*2*math.pi
							end
					
							a:zoom(m_current[_firstplayer]['bgzoom'..i] * m_current[_firstplayer].bgkick)
							local addx = 6 * math.sin(beat*.1*math.pi+offs)
							local addy = 6 * math.cos(beat*.1*math.pi+offs)
							a:x(SCREEN_CENTER_X+(SCREEN_HEIGHT/480)*(addx+m_current[_firstplayer]['bgx'..i]))
							a:y(SCREEN_CENTER_Y+(SCREEN_HEIGHT/480)*(addy+m_current[_firstplayer]['bgy'..i]))
							a:rotationz(m_current[_firstplayer]['bgrot'..i])
							a:rotationx(5 * math.sin(beat*.125*math.pi+offs))
							a:rotationy(5 * math.cos(beat*.125*math.pi+offs))
							a:diffuse(dim,dim,dim,m_current[_firstplayer]['bgalpha'..i])
						end
					end
					
					gemini_pixel1:zoom(1/(1+(m_current[_firstplayer].pixel * SCREEN_HEIGHT/480)))
					gemini_pixel2:zoom((1+(m_current[_firstplayer].pixel * SCREEN_HEIGHT/480)))
					gemini_pixel2:visible(m_current[_firstplayer].pixel > 0)
				end
				
				while ca<=table.getn(ma) and GAMESTATE:GetSongBeat()>=ma[ca][1] do
					if ma[ca][3] or GAMESTATE:GetSongBeat() < ma[ca][1]+2 then
						ma[ca][2]()
					end
					ca = ca+1
				end
			end
			self:sleep(1/60) self:queuecommand('Loop')
		end
	},
	
	Def.Sprite{
		Delay0000= 0.034,
		Delay0001= 0.034,
		Delay0002= 0.034,
		Delay0003= 0.034,
		Frame0000= 0,
		Frame0001= 1,
		Frame0002= 2,
		Frame0003= 3,
		InitCommand= function(self) _static = self; self:SetTextureFiltering(false) end,
		OnCommand= cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;diffusealpha,0;scaletocover,0,0,SCREEN_WIDTH,SCREEN_HEIGHT),
		Texture= "_static 4x1.png",
	},

	
	LoadActor("darkness")..{ InitCommand=function(self) _darkness[1] = self end, OnCommand=cmd(diffusealpha,0) },
	LoadActor("darkness")..{ InitCommand=function(self) _darkness[2] = self end, OnCommand=cmd(diffusealpha,0) },
	LoadActor("darkness")..{ InitCommand=function(self) _darkmask[1] = self end, OnCommand=cmd(zwrite,1;blend,"noeffect";) },
	LoadActor("darkness")..{ InitCommand=function(self) _darkmask[2] = self end, OnCommand=cmd(zwrite,1;blend,"noeffect";) },
	
	Def.Quad{
		InitCommand=function(self) _darkcover = self end,
		OnCommand=cmd(diffuse,1,1,1,0;stretchto,0,0,SCREEN_WIDTH,SCREEN_HEIGHT;ztestmode,"writeonpass";)
	},

	Def.Quad{ InitCommand=cmd(visible,false), OnCommand=cmd(sleep,9E9) },
	
	--RECURSIVE DIGGER -Used to obtain all accessible screen elements
	Def.Quad{
		OnCommand=cmd(visible,false;sleep,1;queuecommand,"ListActors"),
		ListActorsCommand=function(self)
			
			if LIST_ACTORS then
				local file = RageFileUtil.CreateRageFile()
				local path=GAMESTATE:GetCurrentSong():GetSongDir();
				file:Open( path.."lua/TopscreenActorList.txt", 2 ) --2 = write
				
				file:PutLine("Actors part of TopScreen in "..THEME:GetCurThemeName())
				
				function listall(name, actor, level)
					--[[
					if name == "SongForeground" then
						local tabs = ''
						for i=1,level do
							tabs = tabs..'\t'
						end
						file:PutLine(tabs.."(SongForeground contains every actor placed into the fgchanges layer,")
						file:PutLine(tabs.."But that information is not relevant to this list)")
					end
					]]
					if string.sub(tostring(actor),1,10) == "ActorFrame" then
						local tabs = ''
						for i=1,level do
							tabs = tabs..'\t'
						end
						local str = tabs.."Actors part of "..name.." in "..THEME:GetCurThemeName()
						print(str)
						file:PutLine(str)
						for i,v in pairs(actor:GetChildren()) do
							if i and i~= "" then
								if string.sub(name,1,7) == "unnamed" then
									local str2 = tabs.."\tunnamed (within "..name.."):GetChild('"..i.."'); ("..tostring(v)..")"
									file:PutLine(str2);
									listall("unnamed (within "..name..")",v,level+1);
								else
									local str2 = tabs.."\tGetChild('"..name.."'):GetChild('"..i.."'); ("..tostring(v)..")"
									file:PutLine(str2);
									listall(i,v,level+1);
								end
							else
								local str3 = tabs.."\tunnamed actor in "..name.."... ("..tostring(v)..")"
								file:PutLine(str3);
								listall("unnamed (within "..name..")",v,level+1);
							end
						end
					end
				end
				
				local level = 1
				for i,v in pairs(SCREENMAN:GetTopScreen():GetChildren()) do
					if i and i~= "" then
						local str = "\tSCREENMAN:GetTopScreen():GetChild('"..i.."'); ("..tostring(v)..")"
						print(str)
						file:PutLine(str);
						listall(i,v,level+1);
					else
						local str = "\tunnamed actor... ("..tostring(v)..")"
						print(str)
						file:PutLine(str);
						listall("unnamed (top level)",v,level+1);
					end
				end
				
				file:Close();
			
			end
			
		end
	},
	
	Name= "xtl_actor_d",
	
	Def.ActorFrameTexture{
	Name = "ScreenTex";
	InitCommand=function(self)
		self:SetTextureName( "ScreenTex" )
		self:SetWidth(sw);
		self:SetHeight(sh);
		self:EnableAlphaBuffer(true);
		self:Create();
	end;
	OnCommand=function(self)
		--SCREENMAN:GetTopScreen():GetChild('SongBackground'):rotationz(20)
	end;
	PixelMessageCommand=function(self)
		self:visible(true);
		self:Draw();
	end;
		Def.Quad{ OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;diffuse,0,0,0,1), },
		
		Def.ActorProxy{ Name = "ProxyBG"; OnCommand=function(self) self:x(0); self:y(0) self:SetTarget(the_whole_bg); end },
		
		Def.Quad{ OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;diffuse,0,0,0,1-PREFSMAN:GetPreference('BGBrightness')), },
		
		Def.ActorProxy{ Name = "ProxyUL"; OnCommand=function(self) self:x(0); self:y(0) self:SetTarget(SCREENMAN:GetTopScreen():GetChild('Underlay')); end },
		Def.ActorProxy{ Name = "ProxyP1"; OnCommand=function(self) self:x(0); self:y(0)
			
			if not string.find(SCREENMAN:GetTopScreen():GetName(),"^ScreenEdit") then
				if SCREENMAN:GetTopScreen():GetChild('PlayerP1') then
					self:SetTarget(SCREENMAN:GetTopScreen():GetChild('PlayerP1'));
				end
			else
				for _, actor in ipairs(SCREENMAN:GetTopScreen():GetChild('')) do
					if tostring(actor):find("Player") then self:SetTarget(actor); end
				end
			end
			
		end },
		Def.ActorProxy{ Name = "ProxyP2"; OnCommand=function(self) self:x(0); self:y(0)
			if SCREENMAN:GetTopScreen():GetChild('PlayerP2') then
				self:SetTarget(SCREENMAN:GetTopScreen():GetChild('PlayerP2'));
			end
		end },
		Def.ActorProxy{ Name = "ProxyOL"; OnCommand=function(self) self:x(0); self:y(0) self:SetTarget(SCREENMAN:GetTopScreen():GetChild('Overlay')); end },
		
		Def.ActorProxy{ Name = "ProxyStatic"; OnCommand=function(self) self:x(0); self:y(0) self:SetTarget(_static); end },

	
	},
	
	Def.ActorFrameTexture{
	Name = "ScreenPixel";
	InitCommand=function(self)
		self:SetTextureName( "ScreenPixel" )
		self:SetWidth(sw);
		self:SetHeight(sh);
		self:EnableAlphaBuffer(true);
		self:Create();
	end;
	PixelMessageCommand=function(self)
		self:visible(true);
		self:Draw();
	end;
		Def.Sprite{
			Texture = "ScreenTex";
			OnCommand = function(self)
				gemini_pixel1 = self
				self:y(scy)
				self:x(scx)
				self:zoom(1)
				self:visible(true);
			end,
		},
	},

	Def.Sprite{
		Texture = "ScreenPixel";
		OnCommand = function(self)
			gemini_pixel2 = self
			self:y(scy)
			self:x(scx)
			self:zoom(1)
			self:SetTextureFiltering(false)
			self:visible(false);
		end,
	},
	
	
}
return ac