forked from Sokomine/yl_speak_up
added special d_trade dialog; efects based on preconditions can now be executed before showing the trade_list
This commit is contained in:
parent
4b34c46453
commit
5fd501187d
@ -32,6 +32,7 @@ end
|
||||
|
||||
|
||||
-- called by yl_speak_up.input_talk(..)
|
||||
-- and also by yl_speak_up.get_fs_trade_list(..)
|
||||
--
|
||||
-- This function is called *after* the player has clicked on an option
|
||||
-- and *after* any actions (i.e. trade) have been completed either
|
||||
|
@ -403,3 +403,55 @@ yl_speak_up.eval_precondition = function(player, n_id, p, other_options_true_or_
|
||||
-- fallback - unknown type
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- helper function for yl_speak_up.eval_trade_list_preconditions
|
||||
yl_speak_up.eval_precondition_npc_inv = function(p, inv, inv_name)
|
||||
if(p.p_type ~= "npc_inv") then
|
||||
return false
|
||||
end
|
||||
-- determine the right inventory
|
||||
if( p.p_itemstack and p.p_value == "inv_contains") then
|
||||
return inv:contains_item(inv_name, p.p_itemstack)
|
||||
elseif(p.p_itemstack and p.p_value == "inv_does_not_contain") then
|
||||
return not(inv:contains_item(inv_name, p.p_itemstack))
|
||||
elseif(p.p_itemstack and p.p_value == "has_room_for") then
|
||||
return inv:room_for_item(inv_name, p.p_itemstack)
|
||||
elseif(p.p_value == "inv_is_empty") then
|
||||
return inv:is_empty(inv_name)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- cheaper version of eval_all_preconditions for the trade_list (d_trade);
|
||||
-- returns the ID of the first option where the precondition match or nil;
|
||||
-- *only* preconditions of the type "npc_inv" are evaluated!
|
||||
yl_speak_up.eval_trade_list_preconditions = function(player)
|
||||
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
|
||||
if(not(dialog) or not(dialog.n_dialogs) or not(dialog.n_dialogs["d_trade"])
|
||||
or not(dialog.n_dialogs["d_trade"].d_options)) then
|
||||
return
|
||||
end
|
||||
local options = dialog.n_dialogs["d_trade"].d_options
|
||||
local sorted_o_list = yl_speak_up.get_sorted_options(options, "o_sort")
|
||||
|
||||
local inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(n_id)})
|
||||
local inv_name = "npc_main"
|
||||
-- search through all options
|
||||
for i, s_o_id in ipairs(sorted_o_list) do
|
||||
local prereq = options[s_o_id].o_prerequisites
|
||||
local all_ok = true
|
||||
for k, p in pairs(prereq) do
|
||||
if(not(yl_speak_up.eval_precondition_npc_inv(p, inv, inv_name))) then
|
||||
all_ok = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if(all_ok) then
|
||||
return s_o_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -243,14 +243,14 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
"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") then
|
||||
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,7.3]"..
|
||||
"label[0.2,0.0;..this option will be selected automaticly.]"
|
||||
end
|
||||
if(answer_mode == 0 and d_id ~= "d_got_item") then
|
||||
if(answer_mode == 0 and (d_id ~= "d_got_item" and d_id ~= "d_trade")) then
|
||||
answer_text = answer_text..
|
||||
"label[1.2,0.8;A:]"..
|
||||
"field[1.7,0.3;19.6,0.9;text_option_"..minetest.formspec_escape(o_id)..";;"..
|
||||
@ -276,10 +276,22 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
"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 dialog was choosen manually.]"..
|
||||
"label[1.2,2.6;This is useful for offering a diffrent start dialog depending on the "..
|
||||
"player's progress in a quest.]"..
|
||||
"container_end[]"
|
||||
"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.]"..
|
||||
@ -384,7 +396,7 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
-- 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)
|
||||
list_of_effects = res.list
|
||||
local list_of_effects = res.list
|
||||
target_dialog = res.target_dialog
|
||||
target_effect = res.target_effect
|
||||
|
||||
@ -615,8 +627,14 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
"(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 = action_text..
|
||||
-- allow to change the target dialog via a dropdown menu
|
||||
"dropdown[10.2,0.0;3.0,0.7;d_id_"..minetest.formspec_escape(o_id)..";"..
|
||||
dialog_list..";"..dialog_selected..",]"..
|
||||
@ -627,7 +645,6 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
-- ..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.]"..
|
||||
"label[0.4,0.4;The NPC will react to this answer with dialog:]"..
|
||||
yl_speak_up.show_colored_dialog_text(
|
||||
dialog,
|
||||
-- this is either the "dialog" effect or an empty fallback
|
||||
@ -639,7 +656,7 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
"",
|
||||
"button_edit_action_success_dialog")..
|
||||
"container_end[]"
|
||||
|
||||
end
|
||||
end
|
||||
action_text = action_text.."container_end[]"
|
||||
|
||||
|
@ -413,6 +413,39 @@ yl_speak_up.get_fs_talkdialog_main_text_in_edit_mode = function(
|
||||
"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[0.2,5;19.6,17.8;d_text;"..
|
||||
"<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(active_dialog and active_dialog.d_text) then
|
||||
table.insert(formspec, "textarea[0.2,5;19.6,17.8;d_text;;"..
|
||||
minetest.formspec_escape(active_dialog.d_text or "?")..
|
||||
@ -507,6 +540,7 @@ yl_speak_up.get_fs_talkdialog_line_in_edit_mode = function(
|
||||
if v.r_type == "dialog"
|
||||
and (dialog.n_dialogs[v.r_value] ~= nil
|
||||
or v.r_value == "d_end"
|
||||
or v.r_value == "d_trade"
|
||||
or v.r_value == "d_got_item") then
|
||||
-- there may be more than one in the data structure
|
||||
target_dialog = v.r_value
|
||||
@ -735,6 +769,11 @@ yl_speak_up.get_fs_talkdialog = function(player, n_id, d_id, alternate_text, rec
|
||||
yl_speak_up.trade[pname] = nil
|
||||
yl_speak_up.speak_to[pname].trade_id = nil
|
||||
|
||||
-- add a d_trade dialog if necessary
|
||||
if(dialog and dialog.trades and dialog.n_dialogs and not(dialog.n_dialogs["d_trade"])) then
|
||||
yl_speak_up.add_new_dialog(dialog, pname, "trade", "[no text]")
|
||||
end
|
||||
|
||||
--[[ If we have an explicit call for a certain d_id, we grab it from parameters.
|
||||
If not, we grab in from context.
|
||||
When neither are present, we grab it from d_sort
|
||||
|
@ -124,6 +124,17 @@ yl_speak_up.get_fs_trade_list = function(player, show_dialog_option_trades)
|
||||
"label[0.2,0.5;Ups! This NPC lacks ID or name.]"..
|
||||
"button_exit[2,1.5;1,0.9;exit;Exit]"
|
||||
end
|
||||
-- the trade list is a bit special - we need to evaluate the preconditions of the
|
||||
-- options of the d_talk dialog and execute corresponding effects; this can be used
|
||||
-- to refill stock from chests or craft new items to increase stock
|
||||
local do_o_id = yl_speak_up.eval_trade_list_preconditions(player)
|
||||
if(do_o_id) then
|
||||
local effects = dialog.n_dialogs["d_trade"].d_options[do_o_id].o_results
|
||||
-- the return value is of no intrest here - we won't be showing another dialog,
|
||||
-- and alternate_text isn't relevant either; we just do the effects and then show
|
||||
-- the trade list
|
||||
local res = yl_speak_up.execute_all_relevant_effects(player, effects, do_o_id, true)
|
||||
end
|
||||
|
||||
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
|
||||
-- do not show trades attached to dialog options for players who cannot edit the NPC
|
||||
|
@ -302,6 +302,11 @@ yl_speak_up.add_new_option = function(dialog, pname, next_id, d_id, option_text,
|
||||
target_dialog = yl_speak_up.get_start_dialog_id(dialog)
|
||||
-- ...and this option needs to be selected automaticly
|
||||
dialog.n_dialogs[d_id].d_options[future_o_id].o_autoanswer = 1
|
||||
elseif(d_id == "d_trade") then
|
||||
-- we really don't want to go to another dialog from here
|
||||
target_dialog = "d_trade"
|
||||
-- ...and this option needs to be selected automaticly
|
||||
dialog.n_dialogs[d_id].d_options[future_o_id].o_autoanswer = 1
|
||||
end
|
||||
local future_r_id = nil
|
||||
-- create a fitting dialog result automaticly if possible:
|
||||
@ -342,6 +347,25 @@ yl_speak_up.add_new_option = function(dialog, pname, next_id, d_id, option_text,
|
||||
r_id = future_r_id,
|
||||
r_type = "deal_with_offered_item",
|
||||
r_value = "take_all"}
|
||||
|
||||
-- the trade dialog is equally special
|
||||
elseif(d_id == "d_trade") then
|
||||
dialog.n_dialogs[d_id].d_options[future_o_id].o_prerequisites = {}
|
||||
-- this is just an example
|
||||
dialog.n_dialogs[d_id].d_options[future_o_id].o_prerequisites["p_1"] = {
|
||||
p_id = "p_1",
|
||||
p_type = "npc_inv",
|
||||
p_value = "inv_does_not_contain",
|
||||
p_inv_list_name = "npc_main",
|
||||
p_itemstack = "default:stick "..tostring(100-next_id)}
|
||||
future_r_id = yl_speak_up.add_new_result(dialog, d_id, future_o_id)
|
||||
-- example craft
|
||||
dialog.n_dialogs[d_id].d_options[future_o_id].o_results[future_r_id] = {
|
||||
r_id = future_r_id,
|
||||
r_type = "craft",
|
||||
r_value = "default:stick 4",
|
||||
o_sort = "1",
|
||||
r_craft_grid = {"default:wood", "", "", "", "", "", "", "", ""}}
|
||||
end
|
||||
return future_o_id
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user