forked from your-land-mirror/yl_speak_up
split mod into core (this mod) and editor (npc_talk_edit mod)
This commit is contained in:
parent
e262b53a04
commit
5f2917df01
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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")
|
|
@ -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
|
||||
-- add_new_option has added a dialog result for us already - no need to do that again
|
||||
|
||||
-- if this is selected in the options edit menu, we want to move straight on to the new option
|
||||
result["show_next_option"] = future_o_id
|
||||
end
|
||||
end
|
||||
|
||||
-- delete an option directly from the main fs_talkdialog
|
||||
if(dialog.n_dialogs[d_id].d_options) then
|
||||
for o_id, o_v in pairs(dialog.n_dialogs[d_id].d_options) do
|
||||
if(o_id and fields["delete_option_"..o_id]) then
|
||||
fields["del_option"] = true
|
||||
fields.o_id = o_id
|
||||
-- ..or move an option up by one in the list
|
||||
elseif(o_id and fields["option_move_up_"..o_id]) then
|
||||
fields["option_move_up"] = true
|
||||
fields.o_id = o_id
|
||||
-- ..or move an option down by one in the list
|
||||
elseif(o_id and fields["option_move_down_"..o_id]) then
|
||||
fields["option_move_down"] = true
|
||||
fields.o_id = o_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(fields[ "del_option"] and fields.o_id and dialog.n_dialogs[d_id].d_options[fields.o_id]) then
|
||||
local o_id = fields.o_id
|
||||
-- which dialog to show instead of the deleted one?
|
||||
local next_o_id = o_id
|
||||
local sorted_list = yl_speak_up.get_sorted_options(dialog.n_dialogs[d_id].d_options, "o_sort")
|
||||
for i, o in ipairs(sorted_list) do
|
||||
if(o == o_id and sorted_list[ i+1 ]) then
|
||||
next_o_id = sorted_list[ i+1 ]
|
||||
elseif(o == o_id and sorted_list[ i-1 ]) then
|
||||
next_o_id = sorted_list[ i-1 ]
|
||||
end
|
||||
end
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": Option "..tostring(o_id).." deleted.")
|
||||
-- actually delete the dialog
|
||||
dialog.n_dialogs[d_id].d_options[o_id] = nil
|
||||
-- the current dialog is deleted; we need to show another one
|
||||
result["show_next_option"] = next_o_id
|
||||
-- after deleting the entry, all previous/further changes to it are kind of unintresting
|
||||
return result
|
||||
end
|
||||
|
||||
-- move an option up by one
|
||||
local d_options = dialog.n_dialogs[d_id].d_options
|
||||
if(fields[ "option_move_up"] and fields.o_id and d_options[fields.o_id]) then
|
||||
local sorted_o_list = yl_speak_up.get_sorted_options(d_options, "o_sort")
|
||||
local idx = table.indexof(sorted_o_list, fields.o_id)
|
||||
if(idx > 1) then
|
||||
-- swap the two positions
|
||||
local tmp = dialog.n_dialogs[d_id].d_options[fields.o_id].o_sort
|
||||
dialog.n_dialogs[d_id].d_options[fields.o_id].o_sort =
|
||||
dialog.n_dialogs[d_id].d_options[sorted_o_list[idx - 1]].o_sort
|
||||
dialog.n_dialogs[d_id].d_options[sorted_o_list[idx - 1]].o_sort = tmp
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": Option "..tostring(fields.o_id).." was moved up by one.")
|
||||
end
|
||||
-- ..or move the option down by one
|
||||
elseif(fields[ "option_move_down"] and fields.o_id and d_options[fields.o_id]) then
|
||||
local sorted_o_list = yl_speak_up.get_sorted_options(d_options, "o_sort")
|
||||
local idx = table.indexof(sorted_o_list, fields.o_id)
|
||||
if(idx > 0 and idx < #sorted_o_list) then
|
||||
local tmp = dialog.n_dialogs[d_id].d_options[fields.o_id].o_sort
|
||||
dialog.n_dialogs[d_id].d_options[fields.o_id].o_sort =
|
||||
dialog.n_dialogs[d_id].d_options[sorted_o_list[idx + 1]].o_sort
|
||||
dialog.n_dialogs[d_id].d_options[sorted_o_list[idx + 1]].o_sort = tmp
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": Option "..tostring(fields.o_id).." was moved down by one.")
|
||||
end
|
||||
end
|
||||
|
||||
-- ignore entries to o_sort if they are not a number
|
||||
if(fields[ "edit_option_o_sort"]
|
||||
and tonumber(fields[ "edit_option_o_sort"])
|
||||
and fields.o_id and dialog.n_dialogs[d_id].d_options[fields.o_id]) then
|
||||
local o_id = fields.o_id
|
||||
local new_nr = tonumber(fields[ "edit_option_o_sort"])
|
||||
local old_nr = tonumber(dialog.n_dialogs[d_id].d_options[o_id].o_sort)
|
||||
-- if the nr is -1 (do not show) then we are done already: nothing to do
|
||||
if(old_nr == new_nr) then
|
||||
-- -1: do not list as option/answer (but still store and keep it)
|
||||
elseif(new_nr == -1 and old_nr ~= -1) then
|
||||
dialog.n_dialogs[d_id].d_options[o_id].o_sort = "-1"
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": Option "..tostring(o_id).." was set to -1 (do not list).")
|
||||
else
|
||||
-- get the old sorted list
|
||||
local sorted_list = yl_speak_up.get_sorted_options(dialog.n_dialogs[d_id].d_options, "o_sort")
|
||||
-- negative numbers are not shown
|
||||
local entries_shown_list = {}
|
||||
for i, o in ipairs(sorted_list) do
|
||||
local n = tonumber(dialog.n_dialogs[d_id].d_options[o].o_sort)
|
||||
if(n and n > 0 and o ~= o_id) then
|
||||
table.insert(entries_shown_list, o)
|
||||
end
|
||||
end
|
||||
-- insert the entry at the new position and let lua do the job
|
||||
table.insert(entries_shown_list, new_nr, o_id)
|
||||
-- take the indices from that new list as new sort values and store them;
|
||||
-- this has the side effect that duplicate entries get sorted out as well
|
||||
for i, o in ipairs(entries_shown_list) do
|
||||
dialog.n_dialogs[d_id].d_options[o].o_sort = tostring(i)
|
||||
end
|
||||
-- store that there was a cahnge
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": Option "..tostring(o_id).." was moved to position "..
|
||||
tostring(new_nr)..".")
|
||||
end
|
||||
end
|
||||
|
||||
-- changes to options are not possible if there are none
|
||||
if(dialog.n_dialogs[ d_id ].d_options) then
|
||||
|
||||
-- detect changes to text_option_<o_id>: text for option <o_id>
|
||||
for k, v in pairs(dialog.n_dialogs[ d_id ].d_options) do
|
||||
if( fields[ "text_option_"..k ]
|
||||
and fields[ "text_option_"..k ] ~= v.o_text_when_prerequisites_met ) then
|
||||
-- store that there have been changes to this npc
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": The text for option "..tostring(k)..
|
||||
" was changed from \""..tostring(v.o_text_when_prerequisites_met)..
|
||||
"\" to \""..tostring(fields[ "text_option_"..k]).."\".")
|
||||
-- actually change the text of the option
|
||||
dialog.n_dialogs[ d_id ].d_options[ k ].o_text_when_prerequisites_met = fields[ "text_option_"..k ]
|
||||
end
|
||||
end
|
||||
|
||||
-- detect changes to d_id_<o_id>: target dialog for option <o_id>
|
||||
for k, v in pairs(dialog.n_dialogs[ d_id ].d_options) do
|
||||
if(fields[ "d_id_"..k ]) then
|
||||
local new_target_dialog = yl_speak_up.prepare_new_dialog_for_option(
|
||||
dialog, pname, n_id, d_id, k, fields[ "d_id_"..k ], v.o_results)
|
||||
if(new_target_dialog ~= fields[ "d_id_"..k ]
|
||||
and not( dialog.n_dialogs[new_target_dialog]
|
||||
and dialog.n_dialogs[new_target_dialog].d_name
|
||||
and dialog.n_dialogs[new_target_dialog].d_name == fields["d_id_"..k])
|
||||
) then
|
||||
fields[ "d_id_"..k ] = new_target_dialog
|
||||
-- in options edit menu: show this update
|
||||
result["show_next_option"] = k
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- add a new dialog; either via "+" button or "New dialog" in dialog dropdown menu
|
||||
-- this has to be done after all the other changes because those (text changes etc.) still
|
||||
-- apply to the *old* dialog
|
||||
if(fields.show_new_dialog
|
||||
or(fields["d_id"] and fields["d_id"] == yl_speak_up.text_new_dialog_id)) then
|
||||
-- create the new dialog and make sure it gets shown
|
||||
local d_id = yl_speak_up.add_new_dialog(dialog, pname, nil)
|
||||
-- actually show the new dialog
|
||||
fields["d_id"] = d_id
|
||||
fields["show_new_dialog"] = nil
|
||||
end
|
||||
|
||||
-- delete one empty dialog
|
||||
if(fields.delete_this_empty_dialog) then
|
||||
local anz_options = 0
|
||||
-- we need to show a new dialog after this one was deleted
|
||||
local new_dialog = d_id
|
||||
local sorted_list = yl_speak_up.get_sorted_options(dialog.n_dialogs, "d_sort")
|
||||
for i, k in ipairs(sorted_list) do
|
||||
-- count the options of this dialog
|
||||
if(k == d_id) then
|
||||
if(dialog.n_dialogs[d_id].d_options) then
|
||||
for o, w in pairs(dialog.n_dialogs[d_id].d_options) do
|
||||
anz_options = anz_options + 1
|
||||
end
|
||||
end
|
||||
if(sorted_list[i+1]) then
|
||||
new_dialog = sorted_list[i+1]
|
||||
elseif(sorted_list[i-1]) then
|
||||
new_dialog = sorted_list[i-1]
|
||||
end
|
||||
end
|
||||
end
|
||||
-- there needs to be one dialog left after deleting this one,
|
||||
-- (as there is always d_dynamic we need to leave *two* dialogs)
|
||||
if(#sorted_list > 2
|
||||
-- this dialog isn't allowed to hold any more options/answers
|
||||
and anz_options == 0
|
||||
-- we really found a new dialog to show
|
||||
and new_dialog ~= d_id
|
||||
-- and the text needs to be empty
|
||||
and dialog.n_dialogs[ d_id ].d_text == "") then
|
||||
-- actually delete this dialog
|
||||
dialog.n_dialogs[ d_id ] = nil
|
||||
-- ..and store it to disk
|
||||
yl_speak_up.delete_dialog(n_id, d_id)
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"Deleted dialog "..tostring(d_id)..".")
|
||||
-- switch to another dialog (this one was deleted after all)
|
||||
fields["d_id"] = new_dialog
|
||||
fields["show_new_dialog"] = nil
|
||||
else
|
||||
-- deleting is only possible from the talk menu, and there the delete
|
||||
-- button is only shown if the dialog can be deleted; so this can remain
|
||||
-- a chat message
|
||||
minetest.chat_send_player(pname, "Sorry. This dialog cannot be deleted (yet). "..
|
||||
"It is either the only dialog left or has a non-empty text or has at "..
|
||||
"least on remaining option/answer.")
|
||||
end
|
||||
end
|
||||
|
||||
-- not in options edit menu?
|
||||
local o_id = fields.o_id
|
||||
if(not(o_id)) then
|
||||
return result
|
||||
end
|
||||
|
||||
local d_option = dialog.n_dialogs[ d_id ].d_options[ o_id ]
|
||||
-- change alternate text when preconditions are not met
|
||||
-- (only happens in options edit menu)
|
||||
if(fields.option_text_not_met and d_option
|
||||
and d_option.o_text_when_prerequisites_not_met ~= fields.option_text_not_met) then
|
||||
-- add change to changelog
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": The alternate text for option "..tostring(o_id)..
|
||||
" was changed from \""..
|
||||
tostring(d_option.o_text_when_prerequisites_not_met).."\" to \""..
|
||||
tostring(fields.option_text_not_met).."\".")
|
||||
-- actually change the text of the option
|
||||
d_option.o_text_when_prerequisites_not_met = fields.option_text_not_met
|
||||
end
|
||||
|
||||
-- toggle visit often/only *once*
|
||||
if(d_option and fields.option_visits and fields.option_visits ~= "") then
|
||||
local old_visit_mode = "often"
|
||||
if(d_option.o_visit_only_once and d_option.o_visit_only_once == 1) then
|
||||
old_visit_mode = "*once*"
|
||||
end
|
||||
if(fields.option_visits ~= old_visit_mode) then
|
||||
if(fields.option_visits == "often") then
|
||||
d_option.o_visit_only_once = 0
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": Option "..tostring(o_id)..
|
||||
" can now be visited often/unlimited (default).")
|
||||
elseif(fields.option_visits == "*once*") then
|
||||
d_option.o_visit_only_once = 1
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": Option "..tostring(o_id)..
|
||||
" can now be visited only *once* per talk.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- toggle autoselection/autoclick of an option
|
||||
if(d_option and fields.option_autoanswer and fields.option_autoanswer ~= "") then
|
||||
local old_answer_mode = "by clicking on it"
|
||||
if(dialog.n_dialogs[ d_id ].o_random) then
|
||||
old_answer_mode = "randomly"
|
||||
elseif(d_option.o_autoanswer and d_option.o_autoanswer == 1) then
|
||||
old_answer_mode = "automaticly"
|
||||
end
|
||||
if(fields.option_autoanswer ~= old_answer_mode) then
|
||||
local new_answer_mode = ""
|
||||
if(fields.option_autoanswer == "by clicking on it") then
|
||||
d_option.o_autoanswer = nil
|
||||
-- the dialog is no longer random
|
||||
dialog.n_dialogs[ d_id ].o_random = nil
|
||||
new_answer_mode = fields.option_autoanswer
|
||||
elseif(fields.option_autoanswer == "automaticly") then
|
||||
d_option.o_autoanswer = 1
|
||||
-- the dialog is no longer random
|
||||
dialog.n_dialogs[ d_id ].o_random = nil
|
||||
new_answer_mode = fields.option_autoanswer
|
||||
elseif(fields.option_autoanswer == "randomly") then
|
||||
d_option.o_autoanswer = nil
|
||||
-- the entire dialog needs to be set to randomly - not just this option
|
||||
dialog.n_dialogs[ d_id ].o_random = 1
|
||||
new_answer_mode = fields.option_autoanswer
|
||||
end
|
||||
if(new_answer_mode ~= "" and new_answer_mode ~= old_answer_mode) then
|
||||
local random_was_changed = ""
|
||||
if(new_answer_mode == "randomly" or old_answer_mode == "randomly") then
|
||||
random_was_changed = " Note that changes to/from \"randomly\" "..
|
||||
"affect the entire dialog!"
|
||||
end
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": The modus for option "..tostring(o_id)..
|
||||
" was changed from \""..old_answer_mode.."\" to \""..
|
||||
new_answer_mode.."\"."..random_was_changed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- handle hide/grey out/show alternate answer
|
||||
-- (only happens in options edit menu)
|
||||
if(fields.hide_or_grey_or_alternate_answer and d_option) then
|
||||
if(fields.hide_or_grey_or_alternate_answer == "..hide this answer."
|
||||
and d_option.o_hide_when_prerequisites_not_met ~= "true") then
|
||||
d_option.o_hide_when_prerequisites_not_met = "true"
|
||||
d_option.o_grey_when_prerequisites_not_met = "false"
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": If precondition for option "..tostring(o_id)..
|
||||
" is not met, hide option/answer.")
|
||||
-- make sure we show this options update next
|
||||
result["show_next_option"] = o_id
|
||||
elseif(fields.hide_or_grey_or_alternate_answer == "..grey out the following answer:"
|
||||
and d_option.o_grey_when_prerequisites_not_met ~= "true") then
|
||||
d_option.o_hide_when_prerequisites_not_met = "false"
|
||||
d_option.o_grey_when_prerequisites_not_met = "true"
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": If precondition for option "..tostring(o_id)..
|
||||
" is not met, grey out option/answer.")
|
||||
result["show_next_option"] = o_id
|
||||
elseif(fields.hide_or_grey_or_alternate_answer == "..display the following alternate answer:"
|
||||
and (d_option.o_hide_when_prerequisites_not_met ~= "false"
|
||||
or d_option.o_grey_when_prerequisites_not_met) ~= "false") then
|
||||
d_option.o_hide_when_prerequisites_not_met = "false"
|
||||
d_option.o_grey_when_prerequisites_not_met = "false"
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": If precondition for option "..tostring(o_id)..
|
||||
" is not met, show alternate option/answer.")
|
||||
result["show_next_option"] = o_id
|
||||
end
|
||||
end
|
||||
|
||||
-- how many times can the player fail to execute the action successfully?
|
||||
if(fields[ "timer_max_attempts_on_failure"]) then
|
||||
local field_name = "timer_max_attempts_on_failure"
|
||||
local timer_name = "timer_on_failure_"..tostring(d_id).."_"..tostring(o_id)
|
||||
if(not(tonumber(fields[ field_name ]))) then
|
||||
fields[ field_name ] = 0
|
||||
end
|
||||
-- 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", "max_attempts",
|
||||
fields[ field_name ])
|
||||
end
|
||||
end
|
||||
-- ..and how long has the player to wait in order to try again?
|
||||
if(fields[ "timer_max_seconds_on_failure"]) then
|
||||
local field_name = "timer_max_seconds_on_failure"
|
||||
local timer_name = "timer_on_failure_"..tostring(d_id).."_"..tostring(o_id)
|
||||
if(not(tonumber(fields[ field_name ]))) then
|
||||
fields[ field_name ] = 0
|
||||
end
|
||||
-- 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", "duration",
|
||||
fields[ field_name ])
|
||||
end
|
||||
end
|
||||
if(fields[ "timer_max_seconds_on_success"]) then
|
||||
local field_name = "timer_max_seconds_on_success"
|
||||
local timer_name = "timer_on_success_"..tostring(d_id).."_"..tostring(o_id)
|
||||
if(not(tonumber(fields[ field_name ]))) then
|
||||
fields[ field_name ] = 0
|
||||
end
|
||||
-- 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", "duration",
|
||||
fields[ field_name ])
|
||||
end
|
||||
end
|
||||
-- currently only contains result["show_new_option"] (which is needed for options edit menu)
|
||||
return result
|
||||
end
|
||||
-- end of yl_speak_up.edit_mode_apply_changes
|
|
@ -1,62 +0,0 @@
|
|||
|
||||
local old_action_inv_changed = yl_speak_up.action_inv_changed
|
||||
-- monitor changes to the npc_gives and npc_wants slots (in particular when editing actions)
|
||||
-- how: can be "put" or "take"
|
||||
yl_speak_up.action_inv_changed = function(inv, listname, index, stack, player, how)
|
||||
if(not(player)) then
|
||||
return
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
if(not(pname) or not(yl_speak_up.speak_to[pname])) then
|
||||
return
|
||||
end
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
-- if not in edit mode: the player may just be normally interacting with the NPC;
|
||||
-- nothing to do for us here (wait for the player to click on "save")
|
||||
if(not(n_id) or yl_speak_up.edit_mode[pname] ~= n_id) then
|
||||
return old_action_inv_changed(inv, listname, index, stack, player, how)
|
||||
end
|
||||
-- is the player in the process of editing an action of the npc_gives/npc_wants type?
|
||||
local target_fs = "edit_actions"
|
||||
local data = yl_speak_up.speak_to[pname][ "tmp_action" ]
|
||||
if(not(data) or (data.what ~= 4 and data.what ~= 5)) then
|
||||
-- we are editing an action
|
||||
if(data) then
|
||||
return
|
||||
end
|
||||
-- it might be a precondition
|
||||
data = yl_speak_up.speak_to[pname][ "tmp_prereq" ]
|
||||
if(not(data) or (data.what ~= 8)) then
|
||||
return
|
||||
end
|
||||
target_fs = "edit_preconditions"
|
||||
end
|
||||
-- "The NPC gives something to the player (i.e. a quest item).", -- 4
|
||||
-- "The player is expected to give something to the NPC (i.e. a quest item).", -- 5
|
||||
if(how == "put") then
|
||||
data.item_node_name = stack:get_name().." "..stack:get_count()
|
||||
local meta = stack:get_meta()
|
||||
if(meta and meta:get_string("description")) then
|
||||
-- try to reconstruct $PLAYER_NAME$ (may not always work)
|
||||
local item_was_for = meta:get_string("yl_speak_up:quest_item_for")
|
||||
local new_desc = meta:get_string("description")
|
||||
if(item_was_for and item_was_for ~= "") then
|
||||
new_desc = string.gsub(new_desc, item_was_for, "$PLAYER_NAME$")
|
||||
end
|
||||
data.item_desc = new_desc
|
||||
end
|
||||
if(meta and meta:get_string("yl_speak_up:quest_id")) then
|
||||
data.item_quest_id = meta:get_string("yl_speak_up:quest_id")
|
||||
end
|
||||
elseif(how == "take" and data.what == 4) then
|
||||
data.item_desc = "- no item set -"
|
||||
data.item_node_name = ""
|
||||
elseif(how == "take" and data.what == 5) then
|
||||
data.item_desc = "- no item set -"
|
||||
data.item_node_name = ""
|
||||
end
|
||||
-- show the updated formspec to the player
|
||||
yl_speak_up.show_fs(player, target_fs, nil)
|
||||
-- no need to check anything more here; the real checks need to be done
|
||||
-- when the player presses the save/store/execute button
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
local old_execute_all_relevant_effects = yl_speak_up.execute_all_relevant_effects
|
||||
yl_speak_up.execute_all_relevant_effects = function(player, effects, o_id, action_was_successful, d_option,
|
||||
dry_run_no_exec) -- dry_run_no_exec for edit_mode
|
||||
-- if in edit mode: do a dry run - do *not* execute the effects
|
||||
local edit_mode = (player and yl_speak_up.in_edit_mode(player:get_player_name()))
|
||||
-- we pass this as an additional parameter so that it doesn't have to be re-evaluated for each effect
|
||||
return old_execute_all_relevant_effects(player, effects, o_id, action_was_successful, d_option, edit_mode)
|
||||
end
|
|
@ -1,763 +0,0 @@
|
|||
-- helper function to make unintresting zeros in tables less visible
|
||||
local grey_if_zero = function(fs, n)
|
||||
if(n and n == 0) then
|
||||
table.insert(fs, "#444444")
|
||||
else
|
||||
table.insert(fs, "#FFFFFF")
|
||||
end
|
||||
table.insert(fs, minetest.formspec_escape(n))
|
||||
end
|
||||
|
||||
|
||||
-- small helper function
|
||||
local show_error_fs = function(player, text)
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:add_quest_steps",
|
||||
formspec = yl_speak_up.build_fs_quest_edit_error(text, "back_from_error_msg")})
|
||||
end
|
||||
|
||||
|
||||
-- find out in how many quest steps this NPC or location is used;
|
||||
-- ID can either be n_<ID> or a location p_(x,y,z)
|
||||
yl_speak_up.count_used_in_quest_steps = function(id, step_data)
|
||||
local used = 0
|
||||
for s, d in pairs(step_data or {}) do
|
||||
for loc_id, loc in pairs(d.where or {}) do
|
||||
if(loc and loc.n_id and loc.n_id == id) then
|
||||
used = used + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return used
|
||||
end
|
||||
|
||||
|
||||
-- This order imposed here on the quest steps is the one in which the
|
||||
-- quest steps have to be solved - as far as we can tell (the quest
|
||||
-- may be in the process of beeing created and not logicly complete yet).
|
||||
yl_speak_up.get_sorted_quest_step_list_by_prev_step = function(pname, q_id)
|
||||
if(not(q_id) or not(yl_speak_up.quests[q_id]) or not(yl_speak_up.quests[q_id].step_data)) then
|
||||
return {}
|
||||
end
|
||||
|
||||
-- for now: sort alphabeticly
|
||||
local step_data = yl_speak_up.quests[q_id].step_data
|
||||
local liste = {}
|
||||
for k, v in pairs(step_data) do
|
||||
table.insert(liste, k)
|
||||
end
|
||||
table.sort(liste)
|
||||
return liste
|
||||
end
|
||||
|
||||
--[[ still belongs to the above function
|
||||
-- add back links (or rather: forward links to quest steps that get enabled)
|
||||
local connected = table.copy(step_data)
|
||||
for k, v in pairs(connected) do
|
||||
-- will store the inverse data
|
||||
connected[k].inv_one_step_required = {}
|
||||
connected[k].inv_all_steps_require = {}
|
||||
end
|
||||
for k, v in pairs(connected) do
|
||||
if(k and v and v.one_step_required) then
|
||||
for i, s in ipairs(v.one_step_required) do
|
||||
table.insert(connected[s].inv_one_step_required, k)
|
||||
end
|
||||
end
|
||||
if(k and v and v.all_steps_required) then
|
||||
for i, s in ipairs(v.all_steps_required) do
|
||||
table.insert(connected[s].inv_all_steps_required, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- get those quest steps that are not connected and not used yet
|
||||
local liste = {}
|
||||
for k, v in pairs(connected) do
|
||||
if(k and v
|
||||
and #v.one_step_required == 0 and #v.all_steps_required == 0
|
||||
and #v.inv_one_step_required == 0 and #v.inv_all_steps_required == 0) then
|
||||
table.insert(liste, k)
|
||||
end
|
||||
end
|
||||
-- sort alphabeticly
|
||||
table.sort(liste)
|
||||
-- remove those entries from our connection table (they're not connected anyway);
|
||||
-- we have already added them to the beginning of the list
|
||||
for i, v in ipairs(liste) do
|
||||
connected[v] = nil
|
||||
end
|
||||
|
||||
|
||||
return liste
|
||||
end
|
||||
--]]
|
||||
|
||||
|
||||
-- helper function: find out if a quest step is required by other quest steps
|
||||
yl_speak_up.quest_step_get_required_for_steps = function(step_data)
|
||||
local required_for_steps = {}
|
||||
for s, d in pairs(step_data) do
|
||||
required_for_steps[s] = {}
|
||||
end
|
||||
for s, d in pairs(step_data) do
|
||||
if(s and d and d.one_step_required and type(d.one_step_required) == "table") then
|
||||
for i, s2 in ipairs(d.one_step_required) do
|
||||
table.insert(required_for_steps[s2], s)
|
||||
end
|
||||
end
|
||||
if(s and d and d.all_steps_required and type(d.all_steps_required) == "table") then
|
||||
for i, s2 in ipairs(d.all_steps_required) do
|
||||
table.insert(required_for_steps[s2], s)
|
||||
end
|
||||
end
|
||||
end
|
||||
return required_for_steps
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.input_fs_add_quest_steps = function(player, formname, fields)
|
||||
if(not(fields) or not(player)) then
|
||||
return
|
||||
end
|
||||
local res = yl_speak_up.player_is_working_on_quest(player)
|
||||
if(res.error_msg) then
|
||||
return show_error_fs(player, res.error_msg)
|
||||
end
|
||||
local pname = res.pname
|
||||
local q_id = res.q_id
|
||||
local current_step = res.current_step
|
||||
local step_data = res.step_data
|
||||
local quest = res.quest
|
||||
|
||||
if(fields.back_from_error_msg) then
|
||||
yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
return
|
||||
end
|
||||
local mode = yl_speak_up.speak_to[pname].quest_step_mode
|
||||
if(fields.back) then
|
||||
-- go back to quest overview
|
||||
if(mode and (mode == "manage_quest_npcs" or mode == "manage_quest_locations")) then
|
||||
return yl_speak_up.show_fs(player, "manage_quests")
|
||||
end
|
||||
return yl_speak_up.show_fs(player, "manage_quest_steps", current_step)
|
||||
end
|
||||
|
||||
-- has a quest step be selected?
|
||||
local work_step = nil
|
||||
if(fields.add_element and fields.add_element_name) then
|
||||
if( mode and mode == "manage_quest_npcs") then
|
||||
-- manually entered an NPC ID
|
||||
local npc_id = fields.add_element_name or ""
|
||||
-- just check if it is *potentially* an NPC ID; that way NPC the quest
|
||||
-- creator has no write access to can be added
|
||||
if(string.sub(npc_id, 1, 2) ~= "n_"
|
||||
or not(tonumber(string.sub(npc_id, 3)))) then
|
||||
return show_error_fs(player, "This is not an NPC ID. They have the form n_<id>.")
|
||||
end
|
||||
-- only npcs that are not yet added (and we store IDs without n_ prefix)
|
||||
local id = tonumber(string.sub(npc_id, 3))
|
||||
if(id and table.indexof(res.quest.npcs or {}, id) == -1) then
|
||||
table.insert(yl_speak_up.quests[q_id].npcs, id)
|
||||
yl_speak_up.save_quest(q_id)
|
||||
end
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
elseif(mode and mode == "manage_quest_locations") then
|
||||
-- manually entered a quest location
|
||||
local location_id = fields.add_element_name or ""
|
||||
local d = yl_speak_up.player_vars["$NPC_META_DATA$"][location_id]
|
||||
local error_msg = ""
|
||||
-- the owner is not checked; that way, locations can be added where the
|
||||
-- quest onwer does not (yet) have write access
|
||||
if(string.sub(location_id, 1, 1) ~= "p") then
|
||||
error_msg = "This is not a location ID."
|
||||
elseif(not(d)) then
|
||||
error_msg = "Location not found."
|
||||
end
|
||||
if(error_msg ~= "") then
|
||||
return show_error_fs(player, error_msg)
|
||||
end
|
||||
-- only locations that are not yet added
|
||||
if(table.indexof(res.quest.locations or {}, location_id) == -1) then
|
||||
table.insert(yl_speak_up.quests[q_id].locations, location_id)
|
||||
yl_speak_up.save_quest(q_id)
|
||||
end
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
end
|
||||
|
||||
-- create a new quest step
|
||||
local new_step = fields.add_element_name:trim()
|
||||
-- a new one shall be created
|
||||
local msg = yl_speak_up.quest_step_add_quest_step(pname, q_id, new_step)
|
||||
if(msg ~= "OK") then
|
||||
return show_error_fs(player, msg)
|
||||
end
|
||||
-- this will also be set if the quest step exists already; this is fine so far
|
||||
work_step = new_step
|
||||
|
||||
elseif(fields.add_from_available
|
||||
and yl_speak_up.speak_to[pname].list_available) then
|
||||
-- selected a quest step from the list of available steps offered
|
||||
local liste = yl_speak_up.speak_to[pname].list_available
|
||||
local selected = minetest.explode_table_event(fields.add_from_available)
|
||||
if(selected and selected.row and selected.row > 1 and selected.row <= #liste + 1) then
|
||||
work_step = liste[selected.row - 1]
|
||||
end
|
||||
|
||||
elseif(fields.add_to_npc_list
|
||||
and yl_speak_up.speak_to[pname].list_available) then
|
||||
-- selected an NPC from the list of available NPC offered
|
||||
local liste = yl_speak_up.speak_to[pname].list_available
|
||||
local selected = minetest.explode_table_event(fields.add_to_npc_list)
|
||||
if(selected and selected.row and selected.row > 1 and selected.row <= #liste + 1) then
|
||||
local npc_id = liste[selected.row - 1]
|
||||
if(table.indexof(res.quest.npcs or {}, npc_id) == -1) then
|
||||
table.insert(yl_speak_up.quests[q_id].npcs, npc_id)
|
||||
yl_speak_up.save_quest(q_id)
|
||||
end
|
||||
end
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
|
||||
elseif(fields.add_to_location_list
|
||||
and yl_speak_up.speak_to[pname].list_available) then
|
||||
-- selected a location from the list of available locations offered
|
||||
local liste = yl_speak_up.speak_to[pname].list_available
|
||||
local selected = minetest.explode_table_event(fields.add_to_location_list)
|
||||
if(selected and selected.row and selected.row > 1 and selected.row <= #liste + 1) then
|
||||
local location_id = liste[selected.row - 1]
|
||||
if(table.indexof(res.quest.locations or {}, location_id) == -1) then
|
||||
table.insert(yl_speak_up.quests[q_id].locations, location_id)
|
||||
yl_speak_up.save_quest(q_id)
|
||||
end
|
||||
end
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
|
||||
elseif(fields.delete_from_one_step_required and current_step and step_data[current_step]) then
|
||||
-- remove a quest step from the list (from one step required)
|
||||
local selected = minetest.explode_table_event(fields.delete_from_one_step_required)
|
||||
local liste = (step_data[current_step].one_step_required or {})
|
||||
if(selected and selected.row and selected.row > 1 and selected.row <= #liste + 1) then
|
||||
table.remove(yl_speak_up.quests[q_id].step_data[current_step].one_step_required, selected.row-1)
|
||||
end
|
||||
yl_speak_up.save_quest(q_id)
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
|
||||
elseif(fields.delete_from_all_steps_required and current_step and step_data[current_step]) then
|
||||
-- remove a quest step from the lists (from all steps required)
|
||||
local selected = minetest.explode_table_event(fields.delete_from_all_steps_required)
|
||||
local liste = (step_data[current_step].all_steps_required or {})
|
||||
if(selected and selected.row and selected.row > 1 and selected.row <= #liste + 1) then
|
||||
table.remove(yl_speak_up.quests[q_id].step_data[current_step].all_steps_required, selected.row-1)
|
||||
end
|
||||
yl_speak_up.save_quest(q_id)
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
|
||||
elseif(fields.delete_from_npc_list) then
|
||||
-- remove an NPC from the list of contributors
|
||||
local selected = minetest.explode_table_event(fields.delete_from_npc_list)
|
||||
local liste = (res.quest.npcs or {})
|
||||
if(selected and selected.row and selected.row > 1 and selected.row <= #liste + 1) then
|
||||
-- *can* it be removed, or is it needed somewhere?
|
||||
local full_id = "n_"..tostring(liste[selected.row - 1])
|
||||
if(yl_speak_up.count_used_in_quest_steps(full_id, step_data) > 0) then
|
||||
return show_error_fs(player, "This NPC is needed for setting a quest step.")
|
||||
end
|
||||
table.remove(yl_speak_up.quests[q_id].npcs, selected.row - 1)
|
||||
end
|
||||
yl_speak_up.save_quest(q_id)
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
|
||||
elseif(fields.delete_from_location_list) then
|
||||
-- remove a location from the list of contributors
|
||||
local selected = minetest.explode_table_event(fields.delete_from_location_list)
|
||||
local liste = (res.quest.locations or {})
|
||||
if(selected and selected.row and selected.row > 1 and selected.row <= #liste + 1) then
|
||||
-- *can* it be removed, or is it needed somewhere?
|
||||
local full_id = liste[selected.row - 1]
|
||||
if(yl_speak_up.count_used_in_quest_steps(full_id, step_data) > 0) then
|
||||
return show_error_fs(player, "This location is needed for setting a quest step.")
|
||||
end
|
||||
table.remove(yl_speak_up.quests[q_id].locations, selected.row - 1)
|
||||
end
|
||||
yl_speak_up.save_quest(q_id)
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
end
|
||||
|
||||
if(not(work_step)) then
|
||||
return -- TODO
|
||||
elseif(mode == "embedded_select") then
|
||||
yl_speak_up.speak_to[pname].quest_step = work_step
|
||||
return yl_speak_up.show_fs(player, "manage_quest_steps", work_step)
|
||||
elseif(mode == "assign_quest_step") then
|
||||
-- TODO: what if there's already a step assigned?
|
||||
-- actually add the step
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
-- this saves the quest data as well if needed
|
||||
local msg = yl_speak_up.quest_step_add_where(pname, q_id, work_step,
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id})
|
||||
if(msg ~= "OK") then
|
||||
return show_error_fs(player, msg)
|
||||
end
|
||||
if(not(n_id)) then
|
||||
return show_error_fs(player, "NPC or location not found.")
|
||||
end
|
||||
-- store the new connection in the NPC file itself (do not load generic dialogs)
|
||||
local dialog = yl_speak_up.load_dialog(n_id, false)
|
||||
if(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id)) then
|
||||
-- ok - the tables exist, so we can store the connection
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_id = quest.var_name
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_step = work_step
|
||||
-- write it back to disc
|
||||
yl_speak_up.save_dialog(n_id, dialog)
|
||||
else
|
||||
return show_error_fs(player, "Failed to save this quest step for this NPC.")
|
||||
end
|
||||
-- the player is working on the NPC - thus, the NPC may be in a modified stage
|
||||
-- that hasn't been written to disc yet, and we need to adjust this stage as well
|
||||
dialog = yl_speak_up.speak_to[pname].dialog
|
||||
if(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id)) then
|
||||
-- ok - the tables exist, so we can store the connection
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_id = quest.var_name
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_step = work_step
|
||||
yl_speak_up.speak_to[pname].dialog = dialog
|
||||
else
|
||||
return show_error_fs(player, "Failed to update NPC.")
|
||||
end
|
||||
-- show the newly created or selected step
|
||||
yl_speak_up.speak_to[pname].quest_step = work_step
|
||||
-- log the change
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"Dialog "..tostring(d_id)..": Option "..tostring(o_id)..
|
||||
" will now set quest step \""..
|
||||
tostring(dialog.n_dialogs[d_id].d_options[o_id].quest_step)..
|
||||
"\" of quest \""..
|
||||
tostring(dialog.n_dialogs[d_id].d_options[o_id].quest_id).."\".")
|
||||
return yl_speak_up.show_fs(player, "manage_quest_steps", work_step)
|
||||
elseif(not(current_step) or not(step_data[current_step])) then
|
||||
return yl_speak_up.show_fs(player, "manage_quests")
|
||||
end
|
||||
|
||||
local required_for_steps = yl_speak_up.quest_step_get_required_for_steps(step_data)
|
||||
|
||||
-- make sure we have a sane data structure
|
||||
for i, s in ipairs({current_step, work_step}) do
|
||||
if(s and yl_speak_up.quests[q_id].step_data[s]) then
|
||||
if(not(yl_speak_up.quests[q_id].step_data[s].one_step_required)) then
|
||||
yl_speak_up.quests[q_id].step_data[s].one_step_required = {}
|
||||
end
|
||||
if(not(yl_speak_up.quests[q_id].step_data[s].all_steps_required)) then
|
||||
yl_speak_up.quests[q_id].step_data[s].all_steps_required = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
-- actually do the work
|
||||
if(mode == "add_to_one_needed") then
|
||||
table.insert(yl_speak_up.quests[q_id].step_data[current_step].one_step_required, work_step)
|
||||
elseif(mode == "add_to_all_needed") then
|
||||
table.insert(yl_speak_up.quests[q_id].step_data[current_step].all_steps_required, work_step)
|
||||
elseif(mode == "insert_after_prev_step") then
|
||||
-- the work_step requires what the current step used to require
|
||||
if(#step_data[current_step].one_step_required == 1) then
|
||||
-- a clear insert is possible
|
||||
yl_speak_up.quests[q_id].step_data[work_step].one_step_required = {
|
||||
step_data[current_step].one_step_required[1]}
|
||||
yl_speak_up.quests[q_id].step_data[current_step].one_step_required[1] = work_step
|
||||
else
|
||||
-- no useful information on what the new work_step ought to depend on;
|
||||
-- we just insert the new step at the first place
|
||||
table.insert(yl_speak_up.quests[q_id].step_data[current_step].one_step_required,
|
||||
1, work_step)
|
||||
end
|
||||
return yl_speak_up.show_fs(player, "manage_quest_steps", work_step)
|
||||
elseif(mode == "insert_before_next_step") then
|
||||
-- the work_step requires the current_step
|
||||
table.insert(yl_speak_up.quests[q_id].step_data[work_step].one_step_required, 1, current_step)
|
||||
-- the current step has exactly one successor? then we adjust that one
|
||||
if(#required_for_steps[current_step] == 1) then
|
||||
local next_step = required_for_steps[current_step][1]
|
||||
local i = table.indexof(step_data[next_step].one_step_required, current_step)
|
||||
local a = table.indexof(step_data[next_step].all_steps_required, current_step)
|
||||
if(i > -1) then
|
||||
-- is it in one_step_required? -> replace current_step with work_step
|
||||
yl_speak_up.quests[q_id].step_data[next_step].one_step_required[i] = work_step
|
||||
elseif(a > -1) then
|
||||
-- or in all_steps_required? -> replace current_step with work_step
|
||||
yl_speak_up.quests[q_id].step_data[next_step].all_steps_required[i] =work_step
|
||||
end
|
||||
end
|
||||
return yl_speak_up.show_fs(player, "manage_quest_steps", work_step)
|
||||
end
|
||||
yl_speak_up.save_quest(q_id)
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
end
|
||||
|
||||
|
||||
-- small helper function for yl_speak_up.get_fs_add_quest_steps;
|
||||
-- lists all the quest steps found in liste in the order they occour there
|
||||
yl_speak_up.quest_step_list_show_table = function(formspec, table_specs, liste, data, required_for_steps)
|
||||
table.insert(formspec, "tablecolumns["..
|
||||
"color;text,align=right;".. -- #d.one_step_required
|
||||
"color;text,align=right;".. -- #d.all_steps_required
|
||||
"color;text,align=right;".. -- #required_for_steps (quest steps that need this one)
|
||||
"color;text,align=right;".. -- #where (locations/NPC that *set* this quest step)
|
||||
"color;text,align=left".. -- name of quest step
|
||||
"]table[")
|
||||
table.insert(formspec, table_specs)
|
||||
table.insert(formspec,"#FFFFFF,(O),#FFFFFF,(A),#FFFFFF,(U),#FFFFFF,(L),#FFFFFF,Name of step:,")
|
||||
local tmp = {}
|
||||
for i, s in ipairs(liste or {}) do
|
||||
local d = data[s]
|
||||
if(not(d.one_step_required) or type(d.one_step_required) ~= "table") then
|
||||
d.one_step_required = {}
|
||||
end
|
||||
grey_if_zero(tmp, #d.one_step_required)
|
||||
if(not(d.all_steps_required) or type(d.all_steps_required) ~= "table") then
|
||||
d.all_steps_required = {}
|
||||
end
|
||||
grey_if_zero(tmp, #d.all_steps_required)
|
||||
if(not(required_for_steps[s])) then
|
||||
required_for_steps[s] = {}
|
||||
end
|
||||
grey_if_zero(tmp, #required_for_steps[s])
|
||||
|
||||
if(not(d.where) or type(d.where) ~= "table") then
|
||||
d.where = {}
|
||||
end
|
||||
local anz_where = 0
|
||||
for k, v in pairs(d.where) do
|
||||
anz_where = anz_where + 1
|
||||
end
|
||||
grey_if_zero(tmp, anz_where)
|
||||
|
||||
table.insert(tmp, "#AAFFAA")
|
||||
table.insert(tmp, minetest.formspec_escape(s))
|
||||
end
|
||||
table.insert(formspec, table.concat(tmp, ","))
|
||||
table.insert(formspec, ";]")
|
||||
end
|
||||
|
||||
|
||||
-- returns list of NPCs that pname can edit and that are not yet part of quest_npc_list
|
||||
yl_speak_up.quest_get_npc_candidate_list = function(pname, quest_npc_liste)
|
||||
-- build a list of candidates
|
||||
local npc_list = {}
|
||||
for k, v in pairs(yl_speak_up.npc_list) do
|
||||
-- only NPC that are not already added
|
||||
if(table.indexof(quest_npc_liste or {}, k) == -1
|
||||
-- and only those that the player can edit
|
||||
and (v.owner == pname or (v.may_edit and v.may_edit[pname]))) then
|
||||
table.insert(npc_list, k)
|
||||
end
|
||||
end
|
||||
table.sort(npc_list)
|
||||
return npc_list
|
||||
end
|
||||
|
||||
|
||||
-- lists npc that are either already added or could be added
|
||||
-- can also handle locations
|
||||
yl_speak_up.quest_npc_show_table = function(formspec, table_specs, liste, step_data, is_location_list)
|
||||
table.insert(formspec, "tablecolumns["..
|
||||
"color;text,align=right;".. -- used in this many quest steps
|
||||
"color;text,align=left;".. -- n_id (number, for NPC) or p_(-185,3,-146) (for locations)
|
||||
"color;text,align=left;".. -- owner
|
||||
"color;text,align=left".. -- name of NPC
|
||||
"]table[")
|
||||
table.insert(formspec, table_specs)
|
||||
if(is_location_list) then
|
||||
table.insert(formspec,"#FFFFFF,Used:,#FFFFFF,PositionID:,#FFFFFF,Name")
|
||||
else
|
||||
table.insert(formspec,"#FFFFFF,Used:,#FFFFFF,n_id:,#FFFFFF,Name")
|
||||
end
|
||||
table.insert(formspec, minetest.formspec_escape(","))
|
||||
table.insert(formspec, " description:,#FFFFFF,Owner:,")
|
||||
local tmp = {}
|
||||
for i, n_id in ipairs(liste or {}) do
|
||||
local full_id = n_id
|
||||
if(not(is_location_list)) then
|
||||
full_id = "n_"..tostring(n_id)
|
||||
end
|
||||
grey_if_zero(tmp, yl_speak_up.count_used_in_quest_steps(full_id, step_data))
|
||||
-- the n_id of the NPC
|
||||
table.insert(tmp, "#AAFFAA")
|
||||
if(is_location_list) then
|
||||
-- this already encodes the position but contains , and ()
|
||||
table.insert(tmp, minetest.formspec_escape(n_id))
|
||||
else
|
||||
table.insert(tmp, "n_"..minetest.formspec_escape(n_id))
|
||||
end
|
||||
-- get information from the NPC list (see fs_npc_list.lua)
|
||||
local owner = "- ? -"
|
||||
local name = "- ? -"
|
||||
if(yl_speak_up.npc_list[n_id]) then
|
||||
local npc = yl_speak_up.npc_list[n_id]
|
||||
owner = npc.owner
|
||||
name = (npc.name or name)
|
||||
if(npc.desc and npc.desc ~= "") then
|
||||
name = name..', '..(npc.desc or "")
|
||||
end
|
||||
end
|
||||
-- name and description of the NPC
|
||||
table.insert(tmp, "#AAFFAA")
|
||||
table.insert(tmp, minetest.formspec_escape(name))
|
||||
-- owner of the NPC
|
||||
table.insert(tmp, "#AAFFAA")
|
||||
table.insert(tmp, minetest.formspec_escape(owner))
|
||||
end
|
||||
table.insert(formspec, table.concat(tmp, ","))
|
||||
table.insert(formspec, ";]")
|
||||
end
|
||||
|
||||
|
||||
-- returns list of locations that pname can edit and that are not yet part of quest_location_list
|
||||
yl_speak_up.quest_get_location_candidate_list = function(pname, quest_location_liste)
|
||||
-- build a list of candidates of locations
|
||||
local location_list = {}
|
||||
for n_id, v in pairs(yl_speak_up.player_vars["$NPC_META_DATA$"] or {}) do
|
||||
-- TODO: better detection would be helpful
|
||||
if(string.sub(n_id, 1, 1) == "p"
|
||||
-- only locations that are not yet added
|
||||
and table.indexof(quest_location_liste or {}, n_id) == -1
|
||||
-- and only those that the player can edit
|
||||
and (v.owner == pname or (v.may_edit and v.may_edit[pname]))) then
|
||||
table.insert(location_list, n_id)
|
||||
end
|
||||
end
|
||||
table.sort(location_list)
|
||||
return location_list
|
||||
end
|
||||
|
||||
|
||||
-- param is unused
|
||||
yl_speak_up.get_fs_add_quest_steps = function(player, param)
|
||||
local res = yl_speak_up.player_is_working_on_quest(player)
|
||||
if(res.error_msg) then
|
||||
return yl_speak_up.build_fs_quest_edit_error(res.error_msg, "back")
|
||||
end
|
||||
local pname = res.pname
|
||||
local step_data = res.step_data or {}
|
||||
|
||||
|
||||
-- find out if a quest step is required by other quest steps
|
||||
local required_for_steps = yl_speak_up.quest_step_get_required_for_steps(step_data)
|
||||
|
||||
local current_step = nil
|
||||
local this_step_data = nil
|
||||
if(pname and yl_speak_up.speak_to[pname] and yl_speak_up.speak_to[pname].quest_step) then
|
||||
current_step = yl_speak_up.speak_to[pname].quest_step
|
||||
this_step_data = step_data[current_step]
|
||||
end
|
||||
local mode = ""
|
||||
if(param) then
|
||||
mode = param
|
||||
yl_speak_up.speak_to[pname].quest_step_mode = param
|
||||
elseif(pname and yl_speak_up.speak_to[pname] and yl_speak_up.speak_to[pname].quest_step_mode) then
|
||||
mode = yl_speak_up.speak_to[pname].quest_step_mode
|
||||
end
|
||||
|
||||
local add_what = "Add a new quest step named:"
|
||||
if(mode == "manage_quest_npcs") then
|
||||
add_what = "Add the NPC with n_<id>:"
|
||||
elseif(mode == "manage_quest_locations") then
|
||||
add_what = "Add a location by entering its ID directly:"
|
||||
end
|
||||
|
||||
local formspec = {}
|
||||
if(mode and mode == "embedded_select") then
|
||||
table.insert(formspec, "size[30,12]container[6,0;18.5,12]")
|
||||
current_step = nil
|
||||
else
|
||||
table.insert(formspec, "size[18.5,17.3]")
|
||||
end
|
||||
|
||||
-- add back button
|
||||
table.insert(formspec, "button[8,0;2,0.7;back;Back]")
|
||||
-- show which quest we're working at
|
||||
table.insert(formspec, "label[0.2,1.0;Quest ID:]")
|
||||
table.insert(formspec, "label[3.0,1.0;")
|
||||
table.insert(formspec, minetest.formspec_escape(res.q_id))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "label[0.2,1.5;Quest name:]")
|
||||
table.insert(formspec, "label[3.0,1.5;")
|
||||
table.insert(formspec, minetest.formspec_escape(res.quest.name or "- unknown -"))
|
||||
table.insert(formspec, "]")
|
||||
|
||||
-- add new quest step
|
||||
table.insert(formspec, "label[0.2,2.2;")
|
||||
table.insert(formspec, add_what)
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "button[16.1,2.4;1.2,0.7;add_element;Add]")
|
||||
table.insert(formspec, "field[1.0,2.4;15,0.7;add_element_name;;]")
|
||||
|
||||
local y_pos = 3.3
|
||||
if(current_step and mode == "insert_after_prev_step") then
|
||||
local prev_step = "-"
|
||||
if(this_step_data and this_step_data.one_step_required and #this_step_data.one_step_required > 0) then
|
||||
prev_step = this_step_data.one_step_required[1]
|
||||
end
|
||||
table.insert(formspec, "label[0.2,3.3;between the previous step:]")
|
||||
table.insert(formspec, "label[1.0,3.7;")
|
||||
table.insert(formspec, minetest.colorize("#AAFFAA", minetest.formspec_escape(prev_step)))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "label[0.2,4.1;and the currently selected step:]")
|
||||
table.insert(formspec, "label[1.0,4.5;")
|
||||
table.insert(formspec, minetest.colorize("#FFFF00", minetest.formspec_escape(current_step)))
|
||||
table.insert(formspec, "]")
|
||||
y_pos = 5.3
|
||||
elseif(current_step and mode == "insert_before_next_step") then
|
||||
local next_step = "-"
|
||||
if(current_step and required_for_steps[current_step] and #required_for_steps[current_step] > 0) then
|
||||
next_step = required_for_steps[current_step][1]
|
||||
end
|
||||
table.insert(formspec, "label[0.2,3.3;between the currently selected step:]")
|
||||
table.insert(formspec, "label[1.0,3.7;")
|
||||
table.insert(formspec, minetest.colorize("#FFFF00", minetest.formspec_escape(current_step)))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "label[0.2,4.1;and the next step:]")
|
||||
table.insert(formspec, "label[1.0,4.5;")
|
||||
table.insert(formspec, minetest.colorize("#AAFFAA", minetest.formspec_escape(next_step)))
|
||||
table.insert(formspec, "]")
|
||||
y_pos = 5.3
|
||||
elseif(current_step and mode == "add_to_one_needed") then
|
||||
table.insert(formspec, "label[0.2,3.3;as a requirement to the currently selected step:]")
|
||||
table.insert(formspec, "label[1.0,3.7;")
|
||||
table.insert(formspec, minetest.colorize("#FFFF00", minetest.formspec_escape(current_step)))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "label[0.2,4.1;so that "..
|
||||
minetest.colorize("#9999FF", "at least one")..
|
||||
" of these requirements is fulfilled:]")
|
||||
yl_speak_up.quest_step_list_show_table(formspec,
|
||||
"0.2,4.3;17.0,3.0;delete_from_one_step_required;",
|
||||
step_data[current_step].one_step_required,
|
||||
step_data, required_for_steps)
|
||||
table.insert(formspec, "label[0.2,7.5;(Click on an entry to delete it from the list above.)]")
|
||||
y_pos = 8.3
|
||||
elseif(current_step and mode == "add_to_all_needed") then
|
||||
table.insert(formspec, "label[0.2,3.3;as a requirement to the currently selected step:]")
|
||||
table.insert(formspec, "label[1.0,3.7;")
|
||||
table.insert(formspec, minetest.colorize("#FFFF00", minetest.formspec_escape(current_step)))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "label[0.2,4.1;so that "..
|
||||
minetest.colorize("#9999FF", "all")..
|
||||
" of these requirements are fulfilled:]")
|
||||
yl_speak_up.quest_step_list_show_table(formspec,
|
||||
"0.2,4.3;17.0,3.0;delete_from_all_steps_required;",
|
||||
step_data[current_step].all_steps_required,
|
||||
step_data, required_for_steps)
|
||||
table.insert(formspec, "label[0.2,7.5;(Click on an entry to delete it from the list above.)]")
|
||||
y_pos = 8.3
|
||||
-- add a quest step to an NPC or location
|
||||
elseif(mode == "assign_quest_step") then
|
||||
table.insert(formspec, "container[0,3.3;17,4]")
|
||||
-- what are we talking about?
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
-- describe where in the dialog of the NPC or location this quest step shall be set
|
||||
yl_speak_up.quest_step_show_where_set(pname, formspec, "which will be set by ", n_id, d_id, o_id, nil, nil)
|
||||
table.insert(formspec, "container_end[]")
|
||||
y_pos = 7.8
|
||||
|
||||
-- which NPC may contribute to the quest?
|
||||
elseif(mode == "manage_quest_npcs") then
|
||||
table.insert(formspec, "container[0,3.3;18,6]")
|
||||
table.insert(formspec, "label[0.2,0;so that the NPC "..
|
||||
minetest.colorize("#9999FF", "may contribute")..
|
||||
" to the quest like these NPC:]")
|
||||
yl_speak_up.quest_npc_show_table(formspec,
|
||||
"0.2,0.2;17.0,3.0;delete_from_npc_list;",
|
||||
res.quest.npcs or {},
|
||||
step_data, false)
|
||||
table.insert(formspec, "label[0.2,3.4;(Click on an entry to delete it from the list above.)]")
|
||||
local available_npcs = yl_speak_up.quest_get_npc_candidate_list(pname, res.quest.npcs or {})
|
||||
yl_speak_up.speak_to[pname].list_available = available_npcs
|
||||
table.insert(formspec, "label[0.2,4.4;or select an NPC from the list below:]")
|
||||
yl_speak_up.quest_npc_show_table(formspec,
|
||||
"0.2,4.6;17.0,6.0;add_to_npc_list;",
|
||||
available_npcs or {}, step_data, false)
|
||||
table.insert(formspec, "label[0.2,10.8;Used: Shows in how many quest steps this NPC is used.]")
|
||||
table.insert(formspec, "container_end[]")
|
||||
return table.concat(formspec, "")
|
||||
-- which locations may contribute to the quest?
|
||||
elseif(mode == "manage_quest_locations") then
|
||||
table.insert(formspec, "container[0,3.3;18,6]")
|
||||
table.insert(formspec, "label[0.2,0;so that the location "..
|
||||
minetest.colorize("#9999FF", "may contribute")..
|
||||
" to the quest like these locations:]")
|
||||
yl_speak_up.quest_npc_show_table(formspec,
|
||||
"0.2,0.2;17.0,3.0;delete_from_location_list;",
|
||||
res.quest.locations or {},
|
||||
step_data, true)
|
||||
table.insert(formspec, "label[0.2,3.4;(Click on an entry to delete it from the list above.)]")
|
||||
local available_locations = yl_speak_up.quest_get_location_candidate_list(pname, res.quest.locations or {})
|
||||
yl_speak_up.speak_to[pname].list_available = available_locations
|
||||
table.insert(formspec, "label[0.2,4.4;or select a location from the list below:]")
|
||||
yl_speak_up.quest_npc_show_table(formspec,
|
||||
"0.2,4.6;17.0,6.0;add_to_location_list;",
|
||||
available_locations or {}, step_data, true)
|
||||
table.insert(formspec, "label[0.2,10.8;Used: Shows in how many quest steps this location is used.]")
|
||||
table.insert(formspec, "container_end[]")
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
-- some quest steps may not be available/may not make sense
|
||||
local not_available = {}
|
||||
if(current_step and step_data[current_step] and (not(mode) or mode ~= "assign_quest_step")) then
|
||||
-- steps that are already required
|
||||
for i, s in ipairs(step_data[current_step].one_step_required or {}) do
|
||||
not_available[s] = true
|
||||
end
|
||||
for i, s in ipairs(step_data[current_step].all_steps_required or {}) do
|
||||
not_available[s] = true
|
||||
end
|
||||
-- steps that directly require this quest step here
|
||||
for i, s in ipairs(required_for_steps[current_step] or {}) do
|
||||
not_available[s] = true
|
||||
end
|
||||
end
|
||||
if(current_step and (not(mode) or mode ~= "assign_quest_step")) then
|
||||
not_available[current_step] = true
|
||||
end
|
||||
-- build a list of candidates
|
||||
local available_steps = {}
|
||||
for k, v in pairs(step_data) do
|
||||
if(not(not_available[k])) then
|
||||
table.insert(available_steps, k)
|
||||
end
|
||||
end
|
||||
table.sort(available_steps)
|
||||
yl_speak_up.speak_to[pname].list_available = available_steps
|
||||
|
||||
table.insert(formspec, "container[0,")
|
||||
table.insert(formspec, tostring(y_pos))
|
||||
table.insert(formspec, ";30,20]")
|
||||
|
||||
table.insert(formspec, "label[0.2,0;or select an existing quest step from the list below")
|
||||
if(mode and mode == "embedded_select") then
|
||||
table.insert(formspec, minetest.colorize("#9999FF", " to display the step")..":]")
|
||||
else
|
||||
table.insert(formspec, ":]")
|
||||
end
|
||||
yl_speak_up.quest_step_list_show_table(formspec,
|
||||
"0.2,0.2;17,6.0;add_from_available;",
|
||||
available_steps,
|
||||
step_data, required_for_steps)
|
||||
table.insert(formspec, "label[0.2,6.5;Legend: The numbers show the amount of quest steps...\n"..
|
||||
"\t(O) from which (o)ne needs to be achieved for this quest step\n"..
|
||||
"\t(A) that (a)ll need to be achieved for this quest step\n"..
|
||||
"\t(U) that require/(u)se this quest step in some form\n"..
|
||||
"\t(L) Number of locations (npc/places) that "..
|
||||
minetest.colorize("#9999FF", "set").." this quest step]")
|
||||
table.insert(formspec, "container_end[]")
|
||||
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
yl_speak_up.register_fs("add_quest_steps",
|
||||
yl_speak_up.input_fs_add_quest_steps,
|
||||
-- param is unused here
|
||||
yl_speak_up.get_fs_add_quest_steps,
|
||||
-- no special formspec version required
|
||||
nil
|
||||
)
|
|
@ -1,31 +0,0 @@
|
|||
-- override fs/fs_add_trade_simple.lua:
|
||||
-- (this is kept here as it is trade related and does not change the formspec as such)
|
||||
|
||||
local old_input_add_trade_simple = yl_speak_up.input_add_trade_simple
|
||||
yl_speak_up.input_add_trade_simple = function(player, formname, fields, input_to)
|
||||
if(not(player)) then
|
||||
return 0
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
|
||||
input_to = "add_trade_simple"
|
||||
-- are we editing an action of the type trade?
|
||||
if( yl_speak_up.speak_to[pname][ "tmp_action" ]
|
||||
and yl_speak_up.speak_to[pname][ "tmp_action" ].what == 3
|
||||
and yl_speak_up.in_edit_mode(pname)
|
||||
and yl_speak_up.edit_mode[pname] == n_id) then
|
||||
input_to = "edit_actions"
|
||||
end
|
||||
|
||||
return old_input_add_trade_simple(player, formname, fields, input_to)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("add_trade_simple",
|
||||
-- the input function is a new one now
|
||||
yl_speak_up.input_add_trade_simple,
|
||||
-- the get_fs function stays the same
|
||||
yl_speak_up.get_fs_add_trade_simple_wrapper,
|
||||
-- force formspec version 1 (not changed):
|
||||
1
|
||||
)
|
|
@ -1,343 +0,0 @@
|
|||
-- assign a quest step to a dialog option/answe
|
||||
-- This is the formspec where this is handled.
|
||||
|
||||
-- small helper function
|
||||
local show_error_fs = function(player, text)
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:assign_quest_step",
|
||||
formspec = yl_speak_up.build_fs_quest_edit_error(text, "back_from_error_msg")})
|
||||
end
|
||||
|
||||
|
||||
-- small helper function
|
||||
yl_speak_up.get_choose_until_step_list = function(pname, q_id, quest_step)
|
||||
local choose_until_step = {
|
||||
" - the player restarts the quest -",
|
||||
" - this quest step -",
|
||||
" - the quest step immediately following this one -"
|
||||
}
|
||||
local cdata = yl_speak_up.quests[q_id].step_data[quest_step]
|
||||
for step_name, d in pairs(yl_speak_up.quests[q_id].step_data or {}) do
|
||||
if(step_name ~= quest_step
|
||||
and cdata
|
||||
-- exclude steps that quest_step depends on
|
||||
and table.indexof(cdata.one_step_required or {}, step_name) == -1
|
||||
and table.indexof(cdata.all_steps_required or {}, step_name) == -1) then
|
||||
table.insert(choose_until_step, minetest.formspec_escape(step_name))
|
||||
end
|
||||
end
|
||||
return choose_until_step
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.input_fs_assign_quest_step = function(player, formname, fields)
|
||||
if(not(player)) then
|
||||
return ""
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
-- what are we talking about?
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
|
||||
if(not(n_id) or yl_speak_up.edit_mode[pname] ~= n_id) then
|
||||
return
|
||||
end
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
if(not(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id))) then
|
||||
return
|
||||
end
|
||||
|
||||
-- go back to edit options field
|
||||
if((fields and fields.quit)
|
||||
or (fields and fields.back and fields.back ~= "")) then
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id})
|
||||
return
|
||||
elseif(fields and fields.back_from_error_msg) then
|
||||
yl_speak_up.show_fs(player, "assign_quest_step", nil)
|
||||
return
|
||||
-- show manage quests formspec
|
||||
elseif(fields and fields.manage_quests) then
|
||||
-- store information so that the back button can work
|
||||
yl_speak_up.speak_to[pname][ "working_at" ] = "assign_quest_step"
|
||||
yl_speak_up.show_fs(player, "manage_quests", nil)
|
||||
return
|
||||
elseif(fields and fields.show_quest) then
|
||||
local q_id = yl_speak_up.speak_to[pname].q_id
|
||||
local quest_var_name = nil
|
||||
if(q_id and yl_speak_up.quests[q_id]) then
|
||||
quest_var_name = yl_speak_up.strip_pname_from_var(yl_speak_up.quests[q_id].var_name, pname)
|
||||
end
|
||||
yl_speak_up.show_fs(player, "manage_quests", quest_var_name)
|
||||
return
|
||||
elseif(fields and fields.select_quest_id and fields.select_quest_id ~= "") then
|
||||
local parts = string.split(fields.select_quest_id, " ")
|
||||
if(parts and parts[1] and yl_speak_up.quests[parts[1]]) then
|
||||
-- TODO: check if the player has access rights to that quest
|
||||
-- TODO: check if the NPC has been added to that quest
|
||||
yl_speak_up.speak_to[pname].q_id = parts[1]
|
||||
yl_speak_up.show_fs(player, "add_quest_steps", "assign_quest_step")
|
||||
return
|
||||
end
|
||||
elseif(fields and fields.show_step) then
|
||||
yl_speak_up.show_fs(player, "manage_quest_steps", yl_speak_up.speak_to[pname].quest_step)
|
||||
return
|
||||
elseif(fields and fields.change_show_until) then
|
||||
yl_speak_up.show_fs(player, "assign_quest_step", "change_show_until")
|
||||
return
|
||||
elseif(fields and fields.store_show_until and fields.select_show_until) then
|
||||
local res = yl_speak_up.player_is_working_on_quest(player)
|
||||
if(res.error_msg) then
|
||||
return yl_speak_up.build_fs_quest_edit_error(res.error_msg, "back")
|
||||
end
|
||||
local choose_until_step = yl_speak_up.get_choose_until_step_list(
|
||||
res.pname, res.q_id, yl_speak_up.speak_to[pname].quest_step)
|
||||
local index = table.indexof(choose_until_step, fields.select_show_until or "")
|
||||
if(index ~= -1) then
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
if(not(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id))) then
|
||||
return
|
||||
end
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
tostring(d_id).." "..tostring(o_id)..
|
||||
" quest step will be offered until player reached step \""..
|
||||
tostring(fields.select_show_until).."\".")
|
||||
if(fields.select_show_until == " - the player restarts the quest -") then
|
||||
fields.select_show_until = nil
|
||||
elseif(fields.select_show_until == " - this quest step -") then
|
||||
fields.select_show_until = yl_speak_up.speak_to[pname].quest_step
|
||||
elseif(fields.select_show_until == " - the quest step immediately following this one -") then
|
||||
fields.select_show_until = " next_step"
|
||||
end
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_show_until = fields.select_show_until
|
||||
end
|
||||
yl_speak_up.show_fs(player, "assign_quest_step")
|
||||
return
|
||||
elseif(fields.delete_assignment and fields.delete_assignment ~= "") then
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
-- load the dialog (which may be diffrent from what the player is working on)
|
||||
local stored_dialog = yl_speak_up.load_dialog(n_id, false)
|
||||
-- check if the dialog exists
|
||||
if(not(yl_speak_up.check_if_dialog_has_option(stored_dialog, d_id, o_id))) then
|
||||
return show_error_fs(player, "Dialog or option not found.")
|
||||
end
|
||||
local quest_step_name = dialog.n_dialogs[d_id].d_options[o_id].quest_step
|
||||
local var_name = dialog.n_dialogs[d_id].d_options[o_id].quest_id
|
||||
local q_id = yl_speak_up.get_quest_id_by_var_name(var_name, pname)
|
||||
-- we will ignore the return value so that this connection can be deleted even if
|
||||
-- something went wrong (quest deleted, no write access to quest etc.)
|
||||
local msg = yl_speak_up.quest_step_del_where(pname, q_id, quest_step_name,
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id})
|
||||
if(not(n_id)) then
|
||||
return show_error_fs(player, "NPC or location not found.")
|
||||
end
|
||||
-- log the change
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"Dialog "..tostring(d_id)..": Option "..tostring(o_id)..
|
||||
" no longer sets quest step \""..
|
||||
tostring(dialog.n_dialogs[d_id].d_options[o_id].quest_step)..
|
||||
"\" of quest \""..
|
||||
tostring(dialog.n_dialogs[d_id].d_options[o_id].quest_id).."\".")
|
||||
-- we have updated the quest step data - we need to update the NPC as well
|
||||
local dialog = yl_speak_up.load_dialog(n_id, false)
|
||||
if(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id)) then
|
||||
-- ok - the tables exist, so we can delete the connection
|
||||
-- (if it doesn't exist there's no need to change the stored NPC)
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_id = nil
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_step = nil
|
||||
-- write it back to disc
|
||||
yl_speak_up.save_dialog(n_id, dialog)
|
||||
end
|
||||
-- the player is working on the NPC - thus, the NPC may be in a modified stage
|
||||
-- that hasn't been written to disc yet, and we need to adjust this stage as well
|
||||
dialog = yl_speak_up.speak_to[pname].dialog
|
||||
-- delete the connection
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_id = nil
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_step = nil
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id})
|
||||
return
|
||||
elseif(not(fields) or not(fields.save)) then
|
||||
return
|
||||
end
|
||||
-- actually store the data
|
||||
local error_msg = ""
|
||||
-- check if the quest exists
|
||||
local quest_list = yl_speak_up.get_sorted_quest_list(pname)
|
||||
local idx = table.indexof(quest_list, fields.quest_id or "")
|
||||
if(not(fields.quest_id) or fields.quest_id == "" or idx < 1) then
|
||||
error_msg = "Quest not found."
|
||||
elseif(not(fields.quest_step)
|
||||
or string.len(fields.quest_step) < 1
|
||||
or string.len(fields.quest_step) > 80) then
|
||||
error_msg = "The name of the quest step has to be between\n"..
|
||||
"1 and 80 characters long."
|
||||
end
|
||||
if(error_msg ~= "") then
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:assign_quest_step",
|
||||
formspec = "size[9,2]"..
|
||||
"label[0.2,0.5;Error: "..minetest.formspec_escape(error_msg).."]"..
|
||||
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
|
||||
return
|
||||
end
|
||||
-- we identify quests by their var_name - not by their q_id
|
||||
-- (makes it easier to transfer quests from one server to another later)
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_id = yl_speak_up.add_pname_to_var(fields.quest_id, pname)
|
||||
dialog.n_dialogs[d_id].d_options[o_id].quest_step = fields.quest_step
|
||||
if(not(yl_speak_up.npc_was_changed[ n_id ])) then
|
||||
yl_speak_up.npc_was_changed[ n_id ] = {}
|
||||
end
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..d_id..": Option "..tostring(o_id)..
|
||||
" has been set as quest step \""..
|
||||
tostring(fields.quest_step).."\" for quest \""..tostring(fields.quest_id).."\".")
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id})
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_assign_quest_step = function(player, param)
|
||||
if(not(player)) then
|
||||
return ""
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
-- this only works in edit mode
|
||||
if(not(n_id) or yl_speak_up.edit_mode[pname] ~= n_id) then
|
||||
return "size[1,1]label[0,0;You cannot edit this NPC.]"
|
||||
end
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
if(not(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id))) then
|
||||
return "size[4,1]label[0,0;Dialog option does not exist.]"
|
||||
end
|
||||
local d_option = dialog.n_dialogs[d_id].d_options[o_id]
|
||||
local quest_id = d_option.quest_id or ""
|
||||
local quest_step = d_option.quest_step or ""
|
||||
local quest_show_until = d_option.quest_show_until or " - the player restarts the quest -"
|
||||
if(quest_show_until == quest_step) then
|
||||
quest_show_until = " - this quest step -"
|
||||
-- players cannot create quest steps with leading blanks
|
||||
elseif(quest_show_until == " next_step") then
|
||||
quest_show_until = " - the quest step immediately following this one -"
|
||||
end
|
||||
|
||||
-- has a quest been selected?
|
||||
local q_id = yl_speak_up.get_quest_id_by_var_name(quest_id, pname)
|
||||
if(not(q_id)) then
|
||||
local npc_id = tonumber(string.sub(n_id, 3))
|
||||
local quest_list = {}
|
||||
for id, d in pairs(yl_speak_up.quests) do
|
||||
if(table.indexof(d.npcs or {}, npc_id) ~= -1) then
|
||||
table.insert(quest_list, minetest.formspec_escape(
|
||||
tostring(id).." "..tostring(d.name)))
|
||||
end
|
||||
end
|
||||
if(#quest_list < 1) then
|
||||
return "size[14,4]"..
|
||||
"label[4.0,0.5;Using this option/answer shall be a quest step.]"..
|
||||
"label[0.2,1.4;"..
|
||||
"This NPC "..tostring(n_id).." has not been added to a quest yet.\n"..
|
||||
"Please add him to the NPC list of one of your quests first!\n"..
|
||||
"Search the \"Edit\" button for \"NPC that (may) participate:\" "..
|
||||
"while viewing the desired quest.]"..
|
||||
"button[0.2,3.0;3.6,0.8;manage_quests;Manage Quests]"..
|
||||
"button[9.5,3.0;4.0,0.8;back;Back to edit option "..tostring(o_id).."]"
|
||||
end
|
||||
local selected = 1
|
||||
|
||||
-- local quest_list = yl_speak_up.get_sorted_quest_list(pname)
|
||||
-- for i, v in ipairs(quest_list) do
|
||||
-- quest_list[i] = minetest.formspec_escape(v)
|
||||
-- if(quest_id and v == quest_id) then
|
||||
-- selected = i
|
||||
-- end
|
||||
-- end
|
||||
return "size[14,4]"..
|
||||
"label[4.0,0.5;Using this option/answer shall be a quest step.]"..
|
||||
"label[0.2,1.4;Select a quest:]"..
|
||||
"dropdown[4.0,1.0;9.5,0.8;select_quest_id;"..
|
||||
table.concat(quest_list, ',')..";"..
|
||||
tostring(selected)..",]"..
|
||||
"label[0.2,2.1;If you want to use a quest not mentionned here or a new one, "..
|
||||
"click on \"Manage Quests\"\n"..
|
||||
"and search the \"Edit\" button for \"NPC that (may) participate:\".]"..
|
||||
"button[0.2,3.0;3.6,0.8;manage_quests;Manage Quests]"..
|
||||
"button[9.5,3.0;4.0,0.8;back;Back to edit option "..tostring(o_id).."]"
|
||||
end
|
||||
|
||||
-- this is the currently relevant quest
|
||||
yl_speak_up.speak_to[pname].q_id = q_id
|
||||
yl_speak_up.speak_to[pname].quest_step = quest_step
|
||||
local choose_until_step = {}
|
||||
local show_until = ""
|
||||
if(param and param == "change_show_until") then
|
||||
local choose_until_step = yl_speak_up.get_choose_until_step_list(pname, q_id, quest_step)
|
||||
local index = table.indexof(choose_until_step, quest_show_until or "")
|
||||
if(index == -1) then
|
||||
index = 1
|
||||
end
|
||||
show_until = "dropdown[3.0,5.1;10,0.5;select_show_until;"..
|
||||
table.concat(choose_until_step, ",")..";"..tostring(index)..";]"..
|
||||
"button[13.5,4.8;4.3,0.8;store_show_until;Store]"
|
||||
else
|
||||
show_until = "label[3.0,5.4;"..minetest.colorize("#AAFFAA",
|
||||
minetest.formspec_escape(quest_show_until)).."]"..
|
||||
"button[13.5,4.8;4.3,0.8;change_show_until;Edit]"
|
||||
end
|
||||
local formspec = {
|
||||
"size[18,7]"..
|
||||
"label[3.0,0.5;Using this option/answer shall be a quest step.]"..
|
||||
"label[0.2,1.4;Quest ID:]"..
|
||||
"label[0.2,1.9;Quest name:]"..
|
||||
"label[0.2,3.4;quest step:]"..
|
||||
"button[13.5,3.1;4.3,0.8;show_step;Show this quest step]"..
|
||||
"label[0.2,3.9;"..
|
||||
"This quest step will be set for the player after the effects of "..
|
||||
"the dialog option are executed.]"..
|
||||
|
||||
"label[0.2,4.9;"..
|
||||
"This dialog option will be shown until the player has reached the "..
|
||||
"following quest step:]"..
|
||||
"button[0.2,0.2;2.0,0.8;delete_assignment;Delete]"..
|
||||
"tooltip[delete_assignment;"..
|
||||
"Delete the assignment of this quest step to this dialog option.\n"..
|
||||
"Neither the quest step nor the dialog option will be deleted.\n"..
|
||||
"Just their connection. Afterwards, you can assign a new or\n"..
|
||||
"diffrent quest step to the dialog option.]"..
|
||||
"button[13.5,6.0;4.3,0.8;manage_quests;Manage quests]"
|
||||
}
|
||||
table.insert(formspec, "label[3.0,1.4;")
|
||||
table.insert(formspec, minetest.formspec_escape(q_id))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "label[3.0,1.9;")
|
||||
table.insert(formspec, minetest.formspec_escape(yl_speak_up.quests[q_id].name or "- ? -"))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "button[13.5,1.0;4.3,0.8;show_quest;Show this quest ")
|
||||
table.insert(formspec, tostring(q_id))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "label[0.2,2.9;This option here (")
|
||||
table.insert(formspec, tostring(o_id))
|
||||
table.insert(formspec, ") will be available once the player has reached all required ".. "quest steps for the following]")
|
||||
table.insert(formspec, "label[3.0,3.4;")
|
||||
table.insert(formspec, minetest.colorize("#FFFF00", minetest.formspec_escape(quest_step)))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "button[6.0,6.0;6.0,0.8;back;Back to edit option ")
|
||||
table.insert(formspec, tostring(o_id))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, show_until)
|
||||
return table.concat(formspec, " ")
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("assign_quest_step",
|
||||
yl_speak_up.input_fs_assign_quest_step,
|
||||
yl_speak_up.get_fs_assign_quest_step,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,54 +0,0 @@
|
|||
-- spimple trading: one item(stack) for another item(stack)
|
||||
-- (in edit_mode it's a bit diffrent)
|
||||
|
||||
|
||||
-- if in edit mode: go back to the edit_options dialog
|
||||
local old_input_do_trade_simple = yl_speak_up.input_do_trade_simple
|
||||
yl_speak_up.input_do_trade_simple = function(player, formname, fields)
|
||||
if(not(player)) then
|
||||
return 0
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
|
||||
-- which trade are we talking about?
|
||||
local trade = yl_speak_up.trade[pname]
|
||||
|
||||
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
-- if in edit mode: go back to the edit options dialog
|
||||
if(fields.back_to_edit_options
|
||||
and n_id and yl_speak_up.in_edit_mode(pname)) then
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local tr = dialog.trades[ trade.trade_id ]
|
||||
if(tr) then
|
||||
-- done trading
|
||||
yl_speak_up.speak_to[pname].target_d_id = nil
|
||||
yl_speak_up.speak_to[pname].trade_id = nil
|
||||
-- go to the edit options dialog
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = tr.d_id, o_id = tr.o_id})
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- can the player edit this trade?
|
||||
if(fields.edit_trade_simple
|
||||
and n_id and yl_speak_up.in_edit_mode(pname)) then
|
||||
-- force edit mode for this trade
|
||||
trade.edit_trade = true
|
||||
yl_speak_up.trade[pname] = trade
|
||||
end
|
||||
|
||||
return old_input_do_trade_simple(player, formname, fields)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("do_trade_simple",
|
||||
-- new version implemented here:
|
||||
yl_speak_up.input_do_trade_simple,
|
||||
-- this is just the old function:
|
||||
yl_speak_up.get_fs_do_trade_simple_wrapper,
|
||||
-- force formspec version 1:
|
||||
1
|
||||
)
|
|
@ -1,133 +0,0 @@
|
|||
-- This file contains what is necessary to add/edit an action.
|
||||
--
|
||||
-- Which diffrent types of actions are available?
|
||||
-- -> The following fields are part of an action:
|
||||
-- a_id the ID/key of the action
|
||||
-- a_type selected from values_what
|
||||
-- a_value used to store the subtype of a_type
|
||||
--
|
||||
-- no action (none): nothing to do.
|
||||
--
|
||||
-- a trade ("trade"):
|
||||
-- a_buy what the NPC sells (itemstack)
|
||||
-- a_pay what the NPC wants as payment (itemstack)
|
||||
--
|
||||
-- giving and taking of items ("npc_gives" and "npc_wants"):
|
||||
-- a_on_failure if the action fails, go to this dialog
|
||||
-- a_value itemstack of the given/wanted item in string form
|
||||
-- a_item_desc the description the NPC shall set for that itemstack
|
||||
-- (so that the player can distinguish it from other
|
||||
-- itemstacks with the same items)
|
||||
-- a_item_quest_id Special ID to make sure that it is really the *right*
|
||||
-- item and not just something the player faked with an
|
||||
-- engraving table or something similar
|
||||
--
|
||||
-- the player has to enter text ("text_input"):
|
||||
-- a_value the expected answer the player has to enter
|
||||
-- a_question the question the NPC shall ask the player (so that the
|
||||
-- player can know which answer is expected here)
|
||||
--
|
||||
-- Show something custom (has to be provided by the server). (=call a function) ("evaluate"):
|
||||
-- a_value the name of the function that is to be called
|
||||
-- a_param1 the first paramter (optional; depends on function)
|
||||
-- ..
|
||||
-- a_param9 the 9th parameter (optional; depends on function)
|
||||
--
|
||||
-- a general, more complex formspec-basted puzzle ("puzzle"): not supported
|
||||
-- (custom may be more helpful)
|
||||
--
|
||||
--
|
||||
-- Note: Trades are not stored as actions - they are stored in
|
||||
-- dialog.trades[ trade_id ] with <trade_id> == "<d_id> <o_id>"
|
||||
--
|
||||
|
||||
-- some helper lists for creating the formspecs and evaulating
|
||||
-- the player's answers:
|
||||
|
||||
-- general direction of what could make up an action
|
||||
local check_what = {
|
||||
"- please select -",
|
||||
"No action (default).", -- 2
|
||||
"Normal trade - one item(stack) for another item(stack).", -- 3
|
||||
"The NPC gives something to the player (i.e. a quest item).", -- 4
|
||||
"The player is expected to give something to the NPC (i.e. a quest item).", -- 5
|
||||
"The player has to manually enter a password or passphrase or some other text.", -- 6
|
||||
"Show something custom (has to be provided by the server).",
|
||||
-- "The player has to move virtual items in a virtual inventory to the right position.", -- 8
|
||||
}
|
||||
|
||||
-- how to store these as a_type in the action:
|
||||
local values_what = {"", "none", "trade", "npc_gives", "npc_wants", "text_input", "evaluate", "puzzle"}
|
||||
|
||||
|
||||
-- returns a human-readable text as description of the action
|
||||
-- (as shown in the edit options dialog and in the edit effect formspec)
|
||||
yl_speak_up.show_action = function(a)
|
||||
if(not(a.a_type) or a.a_type == "" or a.a_type == "none") then
|
||||
return "(nothing): Nothing to do. No action."
|
||||
elseif(a.a_type == "trade") then
|
||||
return "NPC sells \""..table.concat(a.a_buy, ";").."\" for \""..
|
||||
table.concat(a.a_pay, ";").."\"."
|
||||
elseif(a.a_type == "npc_gives") then
|
||||
return "The NPC gives \""..tostring(a.a_item_desc or "- default description -")..
|
||||
"\" (\""..tostring(a.a_value or "- ? -").."\") "..
|
||||
"with ID \""..tostring(a.a_item_quest_id or "- no special ID -").."\"."
|
||||
elseif(a.a_type == "npc_wants") then
|
||||
return "The NPC wants \""..tostring(a.a_item_desc or "- default description -")..
|
||||
"\" (\""..tostring(a.a_value or "- ? -").."\") "..
|
||||
"with ID \""..tostring(a.a_item_quest_id or "- no special ID -").."\"."
|
||||
elseif(a.a_type == "text_input") then
|
||||
return "Q: \""..tostring(a.a_question).."\" A:\""..tostring(a.a_value).."\"."
|
||||
elseif(a.a_type == "evaluate") then
|
||||
local str = ""
|
||||
for i = 1, 9 do
|
||||
str = str..tostring(a["a_param"..tostring(i)])
|
||||
if(i < 9) then
|
||||
str = str..","
|
||||
end
|
||||
end
|
||||
return "FUNCTION["..tostring(a.a_value).."]("..str..")"
|
||||
-- puzzle is unused; better do that via custom
|
||||
-- elseif(a.a_type == "puzzle") then
|
||||
-- return "puzzle:"
|
||||
end
|
||||
-- fallback
|
||||
return tostring(a.a_value)
|
||||
end
|
||||
|
||||
-- these are only wrapper functions for those in fs_edit_general.lua
|
||||
|
||||
yl_speak_up.input_edit_actions = function(player, formname, fields)
|
||||
return yl_speak_up.handle_input_fs_edit_option_related(player, formname, fields,
|
||||
"a_", "actions", yl_speak_up.max_actions,
|
||||
"(A)ctions", "tmp_action",
|
||||
nil, -- unused - no block operations
|
||||
values_what, {}, {}, {}, {},
|
||||
check_what, {}, {}, {}, {},
|
||||
nil, -- no variables
|
||||
"edit_actions"
|
||||
)
|
||||
end
|
||||
|
||||
yl_speak_up.get_fs_edit_actions = function(player, table_click_result)
|
||||
return yl_speak_up.build_fs_edit_option_related(player, table_click_result,
|
||||
"a_", "actions", yl_speak_up.max_actions,
|
||||
"(A)ctions", "tmp_action",
|
||||
"What do you want to happen in this (A)ction?",
|
||||
values_what, {}, {}, {}, {},
|
||||
check_what, {}, {}, {}, {},
|
||||
nil, -- no variables
|
||||
yl_speak_up.show_action,
|
||||
"table_of_elements",
|
||||
nil, nil, nil, -- no variable handling here
|
||||
nil -- nothing block-related to do here
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("edit_actions",
|
||||
yl_speak_up.input_edit_actions,
|
||||
yl_speak_up.get_fs_edit_actions,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,352 +0,0 @@
|
|||
-- This file contains what is necessary to add/edit an effect.
|
||||
--
|
||||
-- Which diffrent types of effects are available?
|
||||
-- -> The following fields are part of an effect/result:
|
||||
-- r_id the ID/key of the effect/result
|
||||
-- r_type selected from values_what; the staffs allow to use other
|
||||
-- types like "function" or "give_item" etc. - but that is not
|
||||
-- supported here (cannot be edited or created; only be shown)
|
||||
-- r_value used to store the subtype of r_type
|
||||
--
|
||||
-- a state/variable ("state"):
|
||||
-- r_variable name of a variable the player has *write* access to;
|
||||
-- dropdown list with allowed options
|
||||
-- r_operator selected from values_operator
|
||||
-- r_var_cmp_value can be set freely by the player (the variable will be
|
||||
-- set to this value)
|
||||
--
|
||||
-- the value of a property of the NPC (for generic NPC) ("property"):
|
||||
-- r_value name of the property that is to be changed
|
||||
-- r_operator how shall the property be changed?
|
||||
-- r_var_cmp_value the new value (or increment/decrement) for this property
|
||||
--
|
||||
-- something that has to be calculated or evaluated (=call a function) ("evaluate"):
|
||||
-- r_value the name of the function that is to be called
|
||||
-- r_param1 the first paramter (optional; depends on function)
|
||||
-- ..
|
||||
-- r_param9 the 9th parameter (optional; depends on function)
|
||||
--
|
||||
-- a block in the world ("block"):
|
||||
-- r_pos a position in the world; determined by asking the player
|
||||
-- to punch the block
|
||||
-- r_node (follows from r_pos)
|
||||
-- r_param2 (follows from r_pos)
|
||||
--
|
||||
-- place an item into the inventory of a block (i.e. a chest; "put_into_block_inv"):
|
||||
-- r_pos the position of the target block
|
||||
-- r_inv_list_name the inventory list where the item shall be moved to (often "main")
|
||||
-- r_itemstack the itemstack that is to be moved
|
||||
--
|
||||
-- take item out of the inventory of a block (i.e. a chest; "take_from_block_inv");
|
||||
-- same as "put_into_block_inv"
|
||||
--
|
||||
-- accept items the player has given to the NPC ("deal_with_offered_item"):
|
||||
-- r_value subtype; one of yl_speak_up.dropdown_values_deal_with_offered_item
|
||||
--
|
||||
-- a craft receipe ("craft"):
|
||||
-- r_value the expected craft result
|
||||
-- r_craft_grid array containing the stacks in the 9 craft grid fields in string form
|
||||
--
|
||||
-- on_failure ("on_failure"):
|
||||
-- r_value alternate target dialog if the previous *effect* failed
|
||||
--
|
||||
-- chat_all ("chat_all"):
|
||||
-- r_value chat message sent to all players
|
||||
--
|
||||
--
|
||||
-- give item to player ("give_item"): requires yl_speak_up.npc_privs_priv priv
|
||||
-- r_value the itemstack that shall be added to the player's inventory
|
||||
--
|
||||
-- take item from player's inventory ("take_item"): requires yl_speak_up.npc_privs_priv priv
|
||||
-- r_value the itemstack that will be removed from the player's inventory
|
||||
--
|
||||
-- move the player to a position ("move"): requires yl_speak_up.npc_privs_priv priv
|
||||
-- r_value the position where the player shall be moved to
|
||||
--
|
||||
-- execute lua code ("function"): requires npc_master priv
|
||||
-- r_value the lua code that shall be executed
|
||||
--
|
||||
-- Unlike in preconditions, trade (the trade action already happened) and
|
||||
-- inventory actions are not supported as effects.
|
||||
--
|
||||
|
||||
-- some helper lists for creating the formspecs and evaulating
|
||||
-- the player's answers:
|
||||
|
||||
-- general direction of what could make up an effect
|
||||
local check_what = {
|
||||
"- please select -",
|
||||
"an internal state (i.e. of a quest)", -- 2
|
||||
"the value of a property of the NPC (for generic NPC)", -- property
|
||||
"something that has to be calculated or evaluated (=call a function)", -- evaluate
|
||||
"a block somewhere", -- 3
|
||||
"put item from the NPC's inventory into a chest etc.", -- 4
|
||||
"take item from a chest etc. and put it into the NPC's inventory",
|
||||
-- 5
|
||||
"an item the player offered to the NPC",
|
||||
"NPC crafts something", -- 6
|
||||
"go to other dialog if the previous effect failed", -- 7
|
||||
"send a chat message to all players", -- 8
|
||||
"give item (created out of thin air) to player (requires "..
|
||||
tostring(yl_speak_up.npc_privs_priv).." priv)", -- 9
|
||||
"take item from player and destroy it (requires "..
|
||||
tostring(yl_speak_up.npc_privs_priv).." priv)", -- 10
|
||||
"move the player to a given position (requires "..
|
||||
tostring(yl_speak_up.npc_privs_priv).." priv)", -- 11
|
||||
"execute Lua code (requires npc_master priv)", -- 12
|
||||
}
|
||||
|
||||
-- how to store these as r_type in the precondition:
|
||||
local values_what = {"", "state",
|
||||
"property", "evaluate", "block",
|
||||
-- interact with the inventory of blocks on the map
|
||||
"put_into_block_inv", "take_from_block_inv",
|
||||
-- the player gave an item to the NPC; now deal with it somehow
|
||||
"deal_with_offered_item",
|
||||
-- crafting, handling failure, send chat message to all
|
||||
"craft", "on_failure", "chat_all",
|
||||
-- the following require the yl_speak_up.npc_privs_priv priv:
|
||||
"give_item", "take_item", "move",
|
||||
-- the following require the npc_master priv:
|
||||
"function",
|
||||
}
|
||||
|
||||
-- unlike in the preconditions, the "I cannot punch it" option is
|
||||
-- not offered here - because the player (and later the NPC) needs
|
||||
-- to be able to build at this position
|
||||
local check_block = {
|
||||
"- please select -", -- 1
|
||||
"If there is air: Place a block so that it looks like now.", -- 2
|
||||
"If there is a block: Dig it.", -- 3
|
||||
"Punch the block.", -- 4
|
||||
"Right-click the block.", -- 5
|
||||
}
|
||||
|
||||
-- how to store these as p_value (the actual node data gets stored as p_node, p_param2 and p_pos):
|
||||
local values_block = {"", "place", "dig", "punch", "right-click"}
|
||||
|
||||
-- comparison operators for variables
|
||||
local check_operator = {
|
||||
"- please select -", -- 1
|
||||
"new value:", -- 2
|
||||
"discard/unset/forget", -- 3
|
||||
"current time", -- 4
|
||||
"quest step completed:", -- 5
|
||||
minetest.formspec_escape("max(current, new_value)"), -- 6
|
||||
minetest.formspec_escape("min(current, new_value)"), -- 7
|
||||
"increment by:", -- 8
|
||||
"decrement by:", -- 9
|
||||
}
|
||||
|
||||
-- how to store these as r_value (the actual variable is stored in r_variable, and the value in r_new_value):
|
||||
local values_operator = {"", "set_to", "unset", "set_to_current_time",
|
||||
"quest_step", "maximum", "minimum", "increment", "decrement"}
|
||||
|
||||
|
||||
-- get the list of variables the player has *write* access to
|
||||
yl_speak_up.get_sorted_player_var_list_write_access = function(pname)
|
||||
local var_list = {}
|
||||
-- some values - like hour of day or HP of the player - can be read in
|
||||
-- a precondition but not be modified
|
||||
-- get the list of variables the player can *write*
|
||||
local tmp = yl_speak_up.get_quest_variables_with_write_access(pname)
|
||||
-- sort that list (the dropdown formspec element returns just an index)
|
||||
table.sort(tmp)
|
||||
for i, v in ipairs(tmp) do
|
||||
table.insert(var_list, v)
|
||||
end
|
||||
return var_list
|
||||
end
|
||||
|
||||
|
||||
-- helper function for yl_speak_up.show_effect
|
||||
-- used by "state" and "property"
|
||||
yl_speak_up.show_effect_with_operator = function(r, var_name)
|
||||
if(not(r.r_operator)) then
|
||||
return "Error: Operator not defined."
|
||||
elseif(r.r_operator == "set_to") then
|
||||
return "set "..var_name.." to value \""..
|
||||
tostring(r.r_var_cmp_value).."\""
|
||||
elseif(r.r_operator == "unset") then
|
||||
return "discard "..var_name.." (unset)"
|
||||
elseif(r.r_operator == "set_to_current_time") then
|
||||
return "set "..var_name.." to the current time"
|
||||
elseif(r.r_operator == "quest_step") then
|
||||
return "store that the player has completed quest step \""..
|
||||
tostring(r.r_var_cmp_value).."\""
|
||||
elseif(r.r_operator == "maximum") then
|
||||
return "set "..var_name.." to value \""..
|
||||
tostring(r.r_var_cmp_value).."\" if its current value is larger than that"
|
||||
elseif(r.r_operator == "minimum") then
|
||||
return "set "..var_name.." to value \""..
|
||||
tostring(r.r_var_cmp_value).."\" if its current value is lower than that"
|
||||
elseif(r.r_operator == "increment") then
|
||||
return "increment the value of "..var_name.." by \""..
|
||||
tostring(r.r_var_cmp_value).."\""
|
||||
elseif(r.r_operator == "decrement") then
|
||||
return "decrement the value of "..var_name.." by \""..
|
||||
tostring(r.r_var_cmp_value).."\""
|
||||
else
|
||||
return "ERROR: Wrong operator \""..tostring(r.r_operator).."\" for "..var_name
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- returns a human-readable text as description of the effects
|
||||
-- (as shown in the edit options dialog and in the edit effect formspec)
|
||||
yl_speak_up.show_effect = function(r, pname)
|
||||
if(not(r.r_type) or r.r_type == "") then
|
||||
return "(nothing): Nothing to do. No effect."
|
||||
elseif(r.r_type == "give_item") then
|
||||
return "give_item: Add \""..tostring(r.r_value).."\" to the player's inventory."
|
||||
elseif(r.r_type == "take_item") then
|
||||
return "take_item: Take \""..tostring(r.r_value).."\" from the player's inventory."
|
||||
elseif(r.r_type == "move") then
|
||||
return "move: Move the player to "..tostring(r.r_value).."."
|
||||
elseif(r.r_type == "function") then
|
||||
return "function: execute \""..tostring(r.r_value).."\"."
|
||||
elseif(r.r_type == "trade") then
|
||||
return "trade: obsolete (now defined as an action)"
|
||||
elseif(r.r_type == "dialog") then
|
||||
return "Switch to dialog \""..tostring(r.r_value).."\"."
|
||||
elseif(r.r_type == "state") then
|
||||
local var_name = "VARIABLE[ - ? - ]"
|
||||
if(r.r_variable) then
|
||||
var_name = "VARIABLE[ "..tostring(
|
||||
yl_speak_up.strip_pname_from_var(r.r_variable, pname)).." ]"
|
||||
end
|
||||
return yl_speak_up.show_effect_with_operator(r, var_name)
|
||||
-- the value of a property of the NPC (for generic NPC) ("property"):
|
||||
elseif(r.r_type == "property") then
|
||||
local var_name = "PROPERTY[ "..tostring(r.r_value or "- ? -").." ]"
|
||||
return yl_speak_up.show_effect_with_operator(r, var_name)
|
||||
-- something that has to be calculated or evaluated (=call a function) ("evaluate"):
|
||||
elseif(r.r_type == "evaluate") then
|
||||
local str = ""
|
||||
for i = 1, 9 do
|
||||
str = str..tostring(r["r_param"..tostring(i)])
|
||||
if(i < 9) then
|
||||
str = str..","
|
||||
end
|
||||
end
|
||||
return "FUNCTION["..tostring(r.r_value).."]("..str..")"
|
||||
elseif(r.r_type == "block") then
|
||||
if(not(r.r_pos) or type(r.r_pos) ~= "table"
|
||||
or not(r.r_pos.x) or not(r.r_pos.y) or not(r.r_pos.z)) then
|
||||
return "ERROR: r.r_pos is "..minetest.serialize(r.r_pos)
|
||||
-- we don't check here yet which node is actually there - that will be done upon execution
|
||||
elseif(yl_speak_up.check_blacklisted(r.r_value, r.r_node, r.r_node)) then
|
||||
return "ERROR: Blocks of type \""..tostring(r.r_node).."\" do not allow "..
|
||||
"interaction of type \""..tostring(r.r_value).."\" for NPC."
|
||||
elseif(r.r_value == "place") then
|
||||
return "Place \""..tostring(r.r_node).."\" with param2: "..tostring(r.r_param2)..
|
||||
" at "..minetest.pos_to_string(r.r_pos).."."
|
||||
elseif(r.r_value == "dig") then
|
||||
return "Dig the block at "..minetest.pos_to_string(r.r_pos).."."
|
||||
elseif(r.r_value == "punch") then
|
||||
return "Punch the block at "..minetest.pos_to_string(r.r_pos).."."
|
||||
elseif(r.r_value == "right-click") then
|
||||
return "Right-click the block at "..minetest.pos_to_string(r.r_pos).."."
|
||||
else
|
||||
return "ERROR: Don't know what to do with the block at "..
|
||||
minetest.pos_to_string(r.r_pos)..": \""..tostring(r.r_value).."\"?"
|
||||
end
|
||||
elseif(r.r_type == "craft") then
|
||||
-- this is only shown in the edit options menu and when editing an effect;
|
||||
-- we can afford a bit of calculation here (it's not a precondtion...)
|
||||
if(not(r.r_value) or not(r.r_craft_grid)) then
|
||||
return "ERROR: Crafting not configured correctly."
|
||||
end
|
||||
local craft_str = "Craft \""..tostring(r.r_value).."\" from "..
|
||||
table.concat(r.r_craft_grid, ", ").."."
|
||||
-- check here if the craft receipe is broken
|
||||
local input = {}
|
||||
input.items = {}
|
||||
for i, v in ipairs(r.r_craft_grid) do
|
||||
input.items[ i ] = ItemStack(v or "")
|
||||
end
|
||||
input.method = "normal" -- normal crafting; no cooking or fuel or the like
|
||||
input.width = 3
|
||||
local output, decremented_input = minetest.get_craft_result(input)
|
||||
if(output.item:is_empty()) then
|
||||
return "Error: Recipe changed! No output for "..craft_str
|
||||
end
|
||||
-- the craft receipe may have changed in the meantime and yield a diffrent result
|
||||
local expected_stack = ItemStack(r.r_value)
|
||||
if(output.item:get_name() ~= expected_stack:get_name()
|
||||
or output.item:get_count() ~= expected_stack:get_count()) then
|
||||
return "Error: Amount of output changed! "..craft_str
|
||||
end
|
||||
return craft_str
|
||||
elseif(r.r_type == "on_failure") then
|
||||
return "If the *previous* effect failed, go to dialog \""..tostring(r.r_value).. "\"."
|
||||
elseif(r.r_type == "chat_all") then
|
||||
return "Send chat message: \""..tostring(r.r_value).."\""
|
||||
elseif(r.r_type == "put_into_block_inv") then
|
||||
if(not(r.r_pos) or type(r.r_pos) ~= "table"
|
||||
or not(r.r_pos.x) or not(r.r_pos.y) or not(r.r_pos.z)) then
|
||||
return "ERROR: r.r_pos is "..minetest.serialize(r.r_pos)
|
||||
end
|
||||
return "Put item \""..tostring(r.r_itemstack).."\" from NPC inv into block at "..
|
||||
minetest.pos_to_string(r.r_pos)..
|
||||
" in inventory list \""..tostring(r.r_inv_list_name).."\"."
|
||||
elseif(r.r_type == "take_from_block_inv") then
|
||||
if(not(r.r_pos) or type(r.r_pos) ~= "table"
|
||||
or not(r.r_pos.x) or not(r.r_pos.y) or not(r.r_pos.z)) then
|
||||
return "ERROR: r.r_pos is "..minetest.serialize(r.r_pos)
|
||||
end
|
||||
return "Take item \""..tostring(r.r_itemstack).."\" from block at "..
|
||||
minetest.pos_to_string(r.r_pos)..
|
||||
" out of inventory list \""..tostring(r.r_inv_list_name)..
|
||||
"\" and put it into the NPC's inventory."
|
||||
elseif(r.r_type == "deal_with_offered_item") then
|
||||
local nr = 1
|
||||
if(r.r_value) then
|
||||
nr = math.max(1, table.indexof(yl_speak_up.dropdown_values_deal_with_offered_item,
|
||||
r.r_value))
|
||||
return yl_speak_up.dropdown_list_deal_with_offered_item[ nr ]
|
||||
end
|
||||
return "ERROR: Missing subtype r.r_value: \""..tostring(r.r_value).."\""
|
||||
end
|
||||
-- fallback
|
||||
return tostring(r.r_value)
|
||||
end
|
||||
|
||||
-- these are only wrapper functions for those in fs_edit_general.lua
|
||||
|
||||
yl_speak_up.input_edit_effects = function(player, formname, fields)
|
||||
return yl_speak_up.handle_input_fs_edit_option_related(player, formname, fields,
|
||||
"r_", "o_results", yl_speak_up.max_result_effects,
|
||||
"(Ef)fect", "tmp_result",
|
||||
"Please punch the block you want to manipulate in your effect!",
|
||||
values_what, values_operator, values_block, {}, {},
|
||||
check_what, check_operator, check_block, {}, {},
|
||||
-- player variables with write access
|
||||
yl_speak_up.get_sorted_player_var_list_write_access,
|
||||
"edit_effects"
|
||||
)
|
||||
end
|
||||
|
||||
yl_speak_up.get_fs_edit_effects = function(player, table_click_result)
|
||||
return yl_speak_up.build_fs_edit_option_related(player, table_click_result,
|
||||
"r_", "o_results", yl_speak_up.max_result_effects,
|
||||
"(Ef)fect", "tmp_result",
|
||||
"What do you want to change with this effect?",
|
||||
values_what, values_operator, values_block, {}, {},
|
||||
check_what, check_operator, check_block, {}, {},
|
||||
-- player variables with write access
|
||||
yl_speak_up.get_sorted_player_var_list_write_access,
|
||||
yl_speak_up.show_effect,
|
||||
"table_of_elements",
|
||||
"Change the value of the following variable:", "Set variable to:", "New value:",
|
||||
"The NPC shall do something to the block at the following position:"
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("edit_effects",
|
||||
yl_speak_up.input_edit_effects,
|
||||
yl_speak_up.get_fs_edit_effects,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,853 +0,0 @@
|
|||
|
||||
-- helper function; used by
|
||||
-- * yl_speak_up.get_fs_edit_option_dialog and
|
||||
-- * yl_speak_up.get_fs_edit_trade_limit
|
||||
yl_speak_up.get_list_of_effects_and_target_dialog_and_effect = function(dialog, results, pname, target_dialog, target_effect)
|
||||
local list_of_effects = ""
|
||||
local count_effects = 0
|
||||
if(results) then
|
||||
local sorted_key_list = yl_speak_up.sort_keys(results)
|
||||
for i, k in ipairs(sorted_key_list) do
|
||||
local v = results[ k ]
|
||||
if v.r_type == "dialog" and (dialog.n_dialogs[v.r_value] ~= nil or v.r_value == "d_end" or v.r_value == "d_got_item") then
|
||||
list_of_effects = list_of_effects..
|
||||
minetest.formspec_escape(v.r_id)..",#999999,"..
|
||||
minetest.formspec_escape(v.r_type)..","..
|
||||
minetest.formspec_escape(
|
||||
yl_speak_up.show_effect(v, pname))..","
|
||||
-- there may be more than one in the data structure
|
||||
target_dialog = v.r_value
|
||||
target_effect = v
|
||||
elseif v.r_type ~= "dialog" then
|
||||
list_of_effects = list_of_effects..
|
||||
minetest.formspec_escape(v.r_id)..",#FFFF00,"..
|
||||
minetest.formspec_escape(v.r_type)..","..
|
||||
minetest.formspec_escape(
|
||||
yl_speak_up.show_effect(v, pname))..","
|
||||
end
|
||||
count_effects = count_effects + 1
|
||||
end
|
||||
end
|
||||
if(count_effects < yl_speak_up.max_result_effects) then
|
||||
list_of_effects = list_of_effects..",#00FF00,add,Add a new (Ef)fect"
|
||||
else
|
||||
list_of_effects = list_of_effects..",#AAAAAA,-,"..
|
||||
"Maximum amount of allowed (Ef)fects per option reached!"
|
||||
end
|
||||
return {list = list_of_effects, target_dialog = target_dialog, target_effect = target_effect}
|
||||
end
|
||||
|
||||
|
||||
-- process input from formspec created in get_fs_edit_option_dialog(..)
|
||||
yl_speak_up.input_edit_option_dialog = function(player, formname, fields)
|
||||
if formname ~= "yl_speak_up:edit_option_dialog" then
|
||||
return
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
|
||||
-- Is the player working on this particular npc?
|
||||
local edit_mode = (yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id)
|
||||
if(not(edit_mode)) then
|
||||
return
|
||||
end
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local n_dialog = dialog.n_dialogs[d_id]
|
||||
if(not(n_dialog) or not(n_dialog.d_options)) then
|
||||
return
|
||||
end
|
||||
local d_option = n_dialog.d_options[o_id]
|
||||
if(not(d_option)) then
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.assign_quest_step and fields.assign_quest_step ~= "") then
|
||||
yl_speak_up.show_fs(player, "assign_quest_step",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id})
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.switch_tab and fields.switch_tab == "2") then
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id,
|
||||
caller="show_if_action_failed"})
|
||||
return
|
||||
elseif(fields.switch_tab and fields.switch_tab == "1") then
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id,
|
||||
caller="show_if_action_succeeded"})
|
||||
return
|
||||
elseif(fields.switch_tab and fields.switch_tab == "3") then
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id,
|
||||
caller="show_tab_limit_guessing"})
|
||||
return
|
||||
elseif(fields.switch_tab and fields.switch_tab == "4") then
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id,
|
||||
caller="show_tab_limit_repeating"})
|
||||
return
|
||||
end
|
||||
|
||||
-- this menu is specific to an option for a dialog; if no dialog is selected, we really
|
||||
-- can't know what to do
|
||||
if(not(o_id) and d_id) then
|
||||
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id})
|
||||
elseif(not(d_id)) then
|
||||
return
|
||||
end
|
||||
|
||||
-- backwards compatibility to when this was a hidden field
|
||||
fields.o_id = o_id
|
||||
-- handles changes to o_text_when_prerequisites_met, target dialog, adding of a new dialog
|
||||
local result = yl_speak_up.edit_mode_apply_changes(pname, fields)
|
||||
-- if a new option was added or the target dialog of this one changed, display the right new option
|
||||
if(result and result["show_next_option"] and n_dialog.d_options[result["show_next_option"]]) then
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = result["show_next_option"],
|
||||
caller="show_next_option"})
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.save_option) then
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id, caller="save_option"})
|
||||
return
|
||||
end
|
||||
|
||||
-- want to edit the text that is shown when switching to the next dialog?
|
||||
if(fields.button_edit_action_failed_dialog
|
||||
or fields.button_edit_action_success_dialog
|
||||
or fields.save_dialog_modification
|
||||
or fields.button_edit_limit_action_failed_repeat
|
||||
or fields.button_edit_limit_action_success_repeat
|
||||
or fields.turn_alternate_text_into_new_dialog) then
|
||||
if( yl_speak_up.handle_edit_actions_alternate_text(
|
||||
-- x_id, id_prefix, target_element and tmp_data_cache are nil here
|
||||
player, pname, n_id, d_id, o_id, nil, nil,
|
||||
"edit_option_dialog", nil, fields, nil)) then
|
||||
-- the function above showed a formspec already
|
||||
return
|
||||
else
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id,
|
||||
caller="back_from_edit_dialog_modifications"})
|
||||
return
|
||||
end
|
||||
|
||||
elseif(fields.back_from_edit_dialog_modification) then
|
||||
-- no longer working on an alternate text
|
||||
yl_speak_up.speak_to[pname].edit_alternate_text_for = nil
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_id, caller="back_from_edit_dialog_modifications"})
|
||||
return
|
||||
end
|
||||
|
||||
-- back to the main dialog window?
|
||||
-- (this also happens when the last option was deleted)
|
||||
if(fields.show_current_dialog or fields.quit or fields.button_exit or not(d_option) or fields.del_option) then
|
||||
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id})
|
||||
return
|
||||
end
|
||||
|
||||
-- the player wants to see the previous option/answer
|
||||
if(fields.edit_option_prev) then
|
||||
-- sort all options by o_sort
|
||||
local sorted_list = yl_speak_up.get_sorted_options(n_dialog.d_options, "o_sort")
|
||||
local o_found = o_id
|
||||
for i, o in ipairs(sorted_list) do
|
||||
if(o == o_id and sorted_list[ i-1]) then
|
||||
o_found = sorted_list[ i-1 ]
|
||||
end
|
||||
end
|
||||
-- show that dialog; fallback: show the same (o_id) again
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_found, caller="prev option"})
|
||||
return
|
||||
|
||||
-- the player wants to see the next option/answer
|
||||
elseif(fields.edit_option_next) then
|
||||
-- sort all options by o_sort
|
||||
local sorted_list = yl_speak_up.get_sorted_options(n_dialog.d_options, "o_sort")
|
||||
local o_found = o_id
|
||||
for i, o in ipairs(sorted_list) do
|
||||
if(o == o_id and sorted_list[ i+1 ]) then
|
||||
o_found = sorted_list[ i+1 ]
|
||||
end
|
||||
end
|
||||
-- show that dialog; fallback: show the same (o_id) again
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = n_id, d_id = d_id, o_id = o_found, caller="next option"})
|
||||
return
|
||||
|
||||
-- the player clicked on a precondition
|
||||
elseif(fields.table_of_preconditions) then
|
||||
yl_speak_up.show_fs(player, "edit_preconditions", fields.table_of_preconditions)
|
||||
return
|
||||
|
||||
-- the player clicked on an action
|
||||
elseif(fields.table_of_actions) then
|
||||
yl_speak_up.show_fs(player, "edit_actions", fields.table_of_actions)
|
||||
return
|
||||
|
||||
-- the player clicked on an effect
|
||||
elseif(fields.table_of_effects) then
|
||||
yl_speak_up.show_fs(player, "edit_effects", fields.table_of_effects)
|
||||
return
|
||||
end
|
||||
|
||||
-- if ESC is pressed or anything else unpredicted happens: go back to the main dialog edit window
|
||||
-- reason: don't loose any unsaved changes to the dialog
|
||||
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id})
|
||||
end
|
||||
|
||||
|
||||
-- edit options (not via staff but via the "I am your owner" dialog)
|
||||
yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, caller)
|
||||
-- n_id, d_id and o_id have already been checked when this function is called
|
||||
local pname = player:get_player_name()
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local n_dialog = dialog.n_dialogs[d_id]
|
||||
|
||||
-- currently no trade running (we're editing options)
|
||||
yl_speak_up.trade[pname] = nil
|
||||
yl_speak_up.speak_to[pname].trade_id = nil
|
||||
|
||||
if(not(n_dialog) or not(n_dialog.d_options) or not(n_dialog.d_options[o_id])) then
|
||||
return "size[6,2]"..
|
||||
"label[0.2,0.5;Ups! Option "..minetest.formspec_escape(tostring(o_id))..
|
||||
" does not exist.]"..
|
||||
"button_exit[2,1.5;1,0.9;exit;Exit]"
|
||||
end
|
||||
local d_option = n_dialog.d_options[o_id]
|
||||
|
||||
-- if it is a quest step, then show that; else allow creating a quest step
|
||||
local quest_step_text = "button[15.4,0.1;6.0,0.9;assign_quest_step;Turn this into a quest step]"
|
||||
if( d_option.quest_id and d_option.quest_id ~= ""
|
||||
and d_option.quest_step and d_option.quest_step ~= "") then
|
||||
local q_id = ""
|
||||
local quest_name = "["..tostring(d_option.quest_id).."] - unknown quest -"
|
||||
for q_id, data in pairs(yl_speak_up.quests) do
|
||||
if(data and data.var_name == d_option.quest_id) then
|
||||
quest_name = "["..tostring(q_id)..": "..
|
||||
tostring(yl_speak_up.strip_pname_from_var(data.var_name, pname))..
|
||||
"] "..
|
||||
tostring(data.name)
|
||||
end
|
||||
end
|
||||
quest_step_text = table.concat({"box[4.9,0.0;14.0,1.1;#BB77BB]",
|
||||
"label[0.2,0.3;This is quest step:]",
|
||||
"label[5.0,0.3;",
|
||||
minetest.colorize("#00FFFF",
|
||||
minetest.formspec_escape(d_option.quest_step)),
|
||||
"]",
|
||||
"label[0.2,0.8;of the quest:]",
|
||||
"label[5.0,0.8;",
|
||||
minetest.colorize("#CCCCFF",
|
||||
minetest.formspec_escape(quest_name)),
|
||||
"]",
|
||||
"button[19.4,0.1;2.0,0.9;assign_quest_step;Change]"
|
||||
}, "")
|
||||
end
|
||||
|
||||
|
||||
-- offer the correct preselection for hidden/grey/show text
|
||||
local alternate_answer_option = "3"
|
||||
if(d_option.o_hide_when_prerequisites_not_met == "true") then
|
||||
alternate_answer_option = "1"
|
||||
elseif(d_option.o_grey_when_prerequisites_not_met == "true") then
|
||||
alternate_answer_option = "2"
|
||||
end
|
||||
|
||||
local answer_mode = 0
|
||||
-- shall this option be choosen automaticly?
|
||||
if(d_option.o_autoanswer and d_option.o_autoanswer == 1) then
|
||||
answer_mode = 1
|
||||
-- or randomly?
|
||||
elseif(n_dialog.o_random) then
|
||||
answer_mode = 2
|
||||
end
|
||||
|
||||
-- show an option only once
|
||||
local visit_only_once = 0
|
||||
if(d_option.o_visit_only_once and d_option.o_visit_only_once == 1) then
|
||||
visit_only_once = 1
|
||||
end
|
||||
|
||||
local answer_text =
|
||||
-- answer of the player (the actual option)
|
||||
"container[0.0,8.3]"..
|
||||
"label[0.2,0.0;..the player may answer with this text"..
|
||||
minetest.formspec_escape(" [dialog option \""..tostring(o_id).."\"]:").."]"..
|
||||
"dropdown[13.3,-0.4;2.5,0.7;option_visits;"..
|
||||
"often,*once*;"..tostring(visit_only_once + 1)..";]"..
|
||||
"tooltip[option_visits;\"often\" allows to select this option whenever the\n"..
|
||||
"\tpreconditions are fulfilled.\n"..
|
||||
"\"*once*\" greys out the option after it has been selected\n"..
|
||||
"\tone time successfully.\n"..
|
||||
"Useful for visually marking options as read for the player.\n"..
|
||||
"Talking to the NPC anew resets this option and it can be selected again.]"..
|
||||
"dropdown[16.0,-0.4;5.3,0.7;option_autoanswer;"..
|
||||
"by clicking on it,automaticly,randomly;"..tostring(answer_mode+1)..";]"
|
||||
-- (automaticly *by fulfilling the prerequirements*)
|
||||
if(d_id == "d_got_item" or d_id == "d_trade") then
|
||||
answer_mode = 1
|
||||
d_option.o_autoanswer = 1
|
||||
answer_text =
|
||||
"container[0.0,8.3]"..
|
||||
"label[0.2,0.0;..this option will be selected automaticly.]"
|
||||
end
|
||||
if(answer_mode == 0 and (d_id ~= "d_got_item" and d_id ~= "d_trade")) then
|
||||
answer_text = table.concat({answer_text,
|
||||
"label[1.2,0.8;A:]",
|
||||
"field[1.7,0.3;19.6,0.9;text_option_",
|
||||
minetest.formspec_escape(o_id),
|
||||
";;",
|
||||
minetest.formspec_escape(d_option.o_text_when_prerequisites_met),
|
||||
"]",
|
||||
"tooltip[option_text_met;This is the answer the player may choose if the "..
|
||||
"preconditions are all fulfilled.]",
|
||||
-- dropdown for selecting weather to show the alternate answer or not
|
||||
"label[0.2,1.7;..but if at least one pre(C)ondition is not fulfilled, then...]",
|
||||
"dropdown[12.0,1.3;9.3,0.7;hide_or_grey_or_alternate_answer;",
|
||||
"..hide this answer.,",
|
||||
"..grey out the following answer:,",
|
||||
"..display the following alternate answer:;",
|
||||
alternate_answer_option,
|
||||
";]",
|
||||
-- alternate answer
|
||||
"label[1.2,2.5;A:]",
|
||||
"field[1.7,2.0;19.6,0.9;option_text_not_met;;",
|
||||
minetest.formspec_escape(d_option.o_text_when_prerequisites_not_met),
|
||||
"]",
|
||||
"tooltip[option_text_not_met;This is the answer the player may choose if the "..
|
||||
"preconditions are NOT all fulfilled.]",
|
||||
"container_end[]"
|
||||
}, "")
|
||||
elseif(answer_mode == 1) then
|
||||
answer_text = answer_text..
|
||||
"label[1.2,0.8;This option will not be shown but will be selected automaticly if all "..
|
||||
"prerequirements are fullfilled.]"..
|
||||
"label[1.2,1.4;The remaining options of this dialog will in this case not be evaluated.]"..
|
||||
"label[1.2,2.0;The NPC will proceed as if this option was choosen manually.]"..
|
||||
"label[1.2,2.6;"
|
||||
if(d_id == "d_got_item") then
|
||||
answer_text = answer_text..
|
||||
"Note: This is used here to process items that the player gave to the NPC."
|
||||
elseif(d_id == "d_trade") then
|
||||
answer_text = answer_text..
|
||||
"Note: This is useful for refilling stock by crafting new things when "..
|
||||
"necessary, or for getting\nsupplies from a storage, or for storing "..
|
||||
"traded goods in external storage chests."
|
||||
else
|
||||
answer_text = answer_text..
|
||||
"This is i.e. useful for offering a diffrent start dialog depending on the "..
|
||||
"player's progress in a quest."
|
||||
end
|
||||
answer_text = answer_text .. "]container_end[]"
|
||||
elseif(answer_mode == 2) then
|
||||
answer_text = answer_text..
|
||||
"label[1.2,0.8;One option of the dialog - for example this one - will be selected randomly.]"..
|
||||
"label[1.2,1.4;The other options of this dialog will be set to random as well.]"..
|
||||
"label[1.2,2.0;The NPC will proceed as if this dialog was choosen manually.]"..
|
||||
"label[1.2,2.6;Useful for small talk for generic NPC but usually not for quests.]"..
|
||||
"container_end[]"
|
||||
end
|
||||
|
||||
-- remember which option we are working at (better than a hidden field)
|
||||
yl_speak_up.speak_to[pname].o_id = o_id
|
||||
-- are there any preconditions?
|
||||
local list_of_preconditions = ""
|
||||
local prereq = d_option.o_prerequisites
|
||||
local count_prereq = 0
|
||||
if(prereq) then
|
||||
local sorted_key_list = yl_speak_up.sort_keys(prereq)
|
||||
for i, k in ipairs(sorted_key_list) do
|
||||
local v = prereq[ k ]
|
||||
list_of_preconditions = list_of_preconditions..
|
||||
minetest.formspec_escape(v.p_id)..",#FFFF00,"..
|
||||
minetest.formspec_escape(v.p_type)..","..
|
||||
minetest.formspec_escape(
|
||||
yl_speak_up.show_precondition(v, pname))..","
|
||||
count_prereq = count_prereq + 1
|
||||
end
|
||||
end
|
||||
if(count_prereq < yl_speak_up.max_prerequirements) then
|
||||
list_of_preconditions = list_of_preconditions..",#00FF00,add,Add a new pre(C)ondition"
|
||||
else
|
||||
list_of_preconditions = list_of_preconditions..",#AAAAAA,-,"..
|
||||
"Maximum amount of pre(C)onditions per option reached!"
|
||||
end
|
||||
|
||||
-- build action list the same way as list of preconditions and effects
|
||||
local list_of_actions = ""
|
||||
local actions = d_option.actions
|
||||
local count_actions = 0
|
||||
local action_data = nil
|
||||
-- if autoanswer or random is choosen, then there can be no action
|
||||
if(answer_mode == 1 or answer_mode == 2) then
|
||||
actions = nil
|
||||
count_actions = 0
|
||||
caller = ""
|
||||
end
|
||||
if(actions) then
|
||||
local sorted_key_list = yl_speak_up.sort_keys(actions)
|
||||
for i, k in ipairs(sorted_key_list) do
|
||||
local v = actions[ k ]
|
||||
list_of_actions = list_of_actions..
|
||||
minetest.formspec_escape(v.a_id)..",#FFFF00,"..
|
||||
minetest.formspec_escape(v.a_type)..","..
|
||||
minetest.formspec_escape(
|
||||
yl_speak_up.show_action(v))..","
|
||||
count_actions = count_actions + 1
|
||||
action_data = v
|
||||
end
|
||||
end
|
||||
if(count_actions < yl_speak_up.max_actions) then
|
||||
list_of_actions = list_of_actions..",#00FF00,add,Add a new (A)ction"
|
||||
else
|
||||
list_of_actions = list_of_actions..",#AAAAAA,-,"..
|
||||
"Maximum amount of (A)ctions per option reached!"
|
||||
end
|
||||
|
||||
-- list of (A)ctions (there can only be one per option; i.e. a trade)
|
||||
local action_list_text =
|
||||
"container[0.0,12.0]"..
|
||||
"label[0.2,0.0;When this answer has been selected, start the following (A)ction:]"..
|
||||
"tablecolumns[text;color,span=1;text;text]"
|
||||
if(answer_mode == 1) then
|
||||
action_list_text = action_list_text..
|
||||
"label[1.2,0.6;No actions are executed because this option here is automaticly selected.]"..
|
||||
"container_end[]"
|
||||
elseif(answer_mode == 2) then
|
||||
action_list_text = action_list_text..
|
||||
"label[1.2,0.6;No actions are executed because this option here is selected randomly.]"..
|
||||
"container_end[]"
|
||||
else
|
||||
action_list_text = action_list_text..
|
||||
"table[1.2,0.3;20.2,0.7;table_of_actions;"..
|
||||
list_of_actions..";0]"..
|
||||
"container_end[]"
|
||||
end
|
||||
|
||||
-- find the right target dialog for this option (if it exists)
|
||||
local target_dialog = nil
|
||||
-- which effect holds the information about the target dialog?
|
||||
-- set this to a fallback for yl_speak_up.show_colored_dialog_text
|
||||
local target_effect = {r_id = "-?-", r_type = "dialog"}
|
||||
-- and build the list of effects
|
||||
local results = d_option.o_results
|
||||
-- create a new dialog type option if needed
|
||||
if(not(results) or not(next(results))) then
|
||||
target_dialog = yl_speak_up.prepare_new_dialog_for_option(
|
||||
dialog, pname, n_id, d_id, o_id,
|
||||
yl_speak_up.text_new_dialog_id,
|
||||
results)
|
||||
-- make sure we are up to date (a new option was inserted)
|
||||
results = d_option.o_results
|
||||
end
|
||||
-- constructs the list_of_effects; may also update target_dialog and target_effect
|
||||
local res = yl_speak_up.get_list_of_effects_and_target_dialog_and_effect(dialog, results, pname,
|
||||
target_dialog, target_effect)
|
||||
local list_of_effects = res.list
|
||||
target_dialog = res.target_dialog
|
||||
target_effect = res.target_effect
|
||||
|
||||
-- if no target dialog has been selected: default is to go to the dialog with d_sort 0
|
||||
if(not(target_dialog) or target_dialog == "" or
|
||||
(not(dialog.n_dialogs[target_dialog])
|
||||
and target_dialog ~= "d_end"
|
||||
and target_dialog ~= "d_got_item")) then
|
||||
for d, v in pairs(dialog.n_dialogs) do
|
||||
if(v.d_sort and tonumber(v.d_sort) == 0) then
|
||||
target_dialog = d
|
||||
end
|
||||
end
|
||||
end
|
||||
-- build the list of available dialogs for the dropdown list(s)
|
||||
local dialog_list = yl_speak_up.text_new_dialog_id
|
||||
local dialog_selected = "1"
|
||||
-- if there are dialogs defined
|
||||
if(dialog and dialog.n_dialogs) then
|
||||
-- the first entry will be "New dialog"
|
||||
local n = 1
|
||||
for k, v in pairs(dialog.n_dialogs) do
|
||||
local d_name = (v.d_name or v.d_id or "?")
|
||||
-- build the list of available dialogs for the dropdown list(s)
|
||||
dialog_list = dialog_list..","..minetest.formspec_escape(d_name)
|
||||
-- which one is the current dialog?
|
||||
n = n + 1
|
||||
if(v.d_id == target_dialog) then
|
||||
dialog_selected = tostring(n)
|
||||
end
|
||||
end
|
||||
if(target_dialog == "d_end") then
|
||||
dialog_selected = tostring(n + 1)
|
||||
end
|
||||
end
|
||||
dialog_list = dialog_list..",d_end"
|
||||
if(not(target_dialog)) then
|
||||
target_dialog = "- none -"
|
||||
end
|
||||
|
||||
|
||||
-- can the button "prev(ious)" be shown?
|
||||
local button_prev = ""
|
||||
-- can the button "next" be shown?
|
||||
local button_next = ""
|
||||
-- sort all options by o_sort
|
||||
local sorted_list = yl_speak_up.get_sorted_options(n_dialog.d_options, "o_sort")
|
||||
local o_found = o_id
|
||||
local anz_options = 0
|
||||
for i, o in ipairs(sorted_list) do
|
||||
-- the buttons are inside a container; thus, Y is 0.0
|
||||
if(o == o_id and sorted_list[ i-1 ]) then
|
||||
button_prev = ""..
|
||||
"button[7.9,0.0;2.0,0.9;edit_option_prev;Prev]"..
|
||||
"tooltip[edit_option_prev;Go to previous option/answer "..
|
||||
"(according to o_sort).]"
|
||||
end
|
||||
if(o == o_id and sorted_list[ i+1 ]) then
|
||||
button_next = ""..
|
||||
"button[12.5,0.0;2.0,0.9;edit_option_next;Next]"..
|
||||
"tooltip[edit_option_next;Go to next option/answer "..
|
||||
"(according to o_sort).]"
|
||||
end
|
||||
anz_options = anz_options + 1
|
||||
end
|
||||
|
||||
-- less than yl_speak_up.max_number_of_options_per_dialog options?
|
||||
local button_add = ""..
|
||||
-- the buttons are inside a container; thus, Y is 0.0
|
||||
"button[2.4,0.0;2.0,0.9;add_option;Add]"..
|
||||
"tooltip[add_option;Add a new option/answer to this dialog.]"
|
||||
if(anz_options >= yl_speak_up.max_number_of_options_per_dialog
|
||||
or target_dialog == "d_end") then
|
||||
button_add = ""
|
||||
end
|
||||
|
||||
-- make all following coordinates relative
|
||||
local action_text = "container[0.2,14.0]"..
|
||||
"box[0.25,0.0;21.0,6.7;#555555]"
|
||||
local tab_list = "tabheader[0.2,0.0;switch_tab;"..
|
||||
"If the action was successful:,"..
|
||||
"If the action failed:,"..
|
||||
"Limit guessing:,"..
|
||||
"Limit repeating:"
|
||||
-- show what happens if the action fails
|
||||
if(caller == "show_if_action_failed") then
|
||||
-- allow to switch between successful and failed actions
|
||||
action_text = action_text..tab_list..";2;true;true]"..
|
||||
"label[0.4,0.6;"..
|
||||
"If the player *failed* to complete the above action correctly,]"
|
||||
if(action_data and action_data.a_on_failure
|
||||
and dialog.n_dialogs and dialog.n_dialogs[ action_data.a_on_failure]) then
|
||||
action_text = action_text..
|
||||
-- ..and what the NPC will reply to that answer
|
||||
"tooltip[1.2,3.9;19.6,2.5;This is what the NPC will say next when "..
|
||||
"the player has failed to complete the action.]"..
|
||||
|
||||
"container[0.0,3.2]"..
|
||||
"label[0.4,0.4;..the NPC will react to this failed action with the "..
|
||||
"following dialog \""..tostring(action_data.a_on_failure)..
|
||||
"\""..
|
||||
yl_speak_up.show_colored_dialog_text(
|
||||
dialog,
|
||||
action_data,
|
||||
action_data.a_on_failure,
|
||||
"1.2,0.7;19.6,2.5;d_text_next",
|
||||
"with the *modified* text",
|
||||
":]",
|
||||
"button_edit_action_failed_dialog")..
|
||||
"container_end[]"
|
||||
else
|
||||
action_text = action_text..
|
||||
"label[0.4,3.6;..go back to the initial dialog.]"
|
||||
end
|
||||
-- show time-based restrictions (max guesses per time);
|
||||
-- the values will be saved in function yl_speak_up.edit_mode_apply_changes
|
||||
elseif( caller == "show_tab_limit_guessing") 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)
|
||||
if(not(timer_data)) then
|
||||
timer_data = {}
|
||||
end
|
||||
action_text = table.concat({action_text,
|
||||
tab_list,
|
||||
";3;true;true]",
|
||||
-- allow to switch between successful and failed actions
|
||||
"label[0.4,0.6;",
|
||||
"Apply the following time-based restrictions to limit wild guessing:]",
|
||||
-- timer for failed actions
|
||||
"label[0.4,1.6;The player can make]",
|
||||
"field[4.9,1.0;1.5,0.9;timer_max_attempts_on_failure;;",
|
||||
tostring(timer_data[ "max_attempts" ] or 0),
|
||||
"]",
|
||||
"label[6.7,1.6;attempts to complete this action successfully each]",
|
||||
"field[17.5,1.0;1.5,0.9;timer_max_seconds_on_failure;;",
|
||||
tostring(timer_data[ "duration" ] or 0),
|
||||
"]",
|
||||
"label[19.2,1.6;seconds.]",
|
||||
"label[0.4,2.2;Hint: 3 attempts per 1200 seconds (=20 minutes or one MineTest day)"..
|
||||
" may be good values to\navoid wild guessing while not making the player "..
|
||||
"having to wait too long to try again.]"..
|
||||
"tooltip[timer_max_attempts_on_failure;How many tries shall the player have?"..
|
||||
"\nA value of 0 disables this restriction.]"..
|
||||
"tooltip[timer_max_seconds_on_failure;After which time can the player try again?"..
|
||||
"\nA value of 0 disables this restriction.]"..
|
||||
-- ..and what the NPC will explain in such a case
|
||||
"tooltip[1.2,3.9;19.6,2.5;This is what the NPC will say next when "..
|
||||
"\nthe player has failed to complete the action too"..
|
||||
"\nmany times for the NPC's patience and the player"..
|
||||
"\nhas to wait some time before guessing again.]"..
|
||||
"container[0.0,3.2]"..
|
||||
"label[0.4,0.4;The NPC will explain his unwillingness to accept more "..
|
||||
"guesses ",
|
||||
yl_speak_up.show_colored_dialog_text(
|
||||
dialog,
|
||||
{alternate_text = (timer_data[ "alternate_text" ]
|
||||
or yl_speak_up.standard_text_if_action_failed_too_often)},
|
||||
d_id, -- show the same dialog again
|
||||
"1.2,0.7;19.6,2.5;d_text_next",
|
||||
"with the following text",
|
||||
":]",
|
||||
"button_edit_limit_action_failed_repeat"),
|
||||
"container_end[]"
|
||||
}, "")
|
||||
-- show time-based restrictions (time between repeating this action successfully)
|
||||
elseif( caller == "show_tab_limit_repeating") 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)
|
||||
if(not(timer_data)) then
|
||||
timer_data = {}
|
||||
end
|
||||
action_text = table.concat({action_text,
|
||||
tab_list,
|
||||
";4;true;true]",
|
||||
"label[0.4,0.6;",
|
||||
"Apply the following time-based restrictions to limit too quick repeating:]",
|
||||
-- timer for successful actions
|
||||
"label[0.4,1.6;If the player completed the action successfully, he shall have to"..
|
||||
" wait]",
|
||||
"field[15.0,1.0;1.5,0.9;timer_max_seconds_on_success;;",
|
||||
tostring(timer_data[ "duration" ] or 0),
|
||||
"]",
|
||||
"label[16.7,1.6;seconds until he]",
|
||||
"label[0.4,2.1;can repeat the action. Hint: 1200 seconds (=20 minutes or one ",
|
||||
"MineTest day) may be a good value.]",
|
||||
"tooltip[timer_max_seconds_on_success;",
|
||||
minetest.formspec_escape(
|
||||
"If you hand out a quest item, you may not want the player"..
|
||||
"\nto immediately repeat the action countless times, thus"..
|
||||
"\nemptying the NPC's storage and using the quest item for"..
|
||||
"\nother purposes. On the other hand, quest items may get "..
|
||||
"\nlost, so the player needs a way to repeat each step."..
|
||||
"\n1200 seconds may be a good value here as well."),
|
||||
"]",
|
||||
-- ..and what the NPC will explain in such a case
|
||||
"tooltip[1.2,3.9;19.6,2.5;",
|
||||
minetest.formspec_escape(
|
||||
"This is what the NPC will say next when the player"..
|
||||
"\nwants to repeat the action too soon for the NPC's"..
|
||||
"\ntaste - after all the NPC does not have infinite "..
|
||||
"\ninventory ressources, and the player may abuse the "..
|
||||
"\nquest item for entirely diffrent purposes.."),
|
||||
"]",
|
||||
"container[0.0,3.2]",
|
||||
-- this will lead back to the same dialog
|
||||
"label[0.4,0.4;The NPC will explain his unwillingness to repeat the "..
|
||||
"action so soon ",
|
||||
yl_speak_up.show_colored_dialog_text(
|
||||
dialog,
|
||||
{alternate_text = (timer_data[ "alternate_text" ]
|
||||
or yl_speak_up.standard_text_if_action_repeated_too_soon)},
|
||||
d_id, -- show the same dialog again
|
||||
"1.2,0.7;19.6,2.5;d_text_next",
|
||||
"with the following text",
|
||||
":]",
|
||||
"button_edit_limit_action_success_repeat"),
|
||||
"container_end[]"
|
||||
}, "")
|
||||
-- show what happens if the action was successful
|
||||
else
|
||||
-- no action defined
|
||||
if(count_actions == 0) then
|
||||
-- do not show tabheader
|
||||
action_text = action_text..
|
||||
"label[0.4,0.6;"..
|
||||
"There is no (A)ction defined. Directly apply the following (Ef)fects:]"
|
||||
else
|
||||
-- allow to switch between successful and failed actions
|
||||
action_text = table.concat({action_text,
|
||||
tab_list,
|
||||
";1;true;true]",
|
||||
"label[0.4,0.6;",
|
||||
"If the player completed the above action successfully, "..
|
||||
"apply the following (Ef)fects:]"
|
||||
}, "")
|
||||
end
|
||||
action_text = table.concat({action_text,
|
||||
-- list of effects
|
||||
"tablecolumns[text;color,span=1;text;text]",
|
||||
"table[1.2,0.9;19.6,2.0;table_of_effects;",
|
||||
list_of_effects,
|
||||
";0]",
|
||||
"tooltip[1.2,0.9;19.6,2.0;"..
|
||||
"*All* (Ef)fects are executed after the action (if there is\n"..
|
||||
"one defined in this option) has been completed successfully\n"..
|
||||
"by the player. If there is no action defined, then the\n"..
|
||||
"(Ef)fects will always be executed when this option here is\n"..
|
||||
"selected.\n"..
|
||||
"Please click on an (Ef)fect in order to edit or delete it!]",
|
||||
"container[0.0,3.2]",
|
||||
"label[0.4,0.4;The NPC will react to this answer with dialog:]"
|
||||
}, "")
|
||||
if(d_id == "d_trade") then
|
||||
action_text = action_text..
|
||||
"label[13.5,0.4;..by showing his trade list.]"..
|
||||
"container_end[]"
|
||||
else
|
||||
action_text = table.concat({action_text,
|
||||
-- allow to change the target dialog via a dropdown menu
|
||||
"dropdown[11,0.0;9.8,0.7;d_id_",
|
||||
minetest.formspec_escape(o_id),
|
||||
";",
|
||||
dialog_list,
|
||||
";",
|
||||
dialog_selected,
|
||||
",]",
|
||||
"tooltip[10.2,0.0;3.0,0.7;Select the target dialog with which the NPC shall react "..
|
||||
"to this answer.\nCurrently, dialog \"",
|
||||
minetest.formspec_escape(target_dialog),
|
||||
"\" is beeing displayed.;#FFFFFF;#000000]",
|
||||
-- ..and what the NPC will reply to that answer
|
||||
"tooltip[1.2,0.7;19.6,2.5;This is what the NPC will say next when the player has "..
|
||||
"selected this answer here.]",
|
||||
yl_speak_up.show_colored_dialog_text(
|
||||
dialog,
|
||||
-- this is either the "dialog" effect or an empty fallback
|
||||
target_effect,
|
||||
-- this is the text the NPC will say in reaction to this answer
|
||||
target_dialog,
|
||||
"1.2,0.7;19.6,2.5;d_text",
|
||||
"label[13.5,0.4;with the following *modified* text:]",
|
||||
"",
|
||||
"button_edit_action_success_dialog"),
|
||||
"container_end[]"
|
||||
}, "")
|
||||
end
|
||||
end
|
||||
action_text = action_text.."container_end[]"
|
||||
|
||||
-- build up the formspec
|
||||
local formspec = table.concat({
|
||||
"size[22,22]",
|
||||
"bgcolor[#00000000;false]",
|
||||
-- button back to the current dialog (of which this is an option)
|
||||
"button[16.4,0.2;5.0,0.9;show_current_dialog;Back to dialog ",
|
||||
minetest.formspec_escape(d_id),
|
||||
"]",
|
||||
"tooltip[show_current_dialog;Go back to dialog ",
|
||||
minetest.formspec_escape(d_id),
|
||||
" and continue editing that dialog.]",
|
||||
-- tell the player what this formspec is about
|
||||
"label[6.5,0.4;You are editing dialog option \"",
|
||||
tostring(o_id),
|
||||
"\":]",
|
||||
|
||||
-- the text the NPC says
|
||||
"container[0.0,0.9]",
|
||||
"label[0.2,0.0;NPC says ",
|
||||
minetest.formspec_escape("[dialog \""..tostring(d_id).."\"]:"),
|
||||
"]",
|
||||
yl_speak_up.show_colored_dialog_text(
|
||||
dialog,
|
||||
{r_id = "", r_type = "dialog"},
|
||||
d_id,
|
||||
"1.2,0.3;20.2,2.5;d_text",
|
||||
"", -- no modifications possible at this step
|
||||
"",
|
||||
""), -- no edit button here as this text cannot be changed here
|
||||
"tooltip[1.2,0.3;20.2,3.0;This is what the NPC says to the player.]",
|
||||
"container_end[]",
|
||||
|
||||
"container[0.0,3.9]",
|
||||
quest_step_text,
|
||||
"container_end[]",
|
||||
|
||||
-- list the preconditions
|
||||
"container[0.0,5.4]",
|
||||
"label[0.2,0.0;If all of the following pre(C)onditions are fulfilled:]",
|
||||
"tablecolumns[text;color,span=1;text;text]",
|
||||
"table[1.2,0.3;20.2,2.0;table_of_preconditions;",
|
||||
list_of_preconditions,
|
||||
";0]",
|
||||
"tooltip[1.2,0.3;20.2,2.0;",
|
||||
"*All* pre(C)onditions need to be true in order\n"..
|
||||
"for the option to be offered to the player.\n"..
|
||||
"Please click on a pre(C)ondition in order\n"..
|
||||
"to edit or delete it!]",
|
||||
"container_end[]",
|
||||
|
||||
-- answer of the player (the actual option)
|
||||
answer_text,
|
||||
|
||||
-- list of (A)ctions (there can only be one per option; i.e. a trade)
|
||||
action_list_text,
|
||||
|
||||
-- list effects and target dialog for successful - and target dialog for unsuccessful
|
||||
-- actions (including a toggle button)
|
||||
action_text,
|
||||
|
||||
-- container for the buttons/footer
|
||||
"container[0.0,20.9]",
|
||||
-- button: delete
|
||||
"button[0.2,0.0;2.0,0.9;del_option;Delete]",
|
||||
"tooltip[del_option;Delete this option/answer.]",
|
||||
-- button: add new
|
||||
button_add,
|
||||
-- button: save
|
||||
"button[4.6,0.0;2.0,0.9;save_option;Save]",
|
||||
"tooltip[save_option;Save what you canged (or discard it).]",
|
||||
-- button: prev/next
|
||||
button_prev,
|
||||
button_next,
|
||||
-- button: go back to dialog (repeated from top of the page)
|
||||
"button[15.8,0.0;5.0,0.9;show_current_dialog;Back to dialog ",
|
||||
minetest.formspec_escape(d_id),
|
||||
"]",
|
||||
"tooltip[show_current_dialog;Go back to dialog ",
|
||||
minetest.formspec_escape(d_id),
|
||||
" and continue editing that dialog.]",
|
||||
-- allow to enter o_sort
|
||||
"label[10.1,0.5;Sort:]",
|
||||
"field[11.1,0.0;1.0,0.9;edit_option_o_sort;;",
|
||||
minetest.formspec_escape(d_option.o_sort),
|
||||
"]",
|
||||
"tooltip[edit_option_o_sort;o_sort: The lower the number, the higher up in the "..
|
||||
"list this option goes\nNegative values are ignored;#FFFFFF;#000000]",
|
||||
"container_end[]"
|
||||
}, "")
|
||||
return formspec
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_edit_option_dialog_wrapper = function(player, param)
|
||||
if(not(param)) then
|
||||
param = {}
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
yl_speak_up.speak_to[pname].o_id = param.o_id
|
||||
return yl_speak_up.get_fs_edit_option_dialog(player, param.n_id, param.d_id, param.o_id, param.caller)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("edit_option_dialog",
|
||||
yl_speak_up.input_edit_option_dialog,
|
||||
yl_speak_up.get_fs_edit_option_dialog_wrapper,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,377 +0,0 @@
|
|||
-- This file contains what is necessary to add/edit a precondition.
|
||||
--
|
||||
-- Which diffrent types of preconditions are available?
|
||||
-- -> The following fields are part of a precondition:
|
||||
-- p_id the ID/key of the precondition/prerequirement
|
||||
-- p_type selected from values_what
|
||||
-- p_value used to store the subtype of p_type
|
||||
--
|
||||
-- a state/variable ("state"):
|
||||
-- p_variable name of a variable the player has read access to;
|
||||
-- dropdown list with allowed options
|
||||
-- p_operator selected from values_operator
|
||||
-- p_var_cmp_value can be set freely by the player
|
||||
--
|
||||
-- the value of a property of the NPC (for generic NPC) ("property"):
|
||||
-- p_value name of the property that shall be checked
|
||||
-- p_operator operator for cheking the property against p_expected_val
|
||||
-- p_var_cmp_value the expected value of the property
|
||||
--
|
||||
-- something that has to be calculated or evaluated (=call a function) ("evaluate"):
|
||||
-- p_value the name of the function that is to be called
|
||||
-- p_param1 the first paramter (optional; depends on function)
|
||||
-- ..
|
||||
-- p_param9 the 9th parameter (optional; depends on function)
|
||||
-- p_operator operator for checking the result
|
||||
-- p_var_cmp_value compare the result of the function with this value
|
||||
--
|
||||
-- a block in the world ("block"):
|
||||
-- p_pos a position in the world; determined by asking the player
|
||||
-- to punch the block
|
||||
-- p_node (follows from p_pos)
|
||||
-- p_param2 (follows from p_pos)
|
||||
--
|
||||
-- a trade defined as an action ("trade"): no variables needed (buy and pay stack
|
||||
-- follow from the trade set as action)
|
||||
--
|
||||
-- an inventory: ("player_inv", "npc_inv" or "block_inv")
|
||||
-- p_itemstack an itemstack; needs to be a minetest.registered_item[..];
|
||||
-- size/count is also checked
|
||||
--
|
||||
-- the inventory of a block on the map: ("block_inv", in addition to the ones above)
|
||||
-- p_pos a position in the world; determined by asking the player
|
||||
-- to punch the block
|
||||
-- p_inv_list_name name of the inventory list of the block
|
||||
--
|
||||
-- the player offered/gave the NPC an item: ("player_offered_item"):
|
||||
-- p_value an itemstack; needs to be a minetest.registered_item[..];
|
||||
-- size/count is checked for some subtypes
|
||||
-- p_match_stack_size does the NPC expect exactly one stack size - or is
|
||||
-- more or less etc. also ok?
|
||||
-- p_item_group are items of this group instead of the exact item name
|
||||
-- also acceptable?
|
||||
-- p_item_desc the description of the itemstack (set by another quest NPC
|
||||
-- so that the player can distinguish it from other itemstacks
|
||||
-- with the same item name; see action "npc_gives")
|
||||
-- p_item_quest_id Special ID to make sure that it is really the *right*
|
||||
-- item and not just something the player faked with an
|
||||
-- engraving table or something similar
|
||||
--
|
||||
-- a function ("function"): requires npc_master to create and edit
|
||||
-- p_value the lua code to execute and evaulate
|
||||
--
|
||||
-- depends on another option:
|
||||
-- p_value name of the other option of this dialog that is considered
|
||||
-- p_fulfilled shall option p_value be true or false?
|
||||
--
|
||||
-- the type of the entity of the NPC:
|
||||
-- p_value name of the entity (i.e. npc_talk:talking_npc)
|
||||
|
||||
|
||||
-- some helper lists for creating the formspecs and evaulating
|
||||
-- the player's answers:
|
||||
|
||||
-- general direction of what a prerequirement may be about
|
||||
local check_what = {
|
||||
"- please select -",
|
||||
"an internal state (i.e. of a quest)", -- 2
|
||||
"the value of a property of the NPC (for generic NPC)",
|
||||
"something that has to be calculated or evaluated (=call a function)",
|
||||
"a block somewhere", -- 3
|
||||
"a trade", -- 4
|
||||
"the inventory of the player", -- 5
|
||||
"the inventory of the NPC", -- 6
|
||||
"the inventory of a block somewhere", -- 7
|
||||
"an item the player offered/gave to the NPC", -- 8
|
||||
"execute Lua code (requires npc_master priv)", -- 7 -> 9
|
||||
"The preconditions of another dialog option are fulfilled/not fulfilled.", -- 9 -> 11
|
||||
"nothing - always true (useful for generic dialogs)",
|
||||
"nothing - always false (useful for temporally deactivating an option)",
|
||||
"the type of the entity of the NPC",
|
||||
}
|
||||
|
||||
-- how to store these as p_type in the precondition:
|
||||
local values_what = {"", "state", "property", "evaluate", "block", "trade",
|
||||
"player_inv", "npc_inv", "block_inv",
|
||||
"player_offered_item",
|
||||
-- "function" requires npc_master priv:
|
||||
"function",
|
||||
-- depends on the preconditions of another option
|
||||
"other",
|
||||
"true", "false",
|
||||
"entity_type"}
|
||||
|
||||
-- options for "a trade"
|
||||
local check_trade = {
|
||||
"- please select -",
|
||||
"The NPC has the item(s) he wants to sell in his inventory.", -- 2
|
||||
"The player has the item(s) needed to pay the price.", -- 3
|
||||
"The NPC ran out of stock.", -- 4
|
||||
"The player cannot afford the price.", -- 5
|
||||
}
|
||||
|
||||
-- how to store these as p_value:
|
||||
local values_trade = {"", "npc_can_sell", "player_can_buy", "npc_is_out_of_stock", "player_has_not_enough"}
|
||||
|
||||
-- options for "the inventory of " (either player or NPC; perhaps blocks later on)
|
||||
local check_inv = {
|
||||
"- please select -",
|
||||
"The inventory contains the following item:",
|
||||
"The inventory *does not* contain the following item:",
|
||||
"There is room for the following item in the inventory:",
|
||||
"The inventory is empty.",
|
||||
}
|
||||
|
||||
-- how to store these as p_value (the actual itemstack gets stored as p_itemstack):
|
||||
local values_inv = {"", "inv_contains", "inv_does_not_contain", "has_room_for", "inv_is_empty"}
|
||||
|
||||
local check_block = {
|
||||
"- please select -",
|
||||
"The block is as it is now.",
|
||||
"There shall be air instead of this block.",
|
||||
"The block is diffrent from how it is now.",
|
||||
"I can't punch it. The block is as the block *above* the one I punched.",
|
||||
}
|
||||
|
||||
-- how to store these as p_value (the actual node data gets stored as p_node, p_param2 and p_pos):
|
||||
-- Note: "node_is_like" occours twice because it is used to cover blocks that
|
||||
-- cannot be punched as well as normal blocks.
|
||||
local values_block = {"", "node_is_like", "node_is_air", "node_is_diffrent_from", "node_is_like"}
|
||||
|
||||
-- comparison operators for variables
|
||||
local check_operator = {
|
||||
"- please select -", -- 1
|
||||
"== (is equal)", -- 2
|
||||
"~= (is not equal)", -- 3
|
||||
">= (is greater or equal)", -- 4
|
||||
"> (is greater)", -- 5
|
||||
"<= (is smaller or equal)", -- 6
|
||||
"< (is smaller)", -- 7
|
||||
"not (logically invert)", -- 8
|
||||
"is_set (has a value)", -- 9
|
||||
"is_unset (has no value)", -- 10
|
||||
"more than x seconds ago", -- 11
|
||||
"less than x seconds ago", -- 12
|
||||
"has completed quest step", -- 13
|
||||
"quest step *not* completed", -- 14
|
||||
}
|
||||
|
||||
-- how to store these as p_value (the actual variable is stored in p_variable, and the value in p_cmp_value):
|
||||
local values_operator = {"", "==", "~=", ">=", ">", "<=", "<", "not", "is_set", "is_unset",
|
||||
"more_than_x_seconds_ago","less_than_x_seconds_ago",
|
||||
"quest_step_done", "quest_step_not_done"}
|
||||
|
||||
|
||||
|
||||
-- get the list of variables the player has read access to
|
||||
yl_speak_up.get_sorted_player_var_list_read_access = function(pname)
|
||||
local var_list = {}
|
||||
-- copy the values that are server-specific
|
||||
for i, v in ipairs(yl_speak_up.custom_server_functions.precondition_descriptions) do
|
||||
table.insert(var_list, v)
|
||||
end
|
||||
-- get the list of variables the player can read
|
||||
local tmp = yl_speak_up.get_quest_variables_with_read_access(pname)
|
||||
-- sort that list (the dropdown formspec element returns just an index)
|
||||
table.sort(tmp)
|
||||
for i, v in ipairs(tmp) do
|
||||
table.insert(var_list, v)
|
||||
end
|
||||
return var_list
|
||||
end
|
||||
|
||||
|
||||
-- returns a human-readable text as description of the precondition
|
||||
-- (as shown in the edit options dialog and in the edit precondition formspec)
|
||||
yl_speak_up.show_precondition = function(p, pname)
|
||||
if(not(p.p_type) or p.p_type == "") then
|
||||
return "(nothing): Always true."
|
||||
elseif(p.p_type == "item") then
|
||||
return "item: The player has \""..tostring(p.p_value).."\" in his inventory."
|
||||
elseif(p.p_type == "quest") then
|
||||
return "quest: Always false."
|
||||
elseif(p.p_type == "auto") then
|
||||
return "auto: Always true."
|
||||
elseif(p.p_type == "true") then
|
||||
return "true: Always true."
|
||||
elseif(p.p_type == "false") then
|
||||
return "false: Always false."
|
||||
elseif(p.p_type == "function") then
|
||||
return "function: evaluate "..tostring(p.p_value)
|
||||
elseif(p.p_type == "state") then
|
||||
local var_name = "VALUE_OF[ - ? - ]"
|
||||
if(p.p_variable) then
|
||||
var_name = "VALUE_OF[ "..tostring(
|
||||
yl_speak_up.strip_pname_from_var(p.p_variable, pname)).." ]"
|
||||
end
|
||||
if(not(p.p_operator)) then
|
||||
return "Error: Operator not defined."
|
||||
elseif(p.p_operator == "not") then
|
||||
return "not( "..var_name.." )"
|
||||
elseif(p.p_operator == "is_set") then
|
||||
return var_name.." ~= nil (is_set)"
|
||||
elseif(p.p_operator == "is_unset") then
|
||||
return var_name.." == nil (is_unset)"
|
||||
elseif(p.p_operator == "more_than_x_seconds_ago") then
|
||||
return var_name.." was set to current time "..
|
||||
"*more* than "..tostring(p.p_var_cmp_value).." seconds ago"
|
||||
elseif(p.p_operator == "less_than_x_seconds_ago") then
|
||||
return var_name.." was set to current time "..
|
||||
"*less* than "..tostring(p.p_var_cmp_value).." seconds ago"
|
||||
elseif(p.p_operator == "quest_step_done") then
|
||||
return var_name.." shows: player completed quest step \""..
|
||||
tostring(p.p_var_cmp_value).."\" successfully"
|
||||
elseif(p.p_operator == "quest_step_not_done") then
|
||||
return var_name.." shows: player has not yet completed quest step \""..
|
||||
tostring(p.p_var_cmp_value).."\""
|
||||
end
|
||||
if(p.p_var_cmp_value == "") then
|
||||
return var_name.." "..tostring(p.p_operator).." \"\""
|
||||
end
|
||||
return var_name.." "..tostring(p.p_operator).." "..
|
||||
tostring(p.p_var_cmp_value)
|
||||
elseif(p.p_type == "property") then
|
||||
local i = math.max(1,table.indexof(values_operator, p.p_operator))
|
||||
return tostring(p.p_value)..
|
||||
" "..tostring(check_operator[i])..
|
||||
" "..tostring(p.p_var_cmp_value)
|
||||
elseif(p.p_type == "evaluate") then
|
||||
local str = ""
|
||||
for i = 1, 9 do
|
||||
str = str..tostring(p["p_param"..tostring(i)])
|
||||
if(i < 9) then
|
||||
str = str..","
|
||||
end
|
||||
end
|
||||
local i_op = math.max(1,table.indexof(values_operator, p.p_operator))
|
||||
return "FUNCTION["..tostring(p.p_value).."]"..
|
||||
"("..str..") "..tostring(check_operator[i_op])..
|
||||
" "..tostring(p.p_var_cmp_value)
|
||||
elseif(p.p_type == "block") then
|
||||
if(not(p.p_pos) or type(p.p_pos) ~= "table"
|
||||
or not(p.p_pos.x) or not(p.p_pos.y) or not(p.p_pos.z)) then
|
||||
return "ERROR: p.p_pos is "..minetest.serialize(p.p_pos)
|
||||
elseif(p.p_value == "node_is_like") then
|
||||
return "The block at "..minetest.pos_to_string(p.p_pos).." is \""..
|
||||
tostring(p.p_node).."\" with param2: "..tostring(p.p_param2).."."
|
||||
elseif(p.p_value == "node_is_air") then
|
||||
return "There is no block at "..minetest.pos_to_string(p.p_pos).."."
|
||||
elseif(p.p_value == "node_is_diffrent_from") then
|
||||
return "There is another block than \""..tostring(p.p_node).."\" at "..
|
||||
minetest.pos_to_string(p.p_pos)..", or it is at least "..
|
||||
"rotated diffrently (param2 is not "..tostring(p.p_param2)..")."
|
||||
end
|
||||
elseif(p.p_type == "trade") then
|
||||
local nr = table.indexof(values_trade, p.p_value)
|
||||
if(nr and check_trade[ nr ]) then
|
||||
return check_trade[ nr ]
|
||||
end
|
||||
elseif(p.p_type == "player_inv" or p.p_type == "npc_inv" or p.p_type == "block_inv") then
|
||||
local who = "The player"
|
||||
local what = "\""..tostring(p.p_itemstack).."\" in his inventory."
|
||||
if(p.p_type == "npc_inv") then
|
||||
who = "The NPC"
|
||||
elseif(p.p_type == "block_inv") then
|
||||
if(not(p.p_pos) or type(p.p_pos) ~= "table"
|
||||
or not(p.p_pos.x) or not(p.p_pos.y) or not(p.p_pos.z)) then
|
||||
return "ERROR: p.p_pos is "..minetest.serialize(p.p_pos)
|
||||
end
|
||||
who = "The block at "..minetest.pos_to_string(p.p_pos)
|
||||
what = "\""..tostring(p.p_itemstack).."\" in inventory list \""..
|
||||
tostring(p.p_inv_list_name).."\"."
|
||||
end
|
||||
if(p.p_value == "inv_contains") then
|
||||
return who.." has "..what
|
||||
elseif(p.p_value == "inv_does_not_contain") then
|
||||
return who.." does not have "..what
|
||||
elseif(p.p_value == "has_room_for") then
|
||||
return who.." has room for "..what
|
||||
elseif(p.p_value == "inv_is_empty") then
|
||||
if(p.p_type == "block_inv") then
|
||||
return who.." has an empty inventory list \""..
|
||||
tostring(p.p_inv_list_name).."\"."
|
||||
end
|
||||
return who.." has an empty inventory."
|
||||
end
|
||||
elseif(p.p_type == "player_offered_item") then
|
||||
local item = tostring(p.p_value:split(" ")[1])
|
||||
local amount = tostring(p.p_value:split(" ")[2])
|
||||
local match = "any amount"
|
||||
if(p.p_match_stack_size == "any") then
|
||||
match = "any amount"
|
||||
elseif(p.p_match_stack_size == "exactly") then
|
||||
match = "exactly "..tostring(amount)
|
||||
elseif(p.p_match_stack_size == "less"
|
||||
or p.p_match_stack_size == "more") then
|
||||
match = p.p_match_stack_size.." than "..tostring(amount)
|
||||
elseif(p.p_match_stack_size == "another") then
|
||||
match = "another amount than " ..tostring(amount)
|
||||
end
|
||||
if(p.p_item_group and p.p_item_group ~= "") then
|
||||
return "The player offered "..tostring(match).." item(s) of the group \""..
|
||||
tostring(item).."\"."
|
||||
elseif((p.p_item_quest_id and p.p_item_quest_id ~= "")
|
||||
or (p.p_item_desc and p.p_item_desc ~= "")) then
|
||||
return "The player offered "..tostring(match).." of \""..
|
||||
tostring(p.p_item_desc or "- default description -")..
|
||||
"\" (\""..tostring(item or "- ? -").."\") "..
|
||||
"with ID \""..tostring(p.p_item_quest_id or "- no special ID -").."\"."
|
||||
else
|
||||
return "The player offered "..tostring(match).." of \""..tostring(item).."\"."
|
||||
end
|
||||
elseif(p.p_type == "other") then
|
||||
local fulfilled = "fulfilled"
|
||||
if(not(p.p_fulfilled) or p.p_fulfilled ~= "true") then
|
||||
fulfilled = "*not* fulfilled"
|
||||
end
|
||||
return "The preconditions for dialog option \""..tostring(p.p_value).."\" are "..
|
||||
fulfilled.."."
|
||||
elseif(p.p_type == "entity_tpye") then
|
||||
return "the type of the entity of the NPC is: \""..tostring(p.p_value).."\"."
|
||||
end
|
||||
-- fallback
|
||||
return tostring(p.p_value)
|
||||
end
|
||||
|
||||
|
||||
-- these are only wrapper functions for those in fs_edit_general.lua
|
||||
|
||||
yl_speak_up.input_edit_preconditions = function(player, formname, fields)
|
||||
return yl_speak_up.handle_input_fs_edit_option_related(player, formname, fields,
|
||||
"p_", "o_prerequisites", yl_speak_up.max_prerequirements,
|
||||
"pre(C)ondition", "tmp_prereq",
|
||||
"Please punch the block you want to check in your precondition!",
|
||||
values_what, values_operator, values_block, values_trade, values_inv,
|
||||
check_what, check_operator, check_block, check_trade, check_inv,
|
||||
-- player variables with read access
|
||||
yl_speak_up.get_sorted_player_var_list_read_access,
|
||||
"edit_preconditions"
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_edit_preconditions = function(player, table_click_result)
|
||||
return yl_speak_up.build_fs_edit_option_related(player, table_click_result,
|
||||
"p_", "o_prerequisites", yl_speak_up.max_prerequirements,
|
||||
"pre(C)ondition", "tmp_prereq",
|
||||
"What do you want to check in this precondition?",
|
||||
values_what, values_operator, values_block, values_trade, values_inv,
|
||||
check_what, check_operator, check_block, check_trade, check_inv,
|
||||
-- player variables with read access
|
||||
yl_speak_up.get_sorted_player_var_list_read_access,
|
||||
-- show one precondition element
|
||||
yl_speak_up.show_precondition,
|
||||
"table_of_preconditions",
|
||||
"The following expression shall be true:", "Operator:",
|
||||
"Value to compare with (in some cases parameter):",
|
||||
"The following shall be true about the block:"
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("edit_preconditions",
|
||||
yl_speak_up.input_edit_preconditions,
|
||||
yl_speak_up.get_fs_edit_preconditions,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,266 +0,0 @@
|
|||
-- ###
|
||||
-- Fashion
|
||||
-- ###
|
||||
|
||||
-- normal skins for NPC - without wielded items or capes etc.
|
||||
yl_speak_up.input_fashion = function(player, formname, fields)
|
||||
if formname ~= "yl_speak_up:fashion" then
|
||||
return
|
||||
end
|
||||
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
|
||||
-- is the player editing this npc? if not: abort
|
||||
if(not(yl_speak_up.edit_mode[pname])
|
||||
or (yl_speak_up.edit_mode[pname] ~= n_id)) then
|
||||
return ""
|
||||
end
|
||||
|
||||
-- catch ESC as well
|
||||
if(not(fields) or (fields.quit or fields.button_cancel or fields.button_exit)) then
|
||||
yl_speak_up.show_fs(player, "talk", {n_id = yl_speak_up.speak_to[pname].n_id,
|
||||
d_id = yl_speak_up.speak_to[pname].d_id})
|
||||
return
|
||||
end
|
||||
|
||||
-- which texture from the textures list are we talking about?
|
||||
-- this depends on the model!
|
||||
local mesh = yl_speak_up.get_mesh(pname)
|
||||
local texture_index = yl_speak_up.mesh_data[mesh].texture_index
|
||||
if(not(texture_index)) then
|
||||
texture_index = 1
|
||||
end
|
||||
|
||||
-- show extra formspec with wielded item configuration and cape setup
|
||||
if(fields.button_config_wielded_items
|
||||
and yl_speak_up.mesh_data[mesh].can_show_wielded_items) then
|
||||
yl_speak_up.show_fs(player, "fashion_extended")
|
||||
return
|
||||
end
|
||||
|
||||
-- which skins are available? this depends on mob_type
|
||||
local mob_type = yl_speak_up.get_mob_type(pname)
|
||||
local skins = yl_speak_up.mob_skins[mob_type]
|
||||
|
||||
|
||||
local textures = yl_speak_up.speak_to[pname].textures
|
||||
|
||||
-- fallback if something went wrong (i.e. unkown NPC)
|
||||
local skin = (textures[texture_index] or "")
|
||||
if(not(skins)) then
|
||||
skins = {skin}
|
||||
end
|
||||
local skin_index = table.indexof(skins, skin)
|
||||
if(skin_index == -1) then
|
||||
skin_index = 1
|
||||
end
|
||||
local new_skin = skin
|
||||
-- switch back to the stored old skin
|
||||
if(fields.button_old_skin) then
|
||||
local old_texture = yl_speak_up.speak_to[pname].old_texture
|
||||
if(old_texture) then
|
||||
new_skin = old_texture
|
||||
end
|
||||
-- store the new skin
|
||||
elseif(fields.button_store_new_skin) then
|
||||
yl_speak_up.speak_to[pname].old_texture = skin
|
||||
-- show previous skin
|
||||
elseif(fields.button_prev_skin) then
|
||||
if(skin_index > 1) then
|
||||
new_skin = skins[skin_index - 1]
|
||||
else
|
||||
new_skin = skins[#skins]
|
||||
end
|
||||
-- show next skin
|
||||
elseif(fields.button_next_skin) then
|
||||
if(skin_index < #skins) then
|
||||
new_skin = skins[skin_index + 1]
|
||||
else
|
||||
new_skin = skins[1]
|
||||
end
|
||||
-- set directly via list
|
||||
elseif(fields.set_skin_normal) then
|
||||
local new_index = table.indexof(skins, fields.set_skin_normal)
|
||||
if(new_index ~= -1) then
|
||||
new_skin = skins[new_index]
|
||||
end
|
||||
end
|
||||
|
||||
-- if there is a new skin to consider
|
||||
if(textures[texture_index] ~= new_skin) then
|
||||
textures[texture_index] = new_skin
|
||||
yl_speak_up.mesh_update_textures(pname, textures)
|
||||
end
|
||||
if(fields.set_animation
|
||||
and yl_speak_up.mesh_data[mesh]
|
||||
and yl_speak_up.mesh_data[mesh].animation
|
||||
and yl_speak_up.mesh_data[mesh].animation[fields.set_animation]
|
||||
and yl_speak_up.speak_to[pname]
|
||||
and yl_speak_up.speak_to[pname].obj) then
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
obj:set_animation(yl_speak_up.mesh_data[mesh].animation[fields.set_animation])
|
||||
-- store the animation so that it can be restored on reload
|
||||
local entity = obj:get_luaentity()
|
||||
if(entity) then
|
||||
entity.yl_speak_up.animation = yl_speak_up.mesh_data[mesh].animation[fields.set_animation]
|
||||
end
|
||||
end
|
||||
if(fields.button_old_skin or fields.button_store_new_skin) then
|
||||
yl_speak_up.speak_to[pname].old_texture = nil
|
||||
yl_speak_up.show_fs(player, "talk", {n_id = yl_speak_up.speak_to[pname].n_id,
|
||||
d_id = yl_speak_up.speak_to[pname].d_id})
|
||||
return
|
||||
end
|
||||
yl_speak_up.show_fs(player, "fashion")
|
||||
end
|
||||
|
||||
|
||||
-- this only sets the *skin*, depending on the mesh of the NPC;
|
||||
-- capes and wielded items are supported by an extended formspec for those
|
||||
-- NPC that can handle them
|
||||
yl_speak_up.get_fs_fashion = function(pname)
|
||||
-- which texture from the textures list are we talking about?
|
||||
-- this depends on the model!
|
||||
local mesh = yl_speak_up.get_mesh(pname)
|
||||
if(not(mesh) or not(yl_speak_up.mesh_data[mesh])) then
|
||||
return "size[9,2]label[0,0;Error: Mesh data missing.]"
|
||||
end
|
||||
local texture_index = yl_speak_up.mesh_data[mesh].texture_index
|
||||
if(not(texture_index)) then
|
||||
texture_index = 1
|
||||
end
|
||||
|
||||
-- which skins are available? this depends on mob_type
|
||||
local mob_type = yl_speak_up.get_mob_type(pname)
|
||||
local skins = yl_speak_up.mob_skins[mob_type]
|
||||
|
||||
local textures = yl_speak_up.speak_to[pname].textures
|
||||
local skin = ""
|
||||
if(textures and textures[texture_index]) then
|
||||
skin = (textures[texture_index] or "")
|
||||
end
|
||||
-- store the old texture so that we can go back to it
|
||||
local old_texture = yl_speak_up.speak_to[pname].old_texture
|
||||
if(not(old_texture)) then
|
||||
yl_speak_up.speak_to[pname].old_texture = skin
|
||||
old_texture = skin
|
||||
end
|
||||
-- fallback if something went wrong
|
||||
if(not(skins)) then
|
||||
skins = {old_texture}
|
||||
end
|
||||
|
||||
local button_cancel = "Cancel"
|
||||
-- is this player editing this particular NPC? then rename the button
|
||||
if( yl_speak_up.edit_mode[pname]
|
||||
and yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id) then
|
||||
button_cancel = "Back"
|
||||
end
|
||||
|
||||
local skin_list = table.concat(skins, ",")
|
||||
local skin_index = table.indexof(skins, skin)
|
||||
if(skin_index == -1) then
|
||||
skin_index = ""
|
||||
end
|
||||
|
||||
local tmp_textures = textures
|
||||
if(texture_index ~= 1) then
|
||||
tmp_textures = yl_speak_up.textures2skin(textures)
|
||||
end
|
||||
local preview = yl_speak_up.skin_preview_3d(mesh, tmp_textures, "2,1;6,12", "8,1;6,12")
|
||||
-- local preview = yl_speak_up.mesh_data[mesh].skin_preview(skin)
|
||||
|
||||
local formspec = {
|
||||
"container[0.5,4.0]",
|
||||
"dropdown[0.75,14.1;16.25,1.5;set_skin_normal;",
|
||||
skin_list or "",
|
||||
";",
|
||||
tostring(skin_index) or "",
|
||||
"]",
|
||||
"label[0.75,13.6;The name of this skin is:]",
|
||||
|
||||
"button[0.75,0.75;1.2,12;button_prev_skin;<]",
|
||||
"button[15.75,0.75;1.2,12;button_next_skin;>]",
|
||||
"tooltip[button_prev_skin;Select previous skin in list.]",
|
||||
"tooltip[button_next_skin;Select next skin in list.]",
|
||||
"tooltip[set_skin_normal;Select a skin from the list.]",
|
||||
preview,
|
||||
-- we add a special button for setting the skin in the player answer/reply window
|
||||
}
|
||||
if(yl_speak_up.mesh_data[mesh].animation
|
||||
and yl_speak_up.speak_to[pname]
|
||||
and yl_speak_up.speak_to[pname].obj) then
|
||||
local anim_list = {}
|
||||
for k, v in pairs(yl_speak_up.mesh_data[mesh].animation) do
|
||||
table.insert(anim_list, k)
|
||||
end
|
||||
table.sort(anim_list)
|
||||
-- which animation is the NPC currently running?
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
local curr_anim = obj:get_animation(pname)
|
||||
local anim = ""
|
||||
-- does the current animation match any stored one?
|
||||
for k, v in pairs(yl_speak_up.mesh_data[mesh].animation) do
|
||||
if(v.x and v.y and curr_anim and curr_anim.x and curr_anim.y
|
||||
and v.x == curr_anim.x and v.y == curr_anim.y) then
|
||||
anim = k
|
||||
end
|
||||
end
|
||||
local anim_index = table.indexof(anim_list, anim)
|
||||
if(anim_index == -1) then
|
||||
anim_index = "1"
|
||||
end
|
||||
table.insert(formspec, "label[0.75,16.4;Do the following animation:]")
|
||||
table.insert(formspec, "dropdown[0.75,16.9;16.25,1.5;set_animation;")
|
||||
table.insert(formspec, table.concat(anim_list, ','))
|
||||
table.insert(formspec, ";")
|
||||
table.insert(formspec, tostring(anim_index) or "")
|
||||
table.insert(formspec, "]")
|
||||
end
|
||||
table.insert(formspec, "container_end[]")
|
||||
|
||||
local left_window = table.concat(formspec, "")
|
||||
formspec = {}
|
||||
local h = -0.8
|
||||
local button_text = "This shall be your new skin. Wear it proudly!"
|
||||
if(skin == old_texture) then
|
||||
button_text = "This is your old skin. It is fine. Keep it!"
|
||||
end
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"button_store_new_skin",
|
||||
"The NPC will wear the currently selected skin.",
|
||||
button_text,
|
||||
true, nil, nil, nil)
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"button_old_skin",
|
||||
"The NPC will wear the skin he wore before you started changing it.",
|
||||
"On a second throught - Keep your old skin. It was fine.",
|
||||
(skin ~= old_texture), nil, nil, nil)
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"button_config_wielded_items",
|
||||
"What shall the NPC wield, and which cape shall he wear?",
|
||||
"I'll tell you what you shall wield.",
|
||||
(yl_speak_up.mesh_data[mesh].can_show_wielded_items),
|
||||
"You don't know how to show wielded items. Thus, we can't configure them.",
|
||||
nil, nil)
|
||||
return yl_speak_up.show_fs_decorated(pname, true, h,
|
||||
"",
|
||||
left_window,
|
||||
table.concat(formspec, ""),
|
||||
nil,
|
||||
h)
|
||||
end
|
||||
|
||||
yl_speak_up.get_fs_fashion_wrapper = function(player, param)
|
||||
local pname = player:get_player_name()
|
||||
return yl_speak_up.get_fs_fashion(pname)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("fashion",
|
||||
yl_speak_up.input_fashion,
|
||||
yl_speak_up.get_fs_fashion_wrapper,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,205 +0,0 @@
|
|||
|
||||
-- inspired/derived from the wieldview mod in 3darmor
|
||||
yl_speak_up.get_wield_texture = function(item)
|
||||
if(not(item) or not(minetest.registered_items[ item ])) then
|
||||
return "3d_armor_trans.png"
|
||||
end
|
||||
local def = minetest.registered_items[ item ]
|
||||
if(def.inventory_image ~= "") then
|
||||
return def.inventory_image
|
||||
elseif(def.tiles and type(def.tiles[1]) == "string" and def.tiles[1] ~= "") then
|
||||
return minetest.inventorycube(def.tiles[1])
|
||||
end
|
||||
return "3d_armor_trans.png"
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.fashion_wield_give_items_back = function(player, pname)
|
||||
-- move the item back to the player's inventory (if possible)
|
||||
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
||||
local player_inv = player:get_inventory()
|
||||
local left_stack = trade_inv:get_stack("wield", 1)
|
||||
local right_stack = trade_inv:get_stack("wield", 2)
|
||||
if(left_stack and not(left_stack:is_empty())
|
||||
and player_inv:add_item("main", left_stack)) then
|
||||
trade_inv:set_stack("wield", 1, "")
|
||||
end
|
||||
if(right_stack and not(right_stack:is_empty())
|
||||
and player_inv:add_item("main", right_stack)) then
|
||||
trade_inv:set_stack("wield", 2, "")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- set what the NPC shall wield and which cape to wear
|
||||
yl_speak_up.input_fashion_extended = function(player, formname, fields)
|
||||
if formname ~= "yl_speak_up:fashion_extended" then
|
||||
return
|
||||
end
|
||||
|
||||
local pname = player:get_player_name()
|
||||
local textures = yl_speak_up.speak_to[pname].textures
|
||||
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
|
||||
-- is the player editing this npc? if not: abort
|
||||
if(not(yl_speak_up.edit_mode[pname])
|
||||
or (yl_speak_up.edit_mode[pname] ~= n_id)) then
|
||||
return ""
|
||||
end
|
||||
|
||||
-- catch ESC as well
|
||||
if(not(fields)
|
||||
or (fields.quit or fields.button_cancel or fields.button_exit or fields.button_save)) then
|
||||
yl_speak_up.fashion_wield_give_items_back(player, pname)
|
||||
yl_speak_up.show_fs(player, "fashion")
|
||||
return
|
||||
|
||||
elseif(fields.button_wield_left
|
||||
or fields.button_wield_right) then
|
||||
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
||||
local player_inv = player:get_inventory()
|
||||
local left_stack = trade_inv:get_stack("wield", 1)
|
||||
local right_stack = trade_inv:get_stack("wield", 2)
|
||||
if(left_stack and left_stack:get_name() and fields.button_wield_left) then
|
||||
textures[4] = yl_speak_up.get_wield_texture(left_stack:get_name())
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"(fashion) sword changed to "..tostring(fields.set_sword)..".")
|
||||
end
|
||||
if(right_stack and right_stack:get_name() and fields.button_wield_right) then
|
||||
textures[3] = yl_speak_up.get_wield_texture(right_stack:get_name())
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"(fashion) shield changed to "..tostring(fields.set_shield)..".")
|
||||
end
|
||||
yl_speak_up.fashion_wield_give_items_back(player, pname)
|
||||
|
||||
-- only change cape if there really is a diffrent one selected
|
||||
elseif(fields.set_cape and fields.set_cape ~= textures[1]) then
|
||||
|
||||
local mob_type = yl_speak_up.get_mob_type(pname)
|
||||
local capes = yl_speak_up.mob_capes[mob_type] or {}
|
||||
-- only set the cape if it is part of the list of allowed capes
|
||||
if(table.indexof(capes, fields.set_cape) ~= -1) then
|
||||
textures[1] = fields.set_cape
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"(fashion) cape changed to "..tostring(fields.set_cape)..".")
|
||||
end
|
||||
end
|
||||
|
||||
if(fields.button_wield_left or fields.button_wield_right or fields.set_cape or fields.button_sve) then
|
||||
yl_speak_up.fashion_wield_give_items_back(player, pname)
|
||||
yl_speak_up.mesh_update_textures(pname, textures)
|
||||
yl_speak_up.show_fs(player, "fashion_extended")
|
||||
return
|
||||
end
|
||||
yl_speak_up.show_fs(player, "fashion")
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_fashion_extended = function(pname)
|
||||
-- which texture from the textures list are we talking about?
|
||||
-- this depends on the model!
|
||||
local mesh = yl_speak_up.get_mesh(pname)
|
||||
local texture_index = yl_speak_up.mesh_data[mesh].texture_index
|
||||
if(not(texture_index)) then
|
||||
texture_index = 1
|
||||
end
|
||||
|
||||
local textures = yl_speak_up.speak_to[pname].textures
|
||||
local skin = (textures[texture_index] or "")
|
||||
|
||||
-- which skins are available? this depends on mob_type
|
||||
local mob_type = yl_speak_up.get_mob_type(pname)
|
||||
local skins = yl_speak_up.mob_skins[mob_type] or {skin}
|
||||
local capes = yl_speak_up.mob_capes[mob_type] or {}
|
||||
local cape = "" -- TODO
|
||||
|
||||
-- is this player editing this particular NPC? then rename the button
|
||||
if(not(yl_speak_up.edit_mode[pname])
|
||||
or yl_speak_up.edit_mode[pname] ~= yl_speak_up.speak_to[pname].n_id) then
|
||||
return "label[Error. Not in Edit mode!]"
|
||||
end
|
||||
|
||||
-- make sure the cape can be unset again
|
||||
if(#capes < 1 or capes[1] ~= "") then
|
||||
table.insert(capes, 1, "")
|
||||
end
|
||||
local cape_list = table.concat(capes, ",")
|
||||
local cape_index = table.indexof(capes, cape)
|
||||
if(cape_index == -1) then
|
||||
cape_index = ""
|
||||
end
|
||||
|
||||
local tmp_textures = textures
|
||||
if(texture_index ~= 1) then
|
||||
tmp_textures = yl_speak_up.textures2skin(textures)
|
||||
end
|
||||
local preview = yl_speak_up.skin_preview_3d(mesh, tmp_textures, "4.7,0.5;5,10", nil)
|
||||
|
||||
local button_cancel = "Cancel"
|
||||
-- is this player editing this particular NPC? then rename the button
|
||||
if( yl_speak_up.edit_mode[pname]
|
||||
and yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id) then
|
||||
button_cancel = "Back"
|
||||
end
|
||||
local formspec = {
|
||||
"size[13.4,15]",
|
||||
"label[0.3,0.2;Skin: ",
|
||||
minetest.formspec_escape(skin),
|
||||
"]",
|
||||
"label[4.6,0.65;",
|
||||
yl_speak_up.speak_to[pname].n_id,
|
||||
"]",
|
||||
"label[6,0.65;",
|
||||
(yl_speak_up.speak_to[pname].n_npc or "- nameless -"),
|
||||
"]",
|
||||
"dropdown[9.1,0.2;4,0.75;set_cape;",
|
||||
cape_list, ";", cape_index, "]",
|
||||
"label[0.3,4.2;Left:]",
|
||||
"label[9.1,4.2;Right:]",
|
||||
"field_close_on_enter[set_sword;false]",
|
||||
"field_close_on_enter[set_shield;false]",
|
||||
"image[9.1,1;4,2;",
|
||||
textures[1] or "",
|
||||
"]", -- Cape
|
||||
"image[0.3,4.2;4,4;",
|
||||
textures[4] or "",
|
||||
"]", -- Sword
|
||||
"image[9.1,4.2;4,4;",
|
||||
textures[3] or "",
|
||||
"]", --textures[3],"]", -- Shield
|
||||
"tooltip[0.3,4.2;4,4;This is: ",
|
||||
minetest.formspec_escape(textures[4]),
|
||||
"]",
|
||||
"tooltip[9.1,4.2;4,4;This is: ",
|
||||
minetest.formspec_escape(textures[3]),
|
||||
"]",
|
||||
preview or "",
|
||||
"button[0.3,8.4;3,0.75;button_cancel;"..button_cancel.."]",
|
||||
"button[10.1,8.4;3,0.75;button_save;Save]",
|
||||
"list[current_player;main;1.8,10;8,4;]",
|
||||
-- set wielded items
|
||||
"label[0.3,9.7;Wield\nleft:]",
|
||||
"label[12.0,9.7;Wield\nright:]",
|
||||
"list[detached:yl_speak_up_player_"..tostring(pname)..";wield;0.3,10.5;1,1;]",
|
||||
"list[detached:yl_speak_up_player_"..tostring(pname)..";wield;12.0,10.5;1,1;1]",
|
||||
"button[0.3,11.7;1,0.6;button_wield_left;Set]",
|
||||
"button[12.0,11.7;1,0.6;button_wield_right;Set]",
|
||||
"tooltip[button_wield_left;Set and store what your NPC shall wield in its left hand.]",
|
||||
"tooltip[button_wield_right;Set and store what your NPC shall wield in its right hand.]",
|
||||
}
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_fashion_extended_wrapper = function(player, param)
|
||||
local pname = player:get_player_name()
|
||||
return yl_speak_up.get_fs_fashion_extended(pname)
|
||||
end
|
||||
|
||||
yl_speak_up.register_fs("fashion_extended",
|
||||
yl_speak_up.input_fashion_extended,
|
||||
yl_speak_up.get_fs_fashion_extended_wrapper,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,93 +0,0 @@
|
|||
|
||||
-- this function is called in fs_edit_general.lua when creating preconditions/effects
|
||||
-- and from fs_manage_variables.lua when the player clicks on a button;
|
||||
-- input to this formspec is sent to the respective calling functions
|
||||
|
||||
-- find out where this variable is used in NPCs
|
||||
yl_speak_up.fs_get_list_of_usage_of_variable = function(var_name, pname, check_preconditions,
|
||||
back_button_name, back_button_text, is_internal_var)
|
||||
-- TODO: check if the player really has read access to this variable
|
||||
if(not(is_internal_var)) then
|
||||
var_name = yl_speak_up.restore_complete_var_name(var_name, pname)
|
||||
end
|
||||
-- which NPC (might be several) is using this variable?
|
||||
-- TODO: ..or if the player at least is owner of these NPC or has extended privs
|
||||
local npc_list = yl_speak_up.get_variable_metadata(var_name, "used_by_npc")
|
||||
-- list of all relevant preconditions, actions and effects
|
||||
local res = {}
|
||||
local count_read = 0
|
||||
local count_changed = 0
|
||||
for i, n_id in ipairs(npc_list) do
|
||||
-- the NPC may not even be loaded
|
||||
local dialog = yl_speak_up.load_dialog(n_id, false)
|
||||
if(dialog and dialog.n_dialogs) then
|
||||
for d_id, d in pairs(dialog.n_dialogs) do
|
||||
if(d and d.d_options) then
|
||||
for o_id, o in pairs(d.d_options) do
|
||||
local p_text = ""
|
||||
local r_text = ""
|
||||
local sort_value = 0
|
||||
if(o and o.o_prerequisites and check_preconditions) then
|
||||
for p_id, p in pairs(o.o_prerequisites) do
|
||||
if(p and p.p_type and p.p_type == "state"
|
||||
and p.p_variable and p.p_variable == var_name) then
|
||||
p_text = p_text..yl_speak_up.print_as_table_precon(p,pname)
|
||||
sort_value = (p.p_var_cmp_value or 0)
|
||||
count_read = count_read + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if(o and o.o_results) then
|
||||
for r_id, r in pairs(o.o_results) do
|
||||
if(r and r.r_type and r.r_type == "state"
|
||||
and r.r_variable and r.r_variable == var_name) then
|
||||
r_text = r_text..yl_speak_up.print_as_table_effect(r,pname)
|
||||
-- values set in the results are more important than
|
||||
-- those set in preconditions
|
||||
sort_value = (r.r_var_cmp_value or 0)
|
||||
count_changed = count_changed + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
-- if preconditions or effects apply: show the action as well
|
||||
if(o and o.actions and (p_text ~= "" or r_text ~= "")) then
|
||||
for a_id, a in pairs(o.actions) do
|
||||
-- no need to introduce an a_text; this will follow
|
||||
-- directly after p_text, and p_text is finished
|
||||
p_text = p_text..yl_speak_up.print_as_table_action(a, pname)
|
||||
end
|
||||
end
|
||||
yl_speak_up.print_as_table_dialog(p_text, r_text, dialog,
|
||||
n_id, d_id, o_id, res, o, sort_value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local formspec = yl_speak_up.print_as_table_prepare_formspec(res, "table_of_variable_uses",
|
||||
back_button_name, back_button_text)
|
||||
table.insert(formspec,
|
||||
"label[20.0,1.8;"..
|
||||
minetest.formspec_escape("Variable \""..
|
||||
minetest.colorize("#FFFF00", tostring(var_name or "- ? -"))..
|
||||
"\" is used here:").."]")
|
||||
|
||||
if(count_read > 0 or count_changed > 0) then
|
||||
table.insert(formspec,
|
||||
"label[16.0,31.0;The variable is accessed in "..
|
||||
minetest.colorize("#FFFF00", tostring(count_read).." pre(C)onditions")..
|
||||
" and changed in "..
|
||||
minetest.colorize("#55FF55", tostring(count_changed).." (Ef)fects")..
|
||||
".]")
|
||||
elseif(not(is_internal_var)) then
|
||||
table.insert(formspec,
|
||||
"button[0.2,30.6;56.6,1.2;delete_unused_variable;"..
|
||||
minetest.formspec_escape("Delete this unused variable \""..
|
||||
tostring(var_name or "- ? -")).."\".]")
|
||||
else
|
||||
table.insert(formspec,
|
||||
"label[16.0,31.0;This is an internal variable and cannot be deleted.]")
|
||||
end
|
||||
return table.concat(formspec, "\n")
|
||||
end
|
|
@ -1,202 +0,0 @@
|
|||
|
||||
-- in addition: set who can edit this npc;
|
||||
-- add buttons for fashion (skin editing) and properties;
|
||||
local old_input_fs_initial_config = yl_speak_up.input_fs_initial_config
|
||||
yl_speak_up.input_fs_initial_config = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
|
||||
if(fields.back_from_error_msg) then
|
||||
-- no point in showing the formspec or error message again if we did so already
|
||||
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
|
||||
return
|
||||
end
|
||||
-- show this formspec again
|
||||
yl_speak_up.show_fs(player, "initial_config",
|
||||
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false})
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.button_export_dialog) then
|
||||
yl_speak_up.show_fs(player, "export")
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.edit_skin and fields.edit_skin ~= "") then
|
||||
yl_speak_up.show_fs(player, "fashion")
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.edit_properties and fields.edit_properties ~= "") then
|
||||
yl_speak_up.show_fs(player, "properties")
|
||||
return
|
||||
end
|
||||
|
||||
if((not(fields.save_initial_config)
|
||||
and not(fields.show_nametag)
|
||||
and not(fields.list_may_edit)
|
||||
and not(fields.add_may_edit)
|
||||
and not(fields.delete_may_edit)
|
||||
) or (fields and fields.exit)) then
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
-- unconfigured NPC
|
||||
if(fields and fields.exit and not(dialog) or not(dialog.n_dialogs)) then
|
||||
minetest.chat_send_player(pname, "Aborting initial configuration.")
|
||||
return
|
||||
end
|
||||
-- is the player editing the npc? then leaving this config
|
||||
-- dialog has to lead back to the talk dialog
|
||||
if(yl_speak_up.edit_mode[pname] == n_id and n_id) then
|
||||
yl_speak_up.show_fs(player, "talk",
|
||||
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id})
|
||||
end
|
||||
-- else we can quit here
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
local error_msg = nil
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local done = false
|
||||
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
|
||||
error_msg = "You are not allowed to edit this NPC."
|
||||
|
||||
-- want to change who may edit this npc?
|
||||
-- delete a player from the list of those allowed to edit the NPC
|
||||
elseif(fields.delete_may_edit and fields.delete_may_edit ~= ""
|
||||
and fields.list_may_edit and fields.list_may_edit ~= "") then
|
||||
if(pname ~= yl_speak_up.npc_owner[ n_id ]) then
|
||||
error_msg = "Only the owner of the NPC\ncan change this."
|
||||
elseif(not(dialog)) then
|
||||
error_msg = "Please set a name for your NPC first!"
|
||||
else
|
||||
-- actually delete the player from the list
|
||||
dialog.n_may_edit[ fields.list_may_edit ] = nil
|
||||
-- show the next entry
|
||||
yl_speak_up.speak_to[pname].tmp_index = math.max(1,
|
||||
yl_speak_up.speak_to[pname].tmp_index-1)
|
||||
end
|
||||
done = true
|
||||
-- add a player who may edit this NPC
|
||||
elseif(fields.add_may_edit_button and fields.add_may_edit and fields.add_may_edit ~= "") then
|
||||
if(pname ~= yl_speak_up.npc_owner[ n_id ]) then
|
||||
error_msg = "Only the owner of the NPC\ncan change this."
|
||||
-- Note: The owner can now add himself as well. This may be useful before transfering
|
||||
-- ownership of the NPC to an inexperienced new user who might need help.
|
||||
-- elseif(fields.add_may_edit == pname) then
|
||||
-- error_msg = "You are already the owner of this NPC!\nNo need to add you extra here."
|
||||
elseif(not(minetest.check_player_privs(fields.add_may_edit, {interact=true}))) then
|
||||
error_msg = "Player \""..minetest.formspec_escape(fields.add_may_edit)..
|
||||
"\" not found."
|
||||
elseif(not(dialog)) then
|
||||
error_msg = "Please set a name for the NPC first!"
|
||||
else
|
||||
if(not(dialog.n_may_edit)) then
|
||||
dialog.n_may_edit = {}
|
||||
end
|
||||
dialog.n_may_edit[ fields.add_may_edit ] = true
|
||||
-- jump to the index with this player so that the player sees that he has been added
|
||||
local tmp_list = yl_speak_up.sort_keys(dialog.n_may_edit, true)
|
||||
local index = table.indexof(tmp_list, fields.add_may_edit)
|
||||
if(index and index > 0) then
|
||||
-- "Add player:" is added before all other names, so +1
|
||||
yl_speak_up.speak_to[pname].tmp_index = index + 1
|
||||
end
|
||||
end
|
||||
done = true
|
||||
-- selected a player name in the woy may edit this NPC dropdown?
|
||||
elseif(fields.list_may_edit and fields.list_may_edit ~= "") then
|
||||
local tmp_list = yl_speak_up.sort_keys(dialog.n_may_edit, true)
|
||||
local index = table.indexof(tmp_list, fields.list_may_edit)
|
||||
if(fields.list_may_edit == "Add player:") then
|
||||
index = 0
|
||||
end
|
||||
if(index and index > -1) then
|
||||
yl_speak_up.speak_to[pname].tmp_index = index + 1
|
||||
end
|
||||
done = true
|
||||
end
|
||||
if(error_msg) then
|
||||
yl_speak_up.show_fs(player, "msg", { input_to = "yl_speak_up:initial_config",
|
||||
formspec = "size[6,2]"..
|
||||
"label[0.2,0.0;"..tostring(error_msg).."]"..
|
||||
"button[2,1.5;1,0.9;back_from_error_msg;Back]"})
|
||||
return
|
||||
end
|
||||
|
||||
if( fields.add_may_edit and fields.add_may_edit ~= "") then
|
||||
yl_speak_up.save_dialog(n_id, dialog)
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"Added to \"may be edited by\": "..tostring(fields.add_may_edit))
|
||||
elseif(fields.delete_may_edit and fields.delete_may_edit ~= ""
|
||||
and fields.list_may_edit and fields.list_may_edit ~= "") then
|
||||
yl_speak_up.save_dialog(n_id, dialog)
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"Removed from \"may be edited by\": "..tostring(fields.list_may_edit))
|
||||
elseif(not(done) or fields.save_initial_config) then
|
||||
return old_input_fs_initial_config(player, formname, fields)
|
||||
end
|
||||
-- update display after editing may_edit_npc:
|
||||
yl_speak_up.show_fs(player, "initial_config",
|
||||
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false})
|
||||
end
|
||||
|
||||
|
||||
-- initialize the npc without having to use a staff;
|
||||
|
||||
-- add option to show, add and delete other players who may edit this npc;
|
||||
-- add buttons for skin change and editing properties
|
||||
local old_get_fs_initial_config = yl_speak_up.get_fs_initial_config
|
||||
yl_speak_up.get_fs_initial_config = function(player, n_id, d_id, is_initial_config, add_formspec)
|
||||
-- nothing to add if this is the initial configuration
|
||||
if(is_initial_config) then
|
||||
return old_get_fs_initial_config(player, n_id, d_id, is_initial_config, nil)
|
||||
end
|
||||
|
||||
local pname = player:get_player_name()
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
-- dialog.n_may_edit was a string for a short time in development
|
||||
if(not(dialog.n_may_edit) or type(dialog.n_may_edit) ~= "table") then
|
||||
dialog.n_may_edit = {}
|
||||
end
|
||||
local table_of_names = dialog.n_may_edit
|
||||
local may_be_edited_by = {
|
||||
-- these buttons and formspecs are provided by the editor:
|
||||
"button[1.0,5.5;4,0.9;edit_skin;Edit Skin]",
|
||||
"button[6.0,5.5;4,0.9;edit_properties;Edit Properties]",
|
||||
-- who can edit this NPC?
|
||||
"label[0.2,4.45;May be\nedited by:]",
|
||||
-- offer a dropdown list and a text input field for player names for adding
|
||||
yl_speak_up.create_dropdown_playerlist(player, pname,
|
||||
table_of_names, yl_speak_up.speak_to[pname].tmp_index,
|
||||
2.2, 4.3, 0.0, 1.0, "list_may_edit", "player",
|
||||
"Remove selected\nplayer from list",
|
||||
"add_may_edit",
|
||||
"Enter the name of the player whom you\n"..
|
||||
"want to grant the right to edit your NPC.\n"..
|
||||
"The player needs at least the npc_talk_owner priv\n"..
|
||||
"in order to actually edit the NPC.\n"..
|
||||
"Click on \"Add\" to add the new player.",
|
||||
"delete_may_edit",
|
||||
"If you click here, the player will no\n"..
|
||||
"longer be able to edit your NPC."
|
||||
)}
|
||||
if(not(yl_speak_up.speak_to[pname].tmp_index) or yl_speak_up.speak_to[pname].tmp_index < 2) then
|
||||
table.insert(may_be_edited_by, "button[9.8,4.3;1.0,1.0;add_may_edit_button;Add]")
|
||||
table.insert(may_be_edited_by, "tooltip[add_may_edit_button;Click here to add the player "..
|
||||
"listed to the left\nto those who can edit this NPC.]")
|
||||
end
|
||||
-- show the formspec to the player
|
||||
return old_get_fs_initial_config(player, n_id, d_id, is_initial_config, may_be_edited_by)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("initial_config",
|
||||
-- this function has been changed here:
|
||||
yl_speak_up.input_fs_initial_config,
|
||||
-- still handled by the wrapper:
|
||||
yl_speak_up.get_fs_initial_config_wrapper,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,364 +0,0 @@
|
|||
|
||||
-- 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.handle_input_fs_manage_general and is thus pretty short
|
||||
yl_speak_up.input_fs_manage_quest_steps = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
|
||||
-- route diffrently when the task was adding a quest step
|
||||
if(fields and fields.back
|
||||
and pname
|
||||
and yl_speak_up.speak_to[pname].d_id
|
||||
and yl_speak_up.speak_to[pname].o_id) then
|
||||
return yl_speak_up.show_fs(player, "edit_option_dialog", {
|
||||
d_id = yl_speak_up.speak_to[pname].d_id,
|
||||
o_id = yl_speak_up.speak_to[pname].o_id,
|
||||
})
|
||||
end
|
||||
if(not(fields) or fields.manage_quests or fields.back) then
|
||||
return yl_speak_up.show_fs(player, "manage_quests")
|
||||
end
|
||||
local res = yl_speak_up.player_is_working_on_quest(player)
|
||||
|
||||
-- show a particular quest step?
|
||||
if(yl_speak_up.handle_input_routing_show_a_quest_step(player, formname, fields, "back_from_error_msg", res)) then
|
||||
return
|
||||
end
|
||||
|
||||
if(res.current_step) then
|
||||
-- forward input from that formspec...
|
||||
if((yl_speak_up.speak_to[res.pname].quest_step_mode == "embedded_select")
|
||||
and (fields.add_from_available
|
||||
or (fields.add_step and fields.add_quest_step))) then
|
||||
return yl_speak_up.input_fs_add_quest_steps(player, "yl_speak_up:add_quest_steps", fields)
|
||||
end
|
||||
end
|
||||
|
||||
local modes = {"add_to_one_needed", "add_to_all_needed",
|
||||
"insert_after_prev_step", "insert_before_next_step"}
|
||||
for i, mode in ipairs(modes) do
|
||||
if(fields[mode] and fields[mode] ~= "") 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
|
||||
yl_speak_up.speak_to[pname].quest_step_mode = mode
|
||||
yl_speak_up.show_fs(player, "add_quest_steps")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local quest_step_list = yl_speak_up.get_sorted_quest_step_list(pname)
|
||||
local res = yl_speak_up.handle_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
|
||||
|
||||
|
||||
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 yl_speak_up.build_fs_quest_edit_error(res.error_msg, "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.build_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
|
||||
formspec = {} -- we start a new one
|
||||
-- insert a nicely formated list of quest steps
|
||||
yl_speak_up.speak_to[res.pname].quest_step_mode = "embedded_select"
|
||||
table.insert(formspec, yl_speak_up.get_fs_add_quest_steps(player, nil))
|
||||
table.insert(formspec, "container_end[]")
|
||||
local lists = yl_speak_up.quest_step_get_start_end_unconnected_lists(step_data)
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"Start steps:", "select_from_start_steps", lists.start_steps,
|
||||
"0.1", "2.7", "5.6", "4.3", 0, nil, "#AAFFAA",
|
||||
"The quest begins with this (or one of these) steps.\n"..
|
||||
"You need at least one start step.",
|
||||
nil)
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"Unconnected steps:", "select_from_unconnected_steps", lists.unconnected_steps,
|
||||
"0.1", "7.0", "5.6", "4.3", 0, nil, "#FFAAAA",
|
||||
"These steps are not used yet. They are not required\n"..
|
||||
"by any other step and do not require steps either.\n"..
|
||||
"Please decide what to do with them!",
|
||||
nil)
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"Quest ends with steps:", "select_from_end_steps", lists.end_steps,
|
||||
"24", "2.7", "5.6", "8.5", "0.1", nil, "#AAFFAA",
|
||||
"This quest ends with these steps. They are not required\n"..
|
||||
"by any other steps and have no successor.\n"..
|
||||
"Your quest needs at least one end step.",
|
||||
nil)
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
-- find out the next quest step
|
||||
local required_for = yl_speak_up.quest_step_required_for(step_data, selected)
|
||||
|
||||
-- middle (this quest step)
|
||||
table.insert(formspec, "container[6,2.7;12,10.8]"..
|
||||
"label[0.2,0.5;This quest step is named:]"..
|
||||
"box[0.7,0.7;17,0.7;#000000]"..
|
||||
"label[0.8,1.1;")
|
||||
table.insert(formspec, minetest.colorize("#AAFFAA", minetest.formspec_escape(selected)))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "container_end[]")
|
||||
-- show the locations where this quest step is set
|
||||
local c = 0
|
||||
for where_id, d in pairs(step_data[selected].where or {}) do
|
||||
c = c + 1
|
||||
end
|
||||
if(c > 1) then
|
||||
table.insert(formspec, "label[6.2,4.5;This quest step can be set in diffrent ways (")
|
||||
table.insert(formspec, tostring(c))
|
||||
table.insert(formspec, " ways) by:]")
|
||||
table.insert(formspec, "scrollbaroptions[max=")
|
||||
table.insert(formspec, tostring((c-1.5) * 30)) -- 10 units for default 0.1 scroll factor
|
||||
table.insert(formspec, ";thumbsize=15")
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "scrollbar[23.2,4.7;0.3,5;vertical;scrollbar_where;0.1]")
|
||||
elseif(c == 1) then
|
||||
table.insert(formspec, "label[6.2,4.5;This quest step can be set by:]")
|
||||
else
|
||||
table.insert(formspec, "label[6.2,4.5;This quest step cannot be set yet.]")
|
||||
end
|
||||
table.insert(formspec, "scroll_container[6.2,4.7;17,5;scrollbar_where;vertical;]")
|
||||
c = 0
|
||||
for where_id, d in pairs(step_data[selected].where or {}) do
|
||||
table.insert(formspec, "container[0,")
|
||||
table.insert(formspec, tostring(0.2 + c * 3.0))
|
||||
table.insert(formspec, ";17,4]")
|
||||
table.insert(formspec, "box[0,0;17,2.7;")
|
||||
if(c%2 == 0) then
|
||||
table.insert(formspec, "#000000]")
|
||||
else
|
||||
table.insert(formspec, "#222222]")
|
||||
end
|
||||
-- describe where in the dialog of the NPC or location this quest step shall be set
|
||||
local s = "This quest step can be set by "
|
||||
if(c > 0) then
|
||||
s = "..alternatively, this quest step can be set by "
|
||||
end
|
||||
yl_speak_up.quest_step_show_where_set(res.pname, formspec, s, d.n_id, d.d_id, d.o_id,
|
||||
"#444488", c + 1) --"#513F23", c + 1) --"#a37e45", c + 1)
|
||||
table.insert(formspec, "container_end[]")
|
||||
c = c + 1
|
||||
end
|
||||
table.insert(formspec, "scroll_container_end[]")
|
||||
|
||||
-- left side (previous quest step)
|
||||
table.insert(formspec, "container[0,0;5.8,13.5]"..
|
||||
"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]"..
|
||||
"button[0.1,0.1;5.6,0.8;show_step_list;Show all quest steps]")
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
em("One of").." these quest steps:", "one_step_required",
|
||||
step_data[selected].one_step_required,
|
||||
"0.1", "2.7", "5.6", "4.3", 0, nil, "#AAFFAA",
|
||||
"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.",
|
||||
"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.]")
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
em("All of").." these quest steps:", "all_steps_required",
|
||||
step_data[selected].all_steps_required,
|
||||
"0.1", "7.0", "5.6", "4.3", 0, nil, "#AAFFAA",
|
||||
"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.",
|
||||
"button[4.6,0.0;0.94,0.7;add_to_all_needed;Edit]"..
|
||||
"tooltip[add_to_all_needed;Add or remove a quest step to this list.]")
|
||||
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
|
||||
table.insert(formspec, "container_end[]")
|
||||
|
||||
|
||||
-- right side (next quest step)
|
||||
table.insert(formspec, "container[23.8,0;5.8,13.5]"..
|
||||
"label[0.6,2.0;Achieving this quest step]"..
|
||||
"label[0.6,2.4;"..em("helps").." the quester to:]"..
|
||||
"button[0.4,0.1;5.6,0.8;manage_quests;Manage quests]")
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"get these quest step(s) "..em("next")..":", "next_steps_show",
|
||||
required_for,
|
||||
-- the label needs to be moved slightly to the right to make room for the > button
|
||||
"0.4", "2.7", "5.6", "8.5", "0.1", nil, "#AAFFAA",
|
||||
"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.",
|
||||
nil)
|
||||
|
||||
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[0,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[0,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
|
||||
table.insert(formspec, "container_end[]")
|
||||
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("manage_quest_steps",
|
||||
yl_speak_up.input_fs_manage_quest_steps,
|
||||
yl_speak_up.get_fs_manage_quest_steps,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,248 +0,0 @@
|
|||
-- helper functions for yl_speak_up.input_fs_manage_quests(..)
|
||||
-- returns the index of the new quest
|
||||
yl_speak_up.fun_input_fs_manage_quests_add_new_entry = function(pname, entry_name)
|
||||
local res = yl_speak_up.add_quest(pname, entry_name,
|
||||
"Name of your quest",
|
||||
"Enter a longer description here for describing the quest "..
|
||||
"to players who search for one.",
|
||||
"Enter a short description here describing what the quest is about.",
|
||||
"Room for comments/notes")
|
||||
-- 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_list = yl_speak_up.get_sorted_quest_list(pname)
|
||||
return table.indexof(quest_list, entry_name)
|
||||
end
|
||||
|
||||
-- helper functions for yl_speak_up.input_fs_manage_quests(..)
|
||||
-- returns a text describing if deleting the quest worked
|
||||
yl_speak_up.fun_input_fs_manage_quests_del_old_entry = function(pname, entry_name)
|
||||
-- get q_id from entry_name
|
||||
local q_id = yl_speak_up.get_quest_id_by_var_name(entry_name, pname)
|
||||
return yl_speak_up.del_quest(q_id, pname)
|
||||
end
|
||||
|
||||
-- helper functions for yl_speak_up.input_fs_manage_quests(..)
|
||||
-- implements all the functions that are specific to managing quests and not part of
|
||||
-- general item management
|
||||
yl_speak_up.fun_input_fs_manage_quests_check_fields = function(player, formname, fields, quest_name, list_of_entries)
|
||||
local pname = player:get_player_name()
|
||||
if(not(quest_name)) then
|
||||
quest_name = ""
|
||||
end
|
||||
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.handle_input_fs_manage_general and is thus pretty short
|
||||
yl_speak_up.input_fs_manage_quests = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
if(fields and fields.manage_quest_steps and fields.manage_quest_steps ~= "") then
|
||||
-- the quest we're working at is stored in yl_speak_up.speak_to[pname].q_id
|
||||
yl_speak_up.show_fs(player, "manage_quest_steps")
|
||||
return
|
||||
end
|
||||
|
||||
-- show and edit NPCs that may contribute
|
||||
if( fields and fields.edit_npcs) then
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps", "manage_quest_npcs")
|
||||
elseif(fields and fields.edit_locations) then
|
||||
return yl_speak_up.show_fs(player, "add_quest_steps", "manage_quest_locations")
|
||||
end
|
||||
|
||||
-- show a particular quest step from the start/unconnected/end list?
|
||||
local res = yl_speak_up.player_is_working_on_quest(player)
|
||||
if(yl_speak_up.speak_to[pname]
|
||||
and yl_speak_up.speak_to[pname].q_id
|
||||
and yl_speak_up.handle_input_routing_show_a_quest_step(player, formname, fields, "back", res)) then
|
||||
return
|
||||
end
|
||||
|
||||
local quest_list = yl_speak_up.get_sorted_quest_list(pname)
|
||||
local res = yl_speak_up.handle_input_fs_manage_general(player, formname, fields,
|
||||
-- what_is_the_list_about, min_length, max_length, function_add_new_entry,
|
||||
"quest", 2, 80,
|
||||
yl_speak_up.fun_input_fs_manage_quests_add_new_entry,
|
||||
quest_list,
|
||||
yl_speak_up.fun_input_fs_manage_quests_del_old_entry,
|
||||
yl_speak_up.fun_input_fs_manage_quests_check_fields)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_manage_quests = function(player, param)
|
||||
local pname = player:get_player_name()
|
||||
local quest_list = yl_speak_up.get_sorted_quest_list(pname)
|
||||
local formspec = {}
|
||||
if(param and param ~= "") then
|
||||
local index = table.indexof(quest_list, param)
|
||||
yl_speak_up.speak_to[pname].tmp_index_general = index + 1
|
||||
end
|
||||
table.insert(formspec, "size[30,12]"..
|
||||
"container[6,0;18.5,12]"..
|
||||
"label[0.2,1.2;A quest is a linear sequence of quest steps. Quests can "..
|
||||
"depend on and influence other quests.\n"..
|
||||
"Progress for each player is stored in a variable. The name of "..
|
||||
"that variable cannot be changed after creation.]")
|
||||
-- if(true) then return formspec[1] end -- TODO: temporally disabled for YL
|
||||
local selected = yl_speak_up.build_fs_manage_general(player, param,
|
||||
formspec, quest_list,
|
||||
"Create quest",
|
||||
"Create a new varialbe with the name\n"..
|
||||
"you entered in the field to the left.",
|
||||
"quest",
|
||||
"Enter the name of the new quest you want to create.\n"..
|
||||
"You can't change this name afterwards. But you *can*\n"..
|
||||
"add and change a human readable description later on.",
|
||||
"If you click here, the selected quest will be deleted.\n"..
|
||||
"This will only be possible if it's not used anywhere.")
|
||||
if(not(selected) or selected == "") then
|
||||
table.insert(formspec, "container_end[]")
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
local var_name = yl_speak_up.restore_complete_var_name(selected, pname)
|
||||
local quest = {}
|
||||
for q_id, data in pairs(yl_speak_up.quests) do
|
||||
if(data and data.var_name and data.var_name == var_name) then
|
||||
quest = data
|
||||
end
|
||||
end
|
||||
|
||||
-- which quest is the player working on? that's important for showing quest steps
|
||||
if(not(yl_speak_up.speak_to[pname])) then
|
||||
yl_speak_up.speak_to[pname] = {}
|
||||
end
|
||||
yl_speak_up.speak_to[pname].q_id = quest.id
|
||||
|
||||
local quest_state_selected = table.indexof({"created","testing","open","official"}, quest.state)
|
||||
if(quest_state_selected == -1) then
|
||||
quest_state_selected = 1
|
||||
end
|
||||
-- index 1 is "Add variable:"
|
||||
|
||||
table.insert(formspec, "button[12,2.15;4.5,0.6;show_variable;Show and edit this variable]")
|
||||
|
||||
table.insert(formspec, "scroll_container[0,3;18,8;scr0;vertical;1]")
|
||||
table.insert(formspec, "button[12,0.15;4.5,0.6;manage_quest_steps;Manage quest steps]")
|
||||
|
||||
table.insert(formspec, "label[0.5,0.5;Quest ID:]")
|
||||
table.insert(formspec, "label[3.5,0.5;"..minetest.formspec_escape(quest.id or "- ? -").."]")
|
||||
table.insert(formspec, "label[0.5,1.1;State:]")
|
||||
table.insert(formspec, "dropdown[3.5,0.8;4.0,0.5;quest_state;created,testing,open,official;"..tostring(quest_state_selected).."]")
|
||||
table.insert(formspec, "label[0.5,1.7;Creator/Owner:]")
|
||||
table.insert(formspec, "field[3.5,1.4;4.0,0.5;quest_owner;;"..minetest.formspec_escape(quest.owner or "- ? -").."]")
|
||||
table.insert(formspec, "label[0.5,2.3;Name:]")
|
||||
table.insert(formspec, "field[3.5,2.0;13.0,0.5;quest_name;;"..minetest.formspec_escape(quest.name or "- ? -").."]")
|
||||
table.insert(formspec, "label[0.5,2.9;Short Description:]")
|
||||
table.insert(formspec, "field[3.5,2.6;13.0,0.5;quest_short_desc;;"..minetest.formspec_escape(quest.short_desc or "- ? -").."]")
|
||||
table.insert(formspec, "label[0.5,3.5;Full Description:]")
|
||||
table.insert(formspec, "textarea[3.5,3.2;13.0,1.5;quest_desc;;"..minetest.formspec_escape(quest.description or "- ? -").."]")
|
||||
table.insert(formspec, "label[0.5,5.1;Internal comment:]")
|
||||
table.insert(formspec, "textarea[3.5,4.8;13.0,1.5;quest_comment;;"..minetest.formspec_escape(quest.comment or "- ? -").."]")
|
||||
|
||||
table.insert(formspec, "button[3.5,6.5;4.0,0.8;save_changes;TODO Save changes]")
|
||||
table.insert(formspec, "scroll_container_end[]")
|
||||
table.insert(formspec, "container_end[]")
|
||||
|
||||
-- TODO: make the content of the fields and textareas more readable (more contrast)
|
||||
-- TODO: actually process and store changed entries
|
||||
--[[
|
||||
-- TODO: entries that are not yet shown:
|
||||
quest.var_name = var_name -- name of the variable where progress is stored for each player
|
||||
quest.subquests = {} -- list of other quest_ids that contribute to this quest
|
||||
-- -> determined from quests.npcs and quests.locations
|
||||
quest.is_subquest_of = {} -- list of quest_ids this quest contributes to
|
||||
-- -> determined from quests.npcs and quests.locations
|
||||
quest.rewards = {} -- list of rewards (item stacks) for this ques
|
||||
quest.testers = {} -- list of player names that can test the quest
|
||||
-- -> during the created/testing phase: any player for which
|
||||
-- quest.var_name is set to a value
|
||||
quest.solved_by = {} -- list of names of players that solved the quest at least once
|
||||
--]]
|
||||
|
||||
-- left side: quest steps
|
||||
-- quest.step_data = {}
|
||||
-- table containing information about a quest step (=key)
|
||||
-- this may also be information about WHERE a quest step shall take place
|
||||
table.insert(formspec, "button[0.1,0.1;5.6,0.8;show_step_list;Show all quest steps]")
|
||||
local lists = yl_speak_up.quest_step_get_start_end_unconnected_lists(quest.step_data or {})
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"Start steps:", "select_from_start_steps", lists.start_steps,
|
||||
"0.1", "1.0", "5.6", "3.5", 0, nil, "#AAFFAA",
|
||||
"The quest begins with this (or one of these) steps.\n"..
|
||||
"You need at least one start step.",
|
||||
nil)
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"Unconnected steps:", "select_from_unconnected_steps", lists.unconnected_steps,
|
||||
"0.1", "4.5", "5.6", "3.5", 0, nil, "#FFAAAA",
|
||||
"These steps are not used yet. They are not required\n"..
|
||||
"by any other step and do not require steps either.\n"..
|
||||
"Please decide what to do with them!",
|
||||
nil)
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"Quest ends with steps:", "select_from_end_steps", lists.end_steps,
|
||||
"0.1", "8.0", "5.6", "3.5", 0, nil, "#AAFFAA",
|
||||
"This quest ends with these steps. They are not required\n"..
|
||||
"by any other steps and have no successor.\n"..
|
||||
"Your quest needs at least one end step.",
|
||||
nil)
|
||||
|
||||
-- right side:
|
||||
-- All these values could in theory either be derived from quest.var_name
|
||||
-- and/or from quest.step_data.where.
|
||||
-- These lists here are needed regardless of that because they may be used
|
||||
-- to add NPC/locations/quest items that are *not yet* used but are planned
|
||||
-- to be used for this quest eventually.
|
||||
table.insert(formspec, "style[edit_npcs,edit_locations,edit_items;bgcolor=blue;textcolor=yellow]")
|
||||
-- quest.npcs = {}
|
||||
-- list of NPC that *may* contribute to this quest (only IDs without leading n_)
|
||||
-- turn that list into a more readable list of names
|
||||
local npc_names = {}
|
||||
for i, id in ipairs(quest.npcs or {}) do
|
||||
local d = yl_speak_up.npc_list[id] or {}
|
||||
table.insert(npc_names, "n_"..tostring(id).." "..(d.name or "- unknown -"))
|
||||
end
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"NPC that (may) participate:", "select_from_npcs", npc_names,
|
||||
"24", "1.0", "5.6", "3.5", 0, nil, "#AAAAFF",
|
||||
"This is a list of NPC that may be relevant for this quest.\n"..
|
||||
"Add an NPC to this list and then edit the NPC.\n"..
|
||||
"Now you can set quest steps from this quest in the NPC's options.",
|
||||
"button[4.6,0.0;0.94,0.7;edit_npcs;Edit]")
|
||||
-- quest.locations = {}
|
||||
-- list of locations that *may* contribute to this quest
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"Locations:", "select_from_locations", quest.locations or {},
|
||||
"24", "4.5", "5.6", "3.5", 0, nil, "#AAAAFF",
|
||||
"This is a list of locations that may be relevant for this quest.\n"..
|
||||
"It works the same way as for the NPC above.",
|
||||
"button[4.6,0.0;0.94,0.7;edit_locations;Edit]")
|
||||
-- quest.items = {}
|
||||
-- data of quest items that *may* be created and/or accepted in this quest
|
||||
yl_speak_up.get_sub_fs_show_list_in_box(formspec,
|
||||
"Quest items:", "select_from_quest_items", quest.items or {},
|
||||
"24", "8.0", "5.6", "3.5", 0, nil, "#FFFFFF",
|
||||
"This is a list of quest items.\n"..
|
||||
"Add quest items here in order to use them more easily in your NPC.",
|
||||
"button[4.6,0.0;0.94,0.7;edit_items;Edit]")
|
||||
|
||||
|
||||
-- store the quest ID so that we know what we're working at
|
||||
yl_speak_up.speak_to[pname].q_id = quest.id
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("manage_quests",
|
||||
yl_speak_up.input_fs_manage_quests,
|
||||
yl_speak_up.get_fs_manage_quests,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,483 +0,0 @@
|
|||
|
||||
-- helper functions for yl_speak_up.input_fs_manage_variables(..)
|
||||
-- returns the index of the new variable
|
||||
yl_speak_up.fun_input_fs_manage_variables_add_new_entry = function(pname, entry_name)
|
||||
local res = yl_speak_up.add_quest_variable(pname, entry_name)
|
||||
if(not(res)) then
|
||||
return -1
|
||||
end
|
||||
local var_list = yl_speak_up.get_quest_variables(pname, true)
|
||||
-- make names of own variables shorter
|
||||
yl_speak_up.strip_pname_from_varlist(var_list, pname)
|
||||
table.sort(var_list)
|
||||
return table.indexof(var_list, entry_name)
|
||||
end
|
||||
|
||||
-- helper functions for yl_speak_up.input_fs_manage_variables(..)
|
||||
-- returns a text describing if deleting the variable worked
|
||||
yl_speak_up.fun_input_fs_manage_variables_del_old_entry = function(pname, entry_name)
|
||||
-- delete (empty) variable
|
||||
return yl_speak_up.del_quest_variable(pname, entry_name, nil)
|
||||
end
|
||||
|
||||
-- helper functions for yl_speak_up.input_fs_manage_variables(..)
|
||||
-- implements all the functions that are specific to managing variables and not part of
|
||||
-- general item management
|
||||
yl_speak_up.fun_input_fs_manage_variables_check_fields = function(player, formname, fields, var_name, list_of_entries)
|
||||
local pname = player:get_player_name()
|
||||
if(not(var_name)) then
|
||||
var_name = ""
|
||||
end
|
||||
local var_name_with_prefix = yl_speak_up.restore_complete_var_name(var_name, pname)
|
||||
|
||||
-- show all stored values for a variable in a table
|
||||
if(fields and fields.show_stored_values_for_var and var_name) then
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = yl_speak_up.fs_show_all_var_values(player, pname, var_name)
|
||||
})
|
||||
return
|
||||
-- show details about a quest (if it is a quest variable)
|
||||
elseif(fields and fields.show_quest) then
|
||||
yl_speak_up.show_fs(player, "manage_quests", var_name)
|
||||
return
|
||||
-- show where this variable is used
|
||||
elseif(fields and fields.show_var_usage and fields.show_var_usage ~= "") then
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = yl_speak_up.fs_get_list_of_usage_of_variable(
|
||||
fields.list_of_entries, pname, true,
|
||||
"back_from_msg",
|
||||
"Back to manage variables",
|
||||
-- not an internal variable
|
||||
false)
|
||||
})
|
||||
return
|
||||
-- enable, disable and list variables in debug mode
|
||||
elseif(fields and fields.enable_debug_mode and var_name) then
|
||||
yl_speak_up.set_variable_metadata(var_name, pname, "debug", pname, true)
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = "size[10,2]"..
|
||||
"label[0.2,0.0;Activating debug mode for variable \""..
|
||||
minetest.colorize("#FFFF00",
|
||||
minetest.formspec_escape(tostring(var_name)))..
|
||||
"\".\nYou will now receive a chat message whenever the "..
|
||||
"variable changes.]"..
|
||||
"button[1.5,1.5;2,0.9;back_from_msg;Back]"})
|
||||
return
|
||||
elseif(fields and fields.disable_debug_mode and var_name) then
|
||||
yl_speak_up.set_variable_metadata(var_name, pname, "debug", pname, nil)
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = "size[10,2]"..
|
||||
"label[0.2,0.0;Deactivating debug mode for variable \""..
|
||||
minetest.colorize("#FFFF00",
|
||||
minetest.formspec_escape(tostring(var_name)))..
|
||||
"\".\nYou will no longer receive a chat message whenever the "..
|
||||
"variable changes.]"..
|
||||
"button[1.5,1.5;2,0.9;back_from_msg;Back]"})
|
||||
return
|
||||
elseif(fields and fields.list_debug_mode) then
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = "size[10,6]"..
|
||||
"label[0.2,0.0;You are currently receiving debug information for the "..
|
||||
"following variables:]"..
|
||||
"tablecolumns[text]"..
|
||||
"table[0.8,0.8;8.8,4.0;list_of_variables_in_debug_mode;"..
|
||||
-- the table entries will already be formspec_escaped
|
||||
table.concat(yl_speak_up.get_list_of_debugged_variables(pname), ",").."]"..
|
||||
"button[1.5,5.5;2,0.9;back_from_msg;Back]"})
|
||||
return
|
||||
|
||||
-- a player name was given; the value for that player shall be shown
|
||||
elseif(fields and fields.show_stored_value_for_player and var_name
|
||||
and fields.stored_value_for_player and fields.stored_value_for_player ~= "") then
|
||||
yl_speak_up.show_fs(player, "manage_variables", {var_name = var_name,
|
||||
for_player = fields.stored_value_for_player})
|
||||
return
|
||||
-- change the value for a player (possibly to nil)
|
||||
elseif(fields and fields.store_new_value_for_player and var_name
|
||||
and fields.stored_value_for_player and fields.stored_value_for_player ~= "") then
|
||||
local old_value = yl_speak_up.get_quest_variable_value(
|
||||
fields.stored_value_for_player, var_name_with_prefix)
|
||||
yl_speak_up.set_quest_variable_value(fields.stored_value_for_player, var_name_with_prefix,
|
||||
fields.current_value_for_player)
|
||||
local new_value = yl_speak_up.get_quest_variable_value(
|
||||
fields.stored_value_for_player, var_name_with_prefix)
|
||||
local success_msg = minetest.colorize("#00FF00", "Successfully set variable")
|
||||
if(new_value ~= fields.current_value_for_player) then
|
||||
success_msg = minetest.colorize("#FF0000", "FAILED TO set variable")
|
||||
end
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = "size[10,2.5]"..
|
||||
"label[0.2,0.0;"..success_msg.." \""..
|
||||
minetest.colorize("#FFFF00",
|
||||
minetest.formspec_escape(tostring(var_name)))..
|
||||
"\"\nfor player "..
|
||||
minetest.formspec_escape(fields.stored_value_for_player)..
|
||||
"\n(old value: "..
|
||||
minetest.colorize("#AAAAAA", old_value)..
|
||||
")\nto new value "..
|
||||
minetest.colorize("#FFFF00", fields.current_value_for_player)..".]"..
|
||||
"button[1.5,2.0;2,0.9;back_from_msg;Back]"})
|
||||
return
|
||||
-- remove the value for a player (set to nil)
|
||||
elseif(fields and fields.unset_value_for_player and var_name
|
||||
and fields.stored_value_for_player and fields.stored_value_for_player ~= "") then
|
||||
local old_value = yl_speak_up.get_quest_variable_value(
|
||||
fields.stored_value_for_player, var_name_with_prefix)
|
||||
yl_speak_up.set_quest_variable_value(fields.stored_value_for_player, var_name_with_prefix, nil)
|
||||
local new_value = yl_speak_up.get_quest_variable_value(
|
||||
fields.stored_value_for_player, var_name_with_prefix)
|
||||
local success_msg = minetest.colorize("#00FF00", "Unset variable")
|
||||
if(new_value) then
|
||||
success_msg = minetest.colorize("#FF0000", "FAILED TO unset variable")
|
||||
end
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = "size[10,2]"..
|
||||
"label[0.2,0.0;"..success_msg.." \""..
|
||||
minetest.colorize("#FFFF00",
|
||||
minetest.formspec_escape(tostring(var_name)))..
|
||||
"\"\nfor player "..
|
||||
minetest.formspec_escape(fields.stored_value_for_player)..
|
||||
"\n(old value: "..
|
||||
minetest.colorize("#AAAAAA", old_value)..
|
||||
").]"..
|
||||
"button[1.5,1.5;2,0.9;back_from_msg;Back]"})
|
||||
return
|
||||
-- revoke read or write access to a variable
|
||||
elseif(fields
|
||||
and ((fields.revoke_player_var_read_access and fields.revoke_player_var_read_access ~= "")
|
||||
or (fields.revoke_player_var_write_access and fields.revoke_player_var_write_access ~= ""))
|
||||
and var_name) then
|
||||
local right = "read"
|
||||
if(fields.revoke_player_var_write_access and fields.revoke_player_var_write_access ~= "") then
|
||||
right = "write"
|
||||
end
|
||||
-- which player are we talking about?
|
||||
local selected = yl_speak_up.speak_to[pname]["tmp_index_var_"..right.."_access"]
|
||||
local pl_with_access = yl_speak_up.get_access_list_for_var(var_name, pname, right.."_access")
|
||||
local tmp_list = {}
|
||||
for k, v in pairs(pl_with_access) do
|
||||
table.insert(tmp_list, k)
|
||||
end
|
||||
table.sort(tmp_list)
|
||||
local grant_to = ""
|
||||
if(selected > 1) then
|
||||
grant_to = tmp_list[ selected-1 ]
|
||||
end
|
||||
local error_msg = ""
|
||||
local pl_with_access = yl_speak_up.get_access_list_for_var(var_name, pname, right.."_access")
|
||||
if(not(grant_to) or grant_to == "") then
|
||||
error_msg = "For which player do you want to revoke "..right.." access?"
|
||||
elseif(pname ~= yl_speak_up.npc_owner[ n_id ]
|
||||
and not(minetest.check_player_privs(pname, {npc_talk_master=true}))) then
|
||||
error_msg = "Only the owner of the NPC or players with\n"..
|
||||
"the npc_talk_master priv can change this."
|
||||
elseif(not(pl_with_access[ grant_to ])) then
|
||||
error_msg = minetest.formspec_escape(grant_to).." doesn't have "..right..
|
||||
" access\nto this variable. Nothing changed."
|
||||
-- try to revoke access
|
||||
elseif(not(yl_speak_up.manage_access_to_quest_variable(var_name, pname, grant_to,
|
||||
right.."_access", nil))) then
|
||||
error_msg = "An internal error occoured."
|
||||
else
|
||||
-- not really an error message here...rather a success message
|
||||
error_msg = "Revoked "..right.." access to variable\n\""..
|
||||
minetest.formspec_escape(var_name)..
|
||||
"\"\nfor player "..minetest.formspec_escape(grant_to)..".\n"..
|
||||
"Note: This will *not* affect existing preconditions/effects!"
|
||||
end
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = "size[6,2]"..
|
||||
"label[0.2,0.0;"..error_msg.."]"..
|
||||
"button[1.5,1.5;2,0.9;back_from_msg;Back]"})
|
||||
return
|
||||
|
||||
-- grant read or write access to a variable
|
||||
elseif(fields
|
||||
and ((fields.grant_player_var_read_access and fields.grant_player_var_read_access ~= "")
|
||||
or (fields.grant_player_var_write_access and fields.grant_player_var_write_access ~= ""))
|
||||
and var_name) then
|
||||
local right = "read"
|
||||
if(fields.grant_player_var_write_access and fields.grant_player_var_write_access ~= "") then
|
||||
right = "write"
|
||||
end
|
||||
local grant_to = fields[ "grant_player_var_"..right.."_access"]
|
||||
local error_msg = ""
|
||||
local pl_with_access = yl_speak_up.get_access_list_for_var(var_name, pname, right.."_access")
|
||||
if(pname ~= yl_speak_up.npc_owner[ n_id ]
|
||||
and not(minetest.check_player_privs(pname, {npc_talk_master=true}))) then
|
||||
error_msg = "Only the owner of the NPC or players with\n"..
|
||||
"the npc_talk_master priv can change this."
|
||||
elseif(grant_to == pname) then
|
||||
error_msg = "You already have "..right.." access to this variable."
|
||||
elseif(pl_with_access[ grant_to ]) then
|
||||
error_msg = minetest.formspec_escape(grant_to).." already has "..right..
|
||||
" access\nto this variable."
|
||||
elseif(not(minetest.check_player_privs(grant_to, {interact=true}))) then
|
||||
error_msg = "Player \""..minetest.formspec_escape(grant_to).."\" not found."
|
||||
-- try to grant access
|
||||
elseif(not(yl_speak_up.manage_access_to_quest_variable(var_name, pname, grant_to,
|
||||
right.."_access", true))) then
|
||||
error_msg = "An internal error occoured."
|
||||
else
|
||||
-- not really an error message here...rather a success message
|
||||
error_msg = "Granted "..right.." access to variable\n\""..
|
||||
minetest.formspec_escape(var_name)..
|
||||
"\"\nto player "..minetest.formspec_escape(grant_to).."."
|
||||
end
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:manage_variables",
|
||||
formspec = "size[6,2]"..
|
||||
"label[0.2,0.0;"..error_msg.."]"..
|
||||
"button[1.5,1.5;2,0.9;back_from_msg;Back]"})
|
||||
return
|
||||
|
||||
-- the player clicked on a name in the list of players with read or write access
|
||||
elseif(fields
|
||||
and ((fields.list_var_read_access and fields.list_var_read_access ~= "")
|
||||
or (fields.list_var_write_access and fields.list_var_write_access ~= ""))
|
||||
and var_name) then
|
||||
local right = "read"
|
||||
if(fields.list_var_write_access and fields.list_var_write_access ~= "") then
|
||||
right = "write"
|
||||
end
|
||||
local selected = fields[ "list_var_"..right.."_access"]
|
||||
local pl_with_access = yl_speak_up.get_access_list_for_var(var_name, pname, right.."_access")
|
||||
local tmp_list = {}
|
||||
for k, v in pairs(pl_with_access) do
|
||||
table.insert(tmp_list, k)
|
||||
end
|
||||
table.sort(tmp_list)
|
||||
local index = table.indexof(tmp_list, selected)
|
||||
if(selected == "Add player:") then
|
||||
index = 0
|
||||
end
|
||||
if(index and index > -1) then
|
||||
yl_speak_up.speak_to[pname]["tmp_index_var_"..right.."_access"] = index + 1
|
||||
end
|
||||
yl_speak_up.show_fs(player, "manage_variables")
|
||||
return
|
||||
end
|
||||
-- this function didn't have anything to do
|
||||
return "NOTHING FOUND"
|
||||
end
|
||||
|
||||
|
||||
-- makes use of yl_speak_up.handle_input_fs_manage_general and is thus pretty short
|
||||
yl_speak_up.input_fs_manage_variables = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
local list_of_entries = yl_speak_up.get_quest_variables(pname, true)
|
||||
-- make names of own variables shorter
|
||||
yl_speak_up.strip_pname_from_varlist(list_of_entries, pname)
|
||||
table.sort(list_of_entries)
|
||||
|
||||
local res = yl_speak_up.handle_input_fs_manage_general(player, formname, fields,
|
||||
-- what_is_the_list_about, min_length, max_length, function_add_new_entry,
|
||||
"variable", 2, 30,
|
||||
yl_speak_up.fun_input_fs_manage_variables_add_new_entry,
|
||||
list_of_entries,
|
||||
yl_speak_up.fun_input_fs_manage_variables_del_old_entry,
|
||||
yl_speak_up.fun_input_fs_manage_variables_check_fields)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_manage_variables = function(player, param)
|
||||
local pname = player:get_player_name()
|
||||
-- variables owned by the player - including those with write access
|
||||
local var_list = yl_speak_up.get_quest_variables(pname, true)
|
||||
-- make names of own variables shorter
|
||||
yl_speak_up.strip_pname_from_varlist(var_list, pname)
|
||||
|
||||
local formspec = {}
|
||||
if(not(param) or type(param) ~= "table") then
|
||||
param = {}
|
||||
end
|
||||
if(param and type(param) == "table" and param.var_name and param.var_name ~= "") then
|
||||
local index = table.indexof(var_list, param.var_name)
|
||||
yl_speak_up.speak_to[pname].tmp_index_general = index + 1
|
||||
end
|
||||
table.insert(formspec, "size[18,12]"..
|
||||
"label[0.2,1.2;Note: Each variable will store a diffrent value for each "..
|
||||
"player who interacts with the NPC.\n"..
|
||||
"You can grant read and write access to other players for your "..
|
||||
"variables so that they can also use them as well.]")
|
||||
local selected = yl_speak_up.build_fs_manage_general(player, param.var_name,
|
||||
formspec, var_list,
|
||||
"Create variable",
|
||||
"Create a new varialbe with the name\n"..
|
||||
"you entered in the field to the left.",
|
||||
"variable",
|
||||
"Enter the name of the new variable you\n"..
|
||||
"want to create.",
|
||||
"If you click here, the selected variable\n"..
|
||||
"will be deleted.")
|
||||
if(selected and selected ~= "") then
|
||||
local k = selected
|
||||
-- index 1 is "Add variable:"
|
||||
local pl_with_read_access = yl_speak_up.get_access_list_for_var(k, pname, "read_access")
|
||||
local pl_with_write_access = yl_speak_up.get_access_list_for_var(k, pname, "write_access")
|
||||
if(not(yl_speak_up.speak_to[pname].tmp_index_var_read_access)
|
||||
or yl_speak_up.speak_to[pname].tmp_index_var_read_access == 1) then
|
||||
yl_speak_up.speak_to[pname].tmp_index_var_read_access = 1
|
||||
table.insert(formspec, "button[14.6,2.95;1.0,0.6;add_read_access;Add]"..
|
||||
"tooltip[add_read_access;Grant the player whose name you entered\n"..
|
||||
"you entered in the field to the left read access\n"..
|
||||
"to your variable.]")
|
||||
end
|
||||
if(not(yl_speak_up.speak_to[pname].tmp_index_var_write_access)
|
||||
or yl_speak_up.speak_to[pname].tmp_index_var_write_access == 1) then
|
||||
yl_speak_up.speak_to[pname].tmp_index_var_write_access = 1
|
||||
table.insert(formspec, "button[14.6,3.95;1.0,0.6;add_write_access;Add]"..
|
||||
"tooltip[add_write_access;Grant the player whose name you entered\n"..
|
||||
"you entered in the field to the left *write* access\n"..
|
||||
"to your variable.]")
|
||||
end
|
||||
local list_of_npc_users = "- none -"
|
||||
local list_of_node_pos_users = "- none -"
|
||||
-- expand name of variable k again
|
||||
local k_long = yl_speak_up.add_pname_to_var(k, pname)
|
||||
-- which npc and which node_pos use this variable? create a list for display
|
||||
local c1 = 0
|
||||
local c2 = 0
|
||||
if(k_long
|
||||
and yl_speak_up.player_vars[ k_long ]
|
||||
and yl_speak_up.player_vars[ k_long ][ "$META$"]) then
|
||||
local npc_users = yl_speak_up.get_variable_metadata(k_long, "used_by_npc")
|
||||
c1 = #npc_users
|
||||
if(npc_users and c1 > 0) then
|
||||
list_of_npc_users = minetest.formspec_escape(table.concat(npc_users, ", "))
|
||||
end
|
||||
local node_pos_users = yl_speak_up.get_variable_metadata(k_long, "used_by_node_pos")
|
||||
c2 = #node_pos_users
|
||||
if(node_pos_users and c2 > 0) then
|
||||
list_of_node_pos_users = minetest.formspec_escape(table.concat(
|
||||
node_pos_users, ", "))
|
||||
end
|
||||
end
|
||||
table.insert(formspec, "button[10.0,10.05;4.0,0.6;list_debug_mode;What am I debugging?]"..
|
||||
"tooltip[list_debug_mode;"..
|
||||
"Show for which variables you currently have "..
|
||||
"\nactivated the debug mode.]")
|
||||
local debuggers = yl_speak_up.get_variable_metadata(k_long, "debug")
|
||||
local i = table.indexof(debuggers, pname)
|
||||
if(i and i > 0) then
|
||||
table.insert(formspec,
|
||||
"button[5.0,10.05;4.0,0.6;disable_debug_mode;Deactivate debug mode]"..
|
||||
"tooltip[disable_debug_mode;"..
|
||||
"You will no longer receive a chat message "..
|
||||
"\nwhen this value changes for a player.]")
|
||||
else
|
||||
table.insert(formspec,
|
||||
"button[5.0,10.05;4.0,0.6;enable_debug_mode;Activate debug mode]"..
|
||||
"tooltip[enable_debug_mode;"..
|
||||
"You will receive a chat message whenever the value "..
|
||||
"\nof this variable changes for one player. The debug\n"..
|
||||
"messages will be sent even after relogin.]")
|
||||
end
|
||||
-- checking/changing debug value for one specific player
|
||||
if(not(param.for_player)) then
|
||||
param.for_player = ""
|
||||
end
|
||||
table.insert(formspec,
|
||||
"label[0.2,8.05;Show stored value for player:]"..
|
||||
"field[4.9,7.75;4.0,0.6;stored_value_for_player;;")
|
||||
table.insert(formspec, minetest.formspec_escape(param.for_player))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec,
|
||||
"button[9.0,7.75;4.5,0.6;show_stored_value_for_player;Show value for this player]"..
|
||||
"tooltip[stored_value_for_player;Enter the name of the player for which you\n"..
|
||||
"want to check (or change) the stored value.]"..
|
||||
"tooltip[show_stored_value_for_player;Click here to read and the current value"..
|
||||
"\nstored for this player.]")
|
||||
if(param.for_player and param.for_player ~= "") then
|
||||
local v = yl_speak_up.get_quest_variable_value(param.for_player, k_long) or ""
|
||||
table.insert(formspec,
|
||||
"label[0.2,9.05;Found stored value:]"..
|
||||
"field[4.9,8.75;4.0,0.6;current_value_for_player;;")
|
||||
table.insert(formspec, minetest.formspec_escape(v))
|
||||
table.insert(formspec, "]"..
|
||||
"tooltip[current_value_for_player;You can see and change the current "..
|
||||
"value here.]"..
|
||||
"button[9.0,8.75;4.5,0.6;store_new_value_for_player;"..
|
||||
"Store this as new value]"..
|
||||
"tooltip[store_new_value_for_player;"..
|
||||
"Click here to update the stored value for this player."..
|
||||
"\nWARNING: Be very careful here and never do this without"..
|
||||
"\n informing the player about this change!]"..
|
||||
"button[13.9,8.75;3.0,0.6;unset_value_for_player;"..
|
||||
"Remove this entry]"..
|
||||
"tooltip[unset_value_for_player;Click here to delete the entry for this "..
|
||||
"player.\nSetting the entry to an empty string would not be "..
|
||||
"the same!]")
|
||||
end
|
||||
table.insert(formspec, "button[12.2,2.15;3.0,0.6;show_var_usage;Where is it used?]"..
|
||||
"tooltip[show_var_usage;Show which NPC use this variable in which context.]"..
|
||||
-- offer a dropdown list and a text input field for new varialbe names for adding
|
||||
"label[0.2,3.25;Players with read access to this variable:]")
|
||||
table.insert(formspec, yl_speak_up.create_dropdown_playerlist(player, pname,
|
||||
pl_with_read_access,
|
||||
yl_speak_up.speak_to[pname].tmp_index_var_read_access,
|
||||
6.9, 2.95, 0.0, 0.6, "list_var_read_access", "player",
|
||||
"Remove player from list",
|
||||
"grant_player_var_read_access",
|
||||
"Enter the name of the player that shall\n"..
|
||||
"have read access to this variable.",
|
||||
"revoke_player_var_read_access",
|
||||
"If you click here, the selected player\n"..
|
||||
"will no longer be able to add new\n"..
|
||||
"pre(C)onditions which read your variable."))
|
||||
table.insert(formspec, "label[0.2,4.25;Players with *write* access to this variable:]")
|
||||
table.insert(formspec, yl_speak_up.create_dropdown_playerlist(player, pname,
|
||||
pl_with_write_access,
|
||||
yl_speak_up.speak_to[pname].tmp_index_var_write_access,
|
||||
6.9, 3.95, 0.0, 0.6,
|
||||
"list_var_write_access", "player", "Remove player from list",
|
||||
"grant_player_var_write_access",
|
||||
"Enter the name of the player that shall\n"..
|
||||
"have *write* access to this variable.",
|
||||
"revoke_player_var_write_access",
|
||||
"If you click here, the selected player\n"..
|
||||
"will no longer be able to *write* new\n"..
|
||||
"values into this variable."))
|
||||
local var_type = (yl_speak_up.get_variable_metadata(k_long, "var_type")
|
||||
or "String/text or numerical value, depending on how you use it")
|
||||
table.insert(formspec, "label[0.2,5.05;Type of variable: ")
|
||||
table.insert(formspec, minetest.colorize("#FFFF00", var_type)) -- show variable type
|
||||
table.insert(formspec, ".]")
|
||||
if(var_type == "quest") then
|
||||
table.insert(formspec, "button[4.2,4.75;4.5,0.6;show_quest;Show and edit this quest]")
|
||||
end
|
||||
table.insert(formspec, "label[0.2,6.05;This variable is used by the following ")
|
||||
table.insert(formspec,
|
||||
minetest.colorize("#FFFF00", tostring(c1)).." NPC:\n\t"..
|
||||
-- those are only n_id - no need to formspec_escape that
|
||||
minetest.colorize("#FFFF00", list_of_npc_users))
|
||||
table.insert(formspec, ".]")
|
||||
table.insert(formspec, "label[0.2,7.05;This variable is used by the following ")
|
||||
table.insert(formspec,
|
||||
minetest.colorize("#FFFF00", tostring(c2)).." node positions:\n\t"..
|
||||
-- those are only pos_to_string(..) - no need to formspec_escape that
|
||||
minetest.colorize("#FFFF00", list_of_node_pos_users))
|
||||
table.insert(formspec, ".]")
|
||||
table.insert(formspec,
|
||||
"button[0.2,10.05;4.0,0.6;show_stored_values_for_var;Show all stored values]"..
|
||||
"tooltip[show_stored_values_for_var;A diffrent value can be stored for each "..
|
||||
"player.\nShow these values in a table.]")
|
||||
end
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("manage_variables",
|
||||
yl_speak_up.input_fs_manage_variables,
|
||||
yl_speak_up.get_fs_manage_variables,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,66 +0,0 @@
|
|||
|
||||
|
||||
yl_speak_up.input_notes = function(player, formname, fields)
|
||||
if(fields and fields.back) then
|
||||
return yl_speak_up.show_fs(player, "talk")
|
||||
elseif(fields and fields.store_notes and fields.notes_text) then
|
||||
local pname = player:get_player_name()
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
-- update the dialog data the player sees
|
||||
dialog.d_notes = fields.notes_text
|
||||
-- actually store/update it on disc as well
|
||||
local stored_dialog = yl_speak_up.load_dialog(n_id, false)
|
||||
stored_dialog.d_notes = dialog.d_notes
|
||||
yl_speak_up.save_dialog(n_id, stored_dialog)
|
||||
-- log the change
|
||||
yl_speak_up.log_change(pname, n_id, "Updated notes to: "..tostring(dialog.d_notes))
|
||||
return yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:notes",
|
||||
formspec = "size[10,3]"..
|
||||
"label[0.5,1.0;Notes successfully updated.]"..
|
||||
"button[3.5,2.0;2,0.9;back_from_error_msg;Back]"
|
||||
})
|
||||
else
|
||||
return yl_speak_up.show_fs(player, "notes")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_notes = function(player, param)
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
-- generic dialogs are not part of the NPC
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
return table.concat({"size[20,20]",
|
||||
"label[2,0.5;Internal notes on NPC ",
|
||||
minetest.formspec_escape(n_id or "- ? -"),
|
||||
", named ",
|
||||
minetest.formspec_escape(dialog.n_npc) or "- ? -",
|
||||
"]",
|
||||
"button[17.8,0.2;2.0,0.9;back;Back]",
|
||||
"button[15.0,0.2;2.0,0.9;store_notes;Save]",
|
||||
"textarea[0.2,2;19.6,13;notes_text;Notes (shown only to those who can edit this NPC):;",
|
||||
minetest.formspec_escape(dialog.d_notes or "Enter text here."),
|
||||
"]",
|
||||
"textarea[0.2,15.2;19.6,4.8;;;",
|
||||
"This can be used to make your NPC more intresting by storing information about..\n"..
|
||||
"* its character\n"..
|
||||
"* special characteristics of the NPC\n"..
|
||||
"* linguistic peculiarities and habits\n"..
|
||||
"* origin, relationships, lots of lore\n"..
|
||||
"* friendships / enmities\n"..
|
||||
"* personal goals / motivations / background\n"..
|
||||
"* planned quests\n"..
|
||||
"* trades\n"..
|
||||
"and whatever else you want to keep notes on for this NPC.]"
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("notes",
|
||||
yl_speak_up.input_notes,
|
||||
yl_speak_up.get_fs_notes,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,139 +0,0 @@
|
|||
-- allow owner to see and edit properties of the NPC
|
||||
|
||||
yl_speak_up.input_properties = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
if(not(pname) or not(yl_speak_up.speak_to[pname])) then
|
||||
return
|
||||
end
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
|
||||
if(fields and fields.back and fields.back ~= "") then
|
||||
yl_speak_up.show_fs(player, "initial_config",
|
||||
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false})
|
||||
return
|
||||
end
|
||||
|
||||
local selected_row = nil
|
||||
if(fields and fields.store_new_val and fields.store_new_val ~= "" and fields.prop_val) then
|
||||
yl_speak_up.set_npc_property(pname, fields.prop_name, fields.prop_val, "manually")
|
||||
|
||||
elseif(fields and fields.delete_prop and fields.delete_prop ~= "") then
|
||||
-- delete the old property
|
||||
yl_speak_up.set_npc_property(pname, fields.prop_name, nil, "manually")
|
||||
|
||||
elseif(fields and fields.table_of_properties) then
|
||||
local selected = minetest.explode_table_event(fields.table_of_properties)
|
||||
if(selected.type == "CHG" or selected.type == "DLC") then
|
||||
selected_row = selected.row
|
||||
end
|
||||
end
|
||||
yl_speak_up.show_fs(player, "properties", {selected = selected_row})
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_properties = function(pname, selected)
|
||||
if(not(pname)) then
|
||||
return ""
|
||||
end
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
|
||||
-- is the player editing this npc? if not: abort
|
||||
if(not(yl_speak_up.edit_mode[pname])
|
||||
or (yl_speak_up.edit_mode[pname] ~= n_id)) then
|
||||
return ""
|
||||
end
|
||||
|
||||
-- we want the long version with additional information
|
||||
local property_data = yl_speak_up.get_npc_properties_long_version(pname, true)
|
||||
if(not(property_data)) then
|
||||
-- something went wrong - there really is nothing useful we can do
|
||||
-- if the NPC we want to interact with doesn't exist or is broken
|
||||
return
|
||||
end
|
||||
local s = ""
|
||||
if(not(property_data.prop_names)) then
|
||||
property_data.prop_names = {}
|
||||
end
|
||||
local anz_prop = #property_data.prop_names
|
||||
for i, k in ipairs(property_data.prop_names) do
|
||||
local v = property_data.properties[k]
|
||||
s = s.."#BBBBFF,"..minetest.formspec_escape(k)..","..minetest.formspec_escape(v)..","
|
||||
end
|
||||
s = s.."#00FF00,add,Add a new property"
|
||||
|
||||
if(not(selected) or selected == "") then
|
||||
selected = -1
|
||||
end
|
||||
local add_selected = "label[3.5,6.5;No property selected.]"
|
||||
selected = tonumber(selected)
|
||||
if(selected > anz_prop + 1 or selected < 1) then
|
||||
selected = -1
|
||||
elseif(selected > anz_prop) then
|
||||
add_selected = "label[0.2,6.5;Add new property:]"..
|
||||
"field[3.0,6.5;3.5,1.0;prop_name;;]"..
|
||||
"label[6.5,6.5;with value:]"..
|
||||
"field[8.2,6.5;4.5,1.0;prop_val;;]"..
|
||||
"button[8.2,7.8;2.0,1.0;store_new_val;Store]"
|
||||
-- external properties can usually only be read but not be changed
|
||||
elseif(string.sub(property_data.prop_names[selected], 1, 5) == "self."
|
||||
and not(yl_speak_up.custom_property_handler[property_data.prop_names[selected]])) then
|
||||
add_selected = "label[3.5,6.5;Properties of the type \"self.\" usually cannot be modified.]"
|
||||
elseif(string.sub(property_data.prop_names[selected], 1, 6) == "server"
|
||||
and not(minetest.check_player_privs(pname, {npc_talk_admin=true}))) then
|
||||
add_selected = "label[3.5,6.5;Properties starting with \"server\" can only be "..
|
||||
"changed by players\nwho have the \"npc_talk_admin\" priv."
|
||||
else
|
||||
local name = property_data.prop_names[selected]
|
||||
local val = minetest.formspec_escape(property_data.properties[name])
|
||||
local name_esc = minetest.formspec_escape(name)
|
||||
add_selected = "label[0.2,6.5;Change property:]"..
|
||||
"field[3.0,6.5;3.5,1.0;prop_name;;"..name_esc.."]"..
|
||||
"label[6.5,6.5;to value:]"..
|
||||
"field[8.2,6.5;4.5,1.0;prop_val;;"..val.."]"..
|
||||
"button[8.2,7.8;2.0,1.0;store_new_val;Store]"..
|
||||
"button[10.4,7.8;2.0,1.0;delete_prop;Delete]"
|
||||
end
|
||||
if(selected < 1) then
|
||||
selected = ""
|
||||
end
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local npc_name = minetest.formspec_escape(dialog.n_npc or "- nameless -")
|
||||
return table.concat({"size[12.5,8.5]",
|
||||
"label[2,0;Properties of ",
|
||||
npc_name,
|
||||
" (ID: ",
|
||||
tostring(n_id),
|
||||
"):]",
|
||||
"tablecolumns[color,span=1;text;text]",
|
||||
"table[0.2,0.5;12,4.0;table_of_properties;",
|
||||
s,
|
||||
";",
|
||||
tostring(selected),
|
||||
"]",
|
||||
"tooltip[0.2,0.5;12,4.0;",
|
||||
"Click on \"add\" to add a new property.\n",
|
||||
"Click on the name of a property to change or delete it.]",
|
||||
"label[2.0,4.5;"..
|
||||
"Properties are important for NPC that want to make use of generic dialogs.\n"..
|
||||
"Properties can be used to determine which generic dialog(s) shall apply to\n"..
|
||||
"this particular NPC and how they shall be configured. You need the\n"..
|
||||
"\"npc_talk_admin\" priv to edit properties starting with the text \"server\".]",
|
||||
"button[5.0,7.8;2.0,0.9;back;Back]",
|
||||
add_selected
|
||||
}, "")
|
||||
end
|
||||
|
||||
yl_speak_up.get_fs_properties_wrapper = function(player, param)
|
||||
if(not(param)) then
|
||||
param = {}
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
return yl_speak_up.get_fs_properties(pname, param.selected)
|
||||
end
|
||||
|
||||
yl_speak_up.register_fs("properties",
|
||||
yl_speak_up.input_properties,
|
||||
yl_speak_up.get_fs_properties_wrapper,
|
||||
-- force formspec version 1:
|
||||
1
|
||||
)
|
|
@ -1,41 +0,0 @@
|
|||
yl_speak_up.input_quest_gui = function(player, formname, fields)
|
||||
-- this return value is necessary for custom actions
|
||||
local ret = {quit = true}
|
||||
|
||||
local pname = player:get_player_name()
|
||||
if(fields and fields.back_from_msg) then
|
||||
yl_speak_up.show_fs(player, "quest_gui")
|
||||
return ret
|
||||
end
|
||||
|
||||
-- new variables have to be added (and deleted) somewhere after all
|
||||
if(fields.manage_variables) then
|
||||
-- remember which formspec we are comming from
|
||||
yl_speak_up.speak_to[pname][ "working_at" ] = "quest_gui"
|
||||
yl_speak_up.show_fs(player, "manage_variables")
|
||||
return ret
|
||||
elseif(fields.manage_quests) then
|
||||
yl_speak_up.speak_to[pname][ "working_at" ] = "quest_gui"
|
||||
yl_speak_up.show_fs(player, "manage_quests")
|
||||
return ret
|
||||
end
|
||||
-- the calling NPC shall no longer do anything
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_quest_gui = function(player, param)
|
||||
local pname = player:get_player_name()
|
||||
return "size[24,20]"..
|
||||
"label[0,0.5;Hi. This is a quest admin gui.]"..
|
||||
"button[0.2,1.0;4.0,0.6;manage_variables;Manage variables]"..
|
||||
"button[6.2,1.0;4.0,0.6;manage_quests;Manage quests]"
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("quest_gui",
|
||||
yl_speak_up.input_quest_gui,
|
||||
yl_speak_up.get_fs_quest_gui,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,147 +0,0 @@
|
|||
|
||||
-- when the player is editing the NPC and has changed it without having
|
||||
-- saved the changes yet: ask what shall be done (save? discard? back?)
|
||||
yl_speak_up.input_save_or_discard_changes = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
-- if the player is not even talking to this particular npc
|
||||
if(not(yl_speak_up.speak_to[pname])) then
|
||||
return
|
||||
end
|
||||
|
||||
local target_dialog = yl_speak_up.speak_to[pname].target_dialog
|
||||
if(not(target_dialog)) then
|
||||
target_dialog = ""
|
||||
end
|
||||
|
||||
local edit_mode = (yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id)
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
|
||||
-- the player decided to go back and continue editing the current dialog
|
||||
if(edit_mode and fields.back_to_dialog_changes) then
|
||||
-- do NOT clear the list of changes; just show the old dialog again
|
||||
yl_speak_up.show_fs(player, "show_last_fs", {})
|
||||
return
|
||||
|
||||
-- save changes and continue on to the next dialog
|
||||
elseif(edit_mode and fields.save_dialog_changes) then
|
||||
-- actually save the dialog (the one the NPC currently has)
|
||||
yl_speak_up.save_dialog(n_id, yl_speak_up.speak_to[pname].dialog)
|
||||
-- log all the changes
|
||||
for i, c in ipairs(yl_speak_up.npc_was_changed[ n_id ]) do
|
||||
yl_speak_up.log_change(pname, n_id, c)
|
||||
end
|
||||
-- clear list of changes
|
||||
yl_speak_up.npc_was_changed[ n_id ] = {}
|
||||
-- save_dialog removed d_dynamic (because that is never to be saved!); we have
|
||||
-- to add d_dynamic back so that we can use it as a target dialog in further editing:
|
||||
yl_speak_up.speak_to[pname].dialog.n_dialogs["d_dynamic"] = {}
|
||||
yl_speak_up.speak_to[pname].dialog.n_dialogs["d_dynamic"].d_options = {}
|
||||
|
||||
-- discard changes and continue on to the next dialog
|
||||
elseif(edit_mode and fields.discard_dialog_changes) then
|
||||
-- the current dialog and the one we want to show next may both be new dialogs;
|
||||
-- if we just reload the old state, they would both get lost
|
||||
local target_dialog_data = yl_speak_up.speak_to[pname].dialog.n_dialogs[ target_dialog ]
|
||||
-- actually restore the old state and discard the changes by loading the dialog anew
|
||||
yl_speak_up.speak_to[pname].dialog = yl_speak_up.load_dialog(n_id, false)
|
||||
-- clear list of changes
|
||||
yl_speak_up.npc_was_changed[ n_id ] = {}
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
-- do we have to save again after restoring current and target dialog?
|
||||
local need_to_save = false
|
||||
-- if the current dialog was a new one, it will be gone now - restore it
|
||||
if(d_id and d_id ~= "" and not(dialog.n_dialogs[ d_id ])) then
|
||||
-- we can't just restore the current dialog - after all the player wanted
|
||||
-- to discard the changes; but we can recreate the current dialog so that it
|
||||
-- is in the "new dialog" state again
|
||||
local next_id = tonumber(string.sub( d_id, 3))
|
||||
yl_speak_up.add_new_dialog(dialog, pname, next_id)
|
||||
yl_speak_up.log_change(pname, n_id, "Saved new dialog "..tostring( d_id )..".")
|
||||
need_to_save = true
|
||||
end
|
||||
if(target_dialog and target_dialog ~= "" and not(dialog.n_dialogs[ target_dialog ])) then
|
||||
-- restore the new target dialog
|
||||
dialog.n_dialogs[ target_dialog ] = target_dialog_data
|
||||
yl_speak_up.log_change(pname, n_id, "Saved new dialog "..tostring( target_dialog )..".")
|
||||
need_to_save = true
|
||||
end
|
||||
if(need_to_save) then
|
||||
yl_speak_up.save_dialog(n_id, dialog)
|
||||
end
|
||||
end
|
||||
|
||||
-- are there any changes which might be saved or discarded?
|
||||
if(edit_mode
|
||||
and yl_speak_up.npc_was_changed[ n_id ]
|
||||
and #yl_speak_up.npc_was_changed[ n_id ] > 0) then
|
||||
|
||||
yl_speak_up.show_fs(player, "save_or_discard_changes", {})
|
||||
return
|
||||
end
|
||||
|
||||
yl_speak_up.show_fs(player, "proceed_after_save", {})
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.get_fs_save_or_discard_changes = function(player, param)
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
-- TODO
|
||||
local target_name = "quit"
|
||||
local target_dialog = nil -- TODO
|
||||
if(target_dialog and target_dialog ~= "") then
|
||||
target_name = "go on to dialog "..minetest.formspec_escape(target_dialog)
|
||||
if(target_dialog == "edit_option_dialog") then
|
||||
target_name = "edit option \""..
|
||||
minetest.formspec_escape(tostring(o_id)).."\" of dialog \""..
|
||||
minetest.formspec_escape(tostring(d_id)).."\""
|
||||
end
|
||||
end
|
||||
|
||||
yl_speak_up.speak_to[pname].target_dialog = target_dialog
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
-- reverse the order of the changes in the log so that newest are topmost
|
||||
local text = ""
|
||||
for i,t in ipairs(yl_speak_up.npc_was_changed[ n_id ]) do
|
||||
text = minetest.formspec_escape(t).."\n"..text
|
||||
end
|
||||
-- build a formspec showing the changes to this dialog and ask for save
|
||||
return table.concat({"size[14,6.2]",
|
||||
"bgcolor[#00000000;false]",
|
||||
-- TODO: make this more flexible
|
||||
"label[0.2,0.2;You are about to leave dialog ",
|
||||
minetest.formspec_escape(d_id),
|
||||
" and ",
|
||||
target_name,
|
||||
".]",
|
||||
"label[0.2,0.65;These changes have been applied to dialog ",
|
||||
minetest.formspec_escape(d_id),
|
||||
":]",
|
||||
"hypertext[0.2,1;13.5,4;list_of_changes;<normal>",
|
||||
minetest.formspec_escape(text),
|
||||
"\n</normal>",
|
||||
"]",
|
||||
"button_exit[1.2,5.2;3,0.9;discard_dialog_changes;Discard changes]",
|
||||
"button[5.7,5.2;3,0.9;back_to_dialog_changes;Back]",
|
||||
"button_exit[10.2,5.2;3,0.9;save_dialog_changes;Save changes]",
|
||||
"tooltip[save_dialog_changes;Save all changes to this dialog and ",
|
||||
target_name,
|
||||
".]",
|
||||
"tooltip[discard_dialog_changes;Undo all changes and ",
|
||||
target_name,
|
||||
".]",
|
||||
"tooltip[back_to_dialog_changes;Go back to dialog ",
|
||||
minetest.formspec_escape(d_id),
|
||||
" and continue editing it.]"
|
||||
}, "")
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("save_or_discard_changes",
|
||||
yl_speak_up.input_save_or_discard_changes,
|
||||
yl_speak_up.get_fs_save_or_discard_changes,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,64 +0,0 @@
|
|||
|
||||
-- called only by mange_variables formspec
|
||||
yl_speak_up.fs_show_all_var_values = function(player, pname, var_name)
|
||||
-- wrong parameters? no need to show an error message here
|
||||
if(not(var_name) or not(pname) or not(player)) then
|
||||
return ""
|
||||
end
|
||||
-- TODO: check if the player really has read access to this variable
|
||||
var_name = yl_speak_up.restore_complete_var_name(var_name, pname)
|
||||
|
||||
-- player names with values as key; normally the player name is the key and
|
||||
-- the value the value - but that would be a too long list to display, and
|
||||
-- so we rearrange the array for display here
|
||||
local players_with_value = {}
|
||||
-- the diffrent values that exist
|
||||
local values = {}
|
||||
local var_data = yl_speak_up.player_vars[ var_name ]
|
||||
local count_players = 0
|
||||
for player_name, v in pairs(var_data) do
|
||||
-- metadata is diffrent and not of relevance here
|
||||
if(player_name and player_name ~= "$META$" and v) then
|
||||
if(not(players_with_value[ v ])) then
|
||||
players_with_value[ v ] = {}
|
||||
table.insert(values, v)
|
||||
end
|
||||
table.insert(players_with_value[ v ], player_name)
|
||||
count_players = count_players + 1
|
||||
end
|
||||
end
|
||||
-- the values ought to be shown in a sorted way
|
||||
table.sort(values)
|
||||
|
||||
-- construct the lines that shall form the table
|
||||
local lines = {"#FFFFFF,Value:,#FFFFFF,Players for which this value is stored:"}
|
||||
for i, v in ipairs(values) do
|
||||
table.insert(lines,
|
||||
"#FFFF00,"..minetest.formspec_escape(v)..",#CCCCCC,"..
|
||||
-- text, prefix, line_length, max_lines
|
||||
yl_speak_up.wrap_long_lines_for_table(
|
||||
table.concat(players_with_value[ v ], ", "),
|
||||
",,,#CCCCCC,", 80, 8))
|
||||
end
|
||||
-- true here means: lines are already sorted;
|
||||
-- ",": don't insert blank lines between entries
|
||||
local formspec = yl_speak_up.print_as_table_prepare_formspec(lines, "table_of_variable_values",
|
||||
"back_from_msg", "Back", true, ",",
|
||||
"color,span=1;text;color,span=1;text") -- the table columns
|
||||
table.insert(formspec,
|
||||
"label[18.0,1.8;"..
|
||||
minetest.formspec_escape("For variable \""..
|
||||
minetest.colorize("#FFFF00", tostring(var_name or "- ? -"))..
|
||||
"\", these values are stored:").."]")
|
||||
|
||||
if(values and #values > 0) then
|
||||
table.insert(formspec,
|
||||
"label[18.0,31.0;The variable holds "..
|
||||
minetest.colorize("#FFFF00", tostring(#values)).." diffrent values for "..
|
||||
minetest.colorize("#FFFF00", tostring(count_players)).." diffrent players.]")
|
||||
else
|
||||
table.insert(formspec,
|
||||
"label[18.0,31.0;The variable does not currently hold any stored values.]")
|
||||
end
|
||||
return table.concat(formspec, "\n")
|
||||
end
|
|
@ -1,256 +0,0 @@
|
|||
-- helpful for debugging the content/texts of the created dialog structure
|
||||
|
||||
yl_speak_up.input_show_what_points_to_this_dialog = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
if(fields.back_from_show_what_points_here
|
||||
or not(fields.turn_dialog_into_alternate_text)) then
|
||||
-- back to the dialog
|
||||
yl_speak_up.show_fs(player, "talk",
|
||||
{n_id = yl_speak_up.speak_to[pname].n_id,
|
||||
d_id = yl_speak_up.speak_to[pname].d_id})
|
||||
return
|
||||
end
|
||||
-- fields.turn_dialog_into_alternate_text is set
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local this_dialog = yl_speak_up.speak_to[pname].d_id
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
if(not(dialog)
|
||||
or not(dialog.n_dialogs)
|
||||
or not(this_dialog)
|
||||
or not(dialog.n_dialogs[ this_dialog ])) then
|
||||
return
|
||||
end
|
||||
-- only show this information when editing this npc
|
||||
if(yl_speak_up.edit_mode[pname] ~= yl_speak_up.speak_to[pname].n_id) then
|
||||
return
|
||||
end
|
||||
-- find out what needs to be turned into an alternate dialog
|
||||
local found = {}
|
||||
-- how many options does the current dialog have?
|
||||
local count_options = 0
|
||||
-- iterate over all dialogs
|
||||
for d_id, d in pairs(dialog.n_dialogs) do
|
||||
-- the dialog itself may have options that point back to the dialog itself
|
||||
if(d.d_options) then
|
||||
-- iterate over all options
|
||||
for o_id, o in pairs(d.d_options) do
|
||||
-- this is only possible if there are no options for this dialog
|
||||
if(d_id == this_dialog) then
|
||||
count_options = count_options + 1
|
||||
end
|
||||
-- preconditions are not relevant;
|
||||
-- effects are (dialog and on_failure)
|
||||
if(o.o_results) then
|
||||
for r_id, r in pairs(o.o_results) do
|
||||
if(r and r.r_type and r.r_type == "dialog"
|
||||
and r.r_value == this_dialog) then
|
||||
table.insert(found, {d_id=d_id, o_id=o_id, id=r_id,
|
||||
element=r, text="option was selected"})
|
||||
elseif(r and r.r_type and r.r_type == "on_failure"
|
||||
and r.r_value == this_dialog) then
|
||||
table.insert(found, {d_id=d_id, o_id=o_id, id=r_id,
|
||||
element=r, text="the previous effect failed"})
|
||||
end
|
||||
end
|
||||
end
|
||||
-- actions may be relevant
|
||||
if(o.actions) then
|
||||
for a_id, a in pairs(o.actions) do
|
||||
if(a and a.a_on_failure
|
||||
and a.a_on_failure == this_dialog) then
|
||||
table.insert(found, {d_id=d_id, o_id=o_id, id=a_id,
|
||||
element=a, text="action failed"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local error_msg = ""
|
||||
if(count_options > 0) then
|
||||
error_msg = "This dialog still has dialog options.\nConversion not possible."
|
||||
elseif(#found < 1) then
|
||||
error_msg = "Found no option, action or effect\nthat points to this dialog."
|
||||
elseif(#found > 1) then
|
||||
error_msg = "Found more than one option, action\nor effect that points to this dialog."
|
||||
end
|
||||
if(error_msg ~= "") then
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:show_what_points_to_this_dialog",
|
||||
formspec = "size[8,2]"..
|
||||
"label[0.2,0.5;Error: "..error_msg.."]"..
|
||||
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
|
||||
return
|
||||
end
|
||||
|
||||
-- all fine so far; this is the text we want to set as alternate text
|
||||
local d_text = dialog.n_dialogs[ this_dialog ].d_text
|
||||
local f = found[1]
|
||||
-- are we dealing with a result/effect or an action?
|
||||
t = "o_results"
|
||||
if(f.element.a_id) then
|
||||
t = "actions"
|
||||
end
|
||||
-- there may already be an alternate text stored there
|
||||
local alternate_text = dialog.n_dialogs[ f.d_id ].d_options[ f.o_id ][ t ][ f.id ].alternate_text
|
||||
if(not(alternate_text)) then
|
||||
-- no old text found
|
||||
alternate_text = d_text
|
||||
else
|
||||
-- the old text may reference this d_text
|
||||
alternate_text = string.gsub(alternate_text, "%$TEXT%$", d_text)
|
||||
end
|
||||
-- log the change
|
||||
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
||||
"Dialog "..tostring(this_dialog)..": Deleted this dialog and turned it into an "..
|
||||
"alternate text for dialog \""..tostring(f.d_id).."\" option \""..tostring(f.o_id)..
|
||||
"\" element \""..tostring(f.id).."\".")
|
||||
|
||||
-- actually set the new alternate_text
|
||||
dialog.n_dialogs[ f.d_id ].d_options[ f.o_id ][ t ][ f.id ].alternate_text = alternate_text
|
||||
-- delete this dialog
|
||||
dialog.n_dialogs[ this_dialog ] = nil
|
||||
-- we need to show a new/diffrent dialog to the player now - because the old one was deleted
|
||||
yl_speak_up.speak_to[pname].d_id = f.d_id
|
||||
yl_speak_up.speak_to[pname].o_id = f.o_id
|
||||
if(t == "o_results") then
|
||||
-- we can't really know where this ought to point to - the old dialog is gone, so
|
||||
-- let's point to the current dialog to avoid errors
|
||||
dialog.n_dialogs[ f.d_id ].d_options[ f.o_id ][ t ][ f.id ].r_value = f.d_id
|
||||
-- dialog - normal switching to the next dialog or on_failure - the previous effect failed:
|
||||
yl_speak_up.show_fs(player, "edit_effects", f.id)
|
||||
else
|
||||
-- the player may have to change this manually; we really can't know what would fit
|
||||
-- (but the old dialog is gone)
|
||||
dialog.n_dialogs[ f.d_id ].d_options[ f.o_id ][ t ][ f.id ].a_on_failure = f.d_id
|
||||
-- an action failed:
|
||||
yl_speak_up.show_fs(player, "edit_actions", f.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- show which dialogs point/lead to this_dialog
|
||||
yl_speak_up.get_fs_show_what_points_to_this_dialog = function(player, this_dialog)
|
||||
local pname = player:get_player_name()
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
if(not(dialog)
|
||||
or not(dialog.n_dialogs)
|
||||
or not(this_dialog)
|
||||
or not(dialog.n_dialogs[ this_dialog ])) then
|
||||
return ""
|
||||
end
|
||||
|
||||
-- only show this information when editing this npc
|
||||
if(yl_speak_up.edit_mode[pname] ~= yl_speak_up.speak_to[pname].n_id) then
|
||||
return ""
|
||||
end
|
||||
local found = {}
|
||||
-- colored lines for the table showing the results
|
||||
local res = {}
|
||||
-- iterate over all dialogs
|
||||
for d_id, d in pairs(dialog.n_dialogs) do
|
||||
-- the dialog itself may have options that point back to the dialog itself
|
||||
if(d.d_options) then
|
||||
-- iterate over all options
|
||||
for o_id, o in pairs(d.d_options) do
|
||||
local r_text = ""
|
||||
local p_text = ""
|
||||
local alternate_dialog = nil
|
||||
local alternate_text = nil
|
||||
-- preconditions are not relevant;
|
||||
-- effects are (dialog and on_failure)
|
||||
if(o.o_results) then
|
||||
for r_id, r in pairs(o.o_results) do
|
||||
if(r and r.r_type and r.r_type == "dialog"
|
||||
and r.r_value == this_dialog) then
|
||||
r_text = r_text..yl_speak_up.print_as_table_effect(
|
||||
r, pname)
|
||||
table.insert(found, {d_id, o_id, r_id,
|
||||
"option was selected"})
|
||||
alternate_dialog = r.r_value
|
||||
if(r.alternate_text) then
|
||||
alternate_text =
|
||||
"Show alternate text: "..
|
||||
tostring(r.alternate_text)
|
||||
end
|
||||
elseif(r and r.r_type and r.r_type == "on_failure"
|
||||
and r.r_value == this_dialog) then
|
||||
r_text = r_text..yl_speak_up.print_as_table_effect(
|
||||
r, pname)
|
||||
table.insert(found, {d_id, o_id, r_id,
|
||||
"the previous effect failed"})
|
||||
alternate_dialog = r.r_value
|
||||
alternate_text = "The previous effect failed. "
|
||||
if(r.alternate_text) then
|
||||
alternate_text = alternate_text..
|
||||
"Show alternate text: "..
|
||||
tostring(r.alternate_text)
|
||||
else
|
||||
alternate_text = alternate_text..
|
||||
"Show this dialog here."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- actions may be relevant
|
||||
if(o.actions) then
|
||||
for a_id, a in pairs(o.actions) do
|
||||
if(a and a.a_on_failure
|
||||
and a.a_on_failure == this_dialog) then
|
||||
p_text = p_text..yl_speak_up.print_as_table_action(
|
||||
a, pname)
|
||||
table.insert(found, {d_id, o_id, a_id,
|
||||
"action failed"})
|
||||
alternate_dialog = a.a_on_failure
|
||||
alternate_text = "The action failed. "
|
||||
if(a.alternate_text) then
|
||||
alternate_text = alternate_text..
|
||||
"Show this alternate text: "..
|
||||
tostring(a.alternate_text)
|
||||
else
|
||||
alternate_text = alternate_text..
|
||||
"Show this dialog here."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
yl_speak_up.print_as_table_dialog(p_text, r_text, dialog,
|
||||
dialog.n_id, d_id, o_id,
|
||||
-- sort value: formed by dialog and option id (not perfect but
|
||||
-- good enough)
|
||||
res, o, tostring(d_id).." "..tostring(o_id),
|
||||
alternate_dialog, alternate_text)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local d_id = this_dialog
|
||||
local formspec = yl_speak_up.print_as_table_prepare_formspec(res, "table_of_dialog_uses",
|
||||
"back_from_show_what_points_here", "Back to dialog \""..tostring(d_id).."\"")
|
||||
table.insert(formspec,
|
||||
"label[20.0,1.8;Dialog \""..minetest.formspec_escape(this_dialog)..
|
||||
"\" is referenced here:]")
|
||||
if(#found ~= 1) then
|
||||
table.insert(formspec,
|
||||
"label[16.0,31.0;"..
|
||||
minetest.formspec_escape("This dialog \""..tostring(d_id)..
|
||||
"\" can be reached from "..
|
||||
minetest.colorize("#FFFF00", tostring(#found))..
|
||||
" options/actions/results.").."]")
|
||||
else
|
||||
table.insert(formspec,
|
||||
"button[0.2,30.6;56.6,1.2;turn_dialog_into_alternate_text;"..
|
||||
minetest.formspec_escape("Turn this dialog \""..
|
||||
tostring(d_id)).."\" into an alternate text.]")
|
||||
end
|
||||
return table.concat(formspec, "\n")
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.register_fs("show_what_points_to_this_dialog",
|
||||
yl_speak_up.input_show_what_points_to_this_dialog,
|
||||
yl_speak_up.get_fs_show_what_points_to_this_dialog,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
|
@ -1,753 +0,0 @@
|
|||
|
||||
-- we have a better version of this in the editor - so not offer this particular entry:
|
||||
yl_speak_up.get_fs_talkdialog_add_basic_edit = function(
|
||||
pname, formspec, h, pname_for_old_fs, is_a_start_dialog,
|
||||
active_dialog, luaentity, may_edit_npc, anz_options)
|
||||
return {h = h, formspec = formspec}
|
||||
end
|
||||
|
||||
|
||||
-- This is the main talkdialog the NPC shows when right-clicked. (now in edit_mode)
|
||||
local old_input_talk = yl_speak_up.input_talk
|
||||
yl_speak_up.input_talk = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
-- Is the player working on this particular npc?
|
||||
local edit_mode = yl_speak_up.in_edit_mode(pname)
|
||||
-- if not: do the normal things outside edit mode
|
||||
if(not(edit_mode) and not(fields.button_start_edit_mode)) then
|
||||
return old_input_talk(player, formname, fields)
|
||||
end
|
||||
-- selected option/answer
|
||||
local o = ""
|
||||
-- do all the processing and executing old_input_talk (in non-edit_mode)
|
||||
-- can do - but do not execute any actions; just return o
|
||||
fields.just_return_selected_option = true
|
||||
o = old_input_talk(player, formname, fields)
|
||||
-- old_input_talk handled it (including some error detection like
|
||||
-- wrong formname, not talking to npc, npc not configured)
|
||||
|
||||
-- if in edit mode: detect if something was changed;
|
||||
local result = yl_speak_up.edit_mode_apply_changes(pname, fields)
|
||||
-- o is only nil if the old function returned nil; it does that
|
||||
-- when it found a fitting reaction to a button press
|
||||
if(not(o) and not(fields.button_start_edit_mode)) then
|
||||
return
|
||||
end
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
|
||||
-- start edit mode (requires npc_talk_owner)
|
||||
if fields.button_start_edit_mode then
|
||||
-- check if this particular NPC is really owned by this player or if the player has global privs
|
||||
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
|
||||
minetest.chat_send_player(pname, "Sorry. You do not have the npc_talk_owner or npc_talk_master priv.")
|
||||
return
|
||||
end
|
||||
-- the staff allows to create multiple target dialogs as result; this makes no sense
|
||||
-- and is too disambigous
|
||||
if(yl_speak_up.check_for_disambigous_results(n_id, pname)) then
|
||||
-- this needs to be fixed by someone with a staff; we don't know which dialog is the right
|
||||
-- result
|
||||
return
|
||||
end
|
||||
-- make sure the inventory of the NPC is loaded
|
||||
yl_speak_up.load_npc_inventory(n_id, true, nil)
|
||||
-- for older formspec versions: reset scroll counter
|
||||
yl_speak_up.speak_to[pname].counter = 1
|
||||
yl_speak_up.speak_to[pname].option_index = 1
|
||||
-- enter edit mode with that particular NPC
|
||||
yl_speak_up.edit_mode[pname] = yl_speak_up.speak_to[pname].n_id
|
||||
-- load the NPC dialog anew - but only what the NPC itself has to say, no generic dialogs
|
||||
yl_speak_up.speak_to[pname].dialog = yl_speak_up.load_dialog(n_id, false)
|
||||
-- start a new chat - but this time in edit mode
|
||||
yl_speak_up.speak_to[pname].d_id = nil
|
||||
yl_speak_up.show_fs(player, "talk", {n_id = yl_speak_up.speak_to[pname].n_id, d_id = nil})
|
||||
return
|
||||
-- end edit mode (does not require the priv; will only switch back to normal behaviour)
|
||||
elseif fields.button_end_edit_mode then
|
||||
-- if there are any changes done: ask first and don't end edit mode yet
|
||||
yl_speak_up.show_fs(player, "quit", nil)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
-- show which dialogs point to this one
|
||||
if(fields.show_what_points_to_this_dialog) then
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
yl_speak_up.show_fs(player, "show_what_points_to_this_dialog",
|
||||
yl_speak_up.speak_to[pname].d_id)
|
||||
return
|
||||
end
|
||||
|
||||
-- the player wants to change name and description; show the formspec
|
||||
if(fields.button_edit_name_and_description) then
|
||||
-- this is not the initial config - but the same formspec can be used
|
||||
yl_speak_up.show_fs(player, "initial_config",
|
||||
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false})
|
||||
return
|
||||
end
|
||||
|
||||
-- change skin, cape and wielded items
|
||||
if(fields.edit_skin) then
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
-- necessary so that the fashin formspec can be created
|
||||
yl_speak_up.speak_to[pname].n_npc = dialog.n_npc
|
||||
yl_speak_up.show_fs(player, "fashion")
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.button_save_dialog) then
|
||||
yl_speak_up.show_fs(player, "talk",
|
||||
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, do_save = true})
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.button_export_dialog) then
|
||||
yl_speak_up.show_fs(player, "export")
|
||||
return
|
||||
end
|
||||
|
||||
if(fields.button_edit_notes) then
|
||||
yl_speak_up.show_fs(player, "notes")
|
||||
return
|
||||
end
|
||||
|
||||
-- the player wants to give something to the NPC
|
||||
-- (more complex in edit mode)
|
||||
if(fields.player_offers_item) then
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local future_d_id = "d_got_item"
|
||||
-- make sure this dialog exists; create if needed
|
||||
if(not(dialog.n_dialogs[ future_d_id ])) then
|
||||
dialog.n_dialogs[future_d_id] = {
|
||||
d_id = future_d_id,
|
||||
d_type = "text",
|
||||
d_text = "",
|
||||
d_sort = 9999 -- make this the last option
|
||||
}
|
||||
end
|
||||
-- in edit mode: allow to edit the options
|
||||
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = future_d_id})
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
-- button was clicked, now let's execute the results
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
|
||||
-- all three buttons (pre(C)onditions, (Ef)fects, edit option) lead to the same new formspec
|
||||
local n_dialog = dialog.n_dialogs[d_id]
|
||||
|
||||
if(n_dialog and n_dialog.d_options) then
|
||||
for o_id,v in pairs(n_dialog.d_options) do
|
||||
if( fields["edit_option_"..o_id]
|
||||
or fields["conditions_"..o_id]
|
||||
or fields["actions_"..o_id]
|
||||
or fields["quests_"..o_id]
|
||||
or fields["effects_"..o_id]) then
|
||||
-- store which option we want to edit
|
||||
yl_speak_up.speak_to[pname].o_id = o_id
|
||||
-- if something was changed: ask for confirmation
|
||||
yl_speak_up.show_fs(player, "edit_option_dialog",
|
||||
{n_id = yl_speak_up.speak_to[pname].n_id,
|
||||
d_id = d_id, o_id = o_id, caller="button"})
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- we may soon need actions and o_results from the selected_option
|
||||
local selected_option = {}
|
||||
if(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o)) then
|
||||
selected_option = dialog.n_dialogs[d_id].d_options[o]
|
||||
end
|
||||
|
||||
-- translate a dialog name into a d_id
|
||||
fields.d_id = yl_speak_up.d_name_to_d_id(dialog, fields.d_id)
|
||||
-- in edit mode: has another dialog been selected?
|
||||
-- if nothing better can be found: keep the old dialog
|
||||
local show_dialog = d_id
|
||||
-- an option button was selected;
|
||||
-- since we do not execute actions and effects in edit mode, we need to find out the
|
||||
-- right target dialog manually (and assume all went correct)
|
||||
if( o ~= "" ) then
|
||||
-- find out the normal target dialog of this option
|
||||
if(selected_option and selected_option.o_results) then
|
||||
for k, v in pairs(selected_option.o_results) do
|
||||
if(v and v.r_type == "dialog") then
|
||||
show_dialog = v.r_value
|
||||
end
|
||||
end
|
||||
end
|
||||
-- dropdown menu was used; provided the dialog exists (and it's not the "New dialog" option)
|
||||
-- (if a new dialog was added using the "+" button, fields.d_id gets set accordingly)
|
||||
elseif(fields.d_id and fields.d_id ~= show_dialog and dialog.n_dialogs[fields.d_id]) then
|
||||
show_dialog = fields.d_id
|
||||
-- in edit mode: prev_dialog_../next_dialog_.. was selected
|
||||
else
|
||||
for k,v in pairs(dialog.n_dialogs) do
|
||||
if(fields["prev_dialog_"..k]) then
|
||||
show_dialog = k
|
||||
elseif(fields["next_dialog_"..k]) then
|
||||
show_dialog = k
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = show_dialog})
|
||||
-- no option was selected - so we need to end this here
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
-- in edit mode, *all* options are displayed
|
||||
local old_calculate_displayable_options = yl_speak_up.calculate_displayable_options
|
||||
yl_speak_up.calculate_displayable_options = function(pname, d_options, allow_recursion)
|
||||
if(yl_speak_up.in_edit_mode(pname)) then
|
||||
-- no options - nothing to do
|
||||
if(not(d_options)) then
|
||||
return {}
|
||||
end
|
||||
-- in edit mode: show all options (but sort them first)
|
||||
local retval = {}
|
||||
local sorted_list = yl_speak_up.get_sorted_options(d_options, "o_sort")
|
||||
for i, o_k in ipairs(sorted_list) do
|
||||
retval[o_k] = true
|
||||
end
|
||||
return retval
|
||||
end
|
||||
-- outside edit mode: really calculate what can be displayed
|
||||
return old_calculate_displayable_options(pname, d_options, allow_recursion)
|
||||
end
|
||||
|
||||
|
||||
-- in edit mode, autoanswer, random dialogs and d_got_item play no role and are *not* applied
|
||||
-- (we want to see and edit all options regardless of preconditions)
|
||||
local old_apply_autoanswer_etc = yl_speak_up.apply_autoanswer_and_random_and_d_got_item
|
||||
yl_speak_up.apply_autoanswer_and_random_and_d_got_item = function(player, pname, d_id, dialog, allowed, active_dialog, recursion_depth)
|
||||
-- no automatic switching in edit_mode
|
||||
if(yl_speak_up.in_edit_mode(pname)) then
|
||||
return
|
||||
end
|
||||
return old_apply_autoanswer_etc(player, pname, d_id, dialog, allowed, active_dialog, recursion_depth)
|
||||
end
|
||||
|
||||
|
||||
-- helper function for yl_speak_up.get_fs_talkdialog:
|
||||
-- shows the text the NPC "speaks" and adds edit and navigation buttons
|
||||
-- (all only in *edit_mode*)
|
||||
local old_talkdialog_main_text = yl_speak_up.get_fs_talkdialog_main_text
|
||||
yl_speak_up.get_fs_talkdialog_main_text = function(pname, formspec, h, dialog, dialog_list, c_d_id, active_dialog, alternate_text)
|
||||
if(not(yl_speak_up.in_edit_mode(pname))) then
|
||||
return old_talkdialog_main_text(pname, formspec, h, dialog, dialog_list, c_d_id, active_dialog, alternate_text)
|
||||
end
|
||||
local d_id_to_dropdown_index = {}
|
||||
-- allow to change skin, wielded items etc.
|
||||
table.insert(formspec, "button[15.75,3.5;3.5,0.9;edit_skin;Edit Skin]")
|
||||
|
||||
if(not(dialog) or not(dialog.n_dialogs)) then
|
||||
return {h = h, formspec = formspec, d_id_to_dropdown_index = {}, dialog_list = dialog_list}
|
||||
end
|
||||
|
||||
-- display the window with the text the NPC is saying
|
||||
-- sort all dialogs by d_sort
|
||||
local sorted_list = yl_speak_up.get_sorted_options(dialog.n_dialogs, "d_sort")
|
||||
-- add buttons for previous/next dialog
|
||||
for i, d in ipairs(sorted_list) do
|
||||
local d_name = dialog.n_dialogs[d].d_name or d
|
||||
-- build the list of available dialogs for the dropdown list(s)
|
||||
dialog_list = dialog_list..","..minetest.formspec_escape(d_name)
|
||||
if(d == c_d_id) then
|
||||
local prev_dialog = tostring(minetest.formspec_escape(sorted_list[i-1]))
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", "15.4,5.0;2,0.9", "prev_dialog_"..prev_dialog,
|
||||
"<",
|
||||
"Go to previous dialog "..prev_dialog..".",
|
||||
(sorted_list[ i-1 ]))
|
||||
local next_dialog = tostring(minetest.formspec_escape(sorted_list[i+1]))
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", "17.6,5.0;2,0.9", "next_dialog_"..next_dialog,
|
||||
">",
|
||||
"Go to next dialog "..next_dialog..".",
|
||||
(sorted_list[ i+1 ]))
|
||||
end
|
||||
d_id_to_dropdown_index[d] = i + 1
|
||||
end
|
||||
dialog_list = dialog_list..",d_end"
|
||||
d_id_to_dropdown_index["d_end"] = #sorted_list + 2
|
||||
|
||||
|
||||
if(not(yl_speak_up.is_special_dialog(c_d_id))) then
|
||||
table.insert(formspec, "label[0.2,4.2;Dialog ")
|
||||
table.insert(formspec, minetest.formspec_escape(c_d_id))
|
||||
table.insert(formspec, ":]")
|
||||
table.insert(formspec, "field[5.0,3.6;9.8,1.2;d_name;;")
|
||||
table.insert(formspec, minetest.formspec_escape(dialog.n_dialogs[c_d_id].d_name or c_d_id))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "tooltip[d_name;Dialogs can have a *name* that is diffrent from\n"..
|
||||
"their ID (which is i.e. d_4). The name will be shown\n"..
|
||||
"in the dropdown list. Save a new name by clicking on\n"..
|
||||
"the dialog \"Save\" button.]")
|
||||
end
|
||||
|
||||
table.insert(formspec, "label[0.2,5.5;Dialog:]") -- "..minetest.formspec_escape(c_d_id)..":]")
|
||||
table.insert(formspec, "dropdown[5.0,5.0;9.8,1;d_id;"..dialog_list..";"..
|
||||
(d_id_to_dropdown_index[c_d_id] or "1")..",]")
|
||||
table.insert(formspec, "tooltip[5.0,5.0;9.8,1;"..
|
||||
"Select the dialog you want to edit. Currently, dialog "..c_d_id..
|
||||
" is beeing displayed.;#FFFFFF;#000000]")
|
||||
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", "3.5,5.0;1,0.9", "show_new_dialog",
|
||||
"+",
|
||||
"Create a new dialog.",
|
||||
true)
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", "11.0,0.3;2,1.0", "button_edit_notes",
|
||||
"Notes",
|
||||
"Keep notes of what this NPC is for, how his character is etc.",
|
||||
true)
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", "13.2,0.3;2,0.9", "button_edit_name_and_description",
|
||||
"Edit",
|
||||
"Edit name and description of your NPC.",
|
||||
true)
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", "15.4,0.3;2,0.9", "button_save_dialog",
|
||||
"Save",
|
||||
"Save this dialog.",
|
||||
true)
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", "17.5,0.3;2.4,0.9", "button_export_dialog",
|
||||
"Export",
|
||||
"Export: Show the dialog in .json format which you can copy and store on your computer.",
|
||||
true)
|
||||
|
||||
|
||||
local tmp = "[0.2,6;19.6,16.8;d_text;"
|
||||
-- static help text instead of text input field for d_got_item
|
||||
if(c_d_id == "d_got_item") then
|
||||
table.insert(formspec, "hypertext"..tmp..
|
||||
"<normal>Note:\nThis is a special dialog. "..
|
||||
"It will be called when the player clicks on "..
|
||||
"<b>I want to give you something</b>."..
|
||||
"\nMost of the things listed below will be added automaticly when you add a "..
|
||||
"new option to this dialog. In most cases you may just have to edit the "..
|
||||
"<b>precondition</b> so that the <i>right item</i> is accepted, and then "..
|
||||
"set the <b>target dialog</b> <i>according to your needs</i>. Please also "..
|
||||
"edit the <b>alternate text</b> so that it fits your <i>item</i>!"..
|
||||
"\nThis is how it works in detail:"..
|
||||
"\n<b>Each option</b> you add here ought to deal with one item(stack) that "..
|
||||
"the NPC expects from the player, i.e. <i>farming:bread 2</i>. "..
|
||||
"Each option needs to be selected <b>automaticly</b> and ought to contain:"..
|
||||
"\n* a <b>precondition</b> regarding "..
|
||||
"<b>an item the player offered/gave to the NPC</b> "..
|
||||
"(shown as <b>player_offered_item</b> in overview) "..
|
||||
"where you define which item(stack) is relevant for this option"..
|
||||
"\n* an <b>effect</b> regarding <b>an item the player offered to the NPC</b> "..
|
||||
"(shown as <b>deal_with_offered_item</b> in overview) "..
|
||||
"where you define what shall happen to the offered item. Usually "..
|
||||
"the NPC will accept the item and put it into its inventory."..
|
||||
"\n* Don't forget to set a suitable target dialog for the <b>effect</b>! "..
|
||||
"Your NPC ought to comment on what he got, i.e. "..
|
||||
"<i>Thank you for those two breads! You saved me from starving.</i>"..
|
||||
"You can also work with an alternate text here (as is done in the "..
|
||||
"default setup when adding a new option here)."..
|
||||
"\n</normal>]")
|
||||
-- static help text instead of text input field for d_trade
|
||||
elseif(c_d_id == "d_trade") then
|
||||
table.insert(formspec, "hypertext"..tmp..
|
||||
"<normal>Note:\nThis is a special dialog. "..
|
||||
"It will be called when the player clicks on "..
|
||||
"<b>Let's trade!</b>."..
|
||||
"\nSome of the things listed below will be added automaticly when you add a "..
|
||||
"new option to this dialog. In most cases you may just have to edit the "..
|
||||
"<b>precondition</b> so that the <i>right item(stack)</i> is beeing "..
|
||||
"searched for, and you need to add suitable effects. The ones added "..
|
||||
"automaticly are just an example."..
|
||||
"\nNote that once the NPC found a matching precondition, it will execute the "..
|
||||
"relevant effects and present the player the trade list. Any further options "..
|
||||
"that might also fit will not be executed this time. Only <b>one</b> option "..
|
||||
"(or none) will be selected each time."..
|
||||
"\nThis is how it works in detail:"..
|
||||
"\n<b>Each option</b> you add here ought to deal with one item(stack) that "..
|
||||
"the NPC might or might not have in its inventory, "..
|
||||
"i.e. <i>default:stick 4</i>. "..
|
||||
"Each option needs to be selected <b>automaticly</b> and ought to contain:"..
|
||||
"\n* at least one <b>precondition</b> regarding "..
|
||||
"<b>the inventory of the NPC</b> "..
|
||||
"where you define which item(stack) is relevant for this option "..
|
||||
"(you can add multiple such preconditions for each option)"..
|
||||
"\n* at least one <b>effect</b> regarding what the NPC shall do if the "..
|
||||
"precondition matches. In most cases, <b>NPC crafts something</b>, "..
|
||||
"<b>put item from the NPC's inventory into a chest etc.</b> or "..
|
||||
"<b>take item from a chest etc. and put it into the NPC's inventory</b> "..
|
||||
"will be what you are looking for. More than one effect is possible."..
|
||||
"\n* In this particular case, no target dialog needs to be selected. After "..
|
||||
"executing the effect(s), the trade list view will be shown to the "..
|
||||
"player."..
|
||||
"\n</normal>]")
|
||||
elseif(c_d_id == "d_dynamic") then
|
||||
table.insert(formspec, "hypertext"..tmp..
|
||||
"<normal>Note:\nThis is a special dialog. "..
|
||||
"Each time right before this special dialog is displayed, a "..
|
||||
"function is called that can fill the <b>d_dynamic</b> dialog "..
|
||||
"with text and options."..
|
||||
"\nThat function has to decide <b>based on NPC, player and context</b> what "..
|
||||
"it wants to display this time."..
|
||||
"\nThe d_dynamic dialog is <b>never saved</b> as part of the dialog. "..
|
||||
"It has to be dynamicly created by your function each time it is needed."..
|
||||
"\nThe d_dynamic dialog will always be available as a <b>legitimate target "..
|
||||
"dialog</b> of a dialog option. Its options can do all that which "..
|
||||
"options of other dialogs can do. Its options can also lead back to "..
|
||||
"normal static parts of the dialog."..
|
||||
"\n</normal>]")
|
||||
elseif(active_dialog and active_dialog.d_text) then
|
||||
table.insert(formspec, "textarea"..tmp..";"..
|
||||
minetest.formspec_escape(active_dialog.d_text or "?")..
|
||||
"]")
|
||||
else
|
||||
table.insert(formspec, "textarea"..tmp..";"..
|
||||
minetest.formspec_escape("[no text]")..
|
||||
"]")
|
||||
end
|
||||
return {h = h, formspec = formspec, d_id_to_dropdown_index = d_id_to_dropdown_index,
|
||||
dialog_list = dialog_list}
|
||||
end
|
||||
|
||||
|
||||
-- helper function for yl_speak_up.get_fs_talkdialog:
|
||||
-- prints one entry (option/answer) in normal and *edit_mode*
|
||||
local old_talkdialog_line = yl_speak_up.get_fs_talkdialog_line
|
||||
yl_speak_up.get_fs_talkdialog_line = function(
|
||||
formspec, h, pname_for_old_fs, oid, sb_v,
|
||||
dialog, allowed, pname,
|
||||
-- these additional parameters are needed *here*, in edit_mode:
|
||||
active_dialog, dialog_list, d_id_to_dropdown_index,
|
||||
current_index, anz_options)
|
||||
|
||||
if(not(yl_speak_up.in_edit_mode(pname))) then
|
||||
-- in normal mode:
|
||||
return old_talkdialog_line(formspec, h, pname_for_old_fs, oid, sb_v,
|
||||
dialog, allowed, pname,
|
||||
active_dialog, dialog_list, d_id_to_dropdown_index,
|
||||
current_index, anz_options)
|
||||
end
|
||||
|
||||
-- in edit mode:
|
||||
local offset = 0.0
|
||||
local field_length = 43.8
|
||||
if(pname_for_old_fs) then
|
||||
offset = 0.7
|
||||
field_length = 41.8
|
||||
end
|
||||
h = h + 1
|
||||
-- add a button "o_<nr>:" that leads to an edit formspec for this option
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", tostring(2.9+offset).."," .. h .. ";2,0.9", "edit_option_" .. oid,
|
||||
oid,
|
||||
"Edit target dialog, pre(C)onditions and (Ef)fects for option "..oid..".",
|
||||
true)
|
||||
-- find the right target dialog for this option (if it exists):
|
||||
local target_dialog = nil
|
||||
local results = active_dialog.d_options[sb_v.o_id].o_results
|
||||
-- has this option more results/effects than just switching to another dialog?
|
||||
local has_other_results = false
|
||||
if(results ~= nil) then
|
||||
for k, v in pairs(results) do
|
||||
if v.r_type == "dialog"
|
||||
and (dialog.n_dialogs[v.r_value] ~= nil
|
||||
or yl_speak_up.is_special_dialog(v.r_value)) then
|
||||
-- there may be more than one in the data structure
|
||||
target_dialog = v.r_value
|
||||
elseif v.r_type ~= "dialog" then
|
||||
has_other_results = true
|
||||
end
|
||||
end
|
||||
end
|
||||
-- add a button "-> d_<nr>" that leads to the target dialog (if one is set)
|
||||
-- selecting an option this way MUST NOT execute the pre(C)onditions or (Ef)fects!
|
||||
local arrow = "->"
|
||||
local only_once = ""
|
||||
if(sb_v.o_visit_only_once and sb_v.o_visit_only_once == 1) then
|
||||
arrow = "*"
|
||||
only_once = "\nNote: This option can be selected only *once* per talk!"
|
||||
end
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", tostring(12.6+offset)..","..h..";1,0.9", "button_" .. oid,
|
||||
arrow,
|
||||
"Go to target dialog "..minetest.formspec_escape(target_dialog or "")..
|
||||
" that will be shown when this option ("..oid..") is selected."..
|
||||
only_once,
|
||||
(target_dialog))
|
||||
|
||||
-- allow to set a new target dialog
|
||||
table.insert(formspec, "dropdown["..tostring(5.0+offset)..","..h..";7.7,1;d_id_"..
|
||||
oid..";"..
|
||||
dialog_list..";"..
|
||||
(d_id_to_dropdown_index[(target_dialog or "?")] or "0")..",]")
|
||||
-- add a tooltip "Change target dialog"
|
||||
table.insert(formspec, "tooltip[5.0,"..h..";4.7,1;"..
|
||||
"Change target dialog for option "..oid..".;#FFFFFF;#000000]")
|
||||
|
||||
-- are there any prerequirements?
|
||||
local prereq = active_dialog.d_options[sb_v.o_id].o_prerequisites
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", tostring(0.5+offset)..","..h..";0.5,0.9", "conditions_"..oid,
|
||||
"C",
|
||||
"There are pre(C)onditions required for showing this option. Display them.",
|
||||
(prereq and next(prereq)))
|
||||
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", tostring(1.6+offset)..","..h..";0.6,0.9", "effects_"..oid,
|
||||
"Ef",
|
||||
"There are further (Ef)fects (apart from switching\n"..
|
||||
"to a new dialog) set for this option. Display them.",
|
||||
(has_other_results))
|
||||
|
||||
local d_option = active_dialog.d_options[sb_v.o_id]
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", tostring(2.25+offset)..","..h..";0.6,0.9", "quests_"..oid,
|
||||
"Q",
|
||||
"This option sets a (Q)est step if possible.\n"..
|
||||
"A special precondition is evaluated automaticly\n"..
|
||||
"to check if the quest step can be set.",
|
||||
(d_option and d_option.quest_id and d_option.quest_step))
|
||||
|
||||
-- are there any actions defined?
|
||||
local actions = active_dialog.d_options[sb_v.o_id].actions
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", tostring(1.05+offset)..","..h..";0.5,0.9", "actions_"..oid,
|
||||
"A",
|
||||
"There is an (A)ction (i.e. a trade) that will happen\n"..
|
||||
"when switching to a new dialog. Display actions and\n"..
|
||||
"trade of this option.",
|
||||
(actions and next(actions)))
|
||||
|
||||
if(sb_v.o_autoanswer) then
|
||||
table.insert(formspec,
|
||||
"label["..tostring(13.5+offset+0.2)..","..tostring(h+0.5)..";"..
|
||||
minetest.formspec_escape("[Automaticly selected if preconditions are met] "..
|
||||
tostring(sb_v.o_text_when_prerequisites_met))..
|
||||
"]")
|
||||
elseif(active_dialog.o_random) then
|
||||
table.insert(formspec,
|
||||
"label["..tostring(13.5+offset+0.2)..","..tostring(h+0.5)..";"..
|
||||
minetest.formspec_escape("[One of these options is randomly selected] "..
|
||||
tostring(sb_v.o_text_when_prerequisites_met))..
|
||||
"]")
|
||||
else
|
||||
-- show the actual text for the option
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"field", tostring(13.5+offset)..","..h..";"..
|
||||
tostring(field_length-5.3)..",0.9",
|
||||
"text_option_" .. oid,
|
||||
";"..minetest.formspec_escape(sb_v.o_text_when_prerequisites_met),
|
||||
"Edit the text that is displayed on button "..oid..".",
|
||||
true)
|
||||
end
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
"button", tostring(10.5+offset+field_length-2.2)..","..h..";1.0,0.9", "delete_option_"..oid,
|
||||
"Del",
|
||||
"Delete this option/answer.",
|
||||
true)
|
||||
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
-- "image_button", tostring(9.9+offset+field_length-0.5)..","..h..";0.5,0.9"..
|
||||
-- ";gui_furnace_arrow_bg.png^[transformR180",
|
||||
"button", tostring(10.5+offset+field_length-1.1)..","..h..";0.5,0.9",
|
||||
"option_move_down_"..oid,
|
||||
"v",
|
||||
"Move this option/answer one down.",
|
||||
(current_index < anz_options))
|
||||
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
|
||||
-- "image_button", tostring(9.9+offset+field_length-1.0)..","..h..";0.5,0.9"..
|
||||
-- ";gui_furnace_arrow_bg.png",
|
||||
"button", tostring(10.5+offset+field_length-0.5)..","..h..";0.5,0.9",
|
||||
"option_move_up_"..oid,
|
||||
"^",
|
||||
"Move this option/answer one up.",
|
||||
(current_index > 1))
|
||||
return {h = h, formspec = formspec}
|
||||
end
|
||||
|
||||
|
||||
-- add a prefix to "I want to give you something." dialog option in edit_mode:
|
||||
local old_talkdialog_offers_item = yl_speak_up.get_fs_talkdialog_add_player_offers_item
|
||||
yl_speak_up.get_fs_talkdialog_add_player_offers_item = function(pname, formspec, h, dialog, add_text, pname_for_old_fs)
|
||||
local offer_item_add_text = nil
|
||||
if(yl_speak_up.in_edit_mode(pname)) then
|
||||
-- force showing the "I want to give you something"-text
|
||||
offer_item_add_text = minetest.formspec_escape("[dialog d_got_item] -> ")
|
||||
end
|
||||
return old_talkdialog_offers_item(pname, formspec, h, dialog, offer_item_add_text, pname_for_old_fs)
|
||||
end
|
||||
|
||||
|
||||
-- helper function for yl_speak_up.get_fs_talkdialog:
|
||||
-- if the player can edit the NPC,
|
||||
-- either add a button for entering edit mode
|
||||
-- or add the buttons needed to edit the dialog when in *edit mode*
|
||||
local old_talkdialog_add_edit_and_command_buttons = yl_speak_up.get_fs_talkdialog_add_edit_and_command_buttons
|
||||
yl_speak_up.get_fs_talkdialog_add_edit_and_command_buttons = function(
|
||||
pname, formspec, h, pname_for_old_fs, is_a_start_dialog,
|
||||
active_dialog, luaentity, may_edit_npc, anz_options)
|
||||
-- add the buttons that are added to all editable NPC *first*:
|
||||
-- inventory access, commands for mobs_npc, custom commands
|
||||
local res = old_talkdialog_add_edit_and_command_buttons(
|
||||
pname, formspec, h, pname_for_old_fs, is_a_start_dialog,
|
||||
active_dialog, luaentity, may_edit_npc, anz_options)
|
||||
formspec = res.formspec
|
||||
h = res.h
|
||||
-- if the player cannot *enter* edit_mode:
|
||||
if(not(may_edit_npc)) then
|
||||
return res
|
||||
end
|
||||
local edit_mode = yl_speak_up.in_edit_mode(pname)
|
||||
-- button "show log" for those who can edit the NPC (entering edit mode is not required)
|
||||
local text = minetest.formspec_escape(
|
||||
"[Log] Show me your log.")
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"show_log",
|
||||
text, text,
|
||||
true, nil, nil, pname_for_old_fs)
|
||||
-- Offer to enter edit mode if the player has the npc_talk_owner priv OR is allowed to edit the NPC.
|
||||
-- The npc_talk_master priv allows to edit all NPC.
|
||||
if(not(edit_mode)) then
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"button_start_edit_mode",
|
||||
"Enters edit mode. In this mode, you can edit the texts the NPC says and the "..
|
||||
"answers that can be given.",
|
||||
-- chat option: "I am your owner. I have new orders for you.
|
||||
"I am your owner. I have new orders for you.",
|
||||
true, nil, true, pname_for_old_fs) -- is button_exit
|
||||
return {h = h, formspec = formspec}
|
||||
end
|
||||
|
||||
local offset = 0.0
|
||||
-- If in edit mode, add new menu entries: "add new options", "end edit mode" and what else is needed.
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"add_option",
|
||||
-- chat option: "Add a new answer/option to this dialog."
|
||||
"Adds a new option to this dialog. You can delete options via the option edit menu.",
|
||||
"Add a new option/answer to this dialog. You can delete options via the option "..
|
||||
"edit menu.",
|
||||
-- the amount of allowed options/answers has been reached
|
||||
(anz_options < yl_speak_up.max_number_of_options_per_dialog),
|
||||
"Maximum number of allowed answers/options reached. No further options/answers "..
|
||||
"can be added.", nil, pname_for_old_fs)
|
||||
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"delete_this_empty_dialog",
|
||||
-- chat option: "Delete this dialog."
|
||||
"Dialogs can only be deleted when they are empty and have no more "..
|
||||
"options/answers. This is the case here, so the dialog can be deleted.",
|
||||
"Delete this empty dialog.",
|
||||
(active_dialog and active_dialog.d_text == "" and anz_options == 0),
|
||||
-- (but only show this option if the dialog is empty)
|
||||
"If you want to delete this dialog, you need to delete all options and its "..
|
||||
"text first.", nil, pname_for_old_fs)
|
||||
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"show_what_points_to_this_dialog",
|
||||
-- chat option: "Show what points to this dialog."
|
||||
"Show which other dialog options or failed actions\n"..
|
||||
"or effects lead the player to this dialog here.",
|
||||
"Show what points to this dialog.",
|
||||
-- there is no alternate text to show
|
||||
true, nil, nil, pname_for_old_fs)
|
||||
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"make_first_option",
|
||||
-- chat option: "Make this dialog the first one shown when starting to talk."
|
||||
"The NPC has to start with one dialog when he is right-clicked. "..
|
||||
"Make this dialog the one shown.",
|
||||
"Make this dialog the first one shown when starting a conversation.",
|
||||
(active_dialog and active_dialog.d_sort and tonumber(active_dialog.d_sort) ~= 0),
|
||||
-- (but only show this option if it's not already the first one)
|
||||
"This dialog will be shown whenever a conversation is started.", nil,pname_for_old_fs)
|
||||
|
||||
local b_text = "Turn this into"
|
||||
if(is_a_start_dialog) then
|
||||
b_text = "This shall no longer be"
|
||||
end
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"turn_into_a_start_dialog",
|
||||
"With automatic selection of options, it is possible that the real\n"..
|
||||
"start dialog will never be shown to the player. However, we need\n"..
|
||||
"to add some buttons to that start dialog for i.e. giving items\n"..
|
||||
"to the NPC and for trading. Therefore, dialogs can be marked as\n"..
|
||||
"*a* start dialog so that these buttons will be added to those dialogs.",
|
||||
b_text.." *a* start dialog where buttons for trade etc. are shown.",
|
||||
not(active_dialog and active_dialog.d_sort and tonumber(active_dialog.d_sort) == 0),
|
||||
"The start dialog automaticly counts as *a* start dialog where buttons for "..
|
||||
"trade etc. are shown.", nil, pname_for_old_fs)
|
||||
|
||||
-- chat option: Mute/Unmute NPC
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"mute_npc",
|
||||
-- chat option: mute the NPC
|
||||
"The NPC will no longer show his dialogs when he is right-clicked. This is "..
|
||||
"useful while you edit the NPC and don't want players to see "..
|
||||
"unfinished entries and/or quests.",
|
||||
"State: Not muted. Stop talking to other players while I give you new orders.",
|
||||
(luaentity and luaentity.yl_speak_up.talk), nil, nil, pname_for_old_fs)
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"un_mute_npc",
|
||||
-- unmute the NPC
|
||||
"The NPC will show his dialogs to other players when he is right-clicked. "..
|
||||
"This is the normal mode of operation. Choose this when you are "..
|
||||
"finished editing.",
|
||||
"State: You are currently muted. Talk to anyone again who wants to talk to you.",
|
||||
-- the NPC has to be there
|
||||
(luaentity and not(luaentity.yl_speak_up.talk)), nil, nil, pname_for_old_fs)
|
||||
|
||||
|
||||
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
||||
"button_end_edit_mode",
|
||||
"Ends edit mode. From now on, your NPC will talk to you like he talks to other "..
|
||||
"players. You can always give him new orders by entering edit mode again.",
|
||||
-- chat option:"That was all. I'm finished with giving you new orders. Remember them!"
|
||||
"That was all. I'm finished with giving you new orders. Remember them!",
|
||||
true, nil, true, pname_for_old_fs) -- is button_exit
|
||||
return {h = h, formspec = formspec}
|
||||
end
|
||||
|
||||
|
||||
-- apply force_edit_mode if necessary
|
||||
local old_get_fs_talkdialog = yl_speak_up.get_fs_talkdialog
|
||||
yl_speak_up.get_fs_talkdialog = function(player, n_id, d_id, alternate_text, recursion_depth)
|
||||
if(not(player)) then
|
||||
return
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
-- are we in force edit mode, and can the player edit this NPC?
|
||||
if(yl_speak_up.force_edit_mode[pname]
|
||||
-- not already in edit mode?
|
||||
and (not(yl_speak_up.edit_mode[pname]) or yl_speak_up.edit_mode[pname] ~= n_id)
|
||||
and yl_speak_up.may_edit_npc(player, n_id)) then
|
||||
yl_speak_up.edit_mode[pname] = n_id
|
||||
end
|
||||
return old_get_fs_talkdialog(player, n_id, d_id, alternate_text, recursion_depth)
|
||||
end
|
||||
|
||||
--[[
|
||||
yl_speak_up.get_fs_talk_wrapper = function(player, param)
|
||||
if(not(param)) then
|
||||
param = {}
|
||||
end
|
||||
-- recursion depth from autoanswer: 0 (the player selected manually)
|
||||
return yl_speak_up.get_fs_talkdialog(player, param.n_id, param.d_id, param.alternate_text,0)
|
||||
end
|
||||
--]]
|
||||
|
||||
yl_speak_up.register_fs("talk",
|
||||
-- this function is changed here:
|
||||
yl_speak_up.input_talk,
|
||||
-- the underlying function is changed as well - but the wrapper calls that already; so ok:
|
||||
yl_speak_up.get_fs_talk_wrapper,
|
||||
-- no special formspec required:
|
||||
nil
|
||||
)
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
-- helper function
|
||||
yl_speak_up.wrap_long_lines_for_table = function(text, prefix, line_length, max_lines)
|
||||
-- show newlines as <\n> in order to save space
|
||||
local text = (text or "?")
|
||||
text = string.gsub(text, "\n", minetest.formspec_escape("<br>"))
|
||||
-- break the text up into lines of length x
|
||||
local parts = minetest.wrap_text(text, line_length, true)
|
||||
if(not(parts) or #parts < 2) then
|
||||
return minetest.formspec_escape(text)
|
||||
end
|
||||
local show_parts = {}
|
||||
-- only show the first two lines (we don't have infinite room)
|
||||
for i, p in ipairs(parts) do
|
||||
if(i <= max_lines) then
|
||||
table.insert(show_parts, minetest.formspec_escape(p))
|
||||
end
|
||||
end
|
||||
if(#parts > max_lines) then
|
||||
return table.concat(show_parts, prefix)..minetest.formspec_escape(" [...]")
|
||||
end
|
||||
return table.concat(show_parts, prefix)
|
||||
end
|
||||
|
||||
|
||||
-- helper functions for yl_speak_up.fs_get_list_of_usage_of_variable
|
||||
-- and yl_speak_up.show_what_points_to_this_dialog
|
||||
yl_speak_up.print_as_table_precon = function(p, pname)
|
||||
return ",#FFFF00,"..
|
||||
minetest.formspec_escape(tostring(p.p_id))..
|
||||
",#FFFF00,pre(C)ondition,#FFFF00,"..
|
||||
minetest.formspec_escape(p.p_type)..",#FFFF00,"..
|
||||
minetest.formspec_escape(yl_speak_up.show_precondition(p, pname))
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.print_as_table_effect = function(r, pname)
|
||||
return ",#55FF55,"..
|
||||
minetest.formspec_escape(tostring(r.r_id))..
|
||||
",#55FF55,(Ef)fect,#55FF55,"..
|
||||
minetest.formspec_escape(r.r_type)..",#55FF55,"..
|
||||
minetest.formspec_escape(yl_speak_up.show_effect(r, pname))
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.print_as_table_action = function(a, pname)
|
||||
return ",#FF9900,"..
|
||||
minetest.formspec_escape(tostring(a.a_id))..
|
||||
",#FF9900,(A)ction,#FF9900,"..
|
||||
minetest.formspec_escape(a.a_type)..",#FF9900,"..
|
||||
-- these lines can get pretty long when a description for a quest item is set
|
||||
yl_speak_up.wrap_long_lines_for_table(
|
||||
yl_speak_up.show_action(a, pname),
|
||||
",#FFFFFF,,#FFFFFF,,#FFFFFF,,#FF9900,",
|
||||
80, 4)
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.print_as_table_dialog = function(p_text, r_text, dialog, n_id, d_id, o_id, res, o, sort_value,
|
||||
alternate_dialog, alternate_text)
|
||||
if(p_text == "" and r_text == "" ) then
|
||||
return
|
||||
end
|
||||
local d_text = yl_speak_up.wrap_long_lines_for_table(
|
||||
dialog.n_dialogs[ d_id ].d_text or "?",
|
||||
",#FFFFFF,,#FFFFFF,,#FFFFFF,,#BBBBFF,",
|
||||
80, 3)
|
||||
if(not(alternate_dialog) or not(alternate_text)) then
|
||||
alternate_text = ""
|
||||
else
|
||||
alternate_text = ",#BBBBFF,"..minetest.formspec_escape(tostring(alternate_dialog))..
|
||||
-- show alternate text in a diffrent color
|
||||
",#BBBBFF,Dialog,#BBBBFF,says next:,#FFBBBB,"..
|
||||
yl_speak_up.wrap_long_lines_for_table(
|
||||
alternate_text,
|
||||
",#FFFFFF,,#FFFFFF,,#FFFFFF,,#FFBBBB,",
|
||||
80, 3)
|
||||
end
|
||||
res[ tostring(n_id).." "..tostring(d_id).." "..tostring(o_id) ] = {
|
||||
text = "#6666FF,"..
|
||||
tostring(n_id)..",#6666FF,NPC,#6666FF,named:,#6666FF,"..
|
||||
minetest.formspec_escape(dialog.n_npc or "?")..","..
|
||||
"#BBBBFF,"..
|
||||
tostring(d_id)..",#BBBBFF,Dialog,#BBBBFF,says:,#BBBBFF,"..
|
||||
d_text..","..
|
||||
"#FFFFFF,"..
|
||||
tostring(o_id)..",#FFFFFF,Option,#FFFFFF,A:,#FFFFFF,"..
|
||||
minetest.formspec_escape(tostring(o.o_text_when_prerequisites_met or "?"))..
|
||||
p_text..r_text..
|
||||
alternate_text,
|
||||
sort_value = sort_value}
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.print_as_table_prepare_formspec = function(res, table_name, back_button_name, back_button_text,
|
||||
is_already_sorted, concat_with, table_columns)
|
||||
local sorted_res = {}
|
||||
-- this is the default for "show where a variable is used"
|
||||
if(not(is_already_sorted)) then
|
||||
local sorted_list = yl_speak_up.get_sorted_options(res, "sort_value")
|
||||
for i, k in pairs(sorted_list) do
|
||||
table.insert(sorted_res, res[ k ].text)
|
||||
end
|
||||
table_columns = "color,span=1;text;color,span=1;text;color,span=1;text;color,span=1;text"
|
||||
else
|
||||
sorted_res = res
|
||||
end
|
||||
if(not(concat_with)) then
|
||||
-- insert blank lines between lines belonging together
|
||||
concat_with = ",#FFFFFF,,#FFFFFF,,#FFFFFF,,#FFFFFF,,"
|
||||
end
|
||||
local formspec = {
|
||||
"size[57,33]",
|
||||
-- back to the list with that one precondition or effect
|
||||
"button[0.2,0.2;56.6,1.2;"..back_button_name..";"..
|
||||
minetest.formspec_escape(back_button_text).."]",
|
||||
"button[0.2,31.6;56.6,1.2;"..back_button_name..";"..
|
||||
minetest.formspec_escape(back_button_text).."]",
|
||||
"tablecolumns["..tostring(table_columns).."]",
|
||||
}
|
||||
table.insert(formspec,
|
||||
"table[1.2,2.4;55.0,28.0;"..tostring(table_name)..";"..
|
||||
table.concat(sorted_res, concat_with).."]")
|
||||
return formspec
|
||||
end
|
|
@ -1,98 +0,0 @@
|
|||
|
||||
-- when in edit mode: ask for saving dialogs when needed
|
||||
local old_show_fs = yl_speak_up.show_fs
|
||||
yl_speak_up.show_fs = function(player, fs_name, param)
|
||||
if(not(player)) then
|
||||
return
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
if(not(yl_speak_up.speak_to[pname])) then
|
||||
return
|
||||
end
|
||||
|
||||
local last_fs = yl_speak_up.speak_to[pname].last_fs
|
||||
-- show the save or discard changes dialog
|
||||
if(fs_name and fs_name == "save_or_discard_changes") then
|
||||
yl_speak_up.show_fs_ver(pname, "yl_speak_up:save_or_discard_changes",
|
||||
yl_speak_up.get_fs_save_or_discard_changes(player, param))
|
||||
return
|
||||
|
||||
-- the player either saved or discarded; we may proceed now
|
||||
elseif(fs_name and fs_name == "proceed_after_save") then
|
||||
fs_name = yl_speak_up.speak_to[pname].next_fs
|
||||
param = yl_speak_up.speak_to[pname].next_fs_param
|
||||
yl_speak_up.speak_to[pname].next_fs = nil
|
||||
yl_speak_up.speak_to[pname].next_fs_param = nil
|
||||
yl_speak_up.speak_to[pname].last_fs = fs_name
|
||||
yl_speak_up.speak_to[pname].last_fs_param = param
|
||||
if(not(fs_name) or fs_name == "quit") then
|
||||
yl_speak_up.reset_vars_for_player(pname, false)
|
||||
return
|
||||
end
|
||||
|
||||
-- the player clicked on "back" in the above dialog
|
||||
elseif(fs_name and fs_name == "show_last_fs") then
|
||||
-- call the last formspec again - and with the same parameters
|
||||
fs_name = yl_speak_up.speak_to[pname].last_fs
|
||||
param = yl_speak_up.speak_to[pname].last_fs_param
|
||||
|
||||
-- do we need to check if there is something that needs saving?
|
||||
elseif(fs_name
|
||||
-- msg is just a loop for displaying (mostly error) messages
|
||||
and fs_name ~= "msg"
|
||||
and fs_name ~= "player_offers_item"
|
||||
-- is the player editing the NPC? that is: might there be any changes?
|
||||
and (yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id)) then
|
||||
local last_fs = yl_speak_up.speak_to[pname].last_fs
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
-- only these two formspecs need to ask specificly if the data ought to be saved
|
||||
if(last_fs == "talk" or last_fs == "edit_option_dialog" or fs_name == "quit") then
|
||||
local last_param = yl_speak_up.speak_to[pname].last_fs_param
|
||||
local show_save_fs = false
|
||||
if(not(param)) then
|
||||
param = {}
|
||||
end
|
||||
-- set the target dialog
|
||||
yl_speak_up.speak_to[pname].target_dialog = param.d_id
|
||||
-- if we are switching from one dialog to another: is it the same?
|
||||
if(last_fs == "talk" and fs_name == last_fs
|
||||
and param and param.d_id and param.d_id ~= d_id) then
|
||||
-- diffrent parameters: save (if needed)
|
||||
show_save_fs = true
|
||||
elseif(fs_name == "talk" and param and param.do_save) then
|
||||
-- player clicked on save button
|
||||
show_save_fs = true
|
||||
-- leaving a dialog: save!
|
||||
elseif(last_fs == "talk" and fs_name ~= last_fs) then
|
||||
show_save_fs = true
|
||||
-- clicking on "save" in an edit option dialog: save!
|
||||
elseif(last_fs == "edit_option_dialog" and fs_name == last_fs
|
||||
and param and param.caller and param.caller == "save_option") then
|
||||
show_save_fs = true
|
||||
-- leaving editing an option: save!
|
||||
elseif(last_fs == "edit_option_dialog" and fs_name ~= last_fs) then
|
||||
show_save_fs = true
|
||||
-- quitting: save!
|
||||
elseif(fs_name == "quit") then
|
||||
yl_speak_up.speak_to[pname].target_dialog = nil
|
||||
show_save_fs = true
|
||||
end
|
||||
-- show the save or discard dialog
|
||||
if(show_save_fs) then
|
||||
yl_speak_up.speak_to[pname].next_fs = fs_name
|
||||
yl_speak_up.speak_to[pname].next_fs_param = param
|
||||
-- check first if it's necessary to ask for save or discard
|
||||
yl_speak_up.input_save_or_discard_changes(player, "", {})
|
||||
return
|
||||
end
|
||||
end
|
||||
-- store the new formspec
|
||||
yl_speak_up.speak_to[pname].last_fs = fs_name
|
||||
-- and its parameter
|
||||
yl_speak_up.speak_to[pname].last_fs_param = param
|
||||
end
|
||||
|
||||
-- Note: fs_name and param *may* have been changed in edit_mode by the code above
|
||||
old_show_fs(player, fs_name, param)
|
||||
end
|
|
@ -1,70 +0,0 @@
|
|||
-- overrides for api/api_trade_inv.lua:
|
||||
|
||||
-- the player *can* place something into the npc_gives inventory list in edit_mode:
|
||||
local old_trade_inv_allow_put = yl_speak_up.trade_inv_allow_put
|
||||
yl_speak_up.trade_inv_allow_put = function(inv, listname, index, stack, player)
|
||||
if(not(player)) then
|
||||
return 0
|
||||
end
|
||||
-- allow putting something in in edit mode - but not otherwise
|
||||
if(listname and listname == "npc_gives") then
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
-- only in edit mode! else the NPC manages this slot
|
||||
if(n_id and yl_speak_up.in_edit_mode(pname)) then
|
||||
return stack:get_count()
|
||||
end
|
||||
end
|
||||
return old_trade_inv_allow_put(inv, listname, index, stack, player)
|
||||
end
|
||||
|
||||
|
||||
-- prevent do_trade_simple from executing trade and reporting successful action:
|
||||
local old_do_trade_simple = yl_speak_up.do_trade_simple
|
||||
yl_speak_up.do_trade_simple = function(player, count)
|
||||
if(not(player)) then
|
||||
return
|
||||
end
|
||||
|
||||
local pname = player:get_player_name()
|
||||
-- which trade are we talking about?
|
||||
local trade = yl_speak_up.trade[pname]
|
||||
|
||||
if(trade.n_id and yl_speak_up.edit_mode[pname] == trade.n_id) then
|
||||
-- instruct old_do_trade_simple to neither execute the trade nor see this
|
||||
-- as an action that was executed
|
||||
trade.dry_run_no_exec = true
|
||||
end
|
||||
return old_do_trade_simple(player, count)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- overrides for api/api_trade.lua:
|
||||
|
||||
-- do not allow deleting trades that are actions of an option if not in edit mode:
|
||||
local old_delete_trade_simple = yl_speak_up.delete_trade_simple
|
||||
yl_speak_up.delete_trade_simple = function(player, trade_id)
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
-- get the necessary dialog data
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
if(dialog and dialog.trades and trade_id
|
||||
and dialog.trades[ trade_id ] and n_id) then
|
||||
|
||||
if( dialog.trades[ trade_id ].d_id
|
||||
and yl_speak_up.edit_mode[pname] ~= n_id) then
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:do_trade_simple",
|
||||
formspec = "size[6,2]"..
|
||||
"label[0.2,-0.2;"..
|
||||
"Trades that are attached to dialog options\n"..
|
||||
"can only be deleted in edit mode. Please tell\n"..
|
||||
"your NPC that you are its owner and have\n"..
|
||||
"new commands!]"..
|
||||
"button[2,1.5;1,0.9;back_from_error_msg;Back]"})
|
||||
return
|
||||
end
|
||||
end
|
||||
return old_delete_trade_simple(player, trade_id)
|
||||
end
|
3
init.lua
3
init.lua
|
@ -229,7 +229,8 @@ yl_speak_up.reload = function(modpath, log_entry)
|
|||
dofile(modpath .. "export_to_ink.lua")
|
||||
dofile(modpath .. "fs/fs_export.lua")
|
||||
|
||||
dofile(modpath .. "editor/edit_mode.lua")
|
||||
-- edit_mode.lua has been moved to the mod npc_talk_edit:
|
||||
-- dofile(modpath .. "editor/edit_mode.lua")
|
||||
|
||||
-- initialize and load all registered generic dialogs
|
||||
yl_speak_up.load_generic_dialogs()
|
||||
|
|
|
@ -17,6 +17,12 @@ Reporting bugs: Please report issues <a href="https://gitea.your-land.de/Sokomin
|
|||
Clone via i.e. `git clone https://gitea.your-land.de/Sokomine/yl_speak_up`
|
||||
or install via <a href="https://content.minetest.net/">ContentDB</a>.
|
||||
|
||||
In order to be able to edit the dialogs of the NPC ingame, please install
|
||||
<a href="https://gitea.your-land.de/Sokomine/npc_talk_edit">npc_talk_edit</a>.
|
||||
The only situation where you might not need this extra mod is when you
|
||||
design your own adventure game and your players are not expected to edit
|
||||
the NPC.
|
||||
|
||||
Optional dependency:
|
||||
<a href="https://content.minetest.net/packages/TenPlus1/mobs/">mobs_redo</a>
|
||||
is highly recommended. You may be able to use other mob mods with
|
||||
|
@ -30,7 +36,7 @@ You might also wish to use <a href="https://content.minetest.net/packages/TenPlu
|
|||
from TenPlus1 as that mod provides very useful actual NPC and will be used by
|
||||
<a href="https://gitea.your-land.de/Sokomine/npc_talk">npc_talk</a> if installed.
|
||||
|
||||
To get started, best install `yl_speak_up`, `npc_talk`, `mobs_redo` and `mobs_npc` in your world.
|
||||
To get started, best install `yl_speak_up`, `npc_talk_edit`, `npc_talk`, `mobs_redo` and `mobs_npc` in your world.
|
||||
|
||||
|
||||
## Table of Content
|
||||
|
|
Loading…
Reference in New Issue