implemented effect 'property' and prepared effect 'evaluate'

This commit is contained in:
Sokomine 2022-06-19 19:32:30 +02:00
parent 4612576cfc
commit 187416396b
3 changed files with 162 additions and 82 deletions

View File

@ -121,6 +121,68 @@ yl_speak_up.execute_all_relevant_effects = function(player, effects, o_id, actio
end
-- helper function for yl_speak_up.execute_effect
-- used by "state" (pname is nil) and "property" (pname is nil)
yl_speak_up.execute_effect_get_new_value = function(r, var_val, pname)
-- for "state" - but not for "property"
if(pname
and (r.r_operator == "quest_step"
or r.r_operator == "maximum" or r.r_operator == "minimum"
or r.r_operator == "increment" or r.r_operator == "decrement")) then
var_val = yl_speak_up.get_quest_variable_value(pname, r.r_variable)
end
-- set the value of the variable
local new_value = nil
if( r.r_operator and r.r_operator == "set_to") then
new_value = r.r_var_cmp_value
elseif(r.r_operator and r.r_operator == "unset") then
new_value = nil
elseif(r.r_operator and r.r_operator == "set_to_current_time") then
-- we store the time in seconds - because microseconds would just
-- confuse the users and be too fine grained anyway
new_value = math.floor(minetest.get_us_time()/1000000)
elseif(r.r_operator and r.r_operator == "quest_step") then
-- quest_step and maximum are effectively the same
-- TODO: later on, quest steps may be strings
if(var_val and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = math.max(tonumber(var_val), tonumber(r.r_var_cmp_value))
else
new_value = r.r_var_cmp_value
end
elseif(r.r_operator and r.r_operator == "maximum") then
if(var_val and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = math.max(tonumber(var_val), tonumber(r.r_var_cmp_value))
else
new_value = r.r_var_cmp_value
end
elseif(r.r_operator and r.r_operator == "minimum") then
if(var_val and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = math.min(tonumber(var_val), tonumber(r.r_var_cmp_value))
else
new_value = r.r_var_cmp_value
end
elseif(r.r_operator and r.r_operator == "increment") then
if(var_val and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = tonumber(var_val) + tonumber(r.r_var_cmp_value)
else
new_value = r.r_var_cmp_value
end
elseif(r.r_operator and r.r_operator == "decrement") then
if(var_val and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = tonumber(var_val) - tonumber(r.r_var_cmp_value)
else
new_value = -1 * r.r_var_cmp_value
end
else
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
"state: Unsupported type: "..tostring(r.r_value)..".")
-- keep the old value
new_value = var_val
end
return new_value
end
-- executes an effect/result r for the player and npc n_id;
-- returns true on success (relevant for on_failure)
-- Note: In edit mode, this function does not get called.
@ -431,65 +493,43 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
return false
end
local pname = player:get_player_name()
local owner = yl_speak_up.npc_owner[ n_id ]
-- set the value of the variable
local new_value = nil
if( r.r_operator and r.r_operator == "set_to") then
new_value = r.r_var_cmp_value
elseif(r.r_operator and r.r_operator == "unset") then
new_value = nil
elseif(r.r_operator and r.r_operator == "set_to_current_time") then
-- we store the time in seconds - because microseconds would just
-- confuse the users and be too fine grained anyway
new_value = math.floor(minetest.get_us_time()/1000000)
elseif(r.r_operator and r.r_operator == "quest_step") then
-- quest_step and maximum are effectively the same
-- TODO: later on, quest steps may be strings
local var_val = yl_speak_up.get_quest_variable_value(pname, r.r_variable)
if(var_value and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = math.max(tonumber(var_val), tonumber(r.r_var_cmp_value))
else
new_value = r.r_var_cmp_value
end
elseif(r.r_operator and r.r_operator == "maximum") then
local var_val = yl_speak_up.get_quest_variable_value(pname, r.r_variable)
if(var_value and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = math.max(tonumber(var_val), tonumber(r.r_var_cmp_value))
else
new_value = r.r_var_cmp_value
end
elseif(r.r_operator and r.r_operator == "minimum") then
local var_val = yl_speak_up.get_quest_variable_value(pname, r.r_variable)
if(var_value and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = math.min(tonumber(var_val), tonumber(r.r_var_cmp_value))
else
new_value = r.r_var_cmp_value
end
elseif(r.r_operator and r.r_operator == "increment") then
local var_val = yl_speak_up.get_quest_variable_value(pname, r.r_variable)
if(var_value and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = tonumber(var_val) + tonumber(r.r_var_cmp_value)
else
new_value = r.r_var_cmp_value
end
elseif(r.r_operator and r.r_operator == "decrement") then
local var_val = yl_speak_up.get_quest_variable_value(pname, r.r_variable)
if(var_value and tonumber(var_val) and tonumber(r.r_var_cmp_value)) then
new_value = tonumber(var_val) + tonumber(r.r_var_cmp_value)
else
new_value = -1 * r.r_var_cmp_value
end
else
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
"state: Unsupported type: "..tostring(r.r_value)..".")
return false
end
local new_value = yl_speak_up.execute_effect_get_new_value(r, nil, pname)
-- the owner is already encoded in the variable name
local ret = yl_speak_up.set_quest_variable_value(pname, r.r_variable, new_value)
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
"state: Success: "..tostring(ret).." for setting "..tostring(r.r_variable).." to "..
tostring(new_value)..".")
return ret
-- "the value of a property of the NPC (for generic NPC)", -- property
elseif(r.r_type == "property") then
local pname = player:get_player_name()
local property_data = yl_speak_up.get_npc_properties(pname)
if(not(property_data)) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
"property: Failed to access properties of NPC "..tostring(n_id))
return false
end
if(not(r.r_value) or r.r_value == "") then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
"property: No name of property given")
return false
end
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
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)..".")
return true
-- "something that has to be calculated or evaluated (=call a function)", -- evaluate
elseif(r.r_type == "evaluate") then
-- TODO
return true
-- "a block somewhere" -- 3
elseif(r.r_type == "block") then
-- is the position given correctly?

View File

@ -15,6 +15,17 @@
-- r_var_cmp_value can be set freely by the player (the variable will be
-- set to this value)
--
-- the value of a property of the NPC (for generic NPC) ("property"):
-- r_value name of the property that is to be changed
-- r_operator how shall the property be changed?
-- r_var_cmp_value the new value (or increment/decrement) for this property
--
-- something that has to be calculated or evaluated (=call a function) ("evaluate"):
-- r_value the name of the function that is to be called
-- r_param1 the first paramter (optional; depends on function)
-- ..
-- r_param9 the 9th parameter (optional; depends on function)
--
-- a block in the world ("block"):
-- r_pos a position in the world; determined by asking the player
-- to punch the block
@ -69,6 +80,8 @@
local check_what = {
"- please select -",
"an internal state (i.e. of a quest)", -- 2
"the value of a property of the NPC (for generic NPC)", -- property
"something that has to be calculated or evaluated (=call a function)", -- evaluate
"a block somewhere", -- 3
"put item from the NPC's inventory into a chest etc.", -- 4
"take item from a chest etc. and put it into the NPC's inventory",
@ -85,7 +98,8 @@ local check_what = {
}
-- how to store these as r_type in the precondition:
local values_what = {"", "state", "block",
local values_what = {"", "state",
"property", "evaluate", "block",
-- interact with the inventory of blocks on the map
"put_into_block_inv", "take_from_block_inv",
-- the player gave an item to the NPC; now deal with it somehow
@ -145,6 +159,39 @@ yl_speak_up.get_sorted_player_var_list_write_access = function(pname)
end
-- helper function for yl_speak_up.show_effect
-- used by "state" and "property"
yl_speak_up.show_effect_with_operator = function(r, var_name)
if(not(r.r_operator)) then
return "Error: Operator not defined."
elseif(r.r_operator == "set_to") then
return "set "..var_name.." to value \""..
tostring(r.r_var_cmp_value).."\""
elseif(r.r_operator == "unset") then
return "discard "..var_name.." (unset)"
elseif(r.r_operator == "set_to_current_time") then
return "set "..var_name.." to the current time"
elseif(r.r_operator == "quest_step") then
return "store that the player has completed quest step \""..
tostring(r.r_var_cmp_value).."\""
elseif(r.r_operator == "maximum") then
return "set "..var_name.." to value \""..
tostring(r.r_var_cmp_value).."\" if its current value is larger than that"
elseif(r.r_operator == "minimum") then
return "set "..var_name.." to value \""..
tostring(r.r_var_cmp_value).."\" if its current value is lower than that"
elseif(r.r_operator == "increment") then
return "increment the value of "..var_name.." by \""..
tostring(r.r_var_cmp_value).."\""
elseif(r.r_operator == "decrement") then
return "decrement the value of "..var_name.." by \""..
tostring(r.r_var_cmp_value).."\""
else
return "ERROR: Wrong operator \""..tostring(r.r_operator).."\" for "..var_name
end
end
-- returns a human-readable text as description of the effects
-- (as shown in the edit options dialog and in the edit effect formspec)
yl_speak_up.show_effect = function(r, pname)
@ -168,33 +215,21 @@ yl_speak_up.show_effect = function(r, pname)
var_name = "VARIABLE[ "..tostring(
yl_speak_up.strip_pname_from_var(r.r_variable, pname)).." ]"
end
if(not(r.r_operator)) then
return "Error: Operator not defined."
elseif(r.r_operator == "set_to") then
return "set "..var_name.." to value \""..
tostring(r.r_var_cmp_value).."\""
elseif(r.r_operator == "unset") then
return "discard "..var_name.." (unset)"
elseif(r.r_operator == "set_to_current_time") then
return "set "..var_name.." to the current time"
elseif(r.r_operator == "quest_step") then
return "store that the player has completed quest step \""..
tostring(r.r_var_cmp_value).."\""
elseif(r.r_operator == "maximum") then
return "set "..var_name.." to value \""..
tostring(r.r_var_cmp_value).."\" if its current value is larger than that"
elseif(r.r_operator == "minimum") then
return "set "..var_name.." to value \""..
tostring(r.r_var_cmp_value).."\" if its current value is lower than that"
elseif(r.r_operator == "increment") then
return "increment the value of "..var_name.." by \""..
tostring(r.r_var_cmp_value).."\""
elseif(r.r_operator == "decrement") then
return "decrement the value of "..var_name.." by \""..
tostring(r.r_var_cmp_value).."\""
else
return "ERROR: Wrong operator \""..tostring(r.r_operator).."\" for "..var_name
return yl_speak_up.show_effect_with_operator(r, var_name)
-- the value of a property of the NPC (for generic NPC) ("property"):
elseif(r.r_type == "property") then
local var_name = "PROPERTY[ "..tostring(r.r_value or "- ? -").." ]"
return yl_speak_up.show_effect_with_operator(r, var_name)
-- something that has to be calculated or evaluated (=call a function) ("evaluate"):
elseif(r.r_type == "evaluate") then
local str = ""
for i = 1, 9 do
str = str..tostring(p["r_param" + str(i)])
if(i < 9) then
str = str..","
end
end
return "FUNCTION["..tostring(r.r_value).."]("..str..")"
elseif(r.r_type == "block") then
if(not(r.r_pos) or type(r.r_pos) ~= "table"
or not(r.r_pos.x) or not(r.r_pos.y) or not(r.r_pos.z)) then

View File

@ -1387,13 +1387,13 @@ yl_speak_up.get_fs_edit_option_related = function(player, table_click_result,
values_operator, check_operator, get_sorted_player_var_list_function )
-- "the value of a property of the NPC (for generic NPC)"
elseif(data.what and what_type == "property" and id_prefix == "p_") then
elseif(data.what and what_type == "property" and id_prefix ~= "a_") then
return yl_speak_up.get_fs_edit_option_p_and_e_property(
pname, dialog, formspec, data, id_prefix, save_button, e,
text_select_operator, values_operator, check_operator)
-- "something that has to be calculated or evaluated (=call a function)"
elseif(data.what and what_type == "evaluate" and id_prefix == "p_") then
elseif(data.what and what_type == "evaluate" and id_prefix ~= "a_") then
return yl_speak_up.get_fs_edit_option_p_and_e_evaluate(
pname, dialog, formspec, data, id_prefix, save_button, e,
text_select_operator, values_operator, check_operator)
@ -1611,6 +1611,11 @@ yl_speak_up.get_fs_edit_option_p_and_e_property = function(
table.insert(operator_list, v)
end
end
local text_compare_with = "Compare property with this value:"
if(id_prefix == "r_") then
text_select_operator = "Set property to:"
text_compare_with = "New value:"
end
-- the list of available variables needs to be extended with the ones
return formspec..
"label[0.2,3.3;The NPC shall have the following property:]"..
@ -1621,7 +1626,7 @@ yl_speak_up.get_fs_edit_option_p_and_e_property = function(
"dropdown[7.0,4.8;4.5,0.6;select_operator;"..
table.concat(operator_list, ",")..";"..
tostring(data.operator)..";]"..
"label[11.7,4.3;Compare property with this value:]"..
"label[11.7,4.3;"..text_compare_with..":]"..
field_for_value..
"hypertext[1.2,7.0;16.0,2.5;some_text;<normal>"..
"<b>Note:</b> Properties are useful for NPC that have a generic "..