illarion-content/item/base/bookWriting.lua
2025-10-07 12:04:35 +02:00

356 lines
11 KiB
Lua
Raw Permalink Blame History

--[[
Illarion Server
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
]]
local common = require("base.common")
local tailoring = require("craft.final.tailoring")
local lookat = require("base.lookat")
local parchmentSelectionStatus = {}
local M = {}
M.parchmentMaxTextLength = 986
local setTitle
local selectNewPage
local removePage
local signBook
local getWrittenTextAndSignatureFromBook
local function isBookInHand(user)
local bookPositions = {Character.left_tool, Character.right_tool}
for _, bookPos in pairs(bookPositions) do
local book = user:getItemAt(bookPos)
for _, bookColour in pairs(tailoring.books) do --is it a book
for _, bookID in pairs(bookColour) do
if bookID == book.id then
local bookPermissions = book:getData("bookPermissions")
if not common.IsNilOrEmpty(book:getData("book")) or (not common.IsNilOrEmpty(bookPermissions) and tonumber(bookPermissions) ~= user.id) then --is it an official book already or a book written by someone else
user:inform("Dieses Buch wurde von einem anderen Verfasser geschrieben. Bitte kritzel nicht in ihm herum.", "This is a book that's already been written, and by a different author. It's not your place to write in it.")
return false
end
if book.number > 1 then
user:inform("Du kannst nur in einem Buch gleichzeitig schreiben.", "You can only write in one book at a time.")
return false
end
return book
end
end
end
end
user:inform("Nimm das Buch in die Hand um in ihm zu schreiben.", "You must hold a book in your hand if you want to write in it.")
return false
end
function M.writeBook(user)
local book = isBookInHand(user)
if not book then
return
end
local callback = function(dialog)
local success = dialog:getSuccess()
if not success then
return
end
local index = dialog:getSelectedIndex()+1
book = isBookInHand(user) -- Check again in case the book was moved
if not book then
return
end
if index == 1 then
setTitle(user)
elseif index == 2 then
selectNewPage(user)
elseif index == 3 then
removePage(user, book)
elseif index == 4 then
signBook(user, book)
end
end
local dialog = SelectionDialog(common.GetNLS(user,"Verfasse ein Buch","Book Writing") , common.GetNLS(user,"W<EFBFBD>hle aus, was du machen willst.","Select what you want to do.") , callback)
dialog:addOption(0, common.GetNLS(user,"Buchtitel","Set Book Title"))
dialog:addOption(0, common.GetNLS(user,"Neue Seite","Add New Page"))
dialog:addOption(0, common.GetNLS(user,"Entferne die letzte Seite","Remove Last Page"))
dialog:addOption(0, common.GetNLS(user,"Buch signieren","Sign Book"))
user:requestSelectionDialog(dialog)
end
function setTitle(user)
local title = common.GetNLS(user, "Buchtitel", "Set Title")
local callback = function(dialog)
if not dialog:getSuccess() then
return
end
local input = dialog:getInput()
if common.IsNilOrEmpty(input) then
user:inform("Ein Buch ohne Titel ist wie eine Seite ohne Buchstaben.", "The title can not be left blank.")
return
end
if string.len(input) > 40 then
user:inform("Bei dieser Titell<6C>nge hast du es etwas <20>bertrieben.", "The cover of the book is not large enough to fit such a long title.")
return
end
local book = isBookInHand(user)
if not book then
return
end
book:setData("bookTitle", input)
book:setData("descriptionEn", "Title: "..input)
book:setData("descriptionDe", "Titel: "..input)
world:changeItem(book)
user:inform("Neuer Buchtitel: "..input..".", "You set the title of the book to "..input..".")
end
local dialog = InputDialog(title, "", false, 40, callback)
user:requestInputDialog(dialog)
end
function selectNewPage(user)
if not parchmentSelectionStatus[user.name] then
parchmentSelectionStatus[user.name] = {}
end
parchmentSelectionStatus[user.name].status = true
parchmentSelectionStatus[user.name].position = user.pos
user:inform("Benutze die Schriftrolle, die du dem Buch als Seite hinzuf<75>gen m<>chtest.", "Select the parchment you want to add to the book as a page by using it.")
end
local function getWrittenTextFromParchment(theParchment)
if not common.IsNilOrEmpty(theParchment:getData("writtenText")) then
local writtenText = theParchment:getData("writtenText")
for i = 2, 4 do
local addText = theParchment:getData("writtenText"..i)
writtenText = writtenText..addText
end
return writtenText
end
return false
end
function M.addNewPageToBook(user, sourceItem)
parchmentSelectionStatus[user.name].status = false
if sourceItem.wear == 255 then
user:inform("Diesem Buch kannst du keine Seiten hinzuf<75>gen.", "You can't add this page to the book, it's been pinned down!")
return
end
local book = isBookInHand(user)
if not book then
return
end
local pageText = getWrittenTextFromParchment(sourceItem)
if not pageText then
user:inform("Auf der Schriftrolle steht nichts.", "The parchment must have been written on.")
return
end
local lastPage = book:getData("pageCount")
if common.IsNilOrEmpty(lastPage) then
lastPage = 0
end
local nextPage = lastPage + 1
local texts = {
string.sub(pageText, 1, 250),
string.sub(pageText, 251, 500),
string.sub(pageText, 501, 750),
string.sub(pageText, 751, 986),
}
for int , text in ipairs(texts) do
book:setData("page"..nextPage.."part"..int, text)
end
local signature = sourceItem:getData("signatureText")
local finalized = sourceItem:getData("finalized")
if not common.IsNilOrEmpty(signature) then
book:setData("page"..nextPage.."signature", signature)
book:setData("page"..nextPage.."finalized", finalized)
end
book:setData("pageCount", nextPage)
world:changeItem(book)
world:erase(sourceItem, 1)
user:inform("Seite hinzugef<65>gt.", "You added the selected parchment to the book.")
end
function removePage(user, book)
local pageNumber = tonumber(book:getData("pageCount"))
if not pageNumber or pageNumber <= 0 then
user:inform("Du kannst keine Seite aus einem leeren Buch entfernen.", "You can not remove a page from a book that has none.")
return
end
local theText, theSignature, finalized = getWrittenTextAndSignatureFromBook(book, pageNumber)
local theParchment = world:createItemFromId(Item.parchment, 1, user.pos, true, 333, {})
M.convertStringToMultipleParchmentDataValues(theParchment, theText, theSignature, finalized)
local usersBag = user:getBackPack()
if usersBag and usersBag:getSlotCount() > 0 then
world:erase(theParchment, 1)
usersBag:insertItem(theParchment, true)
end
if pageNumber-1 == 0 then
book:setData("pageCount", "")
else
book:setData("pageCount", pageNumber-1)
end
for i = 1, 4 do
book:setData("page"..pageNumber.."part"..i, "")
end
book:setData("page"..pageNumber.."signature", "")
world:changeItem(book)
user:inform("Du rei<65>t die Seite vorsichtig aus dem Buch.", "Carefully removing the page from the book, you are left with a written parchment.")
end
function signBook(user, book)
book:setData("bookPermissions", user.id)
book:setData("bookAuthor", user.name)
local creator = book:getData("craftedBy")
if not common.IsNilOrEmpty(creator) and creator ~= user.name then
lookat.UnsetItemCraftedBy(book)
end
world:changeItem(book)
user:inform("Du hast das Buch signiert. Nur noch du kannst <20>nderungen an ihm vornehmen.", "You sign the book. From now on, only you have the permission to write in the book.")
end
function getWrittenTextAndSignatureFromBook(book, pageNumber)
local writtenText = ""
for i = 1, 4 do
writtenText = writtenText..book:getData("page"..pageNumber.."part"..i)
end
local signature = book:getData("page"..pageNumber.."signature")
local finalized = book:getData("page"..pageNumber.."finalized")
return writtenText, signature, finalized
end
function M.getParchmentSelectionStatus(user)
if not parchmentSelectionStatus[user.name] then
return false
end
if parchmentSelectionStatus[user.name].position ~= user.pos then
return -- user moved
end
return parchmentSelectionStatus[user.name].status
end
M.germanParchmentDescription = "Das Pergament ist beschrieben."
M.englishParchmentDescription = "The parchment has been written on."
function M.convertStringToMultipleParchmentDataValues(theParchment, writtenText, theSignature, finalized)
local texts = {
string.sub(writtenText, 1, 250),
string.sub(writtenText, 251, 500),
string.sub(writtenText, 501, 750),
string.sub(writtenText, 751, M.parchmentMaxTextLength),
}
theParchment:setData("writtenText", texts[1])
for i = 2, 4 do
theParchment:setData("writtenText"..i, texts[i])
end
lookat.SetSpecialDescription(theParchment,M.germanParchmentDescription,M.englishParchmentDescription)
if not common.IsNilOrEmpty(theSignature) then
theParchment:setData("signatureText", theSignature)
if not common.IsNilOrEmpty(finalized) then
theParchment:setData("finalized", finalized)
end
lookat.SetSpecialDescription(theParchment,"Das Pergament ist unterschrieben.","The parchment is signed.")
world:changeItem(theParchment)
end
theParchment.wear = 254 -- Written parchments should have maximum rot time to allow message exchange
world:changeItem(theParchment)
end
return M