forked from your-land-mirror/yl_speak_up
		
	
		
			
				
	
	
		
			222 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| -- Properties for NPC --
 | |
| -- This is used when an NPC doesn't have a specific dialog but still wants to
 | |
| -- make use of a (or some) generic dialog(es)
 | |
| 
 | |
| -- helper function:
 | |
| -- get one property value of the NPC
 | |
| yl_speak_up.get_one_npc_property = function(pname, property_name)
 | |
| 	if(not(pname)) then
 | |
| 		return nil
 | |
| 	end
 | |
| 	-- get just the property data
 | |
| 	return yl_speak_up.get_npc_properties(pname, false)[property_name]
 | |
| end
 | |
| 
 | |
| 
 | |
| -- helper function;
 | |
| -- adds "normal" properties of the npc with a self.<property_name> prefix as well
 | |
| -- if long_version is not set, a table containing all properties is returned;
 | |
| -- if long_version *is* set, a table containing the table above plus additional entries is returned
 | |
| yl_speak_up.get_npc_properties_long_version = function(pname, long_version)
 | |
| 	if(not(pname) or not(yl_speak_up.speak_to[pname])) then
 | |
| 		return {}
 | |
| 	end
 | |
| 	local obj = yl_speak_up.speak_to[pname].obj
 | |
| 	if(not(obj)) then
 | |
| 		return {}
 | |
| 	end
 | |
| 	local entity = obj:get_luaentity()
 | |
| 	if(not(entity)) then
 | |
| 		return {}
 | |
| 	end
 | |
| 	if(not(entity.yl_speak_up)) then
 | |
| 		return {}
 | |
| 	end
 | |
| 	local properties = entity.yl_speak_up.properties
 | |
| 	if(not(properties)) then
 | |
| 		properties = {}
 | |
| 		entity.yl_speak_up.properties = properties
 | |
| 	end
 | |
| 	-- copy other property data that is stored under self.* over as well (like i.e. self.order for mobs_redo)
 | |
| 	for k, v in pairs(entity) do
 | |
| 		local t = type(v)
 | |
| 		if(t == "string" or t == "number" or t == "boolean") then
 | |
| 			properties["self."..tostring(k)] = tostring(v)
 | |
| 		end
 | |
| 	end
 | |
| 	properties["self.name"] = tostring(entity.name)
 | |
| 	if(not(long_version)) then
 | |
| 		return properties
 | |
| 	end
 | |
| 	-- the long version contains additional information
 | |
| 	local prop_names = {}
 | |
| 	for k, v in pairs(properties) do
 | |
| 		table.insert(prop_names, k)
 | |
| 	end
 | |
| 	table.sort(prop_names)
 | |
| 	return {obj = obj, entity = entity, properties = properties, prop_names = prop_names}
 | |
| end
 | |
| 
 | |
| 
 | |
| -- most of the time we don't need object, entity or a list of the names of properties;
 | |
| -- this returns just the properties themshelves
 | |
| yl_speak_up.get_npc_properties = function(pname)
 | |
| 	return yl_speak_up.get_npc_properties_long_version(pname, false)
 | |
| end
 | |
| 
 | |
| 
 | |
| yl_speak_up.set_npc_property = function(pname, property_name, property_value, reason)
 | |
| 	if(not(pname) or not(property_name) or property_name == "") then
 | |
| 		return "No player name or property name given. Cannot load property data."
 | |
| 	end
 | |
| 	-- here we want a table with additional information
 | |
| 	local property_data = yl_speak_up.get_npc_properties_long_version(pname, true)
 | |
| 	if(not(property_data)) then
 | |
| 		return "Failed to load property data of NPC."
 | |
| 	end
 | |
| 	-- it is possible to react to property changes with special custom handlers
 | |
| 	if(yl_speak_up.custom_property_handler[property_name]) then
 | |
| 		-- the table contains the pointer to a fucntion
 | |
| 		local fun = yl_speak_up.custom_property_handler[property_name]
 | |
| 		-- call that function with the current values
 | |
| 		return fun(pname, property_name, property_value, property_data)
 | |
| 	end
 | |
| 	-- properties of type self. are not set directly
 | |
| 	if(string.sub(property_name, 1, 5) == "self.") then
 | |
| 		return "Properties of the type \"self.\" cannot be modified."
 | |
| 	end
 | |
| 	-- properites starting with "server" can only be changed or added manually by
 | |
| 	-- players with the npc_talk_admin priv
 | |
| 	if(string.sub(property_name, 1, 6) == "server") then
 | |
| 		if(not(reason) or reason ~= "manually" or not(pname)
 | |
| 		  or not(minetest.check_player_privs(pname, {npc_talk_admin=true}))) then
 | |
| 			return "Properties starting with \"server\" can only be changed by players "..
 | |
| 				"who have the \"npc_talk_admin\" priv."
 | |
| 		end
 | |
| 	end
 | |
| 	-- store it
 | |
| 	if(property_data.entity) then
 | |
| 		property_data.entity.yl_speak_up.properties[property_name] = property_value
 | |
| 		local n_id = yl_speak_up.speak_to[pname].n_id
 | |
| 		yl_speak_up.log_change(pname, n_id, "Property \""..tostring(property_name)..
 | |
| 					"\" set to \""..tostring(property_value).."\".")
 | |
| 	end
 | |
| 	-- TODO: handle non-npc (blocks etc)
 | |
| 	return "OK"
 | |
| end
 | |
| 
 | |
| 
 | |
| yl_speak_up.input_properties = function(player, formname, fields)
 | |
| 	local pname = player:get_player_name()
 | |
| 	if(not(pname) or not(yl_speak_up.speak_to[pname])) then
 | |
| 		return
 | |
| 	end
 | |
| 	local n_id = yl_speak_up.speak_to[pname].n_id
 | |
| 
 | |
| 	if(fields and fields.back and fields.back ~= "") 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
 | |
| 
 | |
| 	local selected_row = nil
 | |
| 	if(fields and fields.store_new_val and fields.store_new_val ~= "" and fields.prop_val) then
 | |
| 		yl_speak_up.set_npc_property(pname, fields.prop_name, fields.prop_val, "manually")
 | |
| 
 | |
| 	elseif(fields and fields.delete_prop and fields.delete_prop ~= "") then
 | |
| 		-- delete the old property
 | |
| 		yl_speak_up.set_npc_property(pname, fields.prop_name, nil, "manually")
 | |
| 
 | |
| 	elseif(fields and fields.table_of_properties) then
 | |
| 		local selected = minetest.explode_table_event(fields.table_of_properties)
 | |
| 		if(selected.type == "CHG" or selected.type == "DLC") then
 | |
| 			selected_row = selected.row
 | |
| 		end
 | |
| 	end
 | |
| 	yl_speak_up.show_fs(player, "properties", {selected = selected_row})
 | |
| end
 | |
| 
 | |
| 
 | |
| yl_speak_up.get_fs_properties = function(pname, selected)
 | |
| 	if(not(pname)) then
 | |
| 		return ""
 | |
| 	end
 | |
| 	local n_id = yl_speak_up.speak_to[pname].n_id
 | |
| 
 | |
| 	-- is the player editing this npc? if not: abort
 | |
| 	if(not(yl_speak_up.edit_mode[pname])
 | |
| 	  or (yl_speak_up.edit_mode[pname] ~= n_id)) then
 | |
| 		return ""
 | |
| 	end
 | |
| 
 | |
| 	-- we want the long version with additional information
 | |
| 	local property_data = yl_speak_up.get_npc_properties_long_version(pname, true)
 | |
| 	if(not(property_data)) then
 | |
| 		-- something went wrong - there really is nothing useful we can do
 | |
| 		-- if the NPC we want to interact with doesn't exist or is broken
 | |
| 		return
 | |
| 	end
 | |
| 	local s = ""
 | |
| 	if(not(property_data.prop_names)) then
 | |
| 		property_data.prop_names = {}
 | |
| 	end
 | |
| 	local anz_prop = #property_data.prop_names
 | |
| 	for i, k in ipairs(property_data.prop_names) do
 | |
| 		local v = property_data.properties[k]
 | |
| 		s = s.."#BBBBFF,"..minetest.formspec_escape(k)..","..minetest.formspec_escape(v)..","
 | |
| 	end
 | |
| 	s = s.."#00FF00,add,Add a new property"
 | |
| 
 | |
| 	if(not(selected) or selected == "") then
 | |
| 		selected = -1
 | |
| 	end
 | |
| 	local add_selected = "label[3.5,6.5;No property selected.]"
 | |
| 	selected = tonumber(selected)
 | |
| 	if(selected > anz_prop + 1 or selected < 1) then
 | |
| 		selected = -1
 | |
| 	elseif(selected > anz_prop) then
 | |
| 		add_selected = "label[0.2,6.5;Add new property:]"..
 | |
| 			"field[3.0,6.5;3.5,1.0;prop_name;;]"..
 | |
| 			"label[6.5,6.5;with value:]"..
 | |
| 			"field[8.2,6.5;4.5,1.0;prop_val;;]"..
 | |
| 			"button[8.2,7.8;2.0,1.0;store_new_val;Store]"
 | |
| 	-- external properties can usually only be read but not be changed
 | |
| 	elseif(string.sub(property_data.prop_names[selected], 1, 5) == "self."
 | |
| 	  and not(yl_speak_up.custom_property_handler[property_data.prop_names[selected]])) then
 | |
| 		add_selected = "label[3.5,6.5;Properties of the type \"self.\" usually cannot be modified.]"
 | |
| 	elseif(string.sub(property_data.prop_names[selected], 1, 6) == "server"
 | |
| 	  and not(minetest.check_player_privs(pname, {npc_talk_admin=true}))) then
 | |
| 		add_selected = "label[3.5,6.5;Properties starting with \"server\" can only be "..
 | |
| 				"changed by players\nwho have the \"npc_talk_admin\" priv."
 | |
| 	else
 | |
| 		local name = property_data.prop_names[selected]
 | |
| 		local val = minetest.formspec_escape(property_data.properties[name])
 | |
| 		local name_esc = minetest.formspec_escape(name)
 | |
| 		add_selected = "label[0.2,6.5;Change property:]"..
 | |
| 			"field[3.0,6.5;3.5,1.0;prop_name;;"..name_esc.."]"..
 | |
| 			"label[6.5,6.5;to value:]"..
 | |
| 			"field[8.2,6.5;4.5,1.0;prop_val;;"..val.."]"..
 | |
| 			"button[8.2,7.8;2.0,1.0;store_new_val;Store]"..
 | |
| 			"button[10.4,7.8;2.0,1.0;delete_prop;Delete]"
 | |
| 	end
 | |
| 	if(selected < 1) then
 | |
| 		selected = ""
 | |
| 	end
 | |
| 	local dialog = yl_speak_up.speak_to[pname].dialog
 | |
| 	local npc_name = minetest.formspec_escape(dialog.n_npc or "- nameless -")
 | |
| 	return "size[12.5,8.5]" ..
 | |
| 		"label[2,0;Properties of "..npc_name.." (ID: "..tostring(n_id).."):]"..
 | |
| 		"tablecolumns[color,span=1;text;text]"..
 | |
| 		"table[0.2,0.5;12,4.0;table_of_properties;"..s..";"..tostring(selected).."]"..
 | |
| 		"tooltip[0.2,0.5;12,4.0;"..
 | |
| 			"Click on \"add\" to add a new property.\n"..
 | |
| 			"Click on the name of a property to change or delete it.]"..
 | |
| 		"label[2.0,4.5;"..
 | |
| 			"Properties are important for NPC that want to make use of generic dialogs.\n"..
 | |
| 			"Properties can be used to determine which generic dialog(s) shall apply to\n"..
 | |
| 			"this particular NPC and how they shall be configured. You need the\n"..
 | |
| 			"\"npc_talk_admin\" priv to edit properties starting with the text \"server\".]"..
 | |
| 		"button[5.0,7.8;2.0,0.9;back;Back]"..
 | |
| 		add_selected
 | |
| end
 |