-- Dummy Ring Bomb --

-- ABOUT: An edited version of "Bomb Throw For Fang" by Simon_T.

if srb2p return end

-- DRB Variables
local monitor = nil
local autoaim = nil

addHook("ThinkFrame", function()
	for player in players.iterate do
		if player.mo.skin ~= "tails" then
			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.cmd.buttons & BT_CUSTOM1) // Then if Custom 1 isn't pressed...
						player.cust1tapready = true -- The following makes it act as a singular button press
						player.cust1tapping = false
					elseif player.cust1tapready
						player.cust1tapping = true
						player.cust1tapready = false
					else
						player.cust1tapping = false
					end
					if player.mo.state != S_PLAY_THROW and player.mo.state != S_PLAY_THROWFIN and player.mo.state != S_PLAY_FLY
						autoaim = P_LookForEnemies(player, false, true) -- Sets up the auto targeting
					end
					if (autoaim 
					and autoaim.valid 
					and autoaim.health 
					and player.mo.state != S_PLAY_FLY) // If the autotarget is valid
						player.drbangle = R_PointToAngle2(player.mo.x, player.mo.y, autoaim.x, autoaim.y) -- Sets up the angle between you and the target
						if player.mo.state == S_PLAY_WALK 
						or player.mo.state == S_PLAY_RUN 
						or (player.pflags & PF_JUMPED) 
						or player.mo.state == S_PLAY_STND 
						or player.mo.state == S_PLAY_WAIT -- Conditions in which you'll be aiming
							P_SpawnLockOn(player, autoaim, S_LOCKON1) -- Spawns the targeting redicle
						end
					end
					-- Conditions in which you're ready to shoot
					if player.mo.state == S_PLAY_WALK or player.mo.state == S_PLAY_RUN or player.pflags & PF_JUMPED or player.mo.state == S_PLAY_STND or player.mo.state == S_PLAY_WAIT or player.mo.state == S_PLAY_THROW or player.mo.state == S_PLAY_THROWFIN or player.mo.state == S_PLAY_FLY
						if player.cust1tapping and not player.weapondelay // If the above function is true while the cooldown isn't active...
							if autoaim and autoaim.valid and player.mo.state != S_PLAY_FLY
								monitor = P_SpawnMissile(player.mo, autoaim, MT_DUMMYBOMB2)
								S_StartSound(player.mo, sfx_hupp) -- Plays the grunt that Tails makes for snipe throws
							else
								monitor = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + (player.mo.height/2), MT_DUMMYBOMB1)
								if (player.mo.momz > 0 and not player.powers[pw_tailsfly]) // If you're moving vertically, but not flying...
									monitor.momz = (player.mo.momz)+(7*FRACUNIT) -- Launches the monitor based on your vertical momentum
								else // Otherwise...
									if (player.powers[pw_tailsfly]) // If the player is flying...
										monitor.momz = 0*FRACUNIT -- The monitor will be dropped
									else
										monitor.momz = 7*FRACUNIT -- The monitor will be launched upwards
									end
								end
								if (player.mo.eflags & MFE_VERTICALFLIP) // If the player is upside down...
									if (player.powers[pw_tailsfly])
										monitor.momz = 0*FRACUNIT
									else
										monitor.momz = -7*FRACUNIT -- Launches it in the opposite direction
									end
								end
								if not (player.powers[pw_tailsfly]) // If the player isn't flying...
									P_InstaThrust(monitor, player.mo.angle, ((player.speed)+(7*FRACUNIT))) -- Throws the monitor based on your angle and speed
									S_StartSound(player.mo, sfx_hyah) -- Plays the grunt that Tails makes for regular throws
								end
								if (player.powers[pw_tailsfly])
									player.weapondelay = TICRATE*1/4 -- You'll always be able to throw carpet bombs faster
								else
									if player.drbupgraded == 1
										player.weapondelay = TICRATE*1 -- Shortens the firing rate
									else
										player.weapondelay = TICRATE*2 -- Gives the normal firing rate
									end
								end
							end
							monitor.target = player.mo -- Monitors will not hurt the user
							if P_IsObjectOnGround(player.mo) // If the player is on the ground at the time...
								player.mo.state = S_PLAY_THROW -- Gives Tails a throwing animation
							end
						end
					end
				end
			end
		end
		if (player.mo.state == S_PLAY_THROW or player.mo.state == S_PLAY_THROWFIN) // If the throwing animation is playing...
			player.pflags = $|PF_FULLSTASIS -- Stabilizes the player
		end
	end
end)

-- Internal Stuff
addHook("MobjThinker", function(monitor)
	-- Defines the player
	for player in players.iterate do
		local p = player.mo
		-- Gravity Flip
		if (p.eflags & MFE_VERTICALFLIP)
			monitor.eflags = $1|MFE_VERTICALFLIP -- Considers it flipped
			monitor.flags2 = $1|MF2_OBJECTFLIP -- Visually flips it upside down
		end
		-- Pricing
		if monitor.valid
			if p.drbupgraded == 1 then
				mobjinfo[MT_DUMMYBOMB1].reactiontime = -1 -- One ring will be spent for each throw
			else
				mobjinfo[MT_DUMMYBOMB1].reactiontime = -2 -- Two rings will be spent for each throw
			end
		end
		-- Floor breaking
		if P_IsObjectOnGround(monitor) // If the monitor is on the ground...
			for x = monitor.x, monitor.x + monitor.radius, monitor.radius -- The following will set up variables for floor breaking
				for y = monitor.y, monitor.y + monitor.radius, monitor.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 monitor lands...
							EV_CrumbleChain(ss.sector, fof) -- Breaks that floor
						end
					end
				end
			end
		end
	end
end, MT_DUMMYBOMB1)

addHook("MobjSpawn", function(monitor)
	if monitor.valid
		S_StartSound(monitor, sfx_s3k51) -- Plays a throwing sound
	end
end, MT_DUMMYBOMB1)

addHook("MobjThinker", function(monitor)
	-- Defines the player
	for player in players.iterate do
		local p = player.mo
		-- Gravity Flip
		if (p.eflags & MFE_VERTICALFLIP)
			monitor.eflags = $1|MFE_VERTICALFLIP -- Considers it flipped
			monitor.flags2 = $1|MF2_OBJECTFLIP -- Visually flips it upside down
		end
		-- Pricing
		if monitor.valid
			if p.drbupgraded == 1 then
				mobjinfo[MT_DUMMYBOMB2].reactiontime = -2 -- Two rings will be spent for each throw
			else
				mobjinfo[MT_DUMMYBOMB2].reactiontime = -4 -- Four rings will be spent for each throw
			end
		end
		-- Floor breaking
		if P_IsObjectOnGround(monitor) // If the monitor is on the ground...
			for x = monitor.x, monitor.x + monitor.radius, monitor.radius -- The following will set up variables for floor breaking
				for y = monitor.y, monitor.y + monitor.radius, monitor.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 monitor lands...
							EV_CrumbleChain(ss.sector, fof) -- Breaks that floor
						end
					end
				end
			end
		end
	end
end, MT_DUMMYBOMB2)

addHook("MobjSpawn", function(monitor)
	if monitor.valid
		S_StartSound(monitor, sfx_s3k51) -- Plays a throwing sound
	end
end, MT_DUMMYBOMB2)