diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 6921cf989c..7ff97c83e8 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -30,7 +30,7 @@ // If it's a generic arcade machine, pick a random arcade // circuit board for it and make the new machine if(!circuit) - var/choice = pick(typesof(/obj/item/weapon/circuitboard/arcade) - /obj/item/weapon/circuitboard/arcade) + var/choice = pick(subtypesof(/obj/item/weapon/circuitboard/arcade) - /obj/item/weapon/circuitboard/arcade/clawmachine) var/obj/item/weapon/circuitboard/CB = new choice() new CB.build_path(loc, CB) qdel(src) @@ -1072,3 +1072,250 @@ #undef ORION_STATUS_NORMAL #undef ORION_STATUS_GAMEOVER #undef ORION_STATUS_MARKET + +////////////////// +// Claw Machine // +////////////////// + +/obj/machinery/computer/arcade/clawmachine + name = "AlliCo Grab-a-Gift" + desc = "Show off your arcade skills for that special someone!" + icon_state = "clawmachine" + icon_keyboard = null + icon_screen = null + circuit = /obj/item/weapon/circuitboard/arcade/clawmachine + prizes = list(/obj/random/plushie) + var/wintick = 0 + var/winprob = 0 + var/instructions = "Insert 1 thaler or swipe a card to play!" + var/gameStatus = "CLAWMACHINE_NEW" + var/gamepaid = 0 + var/gameprice = 1 + var/winscreen = "" + +/// Payment +/obj/machinery/computer/arcade/clawmachine/attackby(obj/item/I as obj, mob/user as mob) + if(..()) + return + + if(gamepaid == 0 && vendor_account && !vendor_account.suspended) + var/paid = 0 + var/obj/item/weapon/card/id/W = I.GetID() + if(W) //for IDs and PDAs and wallets with IDs + paid = pay_with_card(W,I) + else if(istype(I, /obj/item/weapon/spacecash/ewallet)) + var/obj/item/weapon/spacecash/ewallet/C = I + paid = pay_with_ewallet(C) + else if(istype(I, /obj/item/weapon/spacecash)) + var/obj/item/weapon/spacecash/C = I + paid = pay_with_cash(C, user) + if(paid) + gamepaid = 1 + instructions = "Hit start to play!" + return + return + +////// Cash +/obj/machinery/computer/arcade/clawmachine/proc/pay_with_cash(var/obj/item/weapon/spacecash/cashmoney, mob/user) + if(!emagged) + if(gameprice > cashmoney.worth) + + // This is not a status display message, since it's something the character + // themselves is meant to see BEFORE putting the money in + to_chat(usr, "[bicon(cashmoney)] That is not enough money.") + return 0 + + if(istype(cashmoney, /obj/item/weapon/spacecash)) + + visible_message("\The [usr] inserts some cash into \the [src].") + cashmoney.worth -= gameprice + + if(cashmoney.worth <= 0) + usr.drop_from_inventory(cashmoney) + qdel(cashmoney) + else + cashmoney.update_icon() + + // Machine has no idea who paid with cash + credit_purchase("(cash)") + return 1 + if(emagged) + playsound(src, 'sound/arcade/steal.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) + to_chat(user, "It doesn't seem to accept that! Seem you'll need to swipe a valid ID.") + + +///// Ewallet +/obj/machinery/computer/arcade/clawmachine/proc/pay_with_ewallet(var/obj/item/weapon/spacecash/ewallet/wallet) + if(!emagged) + visible_message("\The [usr] swipes \the [wallet] through \the [src].") + playsound(src, 'sound/machines/id_swipe.ogg', 50, 1) + if(gameprice > wallet.worth) + visible_message("Insufficient funds.") + return 0 + else + wallet.worth -= gameprice + credit_purchase("[wallet.owner_name] (chargecard)") + return 1 + if(emagged) + playsound(src, 'sound/arcade/steal.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) + to_chat(usr, "It doesn't seem to accept that! Seem you'll need to swipe a valid ID.") + +///// ID +/obj/machinery/computer/arcade/clawmachine/proc/pay_with_card(var/obj/item/weapon/card/id/I, var/obj/item/ID_container) + if(I==ID_container || ID_container == null) + visible_message("\The [usr] swipes \the [I] through \the [src].") + else + visible_message("\The [usr] swipes \the [ID_container] through \the [src].") + playsound(src, 'sound/machines/id_swipe.ogg', 50, 1) + var/datum/money_account/customer_account = get_account(I.associated_account_number) + if(!customer_account) + visible_message("Error: Unable to access account. Please contact technical support if problem persists.") + return 0 + + if(customer_account.suspended) + visible_message("Unable to access account: account suspended.") + return 0 + + // Have the customer punch in the PIN before checking if there's enough money. Prevents people from figuring out acct is + // empty at high security levels + if(customer_account.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) + var/attempt_pin = input("Enter pin code", "Vendor transaction") as num + customer_account = attempt_account_access(I.associated_account_number, attempt_pin, 2) + + if(!customer_account) + visible_message("Unable to access account: incorrect credentials.") + return 0 + + if(gameprice > customer_account.money) + visible_message("Insufficient funds in account.") + return 0 + else + // Okay to move the money at this point + if(emagged) + gameprice = customer_account.money + // debit money from the purchaser's account + customer_account.money -= gameprice + + // create entry in the purchaser's account log + var/datum/transaction/T = new() + T.target_name = "[vendor_account.owner_name] (via [name])" + T.purpose = "Purchase of arcade game([name])" + if(gameprice > 0) + T.amount = "([gameprice])" + else + T.amount = "[gameprice]" + T.source_terminal = name + T.date = current_date_string + T.time = stationtime2text() + customer_account.transaction_log.Add(T) + + // Give the vendor the money. We use the account owner name, which means + // that purchases made with stolen/borrowed card will look like the card + // owner made them + credit_purchase(customer_account.owner_name) + return 1 + +/// Add to vendor account + +/obj/machinery/computer/arcade/clawmachine/proc/credit_purchase(var/target as text) + vendor_account.money += gameprice + + var/datum/transaction/T = new() + T.target_name = target + T.purpose = "Purchase of arcade game([name])" + T.amount = "[gameprice]" + T.source_terminal = name + T.date = current_date_string + T.time = stationtime2text() + vendor_account.transaction_log.Add(T) + +/// End Payment + +/obj/machinery/computer/arcade/clawmachine/New() + ..() + +/obj/machinery/computer/arcade/clawmachine/attack_hand(mob/living/user) + if(..()) + return + tgui_interact(user) + +/// TGUI Stuff + +/obj/machinery/computer/arcade/clawmachine/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "ClawMachine", name, 300, 400, master_ui, state) + ui.autoupdate = TRUE + ui.open() + +/obj/machinery/computer/arcade/clawmachine/tgui_data(mob/user) + var/list/data = list() + + data["wintick"] = wintick + data["instructions"] = instructions + data["gameStatus"] = gameStatus + data["winscreen"] = winscreen + + return data + +/obj/machinery/computer/arcade/clawmachine/tgui_act(action, params) + if(..()) + return + + if(action == "newgame" && gamepaid == 0) + playsound(src, 'sound/arcade/steal.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) + + if(action == "newgame" && gamepaid == 1) + gameStatus = "CLAWMACHINE_ON" + icon_state = "clawmachine_move" + instructions = "Guide the claw to the prize you want!" + wintick = 0 + + if(action == "return" && gameStatus == "CLAWMACHINE_END") + gameStatus = "CLAWMACHINE_NEW" + + if(action == "pointless" && wintick < 10) + wintick += 1 + + if(action == "pointless" && wintick >= 10) + instructions = "Insert 1 thaler or swipe a card to play!" + clawvend() + +/obj/machinery/computer/arcade/clawmachine/proc/clawvend() /// True to a real claw machine, it's NEARLY impossible to win. + winprob += 1 /// Yeah. + + if(prob(winprob)) /// YEAH. + if(!emagged) + prizevend() + winscreen = "You won!" + else if(emagged) + gameprice = 1 + emagged = 0 + winscreen = "You won...?" + var/obj/item/weapon/grenade/G = new /obj/item/weapon/grenade/explosive(get_turf(src)) /// YEAAAAAAAAAAAAAAAAAAH!!!!!!!!!! + G.activate() + G.throw_at(get_turf(usr),10,10) /// Play stupid games, win stupid prizes. + + playsound(src, 'sound/arcade/Ori_win.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) + winprob = 0 + + else + playsound(src, 'sound/arcade/Ori_fail.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) + winscreen = "Aw, shucks. Try again!" + wintick = 0 + gamepaid = 0 + icon_state = "clawmachine" + gameStatus = "CLAWMACHINE_END" + +/obj/machinery/computer/arcade/clawmachine/emag_act(mob/user) + if(!emagged) + to_chat(user, "You modify the claw of the machine. The next one is sure to win! You just have to pay...") + name = "AlliCo Snag-A-Prize" + desc = "Get some goodies, all for you!" + instructions = "Swipe a card to play!" + winprob = 100 + gamepaid = 0 + wintick = 0 + gameStatus = "CLAWMACHINE_NEW" + emagged = 1 + return 1 \ No newline at end of file diff --git a/code/game/objects/items/weapons/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm index 91b09022a5..9948edea42 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm @@ -101,6 +101,11 @@ build_path = /obj/machinery/computer/arcade/orion_trail origin_tech = list(TECH_DATA = 1) +/obj/item/weapon/circuitboard/arcade/clawmachine + name = T_BOARD("grab-a-gift arcade machine") + build_path = /obj/machinery/computer/arcade/clawmachine + origin_tech = list(TECH_DATA = 1) + /obj/item/weapon/circuitboard/turbine_control name = T_BOARD("turbine control console") build_path = /obj/machinery/computer/turbine_computer diff --git a/tgui/packages/tgui/interfaces/ClawMachine.js b/tgui/packages/tgui/interfaces/ClawMachine.js new file mode 100644 index 0000000000..6eb372b0c3 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ClawMachine.js @@ -0,0 +1,85 @@ +import { useBackend } from "../backend"; +import { Button, ProgressBar, Flex, Box, LabeledList } from "../components"; +import { Window } from "../layouts"; + +export const ClawMachine = (props, context) => { + const { act, data } = useBackend(context); + const { + wintick, + instructions, + gameStatus, + winscreen, + } = data; + + let body; + + if (gameStatus === 'CLAWMACHINE_NEW') { + body = ( + +

+ Pay to Play!

+ {instructions} +


+