#include "script/common.lua" min_cooldown = GetIntParam("MinTornadoDelay", 15) max_cooldown = GetIntParam("MaxTornadoDelay", 35) local MIN_RADIUS = 0.3 local MAX_RADIUS = 8 local ROT_SPEED = 5 local HEIGHT = 30 local MIN_SPAWN_DIST_TO_PLAYER = 10 local SUCK_RADIUS = 20 local randomtry = 0 local randomtime = 0 local allowtornadospawn = true goforward = false function rnd(mi, ma) return math.random(1000)/1000*(ma-mi) + mi end function rndVec(t) return Vec(rnd(-t, t), rnd(-t, t), rnd(-t, t)) end tornado = {} tornado.pos = Vec() tornado.age = 0 tornado.lifetime = 0 tornado.spawnAngle = 0 tornado.active = false local tornadostartpos = nil local tornadoendpos = nil starttornado = GetBoolParam("StartTornado", true) function init() tornadoSnd = LoadLoop("tornado.ogg") --- Tornado triggers and cooldowns----- triggers = FindTriggers() trigger_cooldown = {} for i = 1, #triggers do SetTag(triggers[i], "id", tostring(i)) trigger_cooldown[i] = 0 end --------------------------------------- tornadostartpos = FindLocation("start") tornadoendpos = FindLocation("finish") end function spawn(startPos, endPos, lifetime) tornado.startPos = startPos tornado.endPos = endPos tornado.age = 0 tornado.lifetime = lifetime tornado.spawnAngle = 0 tornado.pos = startPos tornado.active = true end function mix(lo, hi, t) return lo+(hi-lo)*t end function getOffset(relativeHeight) local bigAng = tornado.age * 1 + relativeHeight*8 local bend = math.sin(relativeHeight*math.pi) * 3 -- Bend only in the middle return Vec(math.sin(bigAng)*bend, 0, math.sin(bigAng*0.7)*bend) end function emitParticles() tornado.spawnAngle = tornado.spawnAngle + 2.39996 TornadoSpawnParticlesCPP(tornado.spawnAngle, HEIGHT, MIN_RADIUS, MAX_RADIUS, ROT_SPEED, tornado.pos, tornado.amount, tornado.age) end function getVelForBody(pos, mass, vel, angVel) --Closest point on tornado local tornadoPoint = VecCopy(tornado.pos) tornadoPoint[2] = pos[2] local tornadoHeight = clamp((tornadoPoint[2] - tornado.pos[2])/HEIGHT, 0.0, 1.0) tornadoPoint = VecAdd(tornadoPoint, getOffset(tornadoHeight)) local toTornado = VecSub(tornadoPoint, pos) local dist = VecLength(toTornado) if dist > 0.0 then toTornado = VecScale(toTornado, 1.0 / dist) end if dist < SUCK_RADIUS then local strength = 1.0 - dist/SUCK_RADIUS strength = strength * (1-tornadoHeight) strength = strength * strength strength = strength * 3.0 * tornado.amount strength = strength * 1000 / (1000+mass) local addVel = VecScale(toTornado, strength) addVel[2] = strength * 0.5 local perp = Vec(toTornado[3], 0.0, -toTornado[1]) addVel = VecAdd(addVel, VecScale(perp, strength*0.2)) local maxVel = 8 for i=1, 3 do if addVel[i] < 0 and vel[i] < -maxVel then addVel[i]=0 end if addVel[i] > 0 and vel[i] > maxVel then addVel[i]=0 end end local maxAngVel = 5 local addAngVel = -ROT_SPEED * strength * 0.05 if angVel[2] < -maxAngVel then addAngVel = 0 end return VecAdd(vel, addVel), VecAdd(angVel, Vec(0, addAngVel, 0)) else return vel, angVel end end function update(dt) for i = 1, #trigger_cooldown do if trigger_cooldown[i] > 0 then trigger_cooldown[i] = trigger_cooldown[i] - dt end end if starttornado then if goforward then spawn(GetLocationTransform(tornadoendpos).pos, GetLocationTransform(tornadostartpos).pos, 10) else spawn(GetLocationTransform(tornadostartpos).pos, GetLocationTransform(tornadoendpos).pos, 10) end goforward = not goforward starttornado = false end if allowtornadospawn then if tornado.active then tornado.pos = VecLerp(tornado.startPos, tornado.endPos, tornado.age/tornado.lifetime) local fadeIn = 3 local fadeOut = 3 if tornado.age < fadeIn then tornado.amount = tornado.age/fadeIn elseif tornado.lifetime-tornado.age < fadeOut then tornado.amount = (tornado.lifetime-tornado.age)/fadeOut else tornado.amount = 1.0 end tornado.amount = tornado.amount * tornado.amount PlayLoop(tornadoSnd, tornado.pos, tornado.amount * 3) tornado.pos[1] = tornado.pos[1] + 0.03 tornado.pos[3] = tornado.pos[3] + 0.03 emitParticles() tornado.age = tornado.age + dt if tornado.age >= tornado.lifetime then starttornado = true end end else randomtime = randomtime + dt if randomtime > 1 then --math.randomseed(GetScriptId()) local rollthedice = math.random(3) if rollthedice > 2 then allowtornadospawn = true else randomtry = randomtry + 1 randomtime = 0 end if randomtry > 2 then allowtornadospawn = true end end end end