-- By Demnyx
-- Compatibility with every monitor by Sapheros
-- Shitty monitor "poof"

freeslot("S_MONIDUST1", "S_MONIDUST2", "S_MONIDUST3", "S_MONIDUST4", "SPR_DUST",
"sfx_boxpop", "sfx_wtrpop", "sfx_bubp1", "sfx_bubp2", "sfx_bubp3", "sfx_bubp4", "sfx_bubp5")

states[S_MONIDUST1] = {SPR_DUST,0,7,nil,0,0,S_MONIDUST2}
states[S_MONIDUST2] = {SPR_DUST,1,6,nil,0,0,S_MONIDUST3}
states[S_MONIDUST3] = {SPR_DUST,2|TR_TRANS30,4,nil,0,0,S_MONIDUST4}
states[S_MONIDUST4] = {SPR_DUST,3|TR_TRANS60,3,nil,0,0,S_NULL}

-- Set up table for the RandomRange
local bubDust = {
S_SMALLBUBBLE,
S_MEDIUMBUBBLE
}

-- This one, too
local bubDustSound = {
sfx_bubp1,
sfx_bubp2,
sfx_bubp3,
sfx_bubp4,
sfx_bubp5
}

-- Get list of monitors in map
local spawnedmonitors = {}
addHook("MobjSpawn", function(mo)
     if mo.flags & MF_MONITOR then
       table.insert(spawnedmonitors, mo)
     end
end)

-- try readding the gold monitors back to the table via mobjremoved?

-- Mutate the elements in spawnedmonitors?
local function countBoxes()
	local boxes = {}
	for  _,box in ipairs(spawnedmonitors) do
		if not box.valid then continue end
		if not boxes[box.type] then
			boxes[box.type] = 0
		end
		boxes[box.type] = $1+1
	end
	return boxes
end

-- Reset list on map change
addHook("MapChange", do
	spawnedmonitors = {}
end)

-- Function for "poof" on monitor death
local function monitorPop(monitor)
	-- Remove fake monitor when kill
	if not (monitor.valid and (monitor.flags & MF_MONITOR))
	return
	end
	if monitor.faketop and monitor.faketop.valid
	and not monitor.health
		P_RemoveMobj(monitor.faketop)
	end
	if monitor.goldfaketop and monitor.goldfaketop.valid
	and not monitor.health
		P_RemoveMobj(monitor.goldfaketop)
	end
	monitor.sprite = SPR_NULL
	monitor.info.deathsound = sfx_boxpop
	
	-- Puff effect on monitor kill
	
	local boxlist = countBoxes()
	if boxlist[monitor.type] then
		for i = 1, 10 do
			local particle = P_SpawnMobj(monitor.x, monitor.y,
				(monitor.z + 25*FRACUNIT) + ((monitor.eflags & MFE_VERTICALFLIP)/MFE_VERTICALFLIP * (monitor.height - mobjinfo[MT_PARTICLE].height)),
				MT_PARTICLE)
				
			if (monitor.eflags & MFE_TOUCHWATER or monitor.eflags & MFE_UNDERWATER) then
				particle.state = bubDust[P_RandomRange(1,2)]
				particle.bubble = true
			else
				particle.state = S_MONIDUST1
				particle.bubble = false
			end
			if (monitor.eflags & MFE_GOOWATER) then
				particle.flags2 = $1|MF2_DONTDRAW
			else
				particle.flags2 = $1 & ~MF2_DONTDRAW
			end
			particle.target = monitor
			particle.eflags = $1 | (monitor.eflags & MFE_VERTICALFLIP)
			particle.scale = monitor.scale*2/3 
			
			if (monitor.eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
				monitor.info.deathsound = sfx_wtrpop
				S_StartSound(monitor, bubDustSound[P_RandomRange(1,5)])
				P_InstaThrust(particle, FixedAngle(P_RandomRange(0,359)*FRACUNIT), FixedMul(1*FRACUNIT-P_RandomByte()<<11, monitor.scale))			
			else
				monitor.info.deathsound = sfx_boxpop
				P_SetObjectMomZ(particle, P_RandomByte()<<10, false)
				P_InstaThrust(particle, FixedAngle(P_RandomRange(0,359)*FRACUNIT), FixedMul(1*FRACUNIT-P_RandomByte()<<11, monitor.scale))
				P_TryMove(particle, particle.x+particle.momx, particle.y+particle.momy, false)
			end
		end
	end
end

-- POP! THAT! BUBBLE!
addHook("MobjThinker", function(mo)	
	if (mo.bubble) and (mo.watertop ~= mo.subsector.sector.floorheight - 1000*FRACUNIT) and (mo.z+mo.height >= mo.watertop - 5*FRACUNIT) then
		mo.flags2 = $1|MF2_DONTDRAW
	end
end, MT_PARTICLE)

-- Using gold monitor actions to spawn a separate object lmao
function A_GoldMonitorRestore(actor)
	super(actor) -- Run original action
	
	-- Setup gold fake item box
	-- Respawns goldfaketop
	-- goldfakebottom is already spawned
	local goldfakeboxtop = P_SpawnMobj(actor.x, actor.y, actor.z, MT_FAKEBOX_TOP)
	goldfakeboxtop.scale = actor.scale
	goldfakeboxtop.sprite = SPR_GMTV
	goldfakeboxtop.frame = 0
	actor.goldfaketop = goldfakeboxtop
	actor.flags = $1 & ~MF_SOLID
end


-- Run hook on monitor death
addHook("MobjDeath", monitorPop)