local fireworkz = {} local minetest = _G.minetest local math = _G.math --Variables local modname = "fireworkz" local modpath = minetest.get_modpath(modname) local S = minetest.get_translator(minetest.get_current_modname()) --Settings fireworkz.settings = {} local settings = Settings(modpath .. "/fireworkz.conf") fireworkz.settings.igniter = settings:get("igniter") or "default:torch" fireworkz.settings.ignition_time = tonumber(settings:get("ignition_time")) or 3 fireworkz.settings.max_hear_distance_fuse = tonumber(settings:get("max_hear_distance_fuse")) or 5 fireworkz.settings.max_hear_distance_launch = tonumber(settings:get("max_hear_distance_launch")) or 13 fireworkz.settings.max_hear_distance_bang = tonumber(settings:get("max_hear_distance_bang")) or 90 local color_map = { blue = "cyan", green = "lime", } local figure_map = { default = "yellow", ball = "magenta", love = "red", hi = "blue" } local figure_ingredient_map = { --[[ 1 2 3 4 x 5 6 x 7 ]] default = {false, true}, ball = {true, true, true, true, true, true, true}, love = {true, false, true, true, true}, hi = {true, false, false, true, true, true, true} } local color_variants = {"red", "green", "blue", "yellow", "white"} local figure_variants = {"default", "ball", "love", "hi"} local variant_list = { {color = "blue_white_red", figure = "ball_default_love", desc = S("Blue-White-Love"), rdt = { {color = "blue", figure = "ball"}, {color = "yellow", figure = "default"}, {color = "red", figure = "love"}, }, recipe = { output = "fireworkz:rocket_ball_default_love_blue_white_red", recipe = { {"dye:blue", "dye:white", "dye:red"}, {"default:paper", "tnt:gunpowder", "default:paper"}, {"default:paper", "default:paper", "default:paper"} }, }, }, {color = "green_yellow_red", figure = "ball_default_love", desc = S("Green-Yellow-Love"), rdt = { {color = "green", figure = "ball"}, {color = "yellow", figure = "default"}, {color = "red", figure = "love"}, }, recipe = { output = "fireworkz:rocket_ball_default_love_green_yellow_red", recipe = { {"dye:green", "dye:yellow", "dye:red"}, {"default:paper", "tnt:gunpowder", "default:paper"}, {"default:paper", "default:paper", "default:paper"} }, } }, } --Functions local figures = {} function figures.line(t, pos, off, rep, vel) if not t then t = {} end local v = {x = pos.x, y = pos.y, z = pos.z} for i = 0, rep, 1 do local w = {x = v.x, y = v.y, z = v.z, v = vel} t[#t+1] = w v.x = v.x+off.x v.y = v.y+off.y v.z = v.z+off.z end return t end -- Figures function figures.default(r) local tab = {} for x=-r, r, 0.02 do for y=-r, r, 0.02 do for z=-r, r, 0.02 do if x*x + y*y + z*z <= r*r then local v = math.random(21,35) --velocity local xrand = math.random(-5, 5) * 0.001 local yrand = math.random(-5, 5) * 0.001 local zrand = math.random(-5, 5) * 0.001 tab[#tab+1] = {x=x+xrand, y=y+yrand, z=z+zrand, v=v} end end end end return tab, 2, 4 end function figures.ball(r) local tab = {} for x= -r, r, 0.01 do for z= -r, r, 0.01 do local y = math.sqrt(r*r-x*x-z*z) if y == y then -- y ~= NaN y = math.floor(y*100)/100 tab[#tab+1] = {x=x,y=y,z=z,v=43} if y~=0 then tab[#tab+1] = {x=x,y=-y,z=z,v=43} end end end end return tab, 4, 4 end function figures.love(r) local tab = { {x=0,y=0,z=0,v=60}, {x=0,y=0,z=-0.02,v=60}, {x=0.01,y=0,z=-0.03,v=60}, {x=0.02,y=0,z=-0.04,v=60}, {x=0.03,y=0,z=-0.04,v=60}, {x=0.04,y=0,z=-0.03,v=60}, {x=0.05,y=0,z=-0.02,v=60}, {x=0.05,y=0,z=-0.01,v=60}, {x=0.04,y=0,z=0,v=60}, {x=0.04,y=0,z=0.01,v=60}, {x=0.03,y=0,z=0.02,v=60}, {x=0.02,y=0,z=0.03,v=60}, {x=0.01,y=0,z=0.04,v=60}, {x=0,y=0,z=0.05,v=60}, {x=-0.01,y=0,z=0.04,v=60}, {x=-0.02,y=0,z=0.03,v=60}, {x=-0.03,y=0,z=0.02,v=60}, {x=-0.04,y=0,z=0.01,v=60}, {x=-0.04,y=0,z=0,v=60}, {x=-0.05,y=0,z=-0.01,v=60}, {x=-0.05,y=0,z=-0.02,v=60}, {x=-0.04,y=0,z=-0.03,v=60}, {x=-0.03,y=0,z=-0.04,v=60}, {x=-0.02,y=0,z=-0.04,v=60}, {x=-0.01,y=0,z=-0.03,v=60}, } return tab, 7, 7 end function figures.hi(r) -- x -- x x -- x -- x x -- 0 xxxx x -- x x x -- x x x -- x x x -- x x x -- -- 3210123 local tab = { {x=0.01,y=0,z=-0.00,v=60}, {x=0.02,y=0,z=-0.00,v=60}, {x=-0.03,y=0,z=0.03,v=60} } figures.line(tab, {x=0.03,y=0,z=-0.04}, {x=0,y=0,z=0.01}, 8, 60) figures.line(tab, {x=-0.03, y=0, z=0.01}, {x=0,y=0,z=-0.01}, 5, 60) figures.line(tab, {x=0,y=0,z=-0.01}, {x=0,y=0,z=-0.01}, 3, 60) return tab, 7, 7 end -- Activate fireworks local function partcl_gen(pos, tab, size_min, size_max, color) for _,i in pairs(tab) do minetest.add_particle({ pos = {x=pos.x, y=pos.y, z=pos.z}, velocity = {x= i.x*i.v, y= i.y*i.v, z= i.z*i.v}, acceleration = {x=0, y=-1.5, z=0}, expirationtime = 3, size = math.random(size_min, size_max), --collisiondetection = true, --collision_removal = false, vertical = false, animation = {type="vertical_frames", aspect_w=9, aspect_h=9, length = 3.5,}, glow = 30, texture = "anim_white_star.png^[multiply:"..(color_map[color] or color), }) end end -- Entity Definition local rocket = { physical = true, --collides with things wield_image = "rocket_default.png", collisionbox = {0, -0.5 ,0 ,0 ,0.5 ,0}, visual = "sprite", textures = {"rocket_default.png"}, timer = 0, rocket_firetime = 0, rocket_flytime = 0, rdt = {} -- rocket data table } --Entity Registration minetest.register_entity("fireworkz:rocket", rocket) function rocket:on_activate(staticdata) minetest.sound_play("fireworkz_rocket", {pos=self.object:getpos(), max_hear_distance = fireworkz.settings.max_hear_distance_launch, gain = 1,}) self.rocket_flytime = math.random(13,15)/10 self.object:setvelocity({x=0, y=9, z=0}) self.object:setacceleration({x= math.random(-5, 5), y= 33, z= math.random(-5, 5)}) end -- Called periodically function rocket:on_step(dtime) self.timer = self.timer + dtime self.rocket_firetime = self.rocket_firetime + dtime if self.rocket_firetime > 0.1 then local pos = self.object:getpos() self.rocket_firetime = 0 local xrand = math.random(-15, 15) / 10 minetest.add_particle({ pos = {x=pos.x, y=pos.y - 0.4, z=pos.z}, velocity = {x=xrand, y=-3, z=xrand}, acceleration = {x=0, y=0, z=0}, expirationtime = 1.5, size = 3, collisiondetection = true, vertical = false, animation = {type="vertical_frames", aspect_w=9, aspect_h=9, length = 1.6,}, glow = 10, texture = "anim_white_star.png", }) end if self.timer > self.rocket_flytime then if #self.rdt > 0 then minetest.sound_play("fireworkz_bang", {pos= self.object:get_pos(), max_hear_distance = fireworkz.settings.max_hear_distance_bang, gain = 3,}) for _, i in pairs(self.rdt) do local pos = self.object:getpos() if figures[i.figure] then local t, min, max = figures[i.figure](0.1) partcl_gen(pos, t, min, max, i.color) end end end self.object:remove() end end --Nodes local function register_fireworkz(color, figure, desc, rdt, recipe) local figure_desc if not desc then desc = S(color:sub(1,1):upper()..color:sub(2)) end if figure == "ball_default_love" then figure_desc = S("Love Ball") else figure_desc = S(figure:sub(1,1):upper()..figure:sub(2)) end inv_image = ("rocket_default_%s.png^(rocket_default.png^[multiply:%s)"):format(color, figure_map[figure] or "white") if not rdt then rdt = {{color = color, figure = figure},} end rdt.texture = inv_image minetest.register_node("fireworkz:rocket_"..figure.."_"..color, { description = S("Rocket").." (".. desc .. "|"..figure_desc..")", drawtype = "plantlike", light_source = 5, inventory_image = inv_image, tiles = {inv_image}, wield_image = inv_image, paramtype = "light", sunlight_propagates = true, walkable = false, is_ground_content = false, groups = {choppy = 3, explody = 1, firework = 1}, mesecons = { effector = { action_on = function(pos) minetest.remove_node(pos) fireworkz.launch(pos,rdt) end }, }, on_punch = function(pos) minetest.remove_node(pos) fireworkz.launch(pos,rdt) end, on_use = function(itemstack, user, pointed_thing) local pos = minetest.get_pointed_thing_position(pointed_thing, true) if pos then itemstack:take_item() fireworkz.launch(pos, rdt) end return itemstack end, on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("firework:rdt", minetest.serialize(rdt)) end, }) if recipe then if recipe == true then local m = figure_ingredient_map[figure] if m then local function r(x) if not m[x] then return "" end if m[x] == true then return "default:paper" end return m[x] end minetest.register_craft { output = "fireworkz:rocket_"..figure.."_"..color, recipe = { {r(1), r(2), r(3)}, {r(4), "tnt:gunpowder", r(5)}, {r(6), "dye:"..color, r(7)} } } end else minetest.register_craft(recipe) end end end fireworkz.launch = function(pos, rdt) local obj = minetest.add_entity(pos, "fireworkz:rocket") --activate if obj then obj:set_properties({ textures={rdt.texture} }) end local obj_ent = obj:get_luaentity() obj_ent.rdt = rdt end -- Register for _, i in pairs(color_variants) do for _, j in pairs(figure_variants) do register_fireworkz(i, j, nil, nil, true) end end for _, i in pairs(variant_list) do register_fireworkz(i.color, i.figure, i.desc, i.rdt, i.recipe) end for k,v in pairs {green = "green", orange = "yellow", red = "red", violet = "blue"} do minetest.register_alias("fireworks:"..k, "fireworkz:rocket_default_"..v) end _G.fireworkz = fireworkz