diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index f4f2d4d4ec6..87560b65d20 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -779,4 +779,15 @@ obj/item/weapon/circuitboard/rdserver origin_tech = "programming=1;engineering=2" req_components = list( /obj/item/weapon/stock_parts/console_screen = 1, - /obj/item/weapon/stock_parts/matter_bin = 3) \ No newline at end of file + /obj/item/weapon/stock_parts/matter_bin = 3) + +/obj/item/weapon/circuitboard/clawgame + name = "circuit board (Claw Game)" + build_path = /obj/machinery/arcade/claw + board_type = "machine" + origin_tech = "programming=2" + req_components = list( + /obj/item/weapon/stock_parts.matter_bin = 1, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/stack/cable_coil = 5, + /obj/item/stack/sheet/glass = 1) \ No newline at end of file diff --git a/code/modules/arcade/arcade_base.dm b/code/modules/arcade/arcade_base.dm new file mode 100644 index 00000000000..8a3a1ae7009 --- /dev/null +++ b/code/modules/arcade/arcade_base.dm @@ -0,0 +1,132 @@ + +/obj/machinery/arcade + name = "Arcade Game" + desc = "One of the most generic arcade games ever." + icon = 'icons/obj/arcade.dmi' + icon_state = "clawmachine_on" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 40 + var/tokens = 0 + var/freeplay = 0 //for debugging and admin kindness + var/token_price = 0 + var/playing = 0 //only has one set of controls, so only one person can play at once + var/last_winner = null //for letting people who to hunt down and steal prizes from + +/obj/machinery/arcade/New() + ..() + var/choice = pick(subtypesof(/obj/machinery/arcade)) + new choice(loc) + qdel(src) + +/obj/machinery/arcade/examine(mob/user) + ..(user) + if(freeplay) + user << "Someone enabled freeplay on this machine!" + else + if(token_price) + user << "\The [src.name] costs [token_price] credits per play." + if(!tokens) + user << "\The [src.name] has no available play credits. Better feed the machine!" + else if(tokens == 1) + user << "\The [src.name] has only 1 play credit left!" + else + user << "\The [src.name] has [tokens] play credits!" + +/obj/machinery/arcade/interact(mob/user as mob) + if(stat & BROKEN || panel_open) + return 0 + if(!tokens && !freeplay) + user << "\The [src.name] doesn't have enough credits to play! Pay first!" + return 0 + if(!playing && (tokens || freeplay)) + user.set_machine(src) + playing = 1 + if(!freeplay) + tokens -= 1 + return 1 + if(playing && (src != user.machine)) + user << "Someone else is already playing this machine, please wait your turn!" + return 0 + return 1 + +/obj/machinery/arcade/attackby(var/obj/item/O as obj, var/mob/user as mob, params) + if(istype(O, /obj/item/weapon/screwdriver) && anchored) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + panel_open = !panel_open + user << "You [panel_open ? "open" : "close"] the maintenance panel." + update_icon() + return + if(!freeplay) + if(istype(O, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/C = O + if(pay_with_card(C)) + tokens += 1 + return + else if(istype(O, /obj/item/weapon/spacecash)) + var/obj/item/weapon/spacecash/C = O + if(pay_with_cash(C, user)) + tokens += 1 + return + if(panel_open&& component_parts && istype(O, /obj/item/weapon/crowbar)) + default_deconstruction_crowbar(O) + +/obj/machinery/arcade/update_icon() + return + +/obj/machinery/arcade/proc/pay_with_cash(var/obj/item/weapon/spacecash/cashmoney, var/mob/user) + if(cashmoney.get_total() < token_price) + user << "\icon[cashmoney] That is not enough money." + return 0 + visible_message("[usr] inserts a credit chip into [src].") + var/left = cashmoney.get_total() - token_price + user.unEquip(cashmoney) + qdel(cashmoney) + if(left) + dispense_cash(left, src.loc, user) + return 1 + +/obj/machinery/arcade/proc/pay_with_card(var/obj/item/weapon/card/id/I, var/mob/user) + visible_message("[usr] swipes a card through [src].") + var/datum/money_account/customer_account = attempt_account_access_nosec(I.associated_account_number) + if (!customer_account) + user <<"Error: Unable to access account. Please contact technical support if problem persists." + return 0 + + if(customer_account.suspended) + user << "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) + user << "Unable to access account: incorrect credentials." + return 0 + + if(token_price > customer_account.money) + user << "Insufficient funds in account." + return 0 + else + // Okay to move the money at this point + + // debit money from the purchaser's account + customer_account.money -= token_price + + // create entry in the purchaser's account log + var/datum/transaction/T = new() + T.target_name = "[src.name]" + T.purpose = "Purchase of [src.name] credit" + if(token_price > 0) + T.amount = "([token_price])" + else + T.amount = "[token_price]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + customer_account.transaction_log.Add(T) + return 1 \ No newline at end of file diff --git a/code/modules/arcade/arcade_prize.dm b/code/modules/arcade/arcade_prize.dm new file mode 100644 index 00000000000..30374d31a52 --- /dev/null +++ b/code/modules/arcade/arcade_prize.dm @@ -0,0 +1,24 @@ + +/obj/item/toy/prizeball + name = "prize ball" + desc = "A toy is a toy, but a prize ball could be anything! It could even be a toy!" + icon = 'icons/obj/arcade.dmi' + icon_state = "prizeball_1" + var/opening = 0 + +/obj/item/toy/prizeball/New() + ..() + icon_state = pick("prizeball_1","prizeball_2","prizeball_3") + +/obj/item/toy/prizeball/attack_self(mob/user as mob) + if(opening) + return + opening = 1 + playsound(src.loc, 'sound/items/bubblewrap.ogg', 30, 1, extrarange = -4, falloff = 10) + icon_state = "prizeconfetti" + src.color = pick(random_color_list) + var/prize_inside = pick(/obj/random/carp_plushie, /obj/random/plushie, /obj/random/figure) //will add ticket bundles later + spawn(10) + user.unEquip(src) + new prize_inside(user.loc) + qdel(src) \ No newline at end of file diff --git a/code/modules/arcade/claw_game.dm b/code/modules/arcade/claw_game.dm new file mode 100644 index 00000000000..fb7d41d487e --- /dev/null +++ b/code/modules/arcade/claw_game.dm @@ -0,0 +1,84 @@ +/var/claw_game_html = null + +/obj/machinery/arcade/claw + name = "Claw Game" + desc = "One of the most infuriating ways to win a toy." + icon = 'icons/obj/arcade.dmi' + icon_state = "clawmachine_1_on" + token_price = 15 + var/machine_image = "_1" + var/bonus_prize_chance = 5 //chance to dispense a SECOND prize if you win, increased by matter bin rating + + //This is to make sure the images are available + var/list/img_resources = list('icons/obj/arcade_images/backgroundsprite.png', + 'icons/obj/arcade_images/clawpieces.png', + 'icons/obj/arcade_images/crane_bot.png', + 'icons/obj/arcade_images/crane_top.png', + 'icons/obj/arcade_images/prize_inside.png', + 'icons/obj/arcade_images/prizeorbs.png') + +/obj/machinery/arcade/claw/New() + machine_image = pick("_1", "_2") + update_icon() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/clawgame(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/stack/cable_coil(null, 5) + component_parts += new /obj/item/stack/sheet/glass(null, 1) + RefreshParts() + if(!claw_game_html) + claw_game_html = file2text('code/modules/arcade/crane.html') + claw_game_html = replacetext(claw_game_html, "/* ref src */", "\ref[src]") + +/obj/machinery/arcade/claw/RefreshParts() + var/bin_upgrades = 0 + for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) + bin_upgrades = B.rating + bonus_prize_chance = bin_upgrades * 5 //equals +5% chance per matter bin rating level (+20% with rating 4) + +/obj/machinery/arcade/claw/update_icon() + if(stat & BROKEN) + icon_state = "clawmachine[machine_image]_broken" + else if(panel_open) + icon_state = "clawmachine[machine_image]_open" + else if(stat & NOPOWER) + icon_state = "clawmachine[machine_image]_off" + else + icon_state = "clawmachine[machine_image]_on" + return + +/obj/machinery/arcade/claw/proc/win() + icon_state = "clawmachine[machine_image]_win" + visible_message("[src.name] beeps, \"WINNER!\"") + if(prob(bonus_prize_chance)) + //double prize mania! + new /obj/item/toy/prizeball(get_turf(src)) + new /obj/item/toy/prizeball(get_turf(src)) + playsound(src.loc, 'sound/arcade/Win.ogg', 50, 1, extrarange = -3, falloff = 10) + spawn(10) + update_icon() + +/obj/machinery/arcade/claw/attack_hand(mob/user as mob) + interact(user) + +/obj/machinery/arcade/claw/interact(mob/user as mob) + if(!..()) + return + user << browse_rsc('page.css') + for(var/i=1, i<=img_resources.len, i++) + user << browse_rsc(img_resources[i]) + user << browse(claw_game_html, "window=arcade;size=700x600;can_close=0") + return + +/obj/machinery/arcade/claw/Topic(href, list/href_list) + if(..()) + return + var/prize_won = null + prize_won = href_list["prizeWon"] + if(!isnull(prize_won)) + usr.unset_machine() + playing = 0 + usr << browse(null, "window=arcade") //just in case + if(prize_won == "1") + win() diff --git a/code/modules/arcade/crane.html b/code/modules/arcade/crane.html new file mode 100644 index 00000000000..22fdc0e782c --- /dev/null +++ b/code/modules/arcade/crane.html @@ -0,0 +1,284 @@ + + +
+ +