apply edit changes but don't store permanent yet

This commit is contained in:
Sokomine 2021-04-30 21:26:48 +02:00
parent 787550eca1
commit 3b90b1bb5d

View File

@ -37,6 +37,10 @@ yl_sokomine["q_apple_explorer"] = {}
-- 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 = {}
function yl_speak_up.init_mob_table()
return false
end
@ -999,6 +1003,7 @@ local function get_fs_talkdialog(player, n_id, d_id)
-- display the window with the text the NPC is saying
-- TODO: make name and description likewise editable?
-- TODO: make name of dialog and sort option editable?
if(edit_mode) then
-- TODO: sort by name?
@ -1197,8 +1202,8 @@ local function get_fs_talkdialog(player, n_id, d_id)
if(edit_mode) then
-- chat option: "Add a new answer/option to this dialog."
h = h + 1
table.insert(formspec, "button_exit[0.5," .. h .. ";53.8,0.9;button_add_option;]")
table.insert(formspec, "tooltip[button_add_option;Adds a new option to this dialog. You can delete options via the option edit menu.]")
table.insert(formspec, "button[0.5," .. h .. ";53.8,0.9;add_option;]")
table.insert(formspec, "tooltip[add_option;Adds a new option to this dialog. You can delete options via the option edit menu.]")
table.insert(formspec, "label[0.7,"..(h+0.45)..";Add a new option/answer to this dialog. You can delete options via the option edit menu.]")
-- chat option: "That was all. I'm finished with giving you new orders. Remember them!"
h = h + 1
@ -1659,6 +1664,153 @@ minetest.register_on_player_receive_fields(
-- talk
-- helper function
yl_speak_up.add_new_dialog = function(dialog, pname)
future_d_id = "d_" .. find_next_id(dialog.n_dialogs)
-- Initialize empty dialog
dialog.n_dialogs[future_d_id] = {
d_id = future_d_id,
d_type = "text",
d_text = "",
d_sort = -1 -- TODO
}
-- store that there have been changes to this npc
table.insert(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname] ],
"Dialog "..future_d_id..": New dialog added.")
return future_d_id
end
-- helper function for formspec "yl_speak_up:talk" 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
-- TODO: implement the change detection and ask the user what to do (save? discard?)
-- TODO: what if it is a new dialog?
-- Parameters:
-- pname player name
-- fields the fields returned from the formspec
yl_speak_up.edit_mode_apply_changes = function(pname, fields)
local d_id = yl_speak_up.speak_to[pname].d_id
local dialog = yl_speak_up.speak_to[pname].dialog
-- this way we can store the actual changes and present them to the player for saving
if(not(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname]])) then
yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname]] = {}
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
-- detect changes to d_text: text of the dialog (what the npc is saying)
if(fields.d_text and dialog.n_dialogs[ d_id ].d_text ~= fields.d_text) then
--minetest.chat_send_player("singleplayer","CHANGED: d_text (what the NPC says) was changed\n from: "..tostring( dialog.n_dialogs[ d_id ].d_text).."\n to: "..tostring(fields.d_text))
-- store that there have been changes to this npc
table.insert(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname] ],
"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
-- TODO: option to delete dialogs (when text empty and no options present?)
end
-- add a new option/answer
-- TODO: limit the amount of possible answers to a sensible amount
if(fields[ "add_option"]) then
local future_o_id = "o_" .. find_next_id(dialog.n_dialogs[d_id].d_options)
if dialog.n_dialogs[d_id].d_options == nil then
dialog.n_dialogs[d_id].d_options = {}
end
dialog.n_dialogs[d_id].d_options[future_o_id] = {
o_id = future_o_id,
o_hide_when_prerequisites_not_met = false,
o_grey_when_prerequisites_not_met = false,
o_sort = -1,
o_text_when_prerequisites_not_met = "",
o_text_when_prerequisites_met = "",
}
-- necessary in order for it to work
local s = sanitize_sort(dialog.n_dialogs[d_id].d_options, yl_speak_up.speak_to[pname].o_sort)
dialog.n_dialogs[d_id].d_options[future_o_id].o_sort = s
table.insert(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname] ],
"Dialog "..d_id..": Added new option/answer "..future_o_id..".")
end
-- changes to options are not possible if there are none
-- TODO: handle adding of a new dialog
if(not(dialog.n_dialogs[ d_id ].d_options)) then
return
end
-- 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
-- TODO: delete option if text is empty
--minetest.chat_send_player("singleplayer", "CHANGED: Text for option "..tostring(k).." was changed\n from: "..tostring(v.o_text_when_prerequisites_met).."\n to: "..tostring(fields[ "text_option_"..k]))
-- store that there have been changes to this npc
table.insert(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname] ],
"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>
-- TODO: this may also point to a new dialog
for k, v in pairs(dialog.n_dialogs[ d_id ].d_options) do
if( fields[ "d_id_"..k ] and v.o_results) then
for kr, vr in pairs(v.o_results) do
if( vr.r_type == "dialog" and vr.r_value and vr.r_value ~= fields[ "d_id_"..k ]) then
--minetest.chat_send_player("singleplayer", "CHANGED: Target dialog for option "..tostring(k).." was changed\n from: "..tostring(vr.r_value).."\n to: "..tostring(fields[ "d_id_"..k]))
-- store that there have been changes to this npc
table.insert(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname] ],
"Dialog "..d_id..": The target dialog for option "..tostring(k).." was changed from "..tostring(vr.r_value).." to "..tostring(fields[ "d_id_"..k])..".")
-- actually change the target dialog
vr.r_value = fields[ "d_id_"..k ]
end
end
-- this might be the first option
elseif( fields["d_id_"..k ]) then
--minetest.chat_send_player("singleplayer", "CHANGED: Target dialog for option "..tostring(k).." was added\n as: "..tostring(fields[ "d_id_"..k]))
-- store that a new option has been added to this dialog
table.insert(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname] ],
"Dialog "..d_id..": The target dialog for option "..tostring(k).." was changed from -default- to "..tostring(fields[ "d_id_"..k])..".")
-- create a new result (first the id, then the actual result)
local future_r_id = "r_" .. find_next_id(dialog.n_dialogs[d_id].d_options[k].o_results)
if future_r_id == "r_1" then
dialog.n_dialogs[d_id].d_options[k].o_results = {}
end
-- actually store the new result
dialog.n_dialogs[d_id].d_options[k].o_results[future_r_id] = {
r_id = future_r_id,
r_type = "dialog",
r_value = fields[ "d_id_"..k ]}
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
d_id = yl_speak_up.add_new_dialog(dialog, pname)
-- actually show the new dialog
fields.d_id = d_id
fields.show_new_dialog = nil
end
-- TODO just for debugging
for k,v in pairs(yl_speak_up.npc_was_changed[ yl_speak_up.edit_mode[pname] ]) do
minetest.chat_send_player("singleplayer", v )
end
end
-- end of yl_speak_up.edit_mode_apply_changes
minetest.register_on_player_receive_fields(
function(player, formname, fields)
if formname ~= "yl_speak_up:talk" then
@ -1668,6 +1820,15 @@ minetest.register_on_player_receive_fields(
local pname = player:get_player_name()
local o = ""
-- 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 in edit mode: detect if something was changed;
if(edit_mode) then
yl_speak_up.edit_mode_apply_changes(pname, fields)
end
-- start edit mode (requires npc_talk_owner)
if fields.button_start_edit_mode then
if( not(minetest.check_player_privs(player, {npc_talk_owner=true}))
@ -1734,9 +1895,6 @@ minetest.register_on_player_receive_fields(
end
end
-- 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) and o == "" then
return
end
@ -1757,7 +1915,7 @@ minetest.register_on_player_receive_fields(
-- if nothing better can be found: keep the old dialog
local show_dialog = d_id
-- "New dialog" button or option from dropdown menu was selected
if(fields.show_new_dialog or fields.d_id and fields.d_id == yl_speak_up.text_new_option_id) then
if(fields.show_new_dialog or (fields.d_id and fields.d_id == yl_speak_up.text_new_option_id)) then
-- TODO
-- dropdown menu was used; provided the dialog exists (and it's not the "New dialog" option)
elseif(fields.d_id and fields.d_id ~= show_dialog and dialog.n_dialogs[fields.d_id]) then