From 0a79a01a155de6038cd27d4b894c841c4205b74d Mon Sep 17 00:00:00 2001 From: EvilDragonfiend <87972842+EvilDragonfiend@users.noreply.github.com> Date: Fri, 2 Sep 2022 19:37:37 +0900 Subject: [PATCH 1/2] VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature) (#7330) * vip budget * dd * dd * done * done2 * oops * nope * flex * fixed * cc valid * fix * last fix * deptlock * minor fix (rename define) `department_locked_jobs` to `DEPARTMENT_LOCKED_JOBS` * minor fix (rename define 2) * after fetch * fix * wrong comment * just better not * better comment * nonstation * comment update Co-authored-by: EvilDragonfiend --- code/__DEFINES/economy.dm | 10 +- code/__HELPERS/jobs.dm | 316 +++++++++++++++ code/controllers/subsystem/economy.dm | 11 + code/game/machinery/PDApainter.dm | 12 + code/game/machinery/_machinery.dm | 2 +- code/game/machinery/cloning.dm | 4 +- code/game/objects/items/cards_ids.dm | 80 ++++ code/game/objects/items/mail.dm | 360 ++++++++++++++++++ code/modules/economy/account.dm | 20 +- code/modules/jobs/job_types/gimmick.dm | 8 + .../file_system/programs/budgetordering.dm | 25 ++ 11 files changed, 843 insertions(+), 5 deletions(-) create mode 100644 code/__HELPERS/jobs.dm create mode 100644 code/game/objects/items/mail.dm diff --git a/code/__DEFINES/economy.dm b/code/__DEFINES/economy.dm index 091544f4988..324e639db47 100644 --- a/code/__DEFINES/economy.dm +++ b/code/__DEFINES/economy.dm @@ -6,7 +6,13 @@ #define PAYCHECK_MEDIUM 40 #define PAYCHECK_HARD 70 #define PAYCHECK_COMMAND 100 -#define PAYCHECK_VIP 250 +#define PAYCHECK_VIP 2000 +/* Note: The current intention for crazy amount of money to VIP is that they can be a rich shitter + or be targeted by antags for their money - oh, my, being rich isn't always good. + The first buff to their money was to 2,000 credits. Nerf is fine if you think it's necessary, + but if you decrease their payment too much, they'll be no longer interested. + I recommend to nerf their gimmick spawn chance instead. */ + #define PAYCHECK_WELFARE 20 //NEETbucks @@ -24,5 +30,7 @@ #define ACCOUNT_CAR_NAME "Cargo Budget" #define ACCOUNT_SEC "SEC" #define ACCOUNT_SEC_NAME "Defense Budget" +#define ACCOUNT_VIP "VIP" +#define ACCOUNT_VIP_NAME "Nanotrasen VIP Expense Account Budget" #define NO_FREEBIES "commies go home" diff --git a/code/__HELPERS/jobs.dm b/code/__HELPERS/jobs.dm new file mode 100644 index 00000000000..9bcc58d911c --- /dev/null +++ b/code/__HELPERS/jobs.dm @@ -0,0 +1,316 @@ +// This proc is only used in `PDApainter.dm`, but for better readability, it's declared as global proc and stored here. +// This returns a card icon style by given job name. Check `card.dmi` for the card list. +/proc/get_cardstyle_by_jobname(jobname) + if(!jobname) + CRASH("The proc has taken a null value") + + var/static/id_style = list( + // Command + "Command (Custom)" = "captain", + JOB_NAME_CAPTAIN = "captain", + "Acting Captain" = "captain", + // Service + "Service (Custom)" = "rawservice", + JOB_NAME_HEADOFPERSONNEL = "hop", + JOB_NAME_ASSISTANT = "id", + JOB_NAME_BOTANIST = "serv", + JOB_NAME_BARTENDER = "serv", + JOB_NAME_COOK = "serv", + JOB_NAME_JANITOR = "janitor", + JOB_NAME_CURATOR = "chap", + JOB_NAME_CHAPLAIN = "chap", + JOB_NAME_LAWYER = "lawyer", + JOB_NAME_CLOWN = "clown", + JOB_NAME_MIME = "mime", + JOB_NAME_STAGEMAGICIAN = "serv", + JOB_NAME_BARBER = "serv", + // Cargo + "Cargo (Custom)" = "rawcargo", + JOB_NAME_QUARTERMASTER = "qm", + JOB_NAME_CARGOTECHNICIAN = "cargo", + JOB_NAME_SHAFTMINER = "miner", + // Engineering + "Engineering (Custom)" = "rawengineering", + JOB_NAME_CHIEFENGINEER = "ce", + JOB_NAME_STATIONENGINEER = "engi", + JOB_NAME_ATMOSPHERICTECHNICIAN = "atmos", + // Medical + "Medical (Custom)" = "rawmedical", + JOB_NAME_CHIEFMEDICALOFFICER = "cmo", + JOB_NAME_MEDICALDOCTOR = "med", + JOB_NAME_PARAMEDIC = "paramed", + JOB_NAME_VIROLOGIST = "viro", + JOB_NAME_GENETICIST = "gene", + JOB_NAME_CHEMIST = "chemist", + JOB_NAME_PSYCHIATRIST = "med", + // R&D + "Science (Custom)" = "rawscience", + JOB_NAME_RESEARCHDIRECTOR = "rd", + JOB_NAME_SCIENTIST = "sci", + JOB_NAME_ROBOTICIST = "roboticist", + JOB_NAME_EXPLORATIONCREW = "exploration", + // Security + "Security (Custom)" = "rawsecurity", + JOB_NAME_HEADOFSECURITY = "hos", + JOB_NAME_WARDEN = "warden", + JOB_NAME_SECURITYOFFICER = "sec", + JOB_NAME_DETECTIVE = "detective", + JOB_NAME_BRIGPHYSICIAN = "brigphys", + JOB_NAME_DEPUTY = "deputy", + // ETC + "Unassigned" = "id", + JOB_NAME_PRISONER = "orange", + // EMAG + "CentCom (Custom)" = "centcom", + "CentCom" = "centcom", + "ERT" = "ert", + JOB_NAME_VIP = "gold", + JOB_NAME_KING = "gold", + "Syndicate" = "syndicate", + "Clown Operative" = "clown_op", + "Unknown" = "unknown", + // ETC2 + "Ratvar" = "ratvar" + ) + return id_style[jobname] || "noname" // default: a card with no shape + +// This returns a hud icon (from `hud.dmi`) by given job name. +// Some custom title is from `PDApainter.dm`. You neec to check it if you're going to remove custom job. +/proc/get_hud_by_jobname(jobname) + if(!jobname) + CRASH("The proc has taken a null value") + + var/static/id_to_hud = list( + // Command + "Command (Custom)" = JOB_HUD_RAWCOMMAND, + JOB_NAME_CAPTAIN = JOB_HUD_CAPTAIN, + "Acting Captain" = JOB_HUD_ACTINGCAPTAIN , + + // Service + "Service (Custom)" = JOB_HUD_RAWSERVICE, + JOB_NAME_HEADOFPERSONNEL = JOB_HUD_HEADOFPERSONNEL, + JOB_NAME_ASSISTANT = JOB_HUD_ASSISTANT, + JOB_NAME_BARTENDER = JOB_HUD_BARTENDER, + JOB_NAME_COOK = JOB_HUD_COOK, + JOB_NAME_BOTANIST = JOB_HUD_BOTANIST, + JOB_NAME_CURATOR = JOB_HUD_CURATOR, + JOB_NAME_CHAPLAIN = JOB_HUD_CHAPLAIN, + JOB_NAME_JANITOR = JOB_HUD_JANITOR, + JOB_NAME_LAWYER = JOB_HUD_LAWYER, + JOB_NAME_MIME = JOB_HUD_MIME, + JOB_NAME_CLOWN = JOB_HUD_CLOWN, + JOB_NAME_STAGEMAGICIAN = JOB_HUD_STAGEMAGICIAN, + JOB_NAME_BARBER = JOB_HUD_BARBER, + + // Cargo + "Cargo (Custom)" = JOB_HUD_RAWCARGO, + JOB_NAME_QUARTERMASTER = JOB_HUD_QUARTERMASTER, + JOB_NAME_CARGOTECHNICIAN = JOB_HUD_CARGOTECHNICIAN, + JOB_NAME_SHAFTMINER = JOB_HUD_SHAFTMINER, + + // Engineering + "Engineering (Custom)" = JOB_HUD_RAWENGINEERING, + JOB_NAME_CHIEFENGINEER = JOB_HUD_CHIEFENGINEER, + JOB_NAME_STATIONENGINEER = JOB_HUD_STATIONENGINEER, + JOB_NAME_ATMOSPHERICTECHNICIAN = JOB_HUD_ATMOSPHERICTECHNICIAN, + + // Medical + "Medical (Custom)" = JOB_HUD_RAWMEDICAL, + JOB_NAME_CHIEFMEDICALOFFICER = JOB_HUD_CHEIFMEDICALOFFICIER, + JOB_NAME_MEDICALDOCTOR = JOB_HUD_MEDICALDOCTOR, + JOB_NAME_PARAMEDIC = JOB_HUD_PARAMEDIC, + JOB_NAME_VIROLOGIST = JOB_HUD_VIROLOGIST, + JOB_NAME_CHEMIST = JOB_HUD_CHEMIST, + JOB_NAME_GENETICIST = JOB_HUD_GENETICIST, + JOB_NAME_PSYCHIATRIST = JOB_HUD_PSYCHIATRIST, + + // R&D + "Science (Custom)" = JOB_HUD_RAWSCIENCE, + JOB_NAME_RESEARCHDIRECTOR = JOB_HUD_RESEARCHDIRECTOR, + JOB_NAME_SCIENTIST = JOB_HUD_SCIENTIST, + JOB_NAME_ROBOTICIST = JOB_HUD_ROBOTICIST, + JOB_NAME_EXPLORATIONCREW = JOB_HUD_EXPLORATIONCREW, + + // Security + "Security (Custom)" = JOB_HUD_RAWSECURITY, + JOB_NAME_HEADOFSECURITY = JOB_HUD_HEADOFSECURITY, + JOB_NAME_SECURITYOFFICER = JOB_HUD_SECURITYOFFICER, + JOB_NAME_WARDEN = JOB_HUD_WARDEN, + JOB_NAME_DETECTIVE = JOB_HUD_DETECTIVE, + JOB_NAME_BRIGPHYSICIAN = JOB_HUD_BRIGPHYSICIAN, + JOB_NAME_DEPUTY = JOB_HUD_DEPUTY, + + // CentCom + "CentCom (Custom)" = JOB_HUD_RAWCENTCOM, + "CentCom" = JOB_HUD_CENTCOM, + "ERT" = JOB_HUD_CENTCOM, + + // ETC + JOB_NAME_VIP = JOB_HUD_VIP, + JOB_NAME_KING = JOB_HUD_KING, + "Syndicate" = JOB_HUD_SYNDICATE, + "Clown Operative" = JOB_HUD_SYNDICATE, + "Unassigned" = JOB_HUD_UNKNOWN, + JOB_NAME_PRISONER = JOB_HUD_PRISONER + ) + return id_to_hud[jobname] || JOB_HUD_UNKNOWN // default: a grey unknown hud + +// This returns a department for banking system by given hud icon. +// currently used in `card.dm` and `PDApainter.dm` to set a card's paycheck department +/proc/get_department_by_hud(jobname) + if(!jobname) + CRASH("The proc has taken a null value") + + var/static/hud_to_department_acc = list( + // Command + JOB_HUD_RAWCOMMAND = ACCOUNT_SEC, + JOB_HUD_CAPTAIN = ACCOUNT_SEC, + JOB_HUD_ACTINGCAPTAIN = ACCOUNT_SEC, + + // Service + Civilian + JOB_HUD_RAWSERVICE = ACCOUNT_SRV, + JOB_HUD_HEADOFPERSONNEL = ACCOUNT_SRV, + JOB_HUD_ASSISTANT = ACCOUNT_CIV, + JOB_HUD_BARTENDER = ACCOUNT_SRV, + JOB_HUD_COOK = ACCOUNT_SRV, + JOB_HUD_BOTANIST = ACCOUNT_SRV, + JOB_HUD_CURATOR = ACCOUNT_CIV, + JOB_HUD_CHAPLAIN = ACCOUNT_CIV, + JOB_HUD_JANITOR = ACCOUNT_SRV, + JOB_HUD_LAWYER = ACCOUNT_CIV, + JOB_HUD_MIME = ACCOUNT_SRV, + JOB_HUD_CLOWN = ACCOUNT_SRV, + JOB_HUD_STAGEMAGICIAN = ACCOUNT_SRV, + JOB_HUD_BARBER = ACCOUNT_CIV, + + // Cargo + JOB_HUD_RAWCARGO = ACCOUNT_CAR, + JOB_HUD_QUARTERMASTER = ACCOUNT_CAR, + JOB_HUD_CARGOTECHNICIAN = ACCOUNT_CAR, + JOB_HUD_SHAFTMINER = ACCOUNT_CAR, + + // Engineering + JOB_HUD_RAWENGINEERING = ACCOUNT_ENG, + JOB_HUD_CHIEFENGINEER = ACCOUNT_ENG, + JOB_HUD_STATIONENGINEER = ACCOUNT_ENG, + JOB_HUD_ATMOSPHERICTECHNICIAN = ACCOUNT_ENG, + + // Medical + JOB_HUD_RAWMEDICAL = ACCOUNT_MED, + JOB_HUD_CHEIFMEDICALOFFICIER = ACCOUNT_MED, + JOB_HUD_MEDICALDOCTOR = ACCOUNT_MED, + JOB_HUD_PARAMEDIC = ACCOUNT_MED, + JOB_HUD_VIROLOGIST = ACCOUNT_MED, + JOB_HUD_CHEMIST = ACCOUNT_MED, + JOB_HUD_GENETICIST = ACCOUNT_MED, + JOB_HUD_PSYCHIATRIST = ACCOUNT_MED, + + // R&D + JOB_HUD_RAWSCIENCE = ACCOUNT_SCI, + JOB_HUD_RESEARCHDIRECTOR = ACCOUNT_SCI, + JOB_HUD_SCIENTIST = ACCOUNT_SCI, + JOB_HUD_ROBOTICIST = ACCOUNT_SCI, + JOB_HUD_EXPLORATIONCREW = ACCOUNT_SCI, + + // Security + JOB_HUD_RAWSECURITY = ACCOUNT_SEC, + JOB_HUD_HEADOFSECURITY = ACCOUNT_SEC, + JOB_HUD_SECURITYOFFICER = ACCOUNT_SEC, + JOB_HUD_WARDEN = ACCOUNT_SEC, + JOB_HUD_DETECTIVE = ACCOUNT_SEC, + JOB_HUD_BRIGPHYSICIAN = ACCOUNT_SEC, + JOB_HUD_DEPUTY = ACCOUNT_SEC, + + // CentCom + JOB_HUD_RAWCENTCOM = ACCOUNT_CIV, + JOB_HUD_CENTCOM = ACCOUNT_CIV, + + // ETC + JOB_HUD_VIP = ACCOUNT_CIV, // Fake VIP gets a station department + JOB_HUD_KING = ACCOUNT_CIV, + JOB_HUD_SYNDICATE = ACCOUNT_CIV, + JOB_HUD_UNKNOWN = ACCOUNT_CIV, + JOB_HUD_PRISONER = ACCOUNT_CIV + ) + return hud_to_department_acc[jobname] || ACCOUNT_CIV // default: Civ budget department + +// used to determine chat color by HUD in `chatmessage.dm` +// Note: custom colors are what I really didn't put much attention into. feel free to change its color when you feel off. +/datum/chatmessage/proc/get_chatcolor_by_hud(jobname) + if(!jobname) + CRASH("The proc has taken a null value") + + var/static/hud_to_chatcolor = list( + // Command + JOB_HUD_RAWCOMMAND = JOB_CHATCOLOR_RAWCOMMAND, + JOB_HUD_CAPTAIN = JOB_CHATCOLOR_CAPTAIN, + JOB_HUD_ACTINGCAPTAIN = JOB_CHATCOLOR_ACTINGCAPTAIN, + + // Service + JOB_HUD_RAWSERVICE = JOB_CHATCOLOR_RAWSERVICE, + JOB_HUD_HEADOFPERSONNEL = JOB_CHATCOLOR_HEADOFPERSONNEL, + JOB_HUD_ASSISTANT = JOB_CHATCOLOR_ASSISTANT, + JOB_HUD_BARTENDER = JOB_CHATCOLOR_BARTENDER, + JOB_HUD_COOK = JOB_CHATCOLOR_COOK, + JOB_HUD_BOTANIST = JOB_CHATCOLOR_BOTANIST, + JOB_HUD_CURATOR = JOB_CHATCOLOR_CURATOR, + JOB_HUD_CHAPLAIN = JOB_CHATCOLOR_CHAPLAIN, + JOB_HUD_JANITOR = JOB_CHATCOLOR_JANITOR, + JOB_HUD_LAWYER = JOB_CHATCOLOR_LAWYER, + JOB_HUD_MIME = JOB_CHATCOLOR_MIME, + JOB_HUD_CLOWN = JOB_CHATCOLOR_CLOWN, + JOB_HUD_STAGEMAGICIAN = JOB_CHATCOLOR_STAGEMAGICIAN, + JOB_HUD_BARBER = JOB_CHATCOLOR_BARBER, + + // Cargo + JOB_HUD_RAWCARGO = JOB_CHATCOLOR_RAWCARGO, + JOB_HUD_QUARTERMASTER = JOB_CHATCOLOR_QUARTERMASTER, + JOB_HUD_CARGOTECHNICIAN = JOB_CHATCOLOR_CARGOTECHNICIAN, + JOB_HUD_SHAFTMINER = JOB_CHATCOLOR_SHAFTMINER, + + // Engineering + JOB_HUD_RAWENGINEERING = JOB_CHATCOLOR_RAWENGINEERING, + JOB_HUD_CHIEFENGINEER = JOB_CHATCOLOR_CHIEFENGINEER, + JOB_HUD_STATIONENGINEER = JOB_CHATCOLOR_STATIONENGINEER, + JOB_HUD_ATMOSPHERICTECHNICIAN = JOB_CHATCOLOR_ATMOSPHERICTECHNICIAN, + + // Medical + JOB_HUD_RAWMEDICAL = JOB_CHATCOLOR_RAWMEDICAL, + JOB_HUD_CHEIFMEDICALOFFICIER = JOB_CHATCOLOR_CHEIFMEDICALOFFICIER, + JOB_HUD_MEDICALDOCTOR = JOB_CHATCOLOR_MEDICALDOCTOR, + JOB_HUD_PARAMEDIC = JOB_CHATCOLOR_PARAMEDIC, + JOB_HUD_VIROLOGIST = JOB_CHATCOLOR_VIROLOGIST, + JOB_HUD_CHEMIST = JOB_CHATCOLOR_CHEMIST, + JOB_HUD_GENETICIST = JOB_CHATCOLOR_GENETICIST, + JOB_HUD_PSYCHIATRIST = JOB_CHATCOLOR_PSYCHIATRIST, + + // R&D + JOB_HUD_RAWSCIENCE = JOB_CHATCOLOR_RAWSCIENCE, + JOB_HUD_RESEARCHDIRECTOR = JOB_CHATCOLOR_RESEARCHDIRECTOR, + JOB_HUD_SCIENTIST = JOB_CHATCOLOR_SCIENTIST, + JOB_HUD_ROBOTICIST = JOB_CHATCOLOR_ROBOTICIST, + JOB_HUD_EXPLORATIONCREW = JOB_CHATCOLOR_EXPLORATIONCREW, + + // Security + JOB_HUD_RAWSECURITY = JOB_CHATCOLOR_RAWSECURITY, + JOB_HUD_HEADOFSECURITY = JOB_CHATCOLOR_HEADOFSECURITY, + JOB_HUD_WARDEN = JOB_CHATCOLOR_WARDEN, + JOB_HUD_SECURITYOFFICER = JOB_CHATCOLOR_SECURITYOFFICER, + JOB_HUD_DETECTIVE = JOB_CHATCOLOR_DETECTIVE, + JOB_HUD_BRIGPHYSICIAN = JOB_CHATCOLOR_BRIGPHYSICIAN, + JOB_HUD_DEPUTY = JOB_CHATCOLOR_DEPUTY, + + // CentCom + JOB_HUD_RAWCENTCOM = JOB_CHATCOLOR_RAWCENTCOM, + JOB_HUD_CENTCOM = JOB_CHATCOLOR_CENTCOM, + + // ETC + JOB_HUD_VIP = JOB_CHATCOLOR_VIP, + JOB_HUD_KING = JOB_CHATCOLOR_KING, + JOB_HUD_SYNDICATE = JOB_CHATCOLOR_SYNDICATE, + JOB_HUD_NOTCENTCOM = JOB_CHATCOLOR_NOTCENTCOM, + JOB_HUD_PRISONER = JOB_CHATCOLOR_PRISONER, + JOB_HUD_UNKNOWN = JOB_CHATCOLOR_UNKNOWN + ) + return hud_to_chatcolor[jobname] || JOB_CHATCOLOR_UNKNOWN + diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm index 39cee97dc63..380ebb4d4b0 100644 --- a/code/controllers/subsystem/economy.dm +++ b/code/controllers/subsystem/economy.dm @@ -1,3 +1,5 @@ +#define VIP_BUDGET_BASE rand(8888888, 11111111) + SUBSYSTEM_DEF(economy) name = "Economy" wait = 5 MINUTES @@ -12,6 +14,7 @@ SUBSYSTEM_DEF(economy) ACCOUNT_SRV = ACCOUNT_SRV_NAME, ACCOUNT_CAR = ACCOUNT_CAR_NAME, ACCOUNT_SEC = ACCOUNT_SEC_NAME) + var/list/nonstation_accounts = list(ACCOUNT_VIP = ACCOUNT_VIP_NAME) var/list/generated_accounts = list() var/full_ancap = FALSE // Enables extra money charges for things that normally would be free, such as sleepers/cryo/cloning. //Take care when enabling, as players will NOT respond well if the economy is set up for low cash flows. @@ -25,6 +28,8 @@ SUBSYSTEM_DEF(economy) var/budget_to_hand_out = round(budget_pool / department_accounts.len) for(var/A in department_accounts) new /datum/bank_account/department(A, budget_to_hand_out) + for(var/A in nonstation_accounts) + new /datum/bank_account/department(A, VIP_BUDGET_BASE) return ..() /datum/controller/subsystem/economy/Recover() @@ -85,3 +90,9 @@ SUBSYSTEM_DEF(economy) sci?.adjust_money(science_cash) civ?.adjust_money(civilian_cash) car?.adjust_money(cargo_cash) + + // VIP budget will not dry + var/datum/bank_account/vip = get_dep_account(ACCOUNT_VIP) + vip?.adjust_money(cargo_cash) + +#undef VIP_BUDGET_BASE diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 403b04a5a26..15f83f8b130 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -220,7 +220,19 @@ return if(!storedid)//is the ID still there? return +<<<<<<< HEAD storedid.icon_state = id_icons[newidskin] +======= + storedid.icon_state = get_cardstyle_by_jobname(newidskin) + storedid.hud_state = get_hud_by_jobname(newidskin) + + // QoL to correct the system behavior + if(storedid.registered_account) + if(!storedid.registered_account.department_locked) + storedid.registered_account.account_department = get_department_by_hud(storedid.hud_state) // your true department by your hud icon color + GLOB.data_core.manifest_modify(storedid.registered_name, storedid.assignment, storedid.hud_state) // update crew manifest + // There are the same code lines in `card.dm` +>>>>>>> 2ee586c7bc... VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature) (#7330) ejectid() else to_chat(user, "[src] is empty.") diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index d2bd5458a6c..ae2c9de1b98 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -299,7 +299,7 @@ Class Procs: nap_violation(occupant) return FALSE var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department) - if(D) + if(D && !D.is_nonstation_account()) D.adjust_money(fair_market_price) else say("[market_verb] NAP Violation: No ID card found.") diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 1baf6947c20..f49b1609cd9 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -314,8 +314,8 @@ if(internal_radio) SPEAK("The cloning of [mob_occupant.real_name] has been ended prematurely due to being unable to pay.") else - var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department) - if(D) + var/datum/bank_account/department/D = SSeconomy.get_dep_account(payment_department) + if(D && !D.is_nonstation_account()) D.adjust_money(fair_market_price) if(mob_occupant && (mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes. connected_message("Clone Rejected: Deceased.") diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 90119e63e9b..258dafb6699 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -722,6 +722,86 @@ update_label("John Doe", "Clowny") department_ID = ACCOUNT_SEC department_name = ACCOUNT_SEC_NAME icon_state = "budget_sec" +<<<<<<< HEAD +======= + hud_state = JOB_HUD_RAWSECURITY + +// This will never be spawned, but should be trackable by admins anyway. +/obj/item/card/id/departmental_budget/vip + department_ID = ACCOUNT_VIP + department_name = ACCOUNT_VIP_NAME + icon_state = "budget" + hud_state = JOB_HUD_VIP + +/// Job Specific ID Cards/// +// These should have default job name and hud state, etc, because chameleon card needs such information +// ---- Command ---- +/obj/item/card/id/job/captain + name = "Job card (Com) - Captain" + icon_state = "captain" + assignment = JOB_NAME_CAPTAIN + hud_state = JOB_HUD_CAPTAIN + +/obj/item/card/id/job/rawcommand + name = "Job card (Com) - Custom" + icon_state = JOB_HUD_RAWCOMMAND + hud_state = JOB_HUD_RAWCOMMAND + +// ---- Service ---- +/obj/item/card/id/job/assistant + name = "Job card (Serv) - Assistant" + icon_state = "id" + assignment = JOB_NAME_ASSISTANT + hud_state = JOB_HUD_ASSISTANT + +/obj/item/card/id/job/head_of_personnel + name = "Job card (Serv) - HoP" + icon_state = "hop" + assignment = JOB_NAME_HEADOFPERSONNEL + hud_state = JOB_HUD_HEADOFPERSONNEL + +/obj/item/card/id/job/botanist + name = "Job card (Serv) - Botanist" + icon_state = "serv" + assignment = JOB_NAME_BOTANIST + hud_state = JOB_HUD_BOTANIST + +/obj/item/card/id/job/cook + name = "Job card (Serv) - Cook" + icon_state = "serv" + assignment = JOB_NAME_COOK + hud_state = JOB_HUD_COOK + +/obj/item/card/id/job/bartender + name = "Job card (Serv) - Bartender" + icon_state = "serv" + assignment = JOB_NAME_BARTENDER + hud_state = JOB_HUD_BARTENDER + +/obj/item/card/id/job/barber + name = "Job card (Serv) - Barber" + icon_state = "serv" + assignment = JOB_NAME_BARBER + hud_state = JOB_HUD_BARBER + +/obj/item/card/id/job/stage_magician + name = "Job card (Serv) - Magician" + icon_state = "serv" + assignment = JOB_NAME_STAGEMAGICIAN + hud_state = JOB_HUD_STAGEMAGICIAN + +/obj/item/card/id/job/curator + name = "Job card (Serv) - Curator" + icon_state = "chap" + assignment = JOB_NAME_CURATOR + hud_state = JOB_HUD_CURATOR + +/obj/item/card/id/job/chaplain + name = "Job card (Serv) - Chaplain" + icon_state = "chap" + assignment = JOB_NAME_CHAPLAIN + hud_state = JOB_HUD_CHAPLAIN +>>>>>>> 2ee586c7bc... VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature) (#7330) ///Job Specific ID Cards/// diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm new file mode 100644 index 00000000000..4e74d6cb3c5 --- /dev/null +++ b/code/game/objects/items/mail.dm @@ -0,0 +1,360 @@ +/// Mail is tamper-evident and unresealable, postmarked by CentCom for an individual recepient. +/obj/item/mail + name = "mail" + gender = NEUTER + desc = "An officially postmarked, tamper-evident parcel powered by bluespace technology and regulated by CentCom, it's made of rather high-quality materials." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "mail_small" + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + item_flags = NOBLUDGEON + w_class = WEIGHT_CLASS_SMALL + throwforce = 0 + throw_range = 1 + throw_speed = 1 + /// Destination tagging for the mail sorter. + mouse_drag_pointer = MOUSE_ACTIVE_POINTER + /// Weak reference to who this mail is for and who can open it. + var/sort_tag = 0 + /// How many goodies this mail contains. + var/datum/weakref/recipient_ref + /// Goodies which can be given to anyone. The base weight for cash is 56. For there to be a 50/50 chance of getting a department item, they need 56 weight as well. + var/goodie_count = 1 + + var/static/list/generic_goodies = list( + /obj/item/stack/spacecash/c10 = 22, //the lamest chance to get item, what do you expect really? + /obj/item/reagent_containers/food/drinks/soda_cans/pwr_game = 10, + /obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy = 10, + /obj/item/reagent_containers/food/snacks/cheesiehonkers = 10, + /obj/item/reagent_containers/food/snacks/candy = 10, + /obj/item/reagent_containers/food/snacks/chips = 10, + /obj/item/stack/spacecash/c50 = 10, + /obj/item/stack/spacecash/c100 = 25, + /obj/item/stack/spacecash/c200 = 15, + /obj/item/stack/spacecash/c500 = 5, + /obj/item/stack/spacecash/c1000 = 1 + ) + + //if the goodie is dangerous for the station, in this list it goes + var/static/list/hazard_goodies = list( + /obj/item/gun/ballistic/rifle/boltaction, + /obj/item/construction/rcd/arcd, + /obj/item/reagent_containers/spray/waterflower/superlube, + /mob/living/simple_animal/hostile/retaliate/clown, + /obj/item/clothing/accessory/holster/detective, + /obj/item/reagent_containers/hypospray/medipen/pumpup, + /obj/item/firing_pin, + /obj/item/storage/lockbox/loyalty, + /obj/item/grenade/clusterbuster/cleaner, + /obj/item/book/granter/spell/mimery_blockade, + /obj/item/gun/ballistic/rifle/boltaction/enchanted, + /obj/item/melee/classic_baton/police/telescopic, + /obj/item/reagent_containers/glass/bottle/random_virus/minor, + /obj/item/reagent_containers/glass/bottle/random_virus, + /obj/item/gun/ballistic/revolver/nagant + ) + + /// Overlays (pure fluff), Does the letter have the postmark overlay? + /// Does the letter have postmarks? + var/postmarked = TRUE + /// Does the letter have a stamp overlay? + var/stamped = TRUE + /// List of all stamp overlays on the letter. + var/list/stamps = list() + /// Maximum number of stamps on the letter. + var/stamp_max = 1 + /// Physical offset of stamps on the object. X direction. + var/stamp_offset_x = 0 + /// Physical offset of stamps on the object. Y direction. + var/stamp_offset_y = 2 + /// Mail will have the color of the department the recipient is in. + var/static/list/department_colors + +/obj/item/mail/envelope + name = "envelope" + icon_state = "mail_large" + goodie_count = 2 + stamp_max = 2 + stamp_offset_y = 5 + +/obj/item/mail/examine(mob/user) + . = ..() + + var/datum/mind/recipient + if(recipient_ref) + recipient = recipient_ref.resolve() + var/msg = "You notice the postmarking on the front of the mail..." + if(recipient) + msg += "\nCertified NT mail for [recipient]." + else + msg += "\nCertified mail for [GLOB.station_name]." + . += "\n[msg]" + + +/obj/item/mail/Initialize() + . = ..() + RegisterSignal(src, COMSIG_MOVABLE_DISPOSING, .proc/disposal_handling) + AddElement(/datum/element/item_scaling, 0.75, 1) + if(isnull(department_colors)) + department_colors = list( + ACCOUNT_CIV = COLOR_WHITE, + ACCOUNT_ENG = COLOR_PALE_ORANGE, + ACCOUNT_SCI = COLOR_PALE_PURPLE_GRAY, + ACCOUNT_MED = COLOR_PALE_BLUE_GRAY, + ACCOUNT_SRV = COLOR_PALE_GREEN_GRAY, + ACCOUNT_CAR = COLOR_BEIGE, + ACCOUNT_SEC = COLOR_PALE_RED_GRAY, + ACCOUNT_VIP = COLOR_YELLOW, + ) + + // Icons + // Add some random stamps. + if(stamped) + var/stamp_count = rand(1, stamp_max) + for(var/i in 1 to stamp_count) + stamps += list("stamp_[rand(2, 10)]") + update_icon() + +/obj/item/mail/update_overlays() + . = ..() + var/bonus_stamp_offset = 0 + for(var/stamp in stamps) + var/image/stamp_image = image( + icon = icon, + icon_state = stamp, + pixel_x = stamp_offset_x, + pixel_y = stamp_offset_y + bonus_stamp_offset + ) + stamp_image.appearance_flags |= RESET_COLOR + add_overlay(stamp_image) + bonus_stamp_offset -= 5 + + if(postmarked) + var/image/postmark_image = image( + icon = icon, + icon_state = "postmark", + pixel_x = stamp_offset_x + rand(-3, 1), + pixel_y = stamp_offset_y + rand(bonus_stamp_offset + 3, 1) + ) + postmark_image.appearance_flags |= RESET_COLOR + add_overlay(postmark_image) + +/obj/item/mail/attackby(obj/item/W, mob/user, params) + // Destination tagging + if(istype(W, /obj/item/dest_tagger)) + var/obj/item/dest_tagger/destination_tag = W + + if(sort_tag != destination_tag.currTag) + var/tag = uppertext(GLOB.TAGGERLOCATIONS[destination_tag.currTag]) + to_chat(user, "*[tag]*") + sort_tag = destination_tag.currTag + playsound(loc, 'sound/machines/twobeep_high.ogg', 100, 1) + +/obj/item/mail/attack_self(mob/user) + if(recipient_ref) + var/datum/mind/recipient = recipient_ref.resolve() + // If the recipient's mind has gone, then anyone can open their mail + // whether a mind can actually be qdel'd is an exercise for the reader + if(recipient && recipient != user?.mind) + if(!is_changeling(user)) + to_chat(user, "You can't open somebody else's mail! That's immoral!") + return + if(user.real_name != recipient.name) + to_chat(user, "We must keep our disguise intact.") // cuz your disguise cant open the mail so you shouldnt either + return + + user.visible_message("[user] start to unwrap a package...", \ + "You start to unwrap the package...", \ + "You hear paper ripping.") + if(!do_after(user, 1.5 SECONDS, target = user)) + return + user.temporarilyRemoveItemFromInventory(src, TRUE) + if(contents.len) + user.put_in_hands(contents[1]) + playsound(loc, 'sound/items/poster_ripped.ogg', 50, 1) + qdel(src) + +// Accepts a mind to initialize goodies for a piece of mail. +/obj/item/mail/proc/initialize_for_recipient(datum/mind/recipient) + switch(rand(1,5)) + if(5) + name = "[initial(name)] critical to [recipient.name] ([recipient.assigned_role])" + else + name = "[initial(name)] for [recipient.name] ([recipient.assigned_role])" + recipient_ref = WEAKREF(recipient) + + //Recipients + var/mob/living/body = recipient.current + //Load the generic list of goodies + var/list/goodies = generic_goodies.Copy() + //Load the List of Dangerous goodies + var/list/danger_goodies = hazard_goodies + + //Load the job the player have + var/datum/job/this_job = SSjob.name_occupations[recipient.assigned_role] + if(this_job) + goodies += this_job.mail_goodies + if(this_job.paycheck_department && department_colors[this_job.paycheck_department]) + color = department_colors[this_job.paycheck_department] + + for(var/i in 1 to goodie_count) + var/target_good = pickweight(goodies) + var/atom/movable/target_atom = new target_good(src) + body.log_message("[key_name(body)] received [target_atom.name] in the mail ([target_good])", LOG_GAME) + if(target_atom.type in danger_goodies) + message_admins("DANGEROUS ITEM RECIEVED:[ADMIN_LOOKUPFLW(body)] received [target_atom.name] in the mail ([target_good]) as a [recipient.assigned_role]") + + return TRUE + +// Alternate setup, just complete garbage inside and anyone can open +/obj/item/mail/proc/junk_mail() + + var/obj/junk = /obj/item/paper/fluff/junkmail_generic + var/special_name = FALSE + add_overlay("[initial(icon_state)]-spam") + + if(prob(25)) + special_name = TRUE + junk = pick(list(/obj/item/paper/pamphlet/gateway, + /obj/item/paper/pamphlet/violent_video_games, + /obj/item/paper/fluff/junkmail_redpill, + /obj/item/paper/fluff/nice_argument + )) + + var/static/list/junk_names = list( + /obj/item/paper/pamphlet/gateway = "[initial(name)] for [pick(GLOB.adjectives)] adventurers", + /obj/item/paper/pamphlet/violent_video_games = "[initial(name)] for the truth about the arcade centcom doesn't want to hear", + /obj/item/paper/fluff/junkmail_redpill = "[initial(name)] for those feeling [pick(GLOB.adjectives)] working at Nanotrasen", + /obj/item/paper/fluff/nice_argument = "[initial(name)] with INCREDIBLY IMPORTANT ARTIFACT- DELIVER TO SCIENCE DIVISION. HANDLE WITH CARE.", + ) + + //better spam mail names instead of being "IMPORTANT MAIL", courtesy of Monkestation + color = "#[pick(random_short_color())]" + switch(rand(1,10)) + + if(1,2) + name = special_name ? junk_names[junk] : "[initial(name)] for [pick(GLOB.alive_mob_list)]" //LETTER FOR IAN / BUBBLEGUM / MONKEY(420) + if(3,4) + name = special_name ? junk_names[junk] : "[initial(name)] for [pick(GLOB.player_list)]" //Letter for ANYONE, even that wizard rampaging through the station. + if(5) + name = special_name ? junk_names[junk] : "DO NOT OPEN" + else + name = special_name ? junk_names[junk] : "[pick("important","critical","crucial","serious","vital")] [initial(name)]" + + junk = new junk(src) + return TRUE + +/obj/item/mail/proc/disposal_handling(disposal_source, obj/structure/disposalholder/disposal_holder, obj/machinery/disposal/disposal_machine, hasmob) + SIGNAL_HANDLER + if(!hasmob) + disposal_holder.destinationTag = sort_tag + +// Subtype that's always junkmail +/obj/item/mail/junkmail/Initialize() + . = ..() + junk_mail() + +/obj/structure/closet/crate/mail + name = "mail crate" + desc = "A certified post crate from CentCom." + icon_state = "mail_crate" + door_anim_time = 0 + +/* Fills this mail crate with N pieces of mail, where N is the lower of the amount var passed, +** and the maximum capacity of this crate. If N is larger than the number of alive human players, the excess will be junkmail.*/ +/obj/structure/closet/crate/mail/proc/populate(amount) + var/mail_count = min(amount, storage_capacity) + //fills the crate for the recipients + var/list/mail_recipients = list() + + for(var/mob/living/carbon/human/human in GLOB.player_list) + // Skip wizards, nuke ops, cyborgs and dead people; Centcom does not send them mail + if(human.stat == DEAD || !human.mind || !SSjob.GetJob(human.mind.assigned_role) || human.mind.special_role) + continue + + mail_recipients += human.mind + + if(mail_count < 15) + for(var/i in 1 to rand(3,8)) + var/obj/item/mail/new_mail + if(prob(FULL_CRATE_LETTER_ODDS)) + new_mail = new /obj/item/mail(src) + else + new_mail = new /obj/item/mail/envelope(src) + new_mail.junk_mail() + + for(var/i in 1 to mail_count) + var/datum/mind/recipient = pick_n_take(mail_recipients) + var/obj/item/mail/new_mail + if(prob(FULL_CRATE_LETTER_ODDS)) + new_mail = new /obj/item/mail(src) + else + new_mail = new /obj/item/mail/envelope(src) + if(recipient) + new_mail.initialize_for_recipient(recipient) + else + new_mail.junk_mail() + + update_icon() + +/// Crate for mail that automatically depletes the economy subsystem's pending mail counter. +/obj/structure/closet/crate/mail/economy/Initialize() + . = ..() + populate(SSeconomy.mail_waiting) + SSeconomy.mail_waiting = 0 + +/// Crate for mail that automatically generates a lot of mail. Usually only normal mail, but on lowpop it may end up just being junk. +/obj/structure/closet/crate/mail/full + name = "brimming mail crate" + desc = "A certified post crate from CentCom. Looks stuffed to the gills." + +/obj/structure/closet/crate/mail/full/Initialize() + . = ..() + populate(null) + +/obj/item/paper/fluff/junkmail_redpill + name = "smudged paper" + icon_state = "scrap" + var/nuclear_option_odds = 0.1 + +/obj/item/paper/fluff/nice_argument + name = "RE: Nice Argument..." + icon_state = "paper" + +/obj/item/paper/fluff/nice_argument/Initialize() + . = ..() + var/station_name = station_name() + info = "Nice argument, however there's a small detail...
IP: '[rand(0,10)].[rand(0,255)].[rand(0,255)].[rand(0,255)]'
Station name: '[station_name]'
" + +/obj/item/paper/fluff/junkmail_redpill/Initialize() + . = ..() + // 1 in 1000 chance of getting 2 random nuke code characters. + if(!prob(nuclear_option_odds)) + info = "You need to escape the simulation. Don't forget the numbers, they help you remember: '[random_code(4)]...'" + return + var/code = random_code(5) + for(var/obj/machinery/nuclearbomb/selfdestruct/nuke in GLOB.nuke_list) + if(nuke) + if(nuke.r_code == "ADMIN") + nuke.r_code = code + message_admins("Through junkmail, the self-destruct code was set to \"[code]\".") + else //Already set by admins/something else? + code = nuke.r_code + else + stack_trace("Station self-destruct not found during lone op team creation.") + code = null + info = "You need to escape the simulation. Don't forget the numbers, they help you remember: '[code[rand(1,5)]][code[rand(1,5)]][code[rand(1,5)]][code[rand(1,5)]]...'" + +//admin letter enabling players to brute force their way through the nuke code if they're so inclined. +/obj/item/paper/fluff/junkmail_redpill/true + nuclear_option_odds = 100 + +/obj/item/paper/fluff/junkmail_generic + name = "important document" + desc = "I wonder what's so important here..." + icon_state = "paper_spam" + color = "#FFCCFF" + +/obj/item/paper/fluff/junkmail_generic/Initialize() + . = ..() + info = pick(GLOB.junkmail_messages) diff --git a/code/modules/economy/account.dm b/code/modules/economy/account.dm index 4909704a681..13a0964a0da 100644 --- a/code/modules/economy/account.dm +++ b/code/modules/economy/account.dm @@ -1,3 +1,4 @@ +#define DEPARTMENT_LOCKED_JOBS list("VIP", "Captain", "Head of Security") #define DUMPTIME 3000 /datum/bank_account @@ -14,6 +15,7 @@ var/welfare = FALSE var/being_dumped = FALSE //pink levels are rising var/withdrawDelay = 0 + var/department_locked = FALSE //TRUE locks from changing `account_department` into something else. used for VIP, Captain, and HoS. Those jobs don't need to change paycheck department. /datum/bank_account/New(newname, job) if(add_to_accounts) @@ -22,6 +24,12 @@ account_job = job account_id = rand(111111,999999) paycheck_amount = account_job.paycheck +<<<<<<< HEAD +======= + account_department = account_job.paycheck_department + if(account_job.title in DEPARTMENT_LOCKED_JOBS) + department_locked = TRUE +>>>>>>> 2ee586c7bc... VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature) (#7330) /datum/bank_account/Destroy() if(add_to_accounts) @@ -116,7 +124,17 @@ /datum/bank_account/department/New(dep_id, budget) department_id = dep_id account_balance = budget - account_holder = SSeconomy.department_accounts[dep_id] + var/list/total_department_list = SSeconomy.department_accounts+SSeconomy.nonstation_accounts + + account_holder = total_department_list[dep_id] + SSeconomy.generated_accounts += src +/datum/bank_account/proc/is_nonstation_account() // returns TRUE if the budget account is not Station department. i.e.) medical budget, security budget: FALSE / `nonstation_accounts` like VIP one: TRUE + for(var/each in SSeconomy.nonstation_accounts) + if(account_holder == SSeconomy.nonstation_accounts[each]) + return TRUE + return FALSE + #undef DUMPTIME +#undef DEPARTMENT_LOCKED_JOBS diff --git a/code/modules/jobs/job_types/gimmick.dm b/code/modules/jobs/job_types/gimmick.dm index e88c2c3e48b..315539aa8c4 100644 --- a/code/modules/jobs/job_types/gimmick.dm +++ b/code/modules/jobs/job_types/gimmick.dm @@ -150,9 +150,17 @@ outfit = /datum/outfit/job/gimmick/celebrity access = list(ACCESS_MAINT_TUNNELS) //Assistants with shitloads of money, what could go wrong? minimal_access = list(ACCESS_MAINT_TUNNELS) +<<<<<<< HEAD gimmick = TRUE paycheck = PAYCHECK_VIP //our power is being fucking rich chat_color = "#ebc96b" +======= + paycheck = PAYCHECK_VIP //our power is being fucking rich + paycheck_department = ACCOUNT_VIP //budget will never dry + + departments = DEPARTMENT_BITFLAG_SERVICE // might need to be changed + rpg_title = "Master of Patronage" +>>>>>>> 2ee586c7bc... VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature) (#7330) species_outfits = list( SPECIES_PLASMAMAN = /datum/outfit/plasmaman/vip diff --git a/code/modules/modular_computers/file_system/programs/budgetordering.dm b/code/modules/modular_computers/file_system/programs/budgetordering.dm index db7e174cbc2..9970f294ae0 100644 --- a/code/modules/modular_computers/file_system/programs/budgetordering.dm +++ b/code/modules/modular_computers/file_system/programs/budgetordering.dm @@ -54,13 +54,21 @@ if(get_buyer_id(user)) if((ACCESS_HEADS in id_card.access) || (ACCESS_QM in id_card.access)) requestonly = FALSE +<<<<<<< HEAD buyer = SSeconomy.get_dep_account(id_card.registered_account.account_job.paycheck_department) +======= + buyer = SSeconomy.get_dep_account(id_card?.registered_account?.account_department) +>>>>>>> 2ee586c7bc... VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature) (#7330) can_approve_requests = TRUE else requestonly = TRUE can_approve_requests = FALSE else requestonly = TRUE + if(isnull(buyer)) + buyer = SSeconomy.get_dep_account(ACCOUNT_CAR) + else if(buyer.is_nonstation_account()) + buyer = SSeconomy.get_dep_account(ACCOUNT_CAR) if(buyer) data["points"] = buyer.account_balance @@ -213,7 +221,18 @@ computer.say("The application rejects [id_card].") return else +<<<<<<< HEAD account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department) +======= + account = SSeconomy.get_dep_account(id_card?.registered_account?.account_department) + if(isnull(account)) + computer.say("The application failed to identify [id_card].") + return + else if(account.is_nonstation_account()) + computer.say("The application rejects [id_card].") + return + +>>>>>>> 2ee586c7bc... VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature) (#7330) var/turf/T = get_turf(src) var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account) @@ -241,7 +260,13 @@ if(SO.id == id) var/obj/item/card/id/id_card = get_buyer_id(usr) if(id_card && id_card?.registered_account) +<<<<<<< HEAD SO.paying_account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department) +======= + SO.paying_account = SSeconomy.get_dep_account(id_card?.registered_account?.account_department) + if(SO.paying_account.is_nonstation_account()) + return +>>>>>>> 2ee586c7bc... VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature) (#7330) SSshuttle.requestlist -= SO SSshuttle.shoppinglist += SO . = TRUE From 4c5d98614e880c9ac19c4115ed173b51b47fd08b Mon Sep 17 00:00:00 2001 From: SinguloBot <88859067+SinguloBot@users.noreply.github.com> Date: Fri, 2 Sep 2022 12:38:38 +0200 Subject: [PATCH 2/2] VIP gets their own department budget than the civilian budget, and gets paid from it. (+department account lock feature)