From c41bd3932c57abcb7c832e01375540af913accc3 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 14 Apr 2021 18:14:21 +0200 Subject: [PATCH] Add global smoke spawning API --- mods/CORE/mcl_particles/init.lua | 55 +++++++++++++++++++ mods/ITEMS/mcl_fire/init.lua | 94 +++----------------------------- mods/ITEMS/mcl_torches/api.lua | 76 ++++++++++---------------- 3 files changed, 91 insertions(+), 134 deletions(-) diff --git a/mods/CORE/mcl_particles/init.lua b/mods/CORE/mcl_particles/init.lua index 757c0452f..48e9db8df 100644 --- a/mods/CORE/mcl_particles/init.lua +++ b/mods/CORE/mcl_particles/init.lua @@ -66,3 +66,58 @@ function mcl_particles.delete_node_particlespawners(pos) end return false end + +-- 3 exptime variants because the animation is not tied to particle expiration time. +-- 3 colorized variants to imitate minecraft's +local smoke_pdef_cached = {} + +function mcl_particles.spawn_smoke(pos, name, smoke_pdef_base) + local min = math.min + local new_minpos = vector.add(pos, smoke_pdef_base.minrelpos) + local new_maxpos = vector.add(pos, smoke_pdef_base.maxrelpos) + + -- populate the cache + if smoke_pdef_cached[name] then + for i, smoke_pdef in ipairs(smoke_pdef_cached[name]) do + smoke_pdef.minpos = new_minpos + smoke_pdef.maxpos = new_maxpos + mcl_particles.add_node_particlespawner(pos, smoke_pdef, "high") + end + -- cache already populated + else + smoke_pdef_cached[name] = {} + + local smoke_pdef = table.copy(smoke_pdef_base) + smoke_pdef.amount = smoke_pdef_base.amount / 9 + smoke_pdef.time = 0 + smoke_pdef.animation = { + type = "vertical_frames", + aspect_w = 8, + aspect_h = 8, + -- length = 3 exptime variants + } + smoke_pdef.collisiondetection = true + smoke_pdef.minpos = new_minpos + smoke_pdef.maxpos = new_maxpos + + -- the last frame plays for 1/8 * N seconds, so we can take advantage of it + -- to have varying exptime for each variant. + local exptimes = { 0.175, 0.375, 1.0 } + local colorizes = { "199", "209", "243" } -- round(78%, 82%, 90% of 256) - 1 + + for _,exptime in ipairs(exptimes) do + for _,colorize in ipairs(colorizes) do + smoke_pdef.maxexptime = exptime * smoke_pdef_base.maxexptime + smoke_pdef.animation.length = exptime + 0.1 + -- minexptime must be set such that the last frame is actully rendered, + -- even if its very short. Larger exptime -> larger range + smoke_pdef.minexptime = min(exptime, (7.0/8.0 * (exptime + 0.1) + 0.1)) + smoke_pdef.texture = "mcl_particles_smoke_anim.png^[colorize:#000000:" ..colorize + + mcl_particles.add_node_particlespawner(pos, smoke_pdef, "high") + + table.insert(smoke_pdef_cached[name], table.copy(smoke_pdef)) + end + end + end +end diff --git a/mods/ITEMS/mcl_fire/init.lua b/mods/ITEMS/mcl_fire/init.lua index 95d76c45d..176fb250c 100644 --- a/mods/ITEMS/mcl_fire/init.lua +++ b/mods/ITEMS/mcl_fire/init.lua @@ -47,94 +47,16 @@ local alldirs= { x = 0, y = 0, z = 1} } --- 3 exptime variants because the animation is not tied to particle expiration time. --- 3 colorized variants to imitate minecraft's -local smoke_pdef_base = { - amount = 0.001, - time = 0, - -- minpos = vector.add(pos, { x = -0.45, y = -0.45, z = -0.45 }), - -- maxpos = vector.add(pos, { x = 0.45, y = 0.45, z = 0.45 }), +local smoke_pdef = { + amount = 0.009, + maxexptime = 4.0, minvel = { x = -0.1, y = 0.3, z = -0.1 }, maxvel = { x = 0.1, y = 1.6, z = 0.1 }, - -- minexptime = 3 exptime variants, - -- maxexptime = 3 exptime variants minsize = 4.0, maxsize = 4.5, - -- texture = "mcl_particles_smoke_anim.png^[colorize:#000000:(3 colourize variants)", - animation = { - type = "vertical_frames", - aspect_w = 8, - aspect_h = 8, - -- length = 3 exptime variants - }, - collisiondetection = true, + minrelpos = { x = -0.45, y = -0.45, z = -0.45 }, + maxrelpos = { x = 0.45, y = 0.45, z = 0.45 }, } -local smoke_pdef_cached = {} -local spawn_smoke = function(pos) - local min = math.min - local new_minpos = vector.add(pos, { x = -0.45, y = -0.45, z = -0.45 }) - local new_maxpos = vector.add(pos, { x = 0.45, y = 0.45, z = 0.45 }) - - -- populate the cache - if not next(smoke_pdef_cached) then - -- the last frame plays for 1/8 * N seconds, so we can take advantage of it - -- to have varying exptime for each variant. - local exptimes = { 0.75, 1.5, 4.0 } - local colorizes = { "199", "209", "243" } -- round(78%, 82%, 90% of 256) - 1 - - local id = 1 - for _,exptime in ipairs(exptimes) do - for _,colorize in ipairs(colorizes) do - smoke_pdef_base.minpos = new_minpos - smoke_pdef_base.maxpos = new_maxpos - smoke_pdef_base.maxexptime = exptime - smoke_pdef_base.animation.length = exptime + 0.1 - -- minexptime must be set such that the last frame is actully rendered, - -- even if its very short. Larger exptime -> larger range - smoke_pdef_base.minexptime = min(exptime, (7.0/8.0 * (exptime + 0.1) + 0.1)) - smoke_pdef_base.texture = "mcl_particles_smoke_anim.png^[colorize:#000000:" ..colorize - - smoke_pdef_cached[id] = table.copy(smoke_pdef_base) - - mcl_particles.add_node_particlespawner(pos, smoke_pdef_cached[id], "high") - - id = id + 1 - end - end - - -- cache already populated - else - for i, smoke_pdef in ipairs(smoke_pdef_cached) do - smoke_pdef.minpos = new_minpos - smoke_pdef.maxpos = new_maxpos - mcl_particles.add_node_particlespawner(pos, smoke_pdef, "high") - end - end - ---[[ Old smoke pdef - local spawn_smoke = function(pos) - mcl_particles.add_node_particlespawner(pos, { - amount = 0.1, - time = 0, - minpos = vector.add(pos, { x = -0.45, y = -0.45, z = -0.45 }), - maxpos = vector.add(pos, { x = 0.45, y = 0.45, z = 0.45 }), - minvel = { x = 0, y = 0.5, z = 0 }, - maxvel = { x = 0, y = 0.6, z = 0 }, - minexptime = 2.0, - maxexptime = 2.0, - minsize = 3.0, - maxsize = 4.0, - texture = "mcl_particles_smoke_anim.png^[colorize:#000000:127", - animation = { - type = "vertical_frames", - aspect_w = 8, - aspect_h = 8, - length = 2.1, - }, - }, "high") - -- ]] - -end -- -- Items @@ -303,7 +225,7 @@ minetest.register_node("mcl_fire:fire", { end fire_timer(pos) - spawn_smoke(pos) + mcl_particles.spawn_smoke(pos, "fire", smoke_pdef) end, on_destruct = function(pos) mcl_particles.delete_node_particlespawners(pos) @@ -367,7 +289,7 @@ minetest.register_node("mcl_fire:eternal_fire", { if has_mcl_portals then --Calling directly minetest.get_modpath consumes 4x more compute time mcl_portals.light_nether_portal(pos) end - spawn_smoke(pos) + mcl_particles.spawn_smoke(pos, "fire", smoke_pdef) end, on_destruct = function(pos) mcl_particles.delete_node_particlespawners(pos) @@ -627,7 +549,7 @@ minetest.register_lbm({ nodenames = {"group:fire"}, run_at_every_load = true, action = function(pos, node) - spawn_smoke(pos) + mcl_particles.spawn_smoke(pos, "fire", smoke_pdef) end, }) diff --git a/mods/ITEMS/mcl_torches/api.lua b/mods/ITEMS/mcl_torches/api.lua index ced566bbd..83320435f 100644 --- a/mods/ITEMS/mcl_torches/api.lua +++ b/mods/ITEMS/mcl_torches/api.lua @@ -1,3 +1,14 @@ +local smoke_pdef = { + amount = 0.5, + maxexptime = 2.0, + minvel = { x = 0.0, y = 0.5, z = 0.0 }, + maxvel = { x = 0.0, y = 0.6, z = 0.0 }, + minsize = 1.5, + maxsize = 1.5, + minrelpos = { x = -1/16, y = 0.04, z = -1/16 }, + maxrelpos = { x = 1/16, y = 0.06, z = 1/16 }, +} + local spawn_flames_floor = function(pos) -- Flames mcl_particles.add_node_particlespawner(pos, { @@ -15,52 +26,39 @@ local spawn_flames_floor = function(pos) glow = minetest.registered_nodes[minetest.get_node(pos).name].light_source, }, "low") -- Smoke - mcl_particles.add_node_particlespawner(pos, { - amount = 0.5, - time = 0, - minpos = vector.add(pos, { x = -1/16, y = 0.04, z = -1/16 }), - maxpos = vector.add(pos, { x = -1/16, y = 0.06, z = -1/16 }), - minvel = { x = 0, y = 0.5, z = 0 }, - maxvel = { x = 0, y = 0.6, z = 0 }, - minexptime = 2.0, - maxexptime = 2.0, - minsize = 1.5, - maxsize = 1.5, - texture = "mcl_particles_smoke_anim.png", - animation = { - type = "vertical_frames", - aspect_w = 8, - aspect_h = 8, - length = 2.05, - }, - }, "medium") + mcl_particles.spawn_smoke(pos, "torch", smoke_pdef) end local spawn_flames_wall = function(pos) local minrelpos, maxrelpos local node = minetest.get_node(pos) local dir = minetest.wallmounted_to_dir(node.param2) + + local smoke_pdef = table.copy(smoke_pdef) + if dir.x < 0 then - minrelpos = { x = -0.38, y = 0.04, z = -0.1 } - maxrelpos = { x = -0.2, y = 0.14, z = 0.1 } + smoke_pdef.minrelpos = { x = -0.38, y = 0.04, z = -0.1 } + smoke_pdef.maxrelpos = { x = -0.2, y = 0.14, z = 0.1 } elseif dir.x > 0 then - minrelpos = { x = 0.2, y = 0.04, z = -0.1 } - maxrelpos = { x = 0.38, y = 0.14, z = 0.1 } + smoke_pdef.minrelpos = { x = 0.2, y = 0.04, z = -0.1 } + smoke_pdef.maxrelpos = { x = 0.38, y = 0.14, z = 0.1 } elseif dir.z < 0 then - minrelpos = { x = -0.1, y = 0.04, z = -0.38 } - maxrelpos = { x = 0.1, y = 0.14, z = -0.2 } + smoke_pdef.minrelpos = { x = -0.1, y = 0.04, z = -0.38 } + smoke_pdef.maxrelpos = { x = 0.1, y = 0.14, z = -0.2 } elseif dir.z > 0 then - minrelpos = { x = -0.1, y = 0.04, z = 0.2 } - maxrelpos = { x = 0.1, y = 0.14, z = 0.38 } + smoke_pdef.minrelpos = { x = -0.1, y = 0.04, z = 0.2 } + smoke_pdef.maxrelpos = { x = 0.1, y = 0.14, z = 0.38 } else return end + + -- Flames mcl_particles.add_node_particlespawner(pos, { amount = 8, time = 0, - minpos = vector.add(pos, minrelpos), - maxpos = vector.add(pos, maxrelpos), + minpos = vector.add(pos, smoke_pdef.minrelpos), + maxpos = vector.add(pos, smoke_pdef.maxrelpos), minvel = { x = -0.01, y = 0, z = -0.01 }, maxvel = { x = 0.01, y = 0.1, z = 0.01 }, minexptime = 0.3, @@ -71,25 +69,7 @@ local spawn_flames_wall = function(pos) glow = minetest.registered_nodes[node.name].light_source, }, "low") -- Smoke - mcl_particles.add_node_particlespawner(pos, { - amount = 0.5, - time = 0, - minpos = vector.add(pos, minrelpos), - maxpos = vector.add(pos, maxrelpos), - minvel = { x = 0, y = 0.5, z = 0 }, - maxvel = { x = 0, y = 0.6, z = 0 }, - minexptime = 2.0, - maxexptime = 2.0, - minsize = 1.5, - maxsize = 1.5, - texture = "mcl_particles_smoke_anim.png", - animation = { - type = "vertical_frames", - aspect_w = 8, - aspect_h = 8, - length = 2.05, - }, - }, "medium") + mcl_particles.spawn_smoke(pos, "torch", smoke_pdef) end local remove_flames = function(pos)