Initial commit
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*~
|
||||
|
32
README.md
Normal file
@ -0,0 +1,32 @@
|
||||
Nuke mod by ShadowNinja
|
||||
=======================
|
||||
|
||||
Nuke is a fast explosives mod for Minetest 0.4. It adds several variands of
|
||||
TNT, and a (very unpolished) missle. It is also configurable and usable on
|
||||
servers, due to it's optional privilege requirements.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Nuke stores it's configuration in `nuke.conf` in the world directory.
|
||||
It contains the following settings:
|
||||
|
||||
* `mese_radius` (24) - Explosion radius of mese TNT.
|
||||
* `iron_radius` (12) - Explosion radius of iron TNT.
|
||||
* `tnt_radius` (3) - Explosion radius of TNT.
|
||||
* `missle_radius` (16) - Explosion radius of the missle.
|
||||
* `missle_misfire_radius` (5) - The explosion radius of the missle when it
|
||||
misfires (hits something before reaching it's max altitude).
|
||||
* `fancy` (true) - Boolean flag enabling fancy effects like particles.
|
||||
* `unprivileged_detonation` (false) - Boolean flag for whether detonation is
|
||||
allowed without the `pyrotechnic` privilege. Allows activating nukes
|
||||
with mesecons and burning nodes (fire, lava).
|
||||
|
||||
Licenses
|
||||
--------
|
||||
|
||||
* Code: LGPLv3+ by ShadowNinja.
|
||||
* Sounds: Unknown
|
||||
* Iron and mese TNT textures: CC-BY-SA 3.0 by sfan5
|
||||
* Everything else: CC-BY-SA 4.0 by ShadowNinja
|
||||
|
85
api.lua
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
-- Create some tables first so that they're only created once
|
||||
local mesecon_def = {effector = {
|
||||
rules = {
|
||||
{x=0, y=1, z=-1},
|
||||
{x=0, y=0, z=-1},
|
||||
{x=0, y=-1, z=-1},
|
||||
{x=0, y=1, z=1},
|
||||
{x=0, y=-1, z=1},
|
||||
{x=0, y=0, z=1},
|
||||
{x=1, y=0, z=0},
|
||||
{x=1, y=1, z=0},
|
||||
{x=1, y=-1, z=0},
|
||||
{x=-1, y=1, z=0},
|
||||
{x=-1, y=-1, z=0},
|
||||
{x=-1, y=0, z=0},
|
||||
{x=0, y=-1, z=0},
|
||||
{x=0, y=1, z=0},
|
||||
{x=0, y=2, z=0},
|
||||
},
|
||||
action_on = function(pos, node)
|
||||
if nuke:can_detonate() then
|
||||
nuke:ignite(pos, node.name)
|
||||
end
|
||||
end,
|
||||
}}
|
||||
|
||||
local node_groups = {dig_immediate = 3, mesecon = 2, falling_node=1}
|
||||
local entity_groups = {punch_operable = 1}
|
||||
local sounds = default.node_sound_stone_defaults()
|
||||
local collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
|
||||
|
||||
local function on_punch(pos, node, player)
|
||||
local stack = player:get_wielded_item()
|
||||
local player_name = player:get_player_name()
|
||||
if stack:get_name() == "default:torch" and
|
||||
nuke:can_detonate(player_name) then
|
||||
nuke:ignite(pos, node.name)
|
||||
end
|
||||
end
|
||||
|
||||
function nuke:register_nuke(name, description, radius, tiles)
|
||||
minetest.register_node(name, {
|
||||
tiles = tiles,
|
||||
description = description,
|
||||
sounds = sounds,
|
||||
groups = node_groups,
|
||||
on_punch = on_punch,
|
||||
mesecons = mesecon_def,
|
||||
})
|
||||
|
||||
local e = self.entity
|
||||
minetest.register_entity(name, {
|
||||
textures = tiles,
|
||||
radius = radius,
|
||||
physical = true,
|
||||
collisionbox = collisionbox,
|
||||
visual = "cube",
|
||||
groups = entity_groups,
|
||||
health = 10,
|
||||
timer = 1,
|
||||
blinktimer = 0,
|
||||
blinkstatus = true,
|
||||
on_activate = e.on_activate,
|
||||
on_step = e.on_step,
|
||||
on_punch = e.on_punch,
|
||||
get_staticdata = e.get_staticdata,
|
||||
smoke_spawner = false,
|
||||
})
|
||||
|
||||
self.cid_names[minetest.get_content_id(name)] = name
|
||||
|
||||
if nuke:can_detonate() then
|
||||
minetest.register_abm({
|
||||
nodenames = {name},
|
||||
neighbors = {"group:igniter"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node)
|
||||
self:ignite(pos, node.name)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
|
21
config.lua
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
local worldpath = minetest.get_worldpath()
|
||||
nuke.config = Settings(worldpath..DIR_DELIM.."nuke.conf")
|
||||
|
||||
local defaults = {
|
||||
missle_radius = "16",
|
||||
missle_misfire_radius = "5",
|
||||
mese_radius = "24",
|
||||
iron_radius = "12",
|
||||
tnt_radius = "3",
|
||||
fancy = "true",
|
||||
unprivileged_detonation = "false",
|
||||
}
|
||||
|
||||
local config = nuke.config
|
||||
for k, v in pairs(defaults) do
|
||||
if config:get(k) == nil then
|
||||
config:set(k, v)
|
||||
end
|
||||
end
|
||||
|
55
definitions.lua
Normal file
@ -0,0 +1,55 @@
|
||||
|
||||
-- Convenience function
|
||||
function nuke:get_tiles(name)
|
||||
local side = name.."_side.png"
|
||||
return {name.."_top.png", name.."_bottom.png",
|
||||
side, side, side, side}
|
||||
end
|
||||
|
||||
-- Mese nuke
|
||||
minetest.register_craft({
|
||||
output = "nuke:mese 3",
|
||||
recipe = {
|
||||
{"nuke:iron", "default:mese_crystal", "nuke:iron"},
|
||||
{"default:mese_crystal", "nuke:iron", "default:mese_crystal"},
|
||||
{"nuke:iron", "default:mese_crystal", "nuke:iron"}
|
||||
}
|
||||
})
|
||||
|
||||
nuke:register_nuke("nuke:mese",
|
||||
"Mese nuke",
|
||||
tonumber(nuke.config:get("mese_radius")),
|
||||
nuke:get_tiles("nuke_mese"))
|
||||
|
||||
|
||||
-- Iron nuke
|
||||
minetest.register_craft({
|
||||
output = "nuke:iron 3",
|
||||
recipe = {
|
||||
{"nuke:tnt", "default:steel_ingot", "nuke:tnt"},
|
||||
{"default:steel_ingot", "nuke:tnt", "default:steel_ingot"},
|
||||
{"nuke:tnt", "default:steel_ingot", "nuke:tnt"}
|
||||
}
|
||||
})
|
||||
|
||||
nuke:register_nuke("nuke:iron",
|
||||
"Iron nuke",
|
||||
tonumber(nuke.config:get("iron_radius")),
|
||||
nuke:get_tiles("nuke_iron"))
|
||||
|
||||
|
||||
-- Normal TNT
|
||||
minetest.register_craft({
|
||||
output = 'nuke:tnt 3',
|
||||
recipe = {
|
||||
{"default:coal_lump", "default:sand", "default:coal_lump"},
|
||||
{"default:sand", "default:coal_lump", "default:sand"},
|
||||
{"default:coal_lump", "default:sand", "default:coal_lump"}
|
||||
}
|
||||
})
|
||||
|
||||
nuke:register_nuke("nuke:tnt",
|
||||
"TNT",
|
||||
tonumber(nuke.config:get("tnt_radius")),
|
||||
nuke:get_tiles("default_tnt"))
|
||||
|
2
depends.txt
Normal file
@ -0,0 +1,2 @@
|
||||
default
|
||||
|
91
entity.lua
Normal file
@ -0,0 +1,91 @@
|
||||
nuke.entity = {}
|
||||
|
||||
function nuke.entity:on_activate(staticdata)
|
||||
local o = self.object
|
||||
o:setvelocity({x=0, y=3, z=0})
|
||||
o:setacceleration({x=0, y=-5, z=0})
|
||||
o:settexturemod("^[brighten")
|
||||
if nuke.config:get_bool("fancy") then
|
||||
local pos = o:getpos()
|
||||
local min_pos = vector.new(pos)
|
||||
min_pos.x = min_pos.x - 0.2
|
||||
min_pos.y = min_pos.y + 0.5
|
||||
min_pos.z = min_pos.z - 0.2
|
||||
local max_pos = vector.new(pos)
|
||||
max_pos.x = max_pos.x + 0.2
|
||||
max_pos.y = max_pos.y + 0.5
|
||||
max_pos.z = max_pos.z + 0.2
|
||||
-- add_particlespawner silently fails in entity callbacks, so
|
||||
-- use minetest.after to call it later.
|
||||
minetest.after(0, function()
|
||||
if self.smoke_spawner == false then
|
||||
self.smoke_spawner = minetest.add_particlespawner({
|
||||
amount = 512,
|
||||
time = 10,
|
||||
minpos = min_pos,
|
||||
maxpos = max_pos,
|
||||
minvel = {x=-1, y=1, z=-1},
|
||||
maxvel = {x=1, y=4, z=1},
|
||||
minacc = vector.new(),
|
||||
maxacc = vector.new(),
|
||||
minexptime = 0.2,
|
||||
maxexptime = 0.4,
|
||||
minsize = 2,
|
||||
maxsize = 3,
|
||||
collisiondetection = false,
|
||||
texture = "nuke_smoke_dark.png",
|
||||
})
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function nuke.entity:on_step(dtime)
|
||||
local o = self.object
|
||||
self.timer = self.timer + dtime
|
||||
self.blinktimer = self.blinktimer + (dtime * self.timer)
|
||||
if self.blinktimer > 1 then
|
||||
self.blinktimer = self.blinktimer - 1
|
||||
o:settexturemod(self.blinkstatus and "" or "^[brighten")
|
||||
self.blinkstatus = not self.blinkstatus
|
||||
end
|
||||
|
||||
if self.timer < 10 then
|
||||
return
|
||||
end
|
||||
-- Explode
|
||||
local pos = vector.round(o:getpos())
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
-- Cause entity physics even if we are put out.
|
||||
-- This isn't very realistic but it allows for cannons.
|
||||
o:remove()
|
||||
minetest.sound_play("nuke_explode",
|
||||
{pos = pos, gain = 1.0, max_hear_distance = 16})
|
||||
nuke:entity_physics(pos, self.radius)
|
||||
if minetest.get_item_group(node.name, "puts_out_fire") <= 0 then
|
||||
nuke:explode(pos, self.radius)
|
||||
end
|
||||
if nuke.config:get_bool("fancy") then
|
||||
nuke:effects(pos, self.radius)
|
||||
end
|
||||
end
|
||||
|
||||
function nuke.entity:on_punch(hitter)
|
||||
self.object:remove()
|
||||
hitter:get_inventory():add_item("main", self.name)
|
||||
if self.smoke_spawner then
|
||||
minetest.delete_particlespawner(self.smoke_spawner)
|
||||
end
|
||||
-- For add_particlespawner hack to detect if we've been removed
|
||||
self.smoke_spawner = nil
|
||||
end
|
||||
|
||||
function nuke.entity:get_staticdata()
|
||||
if self.smoke_spawner then
|
||||
minetest.delete_particlespawner(self.smoke_spawner)
|
||||
end
|
||||
-- For add_particlespawner hack to detect if we've been removed
|
||||
self.smoke_spawner = nil
|
||||
end
|
||||
|
19
init.lua
Normal file
@ -0,0 +1,19 @@
|
||||
-- Nuke mod by ShadowNinja
|
||||
-- Based on the nuke mod by sfan5
|
||||
|
||||
nuke = {}
|
||||
nuke.cid_names = {}
|
||||
|
||||
minetest.register_privilege("pyrotechnic", {
|
||||
description = "Can detonate nukes",
|
||||
})
|
||||
|
||||
local modpath = minetest.get_modpath("nuke") .. DIR_DELIM
|
||||
|
||||
dofile(modpath .. "config.lua")
|
||||
dofile(modpath .. "entity.lua")
|
||||
dofile(modpath .. "api.lua")
|
||||
dofile(modpath .. "internal.lua")
|
||||
dofile(modpath .. "definitions.lua")
|
||||
dofile(modpath .. "missles.lua")
|
||||
|
121
internal.lua
Normal file
@ -0,0 +1,121 @@
|
||||
|
||||
local priv_set = {pyrotechnic=true}
|
||||
function nuke:can_detonate(player_name)
|
||||
if self.config:get_bool("unprivileged_detonation") or
|
||||
(player_name and minetest.check_player_privs(
|
||||
player_name, priv_set)) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function nuke:ignite(pos, name)
|
||||
minetest.dig_node(pos)
|
||||
minetest.sound_play("nuke_ignite",
|
||||
{pos = pos, gain = 1.0, max_hear_distance = 10})
|
||||
return minetest.add_entity(pos, name)
|
||||
end
|
||||
|
||||
|
||||
function nuke:calc_velocity(pos1, pos2, old_vel, power)
|
||||
local vel = vector.direction(pos1, pos2)
|
||||
vel = vector.normalize(vel)
|
||||
vel = vector.multiply(vel, power * 10)
|
||||
|
||||
-- Divide by distanve
|
||||
local dist = vector.distance(pos1, pos2)
|
||||
dist = math.max(dist, 1)
|
||||
vel = vector.divide(vel, dist)
|
||||
|
||||
-- Add old velocity
|
||||
vel = vector.add(vel, old_vel)
|
||||
return vel
|
||||
end
|
||||
|
||||
-- Entity physics
|
||||
function nuke:entity_physics(pos, radius)
|
||||
-- Make the damage radius larger than the destruction radius
|
||||
radius = radius * 2
|
||||
local objs = minetest.get_objects_inside_radius(pos, radius)
|
||||
for _, obj in pairs(objs) do
|
||||
local obj_vel = obj:getvelocity()
|
||||
local obj_pos = obj:getpos()
|
||||
local dist = vector.distance(pos, obj_pos)
|
||||
local damage = (4 / math.max(dist, 1)) * radius
|
||||
obj:set_hp(obj:get_hp() - damage)
|
||||
|
||||
-- Ignore velocity calculation for entities exactly at our
|
||||
-- position (us) and entities without velocity
|
||||
-- (non-LuaEntitySAO).
|
||||
if dist ~= 0 and obj_vel ~= nil then
|
||||
obj:setvelocity(nuke:calc_velocity(pos, obj_pos,
|
||||
obj_vel, radius))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function nuke:effects(pos, radius)
|
||||
minetest.add_particlespawner({
|
||||
amount = math.min(128 * radius / 2, 4096),
|
||||
time = 1,
|
||||
minpos = vector.subtract(pos, radius / 2),
|
||||
maxpos = vector.add(pos, radius / 2),
|
||||
minvel = {x=-20, y=-20, z=-20},
|
||||
maxvel = {x=20, y=20, z=20},
|
||||
minacc = vector.new(),
|
||||
maxacc = vector.new(),
|
||||
minexptime = 1,
|
||||
maxexptime = 3,
|
||||
minsize = 8,
|
||||
maxsize = 16,
|
||||
collisiondetection = true,
|
||||
texture = "nuke_smoke_light.png",
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
function nuke:explode(pos, radius)
|
||||
local start = os.clock()
|
||||
local pos = vector.round(pos)
|
||||
local vm = VoxelManip()
|
||||
local pr = PseudoRandom(os.time())
|
||||
local p1 = vector.subtract(pos, radius)
|
||||
local p2 = vector.add(pos, radius)
|
||||
local MinEdge, MaxEdge = vm:read_from_map(p1, p2)
|
||||
local a = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
|
||||
local data = vm:get_data()
|
||||
|
||||
local cid_names = nuke.cid_names
|
||||
local p = {}
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
for z = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
local vi = a:index(pos.x - radius, pos.y + y, pos.z + z)
|
||||
for x = -radius, radius do
|
||||
if (x * x) + (y * y) + (z * z) <=
|
||||
(radius * radius) + pr:next(-radius, radius) then
|
||||
local name = cid_names[data[vi]]
|
||||
if name then
|
||||
p.x = pos.x + x
|
||||
p.y = pos.y + y
|
||||
p.z = pos.z + z
|
||||
self:ignite(p, name)
|
||||
end
|
||||
data[vi] = c_air
|
||||
end
|
||||
vi = vi + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vm:set_data(data)
|
||||
vm:update_liquids()
|
||||
vm:write_to_map()
|
||||
vm:update_map()
|
||||
print("Nuke exploded in "..(os.clock() - start).." seconds")
|
||||
end
|
||||
|
210
missles.lua
Normal file
@ -0,0 +1,210 @@
|
||||
|
||||
local radius = assert(tonumber(nuke.config:get("missle_radius")),
|
||||
"missle_radius must be convertible to a number")
|
||||
local misfire_radius = assert(tonumber(nuke.config:get("missle_misfire_radius")),
|
||||
"missle_misfire_radius must be convertible to a number")
|
||||
|
||||
local function get_missle(pos)
|
||||
for _, o in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
local e = o:get_luaentity()
|
||||
if e and e.name == "nuke:missle" then
|
||||
return e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function launch_missle(pos, strike_pos)
|
||||
local e = get_missle(pos)
|
||||
if not e then return end
|
||||
e.state = 1
|
||||
e.origin = pos
|
||||
e.strike_pos = strike_pos
|
||||
local ppos = vector.new(pos)
|
||||
ppos.y = ppos.y + 2
|
||||
minetest.add_particlespawner({
|
||||
amount = 128,
|
||||
time = 1,
|
||||
minpos = ppos,
|
||||
maxpos = ppos,
|
||||
minvel = {x=-5, y=-10, z=-5},
|
||||
maxvel = {x=5, y=0, z=5},
|
||||
minacc = vector.new(),
|
||||
maxacc = vector.new(),
|
||||
minexptime = 1,
|
||||
maxexptime = 3,
|
||||
minsize = 4,
|
||||
maxsize = 6,
|
||||
collisiondetection = true,
|
||||
texture = "nuke_smoke_dark.png",
|
||||
})
|
||||
end
|
||||
|
||||
local function get_controller_formspec(strike_pos)
|
||||
return "size[4,1.5]"
|
||||
.."field[0.3,0.5;4,1;pos;Position to strike;"
|
||||
..minetest.formspec_escape(minetest.pos_to_string(strike_pos)).."]"
|
||||
.."button_exit[0,1;2,1;save;Save]"
|
||||
.."button_exit[2,1;2,1;fire;Fire!]"
|
||||
end
|
||||
|
||||
minetest.register_entity("nuke:missle", {
|
||||
textures = {"nuke_missle.png"},
|
||||
visual = "mesh",
|
||||
mesh = "nuke_missle.x",
|
||||
visual_size = {x=3, y=3, z=3},
|
||||
phisical = true,
|
||||
collisionbox = {-0.5, -0.5, -0.5, 0.5, 4, 0.5},
|
||||
state = 0,
|
||||
--origin = vector.new(),
|
||||
on_activate = function(self, static_data)
|
||||
if static_data == "" then return end
|
||||
for k, v in pairs(minetest.deserialize(static_data)) do
|
||||
self[k] = v
|
||||
end
|
||||
end,
|
||||
on_step = function(self, dtime)
|
||||
local o = self.object
|
||||
local pos = vector.round(o:getpos())
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
if self.state == 0 then
|
||||
if not vector.equals(self.object:getvelocity(), {x=0, y=0, z=0}) then
|
||||
-- We are in standby but moving, probably got unloaded
|
||||
-- Drop ourselves
|
||||
minetest.add_item(pos, "nuke:missle")
|
||||
assert(false)
|
||||
end
|
||||
return
|
||||
elseif self.state == 1 then
|
||||
o:setacceleration({x=0, y=10, z=0})
|
||||
if pos.y >= self.origin.y + 100 then
|
||||
local dir = vector.direction(pos, self.strike_pos)
|
||||
dir = vector.normalize(dir)
|
||||
dir = vector.multiply(dir, 20)
|
||||
o:setvelocity(dir)
|
||||
o:setacceleration({x=0, y=0, z=0})
|
||||
self.state = 2
|
||||
end
|
||||
if node.name ~= "air" and pos.y >= self.origin.y + 2 then
|
||||
nuke:explode(pos, misfire_radius)
|
||||
o:remove()
|
||||
end
|
||||
elseif self.state == 2 then
|
||||
if node.name ~= "air" then
|
||||
nuke:explode(pos, radius)
|
||||
o:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_punch = function(self, player)
|
||||
player:get_inventory():add_item("main", "nuke:missle")
|
||||
end,
|
||||
get_staticdata = function(self)
|
||||
if self.state == 0 then
|
||||
return ""
|
||||
end
|
||||
return minetest.serialize({
|
||||
state = self.state,
|
||||
origin = self.origin,
|
||||
strike_pos = self.strike_pos,
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("nuke:missle_controller", {
|
||||
tiles = {"nuke_missle_controller_top.png", "nuke_missle_controller.png",
|
||||
"nuke_missle_controller.png", "nuke_missle_controller.png",
|
||||
"nuke_missle_controller.png", "nuke_missle_controller.png"},
|
||||
groups = {cracky=1},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.3, -0.5, -0.3, 0.3, 1, 0.3}, -- Base
|
||||
{-0.5, 1, -0.5, 0.5, 1.2, 0.5}, -- Top
|
||||
{-0.5, 1.2, 0, 0.5, 1.4, 0.5}, -- Half top
|
||||
}
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local pos_str = minetest.pos_to_string(pos)
|
||||
meta:set_string("strikepos", pos_str)
|
||||
meta:set_string("infotext", "Missle controller")
|
||||
meta:set_string("formspec", get_controller_formspec(pos))
|
||||
end,
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if not fields.pos then return end
|
||||
local node = minetest.get_node(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local strike_pos = minetest.string_to_pos(fields.pos)
|
||||
if not strike_pos then return end
|
||||
local player_name = player:get_player_name()
|
||||
if vector.distance(pos, strike_pos) > 500 then
|
||||
minetest.chat_send_player(player_name, "Strike position is too far.")
|
||||
return
|
||||
end
|
||||
meta:set_string("strikepos", minetest.pos_to_string(strike_pos))
|
||||
meta:set_string("formspec", get_controller_formspec(strike_pos))
|
||||
if fields.fire then
|
||||
if not nuke:can_detonate(player_name) then
|
||||
minetest.chat_send_player(player_name, "You can't detonate nukes!")
|
||||
return
|
||||
end
|
||||
local dir = minetest.facedir_to_dir(node.param2)
|
||||
dir = vector.multiply(dir, 2) -- The launcher is two nodes behind us
|
||||
local launcher_pos = vector.add(pos, dir)
|
||||
launch_missle(launcher_pos, strike_pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("nuke:missle_launcher", {
|
||||
tiles = {"nuke_missle_launcher.png"},
|
||||
groups = {cracky=1},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
--{-1, -0.3, -0.2, -0.8, 4, 0.2}, -- Left bar
|
||||
--{0.8, -0.3, -0.2, 1, 4, 0.2}, -- Right bar
|
||||
{-0.2, -0.3, 0.8, 0.2, 4, 1}, -- Back bar
|
||||
{-0.4, 3.8, 0.2, -0.2, 4, 1}, -- Left holder
|
||||
{0.2, 3.8, 0.2, 0.4, 4, 1}, -- Right holder
|
||||
{-1, -0.5, -1, 1, -0.3, 1}, -- Base
|
||||
}
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Missle launcher")
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker, itemstack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if get_missle(pos) then
|
||||
return itemstack
|
||||
end
|
||||
if itemstack:get_name() == "nuke:missle" then
|
||||
itemstack:take_item()
|
||||
minetest.add_entity(pos, "nuke:missle")
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
after_dig_node = function(pos, node, meta, player)
|
||||
local e = get_missle(pos)
|
||||
if e then
|
||||
e.object:remove()
|
||||
player:get_inventory():add_item("main", "nuke:missle")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("nuke:missle", {
|
||||
description = "Missle",
|
||||
inventory_image = "nuke_missle_wield.png",
|
||||
wield_image = "nuke_missle_wield.png",
|
||||
stack_max = 1,
|
||||
})
|
||||
|
1920
models/nuke_missle.x
Normal file
BIN
sounds/nuke_explode.ogg
Normal file
BIN
sounds/nuke_ignite.ogg
Normal file
BIN
textures/nuke_iron_bottom.png
Normal file
After Width: | Height: | Size: 951 B |
BIN
textures/nuke_iron_side.png
Normal file
After Width: | Height: | Size: 978 B |
BIN
textures/nuke_iron_top.png
Normal file
After Width: | Height: | Size: 1004 B |
BIN
textures/nuke_mese_bottom.png
Normal file
After Width: | Height: | Size: 953 B |
BIN
textures/nuke_mese_side.png
Normal file
After Width: | Height: | Size: 978 B |
BIN
textures/nuke_mese_top.png
Normal file
After Width: | Height: | Size: 1004 B |
BIN
textures/nuke_missle.png
Normal file
After Width: | Height: | Size: 438 B |
BIN
textures/nuke_missle_controller.png
Normal file
After Width: | Height: | Size: 90 B |
BIN
textures/nuke_missle_controller_side.png
Normal file
After Width: | Height: | Size: 131 B |
BIN
textures/nuke_missle_controller_top.png
Normal file
After Width: | Height: | Size: 286 B |
BIN
textures/nuke_missle_launcher.png
Normal file
After Width: | Height: | Size: 536 B |
BIN
textures/nuke_missle_wield.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
textures/nuke_smoke_dark.png
Normal file
After Width: | Height: | Size: 147 B |
BIN
textures/nuke_smoke_light.png
Normal file
After Width: | Height: | Size: 148 B |