epic/blocks/dialogue.lua

149 lines
3.6 KiB
Lua

local update_formspec = function(meta)
local text = meta:get_string("text")
meta:set_string("infotext", "Dialogue block: '" .. text .. "'")
meta:set_string("formspec", "size[8,2;]" ..
"field[0.2,0.5;8,1;text;Text;" .. text .. "]" ..
"button_exit[0.1,1.5;8,1;save;Save]" ..
"")
end
-- player -> {}
local active_dialogues = {}
-- formspec name
local FORMNAME = "epic_dialogue"
-- create the dialogue formspec
local function show_formspec(player_name)
local player_dialogue = active_dialogues[player_name]
local buttons = ""
local i = 0
for pos_str, text in pairs(player_dialogue.targets) do
buttons = buttons ..
"button_exit[0," .. (i+0) .. ";2,1;" .. pos_str .. ";Choose]" ..
"label[2.5," .. (i+0.2) .. ";" .. text .. "]"
i = i + 1
end
minetest.show_formspec(player_name,
FORMNAME,
"size[8," .. (i) .. ";]" ..
buttons
)
end
-- callback
minetest.register_on_player_receive_fields(function(player, formname, fields)
local parts = formname:split(";")
local name = parts[1]
if name ~= FORMNAME then
return
end
print("epic_dialogue", player:get_player_name(), dump(fields))
local player_name = player:get_player_name()
local player_dialogue = active_dialogues[player_name]
if not player_dialogue then
-- dialogue not active
return
end
for pos_str in pairs(player_dialogue.targets) do
if fields[pos_str] then
player_dialogue.selected = pos_str
return true
end
end
-- no choice = quit
player_dialogue.quit = true
return true
end)
minetest.register_node("epic:dialogue", {
description = "Epic dialogue block: show one or more questions in a formspec",
tiles = epic.create_texture("condition", "epic_bubble.png"),
paramtype2 = "facedir",
groups = {cracky=3,oddly_breakable_by_hand=3,epic=1},
on_rotate = epic.on_rotate,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("text", "Example text")
update_formspec(meta, pos)
end,
on_receive_fields = function(pos, _, fields, sender)
local meta = minetest.get_meta(pos);
if not sender or minetest.is_protected(pos, sender:get_player_name()) then
-- not allowed
return
end
if fields.save then
local text = fields.text or "<no text>"
meta:set_string("text", text)
update_formspec(meta, pos)
end
end,
epic = {
on_enter = function(pos, meta, player)
local player_name = player:get_player_name()
local player_dialogue = active_dialogues[player_name]
if not player_dialogue then
-- create dialogue entry
player_dialogue = {
active = false,
quit = false,
selected = nil,
-- pos-str -> bool(selected)
targets = {}
}
-- save
active_dialogues[player_name] = player_dialogue
end
-- mark dialogue as not selected yet
player_dialogue.targets[minetest.pos_to_string(pos)] = meta:get_string("text")
end,
on_check = function(pos, _, player, ctx)
local player_name = player:get_player_name()
local player_dialogue = active_dialogues[player_name]
if player_dialogue then
-- show formspec if not alredy active
if not player_dialogue.active then
show_formspec(player_name)
player_dialogue.active = true
end
if player_dialogue.quit then
-- player quit the formname, abort epic execution
ctx.abort("dialogue-exit")
return
end
-- check if current dialogue node is selected
if player_dialogue.selected and player_dialogue.selected == minetest.pos_to_string(pos) then
-- position matches proceed
ctx.next()
end
end
end,
on_exit = function(_, _, player)
-- clear current dialogue
local player_name = player:get_player_name()
active_dialogues[player_name] = nil
end
}
})