added quest_api.lua; added variable handling in fs_edit_preconditions.lua

This commit is contained in:
Sokomine 2021-06-08 02:09:16 +02:00
parent ce7877bc2b
commit 8a3daab3c0
3 changed files with 131 additions and 29 deletions

View File

@ -1,6 +1,5 @@
-- TODO: check inscription of a sign?
-- TODO: invlist as dropdown of inventory lists at detected position
-- TODO: variable as dropdown of allowed variables
-- Which diffrent types of preconditions are available?
-- -> The following fields are part of a precondition:
@ -11,7 +10,8 @@
-- p_value used to store the subtype of p_type
--
-- a state/variable:
-- p_variable TODO
-- p_variable name of a variable the player has read access to;
-- dropdown list with allowed options
-- p_operator selected from values_operator
-- p_var_cmp_value can be set freely by the player
--
@ -101,11 +101,29 @@ local values_operator = {"", "==", "~=", ">=", ">", "<=", "<", "not", "is_set",
-- some internal ones...
local check_variable = {
"- please select -",
"(internal) hour of ingame day",
"(internal) player's health points",
"(internal) hour of ingame day", -- 2
"(internal) player's health points", -- 3
}
-- get the list of variables the player has read access to
local get_sorted_player_var_list = function(pname)
local var_list = {}
-- copy the values from check_variable
for i, v in ipairs(check_variable) do
table.insert(var_list, v)
end
-- get the list of variables the player can read
local tmp = yl_speak_up.get_quest_variables_with_read_access(pname)
-- sort that list (the dropdown formspec element returns just an index)
table.sort(tmp)
for i, v in ipairs(tmp) do
table.insert(var_list, v)
end
return var_list
end
-- returns a human-readable text as description of the precondition
-- (as shown in the edit options dialog and in the edit precondition formspec)
yl_speak_up.show_precondition = function(p)
@ -120,14 +138,19 @@ yl_speak_up.show_precondition = function(p)
elseif(p.p_type == "function") then
return "function: evaluate "..tostring(p_value)
elseif(p.p_type == "state") then
if(p.p_operator == "not") then
return "not( "..tostring(p.p_variable).." )"
if(not(p.p_operator)) then
return "Error: Operator not defined."
elseif(p.p_operator == "not") then
return "not( VALUE_OF[ "..tostring(p.p_variable).." ] )"
elseif(p.p_operator == "is_set") then
return tostring(p.p_variable).." ~= nil (is_set)"
return "VALUE_OF[ "..tostring(p.p_variable).." ] ~= nil (is_set)"
elseif(p.p_operator == "is_unset") then
return tostring(p.p_variable).." == nil (is_unset)"
return "VALUE_OF[ "..tostring(p.p_variable).." ] == nil (is_unset)"
end
return tostring(p.p_variable).." "..tostring(p.p_operator).." "..
if(p.p_var_cmp_value == "") then
return "VALUE_OF[ "..tostring(p.p_variable).." ] "..tostring(p.p_operator).." \"\""
end
return "VALUE_OF[ "..tostring(p.p_variable).." ] "..tostring(p.p_operator).." "..
tostring(p.p_var_cmp_value)
elseif(p.p_type == "block") then
if(not(p.p_pos) or type(p.p_pos) ~= "table"
@ -216,18 +239,65 @@ yl_speak_up.eval_precondition = function(player, n_id, p)
-- extremly powerful (executes any lua code)
return yl_speak_up.eval_precondition_function(player, p)
elseif(p.p_type == "state") then
-- TODO: implement
--[[
if(p.p_operator == "not") then
return "not( "..tostring(p.p_variable).." )"
elseif(p.p_operator == "is_set") then
return tostring(p.p_variable).." ~= nil (is_set)"
elseif(p.p_operator == "is_unset") then
return tostring(p.p_variable).." == nil (is_unset)"
local var_val = false
if(not(p.p_variable) or p.p_variable == "") then
-- broken precondition
return false
-- "(internal) hour of ingame day", -- 2
elseif(p.p_variable == check_variable[2]) then
-- timeofday is between 0..1; translate to 24 hours
var_val = math.floor((minetest.get_timeofday() * 24)+0.5)
-- "(internal) player's health points", -- 3
elseif(p.p_variable == check_variable[3]) then
var_val = player:get_hp()
else
local pname = player:get_player_name()
local owner = yl_speak_up.npc_owner[ n_id ]
-- get the value of the variable
var_val = yl_speak_up.get_quest_variable_value(owner, pname, p.p_variable)
end
return tostring(p.p_variable).." "..tostring(p.p_operator).." "..
tostring(p.p_var_cmp_value)
--]]
if(p.p_operator == "not") then
return not(var_val)
elseif(p.p_operator == "is_set") then
return var_val ~= nil
elseif(p.p_operator == "is_unset") then
return var_val == nil
-- for security reasons: do this manually instead of just evaluating a term
elseif(p.p_operator == "==") then
-- best do these comparisons in string form to make sure both are of same type
return tostring(var_val) == tostring(p.p_var_cmp_value)
elseif(p.p_operator == "~=") then
return tostring(var_val) ~= tostring(p.p_var_cmp_value)
elseif(p.p_operator == ">=") then
-- compare numeric if possible
if(tonumber(var_val) and tonumber(p.p_var_cmp_value)) then
return tonumber(var_val) >= tonumber(p.p_var_cmp_value)
-- fallback: compare as strings
else
return tostring(var_val) >= tostring(p.p_var_cmp_value)
end
elseif(p.p_operator == ">") then
if(tonumber(var_val) and tonumber(p.p_var_cmp_value)) then
return tonumber(var_val) > tonumber(p.p_var_cmp_value)
else
return tostring(var_val) > tostring(p.p_var_cmp_value)
end
elseif(p.p_operator == "<=") then
if(tonumber(var_val) and tonumber(p.p_var_cmp_value)) then
return tonumber(var_val) <= tonumber(p.p_var_cmp_value)
else
return tostring(var_val) <= tostring(p.p_var_cmp_value)
end
elseif(p.p_operator == "<") then
if(tonumber(var_val) and tonumber(p.p_var_cmp_value)) then
return tonumber(var_val) < tonumber(p.p_var_cmp_value)
else
return tostring(var_val) < tostring(p.p_var_cmp_value)
end
end
-- unsupported operator
return false
elseif(p.p_type == "block") then
if(not(p.p_pos) or type(p.p_pos) ~= "table"
or not(p.p_pos.x) or not(p.p_pos.y) or not(p.p_pos.z)) then
@ -386,7 +456,7 @@ yl_speak_up.input_fs_edit_preconditions = function(player, formname, fields)
-- comparison value for a variable
elseif(fields.var_cmp_value
and data and data.what and data.what >= 5 and data.what <= 6) then
and data and data.what and data.what == 2) then
data.var_cmp_value = fields.var_cmp_value
end
@ -420,9 +490,10 @@ yl_speak_up.input_fs_edit_preconditions = function(player, formname, fields)
-- "an internal state (i.e. of a quest)", -- 2
if(data.what == 2) then
pq.p_value = values_operator[ data.operator ]
pq.p_value = "expression"
pq.p_operator = values_operator[ data.operator ]
pq.p_var_cmp_value = (data.var_cmp_value or "")
-- TODO: p_variable
pq.p_variable = data.variable_name
-- "a block somewhere", -- 3
elseif(data.what == 3) then
@ -509,9 +580,14 @@ yl_speak_up.input_fs_edit_preconditions = function(player, formname, fields)
-- select data regarding a variable
elseif(fields.select_variable) then
-- TODO: this needs to include player-specific variables
local nr = table.indexof(check_variable, fields.select_variable)
yl_speak_up.speak_to[pname].tmp_prereq.variable = nr
-- get the list of available variables (with the same elements
-- and the same sort order as when the dropdown was displayed)
local var_list = get_sorted_player_var_list(pname)
local nr = table.indexof(var_list, fields.select_variable)
if(nr) then
yl_speak_up.speak_to[pname].tmp_prereq.variable = nr
yl_speak_up.speak_to[pname].tmp_prereq.variable_name = var_list[ nr ]
end
-- select data regarding an operator
elseif(fields.select_operator) then
@ -649,13 +725,15 @@ yl_speak_up.get_fs_edit_preconditions = function(player, table_click_result)
if(not(data.operator) or data.operator == 1 or data.operator >= 8) then
field_for_value = "label[11.2,5.1;- not used for this operator -]"
end
-- TODO: the list of available variables needs to be extended
-- with the ones the player has read access to
-- the list of available variables needs to be extended with the ones
-- the player has read access to, and the order has to be constant
-- (because dropdown just returns an index)
local var_list = get_sorted_player_var_list(pname)
formspec = formspec..
"label[0.2,3.3;The following expression shall be true:]"..
"label[0.2,4.3;Name of variable:]"..
"dropdown[0.2,4.8;6.5,0.6;select_variable;"..
table.concat(check_variable, ",")..";"..
table.concat(var_list, ",")..";"..
tostring(data.variable)..";]"..
"label[7.0,4.3;Operator:]"..
"dropdown[7.0,4.8;4.0,0.6;select_operator;"..

View File

@ -33,6 +33,8 @@ dofile(modpath .. "inventory.lua")
dofile(modpath .. "trade_simple.lua")
-- easily accessible list of all trades the NPC offers
dofile(modpath .. "trade_list.lua")
-- handle variables for quests for player-owned NPC
dofile(modpath .. "quest_api.lua")
-- the main functionality of the mod
dofile(modpath .. "functions.lua")
-- a way of determining a node position

22
quest_api.lua Normal file
View File

@ -0,0 +1,22 @@
-- just some handling of variables
yl_speak_up.player_vars = {}
-- get the value of a variable used by a player in an NPC
yl_speak_up.get_quest_variable_value = function(owner_name, current_player_name, variable_name)
-- TODO: actually implement
return tostring(owner_name).." "..tostring(current_player_name).." "..tostring(variable_name)
end
-- which variables can player pname read and use in preconditions?
yl_speak_up.get_quest_variables_with_read_access = function(pname)
-- TODO: actually implement
return {"var_1","var_2","var_3", "var_4"}
end
-- which variables can player pname write and use in effects/results?
yl_speak_up.get_quest_variables_with_write_access = function(pname)
-- TODO: actually implement
return {"var_1","var_2","var_3"}
end