--Borrowed some code from XMomentum for the Hyper Code, the Hyper Dash lua done by me, Sir Thoksalot. This script is Reusable so do whatever the hell you want with it
addHook("PlayerThink", function(player)

    local function hasHyperForm(player)
	    if (player.mo and player.mo.valid)
	        if (player.mo.skin == "ultsonic") then
		        return true
			end
			return false
		end
	end

	local function DeleteThok(player)
        if player.mo and player.mo.valid
        	if (player.charability) and (player.deletethok == true) --and (player.dashdown)
       	     	player.charability = CA_NONE
				player.deletethok = false
			end
    	end
    end

	local function isTransforming(player)
        if player.mo.state == S_PLAY_SUPER_TRANS1
		or player.mo.state == S_PLAY_SUPER_TRANS2
		or player.mo.state == S_PLAY_SUPER_TRANS3
		or player.mo.state == S_PLAY_SUPER_TRANS4
		or player.mo.state == S_PLAY_SUPER_TRANS5
		or player.mo.state == S_PLAY_SUPER_TRANS6 then
		    return true
    	end
    end
	--These Hyper Stars are a WIP, and look kind of shitty imho
	local function SpawnHyperStars(player)
	    local hyperstar = P_SpawnMobjFromMobj(player.mo, P_RandomRange(-14, 13) *FixedMul(5, player.mo.scale),  P_RandomRange(-15, 14) * FRACUNIT, 9*FRACUNIT, MT_SUPERSPARK)
		hyperstar.momx = P_RandomRange(-14, 14) * FRACUNIT + FixedMul(-12, 12, player.mo.scale)
		hyperstar.momy = P_RandomRange(-14, 14) * FRACUNIT + FixedMul(-12, 12, player.mo.scale)
		hyperstar.momz = P_RandomRange(-8, 8) * FRACUNIT + FixedMul(-12, 12, player.mo.scale)
		hyperstar.fuse = 5
		hyperstar.scale = player.mo.scale * 20 / 23
		hyperstar.source = player.mo
	end

	--Only ultsonic can become Hyper ultsonic
	if hasHyperForm(player)
		--You need to collect 100 rings to go Hyper
		if player.rings >= 100 and not player.powers[pw_super]
			player.canturnhyper = true
		end
		if player.rings < 100 and not player.powers[pw_super]
			player.canturnhyper = false
		end
		if not (player.powers[pw_super] and player.canturnhyper == true)
			player.ishyper = false
		else 
		    player.ishyper = true
		end
		--This is the cost of being OP, a double ring drain, you're welcome :)
		if (leveltime % 35 == 18) and (player.powers[pw_super] >= 2) and (player.ishyper == true)
			P_GivePlayerRings(player, -1)
		end
		if (player.ishyper == true)
			--ooh rainbow
			local function getHyperColor(player)
			    if (player.mo.skin == "ultsonic")
			    	if player.mo.state != S_PLAY_SUPER_TRANS1 and player.mo.state != S_PLAY_SUPER_TRANS2 and player.mo.state != SUPER_TRANS3
                        player.mo.color = (SKINCOLOR_HYPER_SEIZURE1 + abs( ( (leveltime >> 1) % 17) - 5))
			    	end
			    end
			end
			SpawnHyperStars(player)
			getHyperColor(player)
			player.thrustfactor = skins[player.mo.skin].thrustfactor * 54 / 41
			--Return ultsonic's CA_THOK charability
			if not (player.deletethok == false) then	
		    	DeleteThok(player) --I have no idea what I'm doing..
			end
			--Hyper ultsonic: "Oxygen? What's that?"
			if (player.mo.eflags & MFE_UNDERWATER)
				player.powers[pw_underwater] = 0
			end
			if P_InSpaceSector(player.mo)
				player.powers[pw_spacetime] = 0
			end
			
			if (player.speed > 3*FRACUNIT or player.mo.momz > 3*FRACUNIT or player.mo.momz < -3*FRACUNIT) and not isTransforming(player) then
				local ghost = P_SpawnGhostMobj(player.mo) --God I wish the games hardcoded afterimages could be recolored with lua
				ghost.fuse = 4	
				ghost.colorized = true
				ghost.color = player.mo.color
				ghost.rollangle = player.mo.rollangle
			end
		else
		    player.thrustfactor = skins[player.mo.skin].thrustfactor
		end
	end
end)

addHook("AbilitySpecial", function(player)

    --My attempt to port S3&K's Hyper ultsonic dash to SRB2
    local function Do3DHyperDash(player) --Handles dashing in 3D
        S_StartSound(player.mo, sfx_s3kb6) 
        P_Earthquake(player.mo, player.mo, 256*FRACUNIT)
    	P_StartQuake(79*FRACUNIT, 3)
    	P_RadiusAttack(player.mo, player.mo, 1214*FRACUNIT)
		P_FlashPal(player, PAL_WHITE, 3)
    	player.pflags = $ | PF_THOKKED
    	if (player.cmd.forwardmove) and not (((player.pflags & PF_USEDOWN) and (player.cmd.forwardmove) or ((player.cmd.forwardmove) and (player.cmd.sidemove))) and not (player.mo.state == S_PLAY_FLOAT or player.mo.state == S_PLAY_FLOAT_RUN))
    	   P_InstaThrust(player.mo, player.mo.angle, player.actionspd * 10 / 7)
		   player.dashforward = true --Forward Dash
    	elseif ((player.cmd.forwardmove) and (player.cmd.sidemove)) and not ((player.pflags & PF_USEDOWN) and not (player.mo.state == S_PLAY_FLOAT or player.mo.state == S_PLAY_FLOAT_RUN))
    	   P_InstaThrust(player.mo, player.drawangle, player.actionspd * 10 / 7)
		   player.dashangled = true  --Diagonal Dash
		elseif (player.cmd.sidemove) and not ((player.cmd.forwardmove) and (player.cmd.sidemove))  and not ((player.pflags & PF_USEDOWN) and not (player.mo.state == S_PLAY_FLOAT or player.mo.state == S_PLAY_FLOAT_RUN))
    	   P_InstaThrust(player.mo, player.drawangle, player.actionspd * 10 / 7)
		   player.dashside = true --Sideways Dash
    	elseif P_GetPlayerControlDirection(player) == 0 and not ((player.pflags & PF_USEDOWN) and not (player.mo.state == S_PLAY_FLOAT or player.mo.state == S_PLAY_FLOAT_RUN))
    	   P_SetObjectMomZ(player.mo, 20*FRACUNIT, false)
		   player.speed = 1 --Momentum cut lul
		   player.dashup = true --Upward Dash
		elseif (player.pflags & PF_USEDOWN) and not (player.mo.state == S_PLAY_FLOAT or player.mo.state == S_PLAY_FLOAT_RUN)
           P_SetObjectMomZ(player.mo, -25*FRACUNIT, false)
	       player.speed = 1 --Momentum cut lul
	       player.dashdown = true --Downward Dash
	       player.deletethok = true
		   return false
		end
		player.deletethok = false
    end

    local function Do2DHyperDash(player) --Handles dashing in 2D
        S_StartSound(player.mo, sfx_s3kb6) 
        P_Earthquake(player.mo, player.mo, 256*FRACUNIT)
    	P_StartQuake(79*FRACUNIT, 3)
    	P_RadiusAttack(player.mo, player.mo, 1214*FRACUNIT)
		P_FlashPal(player, PAL_WHITE, 3)
    	player.pflags = $ | PF_THOKKED
    	if not (player.cmd.forwardmove)
		    P_InstaThrust(player.mo, player.mo.angle, player.actionspd * 10 / 7)
			player.dashforward = true --Dash forward or backward
		elseif (player.cmd.forwardmove > 0) and not (player.cmd.forwardmove < 0)
    	   P_SetObjectMomZ(player.mo, 20*FRACUNIT, false)
		   player.speed = 1 --Momentum cut lul
		   player.dashup = true --Upward Dash
		elseif (player.cmd.forwardmove < 0) and not (player.cmd.forwardmove > 0)
           P_SetObjectMomZ(player.mo, -25*FRACUNIT, false)
	       player.speed = 1 --Momentum cut lul
	       player.dashdown = true --Downward Dash
	       player.deletethok = true
		   return false
		end
		player.deletethok = false
    end

	if (player.mo and player.mo.valid) and player.mo.skin == "ultsonic" and not (player.pflags & PF_THOKKED)
	and (player.ishyper == true) 
	and G_PlatformGametype()
    	if not (player.mo.flags2 & MF2_TWOD)
    	    Do3DHyperDash(player) --3D Hyper Dash
		else
		    Do2DHyperDash(player) --2D Hyper Dash
		end
	elseif (player.ishyper != true) or (player.dashdown == false) -- or (player.deletethok == false) or (player.dashtype != player.dashdown)
	    player.charability = skins[player.mo.skin].ability
	end 
end)

freeslot("SKINCOLOR_HYPER_SEIZURE1", 
"SKINCOLOR_HYPER_SEIZURE2",
"SKINCOLOR_HYPER_SEIZURE3",
"SKINCOLOR_HYPER_SEIZURE4", 
"SKINCOLOR_HYPER_SEIZURE5",
"SKINCOLOR_HYPER_SEIZURE6",
"SKINCOLOR_HYPER_SEIZURE7",
"SKINCOLOR_HYPER_SEIZURE8",
"SKINCOLOR_HYPER_SEIZURE9",
"SKINCOLOR_HYPER_SEIZURE10",
"SKINCOLOR_HYPER_SEIZURE11",
"SKINCOLOR_HYPER_SEIZURE12")

skincolors[SKINCOLOR_HYPER_SEIZURE1] = {
    name = "Hyper Seizure 1",
    ramp = {0,0,0,80,80,80,80,81,81,81,82,82,64,64,64,65},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE2] = {
    name = "Hyper Seizure 2",
    ramp = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE3] = {
    name = "Hyper Seizure 3",
    ramp = {0,0,252,252,208,208,208,48,209,209,209,210,210,210,32,32},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE4] = {
    name = "Hyper Seizure 4",
    ramp = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE5] = {
    name = "Hyper Seizure 5",
    ramp = {0,0,144,144,144,160,160,160,161,161,161,161,162,162,162,162},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE6] = {
    name = "Hyper Seizure 6",
    ramp = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE7] = {
    name = "Hyper Seizure 7",
    ramp = {0,0,144,144,144,144,145,145,145,146,146,146,146,147,147,147},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE8] = {
    name = "Hyper Seizure 8",
    ramp = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE9] = {
    name = "Hyper Seizure 9",
    ramp = {0,0,0,0,88,88,96,96,96,98,98,100,100,101,104,104},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE10] = {
    name = "Hyper Seizure 10",
    ramp = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE11] = {
    name = "Hyper Seizure 11",
    ramp = {0,0,0,80,80,81,81,83,83,64,64,64,64,65,65,65},
	accessible = false
}
skincolors[SKINCOLOR_HYPER_SEIZURE12] = {
    name = "Hyper Seizure 12",
    ramp = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	accessible = false
}