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 += "
" + dat += "" + dat += "" + dat += "Holder name:
" + dat += "Initial funds: (subtracted from station account)
" + dat += "New accounts are automatically assigned a secret number and pin, which are printed separately in a sealed package.
" + dat += "
" + 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 += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + for(var/datum/transaction/T in detailed_account_view.transaction_log) + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "
DateTimeTargetPurposeValueSource terminal ID
[T.date][T.time][T.target_name][T.purpose]$[T.amount][T.source_terminal]
" + 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 += "" + dat += "" + dat += "" + dat += "" + dat += "
#[D.account_number][D.owner_name]View in detail
" + + 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 += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + for(var/datum/transaction/T in authenticated_account.transaction_log) + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "
DateTimeTargetPurposeValueSource terminal ID
[T.date][T.time][T.target_name][T.purpose]$[T.amount][T.source_terminal]
" + if(TRANSFER_FUNDS) + dat += "Account balance: $[authenticated_account.money]
" + dat += "Back

" + dat += "
" + dat += "" + dat += "" + dat += "Target account number:
" + dat += "Funds to transfer:
" + dat += "Transaction purpose:
" + dat += "
" + dat += "
" + else + dat += "Welcome, [authenticated_account.owner_name].
" + dat += "Account balance: $[authenticated_account.money]" + dat += "
" + dat += "" + dat += "" + dat += "
" + dat += "
" + dat += "Change account security level
" + dat += "Make transfer
" + dat += "View transaction log
" + dat += "Print balance statement
" + dat += "Logout
" + else if(linked_db) + dat += "
" + dat += "" + dat += "" + dat += "Account:
" + dat += "PIN:
" + dat += "
" + 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