-- FIREWORK
-- by callmore

if firework then
	return
end
rawset(_G, "firework", true)

local SPARKLE_TICS = 1*TICRATE + (3*TICRATE/4)

freeslot("SPR_BFRW",
		 "MT_FIREWORK_SPAWNER", "MT_FIREWORK_ROCKET", "MT_FIREWORK_FLASH", "MT_FIREWORK_BANG",
		 "S_FIREWORK_ROCKET", "S_FIREWORK_SPARKLE", "S_FIREWORK_FLASH", "S_FIREWORK_BANG")

states[S_FIREWORK_ROCKET] = {SPR_BFRW, 0|FF_FULLBRIGHT|FF_ANIMATE, -1, nil, 3, 2, S_FIREWORK_ROCKET}
states[S_FIREWORK_SPARKLE] = {SPR_BFRW, 4|FF_FULLBRIGHT, SPARKLE_TICS, nil, 0, 0, S_NULL}
states[S_FIREWORK_FLASH] = {SPR_BFRW, 6|FF_FULLBRIGHT|FF_ANIMATE, 6, nil, 2, 2, S_NULL}
states[S_FIREWORK_BANG] = {SPR_BFRW, 5|FF_FULLBRIGHT, (3*TICRATE/4), nil, 0, 0, S_NULL}

mobjinfo[MT_FIREWORK_SPAWNER] = {
	doomednum = 2207,
	spawnstate = S_INVISIBLE,
	spawnhealth = 1000,
	speed = 1,
	radius = 32*FRACUNIT,
	height = 32*FRACUNIT,
	dispoffset = 0,
	mass = 1000,
	flags = MF_NOSECTOR|MF_NOGRAVITY,
}
mobjinfo[MT_FIREWORK_ROCKET] = {
	doomednum = -1,
	spawnstate = S_FIREWORK_ROCKET,
	deathstate = S_FIREWORK_SPARKLE,
	spawnhealth = 1000,
	speed = 1,
	radius = 32*FRACUNIT,
	height = 32*FRACUNIT,
	dispoffset = 0,
	mass = 1000,
	flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP,
}
mobjinfo[MT_FIREWORK_FLASH] = {
	doomednum = -1,
	spawnstate = S_FIREWORK_FLASH,
	spawnhealth = 1000,
	speed = 1,
	radius = 32*FRACUNIT,
	height = 32*FRACUNIT,
	dispoffset = 0,
	mass = 1000,
	flags = MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOGRAVITY,
}
mobjinfo[MT_FIREWORK_BANG] = {
	doomednum = -1,
	spawnstate = S_FIREWORK_BANG,
	spawnhealth = 1000,
	speed = 1,
	radius = 32*FRACUNIT,
	height = 32*FRACUNIT,
	dispoffset = 0,
	mass = 1000,
	flags = MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOGRAVITY,
}


local function spawnerThink(mo)
	if mo.spawnerTimer == nil then
		mo.spawnerTimer = (mo.spawnpoint.extrainfo*TICRATE) or 1
	end
	
	if not mo.spawnerTimer then
		mo.spawnerTimer = (mo.spawnpoint.extrainfo*TICRATE) or 1
		local r = P_SpawnMobj(mo.x, mo.y, mo.z, MT_FIREWORK_ROCKET)
		r.fuse = mo.spawnpoint.angle + 1
		r.color = (abs(leveltime+mo.x+mo.y+mo.z+mo.angle)%SKINCOLOR_LILAC)+1
	else
		mo.spawnerTimer = $-1
	end
end
addHook("MobjThinker", spawnerThink, MT_FIREWORK_SPAWNER)


local function rocketSpawn(mo)
	--pass
end
addHook("MobjSpawn", rocketSpawn, MT_FIREWORK_ROCKET)

local function rocketThinker(mo)
	if mo.state == mo.info.spawnstate then
		if mo.fuse == 1 then
			mo.momz = 0
		else
			mo.momz = mapobjectscale*32
		end
	else
		if mo.tics > TICRATE then
			local scaleamount = FixedMul(FixedDiv((mo.tics-TICRATE), SPARKLE_TICS-TICRATE), mapobjectscale)
			mo.scale = $+scaleamount/2
			mo.momz = 0
		end
		mo.momz = (mo.tics - SPARKLE_TICS)*(mapobjectscale/6)
	end
	if not (leveltime % 4) then
		P_SpawnGhostMobj(mo)
	end
end
addHook("MobjThinker", rocketThinker, MT_FIREWORK_ROCKET)

local function rocketFuse(mo)
	local s = P_SpawnMobj(mo.x, mo.y, mo.z, MT_FIREWORK_FLASH)
	local bang = P_SpawnMobj(mo.x, mo.y, mo.z, MT_FIREWORK_BANG)
	mo.state = mo.info.deathstate
	mo.scale = mapobjectscale/4
	bang.color = mo.color
	bang.scale = mapobjectscale*2
	S_StartSound(mo, sfx_cannon)
	return true
end
addHook("MobjFuse", rocketFuse, MT_FIREWORK_ROCKET)

local function flashThink(mo)
	if not (leveltime % 4) then
		P_SpawnGhostMobj(mo)
	end
end
addHook("MobjThinker", flashThink, MT_FIREWORK_FLASH)

local function bangThink(mo)
	if not (leveltime % 4) then
		P_SpawnGhostMobj(mo)
	end
	mo.scale = $+mapobjectscale/20
end
addHook("MobjThinker", bangThink, MT_FIREWORK_BANG)
