-- LUALOCALS < --------------------------------------------------------- local math, minetest = math, minetest local math_floor, math_min, math_random = math.floor, math.min, math.random -- LUALOCALS > --------------------------------------------------------- local modname = minetest.get_current_modname() local spawners = {} local function calc_scalar(params, def) if not def then return 0 end local total = 0 for i = 1, math_min(#params, #def) do total = total + params[i] * def[i] end return total end local function calc_vector(params, def) if not def then return {x = 0, y = 0, z = 0} end return { x = calc_scalar(params, def.x), y = calc_scalar(params, def.y), z = calc_scalar(params, def.z) } end local function spawn(def, pnum) local params = {1, pnum / def.amount} for _ = 1, 12 do params[#params + 1] = math_random() end minetest.add_particle({ pos = calc_vector(params, def.pos), velocity = calc_vector(params, def.velocity), acceleration = calc_vector(params, def.acceleration), expirationtime = calc_scalar(params, def.expirationtime), size = calc_scalar(params, def.size), glow = calc_scalar(params, def.glow), collisiondetection = def.collisiondetection, collision_removal = def.collision_removal, object_collision = def.object_collision, vertical = def.vertical, texture = def.texture, playername = def.playername, animation = def.animation }) end minetest.register_entity(modname .. ":spawner", { initial_properties = { physical = false, collide_with_objects = false, collisionbox = {0, 0, 0, 0, 0, 0}, visual_size = {x = 0, y = 0}, is_visible = false, static_save = false }, on_activate = function(self, data) if not data then return self.object:remove() end data = minetest.deserialize(data) self.id = data.id self.def = data.def self.age = 0 if self.def.time <= 0 then -- corner case for i = 1, self.def.amount do spawn(self.def, i) end spawners[self.id] = nil return self.object:remove() end end, on_step = function(self, dtime) local start = self.age self.age = self.age + dtime if self.age > self.def.time then self.age = self.def.time end local pstart = math_floor(self.def.amount * start / self.def.time) local pend = math_floor(self.def.amount * self.age / self.def.time) for i = pstart + 1, pend do spawn(self.def, i) end if self.age >= self.def.time then spawners[self.id] = nil return self.object:remove() end end }) minetest.add_particlespawner_advanced = minetest.add_particlespawner_advanced or function(def) local params = {1, 0.5} for _ = 1, 12 do params[#params + 1] = 0.5 end local pos = calc_vector(params, def.pos) local id = #spawners + 1 local obj = minetest.add_entity(pos, modname .. ":spawner", minetest.serialize({id = id, def = def})) if not obj then return end spawners[id] = obj return id end minetest.delete_particlespawner_advanced = minetest.delete_particlespawner_advanced or function(id) if not id then return end local obj = spawners[id] if not obj then return end obj:remove() spawners[id] = nil end