370 lines
13 KiB
Lua
370 lines
13 KiB
Lua
anchorstone = {}
|
|
|
|
local S = minetest.get_translator()
|
|
|
|
local stone_sound = default.node_sound_stone_defaults()
|
|
local stone_texture = "default_stone.png"
|
|
local cobble_texture = "default_stone_block.png"
|
|
local anchorstone_trigger_breaks_sound = "default_tool_breaks"
|
|
|
|
local preserved_source_key = "preserved_source"
|
|
local anchorstone_name = "anchorstone:anchorstone"
|
|
local anchorstone_displaced_name = "anchorstone:displaced"
|
|
|
|
|
|
local anchorstone_resettable = minetest.settings:get_bool("anchorstone_resettable", true)
|
|
local anchorstone_ore = minetest.settings:get_bool("anchorstone_ore", true)
|
|
local anchorstone_trigger_uses = tonumber(minetest.settings:get("anchorstone_trigger_uses")) or 0
|
|
|
|
local trigger_stack_size = 99
|
|
local trigger_wear_amount = 0
|
|
local trigger_tool_capabilities = nil
|
|
if anchorstone_trigger_uses ~= 0 then
|
|
trigger_stack_size = 1
|
|
trigger_wear_amount = math.ceil(65535 / anchorstone_trigger_uses)
|
|
trigger_tool_capabilities = {
|
|
full_punch_interval=1.5,
|
|
max_drop_level=1,
|
|
groupcaps={},
|
|
damage_groups = {},
|
|
}
|
|
end
|
|
|
|
local preserve_anchorstone_meta = function(pos, oldnode, oldmeta, drops)
|
|
local preserved_source = oldmeta[preserved_source_key]
|
|
if preserved_source == nil then
|
|
preserved_source = minetest.pos_to_string(pos)
|
|
end
|
|
for index, itemstack in pairs(drops) do
|
|
if itemstack:get_name() == anchorstone_displaced_name then
|
|
itemstack_meta = itemstack:get_meta()
|
|
itemstack_meta:set_string(preserved_source_key, preserved_source)
|
|
itemstack_meta:set_string("description", S("Anchorstone from @1", preserved_source))
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_node(anchorstone_name, {
|
|
description = S("Native Anchorstone"),
|
|
_doc_items_longdesc = S('A strange mineral that has become mystically bonded to the location in space that it has rested in for so long.'),
|
|
_doc_items_usagehelp = S('When dug out and relocated native anchorstone becomes "displaced" anchorstone. It retains an affinity for the location it was bonded to that can be exploited to teleport objects there, with the right tools.'),
|
|
drawtype = "normal",
|
|
tiles = {stone_texture.."^anchorstone_spark.png"},
|
|
is_ground_content = true,
|
|
node_box = {type="regular"},
|
|
sounds = stone_sound,
|
|
groups = {cracky = 3, stone = 1},
|
|
drop = anchorstone_displaced_name,
|
|
preserve_metadata = preserve_anchorstone_meta,
|
|
})
|
|
|
|
local particle_node_pos_spread = vector.new(0.5,0.5,0.5)
|
|
local particle_user_pos_spread = vector.new(0.5,1.5,0.5)
|
|
local particle_speed_spread = vector.new(0.1,0.1,0.1)
|
|
local min_spark_delay = 30
|
|
local max_spark_delay = 120
|
|
|
|
minetest.register_node(anchorstone_displaced_name, {
|
|
description = S("Displaced Anchorstone"),
|
|
_doc_items_longdesc = S("Anchorstone that bonded to one location but that has been relocated somewhere else."),
|
|
_doc_items_usagehelp = S("Displaced anchorstone would really rather be back in its original location. The bond isn't strong enough to drag it there spontaneously, but the residual spatial tension can be used to teleport other objects there with the right tools."),
|
|
drawtype = "normal",
|
|
tiles = {cobble_texture.."^anchorstone_spark_saturated.png"},
|
|
is_ground_content = true,
|
|
node_box = {type="regular"},
|
|
sounds = stone_sound,
|
|
groups = {cracky = 3, stone = 1, not_in_creative_inventory = 1},
|
|
stack_max = 1,
|
|
|
|
preserve_metadata = preserve_anchorstone_meta,
|
|
|
|
-- Called after constructing node when node was placed using
|
|
-- minetest.item_place_node / minetest.place_node.
|
|
-- If return true no item is taken from itemstack.
|
|
-- `placer` may be any valid ObjectRef or nil.
|
|
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
|
local item_meta = itemstack:get_meta()
|
|
local preserved_source = item_meta:get(preserved_source_key)
|
|
if preserved_source and minetest.string_to_pos(preserved_source) then
|
|
local node_meta = minetest.get_meta(pos)
|
|
node_meta:set_string(preserved_source_key, preserved_source)
|
|
node_meta:mark_as_private(preserved_source_key)
|
|
local node_timer = minetest.get_node_timer(pos)
|
|
node_timer:start(math.random(min_spark_delay, max_spark_delay))
|
|
else
|
|
-- metadata was lost somehow, alas.
|
|
minetest.set_node(pos, {name = anchorstone_name})
|
|
end
|
|
end,
|
|
|
|
on_blast = function(pos, intensity)
|
|
local meta = minetest.get_meta(pos)
|
|
local preserved_source = meta:get(preserved_source_key)
|
|
if preserved_source then
|
|
local preserved_source_pos = minetest.string_to_pos(preserved_source)
|
|
if preserved_source_pos then
|
|
local item = ItemStack(anchorstone_displaced_name)
|
|
local item_meta = item:get_meta()
|
|
item_meta:set_string(preserved_source_key, preserved_source)
|
|
minetest.item_drop(item, nil, pos)
|
|
end
|
|
end
|
|
minetest.set_node(pos, {name = "air"})
|
|
end,
|
|
|
|
on_timer = function(pos, elapsed)
|
|
local meta = minetest.get_meta(pos)
|
|
local preserved_source = meta:get(preserved_source_key)
|
|
if preserved_source then
|
|
local preserved_source_pos = minetest.string_to_pos(preserved_source)
|
|
if preserved_source_pos then
|
|
local dir = vector.multiply(vector.direction(pos, preserved_source_pos), 3)
|
|
minetest.add_particlespawner({
|
|
amount = 10,
|
|
time = 0.5,
|
|
minpos = vector.subtract(pos, particle_node_pos_spread),
|
|
maxpos = vector.add(pos, particle_node_pos_spread),
|
|
minvel = vector.subtract(dir, particle_speed_spread),
|
|
maxvel = vector.add(dir, particle_speed_spread),
|
|
minacc = {x=0, y=0, z=0},
|
|
maxacc = {x=0, y=0, z=0},
|
|
minexptime = 1,
|
|
maxexptime = 3,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
texture = "anchorstone_spark.png",
|
|
})
|
|
|
|
local node_timer = minetest.get_node_timer(pos)
|
|
node_timer:start(math.random(min_spark_delay, max_spark_delay))
|
|
return
|
|
end
|
|
end
|
|
-- metadata was lost somehow, revert to anchorstone
|
|
minetest.set_node(pos, {name = anchorstone_name})
|
|
end,
|
|
})
|
|
|
|
local trigger_help_addendum = ""
|
|
if anchorstone_trigger_uses > 0 then
|
|
trigger_help_addendum = S(" This tool can be used @1 times before breaking.", anchorstone_trigger_uses)
|
|
end
|
|
|
|
local trigger_def = {
|
|
description = S("Anchorstone Trigger"),
|
|
_doc_items_longdesc = S("A triggering device that allows teleportation via displaced anchorstone."),
|
|
_doc_items_usagehelp = S("When applied to a piece of displaced anchorstone this tool becomes entangled in the connection it has to its original location and is magically dragged there (along with whatever's holding on to it).") .. trigger_help_addendum,
|
|
inventory_image = "anchorstone_spark.png^anchorstone_tool_base.png",
|
|
stack_max = trigger_stack_size,
|
|
tool_capabilites = trigger_tool_capabilities,
|
|
sound = {
|
|
breaks = anchorstone_trigger_breaks_sound,
|
|
},
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return itemstack
|
|
end
|
|
|
|
local pos = pointed_thing.under
|
|
local node = minetest.get_node(pos)
|
|
|
|
if not node then
|
|
return itemstack
|
|
end
|
|
if node.name ~= anchorstone_displaced_name then
|
|
return itemstack
|
|
end
|
|
|
|
local node_meta = minetest.get_meta(pos)
|
|
if not node_meta then
|
|
return itemstack
|
|
end
|
|
|
|
local preserved_source_string = node_meta:get(preserved_source_key)
|
|
if not preserved_source_string then
|
|
return itemstack
|
|
end
|
|
|
|
local preserved_pos = minetest.string_to_pos(preserved_source_string)
|
|
if not preserved_pos then
|
|
return itemstack
|
|
end
|
|
|
|
local old_pos = user:get_pos()
|
|
old_pos.y = old_pos.y + 0.5
|
|
|
|
local speed = vector.multiply(vector.direction(old_pos, preserved_pos), 5/0.5)
|
|
minetest.add_particlespawner({
|
|
amount = 100,
|
|
time = 0.1,
|
|
minpos = vector.subtract(old_pos, particle_node_pos_spread),
|
|
maxpos = vector.add(old_pos, particle_user_pos_spread),
|
|
minvel = vector.subtract(speed, particle_speed_spread),
|
|
maxvel = vector.add(speed, particle_speed_spread),
|
|
minacc = {x=0, y=0, z=0},
|
|
maxacc = {x=0, y=0, z=0},
|
|
minexptime = 0.1,
|
|
maxexptime = 0.5,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
texture = "anchorstone_spark.png",
|
|
})
|
|
minetest.sound_play({name="anchorstone_teleport_from"}, {pos = old_pos}, true)
|
|
|
|
user:set_pos({x=preserved_pos.x, y=preserved_pos.y-0.5, z=preserved_pos.z})
|
|
|
|
preserved_pos = vector.subtract(preserved_pos, speed)
|
|
minetest.add_particlespawner({
|
|
amount = 100,
|
|
time = 0.1,
|
|
minpos = vector.subtract(preserved_pos, particle_node_pos_spread),
|
|
maxpos = vector.add(preserved_pos, particle_user_pos_spread),
|
|
minvel = vector.subtract(speed, particle_speed_spread),
|
|
maxvel = vector.add(speed, particle_speed_spread),
|
|
minacc = {x=0, y=0, z=0},
|
|
maxacc = {x=0, y=0, z=0},
|
|
minexptime = 0.5,
|
|
maxexptime = 0.5,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
texture = "anchorstone_spark.png",
|
|
})
|
|
minetest.sound_play({name="anchorstone_teleport_to"}, {pos = preserved_pos}, true)
|
|
|
|
if trigger_wear_amount > 0 then
|
|
itemstack:add_wear(trigger_wear_amount)
|
|
end
|
|
|
|
return itemstack
|
|
end
|
|
}
|
|
|
|
if trigger_tool_capabilities then
|
|
minetest.register_tool("anchorstone:trigger", trigger_def)
|
|
else
|
|
minetest.register_craftitem("anchorstone:trigger", trigger_def)
|
|
end
|
|
|
|
minetest.register_craftitem("anchorstone:reader", {
|
|
description = S("Anchorstone Reader"),
|
|
_doc_items_longdesc = S("A much weaker form of the anchorstone trigger, this tool is able to determine the strength and direction of a displaced anchorstone's bond."),
|
|
_doc_items_usagehelp = S("Simply apply this tool to a piece of displaced anchorstone and it will tell you the location it originated from."),
|
|
inventory_image = "anchorstone_spark.png^[colorize:#8888FF:128^anchorstone_tool_base.png",
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
if user == nil then
|
|
return itemstack
|
|
end
|
|
|
|
if pointed_thing.type ~= "node" then
|
|
return itemstack
|
|
end
|
|
|
|
local pos = pointed_thing.under
|
|
local node = minetest.get_node(pos)
|
|
|
|
if not node then
|
|
return itemstack
|
|
end
|
|
if node.name ~= anchorstone_displaced_name then
|
|
return itemstack
|
|
end
|
|
|
|
local node_meta = minetest.get_meta(pos)
|
|
if not node_meta then
|
|
return itemstack
|
|
end
|
|
|
|
local preserved_source_string = node_meta:get(preserved_source_key)
|
|
if not preserved_source_string then
|
|
return itemstack
|
|
end
|
|
|
|
local preserved_pos = minetest.string_to_pos(preserved_source_string)
|
|
if not preserved_pos then
|
|
return itemstack
|
|
end
|
|
|
|
minetest.chat_send_player(user:get_player_name(), S("Anchorstone origin: @1, @2m away", preserved_source_string, math.floor(vector.distance(pos, preserved_pos))))
|
|
|
|
return itemstack
|
|
end
|
|
})
|
|
|
|
-- An external API to allow convenient creation of displaced anchorstone by other mods
|
|
anchorstone.place_displaced_anchorstone_node = function(pos, destination_pos)
|
|
minetest.set_node(pos, {name = anchorstone_displaced_name})
|
|
local node_meta = minetest.get_meta(pos)
|
|
node_meta:set_string(preserved_source_key, destination_pos)
|
|
node_meta:mark_as_private(preserved_source_key)
|
|
local node_timer = minetest.get_node_timer(pos)
|
|
node_timer:start(math.random(min_spark_delay, max_spark_delay))
|
|
end
|
|
|
|
anchorstone.create_displaced_anchorstone_item = function(destination_pos)
|
|
local item = ItemStack(anchorstone_displaced_name)
|
|
local preserved_source = minetest.pos_to_string(destination_pos)
|
|
itemstack_meta = item:get_meta()
|
|
itemstack_meta:set_string(preserved_source_key, preserved_source)
|
|
itemstack_meta:set_string("description", S("Anchorstone from @1", preserved_source))
|
|
return item
|
|
end
|
|
|
|
----------------------------------------------
|
|
-- More default mod dependencies:
|
|
|
|
minetest.register_craft({
|
|
output = "anchorstone:trigger",
|
|
recipe = {
|
|
{"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
|
|
{"default:mese_crystal_fragment", anchorstone_displaced_name, "default:mese_crystal_fragment"},
|
|
{"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"}
|
|
}
|
|
})
|
|
|
|
if anchorstone_resettable then
|
|
-- Allows players to do arbitrary anchorstone placement
|
|
minetest.register_craft({
|
|
output = anchorstone_name,
|
|
recipe = {
|
|
{"default:mese_crystal_fragment", "bucket:bucket_lava", "default:mese_crystal_fragment"},
|
|
{"bucket:bucket_lava", anchorstone_displaced_name, "bucket:bucket_lava"},
|
|
{"default:mese_crystal_fragment", "bucket:bucket_lava", "default:mese_crystal_fragment"}
|
|
},
|
|
replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}, {"bucket:bucket_lava", "bucket:bucket_empty"}, {"bucket:bucket_lava", "bucket:bucket_empty"}, {"bucket:bucket_lava", "bucket:bucket_empty"}},
|
|
})
|
|
end
|
|
|
|
minetest.register_craft({
|
|
output = "anchorstone:reader",
|
|
recipe = {
|
|
{"", "default:steel_ingot", ""},
|
|
{"default:steel_ingot", anchorstone_displaced_name, "default:steel_ingot"},
|
|
{"", "default:steel_ingot", ""}
|
|
}
|
|
})
|
|
|
|
if anchorstone_ore then
|
|
|
|
minetest.register_ore({
|
|
ore_type = "scatter",
|
|
ore = anchorstone_name,
|
|
wherein = "default:stone",
|
|
clust_scarcity = 32 * 32 * 32,
|
|
-- Ore has a 1 out of clust_scarcity chance of spawning in a node.
|
|
-- If the desired average distance between ores is 'd', set this to
|
|
-- d * d * d.
|
|
|
|
clust_num_ores = 3,
|
|
clust_size = 2,
|
|
|
|
y_min = -31000,
|
|
y_max = 31000,
|
|
})
|
|
end
|