-- Mic Drop --

-- ABOUT: FL Chan's secondary ability.

-- Mic Drop Variables
local mic = nil
local shockwave = nil
local altshckwve = nil

addHook("ThinkFrame", function()
	for player in players.iterate do
		if player.mo.skin ~= "flchan"
			continue
		end
		if not player.exiting // If the player isn't exiting the level...
			if not (P_PlayerInPain(player) or (player.playerstate == PST_DEAD)) // Then, if the player isn't in pain or dead...
				if ((player.powers[pw_carry] == CR_NONE) and not (player.pflags == PF_SPINNING)) // Then if the player isn't being carried or spinning...
					if not (player.mo.state == S_PLAY_FLOAT 
					or player.mo.state == S_PLAY_FLOAT_RUN 
					or player.mo.state == S_PLAY_DASH 
					or player.powers[pw_tailsfly]) // Then if the player isn't Slow Falling, not in their Dash Mode animation, or not swimming...
						if not (player.cmd.buttons & BT_USE) // Then if spin isn't pressed...
							player.spintapready = true -- The following makes it act as a singular button press
							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 the above function is true while the cooldown isn't active...
							if not ((player.mo.boomboxspawned == 1) or (player.mo.flchanhugging == 1)) // Then if there's no Kaboom Box or if the player isn't hugging someone...
								mic = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + (player.mo.height/2), MT_DROPPEDMIC) -- Spawns the mic
								S_StartSound(mic, sfx_brakrl) -- Plays a launching sound
								mic.target = player.mo -- Mics will not hurt the user
								if not P_IsObjectOnGround(player.mo) // If player isn't on the ground...
									player.mo.state = S_MICDROP_MIDAIR -- Plays the midair animation
									if player.mo.flchanupgraded == 1
										player.mo.momz = 20*FRACUNIT -- Boosts the player 20 fracunits upwards
										player.weapondelay = TICRATE*3 -- Even longer cooldown so that you won't abuse it
									else
										player.mo.momz = 10*FRACUNIT -- Boosts the player 10 fracunits upwards
										player.weapondelay = TICRATE*2 -- Longer cooldown so that you won't abuse it
									end
								else // Otherwise...
									player.mo.state = S_MICDROP -- Plays the grounded animation
									player.weapondelay = TICRATE*1 -- Quick cooldown for quick damage
								end
								if (player.mo.eflags & MFE_VERTICALFLIP) // The player is upside down...
									if not P_IsObjectOnGround(player.mo)
										if player.mo.flchanupgraded == 1
											player.mo.momz = -20*FRACUNIT
										else
											player.mo.momz = -10*FRACUNIT
										end
									end
								end
							end
						end
					end
				end
			end
		end
		if (player.mo.state == S_MICDROP or player.mo.state == S_MICDROP_FIN) // If the grounded animation is playing...
			player.pflags = $|PF_FULLSTASIS -- Stabilizes the player
		end
	end
end)

-- Internal Functions
addHook("MobjThinker", function(mic)
	-- Defines the player
	for player in players.iterate do
		local p = player.mo
		-- Dropping
		if (p.eflags & MFE_VERTICALFLIP)
			mic.eflags = $1|MFE_VERTICALFLIP -- Considers it flipped
			mic.flags2 = $1|MF2_OBJECTFLIP -- Visually flips it upside down
			mic.momz = 30*FRACUNIT -- Drops the opposite direction
		else
			mic.momz = -30*FRACUNIT -- Drops it really quick
		end
		-- Shockwave Spawning
		if mic.valid and mic.state == S_XPLD1 // If the mic explodes...
			if p.flchanupgraded
				P_Earthquake(mic, p, 400*FRACUNIT) -- Attacks in a 400 fracunit radius
				shockwave = P_SpawnMobj(mic.x, mic.y, mic.z, MT_SHOCKWAVE2) -- Spawns a bigger shockwave mobj
				altshckwve = P_SpawnMobj(mic.x, mic.y, mic.z, MT_ALTSHCKWVE2) -- Spawns an alternate version of the bigger shockwave with the MF_MISSILE flag
				shockwave.target = p -- Shockwaves will not hurt the user
				altshckwve.target = p
			else
				P_Earthquake(mic, p, 200*FRACUNIT) -- Attacks in a 200 fracunit radius
				shockwave = P_SpawnMobj(mic.x, mic.y, mic.z, MT_SHOCKWAVE1) -- Spawns a shockwave mobj
				altshckwve = P_SpawnMobj(mic.x, mic.y, mic.z, MT_ALTSHCKWVE1) -- Spawns an alternate version of the shockwave with the MF_MISSILE flag
				shockwave.target = p
				altshckwve.target = p
			end
		end
		-- Floor breaking
		if P_IsObjectOnGround(mic) // If the mic is on the ground...
			for x = mic.x, mic.x + mic.radius, mic.radius -- The following will set up variables for floor breaking
				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) // If a breakable floor exists where the mic drops...
							EV_CrumbleChain(ss.sector, fof) -- Breaks that floor
						end
					end
				end
			end
		end
	end
end, MT_DROPPEDMIC)

-- Shield Restriction
addHook("ShieldSpecial", function(player)
	if player.mo.skin == "flchan"
		if player.powers[pw_shield] == SH_FLAMEAURA
		or player.powers[pw_shield] == SH_BUBBLEWRAP // If you have the Fire Shield or Bubble Shield on...
			return false -- Allows you to use their actives
		else
			return true -- No shield actives since Mic Drop gets in the way
		end
	end
end)

-- Spike Destroying
local killspikes = function(thing, tmthing)
	if not (thing and thing.valid and tmthing and tmthing.valid) return end
	if tmthing == shockwave
		P_KillMobj(thing, tmthing)
		return true
	end
end

addHook("MobjCollide", function(thing, tmthing) killspikes(thing, tmthing) end, MT_SPIKE)
addHook("MobjCollide", function(thing, tmthing) killspikes(thing, tmthing) end, MT_WALLSPIKE)

-- Fail Messages
addHook("MobjDeath", function(mo, inflictor, source, damagetype)
	if mo.skin == "henry"
	and mo.valid and not (mo.player.powers[pw_carry] == CR_NIGHTSMODE)
		local player = mo.player
		if inflictor and inflictor.type == MT_DROPPEDMIC
			player.failwhy = "YOU'LL NEVER SEE IT COMING"
			player.failwhy2 = nil
			player.failwhy3 = nil
			player.failwhy4 = nil
			player.failwhy5 = nil
			player.failwhy6 = nil
			player.failwhy7 = nil
			player.failwhy8 = nil
			player.failwhy9 = nil
			player.failwhy10 = nil
		end
		if inflictor and inflictor == shockwave
			player.failwhy = "DR-DR-DROP THE BASS"
			player.failwhy2 = nil
			player.failwhy3 = nil
			player.failwhy4 = nil
			player.failwhy5 = nil
			player.failwhy6 = nil
			player.failwhy7 = nil
			player.failwhy8 = nil
			player.failwhy9 = nil
			player.failwhy10 = nil
		end
	end
end, MT_PLAYER)