--Find handles and load sound
function init()	
	fan = FindBody("fan")
	pos = GetBodyTransform(fan).pos
	fanSound = LoadLoop("MOD/main/snd/fan.ogg")
end


--Return random number between mi and ma
function rnd(mi, ma)
	return math.random()*(ma-mi)+mi
end


--Limit linear and angular velocity of a dynamic body
function limitVelocity(body, lin, ang)
	local linVel = GetBodyVelocity(body)
	local linVelLength = VecLength(linVel)
	if linVelLength > lin then 
		linVel = VecScale(linVel, lin/linVelLength)
		SetBodyVelocity(body, linVel)
	end
	
	local angVel = GetBodyAngularVelocity(body)
	local angVelLength = VecLength(angVel)
	if angVelLength > ang then 
		angVel = VecScale(angVel, ang/angVelLength)
		SetBodyAngularVelocity(body, angVel)
	end
end


function tick(dt)
	--Spin fan, play sound and spawn particles
	--It's just a visual effect has no impact on behavior)
	SetBodyVelocity(fan, Vec(0, 20, 0))
	PlayLoop(fanSound, pos, 1)
                   ParticleType("smoke")
                   ParticleRadius(0.4, 0.0)
                   ParticleColor(0.65, 0.75, 0.8, 1, 1, 1)
                   ParticleGravity(-6)
                   ParticleCollide(1)
                   ParticleDrag(0, 1)
                   ParticleAlpha(1.0, 0.0)
                   SpawnParticle(pos, Vec(rnd(-1,1), 10, rnd(-1,1)), 9)
	
	--Collect all dynamic shapes close to the fan (but exclude the fan itself)
	local strength = 1000
	local maxDist = 2.0
	QueryRejectBody(fan)
	QueryRequire("dynamic")
	local aabbMin = VecAdd(pos, Vec(-maxDist, 0, -maxDist))
	local aabbMax = VecAdd(pos, Vec(maxDist, maxDist, maxDist))
	local shapes = QueryAabbShapes(aabbMin, aabbMax)
	
	--Apply force to dynamic shapes
	for i=1, #shapes do
		local s = shapes[i]
		local hit, cp = GetShapeClosestPoint(s, pos)

		local d = VecSub(cp, pos)
		local l = VecLength(d)
		if l > 0 and l < maxDist then
			--Scale factor based on distance to fan
			local scale = 1.0-l/maxDist
			
			--Create an upwards impulse
			local imp = Vec(0, strength*scale, 0)

			--Apply impulse to the shape's body 
			local b = GetShapeBody(s)
			ApplyBodyImpulse(b, cp, imp)
			
			--This is a bit of a hack (but quite useful method) to avoid dynamic 
			--bodies to spin out of control
			limitVelocity(b, 100, 100)		
		end
	end
end


