/* Library Items
*
* Contains:
* Bookcase
* Book
* Barcode Scanner
*/
/*
* Bookcase
*/
/obj/structure/bookcase
name = "bookcase"
icon = 'icons/obj/library.dmi'
icon_state = "book-0"
anchored = 1
density = 1
opacity = 1
burn_state = FLAMMABLE
burntime = 30
var/health = 50
var/tmp/busy = 0
var/list/allowed_books = list(/obj/item/book, /obj/item/spellbook, /obj/item/storage/bible, /obj/item/tome) //Things allowed in the bookcase
/obj/structure/bookcase/Initialize()
..()
for(var/obj/item/I in loc)
if(is_type_in_list(I, allowed_books))
I.forceMove(src)
update_icon()
/obj/structure/bookcase/attackby(obj/item/O as obj, mob/user as mob, params)
if(busy) //So that you can't mess with it while deconstructing
return 1
if(is_type_in_list(O, allowed_books))
if(!user.drop_item())
return
O.forceMove(src)
update_icon()
return 1
else if(istype(O, /obj/item/storage/bag/books))
var/obj/item/storage/bag/books/B = O
for(var/obj/item/T in B.contents)
if(istype(T, /obj/item/book) || istype(T, /obj/item/spellbook) || istype(T, /obj/item/tome) || istype(T, /obj/item/storage/bible))
B.remove_from_storage(T, src)
to_chat(user, "You empty [O] into [src].")
update_icon()
return 1
else if(istype(O, /obj/item/wrench))
user.visible_message("[user] starts disassembling \the [src].", \
"You start disassembling \the [src].")
playsound(get_turf(src), O.usesound, 50, 1)
busy = 1
if(do_after(user, 50 * O.toolspeed, target = src))
playsound(get_turf(src), O.usesound, 75, 1)
user.visible_message("[user] disassembles \the [src].", \
"You disassemble \the [src].")
busy = 0
density = 0
qdel(src)
else
busy = 0
return 1
else if(istype(O, /obj/item/pen))
var/newname = stripped_input(user, "What would you like to title this [name]?")
if(newname)
name = ("bookcase ([sanitize(newname)])")
return 1
else
switch(O.damtype)
if("fire")
health -= O.force * 1
if("brute")
health -= O.force * 0.75
else
if(health <= 0)
visible_message("The bookcase is smashed apart!")
qdel(src)
return ..()
/obj/structure/bookcase/attack_hand(var/mob/user as mob)
if(contents.len)
var/obj/item/book/choice = input("Which book would you like to remove from [src]?") as null|anything in contents
if(choice)
if(user.incapacitated() || user.lying || !Adjacent(user))
return
if(!user.get_active_hand())
user.put_in_hands(choice)
else
choice.forceMove(get_turf(src))
update_icon()
/obj/structure/bookcase/ex_act(severity)
switch(severity)
if(1.0)
for(var/obj/item/I in contents)
qdel(I)
qdel(src)
return
if(2.0)
for(var/obj/item/I in contents)
if(prob(50))
qdel(I)
qdel(src)
return
if(3.0)
if(prob(50))
qdel(src)
return
return
/obj/structure/bookcase/Destroy()
for(var/i in 1 to 5)
new /obj/item/stack/sheet/wood(get_turf(src))
for(var/obj/item/I in contents)
if(is_type_in_list(I, allowed_books))
I.forceMove(get_turf(src))
return ..()
/obj/structure/bookcase/update_icon()
if(contents.len < 5)
icon_state = "book-[contents.len]"
else
icon_state = "book-5"
/obj/structure/bookcase/manuals/medical
name = "Medical Manuals bookcase"
New()
..()
new /obj/item/book/manual/medical_cloning(src)
update_icon()
/obj/structure/bookcase/manuals/engineering
name = "Engineering Manuals bookcase"
New()
..()
new /obj/item/book/manual/engineering_construction(src)
new /obj/item/book/manual/engineering_particle_accelerator(src)
new /obj/item/book/manual/engineering_hacking(src)
new /obj/item/book/manual/engineering_guide(src)
new /obj/item/book/manual/engineering_singularity_safety(src)
new /obj/item/book/manual/robotics_cyborgs(src)
update_icon()
/obj/structure/bookcase/manuals/research_and_development
name = "R&D Manuals bookcase"
New()
..()
new /obj/item/book/manual/research_and_development(src)
update_icon()
/*
* Book
*/
/obj/item/book
name = "book"
icon = 'icons/obj/library.dmi'
icon_state ="book"
throw_speed = 1
throw_range = 5
force = 2
w_class = WEIGHT_CLASS_NORMAL //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever)
attack_verb = list("bashed", "whacked")
burn_state = FLAMMABLE
var/dat // Actual page content
var/due_date = 0 // Game time in 1/10th seconds
var/author // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned
var/unique = 0 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified
var/title // The real name of the book.
var/carved = 0 // Has the book been hollowed out for use as a secret storage item?
var/forbidden = 0 // Prevent ordering of this book. (0=no, 1=yes, 2=emag only)
var/obj/item/store // What's in the book?
/obj/item/book/attack_self(var/mob/user as mob)
if(carved)
if(store)
to_chat(user, "[store] falls out of [title]!")
store.forceMove(get_turf(loc))
store = null
return
else
to_chat(user, "The pages of [title] have been cut out!")
return
if(src.dat)
user << browse("Penned by [author].
" + "[dat]", "window=book")
if(!isobserver(user))
user.visible_message("[user] opens a book titled \"[title]\" and begins reading intently.")
onclose(user, "book")
else
to_chat(user, "This book is completely blank!")
/obj/item/book/attackby(obj/item/W as obj, mob/user as mob, params)
if(carved)
if(!store)
if(W.w_class < WEIGHT_CLASS_NORMAL)
user.drop_item()
W.forceMove(src)
store = W
to_chat(user, "You put [W] in [title].")
return 1
else
to_chat(user, "[W] won't fit in [title].")
return 1
else
to_chat(user, "There's already something in [title]!")
return 1
if(istype(W, /obj/item/pen))
if(unique)
to_chat(user, "These pages don't seem to take the ink well. Looks like you can't modify it.")
return 1
var/choice = input("What would you like to change?") in list("Title", "Contents", "Author", "Cancel")
switch(choice)
if("Title")
var/newtitle = reject_bad_text(stripped_input(usr, "Write a new title:"))
if(!newtitle)
to_chat(usr, "The title is invalid.")
return 1
else
src.name = newtitle
src.title = newtitle
if("Contents")
var/content = strip_html(input(usr, "Write your book's contents (HTML NOT allowed):") as message|null, MAX_BOOK_MESSAGE_LEN)
if(!content)
to_chat(usr, "The content is invalid.")
return 1
else
src.dat += content
if("Author")
var/newauthor = stripped_input(usr, "Write the author's name:")
if(!newauthor)
to_chat(usr, "The name is invalid.")
return 1
else
src.author = newauthor
return 1
else if(istype(W, /obj/item/barcodescanner))
var/obj/item/barcodescanner/scanner = W
if(!scanner.computer)
to_chat(user, "[W]'s screen flashes: 'No associated computer found!'")
else
switch(scanner.mode)
if(0)
scanner.book = src
to_chat(user, "[W]'s screen flashes: 'Book stored in buffer.'")
if(1)
scanner.book = src
scanner.computer.buffer_book = src.name
to_chat(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)
to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Book has been checked in.'")
return 1
to_chat(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/book in scanner.computer.inventory)
if(book == src)
to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Title already present in inventory, aborting to avoid duplicate entry.'")
return 1
scanner.computer.inventory.Add(src)
to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Title added to general inventory.'")
return 1
else if(istype(W, /obj/item/kitchen/knife) || iswirecutter(W))
if(carved)
return 1
to_chat(user, "You begin to carve out [title].")
if(do_after(user, 30 * W.toolspeed, target = src))
to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.")
carved = 1
return 1
else
return ..()
/obj/item/book/attack(mob/M, mob/living/user)
if(user.a_intent == INTENT_HELP)
force = 0
attack_verb = list("educated")
else
force = initial(force)
attack_verb = list("bashed", "whacked")
..()
/*
* Barcode Scanner
*/
/obj/item/barcodescanner
name = "barcode scanner"
icon = 'icons/obj/library.dmi'
icon_state ="scanner"
throw_speed = 1
throw_range = 5
w_class = WEIGHT_CLASS_TINY
var/obj/machinery/computer/library/checkout/computer // Associated computer - Modes 1 to 3 use this
var/obj/item/book/book // Currently scanned book
var/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
to_chat(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"
to_chat(user, " - Mode [mode] : [modedesc]")
if(src.computer)
to_chat(user, "Computer has been associated with this unit.")
else
to_chat(user, "No associated computer found. Only local scans will function properly.")
to_chat(user, "\n")