diff --git a/TODO.MD b/TODO.MD index 0f6ded1..14d4fbd 100644 --- a/TODO.MD +++ b/TODO.MD @@ -128,3 +128,8 @@ features: catching-throwing game chooglee + + + + +librarian transcribes meta diff --git a/working_villagers/building_sign.lua b/working_villagers/building_sign.lua index b65060e..9984998 100644 --- a/working_villagers/building_sign.lua +++ b/working_villagers/building_sign.lua @@ -1,2 +1,3 @@ building_sign.register_schematic("simple_hut.we") building_sign.register_schematic("fancy_hut.we") + diff --git a/working_villagers/commanding_sceptre.lua b/working_villagers/commanding_sceptre.lua index 627ab81..e15070a 100644 --- a/working_villagers/commanding_sceptre.lua +++ b/working_villagers/commanding_sceptre.lua @@ -35,3 +35,22 @@ minetest.register_tool("working_villages:commanding_sceptre", { end end }) + +if minetest.get_modpath("homedecor_seating") then + local S = minetest.get_translator("working_villages") + + local def = table.copy(minetest.registered_nodes["homedecor:kitchen_chair_padded"]) + def.description = S("Seat of Power") + -- TODO on place... + minetest.register_node("working_villages:throne", def) + -- TODO modify villagers' on_rightclick to treat the sceptre and throne interchangeably ? + -- TODO forceload block ? + -- TODO on_node_move() => village.relocate() + + minetest.register_craft{ + output = "working_villages:throne", + recipe = { + {"working_villages:commanding_sceptre", "homedecor:kitchen_chair_padded",}, + }, + } +end diff --git a/working_villagers/jobs/empty.lua b/working_villagers/jobs/empty.lua index c3352d6..c0b11cb 100644 --- a/working_villagers/jobs/empty.lua +++ b/working_villagers/jobs/empty.lua @@ -19,3 +19,17 @@ minetest.register_craft{ {"default:paper", "default:obsidian"}, }, } + +minetest.register_craft{ + output = "building_sign:building_marker", + recipe = { + --{"working_villages:job_empty", "default:wall_sign_wood",}, + -- maybe other villagers can use other sorts of signs for their jobs ? + {"working_villages:job_builder", "default:wall_sign_wood",}, + -- hmm... maybe some "job safety" warning signs could work-around some of the movement janks + -- e.g., don't go below `y`, beware of falling nodes at `x,z`, etc. + -- maybe secret safety info can be kept in books + -- e.g., villagers should be aware of traps and other security measures intended to keep them safe + }, +} + diff --git a/working_villagers/jobs/librarian.lua b/working_villagers/jobs/librarian.lua new file mode 100644 index 0000000..4f3841d --- /dev/null +++ b/working_villagers/jobs/librarian.lua @@ -0,0 +1,149 @@ +-- TODO WIP + +local func = working_villages.require("jobs/util") +local S = minetest.get_translator("working_villages") +local trivia = working_villages.require("jobs/trivia") + +local bookshelfs = { + names = { + ["default:bookshelf"] = {}, + }, +} + +local bookkeeping_demands = { + ["default:book"] = 99, + ["default:book_written"] = 99, +} + +function bookshelfs.get_book(item_name) + -- check more priority definitions + for key, value in pairs(bookshelfs.names) do + if item_name==key then + return value + end + end + return nil +end + +function bookshelfs.is_book(item_name) + local data = bookshelfs.get_book(item_name); + if (not data) then + return false; + end + return true; +end + +-- TODO support other types of magick items +local function find_book_nodes(self) + return function(pos) + if minetest.is_protected(pos, "") then return false end + if working_villages.failed_pos_test(pos) then return false end + + local node = minetest.get_node(pos); + local data = bookshelfs.get_book(node.name); + if (not data) then + return false; + end + local meta = minetest.get_meta(pos) + local text = meta:get_string("text") + local owner = meta:get_string("owner") + local title = meta:get_string("title") + if text == nil or text == "" then return false end + if owner == nil or owner == "" then return false end + if title == nil or title == "" then return false end + return true; + end +end + +local searching_range = {x = 10, y = 3, z = 10} + +local function put_func(_,stack) + return bookkeeping_demands[stack:get_name()] == nil +end +local function take_func(villager,stack) + local item_name = stack:get_name() + if not bookkeeping_demands[item_name] then return false end + local inv = villager:get_inventory() + local itemstack = ItemStack(item_name) + itemstack:set_count(bookkeeping_demands[item_name]) + --return (not inv:contains_item("wield_item", itemstack)) + return (not inv:contains_item("main", itemstack)) +end + +working_villages.register_job("working_villages:job_librarian", { + description = S("librarian (working_villages)"), + long_description = S("I look for all sorts of bookshelfs and start brute forcing the magick key."), + trivia = trivia.get_trivia({ + }, {trivia.unfinished, trivia.meta,}), + workflow = { + S("Wake up"), + S("Handle my chest"), + S("Equip my tool"), + S("Go to work"), + S("Search for bookshelfs"), + S("Go to bookshelfs"), + S("Use/dig the bookshelfs"), + S("Periodically look away thoughtfully"), + }, + inventory_image = "default_paper.png^working_villages_builder.png", + -- TODO on_create handler to setup mana & hp + jobfunc = function(self) + self:handle_night() + self:handle_chest(take_func, put_func) + self:handle_job_pos() + + self:count_timer("librarian:search") + self:count_timer("librarian:change_dir") + self:handle_obstacles() + if self:timer_exceeded("librarian:search",20) then + self:collect_nearest_item_by_condition(bookshelfs.is_book, searching_range) + local target = func.search_surrounding(self.object:get_pos(), find_book_nodes(self), searching_range) + if target ~= nil then + local destination = func.find_adjacent_clear(target) + if destination then + destination = func.find_ground_below(destination) + end + if destination==false then + print("failure: no adjacent walkable found") + destination = target + end + self:set_displayed_action("copying some books") + --self:go_to(destination) + local success, ret = self:go_to(destination) + if not success then + assert(target ~= nil) + working_villages.failed_pos_record(target) + self:set_displayed_action("looking at the unreachable snow") + self:delay(100) + else + -- TODO for book in inventory + -- check whether a copy already exists on the shelf + -- if not, copy the book and place it on the shelf + -- ehh... I need to think this out some more. + -- whence should I get the empty books and the written books + -- where should I put the copies + -- one copy per shelf sounds alright + local size = vil_inv:get_size("main"); + for index = 1,size do + local stack = vil_inv:get_stack("main", index); + if (not stack:is_empty()) + and stack:get_name() == "default:book" + and not_in_shelf(stack) + then + local chest_meta = minetest.get_meta(chest_pos); + local chest_inv = chest_meta:get_inventory(); + local leftover = chest_inv:add_item("main", stack); + vil_inv:set_stack("main", index, leftover); + for _=0,10 do coroutine.yield() end --wait 10 steps + end + end + end + end + elseif self:timer_exceeded("librarian:change_dir",50) then + self:change_direction_randomly() + end + end, +}) + +working_villages.bookshelfs = bookshelfs + diff --git a/working_villagers/mod.conf b/working_villagers/mod.conf index 026d583..67f1bd3 100644 --- a/working_villagers/mod.conf +++ b/working_villagers/mod.conf @@ -1,4 +1,4 @@ name = working_villages description = A mod adding villager NPCs that are doing predefined work. Big features are planned. depends = default -optional_depends = areas,doors,beds,modutil, mcg_lockworkshop,fakery,mcg_dyemixer,crafting_bench,decraft,iadiscordia, basic_materials,biofuel,claycrafter,composting,decraft,sleeping_mat, wine,farming,snowcone,waffles,church_candles, getname, hopper +optional_depends = areas,doors,beds,modutil, mcg_lockworkshop,fakery,mcg_dyemixer,crafting_bench,decraft,iadiscordia, basic_materials,biofuel,claycrafter,composting,decraft,sleeping_mat, wine,farming,snowcone,waffles,church_candles, getname, hopper, homedecor_seating