-- HOOK BELOW BY GOLDEN FROM SRB2 DISCORD AND A DELETED USER <@456226577798135808> 
local boss = false
addHook("MapLoad", function(map)
    for mo in mobjs.iterate() do -- For each mapthing in the map...
        if mo and mo.valid then -- the mobj is there and valid...
            if mo.flags & MF_BOSS then -- If the mobj has the boss flag...
                boss = true -- We think this is a boss level!
                break
            end
        end
    end
    -- But just to make sure..
    for sector in sectors.iterate do -- We iterate through all the sectors.
        if GetSecSpecial(sector.special, 4) == 2 and not (string.upper(mapheaderinfo[map].lvlttl) == "EGG ROCK" and mapheaderinfo[map].actnum == 3 and gamemap == 26) and not (string.upper(mapheaderinfo[map].lvlttl) == "EGG ROCK CORE")  then -- And if one's an exit sector?
            boss = false -- Then this probably isn't a boss level (like ERZ2).
            break
        end
    end
end)
freeslot("S_PLAY_ROCKET")
states[S_PLAY_ROCKET] = {
        sprite = SPR_PLAY,
        frame = SPR2_DASH,
        tics = 2,
        action = nil,
        var1 = 0,
        var2 = 4,
		nextstate = S_PLAY_ROCKET
}
freeslot("S_PLAY_PREGLIDE")
states[S_PLAY_PREGLIDE] = {
        sprite = SPR_PLAY,
        frame = SPR2_SPNG,
        tics = 2,
        action = nil,
        var1 = 0,
        var2 = 0,
		nextstate = S_PLAY_PREGLIDE
}

addHook("PlayerThink", function(player)
	if (player.mo and player.valid) and (player.mo.skin == "sonic") and player.powers[pw_carry] != CR_NIGHTSMODE
		if player.tier == 0
			player.charflags = $|SF_SUPER|SF_MULTIABILITY
			player.charability = CA_THOK
			player.jumpfactor = 1*FRACUNIT
			player.actionspd = 80*FRACUNIT
		elseif player.tier == 1 
			player.charflags = $ & ~SF_MULTIABILITY
			player.charability = CA_HOMINGTHOK
			player.actionspd = 85*FRACUNIT
			player.jumpfactor = 1*FRACUNIT
		elseif player.tier == 2
			player.jumpfactor = FRACUNIT + FRACUNIT/4
			player.charability = CA_JUMPTHOK
			player.actionspd = 35*FRACUNIT
		end
		if player.tier == 1 and (player.pflags & PF_THOKKED) and player.mo.state == S_PLAY_FALL and not (player.pflags & PF_SHIELDABILITY)
			player.mo.state = S_PLAY_JUMP
			player.pflags = $ & ~PF_NOJUMPDAMAGE
			player.pflags = $|PF_JUMPED
		end
		if player.tier == 1 and (player.pflags & PF_JUMPED) and not (player.pflags & PF_SHIELDABILITY)
			player.charflags = $|SF_CANBUSTWALLS
		elseif player.tier != 1 or not ((player.pflags & PF_JUMPED) and not (player.pflags & PF_SHIELDABILITY))
			player.charflags = $ & ~SF_CANBUSTWALLS
		end
	end
end)
addHook("PlayerThink", function(player)
    if (player.mo and player.valid) and (player.mo.skin == "sonic") and (player.mo.eflags & MFE_UNDERWATER) and player.tier == 2
		player.pflags = $ & ~PF_THOKKED
	elseif (player.mo and player.valid) and (player.mo.skin == "sonic") and not (player.mo.eflags & MFE_UNDERWATER) and player.tier == 2 
		player.charflags = $ & ~SF_MULTIABILITY
		end
end)

addHook("PlayerThink", function(player)
if (player.mo and player.valid) and (player.mo.skin == "tails") and player.powers[pw_carry] != CR_NIGHTSMODE
	if player.tier == 0 and player.bot ~= 1
		player.charability = CA_FLY
		player.actionspd = 52*FRACUNIT
		player.charflags = $ & ~(SF_STOMPDAMAGE|SF_RUNONWATER|SF_NOJUMPSPIN|SF_NOJUMPDAMAGE)
		player.normalspeed = 36*FRACUNIT
		player.acceleration = 40
		player.thrustfactor = 5
		player.accelstart = 96
	elseif player.tier == 1 and player.bot ~= 1
		player.charability = CA_FLY
		player.actionspd = 65*FRACUNIT
		player.charflags = $|SF_NOJUMPSPIN|SF_NOJUMPDAMAGE
		player.normalspeed = 36*FRACUNIT
		player.acceleration = 40
		player.thrustfactor = 5
		player.accelstart = 96
	elseif player.tier == 2 and player.bot ~= 1
		player.actionspd = 100*FRACUNIT
		player.charability = CA_FLY
		player.normalspeed = 26*FRACUNIT
		player.acceleration = 44
		player.charflags = $ & ~(SF_NOJUMPSPIN|SF_NOJUMPDAMAGE)
		player.charflags = $|SF_STOMPDAMAGE|SF_RUNONWATER
		player.accelstart = 144
		player.thrustfactor = 4
	elseif player.bot == 1
		player.actionspd = 100*FRACUNIT
		player.charability = CA_FLY
		player.normalspeed = 36*FRACUNIT
		player.acceleration = 40
		player.charflags = 0
		player.accelstart = 96
		player.thrustfactor = 5
	end
if (player.mo and player.valid) and (player.mo.skin == "tails") and player.powers[pw_carry] != CR_NIGHTSMODE and player.bombcooldown == nil
	player.bombcooldown = 0
end
if (player.cmd.buttons & BT_CUSTOM2) and (player.c2ready == true) and (player.c2tapping == false) and (player.mo.skin == "tails") and player.powers[pw_nocontrol] == 0 and player.exiting == 0 and player.tier == 1 and not P_PlayerInPain(player) and player.bombcooldown < 1 and player.powers[pw_carry] != (CR_MINECART or CR_NIGHTSMODE) and player.weapondelay < 1
	local bombz = 0
	if (player.pflags & PF_THOKKED) and not (player.pflags & PF_SHIELDABILITY)
		bombz = _
	else bombz = player.mo.height
	end
	local thrownbomb = P_SpawnMobjFromMobj(player.mo, player.mo.momx, player.mo.momy, bombz, MT_FBOMB)
	thrownbomb.isthrown = 1
	player.bombcooldown = TICRATE*3/5
	thrownbomb.target = player.mo
	if not (player.pflags & PF_THOKKED) or (player.pflags & PF_SHIELDABILITY)
		P_InstaThrust(thrownbomb, player.mo.angle, FixedMul(player.mo.scale,15*FRACUNIT))
		player.drawangle = player.mo.angle
		P_SetObjectMomZ(thrownbomb,5*FRACUNIT,false)
	elseif (player.pflags & PF_THOKKED) and not (player.pflags & PF_SHIELDABILITY)
		P_SetObjectMomZ(thrownbomb,-5*FRACUNIT,false)
	end
end
if player.bombcooldown >= 1
    player.bombcooldown = $ - 1
	player.weapondelay = player.bombcooldown
end
if (player.cmd.buttons & BT_CUSTOM2) and (player.c2ready == true) and (player.c2tapping == false) and (player.powers[pw_tailsfly] ~= 0) and (player.mo.skin == "tails") and player.powers[pw_nocontrol] == 0 and player.exiting == 0 and player.tier == 0
	if player.mo.eflags & MFE_UNDERWATER and not player.powers[pw_super]
		P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,30)*FRACUNIT)
		elseif not player.powers[pw_super]
		P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,50)*FRACUNIT)
	end
	if player.mo.eflags & MFE_UNDERWATER and player.powers[pw_super]
		P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,60)*FRACUNIT)
		elseif player.powers[pw_super]
		P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,80)*FRACUNIT)
	end
	P_SpawnGhostMobj(player.mo)
	player.powers[pw_tailsfly] = 0
	S_StartSound(player.mo, sfx_cdfm40)
	player.drawangle = player.mo.angle
	end
end
	if not (player.cmd.buttons & BT_CUSTOM2) then
			player.c2ready = true
			player.c2tapping = false
		elseif player.c2ready then
			player.c2tapping = true
			player.c2ready = false
		else
			player.c2tapping = false
		end
end)
addHook("PlayerThink", function(player)
    if (player.mo and player.valid) and (player.mo.skin == "knuckles") and (player.mo.eflags & MFE_UNDERWATER) and player.tier == 2 and not (player.pflags & PF_GLIDING) and not (player.mo.state == S_PLAY_GLIDE or player.mo.state == S_PLAY_SWIM or player.mo.state == S_PLAY_CLING or player.mo.state == S_PLAY_CLIMB or player.mo.state == S_PLAY_FALL or player.mo.state == S_PLAY_FALL or player.mo.state == S_PLAY_GLIDE_LANDING)
        player.charability = CA_SWIM
		player.actionspd = 100*FRACUNIT
	elseif (player.mo and player.valid) and (player.mo.skin == "knuckles") and not (player.mo.eflags & MFE_UNDERWATER) and player.tier == 2
		player.actionspd = 34*FRACUNIT
		end
end)

addHook("AbilitySpecial", function(player)
if (player.mo and player.valid) and (player.mo.skin == "knuckles") and player.powers[pw_carry] != CR_NIGHTSMODE
	if player.canglide == nil
		player.canglide = true
	end
	if player.canglide == true and not ((player.pflags & PF_THOKKED) and not (player.pflags & PF_SHIELDABILITY))
		if player.tier == 2 and not (player.mo.eflags & MFE_UNDERWATER) 
		player.charability = CA_NONE
		player.mo.momz = 0 
		P_SetObjectMomZ(player.mo,11*FRACUNIT,false)
		S_StartSound(player.mo, 14)
		player.mo.momx = 0
		player.mo.momy = 0
		player.mo.state = S_PLAY_PREGLIDE
		player.canglide = false
		end
	end
end
end)

addHook("PlayerThink", function(player)
if (player.mo and player.valid) and (player.mo.skin == "knuckles") and player.powers[pw_carry] != CR_NIGHTSMODE
	if player.tier == 0
		player.charability = CA_GLIDEANDCLIMB
		player.actionspd =  34*FRACUNIT
		player.normalspeed = 36*FRACUNIT
		player.charflags = $|SF_SUPER|SF_NOSUPERJUMPBOOST|SF_CANBUSTWALLS|SF_RUNONWATER
		player.jumpfactor = FRACUNIT*88/100
	elseif player.tier == 1 and player.god != true
		player.charability = CA_GLIDEANDCLIMB
		player.actionspd = 32*FRACUNIT
		player.normalspeed = 36*FRACUNIT
		player.charflags = $ & ~(SF_RUNONWATER|SF_DASHMODE)
		player.jumpfactor = FRACUNIT*95/100
	elseif player.tier == 2
		player.charflags = $ & ~(SF_NOSUPERJUMPBOOST|SF_DASHMODE)
		player.normalspeed = 36*FRACUNIT
		player.jumpfactor = 1*FRACUNIT
	elseif player.god == true and player.tier == 1
		player.charability = CA_GLIDEANDCLIMB
		player.actionspd = 60*FRACUNIT
		player.normalspeed = 50*FRACUNIT
		player.charflags = $|SF_SUPER|SF_CANBUSTWALLS|SF_DASHMODE
		player.jumpfactor = FRACUNIT*150/100
	end
	if player.powers[pw_super] and player.tier == 1
		player.god = true
	end
	if player.god == true and player.powers[pw_super] and player.tier == 1
		if not (leveltime%(TICRATE/2)) and player.rings > 0
			P_GivePlayerRings(player, -1)
		end
		player.pflags = $|PF_GODMODE
	end
	if player.god == true and (not player.powers[pw_super] or player.tier != 1)
		player.god = false
		P_RestoreMusic(player)
		player.pflags = $ & ~PF_GODMODE
	end
	if (player.mo.state == S_PLAY_GLIDE_LANDING) and player.tier == 0
		player.mo.state = S_PLAY_STND
	end
	if player.mo.state != S_PLAY_GLIDE and player.tier == 0 and not (player.pflags & PF_SHIELDABILITY)
		player.pflags = $ & ~PF_THOKKED
	end
	if (P_IsObjectOnGround(player.mo) or player.mo.eflags & MFE_JUSTHITFLOOR) and player.canglide == false 
		player.canglide = true
	end
	if player.tier == 2 and player.canglide == false and not (player.mo.eflags & MFE_UNDERWATER) 
		player.charability = CA_GLIDEANDCLIMB
	end
	if player.tier == 2 and ((P_IsObjectOnGround(player.mo) or player.mo.eflags & MFE_JUSTHITFLOOR) or player.mo.state == S_PLAY_GLIDE_LANDING)
		if not (player.mo.state == S_PLAY_GLIDE and (P_IsObjectOnGround(player.mo) or player.mo.eflags & MFE_JUSTHITFLOOR))
			player.charability = CA_NONE
		end
	end
	if player.mo.state == S_PLAY_PREGLIDE and player.tier == 2 and not(player.mo.eflags & MFE_JUSTHITFLOOR)
		if not (player.mo.eflags & MFE_VERTICALFLIP)
			if player.mo.momz < -1
				player.mo.state = S_PLAY_JUMP
			end
		elseif (player.mo.eflags & MFE_VERTICALFLIP)
			if player.mo.momz > 1
				player.mo.state = S_PLAY_JUMP
			end
		end
		player.charability = CA_GLIDEANDCLIMB
		player.pflags = $|PF_JUMPED
		if (P_IsObjectOnGround(player.mo))
			player.mo.state = S_PLAY_STND
		end
	end
end
end)
addHook("PreThinkFrame", function()
	for player in players.iterate() do
		if (player.mo and player.valid) and (player.mo.skin == "knuckles") and player.powers[pw_carry] != CR_NIGHTSMODE
			if (player.mo.state == S_PLAY_CLING or player.mo.state == S_PLAY_CLIMB or player.mo.state == S_PLAY_GLIDE) and player.canglide == false
				player.canglide = true
			end
			if player.tier == 2 and player.mo.state == S_PLAY_FLY
				player.mo.state = S_PLAY_JUMP
				player.pflags = $|PF_JUMPED
				player.canglide = true
				player.charability = CA_NONE
				player.pflags = $ & ~PF_THOKKED
			end
		end
	end
end)
addHook("ShouldDamage", function(mo,mo2)
	if (mo and mo.valid) and (mo2 and mo2.valid) 
		if mo.health > 1 and mo2.type == MT_PLAYER and mo2.player.tier == 1 and mo2.skin == "knuckles" and mo2.player.god != true
			mo.health = $ - 1
		end
		if (mo and mo.valid) and (mo2 and mo2.valid) and mo2.type == MT_PLAYER and mo2.player.god == true and (mo.flags & MF_ENEMY|MF_BOSS) and not (mo.flags & MF_MONITOR)
			P_KillMobj(mo,mo2)
			if (mo and mo.valid) and (mo2 and mo2.valid) and (mo.flags & MF_BOSS) 
				P_StartQuake(16*FRACUNIT, 1*TICRATE)
			end
		end
	end
end)

addHook("ShouldDamage", function(mo,mo2)
	if (mo and mo.valid) and (mo2 and mo2.valid) 
		if mo2.type == MT_PLAYER and mo2.player.tier == 1 and mo2.skin == "metalsonic" and mo2.player.god != true
			if mo2.player.heat >= 100
				if mo.health > 2
					mo.health = $ - 2
				else mo.health = 0
				end
			elseif mo2.player.heat >= 50
				if mo.health > 1
					mo.health = $ - 1
				end
			end
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player.mo and player.valid) and (player.mo.skin == "fang") and player.powers[pw_carry] != CR_NIGHTSMODE
		if player.tier == 0
			player.charability = CA_BOUNCE
			player.charflags = $ & ~(SF_STOMPDAMAGE)
			player.charability2 = CA2_NONE
			player.jumpfactor = FRACUNIT*11/10
			player.actionspd = 100*FRACUNIT
			player.thrustfactor = 6
		elseif player.tier == 1 
			player.charability = CA_BOUNCE
			player.charflags = $ & ~(SF_STOMPDAMAGE)
			player.charability2 = CA2_GUNSLINGER
			player.jumpfactor = 1*FRACUNIT
			player.actionspd = 100*FRACUNIT
			player.thrustfactor = 6
		elseif player.tier == 2
			player.charability = CA_DOUBLEJUMP
			player.charflags = $|SF_STOMPDAMAGE
			player.charability2 = CA2_NONE
			player.jumpfactor = FRACUNIT*11/10
			player.actionspd = 125*FRACUNIT
			player.thrustfactor = 6
		end
		if player.tier == 0
			player.charability2 = CA2_NONE
		end
		if player.dashmode > 0 and player.dashmode < 2*TICRATE
			player.dashmode = 2*TICRATE
		end
		if player.dashmode > 3*TICRATE
			player.charflags = $|SF_CANBUSTWALLS
		else
			player.charflags = $ & ~SF_CANBUSTWALLS
		end
		if player.tier != 1 and boss == true
			player.charflags = $ & ~SF_NOJUMPSPIN
			player.charflags = $ & ~SF_NOJUMPDAMAGE
		elseif player.tier == 1 or boss == false
			player.charflags = $|SF_NOJUMPSPIN|SF_NOJUMPDAMAGE
		end
		if player.dashmode >= 3*TICRATE and not (player.pflags & PF_SPINDOWN)
			player.normalspeed = $ + FRACUNIT/4
		end
		if player.dashmode < 3*TICRATE
			player.normalspeed = 36*FRACUNIT
		end
		if (player.hasbounced == true) and (player.mo.eflags & MFE_JUSTHITFLOOR)
			player.hasbounced = false
		end
		if (player.pflags & PF_BOUNCING) and player.tier == 1 and (player.hasthrownbomb != true) and (player.mo.eflags & MFE_JUSTHITFLOOR)
			local thrownbomb = P_SpawnMobjFromMobj(player.mo, _, _, player.mo.height*P_MobjFlip(player.mo), MT_FBOMB)
			P_SetObjectMomZ(thrownbomb,7*FRACUNIT,false)
			thrownbomb.isthrown = 1
			player.hasthrownbomb = true
			thrownbomb.target = player.mo
		end
		if player.hasthrownbomb == true and not (P_IsObjectOnGround(player.mo) or player.mo.eflags & MFE_JUSTHITFLOOR)
			player.hasthrownbomb = false
		end
	end
end)
addHook("SpinSpecial", function(player)
	if (player.pflags & PF_SLIDING) return end
	if (player.powers[pw_nocontrol]) return end
    if (player.mo.skin == "fang") and (player.tier == 0) and (player.exiting == 0) and (player.speed > 5*FRACUNIT or player.speed < -5*FRACUNIT) and P_IsObjectOnGround(player.mo) and not player.powers[pw_carry] and player.powers[pw_nocontrol] == 0 and not (player.mo.state == S_PLAY_ROLL or  player.mo.state == S_PLAY_STND or (player.pflags & PF_SPINNING or (player.pflags & PF_BOUNCING)))
		player.mo.state = S_PLAY_ROLL
		player.pflags = $|PF_SPINNING
        return true
    end
end)

addHook("SpinSpecial", function(player)
	if (player.pflags & PF_THOKKED) return end
	if (player.pflags & PF_SLIDING) return end
	if (player.exiting != 0) return end 
	if (player.powers[pw_nocontrol]) return end
	if (player.hasbounced == true) return end
	if (player.mo.state == S_PLAY_BOUNCE_LANDING) return end
    if (P_IsObjectOnGround(player.mo) or player.mo.eflags & MFE_JUSTHITFLOOR) and (player.mo.skin == "fang") and (player.tier == 2) and not (player.pflags & PF_SPINDOWN) and (not player.powers[pw_carry]) and (player.hasbounced != true)
		player.jumpboost = player.normalspeed/3
		player.pflags = $|PF_THOKKED
		player.hasbounced = true
        player.mo.state = S_PLAY_BOUNCE_LANDING
		P_SetObjectMomZ(player.mo, abs(player.jumpboost),false)
		player.mo.momx = 0
		player.mo.momy = 0
		S_StartSound(player.mo, sfx_boingf)
        return true
    end
end)
addHook("JumpSpecial", function(player)
	if (player.hasbounced == true) and not (player.mo.eflags & MFE_JUSTHITFLOOR) and not player.powers[pw_carry] and not (player.pflags & PF_SLIDING) return true end
end)
addHook("MobjMoveCollide", function(mo, mo2)
    if (mo.z < mo2.z - 50*FRACUNIT) or (mo.z >= mo2.z + 50*FRACUNIT) return end
	if not (mo.isthrown == 1) return end
    if (mo2.type == MT_SPIKE or mo2.type == MT_WALLSPIKE)
        P_KillMobj(mo2,mo)
    end
end, MT_FBOMB)

addHook("MobjMoveCollide", function(mo, mo2)
    if (mo.z < mo2.z - 50*FRACUNIT) or (mo.z >= mo2.z + 50*FRACUNIT) return end
	if not (mo.skin == "fang") return end
	if (mo.player.dashmode < 3*TICRATE) return end
	if (P_PlayerInPain(mo.player)) return end
    if (mo2.type == MT_SPIKE or mo2.type == MT_WALLSPIKE and (mo.skin == "fang"))
        P_KillMobj(mo2,mo)
    end
end, MT_PLAYER)
addHook("PlayerCanDamage", function(player,mo)
	if player.mo.state == S_PLAY_PREGLIDE
		return false
	end
	if (player.mo.state == (S_PLAY_GLIDE) or (player.mo.state == (S_PLAY_SWIM))) and player.tier != 1 and player.mo.skin == "knuckles"
		return false
	end
	if (player.dashmode > 3*TICRATE) and (player.mo.skin == "fang") and not (P_PlayerInPain(player))
		return true
	end
	if (player.mo.skin == "amy") and player.tier == 2 and (player.mo.state == S_PLAY_MELEE_FINISH or player.mo.state == S_PLAY_MELEE_LANDING or player.mo.state == S_PLAY_MELEE) and mo.type != MT_SPIKE and mo.type != MT_WALLSPIKE
		return false
	end
end)
local function CheckAndCrumble(mo, sec) //I TRIED TO MAKE MY OWN WALL BREAKING CODE FOR 4 HOURS, IT WAS THE MOST PAINFUL EXPERIENCE I'VE EVER HAD WITH LUA, THIS ONE IS MADE BY Tatsuru#8938 THANK YOU SO MUCH OMG OMG OMG 
  for fof in sec.ffloors()
    if not (fof.flags & FF_EXISTS) continue end 
    if not (fof.flags & FF_BUSTUP) continue end 
    if mo.z + mo.height < fof.bottomheight continue end 
    if mo.z > fof.topheight continue end    
    EV_CrumbleChain(fof)
	if mo.type == MT_FBOMB
		P_KillMobj(mo)
		mo.momz = 0
		mo.momx = 0
		mo.momy = 0
	end
  end
end
addHook("PlayerThink", function(player)
	if (player.mo and player.valid) and (player.mo.skin != "metalsonic") and player.powers[pw_carry] != CR_NIGHTSMODE
		player.heat = 0
		player.heattimer = 0
	end
end)

addHook("PlayerThink", function(player)
	if (player.mo and player.valid) and (player.mo.skin == "metalsonic") and player.powers[pw_carry] != CR_NIGHTSMODE
		if not player.heattimer
			player.heattimer = 0
		end
		if not player.heat
			player.heat = 0
		end
		if player.tier == 0
			player.charability = CA_FLOAT
			player.charability2 = CA2_SPINDASH
			player.actionspd = 100*FRACUNIT
			player.charflags = $|SF_MULTIABILITY
			player.thrustfactor = (600 + (player.heat))/100
			player.jumpfactor = FRACUNIT 
		elseif player.tier == 1 
			player.charability = CA_FLOAT
			player.charability2 = CA2_SPINDASH
			player.charflags = $|SF_MULTIABILITY
			player.jumpfactor = FRACUNIT 
			player.actionspd = 100*FRACUNIT
			player.thrustfactor = (500 + (player.heat))/100
		elseif player.tier == 2
			player.charability = CA_NONE
			player.charability2 = CA2_SPINDASH
			player.jumpfactor = FRACUNIT
			player.charflags = $ & ~(SF_MULTIABILITY)
			player.actionspd = 100*FRACUNIT
			player.thrustfactor = (500 + (player.heat))/100
		end
		if player.tier == 0 and player.dashmode > 0 and player.dashmode < (2*(player.heat/100))*TICRATE
			player.dashmode = (2*(player.heat/100))*TICRATE
		end
		if player.heat == 0 and player.tier == 2 //THIS WAS THE ONLY WAY TO DO THIS DON'T @ ME
			player.jumpfactor = 1*FRACUNIT
		elseif player.heat == 25 and player.tier == 2
			player.jumpfactor = 1*FRACUNIT + FRACUNIT/6
		elseif player.heat == 50 and player.tier == 2
			player.jumpfactor = 1*FRACUNIT + FRACUNIT/5
		elseif player.heat == 75 and player.tier == 2 
			player.jumpfactor = 1*FRACUNIT + FRACUNIT/4
		elseif player.heat == 100 and player.tier == 2
			player.jumpfactor = 1*FRACUNIT + FRACUNIT/3
		end
		if player.heattimer != 0 
			player.heattimer = $ - 1
		end
		if player.dashmode > 3*TICRATE
			player.charflags = $|SF_CANBUSTWALLS
		else
			player.charflags = $ & ~SF_CANBUSTWALLS
		end
		if player.dashmode != 0 and player.mo.state == S_PLAY_SPINDASH and player.tier == 2
			player.dashmode = 0
		end
		if player.mo.state == S_PLAY_DEAD or player.mo.state == S_PLAY_DRWN
			player.heattimer = 0
			player.heat = 0
		end
		if player.dashmode >= 3*TICRATE and player.tier == 0
			player.normalspeed = $ + FRACUNIT/(6 - player.heat/25) 	
		end
		if player.dashmode < 3*TICRATE
			player.normalspeed = 36*FRACUNIT
		end
		if player.dashmode >= 3*TICRATE and (player.tier != 0) 
			if player.normalspeed > 72*FRACUNIT
				player.normalspeed = 72*FRACUNIT
			end
		end
		if player.heat != 0 and player.heattimer == 0
			player.heat = $ - 25
			player.heattimer = 3*TICRATE
		end
		if player.heat > 100
			player.heat = 100
		end
		if player.heat < 0
			player.heat = 0
		end
		if player.heattimer > 8*TICRATE
			player.heattimer = 8*TICRATE
		end
		if player.mo.state == S_PLAY_ROCKET 
			if player.exiting == 0
				P_InstaThrust(player.mo, player.mo.angle,FixedMul(player.mo.scale,60*FRACUNIT))
			end
			player.pflags = $ & ~(PF_SPINNING)
			player.pflags = $|PF_THOKKED
			player.drawangle = player.mo.angle
			player.pflags = $ & ~PF_JUMPED
		end
		if player.mo.state == S_PLAY_ROCKET and not (player.cmd.buttons & BT_JUMP) and not (player.cmd.buttons & BT_SPIN)
			player.mo.momz = 0
		end
	end
end) 

addHook("ShouldDamage", function(mo,mo2,source,damage,damagetype)
	if (mo and mo.valid) and (mo2 and mo2.valid) and boss == false
		if mo.type == MT_PLAYER and not (mo2.flags & MF_BOSS) and not (mo2.type == MT_CYBRAKDEMON_ELECTRIC_BARRIER) and not (mo2.type == MT_PLAYER) and not (mo.player.pflags & PF_GODMODE) and not mo.player.powers[pw_flashing] and not mo.player.powers[pw_invulnerability]
			if mo.skin == "metalsonic" and mo.player.tier == 1 and mo.player.rings == 0 and not mo.player.powers[pw_shield]
				if not (mo2.target != nil and (mo2.target.flags & MF_BOSS or mo2.target.type == MT_PLAYER and mo2.flags & MF_MISSILE))
					P_DoPlayerPain(mo.player)
					if mo.player.score >= 20
						P_AddPlayerScore(mo.player, -20)
					else mo.player.score = 0
					end
					if not (damagetype == DMG_SPIKE)
						S_StartSound(mo, 24)
					else S_StartSound(mo, 132)
					end
				end
			end
		end
	end
end)

addHook("SpinSpecial", function(player)
	if player.mo.state == S_PLAY_ROCKET and not player.powers[pw_carry] and not (player.pflags & PF_SLIDING) 
		P_SetObjectMomZ(player.mo,(-5 - player.heat/25)*FRACUNIT,false)
		return true
	end
end)
addHook('MobjMoveBlocked', function(mo, mobj, line)
	if line and line.valid and mo.player and mo.player.valid
		if mo.state == S_PLAY_ROCKET
			P_DoPlayerPain(mo.player)	
			mo.player.powers[pw_flashing] = 0
		end
	end
end, MT_PLAYER)
addHook("JumpSpecial", function(player)
	if (player.pflags & PF_SLIDING) return end
	if (player.powers[pw_nocontrol]) return end
    if (player.mo.skin == "metalsonic") and (player.tier == 2) and (player.exiting == 0) and (player.dashmode >= 3*TICRATE) and not P_IsObjectOnGround(player.mo) and not player.powers[pw_carry] and player.powers[pw_nocontrol] == 0 and player.mo.state != S_PLAY_ROCKET and not P_PlayerInPain(player) and not (player.pflags & PF_JUMPDOWN) and not (player.pflags & PF_THOKKED) and (player.pflags & PF_JUMPED)
		player.mo.state = S_PLAY_ROCKET
		player.pflags = $|PF_THOKKED
		player.pflags = $ & ~PF_JUMPED
        return true
	elseif (player.mo.skin == "metalsonic") and (player.tier == 2) and (player.exiting == 0) and (player.dashmode >= 3*TICRATE) and not player.powers[pw_carry] and player.powers[pw_nocontrol] == 0 and player.mo.state == S_PLAY_ROCKET
		P_SetObjectMomZ(player.mo,(5 + player.heat/25)*FRACUNIT,false)
		return true
    end
end)
addHook("TouchSpecial", function(mo, mo2)
	if (mo2 and mo2.valid) and (mo and mo.valid) and not (maptol & TOL_NIGHTS or maptol & TOL_XMAS) and mo2.skin == "metalsonic"
		mo2.player.heattimer = $ + TICRATE*2
			if mo2.player.heat >= 100
				P_GivePlayerRings(mo2.player, 1)
				P_AddPlayerScore(mo2.player, 20)
			end
	end
end, (MT_RING))
addHook("TouchSpecial", function(mo, mo2)
	if mo2 and mo2.valid
		if mo2.skin == "metalsonic"
			if mo2.player.heat < 100
				if not (mo2.player.tier == 1 and mo2.player.heat != 75)
					mo2.player.heat = $ + 25
				elseif mo2.player.heat != 75 mo2.player.heat = $ + 50
				end
			end
			mo2.player.heattimer = 8*TICRATE
		end
	end
end, MT_TOKEN)

local function heat(heat, player)
	if (player.mo and player.valid) and (player.mo.skin == "metalsonic") and player.powers[pw_carry] != CR_NIGHTSMODE
		local heatvalue = tostring((player.heat))
		local color = 0
		if player.heat == 0
			color = 0
		elseif player.heat == 25
			color = V_YELLOWMAP
		elseif player.heat == 50
			color = V_GREENMAP
		elseif player.heat == 75
			color = V_BLUEMAP
		elseif player.heat == 100
			color = V_REDMAP
		end
		heat.drawString(120, 18,(heatvalue).."%", V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER|color)
	end
end
hud.add(heat, "game")

addHook("MobjDeath", function(target, inflictor)
	if inflictor and inflictor.valid and ((target.flags & MF_ENEMY) or (target.flags & MF_MONITOR) or target.type == MT_SPIKE or target.type == MT_WALLSPIKE)
		if inflictor.type == MT_PLAYER
			if inflictor.skin == "metalsonic"
				if inflictor.player.heat < 100
					if not (inflictor.player.tier == 1 and inflictor.player.heat != 75)
						inflictor.player.heat = $ + 25
					elseif inflictor.player.heat != 75 inflictor.player.heat = $ + 50
					end
				end
				inflictor.player.heattimer = 8*TICRATE
			end
		end
	end
end)
		
addHook("MobjDamage", function(target, inflictor)
	if inflictor and inflictor.valid and (target.flags & MF_BOSS)
		if inflictor.type == MT_PLAYER
			if inflictor.skin == "metalsonic"
				if inflictor.player.heat < 100
					if not (inflictor.player.tier == 1 and inflictor.player.heat != 75)
						inflictor.player.heat = $ + 25
					elseif inflictor.player.heat != 75 inflictor.player.heat = $ + 50
					end
				end
				inflictor.player.heattimer = 8*TICRATE
			end
		end
	end
end)
addHook("PlayerThink", function(player)
	if (player.mo and player.valid) and (player.mo.skin == "amy") and player.powers[pw_carry] != CR_NIGHTSMODE
		if player.tier == 0
			player.charability = CA_TWINSPIN
			player.charflags = $
			player.charability2 = CA2_SPINDASH
			player.jumpfactor = FRACUNIT*227/200
			player.actionspd = 100*FRACUNIT
			player.mindash = 15*FRACUNIT
			player.maxdash = 70*FRACUNIT
			player.thrustfactor = 6
		elseif player.tier == 1 
			player.charability = CA_TWINSPIN
			player.charflags = $
			player.charability2 = CA2_MELEE
			player.jumpfactor = 227/200*FRACUNIT
			player.actionspd = 100*FRACUNIT
			player.mindash = 2*FRACUNIT
			player.maxdash = 6*FRACUNIT
			player.thrustfactor = 6
		elseif player.tier == 2
			player.charability = CA_TWINSPIN
			player.charflags = $
			player.charability2 = CA2_MELEE
			player.mindash = 8*FRACUNIT
			player.maxdash = 8*FRACUNIT
			player.jumpfactor = FRACUNIT*6/5
			player.actionspd = 125*FRACUNIT
			player.thrustfactor = 6
		end
		if ((player.mo.eflags & MFE_JUSTHITFLOOR) or (P_IsObjectOnGround(player.mo))) and player.tier == 0 and (player.mo.skin == "amy")
			player.charability2 = CA2_SPINDASH
		elseif not (P_IsObjectOnGround(player.mo)) and player.tier == 0 and not (player.mo.eflags & MFE_JUSTHITFLOOR)
			player.charability2 = CA2_MELEE
		end
		if player.tier == 0 and (player.mo.state == S_PLAY_MELEE_FINISH or player.mo.state == S_PLAY_MELEE_LANDING or player.mo.state == S_PLAY_MELEE)
			player.charability2 = CA2_SPINDASH
			player.mo.state = S_PLAY_ROLL
			player.pflags = $|PF_SPINNING
			if not (player.mo.eflags & MFE_UNDERWATER) and not player.powers[pw_super]
				P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,45*FRACUNIT))
			elseif not player.powers[pw_super] P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,20*FRACUNIT))
			end
			if not (player.mo.eflags & MFE_UNDERWATER) and player.powers[pw_super]
				P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,65*FRACUNIT))
			elseif player.powers[pw_super] P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,40*FRACUNIT))
			end
			player.momz = 0 
		end
	end
end)

addHook("SpinSpecial", function(player)
	if (player.charability2 == CA2_SPINDASH) return end
	if not (player.mo.skin == "amy") return end
	if (player.mo.skin != "amy") return end
	if (player.mo.skin == "fang") return end
	if (player.tier != 0) return end
    if (player.mo.skin == "amy") and (player.tier == 0) and (player.charability2 == CA2_MELEE) and (player.mo.eflags & MFE_JUSTHITFLOOR) or (P_IsObjectOnGround(player.mo))
		player.charability2 = CA2_SPINDASH
    end
end)


addHook("ShouldDamage", function(mo,mo2,source,damage,damagetype)
	if (mo and mo.valid)
		if mo.type == MT_PLAYER and not (damagetype == DMG_INSTAKILL) and not (damagetype == DMG_DROWNED) and not (damagetype == DMG_SPACEDROWN) and not (damagetype == DMG_DEATHPIT) and not (damagetype == DMG_CRUSHED)
			if mo.skin == "amy" and mo.player.tier == 1 
				if mo.state == S_PLAY_TWINSPIN
					return false
				end
			end
		end
	end
end)
addHook("JumpSpecial", function(player)
	if (player.pflags & PF_SLIDING) return end
	if not (player.pflags & PF_JUMPED) return end
	if (player.powers[pw_nocontrol]) return end
    if (player.mo.skin == "amy") and (player.tier == 0) and (player.exiting == 0) and not P_IsObjectOnGround(player.mo) and not player.powers[pw_carry] and player.powers[pw_nocontrol] == 0 and not P_PlayerInPain(player) and not (player.pflags & PF_JUMPDOWN) and not (player.pflags & PF_THOKKED)
		if not (player.mo.eflags & MFE_UNDERWATER) and not player.powers[pw_super]
			P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,30*FRACUNIT))
		elseif not player.powers[pw_super] P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,15*FRACUNIT))
		end
		if not (player.mo.eflags & MFE_UNDERWATER) and player.powers[pw_super]
			P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,50*FRACUNIT))
		elseif player.powers[pw_super] P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.mo.scale,25*FRACUNIT))
		end
		S_StartSound(player.mo, sfx_s3k42)
		player.pflags = $|PF_THOKKED
		player.mo.state = S_PLAY_TWINSPIN
        return false
	end
end)
addHook("JumpSpecial", function(player)
	if (player.pflags & PF_SLIDING) return end
	if not (player.pflags & PF_JUMPED) return end
	if (player.powers[pw_nocontrol]) return end
    if (player.mo.skin == "amy") and (player.tier == 2) and (player.exiting == 0) and not P_IsObjectOnGround(player.mo) and not player.powers[pw_carry] and player.powers[pw_nocontrol] == 0 and not P_PlayerInPain(player) and not (player.pflags & PF_JUMPDOWN) and not (player.pflags & PF_THOKKED)
		P_SetObjectMomZ(player.mo,10*FRACUNIT,false)
		S_StartSound(player.mo, sfx_s3k42)
		player.pflags = $|PF_THOKKED
		player.mo.state = S_PLAY_TWINSPIN
        return false
	end
end)
addHook("PlayerThink", function(p)
  if not p.mo return end
  if (not (p.mo.skin == "sonic")) return end
  if (p.mo.skin != "sonic") return end
  if (p.tier != 1) return end
  if (p.pflags & PF_SHIELDABILITY) return end
  if not ((p.pflags & PF_STARTDASH) or (p.pflags & PF_SPINNING)) return end
  if p.tier == 1 and (p.mo.skin == "sonic")
	if (p.mo.skin == "sonic")
		CheckAndCrumble(p.mo, p.mo.subsector.sector)
	end
  end
end)

addHook("PlayerThink", function(p)
  if not p.mo return end
  if (not (p.mo.skin == "metalsonic")) return end
  if (p.mo.skin != "metalsonic") return end
  if (p.tier != 1) return end
  if (p.pflags & PF_SHIELDABILITY) return end
  if not ((p.pflags & PF_STARTDASH) or (p.pflags & PF_SPINNING)) return end
  if p.tier == 1 and (p.mo.skin == "metalsonic")
	if (p.mo.skin == "metalsonic")
		CheckAndCrumble(p.mo, p.mo.subsector.sector)
	end
  end
end)
addHook("PlayerThink", function(p)
  if not p.mo return end
  if (not (p.mo.skin == "fang")) return end
  if p.mo.skin != "fang" return end
  if (p.tier != 2) return end
  if not (p.mo.state == S_PLAY_BOUNCE_LANDING) return end
  if p.tier == 2 and (p.mo.skin == "fang")
	if (p.mo.skin == "fang")
		CheckAndCrumble(p.mo, p.mo.subsector.sector)
	end
  end
end)

addHook("PlayerThink", function(p)
  if not p.mo return end
  if (p.mo.skin != "knuckles") return end
  if p.tier == 1 and p.mo.state ~= S_PLAY_DEAD and p.mo.skin == "knuckles"
	CheckAndCrumble(p.mo, p.mo.subsector.sector)
  end
end)

addHook("MobjLineCollide", function(mo, line)
  if not mo.player return end
  if not (P_IsObjectOnGround(mo) or mo.eflags & MFE_JUSTHITFLOOR) return end
  if mo.skin != "sonic" return end
  if (mo.skin != "sonic" and (mo.player.tier == 0 or mo.player.tier == 2)) return end
  if (mo.player.pflags & PF_SHIELDABILITY) return end
  if not ((mo.player.pflags & PF_STARTDASH) or (mo.player.pflags & PF_SPINNING)) return end
	if mo.player.tier == 1
  for _, sec in ipairs({line.frontsector, line.backsector})
    CheckAndCrumble(mo, sec)
	end
  end
end, MT_PLAYER)

addHook("MobjMoveCollide", function(mo, mo2)
    if (mo.z < mo2.z - 50*FRACUNIT) or (mo.z >= mo2.z + 50*FRACUNIT) return end
	if (mo.skin != "sonic") return end
	if (mo.player.tier != 1) return end
	if (P_PlayerInPain(mo.player)) return end
	if (mo.player.pflags & PF_SHIELDABILITY) return end
	if not ((mo.player.pflags & PF_STARTDASH) or (mo.player.pflags & PF_SPINNING)) return end
    if mo2.type == MT_SPIKE or mo2.type == MT_WALLSPIKE and mo.skin == "sonic"
        P_KillMobj(mo2,mo)
    end
end, MT_PLAYER)

addHook("MobjMoveCollide", function(mo, mo2)
    if (mo.z < mo2.z - 50*FRACUNIT) or (mo.z >= mo2.z + 50*FRACUNIT) return end
	if (mo.skin != "knuckles") return end
	if (mo.player.tier != 1) return end
	if (P_PlayerInPain(mo.player)) return end
    if mo2.type == MT_SPIKE or mo2.type == MT_WALLSPIKE and mo.skin == "knuckles"
        P_KillMobj(mo2,mo)
    end
end, MT_PLAYER)

addHook("MobjThinker", function(thrownbomb)
	if thrownbomb and thrownbomb.isthrown == 1 and thrownbomb.valid
		CheckAndCrumble(thrownbomb, thrownbomb.subsector.sector)
	end
end, MT_FBOMB)

addHook("MobjLineCollide", function(thrownbomb, line)
	if thrownbomb.isthrown == 1 and thrownbomb.valid
		for _, sec in ipairs({line.frontsector, line.backsector})
			CheckAndCrumble(thrownbomb, sec)
		end
	end	
end, MT_FBOMB)
local function flightdash(flightdash, player)
    if (player.mo and player.valid) and (player.mo.skin == "tails") and player.powers[pw_nocontrol] == 0 and player.exiting == 0 and not (player.mo.state == S_PLAY_DEAD or player.mo.state == S_PLAY_FLY_TIRED) and player.tier == 0 and player.powers[pw_carry] != CR_NIGHTSMODE
            flightdash.drawString(-24, 50, "Custom 2 - Flight Dash", V_HUDTRANSHALF|V_PERPLAYER, "small")
    end
end
hud.add(flightdash, "game")

local function bombthrow(bombthrow, player)
    if (player.mo and player.valid) and (player.mo.skin == "tails") and player.powers[pw_nocontrol] == 0 and player.exiting == 0 and not (player.mo.state == S_PLAY_DEAD or player.mo.state == S_PLAY_FLY_TIRED) and player.tier == 1 and player.powers[pw_carry] != CR_NIGHTSMODE
            bombthrow.drawString(-24, 50, "Custom 2 - Throw a Bomb", V_HUDTRANSHALF|V_PERPLAYER, "small")
    end
end
hud.add(bombthrow, "game")