mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 05:00:55 +01:00
Refactors pay stands + custom vendors (#63889)
I am disgruntled by the way pay stations work. They're not intuitive, they're a pain to build and have no interface. Basically: They don't get made, and the potential is lost.
Pay stands => Holopay
Summoned by right clicking your ID
Disappears if the card is out of range.
New TGUI window that offers more customization
Other bundled fixes:
Custom vendors become more user friendly
Code improvement
Lots of documentation + refactoring
New bundled number input will likely take place of animated number in tgui input number
Why It's Good For The Game
More RP opportunity for players, plus bug fixes. It's now much easier for players to start their own in game business selling substances clown shoes.
Changelog
cl
code: Created a new input component that accepts only integers. More usage to come.
refactor: Pay stands are now holographic. It's 2562! Create one by right-clicking your ID.
del: Circuit boards for pay stands.
refactor: Pay stands now have their own TGUI.
fix: Custom vendors now alert you when someone makes a purchase.
fix: Custom vendors now place items in your hand when you make a purchase.
/cl
This commit is contained in:
@@ -173,7 +173,7 @@
|
||||
to_chat(user,span_notice("You don't even have a id and you want to be an art patron?"))
|
||||
return
|
||||
if(!id_card.registered_account || !id_card.registered_account.account_job)
|
||||
to_chat(user,span_notice("No valid non-departamental account found."))
|
||||
to_chat(user,span_notice("No valid non-departmental account found."))
|
||||
return
|
||||
var/datum/bank_account/account = id_card.registered_account
|
||||
if(account.account_balance < painting_metadata.credit_value)
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
/obj/structure/holopay
|
||||
name = "holographic pay stand"
|
||||
desc = "an unregistered pay stand"
|
||||
icon = 'icons/obj/economy.dmi'
|
||||
icon_state = "card_scanner"
|
||||
alpha = 150
|
||||
anchored = TRUE
|
||||
armor = list(MELEE = 0, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 0, BIO = 0, FIRE = 20, ACID = 20)
|
||||
max_integrity = 15
|
||||
layer = FLY_LAYER
|
||||
/// ID linked to the holopay
|
||||
var/datum/weakref/card_ref
|
||||
/// Max range at which the hologram can be projected before it deletes
|
||||
var/max_holo_range = 4
|
||||
/// The holopay shop icon displayed in the UI
|
||||
var/shop_logo = "donate"
|
||||
/// Replaces the "pay whatever" functionality with a set amount when non-zero.
|
||||
var/force_fee = 0
|
||||
|
||||
/obj/structure/holopay/examine(mob/user)
|
||||
. = ..()
|
||||
if(force_fee)
|
||||
. += span_boldnotice("This holopay forces a payment of <b>[force_fee]</b> credit\s per swipe instead of a variable amount.")
|
||||
|
||||
/obj/structure/holopay/attack_hand(mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!user.combat_mode)
|
||||
ui_interact(user)
|
||||
return .
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
take_damage(5, BRUTE, MELEE, 1)
|
||||
|
||||
/obj/structure/holopay/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
switch(damage_type)
|
||||
if(BRUTE)
|
||||
playsound(loc, 'sound/weapons/egloves.ogg', 80, TRUE)
|
||||
if(BURN)
|
||||
playsound(loc, 'sound/weapons/egloves.ogg', 80, TRUE)
|
||||
|
||||
/obj/structure/holopay/deconstruct()
|
||||
dissapate()
|
||||
return ..()
|
||||
|
||||
/obj/structure/holopay/attackby(obj/item/held_item, mob/holder, params)
|
||||
var/mob/living/user = holder
|
||||
if(!isliving(user))
|
||||
return ..()
|
||||
/// Users can pay with an ID to skip the UI
|
||||
if(istype(held_item, /obj/item/card/id))
|
||||
if(force_fee && tgui_alert(holder, "This holopay has a [force_fee] cr fee. Confirm?", "Holopay Fee", list("Pay", "Cancel")) != "Pay")
|
||||
return TRUE
|
||||
process_payment(user)
|
||||
return TRUE
|
||||
/// Users can also pay by holochip
|
||||
if(istype(held_item, /obj/item/holochip))
|
||||
/// Account checks
|
||||
var/obj/item/holochip/chip = held_item
|
||||
if(!chip.credits)
|
||||
balloon_alert(user, "holochip is empty")
|
||||
to_chat(user, span_warning("There doesn't seem to be any credits here."))
|
||||
return FALSE
|
||||
/// Charges force fee or uses pay what you want
|
||||
var/cash_deposit = force_fee || tgui_input_number(user, "How much? (Max: [chip.credits])", "Patronage", max_value = chip.credits)
|
||||
/// Exit sanity checks
|
||||
if(!cash_deposit)
|
||||
return TRUE
|
||||
if(QDELETED(held_item) || QDELETED(user) || QDELETED(src) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return FALSE
|
||||
if(!chip.spend(cash_deposit, FALSE))
|
||||
balloon_alert(user, "insufficient credits")
|
||||
to_chat(user, span_warning("You don't have enough credits to pay with this chip."))
|
||||
return FALSE
|
||||
/// Success: Alert buyer
|
||||
alert_buyer(user, cash_deposit)
|
||||
return TRUE
|
||||
/// Throws errors if they try to use space cash
|
||||
if(istype(held_item, /obj/item/stack/spacecash))
|
||||
to_chat(user, "What is this, the 2000s? We only take card here.")
|
||||
return TRUE
|
||||
if(istype(held_item, /obj/item/coin))
|
||||
to_chat(user, "What is this, the 1800s? We only take card here.")
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/structure/holopay/ui_interact(mob/user, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return FALSE
|
||||
var/mob/living/interactor = user
|
||||
if(isliving(interactor) && interactor.combat_mode)
|
||||
return FALSE
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "HoloPay")
|
||||
ui.open()
|
||||
|
||||
/obj/structure/holopay/ui_status(mob/user)
|
||||
. = ..()
|
||||
if(!in_range(user, src) && !isobserver(user))
|
||||
return UI_CLOSE
|
||||
|
||||
/obj/structure/holopay/ui_static_data(mob/user)
|
||||
. = list()
|
||||
/// Sanity checks
|
||||
var/obj/item/card/id/linked_card = get_card()
|
||||
.["available_logos"] = linked_card.available_logos
|
||||
.["description"] = desc
|
||||
.["max_fee"] = linked_card.holopay_max_fee
|
||||
.["owner"] = linked_card.registered_account?.account_holder || null
|
||||
.["shop_logo"] = shop_logo
|
||||
|
||||
/obj/structure/holopay/ui_data(mob/user)
|
||||
. = list()
|
||||
.["force_fee"] = force_fee
|
||||
.["name"] = name
|
||||
if(!isliving(user))
|
||||
return .
|
||||
var/mob/living/card_holder = user
|
||||
var/obj/item/card/id/id_card = card_holder.get_idcard(TRUE)
|
||||
var/datum/bank_account/account = id_card?.registered_account || null
|
||||
if(account)
|
||||
.["user"] = list()
|
||||
.["user"]["name"] = account.account_holder
|
||||
.["user"]["balance"] = account.account_balance
|
||||
|
||||
/obj/structure/holopay/ui_act(action, list/params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return FALSE
|
||||
var/obj/item/card/id/linked_card = get_card()
|
||||
switch(action)
|
||||
if("done")
|
||||
ui.send_full_update()
|
||||
return TRUE
|
||||
if("fee")
|
||||
linked_card.set_holopay_fee(params["amount"])
|
||||
force_fee = linked_card.holopay_fee
|
||||
if("logo")
|
||||
linked_card.set_holopay_logo(params["logo"])
|
||||
shop_logo = linked_card.holopay_logo
|
||||
if("pay")
|
||||
ui.close()
|
||||
process_payment(usr)
|
||||
return TRUE
|
||||
if("rename")
|
||||
linked_card.set_holopay_name(params["name"])
|
||||
name = linked_card.holopay_name
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Links the source card to the holopay. Begins checking if its in range.
|
||||
*
|
||||
* Parameters:
|
||||
* * turf/target - The tile to project the holopay onto
|
||||
* * obj/item/card/id/card - The card to link to the holopay
|
||||
* Returns:
|
||||
* * TRUE - the card was linked
|
||||
*/
|
||||
/obj/structure/holopay/proc/assign_card(turf/target, obj/item/card/id/card)
|
||||
card_ref = WEAKREF(card)
|
||||
desc = "Pays directly into [card.registered_account.account_holder]'s bank account."
|
||||
force_fee = card.holopay_fee
|
||||
shop_logo = card.holopay_logo
|
||||
name = card.holopay_name
|
||||
add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
|
||||
set_light(2)
|
||||
visible_message(span_notice("A holographic pay stand appears."))
|
||||
/// Start checking if the source projection is in range
|
||||
RegisterSignal(card, COMSIG_MOVABLE_MOVED, .proc/check_operation)
|
||||
if(card.loc)
|
||||
RegisterSignal(card.loc, COMSIG_MOVABLE_MOVED, .proc/check_operation)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* A periodic check to see if the projecting card is nearby.
|
||||
* Deletes the holopay if true.
|
||||
*/
|
||||
/obj/structure/holopay/proc/check_operation()
|
||||
SIGNAL_HANDLER
|
||||
var/obj/item/card/id/linked_card = get_card()
|
||||
if(!IN_GIVEN_RANGE(src, linked_card, max_holo_range) || !IN_GIVEN_RANGE(src, linked_card.loc, max_holo_range))
|
||||
dissapate()
|
||||
|
||||
/**
|
||||
* Creates holopay vanishing effects.
|
||||
* Deletes the holopay thereafter.
|
||||
*/
|
||||
/obj/structure/holopay/proc/dissapate()
|
||||
var/obj/item/card/id/linked_card = get_card()
|
||||
playsound(loc, "sound/effects/empulse.ogg", 40, TRUE)
|
||||
visible_message(span_notice("The pay stand vanishes."))
|
||||
QDEL_NULL(linked_card.holopay_ref)
|
||||
|
||||
/**
|
||||
* Checks that the card is still linked.
|
||||
* Deletes the holopay if not.
|
||||
*
|
||||
* Returns:
|
||||
* * /obj/item/card/id/card - The card that is linked to the holopay
|
||||
*/
|
||||
/obj/structure/holopay/proc/get_card()
|
||||
var/obj/item/card/id/linked_card = card_ref?.resolve()
|
||||
if(!linked_card || !istype(linked_card, /obj/item/card/id))
|
||||
stack_trace("Could not link a holopay to a valid card.")
|
||||
qdel(src)
|
||||
return linked_card
|
||||
|
||||
/**
|
||||
* Initiates a transaction between accounts.
|
||||
*
|
||||
* Parameters:
|
||||
* * mob/living/user - The user who initiated the transaction.
|
||||
* Returns:
|
||||
* * TRUE - transaction was successful
|
||||
*/
|
||||
/obj/structure/holopay/proc/process_payment(mob/living/user)
|
||||
// Preliminary sanity checks
|
||||
var/obj/item/card/id/linked_card = get_card()
|
||||
/// Account checks
|
||||
var/obj/item/card/id/id_card
|
||||
id_card = user.get_idcard(TRUE)
|
||||
if(!id_card || !id_card.registered_account || !id_card.registered_account.account_job)
|
||||
balloon_alert(user, "invalid account")
|
||||
to_chat(user, span_warning("You don't have a valid account."))
|
||||
return FALSE
|
||||
var/datum/bank_account/payee = id_card.registered_account
|
||||
if(payee == linked_card.registered_account)
|
||||
balloon_alert(user, "invalid transaction")
|
||||
to_chat(user, span_warning("You can't pay yourself."))
|
||||
return FALSE
|
||||
/// If the user has enough money, ask them the amount or charge the force fee
|
||||
var/amount = force_fee || tgui_input_number(user, "How much? (Max: [payee.account_balance])", "Patronage", max_value = payee.account_balance)
|
||||
/// Exit checks in case the user cancelled or entered an invalid amount
|
||||
if(!amount || QDELETED(user) || QDELETED(src) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return FALSE
|
||||
if(!payee.adjust_money(-amount))
|
||||
balloon_alert(user, "insufficient credits")
|
||||
to_chat(user, span_warning("You don't have the money to pay for this."))
|
||||
return FALSE
|
||||
/// Success: Alert the buyer
|
||||
alert_buyer(user, amount)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Alerts the owner of the transaction.
|
||||
*
|
||||
* Parameters:
|
||||
* * payee - The user who initiated the transaction.
|
||||
* * amount - The amount of money that was paid.
|
||||
* Returns:
|
||||
* * TRUE - alert was successful.
|
||||
*/
|
||||
/obj/structure/holopay/proc/alert_buyer(payee, amount)
|
||||
/// Sanity checks
|
||||
var/obj/item/card/id/linked_card = get_card()
|
||||
/// Pay the owner
|
||||
linked_card.registered_account.adjust_money(amount)
|
||||
/// Make alerts
|
||||
linked_card.registered_account.bank_card_talk("[payee] has deposited [amount] cr at your holographic pay stand.")
|
||||
say("Thank you for your patronage, [payee]!")
|
||||
playsound(src, 'sound/effects/cashregister.ogg', 20, TRUE)
|
||||
/// Log the event
|
||||
log_econ("[amount] credits were transferred from [payee]'s transaction to [linked_card.registered_account.account_holder]")
|
||||
SSblackbox.record_feedback("amount", "credits_transferred", amount)
|
||||
return TRUE
|
||||
@@ -1,152 +0,0 @@
|
||||
/obj/machinery/paystand
|
||||
name = "unregistered pay stand"
|
||||
desc = "See title."
|
||||
icon = 'icons/obj/economy.dmi'
|
||||
icon_state = "card_scanner"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
var/locked = FALSE
|
||||
var/obj/item/card/id/my_card
|
||||
var/obj/item/assembly/signaler/signaler //attached signaler, let people attach signalers that get activated if the user's transaction limit is achieved.
|
||||
var/signaler_threshold = 0 //signaler threshold amount
|
||||
var/amount_deposited = 0 //keep track of the amount deposited over time so you can pay multiple times to reach the signaler threshold
|
||||
var/force_fee = 0 //replaces the "pay whatever" functionality with a set amount when non-zero.
|
||||
|
||||
/obj/machinery/paystand/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/card/id))
|
||||
if(W == my_card)
|
||||
var/list/items = list(
|
||||
"Rename" = image(icon = 'icons/obj/economy.dmi', icon_state = "name"),
|
||||
"Set the fee" = image(icon = 'icons/obj/economy.dmi', icon_state = "fee")
|
||||
)
|
||||
var/choice = show_radial_menu(user, src, items, null, require_near = TRUE, tooltips = TRUE)
|
||||
if(choice == "Rename")
|
||||
var/rename_msg = tgui_input_text(user, "Rename the Paystand", "Paystand Name", name)
|
||||
if(!rename_msg || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
name = rename_msg
|
||||
return
|
||||
else if(choice == "Set the fee")
|
||||
var/force_fee_input = tgui_input_number(user, "Set the fee", "Fee", max_value = 10000)
|
||||
if(isnull(force_fee_input) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
force_fee = round(force_fee_input)
|
||||
return
|
||||
locked = !locked
|
||||
to_chat(user, span_notice("You [src.locked ? "lock" : "unlock"] the paystand, protecting the bolts from [anchored ? "loosening" : "tightening"]."))
|
||||
return
|
||||
if(!my_card)
|
||||
var/obj/item/card/id/new_card = W
|
||||
if(!new_card.registered_account)
|
||||
return
|
||||
var/msg = tgui_input_text(user, "Name of pay stand", "Paystand Naming", "Paystand (owned by [new_card.registered_account.account_holder])")
|
||||
if(!msg)
|
||||
return
|
||||
name = msg
|
||||
desc = "Owned by [new_card.registered_account.account_holder], pays directly into [user.p_their()] account."
|
||||
my_card = new_card
|
||||
to_chat(user, "You link the stand to your account.")
|
||||
return
|
||||
var/obj/item/card/id/pay_card = W
|
||||
if(pay_card.registered_account)
|
||||
if(!pay_card.registered_account.account_job)//Departmental budget cards like cargo's fall under this
|
||||
to_chat(user, span_warning("ERROR: Personal use of department budgets is not authorized."))
|
||||
return
|
||||
var/credit_amount = 0
|
||||
if(!force_fee)
|
||||
credit_amount = tgui_input_number(user, "How much would you like to deposit?", "Money Deposit")
|
||||
if(isnull(credit_amount))
|
||||
return
|
||||
credit_amount = round(credit_amount)
|
||||
else
|
||||
credit_amount = force_fee
|
||||
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
if(credit_amount < 1)
|
||||
to_chat(user, span_warning("ERROR: Invalid amount designated."))
|
||||
return
|
||||
if(pay_card.registered_account.adjust_money(-credit_amount))
|
||||
purchase(pay_card.registered_account.account_holder, credit_amount)
|
||||
say("Thank you for your patronage, [pay_card.registered_account.account_holder]!")
|
||||
playsound(src, 'sound/effects/cashregister.ogg', 20, TRUE)
|
||||
return
|
||||
else
|
||||
to_chat(user, span_warning("ERROR: Account has insufficient funds to make transaction."))
|
||||
return
|
||||
else
|
||||
to_chat(user, span_warning("ERROR: No bank account assigned to identification card."))
|
||||
return
|
||||
if(istype(W, /obj/item/holochip))
|
||||
var/obj/item/holochip/H = W
|
||||
var/cashmoney = round(tgui_input_number(user, "How much would you like to deposit?", "Money Deposit"))
|
||||
if(isnull(cashmoney))
|
||||
return
|
||||
cashmoney = round(cashmoney)
|
||||
if(H.spend(cashmoney, FALSE))
|
||||
purchase(user, cashmoney)
|
||||
to_chat(user, "Thanks for purchasing! The vendor has been informed.")
|
||||
return
|
||||
else
|
||||
to_chat(user, span_warning("ERROR: Insufficient funds to make transaction."))
|
||||
return
|
||||
if(istype(W, /obj/item/stack/spacecash))
|
||||
to_chat(user, "What is this, the 2000s? We only take card here.")
|
||||
return
|
||||
if(istype(W, /obj/item/coin))
|
||||
to_chat(user, "What is this, the 1800s? We only take card here.")
|
||||
return
|
||||
if(istype(W, /obj/item/assembly/signaler))
|
||||
var/obj/item/assembly/signaler/S = W
|
||||
if(S.secured)
|
||||
to_chat(user, span_warning("The signaler needs to be in attachable mode to add it to the paystand!"))
|
||||
return
|
||||
if(!my_card)
|
||||
to_chat(user, span_warning("ERROR: No identification card has been assigned to this paystand yet!"))
|
||||
return
|
||||
if(!isnull(signaler))
|
||||
to_chat(user, span_warning("A signaler is already attached to this unit!"))
|
||||
return
|
||||
var/cash_limit = tgui_input_number(user, "Enter the minimum amount of cash needed to deposit before the signaler is activated.", "Signaler Activation Threshold", 1, min_value = 1)
|
||||
if(isnull(cash_limit))
|
||||
return
|
||||
cash_limit = round(cash_limit)
|
||||
S.forceMove(src)
|
||||
signaler = S
|
||||
signaler_threshold = cash_limit
|
||||
to_chat(user, "You attach the signaler to the paystand.")
|
||||
desc += " A signaler appears to be attached to the scanner."
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "card_scanner", "card_scanner", W))
|
||||
return
|
||||
|
||||
else if(default_pry_open(W))
|
||||
return
|
||||
|
||||
else if(default_unfasten_wrench(user, W))
|
||||
return
|
||||
|
||||
else if(default_deconstruction_crowbar(W))
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/paystand/proc/purchase(buyer, price)
|
||||
my_card.registered_account.adjust_money(price)
|
||||
my_card.registered_account.bank_card_talk("Purchase made at your vendor by [buyer] for [price] credits.")
|
||||
amount_deposited = amount_deposited + price
|
||||
if(signaler && amount_deposited >= signaler_threshold)
|
||||
signaler.signal()
|
||||
amount_deposited = 0
|
||||
|
||||
/obj/machinery/paystand/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
|
||||
if(locked)
|
||||
to_chat(user, span_warning("The bolts on this paystand are currently covered!"))
|
||||
return FALSE
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/paystand/examine(mob/user)
|
||||
. = ..()
|
||||
if(force_fee)
|
||||
. += span_warning("This paystand forces a payment of <b>[force_fee]</b> credit\s per swipe instead of a variable amount.")
|
||||
if(user.get_active_held_item() == my_card)
|
||||
. += span_notice("Paystands can be edited through swiping your card.")
|
||||
@@ -572,14 +572,6 @@
|
||||
category = list ("Research Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_CARGO
|
||||
|
||||
/datum/design/board/paystand
|
||||
name = "Machine Design (Pay Stand)"
|
||||
desc = "The circuit board for a paystand."
|
||||
id = "paystand"
|
||||
build_path = /obj/item/circuitboard/machine/paystand
|
||||
category = list ("Misc. Machinery")
|
||||
|
||||
|
||||
/datum/design/board/fat_sucker
|
||||
name = "Machine Design (Lipid Extractor)"
|
||||
desc = "The circuit board for a lipid extractor."
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
"micro_mani",
|
||||
"oven_tray",
|
||||
"packagewrap",
|
||||
"paystand",
|
||||
"plasmaglass",
|
||||
"plasmareinforcedglass",
|
||||
"plasteel",
|
||||
|
||||
@@ -1128,7 +1128,7 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
light_mask = "custom-light-mask"
|
||||
refill_canister = /obj/item/vending_refill/custom
|
||||
/// where the money is sent
|
||||
var/datum/bank_account/private_a
|
||||
var/datum/bank_account/linked_account
|
||||
/// max number of items that the custom vendor can hold
|
||||
var/max_loaded_items = 20
|
||||
/// Base64 cache of custom icons.
|
||||
@@ -1139,9 +1139,9 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
. = FALSE
|
||||
if(!isliving(user))
|
||||
return FALSE
|
||||
var/mob/living/L = user
|
||||
var/obj/item/card/id/C = L.get_idcard(FALSE)
|
||||
if(C?.registered_account && C.registered_account == private_a)
|
||||
var/mob/living/living_user = user
|
||||
var/obj/item/card/id/id_card = living_user.get_idcard(FALSE)
|
||||
if(id_card?.registered_account && id_card.registered_account == linked_account)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/vending/custom/canLoadItem(obj/item/I, mob/user)
|
||||
@@ -1158,6 +1158,12 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
if(I.custom_price)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/vending/custom/ui_interact(mob/user)
|
||||
if(!linked_account)
|
||||
balloon_alert(user, "no registered owner")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/vending/custom/ui_data(mob/user)
|
||||
. = ..()
|
||||
.["access"] = compartmentLoadAccessCheck(user)
|
||||
@@ -1191,68 +1197,18 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
return
|
||||
switch(action)
|
||||
if("dispense")
|
||||
. = TRUE
|
||||
if(!vend_ready)
|
||||
return
|
||||
var/N = params["item"]
|
||||
var/obj/item/S
|
||||
vend_ready = FALSE
|
||||
var/obj/item/card/id/C
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
C = L.get_idcard(TRUE)
|
||||
if(!C)
|
||||
say("No card found.")
|
||||
flick(icon_deny,src)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
else if (!C.registered_account)
|
||||
say("No account found.")
|
||||
flick(icon_deny,src)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
var/datum/bank_account/account = C.registered_account
|
||||
for(var/obj/O in contents)
|
||||
if(format_text(O.name) == N)
|
||||
S = O
|
||||
break
|
||||
if(S)
|
||||
if(compartmentLoadAccessCheck(usr))
|
||||
vending_machine_input[N] = max(vending_machine_input[N] - 1, 0)
|
||||
S.forceMove(drop_location())
|
||||
loaded_items--
|
||||
use_power(5)
|
||||
vend_ready = TRUE
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(account.has_money(S.custom_price))
|
||||
account.adjust_money(-S.custom_price)
|
||||
var/datum/bank_account/owner = private_a
|
||||
if(owner)
|
||||
owner.adjust_money(S.custom_price)
|
||||
SSblackbox.record_feedback("amount", "vending_spent", S.custom_price)
|
||||
log_econ("[S.custom_price] credits were spent on [src] buying a [S] by [owner.account_holder], owned by [private_a.account_holder].")
|
||||
vending_machine_input[N] = max(vending_machine_input[N] - 1, 0)
|
||||
S.forceMove(drop_location())
|
||||
loaded_items--
|
||||
use_power(5)
|
||||
if(last_shopper != REF(usr) || purchase_message_cooldown < world.time)
|
||||
say("Thank you for buying local and purchasing [S]!")
|
||||
purchase_message_cooldown = world.time + 5 SECONDS
|
||||
last_shopper = REF(usr)
|
||||
vend_ready = TRUE
|
||||
updateUsrDialog()
|
||||
return
|
||||
else
|
||||
say("You do not possess the funds to purchase this.")
|
||||
vend_act(usr, params["item"])
|
||||
vend_ready = TRUE
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/vending/custom/attackby(obj/item/I, mob/user, params)
|
||||
if(!private_a && isliving(user))
|
||||
if(!linked_account && isliving(user))
|
||||
var/mob/living/L = user
|
||||
var/obj/item/card/id/C = L.get_idcard(TRUE)
|
||||
if(C?.registered_account)
|
||||
private_a = C.registered_account
|
||||
linked_account = C.registered_account
|
||||
say("\The [src] has been linked to [C].")
|
||||
|
||||
if(compartmentLoadAccessCheck(user))
|
||||
@@ -1277,6 +1233,57 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
explosion(src, devastation_range = -1, light_impact_range = 3)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Vends an item to the user. Handles all the logic:
|
||||
* Updating stock, account transactions, alerting users.
|
||||
* @return -- TRUE if a valid condition was met, FALSE otherwise.
|
||||
*/
|
||||
/obj/machinery/vending/custom/proc/vend_act(mob/living/user, choice)
|
||||
if(!vend_ready)
|
||||
return
|
||||
var/obj/item/dispensed_item
|
||||
var/obj/item/card/id/id_card = user.get_idcard(TRUE)
|
||||
vend_ready = FALSE
|
||||
if(!id_card || !id_card.registered_account || !id_card.registered_account.account_job)
|
||||
balloon_alert(usr, "no card found")
|
||||
flick(icon_deny, src)
|
||||
return TRUE
|
||||
var/datum/bank_account/payee = id_card.registered_account
|
||||
for(var/obj/stock in contents)
|
||||
if(format_text(stock.name) == choice)
|
||||
dispensed_item = stock
|
||||
break
|
||||
if(!dispensed_item)
|
||||
return FALSE
|
||||
/// Charges the user if its not the owner
|
||||
if(!compartmentLoadAccessCheck(user))
|
||||
if(!payee.has_money(dispensed_item.custom_price))
|
||||
balloon_alert(user, "insufficient funds")
|
||||
return TRUE
|
||||
/// Make the transaction
|
||||
payee.adjust_money(-dispensed_item.custom_price)
|
||||
linked_account.adjust_money(dispensed_item.custom_price)
|
||||
linked_account.bank_card_talk("[payee.account_holder] made a [dispensed_item.custom_price] \
|
||||
cr purchase at your custom vendor.")
|
||||
/// Log the transaction
|
||||
SSblackbox.record_feedback("amount", "vending_spent", dispensed_item.custom_price)
|
||||
log_econ("[dispensed_item.custom_price] credits were spent on [src] buying a \
|
||||
[dispensed_item] by [payee.account_holder], owned by [linked_account.account_holder].")
|
||||
/// Make an alert
|
||||
if(last_shopper != REF(usr) || purchase_message_cooldown < world.time)
|
||||
say("Thank you for your patronage [user]!")
|
||||
purchase_message_cooldown = world.time + 5 SECONDS
|
||||
last_shopper = REF(usr)
|
||||
/// Remove the item
|
||||
loaded_items--
|
||||
use_power(5)
|
||||
vending_machine_input[choice] = max(vending_machine_input[choice] - 1, 0)
|
||||
if(user.CanReach(src) && user.put_in_hands(dispensed_item))
|
||||
to_chat(user, span_notice("You take [dispensed_item.name] out of the slot."))
|
||||
else
|
||||
to_chat(user, span_warning("[capitalize(dispensed_item.name)] falls onto the floor!"))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/vending/custom/unbreakable
|
||||
name = "Indestructible Vendor"
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
|
||||
Reference in New Issue
Block a user