Initial commit (version 0.1-test)
5
mods/extinguisher/LICENSE.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
explosion sounds (CC0) from https://freesound.org/people/tommccann/sounds/235968/
|
||||
touch sounds (CC0) from http://freesound.org/people/talesjc/sounds/152572/
|
||||
extinguish sounds (CC0) from http://freesound.org/people/Planet-Leader/sounds/155516/
|
||||
textures (CC0) made with the GNU image manipulation program
|
||||
code (CC0) partially copied from my version of the nuke mod
|
||||
6
mods/extinguisher/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
For a description of this Minetest mod, see
|
||||
https://forum.minetest.net/viewtopic.php?f=9&t=10263.
|
||||
|
||||
TODO:
|
||||
* Add a fire extinguisher node which automatically shoots at fire nodes
|
||||
* Add an alternative recipe if poisonify is not available
|
||||
347
mods/extinguisher/init.lua
Normal file
@@ -0,0 +1,347 @@
|
||||
local range = 100
|
||||
local v = 1
|
||||
local a = 100
|
||||
local speed = 0.1 --0 or less for default maximum speed
|
||||
|
||||
local function spray_foam(pos)
|
||||
if minetest.get_node(pos).name == "extinguisher:foam" then
|
||||
-- Do not spray foam onto foam
|
||||
return
|
||||
end
|
||||
for z = -1,1 do
|
||||
for y = -1,1 do
|
||||
for x = -1,1 do
|
||||
local p = {x=pos.x+x, y=pos.y+y, z=pos.z+z}
|
||||
local nn = minetest.get_node(p).name
|
||||
if nn == "fire:basic_flame" or nn == "fire:permanent_flame" then
|
||||
minetest.set_node(p, {name="air"})
|
||||
minetest.sound_play("fire_extinguish_flame",
|
||||
{pos = p, max_hear_distance = 16, gain = 0.15})
|
||||
minetest.check_for_falling(p)
|
||||
elseif math.random(0,3) >= 1 then
|
||||
if nn == "air" then
|
||||
minetest.set_node(p, {name="air"})
|
||||
minetest.check_for_falling(p)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function extinguish(player)
|
||||
--local t1 = os.clock()
|
||||
|
||||
local playerpos = player:get_pos()
|
||||
local dir = player:get_look_dir()
|
||||
|
||||
local startpos = vector.new(playerpos)
|
||||
startpos.y = startpos.y+1.625
|
||||
local bl, pos = minetest.line_of_sight(startpos,
|
||||
vector.add(vector.multiply(dir, range), startpos), 1)
|
||||
local snd = minetest.sound_play("extinguisher",
|
||||
{pos = playerpos, gain = 0.5, max_hear_distance = range})
|
||||
local flight_time = 1
|
||||
if pos then
|
||||
local s = math.max(vector.distance(startpos, pos)-0.5, 0)
|
||||
flight_time = (math.sqrt(v * v + 2 * a * s) - v) / a
|
||||
end
|
||||
if not bl then
|
||||
minetest.after(flight_time, function()
|
||||
-- Extinguish the node
|
||||
minetest.sound_stop(snd)
|
||||
spray_foam(vector.round(pos))
|
||||
end)
|
||||
end
|
||||
minetest.add_particle({
|
||||
pos = startpos,
|
||||
velocity = vector.multiply(dir, v),
|
||||
acceleration = vector.multiply(dir, a),
|
||||
expirationtime = flight_time,
|
||||
size = 1,
|
||||
texture = "extinguisher_shot.png^[transform" .. math.random(0,7),
|
||||
})
|
||||
|
||||
--print("[extinguisher] my shot was calculated after "..tostring(os.clock()-t1).."s")
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
local function table_empty(t)
|
||||
for _,_ in pairs(t) do
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function get_tab(pos)
|
||||
local tab_tmp = {pos}
|
||||
local tab_avoid = {[pos.x.." "..pos.y.." "..pos.z] = true}
|
||||
local tab_done,num = {pos},2
|
||||
while not table_empty(tab_tmp) do
|
||||
for n,p in pairs(tab_tmp) do
|
||||
tab_tmp[n] = nil
|
||||
for z = -2,2 do
|
||||
for y = -2,2 do
|
||||
for x = -2,2 do
|
||||
local p2 = {x=pos.x+x, y=pos.y+y, z=pos.z+z}
|
||||
local pstr = p2.x.." "..p2.y.." "..p2.z
|
||||
if not tab_avoid[pstr]
|
||||
and minetest.get_node(p2).name == "fire:basic_flame" then
|
||||
tab_avoid[pstr] = true
|
||||
tab_done[num] = p2
|
||||
num = num+1
|
||||
table.insert(tab_tmp, p2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return tab_done
|
||||
end]]
|
||||
|
||||
local function stop_all_fire_sounds()
|
||||
local players = minetest.get_connected_players()
|
||||
for i = 1, #players do
|
||||
fire.update_player_sound(players[i])
|
||||
end
|
||||
end
|
||||
|
||||
local c_fire, c_foam, c_lava, c_lavaf, c_obsidian, c_cobble
|
||||
local function extinguish_fire(pos)
|
||||
local t1 = os.clock()
|
||||
c_fire = c_fire or minetest.get_content_id("fire:basic_flame")
|
||||
c_fire1 = c_fire1 or minetest.get_content_id("fire:permanent_flame")
|
||||
c_foam = c_foam or minetest.get_content_id("extinguisher:foam")
|
||||
|
||||
local tab = vector.explosion_table(40)
|
||||
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(vector.add(pos, -40),
|
||||
vector.add(pos, 40))
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
local nodes = manip:get_data()
|
||||
|
||||
for _,i in pairs(tab) do
|
||||
local ran = i[2]
|
||||
if not ran
|
||||
or math.random(2) == 1 then
|
||||
local p = area:indexp(vector.add(pos, i[1]))
|
||||
local d_p = nodes[p]
|
||||
if d_p == c_fire then
|
||||
nodes[p] = air;
|
||||
elseif d_p == c_fire1 then
|
||||
nodes[p] = air;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
stop_all_fire_sounds()
|
||||
print(string.format("[extinguisher] exploded at %s after ca. %.2fs",
|
||||
minetest.pos_to_string(pos), os.clock() - t1))
|
||||
--[[t1 = os.clock()
|
||||
manip:update_map()
|
||||
print(string.format("[extinguisher] map updated after ca. %.2fs", os.clock() - t1))]]
|
||||
end
|
||||
|
||||
local function eexpl(pos)
|
||||
if minetest.get_node(pos).name ~= "extinguisher:automatic" then
|
||||
return
|
||||
end
|
||||
minetest.sound_play("extinguisher_explosion", {pos=pos})
|
||||
minetest.set_node(pos, {name="extinguisher:destroyed"})
|
||||
local startpos = minetest.find_node_near(pos, 2, {"fire:basic_flame"})
|
||||
if not startpos then
|
||||
return
|
||||
end
|
||||
extinguish_fire(startpos)
|
||||
end
|
||||
|
||||
|
||||
minetest.register_node("extinguisher:foam", {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
}
|
||||
},
|
||||
use_texture_alpha = "blend",
|
||||
tiles = {"extinguisher_foam.png"},
|
||||
drop = "",
|
||||
groups = {dig_immediate=3, puts_out_fire=1, not_in_creative_inventory=1, falling_node=1},
|
||||
})
|
||||
|
||||
local adtime = 0
|
||||
local time = minetest.get_us_time()
|
||||
local count = 0
|
||||
minetest.register_abm({
|
||||
nodenames = {"extinguisher:foam"},
|
||||
interval = 5,
|
||||
chance = 5,
|
||||
catch_up = false,
|
||||
action = function(pos)
|
||||
count = count+1
|
||||
local ct = minetest.get_us_time()
|
||||
if count > 10
|
||||
and ct-time < 1000000 then
|
||||
return
|
||||
end
|
||||
time = ct
|
||||
count = 0
|
||||
minetest.remove_node(pos)
|
||||
if adtime < 0.1 then
|
||||
minetest.check_for_falling(pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("extinguisher:automatic", {
|
||||
description = "Extinguisher",
|
||||
tiles = {"extinguisher_top.png", "extinguisher_bottom.png",
|
||||
"extinguisher.png", "extinguisher.png^[transformFX",
|
||||
"extinguisher_front.png", "extinguisher_back.png"},
|
||||
use_texture_alpha = "opaque",
|
||||
inventory_image = "extinguisher.png",
|
||||
wield_image = "extinguisher_pipe.png",
|
||||
paramtype = "light",
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
-- Main bottle
|
||||
{-2/16, -0.5, -5/16, 3/16, 0, 0},
|
||||
{-1/16, 0, -5/16, 2/16, 3/16, 0},
|
||||
{-2/16, 0, -4/16, 3/16, 3/16, -1/16},
|
||||
{-1/16, 3/16, -4/16, 2/16, 5/16, -1/16},
|
||||
{0, 5/16, -3/16, 1/16, 6/16, -2/16},
|
||||
|
||||
-- Outlet
|
||||
{0, 3/16, -1/16, 1/16, 4/16, 2/16},
|
||||
{-1/16, 3/16, 2/16, 0, 4/16, 4/16},
|
||||
{1/16, 3/16, 2/16, 2/16, 4/16, 4/16},
|
||||
{0, 4/16, 2/16, 1/16, 5/16, 6/16},
|
||||
{0, 2/16, 2/16, 1/16, 3/16, 6/16},
|
||||
|
||||
-- Handle
|
||||
{0, 6/16, -6/16, 1/16, 7/16, -1/16},
|
||||
{-1/16, 6/16, -3/16, 2/16, 7/16, -2/16},
|
||||
{0, 5/16, -7/16, 1/16, 6/16, -5/16},
|
||||
{0, 4/16, -7/16, 1/16, 5/16, -6/16},
|
||||
},
|
||||
},
|
||||
groups = {dig_immediate=2},
|
||||
sounds = {dig=""},
|
||||
on_punch = function(pos, _, player)
|
||||
minetest.sound_play("extinguisher_touch", {pos=pos, gain=0.25, max_hear_distance=8})
|
||||
if player:get_wielded_item():get_name() == "main:torch" then
|
||||
minetest.after(math.random()*5, eexpl, pos)
|
||||
end
|
||||
end,
|
||||
on_use = function() -- do not dig or punch nodes
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("extinguisher:destroyed", {
|
||||
description = "Destroyed Extinguisher",
|
||||
tiles = {"extinguisher_top.png", "extinguisher_bottom.png",
|
||||
"extinguisher.png", "extinguisher.png^[transformFX",
|
||||
"extinguisher_front.png", "extinguisher_destroyed.png"},
|
||||
use_texture_alpha = "opaque",
|
||||
inventory_image = "extinguisher.png",
|
||||
wield_image = "extinguisher_pipe.png",
|
||||
paramtype = "light",
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
-- Main bottle
|
||||
{-2/16, -0.5, -3/16, 3/16, 0, 0},
|
||||
{-1/16, 0, -5/16, 1/16, 3/16, 0},
|
||||
{-1/16, 0, -4/16, 3/16, 3/16, -1/16},
|
||||
{-1/16, -3/16, -4/16, 2/16, 4/16, -1/16},
|
||||
},
|
||||
},
|
||||
groups = {dig_immediate=2},
|
||||
sounds = {dig=""},
|
||||
on_punch = function(pos, _, player)
|
||||
minetest.sound_play("extinguisher_touch", {pos=pos, gain=0.25, max_hear_distance=8})
|
||||
if player:get_wielded_item():get_name() == "main:torch" then
|
||||
minetest.after(math.random()*5, eexpl, pos)
|
||||
end
|
||||
end,
|
||||
on_use = function() -- do not dig or punch nodes
|
||||
end,
|
||||
})
|
||||
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
adtime = dtime
|
||||
timer = timer+dtime
|
||||
if timer < speed then
|
||||
return
|
||||
end
|
||||
timer = 0
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
if player:get_wielded_item():get_name() == "extinguisher:automatic"
|
||||
and player:get_player_control().LMB then
|
||||
extinguish(player)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_craftitem("extinguisher:foam_ingredient_1", {
|
||||
description = "Foam Ingredient",
|
||||
inventory_image = "extinguisher_essence_1.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("extinguisher:foam_ingredient_2", {
|
||||
description = "Foam Ingredient",
|
||||
inventory_image = "extinguisher_essence_2.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("extinguisher:foam_bucket", {
|
||||
description = "Foam",
|
||||
inventory_image = "extinguisher_foam_bucket.png",
|
||||
})
|
||||
|
||||
if minetest.registered_items["poisonivy:climbing"] then
|
||||
minetest.register_craft({
|
||||
output = "extinguisher:foam_ingredient_1 2",
|
||||
recipe = {
|
||||
{"default:stone"},
|
||||
{"poisonivy:climbing"},
|
||||
{"default:stone"},
|
||||
},
|
||||
replacements = {{"default:stone", "default:stone"}, {"default:stone", "default:stone"}},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "extinguisher:foam_ingredient_2",
|
||||
recipe = {
|
||||
{"default:stone"},
|
||||
{"poisonivy:seedling"},
|
||||
{"default:stone"},
|
||||
},
|
||||
replacements = {{"default:stone", "default:stone"}, {"default:stone", "default:stone"}},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "extinguisher:foam_ingredient_2 3",
|
||||
recipe = {
|
||||
{"default:stone"},
|
||||
{"poisonivy:sproutling"},
|
||||
{"default:stone"},
|
||||
},
|
||||
replacements = {{"default:stone", "default:stone"}, {"default:stone", "default:stone"}},
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
mods/extinguisher/sounds/extinguisher.1.ogg
Normal file
BIN
mods/extinguisher/sounds/extinguisher.2.ogg
Normal file
BIN
mods/extinguisher/sounds/extinguisher.3.ogg
Normal file
BIN
mods/extinguisher/sounds/extinguisher_explosion.1.ogg
Normal file
BIN
mods/extinguisher/sounds/extinguisher_explosion.2.ogg
Normal file
BIN
mods/extinguisher/sounds/extinguisher_touch.1.ogg
Normal file
BIN
mods/extinguisher/sounds/extinguisher_touch.2.ogg
Normal file
BIN
mods/extinguisher/textures/extinguisher.png
Normal file
|
After Width: | Height: | Size: 308 B |
BIN
mods/extinguisher/textures/extinguisher_back.png
Normal file
|
After Width: | Height: | Size: 218 B |
BIN
mods/extinguisher/textures/extinguisher_bottom.png
Normal file
|
After Width: | Height: | Size: 212 B |
BIN
mods/extinguisher/textures/extinguisher_destroyed.png
Normal file
|
After Width: | Height: | Size: 311 B |
BIN
mods/extinguisher/textures/extinguisher_essence_1.png
Normal file
|
After Width: | Height: | Size: 377 B |
BIN
mods/extinguisher/textures/extinguisher_essence_2.png
Normal file
|
After Width: | Height: | Size: 389 B |
BIN
mods/extinguisher/textures/extinguisher_foam.png
Normal file
|
After Width: | Height: | Size: 499 B |
BIN
mods/extinguisher/textures/extinguisher_foam_bucket.png
Normal file
|
After Width: | Height: | Size: 433 B |
BIN
mods/extinguisher/textures/extinguisher_foam_normal.png
Normal file
|
After Width: | Height: | Size: 718 B |
BIN
mods/extinguisher/textures/extinguisher_front.png
Normal file
|
After Width: | Height: | Size: 247 B |
BIN
mods/extinguisher/textures/extinguisher_pipe.png
Normal file
|
After Width: | Height: | Size: 215 B |
BIN
mods/extinguisher/textures/extinguisher_shot.png
Normal file
|
After Width: | Height: | Size: 314 B |
BIN
mods/extinguisher/textures/extinguisher_top.png
Normal file
|
After Width: | Height: | Size: 172 B |