Add chests, doors, and levers, and improve progressive interaction.

This commit is contained in:
Signal 2025-11-11 01:29:41 -05:00
parent 6439f11c2f
commit 8f98a7fa2d
18 changed files with 692 additions and 107 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 B

After

Width:  |  Height:  |  Size: 172 B

Before After
Before After

View file

@ -1,14 +1,94 @@
local function make_lever_entity(pos) local levers = {}
minetest.register_entity(":artifact:lever_display", {
initial_properties = {
visual = "mesh",
mesh = "artifact_lever.gltf",
textures = {"artifact_lever_wood.png"},
seelctionbox = {
}
},
_interact_time = 0.3,
_interact_marker_offset = function(e)
return vector.new(0, -0.4, 0):rotate(e.rotation)
end,
on_activate = function(e, data)
if not minetest.get_node(e.object:get_pos()).name:find "lever" then
e.object:remove()
return
end end
e.object:set_armor_groups{immortal = 1}
extend(e, minetest.deserialize(data) or {})
levers[e.object:get_pos():round():to_string()] = e
end,
on_deactivte = function(e)
levers[e.object:get_pos():round():to_string()] = nil
end,
get_staticdata = function(e)
return {rotation = e.rotation}
end,
on_interact = function(e)
if e._active then
e._active = false
e._no_interact = true
e.object:set_animation({x=1,y=2}, 2, 0.1, false)
minetest.after(0.5, function()
e._no_interact = nil
end)
else
e._active = true
e._no_interact = true
e.object:set_animation({x=0,y=1}, 2, 0.1, false)
minetest.after(0.5, function()
e._no_interact = nil
end)
end
end,
rotate = function(e, rot)
e.object:set_rotation(rot)
e.rotation = rot
e.object:set_properties {
selectionbox = artifact.rotate_selectionbox({
-3/16, -0.5, -4/16,
3/16, -3/16, 4/16
}, e.rotation)
}
end
})
artifact.register_node("lever", { artifact.register_node("lever", {
drawtype = "airlike", drawtype = "airlike",
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
paramtype2 = "facedir", paramtype2 = "facedir",
pointable = false,
on_construct = function(pos) on_construct = function(pos)
local m = minetest.get_meta(pos)
m:set_string("initialized", "true")
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
minetest.add_entity(pos, "artifact:lever_display", minetest.serialize{type = "wood"}):get_luaentity():rotate(rot)
end,
on_destruct = function(pos)
levers[pos:to_string()].object:remove()
levers[pos:to_string()] = nil
end,
on_load = function(pos)
local m = minetest.get_meta(pos)
-- Dynamically initialize doors that were mapgen'd in.
if not m:contains("initialized") then
m:set_string("initialized", "true")
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
minetest.add_entity(pos, "artifact:lever_display", minetest.serialize{type = "wood"}):get_luaentity():rotate(rot)
end
end,
on_rotate = function(pos, node, p, click, param2)
local node = minetest.get_node(pos)
node.param2 = param2
minetest.swap_node(pos, node)
local rot = minetest.facedir_to_dir(node.param2):dir_to_rotation()
levers[pos:to_string()]:rotate(rot)
return true
end end
}) })

View file

@ -0,0 +1,182 @@
local ns = artifact
local chests = {}
minetest.register_entity(":artifact:chest_slot", {
initial_properties = {
static_save = false,
visual = "mesh",
mesh = "artifact_animator.gltf",
selectionbox = {-0.2, -0.2, -0.2, 0.2, 0.2, 0.2}
},
_interact_time = 0.25,
on_activate = function(e, item)
e._visual = minetest.add_entity(e.object:get_pos(), "display")
e._visual:set_properties {
visual = "item",
wield_item = item,
pointable = false
}
e._visual:set_attach(e.object, "root")
-- That's _one_ way to get a unique ID...
e._name = ""..math.random()
end,
on_deactivate = function(e)
e._visual:remove()
end,
on_hover = function(e, m)
e.object:set_bone_override("root", {
scale = {
vec = vector.new(0.15, 0.15, 0.15), interpolation = 0.2, absolute = true
},
position = {
vec = vector.new(0, 0.01, 0), interpolation = 0.2, absolute = true
}
})
end,
on_unhover = function(e, m)
e.object:set_bone_override("root", {
scale = {
vec = vector.new(0.1, 0.1, 0.1), interpolation = 0.2, absolute = true
},
position = {
vec = vector.new(0, 0.01, 0), interpolation = 0.2, absolute = true
}
})
end
})
minetest.register_entity(":artifact:chest_display", {
initial_properties = {
visual = "mesh",
mesh = "artifact_chest.gltf",
textures = {"artifact_chest_wood.png"},
},
_interact_time = 0.6,
_interact_marker_offset = function(e)
return vector.new(0, 0, 0.5):rotate(e.object:get_rotation())
end,
on_activate = function(e, data)
if not minetest.get_node(e.object:get_pos()).name:find "chest" then
e.object:remove()
return
end
e.object:set_armor_groups{immortal = 1}
e._pos = minetest.deserialize(data)
chests[vector.to_string(e._pos)] = e
end,
on_deactivate = function(e)
chests[vector.to_string(e._pos)] = nil
end,
get_staticdata = function(e)
return minetest.serialize(e._pos)
end,
on_interact = function(e)
e:open()
end,
on_step = function(e)
if e._open then
local found = false
for obj in minetest.objects_inside_radius(e.object:get_pos(), 5) do
if minetest.is_player(obj) then
found = true
break
end
end
if not found then
e:close()
end
end
end,
open = function(e)
e._open = true
e._no_interact = true
e.object:set_properties{pointable = false}
e.object:set_animation({x=0,y=0.5}, 1, 0.1, false)
local pos = e.object:get_pos()
local rot = e.object:get_rotation()
e._slot_main = minetest.add_entity(pos +vector.new(0.2, 0.1, 0):rotate(rot), "artifact:chest_slot", "artifact:stone"):get_luaentity()
e._slot_main.object:set_bone_override("root", {
scale = {
vec = vector.new(0.01, 0.01, 0.01), absolute = true
},
position = {
vec = vector.new(0, -5, 0), absolute = true
}
})
minetest.after(0, function()
e._slot_main.object:set_bone_override("root", {
scale = {
vec = vector.new(0.1, 0.1, 0.1), interpolation = 0.4, absolute = true
},
position = {
vec = vector.new(0, 0.01, 0), interpolation = 0.4, absolute = true
}
})
end)
e._slot_main.master = e
e._slot_main.on_interact = function()
end
e._slot_cancel = minetest.add_entity(pos +vector.new(-0.2, 0.1, 0):rotate(rot), "artifact:chest_slot", "artifact:cancel"):get_luaentity()
e._slot_cancel.object:set_bone_override("root", {
scale = {
vec = vector.new(0.01, 0.01, 0.01), absolute = true
},
position = {
vec = vector.new(0, -5, 0), absolute = true
}
})
minetest.after(0, function()
e._slot_cancel.object:set_bone_override("root", {
scale = {
vec = vector.new(0.1, 0.1, 0.1), interpolation = 0.4, absolute = true
},
position = {
vec = vector.new(0, 0.01, 0), interpolation = 0.4, absolute = true
}
})
end)
e._slot_cancel.master = e
e._slot_cancel.on_interact = function()
e:close()
end
end,
close = function(e)
e._open = false
e._no_interact = nil
e.object:set_properties{pointable = true}
e.object:set_animation({x=0.5,y=1}, 1, 0.1, false)
e._slot_main.object:remove()
e._slot_cancel.object:remove()
end
})
artifact.register_node("chest", {
drawtype = "airlike",
paramtype = "light",
paramtype2 = "facedir",
pointable = false,
groups = {call_on_load = 1},
on_construct = function(pos)
local m = minetest.get_meta(pos)
m:set_string("initialized", "true")
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
rot.y = rot.y -math.pi
minetest.add_entity(pos, "artifact:chest_display", minetest.serialize(pos)):set_rotation(rot)
end,
on_destruct = function(pos)
chests[pos:to_string()].object:remove()
chests[pos:to_string()] = nil
end,
on_load = function(pos)
local m = minetest.get_meta(pos)
-- Dynamically initialize chests that were mapgen'd in.
if not m:contains("initialized") then
m:set_string("initialized", "true")
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
rot.y = rot.y -math.pi
minetest.add_entity(pos, "artifact:chest_display", minetest.serialize(pos)):set_rotation(rot)
end
end
})

View file

@ -0,0 +1,197 @@
local doors = {}
function artifact.rotate_selectionbox(box, rot)
local a = vector.new(box[1], box[2], box[3]):rotate(rot)
local b = vector.new(box[4], box[5], box[6]):rotate(rot)
return {
a.x, a.y, a.z,
b.x, b.y, b.z
}
end
minetest.register_entity(":artifact:door", {
initial_properties = {
visual = "mesh",
mesh = "artifact_door.gltf",
textures = {"artifact_door_wood.png"},
selectionbox = {
-0.5, -0.5, -0.5,
0.5, 1.5, -6/16
}
},
_interact_time = 0.2,
_interact_marker_offset = function(e)
return (e._open and vector.new(-0.5, 0.5, 0) or vector.new(0, 0.5, 0.5)):rotate(e.object:get_rotation())
end,
on_activate = function(e, data)
if not minetest.get_node(e.object:get_pos()).name:find "door" then
e.object:remove()
return
end
e.object:set_armor_groups{immortal = 1}
extend(e, minetest.deserialize(data) or {})
if e.type == "iron" and e._locked == nil then
e._locked = true
e.object:set_properties {
textures = {"artifact_door_iron.png"},
}
end
if e.rotation then
e.rotation.y = e.rotation.y +math.pi
e:rotate(e.rotation)
end
if e._locked then
e._no_interact = true
end
e._name = ""..math.random()
doors[e.object:get_pos():round():to_string()] = e
end,
on_deactivate = function(e)
doors[e.object:get_pos():round():to_string()] = nil
end,
on_interact = function(e)
if e._open then
e._open = nil
e._no_interact = true
e._name = ""..math.random()
e.object:set_animation({x=0.5,y=1}, 1.5, 0.1, false)
minetest.after(0.1, function()
local pos = e.object:get_pos():round()
local node = minetest.get_node(pos)
node.name = "door_"..e.type
minetest.swap_node(pos, node)
e.object:set_properties {
selectionbox = artifact.rotate_selectionbox({
-0.5, -0.5, -0.5,
0.5, 1.5, -6/16
}, e.rotation)
}
end)
minetest.after(0.25, function()
e._no_interact = nil
end)
else
e._open = true
e._no_interact = true
e._name = ""..math.random()
e.object:set_animation({x=0,y=0.5}, 1.5, 0.1, false)
minetest.after(0.1, function()
local pos = e.object:get_pos():round()
local node = minetest.get_node(pos)
node.name = "door_"..e.type.."_open"
minetest.swap_node(pos, node)
e.object:set_properties {
selectionbox = artifact.rotate_selectionbox({
0.5, -0.5, -0.5,
6/16, 1.5, 0.5
}, e.rotation)
}
end)
minetest.after(0.25, function()
e._no_interact = nil
end)
end
end,
get_staticdata = function(e)
return minetest.serialize{type = e.type, _locked = e._locked, rotation = e.rotation}
end,
unlock = function(e)
if e._locked then
e._locked = false
e._no_interact = nil
end
end,
rotate = function(e, rot)
e.object:set_rotation(rot)
rot.y = rot.y -math.pi
e.rotation = rot
e.object:set_properties {
selectionbox = artifact.rotate_selectionbox(e.object:get_properties().selectionbox, e.rotation)
}
end
})
local function register_basic_door(type)
artifact.register_node("door_"..type, {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-0.5, -0.5, -0.5,
0.5, 1.5, -6/16
}
},
paramtype2 = "facedir",
tiles = {"blank.png"},
use_texture_alpha = "clip",
paramtype = "light",
pointable = false,
groups = {call_on_load = 1, whackable = type == "wood" and 1 or nil},
on_construct = function(pos)
local m = minetest.get_meta(pos)
m:set_string("initialized", "true")
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
rot.y = rot.y -math.pi
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
end,
on_destruct = function(pos, reason)
if reason == "whack" then
-- TODO: Particles
end
doors[pos:to_string()].object:remove()
doors[pos:to_string()] = nil
end,
on_load = function(pos)
local m = minetest.get_meta(pos)
-- Dynamically initialize doors that were mapgen'd in.
if not m:contains("initialized") then
m:set_string("initialized", "true")
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
rot.y = rot.y -math.pi
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
end
end
})
artifact.register_node("door_"..type.."_open", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
0.5, -0.5, -0.5,
6/16, 1.5, 0.5
}
},
paramtype2 = "facedir",
tiles = {"blank.png"},
use_texture_alpha = "clip",
paramtype = "light",
pointable = false,
groups = {call_on_load = 1, whackable = type == "wood" and 1 or nil},
on_construct = function(pos)
local m = minetest.get_meta(pos)
m:set_string("initialized", "true")
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
rot.y = rot.y -math.pi
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
end,
on_destruct = function(pos)
doors[pos:to_string()].object:remove()
doors[pos:to_string()] = nil
end,
on_load = function(pos)
local m = minetest.get_meta(pos)
-- Dynamically initialize doors that were mapgen'd in.
if not m:contains("initialized") then
m:set_string("initialized", "true")
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
rot.y = rot.y -math.pi
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
end
end
})
end
register_basic_door("wood")
register_basic_door("iron")

View file

@ -9,22 +9,10 @@ minetest.register_entity(":display", {
end end
}) })
artifact.register_craftitem("cancel", {
inventory_image = "artifact_cancel.png"
minetest.register_entity(":test", {
initial_properties = {
visual = "sprite",
textures = {"blank.png"},
use_texture_alpha = true,
static_save = false
},
on_rightclick = function(e, p)
artifact.players[p:get_player_name()].interacting_with = e
end,
on_hover = function() say "!" end,
on_interact = function(e, m)
end
}) })
include "basics.lua" include "basics.lua"
include "doors.lua"
include "chest.lua"

View file

@ -0,0 +1 @@
{"asset":{"version":"2.0","generator":"Blockbench 4.12.5 glTF exporter"},"scenes":[{"nodes":[2],"name":"blockbench_export"}],"scene":0,"nodes":[{"name":"cube","mesh":0},{"name":"root","children":[0]},{"children":[1]}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":288,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":576,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":768,"byteLength":72,"target":34963}],"buffers":[{"byteLength":840,"uri":"data:application/octet-stream;base64,C9cjOvYoID8L1yM6C9cjOvYoID8AAAAAC9cjOgAAID8L1yM6C9cjOgAAID8AAAAAAAAAAPYoID8AAAAAAAAAAPYoID8L1yM6AAAAAAAAID8AAAAAAAAAAAAAID8L1yM6AAAAAPYoID8AAAAAC9cjOvYoID8AAAAAAAAAAPYoID8L1yM6C9cjOvYoID8L1yM6AAAAAAAAID8L1yM6C9cjOgAAID8L1yM6AAAAAAAAID8AAAAAC9cjOgAAID8AAAAAAAAAAPYoID8L1yM6C9cjOvYoID8L1yM6AAAAAAAAID8L1yM6C9cjOgAAID8L1yM6C9cjOvYoID8AAAAAAAAAAPYoID8AAAAAC9cjOgAAID8AAAAAAAAAAAAAID8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUA"}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[0.0006250000442378223,0.6256250143051147,0.0006250000442378223],"min":[0,0.625,0],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"max":[0,0],"min":[0,0],"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0,"roughnessFactor":1},"alphaMode":"MASK","alphaCutoff":0.05,"doubleSided":true}],"meshes":[{"primitives":[{"mode":4,"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0}]}]}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"asset":{"version":"2.0","generator":"Blockbench 4.12.5 glTF exporter"},"scenes":[{"nodes":[2],"name":"blockbench_export"}],"scene":0,"nodes":[{"translation":[4.375,0,-4.375],"name":"cube","mesh":0},{"translation":[-4.375,0,-4.375],"name":"door","children":[0]},{"children":[1]}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":288,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":576,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":768,"byteLength":72,"target":34963},{"buffer":0,"byteOffset":840,"byteLength":64},{"buffer":0,"byteOffset":904,"byteLength":256}],"buffers":[{"byteLength":1160,"uri":"data:application/octet-stream;base64,AACgQAAAcEEAAKBAAACgQAAAcEEAAHBAAACgQAAAoMAAAKBAAACgQAAAoMAAAHBAAACgwAAAcEEAAHBAAACgwAAAcEEAAKBAAACgwAAAoMAAAHBAAACgwAAAoMAAAKBAAACgwAAAcEEAAHBAAACgQAAAcEEAAHBAAACgwAAAcEEAAKBAAACgQAAAcEEAAKBAAACgwAAAoMAAAKBAAACgQAAAoMAAAKBAAACgwAAAoMAAAHBAAACgQAAAoMAAAHBAAACgwAAAcEEAAKBAAACgQAAAcEEAAKBAAACgwAAAoMAAAKBAAACgQAAAoMAAAKBAAACgQAAAcEEAAHBAAACgwAAAcEEAAHBAAACgQAAAoMAAAHBAAACgwAAAoMAAAHBAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAD8AAAA9AAAAPwAAAAAAAIA/AAAAPQAAgD8AAAA/AAAAAAAACD8AAAAAAAAAPwAAAD8AAAg/AAAAPwAAkD4AAAg/AAAAPQAACD8AAJA+AAAAPwAAAD0AAAA/AAAIPwAAAD8AAJA+AAAAPwAACD8AAAg/AACQPgAACD8AAIA+AAAAAAAAAD8AAAAAAACAPgAAAD8AAAA/AAAAPwAAAAAAAAAAAACAPgAAAAAAAAAAAAAAPwAAgD4AAAA/AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUAAAAAAKuqKj2rqqo9AAAAPlVVVT5VVZU+q6qqPgAAwD5VVdU+AAAAP1VVFT+rqio/AABAP1VVVT+rqmo/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAPnsAvAAAAAD8/X8/AAAAAAQLCL0AAAAA2Nt/PwAAAABsyaW9AAAAAOsofz8AAAAAKj6FvgAAAADkLXc/AAAAAOxY/74AAAAA/eNdPwAAAABOiRa/AAAAAPUPTz8AAAAAisUlvwAAAAAxFEM/AAAAADvoLr8AAAAAie46PwAAAADzBDW/AAAAAPMENT8AAAAAriAvvwAAAACnuTo/AAAAAIrMFr8AAAAAAt9OPwAAAAAV78O+AAAAAF6DbD8AAAAAkpgevgAAAAA16Xw/AAAAABU2A70AAAAAXt5/PwAAAAAAAAAAAAAAAAAAgD8="}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[5,15,5],"min":[-5,-5,3.75],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"max":[0.53125,1],"min":[0,0],"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"},{"bufferView":4,"componentType":5126,"count":16,"max":[1],"min":[0],"type":"SCALAR"},{"bufferView":5,"componentType":5126,"count":16,"max":[0,0,0,1],"min":[0,-0.7071067690849304,0,0.7071067690849304],"type":"VEC4"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0,"roughnessFactor":1,"baseColorTexture":{"index":0}},"alphaMode":"MASK","alphaCutoff":0.05,"doubleSided":true}],"textures":[{"sampler":0,"source":0,"name":"artifact_door_wood"}],"samplers":[{"magFilter":9728,"minFilter":9728,"wrapS":33071,"wrapT":33071}],"images":[{"mimeType":"image/png","name":"artifact_door_wood.png","uri":"artifact_door_wood.png"}],"meshes":[{"primitives":[{"mode":4,"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0}]}],"animations":[{"name":"animation","samplers":[{"input":4,"output":5,"interpolation":"LINEAR"}],"channels":[{"sampler":0,"target":{"node":1,"path":"rotation"}}]}]}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 972 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

View file

@ -67,9 +67,13 @@ Player = setmetatable({
local yaw = p:get_look_horizontal() local yaw = p:get_look_horizontal()
local pitch = p:get_look_vertical() local pitch = p:get_look_vertical()
local dir = p:get_look_dir() local dir = p:get_look_dir()
local vel = p:get_velocity()
local speed = vel:length()
m.pos = pos m.pos = pos
m.pos.y = m.pos.y +m.eye_height m.pos.y = m.pos.y +m.eye_height
-- MARK: Pointing callbacks
local pointed_found = nil local pointed_found = nil
m.pointed_node = nil m.pointed_node = nil
for x in minetest.raycast(m.pos, m.pos +(dir *5)) do for x in minetest.raycast(m.pos, m.pos +(dir *5)) do
@ -83,22 +87,26 @@ Player = setmetatable({
m.pointed_obj:on_unhover(m) m.pointed_obj:on_unhover(m)
end end
if m.pointed_obj.on_interact and m.interaction_marker then if m.pointed_obj.on_interact and m.interaction_marker then
m.interaction_marker:remove() m.object:hud_remove(m.interaction_marker)
m.interaction_marker = nil m.interaction_marker = nil
m.interaction_start = nil
end end
end end
if e.on_interact and not e._no_interact and (not names_match or names_match and not m.interaction_marker) then
if m.interaction_marker then m.object:hud_remove(m.interaction_marker) end
local dst = e.object:get_pos()
if e._interact_marker_offset then dst = dst +e:_interact_marker_offset() end
m.interaction_marker = m.object:hud_add {
type = "image_waypoint",
world_pos = dst,
scale = {x=3, y=3},
text = "artifact_rmb.png"
}
end
if (m.pointed_obj and not names_match and e.on_hover) or not m.pointed_obj then if (m.pointed_obj and not names_match and e.on_hover) or not m.pointed_obj then
if e.on_hover then if e.on_hover then
e:on_hover(m) e:on_hover(m)
end end
if e.on_interact then
if m.interaction_marker then m.interaction_marker:remove() end
m.interaction_marker = minetest.add_entity(e.object:get_pos(), "display")
m.interaction_marker:set_properties {
visual = "sprite",
textures = {"artifact_rmb.png"}
}
end
pointed_found = true pointed_found = true
m.pointed_obj = e m.pointed_obj = e
break break
@ -109,6 +117,18 @@ Player = setmetatable({
end end
elseif x and x.type == "node" then elseif x and x.type == "node" then
m.pointed_node = x m.pointed_node = x
if m.pointed_obj then
if m.pointed_obj.on_unhover then
m.pointed_obj:on_unhover(m)
end
if m.pointed_obj.on_interact and m.interaction_marker then
m.object:hud_remove(m.interaction_marker)
m.interaction_marker = nil
m.interaction_start = nil
end
m.pointed_obj = nil
end
break
end end
end end
if not pointed_found and m.pointed_obj then if not pointed_found and m.pointed_obj then
@ -116,52 +136,89 @@ Player = setmetatable({
m.pointed_obj:on_unhover(m) m.pointed_obj:on_unhover(m)
end end
if m.pointed_obj.on_interact and m.interaction_marker then if m.pointed_obj.on_interact and m.interaction_marker then
m.interaction_marker:remove() m.object:hud_remove(m.interaction_marker)
m.interaction_marker = nil m.interaction_marker = nil
m.interaction_start = nil
end end
m.pointed_obj = nil m.pointed_obj = nil
end end
local ctl = m.object:get_player_control() local ctl = m.object:get_player_control()
if ctl.place and not m.ctl.place and m.pointed_obj and m.pointed_obj.on_interact then -- MARK: Animations
local moving = (ctl.up or ctl.down or ctl.left or ctl.right) and speed > 0.1
if moving then
m.moving = true
if ctl.aux1 and ctl.up then
if p:get_animation().y ~= 2 then p:set_animation({x=1, y=2}, 1.5, 0.2, true) end
p:set_physics_override{
speed = 1.5
}
else
if p:get_animation().y ~= 1 then p:set_animation({x=0, y=1}, 1.5, 0.2, true) end
p:set_physics_override{
speed = 1
}
end
else
m.moving = false
if p:get_animation().y ~= 0 then p:set_animation({x=0, y=0}) end
end
if not m.rot then m.rot = 0 end
if moving then
local fac = 0
if ctl.left then fac = 30 elseif ctl.right then fac = -30 end
m.rot = yaw +math.rad(fac)
elseif math.abs(yaw -m.rot) > math.rad(40) then
m.rot = m.rot +(yaw -(m.yaw or 0))
end
m.rot = m.rot %(math.pi *2)
p:set_bone_override("Head", {
rotation = {vec = vector.new(math.min(math.max(pitch, math.rad(-60)), math.rad(60)),-(yaw -m.rot),0), interpolation = 0.1, absolute = true}
})
p:set_bone_override("root", {
rotation = {vec = vector.new(0,yaw -m.rot,0), interpolation = 0.1, absolute = true}
})
-- MARK: Progressive interaction
if ctl.place and m.ctl.place and m.pointed_obj and m.pointed_obj.on_interact and not m.pointed_obj._no_interact then
if not m.interaction_start then if not m.interaction_start then
m.interaction_start = time m.interaction_start = time
-- m.interaction_marker = minetest.add_entity(m.pointed_obj, "display")
-- m.interaction_marker:set_properties {
-- visual = "sprite",
-- textures = {"rgt_interact_progress_0.png"}
-- }
else else
if time -m.interaction_start > 1100000 then local duration = (m.pointed_obj._interact_time or 1) *1000000
m.interaction_marker:remove() local progress = (time -m.interaction_start) /duration
if progress > 1.1 then
m.pointed_obj:on_interact(m) m.pointed_obj:on_interact(m)
elseif time -m.interaction_start > 1000000 then
m.interaction_marker:set_properties {
textures = {"artifact_rmb_100.png"}
}
elseif time -m.interaction_start > 750000 then
m.interaction_marker:set_properties {
textures = {"artifact_rmb_75.png"}
}
elseif time -m.interaction_start > 500000 then
m.interaction_marker:set_properties {
textures = {"artifact_rmb_50.png"}
}
elseif time -m.interaction_start > 250000 then
m.interaction_marker:set_properties {
textures = {"artifact_rmb_25.png"}
}
end
end
elseif not ctl.place and m.ctl.place and m.interaction_start then
m.interacting_with = nil
m.interaction_start = nil m.interaction_start = nil
m.object:hud_remove(m.interaction_marker)
m.interaction_marker = nil
elseif progress > 1 then
m.object:hud_change(m.interaction_marker, "text", "artifact_rmb_100.png")
elseif progress > 0.75 then
m.object:hud_change(m.interaction_marker, "text", "artifact_rmb_75.png")
elseif progress > 0.5 then
m.object:hud_change(m.interaction_marker, "text", "artifact_rmb_50.png")
elseif progress > 0.25 then
m.object:hud_change(m.interaction_marker, "text", "artifact_rmb_25.png")
end
end
elseif not ctl.place and m.interaction_start and (not m.pointed_obj or not m.pointed_obj._no_interact) then
m.interaction_start = nil
if m.interaction_marker then
m.object:hud_change(m.interaction_marker, "text", "artifact_rmb.png")
end
end end
local wi = p:get_wielded_item() local wi = p:get_wielded_item()
m.wielded_item = wi m.wielded_item = wi
-- MARK: Radial menu handling
if ctl.place and not m.ctl.place and wi:get_name() == "artifact:input" then if ctl.place and not m.ctl.place and wi:get_name() == "artifact:input" then
artifact.show_radial_menu(m, { artifact.show_radial_menu(m, {
name = "construct", name = "construct",
@ -239,37 +296,17 @@ Player = setmetatable({
end, end,
-- Initialize the player's primary HUD display based on saved state. -- Initialize the player's primary HUD display based on saved state.
create_hud = function(m) create_hud = function(m)
-- If called post-init, make sure we delete the previous HUD. m.healthbar = m.object:hud_add {
-- This is useful when we want to recreate the HUD in response type = "statbar",
-- to an event, like freeing Vix. position = {x=0.5,y=1},
-- if m.hud then offset = {x=-27 *5,y=artifact.debug and -96 or -30},
-- for _, x in pairs(m.hud) do scale = {x=4,y=4},
-- if type(x) == "table" then alignment = {x=-1, y=-1},
-- for _, y in pairs(x) do size = {x=27,y=27},
-- m.object:hud_remove(y) text = "artifact_heart_vix.png",
-- end text2 = "artifact_heart_bg.png",
-- else number = 20
-- m.object:hud_remove(x) }
-- end
-- end
-- end
-- m.hud = {
-- key_health = m.object:hud_add {
-- type = "statbar",
-- position = {x=0.5,y=1},
-- offset = {x=-27 *5,y=artifact.debug and -96 or -30},
-- scale = {x=4,y=4},
-- alignment = {x=-1, y=-1},
-- size = {x=27,y=27},
-- text = "artifact_heart_vix.png",
-- text2 = "artifact_heart_bg.png",
-- number = 20
-- }
-- }
--
-- if artifact.debug or artifact.story.states[artifact.story.get_state()] >= artifact.story.states.main then
--
-- end
end, end,
set_hotbar_size = function(m, slots) set_hotbar_size = function(m, slots)
local p = m.object local p = m.object
@ -289,6 +326,7 @@ Player = setmetatable({
artifact.register_craftitem("input", { artifact.register_craftitem("input", {
inventory_image = "artifact_rmb_100.png", inventory_image = "artifact_rmb_100.png",
range = 0,
on_drop = function(s, p, pos) on_drop = function(s, p, pos)
local m = artifact.players[p:get_player_name()] local m = artifact.players[p:get_player_name()]
if artifact.debug or artifat.story.state > artifact.story.states.pre_vix then if artifact.debug or artifat.story.state > artifact.story.states.pre_vix then
@ -313,3 +351,7 @@ minetest.register_on_joinplayer(function(p)
minetest.registered_chatcommands.grantme.func(p:get_player_name(), "all") minetest.registered_chatcommands.grantme.func(p:get_player_name(), "all")
end end
end) end)
minetest.register_on_leaveplayer(function(p)
artifact.players[p:get_player_name()] = nil
end)

View file

@ -11,6 +11,15 @@ function artifact.register_node(name, def)
if not def.groups then def.groups = {} end if not def.groups then def.groups = {} end
def.groups.dig_immediate = 3 def.groups.dig_immediate = 3
end end
if def._variants then
for _, x in ipairs(def._variants) do
if x == "slab" then
artifact.register_slab(def)
elseif x == "stair" then
artifact.register_stair(def)
end
end
end
minetest.register_node(":"..name, def) minetest.register_node(":"..name, def)
if name ~= def._name then if name ~= def._name then
minetest.register_alias(def._name, name) minetest.register_alias(def._name, name)
@ -28,6 +37,58 @@ function artifact.register_craftitem(name, def)
end end
end end
function artifact.register_slab(def)
def = table.copy(def)
def._variants = nil
artifact.register_node(def._name.."_slab", extend(def, {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}
},
paramtype = "light",
paramtype2 = "facedir"
}))
end
function artifact.register_stair(def)
def = table.copy(def)
def._variants = nil
def.groups[def._name.."_stair"] = 1
artifact.register_node(def._name.."_stair", extend(table.copy(def), {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {{-0.5, -0.5, -0.5, 0.5, 0, 0.5}, {-0.5, -0.5, 0, 0.5, 0.5, 0.5}}
},
paramtype = "light",
paramtype2 = "facedir"
}))
artifact.register_node(def._name.."_stair_inner", extend(table.copy(def), {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {{-0.5, -0.5, -0.5, 0.5, 0, 0.5}, {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, {-0.5, -0.5, -0.5, 0, 0.5, 0.5}}
},
paramtype = "light",
paramtype2 = "facedir"
}))
artifact.register_node(def._name.."_stair_outer", extend(def, {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {{-0.5, -0.5, -0.5, 0.5, 0, 0.5}, {-0.5, 0, 0.5, 0, 0.5, 0}}
},
paramtype = "light",
paramtype2 = "facedir"
}))
end
local function rep(tx, size) local function rep(tx, size)
local out = "[combine:"..(size *16).."x"..(size *16) local out = "[combine:"..(size *16).."x"..(size *16)
for x = 0, size -1 do for x = 0, size -1 do
@ -39,29 +100,36 @@ local function rep(tx, size)
end end
artifact.register_node("stone", { artifact.register_node("stone", {
tiles = {"artifact_stone.png"} tiles = {{name = "artifact_stone.png", align_style = "world"}},
_variants = {"stair", "slab"}
}) })
artifact.register_node("stone_mossy", { artifact.register_node("stone_mossy", {
tiles = {{name = rep("artifact_stone.png", 4).."^artifact_moss.png", align_style = "world", scale = 4}} tiles = {{name = rep("artifact_stone.png", 4).."^artifact_moss.png", align_style = "world", scale = 4}},
_variants = {"stair", "slab"},
}) })
artifact.register_node("stone_bricks", { artifact.register_node("stone_bricks", {
tiles = {"artifact_stone_bricks.png"} tiles = {{name = "artifact_stone_bricks.png", align_style = "world"}},
_variants = {"stair", "slab"},
}) })
artifact.register_node("stone_bricks_mossy", { artifact.register_node("stone_bricks_mossy", {
tiles = {{name = rep("artifact_stone_bricks.png", 4).."^artifact_moss_bricks.png", align_style = "world", scale = 4}} tiles = {{name = rep("artifact_stone_bricks.png", 4).."^artifact_moss_bricks.png", align_style = "world", scale = 4}},
_variants = {"stair", "slab"},
}) })
artifact.register_node("stone_bricks_small", { artifact.register_node("stone_bricks_small", {
tiles = {"artifact_stone_bricks_small.png"} tiles = {{name = "artifact_stone_bricks_small.png", align_style = "world"}},
_variants = {"stair", "slab"},
}) })
artifact.register_node("stone_tile", { artifact.register_node("stone_tile", {
tiles = {"artifact_stone_tile.png"} tiles = {{name = "artifact_stone_tile.png", align_style = "world"}},
_variants = {"stair", "slab"},
}) })
artifact.register_node("stone_tile_small", { artifact.register_node("stone_tile_small", {
tiles = {"artifact_stone_tile_small.png"} tiles = {{name = "artifact_stone_tile_small.png", align_style = "world"}},
_variants = {"stair", "slab"},
}) })
@ -85,7 +153,7 @@ artifact.register_node("vines", {
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
tiles = {"artifact_vines.png"}, tiles = {"artifact_vines.png"},
use_texture_alpha = true use_texture_alpha = "clip"
}) })
artifact.register_node("vines_dry", { artifact.register_node("vines_dry", {
drawtype = "nodebox", drawtype = "nodebox",
@ -107,25 +175,26 @@ artifact.register_node("vines_dry", {
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
tiles = {"artifact_vines_dry.png"}, tiles = {"artifact_vines_dry.png"},
use_texture_alpha = true use_texture_alpha = "clip"
}) })
artifact.register_node("leaves", { artifact.register_node("leaves", {
drawtype = "allfaces", drawtype = "allfaces",
-- paramtype = "light", -- paramtype = "light",
tiles = {"artifact_leaves.png"}, tiles = {"artifact_leaves.png"},
use_texture_alpha = true use_texture_alpha = "clip"
}) })
artifact.register_node("leaves_dry", { artifact.register_node("leaves_dry", {
drawtype = "allfaces", drawtype = "allfaces",
-- paramtype = "light", -- paramtype = "light",
tiles = {"artifact_leaves_dry.png"}, tiles = {"artifact_leaves_dry.png"},
use_texture_alpha = true use_texture_alpha = "clip"
}) })
artifact.register_node("wood_planks", { artifact.register_node("wood_planks", {
tiles = {"artifact_wood_planks.png"} tiles = {{name = "artifact_wood_planks.png", align_style = "world"}},
_variants = {"stair", "slab"},
}) })
artifact.register_node("ladder_wood", { artifact.register_node("ladder_wood", {
@ -139,6 +208,13 @@ artifact.register_node("ladder_wood", {
}) })
artifact.register_node("glass", {
drawtype = "glasslike",
use_texture_alpha = "clip",
tiles = {"artifact_glass.png"},
_variants = {"stair", "slab"},
})
local function register_lamp(color, brightness) local function register_lamp(color, brightness)
artifact.register_node("lamp_"..color, { artifact.register_node("lamp_"..color, {
@ -176,11 +252,15 @@ minetest.override_item("air", {
light_source = 2 light_source = 2
}) })
if artifact.debug then
minetest.register_mapgen_script(minetest.get_modpath(minetest.get_current_modname()).."/mapgen.lua") minetest.register_mapgen_script(minetest.get_modpath(minetest.get_current_modname()).."/mapgen.lua")
minetest.register_decoration { minetest.register_decoration {
deco_type = "simple", deco_type = "simple",
decoration = "lamp_gold", decoration = "lamp_blue",
place_on = "stone", place_on = "stone",
fill_ratio = 0.02, fill_ratio = 0.02,
} }
end

View file

@ -2,6 +2,7 @@
local vm_data = {} local vm_data = {}
local c_stone = minetest.get_content_id("artifact:stone") local c_stone = minetest.get_content_id("artifact:stone")
local c_chest = minetest.get_content_id("chest_with_everything:chest")
minetest.register_on_generated(function(vm, minp, maxp) minetest.register_on_generated(function(vm, minp, maxp)
local min, max = vm:get_emerged_area() local min, max = vm:get_emerged_area()
@ -9,10 +10,21 @@ minetest.register_on_generated(function(vm, minp, maxp)
vm:get_data(vm_data) vm:get_data(vm_data)
if max.y < 0 then if maxp.y < 0 then
for i in va:iterp(minp, maxp) do for i in va:iterp(minp, maxp) do
vm_data[i] = c_stone vm_data[i] = c_stone
end end
elseif maxp.y < 50 then
for x = min.x, max.x do
for z = min.z, max.z do
for y = min.y, -1 do
vm_data[va:index(x, y, z)] = c_stone
end
if x == 0 and z == 2 then
vm_data[va:index(x, 0, z)] = c_chest
end
end
end
end end
vm:set_data(vm_data) vm:set_data(vm_data)

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B