addHook("ThinkFrame", do
	for player in players.iterate
		if player.mo
		if not (player.mo.groundboost)
			player.mo.groundboost = 0
		end
		
		if not (player.mo.sound)
			player.mo.sound = 0
		end
			
		if P_IsObjectOnGround(player.mo)	
		and player.cmd.buttons & BT_CUSTOM1
			player.mo.groundboost = 1
		end
		if not (player.cmd.buttons & BT_CUSTOM1)
			player.mo.groundboost = 0
		end
		

		if player.prevrings == nil
			player.prevrings = 1
		end
		if player.notboostmeter == nil
			player.notboostmeter = 50
		end
		if player.notboostmeter > 50
			player.notboostmeter = 50
		end
		if player.boost == nil
			player.boost = 0
		end
		if player.boostdecr == nil
			player.boostdecr = 0
		end
		if player.mo.sound == nil
			player.mo.sound = 0
		end

		if player.mo.health == 1
		and not (player.cmd.buttons & BT_CUSTOM1)
			player.mo.sound = 0
		end
		if player.mo and player.mo.skin == "sonic"
			player.charability2 = CA2_NONE
			if not (player.charflags & SF_SUPER)
				player.charflags = $1 + SF_SUPER
			end
			if gametype == GT_RACE
				if player.powers[pw_sneakers] == 0
					player.mo.groundboost = 0
				else
					player.mo.groundboost = 1
				end
			end
			if player.boost == 1
			and player.mo.groundboost == 1
			and not (player.gotflag)
				player.charflags = $1|SF_RUNONWATER
				if gametype == GT_COOP
				or gametype == GT_RACE
					player.powers[pw_invulnerability] = TICRATE/2
				end
				if player.speed < 55*FRACUNIT
					P_Thrust(player.mo, player.mo.angle, 6*FRACUNIT)
				end
				if player.speed >= 55*FRACUNIT
					if player.mo.sound == 0
						player.mo.sound = 1
						S_StartSound(player.mo, sfx_boost)
						if not(player.mo.eflags & MFE_UNDERWATER)
							S_StartSound(player.mo, sfx_boost2)
						end
					end
					if player.powers[pw_super] == 0
						local boost = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_MTHOK)
							
						boost.target = player.mo
						boost.color = player.mo.color
						boost.angle = player.mo.angle
						local an = player.mo.angle
						local slope = player.aiming
						local speed = boost.info.speed
						
					else
						local boost = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_MTHOK)
								
						boost.target = player.mo
						boost.color = 24
						boost.angle = player.mo.angle
						local an = player.mo.angle
						local slope = player.aiming
						local speed = boost.info.speed
					
					end					
					if not (player.panim == PA_RUN)
					and P_IsObjectOnGround(player.mo)
					and not (player.pflags & PF_SPINNING)
						player.mo.state = S_PLAY_RUN
					end
					if player.powers[pw_super] == 0
						P_InstaThrust(player.mo, player.mo.angle, FixedMul(70*FRACUNIT, player.mo.scale)+10*FRACUNIT)
					else
						P_InstaThrust(player.mo, player.mo.angle, FixedMul(90*FRACUNIT, player.mo.scale)+10*FRACUNIT)
					end
				end
				if player.panim == PA_IDLE
					player.mo.state = S_PLAY_RUN
				end
				player.boostdecr = $1+1
				if player.boostdecr >= 6
					and player.notboostmeter >= 0
					then
					player.notboostmeter = $1 - 1
					player.boostdecr = 0
				end
			else
				player.charflags = $1 & ~SF_RUNONWATER
			end
			if player.notboostmeter == 0
				player.boost = 0
			end
				
			if player.rings < player.mo.health
			then
				player.notboostmeter = $1 + (player.mo.health - player.rings)
			end
				
			if player.exiting
				player.boost = 0
			end
		
			if (player.cmd.buttons & BT_CUSTOM1)
			and player.mo.groundboost == 1
				if player.notboostmeter > 1
				and not (player.pflags & PF_SLIDING)
				and not (player.pflags & PF_STASIS)
				and not (player.pflags & PF_JUMPSTASIS)
				and not (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)
				then
					player.boost = 1
				end
			else
				player.mo.sound = 0
				player.boost = 0
			end
			if player.powers[pw_super]
				player.mo.groundboost = 1
				player.notboostmeter = 50
			end
			if player.boosttowin == 1
				player.notboostmeter = 50
			end
				
				
                    if (player.cmd.buttons & BT_USE)
                    and (player.pflags & PF_USEDOWN)           
					and not (player.pflags & PF_STASIS)
					and (player.pflags & PF_SPINNING)
					and not (player.pflags & PF_STARTDASH)
                    and player.spinningtime > 1
					and (P_IsObjectOnGround(player.mo)) then
                        player.mo.state = S_PLAY_RUN
                        player.pflags = $1 & ~PF_SPINNING
            end
            if (player.pflags & PF_SPINNING) and not (player.pflags & PF_USEDOWN) then
                player.spinningtime = $1+1
            else
                player.spinningtime = 0
            end
		end
		player.prevrings = player.mo.health
		end
	end
end)

freeslot("sfx_stomp", "sfx_ground", "sfx_boost", "sfx_boost2")

local function P_GravAndScale (actor)
	return P_MobjFlip(actor)*actor.scale
end



addHook("ThinkFrame", do
	for player in players.iterate
		if (player.mo and player.mo.skin == "sonic")
			//Initialize stomping variables
				if player.stomping == nil then
					player.stomping = false
				end
				if player.mo.stomp == nil then
					player.mo.stomp = false
				end
				if player.wasjuststomping == nil then
					player.wasjuststomping = false
				end
				//Begin stomping if ready
				if (player.cmd.buttons & BT_USE)
                and (P_IsObjectOnGround(player.mo) == false)
				and not (player.stomping == true) 
					player.mo.state = S_PLAY_FALL
					S_StartSound(player.mo, sfx_stomp)
					player.stomping = true
				end
				if player.stomping == true
				and player.mo.momz < 0
					player.mo.state = S_PLAY_FALL
				end
				if player.mo.state == S_PLAY_SPRING
				or player.panim == PA_ROLL
				or P_IsObjectOnGround(player.mo)
				or player.mo.eflags & MFE_GOOWATER
				or player.mo.momz == 0
					player.stomping = false
				end
				//Stomping effects
				if player.stomping == true then
					player.mo.momx = 0
					player.mo.momy = 0
					player.mo.momz = FixedMul(-60*FRACUNIT, P_GravAndScale(player.mo))
					P_SpawnGhostMobj(player.mo)
				end
				//Create stomp explosion if just stopped stomping
				if (P_IsObjectOnGround(player.mo) == true)
				and (player.stomping == false)
				and (player.wasjuststomping == true) then
					S_StartSound(player.mo, sfx_ground)
					for i = 0,31
						local offset = FixedMul(1*FRACUNIT, P_GravAndScale(player.mo))
						local dust = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + offset, MT_STOMPDUST)
						dust.target = player.mo
						dust.scale = player.mo.scale
						if player.mo.eflags & MFE_VERTICALFLIP then
							dust.flags2 = $1|MF2_OBJECTFLIP // flip gravity!
						end
						local an = i*ANGLE_11hh
						local speed = dust.info.speed/FRACUNIT
						dust.momx = speed*cos(an)
						dust.momy = speed*sin(an)
						dust.momz = 0
					end
				end
				if player.powers[pw_super] 
				and not (player.cmd.buttons & BT_USE)
					player.stomping = false
					player.wasjuststomping = false
				end
				//Determine was-just-stomping variable
				player.wasjuststomping = player.stomping
		end
	end
end)

freeslot("MT_STOMPDUST")

addHook("MobjThinker", function(stompdust) 
	for player in players.iterate
		P_RadiusAttack(stompdust, stompdust.target, 60*FRACUNIT)
		end
end, MT_STOMPDUST)


addHook("MobjMoveCollide", function(stompdust, mobj)
	for player in players.iterate
		if (mobj.valid and mobj.health and mobj.flags & (MF_ENEMY|MF_BOSS))
			P_DamageMobj(mobj, stompdust, stompdust.target.target, 2)
		end
		if (mobj.valid and mobj.health and mobj.flags & MF_MONITOR)
			P_KillMobj(mobj, stompdust, stompdust.target)
		end
	end
end, MT_STOMPDUST)


function A_INVERTSONICDIR(actor, var1, var2)
	for player in players.iterate
		player.mo.angle = FixedAngle(AngleFixed(InvAngle(player.mo.angle))*2)
	end
end

function A_SPAWNSONICWALLJUMPOBJECT(actor, var1, var2)
	local springtype
	if not (actor.target and actor.target.player)
		return
	end
	if actor.target.player.powers[pw_super]
		springtype = var2
	else
		springtype = var1
	end
	
	P_InstaThrust(actor.target.player.mo, actor.target.player.mo.angle, -20*FRACUNIT)
	actor.target.player.mo.angle = R_PointToAngle2(0, 0, actor.target.player.mo.momx, actor.target.player.mo.momy)
	P_InstaThrust(actor.target.player.mo, actor.target.player.mo.angle, 20*FRACUNIT)
	if actor.target.player.powers[pw_super]
		P_SetObjectMomZ(actor.target.player.mo, actor.target.player.jumpfactor*20, false)
	else
		P_SetObjectMomZ(actor.target.player.mo, actor.target.player.jumpfactor*12, false)
	end
	actor.target.player.pflags = 0|PF_JUMPED
	actor.target.player.mo.walljumpcountdown = 0
end

addHook("ThinkFrame", do
	for player in players.iterate
		if (player.mo and player.mo.skin == "sonic")
			if not player.mo.walljumpcountdown
				player.mo.walljumpcountdown = TICRATE
			end
			player.mo.walljumpcountdown = $1 + 1
			if player.mo.walljumpcountdown > TICRATE/4 
			and player.mo.walljumpcountdown < TICRATE/2
				P_InstaThrust(player.mo, player.mo.angle, 15*FRACUNIT)
				player.mo.walljumpcountdown = TICRATE
			end
		end
	end
end)


addHook("ThinkFrame", do
	for player in players.iterate
		if (player.mo and player.mo.skin == "sonic")
			if not (P_IsObjectOnGround(player.mo))
			and not (player.pflags & PF_JUMPED)
			and not (player.panim == PA_ROLL)
				player.mo.state = S_PLAY_FALL
			end
			if player.pflags & PF_JUMPED
				if not (player.panim == PA_ROLL)
					player.mo.state = S_PLAY_ROLL
				end
			end
		end
	end
end)

addHook("AbilitySpecial", function(player)
	
	if player.mo.skin == "sonic"
		P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_PLACEHOLDERSONICWALLJUMP)
		if not (player.pflags & PF_THOKKED)
		and not P_LookForEnemies(player)
			player.charability = CA_NONE
			player.pflags = $1 & ~PF_JUMPED
			P_DoJump(player, true)
			player.pflags = $1 & ~PF_SPINNING
			player.pflags = $1|PF_THOKKED
			player.mo.jump = 1
		else
			player.charability = CA_HOMINGTHOK
		end
		if (player.pflags & PF_THOKKED)
		and P_LookForEnemies(player)
		and player.charability == CA_HOMINGTHOK
			player.pflags = $1 & ~PF_THOKKED
		end
	end
end)

addHook("ThinkFrame", do
	for player in players.iterate
		if player.mo and player.mo.skin == "sonic"
			if not (player.mo.sliding)
				player.mo.sliding = 0
			end
			if not (player.mo.slideslow)
				player.mo.slideslow = 0
			end
			
			if (player.cmd.buttons & BT_USE)
			and not (player.exiting)
			and not (player.pflags & PF_STASIS)
			and not P_PlayerInPain(player)
			and not (player.weapondelay)
			and not (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)
			and player.speed > 1*FRACUNIT
			and P_IsObjectOnGround(player.mo)
			and (player.mo.sliding == 0)
			and (player.mo.slideslow == 0)
				A_Thrust(player.mo, 40, 1)
				player.mo.state = S_PLAY_PAIN
				S_StartSound(player.mo, sfx_stomp)
				P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_SMOKE)
				player.powers[pw_nocontrol] = 32767
				player.mo.sliding = 1
			end
			if player.mo.sliding == 1
			and not (player.cmd.buttons & BT_CUSTOM1)
				player.mo.sliding = 0
				player.mo.slideslow = 1
			end
			if player.mo.slideslow == 1
			and player.mo.momx == 0
			and player.mo.momy == 0
				player.powers[pw_nocontrol] = 0
				player.mo.state = S_PLAY_RUN
				player.mo.slideslow = 0
			end
			if (player.mo.state == S_PLAY_SPRING) then
				player.powers[pw_nocontrol] = 0
			end
			if not P_IsObjectOnGround(player.mo)
				player.powers[pw_nocontrol] = 0
            end
			if (player.mo.slideslow == 1)
			and player.speed < 1
				if ((player.mo.ceilingz - player.mo.floorz) > player.mo.height*2)
						player.pflags = $1 & ~PF_SLIDING
						player.pflags = $1 & ~MF_SLIDEME
						player.powers[pw_nocontrol] = 0
						player.mo.state = S_PLAY_STND
						player.mo.slideslow = 0
				else
						player.pflags = $1|PF_SLIDING
						player.pflags = $1|MF_SLIDEME
						player.powers[pw_nocontrol] = 0
						A_Thrust(player.mo, 5, 0)
				end
			end
            if (player.mo.slideslow == 1)
				P_RadiusAttack(player.mo, player.mo, 120*FRACUNIT)
			end
			if (player.cmd.buttons & BT_CUSTOM1)
			and player.mo.slideslow == 1
				if ((player.mo.ceilingz - player.mo.floorz) > player.mo.height*2)
					player.pflags = $1 & ~PF_SLIDING
					player.pflags = $1 & ~MF_SLIDEME
					player.powers[pw_nocontrol] = 0
					player.mo.state = S_PLAY_RUN
					player.mo.slideslow = 0
				end
			end
			if player.cmd.buttons & BT_JUMP
				player.pflags = $1 & ~PF_SLIDING
				player.pflags = $1 & ~MF_SLIDEME
				player.powers[pw_nocontrol] = 0
				player.mo.slideslow = 0
			end
			if player.mo.slideslow == 1
				player.charability = 3
			elseif player.charability == 3
				player.charability = 4
			end
		end
	end
end)

//HitCoder's LightDash that he insisted i used. Thanks Buddy =P
addHook("ThinkFrame", do
	for player in players.iterate
		if (player.mo)
			if not player.mo.lightdashing
				player.mo.lightdashing = 0
			end
			
			if (player.cmd.buttons & BT_CUSTOM2)
			and player.mo.lightdashing == 0
				player.mo.lightdashing = 1
			end
			
			if player.mo.lightdashing == 1
			or player.mo.lightdashing == 2
				A_FindTarget (player.mo, MT_RING, 0)
				if player.mo.target
				and player.mo.target.type == MT_RING
				and not ((player.mo.target.x - player.mo.x) > 160*FRACUNIT)
				and not ((player.mo.target.x - player.mo.x) < -160*FRACUNIT)
				and not ((player.mo.target.y - player.mo.y) > 160*FRACUNIT)
				and not ((player.mo.target.y - player.mo.y) < -160*FRACUNIT)
				and not ((player.mo.target.z - player.mo.z) > 160*FRACUNIT)
				and not ((player.mo.target.z - player.mo.z) < -160*FRACUNIT)
					
					
					if not (player.mo.state == S_PLAY_FALL)
						player.mo.state = S_PLAY_FALL
					end
					P_SpawnGhostMobj(player.mo)
					player.mo.lightdashing = 2
					
					player.mo.angle = R_PointToAngle2(player.mo.x, player.mo.y, player.mo.target.x, player.mo.target.y)
					P_TeleportMove(player.mo, player.mo.target.x, player.mo.target.y, player.mo.target.z)
					
				else
					if player.mo.lightdashing == 2
						P_InstaThrust(player.mo, player.mo.angle, 32*FRACUNIT)
					end
					player.mo.lightdashing = 0
				end
			end
			if player.mo.lightdashing == 2
				player.mo.momx = 0
				player.mo.momy = 0
				player.mo.momz = 0
			end
		end
	end
end)

//quickstep
freeslot("sfx_sonicd")
addHook("ThinkFrame", do
	for player in players.iterate
		if player.mo
		if player.pflags & PF_JUMPED
			player.pflags = $1 & ~PF_SPINNING
		end
		if not (player.mo.sidestepping)
			player.mo.sidestepping = 0
		end
		if not (player.mo.sidetimer)
			player.mo.sidetimer = 0
		end
		if not (player.mo.sidestep)
			player.mo.sidestep = 0
		end
		if not (player.mo.prevspeed)
			player.mo.prevspeed = 0
		end
		if player.mo.sidestepping == 0
			player.prevspeed = player.speed
		end
		if (player.mo and player.mo.skin == "sonic")
		if P_IsObjectOnGround(player.mo)
		and player.mo and player.mo.valid and player.health
		and player.cmd.sidemove < 0
		and player.mo.sidestepping == 0
		and player.cmd.buttons & BT_CUSTOM3
			if not (player.mo.eflags & MFE_UNDERWATER)
				P_InstaThrust(player.mo, player.mo.angle + ANGLE_90, (FixedMul(64*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
			else
				P_InstaThrust(player.mo, player.mo.angle + ANGLE_90, (FixedMul(28*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
			end
			S_StartSound(player.mo, sfx_sonicd)
			player.mo.sidestepping = 1
			player.mo.sidetimer = 2
			player.mo.sidestep = 1
		else
			if player.cmd.sidemove > 0
			and player.mo and player.mo.valid and player.health
			and player.mo.sidestepping == 0
			and P_IsObjectOnGround(player.mo)
			and player.cmd.buttons & BT_CUSTOM3
				if not (player.mo.eflags & MFE_UNDERWATER)
					P_InstaThrust(player.mo, player.mo.angle - ANGLE_90, (FixedMul(64*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
				else
					P_InstaThrust(player.mo, player.mo.angle - ANGLE_90,  (FixedMul(28*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
				end
				S_StartSound(player.mo, sfx_sonicd)
				player.mo.sidestepping = 1
				player.mo.sidetimer = 2
				player.mo.sidestep = 1
			end
			if (player.cmd.sidemove == 0)
			and player.mo.sidestepping == 1
				player.mo.sidestepping = 0
			end
			if player.mo.sidestep == 1
			and player.mo.sidetimer == 0
				player.mo.sidestep = 0
				P_InstaThrust(player.mo, player.mo.angle - ANGLE_90, (FixedMul(0*FRACUNIT, player.mo.scale)+0*FRACUNIT)+cos(player.aiming))
				P_InstaThrust(player.mo, player.mo.angle + ANGLE_90, (FixedMul(0*FRACUNIT, player.mo.scale)+0*FRACUNIT)+cos(player.aiming))
				P_InstaThrust(player.mo, player.mo.angle, player.prevspeed)
				if player.prevspeed <= 1*FRACUNIT
					player.mo.state = S_PLAY_ROLL
				end
			end	
		end
		if player.mo.sidetimer > 0
			P_SpawnGhostMobj(player.mo)
			player.mo.sidetimer = $1 - 1
		end
		end
		end
	end
end)


addHook("TouchSpecial", function(special, toucher)
local player = toucher.player
	if toucher.valid and toucher.health
	and (toucher.player)
		player.notboostmeter = $1 + 1
	end
end, MT_RING)