From 4c577280ac2f8ed432ffb0443c936ebdaa8be25b Mon Sep 17 00:00:00 2001 From: Sokomine Date: Sun, 17 Jul 2022 19:08:43 +0200 Subject: [PATCH] added handling of property changes through custom functions --- config.lua | 9 ++++ custom_functions_you_can_override.lua | 24 ++++++++++ exec_apply_effects.lua | 10 ++-- fs_properties.lua | 69 ++++++++++++++++++--------- 4 files changed, 85 insertions(+), 27 deletions(-) diff --git a/config.lua b/config.lua index 8fed351..f8c9aab 100644 --- a/config.lua +++ b/config.lua @@ -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" diff --git a/custom_functions_you_can_override.lua b/custom_functions_you_can_override.lua index fe47b4e..95b6594 100644 --- a/custom_functions_you_can_override.lua +++ b/custom_functions_you_can_override.lua @@ -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 diff --git a/exec_apply_effects.lua b/exec_apply_effects.lua index df8958a..03d62ad 100644 --- a/exec_apply_effects.lua +++ b/exec_apply_effects.lua @@ -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)..".") diff --git a/fs_properties.lua b/fs_properties.lua index 58a9361..b16fca8 100644 --- a/fs_properties.lua +++ b/fs_properties.lua @@ -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. 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]"..