2023-02-07 07:24:12 +01:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
2023-02-12 01:04:25 +01:00
local modmeta = minetest.get_mod_storage ( )
2023-02-12 20:01:12 +01:00
local cairn_spacing = tonumber ( minetest.settings : get ( " collectible_lore_cairn_spacing " ) ) or 500
local torch_node = { name = df_dependencies.node_name_torch , param2 = 1 }
collectible_lore.get_light_node = function ( )
return torch_node
end
2023-02-12 11:11:46 +01:00
2023-02-12 04:06:51 +01:00
local cairn_area = AreaStore ( )
local existing_area = modmeta : get ( " areastore_cairn " )
if existing_area then
cairn_area : from_string ( existing_area )
end
2023-02-12 20:01:12 +01:00
local get_itemslot_bg = df_dependencies.get_itemslot_bg
function get_cairn_formspec ( pos )
local spos = pos.x .. " , " .. pos.y .. " , " .. pos.z
local formspec =
" size[8,9] "
.. " list[nodemeta: " .. spos .. " ;main;0,0.3;8,4;] "
.. " list[current_player;main;0,4.85;8,1;] "
.. " list[current_player;main;0,6.08;8,3;8] "
.. " listring[nodemeta: " .. spos .. " ;main] "
.. " listring[current_player;main] "
.. get_itemslot_bg ( 0 , 0.3 , 8 , 4 )
.. get_itemslot_bg ( 0 , 4.85 , 8 , 1 )
.. get_itemslot_bg ( 0 , 6.08 , 8 , 3 )
if minetest.get_modpath ( " default " ) then
formspec = formspec .. default.get_hotbar_bg ( 0 , 4.85 )
end
return formspec
end
2023-02-12 01:04:25 +01:00
local get_cairn_looted_by_list = function ( pos )
local loot_list_string = modmeta : get ( " cairn_ " .. minetest.pos_to_string ( pos ) )
if not loot_list_string then
return { }
end
return minetest.deserialize ( loot_list_string )
end
local set_cairn_looted_by_list = function ( pos , list )
modmeta : set_string ( " cairn_ " .. minetest.pos_to_string ( pos ) , minetest.serialize ( list ) )
end
2023-02-12 20:01:12 +01:00
local cairn_last_collected_index
2023-02-12 04:43:09 +01:00
local cairn_loot = function ( pos , player )
local player_name = player : get_player_name ( )
if not player_name then return end
2023-02-12 01:04:25 +01:00
local list = get_cairn_looted_by_list ( pos )
2023-02-12 20:01:12 +01:00
if list [ player_name ] then
minetest.chat_send_player ( player_name , S ( " You've already collected the lore hidden in this cairn. " ) )
minetest.show_formspec ( player_name , " collectible_lore:cairn_inventory " , get_cairn_formspec ( pos ) )
return false
end
2023-02-12 01:04:25 +01:00
list [ player_name ] = true
2023-02-12 11:11:46 +01:00
local uncollected = collectible_lore.get_player_uncollected_list ( player_name )
--minetest.debug(dump(uncollected))
if next ( uncollected ) then
local random_lorebook = uncollected [ math.random ( # uncollected ) ]
2023-02-12 20:01:12 +01:00
cairn_last_collected_index = random_lorebook
2023-02-12 11:11:46 +01:00
collectible_lore.collect ( player_name , collectible_lore.lorebooks [ random_lorebook ] . id )
minetest.show_formspec ( player_name , " collectible_lore:collected " ,
2023-02-12 20:01:12 +01:00
" formspec_version[6]size[8,2]label[0.5,0.5; "
.. S ( " You've found a collectible item of lore titled: \n @1 " , collectible_lore.lorebooks [ random_lorebook ] . title )
.. " ]button_exit[1,1.5;2,0.4;exit; " .. S ( " Exit " )
.. " ]button[5,1.5;2,0.4;view; " .. S ( " View " ) .. " ] " )
2023-02-12 11:11:46 +01:00
list [ player_name ] = true
set_cairn_looted_by_list ( pos , list )
else
2023-02-12 20:01:12 +01:00
minetest.chat_send_player ( player_name , S ( " You've found all of the collectible items contained in cairns like this one " ) )
minetest.show_formspec ( player_name , " collectible_lore:cairn_inventory " , get_cairn_formspec ( pos ) )
return false
2023-02-12 11:11:46 +01:00
end
2023-02-12 04:43:09 +01:00
local leftover = player : get_inventory ( ) : add_item ( " main " , " collectible_lore:satchel " )
if not leftover : is_empty ( ) then
minetest.item_drop ( leftover , player , vector.add ( pos , vector.new ( 0 , 1 , 0 ) ) )
end
2023-02-12 01:04:25 +01:00
return true
end
2023-02-12 23:53:17 +01:00
local function drop_item_stack ( pos , stack )
if not stack or stack : is_empty ( ) then return end
local drop_offset = vector.new ( math.random ( ) - 0.5 , 0 , math.random ( ) - 0.5 )
minetest.add_item ( vector.add ( pos , drop_offset ) , stack )
end
2023-02-12 00:13:12 +01:00
minetest.register_node ( " collectible_lore:cairn " , {
2023-02-07 07:24:12 +01:00
description = S ( " Cairn " ) ,
2023-02-12 21:06:08 +01:00
_doc_items_longdesc = S ( " A cairn of rocks constructed by a previous explorer to protect documents and supplies. " ) ,
_doc_items_usagehelp = S ( " The first time you discover a cairn like this, it may reveal to you some new record or piece of lore. Afterward it can be used as a public storage location. " ) ,
2023-02-07 07:24:12 +01:00
drawtype = " nodebox " ,
2023-02-12 23:45:26 +01:00
tiles = { df_dependencies.texture_cobble , df_dependencies.texture_cobble , df_dependencies.texture_cobble .. " ^(collectible_lore_cairn_marker.png^[multiply:#100000^[opacity:128) " } ,
2023-02-12 20:01:12 +01:00
is_ground_content = true ,
groups = { cracky = 3 , container = 2 } ,
_mcl_hardness = 1.5 ,
_mcl_blast_resistance = 6 ,
2023-02-07 07:24:12 +01:00
drop = df_dependencies.node_name_cobble ,
2023-02-12 20:01:12 +01:00
sounds = df_dependencies.sound_stone ( ) ,
2023-02-07 07:24:12 +01:00
paramtype = " light " ,
paramtype2 = " facedir " ,
node_box = {
type = " fixed " ,
fixed = {
{ - 0.5 , - 0.5 , - 0.5 , 0.5 , 0 , 0.5 } ,
{ - 0.4375 , 0 , - 0.4375 , 0.4375 , 0.5 , 0.4375 } ,
2023-02-12 20:01:12 +01:00
--{-0.25, 0.5, -0.25, 0.25, 1, 0.25}
2023-02-07 07:24:12 +01:00
}
} ,
2023-02-12 20:01:12 +01:00
-- collision_box = {
-- type = "fixed",
-- fixed = {
-- {-0.5, -0.5, -0.5, 0.5, 1, 0.5}
-- }
-- },
-- selection_box = {
-- type = "fixed",
-- fixed = {
-- {-0.5, -0.5, -0.5, 0.5, 1, 0.5}
-- }
-- },
2023-02-12 01:04:25 +01:00
on_rightclick = function ( pos , node , clicker , itemstack , pointed_thing )
2023-02-12 04:43:09 +01:00
cairn_loot ( pos , clicker )
2023-02-12 01:04:25 +01:00
end ,
2023-02-12 04:06:51 +01:00
can_dig = function ( pos , player )
2023-02-12 20:01:12 +01:00
local inv = minetest.get_meta ( pos ) : get_inventory ( )
return minetest.check_player_privs ( player , { server = true } ) and inv : is_empty ( " main " )
2023-02-12 04:06:51 +01:00
end ,
on_destruct = function ( pos )
modmeta : set_string ( " cairn_ " .. minetest.pos_to_string ( pos ) , " " )
local this_cairn = cairn_area : get_areas_for_pos ( pos )
for index , data in pairs ( this_cairn ) do
2023-02-12 20:01:12 +01:00
--minetest.debug("removing " .. dump(index))
2023-02-12 04:06:51 +01:00
cairn_area : remove_area ( index )
modmeta : set_string ( " areastore_cairn " , cairn_area : to_string ( ) )
end
end ,
on_construct = function ( pos )
2023-02-12 20:01:12 +01:00
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
inv : set_size ( " main " , 8 * 4 )
2023-02-12 21:06:08 +01:00
local nearby = collectible_lore.are_cairns_close_to_pos ( pos )
if nearby then
2023-02-12 20:01:12 +01:00
minetest.log ( " error " , " Cairn placed too close to other cairns. Placed at: " .. minetest.pos_to_string ( pos ) )
for _ , data in pairs ( nearby ) do
minetest.log ( " error " , " nearby: " .. minetest.pos_to_string ( data.min ) )
end
2023-02-12 04:06:51 +01:00
end
cairn_area : insert_area ( pos , pos , " " )
modmeta : set_string ( " areastore_cairn " , cairn_area : to_string ( ) )
2023-02-12 20:01:12 +01:00
local above_pos = { x = pos.x , y = pos.y + 1 , z = pos.z }
local above_node = minetest.get_node ( above_pos )
if minetest.registered_nodes [ above_node.name ] . buildable_to then
minetest.set_node ( above_pos , collectible_lore.get_light_node ( ) )
end
2023-02-12 04:06:51 +01:00
end ,
2023-02-12 20:01:12 +01:00
on_blast = function ( pos , intensity )
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
for i = 1 , inv : get_size ( " main " ) do
drop_item_stack ( pos , inv : get_stack ( " main " , i ) )
end
meta : from_table ( )
minetest.remove_node ( pos )
end ,
2023-02-07 07:24:12 +01:00
} )
2023-02-12 11:11:46 +01:00
collectible_lore.get_nearby_cairns = function ( pos , spacing )
local nearby = cairn_area : get_areas_in_area ( vector.subtract ( pos , spacing / 2 ) , vector.add ( pos , spacing / 2 ) )
2023-02-12 04:06:51 +01:00
if next ( nearby ) then
return nearby
end
return nil
end
2023-02-12 21:06:08 +01:00
collectible_lore.are_cairns_close_to_pos = function ( pos )
2023-02-12 11:11:46 +01:00
local nearby = collectible_lore.get_nearby_cairns ( pos , cairn_spacing )
2023-02-12 21:06:08 +01:00
if nearby then return nearby end
return false
end
collectible_lore.place_cairn = function ( pos )
if collectible_lore.are_cairns_close_to_pos ( pos ) then return end
2023-02-12 20:01:12 +01:00
minetest.set_node ( pos , { name = " collectible_lore:cairn " } )
2023-02-12 21:06:08 +01:00
--minetest.debug("placed " .. minetest.pos_to_string(pos))
2023-02-12 04:06:51 +01:00
end
2023-02-07 07:24:12 +01:00
local player_state = { }
local get_formspec_for_player = function ( player_name )
local selected
local state = player_state [ player_name ] or 1
2023-02-12 11:11:46 +01:00
local collected = collectible_lore.get_player_collected ( player_name )
local collected_count = 0
for index , val in pairs ( collected ) do
collected_count = collected_count + 1
end
2023-02-07 07:24:12 +01:00
local form = { }
2023-02-12 11:11:46 +01:00
table.insert ( form , " formspec_version[6]size[14,8] " )
table.insert ( form , " textlist[0.5,0.5;5,6.5;list; " )
if collected_count > 0 then
local count = 1
for index , value in pairs ( collectible_lore.lorebooks ) do
local iscollected = collected [ value.id ]
if iscollected and state == count then
selected = value
end
count = count + 1
if iscollected then
table.insert ( form , minetest.formspec_escape ( value.title ) )
else
2023-02-12 20:01:12 +01:00
table.insert ( form , " \t " .. S ( " <not found yet> " ) )
2023-02-12 11:11:46 +01:00
end
table.insert ( form , " , " )
2023-02-07 07:24:12 +01:00
end
2023-02-12 11:11:46 +01:00
table.remove ( form ) -- removes trailing comma
2023-02-07 07:24:12 +01:00
end
table.insert ( form , " ; " .. state .. " ] " )
2023-02-12 01:04:25 +01:00
if selected then
2023-02-12 11:11:46 +01:00
table.insert ( form , " label[6,0.5; " .. minetest.formspec_escape ( selected.title ) .. " ] " )
if selected.text then
table.insert ( form , " textarea[6,1;7.5,6.5;;; " .. minetest.formspec_escape ( selected.text ) .. " ] " )
elseif selected.image then
table.insert ( form , " image[6.5,1;6.5,6.5; " .. selected.image .. " ] " )
end
2023-02-12 01:04:25 +01:00
end
2023-02-12 11:11:46 +01:00
table.insert ( form , " label[0.5,7.5; " .. S ( " Collected: @1/@2 " , collected_count , # ( collectible_lore.lorebooks ) ) .. " ] " )
2023-02-12 20:01:12 +01:00
table.insert ( form , " button_exit[2.75,7.3;2,0.4;exit; " .. S ( " Exit " ) .. " ] " )
2023-02-07 07:24:12 +01:00
return table.concat ( form )
end
2023-02-12 04:43:09 +01:00
minetest.register_craftitem ( " collectible_lore:satchel " , {
description = S ( " Collectibles Satchel " ) ,
2023-02-12 21:06:08 +01:00
_doc_items_longdesc = S ( " A satchel containing various documents you've recovered in your travels. " ) ,
_doc_items_usagehelp = S ( " The documents and lore you've unlocked are not tied to a specific satchel, any satchel will let you view your personal collection. " ) ,
2023-02-12 04:43:09 +01:00
inventory_image = " collectible_lore_satchel.png " ,
2023-02-07 07:24:12 +01:00
stack_max = 99 ,
on_use = function ( itemstack , user , pointed_thing )
local player_name = user : get_player_name ( )
2023-02-12 00:13:12 +01:00
minetest.show_formspec ( player_name , " collectible_lore:formspec " , get_formspec_for_player ( player_name ) )
2023-02-07 07:24:12 +01:00
end
} )
2023-02-12 23:45:26 +01:00
minetest.register_craft ( {
output = " collectible_lore:satchel " ,
recipe = {
{ " " , df_dependencies.node_name_string , " " } ,
{ df_dependencies.node_name_string , " " , df_dependencies.node_name_string } ,
{ df_dependencies.node_name_wool_white , df_dependencies.node_name_wool_white , df_dependencies.node_name_wool_white } ,
} ,
} )
2023-02-07 07:24:12 +01:00
minetest.register_on_player_receive_fields ( function ( player , formname , fields )
2023-02-12 20:01:12 +01:00
if formname == " collectible_lore:formspec " then
if fields.list then
local exploded = minetest.explode_textlist_event ( fields.list )
if exploded.type == " CHG " then
local player_name = player : get_player_name ( )
player_state [ player_name ] = exploded.index
minetest.show_formspec ( player_name , " collectible_lore:formspec " , get_formspec_for_player ( player_name ) )
end
end
elseif formname == " collectible_lore:collected " then
if fields.view then
2023-02-07 07:24:12 +01:00
local player_name = player : get_player_name ( )
2023-02-12 20:01:12 +01:00
player_state [ player_name ] = cairn_last_collected_index
2023-02-12 00:13:12 +01:00
minetest.show_formspec ( player_name , " collectible_lore:formspec " , get_formspec_for_player ( player_name ) )
2023-02-07 07:24:12 +01:00
end
end
end )
2023-02-12 20:01:12 +01:00
minetest.register_chatcommand ( " cairn_locations " , {
params = " <range> " , -- Short parameter description
description = S ( " Administrative control of collectibles " ) ,
privs = { server = true } ,
func = function ( name , param )
local range = tonumber ( param ) or 1000
local player = minetest.get_player_by_name ( name )
local player_pos = player : get_pos ( )
local cairn_locations = cairn_area : get_areas_in_area ( vector.subtract ( player_pos , range ) , vector.add ( player_pos , range ) )
for _ , data in pairs ( cairn_locations ) do
minetest.chat_send_player ( name , minetest.pos_to_string ( data.min ) )
end
end ,
} )