From b684ec3307c7b74fe955111a782e0036487dcf85 Mon Sep 17 00:00:00 2001 From: Sokomine Date: Thu, 10 Jun 2021 23:15:28 +0200 Subject: [PATCH] implemented some of the effects --- README.md | 4 ++ fs_edit_effects.lua | 135 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/README.md b/README.md index 077047b..3d0e036 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,10 @@ There are two ways: NPC you want to change. This is much more powerful. Lua code can be entered and later executed by the NPC. +Hint: The command "/npc_talk_debug " allows you to get debug + information regarding preconditions and effects. You can turn it + off with "/npc_talk_debug off". The NPC ID can be seen in the + setup dialog for preconditions and effects. The privs ========= diff --git a/fs_edit_effects.lua b/fs_edit_effects.lua index ddb0bc3..7b104a5 100644 --- a/fs_edit_effects.lua +++ b/fs_edit_effects.lua @@ -27,6 +27,9 @@ -- on_failure: -- r_value alternate target dialog if the action failed -- +-- chat_all: +-- r_value chat message sent to all players +-- -- Unlike in preconditions, trade (the trade action already happened) and -- inventory actions are not supported as effects. -- @@ -152,6 +155,138 @@ yl_speak_up.show_effect = function(r) end +-- executes an effect/result r for the player and npc n_id; +-- returns true on success (relevant for on_failure) +-- TODO: in edit mode, nothing gets executed except perhaps dialog +yl_speak_up.execute_effect = function(player, n_id, o_id, r) + if(not(r.r_type) or r.r_type == "") then + -- nothing to do + return true + elseif(r.r_type == "auto" or r.r_type == "trade") then + -- these effects don't do anything + return true + elseif(r.r_type == "dialog") then + -- TODO: how to handle target dialog? + return true + elseif(r.r_type == "function") then + return yl_speak_up.eval_and_execute_function(player, r, "r_") + elseif(r.r_type == "give_item") then + if(not(v.r_value)) then + return false + end + local item = ItemStack(v.r_value) + if(not(minetest.registered_items[item:get_name()])) then + yl_speak_up.debug_msg(player, n_id, o_id, tostring(r_id).." ".. + "give_item: "..tostring(item:get_name()).." unknown.") + return false + end + local r = player:get_inventory():add_item("main", item) + if(not(r)) then + yl_speak_up.debug_msg(player, n_id, o_id, tostring(r_id).." ".. + "give_item: "..tostring(item:get_name()).." failed.") + return false + end + return true + elseif(r.r_type == "take_item") then + if(not(v.r_value)) then + return false + end + local item = ItemStack(v.r_value) + if(not(minetest.registered_items[item:get_name()])) then + yl_speak_up.debug_msg(player, n_id, o_id, tostring(r_id).." ".. + "take_item: "..tostring(item:get_name()).." unknown.") + return false + end + local r = player:get_inventory():remove_item("main", item) + if(not(r)) then + yl_speak_up.debug_msg(player, n_id, o_id, tostring(r_id).." ".. + "take_item: "..tostring(item:get_name()).." failed.") + return false + end + return true + elseif(r.r_type == "move") then + -- TODO: copy/adjust effect "move" + -- "an internal state (i.e. of a quest)", -- 2 + elseif(r.r_type == "state") then + -- TODO: implement effect "state" + -- "a block somewhere" -- 3 + elseif(r.r_type == "block") then + -- TODO: implement effect "block" + -- ""NPC crafts soemthing", -- 4 + elseif(r.r_type == "craft") then + if(not(r.r_craft_grid) or not(r.r_value)) then + return false + end + local input = {} + input.items = {} + -- multiple slots in the craft grid may contain the same item + local sum_up = {} + for i, v in ipairs(r.r_craft_grid) do + if(v and v ~= "") then + local stack = ItemStack(v) + -- store this for later crafting + input.items[ i ] = stack + local name = stack:get_name() + if(sum_up[ name ]) then + sum_up[ name ] = sum_up[ name ] + stack:get_count() + else + sum_up[ name ] = stack:get_count() + end + else + -- empty itemstack in this slot + input.items[ i ] = ItemStack("") + end + end + -- does the NPC have all these items in his inventory? + local npc_inv = minetest.get_inventory({type="detached", + name="yl_speak_up_npc_"..tostring(n_id)}) + for k, v in pairs(sum_up) do + if(not(npc_inv:contains_item("npc_main", k.." "..v))) then + yl_speak_up.debug_msg(player, n_id, o_id, tostring(r_id).." ".. + "Crafting failed: NPC does not have "..tostring(k.." "..v)) + return false + end + end + -- do these input items form a valid craft recipe? + input.method = "normal" -- normal crafting; no cooking or fuel or the like + input.width = 3 + local output, decremented_input = minetest.get_craft_result(input) + if(output.item:is_empty()) then + yl_speak_up.debug_msg(player, n_id, o_id, tostring(r_id).." ".. + "Crafting failed: No output for that recipe.") + return false + end + -- the craft receipe may have changed in the meantime and yield a diffrent result + local expected_stack = ItemStack(r.r_value) + if(output.item:get_name() ~= expected_stack:get_name() + or output.item:get_count() ~= expected_stack:get_count()) then + yl_speak_up.debug_msg(player, n_id, o_id, tostring(r_id).." ".. + "Crafting failed: Diffrent output: "..tostring(output.item:to_string())) + return false + end + -- TODO: actually consume the items required, return the ones in decremented_input + yl_speak_up.debug_msg(player, n_id, o_id, tostring(r_id).." ".. + "Great: Crafting is possible!") + return true + -- "go to other dialog if the action (i.e. trade) failed", -- 5 + elseif(r.r_type == "on_failure") then + -- TODO: implement effect on_failure + -- "send a chat message to all players", -- 6 + elseif(r.r_type == "chat_all") then + local pname = player:get_player_name() + local dialog = yl_speak_up.speak_to[pname].dialog + local text = r.r_value + -- replace $NPC_NAME$, $OWNER_NAME$, $PLAYER_NAME$ etc. + text = yl_speak_up.replace_vars_in_text(text, dialog, pname) + minetest.chat_send_all(text) + -- sending a chat message always counts as successful + return true + end + -- fallback: unkown type + return false +end + + -- these are only wrapper functions for those in fs_edit_general.lua yl_speak_up.input_fs_edit_effects = function(player, formname, fields)