function rnd(mi, ma) return math.random(1000)/1000*(ma-mi) + mi end function rndVec(t) return VecScale(VecNormalize(Vec(rnd(-1, 1), rnd(-1, 1), rnd(-1, 1))), t) end function init() fireworks = FindLocations("firework") --time between fireworks fireworkTimer = 0 largeExplosionSnd = {} for i=0, 6 do largeExplosionSnd[i] = LoadSound("fireworks/firework-l"..i..".ogg") end mediumExplosionSnd = {} for i=0, 4 do mediumExplosionSnd[i] = LoadSound("fireworks/firework-m"..i..".ogg") end end pyro = {} newPyro = {} function addPyro(type, pos) local p = {} p.type = type p.pos = pos if type=="small" then p.vel = Vec(rnd(-5, 5), rnd(30, 40), rnd(-5, 5)) elseif type =="medium" then p.vel = Vec(rnd(-10, 10), rnd(40, 50), rnd(-10, 10)) elseif type == "large" then p.vel = Vec(rnd(-15, 15), rnd(50, 60), rnd(-15, 15)) elseif type == "trail" then p.vel = Vec(rnd(-10, 10), rnd(40, 50), rnd(-10, 10)) elseif type == "multi" then p.vel = Vec(-rnd(-5, 5), rnd(40, 60), rnd(-5, 5)) elseif type == "secondary" then p.vel = rndVec(rnd(8, 16)) end local r = math.random(1, 4) if p.type == "secondary" or p.type == "trail" then r = 4 end if r == 1 then p.r = 1.0 p.g = rnd(0.3, 0.5) p.b = rnd(0.3, 0.5) elseif r == 2 then p.r = rnd(0.3, 0.5) p.g = 1.0 p.b = rnd(0.3, 0.5) elseif r == 3 then p.r = rnd(0.3, 0.5) p.g = rnd(0.3, 0.5) p.b = 1.0 else p.r = 1.0 p.g = 1.0 p.b = rnd(0.8, 1.0) end p.age = 0 p.lifeTime = math.sqrt(VecLength(p.vel)) * 0.5 if type == "trail" then p.lifeTime = p.lifeTime * 2.0 end p.done = false newPyro[#newPyro+1] = p end function light(p, t) local l = 1 if p.type == "secondary" then l = 0.2 end if p.type == "small" then l = 0.5 end if p.type == "large" then l = 2 end PointLight(p.pos, p.r, p.g, p.b, l*200*t) end function sound(p) local large = false local vol = 1 if p.type == "large" or p.type == "medium" then large = true end if p.type == "secondary" then return end if large then PlaySound(largeExplosionSnd[math.random(0,#largeExplosionSnd)], p.pos, vol*60) else PlaySound(mediumExplosionSnd[math.random(0,#mediumExplosionSnd)], p.pos, vol*60) end end function trail(p) ParticleType("plain") ParticleTile(4) ParticleCollide(0) ParticleEmissive(5, 0) ParticleAlpha(1, 0) ParticleRadius(0.4, 0) ParticleColor(1, 1, 1) ParticleDrag(0.2) if p.type == "trail" then SpawnParticle(p.pos, VecAdd(VecScale(p.vel, 0.0), rndVec(8)), rnd(1.0, 2.0)) else SpawnParticle(p.pos, Vec(0,0,0), 0.1) end end function explode(p) ParticleType("plain") ParticleTile(4) ParticleCollide(0) ParticleEmissive(10, 0, "easeout") ParticleAlpha(1, 0) ParticleRadius(0.3) ParticleDrag(0.1) ParticleGravity(-10) ParticleStretch(2) ParticleColor(p.r, p.g, p.b) if p.type == "small" then for i=1, 80 do SpawnParticle(p.pos, rndVec(rnd(20, 30)), rnd(1.0, 1.5)) end elseif p.type == "medium" then for i=1, 120 do SpawnParticle(p.pos, rndVec(rnd(30, 60)), rnd(1.5, 2.0)) end elseif p.type == "large" then for i=1, 200 do SpawnParticle(p.pos, rndVec(rnd(80, 100)), rnd(2.0, 3.5)) end elseif p.type == "secondary" then for i=1, 25 do SpawnParticle(p.pos, rndVec(rnd(10, 20)), rnd(1.0, 1.5)) end elseif p.type == "multi" then for i=1, 16 do addPyro("secondary", p.pos) end end end function tickPyro(dt) local soundDelay = 1.0 local lightTime = 0.7 for i=1, #pyro do local p = pyro[i] local keep = true p.age = p.age + dt if p.age < p.lifeTime then p.vel = VecAdd(p.vel, VecScale(Vec(0, -10, 0), dt)) p.pos = VecAdd(p.pos, VecScale(p.vel, dt)) trail(p) else if not p.done then explode(p) p.done = true else if p.age < p.lifeTime+lightTime then local t = 1.0 - (p.age-p.lifeTime)/lightTime light(p, t) end if p.age > p.lifeTime+soundDelay then sound(p) keep = false end end end if keep then newPyro[#newPyro+1] = p end end pyro = newPyro newPyro = {} end function tick(dt) tickPyro(dt) if GetBool("level.demolish.fireworks") and GetFloat("level.timeleft") > 30 then fireworkTimer = fireworkTimer - dt if fireworkTimer <= 0 then local i = math.random(1,#fireworks) local t = GetLocationTransform(fireworks[i]) local r = math.random(1, 5) if r == 1 then addPyro("small", t.pos) elseif r == 2 then addPyro("medium", t.pos) elseif r == 3 then addPyro("large", t.pos) elseif r == 4 then addPyro("multi", t.pos) elseif r == 5 then addPyro("trail", t.pos) end fireworkTimer = math.random(5,10) / 10 end end end