394 lines
16 KiB
Lua
394 lines
16 KiB
Lua
-- set name, description and owner of the NPC
|
|
-- (owner can only be set if the player has the npc_talk_master
|
|
-- priv - not with npc_talk_owner priv alone)
|
|
yl_speak_up.input_fs_initial_config = function(player, formname, fields)
|
|
local pname = player:get_player_name()
|
|
local n_id = yl_speak_up.speak_to[pname].n_id
|
|
|
|
if(fields.back_from_error_msg) then
|
|
-- no point in showing the formspec or error message again if we did so already
|
|
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
|
|
return
|
|
end
|
|
-- show this formspec again
|
|
yl_speak_up.show_fs(player, "initial_config",
|
|
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false})
|
|
return
|
|
end
|
|
|
|
if(fields.edit_skin and fields.edit_skin ~= "") then
|
|
yl_speak_up.show_fs(player, "fashion")
|
|
return
|
|
end
|
|
|
|
if(fields.edit_properties and fields.edit_properties ~= "") then
|
|
yl_speak_up.show_fs(player, "properties")
|
|
return
|
|
end
|
|
|
|
if((not(fields.save_initial_config)
|
|
and not(fields.show_nametag)
|
|
and not(fields.list_may_edit)
|
|
and not(fields.add_may_edit)
|
|
) or (fields and fields.exit)) then
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
-- unconfigured NPC
|
|
if(fields and fields.exit and not(dialog) or not(dialog.n_dialogs)) then
|
|
minetest.chat_send_player(pname, "Aborting initial configuration.")
|
|
return
|
|
end
|
|
-- is the player editing the npc? then leaving this config
|
|
-- dialog has to lead back to the talk dialog
|
|
if(yl_speak_up.edit_mode[pname] == n_id and n_id) then
|
|
yl_speak_up.show_fs(player, "talk",
|
|
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id})
|
|
end
|
|
-- else we can quit here
|
|
return
|
|
end
|
|
|
|
local error_msg = nil
|
|
-- remove leading and tailing spaces from the potential new NPC name in order to avoid
|
|
-- confusing names where a player's name (or that of another NPC) is beginning/ending
|
|
-- with blanks
|
|
if(fields.n_npc) then
|
|
fields.n_npc = fields.n_npc:match("^%s*(.-)%s*$")
|
|
end
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
-- the player is trying to save the initial configuration
|
|
-- is the player allowed to initialize this npc?
|
|
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
|
|
error_msg = "You are not allowed to edit this NPC."
|
|
elseif(not(fields.n_npc) or string.len(fields.n_npc) < 2) then
|
|
error_msg = "The name of your NPC needs to be\nat least two characters long."
|
|
elseif(minetest.check_player_privs(fields.n_npc, {interact=true})
|
|
and not(minetest.check_player_privs(player, {npc_talk_master=true}))
|
|
and not(minetest.check_player_privs(player, {npc_talk_admin=true}))) then
|
|
error_msg = "You cannot name your NPC after an existing player.\n"..
|
|
"Only those with the npc_talk_admin priv can do so."
|
|
elseif(not(fields.n_description) or string.len(fields.n_description) < 2) then
|
|
error_msg = "Please provide a description of your NPC!"
|
|
-- sensible length limit
|
|
elseif(string.len(fields.n_npc)>40 or string.len(fields.n_description)>40) then
|
|
error_msg = "The name and description of your NPC\ncannot be longer than 40 characters."
|
|
-- want to change the owner?
|
|
elseif(fields.n_owner and fields.n_owner ~= yl_speak_up.npc_owner[ n_id ]) then
|
|
if( not(minetest.check_player_privs(player, {npc_talk_master=true}))) then
|
|
error_msg = "You need the \"npc_talk_master\" priv\nin order to change the owner."
|
|
elseif(not(minetest.check_player_privs(fields.n_owner, {npc_talk_owner=true}))) then
|
|
error_msg = "The NPC can only be owned by players that\n"..
|
|
"have the \"npc_talk_owner\" priv. Else the\n"..
|
|
"new owner could not edit his own NPC."
|
|
end
|
|
-- want to change who may edit this npc?
|
|
-- delete a player from the list of those allowed to edit the NPC
|
|
elseif(fields.delete_may_edit and fields.delete_may_edit ~= ""
|
|
and fields.list_may_edit and fields.list_may_edit ~= "") then
|
|
if(pname ~= yl_speak_up.npc_owner[ n_id ]) then
|
|
error_msg = "Only the owner of the NPC\ncan change this."
|
|
elseif(not(dialog)) then
|
|
error_msg = "Please set a name for your NPC first!"
|
|
else
|
|
-- actually delete the player from the list
|
|
dialog.n_may_edit[ fields.list_may_edit ] = nil
|
|
-- show the next entry
|
|
yl_speak_up.speak_to[pname].tmp_index = math.max(1,
|
|
yl_speak_up.speak_to[pname].tmp_index-1)
|
|
end
|
|
-- add a player who may edit this NPC
|
|
elseif(fields.add_may_edit and fields.add_may_edit ~= "") then
|
|
if(pname ~= yl_speak_up.npc_owner[ n_id ]) then
|
|
error_msg = "Only the owner of the NPC\ncan change this."
|
|
elseif(fields.add_may_edit == pname) then
|
|
error_msg = "You are already the owner of this NPC!\nNo need to add you extra here."
|
|
elseif(not(minetest.check_player_privs(fields.add_may_edit, {interact=true}))) then
|
|
error_msg = "Player \""..minetest.formspec_escape(fields.add_may_edit)..
|
|
"\" not found."
|
|
elseif(not(dialog)) then
|
|
error_msg = "Please set a name for the NPC first!"
|
|
else
|
|
if(not(dialog.n_may_edit)) then
|
|
dialog.n_may_edit = {}
|
|
end
|
|
dialog.n_may_edit[ fields.add_may_edit ] = true
|
|
-- jump to the index with this player so that the player sees that he has been added
|
|
local tmp_list = yl_speak_up.sort_keys(dialog.n_may_edit, true)
|
|
local index = table.indexof(tmp_list, fields.add_may_edit)
|
|
if(index and index > 0) then
|
|
-- "Add player:" is added before all other names, so +1
|
|
yl_speak_up.speak_to[pname].tmp_index = index + 1
|
|
end
|
|
end
|
|
-- selected a player name in the why may edit this NPC dropdown?
|
|
elseif(fields.list_may_edit and fields.list_may_edit ~= "") then
|
|
local tmp_list = yl_speak_up.sort_keys(dialog.n_may_edit, true)
|
|
local index = table.indexof(tmp_list, fields.list_may_edit)
|
|
if(fields.list_may_edit == "Add player:") then
|
|
index = 0
|
|
end
|
|
if(index and index > -1) then
|
|
yl_speak_up.speak_to[pname].tmp_index = index + 1
|
|
end
|
|
end
|
|
if(error_msg) then
|
|
yl_speak_up.show_fs(player, "msg", { input_to = "yl_speak_up:initial_config",
|
|
formspec = "size[6,2]"..
|
|
"label[0.2,0.0;"..tostring(error_msg).."]"..
|
|
"button[2,1.5;1,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
-- warn players with npc_talk_master priv if the name of an npc is used by a player already
|
|
if(minetest.check_player_privs(fields.n_npc, {interact=true})) then
|
|
minetest.chat_send_player(pname, "WARNING: A player named \'"..tostring(fields.n_npc)..
|
|
"\' exists. This NPC got assigned the same name!")
|
|
end
|
|
|
|
local d_id = yl_speak_up.speak_to[pname].d_id
|
|
local count = 0
|
|
if(dialog and dialog.n_dialogs) then
|
|
for k,v in pairs(dialog.n_dialogs) do
|
|
count = count + 1
|
|
end
|
|
end
|
|
|
|
|
|
-- we checked earlier if the player doing this change and the
|
|
-- player getting the NPC have appropriate privs
|
|
if(fields.n_owner ~= yl_speak_up.npc_owner[ n_id ]) then
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"Owner changed from "..tostring(yl_speak_up.npc_owner[ n_id ])..
|
|
" to "..tostring(fields.n_owner).." for "..
|
|
"NPC name: \""..tostring(fields.n_npc))
|
|
-- the owner will actually be changed further down, at the end of this function
|
|
yl_speak_up.npc_owner[ n_id ] = fields.n_owner
|
|
end
|
|
|
|
-- give the NPC its first dialog
|
|
if(not(dialog) or count==0) then
|
|
local f = {}
|
|
-- create a new dialog
|
|
f.d_id = yl_speak_up.text_new_dialog_id
|
|
-- ...with this text
|
|
f.d_text = "$GOOD_DAY$ $PLAYER_NAME$,\n"..
|
|
"I am $NPC_NAME$. I don't know much yet.\n"..
|
|
"Hopefully $OWNER_NAME$ will teach me to talk soon."
|
|
-- it is the first, initial dialog
|
|
f.d_sort = "0"
|
|
f.n_npc = fields.n_npc
|
|
f.n_description = fields.n_description
|
|
f.npc_owner = yl_speak_up.npc_owner[ n_id ]
|
|
-- create and save the first dialog for this npc
|
|
local dialog = yl_speak_up.fields_to_dialog(pname, f)
|
|
|
|
-- add example answers and dialogs; they may be irritating for experienced
|
|
-- users, but help new users a lot in figuring out how the system works
|
|
--
|
|
-- first, we create three example dialogs as such:
|
|
-- (the first one has already been created in the creation of the dialog;
|
|
-- yl_speak_up.fields_to_dialog stores d_id in yl_speak_up.speak_to[pname].d_id)
|
|
local new_d_1 = "d_1"
|
|
local new_d_2 = yl_speak_up.add_new_dialog(dialog, pname, "2",
|
|
"I'm glad that you wish me to talk to you.\n\n"..
|
|
"I hope we can talk more soon!")
|
|
local new_d_3 = yl_speak_up.add_new_dialog(dialog, pname, "3",
|
|
"Oh! Do you really think so?\n\n"..
|
|
"To me, talking is important.")
|
|
-- we are dealing with a new NPC, so there are no options yet
|
|
-- options added to dialog f.d_id:
|
|
local new_d_1_o_1 = yl_speak_up.add_new_option(dialog, pname, nil,
|
|
"d_1", "I hope so as well!", new_d_2)
|
|
local new_d_1_o_2 = yl_speak_up.add_new_option(dialog, pname, nil,
|
|
"d_1", "No. Talking is overrated.", new_d_3)
|
|
-- options added to dialog new_d_2:
|
|
local new_d_2_o_1 = yl_speak_up.add_new_option(dialog, pname, nil,
|
|
"d_2", "Glad that we agree.", new_d_1)
|
|
-- options added to dialog new_d_3:
|
|
local new_d_3_o_1 = yl_speak_up.add_new_option(dialog, pname, nil,
|
|
"d_3", "No. I was just joking. I want to talk to you!", new_d_2)
|
|
local new_d_3_o_2 = yl_speak_up.add_new_option(dialog, pname, nil,
|
|
"d_3", "Yes. Why am I talking to you anyway?", "d_end")
|
|
-- save our new dialog
|
|
yl_speak_up.save_dialog(n_id, dialog)
|
|
yl_speak_up.speak_to[pname].dialog = dialog
|
|
dialog.n_may_edit = {}
|
|
-- now connect the dialogs via results
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"Initial config saved. "..
|
|
"NPC name: \""..tostring(fields.n_npc)..
|
|
"\" Description: \""..tostring(fields.n_description).."\".")
|
|
elseif(fields.add_may_edit and fields.add_may_edit ~= "") then
|
|
yl_speak_up.save_dialog(n_id, dialog)
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"Added to \"may be edited by\": "..tostring(fields.add_may_edit))
|
|
elseif(fields.delete_may_edit and fields.delete_may_edit ~= ""
|
|
and fields.list_may_edit and fields.list_may_edit ~= "") then
|
|
yl_speak_up.save_dialog(n_id, dialog)
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"Removed from \"may be edited by\": "..tostring(fields.list_may_edit))
|
|
-- just change name and description
|
|
elseif((fields.n_npc and fields.n_npc ~= "")
|
|
or (fields.n_description and fields.n_description ~= "")) then
|
|
dialog = yl_speak_up.speak_to[pname].dialog
|
|
if(dialog.n_npc ~= fields.n_npc
|
|
or dialog.n_description ~= fields.n_description) then
|
|
dialog.n_npc = fields.n_npc
|
|
dialog.n_description = fields.n_description
|
|
yl_speak_up.save_dialog(n_id, dialog)
|
|
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"Name and/or description changed. "..
|
|
"NPC name: \""..tostring(fields.n_npc)..
|
|
"\" Description: \""..tostring(fields.n_description)..
|
|
"\" May be edited by: \""..
|
|
table.concat(yl_speak_up.sort_keys(dialog.n_may_edit, true), " ").."\".")
|
|
end
|
|
end
|
|
|
|
dialog = yl_speak_up.speak_to[pname].dialog
|
|
|
|
-- show nametag etc.
|
|
if yl_speak_up.speak_to[pname].obj then
|
|
local obj = yl_speak_up.speak_to[pname].obj
|
|
local ent = obj:get_luaentity()
|
|
if ent ~= nil then
|
|
if(fields.show_nametag) then
|
|
local new_nametag_state = "- UNDEFINED -"
|
|
if(fields.show_nametag == "false") then
|
|
ent.yl_speak_up.hide_nametag = true
|
|
dialog.hide_nametag = true
|
|
new_nametag_state = "HIDE"
|
|
-- update_nametag else will only work on reload
|
|
obj:set_nametag_attributes({text=""})
|
|
elseif(fields.show_nametag == "true") then
|
|
ent.yl_speak_up.hide_nametag = nil
|
|
dialog.hide_nametag = nil
|
|
new_nametag_state = "SHOW"
|
|
end
|
|
yl_speak_up.save_dialog(n_id, dialog)
|
|
yl_speak_up.log_change(pname, n_id,
|
|
tostring(new_nametag_state).." nametag.")
|
|
minetest.chat_send_player(pname,
|
|
tostring(dialog.n_npc)..": I will "..
|
|
tostring(new_nametag_state).." my nametag.")
|
|
end
|
|
ent.yl_speak_up.npc_name = dialog.n_npc
|
|
ent.yl_speak_up.npc_description = dialog.n_description
|
|
ent.owner = yl_speak_up.npc_owner[ n_id ] or dialog.npc_owner
|
|
local i_text = dialog.n_npc .. "\n" ..
|
|
dialog.n_description .. "\n" ..
|
|
yl_speak_up.infotext
|
|
obj:set_properties({infotext = i_text})
|
|
yl_speak_up.update_nametag(ent)
|
|
end
|
|
end
|
|
|
|
if(not(fields.save_initial_config)) then
|
|
yl_speak_up.show_fs(player, "initial_config",
|
|
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false})
|
|
return
|
|
end
|
|
if((fields.add_may_edit and fields.add_may_edit ~= "")
|
|
or (fields.delete_may_edit and fields.delete_may_edit ~= "")) then
|
|
-- show this formspec again
|
|
yl_speak_up.show_fs(player, "initial_config",
|
|
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false})
|
|
else
|
|
-- actually start a chat with our new npc
|
|
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id})
|
|
end
|
|
end
|
|
|
|
|
|
-- initialize the npc without having to use a staff;
|
|
-- returns true when initialization possible
|
|
yl_speak_up.get_fs_initial_config = function(player, n_id, d_id, is_initial_config)
|
|
local pname = player:get_player_name()
|
|
|
|
-- is the player allowed to edit this npc?
|
|
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
|
|
return "size[6,2]"..
|
|
"label[0.2,0.0;Sorry. You are not authorized\nto edit this NPC.]"..
|
|
"button_exit[2,1.5;1,0.9;back_from_error_msg;Exit]"
|
|
end
|
|
|
|
local tmp_show_nametag = "true"
|
|
local tmp_name = n_id
|
|
local tmp_descr = "A new NPC without description"
|
|
local tmp_text = "Please provide your new NPC with a name and description!"
|
|
local tmp_owner = (yl_speak_up.npc_owner[ n_id ] or "- none -")
|
|
local table_of_names = {}
|
|
local may_be_edited_by = ""
|
|
-- use existing name and description as presets when just editing
|
|
if(not(is_initial_config)) then
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
tmp_show_nametag = not(dialog.hide_nametag)
|
|
tmp_name = (dialog.n_npc or tmp_name)
|
|
tmp_descr = (dialog.n_description or tmp_descr)
|
|
tmp_text = "You can change the name and description of your NPC."
|
|
-- dialog.n_may_edit was a string for a short time in development
|
|
if(not(dialog.n_may_edit) or type(dialog.n_may_edit) ~= "table") then
|
|
dialog.n_may_edit = {}
|
|
end
|
|
table_of_names = dialog.n_may_edit
|
|
may_be_edited_by =
|
|
-- who can edit this NPC?
|
|
"label[0.2,4.75;May be edited by:]"..
|
|
-- offer a dropdown list and a text input field for player names for adding
|
|
yl_speak_up.create_dropdown_playerlist(player, pname,
|
|
table_of_names, yl_speak_up.speak_to[pname].tmp_index,
|
|
3.0, 4.3, 0.0, 1.0, "list_may_edit", "player",
|
|
"Remove selected\nplayer from list",
|
|
"add_may_edit",
|
|
"Enter the name of the player whom you\n"..
|
|
"want to grant the right to edit your NPC.\n"..
|
|
"The player needs at least the npc_talk_owner priv\n"..
|
|
"in order to actually edit the NPC.\n"..
|
|
"Click on \"Save\" to add the new player.",
|
|
"delete_may_edit",
|
|
"If you click here, the player will no\n"..
|
|
"longer be able to edit your NPC."
|
|
)
|
|
end
|
|
local formspec = "size[11,8.0]"..
|
|
"label[0.2,0.5;"..tmp_text.."]"..
|
|
-- name of the npc
|
|
"checkbox[2.2,0.9;show_nametag;;"..tostring(tmp_show_nametag).."]"..
|
|
"label[2.7,0.9;Show nametag]"..
|
|
"label[0.2,1.65;Name:]"..
|
|
"field[2.2,1.2;4,0.9;n_npc;;"..minetest.formspec_escape(tmp_name).."]"..
|
|
"label[7.0,1.65;NPC ID: "..minetest.colorize("#FFFF00",tostring(n_id)).."]"..
|
|
"tooltip[n_npc;n_npc: The name of the NPC;#FFFFFF;#000000]"..
|
|
-- description of the npc
|
|
"label[0.2,2.65;Description:]"..
|
|
"field[2.2,2.2;8,0.9;n_description;;"..minetest.formspec_escape(tmp_descr).."]"..
|
|
"tooltip[n_description;n_description: A description for the NPC;#FFFFFF;#000000]"..
|
|
-- the owner of the NPC
|
|
"label[0.2,3.65;Owner:]"..
|
|
"field[2.2,3.2;8,0.9;n_owner;;"..minetest.formspec_escape(tmp_owner).."]"..
|
|
"tooltip[n_owner;The owner of the NPC. This can only be changed\n"..
|
|
"if you have the npc_talk_master priv.;#FFFFFF;#000000]"..
|
|
may_be_edited_by..
|
|
"button[1.0,5.5;4,0.9;edit_skin;Edit Skin]"..
|
|
"button[6.0,5.5;4,0.9;edit_properties;Edit Properties]"..
|
|
-- save and exit buttons
|
|
"button[3.2,7.0;2,0.9;save_initial_config;Save]"..
|
|
"button_exit[5.4,7.0;2,0.9;exit;Exit]"
|
|
-- show the formspec to the player
|
|
return formspec
|
|
end
|
|
|
|
|
|
yl_speak_up.get_fs_initial_config_wrapper = function(player, param)
|
|
if(not(param)) then
|
|
param = {}
|
|
end
|
|
return yl_speak_up.get_fs_initial_config(player, param.n_id, param.d_id, param.is_initial_config)
|
|
end
|
|
|
|
yl_speak_up.register_fs("initial_config",
|
|
yl_speak_up.input_initial_config,
|
|
yl_speak_up.get_fs_initial_config_wrapper,
|
|
-- no special formspec required:
|
|
nil
|
|
)
|