diff --git a/aurorastation.dme b/aurorastation.dme
index 611dbec244e..a8f148a0ceb 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -484,6 +484,7 @@
#include "code\datums\weakrefs.dm"
#include "code\datums\changelog\changelog.dm"
#include "code\datums\components\_component.dm"
+#include "code\datums\components\commissaryShop.dm"
#include "code\datums\components\connect_mob_behalf.dm"
#include "code\datums\components\drift.dm"
#include "code\datums\components\jukebox.dm"
diff --git a/code/__HELPERS/price.dm b/code/__HELPERS/price.dm
index 3a5331f3bed..50f53df1d76 100644
--- a/code/__HELPERS/price.dm
+++ b/code/__HELPERS/price.dm
@@ -11,35 +11,73 @@
/proc/read_paper_price_list(var/obj/item/paper/R)
var/text = R.info
- // Split on new line
+ // Split on line breaks
var/list/lines = splittext(text, "
")
var/list/result = list()
- // Skip a header line
+ // Skip header line
for(var/i = 2; i <= lines.len; i++)
- var/line = lines[i]
+ var/line = trim(lines[i])
if(!length(line))
continue
- // Split the name and price
var/list/split_input = splittext(line, ";")
- if(split_input.len < 2)
+ // category;name;price
+ if(length(split_input) >= 3)
+ var/category = trim(split_input[1])
+ var/name = trim(split_input[2])
+ var/price_text = trim(split_input[3])
+
+ if(!length(category))
+ category = "Uncategorized"
+ if(!length(name))
+ continue
+
+ var/price = text2num(price_text)
+
+ // Reject null prices
+ if(isnull(price))
+ continue
+
+ // Reject invalid prices
+ if(price == 0 && price_text != "0" && price_text != "0.0" && price_text != "0.00")
+ continue
+
+ result += list(list(
+ "name" = name,
+ "price" = price,
+ "category" = category
+ ))
continue
- var/name = split_input[1]
- var/price_text = split_input[2]
+ // name;price
+ if(length(split_input) >= 2)
+ var/name = trim(split_input[1])
+ var/price_text = trim(split_input[2])
- var/price = text2num(price_text)
+ if(!length(name))
+ continue
- // In case of invalid prices for some reason
- if(price == 0 && price_text != "0" && price_text != "0.0")
- continue
+ var/price = text2num(price_text)
- result += list(list("name" = name, "price" = price))
+ // Reject null prices
+ if(isnull(price))
+ continue
+
+ // Reject invalid prices
+ if(price == 0 && price_text != "0" && price_text != "0.0" && price_text != "0.00" && price != null)
+ continue
+
+ result += list(list(
+ "name" = name,
+ "price" = price,
+ "category" = "Uncategorized"
+ ))
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)
@@ -47,12 +85,17 @@
var/obj/item/paper/notepad/receipt/R = new(paper_loc)
var/title = "Price List: [shop_name]"
- var/text = "name;price
"
+ var/text = "category;name;price
"
for(var/list/L in items)
- var/item_name = L["name"]
+ var/item_category = sanitize_tg(L["category"])
+ var/item_name = sanitize_tg(L["name"])
var/item_price = L["price"]
- text += "[item_name];[round(item_price, 0.01)]
"
+
+ if(!length(item_category))
+ item_category = "Uncategorized"
+
+ text += "[item_category];[item_name];[round(item_price, 0.01)]
"
R.set_content(title, text)
diff --git a/code/datums/components/commissaryShop.dm b/code/datums/components/commissaryShop.dm
new file mode 100644
index 00000000000..6227cdcea27
--- /dev/null
+++ b/code/datums/components/commissaryShop.dm
@@ -0,0 +1,434 @@
+/datum/component/quikpay_shop
+ /// The id associated with the quikpay system. Automatically assigned.
+ var/machine_id = ""
+ /// The Items for sale, containing name and price
+ var/list/items = list()
+ /// The items in the purchase basket, containing name, price and amount
+ var/list/buying = list()
+ /// The input field for new item names
+ var/new_item = ""
+ /// The input field for new item prices
+ var/new_price = 0
+ /// The input field for new item categories
+ var/new_category = ""
+ /// The transaction total for a purchase, 0 when there is no transaction ongoing
+ var/sum = 0
+ /// If the shop can be changed or not, to add new items or change destination account
+ var/editmode = FALSE
+ /// Receipt printing info
+ var/receipt = ""
+ /// The account to receive funds from card transactions
+ var/destinationact = "Operations"
+ /// The credits within the shop object
+ var/credit = 100
+ /// The name used for the shop
+ var/shop_name = "Commissary"
+ /// The owner object, also known as parent. Defined to easily do obj specific procs
+ var/obj/owner
+ /// If it is possible to pay with physical credits or only card
+ var/can_use_credits = TRUE
+ /// The the longer version of the shop name
+ var/shop_long_name = "Idris Quik-Pay Register"
+ /// The access types that can configure the shop
+ var/req_one_access = list(ACCESS_BAR, ACCESS_GALLEY, ACCESS_CARGO)
+
+/datum/component/quikpay_shop/quikpay
+ shop_name = "Quik-Pay"
+ destinationact = "Service"
+ shop_long_name = "Quik-Pay device"
+ can_use_credits = FALSE
+
+/// Add an item by clicking on it with the quikpay
+/datum/component/quikpay_shop/quikpay/proc/add_item(atom/target, mob/user)
+ if(!isobj(target))
+ return
+ if (!editmode)
+ to_chat(user, SPAN_NOTICE("Unlock \the [owner] to add items."))
+ return
+
+ var/obj/O = target
+ var/name_guess = O.name
+ var/price_guess = 0
+ var/category_guess = ""
+
+ price_guess = text2num(tgui_input_text(user, "Set price for [name_guess]:", "[shop_long_name]", 0, 10))
+ if(isnull(price_guess) || price_guess == 0)
+ return
+ price_guess = max(0.01, round(price_guess, 0.01))
+
+ category_guess = tgui_input_text(user, "Set category for [name_guess]:", "[shop_long_name]", "Uncategorized", 32)
+ if(isnull(category_guess) || !length(category_guess))
+ category_guess = "Uncategorized"
+
+ items += list(list(
+ "name" = "[name_guess]",
+ "price" = price_guess,
+ "category" = "[category_guess]"
+ ))
+
+ to_chat(user, SPAN_NOTICE("[owner]: added '[name_guess]' for [price_guess] in category '[category_guess]'."))
+ return TRUE
+
+
+/datum/component/quikpay_shop/Initialize(access = list(ACCESS_BAR, ACCESS_GALLEY, ACCESS_CARGO), destination = "Operations")
+ . = ..()
+ machine_id = "[station_name()] [shop_long_name] #[SSeconomy.num_financial_terminals++]"
+ if(!isobj(parent))
+ return
+ req_one_access = access
+ destinationact = destination
+ owner = parent
+
+/// Put credits in or take them out, assuming the device has credits
+/datum/component/quikpay_shop/proc/take_give_credits(mob/user)
+ if(!can_use_credits)
+ return
+ var/item = user.get_active_hand()
+
+ if(istype(item, /obj/item/spacecash) && !istype(item, /obj/item/spacecash/ewallet))
+ var/obj/item/spacecash/cashmoney = item
+ credit += cashmoney.worth
+ user.drop_from_inventory(cashmoney,get_turf(owner))
+ user.visible_message("\The [user] inserts some credits into \the [owner]." )
+ qdel(cashmoney)
+ return
+
+ var/obj/item/card/id/I = user.GetIdCard()
+ if(istype(I) && has_access(req_one_access = src.req_one_access, accesses = I.access))
+ var/price_guess = text2num(tgui_input_text(user, "How much do you wish to withdraw? Remaining credits: [credit]电", "Quik-Pay", 0, 10))
+ if(isnull(price_guess) || price_guess == 0)
+ return
+ price_guess = max(0, round(price_guess, 0.01))
+ if(credit >= price_guess)
+ spawn_money(price_guess, owner.loc, user)
+ credit = max(0, credit - price_guess)
+ user.visible_message("\The [user] remove some credits from \the [owner].", "You hear a drawer being opened and the clinking of coins, followed by a drawer being closed." )
+
+/// Print out a relevant receipt
+/datum/component/quikpay_shop/proc/print_receipt()
+ var/obj/item/paper/notepad/receipt/R = new(owner.loc)
+ var/receiptname = "Receipt: [machine_id]"
+ R.set_content_unsafe(receiptname, receipt, sum)
+ stamp_receipt(R)
+ usr.put_in_any_hand_if_possible(R)
+
+/// Interact with an object. Papers or payment pethods
+/datum/component/quikpay_shop/proc/interact_object(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))
+ card_pay(attacking_item, user)
+ return
+ else if (istype(attacking_item, /obj/item/card/id))
+ ID_pay(attacking_item, user)
+ return
+ else if(istype(attacking_item, /obj/item/spacecash) && can_use_credits)
+ cash_pay(attacking_item, user)
+ return
+
+/// Paying with cash
+/datum/component/quikpay_shop/proc/cash_pay(obj/item/spacecash/cashmoney, mob/user)
+ if(!can_use_credits)
+ return
+ var/transaction_amount = sum
+ if(transaction_amount > cashmoney.worth)
+ to_chat(user, SPAN_WARNING("[icon2html(cashmoney, user)] That is not enough money."))
+ return FALSE
+ if(istype(cashmoney, /obj/item/spacecash/bundle))
+ user.visible_message(SPAN_INFO("\The [user] inserts some cash into \the [owner]."))
+ var/obj/item/spacecash/bundle/cashmoney_bundle = cashmoney
+ cashmoney_bundle.worth -= transaction_amount
+
+ if(cashmoney_bundle.worth <= 0)
+ usr.drop_from_inventory(cashmoney_bundle,get_turf(owner))
+ qdel(cashmoney_bundle)
+ else
+ cashmoney_bundle.update_icon()
+ else
+ user.visible_message(SPAN_INFO("\The [user] inserts a bill into \the [owner]."))
+ var/left = cashmoney.worth - transaction_amount
+ user.drop_from_inventory(cashmoney,get_turf(owner))
+ qdel(cashmoney)
+
+ if(left)
+ spawn_money(left, get_turf(user), user)
+ credit += transaction_amount
+ print_receipt()
+ clear_order()
+
+/// Paying with an id card
+/datum/component/quikpay_shop/proc/ID_pay(obj/item/attacking_item, mob/user)
+ var/obj/item/card/id/I = attacking_item.GetID()
+ var/transaction_amount = sum
+ var/transaction_purpose = "[destinationact] Payment"
+ var/transaction_terminal = machine_id
+
+ var/transaction = SSeconomy.transfer_money(I.associated_account_number, SSeconomy.get_department_account(destinationact)?.account_number,transaction_purpose,transaction_terminal,transaction_amount,null,usr)
+
+ if(transaction)
+ to_chat(user, SPAN_NOTICE("[icon2html(owner, user)][transaction]."))
+ else
+ end_transaction(user)
+
+/// Paying with a charge card
+/datum/component/quikpay_shop/proc/card_pay(obj/item/attacking_item, mob/user)
+ var/obj/item/spacecash/ewallet/E = attacking_item
+ var/transaction_amount = sum
+ var/transaction_purpose = "[destinationact] Payment"
+ var/transaction_terminal = machine_id
+
+ if(transaction_amount <= E.worth)
+ SSeconomy.charge_to_account(SSeconomy.get_department_account(destinationact)?.account_number, E.owner_name, transaction_purpose, transaction_terminal, transaction_amount)
+ E.worth -= transaction_amount
+
+ end_transaction(user)
+ else if (transaction_amount > E.worth)
+ to_chat(user, SPAN_WARNING("[icon2html(owner, user)]\The [E] doesn't have that much money!"))
+
+/// Read a paper to get data
+/datum/component/quikpay_shop/proc/read_paper_list(obj/item/paper/R, mob/user)
+ if(!editmode)
+ owner.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"],
+ "category" = item["category"] || "Uncategorized"
+ ))
+ owner.balloon_alert(user, "device set!")
+ return TRUE
+
+/// Handles receipt creation
+/datum/component/quikpay_shop/proc/buying_receipt(mob/user)
+ receipt = ""
+ sum = 0
+ var/obj/item/card/id/id_card = user.GetIdCard()
+ var/cashier = id_card ? id_card.registered_name : "Unknown"
+ receipt = "
[shop_name] receipt
Today's date: [worlddate2text()]
Cashier: [cashier]
Purchased items:"
+ for(var/list/bought_item in buying)
+ var/item_name = bought_item["name"]
+ var/item_amount = bought_item["amount"]
+ var/item_price = bought_item["price"]
+
+ receipt += "- [item_name]: [item_amount] x [item_price]电: [item_amount * item_price]电
"
+ sum += item_price * item_amount
+
+ receipt += "
Total: [sum]电
"
+
+/datum/component/quikpay_shop/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "QuikPay", "[shop_long_name]", 550, 550)
+ ui.open()
+
+/datum/component/quikpay_shop/ui_data(mob/user)
+ var/list/data = list()
+
+ data["items"] = items
+ data["buying"] = buying
+ data["sum"] = sum
+ data["new_item"] = new_item
+ data["new_price"] = new_price
+ data["new_category"] = new_category
+ data["editmode"] = editmode
+ data["destinationact"] = destinationact
+
+ return data
+
+/datum/component/quikpay_shop/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+ switch(action)
+ if("add")
+ if(!editmode)
+ owner.balloon_alert(usr, "device locked!")
+ return FALSE
+
+ if(!length(new_item))
+ return FALSE
+
+ if(!length(new_category))
+ new_category = "Uncategorized"
+
+ for(var/list/L in items)
+ if(L["name"] == new_item)
+ return FALSE
+
+ items += list(list(
+ "name" = new_item,
+ "price" = new_price,
+ "category" = new_category
+ ))
+
+ new_item = ""
+ . = TRUE
+
+ if("remove")
+ if(!editmode)
+ owner.balloon_alert(usr, "device locked!")
+ return FALSE
+ var/index = 0
+ for(var/list/L in items)
+ index++
+ if(L["name"] == params["removing"])
+ items.Cut(index, index+1)
+ break
+ . = TRUE
+
+ if("set_new_price")
+ new_price = params["set_new_price"]
+ . = TRUE
+
+ if("set_new_item")
+ new_item = params["set_new_item"]
+ . = TRUE
+
+ if("set_new_category")
+ new_category = params["set_new_category"]
+ . = TRUE
+
+ if("clear")
+ clear_order()
+ . = TRUE
+
+ if("buy")
+ for(var/list/L in buying)
+ if(L["name"] == params["buying"])
+ L["amount"]++
+ return TRUE
+ buying += list(list("name" = sanitize_tg(params["buying"]), "amount" = params["amount"], "price" = params["price"]))
+
+ if("removal")
+ var/index = 0
+ for(var/list/L in buying)
+ index++
+ if(L["name"] == params["removal"])
+ if(L["amount"] > 1)
+ L["amount"]--
+ else
+ buying.Cut(index, index+1)
+ break
+ . = TRUE
+
+ if("confirm")
+ buying_receipt(usr)
+ playsound(owner, 'sound/machines/ping.ogg', 25, TRUE)
+ owner.audible_message(SPAN_NOTICE("[icon2html(owner, viewers(get_turf(owner)))] \The [owner] pings."))
+ . = TRUE
+
+ if("locking")
+ if(editmode)
+ editmode = FALSE
+ owner.balloon_alert(usr, "device locked!")
+ else
+ if(!editmode)
+ var/obj/item/card/id/I = usr.GetIdCard()
+ if(!istype(I))
+ return
+ if(!has_access(req_one_access = src.req_one_access, accesses = I.access))
+ owner.balloon_alert(usr, "no access!")
+ return
+ editmode = !editmode
+ owner.balloon_alert(usr, "device [editmode ? "un" : ""]locked")
+ . = TRUE
+
+ if("accountselect")
+ if(!editmode)
+ owner.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
+ . = TRUE
+
+ if("print_dsv")
+ if(!editmode)
+ owner.balloon_alert(usr, "device locked!")
+ return FALSE
+ print_price_to_paper(shop_name, items, owner.loc, usr)
+ . = TRUE
+
+/// Clear the order from the selection
+/datum/component/quikpay_shop/proc/clear_order()
+ buying.Cut()
+ sum = 0
+ receipt = ""
+
+/// Ends the transaction by using a card, giving a message
+/datum/component/quikpay_shop/proc/end_transaction(mob/user)
+ user.visible_message("\The [user] swipes a card on \the [owner]." )
+ owner.audible_message(SPAN_NOTICE("[icon2html(owner, viewers(get_turf(owner)))] \The [owner] chimes."))
+ playsound(owner, 'sound/machines/chime.ogg', 50, TRUE)
+ print_receipt()
+ to_chat(user, SPAN_NOTICE("Transaction completed, please return to the home screen."))
+ clear_order()
+
+/datum/component/quikpay_shop/orderterminal
+ shop_name = "Commissary"
+ shop_long_name = "Self-serve Shop Teller"
+ can_use_credits = FALSE
+
+/datum/component/quikpay_shop/orderterminal/food
+ var/ticket = ""
+ var/ticket_number = 1
+ shop_name = "Service terminal"
+ shop_long_name = "Idris Food Terminal"
+
+/datum/component/quikpay_shop/orderterminal/food/buying_receipt(mob/user)
+ ticket = ""
+ receipt = ""
+ sum = 0
+ receipt += "[shop_long_name] Receipt
"
+ ticket += "[shop_long_name] Ticket
"
+ for(var/list/bought_item in buying)
+ var/item_name = bought_item["name"]
+ var/item_amount = bought_item["amount"]
+ var/item_price = bought_item["price"]
+ sum += item_price * item_amount
+
+ receipt += "[item_name]: [item_amount] x [item_price]电: [item_amount * item_price]电
"
+ ticket += "[item_name]: [item_amount] x [item_price]电: [item_amount * item_price]电
"
+ receipt += "
Total: [sum]电"
+ ticket += "
Total: [sum]电"
+ sum = sum
+
+/// Print the receipt followed by the order ticket
+/datum/component/quikpay_shop/orderterminal/food/print_receipt()
+ var/obj/item/card/id/id_card
+ if(ishuman(usr))
+ id_card = usr.GetIdCard()
+ ticket += "
Customer: [id_card ? id_card.registered_name : "Unknown"]"
+ receipt += "
Customer: [id_card ? id_card.registered_name : "Unknown"]"
+ var/obj/item/paper/notepad/receipt/R = new(owner.loc)
+ var/receiptname = "Receipt: [machine_id]"
+ R.set_content_unsafe(receiptname, receipt, sum)
+ stamp_receipt(R)
+ usr.put_in_any_hand_if_possible(R)
+ // And now we do it but for the ticket.
+ var/obj/item/paper/notepad/receipt/T = new(owner.loc)
+ var/tickettname = "Order ticket: [ticket_number]"
+ ticket_number++
+ T.set_content_unsafe(tickettname, ticket, sum)
+ stamp_receipt(T)
+ usr.put_in_any_hand_if_possible(T)
+ ticket = ""
+ receipt = ""
+
+/datum/component/quikpay_shop/proc/stamp_receipt(obj/item/paper/R) // Stamps the papers, made into a proc to avoid copy pasting too much
+ var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
+ stampoverlay.icon_state = "paper_stamp-hop"
+ if(!R.stamped)
+ R.stamped = new
+ R.stamped += /obj/item/stamp
+ R.AddOverlays(stampoverlay)
+ R.stamps += "
This paper has been stamped by \the [owner]."
+ R.ripped = TRUE
diff --git a/code/modules/cooking/machinery/commissary.dm b/code/modules/cooking/machinery/commissary.dm
index dba823d2beb..bb89d7ca255 100644
--- a/code/modules/cooking/machinery/commissary.dm
+++ b/code/modules/cooking/machinery/commissary.dm
@@ -41,6 +41,7 @@
display_tiers = 5
display_tier_amt = 3
has_emissive = FALSE
+ visible_takeout = TRUE
/obj/machinery/smartfridge/tradeshelf/clothing
name = "clothing shelf"
@@ -87,6 +88,17 @@
display_tier_amt = 5
has_emissive = TRUE
+/obj/machinery/smartfridge/tradeshelf/food/attackby(obj/item/attacking_item, mob/user)
+ if(attacking_item.tool_behaviour == TOOL_PEN)
+ name_fridge(user)
+ return
+ . = ..()
+
+/obj/machinery/smartfridge/tradeshelf/food/proc/name_fridge(mob/user)
+ var/newname = tgui_input_text(user, "What would you like to rename the fridge? Note that fridge will be appended to the end of it", "Fridge name")
+ if(newname)
+ name = newname + " fridge"
+
/obj/machinery/smartfridge/tradeshelf/toy
name = "toy shelf"
desc = "A commercialized shelf for toys and associated items."
@@ -139,308 +151,119 @@
// -------------------------------------------------
/obj/structure/cash_register/commissary
- var/machine_id = ""
- var/list/items = list()
- var/list/items_to_price = list()
- var/list/buying = list()
- var/new_item = ""
- var/new_price = 0
- var/sum = 0
- var/editmode = FALSE
- var/receipt = ""
- var/destinationact = "Operations"
- var/credit = 100
- var/shop_name = "Commissary"
storage_type = null
+ req_one_access = list(ACCESS_BAR, ACCESS_GALLEY, ACCESS_CARGO)
+ var/destination = "Operations"
/obj/structure/cash_register/commissary/mechanics_hints(mob/user, distance, is_adjacent)
. = list()
- . += "Alt click with a command id in hand, to gain command access."
- . += "Alt click with credits in hand, to deposit them."
- . += "Alt click while having operations access, to withdraw credits from it."
+ . += "Alt-click with credits in hand, to deposit them."
+ . += "Alt-click while having the proper 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()
. = ..()
- machine_id = "[station_name()] Idris Quik-Pay Register #[SSeconomy.num_financial_terminals++]"
+ src.LoadComponent(/datum/component/quikpay_shop, req_one_access, destination)
/obj/structure/cash_register/commissary/AltClick(var/mob/user)
- var/item = user.get_active_hand()
- var/obj/item/card/id/I = item
- if(istype(I) && (ACCESS_HEADS in I.access))
- if(ACCESS_HEADS in I.access)
- editmode = TRUE
- to_chat(user, SPAN_NOTICE("Command access granted."))
- SStgui.update_uis(src)
+ . = ..()
+ var/datum/component/quikpay_shop/qp_shop = src.GetComponent(/datum/component/quikpay_shop)
+ if(!qp_shop)
return
- if(istype(item, /obj/item/spacecash) && !istype(item, /obj/item/spacecash/ewallet))
- var/obj/item/spacecash/cashmoney = item
- credit += cashmoney.worth
- user.drop_from_inventory(cashmoney,get_turf(src))
- visible_message("\The [user] inserts some credits into \the [src]." )
- qdel(cashmoney)
- return
- I = user.GetIdCard()
- if(istype(I) && (ACCESS_CARGO in I.access))
- var/price_guess = text2num(sanitizeSafe( tgui_input_text(user, "How much do you wish to withdraw? Remaining credits: [credit]电", "QuikPay", 0, 10), 10))
- if(isnull(price_guess) || price_guess == 0)
- return
- price_guess = max(0, round(price_guess, 0.01))
- if(credit >= price_guess)
- spawn_money(price_guess, loc, user)
- credit -= price_guess
- visible_message("\The [user] remove some credits from \the [src]." )
- return
-
-/obj/structure/cash_register/commissary/proc/print_receipt()
- var/obj/item/paper/notepad/receipt/R = new(loc)
- var/receiptname = "Receipt: [machine_id]"
- R.set_content_unsafe(receiptname, receipt, sum)
-
- //stamp the paper
- var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
- stampoverlay.icon_state = "paper_stamp-hop"
- if(!R.stamped)
- R.stamped = new
- R.stamped += /obj/item/stamp
- R.AddOverlays(stampoverlay)
- R.stamps += "
This paper has been stamped by the Idris Quik-Pay Register."
- usr.put_in_any_hand_if_possible(R)
- R.ripped = TRUE
+ qp_shop.take_give_credits(user, loc)
/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)
+ . = ..()
+ var/datum/component/quikpay_shop/qp_shop = src.GetComponent(/datum/component/quikpay_shop)
+ if(!qp_shop)
return
- if(sum == 0)
- return
- if (istype(attacking_item, /obj/item/spacecash/ewallet))
- card_pay(attacking_item, user)
- return
- else if (istype(attacking_item, /obj/item/card/id))
- ID_pay(attacking_item, user)
- return
- else if(istype(attacking_item, /obj/item/spacecash))
- cash_pay(attacking_item, user)
- return
-
-/obj/structure/cash_register/commissary/proc/cash_pay(obj/item/spacecash/cashmoney, mob/user)
- var/transaction_amount = sum
- if(transaction_amount > cashmoney.worth)
- to_chat(user, SPAN_WARNING("[icon2html(cashmoney, user)] That is not enough money."))
- return 0
- if(istype(cashmoney, /obj/item/spacecash/bundle))
- visible_message(SPAN_INFO("\The [user] inserts some cash into \the [src]."))
- var/obj/item/spacecash/bundle/cashmoney_bundle = cashmoney
- cashmoney_bundle.worth -= transaction_amount
-
- if(cashmoney_bundle.worth <= 0)
- usr.drop_from_inventory(cashmoney_bundle,get_turf(src))
- qdel(cashmoney_bundle)
- else
- cashmoney_bundle.update_icon()
- else
- visible_message(SPAN_INFO("\The [user] inserts a bill into \the [src]."))
- var/left = cashmoney.worth - transaction_amount
- user.drop_from_inventory(cashmoney,get_turf(src))
- qdel(cashmoney)
-
- if(left)
- spawn_money(left, get_turf(user), user)
- credit += transaction_amount
- print_receipt()
- clear_order()
- return 1
-
-/obj/structure/cash_register/commissary/proc/ID_pay(obj/item/attacking_item, mob/user)
- var/obj/item/card/id/I = attacking_item.GetID()
- var/transaction_amount = sum
- var/transaction_purpose = "[destinationact] Payment"
- var/transaction_terminal = machine_id
-
- var/transaction = SSeconomy.transfer_money(I.associated_account_number, SSeconomy.get_department_account(destinationact)?.account_number,transaction_purpose,transaction_terminal,transaction_amount,null,usr)
-
- if(transaction)
- to_chat(user, SPAN_NOTICE("[icon2html(src, user)][transaction]."))
- else
- 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 = ""
- to_chat(user, SPAN_NOTICE("Transaction completed, please return to the home screen."))
- clear_order()
-
-/obj/structure/cash_register/commissary/proc/card_pay(obj/item/attacking_item, mob/user)
- var/obj/item/spacecash/ewallet/E = attacking_item
- var/transaction_amount = sum
- var/transaction_purpose = "[destinationact] Payment"
- var/transaction_terminal = machine_id
-
- if(transaction_amount <= E.worth)
- SSeconomy.charge_to_account(SSeconomy.get_department_account(destinationact)?.account_number, E.owner_name, transaction_purpose, transaction_terminal, transaction_amount)
- 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)
- print_receipt()
- sum = 0
- receipt = ""
- to_chat(user, SPAN_NOTICE("Transaction completed, please return to the home screen."))
- clear_order()
- else if (transaction_amount > E.worth)
- 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)
+ qp_shop.interact_object(attacking_item, user)
/obj/structure/cash_register/commissary/attack_hand(mob/living/user)
. = ..()
- ui_interact(user)
-
-/obj/structure/cash_register/commissary/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "QuikPay", "Idris Quik-Pay Register", 550, 550)
- ui.open()
-
-/obj/structure/cash_register/commissary/ui_data(var/mob/user)
- var/list/data = list()
-
- data["items"] = items
- data["buying"] = buying
- data["sum"] = sum
- data["new_item"] = new_item
- data["new_price"] = new_price
- data["editmode"] = editmode
- data["destinationact"] = destinationact
-
- return data
-
-/obj/structure/cash_register/commissary/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
- . = ..()
- if(.)
+ var/datum/component/quikpay_shop/qp_shop = src.GetComponent(/datum/component/quikpay_shop)
+ if(!qp_shop)
return
- switch(action)
- if("add")
- if(!editmode)
- balloon_alert(usr, "device locked!")
- return FALSE
+ qp_shop.ui_interact(user)
- items += list(list("name" = new_item, "price" = new_price))
- items_to_price[new_item] = new_price
- . = TRUE
+/obj/machinery/commissary_wall_shop
+ name = "self-serve shop teller"
+ desc = "An ordering terminal designed by Idris for quicker expedition."
+ icon = 'icons/obj/machinery/wall/terminals.dmi'
+ icon_state = "orderterminal"
+ idle_power_usage = 10
+ anchored = TRUE
+ var/turned_on = FALSE
+ req_one_access = list(ACCESS_BAR, ACCESS_GALLEY, ACCESS_CARGO)
+ var/destination = "Operations"
- if("remove")
- if(!editmode)
- balloon_alert(usr, "device locked!")
- return FALSE
- var/index = 0
- for(var/list/L in items)
- index++
- if(L["name"] == params["removing"])
- items.Cut(index, index+1)
- . = TRUE
+/obj/machinery/commissary_wall_shop/mechanics_hints(mob/user, distance, is_adjacent)
+ . += ..()
+ . += "Items can be paid for with id cards or charge cards, and a receipt will be printed."
+ . += "The terminal can print a paper which can be used to quickly fill it out in the future by using it on the register."
+ . += "With the proper access, ctrl-click to turn the machine on and off."
- if("set_new_price")
- new_price = params["set_new_price"]
- . = TRUE
+/obj/machinery/commissary_wall_shop/Initialize()
+ . = ..()
+ src.LoadComponent(/datum/component/quikpay_shop/orderterminal, req_one_access, destination)
+ update_icon()
- if("set_new_item")
- new_item = params["set_new_item"]
- . = TRUE
+/obj/machinery/commissary_wall_shop/attackby(obj/item/attacking_item, mob/user)
+ if(!turned_on)
+ balloon_alert(user, "turned off")
+ return
+ if(stat & NOPOWER)
+ balloon_alert(user, "no power")
+ return
+ var/datum/component/quikpay_shop/orderterminal/qp_shop = src.GetComponent(/datum/component/quikpay_shop/orderterminal)
+ if(!qp_shop)
+ return
+ qp_shop.interact_object(attacking_item, user)
- if("clear")
- clear_order()
- . = TRUE
+/obj/machinery/commissary_wall_shop/attack_hand(mob/living/user)
+ if(!turned_on)
+ balloon_alert(user, "turned off")
+ return
+ if(stat & NOPOWER)
+ balloon_alert(user, "no power")
+ return
+ var/datum/component/quikpay_shop/orderterminal/qp_shop = src.GetComponent(/datum/component/quikpay_shop/orderterminal)
+ if(!qp_shop)
+ return
+ qp_shop.ui_interact(user)
- if("buy")
- for(var/list/L in buying)
- if(L["name"] == params["buying"])
- L["amount"]++
- return TRUE
- buying += list(list("name" = params["buying"], "amount" = params["amount"], "price" = items_to_price[params["buying"]]))
+/obj/machinery/commissary_wall_shop/CtrlClick(mob/user)
+ var/obj/item/card/id/I = user.GetIdCard()
+ if(!istype(I))
+ balloon_alert(user, "no id!")
+ return
+ if(!has_access(req_one_access = src.req_one_access, accesses = I.access))
+ balloon_alert(user, "no access!")
+ return
+ turned_on = !turned_on
+ balloon_alert(user, "turned [turned_on ? "on" : "off"]")
+ update_icon()
- if("removal")
- var/index = 0
- for(var/list/L in buying)
- index++
- if(L["name"] == params["removal"])
- if(L["amount"] > 1)
- L["amount"]--
- else
- buying.Cut(index, index+1)
- . = TRUE
+/obj/machinery/commissary_wall_shop/power_change()
+ ..()
+ update_icon()
- if("confirm")
- // Ensuring it is clear, in case the button is clicked multiple times
- receipt = ""
- sum = 0
- var/obj/item/card/id/id_card = usr.GetIdCard()
- var/cashier = id_card? id_card.registered_name : "Unknown"
- receipt = "[shop_name] receipt
Today's date: [worlddate2text()]
Cashier: [cashier]
Purchased items:"
- for(var/list/bought_item in buying)
- var/item_name = bought_item["name"]
- var/item_amount = bought_item["amount"]
- var/item_price = items_to_price[item_name]
+/obj/machinery/commissary_wall_shop/update_icon()
+ ClearOverlays()
+ if(stat & NOPOWER || !turned_on)
+ set_light(FALSE)
+ return
- receipt += "- [item_name]: [item_amount] x [item_price]电: [item_amount * item_price]电
"
- sum += item_price * item_amount
+ var/mutable_appearance/screen_overlay = mutable_appearance(icon, "kitchenterminal-active", plane = ABOVE_LIGHTING_PLANE)
+ AddOverlays(screen_overlay)
+ set_light(1.4, 1, COLOR_CYAN)
- receipt += "
Total: [sum]电
"
- playsound(src, 'sound/machines/ping.ogg', 25, 1)
- audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] pings."))
- . = TRUE
-
- if("locking")
- if(editmode)
- editmode = FALSE
- balloon_alert(usr, "device locked!")
- else
- if(!editmode)
- var/obj/item/card/id/I = usr.GetIdCard()
- if(!istype(I))
- return
- if(check_access(I))
- editmode = !editmode
- balloon_alert(usr, "device [editmode ? "un" : ""]locked")
- . = TRUE
-
- if("accountselect")
- if(!editmode)
- 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
- . = 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()
- sum = 0
- receipt = ""
+/obj/machinery/commissary_wall_shop/process()
+ if(stat & NOPOWER || !turned_on)
+ ClearOverlays()
+ set_light(FALSE)
+ return
/obj/item/commissary_restrock
name = "commissary cigarette restock pack"
@@ -701,6 +524,17 @@
desc = "A crate packed with boxes of various goods. Handle with care!"
/obj/structure/closet/crate/commissary/fill()
+ for(var/i = 1 to 8)
+ new /obj/item/storage/box/unique/papersack(src)
+ new /obj/item/storage/bag/plasticbag(src)
+ new /obj/item/storage/box/plasticbag(src)
+ new /obj/item/tape_roll(src)
+ new /obj/item/hand_labeler(src)
+ new /obj/item/storage/toolbox/mechanical(src)
+
+/obj/structure/closet/crate/commissary/resupply
+
+/obj/structure/closet/crate/commissary/resupply/fill()
new /obj/item/commissary_restrock(src)
new /obj/item/commissary_restrock/rollable(src)
new /obj/item/commissary_restrock/chewable(src)
diff --git a/code/modules/cooking/machinery/smartfridge.dm b/code/modules/cooking/machinery/smartfridge.dm
index 31957f5890e..19447520bc9 100644
--- a/code/modules/cooking/machinery/smartfridge.dm
+++ b/code/modules/cooking/machinery/smartfridge.dm
@@ -20,6 +20,7 @@
var/scan_id = 1
var/is_secure = 0
var/machineselect = 0
+ var/visible_takeout = FALSE
var/list/accepted_items = list(/obj/item/reagent_containers/food/snacks/grown, /obj/item/seeds, /obj/item/mollusc)
/// List of items that the machine starts with upon spawn
@@ -536,15 +537,20 @@
var/i = amount
for(var/obj/O in contents)
- if(O.name == K)
- if(Adjacent(user))
- user.put_in_hands(O)
- else
- O.forceMove(loc)
- i--
- update_overlays()
- if(i <= 0)
- break
+ if(O.name != K)
+ continue
+ if(Adjacent(user))
+ user.put_in_hands(O)
+ if(visible_takeout)
+ user.visible_message(
+ "[SPAN_BOLD("[user]")] takes \a [O] from \the [src].",
+ SPAN_NOTICE("You take \a [O] from \the [src]."))
+ else
+ O.forceMove(loc)
+ i--
+ update_overlays()
+ if(i <= 0)
+ break
if(item_quants[K] <= 0)
update_static_data_for_all_viewers()
diff --git a/code/modules/economy/OrderTerminal.dm b/code/modules/economy/OrderTerminal.dm
index 9df4983d1a6..d5b1dd8779d 100644
--- a/code/modules/economy/OrderTerminal.dm
+++ b/code/modules/economy/OrderTerminal.dm
@@ -21,16 +21,16 @@
var/ticket = ""
var/destinationact = "Service"
var/ticket_number = 1
- req_one_access = list(ACCESS_BAR, ACCESS_GALLEY) // Access to change the menu
+ req_one_access = list(ACCESS_BAR, ACCESS_GALLEY, ACCESS_CARGO) // Access to change the menu
/obj/machinery/orderterminal/mechanics_hints(mob/user, distance, is_adjacent)
. += ..()
- . += "To edit the menu, select 'Toggle Lock' while wearing an ID with galley access."
- . += "All credits from the machine will automatically go to the civilian account."
+ . += "Items can be paid for with id cards or charge cards, and a receipt will be printed."
+ . += "The terminal can print a paper which can be used to quickly fill it out in the future by using it on the register."
/obj/machinery/orderterminal/Initialize()
. = ..()
- machine_id = "Idris Ordering Terminal #[SSeconomy.num_financial_terminals++]"
+ src.LoadComponent(/datum/component/quikpay_shop/orderterminal/food, req_one_access, destinationact)
update_icon()
/obj/machinery/orderterminal/power_change()
@@ -54,152 +54,19 @@
return
/obj/machinery/orderterminal/attack_hand(var/mob/user)
- ui_interact(user)
-
-/obj/machinery/orderterminal/ui_interact(mob/user, var/datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "OrderTerminal", "Idris Ordering Terminal", 450, 450)
- ui.open()
-
-/obj/machinery/orderterminal/proc/print_receipt() // Print the receipt followed by the order ticket
- var/obj/item/paper/notepad/receipt/R = new(usr.loc)
- var/receiptname = "Receipt: [machine_id]"
- R.set_content_unsafe(receiptname, receipt, sum)
- stamp_receipt(R)
- // And now we do it but for the ticket.
- var/obj/item/paper/notepad/receipt/T = new(usr.loc)
- var/tickettname = "Order ticket: [ticket_number]"
- ticket_number++
- T.set_content_unsafe(tickettname, ticket, sum)
- stamp_receipt(T)
-
-/obj/machinery/orderterminal/proc/stamp_receipt(obj/item/paper/R) // Stamps the papers, made into a proc to avoid copy pasting too much
- var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
- stampoverlay.icon_state = "paper_stamp-hop"
- if(!R.stamped)
- R.stamped = new
- R.stamped += /obj/item/stamp
- R.AddOverlays(stampoverlay)
- R.stamps += "
This paper has been stamped by the Idris Ordering Terminal."
- R.ripped = TRUE
+ if(stat & NOPOWER)
+ balloon_alert(user, "no power")
+ return
+ var/datum/component/quikpay_shop/orderterminal/food/qp_shop = src.GetComponent(/datum/component/quikpay_shop/orderterminal/food)
+ if(!qp_shop)
+ return
+ qp_shop.ui_interact(user)
/obj/machinery/orderterminal/attackby(obj/item/attacking_item, mob/user)
- var/obj/item/card/id/I = attacking_item.GetID()
- if (!I)
+ if(stat & NOPOWER)
+ balloon_alert(user, "no power")
return
- if (!istype(attacking_item))
+ var/datum/component/quikpay_shop/orderterminal/food/qp_shop = src.GetComponent(/datum/component/quikpay_shop/orderterminal/food)
+ if(!qp_shop)
return
-
- else if (confirmorder)
- var/transaction_amount = sum
- var/transaction_purpose = "Idris Ordering Terminal order."
- var/transaction_terminal = machine_id
- if(sum > 0) // it will just get denied if the order is 0 credits. We still need the id regardless for the name
- var/transaction = SSeconomy.transfer_money(I.associated_account_number, SSeconomy.get_department_account(destinationact)?.account_number,transaction_purpose,transaction_terminal,transaction_amount,null,usr)
- if(transaction)
- to_chat(user,"[icon2html(src, user)][transaction].")
- else
- playsound(src, 'sound/machines/chime.ogg', 50, 1)
- src.visible_message("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")
- ticket += "
Customer: [I.registered_name]"
- receipt += "
Customer: [I.registered_name]"
- print_receipt()
- clear_order()
-
-/obj/machinery/orderterminal/ui_data(mob/user)
- var/list/data = list()
-
- data["items"] = items
- data["buying"] = buying
- data["sum"] = sum
- data["new_item"] = new_item
- data["new_price"] = new_price
- data["editmode"] = editmode
- data["destinationact"] = destinationact
-
- return data
-
-/obj/machinery/orderterminal/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
- . = ..()
- if(.)
- return
-
- switch(action)
- if("add")
- if(!editmode)
- to_chat(usr, SPAN_NOTICE("You don't have access to use this option."))
- return FALSE
- items += list(list("name" = new_item, "price" = new_price))
- items_to_price[new_item] = new_price
- . = TRUE
-
- if("remove")
- if(!editmode)
- to_chat(usr, SPAN_NOTICE("You don't have access to use this option."))
- return FALSE
- items -= params["remove"]
- items_to_price -= params["remove"]
- . = TRUE
-
- if("buy")
- for(var/list/L in buying)
- if(L["name"] == params["buying"])
- L["amount"]++
- return TRUE
- buying += list(list("name" = params["buying"], "amount" = params["amount"]))
- . = TRUE
-
- if("removal")
- for(var/list/L in buying)
- if(L["name"] == params["removal"])
- if(L["amount"] > 1)
- L["amount"]--
- else
- buying -= L
- . = TRUE
-
- if("clear")
- clear_order()
- . = TRUE
-
- if("set_new_price")
- new_price = params["set_new_price"]
- . = TRUE
-
- if("set_new_item")
- new_item = params["set_new_item"]
- . = TRUE
-
- if("confirm")
- confirmorder = TRUE
- receipt += "Idris Food Terminal Receipt
"
- ticket += "Idris Food Terminal Ticket
"
- for(var/list/bought_item in buying)
- var/item_name = bought_item["name"]
- var/item_amount = bought_item["amount"]
- var/item_price = items_to_price[item_name]
- sum += item_price
-
- receipt += "[name]: [item_name] x[item_amount] at [item_price]电 each
"
- ticket += "[name]: [item_name] x[item_amount] at [item_price]电 each
"
- receipt += "
Total: [sum]电"
- ticket += "
Total: [sum]电"
- sum = sum
- . = TRUE
-
- if("locking")
- var/obj/item/card/id/I = usr.GetIdCard()
- if(!istype(I))
- return
- if(check_access(I))
- editmode = !editmode
- to_chat(usr, SPAN_NOTICE("Device [editmode ? "un" : ""]locked."))
- . = TRUE
-
-/obj/machinery/orderterminal/proc/clear_order()
- buying.Cut()
- sum = 0
- receipt = ""
- ticket = ""
- confirmorder = FALSE
+ qp_shop.interact_object(attacking_item, user)
diff --git a/code/modules/economy/quikpay.dm b/code/modules/economy/quikpay.dm
index a3c3c01c667..3e29362b030 100644
--- a/code/modules/economy/quikpay.dm
+++ b/code/modules/economy/quikpay.dm
@@ -8,36 +8,31 @@
item_state = "electronic"
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_BELT
- var/machine_id = ""
- var/list/items = list()
- var/list/items_to_price = list()
- var/list/buying = list()
- var/new_item = ""
- var/new_price = 0
- var/sum = 0
- var/editmode = FALSE
- var/receipt = ""
var/destinationact = "Service"
- var/shop_name = "Quikpay"
+ var/shop_name
+ req_one_access = list(ACCESS_BAR, ACCESS_GALLEY, ACCESS_CARGO)
+
+/obj/item/quikpay/mechanics_hints(mob/user, distance, is_adjacent)
+ . += ..()
+ . += "Items can be paid for with id cards or charge cards, and a receipt will be printed."
+ . += "The quikpay can print a paper which can be used to quickly fill it out in the future by using it on the register."
/obj/item/quikpay/Initialize()
. = ..()
- machine_id = "[station_name()] Idris Quik-Pay #[SSeconomy.num_financial_terminals++]"
+ src.LoadComponent(/datum/component/quikpay_shop/quikpay, req_one_access, destinationact)
//create a short manual as well
var/obj/item/paper/R = new(src.loc)
R.name = "Quik And Easy: How to make a transaction"
R.info += "Quik-Pay setup:
"
- R.info += "- Remember your access code included on the paper that is included with your device
"
R.info += "- Unlock it to be able to add items to the menu
"
- R.info += "- Add items to the menu by typing the item name and its price
"
+ R.info += "Add items to the menu by typing the item name and its price, optionally include a category"
R.info += "When starting a new transaction:
"
R.info += "- Have the customer enter the amount of the item they want and then confirm the purchase.
"
R.info += "- Allow them to review the sum.
"
R.info += "- Have them swipe their card to pay for the items.
"
-
//stamp the paper
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
stampoverlay.icon_state = "paper_stamp-cent"
@@ -50,238 +45,24 @@
R.AddOverlays(stampoverlay)
R.stamps += "
This paper has been stamped by the Executive Officer's desk."
-/obj/item/quikpay/AltClick(var/mob/user)
- var/obj/item/card/id/I = user.GetIdCard()
- if(istype(I) && (ACCESS_HEADS in I.access))
- editmode = TRUE
- to_chat(user, SPAN_NOTICE("Command access granted."))
- SStgui.update_uis(src)
-
-/obj/item/quikpay/proc/print_receipt()
- var/obj/item/paper/notepad/receipt/R = new(usr.loc)
- var/receiptname = "Receipt: [machine_id]"
- R.set_content_unsafe(receiptname, receipt, sum)
-
- //stamp the paper
- var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
- stampoverlay.icon_state = "paper_stamp-hop"
- if(!R.stamped)
- R.stamped = new
- R.stamped += /obj/item/stamp
- R.AddOverlays(stampoverlay)
- R.stamps += "
This paper has been stamped by the Quik-Pay device."
- R.ripped = TRUE
- 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)
+ . = ..()
+ var/datum/component/quikpay_shop/quikpay/qp_shop = src.GetComponent(/datum/component/quikpay_shop/quikpay)
+ if(!qp_shop)
return
- if (istype(attacking_item, /obj/item/spacecash/ewallet))
- var/obj/item/spacecash/ewallet/E = attacking_item
- var/transaction_amount = sum
- var/transaction_purpose = "[destinationact] Payment"
- 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)
-
- SSeconomy.charge_to_account(SSeconomy.get_department_account(destinationact)?.account_number, E.owner_name, transaction_purpose, transaction_terminal, transaction_amount)
- E.worth -= transaction_amount
- print_receipt()
- sum = 0
- receipt = ""
- to_chat(user, SPAN_NOTICE("Transaction completed, please return to the home screen."))
- else if (transaction_amount > E.worth)
- to_chat(user, SPAN_WARNING("[icon2html(src, user)]\The [E] doesn't have that much money!"))
- return
-
- var/obj/item/card/id/I = attacking_item.GetID()
- if (!istype(attacking_item))
- return
-
- var/transaction_amount = sum
- var/transaction_purpose = "[destinationact] Payment"
- var/transaction_terminal = machine_id
-
- var/transaction = SSeconomy.transfer_money(I.associated_account_number, SSeconomy.get_department_account(destinationact)?.account_number,transaction_purpose,transaction_terminal,transaction_amount,null,usr)
-
- 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)
- 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)
+ qp_shop.interact_object(attacking_item, user)
/obj/item/quikpay/attack_self(var/mob/user)
- ui_interact(user)
-
-/obj/item/quikpay/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "QuikPay", "Idris Quik-Pay", 550, 550)
- ui.open()
-
-/obj/item/quikpay/ui_data(var/mob/user)
- var/list/data = list()
-
- data["items"] = items
- data["buying"] = buying
- data["sum"] = sum
- data["new_item"] = new_item
- data["new_price"] = new_price
- data["editmode"] = editmode
- data["destinationact"] = destinationact
-
- return data
-
-/obj/item/quikpay/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
- if(.)
+ var/datum/component/quikpay_shop/quikpay/qp_shop = src.GetComponent(/datum/component/quikpay_shop/quikpay)
+ if(!qp_shop)
return
-
- switch(action)
- if("add")
- if(!editmode)
- balloon_alert(usr, "device locked!")
- return FALSE
-
- items += list(list("name" = new_item, "price" = new_price))
- items_to_price[new_item] = new_price
- . = TRUE
-
- if("remove")
- if(!editmode)
- balloon_alert(usr, "device locked!")
- return FALSE
- var/index = 0
- for(var/list/L in items)
- index++
- if(L["name"] == params["removing"])
- items.Cut(index, index+1)
- . = TRUE
-
- if("set_new_price")
- new_price = params["set_new_price"]
- . = TRUE
-
- if("set_new_item")
- new_item = params["set_new_item"]
- . = TRUE
-
- if("clear")
- clear_order()
- . = TRUE
-
- if("buy")
- for(var/list/L in buying)
- if(L["name"] == params["buying"])
- L["amount"]++
- return TRUE
- buying += list(list("name" = params["buying"], "amount" = params["amount"], "price" = items_to_price[params["buying"]]))
-
- if("removal")
- var/index = 0
- for(var/list/L in buying)
- index++
- if(L["name"] == params["removal"])
- if(L["amount"] > 1)
- L["amount"]--
- else
- buying.Cut(index, index+1)
- . = TRUE
-
- if("confirm")
- // Ensuring it is clear, in case the button is clicked multiple times
- receipt = ""
- sum = 0
- var/obj/item/card/id/id_card = usr.GetIdCard()
- var/cashier = id_card? id_card.registered_name : "Unknown"
- receipt = "[shop_name] receipt
Today's date: [worlddate2text()]
Cashier: [cashier]
Purchased items:"
- for(var/list/bought_item in buying)
- var/item_name = bought_item["name"]
- var/item_amount = bought_item["amount"]
- var/item_price = items_to_price[item_name]
-
- receipt += "- [item_name]: [item_amount] x [item_price]电: [item_amount * item_price]电
"
- sum += item_price * item_amount
-
- receipt += "
Total: [sum]电
"
- playsound(src, 'sound/machines/ping.ogg', 25, 1)
- audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] pings."))
- . = TRUE
-
- if("locking")
- if(editmode)
- editmode = FALSE
- balloon_alert(usr, "device locked!")
- else
- if(!editmode)
- var/obj/item/card/id/I = usr.GetIdCard()
- if(!istype(I))
- return
- if(check_access(I))
- editmode = !editmode
- to_chat(usr, SPAN_NOTICE("Device [editmode ? "un" : ""]locked."))
- . = TRUE
-
- if("accountselect")
- if(!editmode)
- 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
- . = 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()
- sum = 0
- receipt = ""
+ qp_shop.ui_interact(user)
/obj/item/quikpay/afterattack(atom/target, mob/user, proximity)
if (!proximity) return
- if (!istype(target, /obj))
+
+ var/datum/component/quikpay_shop/quikpay/qp_shop = src.GetComponent(/datum/component/quikpay_shop/quikpay)
+ if(!qp_shop)
return
- if (!editmode)
- to_chat(user, SPAN_NOTICE("Unlock \the [src] to add items."))
- return
-
- var/obj/O = target
- var/name_guess = O.name
- var/price_guess = 0
-
- price_guess = text2num(sanitizeSafe( tgui_input_text(user, "Set price for [name_guess]:", "QuikPay", 0, 10), 10))
- if(isnull(price_guess) || price_guess == 0)
- return
- price_guess = max(0, round(price_guess, 0.01))
-
- items += list(list("name" = "[name_guess]", "price" = price_guess))
- items_to_price[name_guess] = price_guess
-
- to_chat(user, SPAN_NOTICE("[src]: added '[name_guess]' for [price_guess]."))
+ qp_shop.add_item(target, user)
diff --git a/html/changelogs/CommissaryChanges.yml b/html/changelogs/CommissaryChanges.yml
new file mode 100644
index 00000000000..743518a6308
--- /dev/null
+++ b/html/changelogs/CommissaryChanges.yml
@@ -0,0 +1,13 @@
+author: TheGreyWolf
+
+delete-after: True
+
+changes:
+ - bugfix: "Fixed that the quikpay and cash register prices could be wrong."
+ - rscadd: "The commissary register now has categories."
+ - refactor: "Changed the commissary and quikpay to rely on a component, making them easier to maintan and ensuring they function almost identical."
+ - rscadd: "The commissary now has a wall terminal, that can be enabled by hangar technicians."
+ - bugfix: "The noticeboard in operations is now properly on one side of the wall, instead of on the wall turf itself."
+ - rscadd: "The food and drink fridges in the commissary can now be renamed."
+ - rscadd: "The shelves in the commissary now has a message when an item are taken from them."
+ - rscadd: "The quick-e-meals vendor was readded behind the café."
diff --git a/icons/obj/machinery/wall/terminals.dmi b/icons/obj/machinery/wall/terminals.dmi
index 41a5b5fe63b..08286b10cae 100644
Binary files a/icons/obj/machinery/wall/terminals.dmi and b/icons/obj/machinery/wall/terminals.dmi differ
diff --git a/maps/sccv_horizon/sccv_horizon.dmm b/maps/sccv_horizon/sccv_horizon.dmm
index fce8db4516b..f5dec896418 100644
--- a/maps/sccv_horizon/sccv_horizon.dmm
+++ b/maps/sccv_horizon/sccv_horizon.dmm
@@ -1304,8 +1304,10 @@
/obj/effect/floor_decal/corner/dark_green{
dir = 10
},
-/obj/structure/extinguisher_cabinet/south,
-/obj/machinery/light/floor,
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable/green{
+ icon_state = "1-2"
+ },
/turf/simulated/floor/tiled,
/area/horizon/hallway/primary/deck_2/central)
"agD" = (
@@ -1322,8 +1324,10 @@
/turf/simulated/floor/tiled/dark,
/area/horizon/storage/eva)
"agL" = (
-/obj/structure/closet/crate/commissary,
-/turf/simulated/floor/tiled/dark/full,
+/obj/effect/floor_decal/spline/plain/lime{
+ dir = 9
+ },
+/turf/simulated/floor/tiled/dark,
/area/horizon/operations/commissary)
"agP" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
@@ -1343,6 +1347,7 @@
/area/horizon/hangar/intrepid)
"agU" = (
/obj/machinery/smartfridge/tradeshelf/clothing,
+/obj/machinery/firealarm/west,
/turf/simulated/floor/tiled/full,
/area/horizon/operations/commissary)
"agV" = (
@@ -3465,10 +3470,21 @@
/turf/unsimulated/floor/plating,
/area/antag/mercenary)
"auR" = (
-/obj/structure/table/rack/retail_shelf,
-/obj/machinery/light,
-/turf/simulated/floor/tiled/full,
-/area/horizon/operations/commissary)
+/obj/machinery/atmospherics/pipe/simple/hidden/supply{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ icon_state = "pipe-c"
+ },
+/obj/structure/cable/green{
+ icon_state = "2-8"
+ },
+/obj/structure/lattice/catwalk/indoor/grate,
+/turf/simulated/floor/plating,
+/area/horizon/hallway/primary/deck_2/central)
"auT" = (
/obj/structure/platform/ledge{
dir = 1
@@ -4906,6 +4922,20 @@
},
/turf/simulated/open,
/area/horizon/maintenance/deck_2/main/starboard)
+"aEx" = (
+/obj/structure/table/reinforced/steel,
+/obj/machinery/door/window/desk/northright{
+ req_one_access = list(26,29,31,48,67,35,25,28,37)
+ },
+/obj/machinery/door/firedoor{
+ req_one_access = list(24,11,67,73)
+ },
+/obj/machinery/door/blast/shutters{
+ dir = 2;
+ id = "horizon_commissary_desk"
+ },
+/turf/simulated/floor/tiled/dark/full,
+/area/horizon/operations/commissary)
"aEz" = (
/obj/effect/floor_decal/corner/dark_green{
dir = 1
@@ -6913,15 +6943,13 @@
/turf/simulated/floor/tiled,
/area/horizon/operations/mining_main/refinery)
"aRD" = (
-/obj/structure/bed/stool/chair{
- dir = 4
+/obj/structure/lattice/catwalk/indoor/grate/dark,
+/obj/structure/cable/green{
+ icon_state = "1-2"
},
-/obj/machinery/alarm/west,
-/obj/effect/floor_decal/corner/dark_blue{
- dir = 9
- },
-/turf/simulated/floor/tiled,
-/area/horizon/security/lobby)
+/obj/structure/disposalpipe/segment,
+/turf/simulated/floor/plating,
+/area/horizon/maintenance/deck_2/service/port)
"aRE" = (
/obj/structure/heavy_vehicle_frame,
/obj/machinery/mech_recharger,
@@ -7531,10 +7559,11 @@
/obj/machinery/light{
dir = 1
},
-/obj/effect/floor_decal/corner/dark_blue{
- dir = 5
- },
/obj/structure/reagent_dispensers/water_cooler,
+/obj/effect/floor_decal/corner/dark_blue/full{
+ dir = 8
+ },
+/obj/machinery/newscaster/west,
/turf/simulated/floor/tiled,
/area/horizon/security/lobby)
"aVW" = (
@@ -12763,10 +12792,11 @@
/turf/unsimulated/floor,
/area/centcom/legion/hangar5)
"bFt" = (
-/obj/machinery/power/apc/east,
-/obj/structure/disposalpipe/segment,
-/obj/structure/cable/green,
/obj/structure/lattice/catwalk/indoor/grate/dark,
+/obj/structure/disposalpipe/segment,
+/obj/machinery/light/small/emergency{
+ dir = 4
+ },
/turf/simulated/floor/plating,
/area/horizon/maintenance/deck_2/service/port)
"bFC" = (
@@ -20990,6 +21020,16 @@
/turf/simulated/floor,
/area/tdome/tdome1)
"cMN" = (
+/obj/structure/bed/stool/chair{
+ dir = 4
+ },
+/obj/effect/floor_decal/corner/dark_blue{
+ dir = 9
+ },
+/obj/machinery/atmospherics/unary/vent_scrubber/on{
+ dir = 4
+ },
+/obj/machinery/alarm/west,
/turf/simulated/floor/tiled,
/area/horizon/security/lobby)
"cMP" = (
@@ -26924,18 +26964,20 @@
/turf/simulated/floor/airless,
/area/horizon/hangar/operations)
"dyf" = (
-/obj/structure/bed/stool/chair{
+/obj/machinery/power/apc/east,
+/obj/structure/cable/green{
+ icon_state = "0-8"
+ },
+/obj/effect/floor_decal/spline/plain/lime{
dir = 4
},
-/obj/structure/cable/green{
- icon_state = "0-4"
+/obj/structure/table/reinforced/steel,
+/obj/item/toy/comic/azmarian/issue_1,
+/obj/item/toy/comic/inspector{
+ pixel_x = -4
},
-/obj/effect/floor_decal/corner/dark_blue{
- dir = 9
- },
-/obj/machinery/power/apc/low/west,
-/turf/simulated/floor/tiled,
-/area/horizon/security/lobby)
+/turf/simulated/floor/tiled/dark,
+/area/horizon/operations/commissary)
"dyi" = (
/obj/structure/tank_wall{
icon_state = "m-10"
@@ -30431,10 +30473,19 @@
/turf/simulated/floor/tiled,
/area/horizon/rnd/hallway/secondary)
"dWE" = (
-/obj/random/junk,
+/obj/machinery/door/airlock/maintenance{
+ dir = 1;
+ req_one_access = list(12,26,29,31,48,67,35,25,28,37)
+ },
/obj/structure/disposalpipe/segment,
-/obj/structure/lattice/catwalk/indoor/grate/dark,
-/turf/simulated/floor/plating,
+/obj/structure/cable/green{
+ icon_state = "1-2"
+ },
+/obj/effect/floor_decal/industrial/hatch_door/yellow{
+ dir = 8
+ },
+/obj/machinery/door/firedoor,
+/turf/simulated/floor/tiled/dark/full,
/area/horizon/maintenance/deck_2/service/port)
"dWF" = (
/obj/machinery/space_heater,
@@ -30830,17 +30881,16 @@
/turf/simulated/floor,
/area/horizon/maintenance/deck_3/cafe)
"dZA" = (
-/obj/machinery/door/firedoor{
- req_one_access = list(24,11,67,73);
- dir = 4
+/obj/effect/floor_decal/spline/plain/lime{
+ dir = 6
},
-/obj/effect/floor_decal/industrial/hatch_door/yellow,
-/obj/machinery/door/airlock/maintenance{
- dir = 4;
- name = "Commissary Maintenance";
- req_one_access = list(25,26,28,29,31,35,37,48,67)
+/obj/structure/noticeboard{
+ desc = "A board for uncovering hidden conspiracies.";
+ name = "corkboard";
+ pixel_x = 32
},
-/turf/simulated/floor/tiled/dark/full,
+/obj/item/modular_computer/console/preset/supply,
+/turf/simulated/floor/tiled/dark,
/area/horizon/operations/commissary)
"dZB" = (
/obj/random/tech_supply,
@@ -31501,10 +31551,7 @@
/obj/effect/floor_decal/corner/dark_green{
dir = 10
},
-/obj/structure/disposalpipe/segment,
-/obj/structure/cable/green{
- icon_state = "1-2"
- },
+/obj/machinery/light/floor,
/turf/simulated/floor/tiled,
/area/horizon/hallway/primary/deck_2/central)
"edo" = (
@@ -49334,9 +49381,11 @@
/area/horizon/operations/warehouse)
"gAF" = (
/obj/machinery/light,
-/obj/effect/floor_decal/corner/dark_blue{
- dir = 10
+/obj/structure/bed/stool/chair{
+ dir = 4
},
+/obj/effect/floor_decal/corner/dark_blue/full,
+/obj/machinery/firealarm/west,
/turf/simulated/floor/tiled,
/area/horizon/security/lobby)
"gAJ" = (
@@ -52972,12 +53021,16 @@
/turf/simulated/floor/tiled,
/area/horizon/engineering/hallway/aft)
"hab" = (
-/obj/structure/cable/green{
- icon_state = "4-8"
+/obj/effect/floor_decal/corner/dark_blue{
+ dir = 9
},
-/obj/machinery/atmospherics/unary/vent_scrubber/on{
+/obj/structure/bed/stool/chair{
dir = 4
},
+/obj/structure/cable/green{
+ icon_state = "0-4"
+ },
+/obj/machinery/power/apc/low/west,
/turf/simulated/floor/tiled,
/area/horizon/security/lobby)
"hap" = (
@@ -53907,6 +53960,9 @@
/obj/effect/floor_decal/corner/dark_green{
dir = 9
},
+/obj/machinery/light/floor{
+ dir = 8
+ },
/turf/simulated/floor/tiled,
/area/horizon/operations/commissary)
"hgn" = (
@@ -59280,10 +59336,7 @@
/turf/simulated/floor/tiled/dark/full,
/area/horizon/security/armoury)
"hPw" = (
-/obj/machinery/alarm/east,
-/obj/structure/disposalpipe/segment,
-/obj/structure/lattice/catwalk/indoor/grate/dark,
-/turf/simulated/floor/plating,
+/turf/simulated/wall,
/area/horizon/maintenance/deck_2/service/port)
"hPx" = (
/obj/machinery/light{
@@ -67028,10 +67081,6 @@
/turf/simulated/floor/tiled,
/area/horizon/hangar/operations)
"iSm" = (
-/obj/structure/disposalpipe/segment{
- icon_state = "pipe-c"
- },
-/obj/structure/lattice/catwalk/indoor/grate/dark,
/turf/simulated/floor/plating,
/area/horizon/maintenance/deck_2/service/port)
"iSo" = (
@@ -72391,20 +72440,8 @@
/turf/simulated/floor/tiled,
/area/horizon/hangar/intrepid)
"jEi" = (
-/obj/machinery/door/firedoor,
-/obj/structure/disposalpipe/segment,
-/obj/machinery/door/airlock/maintenance{
- dir = 1;
- req_one_access = list(12,26,29,31,48,67,35,25,28,37)
- },
-/obj/structure/cable/green{
- icon_state = "1-2"
- },
-/obj/effect/floor_decal/industrial/hatch_door/yellow{
- dir = 8
- },
-/turf/simulated/floor/tiled/dark/full,
-/area/horizon/hallway/primary/deck_2/central)
+/turf/simulated/wall/r_wall,
+/area/horizon/operations/commissary)
"jEl" = (
/obj/structure/lattice,
/obj/machinery/atmospherics/pipe/manifold/visible/red,
@@ -75021,13 +75058,6 @@
},
/turf/simulated/floor/wood,
/area/merchant_station/warehouse)
-"jWp" = (
-/obj/machinery/light{
- dir = 8
- },
-/obj/machinery/smartfridge/tradeshelf/food,
-/turf/simulated/floor/tiled/full,
-/area/horizon/operations/commissary)
"jWv" = (
/obj/structure/cable/green{
icon_state = "4-8"
@@ -75199,35 +75229,10 @@
/turf/simulated/floor/plating,
/area/horizon/operations/machinist)
"jXw" = (
-/obj/effect/floor_decal/spline/plain/lime{
- dir = 5
- },
-/obj/machinery/disposal/small/west,
-/obj/structure/closet/crate,
-/obj/item/storage/box/plasticbag,
-/obj/item/storage/box/unique/papersack,
-/obj/item/storage/box/unique/papersack,
-/obj/item/storage/box/unique/papersack,
-/obj/item/storage/box/unique/papersack,
-/obj/item/storage/box/unique/papersack,
-/obj/item/storage/box/unique/papersack,
-/obj/item/storage/box/unique/papersack,
-/obj/item/storage/box/unique/papersack,
-/obj/item/storage/box/plasticbag,
-/obj/item/storage/bag/plasticbag,
-/obj/item/storage/bag/plasticbag,
-/obj/item/storage/bag/plasticbag,
-/obj/item/storage/bag/plasticbag,
-/obj/item/storage/bag/plasticbag,
-/obj/item/storage/bag/plasticbag,
-/obj/item/storage/bag/plasticbag,
-/obj/item/storage/bag/plasticbag,
-/obj/machinery/power/apc/east,
-/obj/structure/disposalpipe/trunk,
/obj/structure/cable/green{
- icon_state = "0-2"
+ icon_state = "2-4"
},
-/obj/item/tape_roll,
+/obj/structure/disposalpipe/segment,
/turf/simulated/floor/tiled/dark,
/area/horizon/operations/commissary)
"jXA" = (
@@ -76253,12 +76258,13 @@
},
/area/centcom/control)
"kep" = (
-/obj/structure/table/rack/retail_shelf,
-/obj/item/hand_labeler,
-/obj/item/storage/toolbox/mechanical{
- pixel_y = 13
+/obj/effect/floor_decal/industrial/outline/operations,
+/obj/machinery/door/window/desk/southleft{
+ req_one_access = list(26,29,31,48,67,35,25,28,37)
},
-/obj/structure/window/reinforced,
+/obj/structure/crate_shelf,
+/obj/structure/closet/crate/commissary/resupply,
+/obj/structure/closet/crate/commissary,
/obj/machinery/door/blast/shutters{
dir = 2;
id = "horizon_commissary_desk"
@@ -77007,6 +77013,20 @@
},
/turf/simulated/floor/tiled/dark,
/area/horizon/rnd/xenoarch/storage)
+"kiP" = (
+/obj/structure/table/reinforced/steel,
+/obj/machinery/door/window/desk/northleft{
+ req_one_access = list(26,29,31,48,67,35,25,28,37)
+ },
+/obj/machinery/door/firedoor{
+ req_one_access = list(24,11,67,73)
+ },
+/obj/machinery/door/blast/shutters{
+ dir = 2;
+ id = "horizon_commissary_desk"
+ },
+/turf/simulated/floor/tiled/dark/full,
+/area/horizon/operations/commissary)
"kiT" = (
/obj/structure/shuttle_part/scc_space_ship{
icon_state = "d3-4-f"
@@ -86408,35 +86428,7 @@
/turf/simulated/floor/wood,
/area/horizon/repoffice/consular_one)
"lrG" = (
-/obj/effect/floor_decal/spline/plain/lime{
- dir = 4
- },
-/obj/machinery/button/remote/airlock{
- dir = 4;
- id = "horizon_commissary_door";
- name = "Commissary Door Bolts";
- pixel_x = 22;
- specialfunctions = 4;
- pixel_y = -2
- },
-/obj/machinery/button/remote/blast_door{
- dir = 4;
- id = "horizon_commissary_desk";
- name = "Desk Shutters";
- pixel_x = 22;
- pixel_y = 10
- },
-/obj/machinery/button/switch/holosign{
- id = "commissary";
- dir = 4;
- pixel_y = 1;
- pixel_x = 29
- },
/obj/machinery/hologram/holopad,
-/obj/machinery/light_switch/east{
- pixel_x = 29;
- pixel_y = 12
- },
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 10
},
@@ -95438,17 +95430,37 @@
/turf/simulated/floor,
/area/horizon/maintenance/deck_3/security/port)
"mEq" = (
-/obj/structure/sign/nosmoking_2{
- pixel_x = -32;
- pixel_y = -32
+/obj/machinery/light_switch/east{
+ pixel_x = 29;
+ pixel_y = 12
},
-/obj/structure/bed/stool/chair{
+/obj/machinery/button/switch/holosign{
+ id = "commissary";
+ dir = 4;
+ pixel_y = 1;
+ pixel_x = 29
+ },
+/obj/machinery/button/remote/airlock{
+ dir = 4;
+ id = "horizon_commissary_door";
+ name = "Commissary Door Bolts";
+ pixel_x = 22;
+ specialfunctions = 4;
+ pixel_y = -2
+ },
+/obj/machinery/button/remote/blast_door{
+ dir = 4;
+ id = "horizon_commissary_desk";
+ name = "Desk Shutters";
+ pixel_x = 22;
+ pixel_y = 10
+ },
+/obj/effect/floor_decal/spline/plain/lime{
dir = 4
},
-/obj/machinery/firealarm/west,
-/obj/effect/floor_decal/corner/dark_blue/full,
-/turf/simulated/floor/tiled,
-/area/horizon/security/lobby)
+/obj/structure/table/reinforced/steel,
+/turf/simulated/floor/tiled/dark,
+/area/horizon/operations/commissary)
"mEu" = (
/obj/structure/table/rack,
/obj/item/gun/energy/rifle/ionrifle{
@@ -113323,6 +113335,13 @@
/obj/structure/flora/ausbushes/brflowers,
/turf/simulated/floor/exoplanet/grass/grove,
/area/centcom/shared_dream)
+"oXJ" = (
+/obj/effect/floor_decal/corner/dark_green{
+ dir = 10
+ },
+/obj/structure/extinguisher_cabinet/south,
+/turf/simulated/floor/tiled,
+/area/horizon/hallway/primary/deck_2/central)
"oXL" = (
/obj/structure/railing/mapped{
dir = 4
@@ -115604,6 +115623,12 @@
req_one_access = list(24,11,67,73);
dir = 4
},
+/obj/item/paper_bin{
+ pixel_y = 2
+ },
+/obj/item/pen{
+ pixel_y = 1
+ },
/turf/simulated/floor/tiled/dark/full,
/area/horizon/security/office)
"pob" = (
@@ -124403,12 +124428,13 @@
/turf/simulated/floor/airless,
/area/horizon/engineering/atmos)
"qAt" = (
-/obj/machinery/light{
- dir = 8
- },
/obj/effect/floor_decal/corner/dark_green{
dir = 9
},
+/obj/machinery/commissary_wall_shop{
+ dir = 8;
+ pixel_x = -16
+ },
/turf/simulated/floor/tiled,
/area/horizon/operations/commissary)
"qAB" = (
@@ -124985,10 +125011,10 @@
/turf/simulated/floor/tiled/dark/full,
/area/horizon/rnd/xenoarch/hallway/hangar)
"qEv" = (
-/obj/effect/floor_decal/spline/plain/lime{
- dir = 9
- },
/obj/machinery/atmospherics/unary/vent_pump/on,
+/obj/effect/floor_decal/spline/plain/lime{
+ dir = 8
+ },
/turf/simulated/floor/tiled/dark,
/area/horizon/operations/commissary)
"qEE" = (
@@ -125602,19 +125628,12 @@
/turf/simulated/floor/tiled/white,
/area/horizon/medical/gen_treatment)
"qIo" = (
-/obj/machinery/newscaster/west,
-/obj/structure/table/standard,
-/obj/item/paper_bin{
- pixel_y = 2
- },
-/obj/item/pen{
- pixel_y = 1
- },
-/obj/effect/floor_decal/corner/dark_blue/full{
- dir = 8
- },
-/turf/simulated/floor/tiled,
-/area/horizon/security/lobby)
+/obj/structure/lattice/catwalk/indoor/grate/dark,
+/obj/machinery/power/apc/east,
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable/green,
+/turf/simulated/floor/plating,
+/area/horizon/maintenance/deck_2/service/port)
"qIB" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
@@ -127419,6 +127438,9 @@
dir = 8;
icon_state = "pipe-c"
},
+/obj/machinery/light/floor{
+ dir = 4
+ },
/turf/simulated/floor/tiled,
/area/horizon/operations/commissary)
"qUZ" = (
@@ -136305,7 +136327,7 @@
dir = 4
},
/turf/simulated/floor/tiled/dark/full,
-/area/horizon/operations/commissary)
+/area/horizon/maintenance/deck_2/service/port)
"scz" = (
/obj/machinery/atmospherics/pipe/simple/visible/cyan{
dir = 10
@@ -141144,13 +141166,13 @@
/obj/structure/window/reinforced{
dir = 8
},
-/obj/structure/table/reinforced/steel,
/obj/item/quikpay{
destinationact = "Operations";
pixel_y = 3;
shop_name = "Commissary Quikpay"
},
/obj/machinery/power/outlet,
+/obj/structure/table/reinforced/steel,
/obj/machinery/door/blast/shutters{
dir = 4;
id = "horizon_commissary_desk"
@@ -147081,13 +147103,18 @@
/turf/simulated/floor/plating,
/area/horizon/engineering/drone_fabrication)
"twp" = (
-/obj/structure/disposalpipe/segment,
-/obj/machinery/light/small/emergency{
- dir = 4
+/obj/machinery/alarm/east,
+/obj/machinery/disposal/small/west,
+/obj/structure/disposalpipe/trunk{
+ dir = 8
},
-/obj/structure/lattice/catwalk/indoor/grate/dark,
-/turf/simulated/floor/plating,
-/area/horizon/maintenance/deck_2/service/port)
+/obj/effect/floor_decal/spline/plain/lime{
+ dir = 5
+ },
+/obj/structure/table/reinforced/steel,
+/obj/machinery/firealarm/north,
+/turf/simulated/floor/tiled/dark,
+/area/horizon/operations/commissary)
"twr" = (
/obj/effect/floor_decal/spline/fancy/wood{
dir = 1
@@ -150309,10 +150336,17 @@
/turf/simulated/floor/plating,
/area/horizon/maintenance/deck_3/aft/port)
"tTn" = (
-/obj/effect/floor_decal/industrial/outline/operations,
-/obj/machinery/alarm/east,
-/obj/structure/crate_shelf,
-/turf/simulated/floor/tiled/dark/full,
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ icon_state = "pipe-c"
+ },
+/obj/effect/floor_decal/spline/plain/lime{
+ dir = 1
+ },
+/obj/machinery/light/floor{
+ dir = 1
+ },
+/turf/simulated/floor/tiled/dark,
/area/horizon/operations/commissary)
"tTp" = (
/obj/machinery/atmospherics/unary/vent_pump/on,
@@ -156399,9 +156433,6 @@
/obj/structure/cable/green{
icon_state = "2-8"
},
-/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
- dir = 10
- },
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 6
},
@@ -158325,11 +158356,9 @@
/turf/simulated/floor/plating,
/area/horizon/engineering/atmos/air)
"uWA" = (
-/obj/structure/disposalpipe/segment,
-/obj/structure/cable/green{
- icon_state = "1-2"
- },
/obj/structure/lattice/catwalk/indoor/grate/dark,
+/obj/structure/disposalpipe/segment,
+/obj/random/junk,
/turf/simulated/floor/plating,
/area/horizon/maintenance/deck_2/service/port)
"uWB" = (
@@ -158864,15 +158893,13 @@
},
/area/centcom/holding)
"vaJ" = (
-/obj/effect/floor_decal/spline/plain/lime{
- dir = 6
- },
/obj/machinery/atmospherics/unary/vent_scrubber/on,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/structure/cable/green{
icon_state = "1-2"
},
/obj/structure/disposalpipe/segment,
+/obj/effect/floor_decal/spline/plain/lime,
/turf/simulated/floor/tiled/dark,
/area/horizon/operations/commissary)
"vaL" = (
@@ -159984,17 +160011,17 @@
/turf/simulated/floor/plating,
/area/horizon/maintenance/deck_2/wing/starboard)
"vje" = (
-/obj/structure/disposalpipe/segment{
- icon_state = "pipe-c"
- },
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
/obj/structure/cable/green{
- icon_state = "2-8"
+ icon_state = "4-8"
},
/obj/structure/lattice/catwalk/indoor/grate,
/turf/simulated/floor/plating,
@@ -160830,8 +160857,10 @@
/obj/structure/cable/green{
icon_state = "1-2"
},
-/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
+/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
+ dir = 10
+ },
/turf/simulated/floor/tiled,
/area/horizon/security/lobby)
"voC" = (
@@ -164646,9 +164675,11 @@
},
/area/centcom/specops)
"vSV" = (
-/obj/structure/noticeboard,
-/turf/simulated/wall,
-/area/horizon/operations/office)
+/obj/machinery/alarm/east,
+/obj/structure/lattice/catwalk/indoor/grate/dark,
+/obj/structure/disposalpipe/segment,
+/turf/simulated/floor/plating,
+/area/horizon/maintenance/deck_2/service/port)
"vSZ" = (
/obj/structure/table/rack,
/obj/machinery/light,
@@ -170950,6 +170981,17 @@
/obj/machinery/light/small/emergency{
dir = 4
},
+/obj/structure/table/rack/folding_table,
+/obj/item/deck/cards{
+ pixel_x = 6
+ },
+/obj/item/material/stool/chair/folding{
+ pixel_y = 19
+ },
+/obj/item/material/stool/chair/folding{
+ pixel_y = 22
+ },
+/obj/effect/floor_decal/industrial/outline/grey,
/obj/effect/floor_decal/industrial/warning,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor,
@@ -178942,16 +178984,7 @@
/area/horizon/maintenance/deck_1/main/interstitial)
"xIF" = (
/obj/effect/floor_decal/industrial/outline/grey,
-/obj/structure/table/rack/folding_table,
-/obj/item/material/stool/chair/folding{
- pixel_y = 22
- },
-/obj/item/material/stool/chair/folding{
- pixel_y = 19
- },
-/obj/item/deck/cards{
- pixel_x = 6
- },
+/obj/machinery/vending/quick_e_meals,
/turf/simulated/floor,
/area/horizon/maintenance/deck_3/cafe)
"xIH" = (
@@ -180727,6 +180760,9 @@
pixel_x = 7
},
/obj/effect/floor_decal/industrial/outline/yellow,
+/obj/structure/noticeboard{
+ pixel_y = 30
+ },
/turf/simulated/floor/tiled,
/area/horizon/operations/office)
"xUQ" = (
@@ -272211,7 +272247,7 @@ gbk
sgk
aFJ
mKO
-vSV
+tWP
xUO
bji
twh
@@ -282232,7 +282268,7 @@ iKu
ccb
pdg
mSK
-jWp
+mrm
kgE
kuV
hgh
@@ -283266,7 +283302,7 @@ oge
pbt
qZz
aeC
-auR
+pfa
xZE
wNA
nOR
@@ -283516,7 +283552,7 @@ hTg
fNg
hkQ
gst
-vGI
+kiP
agL
qEv
qne
@@ -283773,7 +283809,7 @@ hTg
fNg
hkQ
gst
-vGI
+aEx
tTn
jXw
lrG
@@ -284031,13 +284067,13 @@ dvo
sOs
qKQ
qZz
-qZz
-qZz
-qZz
+twp
+dyf
+mEq
dZA
qZz
scw
-qZz
+hPw
xZE
ocO
seV
@@ -284288,12 +284324,12 @@ fNg
vje
edn
jEi
-uWA
-bFt
-hPw
-dWE
-twp
-gOI
+qZz
+qZz
+qZz
+qZz
+qZz
+iSm
ftp
xZE
xZE
@@ -284542,15 +284578,15 @@ kBK
nir
hTg
fNg
-kaK
+auR
agC
-icP
-icP
-icP
-icP
-icP
-icP
-iSm
+dWE
+aRD
+qIo
+vSV
+uWA
+bFt
+rJN
rJN
feo
rJN
@@ -284800,12 +284836,12 @@ rRV
mlB
fNg
kaK
-gst
-glY
-qIo
-dyf
-aRD
-mEq
+oXJ
+icP
+icP
+icP
+icP
+icP
icP
qKg
efg
@@ -352896,8 +352932,8 @@ czZ
eiJ
mfX
qfv
-tKb
xIF
+tKb
wGM
rfH
xMK
diff --git a/tgui/packages/tgui/interfaces/QuikPay.tsx b/tgui/packages/tgui/interfaces/QuikPay.tsx
index b9ec897ecd8..9030db042e2 100644
--- a/tgui/packages/tgui/interfaces/QuikPay.tsx
+++ b/tgui/packages/tgui/interfaces/QuikPay.tsx
@@ -17,6 +17,7 @@ export type PayData = {
buying: ItemBuy[];
new_item: string;
new_price: number;
+ new_category: string;
sum: number;
editmode: BooleanLike;
destinationact: number;
@@ -25,6 +26,7 @@ export type PayData = {
type Item = {
name: string;
price: number;
+ category: string;
};
type ItemBuy = {
@@ -79,52 +81,72 @@ export const QuikPay = (props, context) => {
export const ItemWindow = (props, context) => {
const { act, data } = useBackend(context);
+ const groupedItems = data.items.reduce((groups, item) => {
+ const category = item.category || 'Uncategorized';
+ if (!groups[category]) {
+ groups[category] = [];
+ }
+ groups[category].push(item);
+ return groups;
+ }, {});
+
+ const sortedCategories = Object.keys(groupedItems).sort();
+
return (
-
-
- {data.items.map((item) => (
-
- {item.name}
-
- {item.price.toFixed(2)}电
-
-
- {!data.editmode ? (
-
+
+ ))}
+
+
+ ))}
+
+
- {' '}
{
export const AddItems = (props, context) => {
const { act, data } = useBackend(context);
return (
-