freeslot("S_XTREME_SPINSLASH",
"S_XTREME_SPINSLASH2",
"S_XTREME_VICTORY",
"S_XTREME_VICTORY2",
"S_XTREME_JUMPSQUAT",
"S_XTREME_LAND",
"S_XTREME_FAN",
"S_XTREME_CROUCH1",
"S_XTREME_CROUCH2",
"S_XTREME_CROUCH3",
"S_XTREME_PAIN1",
"S_XTREME_PAIN2",
"S_XTREME_PAIN3",
"S_XTREME_SLIDE")

states[S_XTREME_SPINSLASH] = {SPR_PLAY, SPR2_TIRE|FF_ANIMATE, 8, nil, 7,  1, S_XTREME_SPINSLASH2}
states[S_XTREME_SPINSLASH2] = {SPR_PLAY, SPR2_FLY|FF_ANIMATE, -1, nil, 7,  1, S_XTREME_SPINSLASH2}
states[S_XTREME_VICTORY] = {SPR_PLAY, SPR2_MLEE|FF_SPR2ENDSTATE, 2, nil, S_XTREME_VICTORY2,  0, S_XTREME_VICTORY}
states[S_XTREME_VICTORY2] = {SPR_PLAY, SPR2_MLEE, -1, nil, 0, 0, S_PLAY_STND}
states[S_XTREME_FAN] = {SPR_PLAY, SPR2_TAL0, -1, nil, 0, 0, S_XTREME_FAN}
states[S_XTREME_JUMPSQUAT] = {SPR_PLAY, SPR2_TAL1|FF_SPR2ENDSTATE, 1, nil, S_PLAY_ROLL, 0, S_XTREME_JUMPSQUAT}
states[S_XTREME_LAND] = {SPR_PLAY, SPR2_LAND|FF_SPR2ENDSTATE, 1, nil, S_PLAY_STND, 0, S_XTREME_LAND}
states[S_XTREME_CROUCH1] = {SPR_PLAY, SPR2_TAL2|FF_SPR2ENDSTATE, 1, nil, S_XTREME_CROUCH2, 0, S_XTREME_CROUCH1}
states[S_XTREME_CROUCH2] = {SPR_PLAY, SPR2_TAL2, -1, nil, 0, 0, S_XTREME_CROUCH2}
states[S_XTREME_CROUCH3] = {SPR_PLAY, SPR2_TAL3|FF_SPR2ENDSTATE, 1, nil, S_PLAY_STND, 0, S_XTREME_CROUCH3}
states[S_XTREME_PAIN1] = {SPR_PLAY, SPR2_PAIN|FF_ANIMATE, 9, nil, 0, 3, S_XTREME_PAIN2}
states[S_XTREME_PAIN2] = {SPR_PLAY, SPR2_PAIN|FF_ANIMATE, 21, nil, 0, 7, S_XTREME_PAIN3}
states[S_XTREME_PAIN3] = {SPR_PLAY, SPR2_PAIN|FF_SPR2ENDSTATE, 4, nil, S_PLAY_STND, 0, S_XTREME_PAIN3}
states[S_XTREME_SLIDE] = {SPR_PLAY, SPR2_STUN, 2, nil, 0, 0, S_XTREME_SLIDE}
freeslot("sfx_slash1","sfx_slash2","sfx_slash3")
sfxinfo[sfx_slash1].caption = "Spinslash Start"
sfxinfo[sfx_slash2].caption = "Spinslash"
sfxinfo[sfx_slash2].singular = true
sfxinfo[sfx_slash3].caption = "Spinslash End"
sfxinfo[sfx_s255].caption = "Spinslash Hit"

freeslot("MT_SPINSLASH_SPIKE", "S_SPINSLASH_SPIKE","SPR_XSPK")
states[S_SPINSLASH_SPIKE] = {SPR_XSPK, A, -1, A_None, 0, 0, S_SPINSLASH_SPIKE}
mobjinfo[MT_SPINSLASH_SPIKE] = {
        doomednum = -1,
        spawnstate = S_SPINSLASH_SPIKE,
        spawnhealth = 1,
        seestate = S_NULL,
        seesound = sfx_None,
        reactiontime = 32,
        attacksound = sfx_None,
        painstate = S_NULL,
        painchance = 200,
        painsound = sfx_None,
        meleestate = S_NULL,
        missilestate = S_NULL,
        deathstate = S_NULL,
        xdeathstate = S_NULL,
        deathsound = sfx_None,
        speed = 60*FRACUNIT,
        radius = 30*FRACUNIT,
        height = 30*FRACUNIT,
        dispoffset = 0,
        mass = 0,
        damage = 0,
        activesound = sfx_None,
        flags = MF_MISSILE|MF_NOGRAVITY,
        raisestate = S_NULL
}

//Kirby Support
if not(kirbyabilitytable)
	rawset(_G, "kirbyabilitytable", {})
end
kirbyabilitytable["xtreme"] = 6

COM_AddCommand("xtreme_supermusic", function(player, arg)
	if arg
		if arg == "1" or arg == "spacequeens"
			if io and player == consoleplayer
				local file = io.openlocal("client/xtreme/supermusic.dat", "w+")
				file:write(arg)
				file:close()
			end
			player.spacequeens = true
			CONS_Printf(player, "Xtreme Sonic's super theme is now Space Queens!")
		elseif arg == "0" or arg == "soniccd" or arg == "cd"
			if io and player == consoleplayer
				local file = io.openlocal("client/xtreme/supermusic.dat", "w+")
				file:write(arg)
				file:close()
			end	
			player.spacequeens = false
			CONS_Printf(player, "Xtreme Sonic's super theme is now Sonic CD's prototype title screen music")
		elseif player.spacequeens
			CONS_Printf(player, "xtreme_supermusic [0/1] - Changes Xtreme Sonic's super music. Currently Space Queens.")
		else
			CONS_Printf(player, "xtreme_supermusic [0/1] - Changes Xtreme Sonic's super music. Currently Sonic CD's prototype title screen music.")
		end
	elseif player.spacequeens
		CONS_Printf(player, "xtreme_supermusic [0/1] - Changes Xtreme Sonic's super music. Currently Space Queens (from Sonic Xtreme).")
	else
		CONS_Printf(player, "xtreme_supermusic [0/1] - Changes Xtreme Sonic's super music. Currently Sonic CD's prototype title screen music.")
	end
end, 0)
addHook("PlayerSpawn", function(p)
	if io and p == consoleplayer and p.spacequeens == nil
		local file = io.openlocal("client/xtreme/supermusic.dat")
		if file
			local arg = file:read("*a")
			if arg == "1" or arg == "spacequeens" or arg == nil
				COM_BufInsertText(p, "xtreme_supermusic spacequeens")
			elseif arg == "0" or arg == "soniccd" or arg == "cd" 
				COM_BufInsertText(p, "xtreme_supermusic soniccd")
			end
			file:close()
		end
	end
end)
//Music
//Original Reusable template by Katmint.
addHook("MusicChange", function(oldname, newname)
	if consoleplayer
		local character = skins[consoleplayer.skin].name
		if character == "xtreme" //skin to use custom themes
			if newname == "_super" //intercept and override jingles
				if consoleplayer.spacequeens
					return "xsupr2"
				else
					return "xsuper"
				end
			elseif newname == "_inv"
				return "xinv"
			elseif newname == "_shoes"
				return "xshoes"
			elseif newname == "_clear"
				return "xclear"
			elseif newname == "_1up"
				return "xlife"
			elseif newname == "_gover"
				return "xgover"
			end
		end
	end
end)
addHook("MobjDeath", function(mo)
	if mo and mo.valid
	and mo.skin == "xtreme"
		S_ChangeMusic("xdeath", 0, mo.player)
	end
end, MT_PLAYER)
//Music
addHook("PlayerThink", function(player)
	if (player.mo.valid) and (player.mo.skin == "xtreme")
		player.hassupermusic = true
		if player.powers[pw_invulnerability] == 20*TICRATE
		and player.previnv == 0
			player.powers[pw_invulnerability] = 21*TICRATE
		elseif player.powers[pw_sneakers] == 20*TICRATE
		and player.prevshoes == 0
			player.powers[pw_sneakers] = 21*TICRATE
		end
		player.previnv = player.powers[pw_invulnerability]	
		player.prevshoes = player.powers[pw_sneakers]
		
		if player.xtreme_accel
			if (player.cmd.forwardmove or player.cmd.sidemove)
			and P_GetPlayerControlDirection(player) != 2
			and P_IsObjectOnGround(player.mo)
			or (player.cmd.forwardmove or player.cmd.sidemove)
			and not P_IsObjectOnGround(player.mo)
				player.mo.friction = FRACUNIT
			elseif P_GetPlayerControlDirection(player) == 0
				player.mo.friction = FRACUNIT-21065/6
			end
		end
		if not (player.pflags & PF_JUMPED) and not (player.pflags & PF_THOKKED)
		and player.mo.subsector and player.mo.subsector.sector
		and not P_IsObjectOnGround(player.mo)
			local SECTORZ = player.mo.subsector.sector
			local FANCHECK = (SECTORZ.special == 20480) and true or false
			if not FANCHECK --FOF check, then?
				for fof in SECTORZ.ffloors()
					if fof.sector and (fof.sector.special == 20480)
						FANCHECK = true
					end
				end
			end
			if FANCHECK
				player.mo.state = S_XTREME_FAN
				player.fanspin = 1
			else
				player.fanspin = 0
			end
		end
		if player.mo.state == S_XTREME_FAN
			player.prevdrawangle = $ + ANG20
			player.drawangle = player.prevdrawangle
		else
			player.prevdrawangle = player.drawangle
		end
	end
end)

--Fans and Steam jets make you spin!
local function XtremeFanSpin(s, so)
	if s.valid and so and so.skin == "xtreme" and so.health
	local p = so.player 
		if p
			if (p.pflags & (PF_JUMPED|PF_THOKKED|PF_SPINNING|PF_STARTDASH|PF_SLIDING))
				return
			end	
			if (s.type == MT_FAN)
				if (so.state == S_PLAY_FALL) and (so.momz*P_MobjFlip(so) > so.scale)
					so.state = S_XTREME_FAN
				end
			elseif (s.state <= S_STEAM2) --and (s.type == MT_STEAM)
				if (so.state != S_XTREME_FAN)	
					if (so.state == S_PLAY_FALL) and (so.momz*P_MobjFlip(so) > 8>>16)
						if (s.z <= so.z+66<<16) and not (s.eflags & MFE_VERTICALFLIP)
						or not (s.eflags & MFE_VERTICALFLIP) and (s.z >= so.z-99<<16)
							so.state = S_XTREME_FAN
						end
					end
				end
			end
		end
	end
end
addHook("MobjMoveCollide", XtremeFanSpin,  MT_STEAM)
addHook("MobjCollide", XtremeFanSpin,  MT_STEAM)
addHook("MobjMoveCollide", XtremeFanSpin,  MT_FAN)
addHook("MobjCollide", XtremeFanSpin,  MT_FAN)

local function inputangle(player)
	local prevvalue
	if (twodlevel or player.mo.flags2 & MF2_TWOD) or (player.mo.currentaxis)
		return player.mo.angle
	elseif (player.cmd.forwardmove or player.cmd.sidemove)
		prevvalue = (player.cmd.angleturn<<16 + R_PointToAngle2(0,0,player.cmd.forwardmove*FRACUNIT, -player.cmd.sidemove*FRACUNIT))
		return (player.cmd.angleturn<<16 + R_PointToAngle2(0,0,player.cmd.forwardmove*FRACUNIT, -player.cmd.sidemove*FRACUNIT))
	elseif prevvalue
		return prevvalue
	elseif not prevvalue
		prevvalue = (player.cmd.angleturn<<16)
		return prevvalue
	end
end
					
//Classic spindash behavior by rumia1!
addHook("ThinkFrame", do
	for player in players.iterate
		if player.mo and player.mo.valid
		and not (player.mo.state == S_PLAY_DEAD)
			if(player.mo.skin == "xtreme")
			and player.playerstate == PST_LIVE
				if player.spacequeens == nil
					player.spacequeens = true
				end
				if player.pflags & PF_SLIDING
				and not (player.pflags & PF_JUMPED)
				and (player.mo.eflags & MFE_UNDERWATER)
				or player.powers[pw_carry] == CR_DUSTDEVIL
				or player.powers[pw_carry] == CR_FAN
					player.mo.state = S_XTREME_FAN
				elseif player.pflags & PF_SLIDING
				and not (player.pflags & PF_JUMPED)
					player.mo.state = S_XTREME_SLIDE
					player.mo.frame = (leveltime % 8)/2
				end
								
				if player.mo.state == S_PLAY_PAIN
					player.mo.painanimtimer = $ + 1
					player.mo.anim_duration = -1
					local frame = player.mo.frame&FF_FRAMEMASK
					local timer = player.mo.painanimtimer
					if frame == A
					and timer == 3
						player.mo.state = S_PLAY_PAIN
						player.mo.painanimtimer = 0
					elseif frame == B
					and timer == 3
						player.mo.state = S_PLAY_PAIN
						player.mo.painanimtimer = 0
					elseif frame == C
					and timer == 3
						player.mo.state = S_PLAY_PAIN
						player.mo.painanimtimer = 0
					elseif frame == D
					and timer == 6
						player.mo.state = S_PLAY_PAIN
						player.mo.painanimtimer = 0
					elseif frame == E
					and timer == 6
						player.mo.state = S_PLAY_PAIN
						player.mo.painanimtimer = 0
					elseif frame == F
					and timer == 6
						player.mo.state = S_PLAY_PAIN
						player.mo.painanimtimer = 0
					elseif frame == G
					and timer == 4
						player.mo.state = S_PLAY_PAIN
						player.mo.painanimtimer = 0
					elseif frame == H
					and timer == 4
						player.mo.state = S_PLAY_PAIN
						player.mo.painanimtimer = 0
					elseif frame == I
					and timer == 4
						player.mo.state = S_PLAY_FALL
						player.mo.painanimtimer = 0
					end
				else
					player.mo.painanimtimer = 0
				end
				
				if player.xtreme_accel
				and (player.pflags & PF_SLIDING)
					player.xtreme_accel = false
					player.xtreme_was_accel = true
				end
				if not player.xtreme_accel
				and not (player.pflags & PF_SLIDING)
				and player.xtreme_was_accel
					player.xtreme_accel = true
					player.xtreme_was_accel = nil
				end
			//Genesis Control Scheme pulled from another project
				if player.xtreme_accel
					local AIR
					if P_IsObjectOnGround(player.mo)
						AIR = 1
					else
						AIR = 1
					end
					local WTR
					if player.mo.eflags & MFE_UNDERWATER
						WTR = 2
					else
						WTR = 1
					end
					
					if (player.gen_topspeed == nil) then player.gen_topspeed = 0 end
					if (player.gen_accelfactor == nil) then player.gen_accelfactor = 0 end
					if (player.gen_friction == nil) then player.gen_friction = 0 end
					if (player.gen_deccelfactor == nil) then player.gen_deccelfactor = 0 end
					if (player.gen_speed == nil) then player.gen_speed = 0 end
					if (player.gen_speed1 == nil) then player.gen_speed1 = 0 end
					if (player.gen_speed2 == nil) then player.gen_speed2 = 0 end
					if player.powers[pw_sneakers]
					and not player.powers[pw_super]
						player.gen_topspeed = (72*FU)/WTR
						player.gen_accelfactor = ((5625*FU/10000)*AIR)/WTR
						player.gen_deccelfactor = (3*FU)/WTR
						player.gen_friction = (5625*FU/10000)
					elseif player.powers[pw_sneakers]
					and	player.powers[pw_super]
						player.gen_topspeed = (120*FU)/WTR
						player.gen_accelfactor = ((1125*FU/1000)*AIR)/WTR
						player.gen_deccelfactor = (6*FU)/WTR
						player.gen_friction = (5625*FU/10000)
					elseif player.powers[pw_super]
						player.gen_topspeed = (60*FU)/WTR
						player.gen_accelfactor = ((1125*FU/1000)*AIR)/WTR
						player.gen_deccelfactor = (6*FU)/WTR
						player.gen_friction = (28125*FU/100000)
					else
						player.gen_topspeed = (36*FU)/WTR
						player.gen_accelfactor = ((28125*FU/100000)*AIR)/WTR
						player.gen_deccelfactor = (3*FU)/WTR
						player.gen_friction = (28125*FU/100000)
					end
					if not (player.pflags & PF_SPINNING)
					and not (player.mo.state == S_PLAY_PAIN)
					//acceleration and physics
						if (player.cmd.forwardmove or player.cmd.sidemove)
						and P_GetPlayerControlDirection(player) != 2
						and P_IsObjectOnGround(player.mo)
						and not (player.mo.state == S_XTREME_CROUCH1 or player.mo.state == S_XTREME_CROUCH2 or player.mo.state == S_XTREME_CROUCH3)
						or (player.cmd.forwardmove or player.cmd.sidemove)
						and not P_IsObjectOnGround(player.mo)
-- 							player.mo.friction = FRACUNIT
							local analogstick = 2*FixedHypot(player.cmd.forwardmove,player.cmd.sidemove)
							if FixedHypot(player.mo.momx, player.mo.momy) < analogstick*(player.gen_topspeed)/100
								P_Thrust(player.mo, inputangle(player), player.gen_accelfactor*2)
							elseif FixedHypot(player.mo.momx, player.mo.momy) > player.gen_topspeed
								P_Thrust(player.mo, inputangle(player), player.gen_accelfactor/3)
							end
							//Momentum redirection power is lower in the air than on the ground.
							local redirectPower
							if (P_IsObjectOnGround(player.mo)) then redirectPower = 15
							else redirectPower = 10 end
							//Redirect a portion of the player's current speed in their current input direction.
							local redirectSpeed = FixedHypot(player.mo.momx, player.mo.momy)*redirectPower/100
							player.mo.momx = player.cmomx+((player.mo.momx-player.cmomx)*(100-redirectPower)/100)
							player.mo.momy = player.cmomy+((player.mo.momy-player.cmomy)*(100-redirectPower)/100)				
							P_Thrust(player.mo, inputangle(player), redirectSpeed)
							player.acceleration = 0
							player.accelstart = 0
							player.thrustfactor = 0
						elseif (player.cmd.forwardmove or player.cmd.sidemove)
						and P_GetPlayerControlDirection(player) == 2
						and P_IsObjectOnGround(player.mo)
						or (player.pflags & PF_APPLYAUTOBRAKE)
						and P_IsObjectOnGround(player.mo)
							player.acceleration = skins[player.mo.skin].acceleration
							player.accelstart = skins[player.mo.skin].accelstart
							player.thrustfactor = skins[player.mo.skin].thrustfactor
						elseif P_GetPlayerControlDirection(player) == 0
							player.acceleration = skins[player.mo.skin].acceleration
							player.accelstart = skins[player.mo.skin].accelstart
							player.thrustfactor = skins[player.mo.skin].thrustfactor
						end
					elseif (player.pflags & PF_SPINNING)
						if (player.cmd.forwardmove or player.cmd.sidemove)
						and P_GetPlayerControlDirection(player) == 2
							P_Thrust(player.mo, player.drawangle + ANGLE_180, FixedHypot(player.mo.momx,player.mo.momy)/50)
						elseif P_GetPlayerControlDirection(player) == 0
							P_Thrust(player.mo, player.drawangle + ANGLE_180, FixedHypot(player.mo.momx,player.mo.momy)/50)
						end
						player.acceleration = skins[player.mo.skin].acceleration
						player.accelstart = skins[player.mo.skin].accelstart
						player.thrustfactor = skins[player.mo.skin].thrustfactor*3
					end
				else
					player.acceleration = skins[player.mo.skin].acceleration
					player.accelstart = skins[player.mo.skin].accelstart
					player.thrustfactor = skins[player.mo.skin].thrustfactor
				end
				
				
				
				
//Classic spindash behavior by rumia1!
//Modified by SuperPhanto to work a bit differently...
//setting up the variable to check for how many charges the current spindash has
				if player.spincharges == nil
					player.spincharges = 0
				end
//this one checks how long the spindash has been held for
				if player.dashtime == nil
				or not (player.pflags & PF_STARTDASH)
					player.dashtime = 35
				end
//and this one checks how many automatic charges we've added, as we can only have 4
				if player.dashcounter == nil
				or not (player.pflags & PF_STARTDASH)
					player.dashcounter = 0
				end
//checks if player was holding jump last frame
				if player.jumpwasdown == nil
					player.jumpwasdown = 0
				end
//makes our life easier
				if player.pflags & PF_STARTDASH
					player.dashspeed = player.maxdash
					player.mindash = player.maxdash - (21*player.dashspeed)
				end
				if player.spinrev == nil
					player.spinrev = 0
				end
				if player.dashtime <= 0
					player.dashtime = 35
				end
				if player.spindashing == nil
					player.spindashing = 0
				end
				if player.spindashed == nil
					player.spindashed = 0
				end
				if player.spindashed > 0
					player.spindashed = $-1
				end
				local testing = 0
				if testing == true then print(player.dashcounter+","+player.dashtime+","+player.dashspeed/FRACUNIT+","+player.spincharges+","+player.spinrev+","+player.gen_topspeed) end
				//You gotta be spindashing, man!
				if (player.pflags & PF_STARTDASH)
				and player.spinslash == 0
				and (player.cmd.buttons & BT_SPIN)
					player.dashtime = $ - 1
					player.jumpfactor = 0
					player.mo.state = S_PLAY_SPINDASH
					if player.spinrev > 0
						player.spinrev = $ - (FixedDiv($, FRACUNIT*5/4) / 42)
					elseif player.spinrev <= 0
						player.spinrev = 0
					end
					if player.spinrev > 48*FRACUNIT
						player.spinrev = 48*FRACUNIT
					end
					player.mindash = 0
					player.maxdash = 0
					player.spindashing = 1
					if (player.cmd.buttons & BT_JUMP)
					and not (player.jumpwasdown)
					or (player.cmd.buttons & BT_CUSTOM1)
					and not (player.custom1wasdown)
					or (player.cmd.buttons & BT_CUSTOM2)
					and not (player.custom2wasdown)
					or (player.cmd.buttons & BT_CUSTOM3)
					and not (player.custom3wasdown)	
						player.dashtime = 35
						if player.spincharges < 15
							player.spincharges = $ + 1
						else
							player.spincharges = 15
						end
						if player.spinrev < 48*FRACUNIT
							player.spinrev = $ + 12*FRACUNIT
						end
						S_StopSound(player.mo)
						S_StartSound(player.mo, sfx_s3kab + player.spincharges)
//after adding a maximum of 15, it becomes sfx_s3kabf(Spindash Rev Highest Pitch)
					else
						if player.dashtime == 0
							player.spincharges = 0
						end
					end
				elseif not (player.cmd.buttons & BT_SPIN)
				and player.spindashing == 1
				and player.spinslash == 0
					if player.xtreme_accel
						P_InstaThrust(player.mo, player.mo.angle, player.gen_topspeed + (player.spinrev))
					else
						P_InstaThrust(player.mo, player.mo.angle, player.normalspeed + (player.spinrev))
					end
					S_StartSound(player.mo, sfx_zoom)
					player.pflags = $ | PF_SPINNING & ~PF_STARTDASH
					player.mo.state = S_PLAY_ROLL
					player.spindashing = 0
//You gotta be spinslashing, man!
				elseif player.spinslash == 3
					player.pflags = $|PF_JUMPSTASIS
					player.mo.state = S_XTREME_SPINSLASH2
					if player.mo.frame & FF_FULLBRIGHT
						player.mo.frame = (leveltime % 8)|FF_FULLBRIGHT
					else
						player.mo.frame = (leveltime % 8)
					end
					if (player.cmd.buttons & BT_USE)
						player.dashtime = $ - 1
						if player.spinrev > 0
							player.spinrev = $ - (FixedDiv($, FRACUNIT*5/4) / 42)
						elseif player.spinrev <= 0
							player.spinrev = 0
						end
						if player.spinrev > 48*FRACUNIT
							player.spinrev = 48*FRACUNIT
						end
						player.mindash = 0
						player.maxdash = 0
						player.spindashing = 1
						if (player.cmd.buttons & BT_JUMP)
						and not (player.jumpwasdown)
						or (player.cmd.buttons & BT_CUSTOM1)
						and not (player.custom1wasdown)
						or (player.cmd.buttons & BT_CUSTOM2)
						and not (player.custom2wasdown)
						or (player.cmd.buttons & BT_CUSTOM3)
						and not (player.custom3wasdown)
							player.dashtime = 35
							if player.spincharges < 15
								player.spincharges = $ + 1
							else
								player.spincharges = 15
							end
							if player.spinrev < 48*FRACUNIT
								player.spinrev = $ + 12*FRACUNIT
							end
							S_StopSound(player.mo)
							S_StartSound(player.mo, sfx_s3kab + player.spincharges)
//after adding a maximum of 15, it becomes sfx_s3kabf(Spindash Rev Highest Pitch)
						else
							if player.dashtime == 0
								player.spincharges = 0
							end
						end
					elseif player.spindashing == 1
						if player.xtreme_gravity 
							if player.xtreme_accel
								P_SetObjectMomZ(player.mo, (player.gen_topspeed + (player.spinrev))/2)
							else
								P_SetObjectMomZ(player.mo, (player.normalspeed + (player.spinrev))/2)
							end
						else
							if player.xtreme_accel
								P_SetObjectMomZ(player.mo, (player.gen_topspeed + (player.spinrev))/3)
							else
								P_SetObjectMomZ(player.mo, (player.normalspeed + (player.spinrev))/3)
							end
						end
						S_StartSound(player.mo, sfx_zoom)
						player.spinslash = 0
						player.xtremewallslide = 0
						player.mo.state = S_PLAY_ROLL
						player.spindashing = 0
						player.pflags = $ | PF_JUMPED & ~PF_THOKKED
						player.spindashed = 4
					end
				else
					player.spincharges = 0
					player.spinrev = 0
				end
				if FixedHypot(player.mo.momx, player.mo.momy) <= 5*FRACUNIT
				and P_IsObjectOnGround(player.mo)
				and not (player.mo.state == S_PLAY_SPINDASH)
				and not player.spinslash
					player.charability2 = CA2_NONE
					if (player.cmd.buttons & BT_SPIN)
-- 					and not (player.cmd.forwardmove or player.cmd.sidemove)
					and not (player.mo.state == S_PLAY_PAIN)
						if not (player.mo.state == S_XTREME_CROUCH1)
						and not (player.mo.state == S_XTREME_CROUCH2)
						and not (player.mo.state == S_XTREME_CROUCH3)
							player.mo.state = S_XTREME_CROUCH1
						end
						player.jumpfactor = 0
						P_InstaThrust(player.mo, 0,0)
					end
				elseif not (player.mo.state == S_XTREME_CROUCH1)
				and not (player.mo.state == S_XTREME_CROUCH2)
				and not (player.mo.state == S_XTREME_CROUCH3)
				and not (player.mo.state == S_PLAY_SPINDASH)
				and not (player.mo.state == S_XTREME_SPINSLASH)
				and not (player.mo.state == S_XTREME_SPINSLASH2)
					player.charability2 = CA2_SPINDASH
				else
					player.charability2 = CA2_NONE
				end
				
				if (player.mo.state == S_XTREME_CROUCH1 or player.mo.state == S_XTREME_CROUCH2 or player.mo.state == S_XTREME_CROUCH3)
					player.thrustfactor = 0
				end
				
				if (player.mo.state == S_XTREME_CROUCH1 or player.mo.state == S_XTREME_CROUCH2 or player.mo.state == S_XTREME_CROUCH3)
				and (player.cmd.buttons & BT_JUMP)
				or player.spinslash == 2
				and P_IsObjectOnGround(player.mo)
				and (player.cmd.buttons & BT_SPIN)
				and (player.cmd.buttons & BT_JUMP)
					player.charability2 = CA2_NONE
					player.pflags = $ | PF_STARTDASH | PF_SPINNING
					S_StartSound(player.mo, sfx_spndsh)
					player.mo.state = S_PLAY_SPINDASH
--  			elseif (player.mo.state == S_XTREME_CROUCH1 or player.mo.state == S_XTREME_CROUCH2 or player.mo.state == S_XTREME_CROUCH3)
-- 				and(player.cmd.forwardmove or player.cmd.sidemove)
-- 					player.mo.state = S_PLAY_WALK
				elseif (player.mo.state == S_XTREME_CROUCH1 or player.mo.state == S_XTREME_CROUCH2)
				and not (player.cmd.buttons & BT_SPIN)
					player.mo.state = S_XTREME_CROUCH3
				end
				
				
-- 				if player.prevmomz != nil
-- 					print(player.prevmomz/FU+","+player.climbing2)
-- 				end
				if player.spindashed
				and P_MobjFlip(player.mo) == 1
				and player.mo.momz <= player.prevmomz / 2
					P_SetObjectMomZ(player.mo, player.mo.momz*2)
-- 					print("Wall Spindash Glitch prevented for "..player.name.."!")
				end
				if not player.spinslash
					player.prevmomz = player.mo.momz
				end
//Shoot Spikes
				if player.spinslash == 1
				and player.prevspinslash == player.spinslash
				and player.pflags & PF_THOKKED
				and player.cmd.buttons & BT_JUMP
				and not player.jumpwasdown
					local gs = P_SpawnGhostMobj(player.mo)
					gs.tics = 2
-- 					A_OldRingExplode(gs, MT_SPINSLASH_SPIKE, 0)
					for i=0, 7
						P_SpawnParaloop(player.mo.x, player.mo.y, player.mo.z + player.mo.height, FixedMul(384*FRACUNIT, player.mo.scale), 8, MT_SPINSLASH_SPIKE, i*ANGLE_45, S_SPINSLASH_SPIKE, true)
					end
					searchBlockmap("objects", function(pmo, mo)
						if mo == pmo return end
						if mo.type == MT_SPINSLASH_SPIKE
							mo.target = pmo
							mo.color = mo.target.color
						end
					end, player.mo)
					player.spinslash = 0
					P_SetObjectMomZ(player.mo, 0)
					player.mo.state = S_PLAY_ROLL
					S_StopSound(player.mo)
					S_StartSound(player.mo,sfx_kc5b)
					if player.powers[pw_super]
						player.pflags = $&~PF_THOKKED
					end
				end
				player.prevspinslash = player.spinslash
				
				if player.xtreme_gravity == nil
					player.xtreme_gravity = true
				end
				if player.xtreme_accel == nil
					player.xtreme_accel = true
				end
-- 				if player.mo.state != S_PLAY_SPINDASH
-- 				and player.mo.state != S_XTREME_SPINSLASH2
				if player.mo.state == S_PLAY_WAIT
					if player.cmd.buttons & BT_CUSTOM1
					and not player.custom1wasdown
						if player.xtreme_gravity
							player.xtreme_gravity = false
							S_StartSound(player.mo, sfx_adderr, player)
							COM_BufInsertText(player, "cecho Classic Gravity: Off")
						else
							player.xtreme_gravity = true
							S_StartSound(player.mo, sfx_addfil, player)
							COM_BufInsertText(player, "cecho Classic Gravity: On")
						end
					end
					if player.cmd.buttons & BT_CUSTOM2
					and not player.custom2wasdown
					and not (player.pflags & PF_SLIDING)
						if player.xtreme_accel
							player.xtreme_accel = false
							S_StartSound(player.mo, sfx_adderr, player)
							COM_BufInsertText(player, "cecho Classic Acceleration: Off")
						else
							player.xtreme_accel = true
							S_StartSound(player.mo, sfx_addfil, player)
							COM_BufInsertText(player, "cecho Classic Acceleration: On")
						end
					end
				end
			//Uncurl
				if not player.powers[pw_carry]
				and (player.cmd.buttons & BT_USE)
				and (player.pflags & PF_USEDOWN)
				and not (player.mo.state == S_PLAY_PAIN)
				and not (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)
				and not (player.pflags & PF_STASIS)
				and (player.pflags & PF_SPINNING)
				and not (player.pflags & PF_STARTDASH)
				and not (player.exiting)
				and player.spinningtime > 1
				and (P_IsObjectOnGround(player.mo)) then
					player.mo.state = S_PLAY_WALK
					player.pflags = $1 & ~PF_SPINNING
				end

				if (player.pflags & PF_SPINNING) and not (player.pflags & PF_USEDOWN) then
					player.spinningtime = $+1
				else
					player.spinningtime = 0
				end
//Our "was jump pressed last frame?" check ends here
				player.jumpwasdown = (player.cmd.buttons & BT_JUMP)
				player.custom1wasdown = (player.cmd.buttons & BT_CUSTOM1)
				player.custom2wasdown = (player.cmd.buttons & BT_CUSTOM2)
				player.custom3wasdown = (player.cmd.buttons & BT_CUSTOM3)
			end
		end
	end
end)

//thanks seezee for the gravity code
addHook("PlayerThink", function(player)
	if (player.mo and player.mo.valid)
		if (player.mo.skin == "xtreme")
		and player.xtreme_gravity
		and not (player.powers[pw_carry])
			if player.mo.gooptimer == nil
				player.mo.gooptimer = 0
			end
			if P_IsObjectInGoop(player.mo)
				player.mo.gooptimer = 10
			elseif player.mo.gooptimer > 0
				player.mo.gooptimer = $-1
			end
			if (player.mo.eflags & MFE_SPRUNG or player.previously_in_mace)
			and not player.spinslash
				if player.mo.eflags & MFE_UNDERWATER
-- 					player.mo.momx = $*10/4
-- 					player.mo.momy = $*10/4
					player.mo.momz = $*10/4
				else
-- 					player.mo.momx = $*3/2
-- 					player.mo.momy = $*3/2
					player.mo.momz = $*3/2
				end
			end
			if /* not (player.mo.state == S_PLAY_PAIN)
			and */ not player.spinslash
				if player.mo.state >= S_PLAY_SUPER_TRANS1 and player.mo.state <= S_PLAY_SUPER_TRANS6 return end
				local pr = 1
				local gr = 1
				if player.mo.eflags & MFE_UNDERWATER
					pr = 2
					gr = 1/2
					player.jumpfactor = (3)*FRACUNIT/2
				else
					pr = 1
					gr = 3/2
					player.jumpfactor = (2)*FRACUNIT
				end
				if not P_IsObjectOnGround(player.mo) and not P_IsObjectInGoop(player.mo) and not player.mo.gooptimer and not player.fanspin
					P_SetObjectMomZ(player.mo, -gravity*gr, true)
				end
			end
			player.previously_in_mace = player.powers[pw_carry] == CR_MACESPIN
		elseif (player.mo.skin == "xtreme")
		and not player.xtreme_gravity
			player.jumpfactor = (5)*FRACUNIT/4
		end
	end
end)

//Animation Speed fix + Momentum Stuff
addHook("ThinkFrame", do
	for player in players.iterate
		if (player.mo and player.mo.valid and player.mo.skin == "xtreme")
			if not player.xtreme_accel
				if (FixedHypot(player.rmomx, player.rmomy) > player.normalspeed)
				and P_IsObjectOnGround(player.mo)
				and (player.cmd.forwardmove or player.cmd.sidemove)
				and not (player.pflags & PF_SPINNING)
					if player.powers[pw_super]
					or player.powers[pw_sneakers]
						player.normalspeed = max(FixedHypot(player.mo.momx, player.mo.momy)/5*3, skins[player.mo.skin].normalspeed)
					else
						player.normalspeed = max(FixedHypot(player.mo.momx, player.mo.momy), skins[player.mo.skin].normalspeed)
					end
				elseif (FixedHypot(player.rmomx, player.rmomy) < player.normalspeed-FRACUNIT*20)
				and P_IsObjectOnGround(player.mo)
				and not (player.pflags & PF_SPINNING)
-- 				and not (player.cmd.forwardmove or player.cmd.sidemove)
					if player.powers[pw_super]
					or player.powers[pw_sneakers]
						player.normalspeed = max(FixedHypot(player.mo.momx, player.mo.momy)/5*3, skins[player.mo.skin].normalspeed)
					else
						player.normalspeed = max(FixedHypot(player.mo.momx, player.mo.momy), skins[player.mo.skin].normalspeed)
					end
				end
			end
-- 			if player.mo.state == S_PLAY_FALL
-- 				player.mo.state = S_PLAY_WALK
-- 			end
		//Scale up sprites for Spin Slash (the sprites we have are too small!)
			if player.spinslash
				player.mo.spritexscale = 5*FRACUNIT/4
				player.mo.spriteyscale = 5*FRACUNIT/4
			else
				player.mo.spritexscale = FRACUNIT
				player.mo.spriteyscale = FRACUNIT
			end
			
			if (player.pflags & PF_SPINNING)
			and (player.pflags & PF_JUMPED)
				player.pflags = $ & ~PF_SPINNING
				player.mo.state = S_PLAY_ROLL
			end
			
			if not (player.mo.sprite2 & FF_SPR2SUPER)
				if (player.mo.state == S_PLAY_RUN) and (player.speed > player.runspeed*3)
					player.mo.state = S_PLAY_DASH
				elseif (player.mo.state == S_PLAY_DASH)
-- 					player.mo.state = S_PLAY_DASH
-- 					if leveltime % 2 == 0
-- 						player.mo.state = S_PLAY_DASH
-- 					end
					if (player.speed < player.runspeed*3)
						player.mo.state = S_PLAY_RUN
					end
				end
			end
			
			if (player.mo.state == S_PLAY_ROLL) and (player.speed > 50*FRACUNIT)
				player.mo.state = S_PLAY_GLIDE
			elseif (player.mo.state == S_PLAY_GLIDE) and (player.speed < 50*FRACUNIT)
				player.mo.state = S_PLAY_ROLL
			end
			if player.mo.state == S_PLAY_JUMP
				player.mo.state = S_XTREME_JUMPSQUAT
			end
			if P_IsObjectOnGround(player.mo)
			and not player.wasonground
			and not player.spinslash
			and not (player.cmd.buttons & BT_USE)
			and not (player.pflags & PF_SPINNING)
			and player.speed <= 3*FRACUNIT
				player.mo.state = S_XTREME_LAND
			end
			if not P_IsObjectOnGround(player.mo)
			and player.wasonground
			and player.xtreme_gravity
			and not (player.pflags & PF_JUMPED)
			and not (player.mo.eflags & MFE_SPRUNG)
				if player.mo.eflags & MFE_UNDERWATER
					player.mo.momz = $*3/2
				else
					player.mo.momz = $*2
				end					
			end
			player.wasonground = P_IsObjectOnGround(player.mo)
			
			
			
			if player.walkspeed == nil
				player.walkspeed = 0
			end
			
			if player.speed >= 8*FU
				player.walkspeed = 1
			else
				player.walkspeed = 2
			end
			
			if player.runningspeed == nil
				player.runningspeed = 0
			end
			
			if player.speed >= 30*FU
				player.runningspeed = 1
			else
				player.runningspeed = 2
			end
			
			if (player.mo.state == S_PLAY_STND)
				if (player.mo.anim_duration > 3)
					player.mo.anim_duration = 3
				end
			elseif (player.mo.state == S_PLAY_WAIT)
				if (player.mo.tics > 4)
					player.mo.tics = 4
				end
			elseif (player.mo.state == S_PLAY_SKID)
				if not (player.mo.frame&FF_ANIMATE) player.mo.frame = $|FF_ANIMATE end
				if (player.mo.anim_duration > 1)
					player.mo.anim_duration = 1
				end
			elseif (player.mo.state == S_PLAY_WALK)
				if (player.mo.tics >= 2)
					player.mo.tics = player.walkspeed
				end
				if player.powers[pw_super]
				and (player.speed >= player.runspeed)
					player.mo.state = $
					player.mo.state = $
				end
			elseif (player.mo.state == S_PLAY_RUN)
				if player.mo.tics > 1
					if player.mo.frame&FF_FRAMEMASK == B
					or player.mo.frame&FF_FRAMEMASK == D
					or player.mo.frame&FF_FRAMEMASK == F
					or player.mo.frame&FF_FRAMEMASK == H
						player.mo.tics = 1
					end
				end
			elseif (player.mo.state == S_PLAY_DASH)
				if (player.mo.tics >= 2)
					player.mo.tics = 1
				end
			elseif (player.mo.state == S_PLAY_GLIDE)
				if (player.mo.tics >= 2)
					player.mo.tics = 1
				end
			else
				continue
			end
		end
	end
end)

//Spin Slash Starter
addHook("AbilitySpecial", function(player)
	if not (player.mo and player.mo.valid and player.mo.skin == "xtreme")  return end
	if player.pflags&PF_THOKKED or player.spinslash return true end
	if (player.jumpwasdown) return true end
-- 	if not player.xtreme_gravity
-- 		player.mo.momz = (max(min(P_GetMobjGravity(player.mo),FRACUNIT/2),FRACUNIT/-2)*-10)
-- 	else
-- 		P_SetObjectMomZ(player.mo, 10*FRACUNIT)
-- 	end
	player.charability = CA_GLIDEANDCLIMB
	player.pflags = $|PF_THOKKED&~PF_NOJUMPDAMAGE
	player.spinslash = 1
	player.mo.state = S_XTREME_SPINSLASH
	S_StartSoundAtVolume(player.mo,sfx_slash1,192)
	return true
end)

//Make the Spin Slash block one attack
addHook("MobjDamage", function(target, inflictor, source, damage, damagetype)
	if not (target and target.valid and target.player and target.skin == "xtreme"
	and target.player.spinslash) return end

	if (damagetype&DMG_DEATHMASK) or (CBW_Battle and source and source.valid and source.player) return end
	local i = 0 while i < 10
		S_StopSound(target)
		i = $+1
	end
-- 	if inflictor and inflictor.valid
-- 		if inflictor.flags & MF_MISSILE
-- 			if inflictor.target
-- 				local reflect = P_SpawnMissile(target, inflictor.target, inflictor.type)
-- 				P_RemoveMobj(inflictor)
-- 			else
-- 				inflictor.momx = $*-1
-- 				inflictor.momy = $*-1
-- 				inflictor.momz = $*-1
-- 			end
-- 		end
-- 		target.player.drawangle = R_PointToAngle2(target.x-target.momx,target.y-target.momy,inflictor.x-inflictor.momx,inflictor.y-inflictor.momy)
-- 		P_InstaThrust(target, target.player.drawangle, -10*FRACUNIT)
-- 		target.momx = inflictor.momx target.momy = $+inflictor.momy target.momz = $+inflictor.momz
-- 	else
		target.player.spinslash = 0
		S_StartSound(target,sfx_s255)
		if target.state == S_XTREME_SPINSLASH
			target.player.powers[pw_flashing] = 100
			target.player.pflags = $|PF_JUMPED&~PF_THOKKED
		else
			target.player.powers[pw_flashing] = 7
			target.player.pflags = $|PF_JUMPED|PF_THOKKED
		end
		target.state = S_PLAY_ROLL
		target.momz = $+(max(min(P_GetMobjGravity(target),FRACUNIT/2),FRACUNIT/-2)*-15)
		P_SetObjectMomZ(target, 10*FRACUNIT)
-- 	end
	return true
end, MT_PLAYER)

//Damage while Spin Slashing, to insure it happens
addHook("PlayerCanDamage", function(player, mobj)
	if player.mo and player.mo.valid and player.mo.skin == "xtreme"
	and player.spinslash
	return true end
end)

//Battle Support
local ScriptLoaded = false
addHook("ThinkFrame", function()
	if not(CBW_Battle) or ScriptLoaded then return end
	ScriptLoaded = true
	
	CBW_Battle.CharShieldMax["xtreme"] = 0
	//CBW_Battle.ActionChar["xtreme"] = CBW_Battle.Action.SuperSpinJump
	
	local function GarbagePriority2(player)
		if player and player.mo and player.mo.skin == "xtreme"
		and player.spinslash
			if player.spinslash > 1
				CBW_Battle.SetPriority(player,1,1,nil,1,1)
			else
				CBW_Battle.SetPriority(player,1,2,nil,1,2)
			end
		end
	end

	CBW_Battle.AddPriorityFunction("spinslash",GarbagePriority2)

	CBW_Battle.AddCharPriority("xtreme","basic","spinslash")
	print("xtreme priority script has been loaded.")
end)

//Get rings from shield monitors instead of shields in Battle
local shieldtorings = function(target, inflictor, source)
	if source and source.valid and source.player and source.skin == "xtreme"
	and CBW_Battle and CBW_Battle.BattleGametype and not (gametyperules&GTR_FRIENDLY)
		target.type = MT_RING_BOX
	end
end

addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_PITY_BOX)
addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_ATTRACT_BOX)
addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_FORCE_BOX)
addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_ARMAGEDDON_BOX)
addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_WHIRLWIND_BOX)
addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_ELEMENTAL_BOX)
addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_FLAMEAURA_BOX)
addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_BUBBLEWRAP_BOX)
addHook("MobjDeath", function(target, inflictor, source) shieldtorings(target, inflictor, source)
end,MT_THUNDERCOIN_BOX)

//Jumping out of the Spin Slash
addHook("JumpSpecial", function(player)
	if not (player.mo and player.mo.valid and player.mo.skin == "xtreme")  return end
	if player.spinslash and (player.xtremewallslide or P_IsObjectOnGround(player.mo))
		if not (player.pflags & PF_JUMPDOWN)
			player.spinslash = 0
			player.pflags = $&~PF_JUMPED
			P_DoJump(player,false)
			if player.xtremewallslide
				P_InstaThrust(player.mo, player.drawangle, -10*FRACUNIT)
				player.drawangle = $ - ANGLE_180
			end
			player.xtremewallslide = 0
			S_StartSound(player.mo,sfx_jump)
			player.mo.state = S_PLAY_ROLL --NO MORE SPRING STATE
			player.pflags = $|PF_JUMPED&~PF_THOKKED 
		end
	return true end
end)
//Jumping out of the Spin Slash but with Spin
addHook("SpinSpecial", function(player)
	if not (player.mo and player.mo.valid and player.mo.skin == "xtreme")  return end
	if player.spinslash and player.spinslash <= 2
	and (player.xtremewallslide or P_IsObjectOnGround(player.mo))
		if (player.cmd.buttons & BT_JUMP)
			player.jumpfactor = 0
			if player.xtremewallslide
				player.spinslash = 3
				player.mo.state = S_XTREME_SPINSLASH2
				player.pflags= $|PF_JUMPSTASIS&~PF_THOKKED
				player.jumpwasdown = true
				S_StartSound(player.mo, sfx_spndsh)
				return false
			elseif not (player.pflags & PF_USEDOWN)
				if S_SoundPlaying(player.mo, sfx_slash2)
					local i = 0 while i < 10
						S_StopSound(player.mo)
						i = $+1
					end
					S_StartSound(player.mo,sfx_s255)
				end
				player.spinslash = 0
				player.mo.momx = 0 player.mo.momy = 0
				player.speed = 0
				player.pflags = $&~PF_THOKKED 
				return false
			end
		else
			if (player.pflags & PF_USEDOWN)
			and P_IsObjectOnGround(player.mo)
				player.spinslash = 0
				player.pflags = $ & ~PF_USEDOWN
				return true
			end
			return true
		end
	elseif player.mo.eflags & MFE_JUSTHITFLOOR
	and (player.mo.state == S_PLAY_GLIDE or player.mo.state == S_PLAY_ROLL)
		S_StartSound(player.mo,sfx_spin)
	end
end)
addHook("ShouldDamage", function(target, inflictor, source, damage, damagetype)
	if inflictor and inflictor.type == MT_SPINSLASH_SPIKE
	and (source == nil or source.type == MT_SPINSLASH_SPIKE)
		return false
	end
end, MT_PLAYER)
addHook("MobjThinker", function(mobj)
	if not mobj and mobj.valid return end
-- 	if (mobj.flags & MF_MISSILE)
		mobj.color = mobj.target.color
		if mobj.thingy == nil
			mobj.momx = $*10
			mobj.momy = $*10
			mobj.momz = $*10
			mobj.fuse = 13
			mobj.flags = mobj.info.flags
			mobj.angle = R_PointToAngle2(0, 0, mobj.momx, mobj.momy)
		// Calculate the angle of movement.
		/*
			   momz
			 / |
		   /   |
		 /     |
		0------dist(momx,momy)
		*/

			local dist = FixedHypot(mobj.momx, mobj.momy)
			local angle = R_PointToAngle2(0, 0, dist, mobj.momz)
			
			if angle >= FixedAngle(45*FU/2) --22.5 degrees
			and angle < FixedAngle(135*FU/2) --67.5 degrees
				mobj.frame = C --45
			elseif angle >= FixedAngle(135*FU/2) --67.5 degrees
			and angle < FixedAngle(225*FU/2) --112.5 degrees
				mobj.frame = D --90
			elseif angle >= FixedAngle(225*FU/2) --112.5 degrees
			and angle < FixedAngle(315*FU/2) --157.5 degrees
				mobj.frame = E --135
			elseif angle >= FixedAngle(315*FU/2) --157.5 degrees
			and angle < FixedAngle(405*FU/2) --202.5 degrees
				mobj.frame = F --180
			elseif angle >= FixedAngle(405*FU/2) --202.5 degrees
			and angle < FixedAngle(405*FU/2) --247.5 degrees
				mobj.frame = G --225
			elseif angle >= FixedAngle(405*FU/2) --247.5 degrees
			and angle < FixedAngle(585*FU/2) --292.5 degrees
				mobj.frame = H --270
			elseif angle >= FixedAngle(585*FU/2) --292.5 degrees
			and angle < FixedAngle(675*FU/2) --337.5 degrees
				mobj.frame = A --315
			elseif angle >= FixedAngle(675*FU/2) --337.5 degrees
			and angle < FixedAngle(45*FU/2) --22.5 degrees
				mobj.frame = B --360 or 0
			end
		
			mobj.thingy = true
		end
-- 	end
end, MT_SPINSLASH_SPIKE)


//Reset the Variable on spawn
addHook("PlayerSpawn", function(player)
	player.spinslash = 0
	player.wasonground = true
	player.mo.state = $
	player.xtremewallslide = 0
	//Remove Shields in Battle Mod
	if player.mo and player.mo.valid and player.mo.skin == "xtreme"
	and CBW_Battle and CBW_Battle.BattleGametype and not (gametyperules&GTR_FRIENDLY)
	and player.powers[pw_shield] != SH_NONE and player.powers[pw_shield] != SH_FIREFLOWER
		if player.powers[pw_shield]&SH_FIREFLOWER
			player.powers[pw_shield] = SH_FIREFLOWER
		else
			player.powers[pw_shield] = SH_NONE
		end
	end
end)
//Allow me to access whatever line was collided with this frame
//This is to prevent latching onto objects
//It's also supposed to prevent latching onto invisible walls, but it only works sometimes
addHook("MobjLineCollide", function(mobj, line)
	if mobj and mobj.valid and mobj.player and mobj.skin == "xtreme"
	and mobj.player.spinslash and not mobj.player.climbing2
		local dumbangle = R_PointToAngle2(mobj.x, mobj.y,  P_ClosestPointOnLine(mobj.x, mobj.y, line))
		local platx = P_ReturnThrustX(mobj, dumbangle, mobj.radius + FixedMul(FixedMul(10*FRACUNIT, mobj.scale), mobj.player.speed))
		local platy = P_ReturnThrustY(mobj, dumbangle, mobj.radius + FixedMul(FixedMul(10*FRACUNIT, mobj.scale), mobj.player.speed))
		local glidesector = R_PointInSubsector(mobj.x + platx, mobj.y + platy)
		local ceilingheight = glidesector.sector.ceilingheight
		if glidesector.sector.c_slope ceilingheight = P_GetZAt(glidesector.sector.c_slope, mobj.x, mobj.y) end
		if ceilingheight < mobj.z
		and glidesector.sector.ceilingpic == "F_SKY1"
			mobj.player.spinslashslashline = nil
		else
			mobj.player.spinslashslashline = line
		end
	end
end, MT_PLAYER)

addHook("PostThinkFrame", do
	for player in players.iterate
		if player.spinslashslashline player.spinslashslashline = nil end
		
		if player.spinslash and player.mo.state != S_PLAY_FLY
		and player.mo.state != S_XTREME_SPINSLASH
		and player.mo.state != S_XTREME_SPINSLASH2
			if player.spinslash == 2
				player.mo.state = S_XTREME_SPINSLASH2
				player.mo.tics = -1
				if P_IsObjectOnGround(player.mo) and not player.xtremewallslide
					player.panim = PA_IDLE
				end
			else
 				player.mo.state = S_XTREME_SPINSLASH2
			end
		end
	end
end)

/*
//Getting stuck on walls
addHook("MobjMoveBlocked", function(mobj, thing, line)
	if mobj and mobj.valid and mobj.player and mobj.skin == "xtreme"
	and mobj.player.spinslash and not mobj.player.climbing
	and line and line.valid and line == mobj.player.spinslashslashline
-- 	and line == lines[mobj.player.lastlinehit]
		if line.backsector
			local ceilingheight = line.backsector.ceilingheight
			if ceilingheight < mobj.z
			and line.backsector.ceilingpic == "F_SKY1"
				return
			end
		else
			local ceilingheight = line.frontsector.ceilingheight
			if ceilingheight < mobj.z
			and line.frontsector.ceilingpic == "F_SKY1"
				return
			end
		end
		mobj.player.charability = CA_GLIDEANDCLIMB
		mobj.player.spinslash = 2
		mobj.player.timire = 0
		local i = 0 while i < 10
			S_StopSound(mobj)
			i = $+1
		end
		//Super Form Wall Slam
		if mobj.player.speed > skins[mobj.player.mo.skin].normalspeed
		and mobj.player.powers[pw_super]
			S_StartSound(mo, sfx_s3k61, player)
			P_StartQuake(FRACUNIT*40, TICRATE/4)
			P_RadiusAttack(mobj,mobj,1536*FRACUNIT*2)
		end
		S_StartSound(mobj,sfx_s255, player)
-- 		local prevmomx = mobj.momx local prevmomy = mobj.momy
-- 		P_BounceMove(mobj)
		//mobj.player.drawangle = R_PointToAngle2(mobj.momx, mobj.momy, 0,0)
		mobj.angle = R_PointToAngle2(mobj.x, mobj.y, P_ClosestPointOnLine(mobj.x, mobj.y, line))
		mobj.player.drawangle = mobj.angle
-- 		mobj.momx = prevmomx mobj.momy = prevmomy
		mobj.player.climbing = 35
	end
end, MT_PLAYER)
*/
//Getting stuck on walls
addHook("PlayerThink", function(player)
    if player and player.valid and player.mo and player.mo.valid and player.mo.health
	local p = player
		if player.walljumpmomercy == nil
			player.walljumpmomercy = 0
		end
		player.walljumpmomercy = max($-1, 0)
		//Wall sliding
		if player.xtremewallslide and player.spinslash
			local line = lines[player.lastlinehit]
			local side = sides[player.lastsidehit]
			if not P_IsObjectOnGround(player.mo)
			and line and line.valid
				local pointx, pointy = P_ClosestPointOnLine(player.mo.x, player.mo.y, line)
				player.drawangle = R_PointToAngle2(pointx, pointy, player.mo.x, player.mo.y)-ANGLE_180
				local angle = R_PointToAngle2(line.v1.x, line.v1.y, line.v2.x, line.v2.y)
				if line.frontside == side
					angle = $-ANGLE_180
				end
				//Slide momentum
				
				player.mo.momx = ($ - player.cmomx)*3/6 + player.cmomx
				player.mo.momy = ($ - player.cmomy)*3/6 + player.cmomy
				player.mo.momz = 0
				
				//Stuff
-- 				player.mo.state = S_PLAY_WALLCLING
-- 				player.xtremewallslide = $ - 1
				--player.xtremeslidesfx = max($, 1)
				if side and side.valid
					//Move with conveyors
					if side == player.xtremelastside
						//Move with conveyors
						if side.textureoffset != player.xtremesidexscroll
						or side.rowoffset != player.xtremesideyscroll
							//Horizontal movement
							P_TryMove(player.mo,
							player.mo.x+FixedMul(side.textureoffset-player.xtremesidexscroll, cos(angle)),
							player.mo.y+FixedMul(side.textureoffset-player.xtremesidexscroll, sin(angle)),
							true)
							
							//Verical Movement
							player.mo.z = $ + side.rowoffset-player.xtremesideyscroll
							player.mo.momz = 0
						end
					else
						player.xtremelastside = side
					end
					
					//Update variables
					player.xtremesidexscroll = side.textureoffset
					player.xtremesideyscroll = side.rowoffset
				end
			else
				player.xtremewallslide = 0
			end
			
			if not player.xtremewallslide
				player.mo.state = S_XTREME_SPINSLASH2
				player.xtremelastside = nil
			end
		end
    end
end)
//Wall Collision
addHook("MobjMoveBlocked", function(mo, thing, line)
	local player = mo and mo.valid and mo.player
	if (player.glidetime and P_IsObjectInGoop(mo)) return end
	if P_IsObjectOnGround(mo) then return end
	if mo.skin ~= "xtreme" then return end
	if P_PlayerInPain(mo.player)  then return end
	if mo.player.powers[pw_carry] then return end
	if mo.player.playerstate == PST_DEAD then return end
	if mo.player.playerstate ~= PST_LIVE then return end --Why would i need this ~_~
	if mo.state == S_PLAY_DEAD then return end
	if not mo.player.spinslash then return end
	
	//Wall Sliding and Ledge Grabbing
	if not P_IsObjectOnGround(mo) and not player.climbing 
		local prevline = player.lastlinehit
		local prevside = player.lastsidehit
		
		player.lastlinehit = -1
		player.lastsidehit = -1
		
		P_SlideMove(mo)
		player.powers[pw_pushing] = 3
		
		local line2 = lines[player.lastlinehit]
		local side = sides[player.lastsidehit]
		if line and line.valid
			
			local pointx, pointy = P_ClosestPointOnLine(mo.x, mo.y, line)
			local angle = R_PointToAngle2(mo.x, mo.y, pointx, pointy)
			
			local diff = inputangle(player) - angle
			diff = InvAngle(InvAngle($))
			
			if abs(diff) < ANGLE_90
			and not (line and line.backsector
			and line.backsector.ceilingpic == "F_SKY1"
			and line.frontsector
			and line.frontsector.ceilingpic == "F_SKY1"
			and (mo.z >= line.frontsector.ceilingheight
			or mo.z >= line.backsector.ceilingheight))
			and line.special != 41
				//Wall Slide
				player.drawangle = angle
				if player.xtremewallslide == 0
					S_StartSound(mo, sfx_s255)
				end
				player.xtremewallslide = 3
				if player.spinslash < 2
					player.spinslash = 2
				end
				P_Thrust(player.mo, angle, 1*FU)
				if side and side.valid
					if player.xtremelastside == nil
						player.xtremelastside = side
						player.xtremesidexscroll = side.textureoffset
						player.xtremesideyscroll = side.rowoffset
					end
				end
			end
		else
			player.lastlinehit = prevline
			player.lastsidehit = prevside
		end
		return true
	end
end, MT_PLAYER)
/*
addHook("MobjMoveBlocked", function(mo,mobj,line)
	if mo and mo.valid and mo.player and mo.skin == "xtreme"
	and mo.player.spinslash and not mo.player.climbing
	and not (mobj and mobj.valid and mobj.flags & (MF_MONITOR|MF_ENEMY|MF_BOSS))
		if line and line.valid
			if line.backsector
				local ceilingheight = line.backsector.ceilingheight
				if ceilingheight < mo.z
				and line.backsector.ceilingpic == "F_SKY1"
					return
				end
			else
				local ceilingheight = line.frontsector.ceilingheight
				if ceilingheight < mo.z
				and line.frontsector.ceilingpic == "F_SKY1"
					return
				end
			end	
			local side = sides[mo.player.lastsidehit]
			if side
				if mo.player.xtremelastside == nil
					mo.player.xtremelastside = side
					mo.player.xtremesidexscroll = side.textureoffset
					mo.player.xtremesideyscroll = side.rowoffset
				end
			end
			if PTR_GlideClimbTraverse(mo,line)
			and mo.player and mo.player.valid
				local real,ang = PTR_GlideClimbTraverse(mo,line)
				if (P_IsClimbingValid(mo.player,ang) or (mobj and mobj.valid))
					if mobj and mobj.valid then ang = R_PointToAngle2(mo.x,mo.y,mobj.x,mobj.y) end
					local linex, liney =  P_ClosestPointOnLine(mo.x, mo.y, line)
					P_TryMove(mo, linex, liney)
-- 					mo.angle = ang
					mo.player.drawangle = ang
					mo.player.charability = CA_GLIDEANDCLIMB
					mo.player.spinslash = 2
					mo.player.timire = 0
					local i = 0 while i < 10
						S_StopSound(mo)
						i = $+1
					end
					if mo.player.speed > skins[mo.skin].normalspeed
					and mo.player.powers[pw_super]
						S_StartSound(mo, sfx_s3k61)
						P_StartQuake(FRACUNIT*40, TICRATE/4)
						P_RadiusAttack(mo,mo,1536*FRACUNIT*2)
					end
					S_StartSound(mobj,sfx_s255, player)
					mo.player.climbing2 = 1
 				end
			end
		end
	end
end,MT_PLAYER)
*/
//Prevent climbing around on walls when latched to them
addHook("PreThinkFrame", do
	for player in players.iterate
		if player.mo and player.mo.valid and player.mo.skin == "xtreme"
			player.mo.gpe_hasmomentum = false
			player.mo.gpe_statchanges = false
			player.mo.gpe_sdstyle = 0
			if player.spinslash and (player.xtremewallslide or P_IsObjectOnGround(player.mo))
				player.cmd.forwardmove = 0
				player.cmd.sidemove = 0
			end
		end
	end
end)

//Spike Destroyer
local xtremespike = function(thing, tmthing)
  if not (thing and thing.valid and tmthing and tmthing.valid) return end
	if tmthing.player and tmthing.skin == "xtreme" and (abs(thing.z - tmthing.z) <= 60*tmthing.scale)
		if tmthing.player.spinslash == 1
			local bottomheight = tmthing.z
			local topheight = tmthing.z + tmthing.height

			if (tmthing.eflags & MFE_VERTICALFLIP)
				local swap = bottomheight
				bottomheight = topheight
				topheight = swap
			end

			if not ((P_MobjFlip(tmthing)*(bottomheight - (thing.z + thing.height/2)) > 0)
			and (P_MobjFlip(tmthing)*(tmthing.momz - thing.momz) < 0)) then return end
			
			P_KillMobj(thing, tmthing, tmthing)
			return true
		end
	end
end
addHook("MobjCollide", function(thing, tmthing) xtremespike(thing, tmthing) end, MT_SPIKE)
addHook("MobjCollide", function(thing, tmthing) xtremespike(thing, tmthing) end, MT_WALLSPIKE)

//Win Animation and Spin Slash
addHook("PlayerThink", function(player)
	if not (player.mo and player.mo.valid and player.mo.skin == "xtreme") return end
	
	//Remove Shields in Battle Mod
	if CBW_Battle and CBW_Battle.BattleGametype and not (gametyperules&GTR_FRIENDLY)
	and player.powers[pw_shield] != SH_NONE and player.powers[pw_shield] != SH_FIREFLOWER
		S_StartSound(player.mo,sfx_lose,player)
		local smoke = P_SpawnMobjFromMobj(player.mo,0,0,0,MT_DUST)
		smoke.scale = $*4
		if player.powers[pw_shield]&SH_FIREFLOWER
			player.powers[pw_shield] = SH_FIREFLOWER
		else
			player.powers[pw_shield] = SH_NONE
		end
	end

	//Disallows the rest of the code in certain circumstances
	if P_PlayerInPain(player)
	or (player.pflags & PF_SLIDING)
	or player.powers[pw_carry] != CR_NONE
	or player.spectator
	or player.playerstate != PST_LIVE
	or not player.mo.health
	or player.panim == PA_PAIN
	or player.powers[pw_super] == 1
	or player.iseggrobo
	or player.powers[pw_nocontrol] > 0
-- 	or player.mo.eflags & MFE_SPRUNG
	or (player.mo.recoilthrust != nil and player.mo.recoilthrust != 0)
	or player.actionstate
	or player.exiting != 0
		player.charability = CA_NONE
		if S_SoundPlaying(player.mo, sfx_s3kd8l)
			local i = 0 while i < 10
				S_StopSound(player.mo)
				i = $+1
			end
		end
		player.spinslash = 0
		if player.exiting
			if (player.mo.state != S_XTREME_VICTORY)
			and (player.mo.state != S_XTREME_VICTORY2)
			and P_IsObjectOnGround(player.mo)
			and player.speed <= 5*FRACUNIT
				player.mo.state = S_XTREME_VICTORY
				return
			end
		end
	else		
		if player.climbing2 == 1
			player.drawangle = player.prevdrawangle
			P_InstaThrust(player.mo, 0, 0)
			P_SetObjectMomZ(player.mo, 0)
		else
			player.prevdrawangle = player.drawangle
		end
		if player.spinslash
			player.charability = CA_GLIDEANDCLIMB
			player.charflags = $ | SF_CANBUSTWALLS
			player.pflags = $&~PF_APPLYAUTOBRAKE
			if not P_IsObjectOnGround(player.mo) player.pflags = $|PF_THOKKED end
			player.skidtime = 0
			//Break Floors
			local sectorthing = P_PlayerTouchingSectorSpecial(player, 0, 0)
			if sectorthing.valid then
				for fof in sectorthing.ffloors()
					if fof.valid and (fof.flags & FF_BUSTUP) and (fof.flags & FF_EXISTS)
					and (abs(fof.topheight - player.mo.z) <= 40*player.mo.scale) then
						EV_CrumbleChain(player.sectorthing, fof)
					end
				end
			end
			
			if player.spinslash > 2
				local dust = P_SpawnMobjFromMobj(player.mo,P_ReturnThrustX(nil,player.mo.angle,player.mo.radius),
				P_ReturnThrustY(nil,player.mo.angle,player.mo.radius),0,MT_SPINDUST)
				dust.angle = player.drawangle
				P_Thrust(dust, dust.angle, FRACUNIT*P_RandomByte()/-32)
				dust.angle = $+ANGLE_90
				P_Thrust(dust, dust.angle, FRACUNIT*P_SignedRandom()/-16)
				dust.momz = 23*FRACUNIT/-16
			
			elseif player.spinslash == 2
				player.mo.state = S_XTREME_SPINSLASH2
				if player.mo.frame & FF_FULLBRIGHT
					player.mo.frame = A|FF_FULLBRIGHT
				else
					player.mo.frame = A
				end
				if player.mo.eflags&MFE_JUSTHITFLOOR S_StartSound(player.mo,sfx_s255) end
				if P_IsObjectOnGround(player.mo) and not player.xtremewallslide
					player.panim = PA_IDLE
					player.mo.momx = player.cmomx*20/19
					player.mo.momy = player.cmomy*20/19
					player.mo.momz = 0
				end
			//Super Form Quake
				if player.speed > skins[player.mo.skin].normalspeed
				and player.powers[pw_super]
					S_StartSound(player.mo, sfx_s3k61)
					P_StartQuake(FRACUNIT*40, TICRATE/4)
					P_RadiusAttack(player.mo,player.mo,1536*FRACUNIT*2)
				end
			elseif P_IsObjectOnGround(player.mo)
				player.pflags = $|PF_JUMPSTASIS
				player.spinslash = 2
				local i = 0 while i < 10
					S_StopSound(player.mo)
					i = $+1
				end
				S_StartSound(player.mo,sfx_s255)
			else
				S_StartSoundAtVolume(player.mo,sfx_slash2,192)
				player.pflags = $|PF_JUMPSTASIS
				if not player.xtreme_gravity
					player.mo.momz = $+(P_GetMobjGravity(player.mo)/-2)
				end
			end
		else
			player.charability = CA_NONE
			player.charflags = $ & ~SF_CANBUSTWALLS
			if player.mo.state == S_XTREME_SPINSLASH
			or player.mo.state == S_XTREME_SPINSLASH2
			or player.mo.state == S_PLAY_FLY
				player.mo.state = S_PLAY_FALL
			end
		end
	end
end)

local function XtremeSonicUseSpinHeight(player)
    if player.mo and player.mo.valid and player.mo.skin == "xtreme"
    and (player.mo.state == S_XTREME_CROUCH1
	or player.mo.state == S_XTREME_CROUCH2
	or player.mo.state == S_XTREME_CROUCH3
	or player.mo.state == S_XTREME_SPINSLASH
	or player.mo.state == S_XTREME_SPINSLASH2
	or player.mo.state == S_XTREME_JUMPSQUAT
	or player.mo.state == S_PLAY_FLY
	or player.mo.state == S_PLAY_GLIDE)
        return P_GetPlayerSpinHeight(player)
    end
end
addHook("PlayerHeight", XtremeSonicUseSpinHeight)
addHook("PlayerCanEnterSpinGaps", XtremeSonicUseSpinHeight)