/obj/item/card/id/var/money = 2000
/obj/machinery/atm
name = "Idris SelfServ Teller"
desc = "For all your monetary needs! Astronomical figures!"
icon = 'icons/obj/machinery/wall/terminals.dmi'
icon_state = "atm"
anchored = 1
idle_power_usage = 10
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED
var/datum/money_account/authenticated_account
var/number_incorrect_tries = 0
var/previous_account_number = 0
var/max_pin_attempts = 3
var/ticks_left_locked_down = 0
var/ticks_left_timeout = 0
var/machine_id = ""
var/obj/item/card/held_card
var/editing_security_level = 0
/obj/machinery/atm/Initialize()
. = ..()
machine_id = "[SSeconomy.num_financial_terminals++]"
update_icon()
/obj/machinery/atm/Destroy()
authenticated_account = null
if (held_card)
held_card.forceMove(loc)
held_card = null
return ..()
/obj/machinery/atm/power_change()
..()
update_icon()
/obj/machinery/atm/update_icon()
ClearOverlays()
if(stat & NOPOWER)
set_light(FALSE)
return
var/mutable_appearance/screen_overlay = mutable_appearance(icon, "atm-active", plane = ABOVE_LIGHTING_PLANE)
AddOverlays(screen_overlay)
set_light(1.4, 1, COLOR_CYAN)
if(held_card)
var/mutable_appearance/card_overlay = mutable_appearance(icon, "atm-cardin", plane = ABOVE_LIGHTING_PLANE)
AddOverlays(card_overlay)
/obj/machinery/atm/process()
if(stat & NOPOWER)
ClearOverlays()
set_light(FALSE)
return
if(ticks_left_timeout > 0)
ticks_left_timeout--
if(ticks_left_timeout <= 0)
authenticated_account = null
if(ticks_left_locked_down > 0)
ticks_left_locked_down--
if(ticks_left_locked_down <= 0)
number_incorrect_tries = 0
for(var/obj/item/spacecash/S in src)
S.forceMove(src.loc)
playsound(loc, SFX_PRINT, 50, 1)
/obj/machinery/atm/emag_act(var/remaining_charges, var/mob/user)
if(emagged)
return
//short out the machine, shoot sparks, spew money!
emagged = 1
spark(src, 5, GLOB.alldirs)
spawn_money(rand(2000,5000),src.loc)
//we don't want to grief people by locking their id in an emagged ATM
release_held_id(user)
//display a message to the user
var/response = pick("Initiating withdrawal. Have a nice day!", "CRITICAL ERROR: Activating cash chamber panic siphon.","PIN Code accepted! Emptying account balance.", "Jackpot!")
to_chat(user, SPAN_WARNING("[icon2html(src, user)] The [src] beeps: \"[response]\""))
intent_message(MACHINE_SOUND)
return 1
/obj/machinery/atm/attackby(obj/item/attacking_item, mob/user)
if(istype(attacking_item, /obj/item/card))
if(emagged)
//prevent inserting id into an emagged ATM
to_chat(user, SPAN_WARNING("[icon2html(src, user)] CARD READER ERROR. This system has been compromised!"))
return
else if(istype(attacking_item,/obj/item/card/emag))
attacking_item.resolve_attackby(src, user)
return
var/obj/item/card/id/idcard = attacking_item
if(!held_card)
usr.drop_from_inventory(idcard,src)
held_card = idcard
if(authenticated_account && held_card.associated_account_number != authenticated_account.account_number)
authenticated_account = null
update_icon()
else if(authenticated_account)
if(istype(attacking_item,/obj/item/spacecash))
var/obj/item/spacecash/cash = attacking_item
//consume the money
authenticated_account.money += cash.worth
playsound(loc, SFX_PRINT, 50, 1)
//create a transaction log entry
var/datum/transaction/T = new()
T.target_name = authenticated_account.owner_name
T.purpose = "Credit deposit"
T.amount = cash.worth
T.source_terminal = machine_id
T.date = worlddate2text()
T.time = worldtime2text()
SSeconomy.add_transaction_log(authenticated_account,T)
intent_message(MACHINE_SOUND)
to_chat(user, SPAN_NOTICE("You insert [attacking_item] into [src]."))
src.attack_hand(user)
qdel(attacking_item)
else
..()
/obj/machinery/atm/attack_hand(mob/user)
. = ..()
if(issilicon(user))
to_chat(user, SPAN_WARNING("[icon2html(src, user)] Artificial unit recognized. Artificial units do not currently receive monetary compensation, \
as per system banking regulation #1005."))
return
ui_interact(user)
/obj/machinery/atm/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ATM", "Idris ATM #[machine_id]", 550, 650)
ui.open()
/obj/machinery/atm/ui_data(mob/user)
var/list/data = list()
data["machine_id"] = machine_id
data["card"] = held_card ? held_card.name : null
data["ticks_left_locked_down"] = ticks_left_locked_down
data["authenticated_account"] = !!authenticated_account
if(authenticated_account)
data["owner_name"] = authenticated_account.owner_name
data["security_level"] = authenticated_account.security_level
data["suspended"] = authenticated_account.suspended
data["money"] = authenticated_account.money
data["number_incorrect_tries"] = number_incorrect_tries
data["emagged"] = emagged
if(authenticated_account)
data["transactions"] = list()
for(var/datum/transaction/T in authenticated_account.transactions)
data["transactions"] += list(list(
"target_name" = T.target_name,
"purpose" = T.purpose,
"amount" = T.amount,
"date" = T.date,
"time" = T.time,
"source_terminal" = T.source_terminal
))
return data
/obj/machinery/atm/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
switch(action)
if("transfer")
if(authenticated_account)
var/transfer_amount = text2num(params["funds_amount"])
transfer_amount = round(transfer_amount, 0.01)
if(transfer_amount <= 0)
to_chat(usr, SPAN_WARNING("That is an invalid amount!"))
else if(transfer_amount <= authenticated_account.money)
var/target_account_number = text2num(params["target_acc_number"])
var/transfer_purpose = params["purpose"]
if(SSeconomy.charge_to_account(target_account_number, authenticated_account.owner_name, transfer_purpose, machine_id, transfer_amount))
to_chat(usr, SPAN_NOTICE("[icon2html(src, usr)] Funds transfer successful."))
authenticated_account.money -= transfer_amount
//create an entry in the account transaction log
var/datum/transaction/T = new()
T.target_name = "Account #[target_account_number]"
T.purpose = transfer_purpose
T.source_terminal = machine_id
T.date = worlddate2text()
T.time = worldtime2text()
T.amount = "([transfer_amount])"
SSeconomy.add_transaction_log(authenticated_account,T)
. = TRUE
else
to_chat(usr, SPAN_WARNING("[icon2html(src, usr)] Funds transfer failed."))
else
to_chat(usr, SPAN_WARNING("[icon2html(src, usr)] You don't have enough funds to do that!"))
if("change_security_level")
if(authenticated_account)
var/new_sec_level = max( min(text2num(params["new_security_level"]), 2), 0)
authenticated_account.security_level = new_sec_level
. = TRUE
if("attempt_auth")
if (ticks_left_locked_down)
return
if (!held_card && !params["account_num"])
return
var/tried_account_num = text2num(params["account_num"])
if (!tried_account_num && held_card)
tried_account_num = held_card.associated_account_number
var/tried_pin = text2num(params["account_pin"])
var/datum/money_account/potential_account = SSeconomy.get_account(tried_account_num)
if (!potential_account)
to_chat(usr, SPAN_WARNING("[icon2html(src, usr)] Account not found."))
number_incorrect_tries++
handle_lockdown()
return TRUE
switch (potential_account.security_level+1) //checks the security level of an account number to see what checks to do
if (1) // Security level zero
authenticated_account = SSeconomy.attempt_account_access(tried_account_num, tried_pin, potential_account.security_level)
// It should be impossible to fail at this point
if (2) // Security level one
authenticated_account = SSeconomy.attempt_account_access(text2num(params["account_num"]), tried_pin, potential_account.security_level)
if (3) // Security level two
if (held_card)
if (text2num(params["account_num"]) == held_card.associated_account_number)
authenticated_account = SSeconomy.attempt_account_access(tried_account_num, tried_pin, potential_account.security_level)
else to_chat(usr, SPAN_WARNING("Account not found."))
if (!authenticated_account)
number_incorrect_tries++
to_chat(usr, SPAN_WARNING("[icon2html(src, usr)] Incorrect pin/account combination entered, [(max_pin_attempts+1) - number_incorrect_tries] attempts remaining."))
handle_lockdown(tried_account_num)
. = TRUE
else
SSeconomy.bank_log_access(authenticated_account, machine_id)
number_incorrect_tries = 0
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
ticks_left_timeout = 120
to_chat(usr, SPAN_NOTICE("[icon2html(src, usr)] Access granted. Welcome, [authenticated_account.owner_name], and have an Idris day!"))
. = TRUE
previous_account_number = tried_account_num
if("e_withdrawal")
var/amount = max(text2num(params["funds_amount"]),0)
amount = round(amount, 0.01)
if(amount <= 0)
to_chat(usr, SPAN_WARNING("That is an invalid amount!"))
else if(authenticated_account && amount > 0)
if(amount <= authenticated_account.money)
playsound(src, 'sound/machines/chime.ogg', 50, 1)
//remove the money
authenticated_account.money -= amount
// spawn_money(amount,src.loc)
spawn_ewallet(amount,src.loc,usr)
intent_message(MACHINE_SOUND)
//create an entry in the account transaction log
var/datum/transaction/T = new()
T.target_name = authenticated_account.owner_name
T.purpose = "Credit withdrawal"
T.amount = "([amount])"
T.source_terminal = machine_id
T.date = worlddate2text()
T.time = worldtime2text()
SSeconomy.add_transaction_log(authenticated_account,T)
. = TRUE
else
to_chat(usr, SPAN_WARNING("[icon2html(src, usr)] You don't have enough funds to do that!"))
if("withdrawal")
var/amount = max(text2num(params["funds_amount"]),0)
amount = round(amount, 0.01)
if(amount <= 0)
to_chat(usr, SPAN_WARNING("That is an invalid amount!"))
else if(authenticated_account && amount > 0)
if(amount <= authenticated_account.money)
playsound(src, 'sound/machines/chime.ogg', 50, 1)
//remove the money
authenticated_account.money -= amount
spawn_money(amount,src.loc,usr)
intent_message(MACHINE_SOUND)
//create an entry in the account transaction log
var/datum/transaction/T = new()
T.target_name = authenticated_account.owner_name
T.purpose = "Credit withdrawal"
T.amount = "([amount])"
T.source_terminal = machine_id
T.date = worlddate2text()
T.time = worldtime2text()
SSeconomy.add_transaction_log(authenticated_account,T)
else
to_chat(usr, SPAN_WARNING("[icon2html(src, usr)] You don't have enough funds to do that!"))
. = TRUE
if("balance_statement")
if(authenticated_account)
var/obj/item/paper/notepad/receipt/R = new()
var/pname = "Account balance: [authenticated_account.owner_name]"
var/info = "Idris Automated Teller Account Statement
"
info += "Account holder: [authenticated_account.owner_name]
"
info += "Account number: [authenticated_account.account_number]
"
info += "Balance: $[authenticated_account.money]
"
info += "Date and time: [worldtime2text()], [worlddate2text()]
"
info += "Service terminal ID: [machine_id]
"
R.set_content_unsafe(pname, info)
//stamp the paper
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
stampoverlay.icon_state = "paper_stamp-hop"
if(!R.stamped)
R.stamped = new
R.stamped += /obj/item/stamp
R.AddOverlays(stampoverlay)
R.stamps += "
| Date | " info += "Time | " info += "Target | " info += "Purpose | " info += "Value | " info += "Source terminal ID | " info += "
| [T.date] | " info += "[T.time] | " info += "[T.target_name] | " info += "[T.purpose] | " info += "$[T.amount] | " info += "[T.source_terminal] | " info += "