allowed to refer to other options' preconditions as a new precondition
This commit is contained in:
parent
586a18073e
commit
bcc171dff2
@ -629,6 +629,16 @@ yl_speak_up.save_element_p_or_a_or_e = function(
|
||||
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
|
||||
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
|
||||
end
|
||||
|
||||
-- "The preconditions of another dialog option are fulfilled/not fulfilled.", -- 9
|
||||
-- precondition: 9
|
||||
elseif(data.what and id_prefix == "p_" and data.what == 9) then
|
||||
if(data.other_o_id and data.other_o_id ~= "-select-") then
|
||||
v[ "p_value" ] = data.other_o_id
|
||||
end
|
||||
if(data.fulfilled and data.fulfilled ~= "-select-") then
|
||||
v[ "p_fulfilled" ] = data.fulfilled
|
||||
end
|
||||
end
|
||||
|
||||
v[ "alternate_text" ] = data.alternate_text
|
||||
@ -911,6 +921,15 @@ yl_speak_up.input_fs_edit_option_related = function(player, formname, fields,
|
||||
local nr = table.indexof(check_operator, fields.select_operator)
|
||||
yl_speak_up.speak_to[pname][ tmp_data_cache ].operator = nr
|
||||
end
|
||||
-- another dialog option is true or false
|
||||
-- Note: "-select-" can be choosen here as well
|
||||
if(fields.select_other_o_id and fields.select_other_o_id ~= "") then
|
||||
yl_speak_up.speak_to[pname][ tmp_data_cache ].other_o_id = fields.select_other_o_id
|
||||
end
|
||||
-- Note: "-select-" can be choosen here as well
|
||||
if(fields.select_fulfilled and fields.select_fulfilled ~= "") then
|
||||
yl_speak_up.speak_to[pname][ tmp_data_cache ].fulfilled = fields.select_fulfilled
|
||||
end
|
||||
if(fields.select_on_failure) then
|
||||
-- in this case we really want the name of the target dialog
|
||||
yl_speak_up.speak_to[pname][ tmp_data_cache ].on_failure = fields.select_on_failure
|
||||
@ -987,6 +1006,8 @@ yl_speak_up.input_fs_edit_option_related = function(player, formname, fields,
|
||||
or fields.select_on_action_failure
|
||||
or fields.back_from_error_msg
|
||||
or fields.store_item_name
|
||||
or fields.select_other_o_id
|
||||
or fields.select_fulfilled
|
||||
or was_changed
|
||||
or fields.key_enter
|
||||
or fields.quit
|
||||
@ -1350,6 +1371,12 @@ yl_speak_up.get_fs_edit_option_related = function(player, table_click_result,
|
||||
or (id_prefix == "r_" and data.what == 11))) then
|
||||
return yl_speak_up.get_fs_edit_option_all_custom(
|
||||
pname, dialog, formspec, data, id_prefix, save_button, e)
|
||||
|
||||
-- "The preconditions of another dialog option are fulfilled/not fulfilled.", -- 9
|
||||
-- precondition: 9
|
||||
elseif(data.what and id_prefix == "p_" and data.what == 9) then
|
||||
return yl_speak_up.get_fs_other_option_preconditions(
|
||||
pname, dialog, formspec, data, id_prefix, save_button, e)
|
||||
end
|
||||
-- create a new precondition, action or effect
|
||||
return formspec..save_button
|
||||
@ -1959,6 +1986,69 @@ yl_speak_up.get_fs_edit_option_all_custom = function(
|
||||
return formspec..save_button
|
||||
end
|
||||
|
||||
|
||||
-- "The preconditions of another dialog option are fulfilled/not fulfilled.", -- 9
|
||||
-- precondition: 9
|
||||
yl_speak_up.get_fs_other_option_preconditions = function(
|
||||
pname, dialog, formspec, data, id_prefix, save_button, e)
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
-- only o_id with a *lower* o_sort value are suitable (else evaluation would become
|
||||
-- difficult and loops might be created)
|
||||
local o_id_list = {}
|
||||
local options = dialog.n_dialogs[ d_id ].d_options
|
||||
if(options) then
|
||||
local this_option = options[ o_id ]
|
||||
if(not(this_option) or not(this_option.o_sort)) then
|
||||
this_option = {o_sort = 0}
|
||||
end
|
||||
for k, v in pairs(options) do
|
||||
if(k and v and v.o_sort and v.o_sort < this_option.o_sort) then
|
||||
table.insert(o_id_list, minetest.formspec_escape(k))
|
||||
end
|
||||
end
|
||||
end
|
||||
if(e) then
|
||||
data.other_o_id = e[ "p_value" ]
|
||||
data.fulfilled = e[ "p_fulfilled" ]
|
||||
end
|
||||
local nr = math.max(0, table.indexof(o_id_list, data.other_o_id))
|
||||
nr_fulfilled = 1
|
||||
if(data.fulfilled == "true") then
|
||||
nr_fulfilled = 2
|
||||
elseif(data.fulfilled == "false") then
|
||||
nr_fulfilled = 3
|
||||
end
|
||||
if(nr == 0 or nr_fulfilled == 1) then
|
||||
save_button = ""
|
||||
end
|
||||
return formspec..
|
||||
"label[0.2,3.3;Note: You can only select dialog options with a *lower* o_sort value "..
|
||||
"for this evaluation.]"..
|
||||
"label[0.2,4.0;The preconditions of dialog option:]"..
|
||||
"dropdown[6.0,3.7;3.0,0.6;select_other_o_id;-select-,"..
|
||||
table.concat(o_id_list, ",")..";"..
|
||||
tostring(nr + 1)..";]"..
|
||||
"label[9.2,4.0;..shall be:]"..
|
||||
"dropdown[11,3.7;2.0,0.6;select_fulfilled;-select-,true,false;"..
|
||||
tostring(nr_fulfilled).."]"..
|
||||
"tooltip[select_other_o_id;"..
|
||||
"Sometimes you may need the same preconditions for more than\n"..
|
||||
"one dialog option - or you may need one dialog option to be\n"..
|
||||
"available exactly when another one is *not* available.\n"..
|
||||
"This is what you can do here.]"..
|
||||
"tooltip[select_fulfilled;"..
|
||||
"If you select \"true\" here, then this precondition will be\n"..
|
||||
"fulfilled when all the preconditions of the dialog option you\n"..
|
||||
"selected here are true as well.\n"..
|
||||
"If you select \"false\", this precondition will only be\n"..
|
||||
"fulfilled if the other dialog option you selected here\n"..
|
||||
"is not true.]"..
|
||||
save_button
|
||||
end
|
||||
|
||||
|
||||
-- end of formspecs for types of preconditions, actions and effects
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
|
@ -41,6 +41,7 @@ local check_what = {
|
||||
"the inventory of the NPC", -- 6
|
||||
"execute Lua code (requires npc_master priv)", -- 7
|
||||
"Call custom functions that are supposed to be overridden by the server.", -- 8
|
||||
"The preconditions of another dialog option are fulfilled/not fulfilled.", -- 9
|
||||
}
|
||||
|
||||
-- how to store these as p_type in the precondition:
|
||||
@ -48,7 +49,9 @@ local values_what = {"", "state", "block", "trade", "player_inv", "npc_inv",
|
||||
-- requires npc_master priv
|
||||
"function",
|
||||
-- custom function (does not require npc_master priv)
|
||||
"custom"}
|
||||
"custom",
|
||||
-- depends on the preconditions of another option
|
||||
"other"}
|
||||
|
||||
-- options for "a trade"
|
||||
local check_trade = {
|
||||
@ -216,18 +219,51 @@ yl_speak_up.show_precondition = function(p, pname)
|
||||
end
|
||||
elseif(p.p_type == "custom") then
|
||||
return "Call custom function with param: \""..tostring(p.p_value).."\"."
|
||||
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.."."
|
||||
end
|
||||
-- fallback
|
||||
return tostring(p.p_value)
|
||||
end
|
||||
|
||||
|
||||
-- this is called directly in yl_speak_up.get_fs_talkdialog
|
||||
-- it returns a list of options whose preconditions are fulfilled
|
||||
yl_speak_up.calculate_displayable_options = function(pname, d_options)
|
||||
-- Let's go through all the options and see if we need to display them to the user
|
||||
|
||||
local retval = {}
|
||||
|
||||
local player = minetest.get_player_by_name(pname)
|
||||
|
||||
if d_options == nil then
|
||||
return {}
|
||||
end
|
||||
|
||||
-- sort the entries by o_sort so that preconditions referencing options earlier in the
|
||||
-- list can work without causing loops or the like
|
||||
local sorted_list = yl_speak_up.get_sorted_options(d_options, "o_sort")
|
||||
for i, o_k in ipairs(sorted_list) do
|
||||
local o_v = d_options[ o_k ]
|
||||
-- Can we display this option?
|
||||
retval[o_k] = yl_speak_up.eval_all_preconditions(player, o_v.o_prerequisites, o_k, retval)
|
||||
minetest.chat_send_player("singleplayer","retval "..tostring(o_k)..": "..tostring(retval[o_k])) -- TODO
|
||||
end
|
||||
return retval
|
||||
end
|
||||
|
||||
|
||||
-- called by calculate_displayable_options(..);
|
||||
-- returns false if a single precondition is false
|
||||
-- Important: If something cannot be determined (i.e. the node is nil),
|
||||
-- *both* the condition and its inverse condition may be
|
||||
-- true (or false).
|
||||
yl_speak_up.eval_all_preconditions = function(player, prereq, o_id)
|
||||
yl_speak_up.eval_all_preconditions = function(player, prereq, o_id, other_options_true_or_false)
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
if(not(prereq)) then
|
||||
@ -239,7 +275,7 @@ yl_speak_up.eval_all_preconditions = function(player, prereq, o_id)
|
||||
for k, p in pairs(prereq) do
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, "..checking "..
|
||||
tostring(p.p_id)..": "..yl_speak_up.show_precondition(p, pname))
|
||||
if(not(yl_speak_up.eval_precondition(player, n_id, p))) then
|
||||
if(not(yl_speak_up.eval_precondition(player, n_id, p, other_options_true_or_false))) then
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(p.p_id)..
|
||||
" -> is false. Aborting.")
|
||||
-- no need to look any further - once we hit a false, it'll stay false
|
||||
@ -253,7 +289,7 @@ end
|
||||
|
||||
|
||||
-- checks if precondition p is true for the player and npc n_id
|
||||
yl_speak_up.eval_precondition = function(player, n_id, p)
|
||||
yl_speak_up.eval_precondition = function(player, n_id, p, other_options_true_or_false)
|
||||
if(not(p.p_type) or p.p_type == "") then
|
||||
-- empty prerequirement: automaticly true (fallback)
|
||||
return true
|
||||
@ -365,7 +401,9 @@ yl_speak_up.eval_precondition = function(player, n_id, p)
|
||||
-- this is currently equivalent to >= but may change in the future
|
||||
-- TODO: quest steps may be strings in the future
|
||||
elseif(p.p_operator == "quest_step_done") then
|
||||
if(p.p_var_cmp_value == nil) then
|
||||
-- if the variable is not set at all, then the quest step definitely
|
||||
-- has not been reached yet
|
||||
if((p.p_var_cmp_value == nil) or (var_val == nil)) then
|
||||
return false
|
||||
end
|
||||
-- compare numeric if possible
|
||||
@ -377,10 +415,10 @@ yl_speak_up.eval_precondition = function(player, n_id, p)
|
||||
end
|
||||
-- this is currently equivalent to < but may change in the future
|
||||
-- TODO: quest steps may be strings in the future
|
||||
elseif(p.p_operator < "quest_step_not_done") then
|
||||
elseif(p.p_operator == "quest_step_not_done") then
|
||||
-- if the variable is not set at all, then the quest step definitely
|
||||
-- has not been reached yet
|
||||
if(p.p_var_cmp_value == nil) then
|
||||
if((p.p_var_cmp_value == nil) or (var_val == nil)) then
|
||||
return true
|
||||
end
|
||||
if(tonumber(var_val) and tonumber(p.p_var_cmp_value)) then
|
||||
@ -463,6 +501,12 @@ yl_speak_up.eval_precondition = function(player, n_id, p)
|
||||
elseif(p.p_type == "custom") then
|
||||
-- execute the custom function
|
||||
return yl_speak_up.precondition_custom(player, p.p_value)
|
||||
elseif(p.p_type == "other") then
|
||||
-- are the preconditions of another option fulfilled?
|
||||
return (p.p_value
|
||||
and other_options_true_or_false
|
||||
and other_options_true_or_false[ p.p_value ] ~= nil
|
||||
and tostring(other_options_true_or_false[ p.p_value ]) == tostring(p.p_fulfilled))
|
||||
end
|
||||
-- fallback - unknown type
|
||||
return false
|
||||
|
@ -351,25 +351,6 @@ local function delete_option(n_id, d_id, o_id)
|
||||
end
|
||||
|
||||
|
||||
local function calculate_displayable_options(pname, d_options)
|
||||
-- Let's go through all the options and see if we need to display them to the user
|
||||
|
||||
local retval = {}
|
||||
|
||||
local player = minetest.get_player_by_name(pname)
|
||||
|
||||
if d_options == nil then
|
||||
return {}
|
||||
end
|
||||
|
||||
for o_k, o_v in pairs(d_options) do
|
||||
-- Can we display this option?
|
||||
retval[o_k] = yl_speak_up.eval_all_preconditions(player, o_v.o_prerequisites, o_k)
|
||||
end
|
||||
return retval
|
||||
end
|
||||
|
||||
|
||||
local function calculate_portrait(pname, n_id)
|
||||
local tex = yl_speak_up.speak_to[pname].textures
|
||||
|
||||
@ -800,7 +781,8 @@ yl_speak_up.get_fs_talkdialog = function(player, n_id, d_id, alternate_text)
|
||||
return "size[6,2]"..
|
||||
"label[0.2,0.5;Ups! Something went wrong. Please try again.]"
|
||||
end
|
||||
local allowed = calculate_displayable_options(pname, active_dialog.d_options)
|
||||
-- evaluate the preconditions of each option and check if the option can be offered
|
||||
local allowed = yl_speak_up.calculate_displayable_options(pname, active_dialog.d_options)
|
||||
yl_speak_up.speak_to[pname].allowed = allowed
|
||||
|
||||
local portrait = calculate_portrait(pname, n_id)
|
||||
|
Loading…
Reference in New Issue
Block a user