addHook("PostThinkFrame", function()
	if (mapheaderinfo and mapheaderinfo[gamemap] and (mapheaderinfo[gamemap].typeoflevel & TOL_NIGHTS)) then return end
	for player in players.iterate
		-- Firmly attach any active jet fume AFTER player movement.
		-- PlayerThink can run before final movement is applied, which makes the fume appear to lag behind.
		if player
		and player.mo and player.mo.valid
		and player.mo.skin == "ultclsonic"
		and player.mo.jetfume and player.mo.jetfume.valid then
			local mo = player.mo
			local f = mo.jetfume
			-- Keep the same offset used on spawn
			local fx = mo.x - 16*cos(player.drawangle)
			local fy = mo.y - 16*sin(player.drawangle)
			local fz = mo.z + 2*mo.height/5
			f.flags = $|MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOCLIPHEIGHT
			f.momx, f.momy, f.momz = 0,0,0
			P_MoveOrigin(f, fx, fy, fz)
			f.fuse = 2
		end

		if player.mo.skin == "ultclsonic" 
		and player.powers[pw_super] then
			local ghost = P_SpawnGhostMobj(player.mo)
			ghost.colorized = true
			ghost.fuse = 1
			P_MoveOrigin(ghost, player.mo.x, player.mo.y, player.mo.z - 4*FRACUNIT)
			ghost.frame = $|FF_ADD
			ghost.scale = 1*FRACUNIT + 1*FRACUNIT/6
			if ghost.tracer then
				ghost.tracer.fuse = ghost.fuse
			end
		end
	end
end)