From 3c63532ada3893779dbce80ec1591492026ab889 Mon Sep 17 00:00:00 2001 From: Casper3667 <8396443+Casper3667@users.noreply.github.com> Date: Sun, 1 Mar 2026 07:46:28 +0100 Subject: [PATCH] Make the commissary register able to be filled out with paper forms (#21905) The commissary register can now be filled out by unlocking it and using a filled out piece of paper on it. This adds the listed items to the things listed in it, making it quick to set up for operations crew instead of manually typing it in every round. --------- Signed-off-by: Casper3667 <8396443+Casper3667@users.noreply.github.com> Co-authored-by: Cody Brittain <1779662+Generalcamo@users.noreply.github.com> --- aurorastation.dme | 1 + code/__HELPERS/price.dm | 61 ++++++++++++++++++++ code/modules/cooking/machinery/commissary.dm | 41 ++++++++++--- code/modules/economy/quikpay.dm | 36 +++++++++--- html/changelogs/PaperList.yml | 6 ++ tgui/packages/tgui/interfaces/QuikPay.tsx | 20 +++++-- 6 files changed, 143 insertions(+), 22 deletions(-) create mode 100644 code/__HELPERS/price.dm create mode 100644 html/changelogs/PaperList.yml diff --git a/aurorastation.dme b/aurorastation.dme index 18f07b737fb..86b12c9934e 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -221,6 +221,7 @@ #include "code\__HELPERS\nameof.dm" #include "code\__HELPERS\names.dm" #include "code\__HELPERS\overmap.dm" +#include "code\__HELPERS\price.dm" #include "code\__HELPERS\qdel.dm" #include "code\__HELPERS\ref.dm" #include "code\__HELPERS\sanitize_values.dm" diff --git a/code/__HELPERS/price.dm b/code/__HELPERS/price.dm new file mode 100644 index 00000000000..3a5331f3bed --- /dev/null +++ b/code/__HELPERS/price.dm @@ -0,0 +1,61 @@ +/// Registers name and prices for the commissary from a paper. +/// First line is ignored, acting as header for name/pricing, mainly for readability. +/// The second line and after are read as the name of the thing and the price of the thing. +/// Example below +/// name,price +/// Candy,2.50 +/// Snack,3.10 +/// Meal,10.00 +/// The above would add 3 items, the candy, snack and meal, with their respective prices. +/// It returns a list containing name and prices +/proc/read_paper_price_list(var/obj/item/paper/R) + var/text = R.info + + // Split on new line + var/list/lines = splittext(text, "
") + var/list/result = list() + + // Skip a header line + for(var/i = 2; i <= lines.len; i++) + var/line = lines[i] + if(!length(line)) + continue + + // Split the name and price + var/list/split_input = splittext(line, ";") + + if(split_input.len < 2) + continue + + var/name = split_input[1] + var/price_text = split_input[2] + + var/price = text2num(price_text) + + // In case of invalid prices for some reason + if(price == 0 && price_text != "0" && price_text != "0.0") + continue + + result += list(list("name" = name, "price" = price)) + + return result + +// Prints the prices from a register/quikpay into a list that can be used for read_paper_price_list() +/proc/print_price_to_paper(var/shop_name, var/list/items, var/paper_loc, mob/user) + if(!items || !items.len) + return FALSE + + var/obj/item/paper/notepad/receipt/R = new(paper_loc) + var/title = "Price List: [shop_name]" + var/text = "name;price
" + + for(var/list/L in items) + var/item_name = L["name"] + var/item_price = L["price"] + text += "[item_name];[round(item_price, 0.01)]
" + + R.set_content(title, text) + + user.put_in_any_hand_if_possible(R) + R.ripped = TRUE + return TRUE diff --git a/code/modules/cooking/machinery/commissary.dm b/code/modules/cooking/machinery/commissary.dm index 237a5cb07d3..5e9e2bccac2 100644 --- a/code/modules/cooking/machinery/commissary.dm +++ b/code/modules/cooking/machinery/commissary.dm @@ -157,6 +157,7 @@ . += "Alt click with credits in hand, to deposit them." . += "Alt click while having operations access, to withdraw credits from it." . += "Items can be paid for with id cards, charge cards or physical credits, and a receipt will be printed." + . += "The register can print a paper which can be used to quickly fill it out in the future by using it on the register." /obj/structure/cash_register/commissary/Initialize() . = ..() @@ -207,6 +208,9 @@ R.ripped = TRUE /obj/structure/cash_register/commissary/attackby(obj/item/attacking_item, mob/user) + if(istype(attacking_item, /obj/item/paper)) + read_paper_list(attacking_item, user) + return if(sum == 0) return if (istype(attacking_item, /obj/item/spacecash/ewallet)) @@ -258,9 +262,9 @@ if(transaction) to_chat(user, SPAN_NOTICE("[icon2html(src, user)][transaction].")) else - playsound(src, 'sound/machines/chime.ogg', 50, 1) - visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) visible_message("\The [user] swipes a card on \the [src]." ) + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) + playsound(src, 'sound/machines/chime.ogg', 50, 1) print_receipt() sum = 0 receipt = "" @@ -278,8 +282,8 @@ E.worth -= transaction_amount visible_message("\The [user] swipes a card on \the [src]." ) + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) playsound(src, 'sound/machines/chime.ogg', 50, 1) - src.audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) print_receipt() sum = 0 receipt = "" @@ -289,6 +293,18 @@ to_chat(user, SPAN_WARNING("[icon2html(src, user)]\The [E] doesn't have that much money!")) return +/obj/structure/cash_register/commissary/proc/read_paper_list(obj/item/paper/R, mob/user) + if(!editmode) + balloon_alert(user, "device locked!") + return FALSE + var/result = read_paper_price_list(R) + for(var/item in result) + items += list(list("name" = item["name"], "price" = item["price"])) + items_to_price[item["name"]] += item["price"] + +/obj/structure/cash_register/commissary/proc/print_price(mob/user) + return print_price_to_paper(shop_name, items, loc, user) + /obj/structure/cash_register/commissary/attack_hand(mob/living/user) . = ..() ui_interact(user) @@ -319,7 +335,7 @@ switch(action) if("add") if(!editmode) - to_chat(usr, SPAN_WARNING("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE items += list(list("name" = new_item, "price" = new_price)) @@ -328,7 +344,7 @@ if("remove") if(!editmode) - to_chat(usr, SPAN_NOTICE("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE var/index = 0 for(var/list/L in items) @@ -390,7 +406,7 @@ if("locking") if(editmode) editmode = FALSE - to_chat(usr, SPAN_NOTICE("Device locked.")) + balloon_alert(usr, "device locked!") else if(!editmode) var/obj/item/card/id/I = usr.GetIdCard() @@ -398,19 +414,26 @@ return if(check_access(I)) editmode = !editmode - to_chat(usr, SPAN_NOTICE("Device [editmode ? "un" : ""]locked.")) + balloon_alert(usr, "device [editmode ? "un" : ""]locked") . = TRUE if("accountselect") if(!editmode) - to_chat(usr, SPAN_WARNING("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE var/dest = tgui_input_list(usr, "What account would you like to select?", "Destination Account", assoc_to_keys(SSeconomy.department_accounts)) if(!dest) return FALSE destinationact = dest - return TRUE + . = TRUE + + if("print_dsv") + if(!editmode) + balloon_alert(usr, "device locked!") + return FALSE + print_price(usr) + . = TRUE /obj/structure/cash_register/commissary/proc/clear_order() buying.Cut() diff --git a/code/modules/economy/quikpay.dm b/code/modules/economy/quikpay.dm index 0ecb32e2e05..a3c3c01c667 100644 --- a/code/modules/economy/quikpay.dm +++ b/code/modules/economy/quikpay.dm @@ -74,6 +74,9 @@ usr.put_in_any_hand_if_possible(R) /obj/item/quikpay/attackby(obj/item/attacking_item, mob/user) + if(istype(attacking_item, /obj/item/paper)) + read_paper_list(attacking_item, user) + return if (istype(attacking_item, /obj/item/spacecash/ewallet)) var/obj/item/spacecash/ewallet/E = attacking_item var/transaction_amount = sum @@ -81,8 +84,8 @@ var/transaction_terminal = machine_id if(transaction_amount <= E.worth) + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) playsound(src, 'sound/machines/chime.ogg', 50, 1) - src.visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) SSeconomy.charge_to_account(SSeconomy.get_department_account(destinationact)?.account_number, E.owner_name, transaction_purpose, transaction_terminal, transaction_amount) E.worth -= transaction_amount @@ -107,13 +110,25 @@ if(transaction) to_chat(user, SPAN_NOTICE("[icon2html(src, user)][transaction].")) else + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) playsound(src, 'sound/machines/chime.ogg', 50, 1) - visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) print_receipt() sum = 0 receipt = "" to_chat(user, SPAN_NOTICE("Transaction completed, please return to the home screen.")) +/obj/item/quikpay/proc/read_paper_list(obj/item/paper/R, mob/user) + if(!editmode) + balloon_alert(user, "device locked!") + return FALSE + var/result = read_paper_price_list(R) + for(var/item in result) + items += list(list("name" = item["name"], "price" = item["price"])) + items_to_price[item["name"]] += item["price"] + +/obj/item/quikpay/proc/print_price(mob/user) + return print_price_to_paper(shop_name, items, loc, user) + /obj/item/quikpay/attack_self(var/mob/user) ui_interact(user) @@ -144,7 +159,7 @@ switch(action) if("add") if(!editmode) - to_chat(usr, SPAN_WARNING("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE items += list(list("name" = new_item, "price" = new_price)) @@ -153,7 +168,7 @@ if("remove") if(!editmode) - to_chat(usr, SPAN_NOTICE("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE var/index = 0 for(var/list/L in items) @@ -215,7 +230,7 @@ if("locking") if(editmode) editmode = FALSE - to_chat(usr, SPAN_NOTICE("Device locked.")) + balloon_alert(usr, "device locked!") else if(!editmode) var/obj/item/card/id/I = usr.GetIdCard() @@ -228,14 +243,21 @@ if("accountselect") if(!editmode) - to_chat(usr, SPAN_WARNING("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE var/dest = tgui_input_list(usr, "What account would you like to select?", "Destination Account", assoc_to_keys(SSeconomy.department_accounts)) if(!dest) return FALSE destinationact = dest - return TRUE + . = TRUE + + if("print_dsv") + if(!editmode) + balloon_alert(usr, "device locked!") + return FALSE + print_price(usr) + . = TRUE /obj/item/quikpay/proc/clear_order() buying.Cut() diff --git a/html/changelogs/PaperList.yml b/html/changelogs/PaperList.yml new file mode 100644 index 00000000000..dc79f0a9d65 --- /dev/null +++ b/html/changelogs/PaperList.yml @@ -0,0 +1,6 @@ +author: TheGreyWolf + +delete-after: True + +changes: + - rscadd: "The commissary cash register can now be filled out with a paper form." diff --git a/tgui/packages/tgui/interfaces/QuikPay.tsx b/tgui/packages/tgui/interfaces/QuikPay.tsx index fc42068c4fb..b9ec897ecd8 100644 --- a/tgui/packages/tgui/interfaces/QuikPay.tsx +++ b/tgui/packages/tgui/interfaces/QuikPay.tsx @@ -44,12 +44,20 @@ export const QuikPay = (props, context) => { buttons={ <> {data.editmode ? ( -