split mod into core (this mod) and editor (npc_talk_edit mod)

This commit is contained in:
Sokomine 2024-03-22 22:33:27 +01:00
parent e262b53a04
commit 5f2917df01
37 changed files with 9 additions and 10947 deletions

View File

@ -1,434 +0,0 @@
-- helper function for yl_speak_up.handle_input_fs_edit_option_related
-- (handle editing of alternate texts that are shown instead of the normal dialog)
yl_speak_up.handle_edit_actions_alternate_text = function(
player, pname, n_id, d_id, o_id, x_id, id_prefix,
formspec_input_to, data, fields, tmp_data_cache)
local dialog = yl_speak_up.speak_to[pname].dialog
if(not(dialog)
or not(dialog.n_dialogs)
or not(dialog.n_dialogs[ d_id ])
or not(dialog.n_dialogs[ d_id ].d_options)
or not(dialog.n_dialogs[ d_id ].d_options[ o_id ])) then
return
end
-- edit_dialog_options: these first two buttons can only be pressed in this dialog
-- action failed: want to edit the text that is shown when switching to the next dialog?
if(fields.button_edit_action_failed_dialog) then
-- the target effect is the (failed) action
local target_action = {}
local actions = dialog.n_dialogs[ d_id ].d_options[ o_id ].actions
if(actions) then
for a_id, a in pairs(actions) do
if(a and a.a_id) then
target_action = a
end
end
end
if(not(target_action)) then
return
end
-- remember what we're working at
yl_speak_up.speak_to[pname].edit_alternate_text_for = target_action
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = yl_speak_up.extend_fs_edit_dialog_modification(
dialog, target_action.a_on_failure, target_action.alternate_text,
"if the action \""..tostring(target_action.a_id)..
"\" of option \""..tostring(o_id)..
"\" of dialog \""..tostring(d_id)..
"\" failed because the player did something wrong")
})
-- showing new formspec - the calling function shall return as well
return true
-- action was successful: want to edit the text that is shown when switching to the next dialog?
elseif(fields.button_edit_action_success_dialog) then
-- the target effect is the "dialog" effect
local target_effect = {}
local results = dialog.n_dialogs[ d_id ].d_options[ o_id ].o_results
if(results) then
for r_id, r in pairs(results) do
if(r and r.r_type and r.r_type == "dialog") then
target_effect = r
end
end
end
if(not(target_effect)) then
return
end
-- remember what we're working at
yl_speak_up.speak_to[pname].edit_alternate_text_for = target_effect
-- this only happens in edit_options_dialog; log it directly
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = yl_speak_up.extend_fs_edit_dialog_modification(
dialog, target_effect.r_value, target_effect.alternate_text,
"if the action "..
"of option \""..tostring(o_id)..
"\" of dialog \""..tostring(d_id)..
"\" was successful - or if there was no action")
})
-- showing new formspec - the calling function shall return as well
return true
-- in edit action dialog: edit alternate text for a failed action
elseif(fields.button_edit_action_on_failure_text_change) then
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
local failure_id = ""
-- action is beeing edited; data.action_failure_dialog points to an index
if(data and data.action_failure_dialog) then
failure_id = sorted_dialog_list[ data.action_failure_dialog ]
end
-- remember what we edit
data.x_id = x_id
data.id_prefix = id_prefix
yl_speak_up.speak_to[pname].edit_alternate_text_for = data
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = yl_speak_up.extend_fs_edit_dialog_modification(
dialog, failure_id, data.alternate_text,
"if the action \""..tostring(x_id)..
"\" of option \""..tostring(o_id)..
"\" of dialog \""..tostring(d_id)..
"\" failed because the player did something wrong")
})
-- showing new formspec - the calling function shall return as well
return true
-- edit alternate text for an on_failure effect
elseif(fields.button_edit_effect_on_failure_text_change) then
-- remember what we edit
data.x_id = x_id
data.id_prefix = id_prefix
yl_speak_up.speak_to[pname].edit_alternate_text_for = data
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = yl_speak_up.extend_fs_edit_dialog_modification(
dialog, data.on_failure, data.alternate_text,
"if the effect \""..tostring(x_id)..
"\" of option \""..tostring(o_id)..
"\" of dialog \""..tostring(d_id)..
"\" failed to execute correctly")
})
-- showing new formspec - the calling function shall return as well
return true
-- edit alternate text for when the player has failed to do the action too many times
elseif(fields.button_edit_limit_action_failed_repeat) then
local timer_name = "timer_on_failure_"..tostring(d_id).."_"..tostring(o_id)
local timer_data = yl_speak_up.get_variable_metadata( timer_name, "parameter", true)
local alternate_text = yl_speak_up.standard_text_if_action_failed_too_often
if(timer_data and timer_data["alternate_text"]) then
alternate_text = timer_data["alternate_text"]
end
-- remember what we're working at
yl_speak_up.speak_to[pname].edit_alternate_text_for = "timer_on_failure"
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = yl_speak_up.extend_fs_edit_dialog_modification(
dialog, d_id, alternate_text,
"if the player failed to complete the action "..
"\" of option \""..tostring(o_id)..
"\" of dialog \""..tostring(d_id)..
"\" too many times",
true) -- forbid_turn_into_new_dialog
})
-- showing new formspec - the calling function shall return as well
return true
-- edit alternate text whent he player has to wait a bit until he's allowed to repeat the
-- action (to avoid i.e. unlimited quest item handout)
elseif(fields.button_edit_limit_action_success_repeat) then
local timer_name = "timer_on_success_"..tostring(d_id).."_"..tostring(o_id)
local timer_data = yl_speak_up.get_variable_metadata( timer_name, "parameter", true)
local alternate_text = yl_speak_up.standard_text_if_action_repeated_too_soon
if(timer_data and timer_data["alternate_text"]) then
alternate_text = timer_data["alternate_text"]
end
-- remember what we're working at
yl_speak_up.speak_to[pname].edit_alternate_text_for = "timer_on_success"
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = yl_speak_up.extend_fs_edit_dialog_modification(
dialog, d_id, alternate_text,
"if the player has complete the action "..
"\" of option \""..tostring(o_id)..
"\" of dialog \""..tostring(d_id)..
"\" just not long enough ago",
true) -- forbid_turn_into_new_dialog
})
-- showing new formspec - the calling function shall return as well
return true
-- save the changes
elseif(fields.save_dialog_modification) then
local old_text = "-none-"
local target_element = yl_speak_up.speak_to[pname].edit_alternate_text_for
if(target_element
and (target_element == "timer_on_failure" or target_element == "timer_on_success")) then
-- we're changing a timer (both can be handled the same way here)
local timer_name = target_element.."_"..tostring(d_id).."_"..tostring(o_id)
local timer_data = yl_speak_up.get_variable_metadata( timer_name, "parameter", true)
local alternate_text = yl_speak_up.standard_text_if_action_failed_too_often
if(target_element == "timer_on_success") then
alternate_text = yl_speak_up.standard_text_if_action_repeated_too_soon
end
if(timer_data and timer_data["alternate_text"]) then
alternate_text = timer_data["alternate_text"]
end
-- store the modified alternate text
if(fields.d_text_new and fields.d_text_new ~= ""
and fields.d_text_new ~= alternate_text) then
-- make sure the variable exists
if(yl_speak_up.add_time_based_variable(timer_name)) then
yl_speak_up.set_variable_metadata(timer_name, nil, "parameter",
"alternate_text", fields.d_text_new)
-- log the change
yl_speak_up.log_change(pname, n_id,
"Dialog "..d_id..", option "..tostring(o_id)..
": The text displayed for "..tostring(target_element)..
" was changed from "..
"["..tostring(alternate_text).."] to ["..
tostring(fields.d_text_new).."].")
end
end
elseif(target_element) then
data = target_element
id_prefix = "a_"
if(target_element.r_id) then
id_prefix = "r_"
end
old_text = target_element.alternate_text
else
old_text = data.alternate_text
end
if(data and fields.d_text_new and fields.d_text_new ~= "$TEXT$"
and fields.d_text_new ~= data.alternate_text) then
-- store modification
-- not necessary for edit_option_dialog
if(tmp_data_cache) then
data.alternate_text = fields.d_text_new
yl_speak_up.speak_to[pname][ tmp_data_cache ] = data
else
target_element.alternate_text = fields.d_text_new
end
if(id_prefix == "r_") then
local failure_id = data.on_failure
-- effect is beeing edited; data.on_failure contains the dialog name
if(data and data.on_failure) then
failure_id = data.on_failure
-- edit_option_dialog: data.r_value contains the dialog name
elseif(target_element and target_element.r_value) then
failure_id = target_element.r_value
end
-- record the change
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": The text displayed for dialog "..
tostring(failure_id).." when selecting option "..
tostring(o_id).." in dialog "..tostring( d_id )..
" and effect "..tostring(x_id).." failed "..
" was changed from "..
"["..tostring(old_text).."] to ["..tostring(fields.d_text_new).."].")
elseif(id_prefix == "a_") then
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
local failure_id = ""
-- action is beeing edited; data.action_failure_dialog points to an index
if(data and data.action_failure_dialog) then
failure_id = sorted_dialog_list[ data.action_failure_dialog ]
-- edit_option_dialog: data.a_on_failure contains the dialog name
elseif(target_element and target_element.a_on_failure) then
failure_id = target_element.a_on_failure
end
-- record the change
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": The text displayed for dialog "..
tostring(failure_id).." when the action "..
tostring(x_id).." of option "..
tostring( o_id ).." in dialog "..tostring( d_id )..
" failed, was changed from "..
"["..tostring(old_text).."] to ["..tostring(fields.d_text_new).."].")
end
-- saved; finished editing
yl_speak_up.speak_to[pname].edit_alternate_text_for = nil
end
-- turn this alternate answer into a new dialog
elseif(fields.turn_alternate_text_into_new_dialog) then
local target_element = yl_speak_up.speak_to[pname].edit_alternate_text_for
if(target_element) then
data = target_element
if(data.id_prefix and data.x_id) then
id_prefix = data.id_prefix
x_id = data.x_id
else
id_prefix = "a_"
x_id = target_element.a_id
if(target_element.r_id) then
id_prefix = "r_"
x_id = target_element.r_id
end
end
end
-- create the new dialog
local new_dialog_id = yl_speak_up.add_new_dialog(dialog, pname, nil)
-- set the text (the previous alternate text)
dialog.n_dialogs[ new_dialog_id ].d_text = data.alternate_text
-- edit option: effect dialog - this is the normal progression from this dialog to the next
if( data.r_id and data.r_type and data.r_type == "dialog") then
data.r_value = new_dialog_id
data.alternate_text = nil
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": The alternate text for effect "..tostring(x_id)..
" (dialog) of option "..tostring(o_id).." was turned into the new dialog "..
tostring(new_dialog_id).." (edit option).")
-- edit option: the action failed
elseif(data.a_id and data.a_on_failure) then
data.a_on_failure = new_dialog_id
data.alternate_text = nil
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": The alternate text for action "..tostring(data.a_id)..
" of option "..tostring(o_id).." was turned into the new dialog "..
tostring(new_dialog_id).." (edit option).")
-- edit action: the action failed
elseif(data.what and data.what == 6 and data.action_failure_dialog) then
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
data.action_failure_dialog = math.max(1,
table.indexof(sorted_dialog_list, new_dialog_id))
data.a_on_failure = new_dialog_id
data.alternate_text = nil
-- make sure its stored correctly
dialog.n_dialogs[d_id].d_options[o_id].actions[x_id].a_on_failure = new_dialog_id
dialog.n_dialogs[d_id].d_options[o_id].actions[x_id].alternate_text = nil
yl_speak_up.speak_to[pname][ tmp_data_cache ] = data
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": The alternate text for action "..tostring(x_id)..
" of option "..tostring(o_id).." was turned into the new dialog "..
tostring(new_dialog_id).." (edit action).")
-- edit effect: on_failure - the previous effect failed
elseif(data.what and data.what == 5 and data.on_failure) then
data.on_failure = new_dialog_id
data.alternate_text = nil
-- make sure its stored correctly
dialog.n_dialogs[d_id].d_options[o_id].o_results[x_id].on_failure = new_dialog_id
dialog.n_dialogs[d_id].d_options[o_id].o_results[x_id].alternate_text = nil
yl_speak_up.speak_to[pname][ tmp_data_cache ] = data
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": The alternate text for effect "..tostring(x_id)..
" of option "..tostring(o_id).." was turned into the new dialog "..
tostring(new_dialog_id).." (edit effect).")
end
end
end
yl_speak_up.show_colored_dialog_text = function(dialog, data, d_id, hypertext_pos,
alternate_label_text, postfix, button_name)
if(not(data)) then
return ""
end
-- if(math.random(1,2)==1) then data.alternate_text = "This is an alternate text.\n$TEXT$" end
-- slightly red in order to indicate that this is an on_failure dialog
local color = "776666"
-- ..except for normal redirecting to the next dialog with the dialog effect
-- (slightly yellow there)
if(data.r_id and data.r_type and data.r_type == "dialog") then
color = "777766"
end
local add_info_alternate_text = ""
local text = ""
if(dialog and dialog.n_dialogs and dialog.n_dialogs[ d_id ]) then
text = dialog.n_dialogs[ d_id ].d_text
end
if(d_id == "d_got_item") then
color = "777777"
text = "[This dialog shall only have automatic options. The text is therefore irrelevant.]"
end
if(d_id == "d_end") then
color = "777777"
text = "[The NPC will end this conversation.]"
end
if(not(text)) then
text = "[ERROR: No text!]"
end
if(data and data.alternate_text and data.alternate_text ~= "") then
add_info_alternate_text = alternate_label_text
-- replace $TEXT$ with the normal dialog text and make the new text yellow
text = "<style color=#FFFF00>"..
string.gsub(
data.alternate_text,
"%$TEXT%$",
"<style color=#FFFFFF>"..text.."</style>")..
"</style>"
-- slightly blue in order to indicate that this is a modified text
color = "333366"
end
-- fallback
if(not(text)) then
text = "ERROR: No dialog text found for dialog \""..tostring(d_id).."\"!"
end
-- display the variables in orange
text = yl_speak_up.replace_vars_in_text(text,
-- fake dialog; just adds the colors
-- also MY_NAME..but we can easily replace just one
{ n_npc = "<style color=#FF8800>$NPC_NAME$</style>",
npc_owner = "<style color=#FF8800>$OWNER_NAME$</style>"},
-- pname
"<style color=#FF8800>$PLAYER_NAME$</style>")
local edit_button = ""
-- if there is the possibility that an alternate text may be displayed: allow to edit it
-- and calculate the position of the button from the hypertext_pos position and size
if(button_name and button_name ~= "") then
local parts = string.split(hypertext_pos, ";")
local start = string.split(parts[1], ",")
local size = string.split(parts[2], ",")
edit_button = "button_exit["..
tostring(tonumber(start[1]) + tonumber(size[1]) - 3.5)..","..
tostring(tonumber(start[2]) + tonumber(size[2]) - 0.9)..";"..
"3.0,0.7;"..button_name..";Edit this text]"
end
return add_info_alternate_text..
postfix..
"hypertext["..hypertext_pos..";<global background=#"..color.."><normal>"..
minetest.formspec_escape(text or "?")..
"\n</normal>]"..
-- display the edit button *inside*/on top of the hypertext field
edit_button
end
-- this allows to edit modifications of a dialog that are applied when a given option
-- is choosen - i.e. when the NPC wants to answer some questions - but those answers
-- do not warrant their own dialog
yl_speak_up.extend_fs_edit_dialog_modification = function(dialog, d_id, alternate_dialog_text, explanation,
forbid_turn_into_new_dialog)
local nd = "button[9.0,12.3;6,0.7;turn_alternate_text_into_new_dialog;Turn this into a new dialog]"
if(forbid_turn_into_new_dialog) then
nd = ""
end
return table.concat({"size[20,13.5]",
"label[6.0,0.5;Edit alternate text]",
"label[0.2,1.0;The alternate text which you can edit here will be shown instead of "..
"the normal text of the dialog \"", tostring(d_id), "\" - but *only*\n",
tostring(explanation or "- missing explanation -"), ".]",
"label[0.2,2.3;This is the normal text of dialog \"",
minetest.formspec_escape(tostring(d_id)), "\", shown for reference:]",
yl_speak_up.show_colored_dialog_text(
dialog,
{r_id = "", r_type = "dialog"},
d_id,
"1.2,2.6;18.0,4.0;d_text_orig",
"", -- no modifications possible at this step
"",
""), -- no edit button here as this text cannot be changed here
"label[0.2,7.3;Enter the alternate text here. $TEXT$ will be replaced with the normal "..
"dialog text above:]",
"textarea[1.2,7.6;18.0,4.5;d_text_new;;",
minetest.formspec_escape(alternate_dialog_text or "$TEXT$"), "]",
"button[3.0,12.3;1,0.7;back_from_edit_dialog_modification;Abort]",
"button[6.0,12.3;1,0.7;save_dialog_modification;Save]",
nd
}, "")
end

View File

@ -1,270 +0,0 @@
-- 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
-- check here if the step exists
if(t.current_step and not(t.step_data[t.current_step])) then
yl_speak_up.speak_to[t.pname].quest_step = nil
t.current_step = nil
end
-- t contains pname, q_id, quest, step_data and current_step - or error_msg
return t
end
-- show the error message created above
yl_speak_up.build_fs_quest_edit_error = function(error_msg, back_button_name)
return "size[10,3]"..
"label[0.2,0.5;Error:]"..
"label[0.5,1.0;"..minetest.colorize("#FFFF00",
minetest.formspec_escape(
minetest.wrap_text(tostring(error_msg), 80)))..
"]button[3.5,2.0;2,0.9;"..tostring(back_button_name)..";Back]"
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
-- sorts quest steps into lists: start, middle, end, unconnected
yl_speak_up.quest_step_get_start_end_unconnected_lists = function(step_data)
local start_steps = {}
local end_steps = {}
local unconnected_steps = {}
-- construct tables of *candidates* for start/end steps first
for s, d in pairs(step_data) do
if(#d.one_step_required == 0 and #d.all_steps_required == 0) then
start_steps[s] = true
end
end_steps[s] = true
end
for s, d in pairs(step_data) do
-- anything that is required somewhere cannot be an end step
for i, s2 in ipairs(d.one_step_required or {}) do
end_steps[s2] = nil
end
for i, s2 in ipairs(d.all_steps_required or {}) do
end_steps[s2] = nil
end
end
local lists = {}
lists.start_steps = {}
lists.end_steps = {}
lists.unconnected_steps = {}
lists.middle_steps = {}
for s, d in pairs(step_data) do
-- if it's both a start and end step, then it's an unconnected step
if(start_steps[s] and end_steps[s]) then
table.insert(lists.unconnected_steps, s)
elseif(start_steps[s]) then
table.insert(lists.start_steps, s)
elseif(end_steps[s]) then
table.insert(lists.end_steps, s)
else
table.insert(lists.middle_steps, s)
end
end
return lists
end
-- some lists are offered in diffrent formspecs for selection;
-- this function will display the right quest step if possible
-- res needs to be yl_speak_up.player_is_working_on_quest(player)
yl_speak_up.handle_input_routing_show_a_quest_step = function(player, formname, fields, back_field_name, res)
if(not(player) or not(fields) or (fields and fields.back) or not(res)) then
return false
end
if(res.error_msg) then
yl_speak_up.show_fs(player, "msg", {
input_to = formname,
formspec = yl_speak_up.build_fs_quest_edit_error(error_msg, back_field_name)
})
return true
end
local step_data = res.step_data or {}
-- which quest step to show next? (if any)
local show_step = ""
-- was a quest step selected from the start/end/unconnected lists?
local list = {}
local field_name = ""
local row_offset = 0
if( fields.select_from_start_steps and fields.select_from_start_steps ~= "") then
-- selected a start quest step
list = yl_speak_up.quest_step_get_start_end_unconnected_lists(step_data).start_steps
field_name = "select_from_start_steps"
elseif(fields.select_from_end_steps and fields.select_from_end_steps ~= "") then
-- selected an end quest step
list = yl_speak_up.quest_step_get_start_end_unconnected_lists(step_data).end_steps
field_name = "select_from_end_steps"
elseif(fields.select_from_unconnected_steps and fields.select_from_unconnected_steps ~= "") then
-- selected an unconnected/unused quest step
list = yl_speak_up.quest_step_get_start_end_unconnected_lists(step_data).unconnected_steps
field_name = "select_from_unconnected_steps"
elseif(res.current_step and step_data[res.current_step] and fields.one_step_required) then
list = step_data[res.current_step].one_step_required
field_name = "one_step_required"
elseif(res.current_step and step_data[res.current_step] and fields.all_steps_required) then
list = step_data[res.current_step].all_steps_required
field_name = "all_steps_required"
elseif(res.current_step and step_data[res.current_step] and fields.next_steps_show) then
list = yl_speak_up.quest_step_required_for(step_data, res.current_step)
field_name = "next_steps_show"
elseif(fields.add_from_available) then
-- selected a quest step from the list of available steps offered
list = yl_speak_up.speak_to[res.pname].available_quest_steps or {}
field_name = "add_from_available"
-- this table has a header
row_offset = 1
-- show prev logical step
elseif(fields.show_prev_step and res.current_step and step_data[res.current_step]) then
if( #step_data[res.current_step].one_step_required > 0) then
show_step = step_data[res.current_step].one_step_required[1]
elseif(#step_data[res.current_step].all_steps_required > 0) then
show_step = step_data[res.current_step].all_steps_required[1]
end
-- show next logical step
elseif(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
show_step = list[1]
end
end
if(list and field_name) then
local selected = minetest.explode_table_event(fields[field_name])
-- if a table uses a header, row_offset will be 1; else 0
if(selected and selected.row and selected.row > row_offset and selected.row <= #list + row_offset) then
show_step = list[selected.row - row_offset]
end
end
-- actually show the selected quest step
if(show_step and show_step ~= "") then
yl_speak_up.speak_to[res.pname].quest_step = show_step
yl_speak_up.show_fs(player, "manage_quest_steps", show_step)
return true
-- show the entire list
elseif(fields.show_step_list) then
yl_speak_up.speak_to[res.pname].tmp_index_general = -1
yl_speak_up.speak_to[res.pname].quest_step = nil
yl_speak_up.show_fs(player, "manage_quest_steps", nil)
return true
end
return false
end
-- describe a location where a quest step can be set; also used by yl_speak_up.fs_manage_quest_steps
yl_speak_up.quest_step_show_where_set = function(pname, formspec, label, n_id, d_id, o_id, box_color, nr)
if(not(pname)) then
return
end
-- what are we talking about?
local dialog = nil
if(yl_speak_up.speak_to[pname] and yl_speak_up.speak_to[pname].n_id == n_id) then
dialog = yl_speak_up.speak_to[pname].dialog
else
dialog = yl_speak_up.load_dialog(n_id, false)
end
local name_txt = "- ? -"
local dialog_txt = "- ? -"
local option_txt = "- ? -"
if(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id)) then
dialog_txt = dialog.n_dialogs[d_id].d_text or "- ? -"
option_txt = dialog.n_dialogs[d_id].d_options[o_id].o_text_when_prerequisites_met or "- ? -"
name_txt = (dialog.n_npc or "- ? -")
if(dialog.n_description and dialog.n_description ~= "") then
name_txt = name_txt..", "..tostring(dialog.n_description)
end
end
-- are we dealing with an NPC?
local id_label = "the block at position "
if(n_id and string.sub(n_id, 1, 2) == "n_") then
id_label = "NPC "
end
if(box_color) then
name_txt = name_txt.." ["..tostring(n_id).."]"
table.insert(formspec, "label[0.2,0.2;")
if(nr) then
table.insert(formspec, tostring(nr)..". ")
end
table.insert(formspec, id_label)
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(name_txt)))
table.insert(formspec, " says in dialog ")
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(d_id)..":]"))
table.insert(formspec, "]")
table.insert(formspec, "box[1.0,0.4;16,1.8;")
table.insert(formspec, box_color)
table.insert(formspec, "]")
table.insert(formspec, "textarea[1.0,0.4;16,1.8;;;")
table.insert(formspec, minetest.formspec_escape(dialog_txt))
table.insert(formspec, "]")
table.insert(formspec, "label[1.0,2.4;Answer ")
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(o_id..": ")))
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(option_txt)))
table.insert(formspec, "]")
return
end
table.insert(formspec, "label[0.2,0;")
table.insert(formspec, label or "which will be set by ")
table.insert(formspec, id_label)
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(n_id)))
table.insert(formspec, ":]")
table.insert(formspec, "label[1.0,0.4;")
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(name_txt)))
table.insert(formspec, "]")
table.insert(formspec, "label[0.2,0.9;when answering to dialog ")
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(d_id)))
table.insert(formspec, ":]")
table.insert(formspec, "textarea[1.0,1.1;16,1.8;;;")
table.insert(formspec, minetest.formspec_escape(dialog_txt))
table.insert(formspec, "]")
table.insert(formspec, "label[0.2,3.2;with the following answer/option ")
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(o_id)))
table.insert(formspec, ":]")
table.insert(formspec, "label[1.0,3.6;")
table.insert(formspec, minetest.colorize("#AAAAFF", minetest.formspec_escape(option_txt)))
table.insert(formspec, "]")
end

View File

@ -1,318 +0,0 @@
-- helper function:
-- create a formspec dropdown list with player names (first entry: Add player) and
-- an option to delete players from that list
-- Note: With the what_is_the_list_about-parameter, it is possible to handle i.e. variables as well
yl_speak_up.create_dropdown_playerlist = function(player, pname,
table_of_names, index_selected,
start_x, start_y, stretch_x, h, dropdown_name, what_is_the_list_about, delete_button_text,
field_name_for_adding_player, explain_add_player,
field_name_for_deleting_player, explain_delete_player)
local text = "dropdown["..tostring(start_x)..","..tostring(start_y)..";"..
tostring(3.8 + stretch_x)..","..tostring(h)..";"..
tostring(dropdown_name)..";Add "..tostring(what_is_the_list_about)..":"
-- table_of_names is a table with the playernames as keys
-- we want to work with indices later on; in order to be able to do that reliably, we
-- need a defined order of names
local tmp_list = yl_speak_up.sort_keys(table_of_names, true)
for i, p in ipairs(tmp_list) do
text = text..","..minetest.formspec_escape(p)
end
-- has an entry been selected?
if(not(index_selected) or index_selected < 0 or index_selected > #tmp_list+1) then
index_selected = 1
end
text = text..";"..tostring(index_selected)..";]"
if(index_selected == 1) then
-- first index "Add player" selected? Then offer a field for entering the name
text = text.."field["..tostring(start_x + 4.0 + stretch_x)..","..tostring(start_y)..
";"..tostring(3.5 + stretch_x)..","..tostring(h)..";"..
tostring(field_name_for_adding_player)..";;]"..
"tooltip["..tostring(field_name_for_adding_player)..";"..
tostring(explain_add_player).."]"
else
text = text.."button["..tostring(start_x + 3.8 + stretch_x)..","..tostring(start_y)..
";"..tostring(3.4 + stretch_x)..","..tostring(h)..";"..
tostring(field_name_for_deleting_player)..";"..
tostring(delete_button_text).."]"..
"tooltip["..tostring(field_name_for_deleting_player)..";"..
tostring(explain_delete_player).."]"
end
return text
end
-- manages back, exit, prev, next, add_list_entry, del_entry_general
--
-- if a new entry is to be added, the following function that is passed as a parmeter
-- is called:
-- function_add_new_entry(pname, fields.add_entry_general)
-- expected return value: index of fields.add_entry_general in the new list
--
-- if an entry is to be deleted, the following function that is passed as a parameter
-- is called:
-- function_del_old_entry(pname, entry_name)
-- expected return value: text describing weather the removal worked or not
--
-- if any other fields are set that this function does not process, the following
-- function that is passed on as a parameter can be used:
-- function_input_check_fields(player, formname, fields, entry_name, list_of_entries)
-- expected return value: nil if the function found work; else entry_name
--
yl_speak_up.handle_input_fs_manage_general = function(player, formname, fields,
what_is_the_list_about, min_length, max_length, function_add_new_entry,
list_of_entries, function_del_old_entry, function_input_check_fields)
local pname = player:get_player_name()
local what = minetest.formspec_escape(what_is_the_list_about or "?")
local fs_name = formname
if(formname and string.sub(formname, 0, 12) == "yl_speak_up:") then
formname = string.sub(formname, 13)
end
if(fields and fields.back_from_msg) then
yl_speak_up.show_fs(player, formname, fields.stored_value_for_player)
return
end
-- leave this formspec
if(fields and (fields.quit or fields.exit or fields.back)) then
local last_fs = yl_speak_up.speak_to[pname][ "working_at" ]
local last_params = yl_speak_up.speak_to[pname][ "working_at_params" ]
yl_speak_up.speak_to[pname].tmp_index_general = nil
yl_speak_up.show_fs(player, last_fs, last_params)
return
-- add a new entry?
elseif(fields and fields.add_list_entry) then
local error_msg = ""
if(not(fields.add_entry_general) or fields.add_entry_general == ""
or fields.add_entry_general:trim() == "") then
error_msg = "Please enter the name of the "..what.." you want to create!"
-- limit names to something more sensible
elseif(string.len(fields.add_entry_general) > max_length) then
error_msg = "The name of your new "..what.." is too long.\n"..
"Only up to "..tostring(max_length).." characters are allowed."
elseif(string.len(fields.add_entry_general:trim()) < min_length) then
error_msg = "The name of your new "..what.." is too short.\n"..
"It has to be at least "..tostring(min_length).." characters long."
elseif(table.indexof(list_of_entries, fields.add_entry_general:trim()) > 0) then
error_msg = "A "..what.." with the name\n \""..
minetest.formspec_escape(fields.add_entry_general:trim())..
"\"\nexists already."
else
fields.add_entry_general = fields.add_entry_general:trim()
-- this depends on what is created
local res = function_add_new_entry(pname, fields.add_entry_general)
-- not really an error msg here - but fascilitates output
error_msg = "A new "..what.." named\n \""..
minetest.formspec_escape(fields.add_entry_general)..
"\"\nhas been created."
if(not(res) or (type(res) == "number" and res == -1)) then
error_msg = "Failed to create "..what.." named\n \""..
minetest.formspec_escape(fields.add_entry_general).."\"."
-- pass on any error messages
elseif(type(res) == "string") then
error_msg = res
else
-- select this new entry (add 1 because the first entry of our
-- list is adding a new entry)
yl_speak_up.speak_to[pname].tmp_index_general = res + 1
end
end
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formname,
formspec = "size[10,2]"..
"label[0.2,0.0;"..error_msg.."]"..
"button[1.5,1.5;2,0.9;back_from_msg;Back]"})
return
-- scroll through the variables with prev/next buttons
elseif(fields and (fields["prev"] or fields["next"])) then
local index = yl_speak_up.speak_to[pname].tmp_index_general
if(not(index)) then
yl_speak_up.speak_to[pname].tmp_index_general = 1
elseif(fields["prev"] and index > 1) then
yl_speak_up.speak_to[pname].tmp_index_general = index - 1
elseif(fields["next"] and index <= #list_of_entries) then
yl_speak_up.speak_to[pname].tmp_index_general = index + 1
end
yl_speak_up.show_fs(player, formname, fields.stored_value_for_player)
return
end
-- an entry was selected in the dropdown list
if(fields and fields.list_of_entries and fields.list_of_entries ~= "") then
local index = table.indexof(list_of_entries, fields.list_of_entries)
-- show the "Add <entry>:" entry
if(fields.list_of_entries == "Add "..what..":") then
index = 0
yl_speak_up.speak_to[pname].tmp_index_general = 1
yl_speak_up.show_fs(player, formname, fields.stored_value_for_player)
return
end
if(index and index > -1) then
yl_speak_up.speak_to[pname].tmp_index_general = index + 1
end
end
local entry_name = list_of_entries[ yl_speak_up.speak_to[pname].tmp_index_general - 1]
-- delete entry
if(fields and ((fields.del_entry_general and fields.del_entry_general ~= ""))
and entry_name and entry_name ~= "") then
local text = function_del_old_entry(pname, entry_name)
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formname,
formspec = "size[10,2]"..
"label[0.2,0.0;Trying to delete "..what.." \""..
minetest.formspec_escape(tostring(entry_name))..
"\":\n"..text.."]"..
"button[1.5,1.5;2,0.9;back_from_msg;Back]"})
return
-- maybe the custom function knows what to do with this
elseif(fields
and not(function_input_check_fields(player, formname, fields, entry_name, list_of_entries))) then
-- the function_input_check_fields managed to handle this input
return
-- an entry was selected in the dropdown list
elseif(entry_name and entry_name ~= "") then
-- show the same formspec again, with a diffrent variable selected
yl_speak_up.show_fs(player, formname)
return
end
-- try to go back to the last formspec shown before this one
if(not(yl_speak_up.speak_to[pname])) then
return
end
local last_fs = yl_speak_up.speak_to[pname][ "working_at" ]
local last_params = yl_speak_up.speak_to[pname][ "working_at_params" ]
yl_speak_up.show_fs(player, last_fs, last_params)
end
-- inserts buttons into formspec which allow to select previous/next entry, to go back,
-- create new entries, delete entries and select entries from a dropdown menu;
-- returns the currently selected entry or nil (=create new entry)
-- Note: Designed for a formspec of size "size[18,12]"
yl_speak_up.build_fs_manage_general = function(player, param,
formspec, list_of_entries,
text_add_new, tooltip_add_new,
what_is_the_list_about,
tooltip_add_entry_general, tooltip_del_entry_general,
optional_add_space)
if(not(optional_add_space)) then
optional_add_space = 0
end
local selected = nil
local pname = player:get_player_name()
-- the yl_speak_up.create_dropdown_playerlist function needs a table - not a list
local table_of_entries = {}
for i, k in ipairs(list_of_entries) do
table_of_entries[ k ] = true
end
-- "Add variable:" is currently selected
if(not(yl_speak_up.speak_to[pname].tmp_index_general)
or yl_speak_up.speak_to[pname].tmp_index_general == 1
or not(list_of_entries[ yl_speak_up.speak_to[pname].tmp_index_general - 1])) then
yl_speak_up.speak_to[pname].tmp_index_general = 1
table.insert(formspec, "button[")
table.insert(formspec, tostring(12.2 + 2 * optional_add_space))
table.insert(formspec, ",2.15;")
table.insert(formspec, tostring(2.5 + 2 * optional_add_space))
table.insert(formspec, ",0.6;add_list_entry;")
table.insert(formspec, minetest.formspec_escape(text_add_new))
table.insert(formspec, "]")
table.insert(formspec, "tooltip[add_list_entry;")
table.insert(formspec, minetest.formspec_escape(tooltip_add_new))
table.insert(formspec, "]")
else
-- index 1 is "Add variable:"
selected = list_of_entries[ yl_speak_up.speak_to[pname].tmp_index_general - 1]
end
if(yl_speak_up.speak_to[pname].tmp_index_general > 1) then
table.insert(formspec, "button[4.0,0.2;2.0,0.6;prev;< Prev]"..
"button[4.0,11.0;2.0,0.6;prev;< Prev]")
end
if(yl_speak_up.speak_to[pname].tmp_index_general <= #list_of_entries) then
table.insert(formspec, "button[12.0,0.2;2.0,0.6;next;Next >]"..
"button[12.0,11.0;2.0,0.6;next;Next >]")
end
table.insert(formspec, "button[0.0,0.2;2.0,0.6;back;Back]"..
"button[8.0,11.0;2.0,0.6;back;Back]")
local what = minetest.formspec_escape(what_is_the_list_about)
table.insert(formspec, "label[7.0,0.4;* Manage your ")
table.insert(formspec, what)
table.insert(formspec, "s *]")
table.insert(formspec, "label[0.2,2.45;Your ")
table.insert(formspec, what)
table.insert(formspec, ":]")
-- offer a dropdown list and a text input field for new varialbe names for adding
table.insert(formspec, yl_speak_up.create_dropdown_playerlist(
player, pname,
table_of_entries,
yl_speak_up.speak_to[pname].tmp_index_general,
2.6 + (optional_add_space), 2.15, 1.0, 0.6,
"list_of_entries",
what,
"Delete selected "..what,
"add_entry_general",
minetest.formspec_escape(tooltip_add_entry_general),
"del_entry_general",
minetest.formspec_escape(tooltip_del_entry_general)
))
-- either nil or the text of the selected entry
return selected
end
-- small helper function for the function below
yl_speak_up.get_sub_fs_colorize_table = function(formspec, table_specs, liste, color)
table.insert(formspec, "tablecolumns[color;text]table[")
table.insert(formspec, table_specs)
local tmp = {}
for k, v in pairs(liste) do
table.insert(tmp, color or "#FFFFFF")
table.insert(tmp, minetest.formspec_escape(v))
end
table.insert(formspec, table.concat(tmp, ","))
table.insert(formspec, ";]")
end
yl_speak_up.get_sub_fs_show_list_in_box = function(formspec,
label, field_name, liste, start_x, start_y, width, height, label_ident,
box_color, column_color,
tooltip_text, add_lines)
local dim_str = tostring(width)..","..tostring(height)
table.insert(formspec, "container[")
table.insert(formspec, tostring(start_x)..","..tostring(start_y)..";")
table.insert(formspec, dim_str)
table.insert(formspec, "]")
table.insert(formspec, "box[0,0;")
table.insert(formspec, dim_str)
table.insert(formspec, ";")
table.insert(formspec, box_color or "#666666")
table.insert(formspec, "]")
-- add buttons etc. first so that the label remains visible on top
if(add_lines) then
table.insert(formspec, add_lines)
end
table.insert(formspec, "label[")
table.insert(formspec, tostring(0.1 + label_ident))
table.insert(formspec, ",0.5;")
table.insert(formspec, label)
table.insert(formspec, "]")
yl_speak_up.get_sub_fs_colorize_table(formspec,
"0.1,0.7;"..tostring(width-0.2)..","..tostring(height-0.8)..";"..tostring(field_name)..";",
liste or {}, column_color)
if(tooltip_text and tooltip_text ~= "") then
table.insert(formspec, "tooltip[")
table.insert(formspec, field_name)
table.insert(formspec, ";")
table.insert(formspec, tooltip_text)
table.insert(formspec, "\n\nClick on an element to select it.")
table.insert(formspec, "]")
end
table.insert(formspec, "container_end[]")
end

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
-- Implementation of chat commands that were registered in register_once
-- (here: only add those additional things needed for edit mode)
local old_command_npc_talk = yl_speak_up.command_npc_talk
yl_speak_up.command_npc_talk = function(pname, param)
if(not(pname)) then
return
end
-- activates edit mode when talking to an NPC; but only if the player can edit that NPC
if(param and param == "force_edit") then
-- implemented in functions.lua:
return yl_speak_up.command_npc_talk_force_edit(pname, rest)
end
-- not perfect - but at least some help
if(param
and (param == "help force_edit"
or param == "? force_edit"
or param == "force_edit help")) then
minetest.chat_send_player(pname,
"Toggles force edit mode. This is helpful if you cut yourself out "..
"of editing an NPC by breaking it. From now on all NPC you will talk to "..
"will already be in edit mode (provided you are allowed to edit them)."..
"\nIssuing the command again ends force edit mode.")
return
end
return old_command_npc_talk(pname, param)
end

View File

@ -1,24 +0,0 @@
-- allow to enter force edit mode (useful when an NPC was broken)
yl_speak_up.force_edit_mode = {}
-- command to enter force edit mode
yl_speak_up.command_npc_talk_force_edit = function(pname, param)
if(not(pname)) then
return
end
if(yl_speak_up.force_edit_mode[pname]) then
yl_speak_up.force_edit_mode[pname] = nil
minetest.chat_send_player(pname,
"Ending force edit mode for NPC. From now on talks "..
"will no longer start in edit mode.")
else
yl_speak_up.force_edit_mode[pname] = true
minetest.chat_send_player(pname,
"STARTING force edit mode for NPC. From now on talks "..
"with NPC will always start in edit mode provided "..
"you are allowed to edit this NPC.\n"..
"In order to end force edit mode, give the command "..
"/npc_talk_force_edit a second time.")
end
end

View File

@ -1,151 +0,0 @@
-- if player has npc_talk_owner priv AND is owner of this particular npc:
-- chat option: "I am your owner. I have new orders for you.
-- -> enters edit mode
-- when edit_mode has been enabled, the following chat options are added to the options:
-- chat option: "Add new answer/option to this dialog."
-- -> adds a new aswer/option
-- chat option: "That was all. I'm finished with giving you new orders. Remember them!"
-- -> ends edit mode
-- (happens in fs/fs_talkdialog_in_edit_mode.lua)
-- store if the player is editing a particular NPC; format: yl_speak_up.edit_mode[pname] = npc_id
yl_speak_up.edit_mode = {}
-- changes applied in edit_mode are applied immediately - but not immediately stored to disk
-- (this gives the players a chance to back off in case of unwanted changes)
yl_speak_up.npc_was_changed = {}
-- is the player in edit mode?
yl_speak_up.in_edit_mode = function(pname)
return pname
and yl_speak_up.edit_mode[pname]
and (yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id)
end
-- reset edit_mode when stopping to talk to an NPC
local old_reset_vars_for_player = yl_speak_up.reset_vars_for_player
yl_speak_up.reset_vars_for_player = function(pname, reset_fs_version)
yl_speak_up.edit_mode[pname] = nil
old_reset_vars_for_player(pname, reset_fs_version)
end
-- make sure generic dialogs are never included in edit_mode (because in edit mode we want to
-- edit this particular NPC without generic parts)
local old_load_dialog = yl_speak_up.load_dialog
yl_speak_up.load_dialog = function(n_id, player) -- returns the saved dialog
if(player and yl_speak_up.in_edit_mode(player:get_player_name())) then
return old_load_dialog(n_id, false)
end
return old_load_dialog(n_id, player)
end
-- in edit mode the dialog may be saved. visits to a particular dialog are of no intrest here
local old_count_visits_to_dialog = yl_speak_up.count_visits_to_dialog
yl_speak_up.count_visits_to_dialog = function(pname)
if(yl_speak_up.in_edit_mode(pname)) then
return
end
return old_count_visits_to_dialog(pname)
end
local modname = minetest.get_current_modname()
if(not(modname)) then
modname = "yl_speak_up"
end
-- TODO: adjust to new mod name and paths
local modpath = minetest.get_modpath(modname)..DIR_DELIM.."editor"..DIR_DELIM
-- this is a way to provide additional help if a mod adds further commands (like the editor)
yl_speak_up.add_to_command_help_text = yl_speak_up.add_to_command_help_text..
"\nAdditional commands provided by "..tostring(modname)..":\n"..
" force_edit forces edit mode for any NPC you talk to\n"
-- overrides of functions fo fs/fs_talkdialog.lua when in edit_mode (or for entering/leaving it)
dofile(modpath .. "fs/fs_talkdialog_edit_mode.lua")
-- edit preconditions (can be reached through edit options dialog)
dofile(modpath .. "fs/fs_edit_preconditions.lua")
-- edit actions (can be reached through edit options dialog)
dofile(modpath .. "fs/fs_edit_actions.lua")
-- edit effects (can be reached through edit options dialog)
dofile(modpath .. "fs/fs_edit_effects.lua")
-- edit options dialog (detailed configuration of options in edit mode)
dofile(modpath .. "fs/fs_edit_options_dialog.lua")
-- the player wants to change something regarding the dialog
dofile(modpath .. "edit_mode_apply_changes.lua")
-- handle page changes and asking for saving when in edit mode:
dofile(modpath .. "show_fs_in_edit_mode.lua")
-- ask if the player wants to save, discard or go back in edit mode
dofile(modpath .. "fs/fs_save_or_discard_or_back.lua")
-- the player wants to change something regarding the dialog
dofile(modpath .. "edit_mode_apply_changes.lua")
-- assign a quest step to a dialog option/answer
dofile(modpath .. "fs/fs_assign_quest_step.lua")
-- in edit_mode we need a more complex reaction to inventory changes
dofile(modpath .. "exec_actions_action_inv_changed.lua")
-- in edit_mode: effects are not executed
dofile(modpath .. "exec_all_relevant_effects.lua")
-- some helper functions for formatting text for a formspec talbe
dofile(modpath .. "print_as_table.lua")
-- create i.e. a dropdown list of player names
dofile(modpath .. "api/formspec_helpers.lua")
-- handle alternate text for dialogs
dofile(modpath .. "api/api_alternate_text.lua")
-- helpful for debugging the content of the created dialog structure
dofile(modpath .. "fs/fs_show_what_points_to_this_dialog.lua")
-- common functions for editing preconditions and effects
dofile(modpath .. "api/fs_edit_general.lua")
-- edit preconditions (can be reached through edit options dialog)
dofile(modpath .. "fs/fs_edit_preconditions.lua")
-- edit actions (can be reached through edit options dialog)
dofile(modpath .. "fs/fs_edit_actions.lua")
-- edit effects (can be reached through edit options dialog)
dofile(modpath .. "fs/fs_edit_effects.lua")
-- edit options dialog (detailed configuration of options in edit mode)
dofile(modpath .. "fs/fs_edit_options_dialog.lua")
dofile(modpath .. "fs/fs_initial_config_in_edit_mode.lua")
dofile(modpath .. "trade_in_edit_mode.lua")
dofile(modpath .. "fs/fs_add_trade_simple_in_edit_mode.lua")
-- handle back button diffrently when editing a trade as an action:
dofile(modpath .. "fs/fs_do_trade_simple_in_edit_mode.lua")
-- as the name says: list which npc acesses a variable how and in which context
dofile(modpath .. "fs/fs_get_list_of_usage_of_variable.lua")
-- show which values are stored for which player in a quest variable
dofile(modpath .. "fs/fs_show_all_var_values.lua")
-- manage quest variables: add, delete, manage access rights etc.
dofile(modpath .. "fs/fs_manage_variables.lua")
-- GUI for adding/editing quests
dofile(modpath .. "fs/fs_manage_quests.lua")
-- GUI for adding/editing quest steps for the quests
dofile(modpath .. "api/api_quest_steps.lua")
dofile(modpath .. "fs/fs_manage_quest_steps.lua")
-- used by the above
dofile(modpath .. "fs/fs_add_quest_steps.lua")
-- setting skin, wielded item etc.
dofile(modpath .. "fs/fs_fashion.lua")
dofile(modpath .. "fs/fs_fashion_extended.lua")
-- properties for NPC without specific dialogs that want to make use of
dofile(modpath .. "fs/fs_properties.lua")
-- /npc_talk force_edit (when talking to an NPC in the normal way fails):
dofile(modpath .. "command_force_edit_mode.lua")
-- add the force_edit option to the chat commands
dofile(modpath .. "chat_commands_in_edit_mode.lua")
-- creating and maintaining quests
dofile(modpath .. "fs/fs_quest_gui.lua")
-- take notes regarding what the NPC is for
dofile(modpath .. "fs/fs_notes.lua")

View File

@ -1,570 +0,0 @@
-- helper function for yl_speak_up.edit_mode_apply_changes;
-- makes sure the new dialog (and a result/effect "dialog" for each option) exist
yl_speak_up.prepare_new_dialog_for_option = function(dialog, pname, n_id, d_id, o_id,target_dialog,o_results)
-- this may also point to a new dialog
if(target_dialog == yl_speak_up.text_new_dialog_id) then
-- create a new dialog and show it as new target dialog - but do not display
-- this dialog directly (the player may follow the -> button)
target_dialog = yl_speak_up.add_new_dialog(dialog, pname, nil)
end
-- translate name into dialog id
target_dialog = yl_speak_up.d_name_to_d_id(dialog, target_dialog)
-- is there a result/effect of the type "dialog" already? else use a fallback
local result = {} --{r_value = "-default-"}
if(o_results) then
for kr, vr in pairs(o_results) do
if( vr.r_type == "dialog" ) then
result = vr
-- no problem - the right dialog is set already
if(result.r_value and result.r_value == target_dialog) then
return target_dialog
else
-- no need to search any further
break
end
end
end
end
local old_d = tostring(result.r_value or "-default-")
if(result.r_value and dialog.n_dialogs[result.r_value] and dialog.n_dialogs[result.r_value].d_name) then
old_d = old_d..":"..tostring(dialog.n_dialogs[result.r_value].d_name)
end
local new_d = tostring(target_dialog)
if(target_dialog and dialog.n_dialogs[target_dialog] and dialog.n_dialogs[target_dialog].d_name) then
new_d = new_d..":"..tostring(dialog.n_dialogs[target_dialog].d_name)
end
-- store that a new option has been added to this dialog
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": The target dialog for option "..
tostring(o_id).." was changed from "..
old_d.." to "..new_d..".")
-- does the result/effect of type "dialog" exist already? then we're done
if(result.r_type and result.r_type == "dialog") then
-- actually change the target dialog
result.r_value = target_dialog
return target_dialog
end
-- create a new result (first the id, then the actual result)
local future_r_id = yl_speak_up.add_new_result(dialog, d_id, o_id)
-- actually store the new result
dialog.n_dialogs[d_id].d_options[o_id].o_results[future_r_id] = {
r_id = future_r_id,
r_type = "dialog",
r_value = target_dialog}
return target_dialog
end
-- helper function for formspec "yl_speak_up:talk" *and* formspec "yl_speak_up:edit_option_dialog"
-- when a parameter was changed in edit mode;
-- this is called when the player is in edit_mode (editing the NPC);
-- the function checks if the player has changed any parameters
-- Parameters:
-- pname player name
-- fields the fields returned from the formspec
-- Returns:
-- result table with information about what was added
-- (for now, only result.show_next_option is of intrest in the option edit menu)
yl_speak_up.edit_mode_apply_changes = function(pname, fields)
local n_id = yl_speak_up.edit_mode[pname]
if(not(n_id) or not(yl_speak_up.speak_to[pname])) then
return
end
local d_id = yl_speak_up.speak_to[pname].d_id
local dialog = yl_speak_up.speak_to[pname].dialog
-- check if the player is allowed to edit this NPC
if(not(yl_speak_up.may_edit_npc(minetest.get_player_by_name(pname), n_id))) then
return
end
-- this way we can store the actual changes and present them to the player for saving
if(not(yl_speak_up.npc_was_changed[ n_id ])) then
yl_speak_up.npc_was_changed[ n_id ] = {}
end
-- nothing to do if that dialog does not exist
if(not(d_id) or not(dialog.n_dialogs) or not(dialog.n_dialogs[ d_id ])) then
return
end
-- allow owner to mute/unmute npc (would be bad if players can already see what is going
-- to happen while the owner creates a long quest)
-- mute/unmute gets logged in the function and does not need extra log entries
local obj = yl_speak_up.speak_to[pname].obj
if(fields.mute_npc and obj) then
yl_speak_up.set_muted(pname, obj, true)
elseif(fields.un_mute_npc and obj) then
yl_speak_up.set_muted(pname, obj, false)
end
-- changes to d_dynamic are *not* changed (the content of that dialog has to be provided
-- dynamicly by a function):
if(d_id == "d_dynamic") then
return
end
-- new options etc. may be added; store these IDs so that we can switch to the right target
local result = {}
-- make this the first dialog shown when starting a conversation
if(fields.make_first_option) then
-- check which dialog(s) previously had the highest priority and change thsoe
for k, v in pairs(dialog.n_dialogs) do
if(v and v.d_sort and (v.d_sort=="0" or v.d_sort==0)) then
-- try to derive a sensible future sort priority from the key:
-- here we make use of the d_<nr> pattern; but even if that fails to yield
-- a number, the sort function will later be able to deal with it anyway
local new_priority = string.sub(k, 3)
dialog.n_dialogs[ k ].d_sort = new_priority
end
end
-- actually make this the chat with the highest priority
dialog.n_dialogs[ d_id ].d_sort = "0"
-- this is not immediately saved, even though the changes to the previous dialog with
-- the highest priority cannot be automaticly undone (but as long as it is not saved,
-- it really does not matter; and when saving, the player has to take some care)
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": Turned into new start dialog.")
end
-- if it is *a* start dialog: buttons like give item to npc/trade/etc. will be shown
if(fields.turn_into_a_start_dialog) then
if(dialog.n_dialogs[ d_id ].is_a_start_dialog) then
-- no need to waste space...
dialog.n_dialogs[ d_id ].is_a_start_dialog = nil
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": Is no longer *a* start dialog (regarding buttons).")
else
dialog.n_dialogs[ d_id ].is_a_start_dialog = true
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": Turned into *a* start dialog (regarding buttons).")
end
end
-- detect changes to d_text: text of the dialog (what the npc is saying)
-- (only happens in dialog edit menu)
if(fields.d_text and dialog.n_dialogs[ d_id ].d_text ~= fields.d_text) then
-- store that there have been changes to this npc
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": d_text (what the NPC says) was changed from \""..
tostring( dialog.n_dialogs[ d_id ].d_text)..
"\" to \""..tostring(fields.d_text).."\".")
-- actually change the text - but do not save to disk yet
dialog.n_dialogs[ d_id ].d_text = fields.d_text
end
if(fields.d_name and fields.d_name ~= "" and dialog.n_dialogs[ d_id ].d_name ~= fields.d_name) then
if(fields.d_name ~= d_id
and not(yl_speak_up.is_special_dialog(d_id))) then
local err_msg = nil
-- check if there are no duplicate names
for k, v in pairs(dialog.n_dialogs) do
if(v and v.d_name and v.d_name == fields.d_name and k ~= d_id) then
err_msg = "Sorry. That name has already been used for dialog "..
tostring(k).."."
end
end
if(dialog.n_dialogs[fields.d_name]) then
err_msg = "Sorry. There is already a dialog with a dialog id of "..
tostring(fields.d_name).."."
elseif(yl_speak_up.is_special_dialog(fields.d_name)) then
err_msg = "Sorry. That is a special dialog ID. You cannot use it as "..
"a manually set name."
elseif(string.sub(fields.d_name, 1, 2) == "d_") then
err_msg = "Sorry. Names starting with \"d_\" are not allowed. They "..
"may later be needed for new dialogs."
end
-- TODO: check if the name is allowed (only normal chars, numbers and underscore)
if(err_msg) then
minetest.chat_send_player(pname, err_msg)
else
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": renamed from \""..
tostring(dialog.n_dialogs[ d_id ].d_name)..
"\" to \""..tostring(fields.d_name).."\".")
dialog.n_dialogs[ d_id ].d_name = fields.d_name
end
end
end
-- add a new option/answer
if(fields[ "add_option"]) then
local future_o_id = yl_speak_up.add_new_option(dialog, pname, nil, d_id, "", d_id)
if(not(future_o_id)) then
-- this is already checked earlier on and the button only shown if
-- options can be added; so this can reamin a chat message
minetest.chat_send_player(pname, "Sorry. Only "..
tostring(yl_speak_up.max_number_of_options_per_dialog)..
" options/answers are allowed per dialog.")
fields.add_option = nil
else