SUBSYSTEM_DEF(economy) name = "Economy" flags = SS_BACKGROUND init_order = INIT_ORDER_ECONOMY //needs to init AFTER SSjobs wait = 30 SECONDS runlevels = RUNLEVEL_GAME offline_implications = "Crew wont get their paychecks. No immediate action is needed." // money go down cpu_display = SS_CPUDISPLAY_LOW ///List of all money account databases existing in the round var/list/money_account_databases = list() ///Total amount of account created during the round, neccesary for generating unique account ids var/account_counter = 0 ///The absolute total amount of space cash (not to be confused with credits) in the round, does not count space credits in money accounts var/total_space_cash = 0 ///The absolute total amount of space credits in various economy systems, does not count space cash var/total_space_credits = 0 ///The amount of space credits that have been irreversibly deleted/removed from the round var/space_credits_destroyed = 0 ///The amount of space credits that have been created out of thin air, does not include credits created at round-start var/space_credits_created = 0 ///The amount of transfers (that are worth more than a few credits) that have been accepted during the round var/total_credit_transfers = 0 ///the amount of venor purchases during the round var/total_vendor_transactions = 0 ///amount of money spent in this 15 minute slot during the round var/current_10_minute_spending = 0 ///list of vars that will be tracked throughout the round (a new entry for each key list will be added every 15 minutes) var/list/economy_data = list( "totalcash" = list(), //how much space cash is in circulation "totalcredits" = list(), //How many space credits are in circulation "creditsdestroyed" = list(), //How many space credits have been removed from the round "totaltransfers" = list(), //How many transfers have been accped (above $4) this round "moneyvelocity" = list(), //What is the money velocity of this 10 minute period GDP/MS "totalvends" = list(), //How many purchases have been made from vendors this round "stagnant_accounts" = list(), //How many accounts have not made any transactions this round "stagnant_cash" = list(), //How many credits are sitting in stagnant accounts this round "non_stagnant_cash" = list() //How many credits are in active accounts this round ) ///time to next stats check var/next_data_check = 0 //////CARGO VARIABLES///// ///the department account tethered to this supply console, we keep a ref here for shuttle operations var/datum/money_account/cargo_account ///Current Order number var/ordernum = 1 /// points gained per slip returned var/credits_per_manifest = 5 /// points gained per intel returned var/credits_per_intel = 750 /// points gained per plasma returned var/credits_per_plasma = 10 /// points gained per research design returned var/credits_per_design = 20 /// Remarks from Centcom on how well you checked the last order. var/centcom_message /// Typepaths for unusual plants we've already sent CentComm, associated with their potencies var/list/discovered_plants = list() var/list/tech_levels = list() var/list/research_designs = list() ///Requested crates, waiting for approval by department heads var/list/request_list = list() ///Approved Crates, waiting to be delivered var/list/shopping_list = list() ///Crates that will be on next shuttle var/list/delivery_list = list() ///Full list of all available supply packs to purchase var/list/supply_packs = list() var/sold_atoms = "" var/list/all_supply_groups = list( SUPPLY_EMERGENCY, SUPPLY_SECURITY, SUPPLY_ENGINEER, SUPPLY_MEDICAL, SUPPLY_SCIENCE, SUPPLY_ORGANIC, SUPPLY_MATERIALS, SUPPLY_MISC, SUPPLY_VEND ) ///The modifier on crate prices to multiple the price by. var/pack_price_modifier = 1 //////Paycheck Variables///// /// time to next payday var/next_paycheck_delay = 0 /// total paydays this round var/payday_count = 0 /// Time until the next mail shipment var/next_mail_delay = 0 var/global_paycheck_bonus = 0 var/global_paycheck_deduction = 0 /datum/controller/subsystem/economy/vv_edit_var(var_name, var_value) switch(var_name) //These are all things that admins should not be touching during production, these are either used for logging //or economy critical things that should not be touched if("payday_count") return FALSE //fuck off, used for logging if("sold_atoms") return FALSE //fuck off, used for logging if("cargo_account") if(!istype(var_value, /datum/money_account)) return FALSE //really fuck off, you're vv editing something to a value that will break the economy return ..() /datum/controller/subsystem/economy/Initialize() ///create main station accounts if(!GLOB.current_date_string) GLOB.current_date_string = "[time2text(world.timeofday, "DD Month")], [GLOB.game_year]" if(GLOB.station_money_database) populate_station_database() cargo_account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SUPPLY) if(!cargo_account) WARNING("SSeconomy could not locate the supply department account") //need to set this back to 0 due to how this is tracked (and so we have a clean slate for roundstart) current_10_minute_spending = 0 ordernum = rand(1, 9000) for(var/typepath in subtypesof(/datum/supply_packs)) var/datum/supply_packs/P = typepath if(initial(P.name) == "HEADER") continue // To filter out group headers P = new typepath() supply_packs["[P.type]"] = P centcom_message = "
---[station_time_timestamp()]---

Remember to stamp and send back the supply manifests.
" next_paycheck_delay = 30 MINUTES + world.time next_mail_delay = 15 MINUTES + world.time /datum/controller/subsystem/economy/fire() if(next_paycheck_delay <= world.time) next_paycheck_delay = 30 MINUTES + world.time payday() if(next_data_check <= world.time) next_data_check = 10 MINUTES + world.time record_economy_data() process_job_tasks() if(next_mail_delay <= world.time) if(!is_admin_level(SSshuttle.supply.z) || SSshuttle.supply.areaInstance.moving) return next_mail_delay = 15 MINUTES + world.time SSshuttle.mail_delivery() /datum/controller/subsystem/economy/proc/record_economy_data() economy_data["totalcash"] += total_space_cash economy_data["totalcredits"] += total_space_credits economy_data["creditsdestroyed"] += space_credits_destroyed - listgetindex(economy_data["creditsdestroyed"], length(economy_data["creditsdestroyed"])) economy_data["totaltransfers"] += total_credit_transfers - listgetindex(economy_data["totaltransfers"], length(economy_data["totaltransfers"])) economy_data["totalvends"] += total_vendor_transactions - listgetindex(economy_data["totalvends"], length(economy_data["totalvends"])) economy_data["moneyvelocity"] += round((current_10_minute_spending / total_space_cash), 0.001) var/stagnant_count = 0 var/stagnant_cash = 0 for(var/datum/money_account/account as anything in GLOB.station_money_database.user_accounts) if(length(account.account_log) <= payday_count) stagnant_count++ stagnant_cash += account.credit_balance economy_data["stagnant_accounts"] += stagnant_count economy_data["stagnant_cash"] = stagnant_cash economy_data["non_stagnant_cash"] = total_space_credits - stagnant_cash current_10_minute_spending = 0 /* * # generate_account_number() * * SS proc that will generate a mostly random seven digit account number. * This will allow up to 1000 guaranteed unique account numbers */ /datum/controller/subsystem/economy/proc/generate_account_number() account_counter++ return (rand(1000, 9999) * 1000) + account_counter /datum/controller/subsystem/economy/proc/populate_station_database() var/datum/money_account_database/main_station/station_db = GLOB.station_money_database money_account_databases += station_db for(var/datum/station_department/department as anything in SSjobs.station_departments) station_db.create_department_account(department.department_name, department.account_base_pay, department.account_starting_balance) department.department_account = station_db.get_account_by_department(department.department_name) //some crates ordered outside of cargo members still need QM explicit approval station_db.create_vendor_account() //////////////////////////// /// Supply Stuff ///////// //////////////////////// /datum/controller/subsystem/economy/proc/generate_supply_order(packID, orderedby, occupation, comment) if(!packID) return FALSE var/datum/supply_packs/pack = locateUID(packID) if(!pack) return FALSE var/datum/supply_order/order = new() order.ordernum = ordernum++ order.object = pack order.orderedby = orderedby order.orderedbyRank = occupation order.comment = comment return order /datum/controller/subsystem/economy/proc/process_supply_order(datum/supply_order/order, paid_for) if(!order) CRASH("process_supply_order() called with a null datum/supply_order") if(!paid_for && !(order in request_list)) request_list += order //submit a request but do not finalize it return TRUE if(order.requires_head_approval || order.requires_cargo_approval) return TRUE //if purchaser has already paid it means it's fully approved, finalize order if(paid_for) finalize_supply_order(order) //if payment was succesful, add order to shoppinglist return TRUE log_debug("process_supply_order() called on Crate [order.ordernum] ordered by [order.orderedby] but isn't paid for and doesn't need approval, deleting") qdel(order) //only the strong will survive return FALSE /datum/controller/subsystem/economy/proc/finalize_supply_order(datum/supply_order/order) if(!order) CRASH("finalize_supply_order() called with a null datum/supply_order") if(order in request_list) request_list -= order if(SSshuttle.supply.getDockedId() == "supply_away" && SSshuttle.supply.mode == SHUTTLE_IDLE) delivery_list += order else shopping_list += order //////////////////////////// /// Paycheck Stuff ///////// //////////////////////// /datum/controller/subsystem/economy/proc/payday() payday_count++ var/total_payout = 0 var/total_accounts = 0 var/datum/money_account_database/main_station/station_db = GLOB.station_money_database var/list/all_station_accounts = station_db.user_accounts + station_db.get_all_department_accounts() for(var/datum/money_account/account in all_station_accounts) var/amount_to_pay = account.payday_amount + global_paycheck_bonus - global_paycheck_deduction if(LAZYLEN(account.pay_check_bonuses)) for(var/bonus in account.pay_check_bonuses) amount_to_pay += bonus account.pay_check_bonuses = null for(var/deduction in account.pay_check_deductions) amount_to_pay -= deduction amount_to_pay = max(amount_to_pay, 0) account.pay_check_deductions = null station_db.credit_account(account, amount_to_pay, "Payday", "NAS Trurl Payroll", FALSE) if(account.account_type == ACCOUNT_TYPE_PERSONAL) if(LAZYLEN(account.associated_nanobank_programs)) for(var/datum/data/pda/app/nanobank/program as anything in account.associated_nanobank_programs) program.announce_payday(amount_to_pay) total_accounts++ total_payout += amount_to_pay //reset global paycheck modifiers to 0 global_paycheck_bonus = 0 global_paycheck_deduction = 0 //update space credit statistics space_credits_created += total_payout total_space_credits += total_payout //alert admins and c*ders alike log_debug("Payday Count: [payday_count] - [total_payout] credits paid out to [total_accounts] accounts") //Called by the gameticker /datum/controller/subsystem/economy/proc/process_job_tasks() for(var/mob/M in GLOB.player_list) //why not just make a global list of players with job objectives???? someone else fix this ~sirryan if(!M.mind) continue for(var/datum/job_objective/objective as anything in M.mind.job_objectives) if(objective.completed && objective.payout_given) continue //objective is completed and we've already given out award if(!objective.is_completed()) continue //object is not completed, do not proceed if(objective.completion_payment == 0) objective.payout_given = TRUE continue //objective doesn't giveout payout if(objective.owner_account) objective.owner_account.modify_payroll(objective.completion_payment, TRUE, "Job Objective \"[objective.objective_name]\" completed, award will be included in next paycheck") objective.payout_given = TRUE break // // The NanoCoin Economy is booming // My Parabuck Stocks are Rising // God Bless John Nanotrasen // // __-----__ // ..;;;--'~~~`--;;;.. // /; -~IN NANOTRASEN ;. // // WE TRUST~- \\ // // ,-------, \\ // .// | ;;; ~ \ \\. // || |;;;( /.| || // || |;; _\ || // || '. '=== || // || PROFIT | ''\ ;;;/ || // \\ ,| '\ '|><| 2223 // // \\ | | \ AD// // `;.,|. | '\.-'/ // ~~;;;,._|___.,-;;;~' // ''=--' //