diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 7698d2414c..5a8df08c8a 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -147,6 +147,29 @@
return
/obj/machinery/vending/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if (currently_vending)
+ var/paid = 0
+ var/handled = 0
+ if(istype(W, /obj/item/weapon/card/id))
+ var/obj/item/weapon/card/id/C = W
+ paid = pay_with_card(C)
+ handled = 1
+ else if (istype(W, /obj/item/weapon/spacecash/ewallet))
+ var/obj/item/weapon/spacecash/ewallet/C = W
+ paid = pay_with_ewallet(C)
+ handled = 1
+ else if (istype(W, /obj/item/weapon/spacecash))
+ var/obj/item/weapon/spacecash/C = W
+ paid = pay_with_cash(C, user)
+ handled = 1
+
+ if(paid)
+ src.vend(currently_vending, usr)
+ currently_vending = null
+ return
+ else if(handled)
+ return // don't smack that machine with your 2 thalers
+
if (istype(W, /obj/item/weapon/card/emag))
src.emagged = 1
user << "You short out the product lock on [src]"
@@ -169,49 +192,7 @@
coin = W
user << "\blue You insert the [W] into the [src]"
return
- else if(istype(W, /obj/item/weapon/card) && currently_vending)
- var/obj/item/weapon/card/I = W
- scan_card(I)
- else if (istype(W, /obj/item/weapon/spacecash/ewallet) && currently_vending)
- var/obj/item/weapon/spacecash/ewallet/I = W
- if(I.worth >= currently_vending.price)
- I.worth -= currently_vending.price
- visible_message("[usr] swipes a card through [src].")
-
- src.vend(src.currently_vending, usr)
- currently_vending = null
- else
- usr << "\icon[src]Your chargecard does not have enough money!"
-
- // we shouldn't hit spacewallets by now since they were handled above, so this is cash only
- else if (istype(W, /obj/item/weapon/spacecash) && currently_vending)
- var/obj/item/weapon/spacecash/C = W
- if(C.worth >= currently_vending.price)
- if(istype(C, /obj/item/weapon/spacecash/bundle))
- visible_message("[usr] inserts some cash into [src].")
- C.worth -= currently_vending.price
- if(!C.worth)
- usr.drop_from_inventory(W)
- del(W)
- else
- W.update_icon()
- else
- // Non-bundles are whole bills. We eat the whole cash item and spit out change
- visible_message("[usr] inserts a bill into [src].")
- var/left = C.worth - currently_vending.price
-
- usr.drop_from_inventory(W)
- del(W)
- if(left)
- spawn_money(left, src.loc, user)
-
- src.vend(src.currently_vending, usr)
- currently_vending = null
- else
- usr << "\icon[src]That is not enough money to cover the price!"
-
else if(istype(W, /obj/item/weapon/wrench))
-
if(do_after(user, 20))
if(!src) return
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
@@ -234,67 +215,133 @@
else
..()
-/obj/machinery/vending/proc/scan_card(var/obj/item/weapon/card/I)
- if(!currently_vending) return
- if (istype(I, /obj/item/weapon/card/id))
- var/obj/item/weapon/card/id/C = I
- visible_message("[usr] swipes a card through [src].")
- var/datum/money_account/CH = get_account(C.associated_account_number)
- if (CH) // Only proceed if card contains proper account number.
- if(!CH.suspended)
- if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
- if(vendor_account)
- var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
- var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
- transfer_and_vend(D)
- else
- usr << "\icon[src]Unable to access account. Check security settings and try again."
- else
- //Just Vend it.
- transfer_and_vend(CH)
- else
- usr << "\icon[src]Connected account has been suspended."
+/**
+ * Receive payment with cashmoney.
+ *
+ * usr is the mob who gets the change.
+ */
+/obj/machinery/vending/proc/pay_with_cash(var/obj/item/weapon/spacecash/cashmoney, mob/user)
+ if(currently_vending.price > cashmoney.worth)
+ usr << "\icon[src] That is not enough money."
+ return 0
+
+ if(istype(cashmoney, /obj/item/weapon/spacecash/bundle))
+ // Bundles can just have money subtracted, and will work
+
+ visible_message("[usr] inserts some cash into [src].")
+ var/obj/item/weapon/spacecash/bundle/cashmoney_bundle = cashmoney
+ cashmoney_bundle.worth -= currently_vending.price
+
+ if(cashmoney_bundle.worth <= 0)
+ usr.drop_from_inventory(cashmoney_bundle)
+ del(cashmoney_bundle)
else
- usr << "\icon[src]Error: Unable to access your account. Please contact technical support if problem persists."
-
-/obj/machinery/vending/proc/transfer_and_vend(var/datum/money_account/acc)
- if(acc)
- var/transaction_amount = currently_vending.price
- if(transaction_amount <= acc.money)
-
- //transfer the money
- acc.money -= transaction_amount
- vendor_account.money += transaction_amount
-
- //create entries in the two account transaction logs
- var/datum/transaction/T = new()
- T.target_name = "[vendor_account.owner_name] (via [src.name])"
- T.purpose = "Purchase of [currently_vending.product_name]"
- if(transaction_amount > 0)
- T.amount = "([transaction_amount])"
- else
- T.amount = "[transaction_amount]"
- T.source_terminal = src.name
- T.date = current_date_string
- T.time = worldtime2text()
- acc.transaction_log.Add(T)
- //
- T = new()
- T.target_name = acc.owner_name
- T.purpose = "Purchase of [currently_vending.product_name]"
- T.amount = "[transaction_amount]"
- T.source_terminal = src.name
- T.date = current_date_string
- T.time = worldtime2text()
- vendor_account.transaction_log.Add(T)
-
- // Vend the item
- src.vend(src.currently_vending, usr)
- currently_vending = null
- else
- usr << "\icon[src]You don't have that much money!"
+ cashmoney_bundle.update_icon()
else
- usr << "\icon[src]Error: Unable to access your account. Please contact technical support if problem persists."
+ // Bills (banknotes) cannot really have worth different than face value,
+ // so we have to eat the bill and spit out change in a bundle
+ // This is really dirty, but there's no superclass for all bills, so we
+ // just assume that all spacecash that's not something else is a bill
+
+ visible_message("[usr] inserts a bill into [src].")
+ var/left = cashmoney.worth - currently_vending.price
+ usr.drop_from_inventory(cashmoney)
+ del(cashmoney)
+
+ if(left)
+ spawn_money(left, src.loc, user)
+
+ // Vending machines have no idea who paid with cash
+ credit_purchase("(cash)")
+ return 1
+
+/**
+ * Scan a chargecard and deduct payment from it.
+ *
+ * Takes payment for whatever is the currently_vending item. Returns 1 if
+ * successful, 0 if failed.
+ */
+/obj/machinery/vending/proc/pay_with_ewallet(var/obj/item/weapon/spacecash/ewallet/wallet)
+ visible_message("[usr] swipes a card through [src].")
+ if(currently_vending.price > wallet.worth)
+ usr << "\icon[src] Insufficient funds on chargecard."
+ return 0
+ else
+ wallet.worth -= currently_vending.price
+ credit_purchase("[wallet.owner_name] (chargecard)")
+ return 1
+
+/**
+ * Scan a card and attempt to transfer payment from associated account.
+ *
+ * Takes payment for whatever is the currently_vending item. Returns 1 if
+ * successful, 0 if failed
+ */
+/obj/machinery/vending/proc/pay_with_card(var/obj/item/weapon/card/id/I)
+ visible_message("[usr] swipes a card through [src].")
+ var/datum/money_account/customer_account = get_account(I.associated_account_number)
+ if (!customer_account)
+ usr << "\icon[src] Error: Unable to access account. Please contact technical support if problem persists."
+ return 0
+
+ if(customer_account.suspended)
+ usr << "\icon[src] 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)
+ usr << "\icon[src] Unable to access account: incorrect credentials."
+ return 0
+
+ if(currently_vending.price > customer_account.money)
+ usr << "\icon[src] 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 -= currently_vending.price
+
+ // create entry in the purchaser's account log
+ var/datum/transaction/T = new()
+ T.target_name = "[vendor_account.owner_name] (via [src.name])"
+ T.purpose = "Purchase of [currently_vending.product_name]"
+ if(currently_vending.price > 0)
+ T.amount = "([currently_vending.price])"
+ else
+ T.amount = "[currently_vending.price]"
+ T.source_terminal = src.name
+ T.date = current_date_string
+ T.time = worldtime2text()
+ 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 money for current purchase to the vendor account.
+ *
+ * Called after the money has already been taken from the customer.
+ */
+/obj/machinery/vending/proc/credit_purchase(var/target as text)
+ vendor_account.money += currently_vending.price
+
+ var/datum/transaction/T = new()
+ T.target_name = target
+ T.purpose = "Purchase of [currently_vending.product_name]"
+ T.amount = "[currently_vending.price]"
+ T.source_terminal = src.name
+ T.date = current_date_string
+ T.time = worldtime2text()
+ vendor_account.transaction_log.Add(T)
/obj/machinery/vending/attack_ai(mob/user as mob)
return attack_hand(user)