freeslot("S_PLAY_KOU_AIRTAUNT",
"S_PLAY_KOU_GROUNDTAUNT",
"S_PLAY_KOU_TAUNTSTART",
"S_PLAY_KOU_RARETAUNT",
"S_PLAY_KOU_PIZZA",
"SFX_KUTRC",
"SFX_KUTRK",
"sfx_koudnc",
"sfx_kdncms",
"sfx_kutr1",
"sfx_kutr2",
"sfx_kutr3",
"sfx_kutr4",
"sfx_kutr5",
"sfx_kutr6"
)
sfxinfo[sfx_kutr1].caption = "Taunt"
sfxinfo[sfx_kutr2].caption = "Taunt"
sfxinfo[sfx_kutr3].caption = "Taunt"
sfxinfo[sfx_kutr4].caption = "Taunt"
sfxinfo[sfx_kutr5].caption = "Taunt"
sfxinfo[sfx_kutr6].caption = "Taunt"
sfxinfo[sfx_kutrc].caption = "Taunt"
sfxinfo[sfx_kutrk].caption = "Rare Taunt"
sfxinfo[sfx_koudnc].caption = "Breakdancing"
sfxinfo[sfx_kdncms].caption = "A Sick Beat"

states[S_PLAY_KOU_AIRTAUNT] = {
	sprite = SPR_PLAY,
	frame = SPR2_BNCE,
	nextstate = S_PLAY_FALL,
	tics = 15
}
states[S_PLAY_KOU_GROUNDTAUNT] = {
	sprite = SPR_PLAY,
	frame = SPR2_TAL0,
	nextstate = S_PLAY_STND,
	tics = 15
}
states[S_PLAY_KOU_RARETAUNT] = {
	sprite = SPR_PLAY,
	frame = SPR2_SWIM,
	nextstate = S_PLAY_STND,
	tics = 15
}
states[S_PLAY_KOU_TAUNTSTART] = {
	sprite = SPR_PLAY,
	frame = SPR2_TRNS|FF_ANIMATE,
	nextstate = S_PLAY_STND,
	var2 = 3,
	tics = 5
}
states[S_PLAY_KOU_PIZZA] = {SPR_PLAY, SPR2_DASH, 2, nil, 0, 0, S_PLAY_KOU_PIZZA}

--Kou can't do abilities (PA_DEAD doesn't exist lumy)
local function KouCantMove(player)
	local mo = player and player.mo
	return P_PlayerInPain(player)
	or player.pflags & PF_SLIDING
	or player.powers[pw_carry]
	or player.spectator
	or player.playerstate
	or not mo.health
	or mo.state == S_PLAY_DEAD
	or player.powers[pw_super] == 1
	or player.iseggrobo
	or player.isjettysyn
	or player.guard
	or player.actionstate
	or player.powers[pw_nocontrol]
	or (player.isxmomentum and mo.state == S_PLAY_FACEPLANT)
end

addHook("PlayerThink", function(p)
	if not (p.mo and p.mo.valid) then return end
	if not (p.mo.health and p.mo.skin == "kou" and p.kou)
		if p.mo.kouscaled
			p.mo.spritexscale = FRACUNIT
			p.mo.spriteyscale = p.mo.spritexscale
			p.mo.kouscaled = 0
		end
		return
	end
	
	-- this is special to me. shut up - Fav
	if p.mo.KOU_JetSetRadioedTimer == nil then p.mo.KOU_JetSetRadioedTimer = 0 end
	if p.mo.KOU_JetSetRadioedTimer != 0 then p.mo.KOU_JetSetRadioedTimer = $-1 end
	if p.mo.KOU_JetSetRadioed == nil or p.mo.KOU_JetSetRadioedTimer == 1 then p.mo.KOU_JetSetRadioed = 0 end
	
	if (p.cmd.buttons & BT_TOSSFLAG)
	and not (p.kou.tfdown)
	and not (KouCantMove(p))
	and not p.kou.walltouch
	and not p.kou.currentlyDiving
	and not p.kou.lungetime
	and not p.kou.diveWaiter
		p.mo.state = S_PLAY_STND
		p.mo.state = S_PLAY_KOU_TAUNTSTART
	end
	if p.mo.kouscaled
		p.mo.kouscaled = max($-FRACUNIT/8, 0)
		p.mo.spritexscale = FRACUNIT+p.mo.kouscaled
		p.mo.spriteyscale = p.mo.spritexscale
	end
	if p.mo.state == S_PLAY_KOU_TAUNTSTART and p.mo.tics == 1
		if P_IsObjectOnGround(p.mo)
			p.mo.state = S_PLAY_KOU_GROUNDTAUNT
		else
			p.mo.state = S_PLAY_KOU_AIRTAUNT
		end
		p.mo.kouscaled = FRACUNIT/5
		p.mo.spritexscale = FRACUNIT+p.mo.kouscaled
		p.mo.spriteyscale = p.mo.spritexscale
		
		if P_RandomRange(0, 10) == 10
			--print("lol")
			p.mo.state = S_PLAY_KOU_RARETAUNT
			S_StartSound(p.mo, sfx_kutrk)
		else
			if p.mo.KOU_JetSetRadioed == 0
				S_StartSound(p.mo, sfx_kutr1)
			elseif p.mo.KOU_JetSetRadioed == 1
				S_StartSound(p.mo, sfx_kutr2)
			elseif p.mo.KOU_JetSetRadioed == 2
				S_StartSound(p.mo, sfx_kutr3)
			elseif p.mo.KOU_JetSetRadioed == 3
				S_StartSound(p.mo, sfx_kutr4)
			elseif p.mo.KOU_JetSetRadioed == 4
				S_StartSound(p.mo, sfx_kutr5)
			else
				S_StartSound(p.mo, sfx_kutr6)
			end
			if p.mo.KOU_JetSetRadioed <= 5 then p.mo.KOU_JetSetRadioed = $+1 end
		end	
		p.mo.KOU_JetSetRadioedTimer = TICRATE
		p.mo.frame = P_RandomRange(0, skins[p.mo.skin].sprites[p.mo.sprite2].numframes-1)
		local cir1 = P_SpawnMobjFromMobj(p.mo, 0, 0, 0, MT_KOU_CIRC)
		cir1.destscale = cir1.scale*25
		cir1.scalespeed = cir1.scale/6
		cir1.fuse = 8
		cir1.target = p.mo
		cir1.angle = p.mo.angle+FixedAngle(90*FRACUNIT)
		cir1.blendmode = AST_ADD
		local cir2 = P_SpawnMobjFromMobj(p.mo, 0, 0, 0, MT_KOU_CIRC)
		cir2.destscale = cir2.scale*25
		cir2.state = S_KOU_CIRC2
		cir2.scalespeed = cir2.scale/6
		cir2.fuse = 8
		cir2.target = p.mo
		cir2.angle = p.mo.angle+FixedAngle(90*FRACUNIT)
		cir2.blendmode = AST_ADD
		if P_RandomRange(1, 2) == 1
			cir2.rang = -1
		else
			cir2.rang = 1
		end
	end
	--pizza.
	if p.kou.dancetimer == nil
	or not (p.cmd.buttons & BT_TOSSFLAG)
	or KouCantMove(p)
	or not (p.mo.state == S_PLAY_KOU_PIZZA
	or (p.panim >= PA_IDLE and p.panim <= PA_RUN
	and P_IsObjectOnGround(p.mo) and p.kou.dancetimer <= TICRATE/2))
		p.kou.dancetimer = 0
	else
		p.kou.dancetimer = $+1
		if p.kou.dancetimer == TICRATE/2 and p.mo.state != S_PLAY_KOU_PIZZA
			p.mo.state = S_PLAY_KOU_PIZZA
			S_StartSound(p.mo, sfx_koudnc)
			local box = P_SpawnMobjFromMobj(p.mo, P_RandomRange(-35,35)*p.mo.scale, P_RandomRange(-35,35)*p.mo.scale, 0, MT_KOU_BOOMBOX)
			box.target = p.mo
			box.color = ColorOpposite(p.mo.color)
			for i = 1,10
				local d = P_SpawnMobjFromMobj(box, (P_RandomRange(-5,5)*box.scale), (P_RandomRange(-5,5)*box.scale), (P_RandomRange(-5,5)*box.scale), MT_DUST)
				d.scale = $*(3/2)
				d.momy = P_RandomRange(-3, 3)*d.scale
				d.momx = P_RandomRange(-3, 3)*d.scale
				d.momz = P_RandomRange(0, 4)*d.scale*P_MobjFlip(box)
			end
			P_SetObjectMomZ(box, 8*FRACUNIT)
		end
	end
	if p.mo.state == S_PLAY_KOU_PIZZA
		if p.kou.dancetimer
			if leveltime % 9 == 0
				local part = P_SpawnMobjFromMobj(p.mo, (P_RandomRange(-40,40)*p.mo.scale),(P_RandomRange(-40,40)*p.mo.scale),(P_RandomRange(-5, 30)*p.mo.scale), MT_KOU_BOOMPART)
				part.frame = P_RandomRange(0, 7)
				part.fuse = 40
				part.scale = $/2
				part.destscale = $*2
				part.scalespeed = FRACUNIT/100
				P_SetObjectMomZ(part, 3*FRACUNIT)
			end
			local factor = FixedDiv(p.normalspeed - FixedDiv(p.speed, p.mo.scale), p.normalspeed)
			p.mo.movefactor = min(max(FixedMul($, factor), 0), $)
		else
			p.mo.state = S_PLAY_STND
		end
	end
	
	p.kou.tfdown = (p.cmd.buttons & BT_TOSSFLAG)
end)

addHook("PlayerHeight", function(p)
	if p.mo and p.mo.valid and p.mo.skin == "kou"
	and p.mo.state == S_PLAY_KOU_PIZZA
		return P_GetPlayerSpinHeight(p)
	end
end)
addHook("PlayerCanEnterSpinGaps", function(p)
	if p.mo and p.mo.valid and p.mo.skin == "kou"
	and (p.mo.state == S_PLAY_KOU_PIZZA or p.panim == PA_ROLL)
		return true
	end
end)

addHook("MobjThinker", function(mo)
	if mo and mo.valid 
		if not S_SoundPlaying(mo, sfx_kdncms) -- jammin out bro,,,
			S_StartSound(mo, sfx_kdncms)
		end
		
		if mo.target.state != S_PLAY_KOU_PIZZA
			if S_SoundPlaying(mo, sfx_kdncms) then S_StopSoundByID(mo, sfx_kdncms) end
			for i = 1,10
				local d = P_SpawnMobjFromMobj(mo, (P_RandomRange(-5,5)*mo.scale), (P_RandomRange(-5,5)*mo.scale), (P_RandomRange(-5,5)*mo.scale), MT_DUST)
				d.scale = $*(3/2)
				d.momy = P_RandomRange(-3, 3)*d.scale
				d.momx = P_RandomRange(-3, 3)*d.scale
				d.momz = P_RandomRange(0, 4)*d.scale*P_MobjFlip(mo)
			end
			
			pcall(P_RemoveMobj, mo)
		end
	end
		
end, MT_KOU_BOOMBOX)

addHook("MobjThinker", function(mo)
	if mo and mo.valid
		if mo.fuse == 20
			mo.frame = $|TR_TRANS10
		elseif mo.fuse == 15
			mo.frame = $|TR_TRANS20
		elseif mo.fuse == 10
			mo.frame = $|TR_TRANS40
		elseif mo.fuse == 5
			mo.frame = $|TR_TRANS50
		elseif mo.fuse == 4
			mo.frame = $|TR_TRANS60
		elseif mo.fuse == 3
			mo.frame = $|TR_TRANS70
		elseif mo.fuse == 2
			mo.frame = $|TR_TRANS80
		elseif mo.fuse == 1
			mo.frame = $|TR_TRANS90
		end
	end
end, MT_KOU_BOOMPART)

addHook("MobjThinker", function(mo)
	if mo and mo.valid and mo.health 
		if mo.state == S_KOU_CIRC2
			mo.rollangle = $+FixedAngle(-20*FRACUNIT)
		end
		mo.i = $ or 0
		if mo.target and mo.target.valid and mo.target.health
			A_CapeChase(mo, FRACUNIT*-2*mo.i)
		end
		if mo.fuse == 4
			mo.frame = $|TR_TRANS20
		elseif mo.fuse == 3
			mo.frame = $|TR_TRANS40
		elseif mo.fuse == 2
			mo.frame = $|TR_TRANS60
		elseif mo.fuse == 1
			mo.frame = $|TR_TRANS90
		end
		mo.i = $+1
	end
end, MT_KOU_CIRC)