diff --git a/code/__DEFINES/economy.dm b/code/__DEFINES/economy.dm
new file mode 100644
index 0000000000..bc9534f527
--- /dev/null
+++ b/code/__DEFINES/economy.dm
@@ -0,0 +1,35 @@
+#define STARTING_PAYCHECKS 5
+
+#define PAYCHECK_ASSISTANT 25
+#define PAYCHECK_MINIMAL 75
+#define PAYCHECK_EASY 125
+#define PAYCHECK_MEDIUM 175
+#define PAYCHECK_HARD 200
+#define PAYCHECK_COMMAND 250
+
+#define MAX_GRANT_CIV 2500
+#define MAX_GRANT_ENG 3000
+#define MAX_GRANT_SCI 5000
+#define MAX_GRANT_SECMEDSRV 3000
+
+#define ACCOUNT_CIV "CIV"
+#define ACCOUNT_CIV_NAME "Civil Budget"
+#define ACCOUNT_ENG "ENG"
+#define ACCOUNT_ENG_NAME "Engineering Budget"
+#define ACCOUNT_SCI "SCI"
+#define ACCOUNT_SCI_NAME "Scientific Budget"
+#define ACCOUNT_MED "MED"
+#define ACCOUNT_MED_NAME "Medical Budget"
+#define ACCOUNT_SRV "SRV"
+#define ACCOUNT_SRV_NAME "Service Budget"
+#define ACCOUNT_CAR "CAR"
+#define ACCOUNT_CAR_NAME "Cargo Budget"
+#define ACCOUNT_SEC "SEC"
+#define ACCOUNT_SEC_NAME "Defense Budget"
+
+#define NO_FREEBIES "commies go home"
+
+//ID bank account support defines.
+#define ID_NO_BANK_ACCOUNT 0
+#define ID_FREE_BANK_ACCOUNT 1
+#define ID_LOCKED_BANK_ACCOUNT 2
diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm
index 73e900226e..8b529859ac 100644
--- a/code/__DEFINES/maps.dm
+++ b/code/__DEFINES/maps.dm
@@ -38,6 +38,7 @@ require only minor tweaks.
#define ZTRAIT_SPACE_RUINS "Space Ruins"
#define ZTRAIT_LAVA_RUINS "Lava Ruins"
#define ZTRAIT_ISOLATED_RUINS "Isolated Ruins" //Placing ruins on z levels with this trait will use turf reservation instead of usual placement.
+#define ZTRAIT_VIRTUAL_REALITY "Virtual Reality"
// number - bombcap is multiplied by this before being applied to bombs
#define ZTRAIT_BOMBCAP_MULTIPLIER "Bombcap Multiplier"
@@ -71,6 +72,7 @@ require only minor tweaks.
ZTRAIT_BOMBCAP_MULTIPLIER = 5, \
ZTRAIT_BASETURF = /turf/open/lava/smooth/lava_land_surface)
#define ZTRAITS_REEBE list(ZTRAIT_REEBE = TRUE, ZTRAIT_BOMBCAP_MULTIPLIER = 0.5)
+#define ZTRAITS_VR list(ZTRAIT_VIRTUAL_REALITY = TRUE, ZTRAIT_AWAY = TRUE)
#define DL_NAME "name"
#define DL_TRAITS "traits"
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index 06926317ee..84eed5483a 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -30,8 +30,9 @@
#define CHAT_GHOSTPDA (1<<8)
#define CHAT_GHOSTRADIO (1<<9)
#define CHAT_LOOC (1<<10)
+#define CHAT_BANKCARD (1<<11)
-#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC)
+#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC|CHAT_BANKCARD)
#define PARALLAX_INSANE -1 //for show offs
#define PARALLAX_HIGH 0 //default.
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index 5aa0301bf6..104e69706c 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -65,6 +65,7 @@
#define INIT_ORDER_INSTRUMENTS 53
#define INIT_ORDER_MAPPING 50
#define INIT_ORDER_NETWORKS 45
+#define INIT_ORDER_ECONOMY 40
#define INIT_ORDER_ATOMS 30
#define INIT_ORDER_LANGUAGE 25
#define INIT_ORDER_MACHINES 20
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index 170d93c31f..679f89f4d2 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -506,6 +506,19 @@
return
winset(C, "mainwindow", "flash=5")
+//Recursively checks if an item is inside a given type, even through layers of storage. Returns the atom if it finds it.
+/proc/recursive_loc_check(atom/movable/target, type)
+ var/atom/A = target
+ if(istype(A, type))
+ return A
+
+ while(!istype(A.loc, type))
+ if(!A.loc)
+ return
+ A = A.loc
+
+ return A.loc
+
/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank)
if(!SSticker.IsRoundInProgress() || QDELETED(character))
return
diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm
index 3e6e88c8fa..c903314da0 100644
--- a/code/__HELPERS/level_traits.dm
+++ b/code/__HELPERS/level_traits.dm
@@ -12,3 +12,5 @@
#define is_reserved_level(z) SSmapping.level_trait(z, ZTRAIT_RESERVED)
#define is_away_level(z) SSmapping.level_trait(z, ZTRAIT_AWAY)
+
+#define is_vr_level(z) SSmapping.level_trait(z, ZTRAIT_VIRTUAL_REALITY)
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index afa858afb7..5b91afca4c 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1025,6 +1025,27 @@ B --><-- A
/proc/get_random_station_turf()
return safepick(get_area_turfs(pick(GLOB.the_station_areas)))
+/proc/get_safe_random_station_turf() //excludes dense turfs (like walls) and areas that have valid_territory set to FALSE
+ for (var/i in 1 to 5)
+ var/list/L = get_area_turfs(pick(GLOB.the_station_areas))
+ var/turf/target
+ while (L.len && !target)
+ var/I = rand(1, L.len)
+ var/turf/T = L[I]
+ var/area/X = get_area(T)
+ if(!T.density && X.valid_territory)
+ var/clear = TRUE
+ for(var/obj/O in T)
+ if(O.density)
+ clear = FALSE
+ break
+ if(clear)
+ target = T
+ if (!target)
+ L.Cut(I,I+1)
+ if (target)
+ return target
+
/proc/get_closest_atom(type, list, source)
var/closest_atom
var/closest_distance
@@ -1568,7 +1589,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/proc/blood_sucking_checks(var/mob/living/carbon/target, check_neck, check_blood)
//Bypass this if the target isnt carbon.
if(!iscarbon(target))
- return TRUE
+ return TRUE
if(check_neck)
if(istype(target.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace))
return FALSE
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index 968995e81d..8430e690cc 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -221,3 +221,5 @@ GLOBAL_LIST_INIT(numbers_as_words, world.file2list("strings/numbers_as_words.txt
GLOBAL_LIST_INIT(station_numerals, greek_letters + phonetic_alphabet + numbers_as_words + generate_number_strings())
GLOBAL_LIST_INIT(admiral_messages, list("Do you know how expensive these stations are?","Stop wasting my time.","I was sleeping, thanks a lot.","Stand and fight you cowards!","You knew the risks coming in.","Stop being paranoid.","Whatever's broken just build a new one.","No.", "null","Error: No comment given.", "It's a good day to die!"))
+
+GLOBAL_LIST_INIT(redacted_strings, list("\[REDACTED\]", "\[CLASSIFIED\]", "\[ARCHIVED\]", "\[EXPLETIVE DELETED\]", "\[EXPUNGED\]", "\[INFORMATION ABOVE YOUR SECURITY CLEARANCE\]", "\[MOVE ALONG CITIZEN\]", "\[NOTHING TO SEE HERE\]", "\[ACCESS DENIED\]"))
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index f11093cba7..63e3f489bd 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -74,6 +74,8 @@
/datum/config_entry/flag/disable_peaceborg
+/datum/config_entry/flag/economy //money money money money money money money money money money money money
+
/datum/config_entry/number/minimum_secborg_alert //Minimum alert level for secborgs to be chosen.
config_entry_value = 3
diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm
new file mode 100644
index 0000000000..078d122aa6
--- /dev/null
+++ b/code/controllers/subsystem/economy.dm
@@ -0,0 +1,139 @@
+SUBSYSTEM_DEF(economy)
+ name = "Economy"
+ wait = 5 MINUTES
+ init_order = INIT_ORDER_ECONOMY
+ runlevels = RUNLEVEL_GAME
+ var/roundstart_paychecks = 5
+ var/budget_pool = 35000
+ var/list/department_accounts = list(ACCOUNT_CIV = ACCOUNT_CIV_NAME,
+ ACCOUNT_ENG = ACCOUNT_ENG_NAME,
+ ACCOUNT_SCI = ACCOUNT_SCI_NAME,
+ ACCOUNT_MED = ACCOUNT_MED_NAME,
+ ACCOUNT_SRV = ACCOUNT_SRV_NAME,
+ ACCOUNT_CAR = ACCOUNT_CAR_NAME,
+ ACCOUNT_SEC = ACCOUNT_SEC_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.
+ var/alive_humans_bounty = 100
+ var/crew_safety_bounty = 1500
+ var/monster_bounty = 150
+ var/mood_bounty = 100
+ var/techweb_bounty = 250
+ var/slime_bounty = list("grey" = 10,
+ // tier 1
+ "orange" = 100,
+ "metal" = 100,
+ "blue" = 100,
+ "purple" = 100,
+ // tier 2
+ "dark purple" = 500,
+ "dark blue" = 500,
+ "green" = 500,
+ "silver" = 500,
+ "gold" = 500,
+ "yellow" = 500,
+ "red" = 500,
+ "pink" = 500,
+ // tier 3
+ "cerulean" = 750,
+ "sepia" = 750,
+ "bluespace" = 750,
+ "pyrite" = 750,
+ "light pink" = 750,
+ "oil" = 750,
+ "adamantine" = 750,
+ // tier 4
+ "rainbow" = 1000)
+ var/list/bank_accounts = list() //List of normal accounts (not department accounts)
+ var/list/dep_cards = list()
+
+/datum/controller/subsystem/economy/Initialize(timeofday)
+ 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)
+ return ..()
+
+/datum/controller/subsystem/economy/fire(resumed = 0)
+ eng_payout() // Payout based on nothing. What will replace it? Surplus power, powered APC's, air alarms? Who knows.
+ sci_payout() // Payout based on slimes.
+ secmedsrv_payout() // Payout based on crew safety, health, and mood.
+ civ_payout() // Payout based on ??? Profit
+ car_payout() // Cargo's natural gain in the cash moneys.
+ for(var/A in bank_accounts)
+ var/datum/bank_account/B = A
+ B.payday(1)
+
+
+/datum/controller/subsystem/economy/proc/get_dep_account(dep_id)
+ for(var/datum/bank_account/department/D in generated_accounts)
+ if(D.department_id == dep_id)
+ return D
+
+/datum/controller/subsystem/economy/proc/eng_payout()
+ var/engineering_cash = 3000
+ var/datum/bank_account/D = get_dep_account(ACCOUNT_ENG)
+ if(D)
+ D.adjust_money(engineering_cash)
+
+
+/datum/controller/subsystem/economy/proc/car_payout()
+ var/cargo_cash = 500
+ var/datum/bank_account/D = get_dep_account(ACCOUNT_CAR)
+ if(D)
+ D.adjust_money(cargo_cash)
+
+/datum/controller/subsystem/economy/proc/secmedsrv_payout()
+ var/crew
+ var/alive_crew
+ var/dead_monsters
+ var/cash_to_grant
+ for(var/mob/m in GLOB.mob_list)
+ if(isnewplayer(m))
+ continue
+ if(m.mind)
+ if(isbrain(m) || iscameramob(m))
+ continue
+ if(ishuman(m))
+ var/mob/living/carbon/human/H = m
+ crew++
+ if(H.stat != DEAD)
+ alive_crew++
+ var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
+ var/medical_cash = (H.health / H.maxHealth) * alive_humans_bounty
+ if(mood)
+ var/datum/bank_account/D = get_dep_account(ACCOUNT_SRV)
+ if(D)
+ var/mood_dosh = (mood.mood_level / 9) * mood_bounty
+ D.adjust_money(mood_dosh)
+ medical_cash *= (mood.sanity / 100)
+
+ var/datum/bank_account/D = get_dep_account(ACCOUNT_MED)
+ if(D)
+ D.adjust_money(medical_cash)
+ if(ishostile(m))
+ var/mob/living/simple_animal/hostile/H = m
+ if(H.stat == DEAD && (H.z in SSmapping.levels_by_trait(ZTRAIT_STATION)))
+ dead_monsters++
+ CHECK_TICK
+ var/living_ratio = alive_crew / crew
+ cash_to_grant = (crew_safety_bounty * living_ratio) + (monster_bounty * dead_monsters)
+ var/datum/bank_account/D = get_dep_account(ACCOUNT_SEC)
+ if(D)
+ D.adjust_money(min(cash_to_grant, MAX_GRANT_SECMEDSRV))
+
+/datum/controller/subsystem/economy/proc/sci_payout()
+ var/science_bounty = 0
+ for(var/mob/living/simple_animal/slime/S in GLOB.mob_list)
+ if(S.stat == DEAD)
+ continue
+ science_bounty += slime_bounty[S.colour]
+ var/datum/bank_account/D = get_dep_account(ACCOUNT_SCI)
+ if(D)
+ D.adjust_money(min(science_bounty, MAX_GRANT_SCI))
+
+/datum/controller/subsystem/economy/proc/civ_payout()
+ var/civ_cash = (rand(1,5) * 500)
+ var/datum/bank_account/D = get_dep_account(ACCOUNT_CIV)
+ if(D)
+ D.adjust_money(min(civ_cash, MAX_GRANT_CIV))
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index 91d0db85d1..7fc3f576de 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -477,6 +477,10 @@ SUBSYSTEM_DEF(job)
to_chat(M, "[job.custom_spawn_text]")
if(CONFIG_GET(number/minimal_access_threshold))
to_chat(M, "As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.")
+ if(ishuman(H))
+ var/mob/living/carbon/human/wageslave = H
+ to_chat(M, "Your account ID is [wageslave.account_id].")
+ H.add_memory("Your account ID is [wageslave.account_id].")
if(job && H)
if(job.dresscodecompliant)// CIT CHANGE - dress code compliance
equip_loadout(N, H) // CIT CHANGE - allows players to spawn with loadout items
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index f13d5a2779..5a1f17e8fb 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -438,9 +438,12 @@ GLOBAL_LIST_EMPTY(the_station_areas)
else
if(answer in GLOB.potentialRandomZlevels)
away_name = answer
+ var/list/traits = list(ZTRAIT_AWAY = TRUE)
+ if(answer in GLOB.potentialRandomVRlevels)
+ traits[ZTRAIT_VIRTUAL_REALITY] = TRUE
to_chat(usr,"Loading [away_name]...")
var/datum/map_template/template = new(away_name, "Away Mission")
- away_level = template.load_new_z()
+ away_level = template.load_new_z(traits)
else
return
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index e4a3ff1f9a..b9ec1d647f 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -35,10 +35,8 @@ SUBSYSTEM_DEF(shuttle)
//supply shuttle stuff
var/obj/docking_port/mobile/supply/supply
var/ordernum = 1 //order number given to next order
- var/points = 5000 //number of trade-points we have
var/centcom_message = "" //Remarks from CentCom on how well you checked the last order.
var/list/discoveredPlants = list() //Typepaths for unusual plants we've already sent CentCom, associated with their potencies
- var/passive_supply_points_per_minute = 125
var/list/supply_packs = list()
var/list/shoppinglist = list()
@@ -113,9 +111,6 @@ SUBSYSTEM_DEF(shuttle)
qdel(T, force=TRUE)
CheckAutoEvac()
- if(!(times_fired % CEILING(600/wait, 1)))
- points += passive_supply_points_per_minute
-
var/esETA = emergency?.getModeStr()
emergency_shuttle_stat_text = "[esETA? "[esETA] [emergency.getTimerStr()]" : ""]"
@@ -559,7 +554,6 @@ SUBSYSTEM_DEF(shuttle)
centcom_message = SSshuttle.centcom_message
ordernum = SSshuttle.ordernum
- points = SSshuttle.points
emergencyNoEscape = SSshuttle.emergencyNoEscape
emergencyCallAmount = SSshuttle.emergencyCallAmount
shuttle_purchased = SSshuttle.shuttle_purchased
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 44a891e24a..48518f69c8 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -32,6 +32,9 @@
var/list/filter_data //For handling persistent filters
+ var/custom_price
+ var/custom_premium_price
+
var/datum/component/orbiter/orbiters
var/rad_flags = NONE // Will move to flags_1 when i can be arsed to
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 42904383bb..3f2edd7174 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -26,6 +26,8 @@
var/list/chem_buttons //Used when emagged to scramble which chem is used, eg: antitoxin -> morphine
var/scrambled_chems = FALSE //Are chem buttons scrambled? used as a warning
var/enter_message = "You feel cool air surround you. You go numb as your senses turn inward."
+ payment_department = ACCOUNT_MED
+ fair_market_price = 5
/obj/machinery/sleeper/Initialize()
. = ..()
@@ -205,6 +207,13 @@
ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state)
ui.open()
+/obj/machinery/sleeper/process()
+ ..()
+ check_nap_violations()
+
+/obj/machinery/sleeper/nap_violation(mob/violator)
+ open_machine()
+
/obj/machinery/sleeper/ui_data()
var/list/data = list()
var/chemical_list = list()
@@ -250,7 +259,7 @@
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
-
+
if(mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
chemical_list += list(list("name" = R.name, "volume" = R.volume))
@@ -290,7 +299,7 @@
if(..())
return
var/mob/living/mob_occupant = occupant
-
+ check_nap_violations()
switch(action)
if("door")
if(state_open)
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index 995d11acb7..93121a0753 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -121,6 +121,10 @@ Class Procs:
var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
+ var/fair_market_price = 69
+ var/market_verb = "Customer"
+ var/payment_department = ACCOUNT_ENG
+
/obj/machinery/Initialize()
if(!armor)
armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
@@ -248,6 +252,36 @@ Class Procs:
return FALSE
return TRUE
+/obj/machinery/proc/check_nap_violations()
+ if(!SSeconomy.full_ancap)
+ return TRUE
+ if(occupant && !state_open)
+ if(ishuman(occupant))
+ var/mob/living/carbon/human/H = occupant
+ var/obj/item/card/id/I = H.get_idcard()
+ if(I)
+ var/datum/bank_account/insurance = I.registered_account
+ if(!insurance)
+ say("[market_verb] NAP Violation: No bank account found.")
+ nap_violation()
+ return FALSE
+ else
+ if(!insurance.adjust_money(-fair_market_price))
+ say("[market_verb] NAP Violation: Unable to pay.")
+ nap_violation()
+ return FALSE
+ var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
+ if(D)
+ D.adjust_money(fair_market_price)
+ else
+ say("[market_verb] NAP Violation: No ID card found.")
+ nap_violation()
+ return FALSE
+ return TRUE
+
+/obj/machinery/proc/nap_violation(mob/violator)
+ return
+
////////////////////////////////////////////////////////////////////////////////////////////
//Return a non FALSE value to interrupt attack_hand propagation to subtypes.
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 6fa7fa30c0..e12e4c6cf5 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -32,6 +32,8 @@
var/list/datum/design/matching_designs
var/selected_category
var/screen = 1
+ var/base_price = 25
+ var/hacked_price = 50
var/list/categories = list(
"Tools",
diff --git a/code/game/machinery/bank_machine.dm b/code/game/machinery/bank_machine.dm
index 41867a8520..2b683f16a3 100644
--- a/code/game/machinery/bank_machine.dm
+++ b/code/game/machinery/bank_machine.dm
@@ -8,6 +8,7 @@
var/obj/item/radio/radio
var/radio_channel = RADIO_CHANNEL_COMMON
var/minimum_time_between_warnings = 400
+ var/syphoning_credits = 0
/obj/machinery/computer/bank_machine/Initialize()
. = ..()
@@ -25,9 +26,14 @@
if(istype(I, /obj/item/stack/spacecash))
var/obj/item/stack/spacecash/C = I
value = C.value * C.amount
+ else if(istype(I, /obj/item/holochip))
+ var/obj/item/holochip/H = I
+ value = H.credits
if(value)
- SSshuttle.points += value
- to_chat(user, "You deposit [I]. The station now has [SSshuttle.points] credits.")
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ if(D)
+ D.adjust_money(value)
+ to_chat(user, "You deposit [I]. The Cargo Budget is now [D.account_balance] cr.")
qdel(I)
return
return ..()
@@ -38,14 +44,16 @@
if(siphoning)
if (stat & (BROKEN|NOPOWER))
say("Insufficient power. Halting siphon.")
- siphoning = FALSE
- if(SSshuttle.points < 200)
- say("Station funds depleted. Halting siphon.")
- siphoning = FALSE
- else
- new /obj/item/stack/spacecash/c200(drop_location()) // will autostack
- playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1)
- SSshuttle.points -= 200
+ end_syphon()
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ if(!D.has_money(200))
+ say("Cargo budget depleted. Halting siphon.")
+ end_syphon()
+ return
+
+ playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1)
+ syphoning_credits += 200
+ D.adjust_money(-200)
if(next_warning < world.time && prob(15))
var/area/A = get_area(loc)
var/message = "Unauthorized credit withdrawal underway in [A.map_name]!!"
@@ -61,7 +69,8 @@
/obj/machinery/computer/bank_machine/ui_data(mob/user)
var/list/data = list()
- data["current_balance"] = SSshuttle.points
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ data["current_balance"] = D.account_balance
data["siphoning"] = siphoning
data["station_name"] = station_name()
@@ -78,5 +87,10 @@
. = TRUE
if("halt")
say("Station credit withdrawal halted.")
- siphoning = FALSE
+ end_syphon()
. = TRUE
+
+/obj/machinery/computer/bank_machine/proc/end_syphon()
+ siphoning = FALSE
+ new /obj/item/holochip(drop_location(), syphoning_credits) //get the loot
+ syphoning_credits = 0
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index bc0fec68ba..ecea8c74c3 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -37,6 +37,9 @@
var/list/unattached_flesh
var/flesh_number = 0
+ var/datum/bank_account/current_insurance
+ fair_market_price = 5 // He nodded, because he knew I was right. Then he swiped his credit card to pay me for arresting him.
+ payment_department = ACCOUNT_MED
/obj/machinery/clonepod/Initialize()
. = ..()
@@ -131,7 +134,7 @@
return examine(user)
//Start growing a human clone in the pod!
-/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks)
+/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -161,7 +164,7 @@
mess = TRUE
update_icon()
return FALSE
-
+ current_insurance = insurance
attempting = TRUE //One at a time!!
countdown.start()
@@ -224,15 +227,29 @@
connected_message("Clone Ejected: Loss of power.")
else if(mob_occupant && (mob_occupant.loc == src))
- if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes.
- connected_message("Clone Rejected: Deceased.")
+ if(SSeconomy.full_ancap)
+ if(!current_insurance)
+ go_out()
+ connected_message("Clone Ejected: No bank account.")
+ if(internal_radio)
+ SPEAK("The cloning of [mob_occupant.real_name] has been terminated due to no bank account to draw payment from.")
+ else if(!current_insurance.adjust_money(-fair_market_price))
+ go_out()
+ connected_message("Clone Ejected: Out of Money.")
+ 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)
+ 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.")
if(internal_radio)
SPEAK("The cloning has been \
aborted due to unrecoverable tissue failure.")
go_out()
mob_occupant.copy_from_prefs_vr()
- else if(mob_occupant.cloneloss > (100 - heal_level))
+ else if(mob_occupant && mob_occupant.cloneloss > (100 - heal_level))
mob_occupant.Unconscious(80)
var/dmg_mult = CONFIG_GET(number/damage_multiplier)
//Slowly get that clone healed and finished.
@@ -259,7 +276,7 @@
use_power(7500) //This might need tweaking.
- else if((mob_occupant.cloneloss <= (100 - heal_level)))
+ else if((mob_occupant && mob_occupant.cloneloss <= (100 - heal_level)))
connected_message("Cloning Process Complete.")
if(internal_radio)
SPEAK("The cloning cycle is complete.")
@@ -368,7 +385,7 @@
if(!mob_occupant)
return
-
+ current_insurance = null
REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_MUTATION_STASIS, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index b0e80b63d2..74cceacd12 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -467,7 +467,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
to_chat(usr, "No log exists for this job.")
updateUsrDialog()
return
-
+ if(inserted_modify_id.registered_account)
+ inserted_modify_id.registered_account.account_job = jobdatum // this is a terrible idea and people will grief but sure whatever
inserted_modify_id.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() )
if (inserted_modify_id)
inserted_modify_id.assignment = t1
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 07cc252b87..981a5643a8 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -73,7 +73,7 @@
if(pod.occupant)
continue //how though?
- if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"]))
+ if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"]))
temp = "[R.fields["name"]] => Cloning cycle in progress..."
records -= R
@@ -415,7 +415,7 @@
else if(pod.occupant)
temp = "Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"]))
+ else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"]))
temp = "[C.fields["name"]] => Cloning cycle in progress..."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
@@ -441,9 +441,13 @@
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
+ var/datum/bank_account/has_bank_account
if(ishuman(mob_occupant))
var/mob/living/carbon/C = mob_occupant
dna = C.has_dna()
+ var/obj/item/card/id/I = C.get_idcard()
+ if(I)
+ has_bank_account = I.registered_account
if(isbrain(mob_occupant))
var/mob/living/brain/B = mob_occupant
dna = B.stored_dna
@@ -468,7 +472,10 @@
scantemp = "Subject already in database."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
-
+ if(SSeconomy.full_ancap && !has_bank_account)
+ scantemp = "Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
var/datum/data/record/R = new()
if(dna.species)
// We store the instance rather than the path, because some
@@ -490,6 +497,7 @@
R.fields["features"] = dna.features
R.fields["factions"] = mob_occupant.faction
R.fields["quirks"] = list()
+ R.fields["bank_account"] = has_bank_account
for(var/V in mob_occupant.roundstart_quirks)
var/datum/quirk/T = V
R.fields["quirks"][T.type] = T.clone_data()
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 4c3d85a162..4cef487baf 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -163,11 +163,15 @@
else if(!S.prerequisites_met())
to_chat(usr, "You have not met the requirements for purchasing this shuttle.")
else
- if(SSshuttle.points >= S.credit_cost)
+ var/points_to_check
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ if(D)
+ points_to_check = D.account_balance
+ if(points_to_check >= S.credit_cost)
var/obj/machinery/shuttle_manipulator/M = locate() in GLOB.machines
if(M)
SSshuttle.shuttle_purchased = TRUE
- SSshuttle.points -= S.credit_cost
+ D.adjust_money(-S.credit_cost)
minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase")
message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].")
SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]")
@@ -576,7 +580,8 @@
dat += "
Lift access restrictions on maintenance and external airlocks?
\[ OK | Cancel \]"
if(STATE_PURCHASE)
- dat += "Budget: [SSshuttle.points] Credits.
"
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ dat += "Budget: [D.account_balance] Credits.
"
dat += "
"
dat += "Caution: Purchasing dangerous shuttles may lead to mutiny and/or death.
"
dat += "
"
diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm
index 7b90715f2b..fed54f55f8 100644
--- a/code/game/machinery/doors/airlock_electronics.dm
+++ b/code/game/machinery/doors/airlock_electronics.dm
@@ -1,6 +1,7 @@
/obj/item/electronics/airlock
name = "airlock electronics"
req_access = list(ACCESS_MAINT_TUNNELS)
+ custom_price = 50
var/list/accesses = list()
var/one_access = 0
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 1b83bb4b96..4533d18ae4 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -260,6 +260,7 @@
/obj/item/electronics/firelock
name = "firelock circuitry"
+ custom_price = 50
desc = "A circuit board used in construction of firelocks."
icon_state = "mainboard"
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index db806ef3ac..a9c411c634 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -174,9 +174,11 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
else
linked_techweb.largest_bomb_value = TECHWEB_BOMB_POINTCAP
point_gain = 1000
-
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SCI)
+ if(D)
+ D.adjust_money(point_gain)
linked_techweb.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, point_gain)
- say("Gained [point_gain] points from explosion dataset.")
+ say("Explosion details and mixture analyzed and sold to the highest bidder for [point_gain] cr, with a reward of [point_gain] points.")
else //you've made smaller bombs
say("Data already captured. Aborting.")
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index f4f308c490..16ad36d0e1 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -2,6 +2,7 @@
/obj/item/electronics/firealarm
name = "fire alarm electronics"
+ custom_price = 50
desc = "A fire alarm circuit. Can handle heat levels up to 40 degrees celsius."
/obj/item/wallframe/firealarm
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index d248556a9c..565030b13a 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -154,6 +154,7 @@ RLD
icon_state = "rcd"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
+ custom_price = 1700
max_matter = 160
item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
has_ammobar = TRUE
diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm
index ba0766de00..35843c1030 100644
--- a/code/game/objects/items/RSF.dm
+++ b/code/game/objects/items/RSF.dm
@@ -41,24 +41,21 @@ RSF
/obj/item/rsf/attack_self(mob/user)
playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
switch(mode)
+ if(5)
+ mode = 1
+ to_chat(user, "Changed dispensing mode to 'Drinking Glass'")
if(1)
mode = 2
- to_chat(user, "Changed dispensing mode to 'Drinking Glass'")
+ to_chat(user, "Changed dispensing mode to 'Paper'")
if(2)
mode = 3
- to_chat(user, "Changed dispensing mode to 'Paper'")
+ to_chat(user, "Changed dispensing mode to 'Pen'")
if(3)
mode = 4
- to_chat(user, "Changed dispensing mode to 'Pen'")
+ to_chat(user, "Changed dispensing mode to 'Dice Pack'")
if(4)
mode = 5
- to_chat(user, "Changed dispensing mode to 'Dice Pack'")
- if(5)
- mode = 6
to_chat(user, "Changed dispensing mode to 'Cigarette'")
- if(6)
- mode = 1
- to_chat(user, "Changed dispensing mode to 'Dosh'")
// Change mode
/obj/item/rsf/afterattack(atom/A, mob/user, proximity)
@@ -81,26 +78,22 @@ RSF
playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
switch(mode)
if(1)
- to_chat(user, "Dispensing Dosh...")
- new /obj/item/stack/spacecash/c10(T)
- use_matter(200, user)
- if(2)
to_chat(user, "Dispensing Drinking Glass...")
new /obj/item/reagent_containers/food/drinks/drinkingglass(T)
use_matter(20, user)
- if(3)
+ if(2)
to_chat(user, "Dispensing Paper Sheet...")
new /obj/item/paper(T)
use_matter(10, user)
- if(4)
+ if(3)
to_chat(user, "Dispensing Pen...")
new /obj/item/pen(T)
use_matter(50, user)
- if(5)
+ if(4)
to_chat(user, "Dispensing Dice Pack...")
new /obj/item/storage/pill_bottle/dice(T)
use_matter(200, user)
- if(6)
+ if(5)
to_chat(user, "Dispensing Cigarette...")
new /obj/item/clothing/mask/cigarette(T)
use_matter(10, user)
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index 20e0b09d26..bcc4697d0b 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -6,8 +6,6 @@
* FINGERPRINT CARD
*/
-
-
/*
* DATA CARDS - Used for the IC data card reader
*/
@@ -173,13 +171,19 @@
var/registered_name = null // The name registered_name on the card
var/assignment = null
var/access_txt // mapping aid
-
-
+ var/bank_support = ID_FREE_BANK_ACCOUNT
+ var/datum/bank_account/registered_account
+ var/obj/machinery/paystand/my_store
/obj/item/card/id/Initialize(mapload)
. = ..()
if(mapload && access_txt)
access = text2access(access_txt)
+ var/turf/T = get_turf(src)
+ if(bank_support == ID_FREE_BANK_ACCOUNT && is_vr_level(T.z)) //economy is quite exploitable on VR in so many ways.
+ bank_support = ID_NO_BANK_ACCOUNT
+ else if(bank_support == ID_LOCKED_BANK_ACCOUNT)
+ registered_account = new /datum/bank_account/remote/non_transferable(pick(GLOB.redacted_strings))
/obj/item/card/id/vv_edit_var(var_name, var_value)
. = ..()
@@ -193,12 +197,150 @@
user.visible_message("[user] shows you: [icon2html(src, viewers(user))] [src.name].", \
"You show \the [src.name].")
add_fingerprint(user)
+
+/obj/item/card/id/attackby(obj/item/W, mob/user, params)
+ if(!bank_support)
+ return ..()
+ if(istype(W, /obj/item/holochip))
+ insert_money(W, user)
+ else if(istype(W, /obj/item/stack/spacecash) || istype(W, /obj/item/coin))
+ insert_money(W, user, TRUE)
+ else if(istype(W, /obj/item/storage/bag/money))
+ var/obj/item/storage/bag/money/money_bag = W
+ var/list/money_contained = money_bag.contents
+ var/money_added = mass_insert_money(money_contained, user)
+ if (money_added)
+ to_chat(user, "You stuff the contents into the card! They disappear in a puff of bluespace smoke, adding [money_added] worth of credits to the linked account.")
+ else
+ return ..()
+
+/obj/item/card/id/proc/insert_money(obj/item/I, mob/user, physical_currency)
+ var/cash_money = I.get_item_credit_value()
+ if(!cash_money)
+ to_chat(user, "[I] doesn't seem to be worth anything!")
return
+ if(!registered_account)
+ to_chat(user, "[src] doesn't have a linked account to deposit [I] into!")
+ return
+
+ registered_account.adjust_money(cash_money)
+ if(physical_currency)
+ to_chat(user, "You stuff [I] into [src]. It disappears in a small puff of bluespace smoke, adding [cash_money] credits to the linked account.")
+ else
+ to_chat(user, "You insert [I] into [src], adding [cash_money] credits to the linked account.")
+
+ to_chat(user, "The linked account now reports a balance of [registered_account.account_balance] cr.")
+ qdel(I)
+
+/obj/item/card/id/proc/mass_insert_money(list/money, mob/user)
+ if (!money || !money.len)
+ return FALSE
+
+ var/total = 0
+
+ for (var/obj/item/physical_money in money)
+ var/cash_money = physical_money.get_item_credit_value()
+
+ total += cash_money
+
+ registered_account.adjust_money(cash_money)
+
+ QDEL_LIST(money)
+
+ return total
+
+/obj/item/card/id/proc/alt_click_can_use_id(mob/living/user)
+ if(!isliving(user))
+ return
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ return
+
+ return TRUE
+
+// Returns true if new account was set.
+/obj/item/card/id/proc/set_new_account(mob/living/user)
+ if(bank_support != ID_FREE_BANK_ACCOUNT)
+ to_chat(user, "This ID has no modular banking support whatsover, must be an older model...")
+ return
+ . = FALSE
+ var/datum/bank_account/old_account = registered_account
+
+ var/new_bank_id = input(user, "Enter your account ID number.", "Account Reclamation", 111111) as num | null
+
+ if (isnull(new_bank_id))
+ return
+
+ if(!alt_click_can_use_id(user))
+ return
+ if(!new_bank_id || new_bank_id < 111111 || new_bank_id > 999999)
+ to_chat(user, "The account ID number needs to be between 111111 and 999999.")
+ return
+ if (registered_account && registered_account.account_id == new_bank_id)
+ to_chat(user, "The account ID was already assigned to this card.")
+ return
+
+ for(var/A in SSeconomy.bank_accounts)
+ var/datum/bank_account/B = A
+ if(B.account_id == new_bank_id)
+ if (old_account)
+ old_account.bank_cards -= src
+
+ B.bank_cards += src
+ registered_account = B
+ to_chat(user, "The provided account has been linked to this ID card.")
+
+ return TRUE
+
+ to_chat(user, "The account ID number provided is invalid.")
+ return
+
+/obj/item/card/id/AltClick(mob/living/user)
+ . = ..()
+ if(!bank_support || !alt_click_can_use_id(user))
+ return
+
+ if(!registered_account)
+ set_new_account(user)
+ return
+
+ if (world.time < registered_account.withdrawDelay)
+ registered_account.bank_card_talk("ERROR: UNABLE TO LOGIN DUE TO SCHEDULED MAINTENANCE. MAINTENANCE IS SCHEDULED TO COMPLETE IN [(registered_account.withdrawDelay - world.time)/10] SECONDS.", TRUE)
+ return
+
+ var/amount_to_remove = FLOOR(input(user, "How much do you want to withdraw? Current Balance: [registered_account.account_balance]", "Withdraw Funds", 5) as num|null, 1)
+
+ if(!amount_to_remove || amount_to_remove < 0)
+ return
+ if(!alt_click_can_use_id(user))
+ return
+ if(registered_account.adjust_money(-amount_to_remove))
+ var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove)
+ user.put_in_hands(holochip)
+ to_chat(user, "You withdraw [amount_to_remove] credits into a holochip.")
+ return
+ else
+ var/difference = amount_to_remove - registered_account.account_balance
+ registered_account.bank_card_talk("ERROR: The linked account requires [difference] more credit\s to perform that withdrawal.", TRUE)
+
/obj/item/card/id/examine(mob/user)
. = ..()
if(mining_points)
. += "There's [mining_points] mining equipment redemption point\s loaded onto this card."
+ if(!bank_support || (bank_support == ID_LOCKED_BANK_ACCOUNT && !registered_account))
+ . += "This ID has no banking support whatsover, must be an older model..."
+ else if(registered_account)
+ . += "The account linked to the ID belongs to '[registered_account.account_holder]' and reports a balance of [registered_account.account_balance] cr."
+ if(registered_account.account_job)
+ var/datum/bank_account/D = SSeconomy.get_dep_account(registered_account.account_job.paycheck_department)
+ if(D)
+ . += "The [D.account_holder] reports a balance of [D.account_balance] cr."
+ . += "Alt-Click the ID to pull money from the linked account in the form of holochips."
+ . += "You can insert credits into the linked account by pressing holochips, cash, or coins against the ID."
+ if(registered_account.account_holder == user.real_name)
+ . += "If you lose this ID card, you can reclaim your account by Alt-Clicking a blank ID card while holding it and entering your account ID number."
+ else
+ . += "There is no registered account linked to this card. Alt-Click to add one."
/obj/item/card/id/GetAccess()
return access
@@ -278,7 +420,11 @@ update_label("John Doe", "Clowny")
else
return ..()
- var/popup_input = alert(user, "Choose Action", "Agent ID", "Show", "Forge/Reset")
+ var/popup_input
+ if(bank_support == ID_FREE_BANK_ACCOUNT)
+ popup_input = alert(user, "Choose Action", "Agent ID", "Show", "Forge/Reset", "Change Account ID")
+ else
+ popup_input = alert(user, "Choose Action", "Agent ID", "Show", "Forge/Reset")
if(user.incapacitated())
return
if(popup_input == "Forge/Reset" && !forged)
@@ -302,6 +448,18 @@ update_label("John Doe", "Clowny")
forged = TRUE
to_chat(user, "You successfully forge the ID card.")
log_game("[key_name(user)] has forged \the [initial(name)] with name \"[registered_name]\" and occupation \"[assignment]\".")
+
+ // First time use automatically sets the account id to the user.
+ if (first_use && !registered_account)
+ if(ishuman(user))
+ var/mob/living/carbon/human/accountowner = user
+
+ for(var/bank_account in SSeconomy.bank_accounts)
+ var/datum/bank_account/account = bank_account
+ if(account.account_id == accountowner.account_id)
+ account.bank_cards += src
+ registered_account = account
+ to_chat(user, "Your account number has been automatically assigned.")
return
else if (popup_input == "Forge/Reset" && forged)
registered_name = initial(registered_name)
@@ -311,6 +469,9 @@ update_label("John Doe", "Clowny")
forged = FALSE
to_chat(user, "You successfully reset the ID card.")
return
+ else if (popup_input == "Change Account ID")
+ set_new_account(user)
+ return
return ..()
/obj/item/card/id/syndicate/anyone
@@ -327,6 +488,15 @@ update_label("John Doe", "Clowny")
assignment = "Syndicate Overlord"
access = list(ACCESS_SYNDICATE)
+/obj/item/card/id/no_banking
+ bank_support = ID_NO_BANK_ACCOUNT
+
+/obj/item/card/id/locked_banking
+ bank_support = ID_LOCKED_BANK_ACCOUNT
+
+/obj/item/card/id/syndicate/locked_banking
+ bank_support = ID_LOCKED_BANK_ACCOUNT
+
/obj/item/card/id/captains_spare
name = "captain's spare ID"
desc = "The spare ID of the High Lord himself."
@@ -396,6 +566,17 @@ update_label("John Doe", "Clowny")
access = get_all_accesses()+get_ert_access("sec")-ACCESS_CHANGE_IDS
. = ..()
+/obj/item/card/id/debug
+ name = "\improper Debug ID"
+ desc = "A debug ID card. Has ALL the all access, you really shouldn't have this."
+ icon_state = "centcom"
+ assignment = "Jannie"
+
+/obj/item/card/id/debug/Initialize()
+ access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
+ registered_account = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ . = ..()
+
/obj/item/card/id/prisoner
name = "prisoner ID card"
desc = "You are a number, you are not a free man."
@@ -514,6 +695,34 @@ update_label("John Doe", "Clowny")
desc = "A special ID card that allows access to APC terminals."
access = list(ACCESS_ENGINE_EQUIP)
+/obj/item/card/id/departmental_budget
+ name = "departmental card (FUCK)"
+ desc = "Provides access to the departmental budget."
+ var/department_ID = ACCOUNT_CIV
+ var/department_name = ACCOUNT_CIV_NAME
+
+/obj/item/card/id/departmental_budget/Initialize()
+ . = ..()
+ var/datum/bank_account/B = SSeconomy.get_dep_account(department_ID)
+ if(B)
+ registered_account = B
+ if(!B.bank_cards.Find(src))
+ B.bank_cards += src
+ name = "departmental card ([department_name])"
+ desc = "Provides access to the [department_name]."
+ SSeconomy.dep_cards += src
+
+/obj/item/card/id/departmental_budget/Destroy()
+ SSeconomy.dep_cards -= src
+ return ..()
+
+/obj/item/card/id/departmental_budget/update_label()
+ return
+
+/obj/item/card/id/departmental_budget/car
+ department_ID = ACCOUNT_CAR
+ department_name = ACCOUNT_CAR_NAME
+
//Polychromatic Knight Badge
/obj/item/card/id/knight
@@ -577,4 +786,3 @@ update_label("John Doe", "Clowny")
/obj/item/card/id/debug/Initialize()
access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
. = ..()
-
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 2303278f5c..6ebeffe90f 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -506,6 +506,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
resistance_flags = FIRE_PROOF
light_color = LIGHT_COLOR_FIRE
grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/oil = 5)
+ custom_price = 55
/obj/item/lighter/Initialize()
. = ..()
@@ -710,7 +711,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
item_state = "black_vape"
w_class = WEIGHT_CLASS_TINY
var/chem_volume = 100
- var/vapetime = FALSE //this so it won't puff out clouds every tick
+ var/vapetime = FALSE //this so it won't puff out clouds every tick
var/screw = FALSE // kinky
var/super = FALSE //for the fattest vapes dude.
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index b13cfd9f64..890a17e52c 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -229,10 +229,11 @@
def_components = list(/obj/item/stack/ore/bluespace_crystal = /obj/item/stack/ore/bluespace_crystal/artificial)
/obj/item/circuitboard/machine/vendor
- name = "Booze-O-Mat Vendor (Machine Board)"
+ name = "Custom Vendor (Machine Board)"
desc = "You can turn the \"brand selection\" dial using a screwdriver."
- build_path = /obj/machinery/vending/boozeomat
- req_components = list(/obj/item/vending_refill/boozeomat = 1)
+ custom_premium_price = 100
+ build_path = /obj/machinery/vending/custom
+ req_components = list(/obj/item/vending_refill/custom = 1)
var/static/list/vending_names_paths = list(
/obj/machinery/vending/boozeomat = "Booze-O-Mat",
@@ -269,7 +270,8 @@
/obj/machinery/vending/wardrobe/viro_wardrobe = "ViroDrobe",
/obj/machinery/vending/clothing = "ClothesMate",
/obj/machinery/vending/medical = "NanoMed Plus",
- /obj/machinery/vending/wallmed = "NanoMed")
+ /obj/machinery/vending/wallmed = "NanoMed",
+ /obj/machinery/vending/custom = "Custom Vendor")
/obj/item/circuitboard/machine/vendor/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/screwdriver))
@@ -1019,6 +1021,11 @@
build_path = /obj/machinery/ore_silo
req_components = list()
+/obj/item/circuitboard/machine/paystand
+ name = "Pay Stand (Machine Board)"
+ build_path = /obj/machinery/paystand
+ req_components = list()
+
/obj/item/circuitboard/machine/autobottler
name = "Auto-Bottler (Machine Board)"
build_path = /obj/machinery/rnd/production/protolathe/department/autobottler //Manips make you print things cheaper, even chems
diff --git a/code/game/objects/items/crab17.dm b/code/game/objects/items/crab17.dm
new file mode 100644
index 0000000000..8d55d3d5a2
--- /dev/null
+++ b/code/game/objects/items/crab17.dm
@@ -0,0 +1,229 @@
+/obj/item/suspiciousphone
+ name = "suspicious phone"
+ desc = "This device raises pink levels to unknown highs."
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "suspiciousphone"
+ w_class = WEIGHT_CLASS_SMALL
+ attack_verb = list("dumped")
+ var/dumped = FALSE
+
+/obj/item/suspiciousphone/attack_self(mob/user)
+ if(!ishuman(user))
+ to_chat(user, "This device is too advanced for you!")
+ return
+ if(dumped)
+ to_chat(user, "You already activated Protocol CRAB-17.")
+ return FALSE
+ if(alert(user, "Are you sure you want to crash this market with no survivors?", "Protocol CRAB-17", "Yes", "No") == "Yes")
+ if(dumped || QDELETED(src)) //Prevents fuckers from cheesing alert
+ return FALSE
+ var/turf/targetturf = get_safe_random_station_turf()
+ if (!targetturf)
+ return FALSE
+ new /obj/effect/dumpeetTarget(targetturf, user)
+ dumped = TRUE
+
+/obj/structure/checkoutmachine
+ name = "\improper Nanotrasen Space-Coin Market"
+ desc = "This is good for spacecoin because"
+ icon = 'icons/obj/money_machine.dmi'
+ icon_state = "bogdanoff"
+ layer = LARGE_MOB_LAYER
+ armor = list("melee" = 80, "bullet" = 30, "laser" = 30, "energy" = 60, "bomb" = 90, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80)
+ density = TRUE
+ pixel_z = -8
+ max_integrity = 5000
+ var/list/accounts_to_rob
+ var/mob/living/carbon/human/bogdanoff
+ var/canwalk = FALSE
+
+/obj/structure/checkoutmachine/examine(mob/living/user)
+ . = ..()
+ . += "It's integrated integrity meter reads: HEALTH: [obj_integrity]."
+
+/obj/structure/checkoutmachine/proc/check_if_finished()
+ for(var/i in accounts_to_rob)
+ var/datum/bank_account/B = i
+ if (B.being_dumped)
+ return FALSE
+ return TRUE
+
+/obj/structure/checkoutmachine/attackby(obj/item/W, mob/user, params)
+ if(check_if_finished())
+ qdel(src)
+ return
+ if(istype(W, /obj/item/card/id))
+ var/obj/item/card/id/card = W
+ if(!card.registered_account)
+ to_chat(user, "This card does not have a registered account!")
+ return
+ if(!card.registered_account.being_dumped)
+ to_chat(user, "It appears that your funds are safe from draining!")
+ return
+ if(do_after(user, 40, target = src))
+ if(!card.registered_account.being_dumped)
+ return
+ to_chat(user, "You quickly cash out your funds to a more secure banking location. Funds are safu.") // This is a reference and not a typo
+ card.registered_account.being_dumped = FALSE
+ card.registered_account.withdrawDelay = 0
+ if(check_if_finished())
+ qdel(src)
+ return
+ else
+ return ..()
+
+/obj/structure/checkoutmachine/Initialize(mapload, mob/living/user)
+ . = ..()
+ bogdanoff = user
+ add_overlay("flaps")
+ add_overlay("hatch")
+ add_overlay("legs_retracted")
+ addtimer(CALLBACK(src, .proc/startUp), 50)
+ QDEL_IN(src, 8 MINUTES) //Self destruct after 8 min
+
+
+/obj/structure/checkoutmachine/proc/startUp() //very VERY snowflake code that adds a neat animation when the pod lands.
+ start_dumping() //The machine doesnt move during this time, giving people close by a small window to grab their funds before it starts running around
+ sleep(10)
+ if(QDELETED(src))
+ return
+ playsound(src, 'sound/machines/click.ogg', 15, TRUE, -3)
+ cut_overlay("flaps")
+ sleep(10)
+ if(QDELETED(src))
+ return
+ playsound(src, 'sound/machines/click.ogg', 15, TRUE, -3)
+ cut_overlay("hatch")
+ sleep(30)
+ if(QDELETED(src))
+ return
+ playsound(src,'sound/machines/twobeep.ogg',50,FALSE)
+ var/mutable_appearance/hologram = mutable_appearance(icon, "hologram")
+ hologram.pixel_y = 16
+ add_overlay(hologram)
+ var/mutable_appearance/holosign = mutable_appearance(icon, "holosign")
+ holosign.pixel_y = 16
+ add_overlay(holosign)
+ add_overlay("legs_extending")
+ cut_overlay("legs_retracted")
+ pixel_z += 4
+ sleep(5)
+ if(QDELETED(src))
+ return
+ add_overlay("legs_extended")
+ cut_overlay("legs_extending")
+ pixel_z += 4
+ sleep(20)
+ if(QDELETED(src))
+ return
+ add_overlay("screen_lines")
+ sleep(5)
+ if(QDELETED(src))
+ return
+ cut_overlay("screen_lines")
+ sleep(5)
+ if(QDELETED(src))
+ return
+ add_overlay("screen_lines")
+ add_overlay("screen")
+ sleep(5)
+ if(QDELETED(src))
+ return
+ playsound(src,'sound/machines/triple_beep.ogg',50,FALSE)
+ add_overlay("text")
+ sleep(10)
+ if(QDELETED(src))
+ return
+ add_overlay("legs")
+ cut_overlay("legs_extended")
+ cut_overlay("screen")
+ add_overlay("screen")
+ cut_overlay("screen_lines")
+ add_overlay("screen_lines")
+ cut_overlay("text")
+ add_overlay("text")
+ canwalk = TRUE
+ START_PROCESSING(SSfastprocess, src)
+
+/obj/structure/checkoutmachine/Destroy()
+ stop_dumping()
+ STOP_PROCESSING(SSfastprocess, src)
+ priority_announce("The credit deposit machine at [get_area(src)] has been destroyed. Station funds have stopped draining!", sender_override = "CRAB-17 Protocol")
+ explosion(src, 0,0,1, flame_range = 2)
+ return ..()
+
+/obj/structure/checkoutmachine/proc/start_dumping()
+ accounts_to_rob = SSeconomy.bank_accounts.Copy()
+ accounts_to_rob -= bogdanoff.get_bank_account()
+ for(var/i in accounts_to_rob)
+ var/datum/bank_account/B = i
+ B.dumpeet()
+ dump()
+
+/obj/structure/checkoutmachine/proc/dump()
+ var/percentage_lost = (rand(5, 15) / 100)
+ for(var/i in accounts_to_rob)
+ var/datum/bank_account/B = i
+ if(!B.being_dumped)
+ continue
+ var/amount = B.account_balance * percentage_lost
+ var/datum/bank_account/account = bogdanoff.get_bank_account()
+ if (account) // get_bank_account() may return FALSE
+ account.transfer_money(B, amount)
+ B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src)].")
+ addtimer(CALLBACK(src, .proc/dump), 150) //Drain every 15 seconds
+
+/obj/structure/checkoutmachine/process()
+ var/anydir = pick(GLOB.cardinals)
+ if(Process_Spacemove(anydir))
+ Move(get_step(src, anydir), anydir)
+
+/obj/structure/checkoutmachine/proc/stop_dumping()
+ for(var/i in accounts_to_rob)
+ var/datum/bank_account/B = i
+ B.being_dumped = FALSE
+
+/obj/effect/dumpeetFall //Falling pod
+ name = ""
+ icon = 'icons/obj/money_machine_64.dmi'
+ pixel_z = 300
+ desc = "Get out of the way!"
+ layer = FLY_LAYER//that wasnt flying, that was falling with style!
+ icon_state = "missile_blur"
+
+/obj/effect/dumpeetTarget
+ name = "Landing Zone Indicator"
+ desc = "A holographic projection designating the landing zone of something. It's probably best to stand back."
+ icon = 'icons/mob/actions/actions_items.dmi'
+ icon_state = "sniper_zoom"
+ layer = PROJECTILE_HIT_THRESHHOLD_LAYER
+ light_range = 2
+ var/obj/effect/dumpeetFall/DF
+ var/obj/structure/checkoutmachine/dump
+ var/mob/living/carbon/human/bogdanoff
+
+/obj/effect/ex_act()
+ return
+
+/obj/effect/dumpeetTarget/Initialize(mapload, user)
+ . = ..()
+ bogdanoff = user
+ addtimer(CALLBACK(src, .proc/startLaunch), 100)
+ sound_to_playing_players('sound/items/dump_it.ogg', 20)
+ deadchat_broadcast("Protocol CRAB-17 has been activated. A space-coin market has been launched at the station!", turf_target = get_turf(src))
+
+/obj/effect/dumpeetTarget/proc/startLaunch()
+ DF = new /obj/effect/dumpeetFall(drop_location())
+ dump = new /obj/structure/checkoutmachine(null, bogdanoff)
+ priority_announce("The spacecoin bubble has popped! Get to the credit deposit machine at [get_area(src)] and cash out before you lose all of your funds!", sender_override = "CRAB-17 Protocol")
+ animate(DF, pixel_z = -8, time = 5, , easing = LINEAR_EASING)
+ playsound(src, 'sound/weapons/mortar_whistle.ogg', 70, TRUE, 6)
+ addtimer(CALLBACK(src, .proc/endLaunch), 5, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation
+
+
+
+/obj/effect/dumpeetTarget/proc/endLaunch()
+ QDEL_NULL(DF) //Delete the falling machine effect, because at this point its animation is over. We dont use temp_visual because we want to manually delete it as soon as the pod appears
+ playsound(src, "explosion", 80, TRUE)
+ dump.forceMove(get_turf(src))
+ qdel(src) //The target's purpose is complete. It can rest easy now
diff --git a/code/game/objects/items/credit_holochip.dm b/code/game/objects/items/credit_holochip.dm
new file mode 100644
index 0000000000..0acb225772
--- /dev/null
+++ b/code/game/objects/items/credit_holochip.dm
@@ -0,0 +1,107 @@
+/obj/item/holochip
+ name = "credit holochip"
+ desc = "A hard-light chip encoded with an amount of credits. It is a modern replacement for physical money that can be directly converted to virtual currency and viceversa. Keep away from magnets."
+ icon = 'icons/obj/economy.dmi'
+ icon_state = "holochip"
+ throwforce = 0
+ force = 0
+ w_class = WEIGHT_CLASS_TINY
+ var/credits = 0
+
+/obj/item/holochip/Initialize(mapload, amount)
+ . = ..()
+ credits = amount
+ update_icon()
+
+/obj/item/holochip/examine(mob/user)
+ . = ..()
+ . += "It's loaded with [credits] credit[( credits > 1 ) ? "s" : ""]\n"+\
+ "Alt-Click to split."
+
+/obj/item/holochip/get_item_credit_value()
+ return credits
+
+/obj/item/holochip/update_icon()
+ name = "\improper [credits] credit holochip"
+ var/rounded_credits = credits
+ switch(credits)
+ if(1 to 999)
+ icon_state = "holochip"
+ if(1000 to 999999)
+ icon_state = "holochip_kilo"
+ rounded_credits = round(rounded_credits * 0.001)
+ if(1000000 to 999999999)
+ icon_state = "holochip_mega"
+ rounded_credits = round(rounded_credits * 0.000001)
+ if(1000000000 to INFINITY)
+ icon_state = "holochip_giga"
+ rounded_credits = round(rounded_credits * 0.000000001)
+ var/overlay_color = "#914792"
+ switch(rounded_credits)
+ if(0 to 4)
+ overlay_color = "#8E2E38"
+ if(5 to 9)
+ overlay_color = "#914792"
+ if(10 to 19)
+ overlay_color = "#BF5E0A"
+ if(20 to 49)
+ overlay_color = "#358F34"
+ if(50 to 99)
+ overlay_color = "#676767"
+ if(100 to 199)
+ overlay_color = "#009D9B"
+ if(200 to 499)
+ overlay_color = "#0153C1"
+ if(500 to INFINITY)
+ overlay_color = "#2C2C2C"
+ cut_overlays()
+ var/mutable_appearance/holochip_overlay = mutable_appearance('icons/obj/economy.dmi', "[icon_state]-color")
+ holochip_overlay.color = overlay_color
+ add_overlay(holochip_overlay)
+
+/obj/item/holochip/proc/spend(amount, pay_anyway = FALSE)
+ if(credits >= amount)
+ credits -= amount
+ if(credits == 0)
+ qdel(src)
+ update_icon()
+ return amount
+ else if(pay_anyway)
+ qdel(src)
+ return credits
+ else
+ return 0
+
+/obj/item/holochip/attackby(obj/item/I, mob/user, params)
+ ..()
+ if(istype(I, /obj/item/holochip))
+ var/obj/item/holochip/H = I
+ credits += H.credits
+ to_chat(user, "You insert the credits into [src].")
+ update_icon()
+ qdel(H)
+
+/obj/item/holochip/AltClick(mob/user)
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+ var/split_amount = round(input(user,"How many credits do you want to extract from the holochip?") as null|num)
+ if(split_amount == null || split_amount <= 0 || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+ else
+ var/new_credits = spend(split_amount, TRUE)
+ var/obj/item/holochip/H = new(user ? user : drop_location(), new_credits)
+ if(user)
+ if(!user.put_in_hands(H))
+ H.forceMove(user.drop_location())
+ add_fingerprint(user)
+ H.add_fingerprint(user)
+ to_chat(user, "You extract [split_amount] credits into a new holochip.")
+
+/obj/item/holochip/emp_act(severity)
+ . = ..()
+ if(. & EMP_PROTECT_SELF)
+ return
+ var/wipe_chance = 60 / severity
+ if(prob(wipe_chance))
+ visible_message("[src] fizzles and disappears!")
+ qdel(src) //rip cash
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 29a31122bf..1c50717bd5 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -1,6 +1,7 @@
/obj/item/flashlight
name = "flashlight"
desc = "A hand-held emergency light."
+ custom_price = 100
icon = 'icons/obj/lighting.dmi'
icon_state = "flashlight"
item_state = "flashlight"
@@ -422,6 +423,7 @@
/obj/item/flashlight/glowstick
name = "glowstick"
desc = "A military-grade glowstick."
+ custom_price = 50
w_class = WEIGHT_CLASS_SMALL
brightness_on = 4
color = LIGHT_COLOR_GREEN
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index b6cab8b438..1bc0f81695 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -11,6 +11,7 @@ SLIME SCANNER
/obj/item/t_scanner
name = "\improper T-ray scanner"
desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
+ custom_price = 150
icon = 'icons/obj/device.dmi'
icon_state = "t-ray0"
var/on = FALSE
@@ -79,6 +80,7 @@ SLIME SCANNER
var/mode = 1
var/scanmode = 0
var/advanced = FALSE
+ custom_price = 300
/obj/item/healthanalyzer/suicide_act(mob/living/carbon/user)
user.visible_message("[user] begins to analyze [user.p_them()]self with [src]! The display shows that [user.p_theyre()] dead!")
diff --git a/code/game/objects/items/devices/sensor_device.dm b/code/game/objects/items/devices/sensor_device.dm
index 79d26776a9..07b975f133 100644
--- a/code/game/objects/items/devices/sensor_device.dm
+++ b/code/game/objects/items/devices/sensor_device.dm
@@ -5,6 +5,7 @@
icon_state = "scanner"
w_class = WEIGHT_CLASS_SMALL
slot_flags = ITEM_SLOT_BELT
+ custom_price = 1750
/obj/item/sensor_device/attack_self(mob/user)
GLOB.crewmonitor.show(user,src) //Proc already exists, just had to call it
diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm
index 502930bf65..df5c840a1c 100644
--- a/code/game/objects/items/kitchen.dm
+++ b/code/game/objects/items/kitchen.dm
@@ -70,6 +70,7 @@
sharpness = IS_SHARP_ACCURATE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/bayonet = FALSE //Can this be attached to a gun?
+ custom_price = 250
/obj/item/kitchen/knife/Initialize()
. = ..()
@@ -107,6 +108,7 @@
custom_materials = list(/datum/material/iron=18000)
attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
w_class = WEIGHT_CLASS_NORMAL
+ custom_price = 600
/obj/item/kitchen/knife/combat
name = "combat knife"
@@ -174,6 +176,7 @@
throw_range = 7
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
+ custom_price = 200
/obj/item/kitchen/rollingpin/suicide_act(mob/living/carbon/user)
user.visible_message("[user] begins flattening [user.p_their()] head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm
index 090c2f6d57..5a47b2eecc 100644
--- a/code/game/objects/items/pinpointer.dm
+++ b/code/game/objects/items/pinpointer.dm
@@ -78,6 +78,7 @@
name = "crew pinpointer"
desc = "A handheld tracking device that points to crew suit sensors."
icon_state = "pinpointer_crew"
+ custom_price = 1000
var/has_owner = FALSE
var/pinpointer_owner = null
diff --git a/code/game/objects/items/stacks/cash.dm b/code/game/objects/items/stacks/cash.dm
index 94f6fca28c..430018929d 100644
--- a/code/game/objects/items/stacks/cash.dm
+++ b/code/game/objects/items/stacks/cash.dm
@@ -3,7 +3,7 @@
singular_name = "bill"
icon = 'icons/obj/economy.dmi'
icon_state = "spacecash"
- amount = 1
+ amount = INFINITY
max_amount = 20
throwforce = 0
throw_speed = 2
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 50e9b94e97..588b231bda 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -93,6 +93,7 @@
var/stop_bleeding = 1800
var/heal_brute = 5
self_delay = 10
+ custom_price = 100
/obj/item/stack/medical/gauze/heal(mob/living/M, mob/user)
if(ishuman(M))
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index dc6f5f701e..0cc108c1b9 100755
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -43,6 +43,7 @@
icon_state = "utilitybelt"
item_state = "utility"
content_overlays = TRUE
+ custom_premium_price = 300
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //because this is easier than trying to have showers wash all contents.
/obj/item/storage/belt/utility/ComponentInitialize()
@@ -709,6 +710,7 @@
icon_state = "fannypack_leather"
item_state = "fannypack_leather"
dying_key = DYE_REGISTRY_FANNYPACK
+ custom_price = 100
/obj/item/storage/belt/fannypack/ComponentInitialize()
. = ..()
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index 515c39ffcb..91206df4c2 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -622,6 +622,7 @@
item_state = "zippo"
w_class = WEIGHT_CLASS_TINY
slot_flags = ITEM_SLOT_BELT
+ custom_price = 20
/obj/item/storage/box/matches/ComponentInitialize()
. = ..()
diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm
index 3bc90d3615..18499d66be 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -136,6 +136,7 @@
slot_flags = ITEM_SLOT_BELT
icon_type = "cigarette"
spawn_type = /obj/item/clothing/mask/cigarette/space_cigarette
+ custom_price = 75
/obj/item/storage/fancy/cigarettes/ComponentInitialize()
. = ..()
@@ -276,6 +277,7 @@
icon_state = "cig_paper_pack"
icon_type = "rolling paper"
spawn_type = /obj/item/rollingpaper
+ custom_price = 25
/obj/item/storage/fancy/rollingpapers/ComponentInitialize()
. = ..()
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index 27cd9c8908..0b4b6f54f3 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -16,6 +16,7 @@
STR.cant_hold = typecacheof(list(/obj/item/screwdriver/power))
STR.can_hold = typecacheof(list(
/obj/item/stack/spacecash,
+ /obj/item/holochip,
/obj/item/card,
/obj/item/clothing/mask/cigarette,
/obj/item/flashlight/pen,
@@ -101,17 +102,5 @@
icon_state = "random_wallet"
/obj/item/storage/wallet/random/PopulateContents()
- var/item1_type = pick( /obj/item/stack/spacecash/c10, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, /obj/item/stack/spacecash/c20, /obj/item/stack/spacecash/c200, /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c500)
- var/item2_type
- if(prob(50))
- item2_type = pick( /obj/item/stack/spacecash/c10, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, /obj/item/stack/spacecash/c20, /obj/item/stack/spacecash/c200, /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c500)
- var/item3_type = pick( /obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/gold, /obj/item/coin/iron, /obj/item/coin/iron, /obj/item/coin/iron )
-
- spawn(2)
- if(item1_type)
- new item1_type(src)
- if(item2_type)
- new item2_type(src)
- if(item3_type)
- new item3_type(src)
- update_icon()
+ new /obj/item/holochip(src, rand(5,30))
+ icon_state = "wallet"
diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm
index 6ff5dfc8ad..67dbc19289 100644
--- a/code/game/objects/items/tanks/watertank.dm
+++ b/code/game/objects/items/tanks/watertank.dm
@@ -145,6 +145,7 @@
desc = "A janitorial watertank backpack with nozzle to clean dirt and graffiti."
icon_state = "waterbackpackjani"
item_state = "waterbackpackjani"
+ custom_price = 1200
/obj/item/watertank/janitor/Initialize()
. = ..()
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 8496a8a216..01131a3e85 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -525,6 +525,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = "skateboard2"
item_state = "skateboard2"
board_item_type = /obj/vehicle/ridden/scooter/skateboard/pro
+ custom_premium_price = 500
/obj/item/melee/skateboard/hoverboard
name = "hoverboard"
@@ -532,6 +533,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = "hoverboard_red"
item_state = "hoverboard_red"
board_item_type = /obj/vehicle/ridden/scooter/skateboard/hoverboard
+ custom_premium_price = 2015
/obj/item/melee/skateboard/hoverboard/admin
name = "\improper Board Of Directors"
diff --git a/code/game/objects/structures/crates_lockers/crates/secure.dm b/code/game/objects/structures/crates_lockers/crates/secure.dm
index 4ac69253d3..2c923c1905 100644
--- a/code/game/objects/structures/crates_lockers/crates/secure.dm
+++ b/code/game/objects/structures/crates_lockers/crates/secure.dm
@@ -74,4 +74,43 @@
/obj/structure/closet/crate/secure/medical
desc = "A secure medical crate."
name = "medical crate"
- icon_state = "medical_secure_crate"
\ No newline at end of file
+ icon_state = "medical_secure_crate"
+
+/obj/structure/closet/crate/secure/owned
+ name = "private crate"
+ desc = "A crate cover designed to only open for who purchased its contents."
+ icon_state = "privatecrate"
+ var/datum/bank_account/buyer_account
+ var/privacy_lock = TRUE
+
+/obj/structure/closet/crate/secure/owned/examine(mob/user)
+ . = ..()
+ to_chat(user, "It's locked with a privacy lock, and can only be unlocked by the buyer's ID.")
+
+/obj/structure/closet/crate/secure/owned/Initialize(mapload, datum/bank_account/_buyer_account)
+ . = ..()
+ buyer_account = _buyer_account
+
+/obj/structure/closet/crate/secure/owned/togglelock(mob/living/user, silent)
+ if(privacy_lock)
+ if(!broken)
+ var/obj/item/card/id/id_card = user.get_idcard(TRUE)
+ if(id_card)
+ if(id_card.registered_account)
+ if(id_card.registered_account == buyer_account)
+ if(iscarbon(user))
+ add_fingerprint(user)
+ locked = !locked
+ user.visible_message("[user] unlocks [src]'s privacy lock.",
+ "You unlock [src]'s privacy lock.")
+ privacy_lock = FALSE
+ update_icon()
+ else if(!silent)
+ to_chat(user, "Bank account does not match with buyer!")
+ else if(!silent)
+ to_chat(user, "No linked bank account detected!")
+ else if(!silent)
+ to_chat(user, "No ID detected!")
+ else if(!silent)
+ to_chat(user, "[src] is broken!")
+ else ..()
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index c918e7b867..d0be6c8469 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -689,7 +689,7 @@
name = "ID, jumpsuit and shoes"
uniform = /obj/item/clothing/under/color/random
shoes = /obj/item/clothing/shoes/sneakers/black
- id = /obj/item/card/id
+ id = /obj/item/card/id/no_banking
r_hand = /obj/item/storage/box/syndie_kit/chameleon/ghostcafe
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index c70db70ee8..a06b674e42 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -63,6 +63,7 @@
There can only be one! (40-second delay)
Make all players stupid
Egalitarian Station Mode
+ Anarcho-Capitalist Station Mode
Break all lights
Fix all lights
The floor is lava! (DANGEROUS: extremely lame)
@@ -478,6 +479,17 @@
usr.client.ak47s()
sound_to_playing_players('sound/misc/ak47s.ogg')
+ if("ancap")
+ if(!check_rights(R_FUN))
+ return
+ SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Anarcho-capitalist Station"))
+ SSeconomy.full_ancap = !SSeconomy.full_ancap
+ message_admins("[key_name_admin(usr)] toggled Anarcho-capitalist mode")
+ if(SSeconomy.full_ancap)
+ priority_announce("The NAP is now in full effect.", null, "commandreport")
+ else
+ priority_announce("The NAP has been revoked.", null, "commandreport")
+
if("guns")
if(!check_rights(R_FUN))
return
diff --git a/code/modules/antagonists/blob/blob/blob_report.dm b/code/modules/antagonists/blob/blob/blob_report.dm
index 4385b732c3..d532121e12 100644
--- a/code/modules/antagonists/blob/blob/blob_report.dm
+++ b/code/modules/antagonists/blob/blob/blob_report.dm
@@ -8,6 +8,13 @@
var/mach = 0
/datum/station_state/proc/count()
+ floor = 0
+ wall = 0
+ r_wall = 0
+ window = 0
+ door = 0
+ grille = 0
+ mach = 0
for(var/Z in SSmapping.levels_by_trait(ZTRAIT_STATION))
for(var/turf/T in block(locate(1,1,Z), locate(world.maxx,world.maxy,Z)))
// don't count shuttles since they may have just left
@@ -48,6 +55,10 @@
else if(ismachinery(O))
mach += 1
+ CHECK_TICK
+ CHECK_TICK
+ CHECK_TICK
+
/datum/station_state/proc/score(datum/station_state/result)
if(!result)
return 0
diff --git a/code/modules/antagonists/traitor/syndicate_contract.dm b/code/modules/antagonists/traitor/syndicate_contract.dm
index daa9127591..70ff59eee0 100644
--- a/code/modules/antagonists/traitor/syndicate_contract.dm
+++ b/code/modules/antagonists/traitor/syndicate_contract.dm
@@ -78,14 +78,28 @@
var/mob/living/carbon/human/target = M // After we remove items, at least give them what they need to live.
target.dna.species.give_important_for_life(target)
handleVictimExperience(M) // After pod is sent we start the victim narrative/heal.
- var/points_to_check = SSshuttle.points // This is slightly delayed because of the sleep calls above to handle the narrative. We don't want to tell the station instantly.
- if(points_to_check >= ransom)
- SSshuttle.points -= ransom
- else
- SSshuttle.points -= points_to_check
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ var/points_to_check = min(D.account_balance, ransom)
+ D.adjust_money(min(points_to_check, ransom))
priority_announce("One of your crew was captured by a rival organisation - we've needed to pay their ransom to bring them back. \
As is policy we've taken a portion of the station's funds to offset the overall cost.", null, "attention", null, "Nanotrasen Asset Protection")
+ sleep(30)
+
+ // Pay contractor their portion of ransom
+ if (status == CONTRACT_STATUS_COMPLETE)
+ var/mob/living/carbon/human/H
+ var/obj/item/card/id/C
+ if(ishuman(contract.owner.current))
+ H = contract.owner.current
+ C = H.get_idcard(TRUE)
+
+ if(C && C.registered_account)
+ C.registered_account.adjust_money(points_to_check * 0.35)
+
+ C.registered_account.bank_card_talk("We've processed the ransom, agent. Here's your cut - your balance is now \
+ [C.registered_account.account_balance] cr.", TRUE)
+
/datum/syndicate_contract/proc/handleVictimExperience(var/mob/living/M) // They're off to holding - handle the return timer and give some text about what's going on.
addtimer(CALLBACK(src, .proc/returnVictim, M), 4 MINUTES) // Ship 'em back - dead or alive... 4 minutes wait.
if(M.stat != DEAD) //Even if they weren't the target, we're still treating them the same.
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index a4617462fe..aa1e5c7401 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -36,6 +36,7 @@
/obj/item/electronics/airalarm
name = "air alarm electronics"
icon_state = "airalarm_electronics"
+ custom_price = 50
/obj/item/wallframe/airalarm
name = "air alarm frame"
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index e013a86fd2..b859c536cc 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -33,6 +33,9 @@
var/message_cooldown
var/breakout_time = 300
+ fair_market_price = 10
+ payment_department = ACCOUNT_MED
+
/obj/machinery/atmospherics/components/unary/cryo_cell/Initialize()
. = ..()
initialize_directions = dir
@@ -149,6 +152,9 @@
add_overlay("cover-on")
addtimer(CALLBACK(src, .proc/run_anim, anim_up, occupant_overlay), 7, TIMER_UNIQUE)
+/obj/machinery/atmospherics/components/unary/cryo_cell/nap_violation(mob/violator)
+ open_machine()
+
/obj/machinery/atmospherics/components/unary/cryo_cell/process()
..()
@@ -162,7 +168,8 @@
return
var/mob/living/mob_occupant = occupant
-
+ if(!check_nap_violations())
+ return
if(mob_occupant.stat == DEAD) // We don't bother with dead people.
return
diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm
index d4c9fdbee7..00460e8a85 100644
--- a/code/modules/awaymissions/zlevel.dm
+++ b/code/modules/awaymissions/zlevel.dm
@@ -1,5 +1,7 @@
// How much "space" we give the edge of the map
GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "[global.config.directory]/awaymissionconfig.txt"))
+// So far only adds an additional trait to vr levels. But I'll probably use make VR separate from away missions in a near future.
+GLOBAL_LIST_INIT(potentialRandomVRlevels, generateMapList(filename = "[global.config.directory]/vr_config.txt"))
/proc/createRandomZlevel()
if(GLOB.awaydestinations.len) //crude, but it saves another var!
@@ -8,7 +10,10 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "[global.con
if(GLOB.potentialRandomZlevels && GLOB.potentialRandomZlevels.len)
to_chat(world, "Loading away mission...")
var/map = pick(GLOB.potentialRandomZlevels)
- load_new_z_level(map, "Away Mission")
+ var/list/traits = list(ZTRAIT_AWAY = TRUE)
+ if(map in GLOB.potentialRandomVRlevels)
+ traits[ZTRAIT_VIRTUAL_REALITY] = TRUE
+ load_new_z_level(map, "Away Mission", traits)
to_chat(world, "Away mission loaded.")
/proc/reset_gateway_spawns(reset = FALSE)
diff --git a/code/modules/cargo/bounties/science.dm b/code/modules/cargo/bounties/science.dm
index ad03b2f393..a4632f7ed0 100644
--- a/code/modules/cargo/bounties/science.dm
+++ b/code/modules/cargo/bounties/science.dm
@@ -55,7 +55,7 @@
/datum/bounty/item/science/advanced_mop
name = "Advanced Mop"
- description = "Excuse me. I'd like to request 17 credits for a push broom rebristling. Either that, or an advanced mop."
+ description = "Excuse me. I'd like to request 17 cr for a push broom rebristling. Either that, or an advanced mop."
reward = 3000
wanted_types = list(/obj/item/mop/advanced)
diff --git a/code/modules/cargo/bounty.dm b/code/modules/cargo/bounty.dm
index bfd97e4d1f..b888dc1a28 100644
--- a/code/modules/cargo/bounty.dm
+++ b/code/modules/cargo/bounty.dm
@@ -21,7 +21,9 @@ GLOBAL_LIST_EMPTY(bounties_list)
// Called when the claim button is clicked. Override to provide fancy rewards.
/datum/bounty/proc/claim()
if(can_claim())
- SSshuttle.points += reward
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ if(D)
+ D.adjust_money(reward)
claimed = TRUE
// If an item sent in the cargo shuttle can satisfy the bounty.
@@ -126,11 +128,11 @@ GLOBAL_LIST_EMPTY(bounties_list)
/proc/setup_bounties()
var/pick // instead of creating it a bunch let's go ahead and toss it here, we know we're going to use it for dynamics and subtypes!
-
+
/********************************Subtype Gens********************************/
var/list/easy_add_list_subtypes = list(/datum/bounty/item/assistant = 2,
- /datum/bounty/item/mech = 1,
- /datum/bounty/item/chef = 2,
+ /datum/bounty/item/mech = 1,
+ /datum/bounty/item/chef = 2,
/datum/bounty/item/security = 1,
/datum/bounty/virus = 1,
/datum/bounty/item/engineering = 1,
@@ -139,30 +141,30 @@ GLOBAL_LIST_EMPTY(bounties_list)
/datum/bounty/item/botany = 2,
/datum/bounty/item/silly = 1,
/datum/bounty/item/gardencook = 1)
-
+
for(var/the_type in easy_add_list_subtypes)
for(var/i in 1 to easy_add_list_subtypes[the_type])
pick = pick(subtypesof(the_type))
try_add_bounty(new pick)
-
+
/********************************Strict Type Gens********************************/
var/list/easy_add_list_strict_types = list(/datum/bounty/reagent/simple_drink = 1,
/datum/bounty/reagent/complex_drink = 1,
/datum/bounty/reagent/chemical = 1)
-
+
for(var/the_strict_type in easy_add_list_strict_types)
for(var/i in 1 to easy_add_list_strict_types[the_strict_type])
try_add_bounty(new the_strict_type)
-
+
/********************************Dynamic Gens********************************/
-
+
for(var/i in 0 to 1)
if(prob(50))
pick = pick(subtypesof(/datum/bounty/item/slime))
else
pick = pick(subtypesof(/datum/bounty/item/science))
try_add_bounty(new pick)
-
+
/********************************Cutoff for Non-Low Priority Bounties********************************/
var/datum/bounty/B = pick(GLOB.bounties_list)
B.mark_high_priority()
@@ -172,7 +174,7 @@ GLOBAL_LIST_EMPTY(bounties_list)
/datum/bounty/item/syndicate_documents,
/datum/bounty/item/adamantine,
/datum/bounty/more_bounties)
-
+
for(var/low_priority_bounty in low_priority_strict_type_list)
try_add_bounty(new low_priority_bounty)
diff --git a/code/modules/cargo/bounty_console.dm b/code/modules/cargo/bounty_console.dm
index 45260f4926..f499c38090 100644
--- a/code/modules/cargo/bounty_console.dm
+++ b/code/modules/cargo/bounty_console.dm
@@ -35,10 +35,10 @@
if(!GLOB.bounties_list.len)
setup_bounties()
-
+ var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
var/list/dat = list({"Refresh
Print Paper
-
Credits: [SSshuttle.points]
+Credits: [D.account_balance]