diff --git a/Credits.txt b/Credits.txt index fd9a3d7..861c66a 100644 --- a/Credits.txt +++ b/Credits.txt @@ -8,10 +8,12 @@ Lighter image created by me with Blender. Code: 3d torch code and nodebox's from Carbone, by Calinou CC0 1.0 Will be replaced with mesh torches once I figure that bit out. +Smokebomb and molotov cocktail coded by Napiophelios Inspiration: Napiophelios, from the forum, who gave me some really good ideas from the old campfire mod, which I didn't even know about. + Sound Effects: Sparker sound from BroAsis on Freesound. https://www.freesound.org/people/BroAsis/sounds/106853/ diff --git a/depends.txt b/depends.txt index d6b786c..c14f81b 100644 --- a/depends.txt +++ b/depends.txt @@ -1,2 +1,4 @@ default +farming +fire vessels diff --git a/init.lua b/init.lua index 5f1c427..4a6ee21 100644 --- a/init.lua +++ b/init.lua @@ -60,4 +60,5 @@ dofile(minetest.get_modpath('more_fire')..'/nodes.lua') dofile(minetest.get_modpath('more_fire')..'/craftitems.lua') dofile(minetest.get_modpath('more_fire')..'/crafts.lua') dofile(minetest.get_modpath('more_fire')..'/tools.lua') - +dofile(minetest.get_modpath('more_fire')..'/molotov.lua') +dofile(minetest.get_modpath('more_fire')..'/smokebomb.lua') diff --git a/lib/Vec3_1-0.lua b/lib/Vec3_1-0.lua new file mode 100644 index 0000000..85d91ae --- /dev/null +++ b/lib/Vec3_1-0.lua @@ -0,0 +1,398 @@ +local THIS_VERSION = "1.0" + +--- 3D vector class/operations. + -- + -- Note that methods can be called in either an object-oriented way: + -- v1 = Vec3(1, 2, 3) + -- v2 = v1:add({ x = 2, y = 2, z = 0 }) + -- or as simple functions: + -- Vec3.add({ x = 1, y = 2, z = 3 }, { x = 2, y = 2, z = 0 }) + -- + -- All methods that can be called on a Vec3 using ":" may be called on a table + -- using the second functional syntax, but the first parameter MUST have the + -- expected components "x", "y", and "z". If a vector is used as the second + -- paramter, it may instead be a list/array with numeric indices, like + -- { 1.0, 2.0, 3.0 } in place of { x = 1.0, y = 2.0, z = 3.0 }. + -- + -- @author prestidigitator (as registered at forum.minetest.net) + -- @copyright 2013, licensed under WTFPL + -- +local Vec3 = {} +local Vec3_meta = {} +local Vec3_inst_meta = {} + +Vec3.VERSION = THIS_VERSION + +setmetatable(Vec3, Vec3_meta) +Vec3_inst_meta.__index = Vec3 + +--- Constructs a Vec3 from three numbers. + -- + -- Call with one of: + -- Vec3.new(x, y, z) + -- Vec3(x, y, z) + -- + -- @return a new Vec3 object +local function Vec3_new(x, y, z) + local obj = { x = x or 0.0, y = y or 0.0, z = z or 0.0 } + setmetatable(obj, Vec3_inst_meta) + return obj +end +Vec3.new = Vec3_new + +--- Constructs a new copy of a Vec3. + -- + -- Call with one of: + -- vec:new_copy() + -- Vec3.new_copy(vec) + -- Vec3(vec) + -- + -- @return a new Vec3 object that is a copy of the parameter +local function Vec3_new_copy(v) + local obj = { x = v.x or v[1] or 0.0, + y = v.y or v[2] or 0.0, + z = v.z or v[3] or 0.0 } + setmetatable(obj, Vec3_inst_meta) + return obj +end +Vec3.new_copy = Vec3_new_copy + +Vec3_meta.__call = function(class, a, b, c) + if type(a) == "table" then + return Vec3.new_copy(a) + else + return Vec3.new(a, b, c) + end +end + +--- Computes the square of the length of a Vec3. + -- + -- Call with one of: + -- vec:len_sq() + -- Vec3.len_sq(vec) + -- + -- @return a number +local function Vec3_len_sq(v) + return v.x^2 + v.y^2 + v.z^2 +end +Vec3.len_sq = Vec3_len_sq + +--- Computes the length of a Vec3. + -- + -- Call with one of: + -- vec:len() + -- Vec3.len(vec) + -- + -- @return a number +local function Vec3_len(v) + return math.sqrt(v.x^2 + v.y^2 + v.z^2) +end +Vec3.len = Vec3_len + +--- Computes a unit vector pointing in the same direction as a Vec3. + -- Undefined for a zero-vector and may throw an error. + -- + -- Call with one of: + -- vec:unit() + -- Vec3.unit(vec) + -- + -- @return a new Vec3 with length 1.0 +local function Vec3_unit(v) + local len = math.sqrt(v.x^2 + v.y^2 + v.z^2) + return Vec3.new(v.x/len, v.y/len, v.z/len) +end +Vec3.unit = Vec3_unit + +--- Multiplies a Vec3 by a number. + -- + -- Call with one of: + -- vec:mul(m) + -- Vec3.mul(vec, m) + -- vec*m + -- m*vec + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_mul(v, m) + local mn = tonumber(m) + if not mn then error("Can't multiply vector by non-scalar") end + return Vec3.new(v.x*mn, v.y*mn, v.z*mn) +end +Vec3.mul = Vec3_mul +Vec3_inst_meta.__mul = function(a, b) + if type(a) == "table" then + return Vec3_mul(a, b) + else + return Vec3_mul(b, a) + end +end + +--- Divides a Vec3 by a number. + -- + -- Call with one of: + -- vec:div(m) + -- Vec3.div(vec, m) + -- vec/m + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_div(v, m) + return Vec3.new(v.x/m, v.y/m, v.z/m) +end +Vec3.div = Vec3_div +Vec3_inst_meta.__div = Vec3_div + +--- Negates a Vec3 (signs of all components are inverted). + -- + -- Call with one of: + -- vec:unm() + -- Vec3.unm(vec) + -- -vec + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_unm(v) + return Vec3.new(-v.x, -v.y, -v.z) +end +Vec3.unm = Vec3_unm +Vec3_inst_meta.__unm = Vec3_unm + +--- Adds two Vec3s or a Vec3 composed of three given components. + -- + -- Call with one of: + -- vec1:add(vec2) + -- vec1:add(x, y, z) + -- Vec3.add(vec1, vec2) + -- Vec3.add(vec1, x, y, z) + -- vec1 + vec2 + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_add(v, a, b, c) + if type(a) == "table" then + return Vec3.new(v.x + (a.x or a[1] or 0.0), + v.y + (a.y or a[2] or 0.0), + v.z + (a.z or a[3] or 0.0)) + else + return Vec3.new(v.x + a, v.y + b, v.z + c) + end +end +Vec3.add = Vec3_add + +--- Subtracts two Vec3s or a Vec3 composed of three given components. + -- + -- Call with one of: + -- vec1:sub(vec2) + -- vec1:sub(x, y, z) + -- Vec3.sub(vec1, vec2) + -- Vec3.sub(vec1, x, y, z) + -- vec1 - vec2 + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_sub(v, a, b, c) + if type(a) == "table" then + return Vec3.new(v.x - (a.x or a[1] or 0.0), + v.y - (a.y or a[2] or 0.0), + v.z - (a.z or a[3] or 0.0)) + else + return Vec3.new(v.x - a, v.y - b, v.z - c) + end +end +Vec3.sub = Vec3_sub + +--- Tests two Vec3s or a Vec3 composed of three given components for + -- exact component-wise equality. + -- + -- Call with one of: + -- vec1:eq(vec2) + -- vec1:eq(x, y, z) + -- Vec3.eq(vec1, vec2) + -- Vec3.eq(vec1, x, y, z) + -- vec1 == vec2 + -- vec1 ~= vec2 + -- Note that because of built-in Lua logic "==" and "~=" work ONLY if + -- vec1 and vec2 are actually Vec3s (not tables). + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_eq(v, a, b, c) + if type(a) == "table" then + return v.x == (a.x or a[1] or 0.0) and + v.y == (a.y or a[2] or 0.0) and + v.z == (a.z or a[3] or 0.0) + else + return v.x == a and v.y == b and v.z == c + end +end +Vec3.eq = Vec3_eq + +--- Takes the dot product of a Vec3 and a Vec3s or a Vec3 composed of + -- three given components. + -- + -- Call with one of: + -- vec1:dot(vec2) + -- vec1:dot(x, y, z) + -- Vec3.dot(vec1, vec2) + -- Vec3.dot(vec1, x, y, z) + -- + -- @return a number +local function Vec3_dot(v, a, b, c) + if type(a) == "table" then + return v.x * (a.x or a[1] or 0.0) + + v.y * (a.y or a[2] or 0.0) + + v.z * (a.z or a[3] or 0.0) + else + return v.x * a + v.y * b + v.z * c + end +end +Vec3.dot = Vec3_dot + +--- Takes the cross product of a Vec3 and a Vec3s or a Vec3 composed of + -- three given components. + -- + -- Call with one of: + -- vec1:cross(vec2) + -- vec1:cross(x, y, z) + -- Vec3.cross(vec1, vec2) + -- Vec3.cross(vec1, x, y, z) + -- + -- @return a new Vec3 with the result of the operation +local function Vec3_cross(v, a, b, c) + local ux, uy, uz + if type(a) == "table" then + ux = a.x or a[1] or 0.0 + uy = a.y or a[2] or 0.0 + uz = a.z or a[3] or 0.0 + else + ux = a or 0.0 + uy = b or 0.0 + uz = c or 0.0 + end + + return Vec3.new(v.y*uz - v.z*uy, v.z*ux - v.x*uz, v.x*uy - v.y*ux) +end +Vec3.cross = Vec3_cross + +--- Rotates this (the first) vector around the second vector by the + -- given angle. + -- + -- Call with one of: + -- vec:rot_around(axis, angle) + -- Vec3.rot_around(vec, axis, angle) + -- + -- @param axis + -- The axis about which to rotate. + -- @param angle + -- The angle by which to rotate this vector, in radians. + -- @return + -- a new Vec3 with the result of the operation. +local function Vec3_rot_around(v, axis, angle) + local uaxis = Vec3.new_copy(axis):unit() + + local alen = uaxis:dotvec(v) + local avec = uaxis:mul(alen) + + local pvec = Vec3.subvec(v, avec) + local rvec = uaxis:crossvec(v) + + local v1 = pvec:mul(math.cos(angle)) + local v2 = rvec:mul(math.sin(angle)) + + return avec:addvec(v1):addvec(v2) +end +Vec3.rot_around = Vec3_rot_around + +--- Adds two Vec3s. Optimized for pure Vec3/table operations by removing + -- type checking and conditionals. If called with Vec3-likes table(s), + -- ensure all expected components "x", "y", and "z" exist. + -- + -- Call with one of: + -- vec1:addvec(vec2) + -- Vec3.addvec(vec1, vec2) + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_addvec(v1, v2) + return Vec3.new(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z) +end +Vec3.addvec = Vec3_addvec +Vec3_inst_meta.__add = Vec3_addvec + +--- Subtracts two Vec3s. Optimized for pure Vec3/table operations by + -- removing type checking and conditionals. If called with Vec3-likes + -- table(s), ensure all expected components "x", "y", and "z" exist. + -- + -- Call with one of: + -- vec1:subvec(vec2) + -- Vec3.subvec(vec1, vec2) + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_subvec(v1, v2) + return Vec3.new(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z) +end +Vec3.subvec = Vec3_subvec +Vec3_inst_meta.__sub = Vec3_subvec + +--- Tests two Vec3s for exact component-wise equality. Optimized for pure + -- Vec3/table operations by removing type checking and conditionals. + -- If called with Vec3-likes table(s), ensure all expected components + -- "x", "y", and "z" exist. + -- + -- Call with one of: + -- vec1:eqvec(vec2) + -- Vec3.eqvec(vec1, vec2) + -- + -- @return a new Vec3 object with the result of the operation +local function Vec3_eqvec(v1, v2) + return v1.x == v2.x and v1.y == v2.y and v1.z == v2.z +end +Vec3.eqvec = Vec3_eqvec +Vec3_inst_meta.__eq = Vec3_eqvec + +--- Takes the dot product of two Vec3s. Optimized for pure Vec3/table + -- operations by removing type checking and conditionals. If called + -- with Vec3-likes table(s), ensure all expected components "x", "y", + -- and "z" exist. + -- + -- Call with one of: + -- vec1:dotvec(vec2) + -- Vec3.dotvec(vec1, vec2) + -- + -- @return a number +local function Vec3_dotvec(v1, v2) + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z +end +Vec3.dotvec = Vec3_dotvec + +--- Takes the cross product of two Vec3s. Optimized for pure Vec3/table + -- operations by removing type checking and conditionals. If called + -- with Vec3-likes table(s), ensure all expected components "x", "y", + -- and "z" exist. + -- + -- Call with one of: + -- vec1:crossvec(vec2) + -- Vec3.crossvec(vec1, vec2) + -- + -- @return a new Vec3 with the result of the operation +local function Vec3_crossvec(v1, v2) + return Vec3.new(v1.y*v2.z - v1.z*v2.y, + v1.z*v2.x - v1.x*v2.z, + v1.x*v2.y - v1.y*v2.x) +end +Vec3.crossvec = Vec3_crossvec + +--- Converts Vec3 to a string with format "(x,y,z)". + -- + -- Call with one of: + -- vec:tostring() + -- Vec3.tostring(vec) + -- tostring(vec) + -- + -- @return a string +local function Vec3_tostring(v) + return "(".. + (v.x or v[1] or "0") + ..",".. + (v.y or v[2] or "0") + ..",".. + (v.z or v[3] or "0") + ..")" +end +Vec3.tostring = Vec3_tostring +Vec3_inst_meta.__tostring = Vec3_tostring + +return Vec3 diff --git a/molotov.lua b/molotov.lua new file mode 100644 index 0000000..f265eab --- /dev/null +++ b/molotov.lua @@ -0,0 +1,328 @@ + --Molotov Cocktail_[rev002] + --base code is from throwing enhanced and potions mods + + local MOD_NAME = minetest.get_current_modname() + local MOD_PATH = minetest.get_modpath(MOD_NAME) + local Vec3 = dofile(MOD_PATH.."/lib/Vec3_1-0.lua") + +more_fire = {} + +minetest.register_craftitem("more_fire:molotov_cocktail", { + description = "Molotov Cocktail", + inventory_image = "more_fire_molotov_cocktail.png", + on_place = function(itemstack, user, pointed_thing) + itemstack:take_item() + minetest.sound_play("more_fire_shatter", {gain = 1.0}) + n = minetest.env:get_node(pointed_thing) +if pointed_thing.type == "node" then +minetest.env:add_node(pointed_thing.above, {name="more_fire:napalm"}) +minetest.sound_play("more_fire_ignite", {pos,pos}) +end + --Shattered glass Particles + minetest.add_particlespawner(40, 0.1, + pointed_thing.above, pointed_thing.above, + {x=2, y=0.2, z=2}, {x=-2, y=0.5, z=-2}, + {x=0, y=-6, z=0}, {x=0, y=-10, z=0}, + 0.5, 2, + 0.2, 5, + true, "more_fire_shatter.png") + --fire ember particles + minetest.add_particlespawner(100, 0.1, + pointed_thing.above, pointed_thing.above, + {x=-2, y=0.5, z=-2}, {x=2, y=0.5, z=2}, + {x=0, y=-10, z=0}, {x=0, y=-6, z=0}, + 2, 3, + 0.25, 0.5, + true, "more_fire_spark.png") + local dir = Vec3(user:get_look_dir()) *20 + minetest.add_particle( + {x=user:getpos().x, y=user:getpos().y+1.5, z=user:getpos().z}, {x=dir.x, y=dir.y, z=dir.z}, {x=0, y=-10, z=0}, 0.2, + 6, false, "more_fire_molotov_cocktail.png") + return itemstack + end, +}) + +local function throw_cocktail(item, player) + local playerpos = player:getpos() + local obj = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.625,z=playerpos.z}, "more_fire:molotov_entity") + local dir = player:get_look_dir() + obj:setvelocity({x=dir.x*30, y=dir.y*30, z=dir.z*30}) + obj:setacceleration({x=dir.x*-3, y=-dir.y^8*80-10, z=dir.z*-3}) + if not minetest.setting_getbool("creative_mode") then + item:take_item() + end + return item +end + +local radius = 5.0 + +local function add_effects(pos, radius) + minetest.add_particlespawner({ + amount = 10, + time = 0.2, + minpos = vector.subtract(pos, radius / 2), + maxpos = vector.add(pos, radius / 2), + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=2, y=-4, z=2}, + minacc = {x=0, y=-4, z=0}, + --~ maxacc = {x=-20, y=-50, z=-50}, + minexptime = 1, + maxexptime = 1.5, + minsize = 1, + maxsize = 2, + texture = "more_fire_spark.png", + }) + minetest.add_particlespawner({ + amount = 10, + time = 0.2, + minpos = vector.subtract(pos, radius / 2), + maxpos = vector.add(pos, radius / 2), + minvel = {x=-1.25, y=-1.25, z=-1.25}, + maxvel = {x=0.5, y=-4, z=0.5}, + minacc = {x=1.25, y=-1.25, z=1.25}, + --~ maxacc = {x=-20, y=-50, z=-50}, + minexptime =1, + maxexptime = 1.5, + minsize = 1, + maxsize = 2, + texture = "more_fire_spark.png", + }) +end + +local function napalm(pos) + minetest.sound_play("more_fire_ignite", {pos=pos, gain=1}) + minetest.set_node(pos, {name="more_fire:napalm"}) + minetest.get_node_timer(pos):start(5.0) + add_effects(pos, radius) +end + +local MORE_FIRE_MOLOTOV_ENTITY = { + timer=0, + collisionbox = {0,0,0,0,0,0}, + physical = false, + textures = {"more_fire_molotov_cocktail.png"}, + lastpos={}, +} + +MORE_FIRE_MOLOTOV_ENTITY.on_step = function(self, dtime) + self.timer = self.timer + dtime + local pos = self.object:getpos() + local node = minetest.get_node(pos) +minetest.add_particlespawner({ + amount = 10, + time = 0.5, + minpos = pos, + maxpos = pos, + minvel = {x=-0, y=0, z=-0.5}, + maxvel = {x=0, y=0, z=-0.75}, + minacc = vector.new(), + maxacc = vector.new(), + minexptime = 0.5, + maxexptime = 1, + minsize = 0.25, + maxsize = 0.5, + texture = "more_fire_smoke.png", + }) + minetest.add_particlespawner({ + amount = 100, + time = 0.25, + minpos = pos, + maxpos = pos, + minvel = {x=-0, y=0, z=-0.5}, + maxvel = {x=0, y=0, z=-0.75}, + minacc = {x=0, y=0, z=-0.75}, + maxacc = {x=-0, y=0, z=-0.5}, + minexptime = 0.25, + maxexptime = 0.5, + minsize = 0.5, + maxsize = 0.75, + texture = "more_fire_spark.png", + }) + if self.timer>0.2 then + local objs = minetest.env:get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1) + for k, obj in pairs(objs) do + if obj:get_luaentity() ~= nil then + if obj:get_luaentity().name ~= "more_fire:molotov_entity" and obj:get_luaentity().name ~= "__builtin:item" then + if self.node ~= "" then + minetest.sound_play("more_fire_shatter", {gain = 1.0}) + for dx=-3,3 do + for dy=-3,3 do + for dz=-3,3 do + local p = {x=pos.x+dx, y=pos.y+dy, z=pos.z+dz} + local n = minetest.env:get_node(pos).name + if minetest.registered_nodes[n].groups.flammable or math.random(1, 100) <= 20 then + minetest.sound_play("more_fire_ignite", {pos = self.lastpos}) + minetest.env:set_node(p, {name="more_fire:napalm"}) + else + --minetest.env:remove_node(p) + minetest.sound_play("more_fire_ignite", {pos = self.lastpos}) + minetest.env:set_node(p, {name="fire:basic_flame"}) + end + end + end + end + end + self.object:remove() + end + else + if self.node ~= "" then + minetest.sound_play("more_fire_shatter", {gain = 1.0}) + for dx=-2,2 do + for dy=-2,2 do + for dz=-2,2 do + local p = {x=pos.x+dx, y=pos.y+dy, z=pos.z+dz} + local n = minetest.env:get_node(pos).name + if minetest.registered_nodes[n].groups.flammable or math.random(1, 100) <= 20 then + minetest.sound_play("more_fire_ignite", {pos = self.lastpos}) + minetest.env:set_node(p, {name="more_fire:napalm"}) + else + --minetest.env:remove_node(p) + minetest.sound_play("more_fire_ignite", {pos = self.lastpos}) + minetest.env:set_node(p, {name="fire:basic_flame"}) + end + end + end + end + end + self.object:remove() + end + end + end + + if self.lastpos.x~=nil then + if node.name ~= "air" then + if self.node ~= "" then + minetest.sound_play("more_fire_shatter", {gain = 1.0}) + for dx=-1,1 do + for dy=-1,1 do + for dz=-1,1 do + local p = {x=pos.x+dx, y=pos.y+dy, z=pos.z+dz} + local n = minetest.env:get_node(pos).name + if minetest.registered_nodes[n].groups.flammable or math.random(1, 100) <= 20 then + minetest.sound_play("more_fire_ignite", {pos = self.lastpos}) + minetest.env:set_node(p, {name="more_fire:napalm"}) + else + --minetest.env:remove_node(p) + minetest.sound_play("more_fire_ignite", {pos = self.lastpos}) + minetest.env:set_node(p, {name="fire:basic_flame"}) + end + end + end + end + end + self.object:remove() + napalm(self.lastpos) + end + end + self.lastpos={x=pos.x, y=pos.y, z=pos.z} +end + +minetest.register_entity("more_fire:molotov_entity", MORE_FIRE_MOLOTOV_ENTITY) + +minetest.override_item("more_fire:molotov_cocktail", {on_use = throw_cocktail}) + +minetest.register_node("more_fire:napalm", { + drawtype = "firelike", + tiles = {{ + name="fire_basic_flame_animated.png", + animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=1}, + }}, + inventory_image = "fire_basic_flame.png", + light_source = 14, + groups = {igniter=1,dig_immediate=3, not_in_creative_inventory =1, not_in_craft_guide=1}, + drop = '', + walkable = false, + buildable_to = true, + damage_per_second = 4, +}) + +minetest.register_abm({ + nodenames={"more_fire:napalm"}, + neighbors={"air"}, + interval = 1, + chance = 1, + action = function(pos,node,active_object_count,active_object_count_wider) + minetest.add_particlespawner(200, 3, + pos, pos, + {x=2, y=-0.2, z=2}, {x=-2, y=-0.5, z=-2}, + {x=0, y=-6, z=0}, {x=0, y=-10, z=0}, + 2, 6, + 0.05, 0.5, + false, "more_fire_spark.png") + minetest.add_particlespawner(20, 2, + pos, pos, + {x=-2, y=2, z=-2}, {x=1, y=3, z=1}, + {x=0, y=6, z=0}, {x=0, y=2, z=0}, + 1, 3, + 3, 5, + false, "more_fire_smoke.png") + minetest.add_particlespawner(10, 4, + pos, pos, + {x=0, y= 3, z=0}, {x=0, y=5, z=0}, + {x=0.1, y=0.5, z=-0.1}, {x=-0.2, y=2, z=0.2}, + 1, 3, + 1, 3, + false, "more_fire_smoke.png") +local r = 0-- Radius for destroying + for x = pos.x-r, pos.x+r, 1 do + for y = pos.y-r, pos.y+r, 1 do + for z = pos.z-r, pos.z+r, 1 do + local cpos = {x=x,y=y,z=z} + if minetest.env:get_node(cpos).name == "more_fire:napalm" then + minetest.env:set_node(cpos,{name="fire:basic_flame"}) + end + if math.random(0,1) == 1 + or minetest.env:get_node(cpos).name == "more_fire:napalm" + then + minetest.env:remove_node(cpos) + end + end + end + end + end, +}) + +minetest.register_abm({ + nodenames={"fire:basic_flame"}, + neighbors={"air"}, + interval = 1, + chance = 2, + action = function(pos, node) + if + minetest.get_node({x=pos.x, y=pos.y+1.0, z=pos.z}).name == "air" and + minetest.get_node({x=pos.x, y=pos.y+2.0, z=pos.z}).name == "air" + then + minetest.add_particlespawner(30, 2, + pos, pos, + {x=-2, y=2, z=-2}, {x=1, y=3, z=1}, + {x=0, y=6, z=0}, {x=0, y=2, z=0}, + 1, 3, + 10, 20, + false, "more_fire_smoke.png") + minetest.add_particlespawner(15, 4, + pos, pos, + {x=0, y= 3, z=0}, {x=0, y=5, z=0}, + {x=0.1, y=0.5, z=-0.1}, {x=-0.2, y=2, z=0.2}, + 1, 3, + 5, 10, + false, "more_fire_smoke.png") + end + end +}) + + --crafting recipes + minetest.register_craft( { +output = 'more_fire:molotov_cocktail', +recipe = { +{'farming:cotton'}, +{'more_fire:oil'}, +{'vessels:glass_bottle'}, +} +}) + +-- fuel recipes +minetest.register_craft({ + type = 'fuel', + recipe = 'more_fire:molotov_cocktail', + burntime = 5, +}) \ No newline at end of file diff --git a/smokebomb.lua b/smokebomb.lua new file mode 100644 index 0000000..1ce7eee --- /dev/null +++ b/smokebomb.lua @@ -0,0 +1,252 @@ +--Smoke Bomb_[rev001] +--base code is from throwing enhanced and potions mods + + local MOD_NAME = minetest.get_current_modname() + local MOD_PATH = minetest.get_modpath(MOD_NAME) + local Vec3 = dofile(MOD_PATH.."/lib/Vec3_1-0.lua") + +more_fire = {} + +minetest.register_craftitem("more_fire:smokebomb", { + description = "Smoke Bomb", + inventory_image = "more_fire_smokebomb.png", +on_place = function(itemstack, user, pointed_thing) + itemstack:take_item() + minetest.sound_play("more_fire_shatter", {gain = 1.0}) + --Shattered glass Particles + minetest.add_particlespawner(40, 0.1, + pointed_thing.above, pointed_thing.above, + {x=2, y=0.2, z=2}, {x=-2, y=0.5, z=-2}, + {x=0, y=-6, z=0}, {x=0, y=-10, z=0}, + 0.5, 2, + 0.2, 5, + true, "more_fire_shatter.png") + --smoke particles + minetest.add_particlespawner(400, 0.1, + pointed_thing.above, pointed_thing.above, + {x=2, y=0.2, z=2}, {x=-2, y=0.5, z=-2}, + {x=0, y=-6, z=0}, {x=0, y=-10, z=0}, + 5, 2, + 20, 5, + true, "more_fire_smoke.png") + --more smoke particles + minetest.add_particlespawner(600, 1, + pointed_thing.above, pointed_thing.above, + {x=10, y= 3, z=10}, {x=-10, y= 3, z=-10}, + {x=2, y=2, z=2}, {x=-2, y=1, z=-2}, + 2, 3, + 20, 2, + true, "more_fire_smoke.png") + --even more smoke particles + minetest.add_particlespawner(400, 1, + pointed_thing.above, pointed_thing.above, + {x=0.2, y=0.2, z=0.2}, {x=-0.2, y=0.5, z=-0.2}, + {x=10, y= 2, z=10}, {x=-10, y= 1, z=-10}, + 2, 3, + 20, 2, + true, "more_fire_smoke.png") + local dir = Vec3(user:get_look_dir()) *20 + minetest.add_particle( + {x=user:getpos().x, y=user:getpos().y+1.5, z=user:getpos().z}, {x=dir.x, y=dir.y, z=dir.z}, {x=0, y=-10, z=0}, 0.2, + 6, false, "more_fire_smokebomb.png") + return itemstack + end, + }) + + local function throw_smokebomb(item, player) + local playerpos = player:getpos() + local obj = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.625,z=playerpos.z}, "more_fire:smokebomb_entity") + local dir = player:get_look_dir() + obj:setvelocity({x=dir.x*30, y=dir.y*30, z=dir.z*30}) + obj:setacceleration({x=dir.x*-3, y=-dir.y^8*80-10, z=dir.z*-3}) + if not minetest.setting_getbool("creative_mode") then + item:take_item() + end + return item +end + + local radius = 5 + +local function add_effects(pos, radius) + minetest.add_particlespawner({ + amount = 200, + time = 0.1, + minpos = vector.subtract(pos, radius / 3), + maxpos = vector.add(pos, radius / 3), + minvel = {x=2, y=0.2, z=2}, + maxvel = {x=-2, y=-0.5, z=-2}, + minacc = {x=1, y=-6, z=1}, + maxacc = {x=1, y=-10, z=1}, + minexptime = 1, + maxexptime = 5, + minsize = 10, + maxsize = 20, + texture = "more_fire_smoke.png", + }) + minetest.add_particlespawner({ + amount = 100, + time = 2, + minpos = vector.subtract(pos, radius / 2), + maxpos = vector.add(pos, radius / 2), + minvel = {x=0.2, y=0.2, z=0.2}, + maxvel = {x=-0.2, y=0.5, z=-0.2}, + minacc = {x=10, y= 2, z=10}, + maxacc = {x=-10, y= 1, z=-10}, + minexptime =1, + maxexptime = 3, + minsize = 5, + maxsize = 15, + texture = "more_fire_smoke.png", + }) +end + +local function plume(pos) + minetest.set_node(pos, {name="more_fire:plume"}) + minetest.get_node_timer(pos):start(3.0) + add_effects(pos, radius) +end + +local MORE_FIRE_SMOKEBOMB_ENTITY = { + timer=0, + collisionbox = {0,0,0,0,0,0}, + physical = false, + textures = {"more_fire_smokebomb.png"}, + lastpos={}, +} + +MORE_FIRE_SMOKEBOMB_ENTITY.on_step = function(self, dtime) + self.timer = self.timer + dtime + local pos = self.object:getpos() + local node = minetest.get_node(pos) +minetest.add_particlespawner({ + amount = 10, + time = 0.5, + minpos = pos, + maxpos = pos, + minvel = {x=-0, y=0, z=-0.5}, + maxvel = {x=0, y=0, z=-0.75}, + minacc = vector.new(), + maxacc = vector.new(), + minexptime = 0.5, + maxexptime = 1, + minsize = 0.25, + maxsize = 0.5, + texture = "more_fire_smoke.png", + }) + minetest.add_particlespawner({ + amount = 10, + time = 0.25, + minpos = pos, + maxpos = pos, + minvel = {x=-0, y=0, z=-0.5}, + maxvel = {x=0, y=0, z=-0.75}, + minacc = {x=0, y=0, z=-0.75}, + maxacc = {x=-0, y=0, z=-0.5}, + minexptime = 0.25, + maxexptime = 0.5, + minsize = 0.5, + maxsize = 0.75, + texture = "more_fire_smoke.png", + }) + if self.timer>0.2 then + local objs = minetest.env:get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1) + for k, obj in pairs(objs) do + if obj:get_luaentity() ~= nil then + if obj:get_luaentity().name ~= "more_fire:smokebomb_entity" and obj:get_luaentity().name ~= "__builtin:item" then + if self.node ~= "" then + minetest.sound_play("more_fire_shatter", {gain = 1.0}) + local damage = 1 + obj:punch(self.object, 1.0, { + full_punch_interval=1.0, + damage_groups={fleshy=damage}, + }, nil) + self.object:remove() + end + end + end + end + if self.lastpos.x~=nil then + if node.name ~= "air" then + self.object:remove() + plume(self.lastpos) + end + end + self.lastpos={x=pos.x, y=pos.y, z=pos.z} +end +end + +minetest.register_entity("more_fire:smokebomb_entity", MORE_FIRE_SMOKEBOMB_ENTITY) + +minetest.override_item("more_fire:smokebomb", {on_use = throw_smokebomb}) + +minetest.register_node("more_fire:plume", { +drawtype = "plantlike", +description = "Smoke Plume", + tiles = {{ + name="more_fire_smoke_animated.png", + animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=1}, + }}, + inventory_image = "more_fire_smoke.png", + light_source = 8, + groups = {dig_immediate=3, not_in_creative_inventory =1, not_in_craft_guide=1}, + drop = '', + walkable = false, + buildable_to = true, + on_timer = function(pos, elapsed) + minetest.remove_node(pos) + end, + damage_per_second = 1, +}) + +minetest.register_abm({ + nodenames={"more_fire:plume"}, + neighbors={"air"}, + interval = 1, + chance = 1, + action = function(pos, node) + if + minetest.get_node({x=pos.x, y=pos.y+1.0, z=pos.z}).name == "air" and + minetest.get_node({x=pos.x, y=pos.y+2.0, z=pos.z}).name == "air" + then + minetest.add_particlespawner(400, 3, + pos, pos, + {x=2, y=-0.2, z=2}, {x=-2, y=-0.5, z=-2}, + {x=0, y=-6, z=0}, {x=0, y=-10, z=0}, + 2, 6, + 0.05, 0.5, + false, "more_fire_smoke.png") + minetest.add_particlespawner(50, 2, + pos, pos, + {x=-2, y=0.5, z=-2}, {x=2, y=0.5, z=2}, + {x=0, y=0.04, z=0}, {x=0, y=0.01, z=0}, + 1, 3, + 3, 5, + false, "more_fire_smoke.png") + minetest.add_particlespawner({ + amount = 400, + time = 2, + minpos = vector.subtract(pos, radius / 2), + maxpos = vector.add(pos, radius / 2), + minvel = {x=0.2, y=2, z=0.2}, + maxvel = {x=-0.2, y=2, z=-0.2}, + minacc = {x=10, y= 2, z=10}, + maxacc = {x=-10, y= 1, z=-10}, + minexptime =1, + maxexptime = 3, + minsize = 5, + maxsize = 15, + texture = "more_fire_smoke.png", + }) + end + end +}) + + --crafting recipes + minetest.register_craft( { +output = 'more_fire:smoke_bomb', +recipe = { +{'more_fire:flintstone'}, +{'more_fire:charcoal'}, +{'vessels:glass_bottle'}, +} +}) \ No newline at end of file diff --git a/sounds/potions_ignite.0.ogg b/sounds/potions_ignite.0.ogg new file mode 100644 index 0000000..73494f2 Binary files /dev/null and b/sounds/potions_ignite.0.ogg differ diff --git a/sounds/potions_shatter.0.ogg b/sounds/potions_shatter.0.ogg new file mode 100644 index 0000000..b6cc9e8 Binary files /dev/null and b/sounds/potions_shatter.0.ogg differ diff --git a/sounds/potions_shatter.1.ogg b/sounds/potions_shatter.1.ogg new file mode 100644 index 0000000..2577f40 Binary files /dev/null and b/sounds/potions_shatter.1.ogg differ diff --git a/textures/more_fire_glass.png b/textures/more_fire_glass.png new file mode 100644 index 0000000..a80b8fc Binary files /dev/null and b/textures/more_fire_glass.png differ diff --git a/textures/more_fire_molotov_cocktail.png b/textures/more_fire_molotov_cocktail.png new file mode 100644 index 0000000..fc99a83 Binary files /dev/null and b/textures/more_fire_molotov_cocktail.png differ diff --git a/textures/more_fire_shatter.png b/textures/more_fire_shatter.png new file mode 100644 index 0000000..41f6ec0 Binary files /dev/null and b/textures/more_fire_shatter.png differ diff --git a/textures/more_fire_smoke.png b/textures/more_fire_smoke.png index 3094060..b4b97ba 100644 Binary files a/textures/more_fire_smoke.png and b/textures/more_fire_smoke.png differ diff --git a/textures/more_fire_smoke_animated.png b/textures/more_fire_smoke_animated.png new file mode 100644 index 0000000..38af01f Binary files /dev/null and b/textures/more_fire_smoke_animated.png differ diff --git a/textures/more_fire_smoke_old.png b/textures/more_fire_smoke_old.png new file mode 100644 index 0000000..3094060 Binary files /dev/null and b/textures/more_fire_smoke_old.png differ diff --git a/textures/more_fire_smokebomb.png b/textures/more_fire_smokebomb.png new file mode 100644 index 0000000..fca43e1 Binary files /dev/null and b/textures/more_fire_smokebomb.png differ diff --git a/textures/more_fire_spark.png b/textures/more_fire_spark.png new file mode 100644 index 0000000..a575518 Binary files /dev/null and b/textures/more_fire_spark.png differ