106 lines
3.1 KiB
Lua
106 lines
3.1 KiB
Lua
-- 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
|