diff options
-rw-r--r-- | technic/textures/technic_chainsaw_mini.png | bin | 0 -> 546 bytes | |||
-rw-r--r-- | technic/textures/technic_planter.png | bin | 0 -> 468 bytes | |||
-rw-r--r-- | technic/tools/chainsaw.lua | 109 | ||||
-rw-r--r-- | technic/tools/init.lua | 1 | ||||
-rw-r--r-- | technic/tools/lawn_trimmer.lua | 7 | ||||
-rw-r--r-- | technic/tools/planter.lua | 255 | ||||
-rw-r--r-- | technic/tools/walking_tractor.lua | 1 |
7 files changed, 369 insertions, 4 deletions
diff --git a/technic/textures/technic_chainsaw_mini.png b/technic/textures/technic_chainsaw_mini.png Binary files differnew file mode 100644 index 0000000..b91ca13 --- /dev/null +++ b/technic/textures/technic_chainsaw_mini.png diff --git a/technic/textures/technic_planter.png b/technic/textures/technic_planter.png Binary files differnew file mode 100644 index 0000000..188f733 --- /dev/null +++ b/technic/textures/technic_planter.png diff --git a/technic/tools/chainsaw.lua b/technic/tools/chainsaw.lua index 3928c56..39423fb 100644 --- a/technic/tools/chainsaw.lua +++ b/technic/tools/chainsaw.lua @@ -1,5 +1,6 @@ -- Configuration +local chainsaw_max_charge_mini = 15000 local chainsaw_max_charge = 30000 -- Maximum charge of the saw local chainsaw_max_charge_mk2 = 120000 -- Gives 2500 nodes on a single charge (about 50 complete normal trees) @@ -17,7 +18,7 @@ local timber_nodenames = { ["default:cactus"] = true, ["default:tree"] = true, ["default:apple"] = true, - ["default:pine_tree"] = true, + ["default:pine_tree"] = true, } if chainsaw_leaves then @@ -206,6 +207,7 @@ end local S = technic.getter +technic.register_power_tool("technic:chainsaw_mini", chainsaw_max_charge_mini) technic.register_power_tool("technic:chainsaw", chainsaw_max_charge) technic.register_power_tool("technic:chainsaw_mk2", chainsaw_max_charge_mk2) @@ -383,6 +385,80 @@ local function recursive_dig(pos, remaining_charge, mk, username) return remaining_charge end +-- a non-recursive version +local function nonrecursive_dig(pos, remaining_charge, username) + if remaining_charge < chainsaw_charge_per_node then + return remaining_charge + end + local node = minetest.get_node(pos) + + if not timber_nodenames[node.name] then + return remaining_charge + end + + if minetest.is_protected(pos, username) then + return remaining_charge + end + + local start_pos = { + x = pos.x - 1, + z = pos.z - 1, + y = pos.y + } + local end_pos = { + x = pos.x + 1, + z = pos.z + 1, + y = pos.y + 30 + } + + local positions = {} + + for x = 1,-1,-1 do + for z = 1,-1,-1 do + table.insert(positions, {x = x, z = z}) + end + end + + local h = 40 + + -- find where the tree ends (counting from the ground) + for y=0,h,1 do + local c = 0 + for _,offset in pairs(positions) do + local p = {x = pos.x + offset.x, y = pos.y + y, z = pos.z + offset.z} + local n = minetest.get_node(p) + if not timber_nodenames[n.name] then + c = c + 1 + end + end + if c == #positions then +-- minetest.chat_send_all("tree height: " .. y) + h = y + break + end + end + + for y=h,0,-1 do + for _,offset in pairs(positions) do + if remaining_charge < chainsaw_charge_per_node then + break + end + local p = {x = pos.x + offset.x, y = pos.y + y, z = pos.z + offset.z} + local n = minetest.get_node(p) + if timber_nodenames[n.name] then + -- Wood found - cut it + handle_drops(minetest.get_node_drops(n.name)) + minetest.remove_node(p) + remaining_charge = remaining_charge - chainsaw_charge_per_node + end + end + end + + return remaining_charge +end + + + -- Function to randomize positions for new node drops local function get_drop_pos(pos) local drop_pos = {} @@ -420,7 +496,13 @@ end -- Chainsaw entry point local function chainsaw_dig(pos, current_charge, mk, username) -- Start sawing things down - local remaining_charge = recursive_dig(pos, current_charge, mk, username) + local remaining_charge + if (mk) then + remaining_charge = recursive_dig(pos, current_charge, mk, username) + else + remaining_charge = nonrecursive_dig(pos, current_charge, username) + end + minetest.sound_play("chainsaw", {pos = pos, gain = 1.0, max_hear_distance = 10}) @@ -469,6 +551,8 @@ local function use_chainsaw(itemstack, user, pointed_thing, mk) technic.set_RE_wear(itemstack, meta.charge, chainsaw_max_charge) elseif mk == 2 then technic.set_RE_wear(itemstack, meta.charge, chainsaw_max_charge_mk2) + else + technic.set_RE_wear(itemstack, meta.charge, chainsaw_max_charge_mini) end itemstack:set_metadata(minetest.serialize(meta)) end @@ -499,11 +583,32 @@ minetest.register_tool("technic:chainsaw_mk2", { end }) +minetest.register_tool("technic:chainsaw_mini", { + description = S("Chainsaw Mini"), + inventory_image = "technic_chainsaw_mini.png", + stack_max = 1, + wear_represents = "technic_RE_charge", + on_refill = technic.refill_RE_charge, + groups = {not_in_creative_inventory = 1}, + on_use = function(itemstack, user, pointed_thing) + use_chainsaw(itemstack, user, pointed_thing, nil) + return(itemstack) + end +}) local mesecons_button = minetest.get_modpath("mesecons_button") local trigger = mesecons_button and "mesecons_button:button_off" or "default:mese_crystal_fragment" minetest.register_craft({ + output = "technic:chainsaw_mini", + recipe = { + {"technic:wrought_iron_ingot", "technic:wrought_iron_ingot", "technic:battery"}, + {"", "technic:motor", trigger}, + {"", "", ""}, + } +}) + +minetest.register_craft({ output = "technic:chainsaw", recipe = { {"technic:stainless_steel_ingot", trigger, "technic:battery"}, diff --git a/technic/tools/init.lua b/technic/tools/init.lua index c688e7a..db5ac7d 100644 --- a/technic/tools/init.lua +++ b/technic/tools/init.lua @@ -18,6 +18,7 @@ dofile(path.."/vacuum.lua") dofile(path.."/lawn_trimmer.lua") dofile(path.."/walking_tractor.lua") +dofile(path.."/planter.lua") if minetest.get_modpath("screwdriver") then -- compatibility alias diff --git a/technic/tools/lawn_trimmer.lua b/technic/tools/lawn_trimmer.lua index fa0004f..1be0d52 100644 --- a/technic/tools/lawn_trimmer.lua +++ b/technic/tools/lawn_trimmer.lua @@ -79,12 +79,15 @@ local function trim_the_lawn(itemstack, user) return -- no charge for even a single node, aborting end + local pos = user:get_pos() + minetest.sound_play("technic_lawn_trimmer", { - to_player = user:get_player_name(), +-- to_player = user:get_player_name(), + pos = pos, gain = 0.4, }) - local pos = user:get_pos() + -- Defining the area for the search needs two positions -- The tool has a limited range in the vertical axis, which is capped at +/- 1 node local start_pos = { diff --git a/technic/tools/planter.lua b/technic/tools/planter.lua new file mode 100644 index 0000000..0b1a2fe --- /dev/null +++ b/technic/tools/planter.lua @@ -0,0 +1,255 @@ +--[[ + Planter: a tool for placing rows of objects (primarily, farming plants) + Has 6 mods, corresponding to the width of the row (2...7 blocks). 1 block can be + always planted by hand. +]] + +-- Configuration +-- Intended to hold as much as the chainsaw, 20000 units +local planter_max_charge = 20000 +-- Can remove a curious number of objects +local planter_charge_per_object = 25 + + +local S = technic.getter + +local planter_mode_text = { + S("2 blocks wide planting"), + S("3 blocks wide planting"), + S("4 blocks wide planting"), + S("5 blocks wide planting"), + S("6 blocks wide planting"), + S("7 blocks wide planting"), +} + + +-- Mode switcher for the tool +local function planter_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 Planter modes.")) + meta.mode = 0 + end + + meta.mode = meta.mode % 6 + 1 + + minetest.chat_send_player(player_name, + S("Planter Mode %d"):format(meta.mode) .. ": " + .. planter_mode_text[meta.mode]) + itemstack:set_name("technic:planter_" .. 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 planter_setmode(user, itemstack, meta) + end + + meta.charge = meta.charge or 0 + + local offset = meta.mode + local offet_l = 0 + local offet_r = 0 + if offset % 2 > 0 then + offset_r = math.floor(offset/2) + 1 + offset_l = math.floor(offset/2) + else + offset_r = offset / 2 + offset_l = offset / 2 + end + + + if meta.charge < planter_charge_per_object * (offset+1) then + return -- no charge for a complete row + 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 + + local player_name = user:get_player_name() + local inv = user:get_inventory() + + if not inv:contains_item("main", ItemStack({name=meta.selected, count = 2*offset+1})) then + minetest.chat_send_player(player_name, S("Not enough " .. meta.selected .. " seeds to continue!")) + return itemstack + end + + minetest.sound_play("technic_walking_tractor", { +-- to_player = user:get_player_name(), + pos = user:get_pos(), + gain = 0.5, + }) + + local c = 0 + + 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 + + if ldir == 1 or ldir == 2 then + offset_r, offset_l = offset_l, offset_r + end + + local work_pos = {} + for delta = -offset_l,offset_r,1 do + + if ldir > 1 then + -- along z axis value (x changes) + work_pos = { + type = "node", + under = {x = pointed_thing.under.x + delta, y = pointed_thing.under.y, z = pointed_thing.under.z}, + above = {x = pointed_thing.under.x + delta, y = pointed_thing.under.y + 1, z = pointed_thing.under.z}, + ref = nil + } + else + -- along x axis value (z changes) + work_pos = { + type = "node", + under = {x = pointed_thing.under.x, y = pointed_thing.under.y, z = pointed_thing.under.z + delta}, + above = {x = pointed_thing.under.x, y = pointed_thing.under.y + 1, z = pointed_thing.under.z + delta}, + ref = nil + } + end + + if (minetest.registered_items[meta.selected] or {on_place=minetest.item_place}).on_place(ItemStack({name=meta.selected, count=1}), user, work_pos) then + c = c + 1 + end + + end + + + meta.charge = meta.charge - planter_charge_per_object * c + + -- 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 + inv:remove_item("main", ItemStack({name=meta.selected, count = c})) + technic.set_RE_wear(itemstack, meta.charge, planter_max_charge) + itemstack:set_metadata(minetest.serialize(meta)) + end + return itemstack +end + +local function select_plant(itemstack, user, pointed_thing) + if not user or not user:is_player() or user.is_fake_player then return end + local meta = minetest.deserialize(itemstack:get_metadata()) + + if not meta.selected then + meta.selected = "farming:seed_wheat" + itemstack:set_metadata(minetest.serialize(meta)) + end + + minetest.show_formspec(user:get_player_name(), "technic:planter_control", + "size[8,5]".. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "label[0,0;Crops selected:\n(Press to change)]".. + "item_image_button[2,0;1,1;" .. meta.selected .. ";change;]" .. + "button_exit[3,0;1,1;quit;Cancel]".. + "label[5,0; \nChange to:]".. + "list[current_player;main;7,0;1,1;31]" .. + "list[current_player;main;0,1;8,1;]" .. + "list[current_player;main;0,2;8,3;8]" .. + default.get_hotbar_bg(0,1)) + return +end + + +minetest.register_on_player_receive_fields(function(user, formname, fields) + + if formname ~= "technic:planter_control" then return false end + if not user or not user:is_player() or user.is_fake_player then return end + local itemstack = user:get_wielded_item() + if not string.find(itemstack:get_name(), "^technic:planter") then return true end + + local meta = minetest.deserialize(itemstack:get_metadata()) + + if fields.change then + local inv = user:get_inventory() + local item = inv:get_stack("main", 32) -- using the last cell + local n = item:get_name() + if n then + meta.selected = n + end + end + + itemstack:set_metadata(minetest.serialize(meta)) + user:set_wielded_item(itemstack) + select_plant(itemstack, user, nil) + return true +end) + + +-- Register the tool and its varieties in the game +technic.register_power_tool("technic:planter", planter_max_charge) +minetest.register_tool("technic:planter", { + description = S("Planter"), + inventory_image = "technic_planter.png", + stack_max = 1, + wear_represents = "technic_RE_charge", + on_refill = technic.refill_RE_charge, + on_use = work_on_soil, + on_place = select_plant, +}) + +for i = 1, 6 do + technic.register_power_tool("technic:planter_" .. i, planter_max_charge) + minetest.register_tool("technic:planter_" .. i, { + description = S("Planter Mode %d"):format(i), + inventory_image = "technic_planter.png^technic_tool_mode" .. i .. ".png", + wield_image = "technic_planter.png", + wear_represents = "technic_RE_charge", + on_refill = technic.refill_RE_charge, + groups = {not_in_creative_inventory = 1}, + on_use = work_on_soil, + on_place = select_plant, + }) +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:planter', + recipe = { + {'dye:red', 'technic:battery', trigger}, + {'technic:motor', 'technic:battery', 'default:stick'}, + {'default:chest', 'technic:stainless_steel_ingot', 'technic:rubber'}, + } +}) diff --git a/technic/tools/walking_tractor.lua b/technic/tools/walking_tractor.lua index e78375f..83e464c 100644 --- a/technic/tools/walking_tractor.lua +++ b/technic/tools/walking_tractor.lua @@ -117,6 +117,7 @@ local function work_on_soil(itemstack, user, pointed_thing) minetest.sound_play("technic_walking_tractor", { -- to_player = user:get_player_name(), + pos = user:get_pos(), gain = 0.5, }) |