-- vi: noexpandtab local has_digilines = minetest.get_modpath("digilines") spacecannon.update_formspec = function(meta, is_th) local formspec = "" if not is_th then formspec = formspec .. "formspec_version[4]" .. "size[10.5,9;]" -- Ammo inventory formspec = formspec .. "list[current_name;src;0.375,0.5;1,1;]" .. "list[current_player;main;0.375,4;8,4;]" .. "listring[]" .. "item_image[0.375,0.5;1,1;spacecannon:railgun_slug]" .. "label[1.75,1;Ammunition]" -- Manual "fire" button formspec = formspec .. "button_exit[5.125,0.5;5,1;fire;Fire]" -- Digiline channel if has_digilines then local channel = meta:get_string("channel") or "" formspec = formspec .. "field[0.375,2.375;4,1;digiline_channel;Digiline Channel;" .. channel .. "]" .. "button_exit[4.5,2.375;1,1;set_digiline_channel;Set]" end else formspec = formspec .. "formspec_version[4]" if has_digilines then formspec = formspec .. "size[6,4;]" else formspec = formspec .. "size[6,2;]" end -- Manual "fire" button formspec = formspec .. "button_exit[0.5,0.5;5,1;fire;Fire]" -- Digiline channel if has_digilines then local channel = meta:get_string("channel") or "" formspec = formspec .. "field[0.5,2.5;3.5,1;digiline_channel;Digiline Channel;" .. channel .. "]" .. "button_exit[4.5,2.5;1,1;set_digiline_channel;Set]" end end meta:set_string("formspec", formspec) end spacecannon.can_shoot = function() -- arguments: pos, playername return true end spacecannon.can_destroy = function() -- arguments: pos return true end spacecannon.can_damage = function(_obj) return true end spacecannon.fire = function(pos, playername, color, speed, is_th, storage_require_mod) if not spacecannon.can_shoot(pos, playername) then return end -- check fuel/power local meta = minetest.get_meta(pos) local config_store = spacecannon.config.ki_powerstorage * storage_require_mod if is_th then config_store = spacecannon.config.th_powerstorage * storage_require_mod end if meta:get_int("powerstorage") < config_store then -- not enough power return end -- check ammunition if not is_th then local inv = meta:get_inventory() if inv:is_empty("src") then --minetest.chat_send_player(playername, "No ammunition loaded!") return false end local src_stack = inv:get_list("src")[1] if not src_stack or src_stack:get_name() ~= "spacecannon:railgun_slug" then --minetest.chat_send_player(playername, "Incorrect ammunition!") return end end -- use power meta:set_int("powerstorage", 0) -- use ammo if not is_th then local src_stack = meta:get_inventory():get_list("src")[1] src_stack:take_item(); meta:get_inventory():set_stack("src", 1, src_stack) end minetest.sound_play("spacecannon_shoot", { pos = pos, gain = 1.0, max_hear_distance = 16 }) local node = minetest.get_node(pos) local dir = spacecannon.facedir_to_down_dir(node.param2) local obj = minetest.add_entity({x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z}, "spacecannon:energycube_" .. color) obj:setvelocity({x=dir.x*speed, y=dir.y*speed, z=dir.z*speed}) end -- destroy stuff in range -- TODO: resilient material list spacecannon.destroy = function(pos, range, intensity) if not spacecannon.can_destroy(pos) then return end local particle_texture = nil 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 np={x=pos.x+x,y=pos.y+y,z=pos.z+z} if minetest.is_protected(np, "") then return -- fail fast end local n = minetest.get_node_or_nil(np) if n and n.name ~= "air" then local node_def = minetest.registered_nodes[n.name] if node_def and node_def.tiles and node_def.tiles[1] then particle_texture = node_def.tiles[1] end if node_def.on_blast then -- custom on_blast node_def.on_blast(np, intensity) else -- default behavior local resilience = spacecannon.node_resilience[n.name] or 1 if resilience <= 1 or math.random(resilience) == resilience then minetest.set_node(np, {name="air"}) local itemstacks = minetest.get_node_drops(n.name) for _, itemname in ipairs(itemstacks) do if math.random(5) == 5 then -- chance drop minetest.add_item(np, itemname) end end end end end end end end end local radius = range -- https://github.com/minetest/minetest_game/blob/master/mods/tnt/init.lua minetest.add_particlespawner({ amount = 64, time = 0.5, minpos = vector.subtract(pos, radius / 2), maxpos = vector.add(pos, radius / 2), minvel = {x = -10, y = -10, z = -10}, maxvel = {x = 10, y = 10, z = 10}, minacc = vector.new(), maxacc = vector.new(), minexptime = 1, maxexptime = 2.5, minsize = radius * 3, maxsize = radius * 5, texture = "spacecannon_spark.png", glow = 5 }) if particle_texture then minetest.add_particlespawner({ amount = 64, time = 0.5, minpos = vector.subtract(pos, radius / 2), maxpos = vector.add(pos, radius / 2), minvel = {x = -10, y = -10, z = -10}, maxvel = {x = 10, y = 10, z = 10}, minacc = vector.new(), maxacc = vector.new(), minexptime = 1, maxexptime = 2.5, minsize = radius * 3, maxsize = radius * 5, texture = particle_texture, glow = 5 }) end minetest.sound_play("tnt_explode", {pos = pos, gain = 1.5, max_hear_distance = math.min(radius * 20, 128)}) end -- convert face dir to vector spacecannon.facedir_to_down_dir = function(facing) return ( {[0]={x=0, y=-1, z=0}, {x=0, y=0, z=-1}, {x=0, y=0, z=1}, {x=-1, y=0, z=0}, {x=1, y=0, z=0}, {x=0, y=1, z=0}})[math.floor(facing/4)] end