Files
Bubberstation/code/modules/library/barcode_scanner.dm
_0Steven 5d8e4f09ea Refactors book attackby into item interaction procs, adding screentips, minor qol (#91273)
## About The Pull Request

This mostly just refactors the book `attackby(...)` proc into
`item_interaction(...)`, with some side-effects and screentips.
Notable ones follow here:

We move carving away from combat mode, and instead based it on whether
our tool is a pure writing utensil, a pure carving tool, or both at once
like the captain's fountain pen. If it's a pure tool, both left click
and right click are its respective primary action. If it's both,
however, left click is vandalizing and right click is carving.
This tries to ensure the expected primary interaction is always
left-click, without blocking anything if it could do both.

We move the barcode scanner interaction to the barcode scanner instead.
There's no good reason for this to stay on the book itself.

We add `can_vandalize(...)` as a proc and move all checks in there, so
we can call it after every tgui input. We don't replace the
`to_chat(...)` calls here with balloon alerts because the additional
clarifying info is needed, and it keeps the 'soulful' blind message.

We add `get_attack_self_context(...)` as a proc for getting screentips
on hovering over it in your active hand, because both the bible subtype
and the syndicate bible _bible subtype_ want different screentips there
in different situations, and so while it's clunky it's much less clunky
than the alternatives I considered.

Making it use actual storage datums avoids subtypes needing to make
manual changes to it in the `carve_out(...)` proc, and is just good for
organization.

This doesn't add screentips to most bible-specific interactions, as I
deemed them outside of the scope of this pr.
Those are better off done atomized into another pr.
## Why It's Good For The Game

less attackby, more item interaction
screentips good

I think having the carving interaction on combat mode is unintuitive,
especially when that's the only interaction it can do.
This ensures the expected primary interaction is always left-click.
## Changelog
🆑
refactor: Refactored the book interaction chain. Please report any
issues.
fix: You can no longer vandalize carved out books if you carve it after
opening the input menu but before entering anything.
qol: Added screentips to book interactions.
qol: Added screentips to barcode scanner interactions.
qol: Carving out books no longer uses combat mode, instead using
left-click by default and right-click if your tool can also write.
Screentips account for this.
/🆑

---------

Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
2025-06-15 15:42:24 -04:00

89 lines
3.0 KiB
Plaintext

/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_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_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_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_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)