369 lines
9.6 KiB
Lua
369 lines
9.6 KiB
Lua
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
|