Add the rest of the game.

This commit is contained in:
Signal 2025-11-29 17:24:33 -05:00
parent dd73665a23
commit 9096c33a48
49 changed files with 855 additions and 57 deletions

BIN
menu/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

View file

@ -5,7 +5,7 @@ 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 = false,
colors = { colors = {
gold = "#faf17a", gold = "#faf17a",
red = "#e94f3f", red = "#e94f3f",
@ -54,6 +54,25 @@ function Promise(fn)
} }
end end
function artifact.play_sound(def)
def.max_hear_distance = def.range
--def.gain = nil
if def.pos then
for _, m in pairs(artifact.players) do
local dist = m.pos:distance(def.pos)
if dist <= (def.range or 32) and m.name ~= def.exclude_player and not (def.to_player and m.name ~= def.to_player) then
def.to_player = m.name
def.gain = (def.gain or 1) *(1 -math.sqrt(dist /(def.range or 32)))
minetest.sound_play(def, def)
end
end
else
minetest.sound_play(def.name, def)
end
end
-- HACK: Lookup table for getting a rotation from a -- HACK: Lookup table for getting a rotation from a
-- facedir (because Minetest doesn't have any way -- facedir (because Minetest doesn't have any way
-- to get this information normally) -- to get this information normally)

View file

@ -42,6 +42,15 @@ function ns.apply_vix(m)
end end
function ns._swap_character(m) function ns._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
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")
@ -52,6 +61,17 @@ function ns._swap_character(m)
ns.apply_vix(m) ns.apply_vix(m)
end end
-- If Vix was pointing at something whackable, and the player then switches
-- to Key who is pointing at the same thing, we should show the whack icon.
if m.character == "key" and m.pointed_node and minetest.registered_nodes[m.pointed_node.node_under.name].groups.whackable then
m.whack_hud = m.object:hud_add {
type = "image_waypoint",
world_pos = m.pointed_node.under,
scale = {x=3,y=3},
text = "artifact_icon_whack.png"
}
end
-- We don't need to have the sidekick entity during testing. -- We don't need to have the sidekick entity during testing.
if artifact.sidekick.pos or not artifact.debug then if artifact.sidekick.pos or not artifact.debug then
-- `m.pos` includes eye_height, and we don't want that here. -- `m.pos` includes eye_height, and we don't want that here.
@ -124,6 +144,10 @@ function ns.swap_character(m)
duration = 0.3 duration = 0.3
} }
} }
artifact.play_sound {
name = "artifact_character_swap",
to_player = m.name
}
minetest.after(0.3, function() minetest.after(0.3, function()
ns._swap_character(m) ns._swap_character(m)
fade:animate { fade:animate {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,005 B

After

Width:  |  Height:  |  Size: 1.9 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -13,26 +13,28 @@ minetest.register_entity(":artifact:burst", {
}, },
static_save = false, static_save = false,
}, },
on_activate = function(e, rot) on_activate = function(e)
e.object:set_armor_groups{immortal = 1} e.object:set_armor_groups{immortal = 1}
end, end,
on_deactivate = function(e) on_deactivate = function(e)
for _, x in ipairs(e._particles) do for _, x in ipairs(e._particles or {}) do
minetest.delete_particlespawner(x) minetest.delete_particlespawner(x)
end end
end, end,
on_step = function(e, dtime, movement) on_step = function(e, dtime, movement)
-- Minetest's collision is rather bad, but we also shouldn't collide with players, -- Minetest's collision is rather bad, but we also shouldn't collide with players,
-- hence we must implement our own rudimentary collision detection. -- hence we must implement our own rudimentary collision detection.
-- In this case, any intersection on the segment betwee our last position and our -- In this case, any intersection on the segment between our last position and our
-- current one should be considered a collision and result in detonation (and -- current one should be considered a collision and result in detonation (and
-- at the exact intersection point, if available). -- at the exact intersection point, if available).
local collision 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 if not e._critical then
collision = x for x in minetest.raycast(e.old_pos or e.object:get_pos(), e.object:get_pos(), true, true, {nodes = {}, objects = {playser = false}}) do
break collision = x
break
end
end end
if collision or movement.collides then if collision or movement and movement.collides then
if collision then if collision then
e.object:set_pos(collision.intersection_point) e.object:set_pos(collision.intersection_point)
end end
@ -61,6 +63,10 @@ minetest.register_entity(":artifact:burst", {
drag = 1, drag = 1,
time = 0.1, time = 0.1,
} }
artifact.play_sound {
name = "artifact_burst_impact",
pos = e.object:get_pos()
}
e.object:remove() e.object:remove()
if movement and movement.collisions[1] and 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
@ -116,6 +122,10 @@ minetest.register_entity(":artifact:burst", {
end end
}) })
function ns.do_shoot(m) function ns.do_shoot(m, dir)
minetest.add_entity(m.pos +m.dir, "artifact:burst", tostring(m.yaw)):get_luaentity():impulse(m.dir *30) artifact.play_sound {
name = "artifact_burst_fire",
pos = dir and m or m.pos
}
minetest.add_entity(dir and m +dir or m.pos +m.dir, "artifact:burst"):get_luaentity():impulse((dir or m.dir) *30)
end end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

After

Width:  |  Height:  |  Size: 194 B

Before After
Before After

View file

@ -59,6 +59,11 @@ minetest.register_entity(":artifact:color_swapper_display", {
e._no_interact = true e._no_interact = true
e.object:set_animation({x=7,y=8}, 1, 1, false) e.object:set_animation({x=7,y=8}, 1, 1, false)
m:set_color(e.color) m:set_color(e.color)
artifact.play_sound {
name = "artifact_color_swap",
pos = e.object:get_pos(),
range = 8,
}
minetest.after(1, function() minetest.after(1, function()
if not e._active then return end if not e._active then return end
e.object:set_animation({x=0,y=6}, 1, 1, true) e.object:set_animation({x=0,y=6}, 1, 1, true)
@ -227,10 +232,11 @@ minetest.register_entity(":artifact:color_target_display", {
if m.color == e.color then if m.color == e.color then
e._no_interact = true e._no_interact = true
m:set_color(nil) m:set_color(nil)
local receivers = minetest.deserialize(minetest.get_meta(e.object:get_pos():round()):get("receivers") or "return nil") artifact.play_sound {
if receivers then name = "artifact_color_use",
artifact.dispatch_event(receivers, {type = "pulse"}) pos = e.object:get_pos(),
end range = 8,
}
-- Update the entity's texture every globalstep, because that's the only way to do a texture animation. -- Update the entity's texture every globalstep, because that's the only way to do a texture animation.
local progress = 0 local progress = 0
local delay = 0 local delay = 0
@ -241,6 +247,10 @@ minetest.register_entity(":artifact:color_target_display", {
if progress >= 255 then if progress >= 255 then
dir = false dir = false
minetest.after(1, update) minetest.after(1, update)
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
return return
end end
else else
@ -303,6 +313,7 @@ artifact.register_node("color_target", {
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {call_on_load = 1}, groups = {call_on_load = 1},
sounds = artifact.sounds.metal,
on_construct = target_onload, on_construct = target_onload,
on_load = target_onload, on_load = target_onload,
on_destruct = function(pos) on_destruct = function(pos)

View file

@ -73,7 +73,7 @@ minetest.register_entity(":artifact:door", {
if e._locked then if e._locked then
e._no_interact = true e._no_interact = true
end end
if e.inverted then e:invert() end if e.inverted or nm:get("inverted") == "true" then e:invert() end
doors[e.object:get_pos():round():to_string()] = e doors[e.object:get_pos():round():to_string()] = e
end, end,
on_deactivate = function(e) on_deactivate = function(e)
@ -200,6 +200,10 @@ minetest.register_entity(":artifact:door", {
texture = "artifact_door_wood.png^[sheet:2x8:0,3", texture = "artifact_door_wood.png^[sheet:2x8:0,3",
time = 0.1 time = 0.1
} }
artifact.play_sound {
name = "artifact_door_break",
pos = pos
}
return true return true
end end
end end

View file

@ -268,6 +268,7 @@ artifact.register_node("forcefield_generator", {
1, 0.5, 0.5 1, 0.5, 0.5
} }
}, },
sounds = artifact.sounds.metal,
on_construct = onload, on_construct = onload,
on_load = onload, on_load = onload,
on_rightclick = artifact.debug and function(pos) on_rightclick = artifact.debug and function(pos)
@ -284,8 +285,12 @@ artifact.register_node("forcefield_generator", {
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
node.name = "forcefield_generator_off" node.name = "forcefield_generator_off"
minetest.after(0, function() minetest.after(0, function()
minetest.set_node(pos, node) minetest.set_node(pos, node)
end) end)
artifact.play_sound {
name = "artifact_forcefield_generator_destruct",
pos = pos,
}
minetest.add_particlespawner { minetest.add_particlespawner {
pos = pos, pos = pos,
vel = vector.zero(), vel = vector.zero(),
@ -338,6 +343,7 @@ artifact.register_node("forcefield_generator_off", {
1, 0.5, 0.5 1, 0.5, 0.5
} }
}, },
sounds = artifact.sounds.metal,
on_impact = artifact.debug and function(pos) on_impact = artifact.debug and function(pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
node.name = "forcefield_generator" node.name = "forcefield_generator"

View file

@ -1,5 +1,6 @@
local large_doors = {} local large_doors = {}
artifact.large_doors = large_doors
minetest.register_entity(":artifact:large_door_display", { minetest.register_entity(":artifact:large_door_display", {
initial_properties = { initial_properties = {
@ -49,7 +50,7 @@ minetest.register_entity(":artifact:large_door_display", {
if nm:contains("locks") then if nm:contains("locks") then
e.locks = minetest.deserialize(nm:get_string("locks")) e.locks = minetest.deserialize(nm:get_string("locks"))
end end
if e.locks then if e.locks then
e:set_locks(e.locks) e:set_locks(e.locks)
end end
@ -99,6 +100,23 @@ minetest.register_entity(":artifact:large_door_display", {
local pos = e.object:get_pos():round() local pos = e.object:get_pos():round()
minetest.get_meta(pos):set_string("open", "true") minetest.get_meta(pos):set_string("open", "true")
artifact.play_sound {
name = "artifact_large_door_open",
pos = e.object:get_pos(),
range = 10,
}
local m = minetest.get_meta(pos)
local on_open = m:get("on_open")
if not artifact.debug and on_open then
if on_open == "play_final_scene" then
artifact.story.play_final_scene()
elseif on_open == "play_end_scene" then
artifact.story.play_end_scene()
end
m:set_string("on_open", "")
end
minetest.after(0.75, function() minetest.after(0.75, function()
e._animating = nil e._animating = nil
end) end)
@ -110,6 +128,13 @@ minetest.register_entity(":artifact:large_door_display", {
e.object:set_animation({x=1,y=2}, 1.25, 0.1, false) e.object:set_animation({x=1,y=2}, 1.25, 0.1, false)
local pos = e.object:get_pos():round() local pos = e.object:get_pos():round()
minetest.get_meta(pos):set_string("open", "false") minetest.get_meta(pos):set_string("open", "false")
artifact.play_sound {
name = "artifact_large_door_close",
pos = e.object:get_pos(),
range = 10,
}
minetest.after(0.75, function() minetest.after(0.75, function()
e._animating = nil e._animating = nil
end) end)
@ -185,9 +210,9 @@ local function onload(pos)
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)
local locks = {red = false, blue = false, green = false, "red", "green", "blue"} local locks = minetest.deserialize(m:get("locks") or "return nil") or {red = false, blue = false, green = false, "red", "green", "blue"}
minetest.add_entity(pos, "artifact:large_door_display", minetest.serialize{locks = locks}):get_luaentity():rotate(rot) minetest.add_entity(pos, "artifact:large_door_display", minetest.serialize{locks = locks}):get_luaentity():rotate(rot)
minetest.get_meta(pos):set_string("locks", minetest.serialize(locks)) m:set_string("locks", minetest.serialize(locks))
end end
end end
@ -204,6 +229,47 @@ local function onsignal(pos, event, channel)
if locks[channel] ~= nil then if locks[channel] ~= nil then
locks[channel] = true locks[channel] = true
end end
artifact.play_sound {
name = "artifact_lock_light",
pos = e.object:get_pos(),
range = 10,
}
local idx = table.indexof(locks, channel)
local rot = artifact.facedir_to_rotation(minetest.get_node(pos).param2)
minetest.add_particlespawner {
pos = pos +vector.new(-0.6 +(idx *0.3), 2.25, -0.2):rotate(rot),
vel = {
min = vector.new(-1, 0, -1):rotate(rot),
max = vector.new(1, 2, -0.2):rotate(rot),
},
acc = vector.new(0, -9.81, 0),
texture = {
name = "[fill:1x1:0,0:"..artifact.colors[channel],
alpha_tween = {1, 0}
},
glow = 8,
time = 0.1,
size = 0.25,
amount = 20,
exptime = 0.3
}
minetest.add_particlespawner {
pos = pos +vector.new(-0.6 +(idx *0.3), 2.25, 0.2):rotate(rot),
vel = {
min = vector.new(-1, 0, 0.2):rotate(rot),
max = vector.new(1, 2, 1):rotate(rot),
},
acc = vector.new(0, -8, 0),
texture = {
name = "[fill:1x1:0,0:"..artifact.colors[channel],
alpha_tween = {1, 0}
},
glow = 8,
time = 0.1,
size = 0.25,
amount = 20,
exptime = 0.3
}
e:set_locks(locks) e:set_locks(locks)
minetest.get_meta(pos):set_string("locks", minetest.serialize(locks)) minetest.get_meta(pos):set_string("locks", minetest.serialize(locks))
else else

View file

@ -528,13 +528,22 @@ Player = setmetatable({
end end
}) })
-- Skip the death screen. Once we have an actual damage
-- system, this can be customized properly.
function minetest.show_death_screen(p, reason)
p:respawn()
end
-- Override respawning, so we can save progress. -- Override respawning, so we can save progress.
minetest.register_on_respawnplayer(function(p) minetest.register_on_respawnplayer(function(p)
local m = artifact.players[p:get_player_name()] local m = artifact.players[p:get_player_name()]
return true
--[[ Disabled due to current lack of purpose.
if m.spawn_point then if m.spawn_point then
p:set_pos(m.spawn_point) p:set_pos(m.spawn_point)
return true return true
end end
--]]
end) end)
-- Mirror the player's HP in our custom HUD. -- Mirror the player's HP in our custom HUD.
@ -584,14 +593,6 @@ function artifact.register_input(name)
local m = artifact.players[p:get_player_name()] local m = artifact.players[p:get_player_name()]
if not m._swapping_character and (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,
@ -634,6 +635,13 @@ minetest.register_on_joinplayer(function(p)
end end
end) end)
-- Imposters will be kicked. (But why would you run this on a server anyway?)
minetest.register_on_prejoinplayer(function(name)
if name == "Key" or name == "Vix" then
return "That name is already taken by one of the characters!"
end
end)
minetest.register_on_leaveplayer(function(p) minetest.register_on_leaveplayer(function(p)
artifact.players[p:get_player_name()] = nil artifact.players[p:get_player_name()] = nil
end) end)

View file

@ -4,7 +4,7 @@ artifact.story = {
"init", -- For the opening cutscene. "init", -- For the opening cutscene.
"pre_vix", -- The player doesn't have Vix yet. "pre_vix", -- The player doesn't have Vix yet.
"main", -- The main game state. Progress is managed by checkpoints here. "main", -- The main game state. Progress is managed by checkpoints here.
"end", -- The game is over. "ended", -- The game is over.
}, },
poi = { poi = {
initial_cutscene = { initial_cutscene = {
@ -30,14 +30,36 @@ minetest.register_entity(":artifact:vix_scene", {
initial_properties = { initial_properties = {
visual = "mesh", visual = "mesh",
mesh = "artifact_scene_vix.gltf", mesh = "artifact_scene_vix.gltf",
textures = {"artifact_vix.png"} textures = {"artifact_vix.png"},
backface_culling = false
}, },
on_activate = function(e) on_activate = function(e)
if state > ns.states.pre_vix then if state > ns.states.pre_vix then
e.object:remove() e.object:remove()
return
end end
e.object:set_armor_groups{immortal = 1} e.object:set_armor_groups{immortal = 1}
e.object:set_animation({x=0,y=2}, 0.5, 0.1, true) e.object:set_animation({x=0,y=2}, 0.5, 0.1, true)
e.particles = minetest.add_particlespawner {
pos = e.object:get_pos():offset(0, 0.15, 0),
vel = {
min = vector.new(-0.5, 0,-0.5),
max = vector.new( 0.5, 0, 0.5)
},
acc = vector.new(0, -9.81, 0),
texture = {
name = "artifact_light_gold.png",
alpha_tween = {0.75, 0}
},
collisiondetection = true,
time = 0,
amount = 100,
exptime = 5
}
e._track_pos = e.object:get_pos():offset(0, 0.5, 0)
e._rot = vector.zero()
vix_scene = e vix_scene = e
end, end,
on_deactivate = function(e) on_deactivate = function(e)
@ -51,6 +73,21 @@ minetest.register_entity(":artifact:vix_scene", {
e._can_check = false e._can_check = false
end end
end end
elseif e._track then
local m = artifact.players[next(artifact.players)]
local rot = e._track_pos:direction(m.pos):rotate(e._rot):dir_to_rotation()
if rot.y > -math.pi *(2/3) and rot.y < math.pi *(2/3) then
rot.y = math.pi *(2/3) *math.sign(rot.y)
end
rot.y = -rot.y +math.pi
rot.x = -math.max(-math.pi /3, math.min(math.pi /3, rot.x)) +0.25
e.object:set_bone_override("Head", {
rotation = {
vec = rot,
interpolation = 0.4
}
})
end end
end end
}) })
@ -81,7 +118,7 @@ function ns.enter_pre_vix_state()
end end
db:set_string("checkpoint:pre_vix", "in_room") db:set_string("checkpoint:pre_vix", "in_room")
elseif checkpoint == "in_room" then -- We're actually in the room. elseif checkpoint == "in_room" then -- We're actually in the room.
if target.node_under.name:find "forcefield_generator" then if type == "node" and target.node_under.name:find "forcefield_generator" then
local num = db:get_int("checkpoint:pre_vix_fields_broken") +1 local num = db:get_int("checkpoint:pre_vix_fields_broken") +1
db:set_int("checkpoint:pre_vix_fields_broken", num) db:set_int("checkpoint:pre_vix_fields_broken", num)
if num == 1 then -- Key breaks his first generator. if num == 1 then -- Key breaks his first generator.
@ -90,6 +127,10 @@ function ns.enter_pre_vix_state()
end) end)
elseif num == 5 then -- All generators are down. elseif num == 5 then -- All generators are down.
vix_scene._can_check = nil vix_scene._can_check = nil
-- Wait just a bit, so the player can look up.
minetest.after(0.5, function()
ns.play_vix_scene()
end)
end end
end end
end end
@ -97,9 +138,55 @@ function ns.enter_pre_vix_state()
end end
function ns.enter_main_state() function ns.enter_main_state()
minetest.add_entity(vix_scene.object:get_pos():offset(1.5, -0.8, -0.5), "artifact:sidekick"):set_rotation(vector.new(0, -math.pi /2, 0))
vix_scene.object:remove() vix_scene.object:remove()
end end
function ns.enter_ended_state()
for _, m in pairs(artifact.players) do
local bg = artifact.hud_add(m, {
type = "image",
image = "[fill:16x16:0,0:#000",
opacity = 0,
pos = {x=0.5,y=0.5},
scale = {x=1000,y=1000},
})
bg:animate {
opacity = {
value = 256,
duration = 0.3
}
}
minetest.after(0.3, function()
local txt = artifact.hud_add(m, {
type = "text",
color = "#000",
text = "To be continued...",
pos = {x=0.5,y=0.5},
size = {x=3,y=0},
color = minetest.colorspec_to_table("#000")
})
txt:animate {
color = {
value = minetest.colorspec_to_table("#888"),
duration = 0.3
}
}
minetest.after(8, function()
txt:animate {
color = {
value = minetest.colorspec_to_table("#000"),
duration = 0.3
}
}
minetest.after(0.3, function()
minetest.request_shutdown("You completed the game.")
end)
end)
end)
end
end
function ns.enter_state(to) function ns.enter_state(to)
state = to state = to
if state == ns.states.init then if state == ns.states.init then
@ -108,6 +195,8 @@ function ns.enter_state(to)
ns.enter_pre_vix_state() ns.enter_pre_vix_state()
elseif state == ns.states.main then elseif state == ns.states.main then
ns.enter_main_state() ns.enter_main_state()
elseif state == ns.states.ended then
ns.enter_ended_state()
end end
db:set_int("state", state) db:set_int("state", state)
end end
@ -133,20 +222,492 @@ function artifact.look_at(m, pos, pos2)
m.object:set_look_vertical(-rot.x) m.object:set_look_vertical(-rot.x)
end end
if artifact.debug then
minetest.register_chatcommand("splash", {
func = function(name)
local m = artifact.players[name]
minetest.show_formspec(m.name, "artifact:lock_camera", [[
formspec_version[10]
size[32,18]
padding[0,0]
bgcolor[#000]
animated_image[0,0;32,18;;artifact_splash.png;60;100;;]
]])
end
})
minetest.register_chatcommand("flash", {
func = function(name)
minetest.add_particle {
pos = artifact.origin:offset(-16.5, -71.5, -17),
velocity = vector.zero(),
texture = {
name = "artifact_flash.png",
alpha_tween = {0, 1}
},
size = 60,
expirationtime = 0.1
}
end
})
end
minetest.register_chatcommand("splash", { artifact.register_node("stasis_beacon", {
func = function(name) drawtype = "mesh",
local m = artifact.players[name] mesh = "artifact_stasis_beacon.gltf",
minetest.show_formspec(m.name, "artifact:lock_camera", [[ tiles = {"artifact_stasis_beacon.png"},
formspec_version[10] use_texture_alpha = "blend",
size[32,18] paramtype = "light"
padding[0,0]
bgcolor[#000]
animated_image[0,0;32,18;;artifact_splash.png;60;100;;]
]])
end
}) })
-- The 'cutscene' playerd after the player frees Vix.
function ns.play_vix_scene()
-- Kaboom.
minetest.add_particle {
pos = artifact.origin:offset(-16.5, -71.5, -17),
velocity = vector.zero(),
texture = {
name = "artifact_flash.png",
alpha_tween = {0, 1}
},
size = 60,
expirationtime = 0.1
}
artifact.play_sound {
name = "artifact_free_vix",
pos = artifact.origin:offset(-16.5, -72.5, -17)
}
vix_scene.object:set_animation({x=3,y=150}, 1, 0.1, false)
minetest.delete_particlespawner(vix_scene.particles)
vix_scene.particles = nil
-- Key can walk around freely, so Vix should try to face him once she wakes.
local i = 7
minetest.after(i, function()
vix_scene._track = true
end)
i = i +1
minetest.after(i, function()
-- Is he the one they sent?
artifact.push_chat_message("...Who are you?", minetest.colorize("#f5dd66", "???"), "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
-- Awkward.
artifact.push_chat_message("Uh... Wow, this is awkward. I did not think that through far enough.", "Key", "artifact_key_splash_low.png")
end)
i = i +7
minetest.after(i, function()
-- Oops, that didn't help.
artifact.push_chat_message("Wait, that was bad, let's try this again.", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
-- Better.
artifact.push_chat_message("Hi. I'm Key.", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
-- ...He's not?
artifact.push_chat_message("...Hi.", minetest.colorize("#f5dd66", "???"), "artifact_vix_splash_low.png")
-- [ She sits up ]
vix_scene._track = nil
vix_scene.object:set_bone_override("Head", {
rotation = {
vec = vector.zero(), interpolation = 0.4
}
})
end)
i = i +5
minetest.after(i, function()
vix_scene._track = true
-- So what's the deal?
artifact.push_chat_message("How did you get here?", minetest.colorize("#f5dd66", "???"), "artifact_vix_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("It's actually a long story, but the short version is that I fell in a hole.", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("...", minetest.colorize("#f5dd66", "???"), "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Maintenance might want to have a look at the closet over there.", "Key", "artifact_key_splash_low.png")
end)
i = i +6
minetest.after(i, function()
-- Okay... Wait, how long has it been, anyway? The room is awfully overgrown...
artifact.push_chat_message("I don't think maintenance will mind...", minetest.colorize("#f5dd66", "???"), "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Probably so...", "Key", "artifact_key_splash_low.png")
-- [ Vix climbs off the pedestal ]
vix_scene._track = nil
vix_scene.object:set_bone_override("Head", {
rotation = {
vec = vector.zero(), interpolation = 0.4
}
})
vix_scene._track_pos = vix_scene.object:get_pos():offset(1.5, 0, -0.5)
vix_scene._rot = vector.new(0, -math.pi /2, 0)
end)
i = i +7
minetest.after(i, function()
vix_scene._track = true
artifact.push_chat_message("So, uh, what's _your_ name?", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("...Vix.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Formally pleased to meet you.", "Key", "artifact_key_splash_low.png")
end)
i = i +5
minetest.after(i, function()
-- How trustworthy is he?
artifact.push_chat_message("Why did you... break the forcefields?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Well, when I saw you locked inside all those forcefields, I thought 'Wow, she doesn't look too happy'.", "Key", "artifact_key_splash_low.png")
end)
i = i +7
minetest.after(i, function()
artifact.push_chat_message("Then I thought, 'Hmm, she must have been there a while, what with all the vines over here and not over there.'", "Key", "artifact_key_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("_Then_ I thought, 'Whoever's fault this is probably isn't going to be back. Why not help her out?'", "Key", "artifact_key_splash_low.png")
end)
i = i +7
minetest.after(i, function()
artifact.push_chat_message("So then I used this cool stick I found to trash all the forcefields and let you out.", "Key", "artifact_key_splash_low.png")
end)
i = i +7
minetest.after(i, function()
-- ..._Are_ they going to be back...?
artifact.push_chat_message("What year is it?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("I dunno, I lost count a while back. Somewhere around the turn of the century.", "Key", "artifact_key_splash_low.png")
end)
i = i +5
minetest.after(i, function()
-- ... I guess not.
artifact.push_chat_message("...", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
-- You know what, what am I even doing here?
-- (It's not like staying is a workable option, but that's not really what Vix has in mind.)
artifact.push_chat_message("We need to leave... I don't suppose we could get out the way you got in?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("...Nah.", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("I guess that leaves the hard way.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Let's see if this works...", "Vix", "artifact_vix_splash_low.png")
minetest.after(1, function()
local burst = minetest.add_entity(vix_scene.object:get_pos():offset(0, 1, -1.5), "artifact:burst")
burst:get_luaentity()._critical = true
burst:set_attach(vix_scene.object, "RightArm", vector.new(0, 100, 0))
minetest.after(0, function()
burst:set_detach()
artifact.play_sound {
name = "artifact_burst_fire",
pos = burst:get_pos()
}
burst:get_luaentity():impulse(burst:get_pos():direction(artifact.origin:offset(18, -71, -13)) *30)
end)
end)
end)
i = i +8
minetest.after(i, function()
artifact.push_chat_message("Wow, that's epic.", "Key", "artifact_key_splash_low.png")
end)
i = i +2
minetest.after(i, function()
ns.enter_state(ns.states.main)
minetest.after(10, function()
local m = artifact.players[next(artifact.players)]
if m.character ~= "vix" then
artifact.show_help_message(m, "You can switch between Key and Vix using the Drop control.", "info")
end
end)
end)
i = i +45
minetest.after(i, ns.dialogue_1)
end
function ns.dialogue_1()
local i = 0
artifact.push_chat_message("So, what's the long version of you you got here?", "Vix", "artifact_vix_splash_low.png")
i = i +5
minetest.after(i, function()
artifact.push_chat_message("Well, one fine day, I was strolling along through a little town called Birchwood.", "Key", "artifact_key_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("On the street corner, some guy was doing a huge ad for an adventuring supply company.", "Key", "artifact_key_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("Naturally, I suggested that his wares were overpriced because he was spending so much on advertising.", "Key", "artifact_key_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("I won't bore you with the details, but there was a whole thing that ended with me betting him five gold pieces that I could steal some artifact whose name I forget without any supplies at all.", "Key", "artifact_key_splash_low.png")
end)
i = i +8
minetest.after(i, function()
artifact.push_chat_message("(I told him it was probably guarded by a few bats and a couple average-sized spiders, but he wouldn't believe me.)", "Key", "artifact_key_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("I was wrong about there not being any traps, though. That's why I'm down here and not five gold pieces richer. (Yet.)", "Key", "artifact_key_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("So you came all this way for five gold pieces?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("No, no, I came all this way to prove a point. I'd probably forget I had the gold pieces within the hour.", "Key", "artifact_key_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("Wow.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +15
minetest.after(i, function()
artifact.push_chat_message("So, how about you? What's the story with that awesome burst ability?", "Key", "artifact_key_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("Have you ever heard of Iron Dragon?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Nope.", "Key", "artifact_key_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("They're... Well, they were... a vigilante group, who were fairly powerful fifty-some years ago. My father was one of the generals.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("Early on, they learned to synthesize a controlled form of energy to power tools; you saw some of that in the forcefields.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("Eventually, someone — my aunt, actually — floated the idea that feeding that energy into a human might give them new abilities.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("No one liked it at first. Eventually, though, when we were weakened and all but defeated, my father became desperate enough to consider it.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("He wanted me to be the first test subject. Looking back, I think he wanted to protect me, keep me out of the combat if things got that bad.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("I trusted his judgement.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Incredibly, though, he was right... It makes no sense physiologically, but somehow it worked.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +8
minetest.after(i, function()
artifact.push_chat_message("Now here I am half a century later, and it's all gone...", "Vix", "artifact_vix_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("Wow. Imagine an experiment that worked on the first try.", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Right? I though there could be something to it, but this? It's been half a century, and I feel even better than I did before.", "Vix", "artifact_vix_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("That's what I was thinking. You look sixteen, not 60.", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Really?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Yep.", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("...Huh. That's...", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Really weird?", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Yeah. That's exactly how old I was when this happened...", "Vix", "artifact_vix_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("Most intriguing...", "Key", "artifact_key_splash_low.png")
end)
end
-- Play the final scene.
function ns.play_final_scene()
local scn = minetest.add_entity(artifact.origin:offset(132, -69.5, -22), "display")
scn:set_properties {
visual = "mesh",
mesh = "artifact_scene_final.gltf",
textures = {"artifact_tav.png"}
}
local i = 2
minetest.after(i, function()
artifact.push_chat_message("Hey, who's that?", "Key", "artifact_key_splash_low.png")
minetest.after(1, function()
scn:set_animation({x=0,y=120}, 1, 0, false)
end)
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("I don't know...", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("You.", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +3
minetest.after(i, function()
artifact.push_chat_message("Huh?", "Key", "artifact_key_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("What have you done?", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("I just walked in here, why?", "Key", "artifact_key_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("Vix.", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("What?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("Hm.", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +3
minetest.after(i, function()
artifact.push_chat_message("So you really did?", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("I don't understand...", "Vix", "artifact_vix_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("Is that so?", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Yes?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Traitor.", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +2
minetest.after(i, function()
artifact.push_chat_message("Wow.", "Key", "artifact_key_splash_low.png")
end)
i = i +2
minetest.after(i, function()
artifact.push_chat_message("Huh? Iron Dragon is gone. What are you accusing me of?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("So you don't know. Unfortunate.", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Who are you, anyway?", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("A ghost.", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Whoa, stop being so ambiguous! I don't think we know what you think we know.", "Key", "artifact_key_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("I'd love to banter, but right now I have more important things to do.", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("As far as I'm concerned, you can rot down here — mother.", minetest.colorize("#666", "???"), "artifact_tav_splash_low.png")
minetest.after(1, function()
local door = artifact.large_doors[artifact.origin:offset(137, -69, -22):round():to_string()]
door:open()
minetest.after(3, function()
door:close()
end)
end)
end)
i = i +5
minetest.after(i, function()
artifact.push_chat_message("Excuse me!?", "Key", "artifact_key_splash_low.png")
artifact.push_chat_message("Excuse me!?", "Vix", "artifact_vix_splash_low.png")
end)
i = i +3
minetest.after(i, function()
artifact.push_chat_message("Hey! You're being so cliche right now!", "Key", "artifact_key_splash_low.png")
end)
i = i +7
minetest.after(i, function()
artifact.push_chat_message("Well, that was weird.", "Key", "artifact_key_splash_low.png")
end)
i = i +9
minetest.after(i, function()
artifact.push_chat_message("...So, Vix, you wouldn't happen to know of any ventilation shafts conveniently placed nearby, would you?", "Key", "artifact_key_splash_low.png")
end)
i = i +6
minetest.after(i, function()
artifact.push_chat_message("Well, there is one...", "Vix", "artifact_vix_splash_low.png")
end)
i = i +4
minetest.after(i, function()
artifact.push_chat_message("Nice. Let's get out of this place.", "Key", "artifact_key_splash_low.png")
end)
i = i +4
minetest.after(i, function()
ns.enter_state(ns.states.ended)
end)
end
-- Play the opening cutscene. -- Play the opening cutscene.
function ns.play_intro_cutscene() function ns.play_intro_cutscene()
ns.camera = minetest.add_entity(artifact.origin:offset(0,-0.75,0), "display") ns.camera = minetest.add_entity(artifact.origin:offset(0,-0.75,0), "display")
@ -391,7 +952,7 @@ function ns.load_map()
m.hud.loading_map_bg.remove_after = 0.3 m.hud.loading_map_bg.remove_after = 0.3
m.object:set_pos(start) m.object:set_pos(start)
end end
ns.enter_state(artifact.story.states.pre_vix) ns.enter_state(artifact.story.states.init)
end) end)
end) end)
end) end)
@ -402,6 +963,11 @@ include "objectives.lua"
local started = false local started = false
minetest.register_on_joinplayer(function(p) minetest.register_on_joinplayer(function(p)
local m = artifact.players[p:get_player_name()] local m = artifact.players[p:get_player_name()]
if state == ns.states.ended then
minetest.request_shutdown("You completed the game.")
end
-- Only add the HUD etc. if the player is actually in the game. -- Only add the HUD etc. if the player is actually in the game.
if state == ns.states.init then if state == ns.states.init then
m.object:set_attach(ns.camera) m.object:set_attach(ns.camera)
@ -417,6 +983,11 @@ minetest.register_on_joinplayer(function(p)
wielditem = true wielditem = true
} }
end end
if state == ns.states.pre_vix and db:get_int("checkpoint:pre_vix_fields_broken") >= 5 then
-- If the player left during the scene for some reason, start it over when they join back.
ns.play_vix_scene()
end
-- So we only call this when the _first_ player joins. -- So we only call this when the _first_ player joins.
-- Sure, we're technically a singleplayer game, but, -- Sure, we're technically a singleplayer game, but,
-- as they say, better to have it and not need it than -- as they say, better to have it and not need it than

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -103,6 +103,35 @@ local function rep(tx, size)
end end
-- Sound tables for material types.
artifact.sounds = {
stone = {
footstep = "artifact_step_stone"
},
mossy_stone = {
footstep = "artifact_step_stone_mossy"
},
metal = {
footstep = "artifact_step_stone" -- We don't have a separate sound for this, so just use stone for now.
},
wood = {
footstep = "artifact_step_stone"
},
leaves = {
footstep = "artifact_step_leaves"
},
dry_leaves = {
footstep = "artifact_step_leaves_dry"
},
glass = {
footstep = "artifact_step_glass"
},
water = {
footstep = "artifact_water"
}
}
-- These nodes are only used for the intro cutscene. -- These nodes are only used for the intro cutscene.
artifact.register_node("stone_brown", { artifact.register_node("stone_brown", {
@ -144,38 +173,49 @@ artifact.register_node("torch_standing", {
-- End ad-hoc nodes. -- End ad-hoc nodes.
artifact.register_node("stone", { artifact.register_node("stone", {
tiles = {{name = "artifact_stone.png", align_style = "world"}}, tiles = {{name = "artifact_stone.png", align_style = "world"}},
_variants = {"stair", "slab"} _variants = {"stair", "slab"},
sounds = artifact.sounds.stone,
}) })
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"}, _variants = {"stair", "slab"},
sounds = artifact.sounds.mossy_stone,
}) })
artifact.register_node("stone_bricks", { artifact.register_node("stone_bricks", {
tiles = {{name = "artifact_stone_bricks.png", align_style = "world"}}, tiles = {{name = "artifact_stone_bricks.png", align_style = "world"}},
_variants = {"stair", "slab"}, _variants = {"stair", "slab"},
sounds = artifact.sounds.stone,
}) })
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"}, _variants = {"stair", "slab"},
sounds = artifact.sounds.mossy_stone,
}) })
artifact.register_node("stone_bricks_small", { artifact.register_node("stone_bricks_small", {
tiles = {{name = "artifact_stone_bricks_small.png", align_style = "world"}}, tiles = {{name = "artifact_stone_bricks_small.png", align_style = "world"}},
_variants = {"stair", "slab"}, _variants = {"stair", "slab"},
sounds = artifact.sounds.stone,
})
artifact.register_node("stone_bricks_small_mossy", {
tiles = {{name = rep("artifact_stone_bricks_small.png", 4).."^artifact_moss_bricks_small.png", align_style = "world", scale = 4}},
_variants = {"stair", "slab"},
sounds = artifact.sounds.mossy_stone,
}) })
artifact.register_node("stone_tile", { artifact.register_node("stone_tile", {
tiles = {{name = "artifact_stone_tile.png", align_style = "world"}}, tiles = {{name = "artifact_stone_tile.png", align_style = "world"}},
_variants = {"stair", "slab"}, _variants = {"stair", "slab"},
sounds = artifact.sounds.stone,
}) })
artifact.register_node("stone_tile_small", { artifact.register_node("stone_tile_small", {
tiles = {{name = "artifact_stone_tile_small.png", align_style = "world"}}, tiles = {{name = "artifact_stone_tile_small.png", align_style = "world"}},
_variants = {"stair", "slab"}, _variants = {"stair", "slab"},
sounds = artifact.sounds.stone,
}) })
-- Why does making this texture a tile animation darken it!? -- Why does making this texture a tile animation darken it!?
@ -188,6 +228,7 @@ artifact.register_node("water", {
pointable = artifact.debug, pointable = artifact.debug,
liquid_move_physics = true, liquid_move_physics = true,
post_effect_color = "#2d5a7c55", post_effect_color = "#2d5a7c55",
sounds = artifact.sounds.water,
liquidtype = "source", liquidtype = "source",
-- Minetest pro tip: Do not try to use aliases for these. -- Minetest pro tip: Do not try to use aliases for these.
@ -213,6 +254,7 @@ artifact.register_node("water_flowing", {
liquid_move_physics = true, liquid_move_physics = true,
post_effect_color = "#2d5a7c55", post_effect_color = "#2d5a7c55",
drop = "", drop = "",
sounds = artifact.sounds.water,
liquidtype = "flowing", liquidtype = "flowing",
liquid_alternative_source = "artifact:water", liquid_alternative_source = "artifact:water",
@ -240,6 +282,7 @@ artifact.register_node("water_static", {
pointable = artifact.debug, pointable = artifact.debug,
liquid_move_physics = true, liquid_move_physics = true,
post_effect_color = "#2d5a7c55", post_effect_color = "#2d5a7c55",
sounds = artifact.sounds.water,
}) })
@ -263,7 +306,8 @@ artifact.register_node("vines", {
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
tiles = {"artifact_vines.png"}, tiles = {"artifact_vines.png"},
use_texture_alpha = "clip" use_texture_alpha = "clip",
sounds = artifact.sounds.leaves,
}) })
artifact.register_node("vines_dry", { artifact.register_node("vines_dry", {
drawtype = "nodebox", drawtype = "nodebox",
@ -286,27 +330,50 @@ artifact.register_node("vines_dry", {
paramtype2 = "facedir", paramtype2 = "facedir",
tiles = {"artifact_vines_dry.png"}, tiles = {"artifact_vines_dry.png"},
use_texture_alpha = "clip", use_texture_alpha = "clip",
groups = {whackable = 1} groups = {whackable = 1},
sounds = artifact.sounds.dry_leaves,
on_destruct = function(pos)
artifact.play_sound {
name = "artifact_step_leaves",
pos = pos,
gain = 1.5
}
end
}) })
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 = "clip" use_texture_alpha = "clip",
sounds = artifact.sounds.leaves,
}) })
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 = "clip", use_texture_alpha = "clip",
groups = {whackable = 1} groups = {whackable = 1},
sounds = artifact.sounds.dry_leaves,
on_destruct = function(pos)
artifact.play_sound {
name = "artifact_step_leaves",
pos = pos,
gain = 1.5
}
end
}) })
artifact.register_node("wood_planks", { artifact.register_node("wood_planks", {
tiles = {{name = "artifact_wood_planks.png", align_style = "world"}}, tiles = {{name = "artifact_wood_planks.png", align_style = "world"}},
_variants = {"stair", "slab"}, _variants = {"stair", "slab"},
sounds = artifact.sounds.wood,
})
artifact.register_node("crate", {
tiles = {{name = "artifact_crate.png", align_style = "world"}},
sounds = artifact.sounds.wood,
}) })
artifact.register_node("ladder_wood", { artifact.register_node("ladder_wood", {
@ -316,7 +383,8 @@ artifact.register_node("ladder_wood", {
paramtype2 = "facedir", paramtype2 = "facedir",
tiles = {"artifact_ladder_wood.png"}, tiles = {"artifact_ladder_wood.png"},
walkable = false, walkable = false,
climbable = true climbable = true,
sounds = artifact.sounds.wood,
}) })
artifact.register_node("ladder_iron", { artifact.register_node("ladder_iron", {
@ -326,7 +394,8 @@ artifact.register_node("ladder_iron", {
paramtype2 = "facedir", paramtype2 = "facedir",
tiles = {"artifact_ladder_iron.png"}, tiles = {"artifact_ladder_iron.png"},
walkable = false, walkable = false,
climbable = true climbable = true,
sounds = artifact.sounds.metal,
}) })
@ -335,6 +404,7 @@ artifact.register_node("glass", {
use_texture_alpha = "clip", use_texture_alpha = "clip",
tiles = {"artifact_glass.png"}, tiles = {"artifact_glass.png"},
_variants = {"stair", "slab"}, _variants = {"stair", "slab"},
sounds = artifact.sounds.glass,
}) })
@ -364,6 +434,7 @@ local function register_lamp(color, brightness)
} }
} }
}, },
sounds = artifact.sounds.glass,
}) })
artifact.register_node("lamp_"..color.."_wall", { artifact.register_node("lamp_"..color.."_wall", {
drawtype = "mesh", drawtype = "mesh",
@ -398,7 +469,8 @@ local function register_lamp(color, brightness)
1/16, 6/16, 8/16 1/16, 6/16, 8/16
}, },
} }
} },
sounds = artifact.sounds.glass,
}) })
artifact.register_node("lamp_"..color.."_hanging", { artifact.register_node("lamp_"..color.."_hanging", {
drawtype = "mesh", drawtype = "mesh",
@ -424,7 +496,8 @@ local function register_lamp(color, brightness)
2/16, 4/16, 2/16 2/16, 4/16, 2/16
} }
} }
} },
sounds = artifact.sounds.glass,
}) })
end end

View file

@ -1,5 +1,6 @@
local vm_data = {} local vm_data = {}
local c_air = minetest.get_content_id("air")
local c_stone = minetest.get_content_id("artifact:stone") local c_stone = minetest.get_content_id("artifact:stone")
-- Singlenode, but the single node is stone. -- Singlenode, but the single node is stone.
@ -11,9 +12,12 @@ minetest.register_on_generated(function(vm, minp, maxp)
vm:get_data(vm_data) vm:get_data(vm_data)
for i in va:iterp(minp, maxp) do -- If we load a giant schematic initially, the parts outside view range get eaten by mapgen.
vm_data[i] = c_stone -- for i in va:iterp(minp, maxp) do
end -- if vm_data[i] == c_air then
-- vm_data[i] = c_stone
-- end
-- end
vm:set_data(vm_data) vm:set_data(vm_data)
vm:calc_lighting() vm:calc_lighting()

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB