Skip to content
Snippets Groups Projects
Commit 249dbe04 authored by DarkGod's avatar DarkGod
Browse files

More powerful chat text templating available

parent 92f0ee51
No related branches found
No related tags found
No related merge requests found
......@@ -19,6 +19,7 @@
require "engine.class"
require "engine.dialogs.Chat"
local slt2 = require "slt2"
--- Handle chats between the player and NPCs
module(..., package.seeall, class.make)
......@@ -30,6 +31,7 @@ function _M:init(name, npc, player, data)
self.player = player
self.name = name
data = setmetatable(data or {}, {__index=_G})
self.data = data
local f, err = loadfile("/data/chats/"..name..".lua")
if not f and err then error(err) end
......@@ -53,7 +55,7 @@ function _M:addChat(c)
self:triggerHook{"Chat:add", c=c}
assert(c.id, "no chat id")
assert(c.text, "no chat text")
assert(c.text or c.template, "no chat text or template")
assert(c.answers, "no chat answers")
self.chats[c.id] = c
print("[CHAT] loaded", c.id, c)
......@@ -81,7 +83,12 @@ end
--- Gets the chat with the given id
function _M:get(id)
return self.chats[id]
local c = self.chats[id]
if c and c.template then
local tpl = slt2.loadstring(c.template)
c.text = slt2.render(tpl, {data=self.data, player=self.player, npc=self.npc})
end
return c
end
--- Replace some keywords in the given text
......
game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_open_vert.png

7.95 KiB | W: | H:

game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_open_vert.png

8.41 KiB | W: | H:

game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_open_vert.png
game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_open_vert.png
game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_open_vert.png
game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_open_vert.png
  • 2-up
  • Swipe
  • Onion skin
game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_vert.png

11.1 KiB | W: | H:

game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_vert.png

11.6 KiB | W: | H:

game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_vert.png
game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_vert.png
game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_vert.png
game/modules/tome/data/gfx/shockbolt/terrain/icecave/icecave_door1_vert.png
  • 2-up
  • Swipe
  • Onion skin
--[[
-- slt2 - Simple Lua Template 2
--
-- Project page: https://github.com/henix/slt2
--
-- @License
-- MIT License
--]]
local slt2 = {}
-- a tree fold on inclusion tree
-- @param init_func: must return a new value when called
local function include_fold(template, start_tag, end_tag, fold_func, init_func)
local result = init_func()
start_tag = start_tag or '<?'
end_tag = end_tag or '?>'
local start_tag_inc = start_tag..'include:'
local start1, end1 = string.find(template, start_tag_inc, 1, true)
local start2 = nil
local end2 = 0
while start1 ~= nil do
if start1 > end2 + 1 then -- for beginning part of file
result = fold_func(result, string.sub(template, end2 + 1, start1 - 1))
end
start2, end2 = string.find(template, end_tag, end1 + 1, true)
assert(start2, 'end tag "'..end_tag..'" missing')
do -- recursively include the file
local filename = assert(loadstring('return '..string.sub(template, end1 + 1, start2 - 1)))()
assert(filename)
local fin = assert(io.open(filename))
-- TODO: detect cyclic inclusion?
result = fold_func(result, include_fold(fin:read('*a'), start_tag, end_tag, fold_func, init_func), filename)
fin:close()
end
start1, end1 = string.find(template, start_tag_inc, end2 + 1, true)
end
result = fold_func(result, string.sub(template, end2 + 1))
return result
end
-- preprocess included files
-- @return string
function slt2.precompile(template, start_tag, end_tag)
return table.concat(include_fold(template, start_tag, end_tag, function(acc, v)
if type(v) == 'string' then
table.insert(acc, v)
elseif type(v) == 'table' then
table.insert(acc, table.concat(v))
else
error('Unknown type: '..type(v))
end
return acc
end, function() return {} end))
end
-- unique a list, preserve order
local function stable_uniq(t)
local existed = {}
local res = {}
for _, v in ipairs(t) do
if not existed[v] then
table.insert(res, v)
existed[v] = true
end
end
return res
end
-- @return { string }
function slt2.get_dependency(template, start_tag, end_tag)
return stable_uniq(include_fold(template, start_tag, end_tag, function(acc, v, name)
if type(v) == 'string' then
elseif type(v) == 'table' then
if name ~= nil then
table.insert(acc, name)
end
for _, subname in ipairs(v) do
table.insert(acc, subname)
end
else
error('Unknown type: '..type(v))
end
return acc
end, function() return {} end))
end
-- @return { name = string, code = string / function}
function slt2.loadstring(template, start_tag, end_tag, tmpl_name)
-- compile it to lua code
local lua_code = {}
start_tag = start_tag or '<?'
end_tag = end_tag or '?>'
local output_func = "coroutine.yield"
template = slt2.precompile(template, start_tag, end_tag)
local start1, end1 = string.find(template, start_tag, 1, true)
local start2 = nil
local end2 = 0
local cEqual = string.byte('=', 1)
while start1 ~= nil do
if start1 > end2 + 1 then
table.insert(lua_code, output_func..'('..string.format("%q", string.sub(template, end2 + 1, start1 - 1))..')')
end
start2, end2 = string.find(template, end_tag, end1 + 1, true)
assert(start2, 'end_tag "'..end_tag..'" missing')
if string.byte(template, end1 + 1) == cEqual then
table.insert(lua_code, output_func..'('..string.sub(template, end1 + 2, start2 - 1)..')')
else
table.insert(lua_code, string.sub(template, end1 + 1, start2 - 1))
end
start1, end1 = string.find(template, start_tag, end2 + 1, true)
end
table.insert(lua_code, output_func..'('..string.format("%q", string.sub(template, end2 + 1))..')')
local ret = { name = tmpl_name or '=(slt2.loadstring)' }
if setfenv == nil then -- lua 5.2
ret.code = table.concat(lua_code, '\n')
else -- lua 5.1
ret.code = assert(loadstring(table.concat(lua_code, '\n'), ret.name))
end
return ret
end
-- @return { name = string, code = string / function }
function slt2.loadfile(filename, start_tag, end_tag)
local fin = assert(io.open(filename))
local all = fin:read('*a')
fin:close()
return slt2.loadstring(all, start_tag, end_tag, filename)
end
local mt52 = { __index = _ENV }
local mt51 = { __index = _G }
-- @return a coroutine function
function slt2.render_co(t, env)
local f
if setfenv == nil then -- lua 5.2
if env ~= nil then
setmetatable(env, mt52)
end
f = assert(load(t.code, t.name, 't', env or _ENV))
else -- lua 5.1
if env ~= nil then
setmetatable(env, mt51)
end
f = setfenv(t.code, env or _G)
end
return f
end
-- @return string
function slt2.render(t, env)
local result = {}
local co = coroutine.create(slt2.render_co(t, env))
while coroutine.status(co) ~= 'dead' do
local ok, chunk = coroutine.resume(co)
if not ok then
error(chunk)
end
table.insert(result, chunk)
end
return table.concat(result)
end
return slt2
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment