//Golden Shine: Boing wanted this in, so I've made some minor code adjustments to these stage selection gates from Blue Torch!
//Mostly did some optimizations, merging, and personalization.

freeslot("SPR_XPSG", "MT_XPSTAGEGATE")

mobjinfo[MT_XPSTAGEGATE] = {
//$Name XPACK Stage Gate
//$Sprite XPSGA0
//$Category XPACK
//$Arg0 Warp to Map
//$Arg1 Type
//$Arg2 Color
doomednum = 4002,
spawnstate = S_THOK,
speed = 1,
radius = 55*FRACUNIT,
height = 90*FRACUNIT,
flags = MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT,
}

--Golden Shine: Made this a NON-global MobjSpawn hook, since that's much more intense on performance.
addHook("MobjSpawn", function(s) if not (s and s.valid) return end --
	s.waittimer = 0 
	s.tics = -1
	s.sprite = SPR_XPSG
	s.renderflags = RF_SEMIBRIGHT
	if s.tanation == nil
		local ghs = P_SpawnMobjFromMobj(s,0,0,s.height/2,MT_THOK)
		ghs.sprite = SPR_OILF
		ghs.frame = A|FF_TRANS90|FF_FULLBRIGHT
		ghs.tics = -1
		ghs.flags = MF_SCENERY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NOBLOCKMAP
		ghs.tracer,ghs.target,ghs.tanation = s,s,s
		ghs.blendmode = AST_ADD
		s.tanation = light
	end
end, MT_XPSTAGEGATE)

addHook("MobjThinker", function(s) if not (s and s.valid and s.spawnpoint) return end --
	if ((s.stagespawned or 0) < 2) --Doing setup.
		local ARGS = s.spawnpoint.args
		if ARGS[0]
			s.warp = s.spawnpoint.args[0]
		end
		if not (ARGS[1]) -- Stage Gate Types
			s.spawntype = 0
		else
			if ARGS[1] == 1
				s.spawntype = 1
			elseif ARGS[1] == 2
				s.spawntype = 2
				if ARGS[2]
					s.color = ARGS[2]
					if s.tanation s.tanation.color = ARGS[2] end
				end
			end
		end
		s.stagespawned = s.stagespawned and $+1 or 1
	else
		local ghs = s.tanation
		if ghs and ghs.valid
			local OFF = (leveltime%3==0) and 1200 or (leveltime%2) and 550 or 1
			ghs.spritexscale = s.spritexscale+OFF
			ghs.spriteyscale = s.spriteyscale+OFF
		end
		if s.SHCD 
			s.SHCD = $-1
		end
		if s.waittimer --Waiting time before you can touch it again.
			s.waittimer = $-1
		end
	end
end, MT_XPSTAGEGATE)

addHook("TouchSpecial",function(s, v) --Use a Stage Gate if...
	if v.player	
		local p = v.player
		if p.valid and not (p.bot)
		and ((netgame!=true) or (p==server) or (IsPlayerAdmin(p)))
			if (s.waittimer)				
			or ( 
			(p.speed < 34<<16) --GS: Gonna make this ALOT more strict than the original. 
			and p.cmd.buttons==0 and p.cmd.sidemove==0 and p.cmd.forwardmove==0
			and not (p.pflags & (PF_SPINNING|PF_THOKKED|PF_JUMPED|PF_NOJUMPDAMAGE)) 
			and (p.panim <= PA_RUN) and (p.panim >= PA_IDLE)
			and p.mo and p.mo.valid and P_IsObjectOnGround(p.mo)
			and not (p.xsonictable and p.xsonictable.FreeFlight and p.xsonictable.FreeFlight.LockOn)
			)
				if s.SHCD 
					if (s.SHCD < 8) s.SHCD = $+1 end return true --
				end
				if not (p.mo.XP_selectingstage) and not s.waittimer
					if tonumber(s.warp) == nil
						p.mo.XP_mapselected = s.angle/ANG1
					else
						p.mo.XP_mapselected = tonumber(s.warp)
					end
					p.mo.XP_selectingstage = true
				end
				s.waittimer = 21
			end
		end
	end
	return true --Make sure it returns true, otherwise it dies.
end, MT_XPSTAGEGATE)

--Now for the HUD part.
if not customhubhud rawset(_G, "customhubhud", {}) end
local CH = customhubhud
if CH
	CH["modernsonic"] =	true
	CH["werehog"] =		true
	CH["takis"] = 		true
	CH["samus"] = 		true
	CH["basesamus"] = 	true
end

local FL = V_PERPLAYER|V_HUDTRANS
local modname = "customhubhud"
local altmodname = "vanilla"

local function hubworldhud(v, p) if not (p.mo and p.mo.valid) return end 
	local s = p.mo
	local SKIN = p.mo.skin
	
	if not customhubhud[SKIN] and not mapheaderinfo[gamemap].hubworld
		customhud.SetupItem("score", altmodname)
		customhud.SetupItem("time", altmodname)
		customhud.SetupItem("rings", altmodname)
		customhud.SetupItem("stagetitle", altmodname)
		customhud.SetupItem("lives", altmodname)
		customhud.disable("hubhud")
	elseif mapheaderinfo[gamemap].hubworld and not customhubhud[SKIN]
		customhud.enable("hubhud")
		customhud.SetupItem("score", modname)
		customhud.SetupItem("time", modname)
		customhud.SetupItem("rings", modname)
		customhud.SetupItem("lives", modname)	
		
		local hubhudx = 0
		local hubhudstartx = 0
		local hubhuddestx = -100		
		
		local hubtime = min(s.XP_hubtimer or 0, 35)
		local LIVES = p.lives or 0
		local CM = 	v.getColormap(SKIN, s.color)
		hubhudx = ease.inquint(FixedDiv(hubtime, 35), hubhudstartx, hubhuddestx)

		local p_hud1 = v.cachePatch("HUB1")
		local p_hud2 = v.cachePatch("HUB2")
		local p_lifehud = v.getSprite2Patch(SKIN, SPR2_XTRA, false, A)
			
		v.drawScaled(0+(hubhudx<<16), 0, FRACUNIT, p_hud1, FL|V_SNAPTOTOP|V_SNAPTOLEFT, CM)
		v.drawScaled(0+(hubhudx<<16), 177, FRACUNIT, p_hud2, FL|V_SNAPTOLEFT|V_SNAPTOBOTTOM, CM)
		if p_lifehud --Make sure it's valid
			v.drawScaled(4<<16+(hubhudx<<16), 179<<16, FRACUNIT/2, p_lifehud,FL|V_SNAPTOLEFT|V_SNAPTOBOTTOM, CM)
		end
		v.drawString(16+(hubhudx), 7, " : "+tostring(p.rings or 0), V_PERPLAYER|V_HUDTRANS|V_SNAPTOTOP|V_SNAPTOLEFT)
		if (LIVES >= 0) and (LIVES <= 99)
			v.drawString(22+(hubhudx), 182, " : "+tostring(LIVES), V_PERPLAYER|V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM)
		end
	end
end

addHook("PlayerThink", function(p) -- Player HUD Code
	if not (p.valid and p.mo and p.mo.valid) return end
	local s = p.mo	
	if not (s.XP_selectingstage)
		if s.XP_stagetimer
			s.XP_stagetimer = $-1
		end
		if s.XP_fadetimer
			s.XP_fadetimer = $-1
		end
		if s.XP_hubtimer
			s.XP_hubtimer = $-1
			s.XP_jump,s.XP_spin = 99<<16,99<<16
		end
	else --Currently selecting a stage.	
		if s.XP_hubtimer == nil --Still didn't set up...? Well, set it up.
			s.XP_stagetimer,s.XP_jump,s.XP_spin,s.XP_fadetimer,s.XP_hubtimer = 1,2,2,1,1
		else
			if (s.XP_hubtimer < 35)
				s.XP_hubtimer = $+1
			end
			if (s.XP_stagetimer < 35)
				s.XP_stagetimer = $+1
			end
			if (s.XP_fadetimer < 15)
				s.XP_fadetimer = $+1
			end
		end
		if not p.powers[pw_carry]
			p.powers[pw_carry] = 19201
		end
		p.powers[pw_ignorelatch] = (1<<15)+2		
		p.pflags = $|PF_FULLSTASIS --Keep in stasis for now.
		s.XP_jump = (p.cmd.buttons & BT_JUMP) and $+1 or 0
		s.XP_spin = (p.cmd.buttons & BT_USE) and $+1 or 0
		if s.XP_jump==1 or s.XP_spin==1
			p.pflags = $ & ~ PF_FULLSTASIS
			if p.powers[pw_carry]==19201
				p.powers[pw_carry] = 0
			end
			s.SHCD = 77 
			s.XP_selectingstage = nil
			S_StartSound(nil, (p.cmd.buttons & BT_JUMP) and sfx_menu1 or sfx_kc65, p)
			if (p.cmd.buttons & BT_JUMP)
				if tonumber(s.XP_mapselected) --Must be valid!
					G_SetCustomExitVars(s.XP_mapselected, 1)
				end
				G_ExitLevel()
			end
		end		
	end
end)

local function stageselect(v, p)
	local s = p.mo
	local map = (s.XP_mapselected) and s.XP_mapselected or gamemap or 1
	
	//Text
	local text1 = ""
	local text1height = v.levelTitleHeight(text1)
	
	//Map
	local mapname = "UNKNOWN" -- Placeholder if there is no lvlttl
	local mapact = "Travel?" -- General Name
	
	local MAP = mapheaderinfo[map]
	if MAP
		if MAP.lvlttl
			mapname = MAP.lvlttl
		end
		if (MAP.actnum) --Act Num
			mapact = ""+MAP.actnum
		end
		if (MAP.levelflags & LF_WARNINGTITLE) -- BOSS
			mapact = "\133Travel?"
		end
	end
	
	//Select
	local stage1 = v.cachePatch("STAGSLCT1")
	local stage2 = v.cachePatch("STAGSLCT2")
	local stage3 = v.cachePatch("STAGSLCT3")
	
	local prompt1 = "Jump : \131Accept"
	local prompt2 = "Spin : \133Cancel"

	local mapicon = v.cachePatch( (G_BuildMapName(map))+"P" )

	
	local stage1x,stage2x,stage3x = -300,-300,-300
	local stage1startx,stage2startx,stage3startx = -300,-300,-300
	
	local stage1destx,stage2destx,stage3destx = 0,20,20
	
	//Timer
	local stage1time = min(s.XP_stagetimer or 0, 35)
	
	//Movement
	stage1x = ease.outquint(FixedDiv(stage1time, 35), stage1startx, stage1destx)
	stage2x = ease.outquint(FixedDiv(stage1time, 35), stage2startx, stage2destx)
	stage3x = ease.outquint(FixedDiv(stage1time, 35), stage3startx, stage3destx)
	
	v.fadeScreen(0xFF00, s.XP_fadetimer or 0)
	
	//Drawing
	v.drawScaled(stage1x<<16, 10<<16, FRACUNIT, stage1, FL|V_SNAPTOTOP|V_SNAPTOLEFT)
	v.drawLevelTitle((stage1x+10), 10+text1height, text1, FL|V_SNAPTOTOP|V_SNAPTOLEFT)
	v.drawString(stage3x+48, 184, prompt1, FL, "left")
	v.drawString(stage3x+239, 184, prompt2, FL, "right")
	v.drawScaled(stage2x<<16, 0, FRACUNIT, stage2, FL)
	v.drawString((stage2x+144), 68, mapname, FL, "center") 
	v.drawScaled(stage3x<<16, 0, FRACUNIT, stage3, FL)
	if mapicon 
		local imnothere = v.cachePatch("MISSING")	
		if mapicon != imnothere -- Don't draw a icon if there is none.
			v.drawScaled((stage3x+151)<<16, 122<<16, 1<<15, mapicon, FL)
		end
	end
	v.drawString(stage3x+57, 105, mapact, FL)
end

hud.add(function(v, p)
	if not ((gamestate==GS_LEVEL) and p.mo) return end --In a stage or fuck off.
	customhud.SetupItem("hubhud", modname, hubworldhud(v, p))
	
	customhud.SetupItem("stageselect", modname, stageselect(v, p))
end)