added new tabs 'Limit guessing:' and 'Limit repeating:' to edit options menu

This commit is contained in:
Sokomine 2021-08-04 04:15:45 +02:00
parent bba08f62dc
commit 0629d6ba2c
4 changed files with 189 additions and 12 deletions

View File

@ -67,3 +67,15 @@ yl_speak_up.blacklist_action_quest_item = {}
yl_speak_up.chat_all_prefix = minetest.colorize("#0000FF", "[NPC] ")
-- the NPC will use this color when sending a chat message
yl_speak_up.chat_all_color = "#AAAAFF"
-- it's possible to prevent players from trying actions (i.e. npc_gives, text_input, ..) too often;
-- if no special text is set, this one will be shown (tab "Limit guessing:" in edit options menu)
yl_speak_up.standard_text_if_action_failed_too_often = "You have tried so many times. I'm tired! "..
"Come back when you know the answer - but not before tomorrow."
-- it's also possible to prevent players from successfully executing actions too often (after all the
-- quest items are created from the finite NPC's inventory); this is the standard text that will be
-- shown by default (tab "Limit repeating:" in edit options menu)
yl_speak_up.standard_text_if_action_repeated_too_soon = "I don't have infinite ressources. If you lost "..
"something I gave you - come back tomorrow and we may talk again."

View File

@ -29,6 +29,16 @@ yl_speak_up.input_edit_option_dialog = function(player, formname, fields)
{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
@ -331,13 +341,15 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
-- make all following coordinates relative
local action_text = "container[0.2,13.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
action_text = action_text..
-- allow to switch between successful and failed actions
"tabheader[0.2,0.0;switch_tab;"..
"If the action was successful:,"..
"If the action failed:;2;true;true]"..
-- 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
@ -364,6 +376,97 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
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 = 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 = 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
@ -373,11 +476,8 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
"label[0.4,0.6;"..
"There is no (A)ction defined. Directly apply the following (Ef)fects:]"
else
action_text = action_text..
-- allow to switch between successful and failed actions
"tabheader[0.2,0.0;switch_tab;"..
"If the action was successful:,"..
"If the action failed:;1;true;true]"..
-- allow to switch between successful and failed actions
action_text = 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:]"
@ -418,6 +518,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
action_text = action_text.."container_end[]"

View File

@ -1423,6 +1423,44 @@ yl_speak_up.edit_mode_apply_changes = function(pname, fields)
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

View File

@ -70,6 +70,26 @@ yl_speak_up.add_quest_variable = function(owner_name, variable_name)
end
-- time based variables are used for "Limit guessing:" and "Limit repeating:"; they ensure that
-- options with actions cannot be repeated indefintely;
-- returns false if the variable could not be created; else it returns the variable metadata
yl_speak_up.add_time_based_variable = function(variable_name)
if(not(yl_speak_up.player_vars[ variable_name ])) then
yl_speak_up.player_vars[ variable_name ] = {}
yl_speak_up.player_vars[ variable_name ][ "$META$" ] = {}
yl_speak_up.player_vars[ variable_name ][ "$META$"][ "var_type" ] = "time_based"
yl_speak_up.save_quest_variables(true)
return yl_speak_up.player_vars[ variable_name ][ "$META$"]
elseif(yl_speak_up.player_vars[ variable_name ]
and yl_speak_up.player_vars[ variable_name ][ "$META$"]
and type(yl_speak_up.player_vars[ variable_name ][ "$META$"]) == "table"
and yl_speak_up.player_vars[ variable_name ][ "$META$"][ "var_type" ] == "time_based") then
return yl_speak_up.player_vars[ variable_name ][ "$META$"]
end
return false
end
-- accidentally created or no longer needed variables need to be deleted somehow
-- force_delete if set, the variable will be deleted no matter what; this is for
-- manual maintenance and not used in this mod
@ -305,7 +325,9 @@ end
-- in general, meta_name is a table containing entries entry_name (usually players or npc_ids)
-- with assigned values (usually true) for quick lookup
yl_speak_up.set_variable_metadata = function(k, pname, meta_name, entry_name, new_value)
k = yl_speak_up.add_pname_to_var(k, pname)
if(pname) then
k = yl_speak_up.add_pname_to_var(k, pname)
end
-- delete/unset
if(not(new_value)) then
new_value = nil
@ -451,7 +473,7 @@ end
-- which NPC do use this variable?
yl_speak_up.get_variable_metadata = function(var_name, meta_name)
yl_speak_up.get_variable_metadata = function(var_name, meta_name, get_as_is)
-- var_type (the type of the variable) is a single string
if(meta_name and var_name and meta_name == "var_type") then
if( not(yl_speak_up.player_vars[ var_name ])
@ -469,6 +491,10 @@ yl_speak_up.get_variable_metadata = function(var_name, meta_name)
or type(yl_speak_up.player_vars[ var_name ][ "$META$"][ meta_name ]) ~= "table") then
return {}
end
-- do not transform into a list; get the table
if(get_as_is) then
return yl_speak_up.player_vars[ var_name ][ "$META$"][ meta_name ]
end
local meta_list = {}
for k, v in pairs(yl_speak_up.player_vars[ var_name ][ "$META$"][ meta_name ]) do
table.insert(meta_list, k)