-- FL Chan's Stuff --
local function MicShockwaveThink(mo)
	local src = mo.target
	if mo and mo.valid and src and src.valid
		local fx = mo.x
		local fy = mo.y
		local fr = mo.radius
		searchBlockmap("objects", function(mo, found)
			if found.valid
				if (found.flags & MF_SHOOTABLE and found != src)
				and found.z - found.scale <= mo.z + mo.height
				and found.z + found.height + found.scale >= mo.z
					P_DamageMobj(found, mo, src, 1)
				end
			end
			if (found.valid and found.type == MT_EGGSHIELD) 
			and found.z - found.scale <= mo.z + mo.height
			and found.z + found.height + found.scale >= mo.z
				P_KillMobj(found, mo, src)
			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 <= mo.z + mo.height
			and found.z + found.height + found.scale >= mo.z
				found.flags2 = $ | MF2_CLASSICPUSH
			end
		end, mo, fx-fr, fx+fr, fy-fr, fy+fr)
	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 or PSO)
			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_SPIN)
							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.boombox.target = player.mo
										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
		if player.bot == 1
			if not (player.boombox and player.boombox.valid)
				player.boomboxspawned = 0
			end
		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(mo)
	local src = mo.target
	if mo and mo.valid and src and src.valid
		P_SetObjectMomZ(mo, -30*FRACUNIT)
		if (src.eflags & MFE_VERTICALFLIP)
			mo.eflags = $1|MFE_VERTICALFLIP
			mo.flags2 = $1|MF2_OBJECTFLIP
		end
		if mo.state == S_XPLD1
			if src.player.flchanupgraded == 1
				P_Earthquake(mo, src, 400*FRACUNIT)
				mo.shockwave = P_SpawnMobj(mo.x, mo.y, mo.z, MT_SHOCKWAVE2)
				mo.shockwave.target = src
			else
				P_Earthquake(mo, src, 200*FRACUNIT)
				mo.shockwave = P_SpawnMobj(mo.x, mo.y, mo.z, MT_SHOCKWAVE1)
				mo.shockwave.target = src
			end
		end
		if P_IsObjectOnGround(mo)
			for x = mo.x, mo.x + mo.radius, mo.radius
				for y = mo.y, mo.y + mo.radius, mo.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, 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(mo)
	local src = mo.target
	if mo and mo.valid and src and src.valid
		if (src.eflags & MFE_VERTICALFLIP)
			mo.eflags = $1|MFE_VERTICALFLIP
			mo.flags2 = $1|MF2_OBJECTFLIP
		end
		if src.player.flchanupgraded == 1
			mobjinfo[MT_KABOOMBOX].mass = 32*FRACUNIT
		else
			mobjinfo[MT_KABOOMBOX].mass = 20*FRACUNIT
		end
		if mo.state == S_BOOMBOX_EXPL1
			if src.player.flchanupgraded == 1
				P_NukeEnemies(mo, src, 1600*FRACUNIT)
			else
				P_NukeEnemies(mo, src, 800*FRACUNIT)
			end
		end
		if mo.state == S_AUTODETONATE
			src.player.boomboxspawned = 0
		end
	end
end, MT_KABOOMBOX)

addHook("MobjRemoved", function(mo)
	local src = mo.target
	src.player.boomboxspawned = 0
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)

addHook("MusicChange", function(oldname, newname)
	if consoleplayer
		local character = skins[consoleplayer.skin].name
		if character == "flchan"
			if newname == "_conti"
				return "FNFGO"
			end
		end
	end
end)