", i+7)
if(e_c == 0) e_c = INFINITY
var/e = min(e_s, e_c) // find the closest of the two
if(e == INFINITY) break
var/i_num = text2num(copytext(page, i+7, e))
page = copytext(page, 1, i) + "
[title]
[author]
[pages[cur_page]]
[pages.len > 1 ? navbar() : ""]", "window=book;size=600x500")
if(opening)
if(title)
user.visible_message("[user] opens a book titled \"[src.title]\" and begins reading intently.")
else
user.visible_message("[user] opens a book titled \"[src.name]\" and begins reading intently.")
onclose(user, "book")
else
user << "This book is completely blank!"
attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/pen))
if(unique)
user << "These pages don't seem to take the ink well. Looks like you can't modify it."
return
var/choice = input("What would you like to change?") in list("Title", "Contents", "Author", "Cancel")
switch(choice)
if("Title")
var/ntitle = input("Write a new title:") as text|null
if(!ntitle)
return
else
title = sanitize(ntitle)
name = "Book: [title]"
if("Contents")
var/t = "[src.dat]"
do
t = input(user, "What text do you wish to add?", src.name, t) as message
if ((!in_range(src, usr) && src.loc != user && src.loc.loc != user && user.equipped() != W))
return
if(lentext(t) >= MAX_BOOK_MESSAGE_LEN)
var/cont = input(user, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no")
if(cont == "no")
break
while(lentext(t) > MAX_BOOK_MESSAGE_LEN)
if ((!in_range(src, usr) && src.loc != user && src.loc.loc != user && user.equipped() != W))
return
// check for exploits
for(var/tag in paper_blacklist)
if(findtext(t,"<"+tag))
user << "\blue You think to yourself, \"Hm.. this is only paper...\""
return
src.dat = t
gen_pages()
if("Author")
var/nauthor = input("Write the author's name:") as text|null
if(!nauthor)
return
else
src.author = sanitize(nauthor)
else
return
else if(istype(W, /obj/item/weapon/barcodescanner))
var/obj/item/weapon/barcodescanner/scanner = W
if(!scanner.computer)
user << "[W]'s screen flashes: 'No associated computer found!'"
else
switch(scanner.mode)
if(0)
scanner.book = src
user << "[W]'s screen flashes: 'Book stored in buffer.'"
if(1)
scanner.book = src
scanner.computer.buffer_book = src.name
user << "[W]'s screen flashes: 'Book stored in buffer. Book title stored in associated computer buffer.'"
if(2)
scanner.book = src
for(var/datum/borrowbook/b in scanner.computer.checkouts)
if(b.bookname == src.name)
scanner.computer.checkouts.Remove(b)
user << "[W]'s screen flashes: 'Book stored in buffer. Book has been checked in.'"
return
user << "[W]'s screen flashes: 'Book stored in buffer. No active check-out record found for current title.'"
if(3)
scanner.book = src
for(var/obj/item/weapon/book in scanner.computer.inventory)
if(book == src)
user << "[W]'s screen flashes: 'Book stored in buffer. Title already present in inventory, aborting to avoid duplicate entry.'"
return
scanner.computer.inventory.Add(src)
user << "[W]'s screen flashes: 'Book stored in buffer. Title added to general inventory.'"
else if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel))
if(unique)
user << "These pages seem to be made of a very robust paper. Looks like you can't carve it."
return
if(istype(src.loc, /mob) && usr.l_hand != src && usr.r_hand != src)
user << "\red You either need hold the book or put it down on something first."
return
var/obj/item/weapon/storage/book/B = new(loc)
B.icon_state = icon_state
B.name = name
B.desc = desc
user.remove_from_mob(src)
if(user.get_inactive_hand() == null)
user.put_in_inactive_hand(B)
else
B.loc = user.loc
user << "You carve out the inside of the book. Sneaky!"
del(src)
else
..()
/obj/item/weapon/barcodescanner
name = "barcode scanner"
icon = 'library.dmi'
icon_state ="scanner"
throw_speed = 1
throw_range = 5
w_class = 1.0
flags = FPRINT | TABLEPASS
var
obj/machinery/librarycomp/computer // Associated computer - Modes 1 to 3 use this
obj/item/weapon/book/book // Currently scanned book
mode = 0 // 0 - Scan only, 1 - Scan and Set Buffer, 2 - Scan and Attempt to Check In, 3 - Scan and Attempt to Add to Inventory
attack_self(mob/user as mob)
mode += 1
if(mode > 3)
mode = 0
user << "[src] Status Display:"
var/modedesc
switch(mode)
if(0)
modedesc = "Scan book to local buffer."
if(1)
modedesc = "Scan book to local buffer and set associated computer buffer to match."
if(2)
modedesc = "Scan book to local buffer, attempt to check in scanned book."
if(3)
modedesc = "Scan book to local buffer, attempt to add book to general inventory."
else
modedesc = "ERROR"
user << " - Mode [mode] : [modedesc]"
if(src.computer)
user << "Computer has been associated with this unit."
else
user << "No associated computer found. Only local scans will function properly."
user << "\n"
datum/borrowbook // Datum used to keep track of who has borrowed what when and for how long.
var
bookname
mobname
getdate
duedate
/obj/machinery/librarypubliccomp
name = "visitor computer"
icon = 'library.dmi'
icon_state = "computer"
anchored = 1
density = 1
var
screenstate = 0
title
category = "Any"
author
SQLquery
/obj/machinery/librarypubliccomp/attack_hand(var/mob/user as mob)
usr.machine = src
var/dat = "Library Visitor\n" //
switch(screenstate)
if(0)
dat += "Search Settings
"
dat += "Filter by Title: [title]
"
dat += "Filter by Category: [category]
"
dat += "Filter by Author: [author]
"
dat += "\[Start Search\]
"
if(1)
if(config.sql_enabled)
var/DBConnection/dbcon = new()
dbcon.Connect("dbi:mysql:[sqldb]:[sqladdress]:[sqlport]","[sqllogin]","[sqlpass]")
if(!dbcon.IsConnected())
dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance.
"
else if(!SQLquery)
dat += "ERROR: Malformed search request. Please contact your system administrator for assistance.
"
else
dat += ""
dat += "| AUTHOR | TITLE | CATEGORY | SS13BN |
"
var/DBQuery/query = dbcon.NewQuery(SQLquery)
query.Execute()
while(query.NextRow())
var/author = query.item[1]
var/title = query.item[2]
var/category = query.item[3]
var/id = query.item[4]
dat += "| [author] | [title] | [category] | [id] |
"
dat += "
"
dbcon.Disconnect()
else
dat += ""
dat += "| AUTHOR | TITLE | CATEGORY | SS13BN |
"
var/list/books = book_mgr.getall()
for(var/datum/archived_book/book in books)
// search queries
if(author && !findtext(author, book.author))
continue;
if(title && !findtext(title, book.title))
continue;
if(!category || (category != "Any" && category != book.category))
continue;
dat += "| [book.author] | [book.title] | [book.category] | [book.id] |
"
dat += "
"
dat += "\[Go Back\]
"
user << browse(dat, "window=publiclibrary")
onclose(user, "publiclibrary")
/obj/machinery/librarypubliccomp/Topic(href, href_list)
if(href_list["settitle"])
var/newtitle = input("Enter a title to search for:") as text|null
if(newtitle)
title = sanitize(newtitle)
else
title = null
title = dd_replacetext(title, "'", "''")
if(href_list["setcategory"])
var/newcategory = input("Choose a category to search for:") in list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion")
if(newcategory)
category = newcategory
else
category = "Any"
if(href_list["setauthor"])
var/newauthor = input("Enter an author to search for:") as text|null
if(newauthor)
author = sanitize(newauthor)
else
author = null
author = dd_replacetext(author, "'", "''")
if(href_list["search"])
if(config.sql_enabled)
SQLquery = "SELECT author, title, category, id FROM library WHERE "
if(category == "Any")
SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%'"
else
SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%' AND category='[category]'"
screenstate = 1
if(href_list["back"])
screenstate = 0
src.add_fingerprint(usr)
src.updateUsrDialog()
return
// TODO: Make this an actual /obj/machinery/computer that can be crafted from circuit boards and such
/obj/machinery/librarycomp
name = "Check-In/Out Computer"
icon = 'library.dmi'
icon_state = "computer"
anchored = 1
density = 1
var
emagged = 0
arcanecheckout = 0
screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book
buffer_book
buffer_mob
upload_category = "Fiction"
list/checkouts = list()
list/inventory = list()
checkoutperiod = 5 // In minutes
obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive
bibledelay = 0 // LOL NO SPAM (1 minute delay) -- Doohl
/obj/machinery/librarycomp/attack_hand(var/mob/user as mob)
usr.machine = src
var/dat = "Book Inventory Management\n" //
switch(screenstate)
if(0)
// Main Menu
dat += "1. View General Inventory
"
dat += "2. View Checked Out Inventory
"
dat += "3. Check out a Book
"
dat += "4. Connect to External Archive
"
dat += "5. Upload New Title to Archive
"
dat += "6. Print a Bible
"
if(src.emagged)
dat += "7. Access the Forbidden Lore Vault
"
if(src.arcanecheckout)
new /obj/item/weapon/tome(src.loc)
user << "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a dusty old tome sitting on the desk. You don't really remember printing it."
for (var/mob/V in hearers(src))
V.show_message("[usr] stares at the blank screen for a few moments, his expression frozen in fear. When he finally awakens from it, he looks a lot older.", 2)
src.arcanecheckout = 0
if(1)
// Inventory
dat += "Inventory
"
for(var/obj/item/weapon/book/b in inventory)
dat += "[b.name] (Delete)
"
dat += "(Return to main menu)
"
if(2)
// Checked Out
dat += "Checked Out Books
"
for(var/datum/borrowbook/b in checkouts)
var/timetaken = world.time - b.getdate
//timetaken *= 10
timetaken /= 600
timetaken = round(timetaken)
var/timedue = b.duedate - world.time
//timedue *= 10
timedue /= 600
if(timedue <= 0)
timedue = "(OVERDUE) [timedue]"
else
timedue = round(timedue)
dat += "\"[b.bookname]\", Checked out to: [b.mobname]
--- Taken: [timetaken] minutes ago, Due: in [timedue] minutes
"
dat += "(Check In)
"
dat += "(Return to main menu)
"
if(3)
// Check Out a Book
dat += "Check Out a Book
"
dat += "Book: [src.buffer_book] "
dat += "\[Edit\]
"
dat += "Recipient: [src.buffer_mob] "
dat += "\[Edit\]
"
dat += "Checkout Date : [world.time/600]
"
dat += "Due Date: [(world.time + checkoutperiod)/600]
"
dat += "(Checkout Period: [checkoutperiod] minutes) (+/-)"
dat += "(Commit Entry)
"
dat += "(Return to main menu)
"
if(4)
dat += "External Archive
"
if(config.sql_enabled)
var/DBConnection/dbcon = new()
dbcon.Connect("dbi:mysql:[sqldb]:[sqladdress]:[sqlport]","[sqllogin]","[sqlpass]")
if(!dbcon.IsConnected())
dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance."
else
dat += "(Order book by SS13BN)
"
dat += ""
dat += "| AUTHOR | TITLE | CATEGORY | |
"
var/DBQuery/query = dbcon.NewQuery("SELECT id, author, title, category FROM library")
query.Execute()
while(query.NextRow())
var/id = query.item[1]
var/author = query.item[2]
var/title = query.item[3]
var/category = query.item[4]
dat += "| [author] | [title] | [category] | \[Order\] |
"
dat += "
"
dat += "(Return to main menu)
"
dbcon.Disconnect()
else
dat += "(Order book by SS13BN)
"
dat += ""
dat += "| AUTHOR | TITLE | CATEGORY | |
"
var/list/books = book_mgr.getall()
for(var/datum/archived_book/book in books)
dat += "| [book.author] | [book.title] | [book.category] | [book.id] |
"
dat += "
"
dat += "(Return to main menu)
"
if(5)
dat += "Upload a New Title
"
if(!scanner)
for(var/obj/machinery/libraryscanner/S in range(9))
scanner = S
break
if(!scanner)
dat += "No scanner found within wireless network range.
"
else if(!scanner.cache)
dat += "No data found in scanner memory.
"
else if(scanner.cache.ssbn && (scanner.cache.author_real != user.real_name && scanner.cache.author_key != user.client.ckey))
dat += "This book contains copy protection preventing you from re-uploading this to the database.
"
else
dat += "Data marked for [scanner.cache.ssbn ? "re-" : ""]upload...
"
dat += "Title: [scanner.cache.title]
"
if(!scanner.cache.author)
scanner.cache.author = "Anonymous"
dat += "Author: [scanner.cache.author]
"
dat += "Category: [upload_category]
"
dat += "\[Upload\]
"
dat += "(Return to main menu)
"
if(7)
dat += "Accessing Forbidden Lore Vault v 1.3
"
dat += "Are you absolutely sure you want to proceed? EldritchTomes Inc. takes no responsibilities for loss of sanity resulting from this action."
dat += "Yes.
"
dat += "No.
"
//dat += "Close
"
user << browse(dat, "window=library")
onclose(user, "library")
/obj/machinery/librarycomp/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (src.density && istype(W, /obj/item/weapon/card/emag))
src.emagged = 1
if(istype(W, /obj/item/weapon/barcodescanner))
var/obj/item/weapon/barcodescanner/scanner = W
scanner.computer = src
user << "[scanner]'s associated machine has been set to [src]."
for (var/mob/V in hearers(src))
V.show_message("[src] lets out a low, short blip.", 2)
else
..()
/obj/machinery/librarycomp/Topic(href, href_list)
if(href_list["switchscreen"])
switch(href_list["switchscreen"])
if("0")
screenstate = 0
if("1")
screenstate = 1
if("2")
screenstate = 2
if("3")
screenstate = 3
if("4")
screenstate = 4
if("5")
screenstate = 5
if("6")
if(!bibledelay)
var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(src.loc)
if(ticker && ( ticker.Bible_icon_state && ticker.Bible_item_state) )
B.icon_state = ticker.Bible_icon_state
B.item_state = ticker.Bible_item_state
B.name = ticker.Bible_name
bibledelay = 60
spawn(0)
while(bibledelay >= 1 && src)
sleep(10)
bibledelay -- // subtract one second to countdown
bibledelay = 0
else
for (var/mob/V in hearers(src))
V.show_message("[src]'s monitor flashes, \"[bibledelay] seconds remaining until the bible printer is ready for use.\"")
if("7")
screenstate = 7
if(href_list["arccheckout"])
src.arcanecheckout = 1
src.screenstate = 0
if(href_list["increasetime"])
checkoutperiod += 1
if(href_list["decreasetime"])
checkoutperiod -= 1
if(checkoutperiod < 1)
checkoutperiod = 1
if(href_list["editbook"])
buffer_book = input("Enter the book's title:") as text|null
if(href_list["editmob"])
buffer_mob = input("Enter the recipient's name:") as text|null
if(href_list["checkout"])
var/datum/borrowbook/b = new /datum/borrowbook
b.bookname = sanitize(buffer_book)
b.mobname = sanitize(buffer_mob)
b.getdate = world.time
b.duedate = world.time + (checkoutperiod * 600)
checkouts.Add(b)
if(href_list["checkin"])
var/datum/borrowbook/b = locate(href_list["checkin"])
checkouts.Remove(b)
if(href_list["delbook"])
var/obj/item/weapon/book/b = locate(href_list["delbook"])
inventory.Remove(b)
if(href_list["settitle"])
var/newtitle = input("Enter the book name: ", "Book Upload", scanner.cache.title) as text|null
if(newtitle)
scanner.cache.title = sanitize(newtitle)
scanner.cache.name = "Book: [scanner.cache.title]"
if(href_list["setauthor"])
var/newauthor = input("Enter the author's name: ", "Book Upload", scanner.cache.author) as text|null
if(newauthor)
scanner.cache.author = sanitize(newauthor)
if(href_list["setcategory"])
var/newcategory = input("Choose a category: ") in list("Fiction", "Non-Fiction", "Adult", "Reference", "Religion")
if(newcategory)
upload_category = newcategory
if(href_list["upload"])
if(scanner)
if(scanner.cache)
var/choice = input("Are you certain you wish to upload this title to the Archive?") in list("Confirm", "Abort")
if(choice == "Confirm")
if(config.sql_enabled)
var/DBConnection/dbcon = new()
dbcon.Connect("dbi:mysql:[sqldb]:[sqladdress]:[sqlport]","[sqllogin]","[sqlpass]")
if(!dbcon.IsConnected())
alert("Connection to Archive has been severed. Aborting.")
else
/*
var/sqltitle = dbcon.Quote(scanner.cache.name)
var/sqlauthor = dbcon.Quote(scanner.cache.author)
var/sqlcontent = dbcon.Quote(scanner.cache.dat)
var/sqlcategory = dbcon.Quote(upload_category)
*/
var/sqltitle = dd_replacetext(scanner.cache.name, "'", "''")
var/sqlauthor = dd_replacetext(scanner.cache.author, "'", "''")
var/sqlcontent = dd_replacetext(scanner.cache.dat, "'", "''")
var/sqlcategory = upload_category
///proc/dd_replacetext(text, search_string, replacement_string)
var/DBQuery/query = dbcon.NewQuery("INSERT INTO library (author, title, content, category) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]')")
if(!query.Execute())
usr << query.ErrorMsg()
else
log_game("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] signs")
alert("Upload Complete.")
dbcon.Disconnect()
else
var/datum/archived_book/B = new()
if(scanner.cache.title)
B.title = scanner.cache.title
else
B.title = scanner.cache.name
B.author = scanner.cache.author
B.dat = scanner.cache.dat
B.category = upload_category
if(scanner.cache.ssbn)
B.id = scanner.cache.ssbn
else
B.id = book_mgr.freeid()
B.author_real = scanner.cache.author_real
B.author_key = scanner.cache.author_key
if(scanner.cache.photos.len >= 8)
scanner.cache.photos.len = 8
B.photos = scanner.cache.photos
B.save()
log_game("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] signs")
alert("Upload Complete.")
if(href_list["targetid"])
if(config.sql_enabled)
var/sqlid = href_list["targetid"]
var/DBConnection/dbcon = new()
dbcon.Connect("dbi:mysql:[sqldb]:[sqladdress]:[sqlport]","[sqllogin]","[sqlpass]")
if(!dbcon.IsConnected())
alert("Connection to Archive has been severed. Aborting.")
else
var/DBQuery/query = dbcon.NewQuery("SELECT * FROM library WHERE id=[sqlid]")
query.Execute()
while(query.NextRow())
var/author = query.item[2]
var/title = query.item[3]
var/content = query.item[4]
var/obj/item/weapon/book/B = new(src.loc)
if(title)
B.name = "[title]"
else
B.name = "Untitled book"
B.title = title
B.author = author
B.dat = content
B.gen_pages()
B.icon_state = "book[rand(1,7)]"
src.visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?")
break
dbcon.Disconnect()
else
var/datum/archived_book/AB = new(book_mgr.path(text2num(href_list["targetid"])))
if(!AB)
alert("Book not found!")
else
var/obj/item/weapon/book/B = new(src.loc)
B.name = "Book: [AB.title]"
B.title = AB.title
B.author = AB.author
B.dat = AB.dat
B.gen_pages()
B.icon_state = "book[rand(1,7)]"
B.author_real = AB.author_real
B.author_key = AB.author_key
B.photos = AB.photos
src.visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?")
if(href_list["orderbyid"])
var/orderid = input("Enter your order:") as num|null
if(orderid)
var/nhref = "src=\ref[src];targetid=[orderid]"
spawn() src.Topic(nhref, params2list(nhref), src)
src.add_fingerprint(usr)
src.updateUsrDialog()
return
/obj/machinery/libraryscanner
name = "scanner"
icon = 'library.dmi'
icon_state = "bigscanner"
anchored = 1
density = 1
var
obj/item/weapon/book/cache // Last scanned book
/obj/machinery/libraryscanner/attackby(var/obj/O as obj, var/mob/user as mob)
if(istype(O, /obj/item/weapon/book))
user.drop_item()
O.loc = src
/obj/machinery/libraryscanner/attack_hand(var/mob/user as mob)
usr.machine = src
var/dat = "
Scanner Control Interface\n" //
if(cache)
dat += "Data stored in memory.
"
else
dat += "No data stored in memory.
"
dat += "\[Scan\]"
if(cache)
dat += " \[Clear Memory\]
\[Remove Book\]"
else
dat += "
"
user << browse(dat, "window=scanner")
onclose(user, "scanner")
/obj/machinery/libraryscanner/Topic(href, href_list)
if(href_list["scan"])
for(var/obj/item/weapon/book/B in contents)
cache = B
break
if(href_list["clear"])
cache = null
if(href_list["eject"])
for(var/obj/item/weapon/book/B in contents)
B.loc = src.loc
src.add_fingerprint(usr)
src.updateUsrDialog()
return
/obj/machinery/bookbinder
name = "Book Binder"
icon = 'library.dmi'
icon_state = "binder"
anchored = 1
density = 1
var/obj/item/weapon/book/template
var/list/icon_names
var/i_preview = 1
var/printing = 0
proc/newGenericBook()
template = new(src)
template.title = "Print Job #" + "[rand(100, 999)]"
template.author = "Anonymous"
template.name = "Book: [template.title]"
template.icon_state = "book[rand(1,7)]"
template.dat = ""
template.gen_pages()
template.photos = new()
icon_names = new()
i_preview = 1
attackby(var/obj/O as obj, var/mob/user as mob)
if(istype(O, /obj/item/weapon/paper))
user.drop_item()
O.loc = src
user.visible_message("[user] loads some paper into [src].", "You load some paper into [src].")
if(template)
template.dat += "[O:info]"
template.gen_pages()
else
template = new(src)
template.title = O.name == initial(O.name) ? "Print Job #" + "[rand(100, 999)]" : O.name
template.name = "Book: [template.title]"
template.icon_state = "book[rand(1,7)]"
template.dat = O:info
template.gen_pages()
template.photos = new()
icon_names = new()
i_preview = 1
del(O)
updateUsrDialog()
else if(istype(O, /obj/item/weapon/photo))
user.drop_item()
O.loc = src
user.visible_message("[user] loads a photo into [src].", "You load a photo into [src].")
if(!template)
newGenericBook()
if(template.photos.len >= 8)
user << "\red The photo tray is already full!"
O.loc = src.loc
return
var/icon/imported = new(O.icon)
imported.Crop(6,8,27,27)
imported.Scale(32,32)
template.photos += imported
icon_names += O.name
del(O)
updateUsrDialog()
else if(istype(O, /obj/item/weapon/book))
if(template)
user << "\red The binder already has a book in the buffer!"
return
user.drop_item()
O.loc = src
user.visible_message("[user] loads a book into [src] for editing.", "You load a book into [src] for editing.")
var/obj/machinery/librarycomp/C = locate() in loc.loc
if(C)
if(C.inventory.Find(O))
C.inventory -= O
template = O
icon_names = new()
for(var/i = 1 to template.photos.len)
icon_names += "Photo [i]"
updateUsrDialog()
else
..()
/obj/machinery/bookbinder/attack_paw(user as mob)
return src.attack_hand(user)
/obj/machinery/bookbinder/attack_ai(user as mob)
return src.attack_hand(user)
/obj/machinery/bookbinder/attack_hand(user as mob)
if(..())
return
if(src.stat)
user << "[name] does not seem to be responding to your button mashing."
return
var/dat = "Book BinderNT Publishing House
"
if(printing)
dat += "[src] is currently printing."
else
// general settings
dat += "New Book"
if(template)
template.cache_imgs(user)
dat += " Delete Book
"
dat += "Title: [template.title]
"
dat += "Author: [template.author]
"
// articles
dat += "Pages:"
var/ID = 1
for(var/P in template.pages)
dat += "- Page [ID]"
dat += " Preview"
dat += " Delete
"
ID++
dat += "
New Page
"
// images
dat += "Images:"
ID = 1
for(var/icon/I in template.photos)
dat += "- [ID]: [icon_names[ID]]"
dat += " Delete"
ID++
dat += "
"
if(i_preview >= 1 && i_preview <= template.photos.len)
var/iconname = "book_preview.png"
user << browse_rsc(template.photos[i_preview],iconname)
dat += "[i_preview] ([icon_names[i_preview]]):
"
dat += "
Print"
dat += ""
user << browse(dat, "window=bookbinder")
onclose(user, "bookbinder")
/obj/machinery/bookbinder/Topic(href, href_list)
if(..())
return
usr.machine = src
src.add_fingerprint(usr)
if(href_list["new"])
if(template)
var/R = alert("There is already a book in the buffer. Do you want to delete it and start over?", "Book Binder", "Delete", "Cancel")
if(R == "Cancel")
return
del(template)
newGenericBook()
updateUsrDialog()
if(href_list["delete"])
if(template)
del(template)
updateUsrDialog()
if(href_list["print"])
printing = 1
updateUsrDialog()
src.visible_message("[src] begins to hum as it warms up its printing drums.")
sleep(rand(50,100))
src.visible_message("[src] whirs as it prints and binds a new book.")
if(!template.ssbn)
template.author_real = usr.real_name
if(usr.client)
template.author_key = usr.client.ckey
template.loc = src.loc
template = null
printing = 0
updateUsrDialog()
if(href_list["p_new"])
template.dat += ""
template.gen_pages()
updateUsrDialog()
if(href_list["title"])
var/n_name = input(usr, "What would you like to title your book?", "Book Binder", template.title) as text|null
if(n_name)
template.title = sanitize(n_name)
template.name = "Book: [template.title]"
updateUsrDialog()
if(href_list["author"])
var/n_name = input(usr, "Who would you like your pen name to be?", "Book Binder", template.author) as text|null
if(n_name)
template.author = sanitize(n_name)
updateUsrDialog()
if(href_list["p_edit"])
var/PN = text2num(href_list["p_edit"])
var/list/pages = dd_text2list(template.dat, "")
var/t = pages[PN]
do
t = input(usr, "What text do you wish to add?", "Book Binder P.[PN]", t) as message
if(lentext(t) >= MAX_BOOK_MESSAGE_LEN)
var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no")
if(cont == "no")
break
while(lentext(t) > MAX_BOOK_MESSAGE_LEN)
// check for exploits
for(var/tag in paper_blacklist)
if(findtext(t,"<"+tag))
usr << "\blue You think to yourself, \"Hm.. this is only paper...\""
return
// the actual pages list is formatted and shouldn't be directly editted
pages[PN] = t
template.dat = dd_list2text(pages, "")
template.gen_pages()
updateUsrDialog()
if(href_list["p_delete"])
var/i = text2num(href_list["p_delete"])
var/list/pages = dd_text2list(template.dat, "")
pages.Cut(i, i+1)
template.dat = dd_list2text(pages, "")
template.gen_pages()
updateUsrDialog()
if(href_list["p_preview"])
var/i = text2num(href_list["p_preview"])
var/dat = template.pages[i]
usr << browse(dat, "window=bookbinder_preview;size=600x500")
onclose(usr, "bookbinder_preview")
if(href_list["i_view"])
i_preview = text2num(href_list["i_view"])
updateUsrDialog()
if(href_list["i_delete"])
var/i = text2num(href_list["i_delete"])
template.photos.Cut(i, i+1)
icon_names.Cut(i, i+1)
updateUsrDialog()