diff --git a/mods/default/models/character.png b/mods/default/models/character.png index 0f25af4..b5dd3db 100644 Binary files a/mods/default/models/character.png and b/mods/default/models/character.png differ diff --git a/mods/npcs/init.lua b/mods/npcs/init.lua index 78a65c6..ab4ca43 100644 --- a/mods/npcs/init.lua +++ b/mods/npcs/init.lua @@ -1,8 +1,10 @@ npcs = {} npcs.npcs = {} +npcs.all_npcs = {} function npcs.register_npc(name, def) npcs.npcs[name] = true + table.insert(npcs.all_npcs, name) def.description = def.description or "NPC" def.groups = def.groups or "" @@ -20,25 +22,46 @@ function npcs.register_npc(name, def) if def.npc_type == "quest" then def.on_rightclick = function(pos, node, player, itemstack, pt) local name = player:get_player_name() - if not(quests.has_quest(name, def.npc_quest_title)) then - quests.add_quest(name, def.npc_get_quest(pos, player)) - else - --TODO + if quests.process_npc_goals(name, "talk", pt.under) then + return + end + + local q = def.npc_get_quest(pos, player) + + if not(quests.has_quest(name, q.title .. (q.id or ""))) then + local d = dialogue.new(q.text) + + d:add_option("Ok", function(n) + quests.add_quest(n, q) + end) + + d:add_option("Quit", function(n) + end) + + d:show(name) end end elseif def.npc_type == "text" then def.on_rightclick = function(pos, node, player, itemstack, pt) + if quests.process_npc_goals(player:get_player_name(), "talk", pt.under) then + return + end + local name = player:get_player_name() quests.show_text(def.npc_text, name) end elseif def.npc_type == "quests" then def.on_rightclick = function(pos, node, player, itemstack, pt) + if quests.process_npc_goals(player:get_player_name(), "talk", pt.under) then + return + end + local d = dialogue.new(def.npc_text) local my_quests = def.npc_get_quests(pos, player) for i, q in ipairs(my_quests) do - if not(quests.has_quest(player:get_player_name(), q.title)) then + if not(quests.has_quest(player:get_player_name(), q.title .. (q.id or ""))) then d:add_option(q.title, function(name) quests.add_quest(name, q) end) @@ -49,6 +72,10 @@ function npcs.register_npc(name, def) end elseif def.npc_type == "shop" then def.on_rightclick = function(pos, node, player, itemstack, pt) + if quests.process_npc_goals(player:get_player_name(), "talk", pt.under) then + return + end + local d = dialogue.new(def.npc_text) @@ -72,38 +99,89 @@ function npcs.register_npc(name, def) minetest.register_node(name, def) end ---TEST -npcs.register_npc("npcs:farmer", { - npc_type = "shop", - npc_text = "Hi!", - npc_quest_title = "Test", +minetest.register_node("npcs:spawner", { + description = "NPC Spawner", + drawtype = "airlike", +}) + +minetest.register_abm({ + nodenames = {"npcs:spawner"}, + interval = 1.0, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + minetest.set_node(pos, {name = npcs.all_npcs[math.random(#npcs.all_npcs)], param2 = math.random(0,3)}) + end, +}) + +npcs.register_npc("npcs:farmer_1", { + tiles = {"npc_1.png"}, + npc_type = "quest", npc_get_quest = function(pos, player) local quest = quests.new(nil, "Test", "Test") - local goal_1 = quests.add_place_goal(quest, "Place dirt", {"default:dirt"}, 10, "Place some dirt blocks!") + quest.id = tostring(minetest.get_day_count()) .. " " .. minetest.pos_to_string(pos) + local goal_1 = quests.add_place_goal(quest, "Place dirt", {"default:dirt"}, 1, "Place some dirt blocks!") + local goal_2 = quests.add_talk_goal(quest, "Talk", pos, "Place some dirt blocks!") + + goal_2.requires = goal_1 + return quest end, - npc_get_quests = function(pos, player) - local my_quests = {} - - do - local quest = quests.new(nil, "Test 1", "Test 1") - local goal_1 = quests.add_place_goal(quest, "Place dirt", {"default:dirt"}, 10, "Place some dirt blocks!") - table.insert(my_quests, quest) - end - - do - local quest = quests.new(nil, "Test 2", "Test 2") - local goal_1 = quests.add_place_goal(quest, "Place stone", {"default:stone"}, 10, "Place some stone blocks!") - table.insert(my_quests, quest) - end - - return my_quests - end, - npc_items = { - { - input = "default:stone_item", - output = "default:pick", - text = "Stone -> Pick", - } - }, }) + +npcs.register_npc("npcs:hunter_1", { + tiles = {"npc_2.png"}, + npc_type = "quest", + npc_get_quest = function(pos, player) + local quest = quests.new(nil, "Test", "Test") + quest.id = tostring(minetest.get_day_count()) .. " " .. minetest.pos_to_string(pos) + local goal_1 = quests.add_place_goal(quest, "Place dirt", {"default:dirt"}, 1, "Place some dirt blocks!") + local goal_2 = quests.add_talk_goal(quest, "Talk", pos, "Place some dirt blocks!") + + goal_2.requires = goal_1 + + return quest + end, +}) + +--TEST +--npcs.register_npc("npcs:farmer", { +-- tiles = {"npc_1.png"}, +-- visual_scale = 1.0, +-- npc_type = "quest", +-- npc_text = "Hi!", +-- npc_quest_title = "Test", +-- npc_get_quest = function(pos, player) +-- local quest = quests.new(nil, "Test", "Test") +-- quest.id = tostring(minetest.get_day_count()) .. " " .. minetest.pos_to_string(pos) +-- local goal_1 = quests.add_place_goal(quest, "Place dirt", {"default:dirt"}, 1, "Place some dirt blocks!") +-- local goal_2 = quests.add_talk_goal(quest, "Talk", pos, "Place some dirt blocks!") +-- +-- goal_2.requires = goal_1 +-- +-- return quest +-- end, +-- npc_get_quests = function(pos, player) +-- local my_quests = {} +-- +-- do +-- local quest = quests.new(nil, "Test 1", "Test 1") +-- local goal_1 = quests.add_place_goal(quest, "Place dirt", {"default:dirt"}, 10, "Place some dirt blocks!") +-- table.insert(my_quests, quest) +-- end +-- +-- do +-- local quest = quests.new(nil, "Test 2", "Test 2") +-- local goal_1 = quests.add_place_goal(quest, "Place stone", {"default:stone"}, 10, "Place some stone blocks!") +-- table.insert(my_quests, quest) +-- end +-- +-- return my_quests +-- end, +-- npc_items = { +-- { +-- input = "default:stone_item", +-- output = "default:pick", +-- text = "Stone -> Pick", +-- } +-- }, +--}) diff --git a/mods/npcs/textures/npc_1.png b/mods/npcs/textures/npc_1.png new file mode 100644 index 0000000..2736d80 Binary files /dev/null and b/mods/npcs/textures/npc_1.png differ diff --git a/mods/npcs/textures/npc_2.png b/mods/npcs/textures/npc_2.png new file mode 100644 index 0000000..105638e Binary files /dev/null and b/mods/npcs/textures/npc_2.png differ diff --git a/mods/quests/init.lua b/mods/quests/init.lua index 0db2fb6..2eb2832 100644 --- a/mods/quests/init.lua +++ b/mods/quests/init.lua @@ -62,8 +62,12 @@ function quests.add_quest(player, quest) end function quests.has_quest(name, title) + if not(quests.player_quests[name]) then + return false + end + for i,def in ipairs(quests.player_quests[name]) do - if def.title == title then + if def.title .. (def.id or "") == title then return true end end @@ -184,6 +188,42 @@ function quests.add_craft_goal(quest, title, item, number, description, ending) return goal end +function quests.add_talk_goal(quest, title, pos, description, ending) + local goal = { + title = title, + type = "talk", + pos = pos, + progress = 0, + max = 1, + done = false, + xp = 0, + + description = description or "", + ending = ending or nil + } + table.insert(quest.goals, goal) + return goal +end + +function quests.add_give_goal(quest, title, pos, item, number, description, ending) + local goal = { + title = title, + type = "give", + pos = pos, + item = item, + node = item, + max = number, + progress = 0, + done = false, + xp = 0, + + description = description or "", + ending = ending or nil + } + table.insert(quest.goals, goal) + return goal +end + function quests.process_node_count_goals(player, type, node, count) count = count or 1 local player_quests = quests.player_quests[player] @@ -211,6 +251,55 @@ function quests.process_node_count_goals(player, type, node, count) end) end +function quests.process_npc_goals(player, type, pos, count) + local found = false + count = count or 1 + local player_quests = quests.player_quests[player] + if not(player_quests) or #player_quests == 0 then return end + table.foreach(player_quests, function(_, quest) + if not(quest.goals) or #quest.goals == 0 then return end + table.foreach(quest.goals, function(_, goal) + if (not goal.requires or goal.requires.done) and + goal.type == type then + print("-> talk") + if vector.equals(pos, (goal.pos or vector.new(0, 0, 0))) then + if goal.type == "give" then + for i=1,#goal.node do + if goal.node[i] == node then + goal.progress = goal.progress + count + if goal.progress >= goal.max then + goal.progress = goal.max + + quests.finish_goal(player, quest, goal) + goal.done = true + end + quests.update_hud(minetest.get_player_by_name(player),player) + quests.save() + + found = true + end + end + elseif goal.type == "talk" then + goal.progress = goal.progress + count + if goal.progress >= goal.max then + goal.progress = goal.max + + quests.finish_goal(player, quest, goal) + goal.done = true + end + quests.update_hud(minetest.get_player_by_name(player),player) + quests.save() + + found = true + end + end + end + end) + end) + + return found +end + quests.show_quests_form = "size[8,7.5;]" .. default.gui_colors .. default.gui_bg .. "textlist[-0.1,-0.1;8,7.75;quests;%s]" diff --git a/mods/xp/init.lua b/mods/xp/init.lua index a4d32a0..d7cb6ac 100644 --- a/mods/xp/init.lua +++ b/mods/xp/init.lua @@ -28,7 +28,9 @@ function xp.add_xp(player, num) end end - cmsg.push_message_player(player, "You got "..tostring(num).. " xp!") + if num > 0 then + cmsg.push_message_player(player, "[xp] +"..tostring(num)) + end if xp.player_levels[player:get_player_name()] then if xp.player_xp[player:get_player_name()] > xp.lvl*xp.player_levels[player:get_player_name()] then