commit 8bc13617cba79134d5e451b65e0391f8f6a0c906 Author: OldCoder Date: Sun Sep 4 22:03:30 2022 -0700 Imported from trollstream "ContentDB" diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..c8c18c0 --- /dev/null +++ b/README.txt @@ -0,0 +1,10 @@ +==== Nuke Mod for Minetest === +Version 2.2 + +License of mod code and textures: +MIT + +License of sounds: +- nuke_explode.ogg: Jose Ortiz 'MindChamber' (CC0) +- nuke_ignite.ogg: Wuzzy's derivative work of a sound by Ned Bouhalassa (CC0) + diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..0281dc8 --- /dev/null +++ b/depends.txt @@ -0,0 +1,3 @@ +default +creative? +mesecons? diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..a5dfd87 --- /dev/null +++ b/init.lua @@ -0,0 +1,279 @@ +nuke = {} -- mod-global table + +local all_tnt = {} + +local creative_is_enabled_for = + rawget(_G, "creative") and creative.is_enabled_for or function(name) + return minetest.settings:get_bool("creative_mode") +end + +nuke.spawn_tnt = function(pos, entname) + assert(table.indexof(all_tnt, entname) ~= -1, "attempting to spawn non-tnt") + minetest.sound_play("nuke_ignite", {pos = pos, gain = 1.0, max_hear_distance = 16}) + return minetest.add_entity(pos, entname) +end + +local function expand_tiles(tiles) + if #tiles >= 6 then + return tiles + end + local t = table.copy(tiles) + repeat + t[#t + 1] = t[#t] + until #t == 6 + return t +end + +local function calculate_velocity(distance, tntradius, mult) + -- d is the distance vector + -- tntradius - | d | + -- vel = d * ------------------- * mult + -- tntradius - 1 + local q = (tntradius - vector.length(distance)) / (tntradius - 1) + return vector.multiply(vector.multiply(distance, q), mult) +end + +local function activate_if_tnt(nodename, nodepos, tntpos, tntradius) + local explodetime_short = 4 -- seconds + local explodetime_vary = 1.5 + if table.indexof(all_tnt, nodename) == -1 then + return + end + + local obj = nuke.spawn_tnt(nodepos, nodename) + obj:setvelocity(calculate_velocity(vector.subtract(nodepos, tntpos), tntradius, {x=3, y=5, z=3})) + obj:get_luaentity().timer = explodetime_short + math.random(-explodetime_vary, explodetime_vary) +end + +local function apply_tnt_physics(tntpos, tntradius) + local objs = minetest.get_objects_inside_radius(tntpos, tntradius) + for _, obj in ipairs(objs) do + local mult = {x=1.5, y=2.5, z=1.5} + local vel = calculate_velocity(vector.subtract(obj:getpos(), tntpos), tntradius, mult) + + if obj:is_player() then + if obj:get_hp() > 0 then + obj:set_hp(obj:get_hp() - 1) + end + if obj.add_player_velocity then + vel = vector.multiply(vel, 10) + obj:add_player_velocity(vel) + end + else + if table.indexof(all_tnt, obj:get_entity_name()) ~= -1 then + vel = vector.multiply(vel, 2) -- apply more knockback to tnt entities + end + obj:setvelocity(vector.add(obj:getvelocity(), vel)) + end + end +end + + +nuke.register_tnt = function(nodename, def) + def.explodetime = def.explodetime or 10 -- seconds + if type(def.tiles) ~= "table" then + local t = def.tiles + def.tiles = {t .. "_top.png", t .. "_bottom.png", t .. "_side.png"} + end + + -- register node + minetest.register_node(nodename, { + tiles = def.tiles, + diggable = false, + description = def.description, + mesecons = { + effector = { + action_on = function(pos, node) + minetest.remove_node(pos) + nuke.spawn_tnt(pos, node.name) + minetest.check_for_falling(pos) + end, + action_off = function(pos, node) end, + action_change = function(pos, node) end, + }, + }, + on_punch = function(pos, node, puncher) + minetest.remove_node(pos) + nuke.spawn_tnt(pos, node.name) + minetest.check_for_falling(pos) + end, + }) + + -- register entity + local entity = { + physical = true, -- collision + collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + visual = "cube", + textures = expand_tiles(def.tiles), + health = 1, -- number of punches required to defuse + + timer = 0, + blinktimer = 0, + blinkstatus = true, + } + function entity:on_activate(staticdata) + self.object:setvelocity({x=0, y=4, z=0}) + self.object:setacceleration({x=0, y=-10, z=0}) -- gravity + self.object:settexturemod("^[brighten") + end + function entity:on_step(dtime) + self.timer = self.timer + dtime + local mult = 1 + if self.timer > def.explodetime * 0.8 then -- blink faster before explosion + mult = 4 + elseif self.timer > def.explodetime * 0.5 then + mult = 2 + end + self.blinktimer = self.blinktimer + mult * dtime + + if self.blinktimer > 0.5 then -- actual blinking + self.blinktimer = self.blinktimer - 0.5 + self.object:settexturemod(self.blinkstatus and "^[brighten" or "") + self.blinkstatus = not self.blinkstatus + end + + if self.timer > def.explodetime then -- boom! + minetest.sound_play("nuke_explode", {pos = pos, gain = 0.8, max_hear_distance = 32}) + def.on_explode(vector.round(self.object:get_pos())) + self.object:remove() + end + end + function entity:on_punch(hitter) + self.health = self.health - 1 + if self.health == 0 then -- give tnt node back if defused + self.object:remove() + if not creative_is_enabled_for(hitter:get_player_name()) then + hitter:get_inventory():add_item("main", nodename) + end + end + end + minetest.register_entity(nodename, entity) + + -- save tnt name + all_tnt[#all_tnt + 1] = nodename +end + + +local function on_explode_normal(pos, range) + local ndef = minetest.registered_nodes[minetest.get_node(pos).name] + if ndef ~= nil and ndef.groups.water ~= nil then + apply_tnt_physics(pos, range) + return -- cancel explosion + end + + for x=-range, range do + for y=-range, range do + for z=-range, range do + if x*x+y*y+z*z <= range * range + range then + + local nodepos = {x=pos.x+x, y=pos.y+y, z=pos.z+z} + local n = minetest.get_node(nodepos) + if n.name ~= "air" and n.name ~= "ignore" then + activate_if_tnt(n.name, nodepos, pos, range) + minetest.remove_node(nodepos) + end + + end + end + end + end + apply_tnt_physics(pos, range) +end + +local function on_explode_split(pos, range, entname) + for x=-range, range do + for z=-range, range do + if x*x+z*z <= range * range then + + local nodepos = vector.add(pos, {x=x, y=0, z=z}) + minetest.add_entity(nodepos, entname) + + end + end + end +end + + +-- Iron TNT + +nuke.register_tnt("nuke:iron_tnt", { + description = "Iron TNT", + tiles = "nuke_iron_tnt", + on_explode = function(pos) + on_explode_normal(pos, 6) + end, +}) + +minetest.register_craft({ + output = "nuke:iron_tnt 4", + recipe = { + {"", "group:wood", ""}, + {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"}, + {"", "group:wood", ""}, + } +}) + + +nuke.register_tnt("nuke:iron_tntx", { + description = "Extreme Iron TNT", + tiles = {"nuke_iron_tnt_top.png", "nuke_iron_tnt_bottom.png", "nuke_iron_tnt_side_x.png"}, + on_explode = function(pos) + on_explode_split(pos, 3, "nuke:iron_tnt") + end, +}) + +minetest.register_craft({ + output = "nuke:iron_tntx 1", + recipe = { + {"", "default:coal_lump", ""}, + {"default:coal_lump", "nuke:iron_tnt", "default:coal_lump"}, + {"", "default:coal_lump", ""}, + } +}) + +-- Mese TNT + +nuke.register_tnt("nuke:mese_tnt", { + description = "Mese TNT", + tiles = "nuke_mese_tnt", + on_explode = function(pos) + on_explode_normal(pos, 12) + end, +}) + +minetest.register_craft({ + output = "nuke:mese_tnt 4", + recipe = { + {"", "group:wood", ""}, + {"default:mese_crystal", "default:coal_lump", "default:mese_crystal"}, + {"", "group:wood", ""}, + } +}) + + +nuke.register_tnt("nuke:mese_tntx", { + description = "Extreme Mese TNT", + tiles = {"nuke_mese_tnt_top.png", "nuke_mese_tnt_bottom.png", "nuke_mese_tnt_side_x.png"}, + on_explode = function(pos) + on_explode_split(pos, 3, "nuke:mese_tnt") + end, +}) + +minetest.register_craft({ + output = "nuke:mese_tntx 1", + recipe = { + {"", "default:coal_lump", ""}, + {"default:coal_lump", "nuke:mese_tnt", "default:coal_lump"}, + {"", "default:coal_lump", ""}, + } +}) + +-- Compatibility aliases + +minetest.register_alias("nuke:hardcore_iron_tnt", "nuke:iron_tntx") +minetest.register_alias("nuke:hardcore_mese_tnt", "nuke:mese_tntx") + + +if minetest.settings:get_bool("log_mods") then + print("[Nuke] Loaded") +end diff --git a/sounds/nuke_explode.ogg b/sounds/nuke_explode.ogg new file mode 100644 index 0000000..1691a41 Binary files /dev/null and b/sounds/nuke_explode.ogg differ diff --git a/sounds/nuke_ignite.ogg b/sounds/nuke_ignite.ogg new file mode 100644 index 0000000..aa232f0 Binary files /dev/null and b/sounds/nuke_ignite.ogg differ diff --git a/textures/nuke_iron_tnt_bottom.png b/textures/nuke_iron_tnt_bottom.png new file mode 100644 index 0000000..36ae584 Binary files /dev/null and b/textures/nuke_iron_tnt_bottom.png differ diff --git a/textures/nuke_iron_tnt_side.png b/textures/nuke_iron_tnt_side.png new file mode 100644 index 0000000..bb598b3 Binary files /dev/null and b/textures/nuke_iron_tnt_side.png differ diff --git a/textures/nuke_iron_tnt_side_x.png b/textures/nuke_iron_tnt_side_x.png new file mode 100644 index 0000000..a1fd862 Binary files /dev/null and b/textures/nuke_iron_tnt_side_x.png differ diff --git a/textures/nuke_iron_tnt_top.png b/textures/nuke_iron_tnt_top.png new file mode 100644 index 0000000..e6c2829 Binary files /dev/null and b/textures/nuke_iron_tnt_top.png differ diff --git a/textures/nuke_mese_tnt_bottom.png b/textures/nuke_mese_tnt_bottom.png new file mode 100644 index 0000000..f0a962c Binary files /dev/null and b/textures/nuke_mese_tnt_bottom.png differ diff --git a/textures/nuke_mese_tnt_side.png b/textures/nuke_mese_tnt_side.png new file mode 100644 index 0000000..d87fce5 Binary files /dev/null and b/textures/nuke_mese_tnt_side.png differ diff --git a/textures/nuke_mese_tnt_side_x.png b/textures/nuke_mese_tnt_side_x.png new file mode 100644 index 0000000..c955c8b Binary files /dev/null and b/textures/nuke_mese_tnt_side_x.png differ diff --git a/textures/nuke_mese_tnt_top.png b/textures/nuke_mese_tnt_top.png new file mode 100644 index 0000000..32f2b70 Binary files /dev/null and b/textures/nuke_mese_tnt_top.png differ