added handling of property changes through custom functions

This commit is contained in:
Sokomine 2022-07-17 19:08:43 +02:00
parent 0d86db2088
commit 4c577280ac
4 changed files with 85 additions and 27 deletions

View File

@ -21,6 +21,15 @@ yl_speak_up.enable_yl_mobs = true
yl_speak_up.talk_after_spawn = true
-- some properties from external NPC can be edited and changed (they have the self. prefix),
-- and it is possible to react to property changes with handlers;
-- key: name of the property (i.e. self.order);
-- value: function that reacts to attempts to change the property
-- For an example, see custom_functions_you_can_override.lua
yl_speak_up.custom_property_handler = {}
-- What shall we call the folder all the dialogs will reside in?
yl_speak_up.path = "yl_speak_up_dialogs"

View File

@ -286,4 +286,28 @@ yl_speak_up.custom_functions_r_[ "example function" ] = {
param9_desc = "This is the value passed to the function as 9. parameter.",
}
-----------------------------------------------------------------------------
-- Custom handling of special properties
-----------------------------------------------------------------------------
-- self.order is used by most mobs_redo NPC and stores weather they ought to
-- stand around, follow the player or wander around randomly
yl_speak_up.custom_property_self_order = function(pname, property_name, property_value, property_data)
if(property_name ~= "self.order") then
return "This function handles only the self.order property."
end
if(property_value == "stand") then
property_data.entity.state = stand
property_data.entity.attack = nil
property_data.entity:set_animation("stand")
property_data.entity:set_velocity(0)
elseif(property_value ~= "wander"
and property_value ~= "follow") then
return "self.order can only be set to stand, wander or follow."
end
property_data.entity.order = property_value
return "OK"
end
-- make sure the mod knows how to handle change attempts to the property self.order
yl_speak_up.custom_property_handler["self.order"] = yl_speak_up.custom_property_self_order

View File

@ -518,10 +518,12 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
local var_val = property_data.properties[r.r_value]
-- set the value of the variable
local new_value = yl_speak_up.execute_effect_get_new_value(r, var_val, nil)
-- add the new property or change an existing one
property_data.properties[r.r_value] = new_value
-- store it
property_data.entity.yl_speak_up.properties = property_data.properties
local res = yl_speak_up.set_npc_property(pname, r.r_value, new_value)
if(res ~= "OK") then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
"property: "..tostring(res))
return false
end
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
"state: Success: Set property "..tostring(r.r_value).." to "..
tostring(new_value)..".")

View File

@ -3,7 +3,8 @@
-- 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
-- helper function;
-- adds "normal" properties of the npc with a self.<property_name> prefix as well
yl_speak_up.get_npc_properties = function(pname)
if(not(pname) or not(yl_speak_up.speak_to[pname])) then
return
@ -24,12 +25,45 @@ yl_speak_up.get_npc_properties = function(pname)
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)
local prop_names = {}
for k, v in pairs(properties) do
table.insert(prop_names, k)
end
table.sort(prop_names)
return {entity = entity, properties = properties, prop_names = prop_names}
return {obj = obj, entity = entity, properties = properties, prop_names = prop_names}
end
yl_speak_up.set_npc_property = function(pname, property_name, property_value)
if(not(pname) or not(property_name) or property_name == "") then
return "No player name or property name given. Cannot load property data."
end
local property_data = yl_speak_up.get_npc_properties(pname)
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 "This properties of the type \"self.\" cannot be modified."
end
-- store it
property_data.entity.yl_speak_up.properties[property_name] = property_value
return "OK"
end
@ -47,27 +81,12 @@ yl_speak_up.input_properties = function(player, formname, fields)
end
local selected_row = nil
if(fields and fields.store_new_val and fields.store_new_val ~= "") then
local property_data = yl_speak_up.get_npc_properties(pname)
if(property_data and fields.prop_name and fields.prop_name ~= ""
and fields.prop_val and fields.prop_val ~= "") then
local name = fields.prop_name
local val = fields.prop_val
-- add the new property or change an existing one
property_data.properties[name] = val
-- store it
property_data.entity.yl_speak_up.properties = property_data.properties
end
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)
elseif(fields and fields.delete_prop and fields.delete_prop ~= "") then
local property_data = yl_speak_up.get_npc_properties(pname)
if(property_data and fields.prop_name and fields.prop_name ~= "") then
local name = fields.prop_name
-- delete the old property
property_data.properties[name] = nil
-- store it
property_data.entity.yl_speak_up.properties = property_data.properties
end
-- delete the old property
yl_speak_up.set_npc_property(pname, fields.prop_name, nil)
elseif(fields and fields.table_of_properties) then
local selected = minetest.explode_table_event(fields.table_of_properties)
@ -118,12 +137,16 @@ yl_speak_up.get_fs_properties = function(pname, selected)
"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.]"
else
local name = property_data.prop_names[selected]
local val = minetest.formspec_escape(property_data.properties[name])
name = minetest.formspec_escape(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.."]"..
"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]"..