//Deltaplanes by Sonic1983

freeslot("SPR_DPLN", "S_DELTAPLANE", "MT_DELTAPLANE", "MT_DELTAPLANESPAWN", "S_DELTAPLANESPAWN")

//Simplified version of A_RolloutSpawn
function A_DeltaplaneSpawn(actor, locvar1, locvar2)
	if not (actor.target and actor.target.valid)
	or P_AproxDistance(actor.x - actor.target.x, actor.y - actor.target.y) > locvar1
		actor.target = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar2)
		actor.target.angle = actor.angle
	end
end

mobjinfo[MT_DELTAPLANESPAWN] = {
		doomednum = 512,
		spawnstate = S_DELTAPLANESPAWN,
		spawnhealth = 1000,
		radius = 8*FRACUNIT,
		height = 8*FRACUNIT,
		dispoffset = 0,
		mass = 100,
		damage = 0,
		flags = MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY
}

states[S_DELTAPLANESPAWN] = {SPR_DPLN, A|TR_TRANS70, 1, A_DeltaplaneSpawn, 256*FRACUNIT, MT_DELTAPLANE, S_DELTAPLANESPAWN}

mobjinfo[MT_DELTAPLANE] = {
        //doomednum = 512,
		doomednum = -1,
        spawnstate = S_DELTAPLANE,
        spawnhealth = 1,
        reactiontime = 8,
        deathstate = S_DELTAPLANE,
        deathsound = sfx_None,
        speed = 1,
        radius = 48*FRACUNIT,
        height = 44*FRACUNIT,
        dispoffset = 0,
        mass = 100,
        damage = 0,
        flags = MF_SPECIAL|MF_NOGRAVITY|MF_SLIDEME
}

states[S_DELTAPLANE] = {SPR_DPLN, A, -1}

local function KnucklesGlideRecreation(mo, player)
	local glidespeed = FixedMul(player.normalspeed, mo.scale)
	local speed = mo.scale
	local scale = mo.scale
	local angle
	local moveangle = R_PointToAngle2(0, 0, mo.momx, mo.momy)
	
	angle = mo.angle - FixedAngle(player.cmd.sidemove * FRACUNIT)
	
	local anglediff = angle - moveangle
	local accelfactor = 4*FRACUNIT - 3*cos(anglediff)
	
	local newMagnitude = R_PointToDist2(0, 0, mo.momx, mo.momy)
	local oldMagnitude = R_PointToDist2(0, 0, mo.momx, mo.momy)
		
	speed = FixedMul(glidespeed + mo.glidetime*1500, scale)

	P_Thrust(mo, angle, FixedMul(accelfactor, scale))

	newMagnitude = R_PointToDist2(mo.momx, mo.momy, 0, 0)
	if (newMagnitude > speed)
		local tempmomx
		local tempmomy
		if (oldMagnitude > speed)
			if (newMagnitude > oldMagnitude)
				tempmomx = FixedMul(FixedDiv(mo.momx, newMagnitude), oldMagnitude)
				tempmomy = FixedMul(FixedDiv(mo.momy, newMagnitude), oldMagnitude)
				mo.momx = tempmomx
				mo.momy = tempmomy
			end
		else
			tempmomx = FixedMul(FixedDiv(mo.momx, newMagnitude), speed)
			tempmomy = FixedMul(FixedDiv(mo.momy, newMagnitude), speed)
			mo.momx = tempmomx
			mo.momy = tempmomy
		end
	end
	mo.glidetime = min($+1, 15)
end

local function InsideWindFOF(mo)
	local sector = mo.subsector.sector
	if sector
	and sector.valid
		for rover in sector.ffloors()
			if rover
			and rover.valid
			//and rover.flags & FF_EXISTS
				if mo.z <= rover.topheight
				and mo.z+mo.height >= rover.bottomheight
					local line = P_FindSpecialLineFromTag(541, rover.sector.tag)
					if line != -1
						mo.momz = $+(lines[line].args[2]*FRACUNIT)/32
					end
				end
			end
		end
	end
end

addHook("TouchSpecial", function(special, toucher)
	if not (special and special.valid) return true end
	if not special.health return true end
	if special.target return true end
	if not (toucher and toucher.valid) return true end
	local player = toucher.player
	if player
		if player.powers[pw_carry] return true end
		//if (player.powers[pw_flashing]) return true end
		if P_PlayerInPain(player) return true end
		special.target = toucher
		special.flags = $ & ~MF_NOGRAVITY
		P_ResetPlayer(player)
		toucher.tracer = special
		player.powers[pw_carry] = CR_PLAYER
		player.pflags = $|PF_JUMPSTASIS
		special.momx = toucher.momx
		special.momy = toucher.momy
		S_StartSound(toucher, sfx_s3k4a)
	end
	return true
end, MT_DELTAPLANE)

addHook("MobjThinker", function(mo)
	if mo
	and mo.valid
		if mo.health
			if mo.glidetime == nil
				mo.glidetime = 0
			end
			if P_IsObjectOnGround(mo)
				//P_KillMobj(mo)
				mo.health = 0
				mo.fuse = 4*TICRATE
			end
			if mo.target
			and mo.target.valid
				local player = mo.target.player
				mo.angle = mo.target.angle
				player.drawangle = mo.angle
				P_SetObjectMomZ(mo, gravity*3/4, true)
				KnucklesGlideRecreation(mo, player)
				InsideWindFOF(mo)
				if P_IsObjectOnGround(mo.target)
				or player.playerstate != PST_LIVE
				or not player.powers[pw_carry]
				or not mo.health
					mo.health = 0
					mo.fuse = 4*TICRATE
					player.powers[pw_carry] = 0
					player.mo.tracer = nil
					mo.target = nil
				end
			end
		else
			if mo.target
			and mo.target.valid
				mo.target.player.powers[pw_carry] = 0
				mo.target.tracer = nil
				mo.target = nil
			end
			if mo.fuse <= TICRATE
				if (leveltime%2) == 0
					mo.flags2 = $|MF2_DONTDRAW
				else
					mo.flags2 = $ & ~MF2_DONTDRAW
				end
			end
			if P_IsObjectOnGround(mo)
				local speed = FixedHypot(mo.momx, mo.momy)
				if speed > 2*FRACUNIT
					if not (leveltime % 4)
						local dust = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_SPINDUST)
						if dust
						and dust.valid
							P_InstaThrust(dust, R_PointToAngle2(0, 0, mo.momx, mo.momy)+P_RandomRange(-24, 24)*ANG1, -speed/4)
							P_SetObjectMomZ(dust, FRACUNIT)
						end
						S_StartSound(mo, sfx_s3k7e)
					end
				end
			end
		end
	end
end, MT_DELTAPLANE)

//Failsafe
addHook("MobjRemoved", function(mo)
	if mo.target
	and mo.target.valid
		mo.target.player.powers[pw_carry] = 0
		mo.target.tracer = nil
	end
end, MT_DELTAPLANE)