diff options
-rw-r--r-- | extranodes/lox.lua | 198 | ||||
-rw-r--r-- | extranodes/textures/technic_fbomb.png | bin | 0 -> 2099 bytes | |||
-rw-r--r-- | extranodes/textures/technic_fbombact.png | bin | 0 -> 2427 bytes | |||
-rw-r--r-- | extranodes/textures/technic_snowflake.png | bin | 0 -> 635 bytes | |||
-rw-r--r-- | technic/sounds/technic_walking_tractor.ogg | bin | 0 -> 12176 bytes | |||
-rw-r--r-- | technic/textures/technic_walking_tractor.png | bin | 0 -> 621 bytes | |||
-rw-r--r-- | technic/tools/init.lua | 2 | ||||
-rw-r--r-- | technic/tools/prospector.lua | 2 | ||||
-rw-r--r-- | technic/tools/walking_tractor.lua | 253 |
9 files changed, 411 insertions, 44 deletions
diff --git a/extranodes/lox.lua b/extranodes/lox.lua index 08b2269..93954fe 100644 --- a/extranodes/lox.lua +++ b/extranodes/lox.lua @@ -1,3 +1,6 @@ +-- An small arsenal of tools to battle the lava craters + + local S = rawget(_G, "intllib") and intllib.Getter() or function(s) return s end local freezing_rules = { @@ -13,15 +16,84 @@ local freezing_rules = { ["ethereal:mushroom_dirt"] = "default:dirt_with_snow", } +local function freeze(user, pos, radius, itemstack) + + -- itemstack is true if the function is used in a tool callback + -- if so, user is a playerref + -- if itemstack is false, it's a node using the function, and the + -- user name is plain text string + + if (itemstack) then + + if minetest.is_protected(pos, user:get_player_name()) then + minetest.record_protection_violation(pos, user:get_player_name()) + return + end + + else + if minetest.is_protected(pos, user) then + minetest.record_protection_violation(pos, user) + return + end + end + + local loc = {} + local wrk = false + -- R = 2, d = 3 + -- R = 10, d = 5 + local depth = math.floor(0.25*radius+2.5) + + for y = 0,depth,1 do + for x = -radius,radius,1 do + for z = -radius,radius,1 do + loc = {x = pos.x - x, y = pos.y - y, z = pos.z - z} + if freezing_rules[minetest.get_node(loc).name] then + wrk = true + minetest.swap_node(loc, {name = freezing_rules[minetest.get_node(loc).name]}) + end + if math.random(1,5) == 5 then + if minetest.get_node({x = loc.x, y = loc.y+1, z = loc.z}).name == "air" + and minetest.get_node(loc).name ~= "air" + and minetest.get_node(loc).name ~= "stairs:slab_snowblock" then + minetest.set_node({x = loc.x, y = loc.y+1, z = loc.z}, {name = "stairs:slab_snowblock"}) + end + end + end + end + end + + if wrk then + minetest.sound_play("default_cool_lava", {gain = 1, pos = pos}) + end + + if (itemstack) then + + itemstack:take_item() + local uinv = user:get_inventory() + if uinv:room_for_item("main", "vessels:steel_bottle 1") then + uinv:add_item("main", "vessels:steel_bottle 1") + else + minetest.item_drop(ItemStack("vessels:steel_bottle 1"), user, user:getpos()) + end + + user:set_hp(user:get_hp() - 1) + + return itemstack + else + return true + end + +end + minetest.register_craftitem(":technic:lox", { description = S("Liquid Oxygen"), - drawtype = "plantlike", tiles = {"technic_lox.png"}, inventory_image = "technic_lox.png", wield_image = "technic_lox.png", paramtype = "light", is_ground_content = false, walkable = false, + liquids_pointable = true, selection_box = { type = "fixed", fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} @@ -32,49 +104,89 @@ minetest.register_craftitem(":technic:lox", { if pointed_thing.type ~= "node" then return itemstack end - - if minetest.is_protected(pointed_thing.under, user:get_player_name()) then - minetest.record_protection_violation(pointed_thing.under, user:get_player_name()) - return - end - - local pos = pointed_thing.under + freeze(user, pointed_thing.under, 2, itemstack) + end +}) - local loc = {} - local wrk = false - for y=0,3,1 do - for x=-2,2,1 do - for z = -2,2,1 do - loc = {x = pos.x - x, y = pos.y - y, z = pos.z - z} - if freezing_rules[minetest.get_node(loc).name] then - wrk = true - minetest.swap_node(loc, {name = freezing_rules[minetest.get_node(loc).name]}) - end - if math.random(1,5) == 5 then - if minetest.get_node({x = loc.x, y = loc.y+1, z = loc.z}).name == "air" - and minetest.get_node(loc).name ~= "air" - and minetest.get_node(loc).name ~= "stairs:slab_snowblock" then - minetest.set_node({x = loc.x, y = loc.y+1, z = loc.z}, {name = "stairs:slab_snowblock"}) - end - end - end - end - end - - if wrk then - minetest.sound_play("default_cool_lava", {gain = 1, pos = pos}) - end +minetest.register_node(":technic:fbomb", { + description = S("F-Bomb"), + tiles = {"technic_fbomb.png"}, + paramtype = "light", + is_ground_content = false, + walkable = false, + selection_box = { + type = "fixed", + fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} + }, + groups = {dig_immediate = 2, falling_node = 1}, + sounds = default.node_sound_defaults(), + on_punch = function(pos, node, player, pointed_thing) + minetest.remove_node(pos) + minetest.place_node(pos, {name="technic:fbombact"}) + local nm = minetest.get_meta(pos) + nm:set_string("player", player:get_player_name()) + end +}) - itemstack:take_item() - local uinv = user:get_inventory() - if uinv:room_for_item("main", "vessels:steel_bottle 1") then - uinv:add_item("main", "vessels:steel_bottle 1") - else - minetest.item_drop(ItemStack("vessels:steel_bottle 1"), user, user:getpos()) +minetest.register_node(":technic:fbombact", { + description = S("F-Bomb Active"), + tiles = {"technic_fbombact.png"}, + paramtype = "light", + is_ground_content = false, + walkable = false, + light_source = 3, + selection_box = { + type = "fixed", + fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} + }, + groups = {falling_node = 1, cracky = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_defaults(), + on_construct = function(pos) + local nm = minetest.get_meta(pos) + local id = minetest.add_particlespawner({ + amount = 30, + time = 0, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=0, z=-2}, + maxvel = {x=2, y=0, z=2}, + minacc = {x=0, y=0, z=0}, + maxacc = {x=0.5, y=0, z=0.5}, + minexptime = 1, + maxexptime = 5, + minsize = 1, + maxsize = 4, + collisiondetection = false, + vertical = false, + texture = "technic_snowflake.png", + glow = 2 + }) + nm:set_int("id", id) + local tm = minetest.get_node_timer(pos) + tm:start(5) + end, + on_timer = function(pos, elapsed) + local nm = minetest.get_meta(pos) + local pn = nm:get_string("player") + freeze(pn, pos, 10) + minetest.remove_node(pos) + return false + end, + on_destruct = function(pos) + local nm = minetest.get_meta(pos) + if (nm:get_int("id")) then + minetest.delete_particlespawner(nm:get_int("id")) end - - user:set_hp(user:get_hp() - 1) - - return itemstack - end + end, + drop = "technic:fbomb" + }) + +minetest.register_craft({ + output = "technic:fbomb 3", + recipe = { + { "technic:lox", "tnt:tnt", "technic:lox"}, + { "tnt:tnt", "technic:lox", "tnt:tnt"}, + { "technic:lox", "tnt:tnt", "technic:lox"} + }, + })
\ No newline at end of file diff --git a/extranodes/textures/technic_fbomb.png b/extranodes/textures/technic_fbomb.png Binary files differnew file mode 100644 index 0000000..edae1a1 --- /dev/null +++ b/extranodes/textures/technic_fbomb.png diff --git a/extranodes/textures/technic_fbombact.png b/extranodes/textures/technic_fbombact.png Binary files differnew file mode 100644 index 0000000..061f23f --- /dev/null +++ b/extranodes/textures/technic_fbombact.png diff --git a/extranodes/textures/technic_snowflake.png b/extranodes/textures/technic_snowflake.png Binary files differnew file mode 100644 index 0000000..1e039af --- /dev/null +++ b/extranodes/textures/technic_snowflake.png diff --git a/technic/sounds/technic_walking_tractor.ogg b/technic/sounds/technic_walking_tractor.ogg Binary files differnew file mode 100644 index 0000000..8c9ebc1 --- /dev/null +++ b/technic/sounds/technic_walking_tractor.ogg diff --git a/technic/textures/technic_walking_tractor.png b/technic/textures/technic_walking_tractor.png Binary files differnew file mode 100644 index 0000000..c55cb42 --- /dev/null +++ b/technic/textures/technic_walking_tractor.png diff --git a/technic/tools/init.lua b/technic/tools/init.lua index 7d640d1..c688e7a 100644 --- a/technic/tools/init.lua +++ b/technic/tools/init.lua @@ -15,7 +15,9 @@ dofile(path.."/tree_tap.lua") dofile(path.."/sonic_screwdriver.lua") dofile(path.."/prospector.lua") dofile(path.."/vacuum.lua") + dofile(path.."/lawn_trimmer.lua") +dofile(path.."/walking_tractor.lua") if minetest.get_modpath("screwdriver") then -- compatibility alias diff --git a/technic/tools/prospector.lua b/technic/tools/prospector.lua index b28f1d8..6373e98 100644 --- a/technic/tools/prospector.lua +++ b/technic/tools/prospector.lua @@ -1,6 +1,6 @@ local S = technic.getter -technic.register_power_tool("technic:prospector", 300000) +technic.register_power_tool("technic:prospector", 650000) local function get_metadata(toolstack) local m = minetest.deserialize(toolstack:get_metadata()) diff --git a/technic/tools/walking_tractor.lua b/technic/tools/walking_tractor.lua new file mode 100644 index 0000000..01d3ae1 --- /dev/null +++ b/technic/tools/walking_tractor.lua @@ -0,0 +1,253 @@ +--[[ + Walking tractor: a dedicated farming tool, a miracle of small mechanization. + Replaces hoes and harvests useful plants (fully-grown cultivars, mostly from farming) + Has a variable swipe from 3 to 7 nodes, in either case - in a line, perpendicular + to the user's direction of sight. For smaller areas there are always hoes. + Modes 1-3 are for tilling + Modes 4-6 are for harvesting +]] + +-- Configuration +-- Intended to hold as much as the chainsaw, 10000 units +local walking_tractor_max_charge = 20000 +-- Can remove a curious number of objects +local walking_tractor_charge_per_object = 30 +-- For tilling: cost is less but spent regardless of actual success +local walking_tractor_charge_per_tilled_node = 25 + +local S = technic.getter + +local walking_tractor_mode_text = { + S("3 blocks wide tilling"), + S("5 blocks wide tilling"), + S("7 blocks wide tilling"), + S("3 blocks wide harvesting"), + S("5 blocks wide harvesting"), + S("7 blocks wide harvesting"), +} + +local ripe_for_harvest = { + "farming:barley_7", + "farming:beanpole_5", + "farming:blueberry_4", + "farming:carrot_8", + "farming:chili_8", + "farming:cocoa_4", + "farming:coffee_5", + "farming:corn_8", + "farming:cotton_8", + "farming:cucumber_4", + "farming:garlic_5", + "farming:grapes_8", + "farming:hemp_8", + "farming:melon_8", + "farming:onion_5", + "farming:pea_5", + "farming:pepper_5", + "farming:pineapple_8", + "farming:potato_4", + "farming:pumpkin_8", + "farming:raspberry_4", + "farming:rhubarb_3", + "farming:tomato_8", + "farming:wheat_8", + "ethereal:onion_5", + "ethereal:strawberry_8", +} + +local node_removed + +-- Mode switcher for the tool +local function walking_tractor_setmode(user, itemstack, meta) + local player_name = user:get_player_name() + + if not meta then + meta = {mode = nil} + end + if not meta.mode then + minetest.chat_send_player(player_name, + S("Use while sneaking to change Walking Tractor modes.")) + meta.mode = 0 + end + + meta.mode = meta.mode % 6 + 1 + + minetest.chat_send_player(player_name, + S("Walking Tractor Mode %d"):format(meta.mode) .. ": " + .. walking_tractor_mode_text[meta.mode]) + itemstack:set_name("technic:walking_tractor_" .. meta.mode); + itemstack:set_metadata(minetest.serialize(meta)) + return itemstack +end + + +-- Perform the trimming action +local function work_on_soil(itemstack, user, pointed_thing) + local meta = minetest.deserialize(itemstack:get_metadata()) + local keys = user:get_player_control() + + if not meta or not meta.mode or keys.sneak then + return walking_tractor_setmode(user, itemstack, meta) + end + + meta.charge = meta.charge or 0 + + if meta.charge < walking_tractor_charge_per_object then + return -- no charge for even a single node, aborting + end + + if pointed_thing.type ~= "node" then + return itemstack + end + + local name = user:get_player_name() + if minetest.is_protected(pointed_thing.under, name) then + minetest.record_protection_violation(pointed_thing.under, name) + return + end + + minetest.sound_play("technic_walking_tractor", { +-- to_player = user:get_player_name(), + gain = 0.5, + }) + + local start_pos = {} + local end_pos = {} + + local ldir = 0 + local udir = user:get_look_dir() + if math.abs(udir.x) > math.abs(udir.z) then + if udir.x > 0 then + ldir = 0 -- +X + else + ldir = 1 -- -X + end + else + if udir.z > 0 then + ldir = 2 -- +Z + else + ldir = 3 -- -Z + end + end + + local offset = meta.mode + if offset > 3 then + offset = offset - 3 + end + offset = offset + 0.1 + + if ldir > 1 then + + start_pos = { + x = pointed_thing.under.x - offset, + z = pointed_thing.under.z, + y = pointed_thing.under.y - 0.1 + } + end_pos = { + x = pointed_thing.under.x + offset, + z = pointed_thing.under.z, + y = pointed_thing.under.y + 1.1 + } + + else + start_pos = { + x = pointed_thing.under.x, + z = pointed_thing.under.z - offset, + y = pointed_thing.under.y - 0.1 + } + end_pos = { + x = pointed_thing.under.x, + z = pointed_thing.under.z + offset, + y = pointed_thing.under.y + 1.1 + } + + end + + + + if meta.mode <= 3 then + -- tilling + local found_obj = minetest.find_nodes_in_area(start_pos, end_pos, {"group:soil"}) + for _, f in ipairs(found_obj) do + -- unfortunately, there is no callback to track the node change without + -- digging it first + if not minetest.is_protected(f, name) then + minetest.remove_node(f) + minetest.set_node(f, {name = "farming:soil"}) + meta.charge = meta.charge - walking_tractor_charge_per_tilled_node + end + -- Abort if no charge left for another node + if meta.charge < walking_tractor_charge_per_tilled_node then break end + end + + else + -- harvesting + -- Since nodes sometimes cannot be removed, we cannot rely on repeating + -- find_node_near() and removing found nodes + local found_obj = minetest.find_nodes_in_area(start_pos, end_pos, ripe_for_harvest) + for _, f in ipairs(found_obj) do + node_removed = false + -- Callback will set the flag to true if the node is dug successfully, + -- otherwise skip to the next one. + minetest.node_dig(f, minetest.get_node(f), user) + if node_removed then + meta.charge = meta.charge - walking_tractor_charge_per_object + -- Abort if no charge left for another node + if meta.charge < walking_tractor_charge_per_object then break end + end + end + + end + + -- The charge won't expire in creative mode, but the tool still + -- has to be charged prior to use + if not technic.creative_mode then + technic.set_RE_wear(itemstack, meta.charge, walking_tractor_max_charge) + itemstack:set_metadata(minetest.serialize(meta)) + end + return itemstack +end + +function check_removal() + node_removed = true +end + +-- Register the tool and its varieties in the game +technic.register_power_tool("technic:walking_tractor", walking_tractor_max_charge) +minetest.register_tool("technic:walking_tractor", { + description = S("Walking Tractor"), + inventory_image = "technic_walking_tractor.png", + stack_max = 1, + wear_represents = "technic_RE_charge", + on_refill = technic.refill_RE_charge, + on_use = work_on_soil, + after_use = check_removal +}) + +for i = 1, 6 do + technic.register_power_tool("technic:walking_tractor_" .. i, walking_tractor_max_charge) + minetest.register_tool("technic:walking_tractor_" .. i, { + description = S("Walking Tractor Mode %d"):format(i), + inventory_image = "technic_walking_tractor.png^technic_tool_mode" .. i .. ".png", + wield_image = "technic_walking_tractor.png", + wear_represents = "technic_RE_charge", + on_refill = technic.refill_RE_charge, + groups = {not_in_creative_inventory = 1}, + on_use = work_on_soil, + after_use = check_removal + }) +end + + +-- Provide a crafting recipe +local trigger = minetest.get_modpath("mesecons_button") and "mesecons_button:button_off" + or "default:mese_crystal_fragment" + +minetest.register_craft({ + output = 'technic:walking_tractor', + recipe = { + {'dye:green', 'technic:battery', trigger}, + {'technic:motor', 'technic:battery', 'default:stick'}, + {'technic:diamond_drill_head', 'technic:stainless_steel_ingot', 'technic:rubber'}, + } +}) |