mirror of
https://github.com/luanti-org/minetest_game.git
synced 2025-05-20 22:33:16 -04:00
173 lines
5 KiB
Lua
173 lines
5 KiB
Lua
|
|
local mode_text = {
|
|
{"Change rotation, Don't change axisdir."},
|
|
{"Keep choosen face in front then rotate it."},
|
|
{"Change axis dir, Reset rotation."},
|
|
{"Bring top in front then rotate it."},
|
|
}
|
|
|
|
-- Use Lua-friendly tables to avoid hash-lookups:
|
|
local opposite_faces = {
|
|
-- 0 1 2 3 4 5
|
|
5, 2, 1, 4, 3, 0
|
|
}
|
|
|
|
-- Rotational order for a given rotation axis as primary index:
|
|
-- Negative values indicate X rotation adjustments (rotate to opposite side),
|
|
-- 00 is just a visual indicator for invalid/unused axisdir indices.
|
|
-- Rotation order is always clockwise.
|
|
-- Layout: Row is selected by the face pointed at (the rotation axis),
|
|
-- current axisdir selects column, value is next axisdir:
|
|
local axis_rotations = {
|
|
-- 0 1 2 3 4 5
|
|
{00, 3, 4, 2, 1, 00}, -- Y+
|
|
{ 4, 00, 00, 0, 5, 3}, -- Z+
|
|
{ 3, 00, 00, 5, 0, 4}, -- Z-
|
|
{ 1, -5, 0, 00, 00, -2}, -- X+
|
|
{ 2, 0, -5, 00, 00, -1}, -- X-
|
|
{00, 4, 3, 1, 2, 00}, -- Y-
|
|
}
|
|
|
|
local function screwdriver_setmode(user,itemstack)
|
|
local player_name = user:get_player_name()
|
|
local item = itemstack:to_table()
|
|
local mode = tonumber(itemstack:get_metadata())
|
|
if not mode then
|
|
minetest.chat_send_player(player_name, "Hold shift and use to change screwdriwer modes.")
|
|
mode = 0
|
|
end
|
|
mode = mode + 1
|
|
if mode == 5 then
|
|
mode = 1
|
|
end
|
|
minetest.chat_send_player(player_name, "Screwdriver mode : "..mode.." - "..mode_text[mode][1] )
|
|
itemstack:set_name("screwdriver:screwdriver"..mode)
|
|
itemstack:set_metadata(mode)
|
|
return itemstack
|
|
end
|
|
|
|
local function get_node_face(pointed_thing)
|
|
local ax, ay, az = pointed_thing.above.x, pointed_thing.above.y, pointed_thing.above.z
|
|
local ux, uy, uz = pointed_thing.under.x, pointed_thing.under.y, pointed_thing.under.z
|
|
if ay > uy then return 0 -- Top
|
|
elseif az > uz then return 1 -- Z+ side
|
|
elseif az < uz then return 2 -- Z- side
|
|
elseif ax > ux then return 3 -- X+ side
|
|
elseif ax < ux then return 4 -- X- side
|
|
elseif ay < uy then return 5 -- Bottom
|
|
else
|
|
error("pointed_thing.above and under are the same!")
|
|
end
|
|
end
|
|
|
|
local function screwdriver_handler(itemstack, user, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return
|
|
end
|
|
local pos = pointed_thing.under
|
|
local keys = user:get_player_control()
|
|
local player_name = user:get_player_name()
|
|
local mode = tonumber(itemstack:get_metadata())
|
|
if not mode or keys["sneak"] == true then
|
|
return screwdriver_setmode(user, itemstack)
|
|
end
|
|
if minetest.is_protected(pos, user:get_player_name()) then
|
|
minetest.record_protection_violation(pos, user:get_player_name())
|
|
return
|
|
end
|
|
local node = minetest.get_node(pos)
|
|
local ndef = minetest.registered_nodes[node.name]
|
|
if not ndef or not ndef.paramtype2 == "facedir" or
|
|
(ndef.drawtype == "nodebox" and
|
|
not ndef.node_box.type == "fixed") or
|
|
node.param2 == nil then
|
|
return
|
|
end
|
|
|
|
-- Split current param2 facedir value into axisdir and rotation:
|
|
local rotation = node.param2 % 4
|
|
local axisdir = math.floor(node.param2 / 4) % 6
|
|
|
|
if mode == 1 then
|
|
rotation = rotation + 1
|
|
elseif mode == 2 then
|
|
-- rotates the pointed face clockwise:
|
|
local face = get_node_face(pointed_thing)
|
|
-- when rotating the top/bottom faces, only change rotation:
|
|
if axisdir == face then
|
|
rotation = rotation + 1
|
|
elseif axisdir == opposite_faces[face+1] then
|
|
rotation = rotation - 1
|
|
else
|
|
-- rotate side faces: get next axisdir from table:
|
|
axisdir = axis_rotations[face+1][axisdir+1]
|
|
|
|
-- handle rotation adjustment (to keep face in front):
|
|
if face == 0 then -- Y+ (top) axis rotation fix
|
|
rotation = rotation + 1
|
|
elseif face == 5 then -- Y- (bottom)
|
|
rotation = rotation - 1
|
|
elseif axisdir < 0 then -- X axis rotation fix
|
|
axisdir = -axisdir
|
|
rotation = rotation + 2
|
|
end
|
|
end
|
|
elseif mode == 3 then
|
|
axisdir = axisdir + 1
|
|
rotation = 0
|
|
elseif mode == 4 then
|
|
local face = get_node_face(pointed_thing)
|
|
if axisdir == face then
|
|
rotation = rotation + 1
|
|
else
|
|
axisdir = face
|
|
rotation = 0
|
|
end
|
|
end
|
|
|
|
-- recombine axisdir and rotation to facedir value:
|
|
node.param2 = (axisdir%6) * 4 + (rotation%4)
|
|
minetest.swap_node(pos, node)
|
|
|
|
if not minetest.setting_getbool("creative_mode") then
|
|
local item_wear = tonumber(itemstack:get_wear())
|
|
item_wear = item_wear + 327
|
|
if item_wear > 65535 then
|
|
itemstack:clear()
|
|
return itemstack
|
|
end
|
|
itemstack:set_wear(item_wear)
|
|
end
|
|
return itemstack
|
|
end
|
|
|
|
minetest.register_craft({
|
|
output = "screwdriver:screwdriver",
|
|
recipe = {
|
|
{"default:steel_ingot"},
|
|
{"group:stick"}
|
|
}
|
|
})
|
|
|
|
minetest.register_tool("screwdriver:screwdriver", {
|
|
description = "Screwdriver",
|
|
inventory_image = "screwdriver.png",
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
screwdriver_handler(itemstack, user, pointed_thing)
|
|
return itemstack
|
|
end,
|
|
})
|
|
|
|
for i = 1, 4 do
|
|
minetest.register_tool("screwdriver:screwdriver"..i, {
|
|
description = "Screwdriver in Mode "..i,
|
|
inventory_image = "screwdriver.png^tool_mode"..i..".png",
|
|
wield_image = "screwdriver.png",
|
|
groups = {not_in_creative_inventory=1},
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
screwdriver_handler(itemstack, user, pointed_thing)
|
|
return itemstack
|
|
end,
|
|
})
|
|
end
|
|
|