// Handle players and buttons. Might do with being merged into LUA_THOK at some point, but distinct enough to keep seperate for now.
// This script is NOT about rumps.
local standsectors = {}
local check = 999

addHook("ThinkFrame", do
	// Fill standsectors table if map has been refreshed
	if check > leveltime then
		standsectors = {}
		
		// SECTOR SETUP: ROIA (3,7) sector special tagged to LD1337. Noclimb for red team only, Effect 4 for blue team only.
		//     X offset is tag for ldexec on, Y offset is tag for ldexec off
		for sector in sectors.iterate do
			if GetSecSpecial(sector.special, 3) == 7 then
				local line = P_FindSpecialLineFromTag(1337, sector.tag, -1)
				if line == -1 then continue end
				
				line = lines[line]
				
				local flag = 0
				
				if line.flags & ML_EFFECT4 then
					flag = 2
				elseif line.flags & ML_NOCLIMB then
					flag = 1
				end
				
				table.insert(standsectors, {
					sector = sector,
					fofsectors = {},
					pushable = flag,
					on = line.frontside.textureoffset >> FRACBITS,
					off = line.frontside.rowoffset >> FRACBITS,
					current = false
				})
			end
		end
		
		// Now go through and look for FOFs if needed
		
		// Start by using lines to associate each standsector with a list of tags
		for line in lines.iterate do
			if ({ // Linedef types of all FOF specials
				[100] = true, [101] = true, [102] = true, [103] = true, [104] = true, [105] = true, [140] = true, [141] = true, [142] = true, [143] = true, [144] = true, [145] = true, [146] = true, // FOF (solid)
				[120] = true, [121] = true, [122] = true, [123] = true, [124] = true, [125] = true, [220] = true, [221] = true, [222] = true, [223] = true, // FOF (intangible)
				[170] = true, [171] = true, [172] = true, [173] = true, [174] = true, [175] = true, [176] = true, [177] = true, [178] = true, [179] = true, [180] = true, // FOF (crumbling)
				[150] = true, [151] = true, [152] = true, [160] = true, [190] = true, [191] = true, [192] = true, [193] = true, [194] = true, [195] = true, // FOF (bobbing)
				[200] = true, [201] = true, [202] = true, [250] = true, [251] = true, [252] = true, [253] = true, [254] = true, [255] = true, [256] = true, [257] = true, [258] = true, [259] = true // FOF (special)
			})[line.special] then
				local fofsec = line.frontsector
				for _,standsector in ipairs(standsectors) do
					if fofsec == standsector.sector then
						standsector.fofsectors[line.tag] = true
						standsector.fofseclist = {}
					end
				end
			end
		end
		
		// Now take each tag list and turn it into a sector list
		for sector in sectors.iterate do
			for _,standsector in ipairs(standsectors) do
				if standsector.fofsectors[sector.tag] then
					table.insert(standsector.fofseclist, sector)
				end
			end
		end
		
		for _,standsector in ipairs(standsectors) do
			standsector.fofsectors = standsector.fofseclist
			standsector.fofseclist = nil
		end
		// Done with FOF checking!
	end
	
	check = leveltime
	
	// Check a certain number of standsectors per frame
	for i = 1,#standsectors do
		local c = standsectors[i]
		
		if not c.sector.valid then // Must've retried over a starpost sector! Force rebuilding the list and stop reading the current one
			check = leveltime+256
			break
		end
		
		local current = false
		for mo in c.sector.thinglist() do
			if (not mo.player or mo.player.spectator) then continue end
			
			// Reject based on teams
			if c.pushable and c.pushable ~= mo.player.ctfteam then continue end
			
			if mo.z <= c.sector.floorheight and mo.momz <= 0 then
				current = mo
				break
			end
		end
		
		if (not current) and c.fofsectors then // Now check FOFs!
			for _,v in ipairs(c.fofsectors) do
				for mo in v.thinglist() do
					if (not mo.player or mo.player.spectator) then continue end
					
					// Reject based on teams
					if c.pushable and c.pushable ~= mo.player.ctfteam then continue end
					
					if mo.z <= c.sector.ceilingheight and mo.z >= c.sector.floorheight and mo.momz <= 0 then
						current = mo
						break 2
					end
				end
			end
		end
		
		if current and not c.current then
			c.current = true
			P_LinedefExecute(c.on, current, c.sector)
			c.triggerer = current
		elseif c.current and not current then
			c.current = false
			P_LinedefExecute(c.off, c.triggerer, c.sector)
			c.triggerer = nil
		end
	end
end)