forked from Sokomine/yl_speak_up
first draft of alternate edit mode for players with npc_talk_owner priv
This commit is contained in:
parent
207cd3da43
commit
e40c464af8
227
functions.lua
227
functions.lua
@ -1,7 +1,42 @@
|
||||
-- TODO: just for the apple quest...needs to be deleted later on
|
||||
yl_sokomine = {}
|
||||
yl_sokomine["q_apple_explorer"] = {}
|
||||
-- if player has npc_talk_owner priv AND is owner of this particular npc (second one: TODO):
|
||||
-- chat option: "I am your owner. I have new orders for you.
|
||||
-- -> enters edit mode
|
||||
-- when edit_mode has been enabled, the following chat options are added to the options:
|
||||
-- chat option: "Add new answer/option to this dialog."
|
||||
-- -> adds a new option TODO
|
||||
-- chat option: "That was all. I'm finished with giving you new orders. Remember them!"
|
||||
-- -> ends edit mode
|
||||
--
|
||||
-- TODO: add the actual edit menu for options
|
||||
-- can be entered from the edit, conditions and effects button;
|
||||
-- style: Answer/Option: <text>
|
||||
-- Lets the NPC answer with: <dialog_id> [Button GOTO target dialog]
|
||||
--
|
||||
-- Only offer this answer if all the following conditions are true:
|
||||
-- <list of preconditions>
|
||||
-- If at least one condition is not fulfilled, ..
|
||||
-- <display the following text|grey out this answer|do not offer this answer>
|
||||
-- <alternate answer>
|
||||
-- When this answer has been selected, apply the following effects:
|
||||
-- <list of effects>
|
||||
--
|
||||
-- [Store] [Delete this option] [Back to dialog xyz] [GOTO target diaglog]
|
||||
--
|
||||
-- TODO: check if security is ok (minetest.formspec_escape etc)
|
||||
-- TODO: actually process changed entries
|
||||
-- TODO: allow owner to mute/unmute npc (would be bad if players can already see what is going
|
||||
-- to happen while the owner creates a long quest)
|
||||
|
||||
--###
|
||||
-- Init
|
||||
--###
|
||||
|
||||
-- store if the player is editing a particular NPC; format: yl_speak_up.edit_mode[pname] = npc_id
|
||||
yl_speak_up.edit_mode = {}
|
||||
|
||||
function yl_speak_up.init_mob_table()
|
||||
return false
|
||||
end
|
||||
@ -9,12 +44,14 @@ end
|
||||
minetest.register_on_leaveplayer(
|
||||
function(player)
|
||||
yl_speak_up.speak_to[player:get_player_name()] = nil
|
||||
yl_speak_up.edit_mode[player:get_player_name()] = nil
|
||||
end
|
||||
)
|
||||
|
||||
minetest.register_on_joinplayer(
|
||||
function(player)
|
||||
yl_speak_up.speak_to[player:get_player_name()] = nil
|
||||
yl_speak_up.edit_mode[player:get_player_name()] = nil
|
||||
end
|
||||
)
|
||||
|
||||
@ -949,16 +986,67 @@ local function get_fs_talkdialog(player, n_id, d_id)
|
||||
"image[15.5,0.5;4,4;",
|
||||
portrait,
|
||||
"]",
|
||||
"hypertext[0.2,5;19.6,17.8;d_text;<normal>",
|
||||
minetest.formspec_escape(active_dialog.d_text) .. "\n</normal>",
|
||||
"]",
|
||||
"tooltip[d_text;",
|
||||
minetest.formspec_escape(active_dialog.d_text):trim(),
|
||||
";#000000;#FFFFFF]",
|
||||
"scrollbaroptions[min=0;max=14;smallstep=1;largestep=2;arrows=show]",
|
||||
"scrollbar[0.2,24.2;0.2,7;vertical;scr0;0]",
|
||||
"scroll_container[0,24;56,7;scr0;vertical;1]"
|
||||
}
|
||||
|
||||
-- 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)
|
||||
|
||||
-- this is used to build a list of all available dialogs for a dropdown menu in edit mode
|
||||
-- (only relevant in edit mode)
|
||||
local dialog_list = yl_speak_up.text_new_dialog_id
|
||||
-- find the right index for the dialog_list dropdown above
|
||||
local d_id_to_dropdown_index = {}
|
||||
|
||||
-- display the window with the text the NPC is saying
|
||||
-- TODO: make name and description likewise editable?
|
||||
if(edit_mode) then
|
||||
|
||||
-- build the list of available dialogs for the dropdown list(s)
|
||||
-- if there are dialogs defined
|
||||
if(dialog and dialog.n_dialogs) then
|
||||
-- the first entry will be "New dialog"
|
||||
local n = 1
|
||||
for k, v in pairs(dialog.n_dialogs) do
|
||||
dialog_list = dialog_list .. "," .. v.d_id
|
||||
-- which one is the current dialog?
|
||||
n = n + 1
|
||||
d_id_to_dropdown_index[v.d_id] = n
|
||||
end
|
||||
end
|
||||
|
||||
local i = (d_id_to_dropdown_index[c_d_id] or 0)
|
||||
table.insert(formspec, "label[0.2,4.6;Dialog:]") -- "..minetest.formspec_escape(c_d_id)..":]")
|
||||
table.insert(formspec, "dropdown[3.0,4.0;5,1;d_id;"..dialog_list..";"..i..",]")
|
||||
table.insert(formspec, "tooltip[3.0,4.0;5,1;Select the dialog you want to edit. Currently, dialog "..c_d_id.." is beeing displayed.;#FFFFFF;#000000]")
|
||||
-- add previous/next buttons for previous/next dialog (sorted as in the dropdown menu);
|
||||
-- this is just an alternate way of walking through the dialogs
|
||||
for k,v in pairs(d_id_to_dropdown_index) do
|
||||
if( v == i-1) then
|
||||
table.insert(formspec, "button[8.5,4.0;2,0.9;dialog_"..k..";<]")
|
||||
-- add a tooltip
|
||||
table.insert(formspec, "tooltip[dialog_" .. k .. ";Go to previous dialog "..k..".]")
|
||||
elseif(v == i+1) then
|
||||
table.insert(formspec, "button[11,4.0;2,0.9;dialog_"..k..";>]")
|
||||
-- add a tooltip
|
||||
table.insert(formspec, "tooltip[dialog_" .. k .. ";Go to next dialog "..k..".]")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
table.insert(formspec, "textarea[0.2,5;19.6,17.8;d_text;;")
|
||||
table.insert(formspec, minetest.formspec_escape(active_dialog.d_text))
|
||||
table.insert(formspec, "]")
|
||||
else
|
||||
table.insert(formspec, "hypertext[0.2,5;19.6,17.8;d_text;<normal>")
|
||||
table.insert(formspec, minetest.formspec_escape(active_dialog.d_text) .. "\n</normal>")
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "tooltip[d_text;")
|
||||
table.insert(formspec, minetest.formspec_escape(active_dialog.d_text):trim())
|
||||
table.insert(formspec, ";#000000;#FFFFFF]")
|
||||
end
|
||||
table.insert(formspec, "scrollbaroptions[min=0;max=14;smallstep=1;largestep=2;arrows=show]")
|
||||
table.insert(formspec, "scrollbar[0.2,24.2;0.2,7;vertical;scr0;0]")
|
||||
table.insert(formspec, "scroll_container[0,24;56,7;scr0;vertical;1]")
|
||||
h = -0.8
|
||||
|
||||
-- Let#s sort the options by o_sort
|
||||
@ -969,7 +1057,62 @@ local function get_fs_talkdialog(player, n_id, d_id)
|
||||
end
|
||||
|
||||
for _, sb_v in pairs(sorted_buttons) do
|
||||
if allowed[sb_v.o_id] == true then
|
||||
-- in edit_mode: show all options
|
||||
if edit_mode then
|
||||
h = h + 1
|
||||
-- add a button "o_<nr>:" that leads to an edit formspec for this option
|
||||
table.insert(formspec, "button[1.8," .. h .. ";2,0.9;edit_option_" .. sb_v.o_id .. ";"..sb_v.o_id..":]")
|
||||
-- add a tooltip "Edit target dialog, pre(C)onditions and (E)ffects for option o_<nr>"
|
||||
table.insert(formspec, "tooltip[edit_option_" .. sb_v.o_id .. ";Edit target dialog, pre(C)onditions and (E)ffects for option "..sb_v.o_id..".]")
|
||||
|
||||
-- find the right target dialog for this option (if it exists):
|
||||
local target_dialog = nil
|
||||
local results = active_dialog.d_options[sb_v.o_id].o_results
|
||||
-- has this option more results/effects than just switching to another dialog?
|
||||
local has_other_results = false
|
||||
if(results ~= nil) then
|
||||
for k, v in pairs(results) do
|
||||
if v.r_type == "dialog" and dialog.n_dialogs[v.r_value] ~= nil then
|
||||
-- there may be more than one in the data structure
|
||||
target_dialog = v.r_value
|
||||
elseif v.r_type ~= "dialog" then
|
||||
has_other_results = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if(target_dialog) then
|
||||
-- add a button "-> d_<nr>" that leads to the target dialog (if one is set)
|
||||
table.insert(formspec, "button[8.5," .. h .. ";1,0.9;button_" .. sb_v.o_id .. ";->]")
|
||||
-- add a tooltip "Go to target dialog d_<nr>"
|
||||
table.insert(formspec, "tooltip[button_" .. sb_v.o_id .. ";Go to target dialog "..target_dialog.." that will be shown when this option ("..sb_v.o_id..") is selected.]")
|
||||
|
||||
-- selecting an option this way MUST NOT execute the pre(C)onditions or (E)ffects!
|
||||
end
|
||||
-- allow to set a new target dialog
|
||||
table.insert(formspec, "dropdown[3.9,"..h..";4.7,1;d_id_"..sb_v.o_id..";"..dialog_list..";"..(d_id_to_dropdown_index[target_dialog] or "0")..",]")
|
||||
-- add a tooltip "Change target dialog"
|
||||
table.insert(formspec, "tooltip[3.9,"..h..";4.7,1;Change target dialog for option "..sb_v.o_id..".;#FFFFFF;#000000]")
|
||||
|
||||
-- are there any prerequirements?
|
||||
local prereq = active_dialog.d_options[sb_v.o_id].o_prerequisites
|
||||
if(prereq) then
|
||||
table.insert(formspec, "button[0.5," .. h .. ";0.5,0.9;conditions_"..sb_v.o_id..";C]")
|
||||
-- label: "There are pre(C)onditions required for showing this option. Display them."
|
||||
table.insert(formspec, "tooltip[conditions_" .. sb_v.o_id .. ";There are pre(C)onditions required for showing this option. Display them.]")
|
||||
end
|
||||
if(has_other_results) then
|
||||
table.insert(formspec, "button[1.1," .. h .. ";0.6,0.9;effects_"..sb_v.o_id..";Ef]")
|
||||
-- label: "There are further (E)ffects (apart from switching to a new dialog) set for this option. Display them."
|
||||
table.insert(formspec, "tooltip[effects_" .. sb_v.o_id .. ";There are further (E)ffects (apart from switching to a new dialog) set for this option. Display them.]")
|
||||
end
|
||||
|
||||
-- show the actual text for the option
|
||||
table.insert(formspec, "field[9.4," .. h .. ";44.9,0.9;text_option_" .. sb_v.o_id .. ";;"..sb_v.o_text_when_prerequisites_met.."]")
|
||||
-- add a tooltip "Edit the text that is displayed on button o_<nr>."
|
||||
table.insert(formspec, "tooltip[text_option_" .. sb_v.o_id .. ";Edit the text that is displayed on button "..sb_v.o_id..".]")
|
||||
|
||||
-- normal mode: show an option if the prerequirements (if any are defined) are met
|
||||
elseif allowed[sb_v.o_id] == true then
|
||||
h = h + 1
|
||||
table.insert(formspec, "button[0.5," .. h .. ";53.8,0.9;button_" .. sb_v.o_id .. ";]")
|
||||
table.insert(
|
||||
@ -1045,6 +1188,32 @@ local function get_fs_talkdialog(player, n_id, d_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If in edit mode, add two new menu entries: "add new options" and "end edit mode".
|
||||
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, "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
|
||||
table.insert(formspec, "button_exit[0.5," .. h .. ";53.8,0.9;button_end_edit_mode;]")
|
||||
table.insert(formspec, "tooltip[button_end_edit_mode;Ends edit mode. From now on, your NPC will talk to you like he talks to other players. You can always give him new orders by entering edit mode again.]")
|
||||
table.insert(formspec, "label[0.7,"..(h+0.45)..";That was all. I'm finished with giving you new orders. Remember them!]")
|
||||
|
||||
-- Offer to enter edit mode if the player has the npc_talk_owner priv AND owns the npc.
|
||||
-- The npc_master priv allows to edit all NPC.
|
||||
-- TODO: the player also has to be owner of that particular npc
|
||||
elseif((minetest.check_player_privs(player, {npc_talk_owner=true}))
|
||||
or (minetest.check_player_privs(player, {npc_master=true}))) then
|
||||
-- chat option: "I am your owner. I have new orders for you.
|
||||
h = h + 1
|
||||
table.insert(formspec, "button_exit[0.5," .. h .. ";53.8,0.9;button_start_edit_mode;]")
|
||||
table.insert(formspec, "tooltip[button_start_edit_mode;Enters edit mode. In this mode, you can edit the texts the NPC says and the answers that can be given.]")
|
||||
table.insert(formspec, "label[0.7,"..(h+0.45)..";I am your owner. I have new orders for you.]")
|
||||
end
|
||||
|
||||
h = h + 1
|
||||
table.insert(formspec, "button_exit[0.5," .. h .. ";53.8,0.9;button_exit;]")
|
||||
table.insert(formspec, "tooltip[button_exit;" .. yl_speak_up.message_button_option_exit .. "]")
|
||||
@ -1495,6 +1664,29 @@ minetest.register_on_player_receive_fields(
|
||||
local pname = player:get_player_name()
|
||||
local o = ""
|
||||
|
||||
-- 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}))
|
||||
and not(minetest.check_player_privs(player, {npc_master=true}))) then
|
||||
minetest.chat_send_player(pname, "Sorry. You do not have the npc_talk_owner or npc_master priv.")
|
||||
return
|
||||
end
|
||||
-- TODO: check if this particular NPC is really owned by this player
|
||||
-- enter edit mode with that particular NPC
|
||||
yl_speak_up.edit_mode[pname] = yl_speak_up.speak_to[pname].n_id
|
||||
-- start a new chat - but this time in edit mode
|
||||
-- TODO: this continues where the last chat was and does not start from the beginning
|
||||
minetest.show_formspec(pname, "yl_speak_up:talk", get_fs_talkdialog(player, yl_speak_up.speak_to[pname].n_id))
|
||||
return
|
||||
-- end edit mode (does not require the priv; will only switch back to normal behaviour)
|
||||
elseif fields.button_end_edit_mode then
|
||||
yl_speak_up.edit_mode[pname] = nil
|
||||
-- start a new chat - but this time in normal mode
|
||||
-- TODO: this continues where the last chat was and does not start from the beginning
|
||||
minetest.show_formspec(pname, "yl_speak_up:talk", get_fs_talkdialog(player, yl_speak_up.speak_to[pname].n_id))
|
||||
return
|
||||
end
|
||||
|
||||
if fields.quit or fields.button_exit then
|
||||
-- Formspec was quit
|
||||
yl_speak_up.speak_to[pname] = nil
|
||||
@ -1542,8 +1734,11 @@ minetest.register_on_player_receive_fields(
|
||||
return
|
||||
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)
|
||||
|
||||
-- Let's check if the button was among the "allowed buttons". Only those may be executed
|
||||
if yl_speak_up.speak_to[pname].allowed and yl_speak_up.speak_to[pname].allowed[o] == false then
|
||||
if not(edit_mode) and (yl_speak_up.speak_to[pname].allowed and yl_speak_up.speak_to[pname].allowed[o] == false) then
|
||||
return
|
||||
end
|
||||
|
||||
@ -1560,7 +1755,9 @@ minetest.register_on_player_receive_fields(
|
||||
-- Let's do something if results exist
|
||||
if d_option.o_results ~= nil then
|
||||
for k, v in pairs(d_option.o_results) do
|
||||
if v.r_type == "give_item" then
|
||||
-- in edit_mode, only the switching to the next dialog is executed (we want to edit,
|
||||
-- not solve quests, get/take items, teleport...)
|
||||
if not(edit_mode) and v.r_type == "give_item" then
|
||||
local item = ItemStack(v.r_value)
|
||||
|
||||
if minetest.registered_items[item:get_name()] ~= nil then
|
||||
@ -1569,7 +1766,7 @@ minetest.register_on_player_receive_fields(
|
||||
say("Item not found!")
|
||||
end
|
||||
end
|
||||
if v.r_type == "take_item" then
|
||||
if not(edit_mode) and v.r_type == "take_item" then
|
||||
local item = ItemStack(v.r_value)
|
||||
|
||||
if minetest.registered_items[item:get_name()] ~= nil then
|
||||
@ -1578,7 +1775,7 @@ minetest.register_on_player_receive_fields(
|
||||
say("Item not found!")
|
||||
end
|
||||
end
|
||||
if v.r_type == "move" then
|
||||
if not(edit_mode) and v.r_type == "move" then
|
||||
local target_pos = nil
|
||||
local target_pos_valid = false
|
||||
|
||||
@ -1630,7 +1827,7 @@ minetest.register_on_player_receive_fields(
|
||||
end
|
||||
|
||||
end
|
||||
if v.r_type == "function" then
|
||||
if not(edit_mode) and v.r_type == "function" then
|
||||
local code = v.r_value
|
||||
if code:byte(1) == 27 then
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
|
10
privs.lua
10
privs.lua
@ -4,4 +4,12 @@ local npc_master_priv_definition = {
|
||||
give_to_admin = true,
|
||||
}
|
||||
|
||||
minetest.register_privilege("npc_master", npc_master_priv_definition)
|
||||
minetest.register_privilege("npc_master", npc_master_priv_definition)
|
||||
|
||||
local npc_talk_owner_priv_definition = {
|
||||
description="Can edit the dialogs of his/her own NPCs",
|
||||
give_to_singleplayer = false,
|
||||
give_to_admin = true,
|
||||
}
|
||||
|
||||
minetest.register_privilege("npc_talk_owner", npc_talk_owner_priv_definition)
|
||||
|
Loading…
Reference in New Issue
Block a user