summaryrefslogtreecommitdiff
path: root/callbuttons.lua
diff options
context:
space:
mode:
Diffstat (limited to 'callbuttons.lua')
-rw-r--r--callbuttons.lua152
1 files changed, 152 insertions, 0 deletions
diff --git a/callbuttons.lua b/callbuttons.lua
new file mode 100644
index 0000000..97d839f
--- /dev/null
+++ b/callbuttons.lua
@@ -0,0 +1,152 @@
+local function makebuttontex(dir,upon,downon)
+ local tex = "[combine:64x64:0,0=celevator_cabinet_sides.png:32,0=celevator_cabinet_sides.png:0,32=celevator_cabinet_sides.png:32,32=celevator_cabinet_sides.png:22,24=celevator_callbutton_panel.png"
+ if dir == "up" then
+ tex = tex..":24,35=celevator_callbutton_up.png"
+ if upon then
+ tex = tex..":33,36=celevator_callbutton_light.png"
+ end
+ elseif dir == "down" then
+ tex = tex..":24,35=celevator_callbutton_down.png"
+ if downon then
+ tex = tex..":33,36=celevator_callbutton_light.png"
+ end
+ elseif dir == "both" then
+ tex = tex..":24,28=celevator_callbutton_up.png:24,43=celevator_callbutton_down.png"
+ if upon then
+ tex = tex..":33,29=celevator_callbutton_light.png"
+ end
+ if downon then
+ tex = tex..":33,44=celevator_callbutton_light.png"
+ end
+ end
+ return(tex)
+end
+
+local validstates = {
+ {"up",false,false,"Up"},
+ {"up",true,false,"Up"},
+ {"down",false,false,"Down"},
+ {"down",false,true,"Down"},
+ {"both",false,false,"Up and Down"},
+ {"both",true,false,"Up and Down"},
+ {"both",false,true,"Up and Down"},
+ {"both",true,true,"Up and Down"},
+}
+
+local function setlight(pos,dir,newstate)
+ local node = minetest.get_node(pos)
+ if minetest.get_item_group(node.name,"_celevator_callbutton") ~= 1 then return end
+ if dir == "up" then
+ if minetest.get_item_group(node.name,"_celevator_callbutton_has_up") ~= 1 then return end
+ local lit = minetest.get_item_group(node.name,"_celevator_callbutton_up_lit") == 1
+ if lit == newstate then return end
+ local newname = "celevator:callbutton_"
+ if minetest.get_item_group(node.name,"_celevator_callbutton_has_down") == 1 then
+ newname = newname.."both"
+ else
+ newname = newname.."up"
+ end
+ if newstate then newname = newname.."_upon" end
+ if minetest.get_item_group(node.name,"_celevator_callbutton_down_lit") == 1 then
+ newname = newname.."_downon"
+ end
+ node.name = newname
+ minetest.swap_node(pos,node)
+ elseif dir == "down" then
+ if minetest.get_item_group(node.name,"_celevator_callbutton_has_down") ~= 1 then return end
+ local lit = minetest.get_item_group(node.name,"_celevator_callbutton_down_lit") == 1
+ if lit == newstate then return end
+ local newname = "celevator:callbutton_"
+ if minetest.get_item_group(node.name,"_celevator_callbutton_has_up") == 1 then
+ newname = newname.."both"
+ else
+ newname = newname.."down"
+ end
+ if minetest.get_item_group(node.name,"_celevator_callbutton_up_lit") == 1 then
+ newname = newname.."_upon"
+ end
+ if newstate then newname = newname.."_downon" end
+ node.name = newname
+ minetest.swap_node(pos,node)
+ end
+end
+
+local function disambiguatedir(pos,player)
+ if player and not player.is_fake_player then
+ local eyepos = vector.add(player:get_pos(),vector.add(player:get_eye_offset(),vector.new(0,1.5,0)))
+ local lookdir = player:get_look_dir()
+ local distance = vector.distance(eyepos,pos)
+ local endpos = vector.add(eyepos,vector.multiply(lookdir,distance+1))
+ local ray = minetest.raycast(eyepos,endpos,true,false)
+ local pointed,button,hitpos
+ repeat
+ pointed = ray:next()
+ if pointed and pointed.type == "node" then
+ local node = minetest.get_node(pointed.under)
+ if node.name and (minetest.get_item_group(node.name,"_celevator_callbutton") == 1) then
+ button = pointed.under
+ hitpos = vector.subtract(pointed.intersection_point,button)
+ end
+ end
+ until button or not pointed
+ if not hitpos then return end
+ hitpos.y = -1*hitpos.y
+ hitpos.y = math.floor((hitpos.y+0.5)*64+0.5)+1
+ return hitpos.y >= 40 and "down" or "up"
+ end
+end
+
+for _,state in ipairs(validstates) do
+ local boringside = "[combine:64x64:0,0=celevator_cabinet_sides.png:32,0=celevator_cabinet_sides.png:0,32=celevator_cabinet_sides.png:32,32=celevator_cabinet_sides.png"
+ local nname = "celevator:callbutton_"..state[1]
+ local dropname = nname
+ if state[2] then nname = nname.."_upon" end
+ if state[3] then nname = nname.."_downon" end
+ local idle = not (state[2] or state[3])
+ local description = string.format("%s Call Button%s",state[4],(idle and "" or " (on state, you hacker you!)"))
+ minetest.register_node(nname,{
+ description = description,
+ groups = {
+ dig_immediate = 2,
+ not_in_creative_inventory = (idle and 0 or 1),
+ _celevator_callbutton = 1,
+ _celevator_callbutton_has_up = (state[1] == "down" and 0 or 1),
+ _celevator_callbutton_has_down = (state[1] == "up" and 0 or 1),
+ _celevator_callbutton_up_lit = (state[2] and 1 or 0),
+ _celevator_callbutton_down_lit = (state[3] and 1 or 0),
+ },
+ drop = dropname,
+ tiles = {
+ boringside,
+ boringside,
+ boringside,
+ boringside,
+ boringside,
+ makebuttontex(state[1],state[2],state[3])
+ },
+ paramtype = "light",
+ paramtype2 = "facedir",
+ drawtype = "nodebox",
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
+ {-0.16, -0.37,-0.59, 0.17, 0.13,-0.5 },
+ },
+ },
+ on_rightclick = function(pos,_,clicker)
+ if state[1] == "up" then
+ setlight(pos,"up",not state[2])
+ elseif state[1] == "down" then
+ setlight(pos,"down",not state[3])
+ elseif state[1] == "both" then
+ local dir = disambiguatedir(pos,clicker)
+ if dir == "up" then
+ setlight(pos,"up",not state[2])
+ elseif dir == "down" then
+ setlight(pos,"down",not state[3])
+ end
+ end
+ end,
+ })
+end