diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm
index f3701945017..1b7ca14f941 100644
--- a/code/game/machinery/PDApainter.dm
+++ b/code/game/machinery/PDApainter.dm
@@ -1,102 +1,105 @@
-/obj/machinery/pdapainter
- name = "PDA painter"
- desc = "A PDA painting machine. To use, simply insert your PDA and choose the desired preset paint scheme."
- icon = 'icons/obj/pda.dmi'
- icon_state = "pdapainter"
- density = 1
- anchored = 1
- var/obj/item/pda/storedpda = null
- var/list/colorlist = list()
-
-
-/obj/machinery/pdapainter/update_icon()
- overlays.Cut()
-
- if(stat & BROKEN)
- icon_state = "[initial(icon_state)]-broken"
- return
-
- if(storedpda)
- overlays += "[initial(icon_state)]-closed"
-
- if(powered())
- icon_state = initial(icon_state)
- else
- icon_state = "[initial(icon_state)]-off"
-
- return
-
-/obj/machinery/pdapainter/New()
- ..()
- var/blocked = list(/obj/item/pda/silicon/ai, /obj/item/pda/silicon/robot, /obj/item/pda/silicon/pai, /obj/item/pda/heads,
- /obj/item/pda/clear, /obj/item/pda/syndicate)
-
- for(var/P in typesof(/obj/item/pda)-blocked)
- var/obj/item/pda/D = new P
-
- //D.name = "PDA Style [colorlist.len+1]" //Gotta set the name, otherwise it all comes up as "PDA"
- D.name = D.icon_state //PDAs don't have unique names, but using the sprite names works.
-
- src.colorlist += D
-
-/obj/machinery/pdapainter/Destroy()
- QDEL_NULL(storedpda)
- return ..()
-
-/obj/machinery/pdapainter/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/pda))
- if(storedpda)
- to_chat(user, "There is already a PDA inside.")
- return
- else
- var/obj/item/pda/P = user.get_active_hand()
- if(istype(P))
- if(user.drop_item())
- storedpda = P
- P.forceMove(src)
- P.add_fingerprint(user)
- update_icon()
- else
- return ..()
-
-
-/obj/machinery/pdapainter/attack_hand(mob/user as mob)
- if(..())
- return 1
-
- src.add_fingerprint(user)
-
- if(storedpda)
- var/obj/item/pda/P
- P = input(user, "Select your color!", "PDA Painting") as null|anything in colorlist
- if(!P)
- return
- if(!in_range(src, user))
- return
-
- storedpda.icon_state = P.icon_state
- storedpda.desc = P.desc
-
- else
- to_chat(user, "The [src] is empty.")
-
-
-/obj/machinery/pdapainter/verb/ejectpda()
- set name = "Eject PDA"
- set category = "Object"
- set src in oview(1)
-
- if(usr.incapacitated())
- return
-
- if(storedpda)
- storedpda.loc = get_turf(src.loc)
- storedpda = null
- update_icon()
- else
- to_chat(usr, "The [src] is empty.")
-
-
-/obj/machinery/pdapainter/power_change()
- ..()
+/obj/machinery/pdapainter
+ name = "PDA painter"
+ desc = "A PDA painting machine. To use, simply insert your PDA and choose the desired preset paint scheme."
+ icon = 'icons/obj/pda.dmi'
+ icon_state = "pdapainter"
+ density = 1
+ anchored = 1
+ var/obj/item/pda/storedpda = null
+ var/list/colorlist = list()
+
+
+/obj/machinery/pdapainter/update_icon()
+ overlays.Cut()
+
+ if(stat & BROKEN)
+ icon_state = "[initial(icon_state)]-broken"
+ return
+
+ if(storedpda)
+ overlays += "[initial(icon_state)]-closed"
+
+ if(powered())
+ icon_state = initial(icon_state)
+ else
+ icon_state = "[initial(icon_state)]-off"
+
+ return
+
+/obj/machinery/pdapainter/New()
+ ..()
+ var/blocked = list(/obj/item/pda/silicon/ai, /obj/item/pda/silicon/robot, /obj/item/pda/silicon/pai, /obj/item/pda/heads,
+ /obj/item/pda/clear, /obj/item/pda/syndicate)
+
+ for(var/P in typesof(/obj/item/pda)-blocked)
+ var/obj/item/pda/D = new P
+
+ //D.name = "PDA Style [colorlist.len+1]" //Gotta set the name, otherwise it all comes up as "PDA"
+ D.name = D.icon_state //PDAs don't have unique names, but using the sprite names works.
+
+ src.colorlist += D
+
+/obj/machinery/pdapainter/Destroy()
+ QDEL_NULL(storedpda)
+ return ..()
+
+/obj/machinery/pdapainter/attackby(obj/item/I, mob/user, params)
+ if(default_unfasten_wrench(user, I))
+ power_change()
+ return
+ if(istype(I, /obj/item/pda))
+ if(storedpda)
+ to_chat(user, "There is already a PDA inside.")
+ return
+ else
+ var/obj/item/pda/P = user.get_active_hand()
+ if(istype(P))
+ if(user.drop_item())
+ storedpda = P
+ P.forceMove(src)
+ P.add_fingerprint(user)
+ update_icon()
+ else
+ return ..()
+
+
+/obj/machinery/pdapainter/attack_hand(mob/user as mob)
+ if(..())
+ return 1
+
+ src.add_fingerprint(user)
+
+ if(storedpda)
+ var/obj/item/pda/P
+ P = input(user, "Select your color!", "PDA Painting") as null|anything in colorlist
+ if(!P)
+ return
+ if(!in_range(src, user))
+ return
+
+ storedpda.icon_state = P.icon_state
+ storedpda.desc = P.desc
+
+ else
+ to_chat(user, "The [src] is empty.")
+
+
+/obj/machinery/pdapainter/verb/ejectpda()
+ set name = "Eject PDA"
+ set category = "Object"
+ set src in oview(1)
+
+ if(usr.incapacitated())
+ return
+
+ if(storedpda)
+ storedpda.loc = get_turf(src.loc)
+ storedpda = null
+ update_icon()
+ else
+ to_chat(usr, "The [src] is empty.")
+
+
+/obj/machinery/pdapainter/power_change()
+ ..()
update_icon()
\ No newline at end of file
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 876923f5c28..af067f60688 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -199,6 +199,9 @@
/*if(istype(W,/obj/item/screwdriver))
panel = !panel
to_chat(user, "you [panel ? "open" : "close"] the [src]'s maintenance panel")*/
+ if(default_unfasten_wrench(user, W))
+ power_change()
+ return
if(istype(W,/obj/item/toy/crayon) ||istype(W,/obj/item/stamp))
if( state in list( 1, 3, 6 ) )
if(!crayon)
diff --git a/code/modules/library/computers/checkout.dm b/code/modules/library/computers/checkout.dm
index fdcfee0e87a..10e747b4e31 100644
--- a/code/modules/library/computers/checkout.dm
+++ b/code/modules/library/computers/checkout.dm
@@ -1,462 +1,465 @@
-/*
- * Library Computer
- */
-/obj/machinery/computer/library/checkout
- name = "Check-In/Out Computer"
- icon = 'icons/obj/library.dmi'
- icon_state = "computer"
- anchored = 1
- density = 1
- var/arcanecheckout = 0
- //var/screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book
- var/buffer_book
- var/buffer_mob
- var/upload_category = "Fiction"
- var/list/checkouts = list()
- var/list/inventory = list()
- var/checkoutperiod = 5 // In minutes
- var/obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive
-
- var/bibledelay = 0 // LOL NO SPAM (1 minute delay) -- Doohl
- var/booklist
-
-/obj/machinery/computer/library/checkout/attack_hand(var/mob/user as mob)
- if(..())
- return
- interact(user)
-
-/obj/machinery/computer/library/checkout/interact(var/mob/user)
- if(interact_check(user))
- return
-
- var/dat = ""
- switch(screenstate)
- if(0)
- // Main Menu
-
- dat += {"
- - View General Inventory
- - View Checked Out Inventory
- - Check out a Book
- - Connect to External Archive
- - Upload New Title to Archive
- - Print a Bible
- - Print a Manual
"}
- if(src.emagged)
- dat += "- Access the Forbidden Lore Vault
"
- dat += "
"
-
- if(src.arcanecheckout)
- new /obj/item/tome(src.loc)
- to_chat(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.")
- user.visible_message("[user] stares at the blank screen for a few moments, [user.p_their()] expression frozen in fear. When [user.p_they()] finally awaken[user.p_s()] from it, [user.p_they()] look[user.p_s()] a lot older.", 2)
- src.arcanecheckout = 0
- if(1)
- // Inventory
- dat += "Inventory
"
- for(var/obj/item/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
- (Check In)
"}
- dat += "(Return to main menu)
"
- if(3)
- // Check Out a Book
-
- dat += {"Check Out a Book
- Book: [src.buffer_book]
- \[Edit\]
- Recipient: [src.buffer_mob]
- \[Edit\]
- Checkout Date : [world.time/600]
- Due Date: [(world.time + checkoutperiod)/600]
- (Checkout Period: [checkoutperiod] minutes) (+/-)
- (Commit Entry)
- (Return to main menu)
"}
- if(4)
- dat += "External Archive
"
- if(!dbcon.IsConnected())
- dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance."
- else
- num_results = src.get_num_results()
- num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
- dat += {""}
- var/pagelist = get_pagelist()
-
- dat += {"Search Settings
- Filter by Title: [query.title]
- Filter by Category: [query.category]
- Filter by Author: [query.author]
- \[Start Search\]
"}
- dat += pagelist
-
- dat += {""}
-
- dat += {"
-
- | Author |
- Title |
- Category |
- Controls |
-
"}
-
- for(var/datum/cachedbook/CB in get_page(page_num))
- var/author = CB.author
- var/controls = "\[Order\]"
- controls += {" \[Flag[CB.flagged ? "ged" : ""]\]"}
- if(check_rights(R_ADMIN, 0, user = user))
- controls += " \[Delete\]"
- author += " ([ckey(CB.ckey)]))"
- dat += {"
- | [author] |
- [CB.title] |
- [CB.category] |
- [controls] |
-
"}
-
- dat += "
[pagelist]"
-
- 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
-
- dat += {"Data marked for upload...
- Title: [scanner.cache.name]
"}
- if(!scanner.cache.author)
- scanner.cache.author = "Anonymous"
-
- dat += {"Author: [scanner.cache.author]
- Category: [upload_category]
- \[Upload\]
"}
- dat += "(Return to main menu)
"
- if(7)
- dat += "Print a Manual
"
- dat += ""
-
- var/list/forbidden = list(
- /obj/item/book/manual
- )
-
- if(!emagged)
- forbidden |= /obj/item/book/manual/nuclear
-
- var/manualcount = 1
- var/obj/item/book/manual/M = null
-
- for(var/manual_type in (typesof(/obj/item/book/manual) - forbidden))
- M = new manual_type()
- dat += "| [M.title] |
"
- manualcount++
- QDEL_NULL(M)
- dat += "
"
- dat += "
(Return to main menu)
"
-
- if(8)
-
- dat += {"Accessing Forbidden Lore Vault v 1.3
- Are you absolutely sure you want to proceed? EldritchTomes Inc. takes no responsibilities for loss of sanity resulting from this action.
- Yes.
- No.
"}
-
- var/datum/browser/B = new /datum/browser(user, "library", "Book Inventory Management")
- B.set_content(dat)
- B.open()
-
-/obj/machinery/computer/library/checkout/emag_act(mob/user)
- if(density && !emagged)
- emagged = 1
- to_chat(user, "You override the library computer's printing restrictions.")
-
-/obj/machinery/computer/library/checkout/attackby(obj/item/W as obj, mob/user as mob)
- if(istype(W, /obj/item/barcodescanner))
- var/obj/item/barcodescanner/scanner = W
- scanner.computer = src
- to_chat(user, "[scanner]'s associated machine has been set to [src].")
- audible_message("[src] lets out a low, short blip.", 2)
- return 1
- else
- return ..()
-
-/obj/machinery/computer/library/checkout/Topic(href, href_list)
- if(..())
- usr << browse(null, "window=library")
- onclose(usr, "library")
- return 1
-
- if(href_list["pagenum"])
- if(!num_pages)
- page_num = 1
- else
- var/pn = text2num(href_list["pagenum"])
- if(!isnull(pn))
- page_num = Clamp(pn, 1, num_pages)
-
- if(href_list["page"])
- if(num_pages == 0)
- page_num = 1
- else
- page_num = Clamp(text2num(href_list["page"]), 1, num_pages)
- if(href_list["settitle"])
- var/newtitle = input("Enter a title to search for:") as text|null
- if(newtitle)
- query.title = sanitize(newtitle)
- else
- query.title = null
- if(href_list["setcategory"])
- var/newcategory = input("Choose a category to search for:") in (list("Any") + library_section_names)
- if(newcategory == "Any")
- query.category = null
- else if(newcategory)
- query.category = sanitize(newcategory)
- if(href_list["setauthor"])
- var/newauthor = input("Enter an author to search for:") as text|null
- if(newauthor)
- query.author = sanitize(newauthor)
- else
- query.author = null
-
- if(href_list["search"])
- num_results = src.get_num_results()
- num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
- page_num = 1
-
- screenstate = 4
- if(href_list["del"])
- if(!check_rights(R_ADMIN))
- return
- var/datum/cachedbook/target = getBookByID(href_list["del"]) // Sanitized in getBookByID
- var/ans = alert(usr, "Are you sure you wish to delete \"[target.title]\", by [target.author]? This cannot be undone.", "Library System", "Yes", "No")
- if(ans=="Yes")
- var/DBQuery/query = dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[target.id]")
- var/response = query.Execute()
- if(!response)
- to_chat(usr, query.ErrorMsg())
- return
- log_admin("LIBRARY: [key_name(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!")
- message_admins("[key_name_admin(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!")
- src.updateUsrDialog()
- return
-
- if(href_list["delbyckey"])
- if(!check_rights(R_ADMIN))
- return
- var/tckey = ckey(href_list["delbyckey"])
- var/ans = alert(usr,"Are you sure you wish to delete all books by [tckey]? This cannot be undone.", "Library System", "Yes", "No")
- if(ans=="Yes")
- var/DBQuery/query = dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE ckey='[sanitizeSQL(tckey)]'")
- var/response = query.Execute()
- if(!response)
- to_chat(usr, query.ErrorMsg())
- return
- var/affected=query.RowsAffected()
- if(affected==0)
- to_chat(usr, "Unable to find any matching rows.")
- return
- log_admin("LIBRARY: [key_name(usr)] has deleted [affected] books written by [tckey]!")
- message_admins("[key_name_admin(usr)] has deleted [affected] books written by [tckey]!")
- src.updateUsrDialog()
- return
-
- if(href_list["flag"])
- if(!dbcon.IsConnected())
- alert("Connection to Archive has been severed. Aborting.")
- return
- var/id = href_list["flag"]
- if(id)
- var/datum/cachedbook/B = getBookByID(id)
- if(B)
- if((input(usr, "Are you sure you want to flag [B.title] as having inappropriate content?", "Flag Book #[B.id]") in list("Yes", "No")) == "Yes")
- library_catalog.flag_book_by_id(usr, id)
-
- 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/storage/bible/B = new /obj/item/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
- B.deity_name = ticker.Bible_deity_name
-
- bibledelay = 1
- spawn(60)
- bibledelay = 0
-
- else
- visible_message("[src]'s monitor flashes, \"Bible printer currently unavailable, please wait a moment.\"")
-
- if("7")
- screenstate = 7
- if("8")
- screenstate = 8
- if(href_list["arccheckout"])
- if(src.emagged)
- 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 = copytext(sanitize(input("Enter the book's title:") as text|null),1,MAX_MESSAGE_LEN)
- if(href_list["editmob"])
- buffer_mob = copytext(sanitize(input("Enter the recipient's name:") as text|null),1,MAX_NAME_LEN)
- 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/book/b = locate(href_list["delbook"])
- inventory.Remove(b)
- if(href_list["uploadauthor"])
- var/newauthor = copytext(sanitize(input("Enter the author's name: ") as text|null),1,MAX_MESSAGE_LEN)
- if(newauthor && scanner)
- scanner.cache.author = newauthor
- if(href_list["uploadcategory"])
- 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")
- establish_db_connection()
- if(!dbcon.IsConnected())
- alert("Connection to Archive has been severed. Aborting.")
- else
- var/sqltitle = sanitizeSQL(scanner.cache.name)
- var/sqlauthor = sanitizeSQL(scanner.cache.author)
- var/sqlcontent = sanitizeSQL(scanner.cache.dat)
- var/sqlcategory = sanitizeSQL(upload_category)
- var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, flagged) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[ckey(usr.key)]', 0)")
- var/response = query.Execute()
- if(!response)
- to_chat(usr, query.ErrorMsg())
- else
- log_admin("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] characters in length")
- message_admins("[key_name_admin(usr)] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] characters in length")
-
- if(href_list["id"])
- if(href_list["id"]=="-1")
- href_list["id"] = input("Enter your order:") as null|num
- if(!href_list["id"])
- return
-
- if(!dbcon.IsConnected())
- alert("Connection to Archive has been severed. Aborting.")
- return
-
- var/datum/cachedbook/newbook = getBookByID(href_list["id"]) // Sanitized in getBookByID
- if(!newbook)
- alert("No book found")
- return
- if((newbook.forbidden == 2 && !emagged) || newbook.forbidden == 1)
- alert("This book is forbidden and cannot be printed.")
- return
-
- if(bibledelay)
- audible_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
- else
- bibledelay = 1
- spawn(60)
- bibledelay = 0
- make_external_book(newbook)
- if(href_list["manual"])
- if(!href_list["manual"]) return
- var/bookid = href_list["manual"]
-
- if(!dbcon.IsConnected())
- alert("Connection to Archive has been severed. Aborting.")
- return
-
- var/datum/cachedbook/newbook = getBookByID("M[bookid]")
- if(!newbook)
- alert("No book found")
- return
- if((newbook.forbidden == 2 && !emagged) || newbook.forbidden == 1)
- alert("This book is forbidden and cannot be printed.")
- return
-
- if(bibledelay)
- for(var/mob/V in hearers(src))
- V.show_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
- else
- bibledelay = 1
- spawn(60)
- bibledelay = 0
- make_external_book(newbook)
-
- src.add_fingerprint(usr)
- src.updateUsrDialog()
- return
-
-/*
- * Library Scanner
- */
-
-/obj/machinery/computer/library/checkout/proc/make_external_book(var/datum/cachedbook/newbook)
- if(!newbook || !newbook.id)
- return
- var/obj/item/book/B = new newbook.path(loc)
-
- if(!newbook.programmatic)
- B.name = "Book: [newbook.title]"
- B.title = newbook.title
- B.author = newbook.author
- B.dat = newbook.content
- B.icon_state = "book[rand(1,16)]"
- visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?")
+/*
+ * Library Computer
+ */
+/obj/machinery/computer/library/checkout
+ name = "Check-In/Out Computer"
+ icon = 'icons/obj/library.dmi'
+ icon_state = "computer"
+ anchored = 1
+ density = 1
+ var/arcanecheckout = 0
+ //var/screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book
+ var/buffer_book
+ var/buffer_mob
+ var/upload_category = "Fiction"
+ var/list/checkouts = list()
+ var/list/inventory = list()
+ var/checkoutperiod = 5 // In minutes
+ var/obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive
+
+ var/bibledelay = 0 // LOL NO SPAM (1 minute delay) -- Doohl
+ var/booklist
+
+/obj/machinery/computer/library/checkout/attack_hand(var/mob/user as mob)
+ if(..())
+ return
+ interact(user)
+
+/obj/machinery/computer/library/checkout/interact(var/mob/user)
+ if(interact_check(user))
+ return
+
+ var/dat = ""
+ switch(screenstate)
+ if(0)
+ // Main Menu
+
+ dat += {"
+ - View General Inventory
+ - View Checked Out Inventory
+ - Check out a Book
+ - Connect to External Archive
+ - Upload New Title to Archive
+ - Print a Bible
+ - Print a Manual
"}
+ if(src.emagged)
+ dat += "- Access the Forbidden Lore Vault
"
+ dat += "
"
+
+ if(src.arcanecheckout)
+ new /obj/item/tome(src.loc)
+ to_chat(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.")
+ user.visible_message("[user] stares at the blank screen for a few moments, [user.p_their()] expression frozen in fear. When [user.p_they()] finally awaken[user.p_s()] from it, [user.p_they()] look[user.p_s()] a lot older.", 2)
+ src.arcanecheckout = 0
+ if(1)
+ // Inventory
+ dat += "Inventory
"
+ for(var/obj/item/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
+ (Check In)
"}
+ dat += "(Return to main menu)
"
+ if(3)
+ // Check Out a Book
+
+ dat += {"Check Out a Book
+ Book: [src.buffer_book]
+ \[Edit\]
+ Recipient: [src.buffer_mob]
+ \[Edit\]
+ Checkout Date : [world.time/600]
+ Due Date: [(world.time + checkoutperiod)/600]
+ (Checkout Period: [checkoutperiod] minutes) (+/-)
+ (Commit Entry)
+ (Return to main menu)
"}
+ if(4)
+ dat += "External Archive
"
+ if(!dbcon.IsConnected())
+ dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance."
+ else
+ num_results = src.get_num_results()
+ num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
+ dat += {""}
+ var/pagelist = get_pagelist()
+
+ dat += {"Search Settings
+ Filter by Title: [query.title]
+ Filter by Category: [query.category]
+ Filter by Author: [query.author]
+ \[Start Search\]
"}
+ dat += pagelist
+
+ dat += {""}
+
+ dat += {"
+
+ | Author |
+ Title |
+ Category |
+ Controls |
+
"}
+
+ for(var/datum/cachedbook/CB in get_page(page_num))
+ var/author = CB.author
+ var/controls = "\[Order\]"
+ controls += {" \[Flag[CB.flagged ? "ged" : ""]\]"}
+ if(check_rights(R_ADMIN, 0, user = user))
+ controls += " \[Delete\]"
+ author += " ([ckey(CB.ckey)]))"
+ dat += {"
+ | [author] |
+ [CB.title] |
+ [CB.category] |
+ [controls] |
+
"}
+
+ dat += "
[pagelist]"
+
+ 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
+
+ dat += {"Data marked for upload...
+ Title: [scanner.cache.name]
"}
+ if(!scanner.cache.author)
+ scanner.cache.author = "Anonymous"
+
+ dat += {"Author: [scanner.cache.author]
+ Category: [upload_category]
+ \[Upload\]
"}
+ dat += "(Return to main menu)
"
+ if(7)
+ dat += "Print a Manual
"
+ dat += ""
+
+ var/list/forbidden = list(
+ /obj/item/book/manual
+ )
+
+ if(!emagged)
+ forbidden |= /obj/item/book/manual/nuclear
+
+ var/manualcount = 1
+ var/obj/item/book/manual/M = null
+
+ for(var/manual_type in (typesof(/obj/item/book/manual) - forbidden))
+ M = new manual_type()
+ dat += "| [M.title] |
"
+ manualcount++
+ QDEL_NULL(M)
+ dat += "
"
+ dat += "
(Return to main menu)
"
+
+ if(8)
+
+ dat += {"Accessing Forbidden Lore Vault v 1.3
+ Are you absolutely sure you want to proceed? EldritchTomes Inc. takes no responsibilities for loss of sanity resulting from this action.
+ Yes.
+ No.
"}
+
+ var/datum/browser/B = new /datum/browser(user, "library", "Book Inventory Management")
+ B.set_content(dat)
+ B.open()
+
+/obj/machinery/computer/library/checkout/emag_act(mob/user)
+ if(density && !emagged)
+ emagged = 1
+ to_chat(user, "You override the library computer's printing restrictions.")
+
+/obj/machinery/computer/library/checkout/attackby(obj/item/W as obj, mob/user as mob)
+ if(default_unfasten_wrench(user, W))
+ power_change()
+ return
+ if(istype(W, /obj/item/barcodescanner))
+ var/obj/item/barcodescanner/scanner = W
+ scanner.computer = src
+ to_chat(user, "[scanner]'s associated machine has been set to [src].")
+ audible_message("[src] lets out a low, short blip.", 2)
+ return 1
+ else
+ return ..()
+
+/obj/machinery/computer/library/checkout/Topic(href, href_list)
+ if(..())
+ usr << browse(null, "window=library")
+ onclose(usr, "library")
+ return 1
+
+ if(href_list["pagenum"])
+ if(!num_pages)
+ page_num = 1
+ else
+ var/pn = text2num(href_list["pagenum"])
+ if(!isnull(pn))
+ page_num = Clamp(pn, 1, num_pages)
+
+ if(href_list["page"])
+ if(num_pages == 0)
+ page_num = 1
+ else
+ page_num = Clamp(text2num(href_list["page"]), 1, num_pages)
+ if(href_list["settitle"])
+ var/newtitle = input("Enter a title to search for:") as text|null
+ if(newtitle)
+ query.title = sanitize(newtitle)
+ else
+ query.title = null
+ if(href_list["setcategory"])
+ var/newcategory = input("Choose a category to search for:") in (list("Any") + library_section_names)
+ if(newcategory == "Any")
+ query.category = null
+ else if(newcategory)
+ query.category = sanitize(newcategory)
+ if(href_list["setauthor"])
+ var/newauthor = input("Enter an author to search for:") as text|null
+ if(newauthor)
+ query.author = sanitize(newauthor)
+ else
+ query.author = null
+
+ if(href_list["search"])
+ num_results = src.get_num_results()
+ num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
+ page_num = 1
+
+ screenstate = 4
+ if(href_list["del"])
+ if(!check_rights(R_ADMIN))
+ return
+ var/datum/cachedbook/target = getBookByID(href_list["del"]) // Sanitized in getBookByID
+ var/ans = alert(usr, "Are you sure you wish to delete \"[target.title]\", by [target.author]? This cannot be undone.", "Library System", "Yes", "No")
+ if(ans=="Yes")
+ var/DBQuery/query = dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[target.id]")
+ var/response = query.Execute()
+ if(!response)
+ to_chat(usr, query.ErrorMsg())
+ return
+ log_admin("LIBRARY: [key_name(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!")
+ message_admins("[key_name_admin(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!")
+ src.updateUsrDialog()
+ return
+
+ if(href_list["delbyckey"])
+ if(!check_rights(R_ADMIN))
+ return
+ var/tckey = ckey(href_list["delbyckey"])
+ var/ans = alert(usr,"Are you sure you wish to delete all books by [tckey]? This cannot be undone.", "Library System", "Yes", "No")
+ if(ans=="Yes")
+ var/DBQuery/query = dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE ckey='[sanitizeSQL(tckey)]'")
+ var/response = query.Execute()
+ if(!response)
+ to_chat(usr, query.ErrorMsg())
+ return
+ var/affected=query.RowsAffected()
+ if(affected==0)
+ to_chat(usr, "Unable to find any matching rows.")
+ return
+ log_admin("LIBRARY: [key_name(usr)] has deleted [affected] books written by [tckey]!")
+ message_admins("[key_name_admin(usr)] has deleted [affected] books written by [tckey]!")
+ src.updateUsrDialog()
+ return
+
+ if(href_list["flag"])
+ if(!dbcon.IsConnected())
+ alert("Connection to Archive has been severed. Aborting.")
+ return
+ var/id = href_list["flag"]
+ if(id)
+ var/datum/cachedbook/B = getBookByID(id)
+ if(B)
+ if((input(usr, "Are you sure you want to flag [B.title] as having inappropriate content?", "Flag Book #[B.id]") in list("Yes", "No")) == "Yes")
+ library_catalog.flag_book_by_id(usr, id)
+
+ 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/storage/bible/B = new /obj/item/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
+ B.deity_name = ticker.Bible_deity_name
+
+ bibledelay = 1
+ spawn(60)
+ bibledelay = 0
+
+ else
+ visible_message("[src]'s monitor flashes, \"Bible printer currently unavailable, please wait a moment.\"")
+
+ if("7")
+ screenstate = 7
+ if("8")
+ screenstate = 8
+ if(href_list["arccheckout"])
+ if(src.emagged)
+ 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 = copytext(sanitize(input("Enter the book's title:") as text|null),1,MAX_MESSAGE_LEN)
+ if(href_list["editmob"])
+ buffer_mob = copytext(sanitize(input("Enter the recipient's name:") as text|null),1,MAX_NAME_LEN)
+ 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/book/b = locate(href_list["delbook"])
+ inventory.Remove(b)
+ if(href_list["uploadauthor"])
+ var/newauthor = copytext(sanitize(input("Enter the author's name: ") as text|null),1,MAX_MESSAGE_LEN)
+ if(newauthor && scanner)
+ scanner.cache.author = newauthor
+ if(href_list["uploadcategory"])
+ 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")
+ establish_db_connection()
+ if(!dbcon.IsConnected())
+ alert("Connection to Archive has been severed. Aborting.")
+ else
+ var/sqltitle = sanitizeSQL(scanner.cache.name)
+ var/sqlauthor = sanitizeSQL(scanner.cache.author)
+ var/sqlcontent = sanitizeSQL(scanner.cache.dat)
+ var/sqlcategory = sanitizeSQL(upload_category)
+ var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, flagged) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[ckey(usr.key)]', 0)")
+ var/response = query.Execute()
+ if(!response)
+ to_chat(usr, query.ErrorMsg())
+ else
+ log_admin("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] characters in length")
+ message_admins("[key_name_admin(usr)] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] characters in length")
+
+ if(href_list["id"])
+ if(href_list["id"]=="-1")
+ href_list["id"] = input("Enter your order:") as null|num
+ if(!href_list["id"])
+ return
+
+ if(!dbcon.IsConnected())
+ alert("Connection to Archive has been severed. Aborting.")
+ return
+
+ var/datum/cachedbook/newbook = getBookByID(href_list["id"]) // Sanitized in getBookByID
+ if(!newbook)
+ alert("No book found")
+ return
+ if((newbook.forbidden == 2 && !emagged) || newbook.forbidden == 1)
+ alert("This book is forbidden and cannot be printed.")
+ return
+
+ if(bibledelay)
+ audible_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
+ else
+ bibledelay = 1
+ spawn(60)
+ bibledelay = 0
+ make_external_book(newbook)
+ if(href_list["manual"])
+ if(!href_list["manual"]) return
+ var/bookid = href_list["manual"]
+
+ if(!dbcon.IsConnected())
+ alert("Connection to Archive has been severed. Aborting.")
+ return
+
+ var/datum/cachedbook/newbook = getBookByID("M[bookid]")
+ if(!newbook)
+ alert("No book found")
+ return
+ if((newbook.forbidden == 2 && !emagged) || newbook.forbidden == 1)
+ alert("This book is forbidden and cannot be printed.")
+ return
+
+ if(bibledelay)
+ for(var/mob/V in hearers(src))
+ V.show_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
+ else
+ bibledelay = 1
+ spawn(60)
+ bibledelay = 0
+ make_external_book(newbook)
+
+ src.add_fingerprint(usr)
+ src.updateUsrDialog()
+ return
+
+/*
+ * Library Scanner
+ */
+
+/obj/machinery/computer/library/checkout/proc/make_external_book(var/datum/cachedbook/newbook)
+ if(!newbook || !newbook.id)
+ return
+ var/obj/item/book/B = new newbook.path(loc)
+
+ if(!newbook.programmatic)
+ B.name = "Book: [newbook.title]"
+ B.title = newbook.title
+ B.author = newbook.author
+ B.dat = newbook.content
+ B.icon_state = "book[rand(1,16)]"
+ visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?")
diff --git a/code/modules/library/computers/public.dm b/code/modules/library/computers/public.dm
index 4e0decd4459..c0f61d26eff 100644
--- a/code/modules/library/computers/public.dm
+++ b/code/modules/library/computers/public.dm
@@ -1,122 +1,127 @@
-/obj/machinery/computer/library/public
- name = "visitor computer"
-
-/obj/machinery/computer/library/public/attack_hand(var/mob/user as mob)
- if(..())
- return
- interact(user)
-
-/obj/machinery/computer/library/public/interact(var/mob/user)
- if(interact_check(user))
- return
-
- var/dat = ""
- switch(screenstate)
- if(0)
-
- dat += {"
Search Settings
- Filter by Title: [query.title]
- Filter by Category: [query.category]
- Filter by Author: [query.author]
- \[Start Search\]
"}
- if(1)
- establish_db_connection()
- if(!dbcon.IsConnected())
- dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance.
"
- else if(num_results == 0)
- dat += "No results found."
- else
- var/pagelist = get_pagelist()
-
- dat += pagelist
- dat += {""}
- dat += {"
-
- | Author |
- Title |
- Category |
- SS13BN |
- Controls |
-
"}
- for(var/datum/cachedbook/CB in get_page(page_num))
- dat += {"
- | [CB.author] |
- [CB.title] |
- [CB.category] |
- [CB.id] |
- \[Flag[CB.flagged ? "ged" : ""]\] |
-
"}
-
- dat += "
[pagelist]"
- dat += "\[Go Back\]
"
- var/datum/browser/B = new /datum/browser(user, "library", "Library Visitor")
- B.set_content(dat)
- B.open()
-
-/obj/machinery/computer/library/public/Topic(href, href_list)
- if(..())
- usr << browse(null, "window=publiclibrary")
- onclose(usr, "publiclibrary")
- return
-
- if(href_list["pagenum"])
- if(!num_pages)
- page_num = 1
- else
- var/pn = text2num(href_list["pagenum"])
- if(!isnull(pn))
- page_num = Clamp(pn, 1, num_pages)
-
- if(href_list["settitle"])
- var/newtitle = input("Enter a title to search for:") as text|null
- if(newtitle)
- query.title = sanitize(newtitle)
- else
- query.title = null
- if(href_list["setcategory"])
- var/newcategory = input("Choose a category to search for:") in (list("Any") + library_section_names)
- if(newcategory == "Any")
- query.category = null
- else if(newcategory)
- query.category = sanitize(newcategory)
- if(href_list["setauthor"])
- var/newauthor = input("Enter an author to search for:") as text|null
- if(newauthor)
- query.author = sanitize(newauthor)
- else
- query.author = null
-
- if(href_list["page"])
- if(num_pages == 0)
- page_num = 1
- else
- page_num = Clamp(text2num(href_list["page"]), 1, num_pages)
-
- if(href_list["search"])
- num_results = src.get_num_results()
- num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
- page_num = 1
-
- screenstate = 1
-
- if(href_list["back"])
- screenstate = 0
-
- if(href_list["flag"])
- if(!dbcon.IsConnected())
- alert("Connection to Archive has been severed. Aborting.")
- return
- var/id = href_list["flag"]
- if(id)
- var/datum/cachedbook/B = getBookByID(id)
- if(B)
- if((input(usr, "Are you sure you want to flag [B.title] as having inappropriate content?", "Flag Book #[B.id]") in list("Yes", "No")) == "Yes")
- library_catalog.flag_book_by_id(usr, id)
-
- add_fingerprint(usr)
- updateUsrDialog()
+/obj/machinery/computer/library/public
+ name = "visitor computer"
+
+/obj/machinery/computer/library/public/attack_hand(var/mob/user as mob)
+ if(..())
+ return
+ interact(user)
+
+/obj/machinery/computer/library/public/attackby(obj/item/W as obj, mob/user as mob)
+ if(default_unfasten_wrench(user, W))
+ power_change()
+ return
+
+/obj/machinery/computer/library/public/interact(var/mob/user)
+ if(interact_check(user))
+ return
+
+ var/dat = ""
+ switch(screenstate)
+ if(0)
+
+ dat += {"Search Settings
+ Filter by Title: [query.title]
+ Filter by Category: [query.category]
+ Filter by Author: [query.author]
+ \[Start Search\]
"}
+ if(1)
+ establish_db_connection()
+ if(!dbcon.IsConnected())
+ dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance.
"
+ else if(num_results == 0)
+ dat += "No results found."
+ else
+ var/pagelist = get_pagelist()
+
+ dat += pagelist
+ dat += {""}
+ dat += {"
+
+ | Author |
+ Title |
+ Category |
+ SS13BN |
+ Controls |
+
"}
+ for(var/datum/cachedbook/CB in get_page(page_num))
+ dat += {"
+ | [CB.author] |
+ [CB.title] |
+ [CB.category] |
+ [CB.id] |
+ \[Flag[CB.flagged ? "ged" : ""]\] |
+
"}
+
+ dat += "
[pagelist]"
+ dat += "\[Go Back\]
"
+ var/datum/browser/B = new /datum/browser(user, "library", "Library Visitor")
+ B.set_content(dat)
+ B.open()
+
+/obj/machinery/computer/library/public/Topic(href, href_list)
+ if(..())
+ usr << browse(null, "window=publiclibrary")
+ onclose(usr, "publiclibrary")
+ return
+
+ if(href_list["pagenum"])
+ if(!num_pages)
+ page_num = 1
+ else
+ var/pn = text2num(href_list["pagenum"])
+ if(!isnull(pn))
+ page_num = Clamp(pn, 1, num_pages)
+
+ if(href_list["settitle"])
+ var/newtitle = input("Enter a title to search for:") as text|null
+ if(newtitle)
+ query.title = sanitize(newtitle)
+ else
+ query.title = null
+ if(href_list["setcategory"])
+ var/newcategory = input("Choose a category to search for:") in (list("Any") + library_section_names)
+ if(newcategory == "Any")
+ query.category = null
+ else if(newcategory)
+ query.category = sanitize(newcategory)
+ if(href_list["setauthor"])
+ var/newauthor = input("Enter an author to search for:") as text|null
+ if(newauthor)
+ query.author = sanitize(newauthor)
+ else
+ query.author = null
+
+ if(href_list["page"])
+ if(num_pages == 0)
+ page_num = 1
+ else
+ page_num = Clamp(text2num(href_list["page"]), 1, num_pages)
+
+ if(href_list["search"])
+ num_results = src.get_num_results()
+ num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
+ page_num = 1
+
+ screenstate = 1
+
+ if(href_list["back"])
+ screenstate = 0
+
+ if(href_list["flag"])
+ if(!dbcon.IsConnected())
+ alert("Connection to Archive has been severed. Aborting.")
+ return
+ var/id = href_list["flag"]
+ if(id)
+ var/datum/cachedbook/B = getBookByID(id)
+ if(B)
+ if((input(usr, "Are you sure you want to flag [B.title] as having inappropriate content?", "Flag Book #[B.id]") in list("Yes", "No")) == "Yes")
+ library_catalog.flag_book_by_id(usr, id)
+
+ add_fingerprint(usr)
+ updateUsrDialog()
return
\ No newline at end of file
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index 4cdecae1f66..611b84f8100 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -151,6 +151,9 @@ var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "A
var/obj/item/book/cache // Last scanned book
/obj/machinery/libraryscanner/attackby(obj/item/I, mob/user)
+ if(default_unfasten_wrench(user, I))
+ power_change()
+ return
if(istype(I, /obj/item/book))
user.drop_item()
I.forceMove(src)
@@ -208,6 +211,9 @@ var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "A
/obj/machinery/bookbinder/attackby(obj/item/I, mob/user)
var/obj/item/paper/P = I
+ if(default_unfasten_wrench(user, I))
+ power_change()
+ return
if(istype(P))
user.drop_item()
user.visible_message("[user] loads some paper into [src].", "You load some paper into [src].")
diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm
index 2d031d9c2c5..1b84afb3d74 100644
--- a/code/modules/reagents/chemistry/machinery/chem_heater.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm
@@ -69,6 +69,9 @@
SSnanoui.update_uis(src)
/obj/machinery/chem_heater/attackby(obj/item/I, mob/user)
+ if(default_unfasten_wrench(user, I))
+ power_change()
+ return
if(isrobot(user))
return
diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm
index 81fed023251..0855c4fec4f 100644
--- a/code/modules/reagents/chemistry/machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_master.dm
@@ -50,6 +50,9 @@
stat |= NOPOWER
/obj/machinery/chem_master/attackby(obj/item/B, mob/user, params)
+ if(default_unfasten_wrench(user, B))
+ power_change()
+ return
if(istype(B, /obj/item/reagent_containers/glass) || istype(B, /obj/item/reagent_containers/food/drinks/drinkingglass))
diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm
index 3a5b753217f..7c36334f78d 100644
--- a/code/modules/reagents/chemistry/machinery/pandemic.dm
+++ b/code/modules/reagents/chemistry/machinery/pandemic.dm
@@ -185,18 +185,18 @@
english_symptoms += S.name
var/symtoms = english_list(english_symptoms)
-
+
var/signature
if(alert(user,"Would you like to add your signature?",,"Yes","No") == "Yes")
signature = "[user ? user.real_name : "Anonymous"]"
- else
+ else
signature = ""
-
+
printing = 1
var/obj/item/paper/P = new /obj/item/paper(loc)
visible_message("[src] rattles and prints out a sheet of paper.")
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
-
+
P.info = " Releasing Virus "
P.info += "
"
P.info += "Name of the Virus: [D.name]
"
@@ -318,6 +318,9 @@
/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params)
+ if(default_unfasten_wrench(user, I))
+ power_change()
+ return
if(istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER))
if(stat & (NOPOWER|BROKEN))
return