From eacf5cf7c19eeeaffba98884228023397f67fb02 Mon Sep 17 00:00:00 2001
From: Kapu1178 <75460809+Kapu1178@users.noreply.github.com>
Date: Mon, 19 Feb 2024 19:12:25 -0500
Subject: [PATCH] Kapuconomy Part 2 of X (#802)
* wallets and cash
* atm progress
* remove civilian bounties
* remove holochips
* die holochips die
* atm stuff
* dead people dont get money
* no more PDA imprinting
* map in ATMs
* fix outfit equip
* atm layer
* clean up wallet impl
---
_maps/RandomRuins/SpaceRuins/oldAIsat.dmm | 9 +-
_maps/map_files/Theseus/Theseus.dmm | 293 +++++++-------
_maps/map_files/generic/CentCom.dmm | 78 ++--
_maps/shuttles/emergency_casino.dmm | 4 -
_maps/shuttles/ruin_pirate_cutter.dmm | 1 -
_maps/shuttles/whiteship_delta.dmm | 4 -
_maps/shuttles/whiteship_kilo.dmm | 1 -
code/__DEFINES/dcs/signals/signals_storage.dm | 13 +
code/__DEFINES/inventory.dm | 2 +-
code/__DEFINES/is_helpers.dm | 2 +-
code/__DEFINES/memory_defines.dm | 3 +-
code/__HELPERS/memory_helpers.dm | 5 +-
code/controllers/subsystem/economy.dm | 54 ++-
code/controllers/subsystem/job.dm | 14 +-
.../components/food/ice_cream_holder.dm | 2 +-
code/datums/elements/food/venue_price.dm | 2 +-
code/datums/outfit.dm | 14 +-
code/datums/station_traits/positive_traits.dm | 40 --
code/datums/storage/storage.dm | 11 +-
code/datums/storage/subtypes/pockets.dm | 2 -
code/game/area/areas/station.dm | 1 -
code/game/machinery/atm.dm | 250 ++++++++++++
code/game/machinery/bank_machine.dm | 7 +-
code/game/machinery/civilian_bounties.dm | 383 ------------------
code/game/machinery/computer/security.dm | 39 +-
code/game/machinery/computer/warrant.dm | 8 +-
code/game/machinery/fax_machine.dm | 6 +-
code/game/machinery/slotmachine.dm | 102 ++---
.../effects/effect_system/effect_system.dm | 2 +-
.../effects/spawners/random/entertainment.dm | 4 -
code/game/objects/items.dm | 2 +-
code/game/objects/items/cards_ids.dm | 266 +-----------
.../circuitboards/computer_circuitboards.dm | 4 -
.../circuitboards/machine_circuitboards.dm | 10 -
code/game/objects/items/credit_holochip.dm | 129 ------
code/game/objects/items/mail.dm | 8 +-
code/game/objects/items/stacks/cash.dm | 27 +-
code/game/objects/items/storage/wallets.dm | 229 ++++++-----
.../crates_lockers/closets/secure/freezer.dm | 8 +-
.../structures/crates_lockers/crates.dm | 5 +-
code/modules/cargo/bounties/assistant.dm | 204 ----------
code/modules/cargo/bounties/botany.dm | 223 ----------
code/modules/cargo/bounties/chef.dm | 153 -------
code/modules/cargo/bounties/engineering.dm | 54 ---
code/modules/cargo/bounties/item.dm | 32 --
code/modules/cargo/bounties/mech.dm | 36 --
code/modules/cargo/bounties/medical.dm | 92 -----
code/modules/cargo/bounties/reagent.dm | 230 -----------
code/modules/cargo/bounties/security.dm | 75 ----
code/modules/cargo/bounties/slime.dm | 35 --
code/modules/cargo/bounties/special.dm | 37 --
code/modules/cargo/bounties/virus.dm | 72 ----
code/modules/cargo/bounty.dm | 74 ----
code/modules/cargo/export_scanner.dm | 24 --
code/modules/cargo/exports/civilain_bounty.dm | 8 -
code/modules/cargo/order.dm | 32 +-
code/modules/cargo/packs.dm | 6 +
code/modules/clothing/neck/_neck.dm | 2 +-
code/modules/economy/account.dm | 65 +--
code/modules/economy/holopay.dm | 292 -------------
code/modules/events/pirates.dm | 13 +-
code/modules/explorer_drone/loot.dm | 2 +-
code/modules/jobs/access.dm | 3 +-
code/modules/jobs/job_types/_job.dm | 10 +-
.../jobs/job_types/security_officer.dm | 2 +-
.../ruins/spaceruin_code/crashedship.dm | 2 +-
code/modules/mining/money_bag.dm | 2 +-
.../mob/living/carbon/human/examine.dm | 3 +-
.../mob/living/carbon/human/human_helpers.dm | 4 +-
code/modules/mob/living/living.dm | 6 +-
.../living/simple_animal/friendly/trader.dm | 13 +-
.../computers/item/computer.dm | 6 +-
.../modular_computers/hardware/card_slot.dm | 2 +-
.../modular_computers/laptop_vendor.dm | 11 +-
.../research/designs/comp_board_designs.dm | 5 -
.../research/designs/machine_designs.dm | 7 -
code/modules/vending/_vending.dm | 3 +
code/modules/wiremod/shell/moneybot.dm | 4 +-
daedalus.dme | 18 +-
icons/obj/storage.dmi | Bin 82065 -> 83501 bytes
icons/obj/terminals.dmi | Bin 14963 -> 15814 bytes
strings/memories.json | 2 +-
tools/UpdatePaths/kapuconomy2.txt | 10 +
83 files changed, 853 insertions(+), 3065 deletions(-)
create mode 100644 code/game/machinery/atm.dm
delete mode 100644 code/game/machinery/civilian_bounties.dm
delete mode 100644 code/game/objects/items/credit_holochip.dm
delete mode 100644 code/modules/cargo/bounties/assistant.dm
delete mode 100644 code/modules/cargo/bounties/botany.dm
delete mode 100644 code/modules/cargo/bounties/chef.dm
delete mode 100644 code/modules/cargo/bounties/engineering.dm
delete mode 100644 code/modules/cargo/bounties/item.dm
delete mode 100644 code/modules/cargo/bounties/mech.dm
delete mode 100644 code/modules/cargo/bounties/medical.dm
delete mode 100644 code/modules/cargo/bounties/reagent.dm
delete mode 100644 code/modules/cargo/bounties/security.dm
delete mode 100644 code/modules/cargo/bounties/slime.dm
delete mode 100644 code/modules/cargo/bounties/special.dm
delete mode 100644 code/modules/cargo/bounties/virus.dm
delete mode 100644 code/modules/cargo/bounty.dm
delete mode 100644 code/modules/cargo/exports/civilain_bounty.dm
delete mode 100644 code/modules/economy/holopay.dm
create mode 100644 tools/UpdatePaths/kapuconomy2.txt
diff --git a/_maps/RandomRuins/SpaceRuins/oldAIsat.dmm b/_maps/RandomRuins/SpaceRuins/oldAIsat.dmm
index 237e37134a2c..3d0e00c2d2ca 100644
--- a/_maps/RandomRuins/SpaceRuins/oldAIsat.dmm
+++ b/_maps/RandomRuins/SpaceRuins/oldAIsat.dmm
@@ -246,13 +246,6 @@
/obj/item/paper/crumpled,
/turf/open/floor/iron/airless,
/area/ruin/tcommsat_oldaisat)
-"aX" = (
-/obj/item/food/meat/slab/synthmeat{
- name = "Cuban Pete-Meat"
- },
-/obj/item/stack/spacecash/c200,
-/turf/open/floor/engine,
-/area/ruin/tcommsat_oldaisat)
"aY" = (
/obj/structure/chair{
dir = 4
@@ -2910,7 +2903,7 @@ ag
ao
aE
aE
-aX
+aE
ag
ag
ag
diff --git a/_maps/map_files/Theseus/Theseus.dmm b/_maps/map_files/Theseus/Theseus.dmm
index 67dbbad4c3dc..049f3df7a159 100644
--- a/_maps/map_files/Theseus/Theseus.dmm
+++ b/_maps/map_files/Theseus/Theseus.dmm
@@ -735,19 +735,6 @@
/obj/structure/easel,
/turf/open/floor/plating,
/area/station/maintenance/disposal)
-"ail" = (
-/obj/structure/closet/secure_closet/personal,
-/obj/item/clothing/under/misc/assistantformal,
-/obj/structure/sign/map/left{
- desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown).";
- icon_state = "map-left-MS";
- pixel_y = 32
- },
-/obj/item/clothing/suit/hooded/wintercoat,
-/obj/item/clothing/shoes/winterboots,
-/obj/effect/turf_decal/tile/neutral/fourcorners,
-/turf/open/floor/iron/dark,
-/area/station/commons/locker)
"aim" = (
/obj/structure/table,
/obj/item/controller,
@@ -2907,6 +2894,13 @@
},
/turf/open/floor/iron/dark,
/area/station/engineering/atmos)
+"aJv" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4,
+/obj/effect/turf_decal/tile/dark{
+ dir = 4
+ },
+/turf/open/floor/iron/white,
+/area/station/medical/medbay/lobby)
"aJw" = (
/obj/structure/railing{
dir = 4
@@ -5413,11 +5407,6 @@
},
/turf/open/floor/plating,
/area/station/hallway/secondary/entry)
-"bsm" = (
-/obj/item/beacon,
-/obj/effect/turf_decal/delivery,
-/turf/open/floor/iron/white,
-/area/station/hallway/secondary/entry)
"bsn" = (
/obj/structure/closet/firecloset,
/obj/effect/turf_decal/delivery,
@@ -16186,13 +16175,6 @@
/obj/structure/sign/warning/securearea,
/turf/closed/wall/r_wall/prepainted/daedalus,
/area/station/command/corporate_showroom)
-"eDt" = (
-/obj/machinery/computer/slot_machine{
- pixel_y = 2
- },
-/obj/effect/mapping_helpers/broken_floor,
-/turf/open/floor/wood,
-/area/station/maintenance/port/aft)
"eDG" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
@@ -24362,18 +24344,6 @@
},
/turf/open/floor/iron,
/area/station/engineering/atmos)
-"hhS" = (
-/obj/item/radio/intercom/directional/west,
-/obj/machinery/piratepad/civilian,
-/obj/effect/turf_decal/bot_white,
-/obj/machinery/camera/directional/west{
- c_tag = "Central Primary Hallway - Fore - Port Corner"
- },
-/obj/structure/cable/yellow{
- icon_state = "5"
- },
-/turf/open/floor/iron,
-/area/station/construction/storage_wing)
"hhT" = (
/obj/effect/turf_decal/tile/neutral/fourcorners,
/obj/machinery/vending/cigarette,
@@ -30079,14 +30049,6 @@
/obj/machinery/meter,
/turf/open/floor/iron/ported/techfloor,
/area/station/engineering/supermatter/room)
-"iWt" = (
-/obj/machinery/light/directional/west,
-/obj/machinery/computer/piratepad_control/civilian{
- dir = 4
- },
-/obj/effect/turf_decal/trimline/brown/filled/line,
-/turf/open/floor/iron,
-/area/station/construction/storage_wing)
"iWx" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible,
/turf/open/floor/iron/ported/techfloor_grid,
@@ -30196,13 +30158,6 @@
/obj/structure/sign/poster/random/directional/east,
/turf/open/floor/wood,
/area/station/service/theater)
-"iYM" = (
-/obj/item/radio/intercom/directional/north,
-/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
-/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
-/obj/effect/turf_decal/tile/yellow/opposingcorners,
-/turf/open/floor/iron/dark,
-/area/station/hallway/secondary/exit/departure_lounge)
"iZa" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron,
@@ -31333,6 +31288,17 @@
/obj/effect/landmark/event_spawn,
/turf/open/floor/iron,
/area/station/engineering/main)
+"jqX" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/power/apc/auto_name/directional/east,
+/obj/structure/cable/yellow{
+ icon_state = "3"
+ },
+/obj/structure/cable/yellow{
+ icon_state = "2"
+ },
+/turf/open/floor/catwalk_floor/iron_dark,
+/area/station/maintenance/starboard/lesser)
"jro" = (
/obj/structure/chair/office,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
@@ -31700,15 +31666,6 @@
},
/turf/open/floor/iron/dark,
/area/station/engineering/atmos)
-"jyb" = (
-/obj/structure/chair/stool,
-/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4,
-/obj/effect/turf_decal/tile/dark{
- dir = 4
- },
-/obj/structure/noticeboard/directional/north,
-/turf/open/floor/iron/white,
-/area/station/medical/medbay/lobby)
"jyd" = (
/obj/structure/table,
/obj/effect/turf_decal/bot,
@@ -32912,13 +32869,6 @@
},
/turf/open/floor/iron/dark,
/area/station/engineering/storage/tech)
-"jRR" = (
-/obj/effect/turf_decal/siding/wood{
- dir = 8
- },
-/obj/machinery/restaurant_portal/bar,
-/turf/open/floor/wood,
-/area/station/commons/lounge)
"jRT" = (
/obj/structure/table/wood,
/obj/item/paper_bin{
@@ -35601,6 +35551,11 @@
/obj/machinery/airalarm/directional/south,
/turf/open/floor/iron/freezer,
/area/station/medical/coldroom/starboard)
+"kLe" = (
+/obj/effect/mapping_helpers/broken_floor,
+/obj/machinery/atm,
+/turf/open/floor/wood,
+/area/station/maintenance/port/aft)
"kLn" = (
/obj/structure/cable/yellow{
icon_state = "3"
@@ -36830,6 +36785,22 @@
},
/turf/open/floor/iron,
/area/station/hallway/secondary/service)
+"lfs" = (
+/obj/structure/disposalpipe/segment,
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/obj/machinery/power/apc/auto_name/directional/east,
+/obj/structure/cable/yellow{
+ icon_state = "3"
+ },
+/obj/structure/cable/yellow{
+ icon_state = "2"
+ },
+/turf/open/floor/iron/dark,
+/area/station/command/heads_quarters/ce)
"lfA" = (
/obj/structure/cable/yellow{
icon_state = "12"
@@ -38249,6 +38220,13 @@
},
/turf/open/floor/plating,
/area/station/maintenance/port/aft)
+"lCm" = (
+/obj/effect/turf_decal/siding/wood{
+ dir = 8
+ },
+/obj/machinery/atm,
+/turf/open/floor/wood,
+/area/station/commons/lounge)
"lCs" = (
/obj/effect/turf_decal/stripes/corner{
dir = 4
@@ -39281,11 +39259,6 @@
},
/turf/open/floor/plating,
/area/station/maintenance/starboard/fore)
-"lRn" = (
-/obj/structure/closet/firecloset,
-/obj/effect/turf_decal/tile/yellow/opposingcorners,
-/turf/open/floor/iron/dark,
-/area/station/hallway/secondary/exit/departure_lounge)
"lRr" = (
/obj/structure/chair/stool/directional/east,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
@@ -40913,6 +40886,11 @@
/obj/machinery/light/directional/south,
/turf/open/floor/wood,
/area/station/service/lawoffice)
+"mrE" = (
+/obj/machinery/light/directional/west,
+/obj/effect/turf_decal/trimline/brown/filled/line,
+/turf/open/floor/iron,
+/area/station/construction/storage_wing)
"mrI" = (
/obj/effect/turf_decal/siding/blue{
dir = 4
@@ -43790,6 +43768,13 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/plating,
/area/station/maintenance/port/fore)
+"niT" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/machinery/atm,
+/turf/open/floor/wood,
+/area/station/commons/lounge)
"niW" = (
/obj/effect/spawner/structure/window/reinforced/prepainted/daedalus,
/obj/structure/cable/yellow{
@@ -47951,6 +47936,17 @@
dir = 1
},
/area/station/engineering/main)
+"oyO" = (
+/obj/item/radio/intercom/directional/west,
+/obj/effect/turf_decal/bot_white,
+/obj/machinery/camera/directional/west{
+ c_tag = "Central Primary Hallway - Fore - Port Corner"
+ },
+/obj/structure/cable/yellow{
+ icon_state = "5"
+ },
+/turf/open/floor/iron,
+/area/station/construction/storage_wing)
"oyP" = (
/obj/structure/window/reinforced{
dir = 8
@@ -48254,6 +48250,14 @@
/obj/effect/turf_decal/tile/neutral,
/turf/open/floor/iron,
/area/station/command/heads_quarters/ce)
+"oDP" = (
+/obj/structure/closet/secure_closet/personal,
+/obj/item/clothing/under/misc/assistantformal,
+/obj/item/clothing/suit/hooded/wintercoat,
+/obj/item/clothing/shoes/winterboots,
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/turf/open/floor/iron/dark,
+/area/station/commons/locker)
"oDQ" = (
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
@@ -51651,6 +51655,13 @@
/obj/effect/landmark/start/hangover,
/turf/open/floor/iron,
/area/station/hallway/secondary/command)
+"pID" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/obj/effect/turf_decal/tile/yellow/opposingcorners,
+/obj/machinery/atm,
+/turf/open/floor/iron/dark,
+/area/station/hallway/secondary/exit/departure_lounge)
"pIE" = (
/obj/structure/chair/office{
dir = 4
@@ -52757,17 +52768,6 @@
"qbl" = (
/turf/closed/wall/prepainted/daedalus,
/area/station/maintenance/starboard/greater)
-"qbn" = (
-/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
-/obj/machinery/power/apc/auto_name/directional/east,
-/obj/structure/cable/yellow{
- icon_state = "3"
- },
-/obj/structure/cable/yellow{
- icon_state = "2"
- },
-/turf/open/floor/catwalk_floor/iron_dark,
-/area/station/maintenance/starboard/lesser)
"qby" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/structure/disposalpipe/segment{
@@ -55250,11 +55250,6 @@
},
/turf/open/floor/iron,
/area/station/security/prison)
-"qPK" = (
-/obj/structure/chair/stool/directional/north,
-/obj/effect/mapping_helpers/broken_floor,
-/turf/open/floor/wood,
-/area/station/maintenance/port/aft)
"qPM" = (
/obj/effect/turf_decal/stripes/corner{
dir = 1
@@ -57104,12 +57099,6 @@
/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/station/hallway/primary/central/fore)
-"rtC" = (
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/turf/open/floor/wood,
-/area/station/commons/lounge)
"rtK" = (
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/green{
@@ -60324,22 +60313,6 @@
/obj/effect/spawner/random/maintenance,
/turf/open/floor/plating,
/area/station/maintenance/port/aft)
-"svC" = (
-/obj/structure/disposalpipe/segment,
-/obj/effect/turf_decal/tile/neutral/fourcorners,
-/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
- dir = 1
- },
-/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
-/obj/machinery/power/apc/auto_name/directional/east,
-/obj/structure/cable/yellow{
- icon_state = "3"
- },
-/obj/structure/cable/yellow{
- icon_state = "2"
- },
-/turf/open/floor/iron/dark,
-/area/station/command/heads_quarters/ce)
"svS" = (
/obj/structure/disposalpipe/segment,
/obj/effect/turf_decal/stripes/line{
@@ -61838,19 +61811,6 @@
},
/turf/open/floor/iron,
/area/station/engineering/break_room)
-"sUq" = (
-/obj/structure/closet/secure_closet/personal,
-/obj/item/clothing/under/misc/assistantformal,
-/obj/structure/sign/map/right{
- desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown).";
- icon_state = "map-right-MS";
- pixel_y = 32
- },
-/obj/item/clothing/suit/hooded/wintercoat,
-/obj/item/clothing/shoes/winterboots,
-/obj/effect/turf_decal/tile/neutral/fourcorners,
-/turf/open/floor/iron/dark,
-/area/station/commons/locker)
"sUw" = (
/obj/effect/spawner/random/engineering/tracking_beacon,
/obj/structure/cable/red{
@@ -64482,6 +64442,11 @@
},
/turf/open/floor/iron,
/area/station/hallway/primary/starboard)
+"tME" = (
+/obj/structure/chair/stool,
+/obj/machinery/atm,
+/turf/open/floor/iron/white,
+/area/station/medical/medbay/lobby)
"tMH" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
@@ -65035,6 +65000,14 @@
/obj/structure/sign/poster/contraband/random/directional/north,
/turf/open/floor/wood,
/area/station/service/theater)
+"tYh" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow/opposingcorners,
+/obj/machinery/atm,
+/turf/open/floor/iron/white,
+/area/station/hallway/secondary/entry)
"tYy" = (
/obj/structure/mirror/directional/east,
/obj/machinery/shower{
@@ -65403,6 +65376,17 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden,
/turf/open/floor/iron/white,
/area/station/science/cytology)
+"ucQ" = (
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/structure/cable/yellow{
+ icon_state = "4"
+ },
+/obj/machinery/atm,
+/turf/open/floor/iron/white,
+/area/station/hallway/secondary/entry)
"ucW" = (
/obj/structure/table/wood,
/obj/item/book/manual/wiki/security_space_law,
@@ -66876,16 +66860,6 @@
/obj/machinery/light/small/directional/west,
/turf/open/floor/iron,
/area/station/security/brig)
-"uAH" = (
-/obj/effect/turf_decal/tile/yellow{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
-/obj/structure/cable/yellow{
- icon_state = "4"
- },
-/turf/open/floor/iron/white,
-/area/station/hallway/secondary/entry)
"uAJ" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/effect/turf_decal/trimline/brown/warning{
@@ -75183,6 +75157,12 @@
},
/turf/open/floor/catwalk_floor/iron_dark,
/area/station/maintenance/fore)
+"xhE" = (
+/obj/structure/closet/firecloset,
+/obj/effect/turf_decal/tile/yellow/opposingcorners,
+/obj/item/radio/intercom/directional/west,
+/turf/open/floor/iron/dark,
+/area/station/hallway/secondary/exit/departure_lounge)
"xhO" = (
/obj/effect/turf_decal/stripes/line{
dir = 6
@@ -76851,6 +76831,11 @@
},
/turf/open/floor/carpet,
/area/station/command/heads_quarters/hop)
+"xIz" = (
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/machinery/atm,
+/turf/open/floor/iron/dark,
+/area/station/commons/locker)
"xIE" = (
/obj/machinery/door/airlock/maintenance{
req_one_access_txt = "12;22;25;37;38;46"
@@ -77206,6 +77191,12 @@
},
/turf/open/floor/iron/dark,
/area/station/service/chapel/office)
+"xQQ" = (
+/obj/item/beacon,
+/obj/effect/turf_decal/delivery,
+/obj/machinery/atm,
+/turf/open/floor/iron/white,
+/area/station/hallway/secondary/entry)
"xQU" = (
/obj/structure/railing{
dir = 6
@@ -89209,7 +89200,7 @@ aaa
aaa
aaa
gbI
-aVu
+tYh
kJr
gbI
lMJ
@@ -89969,7 +89960,7 @@ aaa
aaa
lAu
oWO
-bsm
+xQQ
qVL
bvF
mQt
@@ -90213,7 +90204,7 @@ aaa
aaa
aaa
gbI
-uAH
+ucQ
bvF
aWU
bab
@@ -91790,8 +91781,8 @@ xYz
aob
mpF
vYs
-eDt
-qPK
+kLe
+crh
ckP
ckP
dvt
@@ -100238,8 +100229,8 @@ iMB
wcO
mlD
gFr
-hhS
-iWt
+oyO
+mrE
uHx
lrI
nUa
@@ -103612,7 +103603,7 @@ iRv
nNz
xGy
vzN
-gXE
+tME
rFw
tOJ
gME
@@ -103650,7 +103641,7 @@ iIw
rUF
qby
vml
-lRn
+xhE
pkO
iKr
mQS
@@ -103869,7 +103860,7 @@ pnP
nNz
uKz
vzN
-jyb
+aJv
lmv
sBM
gnf
@@ -105450,7 +105441,7 @@ hhT
lqg
jFp
vml
-iYM
+pID
qpk
cLm
cLm
@@ -111279,7 +111270,7 @@ euf
goR
iBZ
goR
-ail
+oDP
tzh
qCf
pRW
@@ -111536,7 +111527,7 @@ gBi
goR
qxK
goR
-sUq
+xIz
tzh
pRW
sZR
@@ -112326,7 +112317,7 @@ tDL
wbk
tFU
gEz
-jRR
+lCm
iSY
xjg
uQY
@@ -113097,7 +113088,7 @@ tDL
wbk
tFU
gEz
-rtC
+niT
uQY
klx
itV
@@ -114669,7 +114660,7 @@ jMi
iAs
dmE
nOu
-qbn
+jqX
duy
fLE
wJr
@@ -118741,7 +118732,7 @@ raR
gFk
ssT
dDX
-svC
+lfs
fxM
irJ
nup
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index e2dcecd9bf4e..2007d78c2f2d 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -967,16 +967,6 @@
/obj/structure/cable/smart_cable/color/yellow,
/turf/open/floor/iron/dark,
/area/centcom/central_command_areas/briefing)
-"cL" = (
-/obj/item/gun/energy/pulse/carbine,
-/obj/item/flashlight/seclite,
-/obj/structure/table/reinforced,
-/obj/machinery/airalarm/directional/south,
-/obj/effect/turf_decal/stripes/line{
- dir = 1
- },
-/turf/open/floor/iron,
-/area/centcom/central_command_areas/admin/storage)
"cN" = (
/obj/effect/turf_decal/siding/wood,
/obj/effect/turf_decal/siding/wood{
@@ -1379,6 +1369,19 @@
},
/turf/open/floor/iron,
/area/centcom/tdome/observation)
+"dY" = (
+/obj/effect/turf_decal/siding/thinplating_new/dark{
+ dir = 8
+ },
+/obj/structure/table/glass/plasmaglass,
+/obj/item/folder/white,
+/obj/item/pen{
+ pixel_x = 6;
+ pixel_y = 5
+ },
+/obj/machinery/light/cold/directional/west,
+/turf/open/floor/mineral/plastitanium,
+/area/centcom/syndicate_mothership/control)
"dZ" = (
/obj/item/kirbyplants{
icon_state = "plant-21"
@@ -5644,6 +5647,16 @@
},
/turf/open/floor/iron,
/area/centcom/central_command_areas/supplypod/loading/ert)
+"pY" = (
+/obj/item/gun/energy/pulse/carbine,
+/obj/item/flashlight/seclite,
+/obj/structure/table/reinforced,
+/obj/machinery/airalarm/directional/south,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/turf/open/floor/iron,
+/area/centcom/central_command_areas/admin/storage)
"pZ" = (
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
@@ -8114,6 +8127,17 @@
/obj/machinery/vending/snack,
/turf/open/floor/engine/cult,
/area/centcom/wizard_station)
+"xy" = (
+/obj/structure/table/reinforced,
+/obj/item/paper/fluff/stations/centcom/disk_memo{
+ pixel_x = -6;
+ pixel_y = -7
+ },
+/obj/item/taperecorder{
+ pixel_y = 15
+ },
+/turf/open/floor/carpet,
+/area/centcom/syndicate_mothership/control)
"xz" = (
/obj/structure/table/wood/fancy,
/obj/item/storage/photo_album,
@@ -10863,18 +10887,6 @@
/obj/item/pen,
/turf/open/floor/iron/dark/textured_large,
/area/centcom/syndicate_mothership/control)
-"Ft" = (
-/obj/structure/table/reinforced,
-/obj/item/paper/fluff/stations/centcom/disk_memo{
- pixel_x = -6;
- pixel_y = -7
- },
-/obj/item/taperecorder{
- pixel_y = 15
- },
-/obj/item/stack/spacecash/c50,
-/turf/open/floor/carpet,
-/area/centcom/syndicate_mothership/control)
"Fv" = (
/obj/machinery/door/airlock/centcom{
name = "CentCom"
@@ -13265,22 +13277,6 @@
/obj/structure/sign/nanotrasen,
/turf/closed/indestructible/reinforced/centcom,
/area/centcom/central_command_areas/briefing)
-"MZ" = (
-/obj/effect/turf_decal/siding/thinplating_new/dark{
- dir = 8
- },
-/obj/structure/table/glass/plasmaglass,
-/obj/item/folder/white,
-/obj/item/pen{
- pixel_x = 6;
- pixel_y = 5
- },
-/obj/machinery/light/cold/directional/west,
-/obj/item/stack/spacecash/c200{
- pixel_y = 17
- },
-/turf/open/floor/mineral/plastitanium,
-/area/centcom/syndicate_mothership/control)
"Na" = (
/obj/effect/turf_decal/siding/thinplating_new/dark/corner,
/turf/open/floor/mineral/plastitanium/red,
@@ -25617,7 +25613,7 @@ ng
VX
XE
od
-MZ
+dY
Sr
nz
br
@@ -37188,7 +37184,7 @@ nz
HN
gJ
dy
-Ft
+xy
nt
HJ
VJ
@@ -58516,7 +58512,7 @@ XA
Sx
Nn
yi
-cL
+pY
YU
vb
oe
diff --git a/_maps/shuttles/emergency_casino.dmm b/_maps/shuttles/emergency_casino.dmm
index 1b4b07f0f694..8277983d9922 100644
--- a/_maps/shuttles/emergency_casino.dmm
+++ b/_maps/shuttles/emergency_casino.dmm
@@ -482,10 +482,6 @@
pixel_x = -2;
pixel_y = 4
},
-/obj/item/stack/spacecash/c50{
- pixel_x = 2;
- pixel_y = 7
- },
/obj/machinery/vending/wallmed/directional/west,
/turf/open/floor/carpet/green,
/area/shuttle/escape)
diff --git a/_maps/shuttles/ruin_pirate_cutter.dmm b/_maps/shuttles/ruin_pirate_cutter.dmm
index 7d55a7941aa9..c0e6d17840fc 100644
--- a/_maps/shuttles/ruin_pirate_cutter.dmm
+++ b/_maps/shuttles/ruin_pirate_cutter.dmm
@@ -552,7 +552,6 @@
"BI" = (
/obj/structure/table,
/obj/machinery/light/small/directional/west,
-/obj/item/stack/spacecash/c200,
/turf/open/floor/iron/dark,
/area/shuttle/caravan/pirate)
"BL" = (
diff --git a/_maps/shuttles/whiteship_delta.dmm b/_maps/shuttles/whiteship_delta.dmm
index a03b5565fb3f..f5c8722528d0 100644
--- a/_maps/shuttles/whiteship_delta.dmm
+++ b/_maps/shuttles/whiteship_delta.dmm
@@ -930,10 +930,6 @@
/obj/effect/decal/cleanable/dirt/dust,
/obj/effect/decal/cleanable/cobweb,
/obj/machinery/firealarm/directional/west,
-/obj/item/stack/spacecash/c200{
- pixel_x = 7;
- pixel_y = 4
- },
/obj/item/pen{
pixel_x = -4
},
diff --git a/_maps/shuttles/whiteship_kilo.dmm b/_maps/shuttles/whiteship_kilo.dmm
index 35ddfeedab7f..fc8a760b4ba1 100644
--- a/_maps/shuttles/whiteship_kilo.dmm
+++ b/_maps/shuttles/whiteship_kilo.dmm
@@ -1634,7 +1634,6 @@
/obj/item/storage/toolbox/mechanical{
pixel_y = 6
},
-/obj/item/stack/spacecash/c200,
/turf/open/floor/mineral/plastitanium,
/area/shuttle/abandoned/bridge)
"db" = (
diff --git a/code/__DEFINES/dcs/signals/signals_storage.dm b/code/__DEFINES/dcs/signals/signals_storage.dm
index 456ac3c0781a..602ec54c0873 100644
--- a/code/__DEFINES/dcs/signals/signals_storage.dm
+++ b/code/__DEFINES/dcs/signals/signals_storage.dm
@@ -2,3 +2,16 @@
#define COMSIG_STORAGE_DUMP_CONTENT "storage_dump_contents"
/// Return to stop the standard dump behavior.
#define STORAGE_DUMP_HANDLED (1<<0)
+
+/// Sent after /datum/storage/attempt_insert(): (obj/item/inserted, mob/user, override, force)
+#define COMSIG_STORAGE_INSERTED_ITEM "storage_inserted_item"
+
+/// Sent when /datum/storage/open_storage(): (mob/to_show, performing_quickdraw)
+#define COMSIG_STORAGE_ATTEMPT_OPEN "storage_attempt_open"
+ /// Interrupt the opening.
+ #define STORAGE_INTERRUPT_OPEN (1<<0)
+
+/// Sent when /datum/storage/can_insert(): (obj/item/to_insert, mob/user, messages, force)
+#define COMSIG_STORAGE_CAN_INSERT "storage_can_insert"
+ /// Disallow the insertion.
+ #define STORAGE_NO_INSERT (1<<0)
diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm
index 2c6b0cec812e..d51aa4fcb404 100644
--- a/code/__DEFINES/inventory.dm
+++ b/code/__DEFINES/inventory.dm
@@ -1,7 +1,7 @@
/*ALL DEFINES RELATED TO INVENTORY OBJECTS, MANAGEMENT, ETC, GO HERE*/
//ITEM INVENTORY WEIGHT, FOR w_class
-/// Usually items smaller then a human hand, (e.g. playing cards, lighter, scalpel, coins/holochips)
+/// Usually items smaller then a human hand, (e.g. playing cards, lighter, scalpel, coins)
#define WEIGHT_CLASS_TINY 1
/// Pockets can hold small and tiny items, (e.g. flashlight, multitool, grenades, GPS device)
#define WEIGHT_CLASS_SMALL 2
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 36f014ec514d..ceb211da6e41 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -223,7 +223,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define ismobholder(A) (istype(A, /obj/item/mob_holder))
-#define iscash(A) (istype(A, /obj/item/coin) || istype(A, /obj/item/stack/spacecash) || istype(A, /obj/item/holochip))
+#define iscash(A) (istype(A, /obj/item/coin) || istype(A, /obj/item/stack/spacecash))
#define isbodypart(A) (istype(A, /obj/item/bodypart))
diff --git a/code/__DEFINES/memory_defines.dm b/code/__DEFINES/memory_defines.dm
index faaab7241610..be388f622099 100644
--- a/code/__DEFINES/memory_defines.dm
+++ b/code/__DEFINES/memory_defines.dm
@@ -108,7 +108,7 @@
*
* ideally these eventually get moved off this system... though engraving your bank account is so HILARIOUSLY dumb so maybe leave that one
*/
-///your memorized code
+///your memorized bank account
#define MEMORY_ACCOUNT "account"
///your memorized drug
#define MEMORY_QUIRK_DRUG "quirk_drug"
@@ -147,6 +147,7 @@
#define DETAIL_HIGHFIVE_TYPE "HIGHFIVE_TYPE"
#define DETAIL_BOMB_TYPE "BOMB_TYPE"
#define DETAIL_ACCOUNT_ID "ACCOUNT_ID"
+#define DETAIL_ACCOUNT_PIN "ACCOUNT_PIN"
#define DETAIL_KISSER "KISSER"
#define DETAIL_FOOD "FOOD"
#define DETAIL_DRINK "DRINK"
diff --git a/code/__HELPERS/memory_helpers.dm b/code/__HELPERS/memory_helpers.dm
index cd96203685d7..64865d0a9f89 100644
--- a/code/__HELPERS/memory_helpers.dm
+++ b/code/__HELPERS/memory_helpers.dm
@@ -60,8 +60,9 @@
/datum/mind/proc/build_story_mob(mob/living/target)
if(isanimal(target))
return "\the [target]"
- if(target.mind?.assigned_role)
- return "\the [lowertext(initial(target.mind?.assigned_role.title))]"
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ return H.get_face_name()
return target
///returns the story name of anything
diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm
index 1d6646c86a11..c7bfcc04e587 100644
--- a/code/controllers/subsystem/economy.dm
+++ b/code/controllers/subsystem/economy.dm
@@ -93,10 +93,19 @@ SUBSYSTEM_DEF(economy)
//Split the station budget amongst the departments
departmental_payouts()
- ///See if we even have enough money to pay these idiots
+ //See if we even have enough money to pay these idiots
var/required_funds = 0
+ var/list/dead_people = list()
+
+ //Dead people don't get money.
+ for(var/datum/data/record/medical_record in GLOB.data_core.general) //dont ask
+ if(medical_record.fields["status"] == "*Deceased*")
+ dead_people += medical_record.fields["name"]
+
for(var/account in bank_accounts_by_id)
var/datum/bank_account/bank_account = bank_accounts_by_id[account]
+ if(bank_account.account_holder in dead_people)
+ continue
required_funds += round(bank_account.account_job.paycheck * bank_account.payday_modifier)
if(payroll_active)
@@ -109,8 +118,16 @@ SUBSYSTEM_DEF(economy)
run_dry = FALSE
for(var/account in bank_accounts_by_id)
var/datum/bank_account/bank_account = bank_accounts_by_id[account]
+ if(bank_account.account_holder in dead_people)
+ continue
bank_account.payday()
+ priority_announce(
+ "Attention staff of [station_name()], you have received payment for this period. You may withdraw funds from your nearest ATM.",
+ "Station Announcement",
+ "Staff Update",
+ )
+
//price_update() This doesn't need to fire every 5 minutes. The only current use is market crash, which handles it on its own.
var/effective_mailcount = round(living_player_count())
mail_waiting += clamp(effective_mailcount, 1, MAX_MAIL_PER_MINUTE * delta_time)
@@ -349,3 +366,38 @@ SUBSYSTEM_DEF(economy)
spawned_paper.update_appearance()
return spawned_paper
+
+/// Spawns a given amount of money in optimal stacks at the given location.
+/datum/controller/subsystem/economy/proc/spawn_cash_for_amount(amt, spawn_loc)
+ amt = round(amt) // Don't pass in decimals you twat
+ var/ten_thousands = 0
+ var/thousands = 0
+ var/hundreds = 0
+ var/tens = 0
+ var/ones = 0
+
+ ten_thousands = floor(amt / 10000)
+ amt -= ten_thousands * 10000
+
+ thousands = floor(amt / 1000)
+ amt -= thousands * 1000
+
+ hundreds = floor(amt / 100)
+ amt -= hundreds * 100
+
+ tens = floor(amt / 10)
+ amt -= tens * 10
+
+ ones = amt
+
+ if(ten_thousands)
+ new /obj/item/stack/spacecash/c10000(spawn_loc, ten_thousands)
+ if(thousands)
+ new /obj/item/stack/spacecash/c1000(spawn_loc, thousands)
+ if(hundreds)
+ new /obj/item/stack/spacecash/c100(spawn_loc, hundreds)
+ if(tens)
+ new /obj/item/stack/spacecash/c10(spawn_loc, tens)
+ if(ones)
+ new /obj/item/stack/spacecash/c1(spawn_loc, ones)
+
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index 71023efbccd6..4e6bf8b9d330 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -548,11 +548,6 @@ SUBSYSTEM_DEF(job)
job.on_join_message(player_client, chosen_title)
if(player_client)
- // We agreed it's safe to remove this, but commented out instead of fully removed incase we want to reverse that decision.
- /*if(job.req_admin_notify)
- to_chat(player_client, "You are playing a job that is important for Game Progression. If you have to disconnect, please notify the admins via adminhelp.")
- */
-
var/related_policy = get_policy(job.title)
if(related_policy)
to_chat(player_client, related_policy)
@@ -562,7 +557,10 @@ SUBSYSTEM_DEF(job)
if(ishuman(equipping))
var/mob/living/carbon/human/wageslave = equipping
- wageslave.mind.add_memory(MEMORY_ACCOUNT, list(DETAIL_ACCOUNT_ID = wageslave.account_id), story_value = STORY_VALUE_SHIT, memory_flags = MEMORY_FLAG_NOLOCATION)
+ var/datum/bank_account/bank = SSeconomy.bank_accounts_by_id["[wageslave.account_id]"]
+
+ wageslave.mind.add_memory(MEMORY_ACCOUNT, list(DETAIL_ACCOUNT_ID = wageslave.account_id, DETAIL_ACCOUNT_PIN = bank.account_pin), story_value = STORY_VALUE_SHIT, memory_flags = MEMORY_FLAG_NOLOCATION)
+ to_chat(player_client, span_obviousnotice("Your bank account pin is: [bank.account_pin]"))
setup_alt_job_items(wageslave, job, player_client) //PARIAH EDIT ADDITION
@@ -846,8 +844,8 @@ SUBSYSTEM_DEF(job)
// Force-give their ID card bridge access.
var/obj/item/id_slot = new_captain.get_item_by_slot(ITEM_SLOT_ID)
if(id_slot)
- var/obj/item/card/id/id_card = id_slot.GetID()
- if(!(ACCESS_HEADS in id_card.access))
+ var/obj/item/card/id/id_card = id_slot.GetID() || locate() in id_slot
+ if(id_card && !(ACCESS_HEADS in id_card.access))
id_card.add_wildcards(list(ACCESS_HEADS), mode=FORCE_ADD_ALL)
assigned_captain = TRUE
diff --git a/code/datums/components/food/ice_cream_holder.dm b/code/datums/components/food/ice_cream_holder.dm
index 432d370dd90c..082619faaf7d 100644
--- a/code/datums/components/food/ice_cream_holder.dm
+++ b/code/datums/components/food/ice_cream_holder.dm
@@ -177,7 +177,7 @@
var/datum/venue/venue_to_pay = sold_to.ai_controller?.blackboard[BB_CUSTOMER_ATTENDING_VENUE]
- new /obj/item/holochip(get_turf(source), venue_price)
+ SSeconomy.spawn_cash_for_amount(venue_price, get_turf(source))
venue_to_pay.total_income += venue_price
playsound(get_turf(source), 'sound/effects/cashregister.ogg', 60, TRUE)
diff --git a/code/datums/elements/food/venue_price.dm b/code/datums/elements/food/venue_price.dm
index 37a6bed81693..6a0df12cab34 100644
--- a/code/datums/elements/food/venue_price.dm
+++ b/code/datums/elements/food/venue_price.dm
@@ -21,6 +21,6 @@
var/datum/venue/venue_to_pay = sold_to.ai_controller?.blackboard[BB_CUSTOMER_ATTENDING_VENUE]
- new /obj/item/holochip(get_turf(container), venue_price)
+ SSeconomy.spawn_cash_for_amount(venue_price, get_turf(sold_to))
venue_to_pay.total_income += venue_price
playsound(get_turf(container), 'sound/effects/cashregister.ogg', 60, TRUE)
diff --git a/code/datums/outfit.dm b/code/datums/outfit.dm
index 29c9e2940a4f..a65b142bf12d 100644
--- a/code/datums/outfit.dm
+++ b/code/datums/outfit.dm
@@ -107,6 +107,8 @@
///ID of the slot containing a gas tank
var/internals_slot = null
+ /// If TRUE, will spawn their ID in a wallet.
+ var/id_in_wallet = FALSE
/**
* Any skillchips the mob should have in their brain.
*
@@ -192,10 +194,18 @@
EQUIP_OUTFIT_ITEM(glasses, ITEM_SLOT_EYES)
if(back)
EQUIP_OUTFIT_ITEM(back, ITEM_SLOT_BACK)
+
if(id)
- EQUIP_OUTFIT_ITEM(id, ITEM_SLOT_ID)
+ if(id_in_wallet && ispath(id, /obj/item/card/id))
+ var/obj/item/storage/wallet/W = /obj/item/storage/wallet
+ EQUIP_OUTFIT_ITEM(W, ITEM_SLOT_ID)
+ W = H.wear_id
+ INVOKE_ASYNC(W, TYPE_PROC_REF(/obj/item, InsertID), SSwardrobe.provide_type(id), TRUE)
+ else
+ EQUIP_OUTFIT_ITEM(id, ITEM_SLOT_ID)
+
if(!visualsOnly && id_trim && H.wear_id)
- var/obj/item/card/id/id_card = H.wear_id
+ var/obj/item/card/id/id_card = H.wear_id.GetID(TRUE)
id_card.registered_age = H.age
if(id_trim)
if(!SSid_access.apply_trim_to_card(id_card, id_trim))
diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm
index 4ca1707cba5a..f7981921b4a1 100644
--- a/code/datums/station_traits/positive_traits.dm
+++ b/code/datums/station_traits/positive_traits.dm
@@ -230,43 +230,3 @@
var/obj/item/implant/deathrattle/implant_to_give = new()
deathrattle_group.register(implant_to_give)
implant_to_give.implant(spawned, spawned, BODY_ZONE_CHEST, TRUE, TRUE)
-
-
-/datum/station_trait/wallets
- name = "Wallets!"
- trait_type = STATION_TRAIT_POSITIVE
- show_in_report = TRUE
- weight = 10
- report_message = "It has become temporarily fashionable to use a wallet, so everyone on the station has been issued one."
-
-/datum/station_trait/wallets/New()
- . = ..()
- RegisterSignal(SSdcs, COMSIG_GLOB_JOB_AFTER_SPAWN, PROC_REF(on_job_after_spawn))
-
-/datum/station_trait/wallets/proc/on_job_after_spawn(datum/source, datum/job/job, mob/living/living_mob, mob/M, joined_late)
- SIGNAL_HANDLER
-
- var/obj/item/card/id/advanced/id_card = living_mob.get_item_by_slot(ITEM_SLOT_ID)
- if(!istype(id_card))
- return
-
- living_mob.temporarilyRemoveItemFromInventory(id_card, force=TRUE)
-
- // "Doc, what's wrong with me?"
- var/obj/item/storage/wallet/wallet = new(src)
- // "You've got a wallet embedded in your chest."
- wallet.add_fingerprint(living_mob, ignoregloves = TRUE)
-
- living_mob.equip_to_slot_if_possible(wallet, ITEM_SLOT_ID, initial=TRUE)
-
- id_card.forceMove(wallet)
-
- var/holochip_amount = id_card.registered_account.account_balance
- new /obj/item/holochip(wallet, holochip_amount)
- id_card.registered_account.adjust_money(-holochip_amount)
-
- new /obj/effect/spawner/random/entertainment/wallet_storage(wallet)
-
- // Put our filthy fingerprints all over the contents
- for(var/obj/item/item in wallet)
- item.add_fingerprint(living_mob, ignoregloves = TRUE)
diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm
index 7d610b4bf06a..8ca4110b57f1 100644
--- a/code/datums/storage/storage.dm
+++ b/code/datums/storage/storage.dm
@@ -365,6 +365,9 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
to_chat(user, span_warning("[resolve_parent] cannot hold [to_insert] as it's a storage item of the same size!"))
return FALSE
+ if(SEND_SIGNAL(src, COMSIG_STORAGE_CAN_INSERT, to_insert, user, messages, force) & STORAGE_NO_INSERT)
+ return FALSE
+
return TRUE
/**
@@ -388,6 +391,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
to_insert.forceMove(resolve_location)
item_insertion_feedback(user, to_insert, override)
resolve_location.update_appearance()
+ SEND_SIGNAL(src, COMSIG_STORAGE_INSERTED_ITEM, to_insert, user, override, force)
return TRUE
/// Checks if the item is allowed into storage based on it's weight class
@@ -491,10 +495,10 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
for(var/mob/viewing in oviewers(user, null))
if(in_range(user, viewing))
viewing.show_message(span_notice("[user] puts [thing] [insert_preposition]to [resolve_parent]."), MSG_VISUAL)
- return
+ continue
if(thing && thing.w_class >= 3)
viewing.show_message(span_notice("[user] puts [thing] [insert_preposition]to [resolve_parent]."), MSG_VISUAL)
- return
+ continue
/**
* Attempts to remove an item from the storage
@@ -948,6 +952,9 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
if(!resolve_parent)
return FALSE
+ if(SEND_SIGNAL(src, COMSIG_STORAGE_ATTEMPT_OPEN) & STORAGE_INTERRUPT_OPEN)
+ return FALSE
+
var/obj/item/resolve_location = real_location?.resolve()
if(!resolve_location)
return FALSE
diff --git a/code/datums/storage/subtypes/pockets.dm b/code/datums/storage/subtypes/pockets.dm
index 60e470c4b534..9bbd05795e3f 100644
--- a/code/datums/storage/subtypes/pockets.dm
+++ b/code/datums/storage/subtypes/pockets.dm
@@ -94,7 +94,6 @@
/obj/item/clothing/mask/cigarette,
/obj/item/lighter,
/obj/item/match,
- /obj/item/holochip,
/obj/item/toy/crayon),
list(/obj/item/screwdriver/power,
/obj/item/ammo_casing/caseless/rocket,
@@ -125,7 +124,6 @@
/obj/item/clothing/mask/cigarette,
/obj/item/lighter,
/obj/item/match,
- /obj/item/holochip,
/obj/item/toy/crayon,
/obj/item/bikehorn),
list(/obj/item/screwdriver/power,
diff --git a/code/game/area/areas/station.dm b/code/game/area/areas/station.dm
index ea348be3122b..01e112a59228 100644
--- a/code/game/area/areas/station.dm
+++ b/code/game/area/areas/station.dm
@@ -1068,7 +1068,6 @@
ambientsounds = list('sound/ambience/aurora_caelus_short.ogg')
//Security
-///When adding a new area to the security areas, make sure to add it to /datum/bounty/item/security/paperwork as well!
/area/station/security
name = "Security"
diff --git a/code/game/machinery/atm.dm b/code/game/machinery/atm.dm
new file mode 100644
index 000000000000..b78540332586
--- /dev/null
+++ b/code/game/machinery/atm.dm
@@ -0,0 +1,250 @@
+/obj/machinery/atm
+ name = "automated teller machine"
+ desc = "An age-old technology for managing one's wealth."
+ icon = 'icons/obj/terminals.dmi'
+ icon_state = "atm"
+ base_icon_state = "atm"
+
+ layer = ABOVE_OBJ_LAYER + 0.001
+ pixel_y = 32
+ base_pixel_y = 32
+
+ resistance_flags = INDESTRUCTIBLE
+ idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.1
+
+ /// The bank account being interfaced
+ var/datum/bank_account/authenticated_account
+ /// The card that is currently inserted
+ var/obj/item/card/id/inserted_card
+
+ /// Particle system for EMAGging
+ var/datum/effect_system/spark_spread/spark_system
+
+ var/entered_pin
+ var/reject_topic = FALSE
+
+/obj/machinery/atm/Initialize(mapload)
+ . = ..()
+ var/static/count = 1
+ name = "[station_name()] A.T.M #[count]"
+ count++
+
+ spark_system = new /datum/effect_system/spark_spread
+ spark_system.set_up(5, 0, src)
+ spark_system.attach(src)
+
+/obj/machinery/atm/Destroy()
+ QDEL_NULL(inserted_card)
+ authenticated_account = null
+ QDEL_NULL(spark_system)
+ return ..()
+
+/obj/machinery/atm/examine(mob/user)
+ . = ..()
+ if(inserted_card)
+ . += span_notice("There is a card in the card slot.")
+
+/obj/machinery/atm/update_icon_state()
+ if(machine_stat & NOPOWER)
+ icon_state = "[base_icon_state]_off"
+ else
+ icon_state = base_icon_state
+
+ return ..()
+
+/obj/machinery/atm/process()
+ if(machine_stat & NOPOWER)
+ return
+
+ use_power(IDLE_POWER_USE)
+
+/obj/machinery/atm/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
+ if(obj_flags & EMAGGED)
+ to_chat(user, span_warning("This machine has already been hacked."))
+ return
+
+ obj_flags |= EMAGGED
+ spark_system.start()
+ dispense_cash(rand(20, 200))
+
+/obj/machinery/atm/attackby(obj/item/I, mob/user, params)
+ if(!isidcard(I) && !iscash(I))
+ return ..()
+
+ if(machine_stat & NOPOWER)
+ to_chat(user, span_warning("You attempt to insert [I] into [src], but nothing happens."))
+ return TRUE
+
+ if(isidcard(I))
+ if(inserted_card)
+ to_chat(user, span_warning("You attempt to insert [I] into [src], but there's already something in the slot."))
+ return TRUE
+ if(!user.transferItemToLoc(I, src))
+ return TRUE
+
+ inserted_card = I
+ updateUsrDialog()
+ to_chat(user, span_notice("You insert [I] into [src]."))
+ return TRUE
+
+ if(iscash(I))
+ if(!authenticated_account)
+ to_chat(user, span_warning("You attempt to insert [I] into [src], but nothing happens."))
+ return TRUE
+
+ if(!user.transferItemToLoc(I, src))
+ return TRUE
+
+ var/value = I.get_item_credit_value()
+ qdel(I)
+ authenticated_account.adjust_money(value)
+
+ to_chat(user, span_notice("You deposit [value] into [src]."))
+ updateUsrDialog()
+ return TRUE
+
+/// Dispense the given amount of cash and give feedback.
+/obj/machinery/atm/proc/dispense_cash(amt)
+ if(!amt)
+ return
+
+ playsound(src, 'sound/machines/ping.ogg')
+ reject_topic = TRUE
+ sleep(2 SECONDS)
+ reject_topic = FALSE
+ visible_message(span_notice("[src] dispenses a wad of money."), vision_distance = COMBAT_MESSAGE_RANGE)
+
+ SSeconomy.spawn_cash_for_amount(amt, drop_location())
+
+/obj/machinery/atm/proc/try_authenticate(pin)
+ if((machine_stat & NOPOWER) || !inserted_card?.registered_account)
+ return FALSE
+
+ if(inserted_card.registered_account.account_pin != pin)
+ return FALSE
+
+ authenticated_account = inserted_card.registered_account
+ return TRUE
+
+/obj/machinery/atm/ui_interact(mob/user, datum/tgui/ui)
+ var/datum/browser/popup = new(user, "atm", name, 460, 270)
+ popup.set_content(jointext(get_content(), ""))
+ popup.open()
+
+/obj/machinery/atm/Topic(href, href_list)
+ . = ..()
+ if(. || reject_topic)
+ return
+
+ if(href_list["eject_id"])
+ inserted_card.forceMove(drop_location())
+ inserted_card = null
+ playsound(src, 'sound/machines/terminal_eject.ogg')
+ updateUsrDialog()
+ return TRUE
+
+ if(href_list["enter_pin"])
+ open_pinpad_ui(usr)
+ return TRUE
+
+ if(href_list["type"])
+ var/key = href_list["type"]
+ switch(key)
+ if("E")
+ if(try_authenticate(entered_pin))
+ entered_pin = ""
+ updateUsrDialog()
+ sleep(world.tick_lag)
+ usr << browse(null, "window=atm-pinpad")
+ else
+ entered_pin = "ERROR"
+ open_pinpad_ui(usr)
+
+ if("C")
+ entered_pin = ""
+ open_pinpad_ui(usr)
+
+ else
+ if(!sanitize_text(key))
+ return TRUE
+ if(length(entered_pin) >= 5)
+ return TRUE
+
+ entered_pin = "[entered_pin][key]"
+ open_pinpad_ui(usr)
+
+ return TRUE
+
+ if(href_list["logout"])
+ authenticated_account = null
+ updateUsrDialog()
+ return TRUE
+
+ if(href_list["withdraw"])
+ var/amt = tgui_input_number(usr, "Enter amount (1-100)", "Withdraw", 0, 100, 0)
+ if(!amt)
+ return TRUE
+
+ amt = min(amt, authenticated_account.account_balance)
+ authenticated_account.adjust_money(-amt)
+ dispense_cash(amt)
+ updateUsrDialog()
+ return TRUE
+
+/obj/machinery/atm/proc/get_content()
+ PRIVATE_PROC(TRUE)
+ . = list()
+ . += "
"
+ . += "
"
+ . += "
"
+
+/obj/machinery/atm/proc/buttons()
+ PRIVATE_PROC(TRUE)
+ RETURN_TYPE(/list)
+ . = list()
+
+ . += "[button_element(src, "Eject Card", "eject_id=1")]
"
+
+ if(!authenticated_account)
+ . += "[button_element(src, "Enter PIN", "enter_pin=1")]
"
+ else
+ . += "[button_element(src, "Withdraw", "withdraw=1")]
"
+ . += "[button_element(src, "Logout", "logout=1")]
"
+
+/obj/machinery/atm/proc/open_pinpad_ui(mob/user)
+ PRIVATE_PROC(TRUE)
+ var/datum/browser/popup = new(user, "atm-pinpad", "Enter Pin", 300, 280)
+ var/dat = "[src]
\n\n"
+ dat += {"
+
\n>[entered_pin]
\n1
+-2
+-3
\n
+4
+-5
+-6
\n
+7
+-8
+-9
\n
+C
+-0
+-E
\n"}
+
+ popup.set_content(dat)
+ popup.open()
diff --git a/code/game/machinery/bank_machine.dm b/code/game/machinery/bank_machine.dm
index 2fb279f08b67..807306388efb 100644
--- a/code/game/machinery/bank_machine.dm
+++ b/code/game/machinery/bank_machine.dm
@@ -26,10 +26,7 @@
var/value = 0
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
+ value = C.get_item_credit_value()
if(value)
var/datum/bank_account/D = SSeconomy.department_accounts_by_id[ACCOUNT_CAR]
if(D)
@@ -100,5 +97,5 @@
/obj/machinery/computer/bank_machine/proc/end_syphon()
siphoning = FALSE
- new /obj/item/holochip(drop_location(), syphoning_credits) //get the loot
+ SSeconomy.spawn_cash_for_amount(syphoning_credits, drop_location())
syphoning_credits = 0
diff --git a/code/game/machinery/civilian_bounties.dm b/code/game/machinery/civilian_bounties.dm
deleted file mode 100644
index a57e53472227..000000000000
--- a/code/game/machinery/civilian_bounties.dm
+++ /dev/null
@@ -1,383 +0,0 @@
-///Percentage of a civilian bounty the civilian will make.
-#define CIV_BOUNTY_SPLIT 30
-
-///Pad for the Civilian Bounty Control.
-/obj/machinery/piratepad/civilian
- name = "civilian bounty pad"
- desc = "A machine designed to send civilian bounty targets to centcom."
- layer = TABLE_LAYER
- resistance_flags = FIRE_PROOF
- circuit = /obj/item/circuitboard/machine/bountypad
-
-///Computer for assigning new civilian bounties, and sending bounties for collection.
-/obj/machinery/computer/piratepad_control/civilian
- name = "civilian bounty control terminal"
- desc = "A console for assigning civilian bounties to inserted ID cards, and for controlling the bounty pad for export."
- status_report = "Ready for delivery."
- icon_screen = "civ_bounty"
- icon_keyboard = "id_key"
- warmup_time = 3 SECONDS
- circuit = /obj/item/circuitboard/computer/bountypad
- interface_type = "CivCargoHoldTerminal"
- ///Typecast of an inserted, scanned ID card inside the console, as bounties are held within the ID card.
- var/obj/item/card/id/inserted_scan_id
-
-/obj/machinery/computer/piratepad_control/civilian/attackby(obj/item/I, mob/living/user, params)
- if(isidcard(I))
- if(id_insert(user, I, inserted_scan_id))
- inserted_scan_id = I
- return TRUE
- return ..()
-
-/obj/machinery/computer/piratepad_control/multitool_act(mob/living/user, obj/item/multitool/I)
- if(istype(I) && istype(I.buffer,/obj/machinery/piratepad/civilian))
- to_chat(user, span_notice("You link [src] with [I.buffer] in [I] buffer."))
- pad_ref = WEAKREF(I.buffer)
- return TRUE
-
-/obj/machinery/computer/piratepad_control/civilian/LateInitialize()
- . = ..()
- if(cargo_hold_id)
- for(var/obj/machinery/piratepad/civilian/C in INSTANCES_OF(/obj/machinery/piratepad))
- if(C.cargo_hold_id == cargo_hold_id)
- pad_ref = WEAKREF(C)
- return
- else
- var/obj/machinery/piratepad/civilian/pad = locate() in range(4,src)
- pad_ref = WEAKREF(pad)
-
-/obj/machinery/computer/piratepad_control/civilian/recalc()
- if(sending)
- return FALSE
- if(!inserted_scan_id)
- status_report = "Please insert your ID first."
- playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE)
- return FALSE
- if(!inserted_scan_id.registered_account.civilian_bounty)
- status_report = "Please accept a new civilian bounty first."
- playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE)
- return FALSE
- status_report = "Civilian Bounty: "
- var/obj/machinery/piratepad/pad = pad_ref?.resolve()
- for(var/atom/movable/AM in get_turf(pad))
- if(AM == pad)
- continue
- if(inserted_scan_id.registered_account.civilian_bounty.applies_to(AM))
- status_report += "Target Applicable."
- playsound(loc, 'sound/machines/synth_yes.ogg', 30 , TRUE)
- return
- status_report += "Not Applicable."
- playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE)
-
-/**
- * This fully rewrites base behavior in order to only check for bounty objects, and nothing else.
- */
-/obj/machinery/computer/piratepad_control/civilian/send()
- playsound(loc, 'sound/machines/wewewew.ogg', 70, TRUE)
- if(!sending)
- return
- if(!inserted_scan_id)
- stop_sending()
- return FALSE
- if(!inserted_scan_id.registered_account.civilian_bounty)
- stop_sending()
- return FALSE
- var/datum/bounty/curr_bounty = inserted_scan_id.registered_account.civilian_bounty
- var/active_stack = 0
- var/obj/machinery/piratepad/pad = pad_ref?.resolve()
- for(var/atom/movable/AM in get_turf(pad))
- if(AM == pad)
- continue
- if(curr_bounty.applies_to(AM))
- active_stack ++
- curr_bounty.ship(AM)
- qdel(AM)
- if(active_stack >= 1)
- status_report += "Bounty Target Found x[active_stack]. "
- else
- status_report = "No applicable targets found. Aborting."
- stop_sending()
- if(curr_bounty.can_claim())
- //Pay for the bounty with the ID's department funds.
- status_report += "Bounty completed! Please give your bounty cube to cargo for your automated payout shortly."
- inserted_scan_id.registered_account.reset_bounty()
- SSeconomy.civ_bounty_tracker++
-
- var/obj/item/bounty_cube/reward = new /obj/item/bounty_cube(drop_location())
- reward.set_up(curr_bounty, inserted_scan_id)
-
- pad.visible_message(span_notice("[pad] activates!"))
- flick(pad.sending_state,pad)
- pad.icon_state = pad.idle_state
- playsound(loc, 'sound/machines/synth_yes.ogg', 30 , TRUE)
- sending = FALSE
-
-///Here is where cargo bounties are added to the player's bank accounts, then adjusted and scaled into a civilian bounty.
-/obj/machinery/computer/piratepad_control/civilian/proc/add_bounties()
- if(!inserted_scan_id || !inserted_scan_id.registered_account)
- return
- var/datum/bank_account/pot_acc = inserted_scan_id.registered_account
- if((pot_acc.civilian_bounty || pot_acc.bounties) && !COOLDOWN_FINISHED(pot_acc, bounty_timer))
- var/curr_time = round((COOLDOWN_TIMELEFT(pot_acc, bounty_timer)) / (1 MINUTES), 0.01)
- say("Internal ID network spools coiling, try again in [curr_time] minutes!")
- return FALSE
- if(!pot_acc.account_job)
- say("Requesting ID card has no job assignment registered!")
- return FALSE
- var/list/datum/bounty/crumbs = list(random_bounty(pot_acc.account_job.bounty_types), // We want to offer 2 bounties from their appropriate job catagories
- random_bounty(pot_acc.account_job.bounty_types), // and 1 guarenteed assistant bounty if the other 2 suck.
- random_bounty(CIV_JOB_BASIC))
- COOLDOWN_START(pot_acc, bounty_timer, 5 MINUTES)
- pot_acc.bounties = crumbs
-
-/obj/machinery/computer/piratepad_control/civilian/proc/pick_bounty(choice)
- if(!inserted_scan_id || !inserted_scan_id.registered_account || !inserted_scan_id.registered_account.bounties || !inserted_scan_id.registered_account.bounties[choice])
- playsound(loc, 'sound/machines/synth_no.ogg', 40 , TRUE)
- return
- inserted_scan_id.registered_account.civilian_bounty = inserted_scan_id.registered_account.bounties[choice]
- inserted_scan_id.registered_account.bounties = null
- return inserted_scan_id.registered_account.civilian_bounty
-
-/obj/machinery/computer/piratepad_control/civilian/AltClick(mob/user)
- . = ..()
- if(!Adjacent(user))
- return FALSE
- id_eject(user, inserted_scan_id)
-
-/obj/machinery/computer/piratepad_control/civilian/ui_data(mob/user)
- . = list()
- .["points"] = points
- .["pad"] = pad_ref?.resolve() ? TRUE : FALSE
- .["sending"] = sending
- .["status_report"] = status_report
- .["id_inserted"] = inserted_scan_id
- if(inserted_scan_id?.registered_account)
- if(inserted_scan_id.registered_account.civilian_bounty)
- .["id_bounty_info"] = inserted_scan_id.registered_account.civilian_bounty.description
- .["id_bounty_num"] = inserted_scan_id.registered_account.bounty_num()
- .["id_bounty_value"] = (inserted_scan_id.registered_account.civilian_bounty.reward) * (CIV_BOUNTY_SPLIT/100)
- if(inserted_scan_id.registered_account.bounties)
- .["picking"] = TRUE
- .["id_bounty_names"] = list(inserted_scan_id.registered_account.bounties[1].name,
- inserted_scan_id.registered_account.bounties[2].name,
- inserted_scan_id.registered_account.bounties[3].name)
- .["id_bounty_values"] = list(inserted_scan_id.registered_account.bounties[1].reward * (CIV_BOUNTY_SPLIT/100),
- inserted_scan_id.registered_account.bounties[2].reward * (CIV_BOUNTY_SPLIT/100),
- inserted_scan_id.registered_account.bounties[3].reward * (CIV_BOUNTY_SPLIT/100))
- else
- .["picking"] = FALSE
-
- return
-
-/obj/machinery/computer/piratepad_control/civilian/ui_act(action, params)
- . = ..()
- if(.)
- return
- if(!pad_ref?.resolve())
- return
- if(!usr.canUseTopic(src, USE_CLOSE|USE_SILICON_REACH) || (machine_stat & (NOPOWER|BROKEN)))
- return
- switch(action)
- if("recalc")
- recalc()
- if("send")
- start_sending()
- if("stop")
- stop_sending()
- if("pick")
- pick_bounty(params["value"])
- if("bounty")
- add_bounties()
- if("eject")
- id_eject(usr, inserted_scan_id)
- inserted_scan_id = null
- . = TRUE
-
-///Self explanitory, holds the ID card in the console for bounty payout and manipulation.
-/obj/machinery/computer/piratepad_control/civilian/proc/id_insert(mob/user, obj/item/inserting_item, obj/item/target)
- var/obj/item/card/id/card_to_insert = inserting_item
- var/holder_item = FALSE
-
- if(!isidcard(card_to_insert))
- card_to_insert = inserting_item.RemoveID()
- holder_item = TRUE
-
- if(!card_to_insert || !user.transferItemToLoc(card_to_insert, src))
- return FALSE
-
- if(target)
- if(holder_item && inserting_item.InsertID(target))
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
- else
- id_eject(user, target)
-
- user.visible_message(span_notice("[user] inserts \the [card_to_insert] into \the [src]."),
- span_notice("You insert \the [card_to_insert] into \the [src]."))
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
- ui_interact(user)
- return TRUE
-
-///Removes A stored ID card.
-/obj/machinery/computer/piratepad_control/civilian/proc/id_eject(mob/user, obj/target)
- if(!target)
- to_chat(user, span_warning("That slot is empty!"))
- return FALSE
- else
- target.forceMove(drop_location())
- if(!issilicon(user) && Adjacent(user))
- user.put_in_hands(target)
- user.visible_message(span_notice("[user] gets \the [target] from \the [src]."), \
- span_notice("You get \the [target] from \the [src]."))
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
- inserted_scan_id = null
- return TRUE
-
-///Upon completion of a civilian bounty, one of these is created. It is sold to cargo to give the cargo budget bounty money, and the person who completed it cash.
-/obj/item/bounty_cube
- name = "bounty cube"
- desc = "A bundle of compressed hardlight data, containing a completed bounty. Sell this on the cargo shuttle to claim it!"
- icon = 'icons/obj/economy.dmi'
- icon_state = "bounty_cube"
- ///Value of the bounty that this bounty cube sells for.
- var/bounty_value = 0
- ///Multiplier for the bounty payout received by the Supply budget if the cube is sent without having to nag.
- var/speed_bonus = 0.2
- ///Multiplier for the bounty payout received by the person who completed the bounty.
- var/holder_cut = 0.3
- ///Multiplier for the bounty payout received by the person who claims the handling tip.
- var/handler_tip = 0.1
- ///Time between nags.
- var/nag_cooldown = 5 MINUTES
- ///How much the time between nags extends each nag.
- var/nag_cooldown_multiplier = 1.25
- ///Next world tick to nag Supply listeners.
- var/next_nag_time
- ///Who completed the bounty.
- var/bounty_holder
- ///What job the bounty holder had.
- var/bounty_holder_job
- ///What the bounty was for.
- var/bounty_name
- ///Bank account of the person who completed the bounty.
- var/datum/bank_account/bounty_holder_account
- ///Bank account of the person who receives the handling tip.
- var/datum/bank_account/bounty_handler_account
- ///Our internal radio.
- var/obj/item/radio/radio
- ///The key our internal radio uses.
- var/radio_key = /obj/item/encryptionkey/headset_cargo
-
-/obj/item/bounty_cube/Initialize(mapload)
- . = ..()
- ADD_TRAIT(src, TRAIT_NO_BARCODES, INNATE_TRAIT) // Don't allow anyone to override our pricetag component with a barcode
- radio = new(src)
- radio.keyslot = new radio_key
- radio.set_listening(FALSE, TRUE)
- radio.recalculateChannels()
- RegisterSignal(radio, COMSIG_ITEM_PRE_EXPORT, PROC_REF(on_export))
-
-/obj/item/bounty_cube/Destroy()
- if(radio)
- UnregisterSignal(radio, COMSIG_ITEM_PRE_EXPORT)
- QDEL_NULL(radio)
- return ..()
-
-/obj/item/bounty_cube/examine()
- . = ..()
- if(speed_bonus)
- . += span_notice("[time2text(next_nag_time - world.time,"mm:ss")] remains until [bounty_value * speed_bonus] credit speedy delivery bonus lost.")
- if(handler_tip && !bounty_handler_account)
- . += span_notice("Scan this in the cargo shuttle with an export scanner to register your bank account for the [bounty_value * handler_tip] credit handling tip.")
-
-/*
- * Signal proc for [COMSIG_ITEM_EXPORTED], registered on the internal radio.
- *
- * Deletes the internal radio before being exported,
- * to stop it from bring counted as an export.
- *
- * No 4 free credits for you!
- */
-/obj/item/bounty_cube/proc/on_export(datum/source)
- SIGNAL_HANDLER
-
- QDEL_NULL(radio)
- return COMPONENT_STOP_EXPORT // stops the radio from exporting, not the cube
-
-/obj/item/bounty_cube/process(delta_time)
- //if our nag cooldown has finished and we aren't on Centcom or in transit, then nag
- if(COOLDOWN_FINISHED(src, next_nag_time) && !is_centcom_level(z) && !is_reserved_level(z))
- //set up our nag message
- var/nag_message = "[src] is unsent in [get_area(src)]."
-
- //nag on Supply channel and reduce the speed bonus multiplier to nothing
- var/speed_bonus_lost = "[speed_bonus ? " Speedy delivery bonus of [bounty_value * speed_bonus] credit\s lost." : ""]"
- radio.talk_into(src, "[nag_message][speed_bonus_lost]", RADIO_CHANNEL_SUPPLY)
- speed_bonus = 0
-
- //alert the holder
- bounty_holder_account.bank_card_talk("[nag_message]")
-
- //if someone has registered for the handling tip, nag them
- bounty_handler_account?.bank_card_talk(nag_message)
-
- //increase our cooldown length and start it again
- nag_cooldown = nag_cooldown * nag_cooldown_multiplier
- COOLDOWN_START(src, next_nag_time, nag_cooldown)
-
-/obj/item/bounty_cube/proc/set_up(datum/bounty/my_bounty, obj/item/card/id/holder_id)
- bounty_value = my_bounty.reward
- bounty_name = my_bounty.name
- bounty_holder = holder_id.registered_name
- bounty_holder_job = holder_id.assignment
- bounty_holder_account = holder_id.registered_account
- name = "\improper [bounty_value] cr [name]"
- desc += " The sales tag indicates it was [bounty_holder] ([bounty_holder_job])'s reward for completing the [bounty_name] bounty."
- AddComponent(/datum/component/pricetag, holder_id.registered_account, holder_cut, FALSE)
- AddComponent(/datum/component/gps, "[src]")
- START_PROCESSING(SSobj, src)
- COOLDOWN_START(src, next_nag_time, nag_cooldown)
- radio.talk_into(src,"Created in [get_area(src)] by [bounty_holder] ([bounty_holder_job]). Speedy delivery bonus lost in [time2text(next_nag_time - world.time,"mm:ss")].", RADIO_CHANNEL_SUPPLY)
-
-//for when you need a REAL bounty cube to test with and don't want to do a bounty each time your code changes
-/obj/item/bounty_cube/debug_cube
- name = "debug bounty cube"
- desc = "Use in-hand to set it up with a random bounty. Requires an ID it can detect with a bank account attached. \
- This will alert Supply over the radio with your name and location, and cargo techs will be dispatched with kill on sight clearance."
- var/set_up = FALSE
-
-/obj/item/bounty_cube/debug_cube/attack_self(mob/user)
- if(!isliving(user))
- to_chat(user, span_warning("You aren't eligible to use this!"))
- return ..()
-
- if(!set_up)
- var/mob/living/squeezer = user
- if(squeezer.get_bank_account())
- set_up(random_bounty(), squeezer.get_idcard())
- set_up = TRUE
- return ..()
- to_chat(user, span_notice("It can't detect your bank account."))
-
- return ..()
-
-///Beacon to launch a new bounty setup when activated.
-/obj/item/civ_bounty_beacon
- name = "civilian bounty beacon"
- desc = "N.T. approved civilian bounty beacon, toss it down and you will have a bounty pad and computer delivered to you."
- icon = 'icons/obj/objects.dmi'
- icon_state = "floor_beacon"
- var/uses = 2
-
-/obj/item/civ_bounty_beacon/attack_self()
- loc.visible_message(span_warning("\The [src] begins to beep loudly!"))
- addtimer(CALLBACK(src, PROC_REF(launch_payload)), 1 SECONDS)
-
-/obj/item/civ_bounty_beacon/proc/launch_payload()
- playsound(src, SFX_SPARKS, 80, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- switch(uses)
- if(2)
- new /obj/machinery/piratepad/civilian(drop_location())
- if(1)
- new /obj/machinery/computer/piratepad_control/civilian(drop_location())
- qdel(src)
- uses--
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 3dcb49b68e07..74b2e491a62b 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -530,23 +530,30 @@ What a mess.*/
if("Pay")
for(var/datum/data/crime/p in active2.fields["citation"])
if(p.dataId == text2num(href_list["cdataid"]))
- var/obj/item/holochip/C = usr.is_holding_item_of_type(/obj/item/holochip)
- if(C && istype(C))
- var/pay = C.get_item_credit_value()
- if(!pay)
- to_chat(usr, span_warning("[C] doesn't seem to be worth anything!"))
- else
- var/diff = p.fine - p.paid
- GLOB.data_core.payCitation(active2.fields["id"], text2num(href_list["cdataid"]), pay)
- to_chat(usr, span_notice("You have paid [pay] credit\s towards your fine."))
- if (pay == diff || pay > diff || pay >= diff)
- investigate_log("Citation Paid off: [p.crimeName] Fine: [p.fine] | Paid off by [key_name(usr)]", INVESTIGATE_RECORDS)
- to_chat(usr, span_notice("The fine has been paid in full."))
- SSblackbox.ReportCitation(text2num(href_list["cdataid"]),"","","","", 0, pay)
- qdel(C)
- playsound(src, SFX_TERMINAL_TYPE, 25, FALSE)
+ var/obj/item/stack/spacecash/S = usr.is_holding_item_of_type(/obj/item/stack/spacecash)
+ if(!istype(S))
+ return TRUE
+
+ var/pay = S.get_item_credit_value()
+ if(!pay)
+ to_chat(usr, span_warning("[S] doesn't seem to be worth anything!"))
else
- to_chat(usr, span_warning("Fines can only be paid with holochips!"))
+ var/diff = p.fine - p.paid
+ GLOB.data_core.payCitation(active2.fields["id"], text2num(href_list["cdataid"]), pay)
+ to_chat(usr, span_notice("You have paid [pay] credit\s towards your fine."))
+ if (pay == diff || pay > diff || pay >= diff)
+ investigate_log("Citation Paid off: [p.crimeName] Fine: [p.fine] | Paid off by [key_name(usr)]", INVESTIGATE_RECORDS)
+ to_chat(usr, span_notice("The fine has been paid in full."))
+
+ var/overflow = pay - diff
+ if(overflow)
+ SSeconomy.spawn_cash_for_amount(overflow, drop_location())
+
+ SSblackbox.ReportCitation(text2num(href_list["cdataid"]),"","","","", 0, pay)
+ qdel(S)
+ playsound(src, SFX_TERMINAL_TYPE, 25, FALSE)
+ else
+ to_chat(usr, span_warning("Fines can only be paid with holochips!"))
if("Print Record")
if(!( printing ))
diff --git a/code/game/machinery/computer/warrant.dm b/code/game/machinery/computer/warrant.dm
index 8976317d5069..1e2e7faa28bf 100644
--- a/code/game/machinery/computer/warrant.dm
+++ b/code/game/machinery/computer/warrant.dm
@@ -116,8 +116,8 @@
if("Pay")
for(var/datum/data/crime/p in current.fields["citation"])
if(p.dataId == text2num(href_list["cdataid"]))
- var/obj/item/holochip/C = M.is_holding_item_of_type(/obj/item/holochip)
- if(C && istype(C))
+ var/obj/item/stack/spacecash/C = M.is_holding_item_of_type(/obj/item/stack/spacecash)
+ if(istype(C))
var/pay = C.get_item_credit_value()
if(!pay)
to_chat(M, span_warning("[C] doesn't seem to be worth anything!"))
@@ -128,6 +128,10 @@
if (pay == diff || pay > diff || pay >= diff)
investigate_log("Citation Paid off: [p.crimeName] Fine: [p.fine] | Paid off by [key_name(usr)]", INVESTIGATE_RECORDS)
to_chat(M, span_notice("The fine has been paid in full."))
+
+ var/overflow = pay - diff
+ if(overflow)
+ SSeconomy.spawn_cash_for_amount(overflow, drop_location())
SSblackbox.ReportCitation(text2num(href_list["cdataid"]),"","","","", 0, pay)
qdel(C)
playsound(src, SFX_TERMINAL_TYPE, 25, FALSE)
diff --git a/code/game/machinery/fax_machine.dm b/code/game/machinery/fax_machine.dm
index ad40d67076ca..dae60acdce19 100644
--- a/code/game/machinery/fax_machine.dm
+++ b/code/game/machinery/fax_machine.dm
@@ -509,7 +509,11 @@ GLOBAL_LIST_EMPTY(fax_machines)
playsound(src, 'sound/machines/buzz-sigh.ogg', 50)
. = FALSE
else
- new /obj/item/holochip(drop_location(), rand(15, 25))
+ if(prob(50))
+ new /obj/item/stack/spacecash/c10(drop_location())
+ else
+ new /obj/item/stack/spacecash/c20(drop_location())
+
playsound(src, 'sound/machines/ping.ogg', 60)
. = TRUE
diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm
index c11004db4f50..8ecdf3b19601 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -11,8 +11,6 @@
#define SPIN_TIME 65 //As always, deciseconds.
#define REEL_DEACTIVATE_DELAY 7
#define SEVEN "7"
-#define HOLOCHIP 1
-#define COIN 2
/obj/machinery/computer/slot_machine
name = "slot machine"
@@ -29,7 +27,6 @@
var/working = FALSE
var/balance = 0 //How much money is in the machine, ready to be CONSUMED.
var/jackpots = 0
- var/paymode = HOLOCHIP //toggles between HOLOCHIP/COIN, defined above
var/cointype = /obj/item/coin/iron //default cointype
var/static/list/coinvalues = list()
var/list/reels = list(list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0)
@@ -84,48 +81,25 @@
return ..()
/obj/machinery/computer/slot_machine/attackby(obj/item/I, mob/living/user, params)
- if(istype(I, /obj/item/coin))
- var/obj/item/coin/C = I
- if(paymode == COIN)
- if(prob(2))
- if(!user.transferItemToLoc(C, drop_location(), silent = FALSE))
- return
- C.throw_at(user, 3, 10)
- if(prob(10))
- balance = max(balance - SPIN_PRICE, 0)
- to_chat(user, span_warning("[src] spits your coin back out!"))
-
- else
- if(!user.temporarilyRemoveItemFromInventory(C))
- return
- to_chat(user, span_notice("You insert [C] into [src]'s slot!"))
- balance += C.value
- qdel(C)
- else
- to_chat(user, span_warning("This machine is only accepting holochips!"))
- else if(istype(I, /obj/item/holochip))
- if(paymode == HOLOCHIP)
- var/obj/item/holochip/H = I
- if(!user.temporarilyRemoveItemFromInventory(H))
- return
- to_chat(user, span_notice("You insert [H.credits] holocredits into [src]'s slot!"))
- balance += H.credits
- qdel(H)
- else
- to_chat(user, span_warning("This machine is only accepting coins!"))
- else if(I.tool_behaviour == TOOL_MULTITOOL)
- if(balance > 0)
- visible_message("[src] says, 'ERROR! Please empty the machine balance before altering paymode'") //Prevents converting coins into holocredits and vice versa
- else
- if(paymode == HOLOCHIP)
- paymode = COIN
- visible_message("[src] says, 'This machine now works with COINS!'")
- else
- paymode = HOLOCHIP
- visible_message("[src] says, 'This machine now works with HOLOCHIPS!'")
- else
+ if(!istype(I, /obj/item/coin))
return ..()
+ var/obj/item/coin/C = I
+ if(prob(2))
+ if(!user.transferItemToLoc(C, drop_location(), silent = FALSE))
+ return
+ C.throw_at(user, 3, 10)
+ if(prob(10))
+ balance = max(balance - SPIN_PRICE, 0)
+ to_chat(user, span_warning("[src] spits your coin back out!"))
+
+ else
+ if(!user.temporarilyRemoveItemFromInventory(C))
+ return
+ to_chat(user, span_notice("You insert [C] into [src]'s slot!"))
+ balance += C.value
+ qdel(C)
+
/obj/machinery/computer/slot_machine/emag_act()
if(obj_flags & EMAGGED)
return
@@ -268,13 +242,10 @@
jackpots += 1
balance += money - give_payout(JACKPOT)
money = 0
- if(paymode == HOLOCHIP)
- new /obj/item/holochip(loc,JACKPOT)
- else
- for(var/i in 1 to 5)
- cointype = pick(subtypesof(/obj/item/coin))
- var/obj/item/coin/C = new cointype(loc)
- random_step(C, 2, 50)
+ for(var/i in 1 to 5)
+ cointype = pick(subtypesof(/obj/item/coin))
+ var/obj/item/coin/C = new cointype(loc)
+ random_step(C, 2, 50)
else if(linelength == 5)
visible_message("[src] says, 'Big Winner! You win a thousand credits!'")
@@ -318,10 +289,7 @@
balance += surplus
/obj/machinery/computer/slot_machine/proc/give_payout(amount)
- if(paymode == HOLOCHIP)
- cointype = /obj/item/holochip
- else
- cointype = obj_flags & EMAGGED ? /obj/item/coin/iron : /obj/item/coin/silver
+ cointype = obj_flags & EMAGGED ? /obj/item/coin/iron : /obj/item/coin/silver
if(!(obj_flags & EMAGGED))
amount = dispense(amount, cointype, null, 0)
@@ -334,22 +302,16 @@
return amount
/obj/machinery/computer/slot_machine/proc/dispense(amount = 0, cointype = /obj/item/coin/silver, mob/living/target, throwit = 0)
- if(paymode == HOLOCHIP)
- var/obj/item/holochip/H = new /obj/item/holochip(loc,amount)
-
+ var/value = coinvalues["[cointype]"]
+ if(value <= 0)
+ CRASH("Coin value of zero, refusing to payout in dispenser")
+ while(amount >= value)
+ var/obj/item/coin/C = new cointype(loc) //DOUBLE THE PAIN
+ amount -= value
if(throwit && target)
- H.throw_at(target, 3, 10)
- else
- var/value = coinvalues["[cointype]"]
- if(value <= 0)
- CRASH("Coin value of zero, refusing to payout in dispenser")
- while(amount >= value)
- var/obj/item/coin/C = new cointype(loc) //DOUBLE THE PAIN
- amount -= value
- if(throwit && target)
- C.throw_at(target, 3, 10)
- else
- random_step(C, 2, 40)
+ C.throw_at(target, 3, 10)
+ else
+ random_step(C, 2, 40)
return amount
@@ -359,5 +321,3 @@
#undef BIG_PRIZE
#undef SMALL_PRIZE
#undef SPIN_PRICE
-#undef HOLOCHIP
-#undef COIN
diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm
index 8fb5d73807e0..74047ac9a466 100644
--- a/code/game/objects/effects/effect_system/effect_system.dm
+++ b/code/game/objects/effects/effect_system/effect_system.dm
@@ -65,7 +65,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
else
direction = pick(GLOB.alldirs)
var/step_amt = pick(1,2,3)
- var/step_delay = 5
+ var/step_delay = 3
var/datum/move_loop/loop = SSmove_manager.move(effect, direction, step_delay, timeout = step_delay * step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY)
RegisterSignal(loop, COMSIG_PARENT_QDELETING, PROC_REF(decrement_total_effect))
diff --git a/code/game/objects/effects/spawners/random/entertainment.dm b/code/game/objects/effects/spawners/random/entertainment.dm
index 0f005d255854..3d0a273ad222 100644
--- a/code/game/objects/effects/spawners/random/entertainment.dm
+++ b/code/game/objects/effects/spawners/random/entertainment.dm
@@ -83,7 +83,6 @@
/obj/item/stack/spacecash/c1 = 10,
/obj/item/stack/spacecash/c10 = 5,
/obj/item/stack/spacecash/c20 = 3,
- /obj/item/stack/spacecash/c50 = 2,
/obj/item/stack/spacecash/c100 = 1,
)
@@ -96,10 +95,7 @@
/obj/item/stack/spacecash/c1 = 100,
/obj/item/stack/spacecash/c10 = 80,
/obj/item/stack/spacecash/c20 = 60,
- /obj/item/stack/spacecash/c50 = 40,
/obj/item/stack/spacecash/c100 = 30,
- /obj/item/stack/spacecash/c200 = 20,
- /obj/item/stack/spacecash/c500 = 10,
/obj/item/stack/spacecash/c1000 = 5,
/obj/item/stack/spacecash/c10000 = 1,
)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 37174c4b4dcc..ef90559f64ea 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -617,7 +617,7 @@ DEFINE_INTERACTABLE(/obj/item)
R.hud_used.update_robot_modules_display()
/obj/item/attackby(obj/item/item, mob/living/user, params)
- if(user.try_slapcraft(src, item))
+ if(user?.try_slapcraft(src, item))
return TRUE
return ..()
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index c3a6876c7660..94d9494bf523 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -7,8 +7,6 @@
/// Fallback time if none of the config entries are set for USE_LOW_LIVING_HOUR_INTERN
#define INTERN_THRESHOLD_FALLBACK_HOURS 15
-/// Max time interval between projecting holopays
-#define HOLOPAY_PROJECTION_INTERVAL 7 SECONDS
/* Cards
* Contains:
@@ -58,30 +56,10 @@
/// How many magical mining Disney Dollars this card has for spending at the mining equipment vendors.
var/mining_points = 0
+
/// Linked bank account.
var/datum/bank_account/registered_account
- /// Linked holopay.
- var/obj/structure/holopay/my_store
- /// Cooldown between projecting holopays
- COOLDOWN_DECLARE(last_holopay_projection)
- /// List of logos available for holopay customization - via font awesome 5
- var/static/list/available_logos = list("angry", "ankh", "bacon", "band-aid", "cannabis", "cat", "cocktail", "coins", "comments-dollar",
- "cross", "cut", "dog", "donate", "dna", "fist-raised", "flask", "glass-cheers", "glass-martini-alt", "hamburger", "hand-holding-usd",
- "hat-wizard", "head-side-cough-slash", "heart", "heart-broken", "laugh-beam", "leaf", "money-check-alt", "music", "piggy-bank",
- "pizza-slice", "prescription-bottle-alt", "radiation", "robot", "smile", "skull-crossbones", "smoking", "space-shuttle", "tram",
- "trash", "user-ninja", "utensils", "wrench")
- /// Replaces the "pay whatever" functionality with a set amount when non-zero.
- var/holopay_fee = 0
- /// The holopay icon chosen by the user
- var/holopay_logo = "donate"
- /// Maximum forced fee. It's unlikely for a user to encounter this type of money, much less pay it willingly.
- var/holopay_max_fee = 5000
- /// Minimum forced fee for holopay stations. Registers as "pay what you want."
- var/holopay_min_fee = 0
- /// The holopay name chosen by the user
- var/holopay_name = "holographic pay stand"
-
/// The name registered on the card (for example: Dr Bryan See)
var/registered_name = null
/// The name used in the ID UI. See update_label()
@@ -130,13 +108,9 @@
register_context()
- RegisterSignal(src, COMSIG_ATOM_UPDATED_ICON, PROC_REF(update_in_wallet))
-
/obj/item/card/id/Destroy()
if (registered_account)
registered_account.bank_cards -= src
- if (my_store)
- QDEL_NULL(my_store)
return ..()
/obj/item/card/id/get_id_examine_strings(mob/user)
@@ -421,21 +395,6 @@
show(user)
add_fingerprint(user)
-/obj/item/card/id/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
- . = ..()
- if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
- return
- if(!proximity_flag || !check_allowed_items(target) || !isfloorturf(target))
- return
- try_project_paystand(user, target)
-
-/obj/item/card/id/attack_self_secondary(mob/user, modifiers)
- . = ..()
- if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
- return
- try_project_paystand(user)
- return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
-
/obj/item/card/id/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
@@ -443,101 +402,8 @@
return
context[SCREENTIP_CONTEXT_LMB] = "Show ID"
- context[SCREENTIP_CONTEXT_RMB] = "Project pay stand"
return CONTEXTUAL_SCREENTIP_SET
-/obj/item/card/id/proc/try_project_paystand(mob/user, turf/target)
- if(!COOLDOWN_FINISHED(src, last_holopay_projection))
- balloon_alert(user, "still recharging")
- return
- if(!registered_account || !registered_account.account_job)
- balloon_alert(user, "no account")
- to_chat(user, span_warning("You need a valid bank account to do this."))
- return
- /// Determines where the holopay will be placed based on tile contents
- var/turf/projection
- var/turf/step_ahead = get_step(user, user.dir)
- var/turf/user_loc = user.loc
- if(target && can_proj_holopay(target))
- projection = target
- else if(can_proj_holopay(step_ahead))
- projection = step_ahead
- else if(can_proj_holopay(user_loc))
- projection = user_loc
- if(!projection)
- balloon_alert(user, "no space")
- to_chat(user, span_warning("You need to be standing on or near an open tile to do this."))
- return
- /// Success: Valid tile for holopay placement
- if(my_store)
- my_store.dissipate()
- var/obj/structure/holopay/new_store = new(projection)
- if(new_store?.assign_card(projection, src))
- COOLDOWN_START(src, last_holopay_projection, HOLOPAY_PROJECTION_INTERVAL)
- playsound(projection, "sound/effects/empulse.ogg", 40, TRUE)
- my_store = new_store
-
-/**
- * Determines whether a new holopay can be placed on the given turf.
- * Checks if there are dense contents, too many contents, or another
- * holopay already exists on the turf.
- *
- * Arguments:
- * * turf/target - The target turf to be checked for dense contents
- * Returns:
- * * TRUE if the target is a valid holopay location, FALSE otherwise.
- */
-/obj/item/card/id/proc/can_proj_holopay(turf/target)
- if(!isfloorturf(target))
- return FALSE
- if(target.density)
- return FALSE
- if(length(target.contents) > 5)
- return FALSE
- for(var/obj/checked_obj in target.contents)
- if(checked_obj.density)
- return FALSE
- if(istype(checked_obj, /obj/structure/holopay))
- return FALSE
- return TRUE
-
-/**
- * Setter for the shop logo on linked holopays
- *
- * Arguments:
- * * new_logo - The new logo to be set.
- */
-/obj/item/card/id/proc/set_holopay_logo(new_logo)
- if(!available_logos.Find(new_logo))
- CRASH("User input a holopay shop logo that didn't exist.")
- holopay_logo = new_logo
-
-/**
- * Setter for changing the force fee on a holopay.
- *
- * Arguments:
- * * new_fee - The new fee to be set.
- */
-/obj/item/card/id/proc/set_holopay_fee(new_fee)
- if(!isnum(new_fee))
- CRASH("User input a non number into the holopay fee field.")
- if(new_fee < holopay_min_fee || new_fee > holopay_max_fee)
- CRASH("User input a number outside of the valid range into the holopay fee field.")
- holopay_fee = new_fee
-
-/**
- * Setter for changing the holopay name.
- *
- * Arguments:
- * * new_name - The new name to be set.
- */
-/obj/item/card/id/proc/set_holopay_name(name)
- if(length(name) < 3 || length(name) > MAX_NAME_LEN)
- to_chat(usr, span_warning("Must be between 3 - 42 characters."))
- else
- holopay_name = html_encode(trim(name, MAX_NAME_LEN))
-
-
/obj/item/card/id/vv_edit_var(var_name, var_value)
. = ..()
if(.)
@@ -549,84 +415,8 @@
if(ispath(trim))
SSid_access.apply_trim_to_card(src, trim)
-/obj/item/card/id/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/rupee))
- to_chat(user, span_warning("Your ID smartly rejects the strange shard of glass. Who knew, apparently it's not ACTUALLY valuable!"))
- return
- else if(iscash(W))
- insert_money(W, user)
- return
- 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, span_notice("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."))
- return
- else
- return ..()
-
-/**
- * Insert credits or coins into the ID card and add their value to the associated bank account.
- *
- * Arguments:
- * money - The item to attempt to convert to credits and insert into the card.
- * user - The user inserting the item.
- * physical_currency - Boolean, whether this is a physical currency such as a coin and not a holochip.
- */
-/obj/item/card/id/proc/insert_money(obj/item/money, mob/user)
- var/physical_currency
- if(istype(money, /obj/item/stack/spacecash) || istype(money, /obj/item/coin))
- physical_currency = TRUE
-
- if(!registered_account)
- to_chat(user, span_warning("[src] doesn't have a linked account to deposit [money] into!"))
- return
- var/cash_money = money.get_item_credit_value()
- if(!cash_money)
- to_chat(user, span_warning("[money] doesn't seem to be worth anything!"))
- return
- registered_account.adjust_money(cash_money)
- SSblackbox.record_feedback("amount", "credits_inserted", cash_money)
- log_econ("[cash_money] credits were inserted into [src] owned by [src.registered_name]")
- if(physical_currency)
- to_chat(user, span_notice("You stuff [money] into [src]. It disappears in a small puff of bluespace smoke, adding [cash_money] credits to the linked account."))
- else
- to_chat(user, span_notice("You insert [money] into [src], adding [cash_money] credits to the linked account."))
-
- to_chat(user, span_notice("The linked account now reports a balance of [registered_account.account_balance] cr."))
- qdel(money)
-
-/**
- * Insert multiple money or money-equivalent items at once.
- *
- * Arguments:
- * money - List of items to attempt to convert to credits and insert into the card.
- * user - The user inserting the items.
- */
-/obj/item/card/id/proc/mass_insert_money(list/money, mob/user)
- if(!registered_account)
- to_chat(user, span_warning("[src] doesn't have a linked account to deposit into!"))
- return FALSE
-
- if (!money || !length(money))
- return FALSE
-
- var/total = 0
-
- for (var/obj/item/physical_money in money)
- total += physical_money.get_item_credit_value()
- CHECK_TICK
-
- registered_account.adjust_money(total)
- SSblackbox.record_feedback("amount", "credits_inserted", total)
- log_econ("[total] credits were inserted into [src] owned by [src.registered_name]")
- QDEL_LIST(money)
-
- return total
-
-/// Helper proc. Can the user alt-click the ID?
-/obj/item/card/id/proc/alt_click_can_use_id(mob/living/user)
+/// Helper proc. Can the user interact with the ID?
+/obj/item/card/id/proc/can_use_id(mob/living/user)
if(!isliving(user))
return
if(!user.canUseTopic(src, USE_CLOSE|USE_IGNORE_TK))
@@ -641,52 +431,29 @@
if(loc != user)
to_chat(user, span_warning("You must be holding the ID to continue!"))
return FALSE
+
var/new_bank_id = tgui_input_number(user, "Enter your account ID number", "Account Reclamation", 111111, 999999, 111111)
- if(!new_bank_id || QDELETED(user) || QDELETED(src) || issilicon(user) || !alt_click_can_use_id(user) || loc != user)
+ if(!new_bank_id || QDELETED(user) || QDELETED(src) || issilicon(user) || !can_use_id(user) || loc != user)
return FALSE
+
if(registered_account?.account_id == new_bank_id)
to_chat(user, span_warning("The account ID was already assigned to this card."))
return FALSE
+
var/datum/bank_account/account = SSeconomy.bank_accounts_by_id["[new_bank_id]"]
if(isnull(account))
to_chat(user, span_warning("The account ID number provided is invalid."))
return FALSE
+
if(old_account)
old_account.bank_cards -= src
account.account_balance += old_account.account_balance
+
account.bank_cards += src
registered_account = account
to_chat(user, span_notice("The provided account has been linked to this ID card. It contains [account.account_balance] credits."))
return TRUE
-/obj/item/card/id/AltClick(mob/living/user)
- if(!alt_click_can_use_id(user))
- return
- if(!registered_account || registered_account.replaceable)
- set_new_account(user)
- return
- if (registered_account.being_dumped)
- registered_account.bank_card_talk(span_warning("内部服务器错误"), TRUE)
- return
- if(loc != user)
- to_chat(user, span_warning("You must be holding the ID to continue!"))
- return
- var/amount_to_remove = tgui_input_number(user, "How much do you want to withdraw? (Max: [registered_account.account_balance] cr)", "Withdraw Funds", max_value = registered_account.account_balance)
- if(!amount_to_remove || QDELETED(user) || QDELETED(src) || issilicon(user) || loc != user)
- 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, span_notice("You withdraw [amount_to_remove] credits into a holochip."))
- SSblackbox.record_feedback("amount", "credits_removed", amount_to_remove)
- log_econ("[amount_to_remove] credits were removed from [src] owned by [src.registered_name]")
- return
- else
- var/difference = amount_to_remove - registered_account.account_balance
- registered_account.bank_card_talk(span_warning("ERROR: The linked account requires [difference] more credit\s to perform that withdrawal."), TRUE)
-
/obj/item/card/id/examine(mob/user)
. = ..()
. += "\[Look at ID\]"
@@ -723,22 +490,12 @@
/obj/item/card/id/GetAccess()
return access.Copy()
-/obj/item/card/id/GetID()
+/obj/item/card/id/GetID(bypass_wallet)
return src
/obj/item/card/id/RemoveID()
return src
-/// Called on COMSIG_ATOM_UPDATED_ICON. Updates the visuals of the wallet this card is in.
-/obj/item/card/id/proc/update_in_wallet()
- SIGNAL_HANDLER
-
- if(istype(loc, /obj/item/storage/wallet))
- var/obj/item/storage/wallet/powergaming = loc
- if(powergaming.front_id == src)
- powergaming.update_label()
- powergaming.update_appearance()
-
/// Updates the name based on the card's vars and state.
/obj/item/card/id/proc/update_label()
var/name_string = registered_name ? "[registered_name]'s ID Card" : initial(name)
@@ -883,9 +640,6 @@
department_name = ACCOUNT_CAR_NAME
icon_state = "car_budget" //saving up for a new tesla
-/obj/item/card/id/departmental_budget/AltClick(mob/living/user)
- registered_account.bank_card_talk(span_warning("Withdrawing is not compatible with this card design."), TRUE) //prevents the vault bank machine being useless and putting money from the budget to your card to go over personal crates
-
/obj/item/card/id/advanced
name = "identification card"
desc = "A card used to provide ID and determine access across the station. Has an integrated digital display and advanced microchips."
diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm
index ac86c642ab73..c474e8bb7c2c 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -332,10 +332,6 @@
name = "Salvage Pod Recall (Computer Board)"
build_path = /obj/machinery/computer/shuttle/white_ship/pod/recall
-/obj/item/circuitboard/computer/bountypad
- name = "Bounty Pad (Computer Board)"
- build_path = /obj/machinery/computer/piratepad_control/civilian
-
/obj/item/circuitboard/computer/tram_controls
name = "Tram Controls (Computer Board)"
build_path = /obj/machinery/computer/tram_controls
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 2e756322efb1..c825f1c7f2f0 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -586,16 +586,6 @@
/obj/item/stack/sheet/glass = 1,
/obj/item/vending_refill/donksoft = 1)
-/obj/item/circuitboard/machine/bountypad
- name = "Civilian Bounty Pad (Machine Board)"
- greyscale_colors = CIRCUIT_COLOR_GENERIC
- build_path = /obj/machinery/piratepad/civilian
- req_components = list(
- /obj/item/stock_parts/card_reader = 1,
- /obj/item/stock_parts/scanning_module = 1,
- /obj/item/stock_parts/micro_laser = 1
- )
-
//Medical
/obj/item/circuitboard/machine/chem_dispenser
diff --git a/code/game/objects/items/credit_holochip.dm b/code/game/objects/items/credit_holochip.dm
deleted file mode 100644
index 25667d753272..000000000000
--- a/code/game/objects/items/credit_holochip.dm
+++ /dev/null
@@ -1,129 +0,0 @@
-/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"
- base_icon_state = "holochip"
- throwforce = 0
- force = 0
- w_class = WEIGHT_CLASS_TINY
- var/credits = 0
-
-/obj/item/holochip/Initialize(mapload, amount)
- . = ..()
- if(amount)
- credits = amount
- update_appearance()
-
-/obj/item/holochip/examine(mob/user)
- . = ..()
- . += "[span_notice("It's loaded with [credits] credit[( credits > 1 ) ? "s" : ""]")]\n"+\
- span_notice("Alt-Click to split.")
-
-/obj/item/holochip/get_item_credit_value()
- return credits
-
-/obj/item/holochip/update_name()
- name = "\improper [credits] credit holochip"
- return ..()
-
-/obj/item/holochip/update_icon_state()
- var/icon_suffix = ""
- switch(credits)
- if(1e3 to (1e6 - 1))
- icon_suffix = "_kilo"
- if(1e6 to (1e9 - 1))
- icon_suffix = "_mega"
- if(1e9 to INFINITY)
- icon_suffix = "_giga"
-
- icon_state = "[base_icon_state][icon_suffix]"
- return ..()
-
-/obj/item/holochip/update_overlays()
- . = ..()
- var/rounded_credits
- switch(credits)
- if(0 to (1e3 - 1))
- rounded_credits = round(credits)
- if(1e3 to (1e6 - 1))
- rounded_credits = round(credits * 1e-3)
- if(1e6 to (1e9 - 1))
- rounded_credits = round(credits * 1e-6)
- if(1e9 to INFINITY)
- rounded_credits = round(credits * 1e-9)
-
- 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"
-
- var/mutable_appearance/holochip_overlay = mutable_appearance('icons/obj/economy.dmi', "[icon_state]-color")
- holochip_overlay.color = overlay_color
- . += holochip_overlay
-
-/obj/item/holochip/proc/spend(amount, pay_anyway = FALSE)
- if(credits >= amount)
- credits -= amount
- if(credits == 0)
- qdel(src)
- update_appearance()
- 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, span_notice("You insert the credits into [src]."))
- update_appearance()
- qdel(H)
-
-/obj/item/holochip/AltClick(mob/user)
- if(!user.canUseTopic(src, USE_CLOSE|USE_DEXTERITY|USE_IGNORE_TK))
- return
- if(loc != user)
- to_chat(user, span_warning("You must be holding the holochip to continue!"))
- return FALSE
- var/split_amount = tgui_input_number(user, "How many credits do you want to extract from the holochip? (Max: [credits] cr)", "Holochip", max_value = credits)
- if(!split_amount || QDELETED(user) || QDELETED(src) || issilicon(user) || !usr.canUseTopic(src, USE_CLOSE|USE_IGNORE_TK|USE_DEXTERITY) || loc != user)
- return
- 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, span_notice("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(span_warning("[src] fizzles and disappears!"))
- qdel(src) //rip cash
-
-/obj/item/holochip/thousand
- credits = 1000
diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm
index 4c11921d011b..d9a358a40fbb 100644
--- a/code/game/objects/items/mail.dm
+++ b/code/game/objects/items/mail.dm
@@ -20,11 +20,9 @@
var/goodie_count = 1
/// 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/list/generic_goodies = list(
- /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,
+ /obj/item/stack/spacecash/c10 = 50,
+ /obj/item/stack/spacecash/c20 = 5,
+ /obj/item/stack/spacecash/c100 = 1,
)
// Overlays (pure fluff)
/// Does the letter have the postmark overlay?
diff --git a/code/game/objects/items/stacks/cash.dm b/code/game/objects/items/stacks/cash.dm
index c5f81af758d8..814df9bfa383 100644
--- a/code/game/objects/items/stacks/cash.dm
+++ b/code/game/objects/items/stacks/cash.dm
@@ -11,9 +11,11 @@
w_class = WEIGHT_CLASS_TINY
full_w_class = WEIGHT_CLASS_TINY
resistance_flags = FLAMMABLE
- var/value = 0
grind_results = list(/datum/reagent/cellulose = 10)
+ /// How much money one "amount" of this is worth. Use get_item_credit_value().
+ VAR_PROTECTED/value = 0
+
/obj/item/stack/spacecash/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
. = ..()
update_desc()
@@ -34,6 +36,11 @@
. = ..()
update_desc()
+/// Like use(), but for financial amounts. use_cash(20) on a stack of 10s will use 2. use_cash(22) on a stack of 10s will use 3.
+/obj/item/stack/spacecash/proc/use_cash(value_to_pay)
+ var/amt = ceil(value_to_pay / value)
+ return use(amt)
+
/obj/item/stack/spacecash/update_icon_state()
. = ..()
switch(amount)
@@ -64,30 +71,12 @@
value = 20
merge_type = /obj/item/stack/spacecash/c20
-/obj/item/stack/spacecash/c50
- icon_state = "spacecash50"
- singular_name = "fifty credit bill"
- value = 50
- merge_type = /obj/item/stack/spacecash/c50
-
/obj/item/stack/spacecash/c100
icon_state = "spacecash100"
singular_name = "one hundred credit bill"
value = 100
merge_type = /obj/item/stack/spacecash/c100
-/obj/item/stack/spacecash/c200
- icon_state = "spacecash200"
- singular_name = "two hundred credit bill"
- value = 200
- merge_type = /obj/item/stack/spacecash/c200
-
-/obj/item/stack/spacecash/c500
- icon_state = "spacecash500"
- singular_name = "five hundred credit bill"
- value = 500
- merge_type = /obj/item/stack/spacecash/c500
-
/obj/item/stack/spacecash/c1000
icon_state = "spacecash1000"
singular_name = "one thousand credit bill"
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index 0f3ce86c5e41..762ffd5baefe 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -1,89 +1,41 @@
/obj/item/storage/wallet
name = "wallet"
- desc = "It can hold a few small and personal things."
+ desc = "An old leather wallet with RFID blocking potential."
icon_state = "wallet"
w_class = WEIGHT_CLASS_SMALL
resistance_flags = FLAMMABLE
slot_flags = ITEM_SLOT_ID
+ /// Is the wallet open?
+ var/is_open = FALSE
+ /// The ID that is visible and functional if the wallet is open.
var/obj/item/card/id/front_id = null
- var/list/combined_access
+
var/cached_flat_icon
/obj/item/storage/wallet/Initialize()
. = ..()
+ atom_storage.animated = FALSE
+ atom_storage.rustle_sound = FALSE
atom_storage.max_slots = 4
- atom_storage.set_holdable(list(
- /obj/item/stack/spacecash,
- /obj/item/holochip,
- /obj/item/card,
- /obj/item/clothing/mask/cigarette,
- /obj/item/flashlight/pen,
- /obj/item/seeds,
- /obj/item/stack/medical,
- /obj/item/toy/crayon,
- /obj/item/coin,
- /obj/item/dice,
- /obj/item/disk,
- /obj/item/implanter,
- /obj/item/lighter,
- /obj/item/lipstick,
- /obj/item/match,
- /obj/item/paper,
- /obj/item/pen,
- /obj/item/photo,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/syringe,
- /obj/item/reagent_containers/pill,
- /obj/item/screwdriver,
- /obj/item/stamp),
- list(/obj/item/screwdriver/power))
+ atom_storage.max_specific_storage = WEIGHT_CLASS_TINY
+ atom_storage.max_total_storage = WEIGHT_CLASS_TINY * 4
+
+ RegisterSignal(atom_storage, COMSIG_STORAGE_CAN_INSERT, PROC_REF(can_insert_item))
+ RegisterSignal(atom_storage, COMSIG_STORAGE_ATTEMPT_OPEN, PROC_REF(on_attempt_open_storage))
+ register_context()
+
+/obj/item/storage/wallet/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+ context[SCREENTIP_CONTEXT_RMB] = is_open ? "Close" : "Open"
+ context[SCREENTIP_CONTEXT_ALT_LMB] = is_open ? "Close" : "Open"
+ return CONTEXTUAL_SCREENTIP_SET
/obj/item/storage/wallet/Exited(atom/movable/gone, direction)
. = ..()
if(istype(gone, /obj/item/card/id))
refreshID()
-/**
- * Calculates the new front ID.
- *
- * Picks the ID card that has the most combined command or higher tier accesses.
- */
-/obj/item/storage/wallet/proc/refreshID()
- LAZYCLEARLIST(combined_access)
-
- front_id = null
- var/winning_tally = 0
- var/is_magnetic_found = FALSE
- for(var/obj/item/card/id/id_card in contents)
- // Certain IDs can forcibly jump to the front so they can disguise other cards in wallets. Chameleon/Agent ID cards are an example of this.
- if(!is_magnetic_found && HAS_TRAIT(id_card, TRAIT_MAGNETIC_ID_CARD))
- front_id = id_card
- is_magnetic_found = TRUE
-
- if(!is_magnetic_found)
- var/card_tally = SSid_access.tally_access(id_card, ACCESS_FLAG_COMMAND)
- if(card_tally > winning_tally)
- winning_tally = card_tally
- front_id = id_card
-
- LAZYINITLIST(combined_access)
- combined_access |= id_card.access
-
- // If we didn't pick a front ID - Maybe none of our cards have any command accesses? Just grab the first card (if we even have one).
- // We could also have no ID card in the wallet at all, which will mean we end up with a null front_id and that's fine too.
- if(!front_id)
- front_id = (locate(/obj/item/card/id) in contents)
-
- if(ishuman(loc))
- var/mob/living/carbon/human/wearing_human = loc
- if(wearing_human.wear_id == src)
- wearing_human.sec_hud_set_ID()
-
- update_label()
- update_appearance(UPDATE_ICON)
- update_slot_icon()
-
/obj/item/storage/wallet/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
. = ..()
if(istype(arrived, /obj/item/card/id))
@@ -92,40 +44,50 @@
/obj/item/storage/wallet/update_overlays()
. = ..()
cached_flat_icon = null
- if(!front_id)
+ if(!is_open)
return
- . += mutable_appearance(front_id.icon, front_id.icon_state)
- . += front_id.overlays
- . += mutable_appearance(icon, "wallet_overlay")
-
-/obj/item/storage/wallet/proc/get_cached_flat_icon()
- if(!cached_flat_icon)
- cached_flat_icon = getFlatIcon(src)
- return cached_flat_icon
-/obj/item/storage/wallet/get_examine_string(mob/user, thats = FALSE)
+ . += image(icon, "wallet_underlay")
if(front_id)
- return "[icon2html(get_cached_flat_icon(), user)] [thats? "That's ":""][get_examine_name(user)]" //displays all overlays in chat
- return ..()
+ . += image(front_id.icon, front_id.icon_state)
+ . += front_id.overlays
+ . += image(icon, "wallet_overlay")
-/obj/item/storage/wallet/proc/update_label()
- if(front_id)
- name = "wallet displaying [front_id]"
+/obj/item/storage/wallet/attack_self(mob/user, modifiers)
+ . = ..()
+ if(.)
+ return
+
+ if(is_open)
+ close()
else
- name = "wallet"
+ open()
-/obj/item/storage/wallet/examine()
+/obj/item/storage/wallet/attack_hand_secondary(mob/user, list/modifiers)
+ if(is_open)
+ close()
+ else
+ open()
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+
+/obj/item/storage/wallet/AltClick(mob/user)
. = ..()
- if(front_id)
- . += span_notice("Alt-click to remove the id.")
+ if(!.)
+ return
+
+ if(is_open)
+ close()
+ else
+ open()
/obj/item/storage/wallet/get_id_examine_strings(mob/user)
. = ..()
- if(front_id)
+ if(front_id && is_open)
. += front_id.get_id_examine_strings(user)
-/obj/item/storage/wallet/GetID()
- return front_id
+/obj/item/storage/wallet/GetID(bypass_wallet)
+ if(is_open || bypass_wallet)
+ return front_id
/obj/item/storage/wallet/RemoveID()
if(!front_id)
@@ -133,21 +95,94 @@
. = front_id
front_id.forceMove(get_turf(src))
-/obj/item/storage/wallet/InsertID(obj/item/inserting_item)
+/obj/item/storage/wallet/InsertID(obj/item/inserting_item, force)
var/obj/item/card/inserting_id = inserting_item.RemoveID()
if(!inserting_id)
return FALSE
- attackby(inserting_id)
- if(inserting_id in contents)
- return TRUE
- return FALSE
+ return atom_storage.attempt_insert(inserting_item, force = force)
/obj/item/storage/wallet/GetAccess()
- if(LAZYLEN(combined_access))
- return combined_access
+ if(is_open && front_id)
+ return front_id.GetAccess()
else
return ..()
+/obj/item/storage/wallet/get_examine_string(mob/user, thats = FALSE)
+ if(front_id && is_open)
+ return "[icon2html(get_cached_flat_icon(), user)] [thats? "That's ":""][get_examine_name(user)]" //displays all overlays in chat
+ return ..()
+
+/obj/item/storage/wallet/proc/open()
+ SIGNAL_HANDLER
+ if(is_open)
+ return
+
+ is_open = TRUE
+ update_appearance()
+
+/obj/item/storage/wallet/proc/close()
+ if(!is_open)
+ return
+ is_open = FALSE
+ atom_storage.close_all()
+ update_appearance()
+
+/obj/item/storage/wallet/proc/get_cached_flat_icon()
+ if(!cached_flat_icon)
+ cached_flat_icon = getFlatIcon(src)
+ return cached_flat_icon
+
+/obj/item/storage/wallet/update_name()
+ . = ..()
+ if(front_id && is_open)
+ name = "wallet displaying \a [front_id.name]"
+ else
+ name = "wallet"
+
+/obj/item/storage/wallet/proc/on_attempt_open_storage(datum/storage/source, mob/user)
+ SIGNAL_HANDLER
+ if(!is_open)
+ return STORAGE_INTERRUPT_OPEN
+
+/obj/item/storage/wallet/proc/can_insert_item(datum/storage/source, obj/item/I, mob/user, messages, force)
+ SIGNAL_HANDLER
+ if(!is_open && user)
+ return STORAGE_NO_INSERT
+
+/obj/item/storage/wallet/proc/id_icon_updated(datum/source)
+ SIGNAL_HANDLER
+ update_appearance()
+
+/**
+ * Calculates the new front ID.
+ *
+ * Picks the ID card that has the most combined command or higher tier accesses.
+ */
+/obj/item/storage/wallet/proc/refreshID()
+ if(front_id)
+ UnregisterSignal(front_id, COMSIG_ATOM_UPDATED_ICON)
+
+ front_id = null
+ for(var/obj/item/card/id/id_card in contents)
+ // Certain IDs can forcibly jump to the front so they can disguise other cards in wallets. Chameleon/Agent ID cards are an example of this.
+ if(HAS_TRAIT(id_card, TRAIT_MAGNETIC_ID_CARD))
+ front_id = id_card
+ break
+
+ if(!front_id)
+ front_id = locate(/obj/item/card/id) in contents
+
+ if(front_id)
+ RegisterSignal(front_id, COMSIG_ATOM_UPDATED_ICON, PROC_REF(id_icon_updated))
+
+ if(ishuman(loc))
+ var/mob/living/carbon/human/wearing_human = loc
+ if(wearing_human.wear_id == src)
+ wearing_human.sec_hud_set_ID()
+
+ update_appearance()
+ update_slot_icon()
+
/obj/item/storage/wallet/random
icon_state = "random_wallet" // for mapping purposes
@@ -156,5 +191,5 @@
icon_state = "wallet"
/obj/item/storage/wallet/random/PopulateContents()
- new /obj/item/holochip(src, rand(5, 30))
+ SSeconomy.spawn_cash_for_amount(rand(5, 30), src)
new /obj/effect/spawner/random/entertainment/wallet_storage(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
index 1e9e86791f47..05f819dc34ea 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
@@ -108,12 +108,10 @@
/obj/structure/closet/secure_closet/freezer/money/PopulateContents()
..()
- for(var/i in 1 to 3)
- new /obj/item/stack/spacecash/c1000(src)
for(var/i in 1 to 5)
- new /obj/item/stack/spacecash/c500(src)
- for(var/i in 1 to 6)
- new /obj/item/stack/spacecash/c200(src)
+ new /obj/item/stack/spacecash/c1000(src)
+ for(var/i in 1 to 15)
+ new /obj/item/stack/spacecash/c100(src)
/obj/structure/closet/secure_closet/freezer/cream_pie
name = "cream pie closet"
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 95a348b0d274..dd828bb56308 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -89,9 +89,8 @@
to_chat(user, span_notice("You tear the manifest off of [src]."))
playsound(src, 'sound/items/poster_ripped.ogg', 75, TRUE)
- manifest.forceMove(loc)
- if(ishuman(user))
- user.put_in_hands(manifest)
+ if(!user.put_in_hands(manifest))
+ manifest.forceMove(loc.drop_location())
manifest = null
update_appearance()
diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm
deleted file mode 100644
index 5a06d102b00b..000000000000
--- a/code/modules/cargo/bounties/assistant.dm
+++ /dev/null
@@ -1,204 +0,0 @@
-/datum/bounty/item/assistant/scooter
- name = "Scooter"
- description = "Ananke has determined walking to be wasteful. Ship a scooter to CentCom to speed operations up."
- reward = CARGO_CRATE_VALUE * 2.16 // the mat hoffman
- wanted_types = list(/obj/vehicle/ridden/scooter = TRUE)
- include_subtypes = FALSE
-
-/datum/bounty/item/assistant/skateboard
- name = "Skateboard"
- description = "Ananke has determined walking to be wasteful. Ship a skateboard to CentCom to speed operations up."
- reward = CARGO_CRATE_VALUE * 1.8 // the tony hawk
- wanted_types = list(
- /obj/vehicle/ridden/scooter/skateboard = TRUE,
- /obj/item/melee/skateboard = TRUE,
- )
-
-/datum/bounty/item/assistant/stunprod
- name = "Stunprod"
- description = "CentCom demands a stunprod to use against dissidents. Craft one, then ship it."
- reward = CARGO_CRATE_VALUE * 2.6
- wanted_types = list(/obj/item/melee/baton/security/cattleprod = TRUE)
-
-/datum/bounty/item/assistant/soap
- name = "Soap"
- description = "Soap has gone missing from CentCom's bathrooms and nobody knows who took it. Replace it and be the hero CentCom needs."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 3
- wanted_types = list(/obj/item/soap = TRUE)
-
-/datum/bounty/item/assistant/spear
- name = "Spears"
- description = "CentCom's security forces are going through budget cuts. You will be paid if you ship a set of spears."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 5
- wanted_types = list(/obj/item/spear = TRUE)
-
-/datum/bounty/item/assistant/toolbox
- name = "Toolboxes"
- description = "There's an absence of robustness at Central Command. Hurry up and ship some toolboxes as a solution."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 6
- wanted_types = list(/obj/item/storage/toolbox = TRUE)
-
-/datum/bounty/item/assistant/statue
- name = "Statue"
- description = "Central Command would like to commision an artsy statue for the lobby. Ship one out, when possible."
- reward = CARGO_CRATE_VALUE * 4
- wanted_types = list(/obj/structure/statue = TRUE)
-
-/datum/bounty/item/assistant/clown_box
- name = "Clown Box"
- description = "The universe needs laughter. Stamp cardboard with a clown stamp and ship it out."
- reward = CARGO_CRATE_VALUE * 3
- wanted_types = list(/obj/item/storage/box/clown = TRUE)
-
-/datum/bounty/item/assistant/cheesiehonkers
- name = "Cheesie Honkers"
- description = "Apparently the company that makes Cheesie Honkers is going out of business soon. CentCom wants to stock up before it happens!"
- reward = CARGO_CRATE_VALUE * 2.4
- required_count = 3
- wanted_types = list(/obj/item/food/cheesiehonkers = TRUE)
-
-/datum/bounty/item/assistant/baseball_bat
- name = "Baseball Bat"
- description = "Baseball fever is going on at CentCom! Be a dear and ship them some baseball bats, so that management can live out their childhood dream."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 5
- wanted_types = list(/obj/item/melee/baseball_bat = TRUE)
-
-/datum/bounty/item/assistant/extendohand
- name = "Extendo-Hand"
- description = "Commander Betsy is getting old, and can't bend over to get the telescreen remote anymore. Management has requested an extendo-hand to help her out."
- reward = CARGO_CRATE_VALUE * 5
- wanted_types = list(/obj/item/extendohand = TRUE)
-
-/datum/bounty/item/assistant/donut
- name = "Donuts"
- description = "CentCom's security forces are facing heavy losses against the Syndicate. Ship donuts to raise morale."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 6
- wanted_types = list(/obj/item/food/donut = TRUE)
-
-/datum/bounty/item/assistant/donkpocket
- name = "Donk-Pockets"
- description = "Consumer safety recall: Warning. Donk-Pockets manufactured in the past year contain hazardous biomatter. Return units to management immediately."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 10
- wanted_types = list(/obj/item/food/donkpocket = TRUE)
-
-/datum/bounty/item/assistant/briefcase
- name = "Briefcase"
- description = "Central Command will be holding a business convention this year. Ship a few briefcases in support."
- reward = CARGO_CRATE_VALUE * 5
- required_count = 5
- wanted_types = list(
- /obj/item/storage/briefcase = TRUE,
- /obj/item/storage/secure/briefcase = TRUE,
- )
-
-/datum/bounty/item/assistant/sunglasses
- name = "Sunglasses"
- description = "A famous blues duo is passing through the sector, but they've lost their shades and they can't perform. Ship new sunglasses to CentCom to rectify this."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 2
- wanted_types = list(/obj/item/clothing/glasses/sunglasses = TRUE)
-
-/datum/bounty/item/assistant/monkey_hide
- name = "Monkey Hide"
- description = "One of the scientists at CentCom is interested in testing products on monkey skin. Your mission is to acquire monkey's hide and ship it."
- reward = CARGO_CRATE_VALUE * 3
- wanted_types = list(/obj/item/stack/sheet/animalhide/monkey = TRUE)
-
-/datum/bounty/item/assistant/comfy_chair
- name = "Comfy Chairs"
- description = "Commander Pat is unhappy with his chair. He claims it hurts his back. Ship some alternatives out to humor him."
- reward = CARGO_CRATE_VALUE * 3
- required_count = 5
- wanted_types = list(/obj/structure/chair/comfy = TRUE)
-
-/datum/bounty/item/assistant/geranium
- name = "Geraniums"
- description = "Commander Zot has the hots for Commander Zena. Send a shipment of geraniums - her favorite flower - and he'll happily reward you."
- reward = CARGO_CRATE_VALUE * 8
- required_count = 3
- wanted_types = list(/obj/item/food/grown/poppy/geranium = TRUE)
- include_subtypes = FALSE
-
-/datum/bounty/item/assistant/poppy
- name = "Poppies"
- description = "Commander Zot really wants to sweep Security Officer Olivia off her feet. Send a shipment of Poppies - her favorite flower - and he'll happily reward you."
- reward = CARGO_CRATE_VALUE * 2
- required_count = 3
- wanted_types = list(/obj/item/food/grown/poppy = TRUE)
- include_subtypes = FALSE
-
-/datum/bounty/item/assistant/shadyjims
- name = "Shady Jim's"
- description = "There's an irate officer at CentCom demanding that he receive a box of Shady Jim's cigarettes. Please ship one. He's starting to make threats."
- reward = CARGO_CRATE_VALUE
- wanted_types = list(/obj/item/storage/fancy/cigarettes/cigpack_shadyjims = TRUE)
-
-/datum/bounty/item/assistant/potted_plants
- name = "Potted Plants"
- description = "Central Command is looking to commission a new BirdBoat-class station. You've been ordered to supply the potted plants."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 8
- wanted_types = list(/obj/item/kirbyplants = TRUE)
-
-/datum/bounty/item/assistant/monkey_cubes
- name = "Monkey Cubes"
- description = "Due to a recent genetics accident, Central Command is in serious need of monkeys. Your mission is to ship monkey cubes."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 3
- wanted_types = list(/obj/item/food/monkeycube = TRUE)
-
-/datum/bounty/item/assistant/ied
- name = "IED"
- description = "The Core Worlds' maximum security prison back home is undergoing personnel training. Ship a handful of IEDs to serve as a training tools."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 3
- wanted_types = list(/obj/item/grenade/iedcasing = TRUE)
-
-/datum/bounty/item/assistant/corgimeat
- name = "Raw Corgi Meat"
- description = "The Syndicate recently stole all of CentCom's Corgi meat. Ship out a replacement immediately."
- reward = CARGO_CRATE_VALUE * 6
- wanted_types = list(/obj/item/food/meat/slab/corgi = TRUE)
-
-/datum/bounty/item/assistant/action_figures
- name = "Action Figures"
- description = "The vice president's son saw an ad for action figures on the telescreen and now he won't shut up about them. Ship some to ease his complaints."
- reward = CARGO_CRATE_VALUE * 8
- required_count = 5
- wanted_types = list(/obj/item/toy/figure = TRUE)
-
-/datum/bounty/item/assistant/dead_mice
- name = "Dead Mice"
- description = "Station 14 ran out of freeze-dried mice. Ship some fresh ones so their janitor doesn't go on strike."
- reward = CARGO_CRATE_VALUE * 10
- required_count = 5
- wanted_types = list(/obj/item/food/deadmouse = TRUE)
-
-/datum/bounty/item/assistant/paper_bin
- name = "Paper Bins"
- description = "Our accounting division is all out of paper. We need a new shipment immediately."
- reward = CARGO_CRATE_VALUE * 5
- required_count = 5
- wanted_types = list(/obj/item/paper_bin = TRUE)
-
-
-/datum/bounty/item/assistant/crayons
- name = "Crayons"
- description = "Dr Jones' kid ate all our crayons again. Please send us yours."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 24
- wanted_types = list(/obj/item/toy/crayon = TRUE)
-
-/datum/bounty/item/assistant/pens
- name = "Pens"
- description = "We are hosting the intergalactic pen balancing competition. We need you to send us some standardized ball point pens."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 10
- include_subtypes = FALSE
- wanted_types = list(/obj/item/pen = TRUE)
diff --git a/code/modules/cargo/bounties/botany.dm b/code/modules/cargo/bounties/botany.dm
deleted file mode 100644
index 71f751c81a13..000000000000
--- a/code/modules/cargo/bounties/botany.dm
+++ /dev/null
@@ -1,223 +0,0 @@
-/datum/bounty/item/botany
- reward = CARGO_CRATE_VALUE * 10
- var/datum/bounty/item/botany/multiplier = 0 //adds bonus reward money; increased for higher tier or rare mutations
- var/datum/bounty/item/botany/bonus_desc //for adding extra flavor text to bounty descriptions
- var/datum/bounty/item/botany/foodtype = "meal" //same here
-
-/datum/bounty/item/botany/New()
- ..()
- description = "Central Command's head chef is looking to prepare a fine [foodtype] with [name]. [bonus_desc]"
- reward += multiplier * (CARGO_CRATE_VALUE * 2)
- required_count = rand(5, 10)
-
-/datum/bounty/item/botany/ambrosia_vulgaris
- name = "Ambrosia Vulgaris Leaves"
- wanted_types = list(/obj/item/food/grown/ambrosia/vulgaris = TRUE)
- foodtype = "stew"
-
-/datum/bounty/item/botany/ambrosia_gaia
- name = "Ambrosia Gaia Leaves"
- wanted_types = list(/obj/item/food/grown/ambrosia/gaia = TRUE)
- multiplier = 4
- foodtype = "stew"
-
-/datum/bounty/item/botany/apple_golden
- name = "Golden Apples"
- wanted_types = list(/obj/item/food/grown/apple/gold = TRUE)
- multiplier = 4
- foodtype = "dessert"
-
-/datum/bounty/item/botany/banana
- name = "Bananas"
- wanted_types = list(
- /obj/item/food/grown/banana = TRUE,
- /obj/item/food/grown/banana/bluespace = FALSE,
- )
- foodtype = "banana split"
-
-/datum/bounty/item/botany/banana_bluespace
- name = "Bluespace Bananas"
- wanted_types = list(/obj/item/food/grown/banana/bluespace = TRUE)
- multiplier = 2
- foodtype = "banana split"
-
-/datum/bounty/item/botany/beans_koi
- name = "Koi Beans"
- wanted_types = list(/obj/item/food/grown/koibeans = TRUE)
- multiplier = 2
-
-/datum/bounty/item/botany/berries_death
- name = "Death Berries"
- wanted_types = list(/obj/item/food/grown/berries/death = TRUE)
- multiplier = 2
- bonus_desc = "He insists that \"he knows what he's doing\"."
- foodtype = "sorbet"
-
-/datum/bounty/item/botany/berries_glow
- name = "Glow-Berries"
- wanted_types = list(/obj/item/food/grown/berries/glow = TRUE)
- multiplier = 2
- foodtype = "sorbet"
-
-/datum/bounty/item/botany/cannabis
- name = "Cannabis Leaves"
- wanted_types = list(
- /obj/item/food/grown/cannabis = TRUE,
- /obj/item/food/grown/cannabis/white = FALSE,
- /obj/item/food/grown/cannabis/death = FALSE,
- /obj/item/food/grown/cannabis/ultimate = FALSE,
- )
- multiplier = 4 //hush money
- bonus_desc = "Do not mention this shipment to security."
- foodtype = "batch of \"muffins\""
-
-/datum/bounty/item/botany/cannabis_white
- name = "Lifeweed Leaves"
- wanted_types = list(/obj/item/food/grown/cannabis/white = TRUE)
- multiplier = 6
- bonus_desc = "Do not mention this shipment to security."
- foodtype = "\"meal\""
-
-/datum/bounty/item/botany/cannabis_death
- name = "Deathweed Leaves"
- wanted_types = list(/obj/item/food/grown/cannabis/death = TRUE)
- multiplier = 6
- bonus_desc = "Do not mention this shipment to security."
- foodtype = "\"meal\""
-
-/datum/bounty/item/botany/cannabis_ultimate
- name = "Omega Weed Leaves"
- wanted_types = list(/obj/item/food/grown/cannabis/ultimate = TRUE)
- multiplier = 6
- bonus_desc = "Under no circumstances mention this shipment to security."
- foodtype = "batch of \"brownies\""
-
-/datum/bounty/item/botany/wheat
- name = "Wheat Grains"
- wanted_types = list(/obj/item/food/grown/wheat = TRUE)
-
-/datum/bounty/item/botany/rice
- name = "Rice Grains"
- wanted_types = list(/obj/item/food/grown/rice = TRUE)
-
-/datum/bounty/item/botany/chili
- name = "Chili Peppers"
- wanted_types = list(/obj/item/food/grown/chili = TRUE)
-
-/datum/bounty/item/botany/ice_chili
- name = "Chilly Peppers"
- wanted_types = list(/obj/item/food/grown/icepepper = TRUE)
- multiplier = 2
-
-/datum/bounty/item/botany/ghost_chili
- name = "Ghost Chili Peppers"
- wanted_types = list(/obj/item/food/grown/ghost_chili = TRUE)
- multiplier = 2
-
-/datum/bounty/item/botany/citrus_lime
- name = "Limes"
- wanted_types = list(/obj/item/food/grown/citrus/lime = TRUE)
- foodtype = "sorbet"
-
-/datum/bounty/item/botany/citrus_lemon
- name = "Lemons"
- wanted_types = list(/obj/item/food/grown/citrus/lemon = TRUE)
- foodtype = "sorbet"
-
-/datum/bounty/item/botany/citrus_oranges
- name = "Oranges"
- wanted_types = list(/obj/item/food/grown/citrus/orange = TRUE)
- bonus_desc = "Do not ship lemons or limes." //I vanted orahnge!
- foodtype = "sorbet"
-
-/datum/bounty/item/botany/eggplant
- name = "Eggplants"
- wanted_types = list(/obj/item/food/grown/eggplant = TRUE)
- bonus_desc = "Not to be confused with egg-plants."
-
-/datum/bounty/item/botany/eggplant_eggy
- name = "Egg-plants"
- wanted_types = list(/obj/item/food/grown/shell/eggy = TRUE)
- bonus_desc = "Not to be confused with eggplants."
- multiplier = 2
-
-/datum/bounty/item/botany/kudzu
- name = "Kudzu Pods"
- wanted_types = list(/obj/item/food/grown/kudzupod = TRUE)
- bonus_desc = "Store in a dry, dark place."
- multiplier = 4
-
-/datum/bounty/item/botany/watermelon
- name = "Watermelons"
- wanted_types = list(/obj/item/food/grown/watermelon = TRUE)
- foodtype = "dessert"
-
-/datum/bounty/item/botany/watermelon_holy
- name = "Holy Melons"
- wanted_types = list(/obj/item/food/grown/holymelon = TRUE)
- multiplier = 2
- foodtype = "dessert"
-
-/datum/bounty/item/botany/glowshroom
- name = "Glowshrooms"
- wanted_types = list(
- /obj/item/food/grown/mushroom/glowshroom = TRUE,
- /obj/item/food/grown/mushroom/glowshroom/glowcap = FALSE,
- /obj/item/food/grown/mushroom/glowshroom/shadowshroom = FALSE,
- )
- foodtype = "omelet"
-
-/datum/bounty/item/botany/glowshroom_cap
- name = "Glowcaps"
- wanted_types = list(/obj/item/food/grown/mushroom/glowshroom/glowcap = TRUE)
- multiplier = 2
- foodtype = "omelet"
-
-/datum/bounty/item/botany/glowshroom_shadow
- name = "Shadowshrooms"
- wanted_types = list(/obj/item/food/grown/mushroom/glowshroom/shadowshroom = TRUE)
- multiplier = 2
- foodtype = "omelet"
-
-/datum/bounty/item/botany/nettles_death
- name = "Death Nettles"
- wanted_types = list(/obj/item/food/grown/nettle/death = TRUE)
- multiplier = 2
- bonus_desc = "Wear protection when handling them."
- foodtype = "cheese"
-
-/datum/bounty/item/botany/pineapples
- name = "Pineapples"
- wanted_types = list(/obj/item/food/grown/pineapple = TRUE)
- bonus_desc = "Not for human consumption."
- foodtype = "ashtray"
-
-/datum/bounty/item/botany/tomato
- name = "Tomatoes"
- wanted_types = list(
- /obj/item/food/grown/tomato = TRUE,
- /obj/item/food/grown/tomato/blue = FALSE,
- )
-
-/datum/bounty/item/botany/tomato_bluespace
- name = "Bluespace Tomatoes"
- wanted_types = list(/obj/item/food/grown/tomato/blue/bluespace = TRUE)
- multiplier = 4
-
-/datum/bounty/item/botany/oatz
- name = "Oats"
- wanted_types = list(/obj/item/food/grown/oat = TRUE)
- multiplier = 2
- foodtype = "batch of oatmeal"
- bonus_desc = "Squats and oats. We're all out of oats."
-
-/datum/bounty/item/botany/bonfire
- name = "Lit Bonfire"
- description = "Space heaters are malfunctioning and the cargo crew of Central Command is starting to feel cold. Grow some logs and Ship a lit bonfire to warm them up."
- wanted_types = list(/obj/structure/bonfire = TRUE)
-
-/datum/bounty/item/botany/bonfire/applies_to(obj/O)
- if(!..())
- return FALSE
- var/obj/structure/bonfire/B = O
- return !!B.burning
diff --git a/code/modules/cargo/bounties/chef.dm b/code/modules/cargo/bounties/chef.dm
deleted file mode 100644
index 3e15c3688bb1..000000000000
--- a/code/modules/cargo/bounties/chef.dm
+++ /dev/null
@@ -1,153 +0,0 @@
-/datum/bounty/item/chef/birthday_cake
- name = "Birthday Cake"
- description = "Nanotrasen's birthday is coming up! Ship them a birthday cake to celebrate!"
- reward = CARGO_CRATE_VALUE * 8
- wanted_types = list(
- /obj/item/food/cake/birthday = TRUE,
- /obj/item/food/cakeslice/birthday = TRUE
- )
-
-/datum/bounty/item/chef/soup
- name = "Soup"
- description = "To quell the homeless uprising, Nanotrasen will be serving soup to all underpaid workers. Ship any type of soup."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 3
- wanted_types = list(/obj/item/food/soup = TRUE)
-
-/datum/bounty/item/chef/popcorn
- name = "Popcorn Bags"
- description = "Upper management wants to host a movie night. Ship bags of popcorn for the occasion."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 3
- wanted_types = list(/obj/item/food/popcorn = TRUE)
-
-/datum/bounty/item/chef/onionrings
- name = "Onion Rings"
- description = "Nanotrasen is remembering Saturn day. Ship onion rings to show the station's support."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 3
- wanted_types = list(/obj/item/food/onionrings = TRUE)
-
-/datum/bounty/item/chef/icecreamsandwich
- name = "Ice Cream Sandwiches"
- description = "Upper management has been screaming non-stop for ice cream. Please send some."
- reward = CARGO_CRATE_VALUE * 8
- required_count = 3
- wanted_types = list(/obj/item/food/icecreamsandwich = TRUE)
-
-/datum/bounty/item/chef/strawberryicecreamsandwich
- name = " Strawberry Ice Cream Sandwiches"
- description = "Upper management has been screaming non-stop for more flavourful ice cream. Please send some."
- reward = CARGO_CRATE_VALUE * 10
- required_count = 3
- wanted_types = list(/obj/item/food/strawberryicecreamsandwich = TRUE)
-
-/datum/bounty/item/chef/bread
- name = "Bread"
- description = "Problems with central planning have led to bread prices skyrocketing. Ship some bread to ease tensions."
- reward = CARGO_CRATE_VALUE * 2
- wanted_types = list(
- /obj/item/food/bread = TRUE,
- /obj/item/food/breadslice = TRUE,
- /obj/item/food/bun = TRUE,
- /obj/item/food/pizzabread = TRUE,
- /obj/item/food/rawpastrybase = TRUE,
- )
-
-/datum/bounty/item/chef/pie
- name = "Pie"
- description = "3.14159? No! CentCom management wants edible pie! Ship a whole one."
- reward = 3142 //Screw it I'll do this one by hand
- wanted_types = list(/obj/item/food/pie = TRUE)
-
-/datum/bounty/item/chef/salad
- name = "Salad or Rice Bowls"
- description = "CentCom management is going on a health binge. Your order is to ship salad or rice bowls."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 3
- wanted_types = list(/obj/item/food/salad = TRUE)
-
-/datum/bounty/item/chef/carrotfries
- name = "Carrot Fries"
- description = "Night sight can mean life or death! A shipment of carrot fries is the order."
- reward = CARGO_CRATE_VALUE * 7
- required_count = 3
- wanted_types = list(/obj/item/food/carrotfries = TRUE)
-
-/datum/bounty/item/chef/superbite
- name = "Super Bite Burger"
- description = "Commander Tubbs thinks he can set a competitive eating world record. All he needs is a super bite burger shipped to him."
- reward = CARGO_CRATE_VALUE * 24
- wanted_types = list(/obj/item/food/burger/superbite = TRUE)
-
-/datum/bounty/item/chef/poppypretzel
- name = "Poppy Pretzel"
- description = "Central Command needs a reason to fire their HR head. Send over a poppy pretzel to force a failed drug test."
- reward = CARGO_CRATE_VALUE * 6
- wanted_types = list(/obj/item/food/poppypretzel = TRUE)
-
-/datum/bounty/item/chef/cubancarp
- name = "Cuban Carp"
- description = "To celebrate the birth of Castro XXVII, ship one cuban carp to CentCom."
- reward = CARGO_CRATE_VALUE * 16
- wanted_types = list(/obj/item/food/cubancarp = TRUE)
-
-/datum/bounty/item/chef/hotdog
- name = "Hot Dog"
- description = "Nanotrasen is conducting taste tests to determine the best hot dog recipe. Ship your station's version to participate."
- reward = CARGO_CRATE_VALUE * 16
- wanted_types = list(/obj/item/food/hotdog = TRUE)
-
-/datum/bounty/item/chef/eggplantparm
- name = "Eggplant Parmigianas"
- description = "A famous singer will be arriving at CentCom, and their contract demands that they only be served Eggplant Parmigiana. Ship some, please!"
- reward = CARGO_CRATE_VALUE * 7
- required_count = 3
- wanted_types = list(/obj/item/food/eggplantparm = TRUE)
-
-/datum/bounty/item/chef/muffin
- name = "Muffins"
- description = "The Muffin Man is visiting CentCom, but he's forgotten his muffins! Your order is to rectify this."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 3
- wanted_types = list(/obj/item/food/muffin = TRUE)
-
-/datum/bounty/item/chef/chawanmushi
- name = "Chawanmushi"
- description = "Nanotrasen wants to improve relations with its sister company, Japanotrasen. Ship Chawanmushi immediately."
- reward = CARGO_CRATE_VALUE * 16
- wanted_types = list(/obj/item/food/chawanmushi = TRUE)
-
-/datum/bounty/item/chef/kebab
- name = "Kebabs"
- description = "Remove all kebab from station you are best food. Ship to CentCom to remove from the premises."
- reward = CARGO_CRATE_VALUE * 7
- required_count = 3
- wanted_types = list(/obj/item/food/kebab = TRUE)
-
-/datum/bounty/item/chef/soylentgreen
- name = "Soylent Green"
- description = "CentCom has heard wonderful things about the product 'Soylent Green', and would love to try some. If you endulge them, expect a pleasant bonus."
- reward = CARGO_CRATE_VALUE * 10
- wanted_types = list(/obj/item/food/soylentgreen = TRUE)
-
-/datum/bounty/item/chef/pancakes
- name = "Pancakes"
- description = "Here at Nanotrasen we consider employees to be family. And you know what families love? Pancakes. Ship a baker's dozen."
- reward = CARGO_CRATE_VALUE * 10
- required_count = 13
- wanted_types = list(/obj/item/food/pancakes = TRUE)
-
-/datum/bounty/item/chef/nuggies
- name = "Chicken Nuggets"
- description = "The vice president's son won't shut up about chicken nuggies. Would you mind shipping some?"
- reward = CARGO_CRATE_VALUE * 8
- required_count = 6
- wanted_types = list(/obj/item/food/nugget = TRUE)
-
-/datum/bounty/item/chef/corgifarming //Butchering is a chef's job.
- name = "Corgi Hides"
- description = "Admiral Weinstein's space yacht needs new upholstery. A dozen Corgi furs should do just fine."
- reward = CARGO_CRATE_VALUE * 60 //that's a lot of dead dogs
- required_count = 12
- wanted_types = list(/obj/item/stack/sheet/animalhide/corgi = TRUE)
diff --git a/code/modules/cargo/bounties/engineering.dm b/code/modules/cargo/bounties/engineering.dm
deleted file mode 100644
index 83d80134134f..000000000000
--- a/code/modules/cargo/bounties/engineering.dm
+++ /dev/null
@@ -1,54 +0,0 @@
-/datum/bounty/item/engineering/gas
- name = "Full Tank of Pluoxium"
- description = "CentCom RnD is researching extra compact internals. Ship us a tank full of Pluoxium and you'll be compensated."
- reward = CARGO_CRATE_VALUE * 15
- wanted_types = list(/obj/item/tank = TRUE)
- var/moles_required = 20 // A full tank is 28 moles, but CentCom ignores that fact.
- var/gas_type
-
-/datum/bounty/item/engineering/gas/applies_to(obj/O)
- if(!..())
- return FALSE
- var/obj/item/tank/T = O
- var/datum/gas_mixture/our_mix = T.unsafe_return_air()
- if(!our_mix.getGroupGas(gas_type))
- return FALSE
- return our_mix.getGroupGas(gas_type) >= moles_required
-
-/datum/bounty/item/engineering/gas/nitrium_tank
- name = "Full Tank of Nitrium"
- description = "The non-human staff of Station 88 has been volunteered to test performance enhancing drugs. Ship them a tank full of Nitrium so they can get started. (20 Moles)"
-// gas_type = /datum/gas/nitrium
-
-/datum/bounty/item/engineering/gas/freon_tank
- name = "Full Tank of Freon"
- description = "The Supermatter of station 33 has started the delamination process. Deliver a tank of Freon gas to help them stop it! (20 Moles)"
- //gas_type = /datum/gas/freon
-
-/datum/bounty/item/engineering/gas/tritium_tank
- name = "Full Tank of Tritium"
- description = "Station 49 is looking to kickstart their research program. Ship them a tank full of Tritium. (20 Moles)"
- //gas_type = /datum/gas/tritium
-
-/datum/bounty/item/engineering/gas/hydrogen_tank
- name = "Full Tank of Hydrogen"
- description = "Our R&D department is working on the development of more efficient electrical batteries using hydrogen as a catalyst. Ship us a tank full of it. (20 Moles)"
- //gas_type = /datum/gas/hydrogen
-
-/datum/bounty/item/engineering/gas/zauker_tank
- name = "Full Tank of Zauker"
- description = "The main planet of \[REDACTED] has been chosen as testing grounds for the new weapon that uses Zauker gas. Ship us a tank full of it. (20 Moles)"
- reward = CARGO_CRATE_VALUE * 20
- //gas_type = /datum/gas/zauker
-
-/datum/bounty/item/engineering/emitter
- name = "Emitter"
- description = "We think there may be a defect in your station's emitter designs, based on the sheer number of delaminations your sector seems to see. Ship us one of yours."
- reward = CARGO_CRATE_VALUE * 5
- wanted_types = list(/obj/machinery/power/emitter = TRUE)
-
-/datum/bounty/item/engineering/hydro_tray
- name = "Hydroponics Tray"
- description = "The lab technicians are trying to figure out how to lower the power drain of hydroponics trays, but we fried our last one. Mind building one for us?"
- reward = CARGO_CRATE_VALUE * 4
- wanted_types = list(/obj/machinery/hydroponics/constructable = TRUE)
diff --git a/code/modules/cargo/bounties/item.dm b/code/modules/cargo/bounties/item.dm
deleted file mode 100644
index 1aa8f9bd4f05..000000000000
--- a/code/modules/cargo/bounties/item.dm
+++ /dev/null
@@ -1,32 +0,0 @@
-/datum/bounty/item
- ///How many items have to be shipped to complete the bounty
- var/required_count = 1
- ///How many items have been shipped for the bounty so far
- var/shipped_count = 0
- ///Types accepted|denied by the bounty. (including all subtypes, unless include_subtypes is set to FALSE)
- var/list/wanted_types
- ///Set to FALSE to make the bounty not accept subtypes of the wanted_types
- var/include_subtypes = TRUE
-
-/datum/bounty/item/New()
- ..()
- wanted_types = string_assoc_list(zebra_typecacheof(wanted_types, only_root_path = !include_subtypes))
-
-/datum/bounty/item/can_claim()
- return ..() && shipped_count >= required_count
-
-/datum/bounty/item/applies_to(obj/O)
- if(!is_type_in_typecache(O, wanted_types))
- return FALSE
- if(O.flags_1 & HOLOGRAM_1)
- return FALSE
- return shipped_count < required_count
-
-/datum/bounty/item/ship(obj/O)
- if(!applies_to(O))
- return
- if(istype(O,/obj/item/stack))
- var/obj/item/stack/O_is_a_stack = O
- shipped_count += O_is_a_stack.amount
- else
- shipped_count += 1
diff --git a/code/modules/cargo/bounties/mech.dm b/code/modules/cargo/bounties/mech.dm
deleted file mode 100644
index 9cacba95ff30..000000000000
--- a/code/modules/cargo/bounties/mech.dm
+++ /dev/null
@@ -1,36 +0,0 @@
-/datum/bounty/item/mech/New()
- ..()
- description = "Upper management has requested one [name] mech be sent as soon as possible. Ship it to receive a large payment."
-
-/datum/bounty/item/mech/ship(obj/O)
- if(!applies_to(O))
- return
- if(istype(O, /obj/vehicle/sealed/mecha))
- var/obj/vehicle/sealed/mecha/M = O
- M.wreckage = null // So the mech doesn't explode.
- ..()
-
-/datum/bounty/item/mech/ripleymk2
- name = "APLU MK-II \"Ripley\""
- reward = CARGO_CRATE_VALUE * 26
- wanted_types = list(/obj/vehicle/sealed/mecha/working/ripley/mk2 = TRUE)
-
-/datum/bounty/item/mech/clarke
- name = "Clarke"
- reward = CARGO_CRATE_VALUE * 32
- wanted_types = list(/obj/vehicle/sealed/mecha/working/clarke = TRUE)
-
-/datum/bounty/item/mech/odysseus
- name = "Odysseus"
- reward = CARGO_CRATE_VALUE * 22
- wanted_types = list(/obj/vehicle/sealed/mecha/medical/odysseus = TRUE)
-
-/datum/bounty/item/mech/gygax
- name = "Gygax"
- reward = CARGO_CRATE_VALUE * 56
- wanted_types = list(/obj/vehicle/sealed/mecha/combat/gygax = TRUE)
-
-/datum/bounty/item/mech/durand
- name = "Durand"
- reward = CARGO_CRATE_VALUE * 40
- wanted_types = list(/obj/vehicle/sealed/mecha/combat/durand = TRUE)
diff --git a/code/modules/cargo/bounties/medical.dm b/code/modules/cargo/bounties/medical.dm
deleted file mode 100644
index 84767efed23f..000000000000
--- a/code/modules/cargo/bounties/medical.dm
+++ /dev/null
@@ -1,92 +0,0 @@
-/datum/bounty/item/medical/heart
- name = "Heart"
- description = "Commander Johnson is in critical condition after suffering yet another heart attack. Doctors say he needs a new heart fast. Ship one, pronto! We'll take a better cybernetic one, if need be."
- reward = CARGO_CRATE_VALUE * 6
- wanted_types = list(
- /obj/item/organ/heart = TRUE,
- /obj/item/organ/heart/cybernetic = FALSE,
- /obj/item/organ/heart/cybernetic/tier2 = TRUE,
- /obj/item/organ/heart/cybernetic/tier3 = TRUE,
- )
-
-/datum/bounty/item/medical/lung
- name = "Lungs"
- description = "A recent explosion at Central Command has left multiple staff with punctured lungs. Ship spare lungs to be rewarded. We'll take a better cybernetic one, if need be."
- reward = CARGO_CRATE_VALUE * 20
- required_count = 3
- wanted_types = list(
- /obj/item/organ/lungs = TRUE,
- /obj/item/organ/lungs/cybernetic = FALSE,
- /obj/item/organ/lungs/cybernetic/tier2 = TRUE,
- /obj/item/organ/lungs/cybernetic/tier3 = TRUE,
- )
-
-/datum/bounty/item/medical/appendix
- name = "Appendix"
- description = "Chef Gibb of Central Command wants to prepare a meal using a very special delicacy: an appendix. If you ship one, he'll pay. We'll take a better cybernetic one, if need be."
- reward = CARGO_CRATE_VALUE * 5 //there are no synthetic appendixes
- wanted_types = list(/obj/item/organ/appendix = TRUE)
-
-/datum/bounty/item/medical/ears
- name = "Ears"
- description = "Multiple staff at Station 12 have been left deaf due to unauthorized clowning. Ship them new ears. "
- reward = CARGO_CRATE_VALUE * 10
- required_count = 3
- wanted_types = list(
- /obj/item/organ/ears = TRUE,
- /obj/item/organ/ears/cybernetic = FALSE,
- /obj/item/organ/ears/cybernetic/upgraded = TRUE,
- )
-
-/datum/bounty/item/medical/liver
- name = "Livers"
- description = "Multiple high-ranking CentCom diplomats have been hospitalized with liver failure after a recent meeting with Third Soviet Union ambassadors. Help us out, will you? We'll take better cybernetic ones, if need be."
- reward = CARGO_CRATE_VALUE * 10
- required_count = 3
- wanted_types = list(
- /obj/item/organ/liver = TRUE,
- /obj/item/organ/liver/cybernetic = FALSE,
- /obj/item/organ/liver/cybernetic/tier2 = TRUE,
- /obj/item/organ/liver/cybernetic/tier3 = TRUE,
- )
-
-/datum/bounty/item/medical/eye
- name = "Organic Eyes"
- description = "Station 5's Research Director Willem is requesting a few pairs of non-robotic eyes. Don't ask questions, just ship them."
- reward = CARGO_CRATE_VALUE * 20
- required_count = 3
- wanted_types = list(
- /obj/item/organ/eyes = TRUE,
- /obj/item/organ/eyes/robotic = FALSE,
- )
-
-/datum/bounty/item/medical/tongue
- name = "Tongues"
- description = "A recent attack by Mime extremists has left staff at Station 23 speechless. Ship some spare tongues."
- reward = CARGO_CRATE_VALUE * 20
- required_count = 3
- wanted_types = list(/obj/item/organ/tongue = TRUE)
-
-/datum/bounty/item/medical/cat_tail
- name = "Cat Tail"
- description = "Central Command has run out of heavy duty pipe cleaners. Can you ship over a cat tail to help us out?"
- reward = CARGO_CRATE_VALUE * 6
- wanted_types = list(/obj/item/organ/tail/cat = TRUE)
-
-/datum/bounty/item/medical/chainsaw
- name = "Chainsaw"
- description = "A CMO at CentCom is having trouble operating on golems. She requests one chainsaw, please."
- reward = CARGO_CRATE_VALUE * 5
- wanted_types = list(/obj/item/chainsaw = TRUE)
-
-/datum/bounty/item/medical/tail_whip //Like the cat tail bounties, with more processing.
- name = "Nine Tails whip"
- description = "Commander Jackson is looking for a fine addition to her exotic weapons collection. She will reward you handsomely for either a Cat o' Nine Tails."
- reward = CARGO_CRATE_VALUE * 8
- wanted_types = list(/obj/item/melee/chainofcommand/kitty = TRUE)
-
-/datum/bounty/item/medical/surgerytable
- name = "Operating Table"
- description = "After a recent influx of infected crew members recently, we've seen that masks just aren't cutting it alone. Silver Operating tables might just do the trick though, send us one to use."
- reward = CARGO_CRATE_VALUE * 6
- wanted_types = list(/obj/structure/table/optable = TRUE)
diff --git a/code/modules/cargo/bounties/reagent.dm b/code/modules/cargo/bounties/reagent.dm
deleted file mode 100644
index c4db3cba2c15..000000000000
--- a/code/modules/cargo/bounties/reagent.dm
+++ /dev/null
@@ -1,230 +0,0 @@
-/datum/bounty/reagent
- var/required_volume = 10
- var/shipped_volume = 0
- var/datum/reagent/wanted_reagent
-
-/datum/bounty/reagent/can_claim()
- return ..() && shipped_volume >= required_volume
-
-/datum/bounty/reagent/applies_to(obj/O)
- if(!istype(O, /obj/item/reagent_containers))
- return FALSE
- if(!O.reagents || !O.reagents.has_reagent(wanted_reagent.type))
- return FALSE
- if(O.flags_1 & HOLOGRAM_1)
- return FALSE
- return shipped_volume < required_volume
-
-/datum/bounty/reagent/ship(obj/O)
- if(!applies_to(O))
- return
- shipped_volume += O.reagents.get_reagent_amount(wanted_reagent.type)
- if(shipped_volume > required_volume)
- shipped_volume = required_volume
-
-/datum/bounty/reagent/simple_drink
- name = "Simple Drink"
- reward = CARGO_CRATE_VALUE * 3
-
-/datum/bounty/reagent/simple_drink/New()
- // Don't worry about making this comprehensive. It doesn't matter if some drinks are skipped.
- var/static/list/possible_reagents = list(\
- /datum/reagent/consumable/ethanol/antifreeze,\
- /datum/reagent/consumable/ethanol/andalusia,\
- /datum/reagent/consumable/tea/arnold_palmer,\
- /datum/reagent/consumable/ethanol/b52,\
- /datum/reagent/consumable/ethanol/bananahonk,\
- /datum/reagent/consumable/ethanol/beepsky_smash,\
- /datum/reagent/consumable/ethanol/between_the_sheets,\
- /datum/reagent/consumable/ethanol/bilk,\
- /datum/reagent/consumable/ethanol/black_russian,\
- /datum/reagent/consumable/ethanol/bloody_mary,\
- /datum/reagent/consumable/ethanol/martini,\
- /datum/reagent/consumable/ethanol/cuba_libre,\
- /datum/reagent/consumable/ethanol/eggnog,\
- /datum/reagent/consumable/ethanol/erikasurprise,\
- /datum/reagent/consumable/ethanol/ginfizz,\
- /datum/reagent/consumable/ethanol/gintonic,\
- /datum/reagent/consumable/ethanol/grappa,\
- /datum/reagent/consumable/ethanol/grog,\
- /datum/reagent/consumable/ethanol/hooch,\
- /datum/reagent/consumable/ethanol/iced_beer,\
- /datum/reagent/consumable/ethanol/irishcarbomb,\
- /datum/reagent/consumable/ethanol/manhattan,\
- /datum/reagent/consumable/ethanol/margarita,\
- /datum/reagent/consumable/ethanol/gargle_blaster,\
- /datum/reagent/consumable/ethanol/rum_coke,\
- /datum/reagent/consumable/ethanol/screwdrivercocktail,\
- /datum/reagent/consumable/ethanol/snowwhite,\
- /datum/reagent/consumable/soy_latte,\
- /datum/reagent/consumable/cafe_latte,\
- /datum/reagent/consumable/ethanol/syndicatebomb,\
- /datum/reagent/consumable/ethanol/tequila_sunrise,\
- /datum/reagent/consumable/ethanol/manly_dorf,\
- /datum/reagent/consumable/triple_citrus,\
- /datum/reagent/consumable/ethanol/vodkamartini,\
- /datum/reagent/consumable/ethanol/whiskeysoda,\
- /datum/reagent/consumable/ethanol/beer/green,\
- /datum/reagent/consumable/ethanol/demonsblood,\
- /datum/reagent/consumable/ethanol/crevice_spike,\
- /datum/reagent/consumable/ethanol/singulo,\
- /datum/reagent/consumable/ethanol/whiskey_sour)
-
- var/reagent_type = pick(possible_reagents)
- wanted_reagent = new reagent_type
- name = wanted_reagent.name
- description = "CentCom is thirsty! Send a shipment of [name] to CentCom to quench the company's thirst."
- reward += rand(0, 2) * 500
-
-/datum/bounty/reagent/complex_drink
- name = "Complex Drink"
- reward = CARGO_CRATE_VALUE * 8
-
-/datum/bounty/reagent/complex_drink/New()
- // Don't worry about making this comprehensive. It doesn't matter if some drinks are skipped.
- var/static/list/possible_reagents = list(\
- /datum/reagent/consumable/ethanol/atomicbomb,\
- /datum/reagent/consumable/ethanol/bacchus_blessing,\
- /datum/reagent/consumable/ethanol/booger,\
- /datum/reagent/consumable/ethanol/hippies_delight,\
- /datum/reagent/consumable/ethanol/drunkenblumpkin,\
- /datum/reagent/consumable/ethanol/fetching_fizz,\
- /datum/reagent/consumable/ethanol/goldschlager,\
- /datum/reagent/consumable/ethanol/manhattan_proj,\
- /datum/reagent/consumable/ethanol/narsour,\
- /datum/reagent/consumable/ethanol/neurotoxin,\
- /datum/reagent/consumable/ethanol/patron,\
- /datum/reagent/consumable/ethanol/quadruple_sec,\
- /datum/reagent/consumable/bluecherryshake,\
- /datum/reagent/consumable/doctor_delight,\
- /datum/reagent/consumable/ethanol/silencer,\
- /datum/reagent/consumable/ethanol/peppermint_patty,\
- /datum/reagent/consumable/ethanol/aloe,\
- /datum/reagent/consumable/pumpkin_latte)
-
- var/reagent_type = pick(possible_reagents)
- wanted_reagent = new reagent_type
- name = wanted_reagent.name
- description = "CentCom is offering a reward for talented mixologists. Ship a container of [name] to claim the prize."
- reward += rand(0, 4) * 500
-
-/datum/bounty/reagent/chemical_simple
- name = "Simple Chemical"
- reward = CARGO_CRATE_VALUE * 8
- required_volume = 30
-
-/datum/bounty/reagent/chemical_simple/New()
- // Chemicals that can be mixed by a single skilled Chemist.
- var/static/list/possible_reagents = list(\
- /datum/reagent/medicine/leporazine,\
- /datum/reagent/medicine/clonexadone,\
- /datum/reagent/medicine/ephedrine,\
- /datum/reagent/medicine/diphenhydramine,
- /datum/reagent/drug/space_drugs,
- /datum/reagent/drug/blastoff,
- /datum/reagent/gunpowder,
- /datum/reagent/napalm,
- /datum/reagent/firefighting_foam,
- /datum/reagent/consumable/mayonnaise,
- /datum/reagent/toxin/itching_powder,
- /datum/reagent/toxin/cyanide,
- /datum/reagent/toxin/heparin,
- /datum/reagent/medicine/atropine,
- /datum/reagent/drug/aranesp,
- /datum/reagent/drug/krokodil,
- /datum/reagent/drug/methamphetamine,
- /datum/reagent/toxin/anacea,
- )
-
- var/reagent_type = pick(possible_reagents)
- wanted_reagent = new reagent_type
- name = wanted_reagent.name
- description = "CentCom is in desperate need of the chemical [name]. Ship a container of it to be rewarded."
- reward += rand(0, 4) * 500 //4000 to 6000 credits
-
-/datum/bounty/reagent/chemical_complex
- name = "Rare Chemical"
- reward = CARGO_CRATE_VALUE * 12
- required_volume = 20
-
-/datum/bounty/reagent/chemical_complex/New()
- // Reagents that require interaction with multiple departments or are a pain to mix. Lower required_volume since acquiring 30u of some is unrealistic
- var/static/list/possible_reagents = list(\
- /datum/reagent/medicine/cryoxadone,
- /datum/reagent/medicine/regen_jelly,
- /datum/reagent/drug/bath_salts,
- /datum/reagent/hair_dye,
- /datum/reagent/consumable/honey,
- /datum/reagent/consumable/frostoil,
- /datum/reagent/toxin/slimejelly,
- /datum/reagent/toxin/mimesbane,
- /datum/reagent/medicine/strange_reagent,
- /datum/reagent/nitroglycerin,
- /datum/reagent/toxin/zombiepowder,
- /datum/reagent/toxin/ghoulpowder,
- /datum/reagent/mulligan
- )
-
- var/reagent_type = pick(possible_reagents)
- wanted_reagent = new reagent_type
- name = wanted_reagent.name
- description = "CentCom is paying premium for the chemical [name]. Ship a container of it to be rewarded."
- reward += rand(0, 5) * 750 //6000 to 9750 credits
-
-/datum/bounty/pill
- /// quantity of the pills needed, this value acts as minimum, gets randomized on new()
- var/required_ammount = 80
- /// counter for pills sent
- var/shipped_ammount = 0
- /// reagent requested
- var/datum/reagent/wanted_reagent
- /// minimum volume of chemical needed, gets randomized on new()
- var/wanted_vol = 30
-
-/datum/bounty/pill/can_claim()
- return ..() && shipped_ammount >= required_ammount
-
-/datum/bounty/pill/applies_to(obj/O)
- if(!istype(O, /obj/item/reagent_containers/pill))
- return FALSE
- if(O?.reagents.get_reagent_amount(wanted_reagent.type) >= wanted_vol)
- return TRUE
- return FALSE
-
-/datum/bounty/pill/ship(obj/O)
- if(!applies_to(O))
- return
- shipped_ammount += 1
- if(shipped_ammount > required_ammount)
- shipped_ammount = required_ammount
-
-/datum/bounty/pill/simple_pill
- name = "Simple Pill"
- reward = CARGO_CRATE_VALUE * 20
-
-/datum/bounty/pill/simple_pill/New()
- //reagent that are possible to be chem factory'd
- var/static/list/possible_reagents = list(
- /datum/reagent/medicine/spaceacillin,
- /datum/reagent/medicine/synthflesh,
- /datum/reagent/medicine/dexalin,
- /datum/reagent/medicine/atropine,
- /datum/reagent/medicine/cryoxadone,
- /datum/reagent/medicine/dexalin,
- /datum/reagent/medicine/dermaline,
- /datum/reagent/medicine/meralyne,
- /datum/reagent/drug/methamphetamine,
- /datum/reagent/nitrous_oxide,
- /datum/reagent/barbers_aid,
- /datum/reagent/flash_powder,
- /datum/reagent/phlogiston,
- /datum/reagent/firefighting_foam
- )
-
- var/datum/reagent/reagent_type = pick(possible_reagents)
- wanted_reagent = new reagent_type
- name = "[wanted_reagent.name] pills"
- required_ammount += rand(1,60)
- wanted_vol += rand(1,20)
- description = "CentCom requires [required_ammount] of [name] containing at least [wanted_vol] each. Ship a container of it to be rewarded."
- reward += rand(1, 5) * (CARGO_CRATE_VALUE * 6)
diff --git a/code/modules/cargo/bounties/security.dm b/code/modules/cargo/bounties/security.dm
deleted file mode 100644
index bce1fcbe210e..000000000000
--- a/code/modules/cargo/bounties/security.dm
+++ /dev/null
@@ -1,75 +0,0 @@
-/datum/bounty/item/security/recharger
- name = "Rechargers"
- description = "The Mars Executive Outcomes military academy is conducting marksmanship exercises. They request that rechargers be shipped."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 3
- wanted_types = list(/obj/machinery/recharger = TRUE)
-
-/datum/bounty/item/security/pepperspray
- name = "Pepperspray"
- description = "We've been having a bad run of riots on Space Station 76. We could use some new pepperspray cans."
- reward = CARGO_CRATE_VALUE * 6
- required_count = 4
- wanted_types = list(/obj/item/reagent_containers/spray/pepper = TRUE)
-
-/datum/bounty/item/security/prison_clothes
- name = "Prison Uniforms"
- description = "Terragov has been unable to source any new prisoner uniforms, so if you have any spares, we'll take them off your hands."
- reward = CARGO_CRATE_VALUE * 4
- required_count = 4
- wanted_types = list(/obj/item/clothing/under/rank/prisoner = TRUE)
-
-/datum/bounty/item/security/plates
- name = "License Plates"
- description = "As a result of a bad clown car crash, we could use an advance on some of your prisoner's license plates."
- reward = CARGO_CRATE_VALUE * 2
- required_count = 10
- wanted_types = list(/obj/item/stack/license_plates/filled = TRUE)
-
-/datum/bounty/item/security/earmuffs
- name = "Earmuffs"
- description = "Central Command is getting tired of your station's messages. They've ordered that you ship some earmuffs to lessen the annoyance."
- reward = CARGO_CRATE_VALUE * 2
- wanted_types = list(/obj/item/clothing/ears/earmuffs = TRUE)
-
-/datum/bounty/item/security/handcuffs
- name = "Handcuffs"
- description = "A large influx of escaped convicts have arrived at Central Command. Now is the perfect time to ship out spare handcuffs (or restraints)."
- reward = CARGO_CRATE_VALUE * 2
- required_count = 5
- wanted_types = list(/obj/item/restraints/handcuffs = TRUE)
-
-
-///Bounties that require you to perform documentation and inspection of your department to send to centcom.
-/datum/bounty/item/security/paperwork
- name = "Routine Security Inspection"
- description = "Perform a routine security inspection using an N-spect scanner on the following station area:"
- required_count = 1
- wanted_types = list(/obj/item/paper/report = TRUE)
- reward = CARGO_CRATE_VALUE * 5
- var/area/demanded_area
-
-/datum/bounty/item/security/paperwork/New()
- ///list of areas for security to choose from to perform an inspection.
- var/static/list/possible_areas = list(\
- /area/station/maintenance,\
- /area/station/commons,\
- /area/station/service,\
- /area/station/hallway/primary,\
- /area/station/security/office,\
- /area/station/security/prison,\
- /area/station/security/range,\
- /area/station/security/checkpoint,\
- /area/station/security/interrogation)
- demanded_area = pick(possible_areas)
- name = name + ": [initial(demanded_area.name)]"
- description = initial(description) + " [initial(demanded_area.name)]"
-
-/datum/bounty/item/security/paperwork/applies_to(obj/O)
- . = ..()
- if(!istype(O, /obj/item/paper/report))
- return FALSE
- var/obj/item/paper/report/slip = O
- if(istype(slip.scanned_area, demanded_area))
- return TRUE
- return FALSE
diff --git a/code/modules/cargo/bounties/slime.dm b/code/modules/cargo/bounties/slime.dm
deleted file mode 100644
index b30588d8ae97..000000000000
--- a/code/modules/cargo/bounties/slime.dm
+++ /dev/null
@@ -1,35 +0,0 @@
-/datum/bounty/item/slime
- reward = CARGO_CRATE_VALUE * 6
-
-/datum/bounty/item/slime/New()
- ..()
- description = "Nanotrasen's science lead is hunting for the rare and exotic [name]. A bounty has been offered for finding it."
- reward += rand(0, 4) * 500
-
-/datum/bounty/item/slime/green
- name = "Green Slime Extract"
- wanted_types = list(/obj/item/slime_extract/green = TRUE)
-
-/datum/bounty/item/slime/pink
- name = "Pink Slime Extract"
- wanted_types = list(/obj/item/slime_extract/pink = TRUE)
-
-/datum/bounty/item/slime/gold
- name = "Gold Slime Extract"
- wanted_types = list(/obj/item/slime_extract/gold = TRUE)
-
-/datum/bounty/item/slime/oil
- name = "Oil Slime Extract"
- wanted_types = list(/obj/item/slime_extract/oil = TRUE)
-
-/datum/bounty/item/slime/black
- name = "Black Slime Extract"
- wanted_types = list(/obj/item/slime_extract/black = TRUE)
-
-/datum/bounty/item/slime/lightpink
- name = "Light Pink Slime Extract"
- wanted_types = list(/obj/item/slime_extract/lightpink = TRUE)
-
-/datum/bounty/item/slime/rainbow
- name = "Rainbow Slime Extract"
- wanted_types = list(/obj/item/slime_extract/rainbow = TRUE)
diff --git a/code/modules/cargo/bounties/special.dm b/code/modules/cargo/bounties/special.dm
deleted file mode 100644
index 93fd8208dd89..000000000000
--- a/code/modules/cargo/bounties/special.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-/datum/bounty/item/alien_organs
- name = "Alien Organs"
- description = "Nanotrasen is interested in studying Xenomorph biology. Ship a set of organs to be thoroughly compensated."
- reward = CARGO_CRATE_VALUE * 50
- required_count = 3
- wanted_types = list(
- /obj/item/organ/brain/alien = TRUE,
- /obj/item/organ/alien = TRUE,
- /obj/item/organ/body_egg/alien_embryo = TRUE,
- /obj/item/organ/liver/alien = TRUE,
- /obj/item/organ/tongue/alien = TRUE,
- /obj/item/organ/eyes/night_vision/alien = TRUE,
- )
-
-/datum/bounty/item/syndicate_documents
- name = "Syndicate Documents"
- description = "Intel regarding the syndicate is highly prized at CentCom. If you find syndicate documents, ship them. You could save lives."
- reward = CARGO_CRATE_VALUE * 30
- wanted_types = list(
- /obj/item/documents/syndicate = TRUE,
- /obj/item/documents/photocopy = TRUE,
- )
-
-/datum/bounty/item/syndicate_documents/applies_to(obj/O)
- if(!..())
- return FALSE
- if(istype(O, /obj/item/documents/photocopy))
- var/obj/item/documents/photocopy/Copy = O
- return (Copy.copy_type && ispath(Copy.copy_type, /obj/item/documents/syndicate))
- return TRUE
-
-/datum/bounty/item/trash
- name = "Trash"
- description = "Recently a group of janitors have run out of trash to clean up, without any trash CentCom wants to fire them to cut costs. Send a shipment of trash to keep them employed, and they'll give you a small compensation."
- reward = CARGO_CRATE_VALUE * 2
- required_count = 10
- wanted_types = list(/obj/item/trash = TRUE)
diff --git a/code/modules/cargo/bounties/virus.dm b/code/modules/cargo/bounties/virus.dm
deleted file mode 100644
index daa41fbea811..000000000000
--- a/code/modules/cargo/bounties/virus.dm
+++ /dev/null
@@ -1,72 +0,0 @@
-/datum/bounty/virus
- reward = CARGO_CRATE_VALUE * 10
- var/shipped = FALSE
- var/stat_value = 0
- var/stat_name = ""
-
-/datum/bounty/virus/New()
- ..()
- stat_value = rand(4, 11)
- if(rand(3) == 1)
- stat_value *= -1
- name = "Virus ([stat_name] of [stat_value])"
- description = "Nanotrasen is interested in a virus with a [stat_name] stat of exactly [stat_value]. Central Command will pay handsomely for such a virus."
- reward += rand(0, 4) * CARGO_CRATE_VALUE
-
-/datum/bounty/virus/can_claim()
- return ..() && shipped
-
-/datum/bounty/virus/applies_to(obj/O)
- if(shipped)
- return FALSE
- if(O.flags_1 & HOLOGRAM_1)
- return FALSE
- if(!istype(O, /obj/item/reagent_containers || !O.reagents || !O.reagents.reagent_list))
- return FALSE
- var/datum/reagent/blood/B = locate() in O.reagents.reagent_list
- if(!B)
- return FALSE
- for(var/V in B.get_diseases())
- if(!istype(V, /datum/disease/advance))
- continue
- if(accepts_virus(V))
- return TRUE
- return FALSE
-
-/datum/bounty/virus/ship(obj/O)
- if(!applies_to(O))
- return
- shipped = TRUE
-
-
-/datum/bounty/virus/proc/accepts_virus(V)
- return TRUE
-
-/datum/bounty/virus/resistance
- stat_name = "resistance"
-
-/datum/bounty/virus/resistance/accepts_virus(V)
- var/datum/disease/advance/A = V
- return A.totalResistance() == stat_value
-
-/datum/bounty/virus/stage_speed
- stat_name = "stage speed"
-
-/datum/bounty/virus/stage_speed/accepts_virus(V)
- var/datum/disease/advance/A = V
- return A.totalStageSpeed() == stat_value
-
-/datum/bounty/virus/stealth
- stat_name = "stealth"
-
-/datum/bounty/virus/stealth/accepts_virus(V)
- var/datum/disease/advance/A = V
- return A.totalStealth() == stat_value
-
-/datum/bounty/virus/transmit
- stat_name = "transmissible"
-
-/datum/bounty/virus/transmit/accepts_virus(V)
- var/datum/disease/advance/A = V
- return A.totalTransmittable() == stat_value
-
diff --git a/code/modules/cargo/bounty.dm b/code/modules/cargo/bounty.dm
deleted file mode 100644
index 480cd6578cc5..000000000000
--- a/code/modules/cargo/bounty.dm
+++ /dev/null
@@ -1,74 +0,0 @@
-/datum/bounty
- var/name
- var/description
- var/reward = 1000 // In credits.
- var/claimed = FALSE
- var/high_priority = FALSE
-
-/datum/bounty/proc/can_claim()
- return !claimed
-
-/// Called when the claim button is clicked. Override to provide fancy rewards.
-/datum/bounty/proc/claim()
- if(can_claim())
- var/datum/bank_account/D = SSeconomy.station_master
- if(D)
- D.adjust_money(reward * SSeconomy.bounty_modifier)
- claimed = TRUE
-
-/// If an item sent in the cargo shuttle can satisfy the bounty.
-/datum/bounty/proc/applies_to(obj/O)
- return FALSE
-
-/// Called when an object is shipped on the cargo shuttle.
-/datum/bounty/proc/ship(obj/O)
- return
-
-/** Returns a new bounty of random type, but does not add it to GLOB.bounties_list.
- *
- * *Guided determines what specific catagory of bounty should be chosen.
- */
-/proc/random_bounty(guided = 0)
- var/bounty_num
- if(guided && (guided != CIV_JOB_RANDOM))
- bounty_num = guided
- else
- bounty_num = rand(1,11)
- switch(bounty_num)
- if(CIV_JOB_BASIC)
- var/subtype = pick(subtypesof(/datum/bounty/item/assistant))
- return new subtype
- if(CIV_JOB_ROBO)
- var/subtype = pick(subtypesof(/datum/bounty/item/mech))
- return new subtype
- if(CIV_JOB_CHEF)
- var/subtype = pick(subtypesof(/datum/bounty/item/chef))
- return new subtype
- if(CIV_JOB_SEC)
- var/subtype = pick(subtypesof(/datum/bounty/item/security))
- return new subtype
- if(CIV_JOB_DRINK)
- if(rand(2) == 1)
- return new /datum/bounty/reagent/simple_drink
- return new /datum/bounty/reagent/complex_drink
- if(CIV_JOB_CHEM)
- if(rand(2) == 1)
- return new /datum/bounty/reagent/chemical_simple
- return new /datum/bounty/reagent/chemical_complex
- if(CIV_JOB_VIRO)
- var/subtype = pick(subtypesof(/datum/bounty/virus))
- return new subtype
- if(CIV_JOB_ENG)
- var/subtype = pick(subtypesof(/datum/bounty/item/engineering))
- return new subtype
- if(CIV_JOB_MED)
- var/subtype = pick(subtypesof(/datum/bounty/item/medical))
- return new subtype
- if(CIV_JOB_GROW)
- var/subtype = pick(subtypesof(/datum/bounty/item/botany))
- return new subtype
-
- stack_trace("Tried to return a null bounty! Replacing with assistant.")
- var/subtype = pick(subtypesof(/datum/bounty/item/assistant))
- return new subtype
-
diff --git a/code/modules/cargo/export_scanner.dm b/code/modules/cargo/export_scanner.dm
index 26d0422c7f8e..988e1b4680ea 100644
--- a/code/modules/cargo/export_scanner.dm
+++ b/code/modules/cargo/export_scanner.dm
@@ -24,27 +24,3 @@
to_chat(user, span_notice("Scanned [O], value: [price] credits[O.contents.len ? " (contents included)" : ""]."))
else
to_chat(user, span_warning("Scanned [O], no export value."))
-
- if(ishuman(user))
- var/mob/living/carbon/human/scan_human = user
- if(istype(O, /obj/item/bounty_cube))
- var/obj/item/bounty_cube/cube = O
- var/datum/bank_account/scanner_account = scan_human.get_bank_account()
-
- if(!istype(get_area(cube), /area/shuttle/supply))
- to_chat(user, span_warning("Shuttle placement not detected. Handling tip not registered."))
-
- else if(cube.bounty_handler_account)
- to_chat(user, span_warning("Bank account for handling tip already registered!"))
-
- else if(scanner_account)
- cube.AddComponent(/datum/component/pricetag, scanner_account, cube.handler_tip, FALSE)
-
- cube.bounty_handler_account = scanner_account
- cube.bounty_handler_account.bank_card_talk("Bank account for [price ? "[price * cube.handler_tip] credit " : ""]handling tip successfully registered.")
-
- if(cube.bounty_holder_account != cube.bounty_handler_account) //No need to send a tracking update to the person scanning it
- cube.bounty_holder_account.bank_card_talk("[cube] was scanned in \the [get_area(cube)] by [scan_human] ([scan_human.job]).")
-
- else
- to_chat(user, span_warning("Bank account not detected. Handling tip not registered."))
diff --git a/code/modules/cargo/exports/civilain_bounty.dm b/code/modules/cargo/exports/civilain_bounty.dm
deleted file mode 100644
index 05241e0ab755..000000000000
--- a/code/modules/cargo/exports/civilain_bounty.dm
+++ /dev/null
@@ -1,8 +0,0 @@
-/datum/export/bounty_box
- cost = 1
- k_elasticity = 0 //Bounties are non-elastic funds.
- unit_name = "completed bounty cube"
- export_types = list(/obj/item/bounty_cube)
-
-/datum/export/bounty_box/get_cost(obj/item/bounty_cube/cube, apply_elastic)
- return cube.bounty_value + (cube.bounty_value * cube.speed_bonus)
diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm
index 89426e9c7b29..2d55cebd43bf 100644
--- a/code/modules/cargo/order.dm
+++ b/code/modules/cargo/order.dm
@@ -1,5 +1,7 @@
/// The chance for a manifest or crate to be created with errors
-#define MANIFEST_ERROR_CHANCE 5
+#define MANIFEST_BAD_CONTENTS_CHANCE 5
+#define MANIFEST_BAD_NAME_CHANCE 5
+#define MANIFEST_MISSING_CONTENTS_CHANCE 7
// MANIFEST BITFLAGS
/// Determines if the station name will be incorrect on the manifest
@@ -19,13 +21,15 @@
order_id = id
order_cost = cost
- if(prob(MANIFEST_ERROR_CHANCE))
+ if(prob(MANIFEST_BAD_NAME_CHANCE))
errors |= MANIFEST_ERROR_NAME
investigate_log("Supply order #[order_id] generated a manifest with an incorrect station name.", INVESTIGATE_CARGO)
- if(prob(MANIFEST_ERROR_CHANCE))
+
+ if(prob(MANIFEST_BAD_CONTENTS_CHANCE))
errors |= MANIFEST_ERROR_CONTENTS
investigate_log("Supply order #[order_id] generated a manifest missing listed contents.", INVESTIGATE_CARGO)
- if(prob(MANIFEST_ERROR_CHANCE))
+
+ if(prob(MANIFEST_MISSING_CONTENTS_CHANCE))
errors |= MANIFEST_ERROR_ITEM
investigate_log("Supply order #[order_id] generated with incorrect contents shipped.", INVESTIGATE_CARGO)
@@ -95,22 +99,26 @@
P.info += "Item: [packname]
"
P.info += "Contents:
"
P.info += ""
- for(var/atom/movable/AM in container.contents - P)
- if((P.errors & MANIFEST_ERROR_CONTENTS))
+
+ for(var/atom/movable/AM as anything in container.contents)
+ if((P.errors & MANIFEST_ERROR_CONTENTS)) // Double or nothing. Literally.
if(prob(50))
P.info += "- [AM.name]
"
else
continue
+
P.info += "- [AM.name]
"
+
P.info += "
"
P.info += "Stamp below to confirm receipt of goods:
"
if(P.errors & MANIFEST_ERROR_ITEM)
- if(istype(container, /obj/structure/closet/crate/secure) || istype(container, /obj/structure/closet/crate/large))
+ if(!pack.can_be_missing_contents)
P.errors &= ~MANIFEST_ERROR_ITEM
else
- var/lost = max(round(container.contents.len / 10), 1)
- while(--lost >= 0)
+ var/lost = max(ceil(container.contents.len * (rand(5, 15) / 100)), 1) // Missing between 5% and 15%
+ while(lost >= 1)
+ lost--
qdel(pick(container.contents))
P.update_appearance()
@@ -120,8 +128,6 @@
var/obj/structure/closet/crate/C = container
C.manifest = P
C.update_appearance()
- else
- container.contents += P
return P
@@ -143,7 +149,9 @@
generateManifest(miscbox, misc_own, "", misc_cost)
return
-#undef MANIFEST_ERROR_CHANCE
#undef MANIFEST_ERROR_NAME
#undef MANIFEST_ERROR_CONTENTS
#undef MANIFEST_ERROR_ITEM
+#undef MANIFEST_BAD_CONTENTS_CHANCE
+#undef MANIFEST_BAD_NAME_CHANCE
+#undef MANIFEST_MISSING_CONTENTS_CHANCE
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 0b69806b92a6..0ce51cf120d5 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -8,17 +8,23 @@
var/access = FALSE
var/access_view = FALSE
var/access_any = FALSE
+
var/list/contains = null
var/crate_name = "crate"
var/id
var/desc = ""//no desc by default
var/crate_type = /obj/structure/closet/crate
+
+ /// If TRUE, can spawn with missing contents due to MANIFEST_ERROR_ITEM occuring.
+ var/can_be_missing_contents = TRUE
var/dangerous = FALSE // Should we message admins?
var/special = FALSE //Event/Station Goals/Admin enabled packs
var/special_enabled = FALSE
+
var/DropPodOnly = FALSE //only usable by the Bluespace Drop Pod via the express cargo console
var/special_pod //If this pack comes shipped in a specific pod when launched from the express console
var/admin_spawned = FALSE
+
var/goody = FALSE //Goodies can only be purchased by private accounts and can have coupons apply to them. They also come in a lockbox instead of a full crate, so the 700 min doesn't apply
/datum/supply_pack/New()
diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm
index 392cbf382942..536ecac58b0d 100644
--- a/code/modules/clothing/neck/_neck.dm
+++ b/code/modules/clothing/neck/_neck.dm
@@ -235,7 +235,7 @@
var/true_price = round(price*profit_scaling)
to_chat(user, span_notice("[selling ? "Sold" : "Getting the price of"] [I], value: [true_price] credits[I.contents.len ? " (exportable contents included)" : ""].[profit_scaling < 1 && selling ? "[round(price-true_price)] credit\s taken as processing fee\s." : ""]"))
if(selling)
- new /obj/item/holochip(get_turf(user),true_price)
+ SSeconomy.spawn_cash_for_amount(true_price, get_turf(user))
else
to_chat(user, span_warning("There is no export value for [I] or any items within it."))
diff --git a/code/modules/economy/account.dm b/code/modules/economy/account.dm
index a8d7c747afb6..2ed534e0c04b 100644
--- a/code/modules/economy/account.dm
+++ b/code/modules/economy/account.dm
@@ -11,20 +11,19 @@
var/datum/job/account_job
///List of the physical ID card objects that are associated with this bank_account
var/list/bank_cards = list()
- ///Should this ID be added to the global list of accounts? If true, will be subject to station-bound economy effects as well as income.
- var/add_to_accounts = TRUE
+
///The Unique ID number code associated with the owner's bank account, assigned at round start.
var/account_id
- ///Is there a CRAB 17 on the station draining funds? Prevents manual fund transfer. pink levels are rising
- var/being_dumped = FALSE
- ///Reference to the current civilian bounty that the account is working on.
- var/datum/bounty/civilian_bounty
- ///If player is currently picking a civilian bounty to do, these options are held here to prevent soft-resetting through the UI.
- var/list/datum/bounty/bounties
+ /// A randomly generated 5-digit pin to access the bank account. This is stored as a string!
+ var/account_pin
+
///Can this account be replaced? Set to true for default IDs not recognized by the station.
var/replaceable = FALSE
- ///Cooldown timer on replacing a civilain bounty. Bounties can only be replaced once every 5 minutes.
- COOLDOWN_DECLARE(bounty_timer)
+ ///Should this ID be added to the global list of accounts? If true, will be subject to station-bound economy effects as well as income.
+ var/add_to_accounts = TRUE
+
+ ///Is there a CRAB 17 on the station draining funds? Prevents manual fund transfer. pink levels are rising
+ var/being_dumped = FALSE
/datum/bank_account/New(newname, job, modifier = 1, player_account = TRUE)
account_holder = newname
@@ -33,6 +32,9 @@
add_to_accounts = player_account
setup_unique_account_id()
+ for(var/i in 1 to 5)
+ account_pin = "[account_pin][rand(0, 9)]"
+
/datum/bank_account/Destroy()
if(add_to_accounts)
SSeconomy.bank_accounts_by_id -= "[account_id]"
@@ -122,7 +124,9 @@
/datum/bank_account/proc/payday(amt_of_paychecks = 1, free = FALSE)
if(!account_job)
return
+
var/money_to_transfer = round(account_job.paycheck * payday_modifier * amt_of_paychecks)
+
if(free)
adjust_money(money_to_transfer)
SSblackbox.record_feedback("amount", "free_income", money_to_transfer)
@@ -131,9 +135,7 @@
else
var/datum/bank_account/D = SSeconomy.station_master
if(D && transfer_money(D, money_to_transfer))
- bank_card_talk("Payday processed, account now holds [account_balance] cr.")
return TRUE
- bank_card_talk("ERROR: Payday aborted, unable to contact departmental account.")
return FALSE
/**
@@ -175,45 +177,6 @@
M.playsound_local(get_turf(sound_atom), 'sound/machines/twobeep_high.ogg', 50, TRUE)
to_chat(M, "[icon2html(icon_source, M)] [span_notice("[message]")]")
-/**
- * Returns a string with the civilian bounty's description on it.
- */
-/datum/bank_account/proc/bounty_text()
- if(!civilian_bounty)
- return FALSE
- return civilian_bounty.description
-
-
-/**
- * Returns the required item count, or required chemical units required to submit a bounty.
- */
-/datum/bank_account/proc/bounty_num()
- if(!civilian_bounty)
- return FALSE
- if(istype(civilian_bounty, /datum/bounty/item))
- var/datum/bounty/item/item = civilian_bounty
- return "[item.shipped_count]/[item.required_count]"
- if(istype(civilian_bounty, /datum/bounty/reagent))
- var/datum/bounty/reagent/chemical = civilian_bounty
- return "[chemical.shipped_volume]/[chemical.required_volume] u"
- if(istype(civilian_bounty, /datum/bounty/virus))
- return "At least 1u"
-
-/**
- * Produces the value of the account's civilian bounty reward, if able.
- */
-/datum/bank_account/proc/bounty_value()
- if(!civilian_bounty)
- return FALSE
- return civilian_bounty.reward
-
-/**
- * Performs house-cleaning on variables when a civilian bounty is replaced, or, when a bounty is claimed.
- */
-/datum/bank_account/proc/reset_bounty()
- civilian_bounty = null
- COOLDOWN_RESET(src, bounty_timer)
-
/datum/bank_account/department
account_holder = "Guild Credit Agency"
var/department_id = "REPLACE_ME"
diff --git a/code/modules/economy/holopay.dm b/code/modules/economy/holopay.dm
deleted file mode 100644
index 845c2204b2e4..000000000000
--- a/code/modules/economy/holopay.dm
+++ /dev/null
@@ -1,292 +0,0 @@
-/obj/structure/holopay
- name = "holographic pay stand"
- desc = "an unregistered pay stand"
- icon = 'icons/obj/economy.dmi'
- icon_state = "card_scanner"
- alpha = 150
- anchored = TRUE
- armor = list(BLUNT = 0, PUNCTURE = 50, SLASH = 0, LASER = 50, ENERGY = 50, BOMB = 0, BIO = 0, FIRE = 20, ACID = 20)
- max_integrity = 15
- layer = FLY_LAYER
- /// ID linked to the holopay
- var/obj/item/card/id/linked_card
- /// Max range at which the hologram can be projected before it deletes
- var/max_holo_range = 4
- /// The holopay shop icon displayed in the UI
- var/shop_logo = "donate"
- /// Replaces the "pay whatever" functionality with a set amount when non-zero.
- var/force_fee = 0
-
-/obj/structure/holopay/examine(mob/user)
- . = ..()
- if(force_fee)
- . += span_boldnotice("This holopay forces a payment of [force_fee] credit\s per swipe instead of a variable amount.")
-
-/obj/structure/holopay/Initialize(mapload)
- . = ..()
- register_context()
-
-/obj/structure/holopay/add_context(atom/source, list/context, obj/item/held_item, mob/user)
- . = ..()
-
- if(istype(held_item, /obj/item/card/id))
- context[SCREENTIP_CONTEXT_LMB] = "Pay"
- var/obj/item/card/id/held_id = held_item
- if(held_id.my_store && held_id.my_store == src)
- context[SCREENTIP_CONTEXT_RMB] = "Dissipate pay stand"
- return CONTEXTUAL_SCREENTIP_SET
-
- else if(istype(held_item, /obj/item/holochip))
- context[SCREENTIP_CONTEXT_LMB] = "Pay"
- return CONTEXTUAL_SCREENTIP_SET
-
-/obj/structure/holopay/attack_hand(mob/living/user, list/modifiers)
- . = ..()
- if(.)
- return
- if(!user.combat_mode)
- ui_interact(user)
- return .
- user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
- user.changeNext_move(CLICK_CD_MELEE)
- take_damage(5, BRUTE, BLUNT, 1)
-
-/obj/structure/holopay/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
- switch(damage_type)
- if(BRUTE)
- playsound(loc, 'sound/weapons/egloves.ogg', 80, TRUE)
- if(BURN)
- playsound(loc, 'sound/weapons/egloves.ogg', 80, TRUE)
-
-/obj/structure/holopay/deconstruct()
- dissipate()
- return ..()
-
-/obj/structure/holopay/Destroy()
- linked_card?.my_store = null
- linked_card = null
- return ..()
-
-/obj/structure/holopay/attackby(obj/item/held_item, mob/item_holder, params)
- var/mob/living/user = item_holder
- if(!isliving(user))
- return ..()
- /// Users can pay with an ID to skip the UI
- if(istype(held_item, /obj/item/card/id))
- if(force_fee && tgui_alert(item_holder, "This holopay has a [force_fee] cr fee. Confirm?", "Holopay Fee", list("Pay", "Cancel")) != "Pay")
- return TRUE
- process_payment(user)
- return TRUE
- /// Users can also pay by holochip
- if(istype(held_item, /obj/item/holochip))
- /// Account checks
- var/obj/item/holochip/chip = held_item
- if(!chip.credits)
- balloon_alert(user, "holochip is empty")
- to_chat(user, span_warning("There doesn't seem to be any credits here."))
- return FALSE
- /// Charges force fee or uses pay what you want
- var/cash_deposit = force_fee || tgui_input_number(user, "How much? (Max: [chip.credits])", "Patronage", max_value = chip.credits)
- /// Exit sanity checks
- if(!cash_deposit)
- return TRUE
- if(QDELETED(held_item) || QDELETED(user) || QDELETED(src) || !user.canUseTopic(src, USE_CLOSE|USE_IGNORE_TK))
- return FALSE
- if(!chip.spend(cash_deposit, FALSE))
- balloon_alert(user, "insufficient credits")
- to_chat(user, span_warning("You don't have enough credits to pay with this chip."))
- return FALSE
- /// Success: Alert buyer
- alert_buyer(user, cash_deposit)
- return TRUE
- /// Throws errors if they try to use space cash
- if(istype(held_item, /obj/item/stack/spacecash))
- to_chat(user, "What is this, the 2000s? We only take card here.")
- return TRUE
- if(istype(held_item, /obj/item/coin))
- to_chat(user, "What is this, the 1800s? We only take card here.")
- return TRUE
- return ..()
-
-/obj/structure/holopay/attackby_secondary(obj/item/weapon, mob/user, params)
- /// Can kill it by right-clicking with ID because it seems useful and intuitive, to me, at least
- if(!istype(weapon, /obj/item/card/id))
- return ..()
- var/obj/item/card/id/attacking_id = weapon
- if(!attacking_id.my_store || attacking_id.my_store != src)
- return ..()
- dissipate()
- return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
-
-/obj/structure/holopay/ui_interact(mob/user, datum/tgui/ui)
- . = ..()
- if(.)
- return FALSE
- var/mob/living/interactor = user
- if(isliving(interactor) && interactor.combat_mode)
- return FALSE
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "HoloPay")
- ui.open()
-
-/obj/structure/holopay/ui_status(mob/user)
- . = ..()
- if(!in_range(user, src) && !isobserver(user))
- return UI_CLOSE
-
-/obj/structure/holopay/ui_static_data(mob/user)
- . = list()
- .["available_logos"] = linked_card.available_logos
- .["description"] = desc
- .["max_fee"] = linked_card.holopay_max_fee
- .["owner"] = linked_card.registered_account?.account_holder || null
- .["shop_logo"] = shop_logo
-
-/obj/structure/holopay/ui_data(mob/user)
- . = list()
- .["force_fee"] = force_fee
- .["name"] = name
- if(!isliving(user))
- return .
- var/mob/living/card_holder = user
- var/obj/item/card/id/id_card = card_holder.get_idcard(TRUE)
- var/datum/bank_account/account = id_card?.registered_account || null
- if(account)
- .["user"] = list()
- .["user"]["name"] = account.account_holder
- .["user"]["balance"] = account.account_balance
-
-/obj/structure/holopay/ui_act(action, list/params, datum/tgui/ui)
- . = ..()
- if(.)
- return FALSE
- switch(action)
- if("done")
- ui.send_full_update()
- return TRUE
- if("fee")
- linked_card.set_holopay_fee(params["amount"])
- force_fee = linked_card.holopay_fee
- if("logo")
- linked_card.set_holopay_logo(params["logo"])
- shop_logo = linked_card.holopay_logo
- if("pay")
- ui.close()
- process_payment(usr)
- return TRUE
- if("rename")
- linked_card.set_holopay_name(params["name"])
- name = linked_card.holopay_name
- return FALSE
-
-/**
- * Links the source card to the holopay. Begins checking if its in range.
- *
- * Parameters:
- * * turf/target - The tile to project the holopay onto
- * * obj/item/card/id/card - The card to link to the holopay
- * Returns:
- * * TRUE - the card was linked
- */
-/obj/structure/holopay/proc/assign_card(turf/target, obj/item/card/id/card)
- linked_card = card
- desc = "Pays directly into [card.registered_account.account_holder]'s bank account."
- force_fee = card.holopay_fee
- shop_logo = card.holopay_logo
- name = card.holopay_name
- add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
- set_light(2)
- visible_message(span_notice("A holographic pay stand appears."))
- /// Start checking if the source projection is in range
- track(linked_card)
- return TRUE
-
-/obj/structure/holopay/proc/track(atom/movable/thing)
- RegisterSignal(thing, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move))
- var/list/locations = get_nested_locs(thing, include_turf = FALSE)
- for(var/atom/movable/location in locations)
- RegisterSignal(location, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move))
-
-/obj/structure/holopay/proc/untrack(atom/movable/thing)
- UnregisterSignal(thing, COMSIG_MOVABLE_MOVED)
- var/list/locations = get_nested_locs(thing, include_turf = FALSE)
- for(var/atom/movable/location in locations)
- UnregisterSignal(location, COMSIG_MOVABLE_MOVED)
-
-/**
- * A periodic check to see if the projecting card is nearby.
- * Deletes the holopay if not.
- */
-/obj/structure/holopay/proc/handle_move(atom/movable/source, atom/old_loc, dir, forced, list/old_locs)
- if(ismovable(old_loc))
- untrack(old_loc)
- if(!IN_GIVEN_RANGE(src, linked_card, max_holo_range))
- dissipate()
- return
- if(ismovable(source.loc))
- track(source.loc)
-
-/**
- * Creates holopay vanishing effects.
- * Deletes the holopay thereafter.
- */
-/obj/structure/holopay/proc/dissipate()
- playsound(loc, "sound/effects/empulse.ogg", 40, TRUE)
- visible_message(span_notice("The pay stand vanishes."))
- qdel(src)
-
-/**
- * Initiates a transaction between accounts.
- *
- * Parameters:
- * * mob/living/user - The user who initiated the transaction.
- * Returns:
- * * TRUE - transaction was successful
- */
-/obj/structure/holopay/proc/process_payment(mob/living/user)
- /// Account checks
- var/obj/item/card/id/id_card
- id_card = user.get_idcard(TRUE)
- if(!id_card || !id_card.registered_account || !id_card.registered_account.account_job)
- balloon_alert(user, "invalid account")
- to_chat(user, span_warning("You don't have a valid account."))
- return FALSE
- var/datum/bank_account/payee = id_card.registered_account
- if(payee == linked_card?.registered_account)
- balloon_alert(user, "invalid transaction")
- to_chat(user, span_warning("You can't pay yourself."))
- return FALSE
- /// If the user has enough money, ask them the amount or charge the force fee
- var/amount = force_fee || tgui_input_number(user, "How much? (Max: [payee.account_balance])", "Patronage", max_value = payee.account_balance)
- /// Exit checks in case the user cancelled or entered an invalid amount
- if(!amount || QDELETED(user) || QDELETED(src) || !user.canUseTopic(src, USE_CLOSE|USE_IGNORE_TK))
- return FALSE
- if(!payee.adjust_money(-amount))
- balloon_alert(user, "insufficient credits")
- to_chat(user, span_warning("You don't have the money to pay for this."))
- return FALSE
- /// Success: Alert the buyer
- alert_buyer(user, amount)
- return TRUE
-
-/**
- * Alerts the owner of the transaction.
- *
- * Parameters:
- * * payee - The user who initiated the transaction.
- * * amount - The amount of money that was paid.
- * Returns:
- * * TRUE - alert was successful.
- */
-/obj/structure/holopay/proc/alert_buyer(payee, amount)
- /// Pay the owner
- linked_card.registered_account.adjust_money(amount)
- /// Make alerts
- linked_card.registered_account.bank_card_talk("[payee] has deposited [amount] cr at your holographic pay stand.")
- say("Thank you for your patronage, [payee]!")
- playsound(src, 'sound/effects/cashregister.ogg', 20, TRUE)
- /// Log the event
- log_econ("[amount] credits were transferred from [payee]'s transaction to [linked_card.registered_account.account_holder]")
- SSblackbox.record_feedback("amount", "credits_transferred", amount)
- return TRUE
diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm
index 3533b4ea5f24..ddb0e72a7063 100644
--- a/code/modules/events/pirates.dm
+++ b/code/modules/events/pirates.dm
@@ -150,7 +150,7 @@
/obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user)
if(credits_stored) // Prevents spamming empty holochips
- new /obj/item/holochip(drop_location(), credits_stored)
+ SSeconomy.spawn_cash_for_amount(credits_stored, drop_location())
to_chat(user,span_notice("You retrieve the siphoned credits!"))
credits_stored = 0
else
@@ -492,13 +492,4 @@
/datum/export/pirate/cash/get_amount(obj/O)
var/obj/item/stack/spacecash/C = O
- return ..() * C.amount * C.value
-
-/datum/export/pirate/holochip
- cost = 1
- unit_name = "holochip"
- export_types = list(/obj/item/holochip)
-
-/datum/export/pirate/holochip/get_cost(atom/movable/AM)
- var/obj/item/holochip/H = AM
- return H.credits
+ return ..() * C.get_item_credit_value()
diff --git a/code/modules/explorer_drone/loot.dm b/code/modules/explorer_drone/loot.dm
index 9fc39c3b6268..5b9aa890a1e1 100644
--- a/code/modules/explorer_drone/loot.dm
+++ b/code/modules/explorer_drone/loot.dm
@@ -69,7 +69,7 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index())
/// Valuables
/datum/adventure_loot_generator/simple/cash
id = "cash"
- loot_list = list(/obj/item/storage/bag/money,/obj/item/antique,/obj/item/stack/spacecash/c1000,/obj/item/holochip/thousand)
+ loot_list = list(/obj/item/storage/bag/money,/obj/item/antique,/obj/item/stack/spacecash/c1000,)
/// Drugs
/datum/adventure_loot_generator/simple/drugs
diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm
index 766c9e2f3408..bc00a11b262b 100644
--- a/code/modules/jobs/access.dm
+++ b/code/modules/jobs/access.dm
@@ -34,7 +34,8 @@
/obj/item/proc/GetAccess()
return list()
-/obj/item/proc/GetID()
+/// Get an /obj/item/card/id from this object. bypass_wallet will grab the ID from a wallet even if it's closed
+/obj/item/proc/GetID(bypass_wallet = FALSE)
return null
/obj/item/proc/RemoveID()
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index 51f8d7a99d16..0848185c9008 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -244,11 +244,16 @@ GLOBAL_LIST_INIT(job_display_order, list(
/mob/living/carbon/human/on_job_equipping(datum/job/equipping, datum/preferences/used_pref)
var/datum/bank_account/bank_account = new(real_name, equipping, dna.species.payday_modifier)
- bank_account.payday(STARTING_PAYCHECKS, TRUE)
account_id = bank_account.account_id
bank_account.replaceable = FALSE
dress_up_as_job(equipping, FALSE, used_pref, TRUE)
+ var/obj/item/storage/wallet/W = wear_id
+ if(istype(W))
+ var/monero = round(equipping.paycheck * dna.species.payday_modifier * STARTING_PAYCHECKS, 10)
+ SSeconomy.spawn_cash_for_amount(monero, W)
+ else
+ bank_account.payday(STARTING_PAYCHECKS, TRUE)
/mob/living/proc/dress_up_as_job(datum/job/equipping, visual_only = FALSE)
return
@@ -321,6 +326,7 @@ GLOBAL_LIST_INIT(job_display_order, list(
shoes = /obj/item/clothing/shoes/sneakers/black
box = /obj/item/storage/box/survival
+ id_in_wallet = TRUE
preload = TRUE // These are used by the prefs ui, and also just kinda could use the extra help at roundstart
var/backpack = /obj/item/storage/backpack
@@ -370,7 +376,7 @@ GLOBAL_LIST_INIT(job_display_order, list(
if(!J)
J = SSjob.GetJob(H.job)
- var/obj/item/card/id/card = H.wear_id
+ var/obj/item/card/id/card = H.wear_id.GetID()
if(istype(card))
ADD_TRAIT(card, TRAIT_JOB_FIRST_ID_CARD, ROUNDSTART_TRAIT)
shuffle_inplace(card.access) // Shuffle access list to make NTNet passkeys less predictable
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index ff3de3128d2b..7bde55c55bda 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -123,7 +123,7 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
// If there's a departmental sec trim to apply to the card, overwrite.
if(dep_trim)
- var/obj/item/card/id/worn_id = spawning.get_idcard(hand_first = FALSE)
+ var/obj/item/card/id/worn_id = spawning.get_idcard(hand_first = FALSE, bypass_wallet = TRUE)
SSid_access.apply_trim_to_card(worn_id, dep_trim)
spawning.sec_hud_set_ID()
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/crashedship.dm b/code/modules/mapfluff/ruins/spaceruin_code/crashedship.dm
index 4f47da876140..61999fc6199b 100644
--- a/code/modules/mapfluff/ruins/spaceruin_code/crashedship.dm
+++ b/code/modules/mapfluff/ruins/spaceruin_code/crashedship.dm
@@ -35,7 +35,7 @@
gloves = /obj/item/clothing/gloves/color/fyellow
head = /obj/item/clothing/head/hardhat
r_pocket = /obj/item/paper/fluff/ruins/crashedship/old_diary
- l_pocket = /obj/item/stack/spacecash/c200
+ l_pocket = /obj/item/stack/spacecash/c100
mask = /obj/item/clothing/mask/breath
belt = /obj/item/tank/internals/emergency_oxygen/engi
diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm
index 2ef2b5b9b4a9..914f4700740e 100644
--- a/code/modules/mining/money_bag.dm
+++ b/code/modules/mining/money_bag.dm
@@ -16,7 +16,7 @@
icon_state = "moneybagalt"
atom_storage.max_slots = 40
atom_storage.max_specific_storage = 40
- atom_storage.set_holdable(list(/obj/item/coin, /obj/item/stack/spacecash, /obj/item/holochip))
+ atom_storage.set_holdable(list(/obj/item/coin, /obj/item/stack/spacecash))
/obj/item/storage/bag/money/vault/PopulateContents()
new /obj/item/coin/silver(src)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 5ac62502d609..521070e05c4a 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -100,7 +100,8 @@
//ID
if(wear_id && !(wear_id.item_flags & EXAMINE_SKIP))
- . += "[t_He] [t_is] wearing [wear_id.get_examine_string(user)]. \[Look at ID\]"
+ var/id_topic = wear_id.GetID() ? " \[Look at ID\]" : ""
+ . += "[t_He] [t_is] wearing [wear_id.get_examine_string(user)].[id_topic]"
//Status effects
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index f88a05a0c2a7..b279e3737fad 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -79,14 +79,14 @@
. = if_no_id //to prevent null-names making the mob unclickable
return
-/mob/living/carbon/human/get_idcard(hand_first = TRUE)
+/mob/living/carbon/human/get_idcard(hand_first = TRUE, bypass_wallet)
RETURN_TYPE(/obj/item/card/id)
. = ..()
if(. && hand_first)
return
//Check inventory slots
- return (wear_id?.GetID() || belt?.GetID())
+ return (wear_id?.GetID(bypass_wallet) || belt?.GetID(bypass_wallet))
/mob/living/carbon/human/can_track(mob/living/user)
if(istype(head, /obj/item/clothing/head))
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b1554e462406..c3f2f0d0bcf9 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -407,7 +407,7 @@
* Argument:
* * hand_firsts - boolean that checks the hands of the mob first if TRUE.
*/
-/mob/living/proc/get_idcard(hand_first)
+/mob/living/proc/get_idcard(hand_first, bypass_wallet)
RETURN_TYPE(/obj/item/card/id)
if(!length(held_items)) //Early return for mobs without hands.
@@ -415,11 +415,11 @@
//Check hands
var/obj/item/held_item = get_active_held_item()
if(held_item) //Check active hand
- . = held_item.GetID()
+ . = held_item.GetID(bypass_wallet)
if(!.) //If there is no id, check the other hand
held_item = get_inactive_held_item()
if(held_item)
- . = held_item.GetID()
+ . = held_item.GetID(bypass_wallet)
/mob/living/proc/get_id_in_hand()
var/obj/item/held_item = get_active_held_item()
diff --git a/code/modules/mob/living/simple_animal/friendly/trader.dm b/code/modules/mob/living/simple_animal/friendly/trader.dm
index 31f8e85ce2c1..033c8c4fa859 100644
--- a/code/modules/mob/living/simple_animal/friendly/trader.dm
+++ b/code/modules/mob/living/simple_animal/friendly/trader.dm
@@ -151,12 +151,13 @@
if(npc_result != "Yes")
return
face_atom(user)
- var/obj/item/holochip/cash
- cash = user.is_holding_item_of_type(/obj/item/holochip)
- if(!cash || cash.credits < products[item_to_buy])
+
+ var/obj/item/stack/spacecash/cash = user.is_holding_item_of_type(/obj/item/stack/spacecash)
+ if(!cash || cash.get_item_credit_value() < products[item_to_buy])
say(nocashphrase)
return
- cash.spend(products[item_to_buy])
+
+ cash.use_cash(products[item_to_buy])
item_to_buy = new item_to_buy(get_turf(user))
user.put_in_hands(item_to_buy)
playsound(src, sell_sound, 50, TRUE)
@@ -213,9 +214,7 @@
* * user - The mob we put the holochip in hands of
*/
/mob/living/simple_animal/hostile/retaliate/trader/proc/generate_cash(value, mob/user)
- var/obj/item/holochip/chip = new /obj/item/holochip(get_turf(user), value)
- user.put_in_hands(chip)
-
+ SSeconomy.spawn_cash_for_amount(value, get_turf(user))
/mob/living/simple_animal/hostile/retaliate/trader/mrbones
name = "Mr. Bones"
desc = "A skeleton merchant, he seems very humerus."
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index 3e70063cf5fe..d7ec158b7f16 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -170,7 +170,7 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
return card_slot.GetAccess()
return ..()
-/obj/item/modular_computer/GetID()
+/obj/item/modular_computer/GetID(bypass_wallet)
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
@@ -617,10 +617,10 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
return TRUE
/obj/item/modular_computer/proc/UpdateDisplay()
- if(!imprint_prefix || !saved_identification)
+ if(!imprint_prefix)
name = initial(name) //No saved ID, no fucked up name.
return
- name = "[imprint_prefix] - [saved_identification] [saved_job ? "([saved_job])" : null]"
+ name = "[imprint_prefix] - [saved_job ? "([saved_job])" : null]"
/obj/item/modular_computer/screwdriver_act(mob/user, obj/item/tool)
if(!deconstructable)
diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm
index 2e527435c8ef..9c7ecae036c9 100644
--- a/code/modules/modular_computers/hardware/card_slot.dm
+++ b/code/modules/modular_computers/hardware/card_slot.dm
@@ -43,7 +43,7 @@
total_access |= card_slot2.stored_card.GetAccess()
return total_access
-/obj/item/computer_hardware/card_slot/GetID()
+/obj/item/computer_hardware/card_slot/GetID(bypass_wallet)
if(stored_card)
return stored_card
return ..()
diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm
index 25adb8307fe3..2a53e21b9f3f 100644
--- a/code/modules/modular_computers/laptop_vendor.dm
+++ b/code/modules/modular_computers/laptop_vendor.dm
@@ -225,16 +225,11 @@
var/obj/item/stack/spacecash/c = I
if(!user.temporarilyRemoveItemFromInventory(c))
return
- credits += c.value
- visible_message(span_info("[span_name("[user]")] inserts [c.value] cr into [src]."))
+ credits += c.get_item_credit_value()
+ visible_message(span_info("[span_name("[user]")] inserts [c.get_item_credit_value()] cr into [src]."))
qdel(c)
return
- else if(istype(I, /obj/item/holochip))
- var/obj/item/holochip/HC = I
- credits += HC.credits
- visible_message(span_info("[user] inserts a [HC.credits] cr holocredit chip into [src]."))
- qdel(HC)
- return
+
else if(istype(I, /obj/item/card/id))
if(state != 2)
return
diff --git a/code/modules/research/designs/comp_board_designs.dm b/code/modules/research/designs/comp_board_designs.dm
index 97a4771987f8..93dab29d6a36 100644
--- a/code/modules/research/designs/comp_board_designs.dm
+++ b/code/modules/research/designs/comp_board_designs.dm
@@ -206,11 +206,6 @@
id = "advanced_camera"
build_path = /obj/item/circuitboard/computer/advanced_camera
-/datum/design/board/bountypad_control
- name = "Circuit Board (Civilian Bounty Pad Control)"
- desc = "Allows for the construction of circuit boards used to build a new civilian bounty pad console."
- id = "bounty_pad_control"
- build_path = /obj/item/circuitboard/computer/bountypad
/datum/design/board/exoscanner_console
name = "Circuit Board (Scanner Array Control Console)"
desc = "Allows for the construction of circuit boards used to build a new scanner array control console."
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index 0fbd2f02cba8..6d9cc5d55375 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -512,13 +512,6 @@
build_path = /obj/item/circuitboard/machine/vendatray
mapload_design_flags = DESIGN_IMPRINTER
-/datum/design/board/bountypad
- name = "Machine Board (Civilian Bounty Pad)"
- desc = "The circuit board for a Civilian Bounty Pad."
- id = "bounty_pad"
- build_path = /obj/item/circuitboard/machine/bountypad
- mapload_design_flags = DESIGN_IMPRINTER
-
/datum/design/board/skill_station
name = "Machine Board (Skill station)"
desc = "The circuit board for Skill station."
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index 163441cd1950..658a54d2c87c 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -1267,16 +1267,19 @@ GLOBAL_LIST_EMPTY(vending_products)
break
if(!dispensed_item)
return FALSE
+
/// Charges the user if its not the owner
if(!compartmentLoadAccessCheck(user))
if(!payee.has_money(dispensed_item.custom_price))
balloon_alert(user, "insufficient funds")
return TRUE
+
/// Make the transaction
payee.adjust_money(-dispensed_item.custom_price)
linked_account.adjust_money(dispensed_item.custom_price)
linked_account.bank_card_talk("[payee.account_holder] made a [dispensed_item.custom_price] \
cr purchase at your custom vendor.")
+
/// Log the transaction
SSblackbox.record_feedback("amount", "vending_spent", dispensed_item.custom_price)
log_econ("[dispensed_item.custom_price] credits were spent on [src] buying a \
diff --git a/code/modules/wiremod/shell/moneybot.dm b/code/modules/wiremod/shell/moneybot.dm
index 2ee9cf6fa023..f63c460e5914 100644
--- a/code/modules/wiremod/shell/moneybot.dm
+++ b/code/modules/wiremod/shell/moneybot.dm
@@ -16,7 +16,7 @@
var/locked = FALSE
/obj/structure/money_bot/deconstruct(disassembled)
- new /obj/item/holochip(drop_location(), stored_money)
+ SSeconomy.spawn_cash_for_amount(stored_money, drop_location())
return ..()
/obj/structure/money_bot/proc/add_money(to_add)
@@ -76,7 +76,7 @@
return
attached_bot.add_money(-to_dispense)
- new /obj/item/holochip(drop_location(), to_dispense)
+ SSeconomy.spawn_cash_for_amount(to_dispense, drop_location())
/obj/item/circuit_component/money_bot
display_name = "Money Bot"
diff --git a/daedalus.dme b/daedalus.dme
index 5bd9169dd60e..3870386a4ab6 100644
--- a/daedalus.dme
+++ b/daedalus.dme
@@ -1265,12 +1265,12 @@
#include "code\game\machinery\ai_slipper.dm"
#include "code\game\machinery\airlock_control.dm"
#include "code\game\machinery\announcement_system.dm"
+#include "code\game\machinery\atm.dm"
#include "code\game\machinery\autolathe.dm"
#include "code\game\machinery\bank_machine.dm"
#include "code\game\machinery\buttons.dm"
#include "code\game\machinery\canister_frame.dm"
#include "code\game\machinery\cell_charger.dm"
-#include "code\game\machinery\civilian_bounties.dm"
#include "code\game\machinery\constructable_frame.dm"
#include "code\game\machinery\dance_machine.dm"
#include "code\game\machinery\data_disk.dm"
@@ -1514,7 +1514,6 @@
#include "code\game\objects\items\courtroom.dm"
#include "code\game\objects\items\crab17.dm"
#include "code\game\objects\items\crayons.dm"
-#include "code\game\objects\items\credit_holochip.dm"
#include "code\game\objects\items\debug_items.dm"
#include "code\game\objects\items\defib.dm"
#include "code\game\objects\items\dehy_carp.dm"
@@ -2497,7 +2496,6 @@
#include "code\modules\cards\deck\kotahi.dm"
#include "code\modules\cards\deck\tarot.dm"
#include "code\modules\cards\deck\wizoff.dm"
-#include "code\modules\cargo\bounty.dm"
#include "code\modules\cargo\centcom_podlauncher.dm"
#include "code\modules\cargo\coupon.dm"
#include "code\modules\cargo\department_order.dm"
@@ -2511,20 +2509,7 @@
#include "code\modules\cargo\packs.dm"
#include "code\modules\cargo\supplypod.dm"
#include "code\modules\cargo\supplypod_beacon.dm"
-#include "code\modules\cargo\bounties\assistant.dm"
-#include "code\modules\cargo\bounties\botany.dm"
-#include "code\modules\cargo\bounties\chef.dm"
-#include "code\modules\cargo\bounties\engineering.dm"
-#include "code\modules\cargo\bounties\item.dm"
-#include "code\modules\cargo\bounties\mech.dm"
-#include "code\modules\cargo\bounties\medical.dm"
-#include "code\modules\cargo\bounties\reagent.dm"
-#include "code\modules\cargo\bounties\security.dm"
-#include "code\modules\cargo\bounties\slime.dm"
-#include "code\modules\cargo\bounties\special.dm"
-#include "code\modules\cargo\bounties\virus.dm"
#include "code\modules\cargo\exports\antiques.dm"
-#include "code\modules\cargo\exports\civilain_bounty.dm"
#include "code\modules\cargo\exports\food_and_drink.dm"
#include "code\modules\cargo\exports\gear.dm"
#include "code\modules\cargo\exports\large_objects.dm"
@@ -2852,7 +2837,6 @@
#include "code\modules\discord\discord_sql_functions.dm"
#include "code\modules\economy\_economy.dm"
#include "code\modules\economy\account.dm"
-#include "code\modules\economy\holopay.dm"
#include "code\modules\emoji\emoji_parse.dm"
#include "code\modules\error_handler\error_handler.dm"
#include "code\modules\error_handler\error_viewer.dm"
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index 7dce9bbed3bd6a21817043b954ab5c11cc2078b4..7fd093bd3dbefeaa401d19802b15edb041803aee 100644
GIT binary patch
delta 62514
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