Files
John Willard 1d4081e6c0 Barcode scanner now lets you check books out (#95431)
## About The Pull Request

The barcode scanner has a check-in mode, but to checkout you have to
scroll through a (potentially) large list of books. This aims to fix
that by letting you skip the UI using the same item you use to check-in.



https://github.com/user-attachments/assets/916b743e-d974-4e7d-a9f2-a407562c5123


Also limits library book borrowing time to 2 hours, cause the UI looked
really weird with it uncapped (also any round that goes more than 2
hours you should bring your books back)

## Why It's Good For The Game

Better UX I think.
2026-03-24 12:11:28 -05:00

119 lines
4.2 KiB
Plaintext

#define BARCODE_SCANNER_CHECKIN "check_in"
#define BARCODE_SCANNER_CHECKOUT "check_out"
#define BARCODE_SCANNER_INVENTORY "inventory"
/obj/item/barcodescanner
name = "barcode scanner"
icon = 'icons/obj/service/library.dmi'
icon_state ="scanner"
desc = "A fabulous tool if you need to scan a barcode."
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_TINY
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2)
///Weakref to the library computer we are connected to.
var/datum/weakref/computer_ref
///The current scanning mode (BARCODE_SCANNER_CHECKIN|BARCODE_SCANNER_CHECKOUT|BARCODE_SCANNER_INVENTORY)
var/scan_mode = BARCODE_SCANNER_CHECKIN
/obj/item/barcodescanner/Initialize(mapload)
. = ..()
register_item_context()
register_context()
/obj/item/barcodescanner/add_item_context(obj/item/source, list/context, atom/target, mob/living/user)
if(!istype(target, /obj/item/book))
return NONE
switch(scan_mode)
if(BARCODE_SCANNER_CHECKIN)
context[SCREENTIP_CONTEXT_LMB] = "Check in"
if(BARCODE_SCANNER_CHECKOUT)
context[SCREENTIP_CONTEXT_LMB] = "Check out"
if(BARCODE_SCANNER_INVENTORY)
context[SCREENTIP_CONTEXT_LMB] = "Add to inventory"
return CONTEXTUAL_SCREENTIP_SET
/obj/item/barcodescanner/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
if(held_item == src)
context[SCREENTIP_CONTEXT_LMB] = "Toggle scanning mode"
return CONTEXTUAL_SCREENTIP_SET
return NONE
/obj/item/barcodescanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(istype(interacting_with, /obj/item/book))
return interact_with_book(interacting_with, user)
return NONE
/obj/item/barcodescanner/proc/interact_with_book(obj/item/book/target_book, mob/living/user)
var/obj/machinery/computer/libraryconsole/bookmanagement/linked_computer = computer_ref?.resolve()
if(isnull(linked_computer))
user.balloon_alert(user, "not connected to computer!")
return ITEM_INTERACT_BLOCKING
switch(scan_mode)
if(BARCODE_SCANNER_CHECKIN)
var/list/checkouts = linked_computer.checkouts
for(var/checkout_ref in checkouts)
var/datum/borrowbook/maybe_ours = checkouts[checkout_ref]
if(!target_book.book_data.compare(maybe_ours.book_data))
continue
checkouts -= checkout_ref
linked_computer.checkout_update()
balloon_alert(user, "checked in")
playsound(src, 'sound/items/barcodebeep.ogg', 20, FALSE)
return ITEM_INTERACT_SUCCESS
user.balloon_alert(user, "isn't checked out!")
return ITEM_INTERACT_BLOCKING
if(BARCODE_SCANNER_CHECKOUT)
var/list/checkouts = linked_computer.checkouts
for(var/checkout_ref in checkouts)
var/datum/borrowbook/maybe_ours = checkouts[checkout_ref]
if(target_book.book_data.compare(maybe_ours.book_data))
user.balloon_alert(user, "already checked out!")
return ITEM_INTERACT_BLOCKING
for(var/copy_ref in linked_computer.inventory)
if(!target_book.book_data.compare(linked_computer.inventory[copy_ref]))
continue
linked_computer.checking_out_book = target_book.book_data
balloon_alert(user, "set for check out")
playsound(src, 'sound/items/barcodebeep.ogg', 20, FALSE)
return ITEM_INTERACT_SUCCESS
user.balloon_alert(user, "not in inventory!")
return ITEM_INTERACT_BLOCKING
if(BARCODE_SCANNER_INVENTORY)
var/datum/book_info/our_copy = target_book.book_data.return_copy()
linked_computer.inventory[ref(our_copy)] = our_copy
linked_computer.inventory_update()
balloon_alert(user, "added to inventory")
playsound(src, 'sound/items/barcodebeep.ogg', 20, FALSE)
return ITEM_INTERACT_SUCCESS
return NONE
/obj/item/barcodescanner/attack_self(mob/user)
. = ..()
if(.)
return
if(!computer_ref?.resolve())
balloon_alert(user, "connect to computer!")
return
switch(scan_mode)
if(BARCODE_SCANNER_CHECKIN)
scan_mode = BARCODE_SCANNER_CHECKOUT
balloon_alert(user, "check-out mode")
if(BARCODE_SCANNER_CHECKOUT)
scan_mode = BARCODE_SCANNER_INVENTORY
balloon_alert(user, "inventory adding mode")
if(BARCODE_SCANNER_INVENTORY)
scan_mode = BARCODE_SCANNER_CHECKIN
balloon_alert(user, "check-in mode")
playsound(loc, 'sound/items/click.ogg', 20, TRUE)
#undef BARCODE_SCANNER_CHECKIN
#undef BARCODE_SCANNER_CHECKOUT
#undef BARCODE_SCANNER_INVENTORY