Reimplement basic Minecraft-like fire spread

This commit is contained in:
cora 2022-01-15 03:31:15 +01:00 committed by Nils Dagsson Moskopp
parent 4deca628dc
commit c12076e74d
Signed by untrusted user who does not match committer: erle
GPG Key ID: A3BC671C35191080
1 changed files with 39 additions and 91 deletions

View File

@ -5,29 +5,6 @@ mcl_fire = {}
local S = minetest.get_translator("mcl_fire")
local N = function(s) return s end
-- inverse pyramid pattern above lava source, floor 1 of 2:
local lava_fire=
{
{ x =-1, y = 1, z =-1},
{ x =-1, y = 1, z = 0},
{ x =-1, y = 1, z = 1},
{ x = 0, y = 1, z =-1},
{ x = 0, y = 1, z = 0},
{ x = 0, y = 1, z = 1},
{ x = 1, y = 1, z =-1},
{ x = 1, y = 1, z = 0},
{ x = 1, y = 1, z = 1}
}
local alldirs=
{
{ x =-1, y = 0, z = 0},
{ x = 1, y = 0, z = 0},
{ x = 0, y =-1, z = 0},
{ x = 0, y = 1, z = 0},
{ x = 0, y = 0, z =-1},
{ x = 0, y = 0, z = 1}
}
local spawn_smoke = function(pos)
mcl_particles.add_node_particlespawner(pos, {
amount = 0.1,
@ -359,16 +336,28 @@ minetest.register_abm({
-- Enable the following ABMs according to 'enable fire' setting
-- [...]a fire that is not adjacent to any flammable block does not spread, even to another flammable block within the normal range.
-- https://minecraft.fandom.com/wiki/Fire#Spread
local function has_flammable(pos)
local npos, node
for n, v in ipairs(alldirs) do
npos = vector.add(pos, v)
node = minetest.get_node_or_nil(npos)
if node and node.name and minetest.get_item_group(node.name, "flammable") ~= 0 then
return npos
end
return minetest.find_node_near(pos, 1, {"group:flammable"})
end
local function check_aircube(p1,p2)
local nds=minetest.find_nodes_in_area(p1,p2,{"air"})
for k,v in pairs(nds) do
if has_flammable(v) then return v end
end
return false
end
-- [...] a fire block can turn any air block that is adjacent to a flammable block into a fire block. This can happen at a distance of up to one block downward, one block sideways (including diagonals), and four blocks upward of the original fire block (not the block the fire is on/next to).
local function get_ignitable(pos)
return check_aircube(vector.add(pos,vector.new(-1,-1,-1)),vector.add(pos,vector.new(1,4,1)))
end
-- Fire spreads from a still lava block similarly: any air block one above and up to one block sideways (including diagonals) or two above and two blocks sideways (including diagonals) that is adjacent to a flammable block may be turned into a fire block.
local function get_ignitable_by_lava(pos)
return check_aircube(vector.add(pos,vector.new(-1,1,-1)),vector.add(pos,vector.new(1,1,1))) or check_aircube(vector.add(pos,vector.new(-2,2,-2)),vector.add(pos,vector.new(2,2,2))) or nil
end
if not fire_enabled then
@ -386,78 +375,37 @@ if not fire_enabled then
else -- Fire enabled
-- Set fire to air nodes
minetest.register_abm({
label = "Ignite fire by lava",
nodenames = {"group:lava"},
neighbors = {"air"},
interval = 7,
chance = 3,
catch_up = false,
action = function(pos)
local i, dir, target, node, i2, f
i = math.random(1,9)
dir = lava_fire[i]
target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z}
node = minetest.get_node(target)
if not node or node.name ~= "air" then
i = ((i + math.random(0,7)) % 9) + 1
dir = lava_fire[i]
target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z}
node = minetest.get_node(target)
if not node or node.name ~= "air" then
return
end
end
i2 = math.random(1,15)
if i2 < 10 then
local dir2, target2, node2
dir2 = lava_fire[i2]
target2 = {x=target.x+dir2.x, y=target.y+dir2.y, z=target.z+dir2.z}
node2 = minetest.get_node(target2)
if node2 and node2.name == "air" then
f = has_flammable(target2)
if f then
minetest.after(1, spawn_fire, {x=target2.x, y=target2.y, z=target2.z})
minetest.add_particle({
pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}),
velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.7), z=f.z-pos.z},
expirationtime=1, size=1.5, collisiondetection=false,
glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png"
})
return
end
end
end
f = has_flammable(target)
if f then
minetest.after(1, spawn_fire, {x=target.x, y=target.y, z=target.z})
minetest.add_particle({
pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}),
velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z},
expirationtime=1, size=1, collisiondetection=false,
glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png"
})
end
end,
})
-- Ignite neighboring nodes, add basic flames
-- Fire Spread
minetest.register_abm({
label = "Ignite flame",
nodenames = {"group:flammable"},
neighbors = {"mcl_fire:fire","mcl_fire:eternal_fire","mcl_core:lava_source","mcl_core:lava_flowing","mcl_nether:nether_lava_source","mcl_nether:nether_lava_flowing",},
nodenames ={"mcl_fire:fire","mcl_fire:eternal_fire"},
interval = 7,
chance = 12,
catch_up = false,
action = function(pos)
local p = minetest.find_node_near(pos, 1, {"air"})
local p = get_ignitable(pos)
if p then
minetest.set_node(p, {name = "mcl_fire:fire"})
end
end
})
--lava fire spread
minetest.register_abm({
label = "Ignite fire by lava",
nodenames = {"mcl_core:lava_source","mcl_nether:nether_lava_source"},
neighbors = {"air","group:flammable"},
interval = 7,
chance = 3,
catch_up = false,
action = function(pos)
local p=get_ignitable_by_lava(pos)
if p then
minetest.set_node(p, {name = "mcl_fire:fire"})
end
end,
})
-- Remove flammable nodes around basic flame
minetest.register_abm({
label = "Remove flammable nodes",