955 lines
39 KiB
Lua
955 lines
39 KiB
Lua
-- This file contains what is necessary to execute/apply an effect.
|
|
|
|
-- for "deal_with_offered_item", used i.e. in yl_speak_up.get_fs_edit_option_effect_deal_with_offered_item
|
|
yl_speak_up.dropdown_list_deal_with_offered_item = {
|
|
minetest.formspec_escape("- please select -"),
|
|
"Take the expected part of the offered item(s) and put them in the NPC's inventory.",
|
|
"Accept all of the offered item(s) and put them in the NPC's inventory.",
|
|
"Refuse and give the item(s) back."
|
|
}
|
|
-- the values that will be stored for yl_speak_up.dropdown_list_deal_with_offered_item above
|
|
yl_speak_up.dropdown_values_deal_with_offered_item = {
|
|
"do_nothing", "take_as_wanted", "take_all", "refuse_all"}
|
|
|
|
|
|
-- check if a block of type node_name is blacklisted for a certain interaction
|
|
-- (this is needed if a block is not prepared for interaction with NPC and
|
|
-- expects to always be dealing with a player)
|
|
-- Parameters:
|
|
-- how how to interact with the node
|
|
-- node_name the node to place
|
|
-- node_there the node that can currently be found at that position
|
|
-- tool_name the name of the tool the NPC wants to use (punch or right-click with)
|
|
yl_speak_up.check_blacklisted = function(how, node_name, node_there, tool_name)
|
|
if(tool_name) then
|
|
return yl_speak_up.blacklist_effect_tool_use[ tool_name ]
|
|
end
|
|
return yl_speak_up.blacklist_effect_on_block_interact[ node_name ]
|
|
or yl_speak_up.blacklist_effect_on_block_interact[ node_there ]
|
|
or (how == "place" and yl_speak_up.blacklist_effect_on_block_place[ node_name ])
|
|
or (how == "dig" and yl_speak_up.blacklist_effect_on_block_dig[ node_there ])
|
|
or (how == "punch" and yl_speak_up.blacklist_effect_on_block_punch[ node_there ])
|
|
or (how == "right-click" and yl_speak_up.blacklist_effect_on_block_right_click[ node_there])
|
|
or (how == "put" and yl_speak_up.blacklist_effect_on_block_right_click[ node_there])
|
|
or (how == "take" and yl_speak_up.blacklist_effect_on_block_right_click[ node_there])
|
|
end
|
|
|
|
|
|
-- create fake playerdata so that the NPC can interact with inventories, punch and right-click blocks
|
|
yl_speak_up.get_fake_player = function(owner_name, wielded_item)
|
|
return {
|
|
get_player_name = function()
|
|
return owner_name
|
|
end,
|
|
is_player = function()
|
|
return true
|
|
end,
|
|
is_fake_player = true,
|
|
get_wielded_item = function(self, item)
|
|
return ItemStack(wielded_item)
|
|
end,
|
|
get_player_control = function()
|
|
-- NPC is not sneaking
|
|
return {}
|
|
end,
|
|
}
|
|
end
|
|
|
|
|
|
-- shall the NPC wield and use a tool? if so that tools' on_use or on_place
|
|
-- function takes precedence over the block it's used on
|
|
yl_speak_up.use_tool_on_block = function(r, fun_name, player, n_id, o_id)
|
|
if(not(r.r_wielded) or r.r_wielded == "") then
|
|
return false
|
|
end
|
|
-- we need the owner_name for creating the fake player
|
|
local owner_name = yl_speak_up.npc_owner[ n_id ]
|
|
if(not(owner_name) or owner_name == "") then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": NPC does not have an owner. Aborting.")
|
|
return false
|
|
end
|
|
local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(n_id)})
|
|
-- can the tool be used?
|
|
local tool_err_msg = nil
|
|
if(not(minetest.registered_items[r.r_wielded])) then
|
|
tool_err_msg = "Tool not defined"
|
|
elseif(not(minetest.registered_items[r.r_wielded][fun_name])) then
|
|
tool_err_msg = "Tool does not support "..tostring(r.r_value).."ing"
|
|
-- do not use forbidden tools
|
|
elseif(yl_speak_up.check_blacklisted(nil, nil, nil, r.r_wielded)) then
|
|
tool_err_msg = "NPC are not allowed to use this tool"
|
|
-- does the NPC have the item he's supposed to wield?
|
|
elseif(not(npc_inv:contains_item("npc_main", r.r_wielded, false))) then
|
|
tool_err_msg = "NPC lacks tool"
|
|
end
|
|
if(tool_err_msg) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id)..
|
|
" block: "..tostring(r.r_value).." - "..tool_err_msg.. ": \""..tostring(r.r_wielded).."\".")
|
|
return false
|
|
end
|
|
-- act in the name of the owner when accessing inventories
|
|
local fake_player = yl_speak_up.get_fake_player(owner_name, r.r_wielded)
|
|
local itemstack = fake_player:get_wielded_item()
|
|
local pointed_thing = {
|
|
type = "node",
|
|
under = r.r_pos,
|
|
above = {x=r.r_pos.x, y=r.r_pos.y+1, z=r.r_pos.z}
|
|
}
|
|
local new_itemstack = minetest.registered_items[r.r_wielded][fun_name](
|
|
itemstack, fake_player, pointed_thing)
|
|
minetest.chat_send_player("singleplayer", "Did the rightclicking. Result: "..new_itemstack:get_name().." fun_name: "..tostring(fun_name))
|
|
if(new_itemstack) then
|
|
-- apply any itemstack changes
|
|
npc_inv:remove_item("npc_main", itemstack)
|
|
npc_inv:add_item("npc_main", new_itemstack)
|
|
end
|
|
return true
|
|
end
|
|
|
|
|
|
-- called by yl_speak_up.input_talk(..)
|
|
-- and also by yl_speak_up.get_fs_trade_list(..)
|
|
--
|
|
-- 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, d_option,
|
|
dry_run_no_exec) -- dry_run_no_exec for edit_mode
|
|
local target_dialog = ""
|
|
local pname = player:get_player_name()
|
|
local n_id = yl_speak_up.speak_to[pname].n_id
|
|
if(not(effects)) then
|
|
-- it may still be necessary to set the quest step
|
|
if(d_option and d_option.quest_id and d_option.quest_step) then
|
|
local d_id = yl_speak_up.speak_to[pname].d_id
|
|
yl_speak_up.debug_msg(player, n_id, o_id, "Setting quest step \""..
|
|
tostring(d_option.quest_step).."\" in quest \""..
|
|
tostring(d_option.quest_id).."\".")
|
|
yl_speak_up.quest_step_reached(player, d_option.quest_step, d_option.quest_id,
|
|
n_id, d_id, o_id)
|
|
end
|
|
yl_speak_up.debug_msg(player, n_id, o_id, "No effects given.")
|
|
-- the player has visited this option successfully
|
|
yl_speak_up.count_visits_to_option(pname, o_id)
|
|
-- no effects? Then...return to the start dialog
|
|
return {next_dialog = "", alternate_text = nil}
|
|
end
|
|
-- Important: the list of effects is *sorted* here. The order remains constant!
|
|
local sorted_key_list = yl_speak_up.sort_keys(effects)
|
|
if(not(sorted_key_list) or #sorted_key_list < 1) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, "Error: No effects found. At least one of "..
|
|
"type \"dialog\" is necessary.")
|
|
elseif(not(dry_run_no_exec)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, "Executing effects: "..
|
|
table.concat(sorted_key_list, ", ")..".")
|
|
else
|
|
yl_speak_up.debug_msg(player, n_id, o_id, "Not executing effects because in edit mode.")
|
|
end
|
|
-- failed actions may set an alternate text
|
|
local alternate_text = nil
|
|
local last_result = action_was_successful
|
|
local res = true
|
|
local refuse_items = true
|
|
local properties = yl_speak_up.get_npc_properties(pname)
|
|
local no_log = properties["server_nolog_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, pname))
|
|
-- do not execute effects in edit mode
|
|
if(not(dry_run_no_exec)) then
|
|
if(not(no_log)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id,
|
|
"Executing effect "..tostring(r.r_id)..".")
|
|
end
|
|
res = yl_speak_up.execute_effect(player, n_id, o_id, r)
|
|
if(no_log) then
|
|
if(not(res)) then
|
|
alternate_text = r.alternate_text
|
|
end
|
|
elseif(not(res)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id)..
|
|
" -> Effect failed to execute.")
|
|
if(r.r_type ~= "dialog") then
|
|
local d_id = yl_speak_up.speak_to[pname].d_id
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"Failed to execute effect "..tostring(r.r_id)..
|
|
" "..tostring(o_id).." "..tostring(d_id)..": "..
|
|
yl_speak_up.show_effect(r, pname))
|
|
end
|
|
alternate_text = r.alternate_text
|
|
else
|
|
if(r.r_type ~= "dialog") then
|
|
local d_id = yl_speak_up.speak_to[pname].d_id
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"Executed effect "..tostring(r.r_id)..
|
|
" "..tostring(o_id).." "..tostring(d_id)..": "..
|
|
yl_speak_up.show_effect(r, pname))
|
|
end
|
|
end
|
|
if(r and r.r_type and r.r_type == "deal_with_offered_item") then
|
|
refuse_items = true
|
|
if(not(r.r_value) or r.r_value == "do_nothing") then
|
|
refuse_items = false
|
|
end
|
|
end
|
|
else
|
|
-- in edit mode: assume that the effect was successful
|
|
res = true
|
|
end
|
|
-- "dialog" gives us the normal target_dialog
|
|
if(r.r_type and r.r_type == "dialog") then
|
|
target_dialog = r.r_value
|
|
alternate_text = r.alternate_text
|
|
-- "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
|
|
-- any quest step is NOT set (because effects and/or action weren't successful)
|
|
-- the visit counter for this option is not incresed - after all the visit failed
|
|
return {next_dialog = r.r_value, alternate_text = r.alternate_text}
|
|
end
|
|
last_result = res
|
|
end
|
|
-- all preconditions are true
|
|
yl_speak_up.debug_msg(player, n_id, o_id, "Finished executing effects.")
|
|
-- make sure to give unwanted items back if needed
|
|
if(refuse_items) then
|
|
-- check if there is actually something that needs to be given back
|
|
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
|
if(not(trade_inv:is_empty("npc_wants"))) then
|
|
target_dialog = "d_got_item"
|
|
end
|
|
end
|
|
|
|
-- it may still be necessary to set the quest step
|
|
if(d_option and d_option.quest_id and d_option.quest_step) then
|
|
local d_id = yl_speak_up.speak_to[pname].d_id
|
|
yl_speak_up.debug_msg(player, n_id, o_id, "Setting quest step \""..
|
|
tostring(d_option.quest_step).."\" in quest \""..
|
|
tostring(d_option.quest_id).."\".")
|
|
yl_speak_up.quest_step_reached(player, d_option.quest_step, d_option.quest_id,
|
|
n_id, d_id, o_id)
|
|
end
|
|
-- the player has visited this option successfully
|
|
yl_speak_up.count_visits_to_option(pname, o_id)
|
|
return {next_dialog = target_dialog, alternate_text = alternate_text}
|
|
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.
|
|
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 == "put_into_block_inv"
|
|
or r.r_type == "take_from_block_inv") then
|
|
-- get the inventory of the block
|
|
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
|
|
-- position not found?
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": No or incorrect position given: "..
|
|
minetest.serialize(r.rp_pos)..".")
|
|
return false
|
|
end
|
|
local meta = minetest.get_meta(r.r_pos)
|
|
if(not(meta)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": Failed to get metadata at "..
|
|
minetest.serialize(r.rp_pos)..".")
|
|
return false
|
|
end
|
|
local inv = meta:get_inventory()
|
|
if(not(inv)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": Failed to get inventory at "..
|
|
minetest.serialize(r.rp_pos)..".")
|
|
return false
|
|
end
|
|
local inv_name = r.r_inv_list_name
|
|
-- get the inventory of the npc
|
|
local npc_inv = minetest.get_inventory({type="detached",
|
|
name="yl_speak_up_npc_"..tostring(n_id)})
|
|
local npc_inv_name = "npc_main"
|
|
-- for easier checking
|
|
local how_to_interact = "take"
|
|
if(r.r_type and r.r_type == "put_into_block_inv") then
|
|
how_to_interact = "put"
|
|
end
|
|
local stack = ItemStack(r.r_itemstack)
|
|
-- is there enough room for the item?
|
|
if(how_to_interact == "put"
|
|
and not(inv:room_for_item(inv_name, stack))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": No room for \""..
|
|
minetest.serialize(r.r_itemstack).."\""..
|
|
" in node at "..
|
|
minetest.serialize(r.r_pos)..", inv list \""..
|
|
minetest.serialize(inv_name).."\".")
|
|
return false
|
|
elseif(how_to_interact == "take"
|
|
and not(npc_inv:room_for_item("npc_main", stack))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": NPC has no room for \""..
|
|
minetest.serialize(r.r_itemstack).."\".")
|
|
return false
|
|
end
|
|
-- does the item exist?
|
|
if(how_to_interact == "put"
|
|
and not(npc_inv:contains_item(npc_inv_name, stack, false))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": NPC does not have \""..
|
|
minetest.serialize(r.r_itemstack).."\".")
|
|
return false
|
|
elseif(how_to_interact == "take"
|
|
and not(inv:contains_item(inv_name, stack, false))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": Block at "..minetest.serialize(r.r_pos)..
|
|
" does not contain \""..tostring(r.r_itemstack).."\" in list \""..
|
|
tostring(r.r_inv_list).."\".")
|
|
return false
|
|
end
|
|
-- check the blacklist
|
|
local node = minetest.get_node(r.r_pos)
|
|
if(not(node) or not(node.name)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": No node found at "..minetest.serialize(r.r_pos)..".")
|
|
return false
|
|
end
|
|
-- do not interact with nodes on the blacklist
|
|
-- (this here is inventory interaction, so no need to check for tools)
|
|
if(yl_speak_up.check_blacklisted(how_to_interact, node.name, node.name, nil)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": Blocks of type \""..tostring(node.name).."\" do not allow "..
|
|
"interaction of type \""..tostring(r.r_value).."\" for NPC.")
|
|
return false
|
|
end
|
|
-- construct a fake player
|
|
local owner_name = yl_speak_up.npc_owner[ n_id ]
|
|
if(not(owner_name) or owner_name == "") then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": NPC does not have an owner. Aborting.")
|
|
return false
|
|
end
|
|
-- act in the name of the owner when accessing inventories
|
|
local fake_player = yl_speak_up.get_fake_player(owner_name, "")
|
|
local def = minetest.registered_nodes[ node.name ]
|
|
if(def and def[ "allow_metadata_inventory_"..how_to_interact ]) then
|
|
local res = def[ "allow_metadata_inventory_"..how_to_interact ](
|
|
r.r_pos, inv_name, 1,
|
|
ItemStack(r.r_itemstack),
|
|
fake_player)
|
|
if(not(res) or res < ItemStack(r.r_itemstack):get_count()) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": allow_metadata_inventory_"..tostring(how_to_interact)..
|
|
" forbits interaction at "..minetest.serialize(r.r_pos)..".")
|
|
return false
|
|
end
|
|
end
|
|
-- all ok so far; we can proceed
|
|
if(how_to_interact == "put") then
|
|
local r1 = npc_inv:remove_item(npc_inv_name, stack)
|
|
local r2 = inv:add_item(inv_name, r1)
|
|
return true
|
|
elseif(how_to_interact == "take") then
|
|
local r1 = inv:remove_item(inv_name, stack)
|
|
local r2 = npc_inv:add_item(npc_inv_name, r1)
|
|
return true
|
|
end
|
|
return false
|
|
elseif(r.r_type == "deal_with_offered_item") then
|
|
-- possible r_value: "do_nothing", "take_as_wanted", "take_all", "refuse_all"}
|
|
if(not(r.r_value) or r.r_value == "do_nothing") then
|
|
return true -- we're good at doing nothing
|
|
end
|
|
local pname = player:get_player_name()
|
|
local inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
|
local stack_got = inv:get_stack("npc_wants",1)
|
|
if(stack_got:is_empty()) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": The offered stack is empty.")
|
|
return false -- the player gave nothing
|
|
end
|
|
-- get the inventory of the npc
|
|
local npc_inv = minetest.get_inventory({type="detached",
|
|
name="yl_speak_up_npc_"..tostring(n_id)})
|
|
-- shall we take all or just as much as the NPC wants?
|
|
local stack_wanted = ItemStack(r.r_value)
|
|
local amount = 0
|
|
if(r.r_value == "take_all") then
|
|
amount = stack_got:get_count()
|
|
elseif(r.r_value == "takeas_wanted") then
|
|
amount = stack_wanted:get_count()
|
|
-- the NPC didn't get enough
|
|
if(amount > stack_got:get_count()) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": The offered stack \""..tostring(stack_got)..
|
|
"is smaller than what the NPC wanted: \""..
|
|
tostring(stack_wanted).."\".")
|
|
return false
|
|
end
|
|
end
|
|
local take_stack = stack_got:get_name().." "..tostring(amount)
|
|
if(not(npc_inv:room_for_item("npc_main", take_stack))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": The NPC has not enough room for \""..tostring(take_stack).."\".")
|
|
return false
|
|
end
|
|
-- actually transfer the item from the player to the NPC's inventory
|
|
npc_inv:add_item("npc_main", take_stack)
|
|
inv:remove_item("npc_wants", take_stack)
|
|
-- returning of any leftover items needs to happen after *all* effects
|
|
-- are executed; we don't need to take any special preparations here
|
|
|
|
-- this action was a success
|
|
return true
|
|
|
|
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
|
|
if(not(yl_speak_up.npc_has_priv(n_id, "effect_exec_lua", r.r_is_generic))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": The NPC does not have the \"effect_exec_lua\" priv.")
|
|
return false
|
|
end
|
|
return yl_speak_up.eval_and_execute_function(player, r, "r_")
|
|
-- this can only be set and edited with the staff
|
|
elseif(r.r_type == "give_item") then
|
|
if(not(r.r_value)) then
|
|
return false
|
|
end
|
|
if(not(yl_speak_up.npc_has_priv(n_id, "effect_give_item", r.r_is_generic))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": The NPC does not have the \"effect_give_item\" priv.")
|
|
return false
|
|
end
|
|
local item = ItemStack(r.r_value)
|
|
if(not(minetest.registered_items[item:get_name()])) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"give_item: "..tostring(item:get_name()).." unknown.")
|
|
return false
|
|
end
|
|
local r = player:get_inventory():add_item("main", item)
|
|
if(not(r) or not(r:is_empty())) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"give_item: "..tostring(item:get_name()).." failed.")
|
|
local pname = player:get_player_name()
|
|
yl_speak_up.log_change(pname, n_id, "No room for item: "..r:to_string())
|
|
return false
|
|
end
|
|
return true
|
|
-- this can only be set and edited with the staff
|
|
elseif(r.r_type == "take_item") then
|
|
if(not(yl_speak_up.npc_has_priv(n_id, "effect_take_item", r.r_is_generic))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": The NPC does not have the \"effect_take_item\" priv.")
|
|
return false
|
|
end
|
|
if(not(r.r_value)) then
|
|
return false
|
|
end
|
|
local item = ItemStack(r.r_value)
|
|
if(not(minetest.registered_items[item:get_name()])) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.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.r_id).." "..
|
|
"take_item: "..tostring(item:get_name()).." failed.")
|
|
return false
|
|
end
|
|
return true
|
|
-- this can only be set and edited with the staff
|
|
elseif(r.r_type == "move") then
|
|
if(not(yl_speak_up.npc_has_priv(n_id, "effect_move_player", r.r_is_generic))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": The NPC does not have the \"effect_move_player\" priv.")
|
|
return false
|
|
end
|
|
-- copeid/moved here from AliasAlreadyTakens code in functions.lua
|
|
local target_pos = nil
|
|
local target_pos_valid = false
|
|
|
|
--pos like (100,20,400)
|
|
if minetest.string_to_pos(r.r_value) then
|
|
target_pos = minetest.string_to_pos(r.r_value)
|
|
target_pos_valid = true
|
|
end
|
|
|
|
--pos like 100,20,400
|
|
local maybe = string.split(r.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(r.r_value,1,1) == "{"
|
|
and string.sub(r.r_value,-1,-1) == "}" then
|
|
local might_be_pos = minetest.deserialize("return " .. r.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
|
|
yl_speak_up.log_change(pname, n_id, tostring(r.r_id)..": "..
|
|
"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 = yl_speak_up.get_number_from_id(n_id)
|
|
if obj:get_luaentity() and tonumber(npc) then
|
|
yl_speak_up.log_change(pname, n_id, tostring(r.r_id)..": "..
|
|
"NPC at "..minetest.pos_to_string(obj:get_pos(),0)..
|
|
" could not move player "..pname.." because the content of "..
|
|
tostring(r.r_id).." is wrong:"..dump(r.r_value))
|
|
else
|
|
yl_speak_up.log_change(pname, n_id, tostring(r.r_id)..": "..
|
|
"NPC with unknown ID or without proper object "..
|
|
" could not move player "..pname.." because the content of "..
|
|
tostring(r.r_id).." is wrong:"..dump(r.r_value))
|
|
end
|
|
return false
|
|
end
|
|
return true
|
|
|
|
-- "an internal state (i.e. of a quest)", -- 2
|
|
elseif(r.r_type == "state") then
|
|
if(not(r.r_variable) or r.r_variable == "") then
|
|
return false
|
|
end
|
|
local pname = player:get_player_name()
|
|
-- set the value of the variable
|
|
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()
|
|
-- get the properties of the NPC
|
|
local properties = yl_speak_up.get_npc_properties(pname)
|
|
if(not(properties)) 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 = 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)
|
|
local res = yl_speak_up.set_npc_property(pname, r.r_value, new_value, "effect")
|
|
if(res ~= "OK") then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"property: "..tostring(res))
|
|
return false
|
|
end
|
|
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
|
|
if(not(player) or not(r.r_value)) then
|
|
return false
|
|
end
|
|
local custom_data = yl_speak_up.custom_functions_r_[r.r_value]
|
|
if(not(custom_data) or not(custom_data.code)) then
|
|
return false
|
|
end
|
|
local fun = custom_data.code
|
|
-- actually call the function
|
|
return fun(player, n_id, r)
|
|
-- "a block somewhere" -- 3
|
|
elseif(r.r_type == "block") then
|
|
-- is the position given correctly?
|
|
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
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: Missing or wrong position given: "..
|
|
minetest.serialize(r.r_pos)..".")
|
|
return false
|
|
end
|
|
-- check protection (relevant for some actions): the *owner*
|
|
-- of the NPC needs to be able to build there
|
|
local is_protected = minetest.is_protected(r.r_pos, yl_speak_up.npc_owner[ n_id ] or "?")
|
|
-- human readable position; mostly for debug messages
|
|
local pos_str = tostring(minetest.pos_to_string(r.r_pos))
|
|
-- the area has to be loaded
|
|
local node = minetest.get_node_or_nil(r.r_pos)
|
|
if(not(node)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: Not loaded (nil) at pos "..pos_str..".")
|
|
return false
|
|
end
|
|
-- do not interact with nodes on the blacklist
|
|
if(yl_speak_up.check_blacklisted(r.r_value, r.r_node, node.name, nil)) then
|
|
-- construct the right text for the error message
|
|
local nname = node.name
|
|
if(r.r_value == "place") then
|
|
nname = r.r_node
|
|
end
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: Blocks of type \""..tostring(nname).."\" do not allow "..
|
|
"interaction of type \""..tostring(r.r_value).."\" for NPC.")
|
|
return false
|
|
end
|
|
-- if node has owner set: check if owner == npc owner
|
|
local meta = minetest.get_meta(r.r_pos)
|
|
if(meta
|
|
and meta:get_string("owner") and meta:get_string("owner") ~= ""
|
|
and meta:get_string("owner") ~= yl_speak_up.npc_owner[ n_id ]) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: Blocks at "..pos_str.." is owned by "..meta:get_string("owner")..
|
|
". NPC is owned by "..tostring(yl_speak_up.npc_owner[ n_id ])..
|
|
" and thus cannot interact with it.")
|
|
return false
|
|
end
|
|
-- create a fake player and a suitable itemstack
|
|
local owner_name = yl_speak_up.npc_owner[ n_id ]
|
|
if(not(owner_name) or owner_name == "") then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
r.r_type..": NPC does not have an owner. Aborting.")
|
|
return false
|
|
end
|
|
|
|
-- "If there is air: Place a block so that it looks like now.", -- 2
|
|
if(r.r_value and r.r_value == "place") then
|
|
if(is_protected) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: place - "..pos_str.." is protected. Can't place.")
|
|
return false
|
|
end
|
|
if(not(node) or not(node.name) or node.name ~= "air") then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: place - there is already a block at pos "..pos_str..
|
|
". Can't place.")
|
|
return false
|
|
end
|
|
-- does the NPC have this block in his inventory? else he can't place it
|
|
local npc_inv = minetest.get_inventory({type="detached",
|
|
name="yl_speak_up_npc_"..tostring(n_id)})
|
|
if(not(npc_inv:contains_item("npc_main", tostring(r.r_node)))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: place - NPC does not have "..tostring(r.r_node)..
|
|
" in his inventory for placing at "..pos_str..".")
|
|
return false
|
|
end
|
|
-- TODO: switch to minetest.place_node in the future once the bug with placing
|
|
-- on an air node is fixed
|
|
-- actually place the node
|
|
minetest.set_node(r.r_pos, {name=r.r_node, param2=r.r_param2})
|
|
-- consume the item
|
|
npc_inv:remove_item("npc_main", tostring(r.r_node))
|
|
return true
|
|
-- "If there is a block: Dig it.", -- 3
|
|
elseif(r.r_value and r.r_value == "dig") then
|
|
if(is_protected) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: place - "..pos_str.." is protected. Can't place.")
|
|
return false
|
|
end
|
|
if(not(node) or not(node.name) or node.name == "air"
|
|
or not(minetest.registered_items[ node.name ])) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: dig - there is no block at pos "..pos_str..".")
|
|
return false
|
|
end
|
|
-- TODO: use dig_node once that can put the items in the inventory
|
|
-- local dig_res = minetest.dig_node(r.r_pos)
|
|
if(minetest.registered_items[ node.name ].can_dig
|
|
and not(minetest.registered_items[ node.name ].can_dig(r.r_pos))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: dig - Can't dig block at pos "..pos_str..".")
|
|
return false
|
|
end
|
|
-- actually remove the node
|
|
minetest.remove_node(r.r_pos)
|
|
-- get node drops when digging without a tool
|
|
local drop_list = minetest.get_node_drops(node, nil)
|
|
local npc_inv = minetest.get_inventory({type="detached",
|
|
name="yl_speak_up_npc_"..tostring(n_id)})
|
|
-- put the drops into the inventory of the NPC
|
|
for i, d in ipairs(drop_list) do
|
|
local rest = npc_inv:add_item("npc_main", ItemStack(d))
|
|
if(rest and not(rest:is_empty()) and rest:get_count()>0) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id)..
|
|
" block: dig (info) - NPC had no room for item drop "..
|
|
rest:to_string().." from digging at "..pos_str..".")
|
|
end
|
|
end
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: dig - success: "..tostring(node.name).." at pos "..pos_str..".")
|
|
return true
|
|
-- "Punch the block.", -- 4
|
|
elseif(r.r_value and r.r_value == "punch") then
|
|
-- shall the NPC wield and use an item? if so that items' on_use function takes
|
|
-- precedence
|
|
if(r.r_wielded and r.r_wielded ~= "") then
|
|
return yl_speak_up.use_tool_on_block(r, "on_use", player, n_id, o_id)
|
|
end
|
|
-- even air can be punched - even if that is pretty pointless
|
|
-- TODO: some blocks may define their own functions and care for what the player wields (i.e. cheese mod)
|
|
minetest.punch_node(r.r_pos, nil)
|
|
return true
|
|
-- "Right-click the block.", -- 5
|
|
elseif(r.r_value and r.r_value == "right-click") then
|
|
-- shall the NPC wield and use an item? if so that items' on_use function takes
|
|
-- precedence
|
|
if(r.r_wielded and r.r_wielded ~= "") then
|
|
return yl_speak_up.use_tool_on_block(r, "on_place", player, n_id, o_id)
|
|
end
|
|
-- with a tool, clicking on air might make sense; without a tool it doesn't
|
|
if(not(node) or not(node.name) or not(minetest.registered_nodes[node.name])) then
|
|
return false
|
|
end
|
|
-- do not right-click nodes that have a metadata formspec string
|
|
local meta = minetest.get_meta(r.r_pos)
|
|
if(meta and meta:get_string("formspec") and meta:get_string("formspec") ~= "") then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: right-click - The block at "..pos_str.." has a "..
|
|
"formspec set. NPC can't read these. Interaction not possible.")
|
|
return false
|
|
end
|
|
-- do not right-click nodes that have an inventory (they most likely show a
|
|
-- formspec - which the NPC can't use anyway)
|
|
local inv = meta:get_inventory()
|
|
for k, l in pairs(inv:get_lists()) do
|
|
-- if the inventory contains any lists: abort
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: right-click - The block at "..pos_str.." has an "..
|
|
"inventory. Most likely it will show a formspec on right-click. "..
|
|
"NPC can't read these. Interaction not possible.")
|
|
return false
|
|
end
|
|
-- is it a door?
|
|
if(doors.registered_doors[node.name]) then
|
|
doors.door_toggle( r.r_pos, node, nil) --, clicker)
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: Opened/closed door at "..pos_str..".")
|
|
-- is it a normal trapdoor?
|
|
elseif(doors.registered_trapdoors[node.name]) then
|
|
doors.trapdoor_toggle(r.r_pos, node, nil) --, clicker)
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: Opened/closed trapdoor at "..pos_str..".")
|
|
elseif(minetest.registered_nodes[node.name]
|
|
and minetest.registered_nodes[node.name].on_rightclick) then
|
|
local fake_player = yl_speak_up.get_fake_player(owner_name, "")
|
|
local itemstack = ItemStack("")
|
|
local pointed_thing = nil -- TODO
|
|
if(minetest.registered_nodes[node.name].on_rightclick(
|
|
r.r_pos, node, fake_player, itemstack, pointed_thing)) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: right-clicked at at pos "..pos_str..".")
|
|
else
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"block: right-click at at pos "..pos_str.." had no effect.")
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
-- ""NPC crafts something", -- 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.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.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.r_id).." "..
|
|
"Crafting failed: Diffrent output: "..tostring(output.item:to_string()))
|
|
return false
|
|
end
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"Great: Crafting is possible!")
|
|
-- actually consume the items required, return the ones in decremented_input
|
|
for i, v in ipairs(r.r_craft_grid) do
|
|
if(v and v ~= "") then
|
|
npc_inv:remove_item("npc_main", ItemStack(v))
|
|
end
|
|
end
|
|
-- add the craft result
|
|
if(not(npc_inv:room_for_item("npc_main", output.item))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"No room for craft result "..output.item:to_string())
|
|
end
|
|
npc_inv:add_item("npc_main", output.item)
|
|
-- add the decremented_inputs
|
|
for k,v in pairs(decremented_input.items) do
|
|
if(k and not(v:is_empty())) then
|
|
if(not(npc_inv:room_for_item("npc_main", v))) then
|
|
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
|
"No room for craft decr. input "..v:to_string())
|
|
end
|
|
-- actually give the decremented input to the NPC
|
|
npc_inv:add_item("npc_main", v)
|
|
end
|
|
end
|
|
return true
|
|
-- "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(
|
|
yl_speak_up.chat_all_prefix..
|
|
minetest.colorize(yl_speak_up.chat_all_color, text))
|
|
-- sending a chat message always counts as successful
|
|
return true
|
|
end
|
|
-- fallback: unkown type
|
|
return false
|
|
end
|