mirror of
https://gitea.your-land.de/Sokomine/yl_speak_up.git
synced 2025-06-19 21:58:03 +02:00
387 lines
16 KiB
Lua
387 lines
16 KiB
Lua
|
|
-- returns a table with helpful information *if* the player is working on a quest;
|
|
-- else error_msg is set
|
|
yl_speak_up.player_is_working_on_quest = function(player)
|
|
if(not(player)) then
|
|
return
|
|
end
|
|
local t = {}
|
|
t.pname = player:get_player_name()
|
|
if(not(t.pname)) then
|
|
return {error_msg = "Player not found."}
|
|
end
|
|
if(not(yl_speak_up.speak_to or not(yl_speak_up.speak_to[t.pname]))) then
|
|
return {error_msg = "Player not working on a quest."}
|
|
end
|
|
t.q_id = yl_speak_up.speak_to[t.pname].q_id
|
|
if(not(t.q_id) or not(yl_speak_up.quests) or not(yl_speak_up.quests[t.q_id])) then
|
|
return {error_msg = "No quest selected or quest not found."}
|
|
end
|
|
t.quest = yl_speak_up.quests[t.q_id]
|
|
if(not(t.quest.step_data) or type(t.quest.step_data) ~= "table") then
|
|
yl_speak_up.quests[t.q_id].step_data = {}
|
|
end
|
|
-- TODO: check if the player has access to that data
|
|
t.step_data = yl_speak_up.quests[t.q_id].step_data
|
|
t.current_step = yl_speak_up.speak_to[t.pname].quest_step
|
|
if(t.quest_step and t.step_data[t.quest_step]) then
|
|
local data = t.step_data[t.quest_step]
|
|
-- make sure needed tables exist
|
|
if(not(data.one_step_required) or type(data.one_step_required) ~= "table") then
|
|
yl_speak_up.quests[t.q_id].step_data[t.current_step].one_step_required = {}
|
|
end
|
|
if(not(data.all_steps_required) or type(data.one_step_required) ~= "table") then
|
|
yl_speak_up.quests[t.q_id].step_data[t.current_step].all_steps_required = {}
|
|
end
|
|
end
|
|
-- t contains pname, q_id, quest, step_data and current_step - or error_msg
|
|
return t
|
|
end
|
|
|
|
|
|
-- for which other quest steps is this_step needed for?
|
|
yl_speak_up.quest_step_required_for = function(step_data, this_step)
|
|
-- find out the next quest step
|
|
local required_for = {}
|
|
for s, d in pairs(step_data) do
|
|
if(s and d and d.one_step_required and type(d.one_step_required) == "table"
|
|
and table.indexof(d.one_step_required, this_step) ~= -1) then
|
|
table.insert(required_for, s)
|
|
end
|
|
if(s and d and d.all_steps_required and type(d.all_steps_required) == "table"
|
|
and table.indexof(d.all_steps_required, this_step) ~= -1) then
|
|
table.insert(required_for, s)
|
|
end
|
|
end
|
|
table.sort(required_for)
|
|
return required_for
|
|
end
|
|
|
|
|
|
-- Imposing an order on the quest steps is...tricky as best as what will
|
|
-- be more important to the players will be the order in which the
|
|
-- quest steps have to be solved/done - and not an alphabetical order.
|
|
-- But we need an order here for a dropdown menu to select each
|
|
-- quest step even if it hasn't been assigned any place in the chain
|
|
-- of quest steps yet. So - alphabetical order.
|
|
yl_speak_up.get_sorted_quest_step_list = function(pname, q_id)
|
|
local quest_step_list = {}
|
|
if(not(pname) or not(yl_speak_up.speak_to[pname])) then
|
|
return {}
|
|
end
|
|
local q_id = yl_speak_up.speak_to[pname].q_id
|
|
|
|
if(q_id and yl_speak_up.quests[q_id] and yl_speak_up.quests[q_id].step_data) then
|
|
for step_id, v in pairs(yl_speak_up.quests[q_id].step_data) do
|
|
table.insert(quest_step_list, step_id)
|
|
end
|
|
end
|
|
table.sort(quest_step_list)
|
|
return quest_step_list
|
|
end
|
|
|
|
|
|
-- helper functions for yl_speak_up.input_fs_manage_quest_steps(..)
|
|
-- returns the index of the new quest step
|
|
yl_speak_up.input_fs_manage_quest_steps_add_new_entry = function(pname, entry_name)
|
|
local q_id = yl_speak_up.speak_to[pname].q_id
|
|
local res = yl_speak_up.quest_step_add_quest_step(pname, q_id, entry_name)
|
|
-- might make sense to show the error message somewhere
|
|
if(res ~= "OK") then
|
|
return res
|
|
end
|
|
-- the new entry will be somewhere in it
|
|
local quest_step_list = yl_speak_up.get_sorted_quest_step_list(pname)
|
|
return table.indexof(quest_step_list, entry_name)
|
|
end
|
|
|
|
|
|
-- helper functions for yl_speak_up.input_fs_manage_quest_steps(..)
|
|
-- returns a text describing if deleting the quest worked
|
|
yl_speak_up.input_fs_manage_quest_steps_del_old_entry = function(pname, entry_name)
|
|
local q_id = yl_speak_up.speak_to[pname].q_id
|
|
return yl_speak_up.quest_step_del_quest_step(pname, q_id, entry_name)
|
|
end
|
|
|
|
|
|
-- helper functions for yl_speak_up.input_fs_manage_quest_steps(..)
|
|
-- implements all the functions that are specific to managing quest steps and not part of
|
|
-- general item management
|
|
yl_speak_up.input_fs_manage_quest_steps_check_fields = function(player, formname, fields, quest_step_name, list_of_entries)
|
|
local pname = player:get_player_name()
|
|
if(not(quest_step_name)) then
|
|
quest_step_name = ""
|
|
end
|
|
--[[ TODO: implement some back button functionality?
|
|
if(fields and fields.show_variable) then
|
|
yl_speak_up.show_fs(player, "manage_variables", {var_name = quest_name})
|
|
return
|
|
end
|
|
--]]
|
|
-- this function didn't have anything to do
|
|
return "NOTHING FOUND"
|
|
end
|
|
|
|
|
|
-- makes use of yl_speak_up.input_fs_manage_general and is thus pretty short
|
|
yl_speak_up.input_fs_manage_quest_steps = function(player, formname, fields)
|
|
-- TODO: check if the player is allowed to access that quest
|
|
local pname = player:get_player_name()
|
|
|
|
if(fields and fields.back) then
|
|
yl_speak_up.show_fs(player, "manage_quests")
|
|
return
|
|
end
|
|
local res = yl_speak_up.player_is_working_on_quest(player)
|
|
if(not(res.error_msg) and res.current_step) then
|
|
local selected_from = nil
|
|
local list = {}
|
|
if( fields and fields.one_step_required) then
|
|
selected_from = fields.one_step_required
|
|
list = res.step_data[res.current_step].one_step_required
|
|
elseif(fields and fields.all_steps_required) then
|
|
selected_from = fields.all_steps_required
|
|
list = res.step_data[res.current_step].all_steps_required
|
|
elseif(fields and fields.next_steps_show) then
|
|
selected_from = fields.next_steps_show
|
|
list = yl_speak_up.quest_step_required_for(res.step_data, res.current_step)
|
|
end
|
|
if(selected_from) then
|
|
local selected = minetest.explode_table_event(selected_from)
|
|
if(selected and selected.row and selected.row > 0 and selected.row <= #list) then
|
|
-- show the selected quest step
|
|
yl_speak_up.speak_to[pname].quest_step = list[selected.row]
|
|
yl_speak_up.show_fs(player, "manage_quest_steps", list[selected.row])
|
|
return
|
|
end
|
|
end
|
|
-- show prev logical step
|
|
if(fields and fields.show_prev_step) then
|
|
if(#res.step_data[res.current_step].one_step_required > 0) then
|
|
yl_speak_up.show_fs(player, "manage_quest_steps",
|
|
res.step_data[res.current_step].one_step_required[1])
|
|
return
|
|
elseif(#res.step_data[res.current_step].all_steps_required > 0) then
|
|
yl_speak_up.show_fs(player, "manage_quest_steps",
|
|
res.step_data[res.current_step].all_steps_required[1])
|
|
return
|
|
end
|
|
-- show next logical step
|
|
elseif(fields and fields.show_next_step) then
|
|
local list = yl_speak_up.quest_step_required_for(res.step_data, res.current_step)
|
|
if(list and #list > 0) then
|
|
yl_speak_up.show_fs(player, "manage_quest_steps", list[1])
|
|
return
|
|
end
|
|
end
|
|
end
|
|
if(fields
|
|
and (fields.add_to_one_needed or fields.add_to_all_needed
|
|
or fields.insert_after_prev_step or fields.insert_before_next_step)) then
|
|
-- let that function sort out what to do;
|
|
-- yl_speak_up.speak_to[pname].q_id and yl_speak_up.speak_to[pname].quest_step
|
|
-- ought to be set to the current quest and step by now
|
|
if(fields.add_to_one_needed) then
|
|
yl_speak_up.speak_to[pname].quest_step_mode = "add_to_one_needed"
|
|
elseif(fields.add_to_all_needed) then
|
|
yl_speak_up.speak_to[pname].quest_step_mode = "add_to_all_needed"
|
|
elseif(fields.insert_after_prev_step) then
|
|
yl_speak_up.speak_to[pname].quest_step_mode = "insert_after_prev_step"
|
|
elseif(fields.insert_before_next_step) then
|
|
yl_speak_up.speak_to[pname].quest_step_mode = "insert_before_next_step"
|
|
else
|
|
yl_speak_up.speak_to[pname].quest_step_mode = nil
|
|
end
|
|
yl_speak_up.show_fs(player, "add_quest_steps")
|
|
return
|
|
end
|
|
local quest_step_list = yl_speak_up.get_sorted_quest_step_list(pname)
|
|
local res = yl_speak_up.input_fs_manage_general(player, formname, fields,
|
|
-- what_is_the_list_about, min_length, max_length, function_add_new_entry,
|
|
"quest step", 2, 70,
|
|
yl_speak_up.input_fs_manage_quest_steps_add_new_entry,
|
|
quest_step_list,
|
|
yl_speak_up.input_fs_manage_quest_steps_del_old_entry,
|
|
yl_speak_up.input_fs_manage_quest_steps_check_fields)
|
|
return true
|
|
end
|
|
|
|
|
|
-- small helper function for yl_speak_up.get_fs_manage_quest_steps
|
|
yl_speak_up.quest_step_show_table = function(formspec, table_specs, liste)
|
|
table.insert(formspec, "tablecolumns[color;text]table[")
|
|
table.insert(formspec, table_specs)
|
|
local tmp = {}
|
|
for k, v in pairs(liste) do
|
|
table.insert(tmp, "#AAFFAA")
|
|
table.insert(tmp, minetest.formspec_escape(v))
|
|
end
|
|
table.insert(formspec, table.concat(tmp, ","))
|
|
table.insert(formspec, ";]")
|
|
end
|
|
|
|
|
|
yl_speak_up.get_fs_manage_quest_steps = function(player, param)
|
|
-- small helper function
|
|
local em = function(text)
|
|
return minetest.colorize("#9999FF", text)
|
|
end
|
|
|
|
local res = yl_speak_up.player_is_working_on_quest(player)
|
|
if(res.error_msg) then
|
|
return "size[9,2]"..
|
|
"label[0,0;"..minetest.formspec_escape("Error: "..tostring(res.error_msg)).."]"..
|
|
"button[1.5,1.5;2,0.9;back;Back]"
|
|
end
|
|
local step_data = res.step_data
|
|
local quest_step_list = yl_speak_up.get_sorted_quest_step_list(res.pname)
|
|
if(param and param ~= "") then
|
|
local index = table.indexof(quest_step_list, param)
|
|
yl_speak_up.speak_to[res.pname].tmp_index_general = index + 1
|
|
end
|
|
local idx = yl_speak_up.speak_to[res.pname].tmp_index_general
|
|
if(idx and idx > 1) then
|
|
yl_speak_up.speak_to[res.pname].quest_step = quest_step_list[idx - 1]
|
|
end
|
|
|
|
local formspec = {}
|
|
table.insert(formspec, "size[30,12]"..
|
|
"container[6,0;18.5,12]"..
|
|
"label[0.2,1.2;A quest step is a single thing a player may do in a quest - "..
|
|
"like talking to an NPC.\n"..
|
|
"Usually not all quest steps can be done/solved at all times.]")
|
|
local selected = yl_speak_up.get_fs_manage_general(player, param,
|
|
formspec, quest_step_list,
|
|
"Create quest step",
|
|
"Create a new quest step for this quest.",
|
|
"quest step",
|
|
"Enter the name of the new quest step you want to create.\n"..
|
|
"This is an internal text shown only to yourself.\n"..
|
|
"Players cannot see the names of quest steps.",
|
|
"If you click here, the selected quest step will be deleted.\n"..
|
|
"This will only be possible if it's not used anywhere.",
|
|
"1.0")
|
|
table.insert(formspec, "container_end[]")
|
|
|
|
if(not(selected) or selected == "" or not(step_data) or not(step_data[selected])) then
|
|
return table.concat(formspec, "")
|
|
end
|
|
-- find out the next quest step
|
|
local required_for = yl_speak_up.quest_step_required_for(step_data, selected)
|
|
|
|
-- left side (previous quest step)
|
|
table.insert(formspec, "label[0.2,2.0;"..em("Required previous").."]"..
|
|
"label[0.2,2.4;quest step(s):]"..
|
|
"style[insert_before_next_step,insert_after_prev_step,"..
|
|
"add_to_one_needed,add_to_all_needed;bgcolor=blue;textcolor=yellow]"..
|
|
"container[0.1,2.7;5.6,10.8]"..
|
|
"box[0,0;5.6,8.5;#666666]"..
|
|
"button[4.6,0.0;0.94,0.7;add_to_one_needed;Edit]"..
|
|
"tooltip[add_to_one_needed;Add or remove a quest step to this list.]"..
|
|
"label[0.1,0.5;"..em("One of").." these quest steps:]")
|
|
yl_speak_up.quest_step_show_table(formspec, "0.1,0.7;5.4,2.7;one_step_required;",
|
|
step_data[selected].one_step_required or {})
|
|
table.insert(formspec, "tooltip[one_step_required;"..
|
|
"At least "..em("one of").." these previous quest steps listed ".. "here has to be\n"..
|
|
"achieved by the player who is trying to solve this quest.\n"..
|
|
"Only then can the player try to achieve this current quest\n"..
|
|
"step that you are editing here.\n"..
|
|
"If this is empty, then it's usually the/a first step of the quest.\n"..
|
|
"If there is one entry, then that entry is the previous quest step.\n"..
|
|
"If there are multiple entries, then players have alternate ways\n"..
|
|
"to achieve this current quest step here.]")
|
|
|
|
table.insert(formspec, "label[0.1,4.0;"..em("All of").." these quest steps:]"..
|
|
"button[4.6,3.5;0.94,0.7;add_to_all_needed;Edit]"..
|
|
"tooltip[add_to_all_needed;Add or remove a quest step to this list.]")
|
|
yl_speak_up.quest_step_show_table(formspec, "0.1,4.2;5.4,4.0;all_steps_required;",
|
|
step_data[selected].all_steps_required or {})
|
|
table.insert(formspec, "tooltip[all_steps_required;"..
|
|
"Sometimes there may not be a particular order in which\n"..
|
|
"quest steps ought to be solved. Imagine for example getting\n"..
|
|
"indigrents for a cake and delivering them to an NPC.\n"..
|
|
"The quest steps listed here can be done in "..em("any order")..".\n"..
|
|
"They have "..em("all").." to be achieved first in order for this current\n"..
|
|
"quest step to become available.\n"..
|
|
"Usually this list is empty.]")
|
|
table.insert(formspec, "container_end[]")
|
|
|
|
|
|
-- right side (next quest step)
|
|
table.insert(formspec, "label[24.4,2.0;Achieving this quest step]"..
|
|
"label[24.4,2.4;"..em("helps").." the quester to:]"..
|
|
"container[24.2,2.7;5.6,10.8]"..
|
|
"box[0,0;5.6,8.5;#666666]"..
|
|
"label[0.1,0.5;get these quest step(s) "..em("next")..":]")
|
|
yl_speak_up.quest_step_show_table(formspec, "0.1,0.7;5.4,7.7;next_steps_show;",
|
|
required_for or {})
|
|
table.insert(formspec, "tooltip[next_steps_show;"..
|
|
"Once the current quest step has been achieved by the\n"..
|
|
"player, the player can strive to achieve these next\n"..
|
|
"quest step(s).\n"..
|
|
"If this is empty, then it's either the/a last step (quest\n"..
|
|
"solved!) - or the quest is not properly set up.]")
|
|
table.insert(formspec, "container_end[]")
|
|
|
|
-- middle (this quest step)
|
|
table.insert(formspec, "container[6,2.7;12,10.8]"..
|
|
"label[0.2,0.5;This quest step:]"..
|
|
"dropdown[0.7,0.7;17,0.7;curr_step_show;")
|
|
table.insert(formspec, minetest.formspec_escape(selected))
|
|
table.insert(formspec, ";1;]")
|
|
table.insert(formspec, "container_end[]")
|
|
|
|
if( #step_data[selected].one_step_required > 0
|
|
or #step_data[selected].all_steps_required > 0) then
|
|
if( #step_data[selected].one_step_required
|
|
+ #step_data[selected].all_steps_required > 1) then
|
|
table.insert(formspec, "style[show_prev_step;bgcolor=red]")
|
|
end
|
|
table.insert(formspec, "button[5.6,1.7;0.6,7.0;show_prev_step;<]"..
|
|
"tooltip[show_prev_step;Show the previous step according to "..
|
|
em("your quest logic")..".\n"..
|
|
"The button turns "..minetest.colorize("#FF0000", "red")..
|
|
" if there is more than one option. In such\na case "..
|
|
"the alphabeticly first previous quest step is choosen.\n"..
|
|
"The other "..em("< Prev").." button shows the previous step "..
|
|
"in\n"..em("alphabetical order")..".]")
|
|
end
|
|
-- add buttons for inserting steps between this and the prev/next one
|
|
if(#step_data[selected].one_step_required <= 1) then
|
|
table.insert(formspec,
|
|
"button[5.6,8.7;0.6,2.6;insert_after_prev_step;+]"..
|
|
"tooltip[insert_after_prev_step;"..
|
|
"Insert a new quest step between the "..em("previous step")..
|
|
" (shown\n"..
|
|
"to the left) and the "..em("current step")..
|
|
" (shown in the middle).\n"..
|
|
"Note: This only makes sense if there's just one or no\n"..
|
|
" previous step.]")
|
|
end
|
|
if(required_for and #required_for > 0) then
|
|
if(#required_for > 1) then
|
|
table.insert(formspec, "style[show_next_step;bgcolor=red]")
|
|
end
|
|
table.insert(formspec, "button[23.8,1.7;0.6,7.0;show_next_step;>]"..
|
|
"tooltip[show_next_step;Show the next step according to "..
|
|
em("your quest logic")..".\n"..
|
|
"The button turns "..minetest.colorize("#FF0000", "red")..
|
|
" if there is more than one option. In such\na case "..
|
|
"the alphabeticly first next quest step is choosen.\n"..
|
|
"The other "..em("Next >").." button shows the next step "..
|
|
"in\n"..em("alphabetical order")..".]")
|
|
end
|
|
if(#required_for <= 1) then
|
|
table.insert(formspec,
|
|
"button[23.8,8.7;0.6,2.6;insert_before_next_step;+]"..
|
|
"tooltip[insert_before_next_step;"..
|
|
"Insert a new quest step between "..em("current step")..
|
|
" (shown\nin the middle) "..
|
|
"and the "..em("next step").." (shown to the right).\n"..
|
|
"Note: This only makes sense if there's just one or no\n"..
|
|
" next step.]")
|
|
end
|
|
|
|
return table.concat(formspec, "")
|
|
end
|