summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--technic/textures/technic_chainsaw_mini.pngbin0 -> 546 bytes
-rw-r--r--technic/textures/technic_planter.pngbin0 -> 468 bytes
-rw-r--r--technic/tools/chainsaw.lua109
-rw-r--r--technic/tools/init.lua1
-rw-r--r--technic/tools/lawn_trimmer.lua7
-rw-r--r--technic/tools/planter.lua255
-rw-r--r--technic/tools/walking_tractor.lua1
7 files changed, 369 insertions, 4 deletions
diff --git a/technic/textures/technic_chainsaw_mini.png b/technic/textures/technic_chainsaw_mini.png
new file mode 100644
index 0000000..b91ca13
--- /dev/null
+++ b/technic/textures/technic_chainsaw_mini.png
Binary files differ
diff --git a/technic/textures/technic_planter.png b/technic/textures/technic_planter.png
new file mode 100644
index 0000000..188f733
--- /dev/null
+++ b/technic/textures/technic_planter.png
Binary files differ
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,
})