// --------------------------------------
// Lua_Tornado
// Tornado ability!
// --------------------------------------
local maxtornadotime = TICRATE*3
local tornadotranstime = TICRATE/3

local function buttonPressed(player, button)
	if(player.cmd.buttons & button)
		and not(player.kvars.prevcmd & button)
		return true
	end
	return false
end

local function lockControl(player)
	if(player.powers[pw_nocontrol] <= 2)
		player.powers[pw_nocontrol] = 2
	end
	player.pflags = $1|PF_STASIS
end

local function zInWater(mobj, atz)
	local rover
	local topheight
	local bottomheight

	for rover in mobj.subsector.sector.ffloors()
		if not(rover.flags & FF_EXISTS)
			or not(rover.flags & FF_SWIMMABLE)
			continue
		end
		
		topheight = rover.topheight
		bottomheight = rover.bottomheight
		if(rover.t_slope) topheight = P_GetZAt(rover.t_slope, mobj.x, mobj.y) end
		if(rover.b_slope) bottomheight = P_GetZAt(rover.b_slope, mobj.x, mobj.y) end

		if(topheight >= atz and bottomheight <= atz)
			return true
		end
	end
	return false
end

local function spawnTornadoDust(mobj)
	local pos = mobj.floorz
	if(P_MobjFlip(mobj) < 0)
		pos = mobj.ceilingz
	end
	local toscale = FixedDiv(FRACUNIT, abs((mobj.z+(mobj.height/2))-pos)/24)
	if(toscale > mobj.scale)
		toscale = mobj.scale
	end

	local dist = mobj.scale * 14
	local angle1 = FixedAngle((P_RandomByte()*360/256)*FRACUNIT)
	local angle2 = FixedAngle((P_RandomByte()*360/256)*FRACUNIT/2)
	local momx = FixedMul(FixedMul(cos(angle1), cos(angle2)), dist)
	local momy = FixedMul(FixedMul(sin(angle1), cos(angle2)), dist)
	local momz = (abs(FixedMul(dist/2, sin(angle2)))+4*mobj.scale)*P_MobjFlip(mobj)
	momx = FixedMul($1, toscale)
	momy = FixedMul($1, toscale)
	momz = FixedMul($1, toscale)
	local spark = P_SpawnMobj(mobj.x+momx, mobj.y+momy, pos, MT_SPINDUST)
	spark.momx = momx
	spark.momy = momy
	spark.momz = momz
	spark.scale = FixedMul(mobj.scale, toscale)
	if(mobj.eflags & MFE_VERTICALFLIP)
		spark.eflags = $1|MFE_VERTICALFLIP
		spark.flags2 = $1|MF2_OBJECTFLIP
	end
	local watertop = mobj.floorz
	if(spark.eflags & MFE_VERTICALFLIP)
		watertop = mobj.ceilingz
	end
	if(zInWater(spark, watertop))
		spark.state = S_SPINDUST_BUBBLE1
	end
end

rawset(_G, "K_Tornado", function(checkflags, destroy, late, player)
	if(checkflags)
		if(player.kvars.ablstate > 0)
			return AF_NOFLOAT|AF_NODUCK|AF_NOJUMP|AF_NOSWIM|AF_NODROP
		end
		return 0
	end
	if(destroy)
		return
	end
	if(late)
		return
	end
	
	if(buttonPressed(player, BT_USE))
		and not(player.kvars.ablstate)
		and not(player.kvars.ducking)
		and not(player.kvars.floating)
		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.powers[pw_nocontrol])
		and not(player.kvars.industdevil)
		player.mo.state = S_KIRBY_TORNADO
		player.kvars.ablstate = 1
	end
	
	if(player.kvars.ablstate > 0)
		and not(player.kvars.ablstate > maxtornadotime)
		and not(player.kvars.ducking)
		and not(player.kvars.floating)
		and not(player.pflags & PF_SLIDING)
		and not(player.powers[pw_carry] or player.kvars.prevcarry)
		player.pflags = ($1|PF_JUMPED) & !PF_NOJUMPDAMAGE
		
		local rotspeed = 0
		if(player.kvars.ablstate < tornadotranstime)
			player.mo.state = S_KIRBY_TORNADO
			rotspeed = player.kvars.ablstate*FixedAngle(15*FRACUNIT)
		elseif(player.kvars.ablstate > maxtornadotime - tornadotranstime)
			if(player.kvars.ablstate-1 == maxtornadotime - tornadotranstime)
				player.drawangle = $1 - ANGLE_90
			end
			player.mo.state = S_KIRBY_TORNADO
			rotspeed = (maxtornadotime-player.kvars.ablstate)*FixedAngle(15*FRACUNIT)
		elseif not(player.mo.state >= S_TORNADO1 and player.mo.state <= S_TORNADO4)
			player.mo.state = S_TORNADO1
		end
		
		if(rotspeed)
			if(player.powers[pw_justsprung] < 2)
				player.powers[pw_justsprung] = 2
			end
			player.drawangle = $1 + rotspeed
		end
		
		if(player.kvars.ablstate%4 == 1)
			S_StartSound(player.mo, sfx_swords)
		end
		
		if((player.cmd.buttons & BT_USE) or(player.cmd.buttons & BT_JUMP))
			and not(player.exiting)
			and not(player.pflags & PF_STASIS)
			and not(player.powers[pw_nocontrol])
			and not(player.kvars.industdevil)
			player.mo.momz = $1 - P_GetMobjGravity(player.mo)
			player.mo.momz = $1 + player.mo.scale*P_MobjFlip(player.mo)/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
		elseif not(P_IsObjectOnGround(player.mo))
			player.mo.momz = $1 - P_GetMobjGravity(player.mo)/2
		end
		
		player.kvars.ablstate = $1 + 1
		
		spawnTornadoDust(player.mo)
	else
		if(player.kvars.ablstate > 0)
			player.kvars.ablstate = -1
			player.pflags = ($1 & !PF_JUMPED)|PF_NOJUMPDAMAGE
			if(P_IsObjectOnGround(player.mo))
				player.mo.state = S_PLAY_RUN
			else
				player.mo.state = S_PLAY_FALL
			end
		end
	end
	
	if(P_IsObjectOnGround(player.mo) or (player.mo.eflags & MFE_UNDERWATER))
		and(player.kvars.ablstate < 0)
		player.kvars.ablstate = 0
	end
end)
