From eee922ee7fe81dc7d9110f587671274d54429a85 Mon Sep 17 00:00:00 2001 From: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Date: Mon, 6 Jul 2020 04:37:06 -0400 Subject: [PATCH] Updates vend-a-trays to have a unique UI, improves accessibility. (#51931) * Initial commit, updates trays into 2020 * Adds vend-a-trays as a service machine, without it being a machine. * Replaced the mapped vend-a-trays with service unique versions. * "YoUr BuIlD DiFfErS fRoM mAsTeR" * Removes {}s from img, workin on the other part * All my homies recompile on merge conflict * Fixes end of line because honestly there must be no god on this green earth * hopefully this isn't too excessive. * How's this? * Applies Anturk's Confirm suggestion. * Shipped, workshopped with style a bit * Alright that's probably enough fiddling for now * Rebuilds. --- _maps/map_files/BoxStation/BoxStation.dmm | 4 +- .../map_files/Deltastation/DeltaStation2.dmm | 4 +- .../map_files/IceBoxStation/IceBoxStation.dmm | 4 +- _maps/map_files/MetaStation/MetaStation.dmm | 2 +- _maps/map_files/PubbyStation/PubbyStation.dmm | 4 +- .../circuitboards/machine_circuitboards.dm | 7 + code/game/objects/structures/displaycase.dm | 196 ++++++++++++------ tgui/packages/tgui/interfaces/Vendatray.js | 97 +++++++++ tgui/packages/tgui/public/tgui.bundle.js | 2 +- 9 files changed, 246 insertions(+), 74 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/Vendatray.js diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index ecc325f6260..746f49e0d17 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -53241,7 +53241,7 @@ id = "kitchen"; name = "kitchen shutters" }, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/kitchen) "tYi" = ( @@ -54602,7 +54602,7 @@ /obj/effect/turf_decal/tile/bar{ dir = 1 }, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel, /area/crew_quarters/bar) "wlL" = ( diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 828d687ee2e..57a52c6580b 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -113279,7 +113279,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel/dark, /area/crew_quarters/bar) "kEN" = ( @@ -114755,7 +114755,7 @@ name = "Kitchen Counter Shutters" }, /obj/effect/turf_decal/delivery, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel, /area/crew_quarters/kitchen) "qkG" = ( diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index ffc4b3d7ea8..8c19363a3b0 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -27477,7 +27477,7 @@ /obj/effect/turf_decal/tile/bar{ dir = 1 }, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel, /area/crew_quarters/bar) "bne" = ( @@ -27514,7 +27514,7 @@ id = "kitchen"; name = "kitchen shutters" }, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/kitchen) "bni" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index f062c79726a..2883c58ce83 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -74566,7 +74566,7 @@ /obj/effect/turf_decal/tile/bar{ dir = 1 }, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel, /area/crew_quarters/bar) "pAv" = ( diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index f5c361d3395..7f16f57179b 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -55223,7 +55223,7 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel/dark, /area/crew_quarters/bar) "pVD" = ( @@ -56172,7 +56172,7 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/structure/displaycase/forsale, +/obj/structure/displaycase/forsale/kitchen, /turf/open/floor/plasteel/dark, /area/crew_quarters/kitchen) "sbY" = ( diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index 3637611e795..c9831e80647 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -1117,6 +1117,13 @@ icon_state = "service" build_path = /obj/machinery/rnd/production/techfab/department/service +/obj/item/circuitboard/machine/vendatray + name = "Vend-A-Tray (Machine Board)" + icon_state = "service" + build_path = /obj/structure/displaycase/forsale + req_components = list( + /obj/item/stock_parts/card_reader = 1) + //Supply /obj/item/circuitboard/machine/mining_equipment_vendor diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 5cb23a757f3..55adb23602b 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -370,7 +370,7 @@ desc = "A display case with an ID-card swiper. Use your ID to purchase the contents." density = FALSE max_integrity = 100 - req_access = list(ACCESS_KITCHEN) + req_access = null showpiece_type = /obj/item/reagent_containers/food alert = FALSE //No, we're not calling the fire department because someone stole your cookie. glass_fix = FALSE //Fixable with tools instead. @@ -378,6 +378,8 @@ var/sale_price = 20 ///The Account which will receive payment for purchases. Set by the first ID to swipe the tray. var/datum/bank_account/payments_acc = null + ///We're using the same trick as paper does in order to cache the image, and only load the UI when messed with. + var/list/viewing_ui = list() /obj/structure/displaycase/forsale/update_icon() //remind me to fix my shitcode later var/icon/I @@ -396,6 +398,109 @@ src.icon = I return +/obj/structure/displaycase/forsale/ui_interact(mob/user, ui_key, datum/tgui/ui, force_open, datum/tgui/master_ui, datum/ui_state/state) + . = ..() + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "Vendatray", name, 300, 270, master_ui, state) + ui.set_autoupdate(FALSE) + viewing_ui[user] = ui + ui.open() + +/obj/structure/displaycase/forsale/ui_data(mob/user) + var/list/data = list() + var/register = FALSE + if(payments_acc) + register = TRUE + data["owner_name"] = payments_acc.account_holder + if(showpiece) + data["product_name"] = capitalize(showpiece.name) + var/base64 = icon2base64(icon(showpiece.icon, showpiece.icon_state)) + data["product_icon"] = base64 + data["registered"] = register + data["product_cost"] = sale_price + data["tray_open"] = open + return data + +/obj/structure/displaycase/forsale/ui_act(action, params) + if(..()) + return + var/obj/item/card/id/potential_acc = usr.get_idcard(hand_first = TRUE) + switch(action) + if("Buy") + if(!showpiece) + to_chat(usr, "There's nothing for sale.") + return TRUE + if(broken) + to_chat(usr, "[src] appears to be broken.") + return TRUE + if(!payments_acc) + to_chat(usr, "[src] hasn't been registered yet.") + return TRUE + if(!usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return TRUE + if(!potential_acc) + to_chat(usr, "No ID card detected.") + return + var/datum/bank_account/account = potential_acc.registered_account + if(!account) + to_chat(usr, "[potential_acc] has no account registered!") + return + if(!account.has_money(sale_price)) + to_chat(usr, "You do not possess the funds to purchase this.") + return TRUE + else + account.adjust_money(-sale_price) + if(payments_acc) + payments_acc.adjust_money(sale_price) + usr.put_in_hands(showpiece) + to_chat(usr, "You purchase [showpiece] for [sale_price] credits.") + playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE) + icon = 'icons/obj/stationobjs.dmi' + flick("laserbox_vend", src) + showpiece = null + update_icon() + SStgui.update_uis(src) + return TRUE + if("Open") + if(!payments_acc) + to_chat(usr, "[src] hasn't been registered yet.") + return TRUE + if(!potential_acc || !potential_acc.registered_account) + return + if(!check_access(potential_acc)) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE) + return + toggle_lock() + SStgui.update_uis(src) + if("Register") + if(payments_acc) + return + if(!potential_acc || !potential_acc.registered_account) + return + if(!check_access(potential_acc)) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE) + return + payments_acc = potential_acc.registered_account + playsound(src, 'sound/machines/click.ogg', 20, TRUE) + if("Adjust") + if(!check_access(potential_acc) || potential_acc.registered_account != payments_acc) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE) + return + + var/new_price_input = input(usr,"Set the sale price for this vend-a-tray.","new price",0) as num|null + if(isnull(new_price_input) || (payments_acc != potential_acc.registered_account)) + to_chat(usr, "[src] rejects your new price.") + return + if(!usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK) ) + to_chat(usr, "You need to get closer!") + return + new_price_input = clamp(round(new_price_input, 1), 10, 1000) + sale_price = new_price_input + to_chat(usr, "The cost is now set to [sale_price].") + SStgui.update_uis(src) + return TRUE + . = TRUE /obj/structure/displaycase/forsale/attackby(obj/item/I, mob/living/user, params) if(isidcard(I)) //Card Registration @@ -403,57 +508,29 @@ if(!potential_acc.registered_account) to_chat(user, "This ID card has no account registered!") return - if(!payments_acc && potential_acc.registered_account) - payments_acc = potential_acc.registered_account + if(payments_acc == potential_acc.registered_account) playsound(src, 'sound/machines/click.ogg', 20, TRUE) - to_chat(user, "Vend-a-tray registered. Use your ID on grab intent to change the sale price, or disarm intent to open the tray.") + toggle_lock() return - //Buying the contained item with the ID. - switch(user.a_intent) - if(INTENT_HELP) - if(!showpiece) - to_chat(user, "There's nothing for sale.") - return TRUE - if(broken) - to_chat(user, "[src] appears to be broken.") - return TRUE - var/confirm = alert(user, "Purchase [showpiece] for [sale_price]?", "Purchase?", "Confirm", "Cancel") - if(confirm == "Cancel" || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) - return TRUE - var/datum/bank_account/account = potential_acc.registered_account - if(!account.has_money(sale_price)) - to_chat(user, "You do not possess the funds to purchase this.") - return TRUE - else - account.adjust_money(-sale_price) - if(payments_acc) - payments_acc.adjust_money(sale_price) - user.put_in_hands(showpiece) - to_chat(user, "You purchase [showpiece] for [sale_price] credits.") - playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE) - icon = 'icons/obj/stationobjs.dmi' - flick("laserbox_vend", src) - showpiece = null - update_icon() - return TRUE - //Setting the object's price. - if(INTENT_GRAB) - var/new_price_input = input(user,"Set the sale price for this vend-a-tray.","new price",0) as num|null - if(isnull(new_price_input) || (payments_acc != potential_acc.registered_account)) - to_chat(user, "The vend-a-tray rejects your new price.") - return - if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK) ) - to_chat(user, "You need to get closer!") - return - new_price_input = clamp(round(new_price_input, 1), 10, 1000) - sale_price = new_price_input - to_chat(user, "The cost is now set to [sale_price].") - return TRUE - if(INTENT_DISARM || INTENT_HARM) - if(payments_acc && payments_acc != potential_acc.registered_account) - to_chat(user, "This Vend-a-tray is already registered!") - return - if(I.tool_behaviour == TOOL_WRENCH && open && user.a_intent == INTENT_HELP ) + if(istype(I, /obj/item/pda)) + return TRUE + SStgui.update_uis(src) + . = ..() + + +/obj/structure/displaycase/forsale/multitool_act(mob/living/user, obj/item/I) + . = ..() + if(obj_integrity <= (integrity_failure * max_integrity)) + to_chat(user, "You start recalibrating [src]'s hover field...") + if(do_after(user, 20, target = src)) + broken = 0 + obj_integrity = max_integrity + update_icon() + return TRUE + +/obj/structure/displaycase/forsale/wrench_act(mob/living/user, obj/item/I) + . = ..() + if(open && user.a_intent == INTENT_HELP ) if(anchored) to_chat(user, "You start unsecuring [src]...") else @@ -467,22 +544,9 @@ to_chat(user, "You secure [src].") anchored = !anchored return - else if(I.tool_behaviour == TOOL_WRENCH && !open && user.a_intent == INTENT_HELP) + else if(!open && user.a_intent == INTENT_HELP) to_chat(user, "[src] must be open to move it.") return - if(istype(I, /obj/item/pda)) - return TRUE - . = ..() - -/obj/structure/displaycase/forsale/multitool_act(mob/living/user, obj/item/I) - . = ..() - if(obj_integrity <= (integrity_failure * max_integrity)) - to_chat(user, "You start recalibrating [src]'s hover field...") - if(do_after(user, 20, target = src)) - broken = 0 - obj_integrity = max_integrity - update_icon() - return TRUE /obj/structure/displaycase/forsale/emag_act(mob/user) . = ..() @@ -503,3 +567,7 @@ playsound(src, "shatter", 70, TRUE) update_icon() trigger_alarm() //In case it's given an alarm anyway. + +/obj/structure/displaycase/forsale/kitchen + desc = "A display case with an ID-card swiper. Use your ID to purchase the contents. Meant for the bartender and chef." + req_access = list(ACCESS_KITCHEN) diff --git a/tgui/packages/tgui/interfaces/Vendatray.js b/tgui/packages/tgui/interfaces/Vendatray.js new file mode 100644 index 00000000000..fbf2cc9a3e6 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Vendatray.js @@ -0,0 +1,97 @@ +import { useBackend } from '../backend'; +import { Fragment } from 'inferno'; +import { Button, LabeledList, Section, Flex, Box } from '../components'; +import { Window } from '../layouts'; +import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox'; + +export const Vendatray = (props, context) => { + const { act, data } = useBackend(context); + const locked = data.locked && !data.siliconUser; + const { + product_name, + product_cost, + tray_open, + registered, + owner_name, + } = data; + return ( + + + + + {!!product_name && ( + + )} + + +
+ {product_name ? product_name : "Empty"} + + {product_name ? product_cost : "N/A"} cr +
+ +