Add fire. Lava can cause it, and you can /giveme fire:basic_flame.
authorPerttu Ahola <celeron55@gmail.com>
Sun, 8 Apr 2012 07:28:10 +0000 (10:28 +0300)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 8 Apr 2012 12:32:31 +0000 (15:32 +0300)
mods/default/init.lua
mods/fire/README.txt [new file with mode: 0644]
mods/fire/init.lua [new file with mode: 0644]
mods/fire/sounds/fire_large.ogg [new file with mode: 0644]
mods/fire/sounds/fire_small.ogg [new file with mode: 0644]
mods/fire/textures/fire_basic_flame.png [new file with mode: 0644]

index a2db93d9e377a4906ddabbb84dab3b11a0daa27d..b3679866de886a411ec9d014be4afc41acf79dfd 100644 (file)
@@ -1009,7 +1009,7 @@ minetest.register_node("default:water_flowing", {
                {image="default_water.png", backface_culling=false},
                {image="default_water.png", backface_culling=true},
        },
-       groups = {water=3, liquid=3},
+       groups = {water=3, liquid=3, puts_out_fire=1},
 })
 
 minetest.register_node("default:water_source", {
@@ -1032,7 +1032,7 @@ minetest.register_node("default:water_source", {
                -- New-style water source material (mostly unused)
                {image="default_water.png", backface_culling=false},
        },
-       groups = {water=3, liquid=3},
+       groups = {water=3, liquid=3, puts_out_fire=1},
 })
 
 minetest.register_node("default:lava_flowing", {
@@ -1056,7 +1056,7 @@ minetest.register_node("default:lava_flowing", {
                {image="default_lava.png", backface_culling=false},
                {image="default_lava.png", backface_culling=true},
        },
-       groups = {lava=3, liquid=2, hot=3, igniter=3},
+       groups = {lava=3, liquid=2, hot=3, igniter=2},
 })
 
 minetest.register_node("default:lava_source", {
@@ -1080,7 +1080,7 @@ minetest.register_node("default:lava_source", {
                -- New-style lava source material (mostly unused)
                {image="default_lava.png", backface_culling=false},
        },
-       groups = {lava=3, liquid=2, hot=3, igniter=3},
+       groups = {lava=3, liquid=2, hot=3, igniter=2},
 })
 
 minetest.register_node("default:torch", {
@@ -1100,7 +1100,7 @@ minetest.register_node("default:torch", {
                wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
                wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
        },
-       groups = {choppy=2,dig_immediate=3},
+       groups = {choppy=2,dig_immediate=3,flammable=1},
        legacy_wallmounted = true,
        sounds = default.node_sound_defaults(),
 })
diff --git a/mods/fire/README.txt b/mods/fire/README.txt
new file mode 100644 (file)
index 0000000..b240f11
--- /dev/null
@@ -0,0 +1,30 @@
+Minetest 0.4 mod: fire
+======================
+
+License of source code:
+-----------------------
+Copyright (C) 2012 Perttu Ahola (celeron55) <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+http://www.gnu.org/licenses/gpl-2.0.html
+
+License of media (textures and sounds)
+--------------------------------------
+Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)                                 
+http://creativecommons.org/licenses/by-sa/3.0/
+
+Authors of media files
+-----------------------
+Everything not listed in here:
+Copyright (C) 2012 Perttu Ahola (celeron55) <celeron55@gmail.com>
+
+fire_small.ogg sampled from:
+  http://www.freesound.org/people/dobroide/sounds/4211/
+
+fire_large.ogg sampled from:
+  http://www.freesound.org/people/Dynamicell/sounds/17548/
+
diff --git a/mods/fire/init.lua b/mods/fire/init.lua
new file mode 100644 (file)
index 0000000..78f9726
--- /dev/null
@@ -0,0 +1,188 @@
+-- minetest/fire/init.lua
+
+minetest.register_node("fire:basic_flame", {
+       description = "Fire",
+       drawtype = "glasslike",
+       tile_images = {"fire_basic_flame.png"},
+       light_source = 14,
+       groups = {igniter=3,dig_immediate=3},
+       drop = '',
+       walkable = false,
+})
+
+local fire = {}
+fire.D = 6
+-- key: position hash of low corner of area
+-- value: {handle=sound handle, name=sound name}
+fire.sounds = {}
+
+function fire.get_area_p0p1(pos)
+       local p0 = {
+               x=math.floor(pos.x/fire.D)*fire.D,
+               y=math.floor(pos.y/fire.D)*fire.D,
+               z=math.floor(pos.z/fire.D)*fire.D,
+       }
+       local p1 = {
+               x=p0.x+fire.D-1,
+               y=p0.y+fire.D-1,
+               z=p0.z+fire.D-1
+       }
+       return p0, p1
+end
+
+function fire.update_sounds_around(pos)
+       local p0, p1 = fire.get_area_p0p1(pos)
+       local cp = {x=(p0.x+p1.x)/2, y=(p0.y+p1.y)/2, z=(p0.z+p1.z)/2}
+       local flames_p = minetest.env:find_nodes_in_area(p0, p1, {"fire:basic_flame"})
+       --print("number of flames at "..minetest.pos_to_string(p0).."/"
+       --              ..minetest.pos_to_string(p1)..": "..#flames_p)
+       local should_have_sound = (#flames_p > 0)
+       local wanted_sound = nil
+       if #flames_p >= 9 then
+               wanted_sound = {name="fire_large", gain=1.5}
+       elseif #flames_p > 0 then
+               wanted_sound = {name="fire_small", gain=1.5}
+       end
+       local p0_hash = minetest.hash_node_position(p0)
+       local sound = fire.sounds[p0_hash]
+       if not sound then
+               if should_have_sound then
+                       fire.sounds[p0_hash] = {
+                               handle = minetest.sound_play(wanted_sound, {pos=cp, loop=true}),
+                               name = wanted_sound.name,
+                       }
+               end
+       else
+               if not wanted_sound then
+                       minetest.sound_stop(sound.handle)
+                       fire.sounds[p0_hash] = nil
+               elseif sound.name ~= wanted_sound.name then
+                       minetest.sound_stop(sound.handle)
+                       fire.sounds[p0_hash] = {
+                               handle = minetest.sound_play(wanted_sound, {pos=cp, loop=true}),
+                               name = wanted_sound.name,
+                       }
+               end
+       end
+end
+
+function fire.on_flame_add_at(pos)
+       --print("flame added at "..minetest.pos_to_string(pos))
+       fire.update_sounds_around(pos)
+end
+
+function fire.on_flame_remove_at(pos)
+       --print("flame removed at "..minetest.pos_to_string(pos))
+       fire.update_sounds_around(pos)
+end
+
+function fire.find_pos_for_flame_around(pos)
+       return minetest.env:find_node_near(pos, 1, {"air"})
+end
+
+function fire.flame_should_extinguish(pos)
+       --return minetest.env:find_node_near(pos, 1, {"group:puts_out_fire"})
+       local p0 = {x=pos.x-2, y=pos.y, z=pos.z-2}
+       local p1 = {x=pos.x+2, y=pos.y, z=pos.z+2}
+       local ps = minetest.env:find_nodes_in_area(p0, p1, {"group:puts_out_fire"})
+       return (#ps ~= 0)
+end
+
+minetest.register_on_placenode(function(pos, newnode, placer)
+       if newnode.name == "fire:basic_flame" then
+               fire.on_flame_add_at(pos)
+       end
+end)
+
+minetest.register_on_dignode(function(pos, oldnode, digger)
+       if oldnode.name == "fire:basic_flame" then
+               fire.on_flame_remove_at(pos)
+       end
+end)
+
+-- Ignite neighboring nodes
+minetest.register_abm({
+       nodenames = {"group:flammable"},
+       neighbors = {"group:igniter"},
+       interval = 1,
+       chance = 2,
+       action = function(p0, node, _, _)
+               -- If there is water or stuff like that around flame, don't ignite
+               if fire.flame_should_extinguish(p0) then
+                       return
+               end
+               local p = fire.find_pos_for_flame_around(p0)
+               if p then
+                       minetest.env:set_node(p, {name="fire:basic_flame"})
+                       fire.on_flame_add_at(p)
+               end
+       end,
+})
+
+-- Rarely ignite things from far
+minetest.register_abm({
+       nodenames = {"group:igniter"},
+       neighbors = {"air"},
+       interval = 2,
+       chance = 10,
+       action = function(p0, node, _, _)
+               local reg = minetest.registered_nodes[node.name]
+               if not reg or not reg.groups.igniter or reg.groups.igniter < 2 then
+                       return
+               end
+               local d = reg.groups.igniter
+               local p = minetest.env:find_node_near(p0, d, {"group:flammable"})
+               if p then
+                       -- If there is water or stuff like that around flame, don't ignite
+                       if fire.flame_should_extinguish(p) then
+                               return
+                       end
+                       local p2 = fire.find_pos_for_flame_around(p)
+                       if p2 then
+                               minetest.env:set_node(p2, {name="fire:basic_flame"})
+                               fire.on_flame_add_at(p2)
+                       end
+               end
+       end,
+})
+
+-- Remove flammable nodes and flame
+minetest.register_abm({
+       nodenames = {"fire:basic_flame"},
+       interval = 1,
+       chance = 2,
+       action = function(p0, node, _, _)
+               -- If there is water or stuff like that around flame, remove flame
+               if fire.flame_should_extinguish(p0) then
+                       minetest.env:remove_node(p0)
+                       fire.on_flame_remove_at(p0)
+                       return
+               end
+               -- Make the following things rarer
+               if math.random(1,3) == 1 then
+                       return
+               end
+               -- If there are no flammable nodes around flame, remove flame
+               if not minetest.env:find_node_near(p0, 1, {"group:flammable"}) then
+                       minetest.env:remove_node(p0)
+                       fire.on_flame_remove_at(p0)
+                       return
+               end
+               if math.random(1,4) == 1 then
+                       -- remove a flammable node around flame
+                       local p = minetest.env:find_node_near(p0, 1, {"group:flammable"})
+                       if p then
+                               -- If there is water or stuff like that around flame, don't remove
+                               if fire.flame_should_extinguish(p0) then
+                                       return
+                               end
+                               minetest.env:remove_node(p)
+                       end
+               else
+                       -- remove flame
+                       minetest.env:remove_node(p0)
+                       fire.on_flame_remove_at(p0)
+               end
+       end,
+})
+
diff --git a/mods/fire/sounds/fire_large.ogg b/mods/fire/sounds/fire_large.ogg
new file mode 100644 (file)
index 0000000..fe78e62
Binary files /dev/null and b/mods/fire/sounds/fire_large.ogg differ
diff --git a/mods/fire/sounds/fire_small.ogg b/mods/fire/sounds/fire_small.ogg
new file mode 100644 (file)
index 0000000..5aac595
Binary files /dev/null and b/mods/fire/sounds/fire_small.ogg differ
diff --git a/mods/fire/textures/fire_basic_flame.png b/mods/fire/textures/fire_basic_flame.png
new file mode 100644 (file)
index 0000000..a5c2afd
Binary files /dev/null and b/mods/fire/textures/fire_basic_flame.png differ