• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Update script to TFS 1.3


Active Member
Jan 5, 2020
Reaction score
Hello guys, I found this script in another forum of tibia and I would like to update it to TFS 1.3 and also to not use as MOD, it can be actions, creaturescript, globalevent, anything but MOD.

Credits for the original script goes to: Dwarfer from tibiaking;

The script he made is for TFS 0.4 and uses MOD.
The script works like this:
  • Player uses bookshelf and receive a book.
  • If player uses command !book it will show all books the player received so far.
  • If player uses !book Name_of_the_book the book will appear to the player as a popup

<?xml version="1.0" encoding="UTF-8"?>
<mod name="Book System" version="1.0" author="Dwarfer" contact="tibiaking.com" enabled="yes">
<config name="Book_func"><![CDATA[
books = {
[1] = {aid = 17710, title = "Criar cerveja", icon = 4839},
[2] = {aid = 17711, title = "Extended Vision", icon = 5898},
[3] = {aid = 17712, title = "Miners Journal", icon = 4874},
[4] = {aid = 17713, title = "Dwarfer, the legend", icon = 2322}

stories = {
[1] = {"Nenhum anão pode resistir a uma boa caneca de cerveja de Jimbin e essa magia um dia permitirá a você criar tal cerveja com alguns",
" ingredientes simples. Colete o cabelo de um troll, um cogumelo de qualquer tipo, um pequeno amontoado de alma do vale do mago louco um pouco",
" de água dos arredores do vale do mago louco e o silêncio antes do amanhecer. Coloque todos os ingredientes em um frasco de água do vale do mago",
" louco, tampe-o com uma rolha e ferva-o. Remova a rolha e ponha uma pequena amostra da poção em uma caneca e chacoalhe-a. Agora nós temos que",
" descobrir como introduzir o silêncio antes do amanhecer de uma maneira apropriada. Você deve então ter uma caneca cheia de cerveja se tudo",
" funcionar conforme calculado até aqui. Nós estimamos que uma poção deve ser uma semana de abastecimento de cerveja se você minimizar seu consumo",
" para 7 canecas por dia."

[2] = {"Most dwarves have a excellent eyesight even in dark enviroments but this spell will one day allow you to see nearly twice as far",
" as you currently do. What's needed is the fire of a fire element, the head of a ghoul,the essence of a red royal blossom, some",
" water from Blood Bay and the laugh of a mute sinner. Light a fire with the flame of the fire element. Pour the water from Blood",
" Bay into a cauldron and place it over the fire. Throw in the head of the ghoul and the essence of the red royal Blossom and mix",
" it untill a grey myst emerges.Take some of the potion and mix it with the laugh while cooling it. Now we only need to find out the",
" missing catalysts and the magic words to imbue it with energy."

[3] = {"We've dug that deep, that even we dwarves can hardly see. Fruzek told us stories of a monster making odd sounds from below the earth.",
" These frightening tales of the basilisk have halted our mining schedule, forcing us to double the guards protecting the miners."

[4] = {"Everybody knows the legend. The most powerful dwarf ever. His name? HOW COME DON'T YOU KNOW HIS NAME? (Orcs...) DWARFER, sure! Long live Dwarfer!"}

function setPlayerStorageTable(cid, storage, tab)
local tabstr = "&"
for i,x in pairs(tab) do
tabstr = tabstr .. i .. "," .. x .. ";"
setPlayerStorageValue(cid, storage, tabstr:sub(1, #tabstr-1))

function isInTable(cid, bookId)
for _,i in pairs(getPlayerStorageTable(cid, 17709))do
if tonumber(i) == tonumber(bookId) then
return true
return false

function addBookTable(cid, bookId)
local x = {}
for i = 1,#getPlayerStorageTable(cid, 17709) do
table.insert(x,getPlayerStorageTable(cid, 17709))
if x ~= 0 then
setPlayerStorageTable(cid, 17709, x)
setPlayerStorageTable(cid, 17709, {bookId})

function getPlayerStorageTable(cid, storage)
local tabstr = getPlayerStorageValue(cid, storage)
local tab = {}
if type(tabstr) ~= "string" then
return {}
if tabstr:sub(1,1) ~= "&" then
return {}
local tabstr = tabstr:sub(2, #tabstr)
local a = string.explode(tabstr, ";")
for i,x in pairs(a) do
local b = string.explode(x, ",")
tab[tonumber(b[1]) or b[1]] = tonumber(b[2]) or b[2]
return tab

function ShowLibrary(cid)
local str,n = "-- [My Library] --\n\n",0
for i = 1,#getPlayerStorageTable(cid, 17709) do
n = n + 1
str = str..""..n.." - "..(getBookInfo(getPlayerStorageTable(cid, 17709)).title).."\n"
return doPlayerPopupFYI(cid, str)

function getBookInfo(param)
for i, v in pairs(books) do
if tonumber(param) == v.aid then
return {id = i, aid = param, title = v.title, icon = v.icon}
elseif tostring(param) == v.title then
return {id = i, aid = v.aid, title = tostring(param), icon = v.icon}
return {}

function hasAid(item)
for _, v in pairs(books) do
if item.actionid == v.aid then
return true
return false

<action itemid="1718;1721" event="script"><![CDATA[
if isInTable(cid, item.actionid) then
return doPlayerSendCancel(cid, "You have already know this book.")
if hasAid(item) then
addBookTable(cid, item.actionid)
doSendMagicEffect(fromPosition, 30)
doCreatureSay(cid, "You have found a mysterious book.", TALKTYPE_ORANGE_1)
<talkaction words="!book;/book" event="buffer"><![CDATA[
local t = string.explode(string.lower(param), ",")
if not t[1] then
ShowLibrary(cid) return true
elseif tonumber(t[1]) then
doPlayerSendCancel(cid, "Enter !book Title to read.") return true
elseif tostring(t[1]) then
local b = getBookInfo(param)
if not isInTable(cid, b.aid) then
doPlayerSendCancel(cid, "There isn't this book in your personal library.") return true
doShowTextDialog(cid, b.icon, table.concat(stories[b.id])) return true
Still getting only book 1 after getting one diferente book.
Was a small typo
local virtualLibrary = {
    -- {actionid&storage, itemidYouWantToShowInPicture, "Book title", "text inside"}
    {45001, 1950, "The King's Credence; Book 1", "The valiant king was a mage. The end."},
    {45002, 1950, "The King's Credence; Book 2", "The valiant king was a sorcerer. The end."},
    {45003, 1950, "The King's Credence; Book 3", "The valiant king was a warlock. The end."},

local action_virtualLibrary = Action()

function action_virtualLibrary.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local unknownBooks = {}
    for i = 1, #virtualLibrary do
        if player:getStorageValue(virtualLibrary[i][1]) < 1 then...