freeslot("MT_MOBJSPAWNER") --RLQ: thanks and credit to eldog for this whole script

mobjinfo[MT_MOBJSPAWNER] = {
	--$Name Generic Mobj Spawner
	doomednum = 11400,
	spawnstate = S_INVISIBLE,
	flags = MF_NOBLOCKMAP|MF_NOGRAVITY
}

local function CopyMobjProperties(mo1, mo2)
	mo1.scale = mo2.scale
	mo1.angle = mo2.angle
	mo1.pitch = mo2.pitch
	mo1.roll  = mo2.roll
	mo1.spritexscale = mo2.spritexscale
	mo1.spriteyscale = mo2.spriteyscale
end -- Close function

local spawnedMobj
local function SpawnMobjWithThrust(mobj)
	spawnedMobj = P_SpawnMobjFromMobj(mobj, 0, 0, 0, _G[mobj.mobjType])
	CopyMobjProperties(spawnedMobj, mobj)
	-- Thrust spawned object
	P_InstaThrust(spawnedMobj, mobj.angle, FixedMul(mobj.mobjMomh, mapobjectscale))
	spawnedMobj.momz = FixedMul((mobj.flags2 & MF2_OBJECTFLIP and mobj.mobjMomv * -1 or mobj.mobjMomv), mapobjectscale)
end -- Close function

local function SetProperties(mobj, thing)
	-- If ANY timing variables are set, assume this isn't being triggered with ACS
	mobj.acsTriggered = true
	local i = 0
	for i = 0, 3 do
		if (thing.args[i] ~= 0) then mobj.acsTriggered = false end
	end
	-- If not being triggered by acs, then set relevant variables
	if not (mobj.acsTriggered) then
		-- Get spawn cycle timings
		mobj.onTics    = thing.args[0] -- Number of tics to spawn mobjs
		mobj.offTics   = thing.args[1] -- Number of tics disabled
		mobj.delayTics = thing.args[2] -- Number of tics delayed at map start. Useful for offsets
		mobj.spawnTics = (thing.args[3] or mobj.onTics) -- Frequency at which to spawn mobjs.
	end
	-- Get properties of mobj to be spawned
	mobj.mobjType = thing.stringargs[1]
	mobj.mobjMomh = thing.args[8] * mapobjectscale -- Horizontal momentum for spawned mobjs to inherit
	mobj.mobjMomv = thing.args[9] * mapobjectscale -- Vertical momentum for spawned mobjs to inherit
	-- Properties for spawned mobjs
	mobj.scale = FixedMul(thing.scale, mapobjectscale)
	mobj.angle = thing.angle * ANG1
	mobj.pitch = thing.pitch * ANG1
	mobj.roll  = thing.roll  * ANG1
	mobj.spritexscale = thing.spritexscale
	mobj.spriteyscale = thing.spriteyscale
	if (mobj.acsTriggered) then
		mobj.flags = $ | MF_NOTHINK -- ACS-Triggered mobjs don't need to think
	end
end -- Close function
local function SpawnerThinker(mobj)
	-- Delay mobj at level start to change timing offset
	if (mobj.delayTics and mobj.delayTics >= leveltime) then return end
	
	-- Spawn mobjs
	if (mobj.spawning) then
		-- Only spawn mobjs at the desired frequency
		if (mobj.fuse % mobj.spawnTics == 0) then
			SpawnMobjWithThrust(mobj)
		end
	end
	-- Enable / Disable spawner
	if (mobj.fuse <= 0) then
		if (mobj.spawning) then
			mobj.spawning = false
			mobj.fuse = mobj.offTics
		else
			mobj.spawning = true
			mobj.fuse = mobj.onTics
		end
	end
end -- Close function
addHook("MapThingSpawn", SetProperties, MT_MOBJSPAWNER)
addHook("MobjThinker",	SpawnerThinker, MT_MOBJSPAWNER)
addHook("MobjFuse", do return true end, MT_MOBJSPAWNER) -- Don't die when fuse hits 0

addHook("SpecialExecute", function(activator, args)
	for mt in mapthings.iterate
		if (mt.type == 11400 and mt.tid == args[1]) then
			if (mt.mobj and mt.mobj.valid and mt.mobj.acsTriggered) then
				SpawnMobjWithThrust(mt.mobj)
			end
		end
	end
end, "TRIGGERITEMSPAWN")