-- FL Chan's Stuff --
local boomboxspawned = 0
local flchanupgraded = 0

local function MicShockwaveThink(micshockwave)
	for player in players.iterate do
		local p = player.mo
		if micshockwave and micshockwave.valid and p and p.valid and p.skin == "flchan"
			local fx = micshockwave.x
			local fy = micshockwave.y
			local fr = micshockwave.radius
			searchBlockmap("objects", function(micshockwave, found)
				if found.valid
					if found.flags & MF_SHOOTABLE
					and found.z - found.scale <= micshockwave.z + micshockwave.height
					and found.z + found.height + found.scale >= micshockwave.z
						P_DamageMobj(found, micshockwave, p, 1)
					end
				end
				if (found.valid and found.type == MT_EGGSHIELD) 
				and found.z - found.scale <= micshockwave.z + micshockwave.height
				and found.z + found.height + found.scale >= micshockwave.z
					P_KillMobj(found, micshockwave, p)
				end
				if (found.valid and found.type == MT_METALSONIC_BATTLE) 
				and found.state == found.info.spawnstate
				and not (found.flags2 & MF2_CLASSICPUSH) 
				and found.z - found.scale <= micshockwave.z + micshockwave.height
				and found.z + found.height + found.scale >= micshockwave.z
					found.flags2 = $ | MF2_CLASSICPUSH
				end
			end, micshockwave, fx-fr, fx+fr, fy-fr, fy+fr)
		end
	end
end

local function FLKillSpikes(thing, tmthing)
	if thing and thing.valid and tmthing and tmthing.valid
	and (tmthing.type == MT_SHOCKWAVE1 or tmthing.type == MT_SHOCKWAVE2) 
	and thing.z - thing.scale <= tmthing.z + tmthing.height + (tmthing and P_MobjFlip(tmthing) or tmthing.momz) 
	and thing.z + thing.height + thing.scale >= tmthing.z + (tmthing and P_MobjFlip(tmthing) or tmthing.momz)
		P_KillMobj(thing, tmthing)
		return true
	end
end

local function FLFakeNoClip(mo)
	P_SetOrigin(mo, mo.x + mo.momx, mo.y + mo.momy, mo.z + mo.momz)
    return
	true
end

local function FLVariableReset(player, health)
	if (player.flvars == nil)
		player.flvars = {}
	end
	player.boomboxspawned = 0
	player.flchanupgraded = 0
end

addHook("MapLoad", function()
	for player in players.iterate
		FLVariableReset(player, false)
	end
end)

addHook("PlayerThink", function(player)
	if player.mo and player.mo.skin == "flchan"
		if (player.flvars == nil)
			FLVariableReset(player, true)
		end
		player.powers[pw_underwater] = 0
		player.powers[pw_spacetime] = 0
		if (player.mo.eflags & MFE_UNDERWATER)
			player.charability = CA_SWIM
			player.charflags = $ & ~SF_MULTIABILITY
		else
			player.charability = CA_SLOWFALL
			if player.flchanupgraded == 1
				player.charflags = $|SF_MULTIABILITY
			else
				player.charflags = $ & ~SF_MULTIABILITY
			end
		end
		if ((player.powers[pw_shield] == SH_ELEMENTAL) 
		or (player.powers[pw_shield] == SH_ATTRACT) 
		or (player.powers[pw_shield] & SH_FORCE))
			player.charflags = $|SF_NOSHIELDABILITY
		else
			player.charflags = $ & ~SF_NOSHIELDABILITY
		end
		if not (player.exiting or srb2p)
			if not (P_PlayerInPain(player) or (player.playerstate == PST_DEAD))
				if ((player.powers[pw_carry] == CR_NONE) and not (player.pflags == PF_SPINNING))
					if not (player.mo.state == S_PLAY_FLOAT 
					or player.mo.state == S_PLAY_FLOAT_RUN 
					or player.powers[pw_tailsfly])
						if (player.cmd.buttons & BT_USE)
							player.spintapready = true
							player.spintapping = false
						elseif player.spintapready
							player.spintapping = true
							player.spintapready = false
						else
							player.spintapping = false
						end
						if player.spintapping and not player.weapondelay
							if player.boomboxspawned == 0
								player.mic = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + (player.mo.height/2), MT_DROPPEDMIC)
								S_StartSound(player.mic, sfx_brakrl)
								player.mic.target = player.mo
								if not P_IsObjectOnGround(player.mo)
									player.mo.state = S_MDAIR
									if player.flchanupgraded == 1
										P_SetObjectMomZ(player.mo, 20*FRACUNIT)
										player.weapondelay = TICRATE*3
									else
										P_SetObjectMomZ(player.mo, 10*FRACUNIT)
										player.weapondelay = TICRATE*2
									end
								else
									player.mo.state = S_MICDROP
									player.weapondelay = TICRATE*1
								end
							end
						end
						if (player.cmd.buttons & BT_CUSTOM1)
							player.boomboxspawnready = true
							player.boomboxspawning = false
						elseif player.boomboxspawnready
							player.boomboxspawning = true
							player.boomboxspawnready = false
						else
							player.boomboxspawning = false
						end
						if player.boomboxspawning then
							if P_IsObjectOnGround(player.mo)
								if player.boomboxspawned == 0
									if not player.weapondelay
										player.mo.state = S_KBBSETUP
										player.boomboxspawned = 1
										S_StartSound(player.mo, sfx_nbmper)
										player.boombox = P_SpawnMobj(player.mo.x + FixedMul(50*FRACUNIT, cos(player.mo.angle)), player.mo.y + FixedMul(50*FRACUNIT, sin(player.mo.angle)), player.mo.z, MT_KABOOMBOX)
										player.weapondelay = TICRATE*1
									end
								end
							end
						end
						if player.boomboxspawned == 1 and player.spintapping
							if not player.weapondelay
								P_NukeEnemies(player.boombox, player.mo, 1*FRACUNIT)
								player.mo.state = S_KBBACTIVATE
								player.weapondelay = TICRATE*2
							end
						end
					end
				end
			end
		end
		if (player.mo.state == S_MICDROP or player.mo.state == S_MICDROP_FIN)
			player.pflags = $|PF_FULLSTASIS
		end
		if (player.mo.state == S_KBBSETUP 
		or player.mo.state == S_KBBACTIVATE 
		or player.mo.state == S_KBBACTIVATE_FIN)
			player.pflags = $|PF_FULLSTASIS
		end
		if (All7Emeralds(emeralds)) and not player.flnotified
			player.flnotified = true
			S_StartSound(player.mo, sfx_s3k68)
			print("\x83\FL Chan Emerald Upgrades:", "\x87\Slow Fall: \x80\You can now perform this ability multiple times per jump. Swimming will remain unaffected.",
			"\x87\Mic Drop: \x80\Mics will now create larger shockwaves and you'll now gain extra height when using this ability in midair.",
			"\x87\Kaboom Box: \x80\Kaboom Boxes will now create larger sound blasts when detonated and you'll now be sent higher in the air when using the Kaboom Box's passive.")
		end
		if (All7Emeralds(emeralds))
			player.flchanupgraded = 1
		else
			player.flchanupgraded = 0
		end
	end
end)

addHook("PlayerCanEnterSpinGaps", function(player)
	if player.mo and player.mo.skin == "flchan"
		if player.mo.state == S_PLAY_DASH and not (player.pflags & PF_SPINNING)
			return false
		end
	end
end)

addHook("MobjThinker", function(mic)
	for player in players.iterate do
		local p = player.mo
		if mic and mic.valid and p and p.valid and p.skin == "flchan"
			P_SetObjectMomZ(mic, -30*FRACUNIT)
			if (p.eflags & MFE_VERTICALFLIP)
				mic.eflags = $1|MFE_VERTICALFLIP
				mic.flags2 = $1|MF2_OBJECTFLIP
			end
			if mic.state == S_XPLD1
				if player.flchanupgraded == 1
					P_Earthquake(mic, p, 400*FRACUNIT)
					mic.shockwave = P_SpawnMobj(mic.x, mic.y, mic.z, MT_SHOCKWAVE2)
				else
					P_Earthquake(mic, p, 200*FRACUNIT)
					mic.shockwave = P_SpawnMobj(mic.x, mic.y, mic.z, MT_SHOCKWAVE1)
				end
			end
			if P_IsObjectOnGround(mic)
				for x = mic.x, mic.x + mic.radius, mic.radius
					for y = mic.y, mic.y + mic.radius, mic.radius
						local ss = R_PointInSubsector(x,y)
						for fof in ss.sector.ffloors()
							if (fof.flags & FF_BUSTUP) and (fof.flags & FF_EXISTS)
								EV_CrumbleChain(ss.sector, fof)
							end
						end
					end
				end
			end
		end
	end
end, MT_DROPPEDMIC)

addHook("MobjThinker", MicShockwaveThink, MT_SHOCKWAVE1)
addHook("MobjMoveBlocked", FLFakeNoClip, MT_SHOCKWAVE1)

addHook("MobjThinker", MicShockwaveThink, MT_SHOCKWAVE2)
addHook("MobjMoveBlocked", FLFakeNoClip, MT_SHOCKWAVE2)

addHook("MobjThinker", function(kaboombox)
	for player in players.iterate do
		local p = player.mo
		if kaboombox and kaboombox.valid and p and p.valid and p.skin == "flchan"
			if (p.eflags & MFE_VERTICALFLIP)
				kaboombox.eflags = $1|MFE_VERTICALFLIP
				kaboombox.flags2 = $1|MF2_OBJECTFLIP
			end
			if player.flchanupgraded == 1
				mobjinfo[MT_KABOOMBOX].mass = 32*FRACUNIT
			else
				mobjinfo[MT_KABOOMBOX].mass = 20*FRACUNIT
			end
			if kaboombox.state == S_BOOMBOX_EXPL1
				if player.flchanupgraded == 1
					P_NukeEnemies(kaboombox, p, 1600*FRACUNIT)
				else
					P_NukeEnemies(kaboombox, p, 800*FRACUNIT)
				end
			end
			if kaboombox.state == S_AUTODETONATE
				player.boomboxspawned = 0
			end
		end
	end
end, MT_KABOOMBOX)

addHook("MobjRemoved", function(kaboombox)
	for player in players.iterate do
		local p = player.mo
		player.boomboxspawned = 0
	end
end, MT_KABOOMBOX)

addHook("MobjCollide", FLKillSpikes, MT_SPIKE)
addHook("MobjCollide", FLKillSpikes, MT_WALLSPIKE)

hud.add(function(v, player)
	if player.mo == nil or player.mo.skin ~= "flchan" or srb2p
		return
	end
	local emerdudes1 = v.cachePatch('FHUDA0')
	if (All7Emeralds(emeralds))
		if (leveltime > 0) and (leveltime < 150)
			v.draw(70, 60, emerdudes1, V_PERPLAYER)
			v.drawString(30, 150, "FL Chan's now upgraded by the Emeralds!", V_PERPLAYER)
			v.drawString(60, 160, "Check the console to learn more!", V_PERPLAYER)
		end
	end
end)