local function rot_to_dir(rot)
	local x = -math.cos(rot.x) * math.sin(rot.y)
	local y = math.sin(rot.x)
	local z = math.cos(rot.x) * math.cos(rot.y)
	return {x = x, y = y, z = z}
end

local on_step = function(self, dtime, moveresult)
	local vel = self.object:get_velocity()
	local speed = vector.length(vel)
	local rot = self.object:get_rotation()
	local driver = minetest.get_player_by_name(self.driver)
	local pos = self.object:get_pos()
	
	--Check Surroundings
	local land = false
	local crash_speed = 0
	if moveresult and moveresult.collisions and moveresult.collides then
		for _,collision in pairs(moveresult.collisions) do
			land = true
			crash_speed = crash_speed+
						  math.abs(collision.old_velocity.x-collision.new_velocity.x)+
						  math.abs(collision.old_velocity.y-collision.new_velocity.y)+
						  math.abs(collision.old_velocity.z-collision.new_velocity.z)
		end
	end
	if minetest.get_node(pos).name~="air" then
		land=true
		crash_speed=6 -- just to trigger crash_damage below
	end
	
	if land then
		driver:set_detach()
		driver:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
		driver:add_velocity(vel)
		local crash_dammage = math.floor(math.max(crash_speed-5, 0))
		if crash_dammage > 0 then
			local node = minetest.get_node(pos)
			if minetest.registered_nodes[node.name].liquidtype == "none" then
				local hp = driver:get_hp()
				driver:set_hp(hp-crash_dammage, {type = "fall"})
			end
		end
		self.object:remove()
	end
	
	-- Keyboard controls not supported here.
	rot.x = rot.x + (-driver:get_look_vertical()-rot.x)*(dtime*2)
	local hor = driver:get_look_horizontal()
	local angle = hor-rot.y
	if angle < -math.pi then angle = angle + math.pi*2 end
	if angle > math.pi then angle = angle - math.pi*2 end
	rot.y = rot.y + angle*(dtime*2)
	if speed>10 then
		-- shake if overspeed
		rot.z=-angle+(math.random()-0.5)/2
		speed=10
	else 
		rot.z = -angle
	end
	-- speed = math.max(speed - (rot.x^3)*4 * dtime, 0)
	local ctrl=driver:get_player_control_bits()%32
	if (ctrl>=16) and mfplayers[driver:get_player_name()].energy>0.1 then
		speed=11
	else
		speed = speed  - (angle + rot.x) * dtime
	end
	self.object:set_rotation(rot)
	local dir = rot_to_dir(rot)
	self.object:set_velocity {x = dir.x*speed, y = dir.y*speed-2*(1+math.sin(rot.x)), z = dir.z*speed}
end




minetest.register_entity("glider:hangglider", {
	initial_properties={
		physical = true,
		visual = "mesh",
		mesh = "glider_hangglider.obj",
		pointable = false,
		textures = {"glider_hangglider.png"},
		static_save = false,
	},
	--Functions
	on_step = on_step,
	driver = "",
	free_fall = false,
	speed = 0,
})

glider= {
	deploy= function(itemstack, user)
		local name = user:get_player_name()
		local pos = user:get_pos()
		if not user:get_attach() then
			minetest.sound_play("doors_door_close", {pos=pos, pitch=0.5, max_hear_distance=8, start_time=0.1}, true)
			pos.y = pos.y + 1.5
			local ent = minetest.add_entity(pos, "glider:hangglider")
			local luaent = ent:get_luaentity()
			luaent.driver = name
			ent:set_rotation{y = user:get_look_horizontal(), x = -user:get_look_vertical(), z = 0}
			local vel = user:get_velocity()
			-- For the initial speed we consider vertical speed vel.y is 0, because it is easy to
			-- get a high value.
			vel.y=0
			ent:set_velocity(vel)
			user:set_attach(ent, "", {x=0,y=0,z=-10}, {x=90,y=0,z=0})
			user:set_eye_offset({x=0,y=-16.25,z=0},{x=0,y=-15,z=0})
			if itemstack then itemstack:take_item() end
			return itemstack
		end
	end,
}

minetest.register_tool("glider:glider", {
	description = "Glider\nHow to use: run, jump, deploy. Mouse controlled.",
	inventory_image = "glider_glider.png",
	on_use = glider.deploy})

