yl_speak_up.execute_all_relevant_effects

This commit is contained in:
Sokomine 2021-06-11 00:20:40 +02:00
parent 7cfad9586a
commit d3d90134ee
2 changed files with 72 additions and 105 deletions

View File

@ -155,6 +155,65 @@ yl_speak_up.show_effect = function(r)
end
-- called by yl_speak_up.input_talk(..); -- TODO
-- This function is called *after* the player has clicked on an option
-- and *after* any actions (i.e. trade) have been completed either
-- successfully (=action_was_succesful is true) or not.
-- Unlike the preconditions, the effects are executed in ordered form,
-- ordered by their r_id.
-- Returns the new target dialog that is to be displayed next. This will
-- usually be the one with the r_type "dialog" - unless r_type "on_failure"
-- was encountered after an unsuccessful action *or* right after an
-- effect that returned false.
-- Note: In edit mode, effects will *not* be executed.
yl_speak_up.execute_all_relevant_effects = function(player, effects, o_id, action_was_successful)
local target_dialog = ""
if(not(effects)) then
yl_speak_up.debug_msg(player, n_id, o_id, "No effects given.")
-- no effects? Then...return to the start dialog
return ""
end
local pname = player:get_player_name()
local n_id = yl_speak_up.speak_to[pname].n_id
local edit_mode = (yl_speak_up.edit_mode[pname] == n_id)
if(not(edit_mode)) then
yl_speak_up.debug_msg(player, n_id, o_id, "Executing effects.")
else
yl_speak_up.debug_msg(player, n_id, o_id, "Not executing effects because in edit mode.")
end
local last_result = action_was_successful
-- Important: the list of effects is *sorted* here. The order remains constant!
local sorted_key_list = yl_speak_up.sort_keys(effects)
for i, k in ipairs(sorted_key_list) do
local r = effects[ k ]
yl_speak_up.debug_msg(player, n_id, o_id, "..executing "..
tostring(r.r_id)..": "..yl_speak_up.show_effect(r))
-- do not execute effects in edit mode
if(not(edit_mode)) then
local res = yl_speak_up.execute_effect(player, n_id, o_id, r)
if(not(res)) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id)..
" -> Effect failed to execute.")
end
end
-- "dialog" gives us the normal target_dialog
if(r.r_type and r.r_type == "dialog") then
target_dialog = r.r_value
-- "on_failure" gives an alternate target dialog if the action
-- or last effect failed
elseif(r.r_type and r.r_type == "on_failure" and r.r_value and not(last_result)) then
yl_speak_up.debug_msg(player, n_id, o_id, "Aborted executing effects at "..
tostring(r.r_id)..". New target dialog: "..tostring(r.r_value)..".")
-- we also stop execution here
return r.r_value
end
end
-- all preconditions are true
yl_speak_up.debug_msg(player, n_id, o_id, "Finished executing effects.")
return target_dialog
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
@ -165,8 +224,9 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
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?
elseif(r.r_type == "dialog"
or r.r_type == "on_failure") then
-- this needs to be handled in the calling function
return true
elseif(r.r_type == "function") then
-- this can only be set and edited with the staff
@ -338,9 +398,6 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
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()

View File

@ -2510,103 +2510,14 @@ yl_speak_up.input_talk = function(player, formname, fields)
local d_option = n_dialog.d_options[o]
-- which dialog do we have to show next? default: keep this one
local target_dialog = d_id
-- which dialog do we have to show next?
-- determine that by executing the effects
local target_dialog = yl_speak_up.execute_all_relevant_effects(
player, d_option.o_results, o, true) --action_was_successful) --TODO
-- Let's do something if results exist
if d_option.o_results ~= nil then
for k, v in pairs(d_option.o_results) do
-- in edit_mode, only the switching to the next dialog is executed (we want to edit,
-- not solve quests, get/take items, teleport...)
if not(edit_mode) and v.r_type == "give_item" then
local item = ItemStack(v.r_value)
if minetest.registered_items[item:get_name()] ~= nil then
local r = player:get_inventory():add_item("main", item)
else
say("Item not found!")
end
end
if not(edit_mode) and v.r_type == "take_item" then
local item = ItemStack(v.r_value)
if minetest.registered_items[item:get_name()] ~= nil then
local r = player:get_inventory():remove_item("main", item)
else
say("Item not found!")
end
end
if not(edit_mode) and v.r_type == "move" then
local target_pos = nil
local target_pos_valid = false
--pos like (100,20,400)
if minetest.string_to_pos(v.r_value) then
target_pos = minetest.string_to_pos(v.r_value)
target_pos_valid = true
end
--pos like 100,20,400
local maybe = string.split(v.r_value, ",")
if not target_pos_valid and maybe and tonumber(maybe[1]) and tonumber(maybe[2]) and tonumber(maybe[3]) and maybe[4] == nil and
tonumber(maybe[1]) <= 32000 and tonumber(maybe[1]) >= -32000 and
tonumber(maybe[2]) <= 32000 and tonumber(maybe[2]) >= -32000 and
tonumber(maybe[3]) <= 32000 and tonumber(maybe[3]) >= -32000 then
target_pos = {x=maybe[1],y=maybe[2],z=maybe[3]}
target_pos_valid = true
end
--pos like {x=100,y=20,z=400}
if not target_pos_valid and string.sub(v.r_value,1,1) == "{" and string.sub(v.r_value,-1,-1) == "}" then
local might_be_pos = minetest.deserialize("return " .. v.r_value)
if tonumber(might_be_pos.x) and tonumber(might_be_pos.x) <= 32000 and tonumber(might_be_pos.x) >= -32000 and
tonumber(might_be_pos.y) and tonumber(might_be_pos.y) <= 32000 and tonumber(might_be_pos.y) >= -32000 and
tonumber(might_be_pos.z) and tonumber(might_be_pos.z) <= 32000 and tonumber(might_be_pos.z) >= -32000 then
target_pos = might_be_pos
target_pos_valid = true
end
end
if target_pos_valid == true then
player:set_pos(target_pos)
if vector.distance(player:get_pos(),target_pos) >= 2 then
say("Something went wrong! Player wasn't moved properly.")
end
end
-- Debug
if target_pos_valid == false 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 move player "..pname.." because the content of "..v.r_id.." is wrong:"..dump(v.r_value))
else
minetest.log("error","[MOD] yl_speak_up: NPC with unknown ID or without proper object could not move player "..dump(pname).." because the content of "..v.r_id.." is wrong:"..dump(v.r_value))
end
end
end
if not(edit_mode) and v.r_type == "function" then
yl_speak_up.eval_and_execute_function(player, v, "r_")
end
if v.r_type == "dialog" then
if dialog.n_dialogs[v.r_value] ~= nil then
target_dialog = v.r_value
else
say("This dialog does not exist")
end
end
if v.r_type == "auto" then
say("auto forward")
end
end -- end of loop over d_option.o_results
-- if there is a trade associated with this dialog and option, show that trade now
local trade_id = tostring(d_id).." "..tostring(o)
if(dialog.trades and dialog.trades[ trade_id ]) then
-- if there is a trade associated with this dialog and option, show that trade now
local trade_id = tostring(d_id).." "..tostring(o)
if(dialog.trades and dialog.trades[ trade_id ]) then
-- remember which option was selected
yl_speak_up.speak_to[pname].o_id = o
-- which dialog shall be shown in case of a successful trade?
@ -2614,14 +2525,13 @@ yl_speak_up.input_talk = function(player, formname, fields)
-- show the trade dialog
yl_speak_up.show_fs(player, "trade_simple", trade_id)
return
end
end
-- else switch to the target dialog as stated in results/effects
if(target_dialog ~= d_id) then
-- else switch to the target dialog as stated in results/effects
if(target_dialog ~= d_id) then
-- if there are any changes done: ask first and don't switch to the new dialog yet
yl_speak_up.save_changes_and_switch_to_other_dialog(player, fields, target_dialog)
return
end
end
end