forked from Sokomine/yl_speak_up
moved code from calculate_displayable_options to yl_speak_up.eval_precondition_function; added yl_speak_up.eval_all_preconditions; added yl_speak_up.eval_precondition
This commit is contained in:
parent
80c25fb9fa
commit
b0f141b09d
@ -109,7 +109,17 @@ local check_variable = {
|
||||
-- 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)
|
||||
if(p.p_type == "state") then
|
||||
if(not(p.p_type) or p.p_type == "") then
|
||||
return "(nothing): Always true."
|
||||
elseif(p.p_type == "item") then
|
||||
return "item: The player has "..tostring(p.p_value).." in his inventory."
|
||||
elseif(p.p_type == "quest") then
|
||||
return "quest: Always false."
|
||||
elseif(p.p_type == "auto") then
|
||||
return "auto: Always true."
|
||||
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).." )"
|
||||
elseif(p.p_operator == "is_set") then
|
||||
@ -158,6 +168,141 @@ yl_speak_up.show_precondition = function(p)
|
||||
end
|
||||
|
||||
|
||||
-- called by calculate_displayable_options(..);
|
||||
-- returns false if a single precondition is false
|
||||
-- Important: If something cannot be determined (i.e. the node is nil),
|
||||
-- *both* the condition and its inverse condition may be
|
||||
-- true (or false).
|
||||
yl_speak_up.eval_all_preconditions = function(player, prereq, o_id)
|
||||
if(not(prereq)) then
|
||||
minetest.chat_send_player(player:get_player_name(), "No preconditions given for "..tostring(o_id)..".")
|
||||
-- no prerequirements? then they are automaticly fulfilled
|
||||
return true
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
minetest.chat_send_player(pname, "Checking preconditions for "..tostring(o_id).."..") -- TODO
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
for k, p in pairs(prereq) do
|
||||
minetest.chat_send_player(pname, "..checking "..tostring(p.p_id)..": "..yl_speak_up.show_precondition(p)) -- TODO
|
||||
if(not(yl_speak_up.eval_precondition(player, n_id, p))) then
|
||||
-- no need to look any further - once we hit a false, it'll stay false
|
||||
minetest.chat_send_player(pname, " -> is false! Aborting.") -- TODO
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- all preconditions are true
|
||||
minetest.chat_send_player(pname, "All preconditions true for "..tostring(o_id)..".") -- TODO
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-- checks if precondition p is true for the player and npc n_id
|
||||
yl_speak_up.eval_precondition = function(player, n_id, p)
|
||||
if(not(p.p_type) or p.p_type == "") then
|
||||
-- empty prerequirement: automaticly true (fallback)
|
||||
return true
|
||||
elseif(p.p_type == "item") then
|
||||
-- a precondition set by using the staff;
|
||||
-- aequivalent to p.p_type == "player_inv" and p.p_itemstack == "inv_contains"
|
||||
return player:get_inventory():contains_item("main", p.p_value)
|
||||
elseif(p.p_type == "quest") then
|
||||
-- a precondition set by using the staff; intended as future quest interface?
|
||||
return false
|
||||
elseif(p.p_type == "auto") then
|
||||
-- a precondition set by using the staff; kept for compatibility
|
||||
return true
|
||||
elseif(p.p_type == "function") then
|
||||
-- a precondition set by using the staff;
|
||||
-- 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)"
|
||||
end
|
||||
return 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"
|
||||
or not(p.p_pos.x) or not(p.p_pos.y) or not(p.p_pos.z)) then
|
||||
return false
|
||||
elseif(p.p_value == "node_is_like") then
|
||||
local node = minetest.get_node_or_nil(p.p_pos)
|
||||
return (node and node.name and node.name == p.p_node and node.param2 == p.p_param2)
|
||||
elseif(p.p_value == "node_is_air") then
|
||||
local node = minetest.get_node_or_nil(p.p_pos)
|
||||
return (node and node.name and node.name == "air")
|
||||
elseif(p.p_value == "node_is_diffrent_from") then
|
||||
local node = minetest.get_node_or_nil(p.p_pos)
|
||||
return (node and node.name and (node.name ~= p.p_node or node.param2 ~= p.p_param2))
|
||||
end
|
||||
-- fallback - unsupported option
|
||||
return false
|
||||
elseif(p.p_type == "trade") then
|
||||
local pname = player:get_player_name()
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local d_id = yl_speak_up.speak_to[pname].d_id
|
||||
local o_id = yl_speak_up.speak_to[pname].o_id
|
||||
-- if there is no trade, then this condition is true
|
||||
if(not(dialog) or not(dialog.trades) or not(d_id) or not(o_id)) then
|
||||
return true
|
||||
end
|
||||
local trade = dialog.trades[ tostring(d_id).." "..tostring(o_id) ]
|
||||
-- something is wrong with the trade
|
||||
if(not(trade)
|
||||
or not(trade.pay) or not(trade.pay[1]) or not(trade.buy) or not(trade.buy[1])) then
|
||||
return false
|
||||
end
|
||||
if( p.p_value == "npc_can_sell") then
|
||||
local npc_inv = minetest.get_inventory({type="detached",
|
||||
name="yl_speak_up_npc_"..tostring(n_id)})
|
||||
return npc_inv:contains_item("npc_main", trade.buy[1])
|
||||
elseif(p.p_value == "npc_is_out_of_stock") then
|
||||
local npc_inv = minetest.get_inventory({type="detached",
|
||||
name="yl_speak_up_npc_"..tostring(n_id)})
|
||||
return not(npc_inv:contains_item("npc_main", trade.buy[1]))
|
||||
elseif(p.p_value == "player_can_buy") then
|
||||
local player_inv = player:get_inventory()
|
||||
return player_inv:contains_item("main", trade.pay[1])
|
||||
elseif(p.p_value == "player_has_not_enough") then
|
||||
local player_inv = player:get_inventory()
|
||||
return not(player_inv:contains_item("main", trade.pay[1]))
|
||||
end
|
||||
return false
|
||||
elseif(p.p_type == "player_inv" or p.p_type == "npc_inv") then
|
||||
local inv = nil
|
||||
local inv_name = "main"
|
||||
-- determine the right inventory
|
||||
if(p.p_type == "player_inv") then
|
||||
inv = player:get_inventory()
|
||||
else
|
||||
inv = minetest.get_inventory({type="detached",
|
||||
name="yl_speak_up_npc_"..tostring(n_id)})
|
||||
inv_name = "npc_main"
|
||||
end
|
||||
if( p.p_itemstack and p.p_value == "inv_contains") then
|
||||
return inv:contains_item(inv_name, p.p_itemstack)
|
||||
elseif(p.p_itemstack and p.p_value == "inv_does_not_contain") then
|
||||
return not(inv:contains_item(inv_name, p.p_itemstack))
|
||||
elseif(p.p_itemstack and p.p_value == "has_room_for") then
|
||||
return inv:room_for_item(inv_name, p.p_itemstack)
|
||||
elseif(p.p_value == "inv_is_empty") then
|
||||
return inv:is_empty(inv_name)
|
||||
end
|
||||
return false
|
||||
end
|
||||
-- fallback - unknown type
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
yl_speak_up.input_fs_edit_preconditions = function(player, formname, fields)
|
||||
if(not(player)) then
|
||||
return
|
||||
|
168
functions.lua
168
functions.lua
@ -349,6 +349,70 @@ local function delete_option(n_id, d_id, o_id)
|
||||
end
|
||||
|
||||
|
||||
-- evaluate those preconditions of type "function" (set by the staff)
|
||||
-- WARNING: This is extremly powerful!
|
||||
-- The code is taken out of the function
|
||||
-- calculate_displayable_options(..)
|
||||
-- (written by AliasAlreadyTaken).
|
||||
-- It requires the npc_master priv to add or edit this prereq.
|
||||
-- The function is called by yl_speak_up.eval_precondition
|
||||
yl_speak_up.eval_precondition_function = function(player, p_v)
|
||||
local pname = player:get_player_name()
|
||||
|
||||
--minetest.chat_send_all("this is in a single prereq: "..dump(p_v))
|
||||
local p_id = p_v.p_id
|
||||
if p_v.p_type ~= "function" then
|
||||
return true
|
||||
end
|
||||
|
||||
local code = p_v.p_value
|
||||
if code:byte(1) == 27 then
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local npc = get_number_from_id(n_id)
|
||||
if obj:get_luaentity() and tonumber(npc) then
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not compile the content of "..p_id.." :"..dump(code) .. " because of illegal bytecode for player "..pname)
|
||||
else
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not compile the content of "..p_id.." :"..dump(code) .. " for player unknown because of illegal bytecode")
|
||||
end
|
||||
end
|
||||
|
||||
local f, msg = loadstring("return function(playername) " .. code .. " end")
|
||||
|
||||
if not f then
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local npc = get_number_from_id(n_id)
|
||||
if obj:get_luaentity() and tonumber(npc) then
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not compile the content of "..p_id.." :"..dump(code) .. " for player "..pname)
|
||||
else
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not compile the content of "..p_id.." :"..dump(code) .. " for player unknown")
|
||||
end
|
||||
else
|
||||
local func = f()
|
||||
|
||||
local ok, ret = pcall(func,pname)
|
||||
|
||||
if not ok then
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local npc = get_number_from_id(n_id)
|
||||
if obj:get_luaentity() and tonumber(npc) then
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not execute the content of "..p_id.." :"..dump(code) .. " for player "..pname)
|
||||
else
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not execute the content of "..p_id.." :"..dump(code) .. " for player unknown")
|
||||
end
|
||||
end
|
||||
|
||||
if type(ret) == "boolean" then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
-- fallback
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
local function calculate_displayable_options(pname, d_options)
|
||||
-- Let's go through all the options and see if we need to display them to the user
|
||||
|
||||
@ -361,113 +425,13 @@ local function calculate_displayable_options(pname, d_options)
|
||||
end
|
||||
|
||||
for o_k, o_v in pairs(d_options) do
|
||||
--minetest.chat_send_all("#####"..o_k.."#####")
|
||||
local o_p_met = true
|
||||
if o_v.o_prerequisites == nil then
|
||||
--minetest.chat_send_all("display this because no prereq:"..dump(o_v))
|
||||
else
|
||||
--minetest.chat_send_all("prereqs exists")
|
||||
if next(o_v.o_prerequisites) == nil then
|
||||
--minetest.chat_send_all("prereqs exist, but empty")
|
||||
else
|
||||
--minetest.chat_send_all("prereqs exists and not empty")
|
||||
--minetest.chat_send_all("if all prereqs are met, then we can display the option")
|
||||
local p_met = {}
|
||||
for p_k, p_v in pairs(o_v.o_prerequisites) do
|
||||
--minetest.chat_send_all("this is in a single prereq: "..dump(p_v))
|
||||
p_met[p_k] = false
|
||||
local p_id = p_v.p_id
|
||||
if p_v.p_type == "item" then
|
||||
--minetest.chat_send_all("item! Does the player have this thing?")
|
||||
if player:get_inventory():contains_item("main", p_v.p_value) then
|
||||
--minetest.chat_send_all("found item:"..p_v.p_value)
|
||||
p_met[p_k] = true
|
||||
end
|
||||
end
|
||||
if p_v.p_type == "quest" then
|
||||
--minetest.chat_send_all("quest! let's call the quest api?")
|
||||
p_met[p_k] = false
|
||||
end
|
||||
if p_v.p_type == "function" then
|
||||
|
||||
local code = p_v.p_value
|
||||
if code:byte(1) == 27 then
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local npc = get_number_from_id(n_id)
|
||||
if obj:get_luaentity() and tonumber(npc) then
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not compile the content of "..p_id.." :"..dump(code) .. " because of illegal bytecode for player "..pname)
|
||||
else
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not compile the content of "..p_id.." :"..dump(code) .. " for player unknown because of illegal bytecode")
|
||||
end
|
||||
end
|
||||
|
||||
local f, msg = loadstring("return function(playername) " .. code .. " end")
|
||||
|
||||
if not f then
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local npc = get_number_from_id(n_id)
|
||||
if obj:get_luaentity() and tonumber(npc) then
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not compile the content of "..p_id.." :"..dump(code) .. " for player "..pname)
|
||||
else
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not compile the content of "..p_id.." :"..dump(code) .. " for player unknown")
|
||||
end
|
||||
else
|
||||
|
||||
|
||||
local func = f()
|
||||
|
||||
local ok, ret = pcall(func,pname)
|
||||
|
||||
if not ok then
|
||||
local obj = yl_speak_up.speak_to[pname].obj
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local npc = get_number_from_id(n_id)
|
||||
if obj:get_luaentity() and tonumber(npc) then
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not execute the content of "..p_id.." :"..dump(code) .. " for player "..pname)
|
||||
else
|
||||
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not execute the content of "..p_id.." :"..dump(code) .. " for player unknown")
|
||||
end
|
||||
end
|
||||
|
||||
if type(ret) == "boolean" then
|
||||
p_met[p_k] = ret
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
if p_v.p_type == "auto" then
|
||||
--minetest.chat_send_all("auto! what shall we do now?")
|
||||
p_met[p_k] = true
|
||||
end
|
||||
end
|
||||
-- is there a "false" in the p_met ?
|
||||
for m_k, m_v in pairs(p_met) do
|
||||
--minetest.chat_send_all(o_k..",m_v="..dump(m_v))
|
||||
if m_v == false then
|
||||
o_p_met = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Can we display this option?
|
||||
retval[o_k] = o_p_met
|
||||
--[[
|
||||
if o_p_met == true then
|
||||
minetest.chat_send_all("Prereqs say YES")
|
||||
retval[o_k] = o_p_met
|
||||
else
|
||||
minetest.chat_send_all("Prereqs say NOO")
|
||||
end
|
||||
]]--
|
||||
retval[o_k] = yl_speak_up.eval_all_preconditions(player, o_v.o_prerequisites, o_k)
|
||||
end
|
||||
return retval
|
||||
end
|
||||
|
||||
|
||||
local function calculate_portrait(pname, n_id)
|
||||
local tex = yl_speak_up.speak_to[pname].textures
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user