added functions for updating and importing dialogs and options for future ink import

This commit is contained in:
Sokomine 2025-01-01 22:37:59 +01:00
parent 10e90e412a
commit c0fcbecd63

View File

@ -11,6 +11,10 @@
-- Helpers
--###
yl_speak_up.string_starts_with = function(str, starts_with)
return (string.sub(str, 1, string.len(starts_with)) == starts_with)
end
yl_speak_up.get_number_from_id = function(any_id)
if(not(any_id) or any_id == "d_got_item" or any_id == "d_end" or any_id == "d_dynamic") then
return "0"
@ -97,6 +101,50 @@ yl_speak_up.add_new_dialog = function(dialog, pname, next_id, dialog_text)
return future_d_id
end
-- update existing or create a new dialog named d_name with d_text
-- (useful for import from ink and likewise functionality)
yl_speak_up.update_dialog = function(log, dialog, dialog_name, dialog_text)
-- does a dialog with name d_name already exist?
local d_id = yl_speak_up.d_name_to_d_id(dialog, dialog_name)
-- name the thing for logging purposes
local log_str = "Dialog "..tostring(d_id)
if(dialog_name and dialog_name ~= d_id) then
log_str = " ["..tostring(dialog_name).."]: "
end
if(not(d_id)) then
-- pname is nil - thus no logging and no adding of a back to start option
-- next_id is also nil - so just add a new dialog
d_id = yl_speak_up.add_new_dialog(dialog, nil, nil, dialog_text)
if(not(d_id)) then
-- the creation may have failed (i.e. dialog not beeing a dialog,
-- or too many dialogs in dialog already)
table.insert(log, log_str.."FAILED to create new dialog.")
return nil
end
table.insert(log, log_str.."Successfully created dialog.")
elseif(dialog.n_dialogs[d_id].d_text ~= dialog_text) then
-- else update the text
table.insert(log, log_str.."Changed dialog text from \""..
tostring(dialog.n_dialogs[d_id].d_text).."\" to \""..tostring(dialog_text).."\".")
-- actually change the dialog text
dialog.n_dialogs[d_id].d_text = dialog_text
end
-- set d_name if it differs from d_id
if(d_id ~= dialog_name
and (not(dialog.n_dialogs[d_id].d_name)
or(dialog.n_dialogs[d_id].d_name ~= dialog_name))) then
table.insert(log, log_str.."Changed dialog name from \""..
tostring(dialog.n_dialogs[d_id].d_name).."\" to \""..tostring(dialog_name).."\".")
-- actually change the dialog name
dialog.n_dialogs[d_id].d_name = dialog_name
end
return d_id
end
-- add a new option/answer to dialog d_id with option_text (or default "")
-- option_text (optional) the text that shall be shown as option/answer
-- target_dialog (optional) the target dialog where the player will end up when choosing
@ -227,6 +275,198 @@ yl_speak_up.add_new_option = function(dialog, pname, next_id, d_id, option_text,
end
-- update existing or create a new option named option_name for dialog dialog_name
-- If option_name starts with..
-- new_ create a new option (discard the rest of option_name)
-- automaticly_ set o_autoanswer
-- randomly_ set o_random
-- grey_out_ set o_text_when_prerequisites_not_met
-- ..and take what remains as option_name.
-- (useful for import from ink and likewise functionality)
--
-- TODO: these notes need to be taken care of in the calling function
-- Note: The calling function may need to adjust o_sort according to its needs.
-- Note: The calling function also needs to take care to set *all* dialog options to
-- *randomly selected* if at least *one* is set to this value. This cannot be done
-- here as the other dialog options may not even be definied here yet.
-- Note: Preconditions, actions and effects are not handled here (apart from the "dialog"
-- effect/result for the redirection to the target dialog)
yl_speak_up.update_dialog_option = function(log, dialog, dialog_name, option_name, option_text, target_dialog,
alternate_text, visit_only_once)
-- does the dialog we want to add to exist?
local d_id = yl_speak_up.d_name_to_d_id(dialog, dialog_name)
if(not(d_id)) then
-- the dialog does not exist - we cannot add an option to a nonexistant dialog
return nil
end
-- name the thing for logging purposes
local log_str = "Dialog "..tostring(d_id)
if(dialog_name and dialog_name ~= d_id) then
log_str = " ["..tostring(dialog_name).."], option <"..tostring(option_name)..">: "
end
-- translate the name of the target_dialog if needed
if(target_dialog and not(yl_speak_up.is_special_dialog(target_dialog))) then
target_dialog = yl_speak_up.d_name_to_d_id(dialog, target_dialog)
end
-- TODO: dialogs d_got_item and d_trade are special
local o_id = option_name
local mode = 0
local text_when_prerequisites_not_met = ""
if( o_id and syl_speak_up.string_starts_with(o_id, "new_")) then
-- we are asked to create a *new* option
o_id = nil
elseif(o_id and yl_speak_up.string_starts_with(o_id, "automaticly_")) then
-- this option will be automaticly selected if its preconditions are true
mode = 1
option_name = string.sub(o_id, string.find(o_id, "automaticly_") + 1)
o_id = option_name
elseif(o_id and yl_speak_up.string_starts_with(o_id, "randomly_")) then
-- this option will be randomly selected if its preconditions are true;
-- (that means all other options of this dialog will have to be randomly as well;
-- something which cannot be done here as there is no guarantee that all options
-- *exist* at this point)
mode = 2
option_name = string.sub(o_id, string.find(o_id, "randomly_") + 1)
o_id = option_name
elseif(o_id and yl_speak_up.string_starts_with(o_id, "grey_out_")) then
-- this sets o_text_when_prerequisites_not_met
mode = 3
option_name = string.sub(o_id, string.find(o_id, "grey_out_") + 1)
o_id = option_name
-- in this case we don't want to change the old text - just the greyed out one
-- (we keep option_text in case the option needs to be created)
text_when_prerequisites_not_met = option_text
end
-- if the option does not exist: create it
if( not(dialog.n_dialogs[d_id].d_options)
or not(o_id) or o_id == ""
or not(dialog.n_dialogs[d_id].d_options[o_id])) then
local next_id = nil
-- get the id part (number) from o_id - because we may be creating a new option here -
-- but said option may have a diffrent *name* than what a new option would get by
-- default
if(o_id) then
next_id = string.sub(o_id, 3)
if(next_id == "" or not(tonumber(next_id))) then
next_id = nil
table.insert(log, log_str.."FAILED to create new option.")
end
end
-- pname is nil - thus no logging here
o_id = yl_speak_up.add_new_option(dialog, nil, next_id, d_id, option_text, target_dialog)
if(not(o_id)) then
return nil
end
table.insert(log, log_str.."Successfully created new option \""..tostring(o_id).."\".")
-- do not change the option_text when we want to change the text of the grey_out_ option text
elseif(dialog.n_dialogs[d_id].d_options[o_id].o_text_when_prerequisites_met ~= option_text
and mode ~= 3) then
-- else update the text
table.insert(log, log_str.."Changed option text from \""..
tostring(dialog.n_dialogs[d_id].d_text.d_options[o_id])..
"\" to \""..tostring(option_text).."\" for option \""..tostring(o_id).."\".")
-- actually update the text
dialog.n_dialogs[d_id].d_options[o_id].o_text_when_prerequisites_met = option_text
end
-- abbreviate that
local o_data = dialog.n_dialogs[d_id].d_options[o_id]
local r_found = false
-- the target_dialog may have been changed
for r_id, r in pairs(o_data.o_results or {}) do
-- we found the right result/effect that holds the (current) target_dialog
if(r and r.r_type and r.r_type == "dialog") then
if(not(r.r_value) or r.r_value ~= target_dialog) then
table.insert(log, log_str.."Changed target dialog from \""..
tostring(r.r_value).."\" to \""..tostring(target_dialog)..
"\" for option \""..tostring(o_id).."\".")
-- actually change the target dialog
r_found = true
r.r_value = target_dialog
end
-- the alternate_text may have been changed
if(r.alternate_text ~= alternate_text) then
table.insert(log, log_str.."Changed alternate text from \""..
tostring(r.r_alternate_text).."\" to \""..tostring(alternate_text)..
"\" for option \""..tostring(o_id).."\".")
r.alternate_text = alternate_text
end
end
end
-- for some reason the effect pointing to the target dialog got lost!
if(not(r_found)) then
-- create the result/effect that points to the target_dialog
local r_id = yl_speak_up.add_new_result(dialog, d_id, o_id)
if(r_id) then
o_data.o_results[r_id].r_type = "dialog"
o_data.o_results[r_id].r_value = target_dialog
o_data.o_results[r_id].alternate_text = alternate_text
table.insert(log, log_str.."Set target dialog to "..tostring(target_dialog)..
" for option \""..tostring(o_id).."\".")
end
end
-- is this option selected automaticly if all preconditions are met?
if( mode == 1 and not(o_data.o_autoanswer)) then
o_data.o_autoanswer = 1
table.insert(log, log_str.."Changed option \""..tostring(o_id).."\" to AUTOMATICLY SELECTED.")
-- actually update the text
-- is this option selected randomly?
elseif(mode == 2 and not(o_data.o_random)) then
o_data.o_random = 1
table.insert(log, log_str.."Changed option \""..tostring(o_id).."\" to RANDOMLY SELECTED.")
-- grey out the given text and show that as answer when preconditions not met?
elseif(mode == 3) then
if((not(o_dat.o_text_when_prerequisites_not_met
or o_data.o_text_when_prerequisites_not_met ~= text_when_prerequisites_not_met))) then
table.insert(log, log_str.."Changed option text WHEN PREREQUISITES NOT MET from \""..
tostring(o_data.o_text_when_prerequisites_not_met)..
"\" to \""..tostring(text_when_prerequisites_not_met)..
"\" for option \""..tostring(o_id).."\".")
-- actually change it
o_data.o_text_when_prerequisites_not_met = text_when_prerequisites_not_met
end
-- make sure this text is really shown - and greyed out
-- (resetting this can only happen through editing the NPC directly; not through import)
o_data.o_hide_when_prerequisites_not_met = "false"
o_data.o_grey_when_prerequisites_not_met = "true"
else
-- mode is 0 - that means everything is normal for this option
if(o_data.o_autoanswer) then
o_data.o_autoanswer = nil
table.insert(log, log_str.."Removed AUTOMATICLY SELECTED from option \""..
tostring(o_id).."\".")
end
if(o_data.o_random) then
o_data.o_random = nil
table.insert(log, log_str.."Removed RANDOMLY SELECTED from option \""..
tostring(o_id).."\".")
end
-- set visibility back to default
o_data.o_hide_when_prerequisites_not_met = "false"
o_data.o_grey_when_prerequisites_not_met = "false"
end
-- the visit_only_once option is handled without logging as it might create too many
-- entries in the log without adding any helpful information
if(visit_only_once
and (not(o_data.sb_v.o_visit_only_once) or o_data.o_visit_only_once ~= 1)) then
o_data.sb_v.o_visit_only_once = 1
elseif(not(visit_only_once)
and o_data.sb_v.o_visit_only_once and o_data.o_visit_only_once == 1) then
o_data.sb_v.o_visit_only_once = nil
end
return o_id
end
-- add a new result to option o_id of dialog d_id
yl_speak_up.add_new_result = function(dialog, d_id, o_id)
if(not(dialog) or not(dialog.n_dialogs) or not(dialog.n_dialogs[d_id])
@ -239,8 +479,10 @@ yl_speak_up.add_new_result = function(dialog, d_id, o_id)
dialog.n_dialogs[d_id].d_options[o_id].o_results = {}
end
dialog.n_dialogs[d_id].d_options[o_id].o_results[future_r_id] = {}
dialog.n_dialogs[d_id].d_options[o_id].o_results[future_r_id].r_id = future_r_id
return future_r_id
end
-- TODO: we need yl_speak_up.update_dialog_option_result as well
-- this is useful for result types that can exist only once per option
@ -366,6 +608,7 @@ yl_speak_up.d_name_to_d_id = function(dialog, d_name)
return k
end
end
return nil
end