// --------------------------------------
// Lua_UFO
// UFO ability!
// --------------------------------------
local floatheight = 60
local maxfloattime = TICRATE*6
local chargetime = TICRATE

local function highestMud(player)
	local topheight
	local lasttop

	for rover in player.mo.subsector.sector.ffloors()
		if not(rover.flags & FF_EXISTS)
			or not(rover.flags & FF_QUICKSAND)
			continue
		end
		
		if(player.mo.eflags & MFE_VERTICALFLIP)
			topheight = rover.bottomheight
			if(rover.t_slope) topheight = P_GetZAt(rover.t_slope, player.mo.x, player.mo.y) end
		else
			topheight = rover.topheight
			if(rover.b_slope) topheight = P_GetZAt(rover.b_slope, player.mo.x, player.mo.y) end
			topheight = $1 * P_MobjFlip(player.mo)
		end
		
		if(lasttop == nil)
			or(topheight > lasttop)
			lasttop = topheight
		end
	end
	return lasttop
end

rawset(_G, "K_UFO", function(checkflags, destroy, late, player)
	if(checkflags)
		return AF_NOFLOAT|AF_NODUCK|AF_NOJUMP|AF_NOSWIM
	end
	if(destroy)
		player.mo.rollangle = 0
		player.mo.state = S_PLAY_FALL
		return
	end
	
	// Animate
	local tics = player.mo.tics
	if not(player.kvars.ablstate)
		if not(player.mo.state >= S_KIRBY_UFO1 and player.mo.state <= S_KIRBY_UFO3)
			if(player.mo.state >= S_KIRBY_UFOHOLD1 and player.mo.state <= S_KIRBY_UFOHOLD3)
				player.mo.state = $1 + (S_KIRBY_UFO1 - S_KIRBY_UFOOPEN1)
				player.mo.tics = tics
			elseif(player.mo.state >= S_KIRBY_UFOCHARGE1 and player.mo.state <= S_KIRBY_UFOCHARGE3)
				player.mo.state = $1 + (S_KIRBY_UFO1 - S_KIRBY_UFOCHARGE1)
				player.mo.tics = tics
			else
				player.mo.state = S_KIRBY_UFO1
			end
		end
	elseif(player.kvars.ablstate <= chargetime)
		if not(player.mo.state >= S_KIRBY_UFOOPEN1 and player.mo.state <= S_KIRBY_UFOHOLD3)
			player.mo.state = S_KIRBY_UFOHOLD1
		end
	else
		if not(player.mo.state >= S_KIRBY_UFOCHARGE1 and player.mo.state <= S_KIRBY_UFOCHARGE3)
			if(player.mo.state >= S_KIRBY_UFOHOLD1 and player.mo.state <= S_KIRBY_UFOHOLD3)
				player.mo.state = $1 + (S_KIRBY_UFOCHARGE1 - S_KIRBY_UFOOPEN1)
				player.mo.tics = tics
			else
				player.mo.state = S_KIRBY_UFOCHARGE1
			end
		end
	end
	
	if(late)
		return
	end
	
	if(player.mo.eflags & MFE_UNDERWATER)
		player.kvars.ablvar1 = 0
	end
	
	if not(leveltime%3)
		S_StartSound(player.mo, sfx_kufo)
	end
	
	if(player.cmd.buttons & BT_JUMP)
		and(player.kvars.ablvar1 < maxfloattime)
		player.kvars.ablvar1 = $1 + 1
		player.mo.momz = 5*player.mo.scale*P_MobjFlip(player.mo)
	else
		local floorz = player.mo.floorz
		local center = (player.mo.z+(player.mo.height/2))*P_MobjFlip(player.mo)
		if(player.mo.eflags & MFE_VERTICALFLIP)
			floorz = player.mo.ceilingz*P_MobjFlip(player.mo)
		end
		// Hover over mud
		local mud = highestMud(player)
		if not(mud == nil)
			floorz = mud
		end
		if(center-floorz < floatheight*player.mo.scale)
			player.mo.momz = $1 - P_GetMobjGravity(player.mo)
			player.mo.momz = $1+FixedMul(((center-floorz)-(floatheight*player.mo.scale))/12, P_GetMobjGravity(player.mo))
			if(player.mo.momz*P_MobjFlip(player.mo) > 5*player.mo.scale)
				player.mo.momz = 5*player.mo.scale*P_MobjFlip(player.mo)
			end
			player.kvars.ablvar1 = 0
		elseif not(P_IsObjectOnGround(player.mo))
			if(player.mo.momz*P_MobjFlip(player.mo) > 0)
				and(player.kvars.ablvar1)
				player.kvars.ablvar1 = $1 + 1	// Tapping...
			end
		//	if(player.mo.momz*P_MobjFlip(player.mo) < 0)
				player.mo.momz = $1 - P_GetMobjGravity(player.mo)*2/3
				if(player.mo.momz*P_MobjFlip(player.mo) < -5*player.mo.scale)
					player.mo.momz = -5*player.mo.scale*P_MobjFlip(player.mo)
				end
		//	end
		end
	end
	
	// Shooting
	if(player.cmd.buttons & BT_USE)
		and not(player.kvars.prevcmd & BT_USE)
		and not(player.kvars.ablvar2)
		and not(player.pflags & PF_SLIDING)
		and not(player.powers[pw_carry] or player.kvars.prevcarry)
		and not(player.exiting)
		and not(player.pflags & PF_STASIS)
		and not(player.kvars.industdevil)
		player.mo.state = S_KIRBY_UFOOPEN1
		player.kvars.ablstate = 1
	end
	
	if(player.pflags & PF_SLIDING)
		and not(player.powers[pw_carry] or player.kvars.prevcarry)
		and not(player.kvars.industdevil)
		player.kvars.ablstate = 0
	elseif(player.kvars.ablstate)
		player.kvars.ablstate = $1 + 1
		local charged = false
		if(player.kvars.ablstate >= chargetime+1)
			player.kvars.ablstate = chargetime+1
			charged = true
		end
		
		if not(player.cmd.buttons & BT_USE)
			S_StartSound(player.mo, sfx_klaser)
			local m = P_SPMAngle(player.mo, MT_KIRBY_UFOBEAM, player.mo.angle, 0)
			if(m and m.valid)
				m.state = S_KIRBY_UFOBEAM3
				if(charged)
					S_StartSound(player.mo, sfx_spitl)
					m.momx = $1 * 3 / 2
					m.momy = $1 * 3 / 2
					m.momz = $1 * 3 / 2
					m.state = S_KIRBY_UFOBEAMC3
					m.kirbymulti = true
				end
				if(player.mo.eflags & MFE_VERTICALFLIP)
					m.eflags = $1|MFE_VERTICALFLIP
					m.flags2 = $1|MF2_OBJECTFLIP
				end
				P_TeleportMove(m, m.x, m.y, m.z-(P_MobjFlip(player.mo)*player.mo.height/2))
			end
			player.drawangle = player.mo.angle
			player.kvars.ablstate = 0
			player.kvars.ablvar2 = TICRATE/5
		else
			local sx = player.mo.x+FixedMul(cos(player.drawangle), 20*player.mo.scale)
			local sy = player.mo.y+FixedMul(sin(player.drawangle), 20*player.mo.scale)
			local zoff = 0
			if(player.mo.eflags & MFE_VERTICALFLIP)
				zoff = -FixedMul(mobjinfo[MT_KIRBY_UFOBEAM].height, player.mo.scale)
			end
			local m = P_SpawnMobj(sx, sy, player.mo.z+zoff+(player.mo.height/2)-(P_MobjFlip(player.mo)*player.mo.height/2), MT_KIRBY_UFOBEAM)
			m.scale = player.mo.scale
			m.angle = player.drawangle
			if(player.mo.eflags & MFE_VERTICALFLIP)
				m.eflags = $1|MFE_VERTICALFLIP
			end
			m.flags = ($1 & !MF_MISSILE)|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING
			m.fuse = 1
			m.state = $1+((leveltime/2)&1)
			if(charged)
				m.state = $1 + S_KIRBY_UFOBEAMC1-S_KIRBY_UFOBEAM1
			end
		end
	end
	
	if(player.kvars.ablvar2)
		player.kvars.ablvar2 = $1 - 1
		player.drawangle = player.mo.angle
	end
	
	player.mo.rollangle = FixedAngle(cos(FixedAngle(leveltime*13*FRACUNIT))*10)//+(FixedAngle(360*FRACUNIT/(24*2)))
	
	player.charflags = $1 & !SF_NOSKID
end)

addHook("MobjMoveCollide", function(mo, enemy)
	if(enemy.valid and mo.valid)		// We still exsist?
		and((enemy.flags & MF_ENEMY) or (enemy.flags & MF_MONITOR))
		and(enemy.health > 0)		// Enemy isn't already dead?
		and(mo.kirbymulti)			// Only when we're big!
		// Did we actual HIT the enemy?
		and(mo.z+mo.height >= enemy.z)
		and(mo.z <= enemy.z+enemy.height)
		P_KillMobj(enemy, mo, mo.target)	// Rip enemy 1991-2016
		return false
	end
end, MT_KIRBY_UFOBEAM)
