freeslot(
	"MT_SDMPARTICLES",
	"S_SDMPARTICLES1",
	"S_SDMPARTICLES2",
	"S_SDMPARTICLES3",
	"S_SDMPARTICLES4",
	"SPR_SDMP",
	"MT_TRNSEMMY1",
	"MT_TRNSEMMY2",
	"MT_TRNSEMMY3",
	"MT_TRNSEMMY4",
	"MT_TRNSEMMY5",
	"MT_TRNSEMMY6",
	"MT_TRNSEMMY7",
	"S_TRNSEMMY1A",
	"S_TRNSEMMY1B",
	"S_TRNSEMMY1C",
	"S_TRNSEMMY1D",
	"S_TRNSEMMY2A",
	"S_TRNSEMMY2B",
	"S_TRNSEMMY2C",
	"S_TRNSEMMY2D",
	"S_TRNSEMMY3A",
	"S_TRNSEMMY3B",
	"S_TRNSEMMY3C",
	"S_TRNSEMMY3D",
	"S_TRNSEMMY4A",
	"S_TRNSEMMY4B",
	"S_TRNSEMMY4C",
	"S_TRNSEMMY4D",
	"S_TRNSEMMY5A",
	"S_TRNSEMMY5B",
	"S_TRNSEMMY5C",
	"S_TRNSEMMY5D",
	"S_TRNSEMMY6A",
	"S_TRNSEMMY6B",
	"S_TRNSEMMY6C",
	"S_TRNSEMMY6D",
	"S_TRNSEMMY7A",
	"S_TRNSEMMY7B",
	"S_TRNSEMMY7C",
	"S_TRNSEMMY7D",
	"SPR_ASEM",
	"MT_STRNSEMMY1",
	"MT_STRNSEMMY2",
	"MT_STRNSEMMY3",
	"MT_STRNSEMMY4",
	"MT_STRNSEMMY5",
	"MT_STRNSEMMY6",
	"MT_STRNSEMMY7",
	"S_STRNSEMMY1A",
	"S_STRNSEMMY1B",
	"S_STRNSEMMY1C",
	"S_STRNSEMMY1D",
	"S_STRNSEMMY2A",
	"S_STRNSEMMY2B",
	"S_STRNSEMMY2C",
	"S_STRNSEMMY2D",
	"S_STRNSEMMY3A",
	"S_STRNSEMMY3B",
	"S_STRNSEMMY3C",
	"S_STRNSEMMY3D",
	"S_STRNSEMMY4A",
	"S_STRNSEMMY4B",
	"S_STRNSEMMY4C",
	"S_STRNSEMMY4D",
	"S_STRNSEMMY5A",
	"S_STRNSEMMY5B",
	"S_STRNSEMMY5C",
	"S_STRNSEMMY5D",
	"S_STRNSEMMY6A",
	"S_STRNSEMMY6B",
	"S_STRNSEMMY6C",
	"S_STRNSEMMY6D",
	"S_STRNSEMMY7A",
	"S_STRNSEMMY7B",
	"S_STRNSEMMY7C",
	"S_STRNSEMMY7D",
	"MT_EMMYSPARKLES",
	"SPR2_LAFF",
	"S_PLAY_ALTLAUGH",
	"SPR2_SINS",
	"S_PLAY_SINSLAUGH",
	"sfx_sins",
	"sfx_wzws"
)

sfxinfo[sfx_sins].caption = "sans"
sfxinfo[sfx_wzws].caption = "Unfathomable Pain"

local laugh = S_PLAY_ALTLAUGH
states[laugh].sprite = SPR_PLAY
states[laugh].frame = SPR2_LAFF|FF_ANIMATE
states[laugh].var1 = 1
states[laugh].var2 = 3
states[laugh].tics = -1
states[laugh].nextstate = S_PLAY_ALTLAUGH

local sins = S_PLAY_SINSLAUGH
states[sins].sprite = SPR_PLAY
states[sins].frame = SPR2_SINS|FF_ANIMATE
states[sins].var1 = 1
states[sins].var2 = 3
states[sins].tics = -1
states[sins].nextstate = S_PLAY_SINSLAUGH

addHook("ThinkFrame", function(player)
for player in players.iterate do
	if player.mo and player.mo.valid and player.mo.skin == "altsonic"
		if gametype == GT_ROLLOUT_TIME
		or gametype == GT_ROLLOUT_STOCK
			if player.mo.fuse == 1
				S_StopSoundByID(player.mo, sfx_wzws)
			end
		end
		if player.powers[pw_super]
		and leveltime % 4 == 0
			local altssparkle = P_SpawnMobjFromMobj(player.mo, FRACUNIT*P_RandomRange(-16,16), FRACUNIT*P_RandomRange(-16,16), FixedDiv(player.mo.height/2,player.mo.scale)+(P_RandomRange(-16,16)*FRACUNIT), MT_ALTSSPARKLES)
				altssparkle.momz = FixedMul(FRACUNIT*2, player.mo.scale)*P_MobjFlip(player.mo)
				altssparkle.scale = player.mo.scale*6/10
				altssparkle.color = player.mo.color
				altssparkle.target = player.mo
				if altssparkle.target.player == displayplayer
					local chasecam = CV_FindVar("chasecam")
					if (chasecam.value == 1)
						altssparkle.flags2 = $ & ~MF2_DONTDRAW
					elseif (chasecam.value == 0)
						altssparkle.flags2 = $ | MF2_DONTDRAW
					end
				end
			end
		end
	end
end)
		
addHook("PlayerThink", function(player)
		if player.mo and player.mo.valid and player.mo.skin == "altsonic"
			if player.mo.emmyorbit == nil
					player.mo.emmyorbit = 0
			end
//Chaos Emerald Orbiting.
			if player.powers[pw_super] == 1
			and not player.althyper.transforming
				player.mo.emmyorbit = $ + 1
				local distsin = sin(FixedAngle((player.mo.emmyorbit*FRACUNIT/31)*180))
				local distance = 16*FRACUNIT + distsin*40
				local vertangle = 0
				for i = 0,6 do
					local vertangle = (i * (103*FRACUNIT/2)) + player.mo.emmyorbit*10*FRACUNIT
					vertangle = FixedAngle(vertangle)
					local vertanglep = (i * (103*FRACUNIT/2)) + player.mo.emmyorbit*10*FRACUNIT
					vertanglep = FixedAngle(vertanglep)
					local x = FixedMul(distance, FixedMul(cos(vertangle), cos(player.cmd.angleturn << 16+ANGLE_90)))
					local y = FixedMul(distance, FixedMul(cos(vertangle), sin(player.cmd.angleturn << 16+ANGLE_90)))
					local z = FixedMul(distance, sin(vertangle)) + skins[player.mo.skin].height / 2 * 5 / 4 + 3*FRACUNIT
					if SUBVERSION >= 9
						z = FixedMul(distance, sin(vertangle)) + skins[player.mo.skin].height / 2 * 5 / 4 - 8*FRACUNIT
					else
						z = FixedMul(distance, sin(vertangle)) + skins[player.mo.skin].height / 2 * 5 / 4 + 3*FRACUNIT
					end
					local xp = FixedMul(distance, FixedMul(cos(vertanglep), cos(player.cmd.angleturn << 16+ANGLE_90)))
					local yp = FixedMul(distance, FixedMul(cos(vertanglep), sin(player.cmd.angleturn << 16+ANGLE_90)))
					local zp = FixedMul(distance, sin(vertanglep)) + skins[player.mo.skin].height / 2 * 5 / 3 + skins[player.mo.skin].height / 15 + 3*FRACUNIT
					if SUBVERSION >= 9
						zp = FixedMul(distance, sin(vertanglep)) + skins[player.mo.skin].height / 2 * 5 / 3 + skins[player.mo.skin].height / 15 - 8*FRACUNIT
					else
						zp = FixedMul(distance, sin(vertanglep)) + skins[player.mo.skin].height / 2 * 5 / 3 + skins[player.mo.skin].height / 15 + 3*FRACUNIT
					end
					local emmy = P_SpawnMobjFromMobj(player.mo, x, y, z, MT_TRNSEMMY1 + (i))
					local emmyp = P_SpawnMobjFromMobj(player.mo, xp, yp, zp, MT_EMMYSPARKLES)
					emmyp.state = S_ASPARKLES10
					if i ==  0
						emmyp.color = SKINCOLOR_GREEN
					elseif i == 1
						emmyp.color = SKINCOLOR_MAGENTA
					elseif i == 2
						emmyp.color = SKINCOLOR_BLUE
					elseif i == 3
						emmyp.color = SKINCOLOR_SKY
					elseif i == 4
						emmyp.color = SKINCOLOR_ORANGE
					elseif i == 5
						emmyp.color = SKINCOLOR_RED
					elseif i == 6
						emmyp.color = SKINCOLOR_SILVER
					end
				end
			end
//I really hate basically making code duplicates, but sometimes you just gotta.
//Super Emerald Orbiting.
			if player.althyper.transforming > 1
			and player.althyper.transforming < 35
				player.mo.emmyorbit = $ + 1
				local distsin = sin(FixedAngle((player.mo.emmyorbit*FRACUNIT/31)*180))
				local distance = 24*FRACUNIT + distsin*40
				local vertangle = 0
				for i = 0,6 do
					local vertangle = (i * (103*FRACUNIT/2)) + player.mo.emmyorbit*10*FRACUNIT
					vertangle = FixedAngle(vertangle)
					local vertanglep = (i * (103*FRACUNIT/2)) + player.mo.emmyorbit*10*FRACUNIT
					vertanglep = FixedAngle(vertanglep)
					local x = FixedMul(distance, FixedMul(cos(vertangle), cos(player.cmd.angleturn << 16+ANGLE_90)))
					local y = FixedMul(distance, FixedMul(cos(vertangle), sin(player.cmd.angleturn << 16+ANGLE_90)))
					local z = FixedMul(distance, sin(vertangle)) + skins[player.mo.skin].height / 2 * 5 / 4 + 2*FRACUNIT
					if SUBVERSION >= 9
						z = FixedMul(distance, sin(vertangle)) + skins[player.mo.skin].height / 2 * 5 / 4 - 9*FRACUNIT
					else
						z = FixedMul(distance, sin(vertangle)) + skins[player.mo.skin].height / 2 * 5 / 4 + 2*FRACUNIT
					end
					local xp = FixedMul(distance, FixedMul(cos(vertanglep), cos(player.cmd.angleturn << 16+ANGLE_90)))
					local yp = FixedMul(distance, FixedMul(cos(vertanglep), sin(player.cmd.angleturn << 16+ANGLE_90)))
					local zp = FixedMul(distance, sin(vertanglep)) + skins[player.mo.skin].height / 2 * 5 / 3 + skins[player.mo.skin].height / 15 + 2*FRACUNIT
					if SUBVERSION >= 9
						zp = FixedMul(distance, sin(vertanglep)) + skins[player.mo.skin].height / 2 * 5 / 3 + skins[player.mo.skin].height / 15 - 9*FRACUNIT
					else
						zp = FixedMul(distance, sin(vertanglep)) + skins[player.mo.skin].height / 2 * 5 / 3 + skins[player.mo.skin].height / 15 + 2*FRACUNIT
					end
					local emmy = P_SpawnMobjFromMobj(player.mo, x, y, z, MT_STRNSEMMY1 + (i))
					local emmyp = P_SpawnMobjFromMobj(player.mo, xp, yp, zp, MT_EMMYSPARKLES)
					emmy.scale = emmy.scale
					emmyp.scale = emmyp.scale
					emmyp.state = S_ASPARKLES10
					if i ==  0
						emmyp.color = SKINCOLOR_GREEN
					elseif i == 1
						emmyp.color = SKINCOLOR_MAGENTA
					elseif i == 2
						emmyp.color = SKINCOLOR_BLUE
					elseif i == 3
						emmyp.color = SKINCOLOR_SKY
					elseif i == 4
						emmyp.color = SKINCOLOR_ORANGE
					elseif i == 5
						emmyp.color = SKINCOLOR_RED
					elseif i == 6
						emmyp.color = SKINCOLOR_SILVER
					end
				end
			end
		end
	end)
	
addHook("PlayerThink", function(player)
		if player.mo and player.mo.valid and player.mo.skin == "altsonic"
			if not (player.powers[pw_super] or player.althyper.transforming)
			or (player.powers[pw_super] == 2 or player.althyper.transforming == TICRATE)
				player.mo.emmyorbit = 0
			end
		end
		if not (player.wazowscream)
			player.wazowscream = 0
		end
		if player.mo and player.mo.valid and player.mo.skin == "altsonic"
		and player.playerstate == PST_DEAD
		and player.wazowscream == 0
			player.wazowscream = 1
			if P_RandomChance(FRACUNIT/100*5)
			or player.mo.color == SKINCOLOR_PERIDOT
				S_StartSound(player.mo, sfx_wzws)
			end
		end
		if player.playerstate != PST_DEAD
			player.wazowscream = 0
		end
	end)
	
addHook("PlayerThink", function(player)
//print(player.dashmode)
	if player.mo and player.mo.valid and player.mo.skin == "altsonic"
		if player.dashpreserve == nil
				player.dashpreserve = 0
			end
		if player.dashmode > 3*TICRATE //If you have dash mode, preserve it in the air.
			player.dashpreserve = true
		end
		if not P_IsObjectOnGround(player.mo) //If in the air, keep dash mode set so it doesn't count down.
			if player.dashpreserve == true
				player.dashmode = max(player.dashmode, 3*36)
			end
		end
		if not P_IsObjectOnGround(player.mo) //Build dash mode in the air the same way you would on the ground. Based on source code.
		and (player.dashmode >= 3*TICRATE)
		and player.speed > 28*FRACUNIT
			if (player.normalspeed < skins[player.mo.skin].normalspeed*2) // If the player normalspeed is not currently at normalspeed*2 in dash mode, add speed each tic.
				player.normalspeed = $ + FRACUNIT/5
			end
			if (player.jumpfactor < FixedMul(skins[player.mo.skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height.
				player.jumpfactor = $ + FRACUNIT/300
			end
		end
		if (player.dashmode) //If you have dash mode :v
            if not (player.mo.health) //If any of these conditionals are met, don't preserve dash mode.
            or (P_PlayerInPain(player))
            or (player.gotflag)
            or (player.exiting)
            or (player.pflags & (PF_STASIS|PF_JUMPSTASIS))
            or (player.powers[pw_carry])
            or (player.powers[pw_super] == 1)
			or (player.mo.chargefalling == true)
                player.dashpreserve = false
			end
		end
		if P_IsObjectOnGround(player.mo) //If on the ground and dash mode isn't active, don't preserve what doesn't exist.
            if player.dashmode <= 3*TICRATE
                player.dashpreserve = false
            end
        end
	end
end)

addHook("PlayerThink", function(p)
    if p.mo and p.mo.valid and p.mo.skin == "altsonic" and p.althyper.transforming
        if not p.hypertune
			if p.altmusic1
				P_PlayJingleMusic(p, "AHYPR", 0, true, JT_SUPER)
			elseif p.altmusic2
				P_PlayJingleMusic(p, "AHYPA", 0, true, JT_SUPER)
			elseif p.altmusic3
				P_PlayJingleMusic(p, "AHYPB", 0, true, JT_SUPER)
			elseif p.altmusic4
				P_PlayJingleMusic(p, "AHYPO", 0, true, JT_SUPER)
			elseif p.altmusic5
				P_PlayJingleMusic(p, "AHYPC", 0, true, JT_SUPER)
			elseif p.altmusic6
				P_PlayJingleMusic(p, "_NITAT", 0, true, JT_SUPER)
			elseif p.altmusic7
				P_PlayJingleMusic(p, "AHYPG", 0, true, JT_SUPER)
			end
        end
        p.hypertune = true
    else
        p.hypertune = false
    end
end)

//Alt Sonic's Laugh Stuff.

//Main Thinker	
addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid
	and (player.mo.skin == "altsonic")
		
		//Disallows the rest of the code in certain circumstances
		if P_PlayerInPain(player)
		or (player.pflags & PF_SLIDING)
		or (player.pflags & PF_SHIELDABILITY)
		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.mo.state != S_PLAY_STND and player.mo.state != S_PLAY_ALTLAUGH and player.mo.state != S_PLAY_SINSLAUGH and player.mo.state != S_PLAY_WAIT
		or player.iseggrobo
		or (player.dirk_frozen)
		or (player.gotflag or player.gotcrystal)
		or player.powers[pw_nocontrol]
			if player.altlaugh
				if player.mo.state == S_PLAY_ALTLAUGH
				or player.mo.state == S_PLAY_SINSLAUGH
					player.mo.state = S_PLAY_STND
				end
				player.altlaugh = false
			end
		return end
		
		if player.powers[pw_super]
		and player.althyper.transforming
		and (player.mo.state == S_PLAY_SINSLAUGH or player.mo.state == S_PLAY_ALTLAUGH)
			player.mo.tics = 1
		end
		if player.mo.state == S_PLAY_SINSLAUGH
			if player.mo.frame&FF_FRAMEMASK == 1
				if not player.sanslaff
					S_StartSound(player.mo, sfx_sins)
					player.sanslaff = true
				end
			else
				player.sanslaff = false
			end
		end
		
		//l a u g h .
		if P_IsObjectOnGround(player.mo)
			if player.cmd.buttons & BT_CUSTOM3
				if not player.c3down
					if P_RandomChance(FRACUNIT/100*2)
						player.mo.state = S_PLAY_SINSLAUGH
					else
						player.mo.state = S_PLAY_ALTLAUGH
					end
					player.c3down = true
				end
				player.pflags = $|PF_FULLSTASIS
			else
				player.c3down = false
				if player.mo.state == S_PLAY_ALTLAUGH
				or player.mo.state == S_PLAY_SINSLAUGH
					player.mo.state = S_PLAY_STND
				end
			end
		else
			if player.mo.state == S_PLAY_ALTLAUGH
			or player.mo.state == S_PLAY_SINSLAUGH
				player.mo.state = S_PLAY_STND
			end
        end
    end
end)