diff --git a/baystation12.dme b/baystation12.dme
index e98adba9efc..7f2730fbfb8 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1129,9 +1129,11 @@
#include "code\WorkInProgress\Cael_Aislinn\sculpture.dm"
#include "code\WorkInProgress\Cael_Aislinn\shield_capacitor.dm"
#include "code\WorkInProgress\Cael_Aislinn\shield_gen.dm"
+#include "code\WorkInProgress\Cael_Aislinn\Economy\Accounts.dm"
#include "code\WorkInProgress\Cael_Aislinn\Economy\Economy.dm"
#include "code\WorkInProgress\Cael_Aislinn\Economy\Economy_Events.dm"
#include "code\WorkInProgress\Cael_Aislinn\Economy\Economy_TradeDestinations.dm"
+#include "code\WorkInProgress\Cael_Aislinn\Economy\EFTPOS.dm"
#include "code\WorkInProgress\Cael_Aislinn\Jungle\falsewall.dm"
#include "code\WorkInProgress\Cael_Aislinn\Jungle\jungle.dm"
#include "code\WorkInProgress\Cael_Aislinn\Jungle\jungle_animals.dm"
@@ -1157,6 +1159,7 @@
#include "code\WorkInProgress\Cael_Aislinn\Supermatter\SuperMatter.dm"
#include "code\WorkInProgress\Cael_Aislinn\Supermatter\ZeroPointLaser.dm"
#include "code\WorkInProgress\Chinsky\ashtray.dm"
+#include "code\WorkInProgress\Mini\ATM.dm"
#include "code\WorkInProgress\Ported\policetape.dm"
#include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm"
#include "code\WorkInProgress\Susan\susan_desert_turfs.dm"
@@ -1179,7 +1182,7 @@
#include "code\ZAS\ZAS_Zones.dm"
#include "interface\interface.dm"
#include "interface\skin.dmf"
-#include "maps\tgstation.2.1.0.dmm"
+#include "maps\tgstation.2.1.0.0.1.dmm"
#include "maps\RandomZLevels\Academy.dm"
#include "maps\RandomZLevels\challenge.dm"
#include "maps\RandomZLevels\stationCollision.dm"
diff --git a/code/WorkInProgress/Cael_Aislinn/Economy/Accounts.dm b/code/WorkInProgress/Cael_Aislinn/Economy/Accounts.dm
new file mode 100644
index 00000000000..a69f364e0ff
--- /dev/null
+++ b/code/WorkInProgress/Cael_Aislinn/Economy/Accounts.dm
@@ -0,0 +1,298 @@
+var/global/current_date_string
+var/global/num_financial_terminals = 1
+var/global/datum/money_account/station_account
+var/global/next_account_number = 0
+
+/proc/create_station_account()
+ if(!station_account)
+ next_account_number = rand(111111, 999999)
+
+ station_account = new()
+ station_account.owner_name = "[station_name()] Station Account"
+ station_account.account_number = rand(111111, 999999)
+ station_account.remote_access_pin = rand(1111, 111111)
+ station_account.money = 10000
+
+ //create an entry in the account transaction log for when it was created
+ var/datum/transaction/T = new()
+ T.target_name = station_account.owner_name
+ T.purpose = "Account creation"
+ T.amount = 10000
+ T.date = "2nd April, 2555"
+ T.time = "11:24"
+ T.source_terminal = "Biesel GalaxyNet Terminal #277"
+
+ //add the account
+ station_account.transaction_log.Add(T)
+ for(var/obj/machinery/account_database/A in world)
+ A.accounts.Add(station_account)
+
+//the current ingame time (hh:mm) can be obtained by calling:
+//worldtime2text()
+
+/datum/money_account
+ var/owner_name = ""
+ var/account_number = 0
+ var/remote_access_pin = 0
+ var/money = 0
+ var/list/transaction_log = list()
+ var/security_level = 1 //0 - auto-identify from worn ID, require only account number
+ //1 - require manual login / account number and pin
+ //2 - require card and manual login
+
+/datum/transaction
+ var/target_name = ""
+ var/purpose = ""
+ var/amount = 0
+ var/date = ""
+ var/time = ""
+ var/source_terminal = ""
+
+/obj/machinery/account_database
+ name = "Accounts database"
+ desc = "Holds transaction logs, account data and all kinds of other financial records."
+ icon = 'virology.dmi'
+ icon_state = "analyser"
+ density = 1
+ var/list/accounts = list()
+ req_one_access = list(access_hop, access_captain)
+ var/receipt_num
+ var/machine_id = ""
+ var/obj/item/weapon/card/id/held_card
+ var/access_level = 0
+ var/datum/money_account/detailed_account_view
+ var/creating_new_account = 0
+
+/obj/machinery/account_database/New()
+ ..()
+ if(!station_account)
+ create_station_account()
+
+ if(!current_date_string)
+ current_date_string = "[num2text(rand(1,31))] [pick("January","February","March","April","May","June","July","August","September","October","November","December")], 2557"
+
+ machine_id = "[station_name()] Acc. DB #[num_financial_terminals++]"
+
+/obj/machinery/account_database/attack_hand(mob/user as mob)
+ if(get_dist(src,user) <= 1)
+ var/dat = "Accounts Database
"
+ dat += "[machine_id]
"
+ dat += "Confirm identity: [held_card ? held_card : "-----"]
"
+
+ if(access_level > 0)
+ dat += "You may not edit accounts at this terminal, only create and view them.
"
+ if(creating_new_account)
+ dat += "
"
+ dat += "Return to accounts list"
+ dat += "
"
+ else
+ if(detailed_account_view)
+ dat += "
"
+ dat += "Return to accounts list
"
+ dat += "Account number: #[detailed_account_view.account_number]
"
+ dat += "Account holder: [detailed_account_view.owner_name]
"
+ dat += "Account balance: $[detailed_account_view.money]
"
+ dat += ""
+ dat += ""
+ dat += "| Date | "
+ dat += "Time | "
+ dat += "Target | "
+ dat += "Purpose | "
+ dat += "Value | "
+ dat += "Source terminal ID | "
+ dat += "
"
+ for(var/datum/transaction/T in detailed_account_view.transaction_log)
+ dat += ""
+ dat += "| [T.date] | "
+ dat += "[T.time] | "
+ dat += "[T.target_name] | "
+ dat += "[T.purpose] | "
+ dat += "$[T.amount] | "
+ dat += "[T.source_terminal] | "
+ dat += "
"
+ dat += "
"
+ else
+ dat += "Create new account Sync accounts across databases
"
+ dat += ""
+ for(var/i=1, i<=accounts.len, i++)
+ var/datum/money_account/D = accounts[i]
+ dat += ""
+ dat += "| #[D.account_number] | "
+ dat += "[D.owner_name] | "
+ dat += "View in detail | "
+ dat += "
"
+ dat += "
"
+
+ user << browse(dat,"window=account_db;size=700x650")
+ else
+ user << browse(null,"window=account_db")
+
+/obj/machinery/account_database/attackby(O as obj, user as mob)//TODO:SANITY
+ if(istype(O, /obj/item/weapon/card))
+ var/obj/item/weapon/card/id/idcard = O
+ if(!held_card)
+ usr.drop_item()
+ idcard.loc = src
+ held_card = idcard
+
+ if(access_cent_captain in idcard.access)
+ access_level = 2
+ else if(access_hop in idcard.access || access_captain in idcard.access)
+ access_level = 1
+ else
+ ..()
+
+/obj/machinery/account_database/Topic(var/href, var/href_list)
+ if(href_list["choice"])
+ switch(href_list["choice"])
+ if("sync_accounts")
+ for(var/obj/machinery/account_database/A in world)
+ for(var/datum/money_account/M in src.accounts)
+ if(!A.accounts.Find(M))
+ A.accounts.Add(M)
+ usr << "\icon[src] Accounts synched across all databases in range."
+
+ if("create_account")
+ creating_new_account = 1
+ if("finalise_create_account")
+ var/account_name = href_list["holder_name"]
+ var/starting_funds = max(text2num(href_list["starting_funds"]), 0)
+ add_account(account_name, starting_funds)
+ if(starting_funds > 0)
+ //subtract the money
+ station_account.money -= starting_funds
+
+ //create a transaction log entry
+ var/datum/transaction/T = new()
+ T.target_name = account_name
+ T.purpose = "New account funds initialisation"
+ T.amount = "([starting_funds])"
+ T.date = current_date_string
+ T.time = worldtime2text()
+ T.source_terminal = machine_id
+ station_account.transaction_log.Add(T)
+
+ creating_new_account = 0
+ if("insert_card")
+ if(held_card)
+ held_card.loc = src.loc
+
+ if(ishuman(usr) && !usr.get_active_hand())
+ usr.put_in_hands(held_card)
+ held_card = null
+ access_level = 0
+
+ else
+ var/obj/item/I = usr.get_active_hand()
+ if (istype(I, /obj/item/weapon/card/id))
+ var/obj/item/weapon/card/id/C = I
+ usr.drop_item()
+ C.loc = src
+ held_card = C
+
+ if(access_cent_captain in C.access)
+ access_level = 2
+ else if(access_hop in C.access || access_captain in C.access)
+ access_level = 1
+ if("view_account_detail")
+ var/index = text2num(href_list["account_index"])
+ if(index && index <= accounts.len)
+ detailed_account_view = accounts[index]
+ if("view_accounts_list")
+ detailed_account_view = null
+ creating_new_account = 0
+
+ src.attack_hand(usr)
+
+/obj/machinery/account_database/proc/add_account(var/new_owner_name = "Default user", var/starting_funds = 0, var/pre_existing = 0)
+
+ //create a new account
+ var/datum/money_account/M = new()
+ M.owner_name = new_owner_name
+ M.remote_access_pin = rand(1111, 111111)
+ M.money = starting_funds
+
+ //create an entry in the account transaction log for when it was created
+ var/datum/transaction/T = new()
+ T.target_name = new_owner_name
+ T.purpose = "Account creation"
+ T.amount = starting_funds
+ if(pre_existing)
+ //set a random date, time and location some time over the past few decades
+ T.date = "[num2text(rand(1,31))] [pick("January","February","March","April","May","June","July","August","September","October","November","December")], 25[rand(10,56)]"
+ T.time = "[rand(0,24)]:[rand(11,59)]"
+ T.source_terminal = "NTGalaxyNet Terminal #[rand(111,1111)]"
+
+ M.account_number = rand(111111, 999999)
+ else
+ T.date = current_date_string
+ T.time = worldtime2text()
+ T.source_terminal = machine_id
+
+ M.account_number = next_account_number
+ next_account_number += rand(1,25)
+
+ //create a sealed package containing the account details
+ var/obj/item/smallDelivery/P = new(src.loc)
+
+ var/obj/item/weapon/paper/R = new(P)
+ P.wrapped = R
+ R.name = "Account information: [M.owner_name]"
+ R.info = "Account details (confidential)
"
+ R.info += "Account holder: [M.owner_name]
"
+ R.info += "Account number: [M.account_number]
"
+ R.info += "Account pin: [M.remote_access_pin]
"
+ R.info += "Starting balance: $[M.money]
"
+ R.info += "Date and time: [worldtime2text()], [current_date_string]
"
+ R.info += "Creation terminal ID: [machine_id]
"
+ R.info += "Authorised NT officer overseeing creation: [held_card.registered_name]
"
+
+ //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/weapon/stamp
+ R.overlays += stampoverlay
+ R.stamps += "
This paper has been stamped by the Accounts Database."
+
+
+ //add the account
+ M.transaction_log.Add(T)
+ accounts.Add(M)
+
+/obj/machinery/account_database/proc/charge_to_account(var/attempt_account_number, var/source_name, var/purpose, var/terminal_id, var/amount)
+ for(var/datum/money_account/D in accounts)
+ if(D.account_number == attempt_account_number)
+ D.money += amount
+
+ //create a transaction log entry
+ var/datum/transaction/T = new()
+ T.target_name = source_name
+ T.purpose = purpose
+ if(amount < 0)
+ T.amount = "([amount])"
+ else
+ T.amount = "[amount]"
+ T.date = current_date_string
+ T.time = worldtime2text()
+ T.source_terminal = terminal_id
+ D.transaction_log.Add(T)
+
+ return 1
+
+ return 0
+
+//this returns the first account datum that matches the supplied accnum/pin combination, it returns null if the combination did not match any account
+/obj/machinery/account_database/proc/attempt_account_access(var/attempt_account_number, var/attempt_pin_number, var/security_level_passed = 0)
+ for(var/datum/money_account/D in accounts)
+ if(D.account_number == attempt_account_number)
+ if( D.security_level <= security_level_passed && (!D.security_level || D.remote_access_pin == attempt_pin_number) )
+ return D
diff --git a/code/WorkInProgress/Cael_Aislinn/Economy/EFTPOS.dm b/code/WorkInProgress/Cael_Aislinn/Economy/EFTPOS.dm
new file mode 100644
index 00000000000..5fc619755ad
--- /dev/null
+++ b/code/WorkInProgress/Cael_Aislinn/Economy/EFTPOS.dm
@@ -0,0 +1,177 @@
+/obj/item/weapon/eftpos
+ name = "EFTPOS scanner"
+ desc = "Swipe your ID card to pay electronically."
+ icon = 'icons/obj/library.dmi'
+ icon_state = "scanner"
+ var/machine_id = ""
+ var/eftpos_name = "Default EFTPOS scanner"
+ var/transaction_locked = 0
+ var/transaction_paid = 0
+ var/transaction_amount = 0
+ var/transaction_purpose = "Default charge"
+ var/access_code = 0
+ var/obj/machinery/account_database/linked_db
+ var/datum/money_account/linked_account
+
+/obj/item/weapon/eftpos/New()
+ ..()
+ machine_id = "[station_name()] EFTPOS #[num_financial_terminals++]"
+ access_code = rand(1111,111111)
+ reconnect_database()
+ print_reference()
+
+ //by default, connect to the station account
+ //the user of the EFTPOS device can change the target account though, and no-one will be the wiser (except whoever's being charged)
+ linked_account = station_account
+
+/obj/item/weapon/eftpos/proc/print_reference()
+ var/obj/item/weapon/paper/R = new(get_turf(src))
+ R.name = "Reference: [eftpos_name]"
+ R.info = "[eftpos_name] reference
"
+ R.info += "Access code: [access_code]
"
+ R.info += "Do not lose this code, or the device will have to be replaced.
"
+
+ //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/weapon/stamp
+ R.overlays += stampoverlay
+ R.stamps += "
This paper has been stamped by the EFTPOS device."
+
+/obj/item/weapon/eftpos/proc/reconnect_database()
+ for(var/obj/machinery/account_database/DB in world)
+ if(DB.z == src.z)
+ linked_db = DB
+ break
+
+/obj/item/weapon/eftpos/attack_self(mob/user as mob)
+ if(get_dist(src,user) <= 1)
+ var/dat = "[eftpos_name]
"
+ dat += "This terminal is [machine_id]. Report this code when contacting NanoTrasen IT Support
"
+ if(transaction_locked)
+ dat += "Reset[transaction_paid ? "" : " (authentication required)"]
"
+
+ dat += "Transaction purpose: [transaction_purpose]
"
+ dat += "Value: $[transaction_amount]
"
+ dat += "Linked account: [linked_account ? linked_account.owner_name : "None"]
"
+ if(transaction_paid)
+ dat += "This transaction has been processed successfully.
"
+ else
+ dat += "Swipe your card below the line to finish this transaction.
"
+ dat += "\[------\]"
+ else
+ dat += "Lock in new transaction
"
+
+ dat += "Transaction purpose: [transaction_purpose]
"
+ dat += "Value: $[transaction_amount]
"
+ dat += "Linked account: [linked_account ? linked_account.owner_name : "None"]
"
+ dat += "Change access code"
+ user << browse(dat,"window=eftpos")
+ else
+ user << browse(null,"window=eftpos")
+
+/obj/item/weapon/eftpos/attackby(O as obj, user as mob)
+ if(istype(O, /obj/item/weapon/card))
+ //attempt to connect to a new db, and if that doesn't work then fail
+ if(!linked_db)
+ reconnect_database()
+ if(linked_db && linked_account)
+ var/obj/item/weapon/card/I = O
+ scan_card(I)
+ else
+ usr << "\icon[src]Unable to connect to accounts database."
+ else
+ ..()
+
+/obj/item/weapon/eftpos/Topic(var/href, var/href_list)
+ if(href_list["choice"])
+ switch(href_list["choice"])
+ if("change_code")
+ var/attempt_code = text2num(input("Re-enter the current EFTPOS access code", "Confirm old EFTPOS code"))
+ if(attempt_code == access_code)
+ access_code = text2num(input("Enter a new access code for this device", "Enter new EFTPOS code"))
+ print_reference()
+ else
+ usr << "\icon[src]Incorrect code entered."
+ if("link_account")
+ if(linked_db)
+ var/attempt_account_num = text2num(input("Enter account number to pay EFTPOS charges into", "New account number"))
+ var/attempt_pin = text2num(input("Enter pin code", "Account pin"))
+ linked_account = linked_db.attempt_account_access(attempt_account_num, attempt_pin, 1)
+ else
+ usr << "Unable to connect to accounts database."
+ if("trans_purpose")
+ transaction_purpose = input("Enter reason for EFTPOS transaction", "Transaction purpose")
+ if("trans_value")
+ transaction_amount = max(text2num(input("Enter amount for EFTPOS transaction", "Transaction amount")),0)
+ if("toggle_lock")
+ if(transaction_locked)
+ var/attempt_code = text2num(input("Enter EFTPOS access code", "Reset Transaction"))
+ if(attempt_code == access_code)
+ transaction_locked = 0
+ transaction_paid = 0
+ else if(linked_account)
+ transaction_locked = 1
+ else
+ usr << "\icon[src] No account connected to send transactions to."
+ if("scan_card")
+ //attempt to connect to a new db, and if that doesn't work then fail
+ if(!linked_db)
+ reconnect_database()
+ if(linked_db && linked_account)
+ var/obj/item/I = usr.get_active_hand()
+ if (istype(I, /obj/item/weapon/card))
+ scan_card(I)
+ else
+ usr << "\icon[src]Unable to link accounts."
+
+ src.attack_self(usr)
+
+/obj/item/weapon/eftpos/proc/scan_card(var/obj/item/weapon/card/I)
+ if (istype(I, /obj/item/weapon/card/id))
+ var/obj/item/weapon/card/id/C = I
+ visible_message("[usr] swipes a card through [src].")
+ if(transaction_locked && !transaction_paid)
+ if(linked_account)
+ var/attempt_pin = text2num(input("Enter pin code", "EFTPOS transaction"))
+ var/datum/money_account/D = linked_db.attempt_account_access(C.associated_account_number, attempt_pin, 2)
+ if(D)
+ if(transaction_amount <= D.money)
+ playsound(src, 'chime.ogg', 50, 1)
+ src.visible_message("\icon[src] The [src] chimes.")
+ transaction_paid = 1
+
+ //transfer the money
+ D.money -= transaction_amount
+ linked_account.money += transaction_amount
+
+ //create entries in the two account transaction logs
+ var/datum/transaction/T = new()
+ T.target_name = "[linked_account.owner_name] ([eftpos_name])"
+ T.purpose = transaction_purpose
+ T.amount = "([transaction_amount])"
+ T.source_terminal = machine_id
+ T.date = current_date_string
+ T.time = worldtime2text()
+ D.transaction_log.Add(T)
+ //
+ T = new()
+ T.target_name = D.owner_name
+ T.purpose = transaction_purpose
+ T.amount = "[transaction_amount]"
+ T.source_terminal = machine_id
+ T.date = current_date_string
+ T.time = worldtime2text()
+ linked_account.transaction_log.Add(T)
+ else
+ usr << "\icon[src]You don't have that much money!"
+ else
+ usr << "\icon[src]EFTPOS is not connected to an account."
+ else
+ usr << "\icon[src]Unable to access account. Check security settings and try again."
+ else
+ ..()
+
+ //emag?
\ No newline at end of file
diff --git a/code/WorkInProgress/Mini/ATM.dm b/code/WorkInProgress/Mini/ATM.dm
index 17b6ef2e47c..7551e96e9c5 100644
--- a/code/WorkInProgress/Mini/ATM.dm
+++ b/code/WorkInProgress/Mini/ATM.dm
@@ -7,6 +7,11 @@ log transactions
*/
+#define NO_SCREEN 0
+#define CHANGE_SECURITY_LEVEL 1
+#define TRANSFER_FUNDS 2
+#define VIEW_TRANSACTION_LOGS 3
+
/obj/item/weapon/card/id/var/money = 2000
/obj/machinery/atm
@@ -17,72 +22,346 @@ log transactions
anchored = 1
use_power = 1
idle_power_usage = 10
+ var/obj/machinery/account_database/linked_db
+ 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/weapon/card/held_card
+ var/editing_security_level = 0
+ var/view_screen = NO_SCREEN
+
+/obj/machinery/atm/New()
+ ..()
+ reconnect_database()
+ machine_id = "[station_name()] RT #[num_financial_terminals++]"
+
+/obj/machinery/atm/process()
+ 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--
+
+ for(var/obj/item/weapon/spacecash/S in src)
+ S.loc = src.loc
+ if(prob(50))
+ playsound(loc, 'sound/items/polaroid1.ogg', 50, 1)
+ else
+ playsound(loc, 'sound/items/polaroid2.ogg', 50, 1)
+ break
+
+/obj/machinery/atm/proc/reconnect_database()
+ for(var/obj/machinery/account_database/DB in world)
+ if(DB.z == src.z)
+ linked_db = DB
+ break
/obj/machinery/atm/attackby(obj/item/I as obj, mob/user as mob)
- if(ishuman(user))
- var/obj/item/weapon/card/id/user_id = src.scan_user(user)
+ if(istype(I, /obj/item/weapon/card))
+ var/obj/item/weapon/card/id/idcard = I
+ if(!held_card)
+ usr.drop_item()
+ idcard.loc = src
+ held_card = idcard
+ authenticated_account = null
+ else if(authenticated_account)
if(istype(I,/obj/item/weapon/spacecash))
- user_id.money += I:worth
+ //consume the money
+ authenticated_account.money += I:worth
+ if(prob(50))
+ playsound(loc, 'sound/items/polaroid1.ogg', 50, 1)
+ else
+ playsound(loc, 'sound/items/polaroid2.ogg', 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 = I:worth
+ T.source_terminal = machine_id
+ T.date = current_date_string
+ T.time = worldtime2text()
+ authenticated_account.transaction_log.Add(T)
+
+ user << "You insert [I] into [src]."
+ src.attack_hand(user)
del I
+ else ..()
/obj/machinery/atm/attack_hand(mob/user as mob)
if(istype(user, /mob/living/silicon))
user << "\red Artificial unit recognized. Artificial units do not currently receive monetary compensation, as per NanoTrasen regulation #1005."
return
+ if(get_dist(src,user) <= 1)
+ //check to see if the user has low security enabled
+ scan_user(user)
- var/obj/item/weapon/card/id/user_id = src.scan_user(user)
- if(..())
- return
- var/dat = ""
- dat += "NanoTrasen Automatic Teller Machine
"
- dat += "For all your monetary needs!
"
- dat += "Welcome, [user_id.registered_name].
"
- dat += "You have $[user_id.money] in your account.
"
- dat += "Withdraw
"
- user << browse(dat,"window=atm")
+ //js replicated from obj/machinery/computer/card
+ var/dat = "NanoTrasen Automatic Teller Machine
"
+ dat += "For all your monetary needs!
"
+ dat += "This terminal is [machine_id]. Report this code when contacting NanoTrasen IT Support
"
+ dat += "Card: [held_card ? held_card.name : "------"]
"
+
+ if(ticks_left_locked_down > 0)
+ dat += "Maximum number of pin attempts exceeded! Access to this ATM has been temporarily disabled."
+ else if(authenticated_account)
+ switch(view_screen)
+ if(CHANGE_SECURITY_LEVEL)
+ dat += "Select a new security level for this account:
"
+ var/text = "Zero - Only account number or card is required to access this account. EFTPOS transactions will require a card and ask for a pin, but not verify the pin is correct."
+ if(authenticated_account.security_level != 0)
+ text = "[text]"
+ dat += "[text]
"
+ text = "One - Both an account number and pin is required to access this account and process transactions."
+ if(authenticated_account.security_level != 1)
+ text = "[text]"
+ dat += "[text]
"
+ text = "Two - In addition to account number and pin, a card is required to access this account and process transactions."
+ if(authenticated_account.security_level != 2)
+ text = "[text]"
+ dat += "[text]
"
+ dat += "Back"
+ if(VIEW_TRANSACTION_LOGS)
+ dat += "Transaction logs
"
+ dat += "Back"
+ dat += ""
+ dat += ""
+ dat += "| Date | "
+ dat += "Time | "
+ dat += "Target | "
+ dat += "Purpose | "
+ dat += "Value | "
+ dat += "Source terminal ID | "
+ dat += "
"
+ for(var/datum/transaction/T in authenticated_account.transaction_log)
+ dat += ""
+ dat += "| [T.date] | "
+ dat += "[T.time] | "
+ dat += "[T.target_name] | "
+ dat += "[T.purpose] | "
+ dat += "$[T.amount] | "
+ dat += "[T.source_terminal] | "
+ dat += "
"
+ dat += "
"
+ if(TRANSFER_FUNDS)
+ dat += "Account balance: $[authenticated_account.money]
"
+ dat += "Back
"
+ dat += ""
+ else
+ dat += "Welcome, [authenticated_account.owner_name].
"
+ dat += "Account balance: $[authenticated_account.money]"
+ dat += ""
+ dat += "Change account security level
"
+ dat += "Make transfer
"
+ dat += "View transaction log
"
+ dat += "Print balance statement
"
+ dat += "Logout
"
+ else if(linked_db)
+ dat += ""
+ else
+ dat += "Unable to connect to accounts database, please retry and if the issue persists contact NanoTrasen IT support."
+ reconnect_database()
+
+ user << browse(dat,"window=atm;size=500x650")
+ else
+ user << browse(null,"window=atm")
/obj/machinery/atm/Topic(var/href, var/href_list)
- if(href_list["withdraw"] && href_list["id"])
- var/amount = input("How much would you like to withdraw?", "Amount", 0) in list(1,10,20,50,100,200,500,1000, 0)
- var/obj/item/weapon/card/id/user_id = locate(href_list["id"])
- if(amount != 0 && user_id)
- if(amount <= user_id.money)
- user_id.money -= amount
- //hueg switch for giving moneh out
- switch(amount)
- if(1)
- new /obj/item/weapon/spacecash(loc)
- if(10)
- new /obj/item/weapon/spacecash/c10(loc)
- if(20)
- new /obj/item/weapon/spacecash/c20(loc)
- if(50)
- new /obj/item/weapon/spacecash/c50(loc)
- if(100)
- new /obj/item/weapon/spacecash/c100(loc)
- if(200)
- new /obj/item/weapon/spacecash/c200(loc)
- if(500)
- new /obj/item/weapon/spacecash/c500(loc)
- if(1000)
- new /obj/item/weapon/spacecash/c1000(loc)
- else
- usr << browse("You don't have that much money!
Back","window=atm")
- return
+ if(href_list["choice"])
+ switch(href_list["choice"])
+ if("transfer")
+ if(authenticated_account && linked_db)
+ var/target_account_number = text2num(href_list["target_acc_number"])
+ var/transfer_amount = text2num(href_list["funds_amount"])
+ var/transfer_purpose = href_list["purpose"]
+ if(transfer_amount <= authenticated_account.money)
+ if(linked_db.charge_to_account(target_account_number, authenticated_account.owner_name, transfer_purpose, machine_id, transfer_amount))
+ usr << "\icon[src]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 = current_date_string
+ T.time = worldtime2text()
+ T.amount = "([transfer_amount])"
+ authenticated_account.transaction_log.Add(T)
+ else
+ usr << "\icon[src]Funds transfer failed."
+
+ else
+ usr << "\icon[src]You don't have enough funds to do that!"
+ if("view_screen")
+ view_screen = text2num(href_list["view_screen"])
+ if("change_security_level")
+ if(authenticated_account)
+ var/new_sec_level = max( min(text2num(href_list["new_security_level"]), 2), 0)
+ authenticated_account.security_level = new_sec_level
+ if("attempt_auth")
+ if(linked_db)
+ var/tried_account_num = text2num(href_list["account_num"])
+ if(!tried_account_num)
+ tried_account_num = held_card.associated_account_number
+ var/tried_pin = text2num(href_list["account_pin"])
+
+ authenticated_account = linked_db.attempt_account_access(tried_account_num, tried_pin, held_card && held_card.associated_account_number == tried_account_num ? 2 : 1)
+ if(!authenticated_account)
+ if(previous_account_number == tried_account_num)
+ if(++number_incorrect_tries > max_pin_attempts)
+ //lock down the atm
+ number_incorrect_tries = 0
+ ticks_left_locked_down = 10
+ playsound(src, 'buzz-two.ogg', 50, 1)
+
+ //create an entry in the account transaction log
+ var/datum/transaction/T = new()
+ T.target_name = authenticated_account.owner_name
+ T.purpose = "Unauthorised login attempt"
+ T.source_terminal = machine_id
+ T.date = current_date_string
+ T.time = worldtime2text()
+ authenticated_account.transaction_log.Add(T)
+ else
+ previous_account_number = tried_account_num
+ number_incorrect_tries = 1
+ playsound(src, 'buzz-sigh.ogg', 50, 1)
+ else
+ playsound(src, 'twobeep.ogg', 50, 1)
+ ticks_left_timeout = 120
+ view_screen = NO_SCREEN
+
+ //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 = current_date_string
+ T.time = worldtime2text()
+ authenticated_account.transaction_log.Add(T)
+ if("withdrawal")
+ var/amount = max(text2num(href_list["funds_amount"]),0)
+ if(authenticated_account && amount > 0)
+ if(amount <= authenticated_account.money)
+ playsound(src, 'chime.ogg', 50, 1)
+
+ //remove the money
+ authenticated_account.money -= amount
+ withdraw_arbitrary_sum(amount)
+
+ //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 = current_date_string
+ T.time = worldtime2text()
+ authenticated_account.transaction_log.Add(T)
+ else
+ usr << "\icon[src]You don't have enough funds to do that!"
+ if("balance_statement")
+ if(authenticated_account)
+ var/obj/item/weapon/paper/R = new(src.loc)
+ R.name = "Account balance: [authenticated_account.owner_name]"
+ R.info = "NT Automated Teller Account Statement
"
+ R.info += "Account holder: [authenticated_account.owner_name]
"
+ R.info += "Account number: [authenticated_account.account_number]
"
+ R.info += "Balance: $[authenticated_account.money]
"
+ R.info += "Date and time: [worldtime2text()], [current_date_string]
"
+ R.info += "Service terminal ID: [machine_id]
"
+
+ //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/weapon/stamp
+ R.overlays += stampoverlay
+ R.stamps += "
This paper has been stamped by the Automatic Teller Machine."
+
+ if(prob(50))
+ playsound(loc, 'sound/items/polaroid1.ogg', 50, 1)
+ else
+ playsound(loc, 'sound/items/polaroid2.ogg', 50, 1)
+ if("insert_card")
+ if(held_card)
+ held_card.loc = src.loc
+ authenticated_account = null
+
+ if(ishuman(usr) && !usr.get_active_hand())
+ usr.put_in_hands(held_card)
+ held_card = null
+
+ else
+ var/obj/item/I = usr.get_active_hand()
+ if (istype(I, /obj/item/weapon/card/id))
+ usr.drop_item()
+ I.loc = src
+ held_card = I
+ if("logout")
+ authenticated_account = null
src.attack_hand(usr)
+//create the most effective combination of notes to make up the requested amount
+/obj/machinery/atm/proc/withdraw_arbitrary_sum(var/arbitrary_sum)
+ while(arbitrary_sum >= 1000)
+ arbitrary_sum -= 1000
+ new /obj/item/weapon/spacecash/c1000(src)
+ while(arbitrary_sum >= 500)
+ arbitrary_sum -= 500
+ new /obj/item/weapon/spacecash/c500(src)
+ while(arbitrary_sum >= 200)
+ arbitrary_sum -= 200
+ new /obj/item/weapon/spacecash/c200(src)
+ while(arbitrary_sum >= 100)
+ arbitrary_sum -= 100
+ new /obj/item/weapon/spacecash/c100(src)
+ while(arbitrary_sum >= 50)
+ arbitrary_sum -= 50
+ new /obj/item/weapon/spacecash/c50(src)
+ while(arbitrary_sum >= 20)
+ arbitrary_sum -= 20
+ new /obj/item/weapon/spacecash/c20(src)
+ while(arbitrary_sum >= 10)
+ arbitrary_sum -= 10
+ new /obj/item/weapon/spacecash/c10(src)
+ while(arbitrary_sum >= 1)
+ arbitrary_sum -= 1
+ new /obj/item/weapon/spacecash(src)
+
//stolen wholesale and then edited a bit from newscasters, which are awesome and by Agouri
/obj/machinery/atm/proc/scan_user(mob/living/carbon/human/human_user as mob)
- if(human_user.wear_id)
- if(istype(human_user.wear_id, /obj/item/device/pda) )
- var/obj/item/device/pda/P = human_user.wear_id
- if(P.id)
- return P.id
- else
- return null
- else if(istype(human_user.wear_id, /obj/item/weapon/card/id) )
- return human_user.wear_id
- else
- return null
- else
- return null
+ if(!authenticated_account && linked_db)
+ if(human_user.wear_id)
+ var/obj/item/weapon/card/id/I
+ if(istype(human_user.wear_id, /obj/item/weapon/card/id) )
+ I = human_user.wear_id
+ else if(istype(human_user.wear_id, /obj/item/device/pda) )
+ var/obj/item/device/pda/P = human_user.wear_id
+ I = P.id
+ if(I)
+ authenticated_account = linked_db.attempt_account_access(I.associated_account_number)
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 959f1cef712..94caf0454db 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -27,7 +27,7 @@
/obj/item/weapon/spacecash
- name = "space cash"
+ name = "1 credit chip"
desc = "It's worth 1 credit."
gender = PLURAL
icon = 'icons/obj/items.dmi'
@@ -42,35 +42,57 @@
w_class = 1.0
var/access = list()
access = access_crate_cash
+ var/worth = 1
/obj/item/weapon/spacecash/c10
+ name = "10 credit chip"
icon_state = "spacecash10"
access = access_crate_cash
desc = "It's worth 10 credits."
+ worth = 10
+
/obj/item/weapon/spacecash/c20
+ name = "20 credit chip"
icon_state = "spacecash20"
access = access_crate_cash
desc = "It's worth 20 credits."
+ worth = 20
+
/obj/item/weapon/spacecash/c50
+ name = "50 credit chip"
icon_state = "spacecash50"
access = access_crate_cash
desc = "It's worth 50 credits."
+ worth = 50
+
/obj/item/weapon/spacecash/c100
+ name = "100 credit chip"
icon_state = "spacecash100"
access = access_crate_cash
desc = "It's worth 100 credits."
+ worth = 100
+
/obj/item/weapon/spacecash/c200
+ name = "200 credit chip"
icon_state = "spacecash200"
access = access_crate_cash
desc = "It's worth 200 credits."
+ worth = 200
+
/obj/item/weapon/spacecash/c500
+ name = "500 credit chip"
icon_state = "spacecash500"
access = access_crate_cash
desc = "It's worth 500 credits."
+ worth = 500
+
/obj/item/weapon/spacecash/c1000
+ name = "1000 credit chip"
icon_state = "spacecash1000"
access = access_crate_cash
desc = "It's worth 1000 credits."
+ worth = 1000
+
/obj/item/weapon/bananapeel
name = "banana peel"
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 028b5c93f6b..649a4fe713c 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -16,6 +16,7 @@
desc = "Does card things."
icon = 'icons/obj/card.dmi'
w_class = 1.0
+ var/associated_account_number = 0
var/list/files = list( )
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 6ce1454ff41..64570ee032d 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/terminals.dmi b/icons/obj/terminals.dmi
index a3ad55381a0..ab3d80a03c4 100644
Binary files a/icons/obj/terminals.dmi and b/icons/obj/terminals.dmi differ