Add color swappers, color swapping, and color targets.

This commit is contained in:
Signal 2025-11-19 11:43:24 -05:00
parent 9acd605c86
commit 5fd67703c0
34 changed files with 688 additions and 29 deletions

View file

@ -5,7 +5,13 @@ artifact = {
-- This toggles a lot of things, including whether initialization takes place, -- This toggles a lot of things, including whether initialization takes place,
-- whether nodes can be pointed, and whether the player is permitted to -- whether nodes can be pointed, and whether the player is permitted to
-- bypass certain restrictions imposed by the story. -- bypass certain restrictions imposed by the story.
debug = true debug = true,
colors = {
gold = "#faf17a",
red = "#e94f3f",
green = "#6aae68",
blue = "#789fd8"
}
} }
-- For brevity. -- For brevity.

View file

@ -41,7 +41,7 @@ function ns.apply_vix(m)
end end
end end
function ns.swap_character(m) function ns._swap_character(m)
if m.character == "vix" then if m.character == "vix" then
artifact.sidekick.character = "vix" artifact.sidekick.character = "vix"
m:set_character("key") m:set_character("key")
@ -103,6 +103,45 @@ function ns.swap_character(m)
artifact.sidekick.save() artifact.sidekick.save()
end end
function ns.swap_character(m)
if m._swapping_character then return end
if artifact.sidekick.ref then
artifact.sidekick.ref._no_interact = true
end
m._swapping_character = true
local fade = artifact.hud_add(m, {
type = "image",
pos = {x=0.5,y=1},
offset = {x=0,y=0},
align = {x=0,y=0},
scale = {x=50000,y=50000},
opacity = 0,
image = "[fill:1x1:0,0:#000",
})
fade:animate {
opacity = {
value = 256,
duration = 0.3
}
}
minetest.after(0.3, function()
ns._swap_character(m)
fade:animate {
opacity = {
value = 0,
duration = 0.3
}
}
minetest.after(0.3, function()
m._swapping_character = nil
if artifact.sidekick.ref then
artifact.sidekick.ref._no_interact = nil
end
end)
end)
end
include "key.lua" include "key.lua"

View file

@ -6,7 +6,7 @@ minetest.register_entity(":artifact:burst", {
textures = {"blank.png"}, textures = {"blank.png"},
pointable = false, pointable = false,
physical = true, physical = true,
-- collide_with_objects = false, collide_with_objects = false,
collisionbox = { collisionbox = {
-0.2, -0.2, -0.2, -0.2, -0.2, -0.2,
0.2, 0.2, 0.2 0.2, 0.2, 0.2
@ -22,7 +22,20 @@ minetest.register_entity(":artifact:burst", {
end end
end, end,
on_step = function(e, dtime, movement) on_step = function(e, dtime, movement)
if movement.collides then -- Minetest's collision is rather bad, but we also shouldn't collide with players,
-- hence we must implement our own rudimentary collision detection.
-- In this case, any intersection on the segment betwee our last position and our
-- current one should be considered a collision and result in detonation (and
-- at the exact intersection point, if available).
local collision
for x in minetest.raycast(e.old_pos or e.object:get_pos(), e.object:get_pos(), true, true, {nodes = {}, objects = {playser = false}}) do
collision = x
break
end
if collision or movement.collides then
if collision then
e.object:set_pos(collision.intersection_point)
end
minetest.add_particlespawner { minetest.add_particlespawner {
pos = e.object:get_pos(), pos = e.object:get_pos(),
radius = 0.1, radius = 0.1,
@ -49,14 +62,16 @@ minetest.register_entity(":artifact:burst", {
time = 0.1, time = 0.1,
} }
e.object:remove() e.object:remove()
if movement.collisions[1].type == "node" then if movement and movement.collisions[1] and movement.collisions[1].type == "node" then
local pos = movement.collisions[1].node_pos local pos = movement.collisions[1].node_pos
local name = minetest.get_node(pos).name local name = minetest.get_node(pos).name
if minetest.registered_nodes[name].on_impact then if minetest.registered_nodes[name].on_impact then
minetest.registered_nodes[name].on_impact(pos) minetest.registered_nodes[name].on_impact(pos)
end end
end end
return
end end
e.old_pos = e.object:get_pos()
end, end,
impulse = function(e, vel) impulse = function(e, vel)
-- The documentation said that `vel` is relative to the parent entity... -- The documentation said that `vel` is relative to the parent entity...
@ -90,7 +105,7 @@ minetest.register_entity(":artifact:burst", {
pos = vector.zero(), pos = vector.zero(),
vel = vel, vel = vel,
texture = "[fill:16x16:0,0:#fff", texture = "[fill:16x16:0,0:#fff",
size = 3, size_tween = {3, 0},
glow = 14, glow = 14,
amount = 150, amount = 150,
time = 0, time = 0,

View file

@ -1,14 +1,319 @@
artifact.register_entity("ccolor_swapper_display", { local swappers = {}
minetest.register_entity(":artifact:color_swapper_display", {
initial_properties = { initial_properties = {
visual = "mesh", visual = "mesh",
mesh = "artifact_color_swapper.gltf", mesh = "artifact_color_swapper.gltf",
textures = {"artifact_color_swapper_gold.png"} textures = {"artifact_color_swapper_base.png", "artifact_color_swapper_cube.png"},
} selectionbox = {
}) -0.2, -0.2, -0.2,
0.2, 0.2, 0.2
artifact.register_node("color_swapper", { },
on_construct = function(pos) collisionbox = {
-0.2, -0.2, -0.2,
0.2, 0.2, 0.2
},
use_texture_alpha = true,
shaded = false,
glow = 10,
},
_interact_time = 0.4,
_can_interact = function(e, m)
return m.character == "key"
end,
on_activate = function(e, data)
local pos = e.object:get_pos()
local node = minetest.get_node(pos)
if not node.name:find "color_swapper" then
e.object:remove()
return
end
e.object:set_armor_groups{immortal = 1}
extend(e, minetest.deserialize(data) or {})
if e.rotation then
e:rotate(e.rotation)
else
e:rotate(vector.zero())
end
e._name = ""..math.random()
local nm = minetest.get_meta(e.object:get_pos())
local color = nm:get("color") or e.color
e:set_color(color)
swappers[e.object:get_pos():round():to_string()] = e
end,
on_deactivate = function(e)
if e.particles then
minetest.delete_particlespawner(e.particles)
end
swappers[e.object:get_pos():round():to_string()] = nil
end,
get_staticdata = function(e)
return minetest.serialize{rotation = e.rotation, color = e.color}
end,
on_interact = function(e, m)
e._no_interact = true
e.object:set_animation({x=7,y=8}, 1, 1, false)
m:set_color(e.color)
minetest.after(1, function()
if not e._active then return end
e.object:set_animation({x=0,y=6}, 1, 1, true)
e._no_interact = nil
end)
end,
on_step = function(e)
local found = artifact.sidekick.pos and artifact.sidekick.character == "key" and artifact.sidekick.pos:distance(e.object:get_pos()) < 6
for _, m in pairs(artifact.players) do
if m.character == "key" and m.object:get_pos():distance(e.object:get_pos()) < 6 then
found = true
break
end
end
if found and e._active ~= true then
e._active = true
e.object:set_animation({x=9.5,y=10}, 1, 1, false)
local pos = e.object:get_pos()
e.particles = minetest.add_particlespawner {
pos = {
min = pos:offset(-0.5,-0.5,-0.5),
max = pos:offset(0.5,0.5,0.5)
},
vel = {
min = vector.new(-1,-1,-1) *0.5,
max = vector.new(1,1,1) *0.5
},
size = 0.25,
texture = {
name = "artifact_light_"..e.color..".png",
alpha_tween = {1,0}
},
time = 0,
amount = 5,
attract = {
kind = "point",
origin = pos,
strength = 0.5,
}
}
minetest.after(0.5, function()
if not e._active then return end
e.object:set_animation({x=0,y=6}, 1, 1, true)
e._no_interact = nil
end)
elseif not found and e._active ~= false then
e._active = false
e.object:set_animation({x=9,y=9.5}, 1, 1, false)
if e.particles then
minetest.delete_particlespawner(e.particles)
e.particles = nil
end
end
end,
-- Let us update the color live in debug mode.
on_punch = artifact.debug and function(e)
local nm = minetest.get_meta(e.object:get_pos())
local color = nm:get("color") or e.color
e:set_color(color)
end or nil,
set_color = function(e, color)
e.color = color
e.object:set_properties {
textures = {"blank.png", "artifact_color_swapper_cube_"..e.color..".png"}
}
local nm = minetest.get_meta(e.object:get_pos())
nm:set_string("color", color)
end,
rotate = function(e, rot)
e.object:set_rotation(rot)
e.rotation = rot
end, end,
}) })
local function swapper_onload(pos)
local m = minetest.get_meta(pos)
if not m:contains("initialized") then
m:set_string("initialized", "true")
local rot = artifact.facedir_to_rotation(minetest.get_node(pos).param2)
minetest.add_entity(pos, "artifact:color_swapper_display", minetest.serialize{rotation = rot, color = "gold"})
end
end
artifact.register_node("color_swapper", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-0.5, -0.45, -0.5,
0.5, -0.45, 0.5
}
},
tiles = {"artifact_color_swapper_base.png"},
use_texture_alpha = "clip",
paramtype = "light",
walkable = false,
paramtype2 = "facedir",
groups = {call_on_load = 1},
light_source = 8,
on_construct = swapper_onload,
on_load = swapper_onload,
on_destruct = function(pos)
swappers[pos:to_string()].object:remove()
swappers[pos:to_string()] = nil
end,
on_rotate = function(pos, node, p, click, param2)
node.param2 = param2
minetest.swap_node(pos, node)
local rot = artifact.facedir_to_rotation(param2)
swappers[pos:to_string()]:rotate(rot)
return true
end
})
-- MARK: Targets
local targets = {}
minetest.register_entity(":artifact:color_target_display", {
initial_properties = {
visual = "cube",
mesh = "artifact_color_target.gltf",
textures = {"artifact_color_target_base.png^artifact_color_target_gold_off.png"},
use_texture_alpha = true,
shaded = false,
},
_interact_time = 0.4,
_can_interact = function(e, m)
return m.character == "key" and m.color == e.color
end,
on_activate = function(e, data)
local pos = e.object:get_pos()
local node = minetest.get_node(pos)
if not node.name:find "color_target" then
e.object:remove()
return
end
e.object:set_armor_groups{immortal = 1}
extend(e, minetest.deserialize(data) or {})
if e.rotation then
e:rotate(e.rotation)
else
e:rotate(vector.zero())
end
e._name = ""..math.random()
local nm = minetest.get_meta(e.object:get_pos())
local color = nm:get("color") or e.color
e:set_color(color)
targets[e.object:get_pos():round():to_string()] = e
end,
on_deactivate = function(e)
targets[e.object:get_pos():round():to_string()] = nil
end,
get_staticdata = function(e)
return minetest.serialize{rotation = e.rotation, color = e.color}
end,
on_interact = function(e, m)
if m.color == e.color then
e._no_interact = true
m:set_color(nil)
local receivers = minetest.deserialize(minetest.get_meta(e.object:get_pos():round()):get("receivers") or "return nil")
if receivers then
artifact.dispatch_event(receivers, {type = "pulse"})
end
-- Update the entity's texture every globalstep, because that's the only way to do a texture animation.
local progress = 0
local delay = 0
local dir = true
local function update()
if dir then
progress = progress +(255 *0.05)
if progress >= 255 then
dir = false
minetest.after(1, update)
return
end
else
progress = progress -(255 *0.05)
if progress < 0 then
e._no_interact = nil
local tx = "artifact_color_target_base.png^artifact_color_target_"..e.color.."_off.png"
e.object:set_properties {
textures = {tx, tx, tx, tx, tx, tx}
}
return
end
end
local tx = "artifact_color_target_base.png^artifact_color_target_"..e.color.."_off.png^(artifact_color_target_"..e.color.."_on.png^[opacity:"..progress..")"
e.object:set_properties {
textures = {tx, tx, tx, tx, tx, tx}
}
minetest.after(0, update)
end
minetest.after(0, update)
end
end,
-- Let us update the color live in debug mode.
on_punch = artifact.debug and function(e)
local nm = minetest.get_meta(e.object:get_pos())
local color = nm:get("color") or e.color
e:set_color(color)
end or nil,
set_color = function(e, color)
e.color = color
local tx = "artifact_color_target_base.png^artifact_color_target_"..e.color.."_off.png"
e.object:set_properties {
textures = {tx, tx, tx, tx, tx, tx}
}
local nm = minetest.get_meta(e.object:get_pos())
nm:set_string("color", color)
end,
rotate = function(e, rot)
e.object:set_rotation(rot)
e.rotation = rot
end,
})
local function target_onload(pos)
local m = minetest.get_meta(pos)
if not m:contains("initialized") then
m:set_string("initialized", "true")
local rot = artifact.facedir_to_rotation(minetest.get_node(pos).param2)
minetest.add_entity(pos, "artifact:color_target_display", minetest.serialize{rotation = rot, color = "gold"})
end
end
artifact.register_node("color_target", {
drawtype = "airlike",
tiles = {"artifact_color_target_base.png^artifact_color_target_gold_off.png"},
use_texture_alpha = "clip",
paramtype = "light",
paramtype2 = "facedir",
groups = {call_on_load = 1},
on_construct = target_onload,
on_load = target_onload,
on_destruct = function(pos)
targets[pos:to_string()].object:remove()
targets[pos:to_string()] = nil
end,
on_rotate = function(pos, node, p, click, param2)
node.param2 = param2
minetest.swap_node(pos, node)
local rot = artifact.facedir_to_rotation(param2)
targets[pos:to_string()]:rotate(rot)
return true
end
})

View file

@ -54,16 +54,10 @@ minetest.register_entity(":artifact:door", {
} }
end end
if e.rotation then if e.rotation then
e.rotation.y = e.rotation.y +math.pi
e:rotate(e.rotation) e:rotate(e.rotation)
else else
e.rotation = vector.zero() e:rotate(vector.zero())
end end
local box = artifact.rotate_selectionbox(e.box_closed_normal, e.rotation)
e.object:set_properties {
selectionbox = box,
collisionbox = box
}
e._name = ""..math.random() e._name = ""..math.random()
local nm = minetest.get_meta(e.object:get_pos()) local nm = minetest.get_meta(e.object:get_pos())
@ -147,6 +141,15 @@ minetest.register_entity(":artifact:door", {
get_staticdata = function(e) get_staticdata = function(e)
return minetest.serialize{type = e.type, _locked = e._locked, rotation = e.rotation, inverted = e.inverted} return minetest.serialize{type = e.type, _locked = e._locked, rotation = e.rotation, inverted = e.inverted}
end, end,
on_punch = artifact.debug and function(e)
local nm = minetest.get_meta(e.object:get_pos())
if nm:get_string("locked") == "true" then
e._locked = true
end
if e._locked then
e._no_interact = true
end
end or nil,
unlock = function(e) unlock = function(e)
if e._locked then if e._locked then
e._locked = false e._locked = false
@ -156,8 +159,10 @@ minetest.register_entity(":artifact:door", {
rotate = function(e, rot) rotate = function(e, rot)
e.object:set_rotation(rot) e.object:set_rotation(rot)
e.rotation = rot e.rotation = rot
local box = artifact.rotate_selectionbox(e._open and (e.inverted and e.box_open_inverted or e.box_open_normal) or e.box_closed_normal, e.rotation)
e.object:set_properties { e.object:set_properties {
selectionbox = box selectionbox = box,
collisionbox = box
} }
end, end,
on_whack = function(e) on_whack = function(e)
@ -191,7 +196,7 @@ local function register_basic_door(type)
if not m:contains("initialized") then if not m:contains("initialized") then
m:set_string("initialized", "true") m:set_string("initialized", "true")
local rot = artifact.facedir_to_rotation(minetest.get_node(pos).param2) local rot = artifact.facedir_to_rotation(minetest.get_node(pos).param2)
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot) minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type, rotation = rot})
end end
end end
local function ondestruct(pos, reason) local function ondestruct(pos, reason)

View file

@ -32,6 +32,7 @@ end
include "basics.lua" include "basics.lua"
include "doors.lua" include "doors.lua"
include "colors.lua"
include "large_doors.lua" include "large_doors.lua"
include "chest.lua" include "chest.lua"

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 972 B

After

Width:  |  Height:  |  Size: 892 B

Before After
Before After

View file

@ -17,6 +17,7 @@ Player = setmetatable({
m.meta = p:get_meta() m.meta = p:get_meta()
m.character = m.meta:get("character") or "key" m.character = m.meta:get("character") or "key"
m.spawn_point = m.meta:get("spawnpoint") or artifact.origin m.spawn_point = m.meta:get("spawnpoint") or artifact.origin
m.color = m.meta:get("color")
m.inv = p:get_inventory() m.inv = p:get_inventory()
m.inv:set_stack("main", 1, ItemStack("input_"..m.character)) m.inv:set_stack("main", 1, ItemStack("input_"..m.character))
@ -82,6 +83,10 @@ Player = setmetatable({
-- No unreasonable FOV settings here. -- No unreasonable FOV settings here.
p:set_fov(72) p:set_fov(72)
p:set_fov(0, true, 0)
-- Tell raycast collisions that we're a player.
p:set_armor_groups(extend(p:get_armor_groups(), {player = 1}))
m.hud = {} m.hud = {}
m.poi = {} m.poi = {}
@ -142,7 +147,7 @@ Player = setmetatable({
m.interaction_start = 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 e.on_interact and not e._no_interact and (not names_match or names_match and not m.interaction_marker) and (not e._can_interact or e:_can_interact(m)) then
if m.interaction_marker then m.object:hud_remove(m.interaction_marker) end if m.interaction_marker then m.object:hud_remove(m.interaction_marker) end
local dst = e.object:get_pos() local dst = e.object:get_pos()
if e._interact_marker_offset then dst = dst +e:_interact_marker_offset() end if e._interact_marker_offset then dst = dst +e:_interact_marker_offset() end
@ -204,13 +209,25 @@ Player = setmetatable({
p:set_physics_override{ p:set_physics_override{
speed = 1.5 speed = 1.5
} }
p:set_fov(1.1, true, 0.2)
else else
if p:get_animation().y ~= 1 then p:set_animation({x=0, y=1}, 1.5, 0.2, true) end if p:get_animation().y ~= 1 then p:set_animation({x=0, y=1}, 1.5, 0.2, true) end
p:set_physics_override{ p:set_physics_override{
speed = 1 speed = 1
} }
p:set_fov(0, true, 0.2)
end end
else else
-- We can't call this unconditionally because during the first couple
-- globalsteps, doing so will heavily distort the player's FOV for
-- some reason. Since `m.moving` is never set to true until the player
-- starts sprinting, we can sidestep this issue fairly trivially.
if m.moving then
p:set_physics_override{
speed = 1
}
p:set_fov(0, true, 0.2)
end
m.moving = false m.moving = false
if p:get_animation().y ~= 0 then p:set_animation({x=0, y=0}) end if p:get_animation().y ~= 0 then p:set_animation({x=0, y=0}) end
end end
@ -263,7 +280,7 @@ Player = setmetatable({
-- MARK: Progressive interaction -- 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 ctl.place and m.ctl.place and m.pointed_obj and m.pointed_obj.on_interact and not m.pointed_obj._no_interact and (not m.pointed_obj._can_interact or m.pointed_obj:_can_interact(m)) then
if not m.interaction_start then if not m.interaction_start then
m.interaction_start = time m.interaction_start = time
else else
@ -284,7 +301,7 @@ Player = setmetatable({
m.object:hud_change(m.interaction_marker, "text", "artifact_rmb_25.png") m.object:hud_change(m.interaction_marker, "text", "artifact_rmb_25.png")
end end
end end
elseif not ctl.place and m.interaction_start and (not m.pointed_obj or not m.pointed_obj._no_interact) then elseif not ctl.place and m.interaction_start and (not m.pointed_obj or not m.pointed_obj._no_interact or m.pointed_obj._can_interact and m.pointed_obj:_can_interact(m)) then
m.interaction_start = nil m.interaction_start = nil
if m.interaction_marker then if m.interaction_marker then
m.object:hud_change(m.interaction_marker, "text", "artifact_rmb.png") m.object:hud_change(m.interaction_marker, "text", "artifact_rmb.png")
@ -386,12 +403,72 @@ Player = setmetatable({
set_character = function(m, to) set_character = function(m, to)
m.character = to m.character = to
m.meta:set_string("character", to) m.meta:set_string("character", to)
if to == "vix" then
if m.color_hud then
m.object:hud_remove(m.color_hud)
m.color_hud = nil
end
else
if m.color and not m.color_hud then
m.color_hud = m.object:hud_add {
type = "image",
position = {x=0.5,y=1},
offset = {x=0,y=0},
alignment = {x=0,y=-1},
scale = {x=500,y=5},
text = "[fill:1x1:0,0:"..artifact.colors[m.color],
}
end
end
end,
set_color = function(m, color)
if artifact.debug or artifact.story.get_state() > artifact.story.states.pre_vix and m.character == "key" then
m.color = color
m.meta:set_string("color", color or "")
if m.color_hud then
m.object:hud_remove(m.color_hud)
end
-- If we cleared the color by passing nil, there's no need to animate or re-add the HUD.
if not color then return end
m.color_hud = m.object:hud_add {
type = "image",
position = {x=0.5,y=1},
offset = {x=0,y=0},
alignment = {x=0,y=-1},
scale = {x=500,y=5},
text = "[fill:1x1:0,0:"..artifact.colors[m.color],
}
local el = artifact.hud_add(m, {
type = "image",
pos = {x=0.5,y=0.5},
scale = {x=10000,y=10000},
opacity = 0,
image = "[fill:1x1:"..artifact.colors[m.color]
})
el:animate {
opacity = {
value = 25,
duration = 0.3
}
}
minetest.after(0.3, function()
el:animate {
opacity = {
value = 0,
duration = 0.3
}
}
minetest.after(0.3, function()
el:remove(m)
end)
end)
end
end, end,
add_health_bar = function(m) add_health_bar = function(m)
m.healthbar = m.object:hud_add { m.healthbar = m.object:hud_add {
type = "statbar", type = "statbar",
position = {x=0.5,y=1}, position = {x=0.5,y=1},
offset = {x=-27 *5,y=artifact.debug and -96 or -40}, offset = {x=-27 *5,y=artifact.debug and -96 or -42},
scale = {x=4,y=4}, scale = {x=4,y=4},
alignment = {x=-1, y=-1}, alignment = {x=-1, y=-1},
size = {x=27,y=27}, size = {x=27,y=27},
@ -464,10 +541,27 @@ function artifact.register_input(name)
end, end,
drop = "", drop = "",
range = 0, range = 0,
pointabilities = {
nodes = {
["group:everything"] = false
},
objects = {
["group:immortal"] = false,
["group:fleshy"] = false
}
},
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 artifact.story.get_state() > artifact.story.states.pre_vix then if not m._swapping_character and (artifact.debug or artifact.story.get_state() > artifact.story.states.pre_vix) then
artifact.swap_character(m) artifact.swap_character(m)
-- If Key was pointing at something Vix shouldn't be able to interact with,
-- but Vix is also pointing at it, then remove the interaction marker since
-- it would be misleading.
if m.pointed_obj and m.interaction_marker and (not m.pointed_obj._can_interact or m.pointed_obj:_can_interact(m)) then
m.object:hud_remove(m.interaction_marker)
m.interaction_marker = nil
m.interaction_start = nil
end
end end
return s return s
end, end,

View file

@ -11,6 +11,8 @@ function artifact.register_node(name, def)
if not def.groups then def.groups = {} end if not def.groups then def.groups = {} end
if artifact.debug then if artifact.debug then
def.groups.dig_immediate = 3 def.groups.dig_immediate = 3
else
def.groups.everything = 1
end end
if def._variants then if def._variants then
for _, x in ipairs(def._variants) do for _, x in ipairs(def._variants) do
@ -317,6 +319,16 @@ artifact.register_node("ladder_wood", {
climbable = true climbable = true
}) })
artifact.register_node("ladder_iron", {
drawtype = "mesh",
mesh = "artifact_ladder.obj",
paramtype = "light",
paramtype2 = "facedir",
tiles = {"artifact_ladder_iron.png"},
walkable = false,
climbable = true
})
artifact.register_node("glass", { artifact.register_node("glass", {
drawtype = "glasslike", drawtype = "glasslike",
@ -333,7 +345,38 @@ local function register_lamp(color, brightness)
tiles = {"artifact_lamp_"..color..".png"}, tiles = {"artifact_lamp_"..color..".png"},
light_source = brightness, light_source = brightness,
paramtype = "light", paramtype = "light",
sunlight_propagates = true sunlight_propagates = true,
collision_box = {
type = "fixed",
fixed = {
{
-2/16,0,-2/16,
2/16, 4/16, 2/16
}
}
}
})
artifact.register_node("lamp_"..color.."_wall", {
drawtype = "mesh",
mesh = "artifact_lamp_wall.obj",
tiles = {"artifact_lamp_"..color..".png"},
light_source = brightness,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
collision_box = {
type = "fixed",
fixed = {
{
-2/16,-1/16,-1/16,
2/16, 3/16, 3/16
},
{
-1/16,4/16,-1/16,
1/16, 6/16, 8/16
},
}
}
}) })
artifact.register_node("lamp_"..color.."_hanging", { artifact.register_node("lamp_"..color.."_hanging", {
drawtype = "mesh", drawtype = "mesh",
@ -341,7 +384,16 @@ local function register_lamp(color, brightness)
tiles = {"artifact_lamp_"..color..".png"}, tiles = {"artifact_lamp_"..color..".png"},
light_source = brightness, light_source = brightness,
paramtype = "light", paramtype = "light",
sunlight_propagates = true sunlight_propagates = true,
collision_box = {
type = "fixed",
fixed = {
{
-2/16,0,-2/16,
2/16, 4/16, 2/16
}
}
}
}) })
end end

View file

@ -0,0 +1,141 @@
# Made in Blockbench 4.12.5
mtllib artifact_lamp_wall.mtl
o cube
v 0.125 0.1875 0.1875
v 0.125 0.1875 -0.0625
v 0.125 -0.0625 0.1875
v 0.125 -0.0625 -0.0625
v -0.125 0.1875 -0.0625
v -0.125 0.1875 0.1875
v -0.125 -0.0625 -0.0625
v -0.125 -0.0625 0.1875
vt 0 1
vt 0.25 1
vt 0.25 0.75
vt 0 0.75
vt 0 0.75
vt 0.25 0.75
vt 0.25 0.5
vt 0 0.5
vt 0.25 1
vt 0.5 1
vt 0.5 0.75
vt 0.25 0.75
vt 0.25 0.75
vt 0.5 0.75
vt 0.5 0.5
vt 0.25 0.5
vt 0.25 0.25
vt 0 0.25
vt 0 0.5
vt 0.25 0.5
vt 0.75 1
vt 0.5 1
vt 0.5 0.75
vt 0.75 0.75
vn 0 0 -1
vn 1 0 0
vn 0 0 1
vn -1 0 0
vn 0 1 0
vn 0 -1 0
usemtl m_d2e02cf9-1542-9bb0-7e9d-18f7f87eca79
f 4/4/1 7/3/1 5/2/1 2/1/1
f 3/8/2 4/7/2 2/6/2 1/5/2
f 8/12/3 3/11/3 1/10/3 6/9/3
f 7/16/4 8/15/4 6/14/4 5/13/4
f 6/20/5 1/19/5 2/18/5 5/17/5
f 7/24/6 4/23/6 3/22/6 8/21/6
o cube
v -0.0624999999999993 0.24999999999999928 2.42146138045992e-16
v -0.06250000000000071 0.3749999999999993 -2.5745422303532846e-16
v -0.062499999999999355 0.2500000000000013 0.5000000000000002
v -0.06250000000000076 0.3750000000000013 0.4999999999999998
v 0.0624999999999993 0.3750000000000007 -2.42146138045992e-16
v 0.06250000000000071 0.2500000000000007 2.5745422303532846e-16
v 0.06249999999999924 0.3750000000000027 0.4999999999999998
v 0.06250000000000064 0.2500000000000027 0.5000000000000002
vt 0.25 0.5
vt 0.375 0.5
vt 0.375 0
vt 0.25 0
vt 0.5 0.75
vt 0.625 0.75
vt 0.625 0.25
vt 0.5 0.25
vt 0.375 0.5
vt 0.5 0.5
vt 0.5 0
vt 0.375 0
vt 0.625 0.75
vt 0.75 0.75
vt 0.75 0.25
vt 0.625 0.25
vt 0.125 0.125
vt 0 0.125
vt 0 0.25
vt 0.125 0.25
vt 0.875 1
vt 0.75 1
vt 0.75 0.875
vt 0.875 0.875
vn -1.12246949261663e-14 1 -3.996802888650565e-15
vn -1 -1.12246949261663e-14 -1.2246467991469107e-16
vn 1.12246949261663e-14 -1 3.996802888650565e-15
vn 1 1.12246949261663e-14 1.2246467991469107e-16
vn 1.2246467991473663e-16 -3.996802888650562e-15 -1
vn -1.2246467991473663e-16 3.996802888650562e-15 1
usemtl m_d2e02cf9-1542-9bb0-7e9d-18f7f87eca79
f 12/28/7 15/27/7 13/26/7 10/25/7
f 11/32/8 12/31/8 10/30/8 9/29/8
f 16/36/9 11/35/9 9/34/9 14/33/9
f 15/40/10 16/39/10 14/38/10 13/37/10
f 14/44/11 9/43/11 10/42/11 13/41/11
f 15/48/12 12/47/12 11/46/12 16/45/12
o cube
v 0.09375 0.25 0.15625
v 0.09375 0.25 -0.03125
v 0.09375 0.1875 0.15625
v 0.09375 0.1875 -0.03125
v -0.09375 0.25 -0.03125
v -0.09375 0.25 0.15625
v -0.09375 0.1875 -0.03125
v -0.09375 0.1875 0.15625
vt 0.5 0.6875
vt 0.6875 0.6875
vt 0.6875 0.640625
vt 0.5 0.640625
vt 0.5 0.6875
vt 0.6875 0.6875
vt 0.6875 0.640625
vt 0.5 0.640625
vt 0.5 0.6875
vt 0.6875 0.6875
vt 0.6875 0.640625
vt 0.5 0.640625
vt 0.5 0.6875
vt 0.6875 0.6875
vt 0.6875 0.640625
vt 0.5 0.640625
vt 0.3125 0.4375
vt 0.5 0.4375
vt 0.5 0.25
vt 0.3125 0.25
vt 0.3125 0.4375
vt 0.5 0.4375
vt 0.5 0.25
vt 0.3125 0.25
vn 0 0 -1
vn 1 0 0
vn 0 0 1
vn -1 0 0
vn 0 1 0
vn 0 -1 0
usemtl m_d2e02cf9-1542-9bb0-7e9d-18f7f87eca79
f 20/52/13 23/51/13 21/50/13 18/49/13
f 19/56/14 20/55/14 18/54/14 17/53/14
f 24/60/15 19/59/15 17/58/15 22/57/15
f 23/64/16 24/63/16 22/62/16 21/61/16
f 22/68/17 17/67/17 18/66/17 21/65/17
f 23/72/18 20/71/18 19/70/18 24/69/18

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B