mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-16 02:17:06 +01:00
4ecb0bc21c
Repaths obj/machinery to obj/structure/machinery. **Note for reviewers:** the only meaningful changed code exists within **code/game/objects/structures.dm** and **code/game/objects/structures/_machinery.dm**, largely concerning damage procs. With the exception of moving airlock defines to their own file, ALL OTHER CHANGES ARE STRICTLY PATH CHANGES. Objects, _categorically_, are largely divided between those you can hold in your hand/inventory and those you can't. Machinery objects are already subtypes of Structures behaviorally, this PR just makes their pathing reflect that, and allows for future work (tool actions, more health/destruction functionality) to be developed without unnecessary code duplication. I have tested this PR by loading up the Horizon and dismantling various machines and structures with tools, shooting guns of various types throughout the ship, and detonating a bunch of explosions throughout the ship.
465 lines
17 KiB
Plaintext
465 lines
17 KiB
Plaintext
/obj/item/card/id/var/money = 2000
|
|
|
|
/obj/structure/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/structure/machinery/atm/Initialize()
|
|
. = ..()
|
|
machine_id = "[SSeconomy.num_financial_terminals++]"
|
|
update_icon()
|
|
|
|
/obj/structure/machinery/atm/Destroy()
|
|
authenticated_account = null
|
|
if (held_card)
|
|
held_card.forceMove(loc)
|
|
held_card = null
|
|
|
|
return ..()
|
|
|
|
/obj/structure/machinery/atm/power_change()
|
|
..()
|
|
update_icon()
|
|
|
|
/obj/structure/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, 0.75, COLOR_CYAN)
|
|
|
|
if(held_card)
|
|
var/mutable_appearance/card_overlay = mutable_appearance(icon, "atm-cardin", plane = ABOVE_LIGHTING_PLANE)
|
|
AddOverlays(card_overlay)
|
|
|
|
/obj/structure/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/structure/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/structure/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))
|
|
if(istype(attacking_item, /obj/item/spacecash/ewallet/persistent_charge_card))
|
|
to_chat(user, SPAN_WARNING("You insert the [attacking_item] into [src], but the machine immediately rejects it!"))
|
|
return
|
|
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/structure/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/structure/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/structure/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/structure/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 = "<b>Idris Automated Teller Account Statement</b><br><br>"
|
|
info += "<i>Account holder:</i> [authenticated_account.owner_name]<br>"
|
|
info += "<i>Account number:</i> [authenticated_account.account_number]<br>"
|
|
info += "<i>Balance:</i> $[authenticated_account.money]<br>"
|
|
info += "<i>Date and time:</i> [worldtime2text()], [worlddate2text()]<br><br>"
|
|
info += "<i>Service terminal ID:</i> [machine_id]<br>"
|
|
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 += "<HR><i>This paper has been stamped by the Automatic Teller Machine.</i>"
|
|
R.ripped = TRUE
|
|
print(R, user = usr)
|
|
|
|
release_held_id(usr) // printing ends the ATM session similar to real life + prevents spam
|
|
. = TRUE
|
|
|
|
playsound(loc, SFX_PRINT, 50, 1)
|
|
if ("print_transaction")
|
|
if(authenticated_account)
|
|
var/obj/item/paper/notepad/receipt/R = new()
|
|
var/pname = "Transaction logs: [authenticated_account.owner_name]"
|
|
var/info = "<b>Transaction logs</b><br>"
|
|
info += "<i>Account holder:</i> [authenticated_account.owner_name]<br>"
|
|
info += "<i>Account number:</i> [authenticated_account.account_number]<br>"
|
|
info += "<i>Date and time:</i> [worldtime2text()], [worlddate2text()]<br><br>"
|
|
info += "<i>Service terminal ID:</i> [machine_id]<br>"
|
|
info += "<table border=1 style='width:100%'>"
|
|
info += "<tr>"
|
|
info += "<td><b>Date</b></td>"
|
|
info += "<td><b>Time</b></td>"
|
|
info += "<td><b>Target</b></td>"
|
|
info += "<td><b>Purpose</b></td>"
|
|
info += "<td><b>Value</b></td>"
|
|
info += "<td><b>Source terminal ID</b></td>"
|
|
info += "</tr>"
|
|
for(var/datum/transaction/T in authenticated_account.transactions)
|
|
info += "<tr>"
|
|
info += "<td>[T.date]</td>"
|
|
info += "<td>[T.time]</td>"
|
|
info += "<td>[T.target_name]</td>"
|
|
info += "<td>[T.purpose]</td>"
|
|
info += "<td>$[T.amount]</td>"
|
|
info += "<td>[T.source_terminal]</td>"
|
|
info += "</tr>"
|
|
info += "</table>"
|
|
|
|
R.set_content_unsafe(pname, info)
|
|
|
|
//stamp the paper
|
|
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
|
|
stampoverlay.icon_state = "paper_stamp-cent"
|
|
if(!R.stamped)
|
|
R.stamped = new
|
|
R.stamped += /obj/item/stamp
|
|
R.AddOverlays(stampoverlay)
|
|
R.stamps += "<HR><i>This paper has been stamped by the Automatic Teller Machine.</i>"
|
|
R.ripped = TRUE
|
|
print(R, user = usr)
|
|
|
|
playsound(loc, SFX_PRINT, 50, 1)
|
|
release_held_id(usr) // printing ends the ATM session similar to real life + prevents spam
|
|
. = TRUE
|
|
|
|
if("insert_card")
|
|
if(!held_card)
|
|
//this might happen if the user had the browser window open when somebody emagged it
|
|
if(emagged)
|
|
to_chat(usr, SPAN_WARNING("[icon2html(src, usr)] The ATM card reader rejects your ID!"))
|
|
else
|
|
var/obj/item/I = usr.get_active_hand()
|
|
if (istype(I, /obj/item/card/id))
|
|
usr.drop_from_inventory(I,src)
|
|
held_card = I
|
|
update_icon()
|
|
. = TRUE
|
|
else
|
|
release_held_id(usr)
|
|
. = TRUE
|
|
|
|
if("logout")
|
|
authenticated_account = null
|
|
. = TRUE
|
|
|
|
//stolen wholesale and then edited a bit from newscasters, which are awesome and by Agouri
|
|
/obj/structure/machinery/atm/proc/scan_user(mob/living/carbon/human/human_user)
|
|
if(!authenticated_account)
|
|
if(istype(human_user))
|
|
var/obj/item/card/id/I = human_user.GetIdCard()
|
|
if(istype(I))
|
|
authenticated_account = SSeconomy.attempt_account_access(I.associated_account_number)
|
|
if(authenticated_account)
|
|
to_chat(human_user, SPAN_WARNING("[icon2html(src, usr)] Access granted. Welcome, [authenticated_account.owner_name]."))
|
|
|
|
//create a transaction log entry
|
|
var/datum/transaction/T = new()
|
|
T.target_name = authenticated_account.owner_name
|
|
T.purpose = "Remote terminal access"
|
|
T.source_terminal = machine_id
|
|
T.date = worlddate2text()
|
|
T.time = worldtime2text()
|
|
SSeconomy.add_transaction_log(authenticated_account,T)
|
|
|
|
// checks if the ATM needs to be locked down and locks it down if it does
|
|
/obj/structure/machinery/atm/proc/handle_lockdown(var/tried_account_num = null)
|
|
if (number_incorrect_tries > max_pin_attempts)
|
|
//lock down the atm
|
|
var/area/t = get_area(src)
|
|
ticks_left_locked_down = 60
|
|
playsound(src, 'sound/machines/buzz-two.ogg', 50, 1)
|
|
GLOB.global_announcer.autosay("An ATM has gone into lockdown in [t.name].", machine_id)
|
|
if (tried_account_num)
|
|
SSeconomy.bank_log_unauthorized(SSeconomy.get_account(tried_account_num), machine_id)
|
|
else
|
|
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1)
|
|
|
|
|
|
/obj/structure/machinery/atm/AltClick(var/mob/user)
|
|
release_held_id(user)
|
|
|
|
// put the currently held id on the ground or in the hand of the user
|
|
/obj/structure/machinery/atm/proc/release_held_id(mob/living/carbon/human/human_user as mob)
|
|
|
|
if (!ishuman(human_user))
|
|
return
|
|
|
|
if(!held_card)
|
|
return
|
|
|
|
if(human_user.stat || human_user.lying || human_user.restrained() || !Adjacent(human_user)) return
|
|
|
|
held_card.forceMove(src.loc)
|
|
authenticated_account = null
|
|
|
|
if(!human_user.get_active_hand())
|
|
human_user.put_in_hands(held_card)
|
|
held_card = null
|
|
authenticated_account = null
|
|
update_icon()
|
|
|
|
/obj/structure/machinery/atm/proc/spawn_ewallet(var/sum, loc, mob/living/carbon/human/human_user as mob)
|
|
var/obj/item/spacecash/ewallet/E = new /obj/item/spacecash/ewallet(loc)
|
|
if(ishuman(human_user) && !human_user.get_active_hand())
|
|
human_user.put_in_hands(E)
|
|
E.worth = sum
|
|
E.owner_name = authenticated_account.owner_name
|