diff --git a/_maps/shuttles/~doppler_shuttles/pirate_sapper.dmm b/_maps/shuttles/~doppler_shuttles/pirate_sapper.dmm
new file mode 100644
index 0000000000000..58c96b286ba98
--- /dev/null
+++ b/_maps/shuttles/~doppler_shuttles/pirate_sapper.dmm
@@ -0,0 +1,702 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"cz" = (
+/obj/machinery/light/floor,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"dZ" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
+ dir = 8
+ },
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"fn" = (
+/obj/structure/cable,
+/obj/machinery/door/poddoor/shutters/window{
+ id = "pirate_sapper_shutter_L";
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"fK" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"fP" = (
+/obj/structure/cable/layer1,
+/obj/structure/rack,
+/obj/machinery/light/floor,
+/obj/machinery/power/terminal{
+ dir = 4;
+ cable_layer = 1
+ },
+/obj/effect/decal/cleanable/plasma,
+/obj/item/storage/medkit/frontier/stocked,
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"gr" = (
+/obj/structure/lattice,
+/obj/structure/marker_beacon/yellow,
+/obj/machinery/button/door/directional/south{
+ id = "pirate_sapper_shutter_R";
+ req_access = list("sapper_ship")
+ },
+/turf/open/space/basic,
+/area/shuttle/pirate/sapper)
+"hV" = (
+/obj/structure/cable/layer1,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"jZ" = (
+/obj/effect/decal/cleanable/wrapping,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"lZ" = (
+/obj/machinery/light/floor,
+/obj/effect/decal/cleanable/robot_debris/limb,
+/obj/item/trash/empty_side_pack/yangyu{
+ pixel_x = -6;
+ pixel_y = -6
+ },
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"mE" = (
+/obj/machinery/button/door/directional/north{
+ id = "pirate_sapper_shutter_L";
+ req_access = list("sapper_ship")
+ },
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"mL" = (
+/obj/structure/cable/layer1,
+/obj/machinery/space_heater,
+/obj/effect/decal/cleanable/shreds,
+/obj/effect/decal/cleanable/dirt/dust,
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"mY" = (
+/turf/closed/wall/mineral/titanium/overspace,
+/area/shuttle/pirate/sapper)
+"nt" = (
+/obj/machinery/rnd/production/colony_lathe,
+/obj/structure/sign/poster/contraband/rebels_unite/directional/north,
+/obj/effect/turf_decal/stripes/box,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/engine,
+/area/shuttle/pirate/sapper)
+"nE" = (
+/obj/machinery/button/door/directional/north{
+ id = "pirate_sapper_shutter_R";
+ req_access = list("sapper_ship")
+ },
+/obj/effect/decal/cleanable/ash,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"nM" = (
+/obj/structure/cable,
+/obj/machinery/door/poddoor/shutters/window{
+ id = "pirate_sapper_shutter_R";
+ dir = 4
+ },
+/obj/docking_port/mobile/pirate/sapper{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"pt" = (
+/obj/structure/cable/layer1,
+/obj/machinery/light/cold/directional/east,
+/obj/structure/sign/warning/directional/south,
+/obj/structure/closet/crate/engineering/electrical,
+/obj/item/stack/cable_coil/thirty,
+/obj/item/stack/cable_coil/thirty,
+/obj/item/stack/cable_coil/thirty,
+/obj/item/stack/cable_coil/thirty,
+/obj/item/trash/energybar,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/stock_parts/power_store/cell/high,
+/obj/item/stock_parts/power_store/cell/high,
+/obj/item/stock_parts/power_store/cell/high,
+/obj/item/stock_parts/power_store/cell/high,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"pH" = (
+/obj/item/rcd_ammo/large{
+ pixel_x = 8
+ },
+/obj/item/rcd_ammo/large{
+ pixel_x = -3;
+ pixel_y = -4
+ },
+/obj/item/rcd_ammo/large{
+ pixel_x = -9;
+ pixel_y = 9
+ },
+/obj/effect/decal/cleanable/oil,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"qq" = (
+/obj/structure/table/reinforced,
+/obj/machinery/turretid{
+ icon_state = "control_off";
+ lethal = 1;
+ locked = 0;
+ req_access = list("sapper_ship");
+ pixel_y = 4;
+ pixel_x = -1;
+ control_area = "/area/shuttle/pirate/sapper";
+ enabled = 0
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/item/food/vendor_tray_meal/mushroom_fry{
+ pixel_x = -5
+ },
+/obj/effect/decal/cleanable/dirt/dust,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"qL" = (
+/obj/machinery/computer/shuttle/pirate/sapper,
+/obj/machinery/light/floor,
+/obj/structure/cable/layer1,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt/dust,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"rL" = (
+/obj/machinery/light/floor,
+/obj/effect/decal/cleanable/oil,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"sr" = (
+/obj/machinery/computer/monitor,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt/dust,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"sM" = (
+/obj/structure/cable,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"tM" = (
+/obj/effect/decal/cleanable/dirt/dust,
+/obj/machinery/atmospherics/components/tank/air/layer4,
+/obj/structure/cable/layer1,
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"ua" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/obj/structure/cable/layer1,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"uz" = (
+/obj/structure/window/reinforced/spawner/directional/north{
+ pixel_y = 1
+ },
+/obj/machinery/power/shuttle_engine/heater,
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/pirate/sapper)
+"uD" = (
+/obj/item/clothing/mask/gas/atmos/sapper{
+ pixel_x = -2;
+ pixel_y = -3
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"vB" = (
+/obj/structure/cable/layer1,
+/obj/effect/decal/cleanable/dirt/dust,
+/obj/machinery/power/port_gen/pacman/pre_loaded{
+ cable_layer = 1;
+ anchored = 1
+ },
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"wf" = (
+/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/pirate/sapper,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt/dust,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"xf" = (
+/obj/item/stack/sheet/iron/twenty,
+/obj/item/stack/sheet/glass{
+ amount = 20
+ },
+/obj/item/stack/sheet/plastic/five,
+/obj/item/stack/sheet/mineral/titanium{
+ amount = 5
+ },
+/obj/item/stack/sheet/mineral/gold{
+ amount = 5
+ },
+/obj/machinery/ore_silo/colony_lathe,
+/obj/item/stack/sheet/mineral/silver{
+ amount = 5
+ },
+/obj/structure/sign/poster/contraband/power/directional/north,
+/obj/effect/turf_decal/stripes/box,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/engine,
+/area/shuttle/pirate/sapper)
+"xA" = (
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"yt" = (
+/obj/machinery/light/floor,
+/obj/effect/decal/cleanable/plastic,
+/obj/item/pizzabox/vegetable{
+ open = 1
+ },
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"yx" = (
+/obj/structure/window/reinforced/spawner/directional/north{
+ pixel_y = 1
+ },
+/obj/machinery/power/shuttle_engine/heater,
+/turf/open/floor/plating/airless,
+/area/shuttle/pirate/sapper)
+"yE" = (
+/turf/closed/wall/mineral/titanium,
+/area/shuttle/pirate/sapper)
+"zk" = (
+/obj/structure/cable,
+/obj/item/storage/toolbox/emergency/turret{
+ pixel_x = 10;
+ pixel_y = 9
+ },
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"zy" = (
+/obj/structure/lattice,
+/obj/structure/marker_beacon/yellow,
+/turf/open/space/basic,
+/area/shuttle/pirate/sapper)
+"Bp" = (
+/obj/structure/table/reinforced,
+/obj/machinery/button/door/directional{
+ id = "pirate_sapper_shutter";
+ pixel_x = 6;
+ req_access = list("sapper_ship")
+ },
+/obj/machinery/recharger{
+ pixel_x = -6;
+ pixel_y = 3
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/item/reagent_containers/cup/glass/waterbottle/tea/strawberry{
+ pixel_x = 6;
+ pixel_y = 15
+ },
+/obj/effect/decal/cleanable/dirt/dust,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"BT" = (
+/obj/machinery/power/smes/ship{
+ cable_layer = 1
+ },
+/obj/effect/decal/cleanable/dirt/dust,
+/obj/structure/cable/layer1,
+/obj/item/toy/plush/modular/deer{
+ name = "powerful deer plushie";
+ pixel_x = 3;
+ pixel_y = 17
+ },
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"CM" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"Dl" = (
+/obj/machinery/door/poddoor/shutters{
+ id = "pirate_sapper_shutter_L";
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"DT" = (
+/mob/living/basic/bot/medbot/sapper,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"DZ" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
+ dir = 4
+ },
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"EE" = (
+/obj/structure/cable/layer1,
+/obj/machinery/airalarm/directional/east{
+ req_access = list("sapper_ship")
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/structure/closet/crate/engineering,
+/obj/item/pipe_dispenser,
+/obj/item/pipe_dispenser,
+/obj/item/rpd_upgrade/unwrench,
+/obj/item/rpd_upgrade/unwrench,
+/obj/item/airlock_painter,
+/obj/item/airlock_painter/decal,
+/obj/item/airlock_painter/decal/tile,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"Ih" = (
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/pirate/sapper)
+"In" = (
+/obj/machinery/power/shuttle_engine/propulsion,
+/obj/effect/turf_decal/stripes/line,
+/turf/open/floor/plating/airless,
+/area/shuttle/pirate/sapper)
+"IH" = (
+/obj/structure/cable/layer1,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/item/stack/sheet/mineral/sandbags{
+ amount = 15
+ },
+/obj/structure/closet{
+ icon_state = "eng";
+ icon_door = "eng_tool"
+ },
+/obj/item/stack/sheet/plasteel/twenty,
+/obj/item/stack/sheet/iron/twenty,
+/obj/item/stack/sheet/rglass{
+ amount = 20
+ },
+/obj/item/holosign_creator/atmos,
+/obj/item/radio/intercom/directional/west,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/stack/sheet/mineral/wood{
+ amount = 20
+ },
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"JD" = (
+/obj/structure/cable,
+/obj/item/storage/toolbox/emergency/turret{
+ pixel_x = -8;
+ pixel_y = -4
+ },
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"JF" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"Mi" = (
+/obj/machinery/power/shuttle_engine/propulsion,
+/obj/effect/turf_decal/stripes/line{
+ dir = 10
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/pirate/sapper)
+"Ml" = (
+/obj/structure/cable/layer1,
+/obj/machinery/power/apc/auto_name/directional/west{
+ cable_layer = 1;
+ req_access = list("sapper_ship")
+ },
+/obj/structure/table/reinforced,
+/obj/effect/spawner/random/food_or_drink/donkpockets,
+/obj/item/reagent_containers/condiment/ketchup{
+ pixel_x = -5;
+ pixel_y = 13
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"Mz" = (
+/obj/structure/lattice,
+/obj/structure/marker_beacon/yellow,
+/obj/machinery/button/door/directional/south{
+ id = "pirate_sapper_shutter_L";
+ req_access = list("sapper_ship")
+ },
+/turf/open/space/basic,
+/area/shuttle/pirate/sapper)
+"NX" = (
+/obj/structure/window/reinforced/spawner/directional/north{
+ pixel_y = 1
+ },
+/obj/machinery/power/shuttle_engine/heater,
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/pirate/sapper)
+"Oc" = (
+/obj/structure/cable/layer1,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/item/stack/sheet/mineral/sandbags{
+ amount = 15
+ },
+/obj/structure/closet{
+ icon_state = "eng";
+ icon_door = "eng_tool"
+ },
+/obj/item/stack/sheet/plasteel/twenty,
+/obj/item/stack/sheet/iron/twenty,
+/obj/item/stack/sheet/rglass{
+ amount = 20
+ },
+/obj/item/holosign_creator/atmos,
+/obj/item/radio/intercom/directional/east,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/stack/sheet/mineral/wood{
+ amount = 20
+ },
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"Sa" = (
+/obj/structure/cable,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"Tb" = (
+/obj/machinery/power/shuttle_engine/propulsion,
+/obj/effect/turf_decal/stripes/line{
+ dir = 6
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/pirate/sapper)
+"Tx" = (
+/obj/machinery/door/poddoor/shutters{
+ id = "pirate_sapper_shutter_R";
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"TF" = (
+/obj/effect/decal/cleanable/robot_debris/up,
+/obj/item/toy/crayon/spraycan,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"Vt" = (
+/obj/structure/cable,
+/obj/item/powersink/creditminer,
+/obj/machinery/piratepad/sapper,
+/obj/effect/turf_decal/delivery/white,
+/obj/item/paper/fluff/sapper_recovery_instructions,
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"Wo" = (
+/obj/item/clothing/mask/gas/atmos/sapper/partner{
+ pixel_x = 2;
+ pixel_y = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/mineral/titanium/white,
+/area/shuttle/pirate/sapper)
+"WY" = (
+/obj/machinery/computer/piratepad_control/sapper,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"Xc" = (
+/obj/structure/cable/layer1,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/effect/decal/cleanable/plastic,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"Xr" = (
+/obj/structure/cable/layer1,
+/obj/machinery/light/cold/directional/west,
+/obj/structure/sign/warning/directional/south,
+/obj/structure/table/reinforced,
+/obj/machinery/microwave/engineering/cell_included,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+"XX" = (
+/obj/effect/spawner/structure/window/reinforced/shuttle,
+/obj/machinery/door/poddoor/shutters/preopen{
+ id = "pirate_sapper_shutter"
+ },
+/obj/structure/cable/layer1,
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"Yo" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/effect/mapping_helpers/broken_floor,
+/turf/open/floor/plating,
+/area/shuttle/pirate/sapper)
+"Yx" = (
+/turf/open/space/basic,
+/area/template_noop)
+"Zc" = (
+/obj/structure/cable/layer1,
+/obj/structure/cable,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/turf/open/floor/catwalk_floor/iron_white,
+/area/shuttle/pirate/sapper)
+
+(1,1,1) = {"
+Yx
+Yx
+Mz
+mY
+Dl
+fn
+Dl
+mY
+zy
+Yx
+Yx
+"}
+(2,1,1) = {"
+Yx
+yE
+yE
+Ih
+mE
+sM
+xA
+Ih
+yE
+yE
+Yx
+"}
+(3,1,1) = {"
+yE
+Ih
+nt
+IH
+hV
+Zc
+hV
+Ml
+Xr
+Ih
+mY
+"}
+(4,1,1) = {"
+XX
+wf
+CM
+hV
+TF
+Sa
+dZ
+jZ
+mL
+uz
+Mi
+"}
+(5,1,1) = {"
+XX
+Bp
+uD
+hV
+rL
+JD
+yt
+xA
+vB
+yx
+In
+"}
+(6,1,1) = {"
+XX
+qL
+ua
+hV
+DT
+Vt
+WY
+xA
+fP
+yx
+In
+"}
+(7,1,1) = {"
+XX
+qq
+Wo
+hV
+lZ
+Sa
+cz
+xA
+BT
+yx
+In
+"}
+(8,1,1) = {"
+XX
+sr
+fK
+Xc
+DZ
+zk
+pH
+Yo
+tM
+NX
+Tb
+"}
+(9,1,1) = {"
+yE
+Ih
+xf
+Oc
+hV
+Zc
+hV
+EE
+pt
+Ih
+mY
+"}
+(10,1,1) = {"
+Yx
+yE
+yE
+Ih
+nE
+Sa
+JF
+Ih
+yE
+yE
+Yx
+"}
+(11,1,1) = {"
+Yx
+Yx
+gr
+mY
+Tx
+nM
+Tx
+mY
+zy
+Yx
+Yx
+"}
diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index 159f1da9b45ff..96d638c893e31 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -285,6 +285,7 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list(
/datum/antagonist/nukeop,
/datum/antagonist/pirate,
/datum/antagonist/wizard,
+ /datum/antagonist/sapper, // DOPPLER ADDITION - sapper gang antag ⚡
))
/// Returns true if the given mob has an antag datum which is assigned to a human antagonist who doesn't spawn on the space station
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index 9d2cf451c62e1..56e39fd198899 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -66,6 +66,10 @@
#define AWAY_IMPRINTER (1<<9)
/// For wiremod/integrated circuits. Uses various minerals.
#define COMPONENT_PRINTER (1<<10)
+// DOPPLER EDIT ADDITION
+/// Can be made by the orderable colony fabricator
+#define COLONY_FABRICATOR (1<<11)
+// DOPPLER EDIT END
#define HYPERTORUS_INACTIVE 0 // No or minimal energy
#define HYPERTORUS_NOMINAL 1 // Normal operation
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index a5725326a3c73..004c6faf73fae 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -712,6 +712,9 @@ GLOBAL_LIST_INIT(human_heights_to_offsets, list(
#define DAMAGE_LAYER 28
/// Jumpsuit clothing layer
#define UNIFORM_LAYER 27
+/// DOPPLER SHIFT ADDITION BEGIN
+#define BANDAGE_LAYER 26.5
+/// DOPPLER SHIFT ADDITION END
/// ID card layer
#define ID_LAYER 26
/// ID card layer (might be deprecated)
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index bc8987b4539d5..7e6dae616ae36 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -136,6 +136,9 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_SPY = 0,
// Midround
+ /* DOPPLER STATION ADDITIONS START */
+ ROLE_SPACE_SAPPER = 0,
+ /* DOPPLER STATION ADDITIONS END */
ROLE_ABDUCTOR = 0,
ROLE_ALIEN = 0,
ROLE_BLOB = 0,
diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm
index 91614c7d8a7e5..79dfb13edfcfc 100644
--- a/code/__DEFINES/wounds.dm
+++ b/code/__DEFINES/wounds.dm
@@ -128,6 +128,11 @@ GLOBAL_LIST_INIT(bio_state_anatomy, list(
/// Cranial fissure wound.
#define WOUND_SERIES_CRANIAL_FISSURE "wound_series_cranial_fissure"
+// NOVA EDIT ADDITION BEGIN - MUSCLE AND SYNTH WOUNDS
+// Have to put it here so I can use it in the global list of wound series
+/// See muscle.dm and robotic_blunt.dm
+#define WOUND_SERIES_MUSCLE_DAMAGE "nova_wound_series_muscle_damage"
+
/// A assoc list of (wound typepath -> wound_pregen_data instance). Every wound should have a pregen data.
GLOBAL_LIST_INIT_TYPED(all_wound_pregen_data, /datum/wound_pregen_data, generate_wound_static_data())
diff --git a/code/__DEFINES/~doppler_defines/DNA.dm b/code/__DEFINES/~doppler_defines/DNA.dm
new file mode 100644
index 0000000000000..9183d1e4c9d98
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/DNA.dm
@@ -0,0 +1,6 @@
+//Defines for processing reagents, for synths, IPC's and Vox
+#define PROCESS_ORGANIC 1 //Only processes reagents with "ORGANIC" or "ORGANIC | SYNTHETIC"
+#define PROCESS_SYNTHETIC 2 //Only processes reagents with "SYNTHETIC" or "ORGANIC | SYNTHETIC"
+
+#define REAGENT_ORGANIC 1
+#define REAGENT_SYNTHETIC 2
diff --git a/code/__DEFINES/~doppler_defines/access.dm b/code/__DEFINES/~doppler_defines/access.dm
new file mode 100644
index 0000000000000..e9d93326eba82
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/access.dm
@@ -0,0 +1,11 @@
+
+/* Access is broken down by department, department special functions/rooms, and departmental roles
+* The first access for the department will always be its general access function
+* Please try to make the strings for any new accesses as close to the name of the define as possible
+* If you are going to add an access to the list, make sure to also add it to its respective region further below
+* If you're varediting on the map, it uses the string. If you're editing the object directly, use the define name
+*/
+
+/// - - - ANTAGONIST - - -
+/// PLUTONIAN
+#define ACCESS_SAPPER_SHIP "sapper_ship"
diff --git a/code/__DEFINES/~doppler_defines/armor_defines.dm b/code/__DEFINES/~doppler_defines/armor_defines.dm
new file mode 100644
index 0000000000000..bfb239621e2a7
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/armor_defines.dm
@@ -0,0 +1,8 @@
+#define ARMOR_LEVEL_TINY 10
+#define ARMOR_LEVEL_WEAK 30
+#define ARMOR_LEVEL_MID 50
+#define ARMOR_LEVEL_INSANE 90
+
+#define WOUND_ARMOR_WEAK 10
+#define WOUND_ARMOR_STANDARD 20
+#define WOUND_ARMOR_HIGH 30
diff --git a/code/__DEFINES/~doppler_defines/atom_hud.dm b/code/__DEFINES/~doppler_defines/atom_hud.dm
new file mode 100644
index 0000000000000..f184fa7b2f894
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/atom_hud.dm
@@ -0,0 +1,8 @@
+// for secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list
+// note: if you add more HUDs, even for non-human atoms, make sure to use unique numbers for the defines!
+// /datum/atom_hud expects these to be unique
+// these need to be strings in order to make them associative lists
+
+/// - - - ANTAGONIST - - -
+/// PLUTONIAN
+#define SECHUD_SAPPER "hudsapper"
diff --git a/code/__DEFINES/~doppler_defines/cells.dm b/code/__DEFINES/~doppler_defines/cells.dm
new file mode 100644
index 0000000000000..376910741b2b7
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/cells.dm
@@ -0,0 +1,13 @@
+//General defines for items that use power and the cell component.
+/// The minimal amount of power an item can use.
+#define POWER_CELL_USE_MINIMUM 1
+/// For items that barely use any power at all.
+#define POWER_CELL_USE_VERY_LOW 10
+/// For items that generally wouldn't use very much power.
+#define POWER_CELL_USE_LOW 30
+/// For items that use a average amount of power.
+#define POWER_CELL_USE_NORMAL 50
+/// For items that use a high amount of power.
+#define POWER_CELL_USE_HIGH 70
+/// For items that use A LOT OF POWER.
+#define POWER_CELL_USE_INSANE 100
diff --git a/code/__DEFINES/~doppler_defines/colony_fabricator_misc.dm b/code/__DEFINES/~doppler_defines/colony_fabricator_misc.dm
new file mode 100644
index 0000000000000..313c2477cb45e
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/colony_fabricator_misc.dm
@@ -0,0 +1,44 @@
+/// Category for clothing in the organics printer
+#define RND_CATEGORY_AKHTER_CLOTHING "Clothing"
+/// Category for equipment like belts and bags in the organics printer
+#define RND_CATEGORY_AKHTER_EQUIPMENT "Equipment"
+/// Category for resources made by the organics printer
+#define RND_CATEGORY_AKHTER_RESOURCES "Resources"
+
+/// Category for ingredients in the ration printer
+#define RND_CATEGORY_AKHTER_FOODRICATOR_INGREDIENTS "Ingredients"
+/// Category for bags and containers of reagents in the ration printer
+#define RND_CATEGORY_AKHTER_FOODRICATOR_BAGS "Containers"
+/// Category for snacks in the ration printer
+#define RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS "Luxuries"
+/// Category for utensils and whatnot in the ration printer
+#define RND_CATEGORY_AKHTER_FOODRICATOR_UTENSILS "Utensils"
+/// Category for the seeds the organics printer can make
+#define RND_CATEGORY_AKHTER_SEEDS "Synthesized Seeds"
+
+/// Medical items in the deforest medstation
+#define RND_CATEGORY_DEFOREST_MEDICAL "Emergency Medical"
+/// Blood and blood bags
+#define RND_CATEGORY_DEFOREST_BLOOD "Synthesized Blood"
+
+/// The items the frontier clothing can hold
+GLOBAL_LIST_INIT(colonist_suit_allowed, list(
+ /obj/item/ammo_box,
+ /obj/item/ammo_casing,
+ /obj/item/flashlight,
+ /obj/item/gun,
+ /obj/item/melee,
+ /obj/item/tank/internals,
+ /obj/item/storage/belt/holster,
+ /obj/item/construction,
+ /obj/item/fireaxe,
+ /obj/item/pipe_dispenser,
+ /obj/item/storage/bag,
+ /obj/item/pickaxe,
+ /obj/item/resonator,
+ /obj/item/t_scanner,
+ /obj/item/analyzer,
+ /obj/item/storage/medkit,
+ /obj/item/fireaxe/metal_h2_axe,
+ /obj/item/forging/reagent_weapon,
+))
diff --git a/code/__DEFINES/~doppler_defines/declarations.dm b/code/__DEFINES/~doppler_defines/declarations.dm
new file mode 100644
index 0000000000000..37dbb5fd21780
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/declarations.dm
@@ -0,0 +1,4 @@
+/// Trait that changes the ending effects of twitch leaving your system
+#define TRAIT_TWITCH_ADAPTED "twitch_adapted"
+/// Given to the detective, if they have this, they can see syndicate special descriptions.
+#define TRAIT_DETECTIVE "detective_ability"
diff --git a/code/__DEFINES/~doppler_defines/examinemore.dm b/code/__DEFINES/~doppler_defines/examinemore.dm
new file mode 100644
index 0000000000000..2c942cd321543
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/examinemore.dm
@@ -0,0 +1,14 @@
+/*
+These are the defines for controlling what conditions are required to display
+an items special description.
+
+See the examinemore module for information.
+*/
+
+#define EXAMINE_CHECK_NONE "none" //Displays the special_desc regardless if it's set.
+#define EXAMINE_CHECK_SYNDICATE "syndicate" //For displaying descriptors for those with the SYNDICATE faction assigned.
+#define EXAMINE_CHECK_SYNDICATE_TOY "syndicate_toy" //Ditto, only instead of displaying nothing for heathens, it shows "The src looks like a toy, not the real thing."
+#define EXAMINE_CHECK_MINDSHIELD "mindshield" //For displaying descriptors for those with a mindshield implant.
+#define EXAMINE_CHECK_ROLE "role" //For displaying description information based on a specific ROLE, e.g. traitor. Remember to set the special_desc_role var on the item.
+#define EXAMINE_CHECK_JOB "job" //For displaying descriptors for specific jobs, e.g scientist. Remember to set the special_desc_job var on the item.
+#define EXAMINE_CHECK_FACTION "faction" //For displaying descriptors for mob factions, e.g. a zombie, or... turrets. Or syndicate. Remember to set special_desc_factions.
diff --git a/code/__DEFINES/~doppler_defines/manufacturer_strings.dm b/code/__DEFINES/~doppler_defines/manufacturer_strings.dm
new file mode 100644
index 0000000000000..81819d4f0ef35
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/manufacturer_strings.dm
@@ -0,0 +1,30 @@
+// Text for what examine blurb will come up when used with /datum/element/manufacturer_examine
+// Very loosely grouped based on what company makes what mainly for your viewing pleasure
+
+#define COMPANY_DONK "It has a [span_green("Donk Corporation")] label visible on it."
+#define COMPANY_BOLT "It has [span_yellow("Bolt Fabrications")] stamped onto it."
+#define COMPANY_NANOTRASEN "It has [span_blue("Nanotrasen Armories")] etched into it."
+
+#define COMPANY_CARWO "It has a small [span_cyan("four pointed star")] alongside [span_cyan("Carwo Defense Systems")] etched into it."
+#define COMPANY_TRAPPISTE "It has a small [span_red("pattern of five squares")] alongside [span_red("Trappiste Fabriek")] etched into it."
+
+#define COMPANY_CYBERSUN "It has a [span_red("red circle")] broken by a hexagonal flower alongside [span_red("Cybersun Industries")] in Konjin etched into it."
+#define COMPANY_SCARBOROUGH "It has [span_orange("Scarborough Arms")] stamped onto it."
+#define COMPANY_INTERDYNE "It has [span_cyan("Interdyne Pharmaceuticals")] stamped onto it."
+
+#define COMPANY_ALLSTAR "It has [span_red("Allstar Lasers Inc.")] stamped onto it."
+#define COMPANY_MICRON "It has [span_cyan("Micron Control Sys.")] cut into it."
+
+#define COMPANY_NAKAMURA "It has [span_orange("Nakamura Engineering")] embossed onto it."
+#define COMPANY_BLACKSTEEL "It bears the [span_grey("crossed sword and hammer")] crafter's mark of the [span_grey("Jarnsmiour Blacksteel Foundation")] upon its fore."
+
+#define COMPANY_SZOT "It has a small [span_engradio("three point crown")] alongside [span_engradio("Szot Dynamica")] cut into it."
+#define COMPANY_SAKHNO "It has [span_green("Sakhno Concern")] stamped onto it."
+#define COMPANY_XHIHAO "It has [span_purple("Xhihao Light Arms")] etched into it."
+
+#define COMPANY_ABDUCTOR "It has [span_abductor("✌︎︎♌︎︎♎︎︎◆︎︎♍︎︎⧫︎︎❄︎♏︎♍︎♒︎")] engraved into it."
+
+#define COMPANY_FRONTIER "It has a small label with [span_engradio("Akhter Company Frontier Equipment")] printed on it, alongside various xerxian proof-marks."
+#define COMPANY_KAHRAMAN "It has a [span_red("red label")] with [span_red("K - A - S")] printed on it, alongside various xerxian proof-marks."
+
+#define COMPANY_REMOVED "It has had [span_grey("all identifying marks scrubbed off")]."
diff --git a/code/__DEFINES/~doppler_defines/mobfactions.dm b/code/__DEFINES/~doppler_defines/mobfactions.dm
new file mode 100644
index 0000000000000..738ef89060f79
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/mobfactions.dm
@@ -0,0 +1,5 @@
+// Contains mob factions that are not handled by special role defines (for example, viscerators having ROLE_SYNDICATE)
+
+/// - - - ANTAGONIST - - -
+/// PLUTONIAN
+#define FACTION_SAPPER "sapper"
diff --git a/code/__DEFINES/~doppler_defines/role_preferences.dm b/code/__DEFINES/~doppler_defines/role_preferences.dm
new file mode 100644
index 0000000000000..bcdd604e7ba63
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/role_preferences.dm
@@ -0,0 +1,9 @@
+//Values for antag preferences, event roles, etc. unified here
+
+
+
+//These are synced with the Database, if you change the values of the defines
+//then you MUST update the database!
+
+// Midround roles
+#define ROLE_SPACE_SAPPER "Space Sapper"
diff --git a/code/__DEFINES/~doppler_defines/signals.dm b/code/__DEFINES/~doppler_defines/signals.dm
index 9142e6086a8ab..2cb1bc8d372ef 100644
--- a/code/__DEFINES/~doppler_defines/signals.dm
+++ b/code/__DEFINES/~doppler_defines/signals.dm
@@ -1,2 +1,10 @@
///Fired in combat_indicator.dm, used for syncing CI between mech and pilot
#define COMSIG_MOB_CI_TOGGLED "mob_ci_toggled"
+
+// Power signals
+/// Sent when an obj/item calls item_use_power: (use_amount, user, check_only)
+#define COMSIG_ITEM_POWER_USE "item_use_power"
+ #define NO_COMPONENT NONE
+ #define COMPONENT_POWER_SUCCESS (1<<0)
+ #define COMPONENT_NO_CELL (1<<1)
+ #define COMPONENT_NO_CHARGE (1<<2)
diff --git a/code/__DEFINES/~doppler_defines/span.dm b/code/__DEFINES/~doppler_defines/span.dm
index c72af85fd2664..4c3c1bd145f99 100644
--- a/code/__DEFINES/~doppler_defines/span.dm
+++ b/code/__DEFINES/~doppler_defines/span.dm
@@ -1 +1,6 @@
#define span_italics(str) ("" + str + "")
+#define span_pink(str) ("" + str + "")
+#define span_brown(str) ("" + str + "")
+#define span_cyan(str) ("" + str + "")
+#define span_orange(str) ("" + str + "")
+#define span_yellow(str) ("" + str + "")
diff --git a/code/__DEFINES/~doppler_defines/wounds.dm b/code/__DEFINES/~doppler_defines/wounds.dm
new file mode 100644
index 0000000000000..f6a9275db8e24
--- /dev/null
+++ b/code/__DEFINES/~doppler_defines/wounds.dm
@@ -0,0 +1,2 @@
+/// If this wound, when bandaged, will cause a splint overlay to generate rather than a bandage overlay.
+#define SPLINT_OVERLAY (1<<200) // we use a big number since tg realistically wouldnt go to it
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index b92f2b7ff040f..4837cf47551a3 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -678,12 +678,14 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_TURF_IGNORE_SLIPPERY" = TRAIT_TURF_IGNORE_SLIPPERY,
"TRAIT_TURF_IGNORE_SLOWDOWN" = TRAIT_TURF_IGNORE_SLOWDOWN,
),
- // DOPPLER EDIT ADDITION START - DOPPLER TRAITS
- /obj/item/clothing/suit/jacket/doppler = list(
+ // DOPPLER EDIT ADDITION START - MODULAR TRAITS
+ /obj/item/toy/plush/modular = list(
"TRAIT_CURRENTLY_GLASSBLOWING" = TRAIT_CURRENTLY_GLASSBLOWING,
"TRAIT_FELINE" = TRAIT_FELINE,
"TRAIT_GLASSBLOWING" = TRAIT_GLASSBLOWING,
"TRAIT_XENOARCH_QUALIFIED" = TRAIT_XENOARCH_QUALIFIED,
+ "TRAIT_DETECTIVE" = TRAIT_DETECTIVE,
+ "TRAIT_TWITCH_ADAPTED" = TRAIT_TWITCH_ADAPTED,
),
// DOPPLER EDIT ADDITION END
))
diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm
index e92bc8ec4ae72..26045c4e7c075 100644
--- a/code/_globalvars/traits/admin_tooling.dm
+++ b/code/_globalvars/traits/admin_tooling.dm
@@ -369,12 +369,14 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
/obj/item/organ/internal/lungs = list(
"TRAIT_SPACEBREATHING" = TRAIT_SPACEBREATHING,
),
- // DOPPLER EDIT ADDITION START - DOPPLER TRAITS
- /obj/item/clothing/suit/jacket/doppler = list(
+ // DOPPLER EDIT ADDITION START - MODULAR TRAITS
+ /obj/item/toy/plush/modular = list(
"TRAIT_CURRENTLY_GLASSBLOWING" = TRAIT_CURRENTLY_GLASSBLOWING,
"TRAIT_FELINE" = TRAIT_FELINE,
"TRAIT_GLASSBLOWING" = TRAIT_GLASSBLOWING,
"TRAIT_XENOARCH_QUALIFIED" = TRAIT_XENOARCH_QUALIFIED,
+ "TRAIT_DETECTIVE" = TRAIT_DETECTIVE,
+ "TRAIT_TWITCH_ADAPTED" = TRAIT_TWITCH_ADAPTED,
),
// DOPPLER EDIT ADDITION END
))
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 978714e9bf7a3..ae0ad9c6662bf 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -561,11 +561,11 @@
if (!IS_ORGANIC_LIMB(limb))
. += (limb.brute_dam * limb.body_damage_coeff) + (limb.burn_dam * limb.body_damage_coeff)
-/mob/living/carbon/grabbedby(mob/living/user, supress_message = FALSE)
+/mob/living/carbon/grabbedby(mob/living/user, supress_message = FALSE, grabbed_part) // DOPPLER EDIT CHANGE - ORIGINAL: /mob/living/carbon/grabbedby(mob/living/user, supress_message = FALSE)
if(user != src)
return ..()
- var/obj/item/bodypart/grasped_part = get_bodypart(zone_selected)
+ var/obj/item/bodypart/grasped_part = grabbed_part ? grabbed_part : get_bodypart(zone_selected) // DOPPLER EDIT CHANGE - ORIGINAL: var/obj/item/bodypart/grasped_part = get_bodypart(zone_selected)
if(!grasped_part?.can_be_grasped())
return
var/starting_hand_index = active_hand_index
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 7e724d8862117..88525b91bd874 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -252,7 +252,7 @@
/**
* Called when this mob is grabbed by another mob.
*/
-/mob/living/proc/grabbedby(mob/living/user, supress_message = FALSE)
+/mob/living/proc/grabbedby(mob/living/user, supress_message = FALSE, grabbed_part) // DOPPLER EDIT CHANGE - ORIGINAL: /mob/living/proc/grabbedby(mob/living/user, supress_message = FALSE)
if(user == src || anchored || !isturf(user.loc))
return FALSE
diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm
index c69de9bb2d9c1..4d90e3cd34b29 100644
--- a/code/modules/research/machinery/_production.dm
+++ b/code/modules/research/machinery/_production.dm
@@ -214,7 +214,7 @@
* * path - the design path to check for
*/
/obj/machinery/rnd/production/proc/build_efficiency(path)
- PRIVATE_PROC(TRUE)
+ PROTECTED_PROC(TRUE) // DOPPLER EDIT CHANGE - ORIGINAL: PRIVATE_PROC(TRUE)
SHOULD_BE_PURE(TRUE)
if(ispath(path, /obj/item/stack/sheet) || ispath(path, /obj/item/stack/ore/bluespace_crystal))
diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_spacesapper.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_spacesapper.png
new file mode 100644
index 0000000000000..ee463666fca85
Binary files /dev/null and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_spacesapper.png differ
diff --git a/modular_doppler/cell_component/code/cell_component.dm b/modular_doppler/cell_component/code/cell_component.dm
new file mode 100644
index 0000000000000..c9e467bbd26b3
--- /dev/null
+++ b/modular_doppler/cell_component/code/cell_component.dm
@@ -0,0 +1,207 @@
+/*
+CELL COMPONENT
+
+What we aim to achieve with cell components is a universal framework for all items that would logically use batteries,
+Be it a flashlight, T-ray scanner or multitool. All of them would logically require batteries right? Well, welcome,
+to the cell component.
+
+General logic:
+Component attaches to parent(flashlight etc)
+Registers onhit signal to check if it's being slapped by a battery
+Component moves battery to equipment loc, keeps a record, and then communicates with
+the equipment and controls the behaviour of said equipment.
+
+If it's a robot, it uses the robot cell - Using certified shitcode.(this needs redone)
+
+If you are adding this to an item that is active for a period of time, register signal to COMSIG_CELL_START_USE when it would start using the cell
+and COMSIG_CELL_STOP_USE when it should stop. To handle the turning off of said item once the cell is depleted, add your code into the
+component_cell_out_of_charge/component_cell_removed proc using loc where necessary, processing is done in the component!
+*/
+
+/datum/component/cell
+ /// Our reference to the inserted cell, which will be stored in the parent.
+ var/obj/item/stock_parts/power_store/cell/inserted_cell
+ /// The item reference to parent.
+ var/obj/item/equipment
+ /// How much power do we use each process?
+ var/power_use_amount = POWER_CELL_USE_NORMAL
+ /// Are we using a robot's powersource?
+ var/inside_robot = FALSE
+ /// Callback interaction for when the cell is removed.
+ var/datum/callback/on_cell_removed = null
+ ///Can this cell be removed from the parent?
+ var/cell_can_be_removed = TRUE
+ ///Our reference to the cell overlay
+ var/mutable_appearance/cell_overlay = null
+ ///Do we have cell overlays to be applied?
+ var/has_cell_overlays
+
+/datum/component/cell/Initialize(cell_override, _on_cell_removed, _power_use_amount, start_with_cell = TRUE, _cell_can_be_removed, _has_cell_overlays = TRUE)
+ if(QDELETED(parent))
+ qdel(src)
+ return
+
+ if(!isitem(parent)) //Currently only compatable with items.
+ return COMPONENT_INCOMPATIBLE
+
+ equipment = parent //We'd like a simple reference to the atom this component is attached to instead of having to declare it every time we use it.
+
+ if(_on_cell_removed)
+ src.on_cell_removed = _on_cell_removed
+
+ has_cell_overlays = _has_cell_overlays
+
+ if(_power_use_amount)
+ power_use_amount = _power_use_amount
+ else
+ power_use_amount = equipment.power_use_amount
+
+ if(_cell_can_be_removed)
+ cell_can_be_removed = _cell_can_be_removed
+
+ //So this is shitcode in its ultimate form. Right now, as far as I can see, this is the only way to handle robot items that would normally use a cell.
+ if(istype(equipment.loc, /obj/item/robot_model)) //Really, I absolutely hate borg code.
+ inside_robot = TRUE
+ else if(start_with_cell)
+ var/obj/item/stock_parts/power_store/cell/new_cell
+ if(!cell_override)
+ new_cell = new /obj/item/stock_parts/power_store/cell/upgraded()
+ else
+ new_cell = new cell_override()
+ inserted_cell = new_cell
+ new_cell.forceMove(parent) //We use the parents location so things like EMP's can interact with the cell.
+ handle_cell_overlays()
+ return ..()
+
+/datum/component/cell/RegisterWithParent()
+ //Component to Parent signal registries
+ RegisterSignal(parent, COMSIG_ITEM_POWER_USE, PROC_REF(simple_power_use))
+ RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(insert_cell))
+ RegisterSignal(parent, COMSIG_CLICK_CTRL_SHIFT , PROC_REF(remove_cell))
+ RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examine_cell))
+
+/datum/component/cell/UnregisterFromParent()
+ UnregisterSignal(parent, COMSIG_ITEM_POWER_USE)
+ UnregisterSignal(parent, COMSIG_ATOM_ATTACKBY)
+ UnregisterSignal(parent, COMSIG_CLICK_CTRL_SHIFT)
+ UnregisterSignal(parent, COMSIG_ATOM_EXAMINE)
+
+/datum/component/cell/Destroy(force)
+ if(on_cell_removed)
+ on_cell_removed = null
+ if(inserted_cell)
+ if(!inside_robot) //We really don't want to be deleting the robot's cell.
+ QDEL_NULL(inserted_cell)
+ inserted_cell = null
+ return ..()
+
+/**
+ * The basic way of processing the cell, with included feedback.
+ *
+ * This proc is the basic way of processing the cell, with included feedback.
+ * It will return a bitflag if it failed to use the power, or COMPONENT_POWER_SUCCESS if it succeeds.
+ * Arguments:
+ * * use_amount - an override
+ * * check_only - will only return if it can use the cell and feedback relating to that including any relevant detail
+ */
+/datum/component/cell/proc/simple_power_use(datum/source, use_amount, mob/user, check_only)
+ SIGNAL_HANDLER
+
+ if(inside_robot)
+ return COMPONENT_POWER_SUCCESS
+
+ if(!use_amount)
+ use_amount = power_use_amount
+
+ if(!inserted_cell)
+ if(user)
+ to_chat(user, span_danger("There is no cell inside [equipment]"))
+ return COMPONENT_NO_CELL
+
+ if(check_only && inserted_cell.charge < use_amount)
+ if(user)
+ to_chat(user, span_danger("The cell inside [equipment] does not have enough charge to perform this action!"))
+ return COMPONENT_NO_CHARGE
+
+ if(!inserted_cell.use(use_amount))
+ inserted_cell.update_appearance() //Updates the attached cell sprite - Why does this not happen in cell.use?
+ if(user)
+ to_chat(user, span_danger("The cell inside [equipment] does not have enough charge to perform this action!"))
+ return COMPONENT_NO_CHARGE
+
+ inserted_cell.update_appearance()
+
+ return COMPONENT_POWER_SUCCESS
+
+/datum/component/cell/proc/examine_cell(atom/A, mob/user, list/examine_list)
+ SIGNAL_HANDLER
+
+ if(!inserted_cell)
+ examine_list += span_danger("It does not have a cell inserted!")
+ else if(!inside_robot)
+ examine_list += span_notice("It has [inserted_cell] inserted. It has [inserted_cell.percent()]% charge left. \
+ Ctrl+Shift+Click to remove the [inserted_cell].")
+ else
+ examine_list += span_notice("It is drawing power from an external powersource, reading [inserted_cell.percent()]% charge.")
+
+/// Handling of cell removal.
+/datum/component/cell/proc/remove_cell(datum/source, mob/user)
+ SIGNAL_HANDLER
+ if(!equipment.can_interact(user))
+ return
+
+ if(inside_robot)
+ return
+
+ if(!cell_can_be_removed)
+ return
+
+ if(!isliving(user))
+ return
+
+ if(inserted_cell)
+ to_chat(user, span_notice("You remove [inserted_cell] from [equipment]!"))
+ playsound(equipment, 'sound/weapons/magout.ogg', 40, TRUE)
+ inserted_cell.forceMove(get_turf(equipment))
+ INVOKE_ASYNC(user, TYPE_PROC_REF(/mob/living, put_in_hands), inserted_cell)
+ inserted_cell = null
+ if(on_cell_removed)
+ on_cell_removed.Invoke()
+ handle_cell_overlays(TRUE)
+ else
+ to_chat(user, span_danger("There is no cell inserted in [equipment]!"))
+
+/// Handling of cell insertion.
+/datum/component/cell/proc/insert_cell(datum/source, obj/item/inserting_item, mob/living/user, params)
+ SIGNAL_HANDLER
+ if(!equipment.can_interact(user))
+ return
+
+ if(inside_robot) //More robot shitcode, if we allowed them to remove the cell, it would cause the universe to implode.
+ return
+
+ if(!istype(inserting_item, /obj/item/stock_parts/power_store/cell))
+ return
+
+ if(inserted_cell) //No quickswap compatibility
+ to_chat(user, span_danger("There is already a cell inserted in [equipment]!"))
+ return
+
+ to_chat(user, span_notice("You insert [inserting_item] into [equipment]!"))
+ playsound(equipment, 'sound/weapons/magin.ogg', 40, TRUE)
+ inserted_cell = inserting_item
+ inserting_item.forceMove(parent)
+ handle_cell_overlays(FALSE)
+
+/datum/component/cell/proc/handle_cell_overlays(update_overlays)
+ if(!has_cell_overlays)
+ return
+ if(inserted_cell)
+ cell_overlay = mutable_appearance(equipment.icon, "[initial(equipment.icon_state)]_cell")
+ equipment.add_overlay(cell_overlay)
+ else
+ QDEL_NULL(cell_overlay)
+ cell_overlay = null
+ if(update_overlays)
+ equipment.overlays.Cut()
+ equipment.update_overlays()
diff --git a/modular_doppler/colony_fabricator/code/appliances/chem_machines.dm b/modular_doppler/colony_fabricator/code/appliances/chem_machines.dm
new file mode 100644
index 0000000000000..d3b46067d18dc
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/chem_machines.dm
@@ -0,0 +1,146 @@
+// Machine that makes water and nothing else
+
+/obj/machinery/plumbing/synthesizer/water_synth
+ name = "water synthesizer"
+ desc = "An infinitely useful device for those finding themselves in a frontier without a stable source of water. \
+ Using a simplified version of the chemistry dispenser's synthesizer process, it can create water out of nothing \
+ but good old electricity."
+ icon = 'modular_doppler/colony_fabricator/icons/chemistry_machines.dmi'
+ icon_state = "water_synth"
+ anchored = FALSE
+ /// Reagents that this can dispense, overrides the default list on init
+ var/static/list/synthesizable_reagents = list(
+ /datum/reagent/water,
+ )
+ /// What this repacks into
+ var/repacked_type = /obj/item/flatpacked_machine/water_synth
+
+/obj/machinery/plumbing/synthesizer/water_synth/Initialize(mapload, bolt = FALSE, layer)
+ . = ..()
+ dispensable_reagents = synthesizable_reagents
+ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+// Deployable item for cargo for the water synth
+
+/obj/item/flatpacked_machine/water_synth
+ name = "water synthesizer parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/chemistry_machines.dmi'
+ icon_state = "water_synth_parts"
+ w_class = WEIGHT_CLASS_NORMAL
+ type_to_deploy = /obj/machinery/plumbing/synthesizer/water_synth
+ deploy_time = 2 SECONDS
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ )
+
+// Machine that makes botany nutrients for hydroponics farming
+
+/obj/machinery/plumbing/synthesizer/colony_hydroponics
+ name = "hydroponics chemical synthesizer"
+ desc = "An infinitely useful device for those finding themselves in a frontier without a stable source of nutrients for crops. \
+ Using a simplified version of the chemistry dispenser's synthesizer process, it can create hydroponics nutrients out of nothing \
+ but good old electricity."
+ icon = 'modular_doppler/colony_fabricator/icons/chemistry_machines.dmi'
+ icon_state = "hydro_synth"
+ anchored = FALSE
+ /// Reagents that this can dispense, overrides the default list on init
+ var/static/list/synthesizable_reagents = list(
+ /datum/reagent/plantnutriment/eznutriment,
+ /datum/reagent/plantnutriment/left4zednutriment,
+ /datum/reagent/plantnutriment/robustharvestnutriment,
+ /datum/reagent/plantnutriment/endurogrow,
+ /datum/reagent/plantnutriment/liquidearthquake,
+ /datum/reagent/toxin/plantbgone/weedkiller,
+ /datum/reagent/toxin/pestkiller,
+ )
+ /// What this repacks into
+ var/repacked_type = /obj/item/flatpacked_machine/hydro_synth
+
+/obj/machinery/plumbing/synthesizer/colony_hydroponics/Initialize(mapload, bolt = FALSE, layer)
+ . = ..()
+ dispensable_reagents = synthesizable_reagents
+ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+// Deployable item for cargo for the hydro synth
+
+/obj/item/flatpacked_machine/hydro_synth
+ name = "hydroponics chemical synthesizer parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/chemistry_machines.dmi'
+ icon_state = "hydro_synth_parts"
+ w_class = WEIGHT_CLASS_NORMAL
+ type_to_deploy = /obj/machinery/plumbing/synthesizer/colony_hydroponics
+ deploy_time = 2 SECONDS
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ )
+
+// Chem dispenser with a limited range of thematic reagents to dispense
+
+/obj/machinery/chem_dispenser/frontier_appliance
+ name = "sustenance dispenser"
+ desc = "Creates and dispenses a small pre-defined set of chemicals and other liquids for the convenience of those typically on the frontier. \
+ While the machine is loved by many, it also has a reputation for making some of the worst coffees this side of the galaxy. Use at your own risk."
+ icon = 'modular_doppler/colony_fabricator/icons/chemistry_machines.dmi'
+ icon_state = "dispenser"
+ base_icon_state = "dispenser"
+ pass_flags = PASSTABLE
+ anchored_tabletop_offset = 4
+ anchored = FALSE
+ circuit = null
+ power_cost = 0.4 KILO JOULES
+ recharge_amount = 2 KILO WATTS //50 secs for full charge but shouldn't kill our crappy colony powergrid.
+ show_ph = FALSE
+ base_reagent_purity = 0.5
+ // God's strongest coffee machine
+ dispensable_reagents = list(
+ /datum/reagent/water,
+ /datum/reagent/consumable/powdered_milk,
+ /datum/reagent/consumable/sugar,
+ /datum/reagent/consumable/powdered_lemonade,
+ /datum/reagent/consumable/powdered_coco,
+ /datum/reagent/consumable/powdered_coffee,
+ /datum/reagent/consumable/powdered_tea,
+ /datum/reagent/consumable/vanilla,
+ /datum/reagent/consumable/caramel,
+ /datum/reagent/consumable/korta_nectar,
+ /datum/reagent/consumable/korta_milk,
+ /datum/reagent/consumable/astrotame,
+ /datum/reagent/consumable/salt,
+ /datum/reagent/consumable/blackpepper,
+ /datum/reagent/consumable/nutraslop,
+ /datum/reagent/consumable/enzyme,
+ )
+ /// Since we don't have a board to take from, we use this to give the dispenser a cell on spawning
+ var/cell_we_spawn_with = /obj/item/stock_parts/power_store/cell/high
+
+/obj/machinery/chem_dispenser/frontier_appliance/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ cell = new cell_we_spawn_with(src)
+
+/obj/machinery/chem_dispenser/frontier_appliance/display_beaker()
+ var/mutable_appearance/overlayed_beaker = beaker_overlay || mutable_appearance(icon, "disp_beaker")
+ return overlayed_beaker
+
+/obj/machinery/chem_dispenser/frontier_appliance/examine(mob/user)
+ . = ..()
+ . += span_notice("It cannot be repacked, but can be deconstructed normally.")
+
+// Deployable item for cargo for the sustenance machine
+
+/obj/item/flatpacked_machine/sustenance_machine
+ name = "sustenance dispenser parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/chemistry_machines.dmi'
+ icon_state = "dispenser_parts"
+ w_class = WEIGHT_CLASS_NORMAL
+ type_to_deploy = /obj/machinery/chem_dispenser/frontier_appliance
+ deploy_time = 2 SECONDS
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/appliances/co2_cracker.dm b/modular_doppler/colony_fabricator/code/appliances/co2_cracker.dm
new file mode 100644
index 0000000000000..39d642e9f7a77
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/co2_cracker.dm
@@ -0,0 +1,121 @@
+// We can't just use electrolyzer reactions, because that'd let electrolyzers do co2 cracking
+
+GLOBAL_LIST_INIT(cracker_reactions, cracker_reactions_list())
+
+/// Global proc to build up the list of co2 cracker reactions
+/proc/cracker_reactions_list()
+ var/list/built_reaction_list = list()
+ for(var/reaction_path in subtypesof(/datum/cracker_reaction))
+ var/datum/cracker_reaction/reaction = new reaction_path()
+
+ built_reaction_list[reaction.id] = reaction
+
+ return built_reaction_list
+
+/datum/cracker_reaction
+ var/list/requirements
+ var/name = "reaction"
+ var/id = "r"
+ var/desc = ""
+ var/list/factor
+
+/// Called when the co2 cracker reaction is run, should be where the code for actually changing gasses around is run
+/datum/cracker_reaction/proc/react(turf/location, datum/gas_mixture/air_mixture, working_power)
+ return
+
+/// Checks if this reaction can actually be run
+/datum/cracker_reaction/proc/reaction_check(datum/gas_mixture/air_mixture)
+ var/temp = air_mixture.temperature
+ var/list/cached_gases = air_mixture.gases
+ if((requirements["MIN_TEMP"] && temp < requirements["MIN_TEMP"]) || (requirements["MAX_TEMP"] && temp > requirements["MAX_TEMP"]))
+ return FALSE
+ for(var/id in requirements)
+ if(id == "MIN_TEMP" || id == "MAX_TEMP")
+ continue
+ if(!cached_gases[id] || cached_gases[id][MOLES] < requirements[id])
+ return FALSE
+ return TRUE
+
+/datum/cracker_reaction/co2_cracking
+ name = "CO2 Cracking"
+ id = "co2_cracking"
+ desc = "Conversion of CO2 into equal amounts of O2"
+ requirements = list(
+ /datum/gas/carbon_dioxide = MINIMUM_MOLE_COUNT,
+ )
+ factor = list(
+ /datum/gas/carbon_dioxide = "1 mole of CO2 gets consumed",
+ /datum/gas/oxygen = "1 mole of O2 gets produced",
+ "Location" = "Can only happen on turfs with an active CO2 cracker.",
+ )
+
+/datum/cracker_reaction/co2_cracking/react(turf/location, datum/gas_mixture/air_mixture, working_power)
+ var/old_heat_capacity = air_mixture.heat_capacity()
+ air_mixture.assert_gases(/datum/gas/water_vapor, /datum/gas/oxygen)
+ var/proportion = min(air_mixture.gases[/datum/gas/carbon_dioxide][MOLES] * INVERSE(2), (2.5 * (working_power ** 2)))
+ air_mixture.gases[/datum/gas/carbon_dioxide][MOLES] -= proportion
+ air_mixture.gases[/datum/gas/oxygen][MOLES] += proportion
+ var/new_heat_capacity = air_mixture.heat_capacity()
+ if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
+ air_mixture.temperature = max(air_mixture.temperature * old_heat_capacity / new_heat_capacity, TCMB)
+
+// CO2 cracker machine itself
+
+/obj/machinery/electrolyzer/co2_cracker
+ name = "portable CO2 cracker"
+ desc = "A portable device that is the savior of many a colony on the frontier. Performing similarly to an electrolyzer, \
+ it takes in nearby gasses and breaks them into different gasses. The big draw of this one? It can crack carbon dioxide \
+ into breathable oxygen. Handy for places where CO2 is all too common, and oxygen is all too hard to find."
+ icon = 'modular_doppler/colony_fabricator/icons/portable_machines.dmi'
+ circuit = null
+ working_power = 1
+ /// Soundloop for while the thermomachine is turned on
+ var/datum/looping_sound/conditioner_running/soundloop
+ /// What this repacks into
+ var/repacked_type = /obj/item/flatpacked_machine/co2_cracker
+
+/obj/machinery/electrolyzer/co2_cracker/Initialize(mapload)
+ . = ..()
+ soundloop = new(src, FALSE)
+ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+/obj/machinery/electrolyzer/co2_cracker/process_atmos()
+ if(on && !soundloop.loop_started)
+ soundloop.start()
+ else if(soundloop.loop_started)
+ soundloop.stop()
+ return ..()
+
+/obj/machinery/electrolyzer/co2_cracker/call_reactions(datum/gas_mixture/env)
+ for(var/reaction in GLOB.cracker_reactions)
+ var/datum/cracker_reaction/current_reaction = GLOB.cracker_reactions[reaction]
+
+ if(!current_reaction.reaction_check(env))
+ continue
+
+ current_reaction.react(loc, env, working_power)
+
+ env.garbage_collect()
+
+/obj/machinery/electrolyzer/co2_cracker/RefreshParts()
+ . = ..()
+ working_power = 2
+ efficiency = 1
+
+/obj/machinery/electrolyzer/co2_cracker/crowbar_act(mob/living/user, obj/item/tool)
+ return
+
+// "parts kit" for buying these from cargo
+
+/obj/item/flatpacked_machine/co2_cracker
+ name = "CO2 cracker parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/parts_kits.dmi'
+ icon_state = "co2_cracker"
+ type_to_deploy = /obj/machinery/electrolyzer/co2_cracker
+ deploy_time = 2 SECONDS
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/plasma = HALF_SHEET_MATERIAL_AMOUNT, // We're gonna pretend plasma is the catalyst for co2 cracking
+ )
diff --git a/modular_doppler/colony_fabricator/code/appliances/foodricator.dm b/modular_doppler/colony_fabricator/code/appliances/foodricator.dm
new file mode 100644
index 0000000000000..2e0775ec4f3d5
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/foodricator.dm
@@ -0,0 +1,50 @@
+/obj/machinery/biogenerator/foodricator
+ name = "organic rations printer"
+ desc = "An advanced machine seen in frontier outposts and colonies capable of turning organic plant matter into \
+ various foods or ingredients. The best friend of a chef where deliveries are inconsistent or simply don't exist. \
+ Some of those that consume the food from this complain that the foods it makes have poor taste, though they must \
+ not appreciate being able to eat steak and eggs for breakfast with a lack of any livestock at all in the colony."
+ icon = 'modular_doppler/colony_fabricator/icons/foodricator.dmi'
+ circuit = null
+ anchored = FALSE
+ pass_flags = PASSTABLE
+ efficiency = 1
+ productivity = 2.5
+ anchored_tabletop_offset = 6
+ show_categories = list(
+ RND_CATEGORY_AKHTER_FOODRICATOR_INGREDIENTS,
+ RND_CATEGORY_AKHTER_FOODRICATOR_BAGS,
+ RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS,
+ RND_CATEGORY_AKHTER_FOODRICATOR_UTENSILS,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
+ /// What this repacks into
+ var/repacked_type = /obj/item/flatpacked_machine/organics_ration_printer
+
+/obj/machinery/biogenerator/foodricator/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ AddElement(/datum/element/repackable, repacked_type, 5 SECONDS)
+
+/obj/machinery/biogenerator/foodricator/RefreshParts()
+ . = ..()
+ efficiency = 1
+ productivity = 3
+
+/obj/machinery/biogenerator/foodricator/default_deconstruction_crowbar()
+ return
+
+// Deployable item for cargo for the rations printer
+
+/obj/item/flatpacked_machine/organics_ration_printer
+ name = "organic rations printer parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/foodricator.dmi'
+ icon_state = "biogenerator_parts"
+ type_to_deploy = /obj/machinery/biogenerator/foodricator
+ w_class = WEIGHT_CLASS_NORMAL
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/silver = SHEET_MATERIAL_AMOUNT,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/griddle.dm b/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/griddle.dm
new file mode 100644
index 0000000000000..53101f84a59df
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/griddle.dm
@@ -0,0 +1,38 @@
+/obj/machinery/griddle/frontier_tabletop
+ name = "tabletop griddle"
+ desc = "A griddle type slim enough to fit atop a table without much fuss. This type in particular \
+ was made to be broken down into many parts and shipped across the glaxy. This makes it a favourite in \
+ pop-up food stalls and colony kitchens all around."
+ icon = 'modular_doppler/colony_fabricator/icons/kitchen_stuff/griddle.dmi'
+ icon_state = "griddletable_off"
+ variant = "table"
+ pass_flags_self = LETPASSTHROW
+ pass_flags = PASSTABLE
+ circuit = null
+ // Lines up perfectly with tables when anchored on them
+ anchored_tabletop_offset = 3
+ /// What type this repacks into
+ var/repacked_type = /obj/item/flatpacked_machine/frontier_griddle
+
+/obj/machinery/griddle/frontier_tabletop/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+/obj/machinery/griddle/frontier_tabletop/unanchored
+ anchored = FALSE
+
+// Deployable item for cargo
+
+/obj/item/flatpacked_machine/frontier_griddle
+ name = "flat-packed tabletop griddle"
+ icon = 'modular_doppler/colony_fabricator/icons/kitchen_stuff/griddle.dmi'
+ icon_state = "griddle_parts"
+ w_class = WEIGHT_CLASS_NORMAL
+ type_to_deploy = /obj/machinery/griddle/frontier_tabletop
+ deploy_time = 2 SECONDS
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/macrowave.dm b/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/macrowave.dm
new file mode 100644
index 0000000000000..07053542263bb
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/macrowave.dm
@@ -0,0 +1,42 @@
+/obj/machinery/microwave/frontier_printed
+ desc = "A plastic-paneled microwave oven, capable of doing anything a standard microwave could do. \
+ This one is special designed to be tightly packed into a shape that can be easily re-assembled \
+ later from the factory. There don't seem to be included instructions on getting it folded back \
+ together, though..."
+ icon = 'modular_doppler/colony_fabricator/icons/kitchen_stuff/microwave.dmi'
+ circuit = null
+ max_n_of_items = 5
+ efficiency = 2
+ vampire_charging_capable = TRUE
+
+/obj/machinery/microwave/frontier_printed/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+/obj/machinery/microwave/frontier_printed/RefreshParts()
+ . = ..()
+ max_n_of_items = 5
+ efficiency = 2
+ vampire_charging_capable = TRUE
+
+/obj/machinery/microwave/frontier_printed/examine(mob/user)
+ . = ..()
+ . += span_notice("It cannot be repacked, but can be deconstructed normally.")
+
+/obj/machinery/microwave/frontier_printed/unanchored
+ anchored = FALSE
+
+// Deployable item for cargo
+
+/obj/item/flatpacked_machine/macrowave
+ name = "microwave oven parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/kitchen_stuff/microwave.dmi'
+ icon_state = "packed_microwave"
+ w_class = WEIGHT_CLASS_NORMAL
+ type_to_deploy = /obj/machinery/microwave/frontier_printed
+ deploy_time = 2 SECONDS
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/range.dm b/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/range.dm
new file mode 100644
index 0000000000000..f598b9fae81ed
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/kitchen_appliances/range.dm
@@ -0,0 +1,38 @@
+/obj/machinery/oven/range_frontier
+ name = "frontier range"
+ desc = "A combined oven and stove commonly seen on the frontier. Comes from the factory packed up \
+ in a neatly compact format that can then be deployed into a nearly full size appliance. \
+ It seems, however, that the designer forgot to include instructions on packing these things back up."
+ icon = 'modular_doppler/colony_fabricator/icons/kitchen_stuff/range.dmi'
+ icon_state = "range_off"
+ base_icon_state = "range"
+ pass_flags_self = PASSMACHINE|PASSTABLE|LETPASSTHROW
+ active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 1.2
+ circuit = null
+
+/obj/machinery/oven/range_frontier/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ AddComponent(/datum/component/stove, container_x = -3, container_y = 14)
+
+/obj/machinery/oven/range_frontier/examine(mob/user)
+ . = ..()
+ . += span_notice("It cannot be repacked, but can be deconstructed normally.")
+
+/obj/machinery/oven/range_frontier/unanchored
+ anchored = FALSE
+
+// Deployable item for cargo
+
+/obj/item/flatpacked_machine/frontier_range
+ name = "frontier range parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/kitchen_stuff/range.dmi'
+ icon_state = "range_packed"
+ w_class = WEIGHT_CLASS_NORMAL
+ type_to_deploy = /obj/machinery/oven/range_frontier
+ deploy_time = 2 SECONDS
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/appliances/recycler.dm b/modular_doppler/colony_fabricator/code/appliances/recycler.dm
new file mode 100644
index 0000000000000..feaf3f9202939
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/recycler.dm
@@ -0,0 +1,81 @@
+/obj/machinery/colony_recycler
+ name = "materials recycler"
+ desc = "A large crushing machine used to recycle small items inefficiently. Items are inserted by hand, rather than by belt. \
+ Mind your fingers."
+ icon = 'modular_doppler/colony_fabricator/icons/portable_machines.dmi'
+ icon_state = "recycler"
+ anchored = FALSE
+ density = TRUE
+ circuit = null
+ /// The percentage of materials returned
+ var/amount_produced = 80
+ /// The sound made when an item is eaten
+// var/item_recycle_sound = 'modular_doppler/reagent_forging/sound/forge.ogg'
+ /// The recycler's internal materials storage, for when items recycled don't produce enough to make a full sheet of that material
+ var/datum/component/material_container/materials
+ /// The list of all the materials we can recycle
+ var/static/list/allowed_materials = list(
+ /datum/material/iron,
+ /datum/material/glass,
+ /datum/material/silver,
+ /datum/material/plasma,
+ /datum/material/gold,
+ /datum/material/diamond,
+ /datum/material/plastic,
+ /datum/material/uranium,
+ /datum/material/bananium,
+ /datum/material/titanium,
+ /datum/material/bluespace,
+ )
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/flatpacked_machine/recycler
+
+/obj/machinery/colony_recycler/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, repacked_type, 5 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ materials = AddComponent( \
+ /datum/component/material_container, \
+ allowed_materials, \
+ INFINITY, \
+ MATCONTAINER_EXAMINE, \
+ container_signals = list(COMSIG_MATCONTAINER_ITEM_CONSUMED = TYPE_PROC_REF(/obj/machinery/colony_recycler, has_eaten_materials)), \
+ )
+
+/obj/machinery/colony_recycler/Destroy()
+ materials = null
+ return ..()
+
+/obj/machinery/colony_recycler/examine(mob/user)
+ . = ..()
+ . += span_notice("Reclaiming [amount_produced]% of materials salvaged.")
+ . += span_notice("Can be secured with a wrench using Right-Click.")
+
+/obj/machinery/colony_recycler/wrench_act_secondary(mob/living/user, obj/item/tool)
+ default_unfasten_wrench(user, tool)
+ return ITEM_INTERACT_SUCCESS
+
+/// Proc called when the recycler eats new materials, checks if we should spit out new material sheets
+/obj/machinery/colony_recycler/proc/has_eaten_materials(container, obj/item/item_inserted, last_inserted_id, mats_consumed, amount_inserted, atom/context)
+ SIGNAL_HANDLER
+
+ flick("recycler_grind", src)
+// playsound(src, item_recycle_sound, 50, TRUE)
+ use_energy(min(active_power_usage * 0.25, amount_inserted / 100))
+
+ if(amount_inserted)
+ materials.retrieve_all(drop_location())
+
+// "parts kit" for buying these from cargo
+
+/obj/item/flatpacked_machine/recycler
+ name = "recycler parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/parts_kits.dmi'
+ icon_state = "recycler"
+ type_to_deploy = /obj/machinery/colony_recycler
+ deploy_time = 2 SECONDS
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT, // Titan for the crushing element
+ )
diff --git a/modular_doppler/colony_fabricator/code/appliances/space_heater.dm b/modular_doppler/colony_fabricator/code/appliances/space_heater.dm
new file mode 100644
index 0000000000000..716276d9d82a2
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/space_heater.dm
@@ -0,0 +1,124 @@
+/obj/machinery/space_heater/wall_mounted
+ name = "mounted heater"
+ desc = "A compact heating and cooling device for small scale applications, made to mount onto walls up and out of the way. \
+ Like other, more free-standing space heaters however, these still require cell power to function."
+ icon = 'modular_doppler/colony_fabricator/icons/space_heater.dmi'
+ anchored = TRUE
+ density = FALSE
+ circuit = null
+ heating_energy = parent_type::heating_energy * 2
+ efficiency = parent_type::efficiency * 2
+ display_panel = TRUE
+ cell = null
+ /// What this repacks into when it's wrenched off a wall
+ var/repacked_type = /obj/item/wallframe/wall_heater
+
+MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/space_heater/wall_mounted, 29)
+
+/obj/machinery/space_heater/wall_mounted/Initialize(mapload)
+ . = ..()
+ find_and_hang_on_wall()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ RemoveElement(/datum/element/elevation, pixel_shift = 8) //they're on the wall, you can't climb this
+ RemoveElement(/datum/element/climbable)
+
+/obj/machinery/space_heater/wall_mounted/RefreshParts()
+ . = ..()
+ heating_energy = src::heating_energy
+ efficiency = src::efficiency
+
+/obj/machinery/space_heater/wall_mounted/default_deconstruction_crowbar()
+ return
+
+/obj/machinery/space_heater/wall_mounted/default_unfasten_wrench(mob/living/user, obj/item/wrench, time)
+ user.balloon_alert(user, "deconstructing...")
+ wrench.play_tool_sound(src)
+ if(wrench.use_tool(src, user, 1 SECONDS))
+ playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
+ deconstruct(TRUE)
+ return
+
+/obj/machinery/space_heater/wall_mounted/on_deconstruction(disassembled)
+ if(disassembled)
+ var/obj/item/wallframe/wall_heater/frame = new repacked_type(drop_location())
+ frame.cell = cell
+ cell?.forceMove(frame)
+ else
+ cell.forceMove(drop_location())
+ cell = null
+ return ..()
+
+// Wallmount for creating the heaters
+
+/obj/item/wallframe/wall_heater
+ name = "unmounted wall heater"
+ desc = "A compact heating and cooling device for small scale applications, made to mount onto walls up and out of the way. \
+ Like other, more free-standing space heaters however, these still require cell power to function."
+ icon = 'modular_doppler/colony_fabricator/icons/space_heater.dmi'
+ icon_state = "sheater-off"
+ w_class = WEIGHT_CLASS_NORMAL
+ result_path = /obj/machinery/space_heater/wall_mounted
+ pixel_shift = 29
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4,
+ /datum/material/silver = SHEET_MATERIAL_AMOUNT * 1,
+ /datum/material/gold = SMALL_MATERIAL_AMOUNT,
+ )
+ /// lazy-initialized cell stored in the actual heater (so that it can start with one without making a new one every placement)
+ var/obj/item/stock_parts/power_store/cell = /obj/machinery/space_heater::cell
+
+/obj/item/wallframe/wall_heater/Initialize(mapload)
+ . = ..()
+ register_context()
+
+/obj/item/wallframe/wall_heater/after_attach(obj/machinery/space_heater/wall_mounted/attached_to)
+ . = ..()
+ if(!istype(attached_to))
+ return
+ if(ispath(cell))
+ cell = new cell
+ attached_to.cell = cell
+ cell?.forceMove(attached_to)
+ cell = null
+
+/obj/item/wallframe/wall_heater/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(!istype(tool, /obj/item/stock_parts/power_store/cell))
+ return NONE
+ if(ispath(cell))
+ cell = new cell
+ playsound(src, 'sound/machines/click.ogg', 75, TRUE)
+ user.transferItemToLoc(tool, src)
+ if(!isnull(cell))
+ user.put_in_hands(cell)
+ user.balloon_alert(user, "swapped")
+ cell = tool
+ return ITEM_INTERACT_SUCCESS
+
+/obj/item/wallframe/wall_heater/attack_hand_secondary(mob/user, list/modifiers)
+ . = ..()
+ if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
+ return
+ if(isnull(cell))
+ return SECONDARY_ATTACK_CALL_NORMAL
+ if(ispath(cell))
+ cell = new cell
+ playsound(src, 'sound/machines/click.ogg', 75, TRUE)
+ user.put_in_hands(cell)
+ cell = null
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+
+/obj/item/wallframe/wall_heater/examine(mob/user)
+ . = ..()
+ if(cell)
+ . += span_notice("It contains a [ispath(cell) ? cell::name : cell.name], which could be replaced.")
+ else
+ . += span_notice("It is empty. You could insert a [span_bold("cell")].")
+
+/obj/item/wallframe/wall_heater/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+ if(!isnull(cell) && isnull(held_item))
+ context[SCREENTIP_CONTEXT_RMB] = "Remove cell"
+ . = CONTEXTUAL_SCREENTIP_SET
+ if(istype(held_item, /obj/item/stock_parts/power_store))
+ context[SCREENTIP_CONTEXT_LMB] = "Insert cell"
+ . = CONTEXTUAL_SCREENTIP_SET
diff --git a/modular_doppler/colony_fabricator/code/appliances/wall_cell_charger.dm b/modular_doppler/colony_fabricator/code/appliances/wall_cell_charger.dm
new file mode 100644
index 0000000000000..8cdf5771b0a7c
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/wall_cell_charger.dm
@@ -0,0 +1,241 @@
+/obj/machinery/cell_charger_multi
+ name = "mounted multi-cell charging rack"
+ desc = "The innovative technology of a cell charging rack, but mounted neatly on a wall out of the way!"
+ icon = 'modular_doppler/colony_fabricator/icons/cell_charger.dmi'
+ icon_state = "wall_charger"
+ base_icon_state = "wall_charger"
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 5
+ active_power_usage = 60
+ power_channel = AREA_USAGE_EQUIP
+ circuit = null
+ /// The list of batteries we are gonna charge!
+ var/list/charging_batteries = list()
+ /// Number of concurrent batteries that can be charged
+ var/max_batteries = 3
+ /// The base charge rate when spawned
+ var/charge_rate = STANDARD_CELL_RATE * 3
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/wallframe/cell_charger_multi
+
+MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/cell_charger_multi, 29)
+
+/obj/machinery/cell_charger_multi/Initialize(mapload)
+ . = ..()
+ find_and_hang_on_wall()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+/obj/machinery/cell_charger_multi/update_overlays()
+ . = ..()
+
+ if(!charging_batteries.len)
+ return
+
+ for(var/i = charging_batteries.len, i >= 1, i--)
+ var/obj/item/stock_parts/power_store/cell/charging = charging_batteries[i]
+ var/newlevel = round(charging.percent() * 4 / 100)
+ var/mutable_appearance/charge_overlay = mutable_appearance(icon, "[base_icon_state]-o[newlevel]")
+ var/mutable_appearance/cell_overlay = mutable_appearance(icon, "[base_icon_state]-cell")
+ charge_overlay.pixel_x = 5 * (i - 1)
+ cell_overlay.pixel_x = 5 * (i - 1)
+ . += new /mutable_appearance(charge_overlay)
+ . += new /mutable_appearance(cell_overlay)
+
+/obj/machinery/cell_charger_multi/attack_hand_secondary(mob/user, list/modifiers)
+ if(!can_interact(user) || !charging_batteries.len)
+ return
+ to_chat(user, span_notice("You press the quick release as all the cells pop out!"))
+ for(var/i in charging_batteries)
+ removecell()
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+
+/obj/machinery/cell_charger_multi/examine(mob/user)
+ . = ..()
+ if(!charging_batteries.len)
+ . += "There are no cells in [src]."
+ else
+ . += "There are [charging_batteries.len] cells in [src]."
+ for(var/obj/item/stock_parts/power_store/cell/charging in charging_batteries)
+ . += "There's [charging] cell in the charger, current charge: [round(charging.percent(), 1)]%."
+ if(in_range(user, src) || isobserver(user))
+ . += span_notice("The status display reads: Charging power: [display_power(charge_rate, convert = FALSE)] per cell.")
+ . += span_notice("Right click it to remove all the cells at once!")
+
+/obj/machinery/cell_charger_multi/wrench_act(mob/living/user, obj/item/tool)
+ . = ..()
+ user.balloon_alert(user, "deconstructing...")
+ tool.play_tool_sound(src)
+ if(tool.use_tool(src, user, 1 SECONDS))
+ playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
+ deconstruct(TRUE)
+ return
+
+
+/obj/machinery/cell_charger_multi/attackby(obj/item/tool, mob/user, params)
+ if(istype(tool, /obj/item/stock_parts/power_store/cell) && !panel_open)
+ if(machine_stat & BROKEN)
+ to_chat(user, span_warning("[src] is broken!"))
+ return
+ if(!anchored)
+ to_chat(user, span_warning("[src] isn't attached to the ground!"))
+ return
+ var/obj/item/stock_parts/power_store/cell/inserting_cell = tool
+ if(inserting_cell.chargerate <= 0)
+ to_chat(user, span_warning("[inserting_cell] cannot be recharged!"))
+ return
+ if(length(charging_batteries) >= max_batteries)
+ to_chat(user, span_warning("[src] is full, and cannot hold anymore cells!"))
+ return
+ else
+ var/area/current_area = loc.loc // Gets our locations location, like a dream within a dream
+ if(!isarea(current_area))
+ return
+ if(current_area.power_equip == 0) // There's no APC in this area, don't try to cheat power!
+ to_chat(user, span_warning("[src] blinks red as you try to insert the cell!"))
+ return
+ if(!user.transferItemToLoc(tool,src))
+ return
+
+ charging_batteries += tool
+ user.visible_message(span_notice("[user] inserts a cell into [src]."), span_notice("You insert a cell into [src]."))
+ update_appearance()
+ else
+ if(!charging_batteries.len && default_deconstruction_screwdriver(user, icon_state, icon_state, tool))
+ return
+ if(default_deconstruction_crowbar(tool))
+ return
+ if(!charging_batteries.len && default_unfasten_wrench(user, tool))
+ return
+ return ..()
+
+/obj/machinery/cell_charger_multi/process(seconds_per_tick)
+ if(!charging_batteries.len || !anchored || (machine_stat & (BROKEN|NOPOWER)))
+ return
+
+ // create a charging queue, we only want cells that require charging to use the power budget
+ var/list/charging_queue
+ for(var/obj/item/stock_parts/power_store/cell/battery_slot in charging_batteries)
+ if(battery_slot.percent() >= 100)
+ continue
+ LAZYADD(charging_queue, battery_slot)
+
+ if(!LAZYLEN(charging_queue))
+ return
+
+ //use a small bit for the charger itself, but power usage scales up with the part tier
+ use_energy(charge_rate / length(charging_queue) * seconds_per_tick * 0.01)
+
+ for(var/obj/item/stock_parts/power_store/cell/charging_cell in charging_queue)
+ charge_cell(charge_rate * seconds_per_tick, charging_cell)
+
+ LAZYNULL(charging_queue)
+ update_appearance()
+
+/obj/machinery/cell_charger_multi/attack_tk(mob/user)
+ if(!charging_batteries.len)
+ return
+
+ to_chat(user, span_notice("You telekinetically remove [removecell(user)] from [src]."))
+
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+
+/obj/machinery/cell_charger_multi/RefreshParts()
+ . = ..()
+ var/tier_total
+ for(var/datum/stock_part/capacitor/capacitor in component_parts)
+ tier_total += capacitor.tier
+ charge_rate = tier_total * (initial(charge_rate) / 6)
+
+/obj/machinery/cell_charger_multi/emp_act(severity)
+ . = ..()
+
+ if(machine_stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_CONTENTS)
+ return
+
+ for(var/obj/item/stock_parts/power_store/cell/charging in charging_batteries)
+ charging.emp_act(severity)
+
+/obj/machinery/cell_charger_multi/on_deconstruction(disassembled)
+ for(var/obj/item/stock_parts/power_store/cell/charging in charging_batteries)
+ charging.forceMove(drop_location())
+ charging_batteries = null
+ return ..()
+
+
+/obj/machinery/cell_charger_multi/attack_ai(mob/user)
+ return
+
+/obj/machinery/cell_charger_multi/attack_hand(mob/user, list/modifiers)
+ . = ..()
+ if(.)
+ return
+
+ var/obj/item/stock_parts/power_store/cell/charging = removecell(user)
+
+ if(!charging)
+ return
+
+ user.put_in_hands(charging)
+ charging.add_fingerprint(user)
+
+ user.visible_message(span_notice("[user] removes [charging] from [src]."), span_notice("You remove [charging] from [src]."))
+
+/obj/machinery/cell_charger_multi/proc/removecell(mob/user)
+ if(!charging_batteries.len)
+ return FALSE
+ var/obj/item/stock_parts/power_store/cell/charging
+ if(charging_batteries.len > 1 && user)
+ var/list/buttons = list()
+ for(var/obj/item/stock_parts/power_store/cell/battery in charging_batteries)
+ buttons["[battery.name] ([round(battery.percent(), 1)]%)"] = battery
+ var/cell_name = tgui_input_list(user, "Please choose what cell you'd like to remove.", "Remove a cell", buttons)
+ charging = buttons[cell_name]
+ else
+ charging = charging_batteries[1]
+ if(!charging)
+ return FALSE
+ charging.forceMove(drop_location())
+ charging.update_appearance()
+ charging_batteries -= charging
+ update_appearance()
+ return charging
+
+/obj/machinery/cell_charger_multi/Destroy()
+ for(var/obj/item/stock_parts/power_store/cell/charging in charging_batteries)
+ QDEL_NULL(charging)
+ charging_batteries = null
+ return ..()
+
+// formerly NO_DECONSTRUCTION
+/obj/machinery/cell_charger_multi/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/cell_charger_multi/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/cell_charger_multi/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+/obj/machinery/cell_charger_multi/on_deconstruction(disassembled)
+ if(disassembled)
+ new repacked_type(drop_location())
+
+/obj/machinery/cell_charger_multi/RefreshParts()
+ . = ..()
+ charge_rate = STANDARD_CELL_RATE * 3 // Nuh uh!
+
+// Item for creating the arc furnace or carrying it around
+
+/obj/item/wallframe/cell_charger_multi
+ name = "unmounted wall multi-cell charging rack"
+ desc = "The innovative technology of a cell charging rack, but able to be mounted neatly on a wall out of the way!"
+ icon = 'modular_doppler/colony_fabricator/icons/packed_machines.dmi'
+ icon_state = "cell_charger_packed"
+ w_class = WEIGHT_CLASS_NORMAL
+ result_path = /obj/machinery/cell_charger_multi
+ pixel_shift = 29
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/silver = SHEET_MATERIAL_AMOUNT * 1,
+ )
diff --git a/modular_doppler/colony_fabricator/code/appliances/wind_turbine.dm b/modular_doppler/colony_fabricator/code/appliances/wind_turbine.dm
new file mode 100644
index 0000000000000..975ef07da1a53
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/appliances/wind_turbine.dm
@@ -0,0 +1,88 @@
+/obj/machinery/power/colony_wind_turbine
+ name = "miniature wind turbine"
+ desc = "A post with two special-designed vertical turbine blades attached to its sides. \
+ When placed outdoors in a planet with an atmosphere, will produce a small trickle of power \
+ for free. If there is a storm in the area the turbine is placed, the power production will \
+ multiply significantly."
+ icon = 'modular_doppler/colony_fabricator/icons/wind_turbine.dmi'
+ icon_state = "turbine"
+ density = TRUE
+ max_integrity = 100
+ idle_power_usage = 0
+ anchored = TRUE
+ can_change_cable_layer = FALSE
+ circuit = null
+ layer = ABOVE_MOB_LAYER
+ can_change_cable_layer = TRUE
+ /// How much power the turbine makes without a storm
+ var/regular_power_production = 2500
+ /// How much power the turbine makes during a storm
+ var/storm_power_production = 10000
+ /// Is our pressure too low to function?
+ var/pressure_too_low = FALSE
+ /// Minimum external pressure needed to work
+ var/minimum_pressure = 5
+ /// What we undeploy into
+ var/undeploy_type = /obj/item/flatpacked_machine/wind_turbine
+
+/obj/machinery/power/colony_wind_turbine/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, undeploy_type, 2 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ connect_to_network()
+
+/obj/machinery/power/colony_wind_turbine/examine(mob/user)
+ . = ..()
+ var/area/turbine_area = get_area(src)
+ if(!turbine_area.outdoors)
+ . += span_notice("Its must be constructed outdoors to function.")
+ if(pressure_too_low)
+ . += span_notice("There must be enough atmospheric pressure for the turbine to spin.")
+
+
+/obj/machinery/power/colony_wind_turbine/process()
+ var/area/our_current_area = get_area(src)
+ if(!our_current_area.outdoors)
+ icon_state = "turbine"
+ add_avail(0)
+ return
+
+ var/turf/our_turf = get_turf(src)
+ var/datum/gas_mixture/environment = our_turf.return_air()
+
+ if(environment.return_pressure() < minimum_pressure)
+ pressure_too_low = TRUE
+ icon_state = "turbine"
+ add_avail(0)
+ return
+
+ pressure_too_low = FALSE
+ var/storming_out = FALSE
+
+ var/datum/weather/weather_we_track
+ for(var/datum/weather/possible_weather in SSweather.processing)
+ if((our_turf.z in possible_weather.impacted_z_levels) || (our_current_area in possible_weather.impacted_areas))
+ weather_we_track = possible_weather
+ break
+ if(weather_we_track)
+ if(!(weather_we_track.stage == END_STAGE))
+ storming_out = TRUE
+
+ add_avail(power_to_energy(storming_out ? storm_power_production : regular_power_production))
+
+ var/new_icon_state = (storming_out ? "turbine_storm" : "turbine_normal")
+ icon_state = new_icon_state
+
+
+// Item for deploying wind turbines
+/obj/item/flatpacked_machine/wind_turbine
+ name = "flat-packed miniature wind turbine"
+ icon = 'modular_doppler/colony_fabricator/icons/wind_turbine.dmi'
+ icon_state = "turbine_packed"
+ type_to_deploy = /obj/machinery/power/colony_wind_turbine
+ w_class = WEIGHT_CLASS_NORMAL
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/colony_fabricator.dm b/modular_doppler/colony_fabricator/code/colony_fabricator.dm
new file mode 100644
index 0000000000000..ff65c11221114
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/colony_fabricator.dm
@@ -0,0 +1,117 @@
+/obj/machinery/rnd/production/colony_lathe
+ name = "rapid construction fabricator"
+ desc = "These bad boys are seen just about anywhere someone would want or need to build fast, damn the consequences. \
+ That tends to be colonies, especially on dangerous worlds, where the influences of this one machine can be seen \
+ in every bit of architecture."
+ icon = 'modular_doppler/colony_fabricator/icons/machines.dmi'
+ icon_state = "colony_lathe"
+ base_icon_state = "colony_lathe"
+ production_animation = null
+ circuit = null
+ production_animation = "colony_lathe_n"
+ light_color = LIGHT_COLOR_BRIGHT_YELLOW
+ light_power = 5
+ allowed_buildtypes = COLONY_FABRICATOR
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/flatpacked_machine
+ /// The sound loop played while the fabricator is making something
+ var/datum/looping_sound/colony_fabricator_running/soundloop
+
+/obj/machinery/rnd/production/colony_lathe/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, repacked_type, 5 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ // We don't get new designs but can't print stuff if something's not researched, so we use the web that has everything researched
+ stored_research = locate(/datum/techweb/admin) in SSresearch.techwebs
+ soundloop = new(src, FALSE)
+ if(!mapload)
+ flick("colony_lathe_deploy", src) // Sick ass deployment animation
+
+/obj/machinery/rnd/production/colony_lathe/Destroy()
+ QDEL_NULL(soundloop)
+ return ..()
+
+// formerly NO_DECONSTRUCTION
+/obj/machinery/rnd/production/colony_lathe/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/rnd/production/colony_lathe/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/rnd/production/colony_lathe/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+/// Proc for starting extra printing visuals, because upstream removed any nice way to do this
+/obj/machinery/rnd/production/proc/start_printing_visuals()
+ return
+
+/obj/machinery/rnd/production/colony_lathe/start_printing_visuals()
+ soundloop.start()
+ set_light(l_range = 1.5)
+ icon_state = "colony_lathe_working"
+ update_appearance()
+
+/obj/machinery/rnd/production/colony_lathe/finalize_build()
+ . = ..()
+ soundloop.stop()
+ set_light(l_range = 0)
+ icon_state = base_icon_state
+ update_appearance()
+ flick("colony_lathe_finish_print", src)
+
+/obj/machinery/rnd/production/colony_lathe/build_efficiency()
+ return 1
+
+// We take from all nodes even unresearched ones
+/obj/machinery/rnd/production/colony_lathe/update_designs()
+ var/previous_design_count = cached_designs.len
+
+ cached_designs.Cut()
+
+ for(var/design_id in SSresearch.techweb_designs)
+ var/datum/design/design = SSresearch.techweb_designs[design_id]
+
+ if((isnull(allowed_department_flags) || (design.departmental_flags & allowed_department_flags)) && (design.build_type & allowed_buildtypes))
+ cached_designs |= design
+
+ var/design_delta = cached_designs.len - previous_design_count
+
+ if(design_delta > 0)
+ say("Received [design_delta] new design[design_delta == 1 ? "" : "s"].")
+ playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE)
+
+ update_static_data_for_all_viewers()
+
+// Item for carrying the lathe around and building it
+
+/obj/item/flatpacked_machine
+ name = "flat-packed rapid construction fabricator"
+ icon = 'modular_doppler/colony_fabricator/icons/packed_machines.dmi'
+ icon_state = "colony_lathe_packed"
+ w_class = WEIGHT_CLASS_BULKY
+ /// What structure is created by this item.
+ var/obj/type_to_deploy = /obj/machinery/rnd/production/colony_lathe
+ /// How long it takes to create the structure in question.
+ var/deploy_time = 4 SECONDS
+
+/obj/item/flatpacked_machine/Initialize(mapload)
+ . = ..()
+ desc = initial(type_to_deploy.desc)
+ give_deployable_component()
+ give_manufacturer_examine()
+
+/// Adds the deployable component, so that it can be overridden in case that's wanted
+/obj/item/flatpacked_machine/proc/give_deployable_component()
+ AddComponent(/datum/component/deployable, deploy_time, type_to_deploy)
+
+/// Adds the manufacturer examine element to the flatpack machine, but can be overridden in the future
+/obj/item/flatpacked_machine/proc/give_manufacturer_examine()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+/obj/item/borg/apparatus/sheet_manipulator/Initialize(mapload)
+ . = ..()
+ storable += /obj/item/flatpacked_machine
+
+/obj/item/borg/apparatus/circuit/Initialize(mapload)
+ . = ..()
+ storable += /obj/item/flatpacked_machine
diff --git a/modular_doppler/colony_fabricator/code/construction/doors.dm b/modular_doppler/colony_fabricator/code/construction/doors.dm
new file mode 100644
index 0000000000000..c322858bb807d
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/construction/doors.dm
@@ -0,0 +1,54 @@
+// Shutters
+
+/obj/machinery/door/poddoor/shutters/colony_fabricator
+ name = "prefab shutters"
+ icon = 'modular_doppler/colony_fabricator/icons/doors/shutter.dmi'
+
+/obj/machinery/door/poddoor/shutters/colony_fabricator/preopen
+ icon_state = "open"
+ density = FALSE
+ opacity = FALSE
+
+/obj/machinery/door/poddoor/shutters/colony_fabricator/animation_effects(animation)
+ switch(animation)
+ if(DOOR_OPENING_ANIMATION)
+ playsound(src, animation_sound, 30, TRUE)
+ if(DOOR_CLOSING_ANIMATION)
+ playsound(src, animation_sound, 30, TRUE)
+
+/obj/item/flatpacked_machine/shutter_kit
+ name = "prefab shutters parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/doors/packed.dmi'
+ icon_state = "shutters_parts"
+ type_to_deploy = /obj/machinery/door/poddoor/shutters/colony_fabricator/preopen
+ w_class = WEIGHT_CLASS_NORMAL
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ )
+
+// Airlocks
+
+/obj/machinery/door/airlock/colony_prefab
+ name = "prefab airlock"
+ icon = 'modular_doppler/colony_fabricator/icons/doors/airlock.dmi'
+ overlays_file = 'modular_doppler/colony_fabricator/icons/doors/overlays.dmi'
+ assemblytype = /obj/structure/door_assembly/door_assembly_colony_prefab
+
+/obj/structure/door_assembly/door_assembly_colony_prefab
+ name = "prefab airlock assembly"
+ icon = 'modular_doppler/colony_fabricator/icons/doors/airlock.dmi'
+ base_name = "prefab airlock"
+ airlock_type = /obj/machinery/door/airlock/colony_prefab
+ noglass = TRUE
+
+/obj/item/flatpacked_machine/airlock_kit
+ name = "prefab airlock parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/doors/packed.dmi'
+ icon_state = "airlock_parts"
+ type_to_deploy = /obj/machinery/door/airlock/colony_prefab
+ w_class = WEIGHT_CLASS_NORMAL
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ )
diff --git a/modular_doppler/colony_fabricator/code/construction/manual_door.dm b/modular_doppler/colony_fabricator/code/construction/manual_door.dm
new file mode 100644
index 0000000000000..630b9fea34a8f
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/construction/manual_door.dm
@@ -0,0 +1,80 @@
+/obj/structure/mineral_door/manual_colony_door
+ name = "manual airlock"
+ icon = 'modular_doppler/colony_fabricator/icons/doors/airlock_manual.dmi'
+ material_flags = NONE
+ icon_state = "manual"
+ openSound = 'modular_doppler/colony_fabricator/sounds/manual_door/manual_door_open.wav'
+ closeSound = 'modular_doppler/colony_fabricator/sounds/manual_door/manual_door_close.wav'
+ /// What we disassemble into
+ var/disassembled_type = /obj/item/flatpacked_machine/airlock_kit_manual
+ /// How long it takes to open/close the door
+ var/manual_actuation_delay = 1 SECONDS
+
+/obj/structure/mineral_door/manual_colony_door/atom_deconstruct(disassembled = TRUE)
+ if(disassembled)
+ new disassembled_type(get_turf(src))
+
+// Pickaxes won't dig these apart
+/obj/structure/mineral_door/manual_colony_door/pickaxe_door(mob/living/user, obj/item/item_in_question)
+ return
+
+// These doors have a short do_after to check if you can open or close them
+/obj/structure/mineral_door/manual_colony_door/TryToSwitchState(atom/user)
+ if(isSwitchingStates || !anchored)
+ return
+ if(!do_after(user, manual_actuation_delay, src))
+ return
+ return ..()
+
+// We don't care about being bumped, just a copy of the base bumped proc
+/obj/structure/mineral_door/manual_colony_door/Bumped(atom/movable/bumped_atom)
+ set waitfor = FALSE
+ SEND_SIGNAL(src, COMSIG_ATOM_BUMPED, bumped_atom)
+
+/obj/structure/mineral_door/manual_colony_door/Open()
+ isSwitchingStates = TRUE
+ playsound(src, openSound, 100, TRUE)
+ set_opacity(FALSE)
+ flick("[initial(icon_state)]opening",src)
+ icon_state = "[initial(icon_state)]open"
+ sleep(1 SECONDS)
+ set_density(FALSE)
+ door_opened = TRUE
+ layer = OPEN_DOOR_LAYER
+ air_update_turf(TRUE, FALSE)
+ update_appearance()
+ isSwitchingStates = FALSE
+
+ if(close_delay != -1)
+ addtimer(CALLBACK(src, PROC_REF(Close)), close_delay)
+
+/obj/structure/mineral_door/manual_colony_door/Close()
+ if(isSwitchingStates || !door_opened)
+ return
+ var/turf/T = get_turf(src)
+ for(var/mob/living/L in T)
+ return
+ isSwitchingStates = TRUE
+ playsound(src, closeSound, 100, TRUE)
+ flick("[initial(icon_state)]closing",src)
+ icon_state = initial(icon_state)
+ sleep(1 SECONDS)
+ set_density(TRUE)
+ set_opacity(TRUE)
+ door_opened = FALSE
+ layer = initial(layer)
+ air_update_turf(TRUE, TRUE)
+ update_appearance()
+ isSwitchingStates = FALSE
+
+// Parts kit for putting the door together
+/obj/item/flatpacked_machine/airlock_kit_manual
+ name = "prefab manual airlock parts kit"
+ icon = 'modular_doppler/colony_fabricator/icons/doors/packed.dmi'
+ icon_state = "airlock_parts_manual"
+ type_to_deploy = /obj/structure/mineral_door/manual_colony_door
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ )
+ w_class = WEIGHT_CLASS_NORMAL
diff --git a/modular_doppler/colony_fabricator/code/construction/turfs.dm b/modular_doppler/colony_fabricator/code/construction/turfs.dm
new file mode 100644
index 0000000000000..a2540b677c21d
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/construction/turfs.dm
@@ -0,0 +1,168 @@
+// Plastic panel walls, how colony of you
+
+/turf/closed/wall/prefab_plastic
+ name = "prefabricated wall"
+ desc = "A conservatively built metal frame with plastic paneling covering a thin air-seal layer. \
+ It's a little unnerving, but it's better than nothing at all."
+ icon = 'modular_doppler/colony_fabricator/icons/prefab_wall.dmi'
+ icon_state = "prefab-0"
+ base_icon_state = "prefab"
+ can_engrave = FALSE
+ girder_type = null
+ hardness = 70
+ slicing_duration = 5 SECONDS
+ sheet_type = /obj/item/stack/sheet/plastic_wall_panel
+ sheet_amount = 1
+
+GLOBAL_LIST_INIT(plastic_wall_panel_recipes, list(
+ new/datum/stack_recipe("prefabricated wall", /turf/closed/wall/prefab_plastic, time = 3 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_STRUCTURE), \
+ new/datum/stack_recipe("prefabricated window", /obj/structure/window/fulltile/colony_fabricator, time = 1 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ON_SOLID_GROUND | CRAFT_CHECK_DIRECTION | CRAFT_IS_FULLTILE, category = CAT_WINDOWS), \
+ ))
+
+/obj/item/stack/sheet/plastic_wall_panel
+ name = "plastic panels"
+ singular_name = "plastic panel"
+ desc = "What better material to make the walls of your soon to be home out of than sheets of flimsy plastic? \
+ Metal? What are you talking about, metal walls, in this economy? May also be used to make structures other \
+ than walls."
+ icon = 'modular_doppler/colony_fabricator/icons/tiles_item.dmi'
+ icon_state = "sheet-plastic"
+ inhand_icon_state = "sheet-plastic"
+ mats_per_unit = list(
+ /datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ has_unique_girder = TRUE
+ material_type = /datum/material/plastic
+ merge_type = /obj/item/stack/sheet/plastic_wall_panel
+ walltype = /turf/closed/wall/prefab_plastic
+
+/obj/item/stack/sheet/plastic_wall_panel/examine(mob/user)
+ . = ..()
+ . += span_notice("You can build a prefabricated wall by right clicking on an empty floor.")
+
+/obj/item/stack/sheet/plastic_wall_panel/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
+ if(!isopenturf(interacting_with))
+ return NONE
+ var/turf/open/build_on = interacting_with
+ if(isgroundlessturf(build_on))
+ user.balloon_alert(user, "can't place it here!")
+ return ITEM_INTERACT_BLOCKING
+ if(build_on.is_blocked_turf())
+ user.balloon_alert(user, "something is blocking the tile!")
+ return ITEM_INTERACT_BLOCKING
+ if(get_amount() < 1)
+ user.balloon_alert(user, "not enough material!")
+ return ITEM_INTERACT_BLOCKING
+ if(!do_after(user, 3 SECONDS, build_on))
+ return ITEM_INTERACT_BLOCKING
+ if(build_on.is_blocked_turf())
+ user.balloon_alert(user, "something is blocking the tile!")
+ return ITEM_INTERACT_BLOCKING
+ if(!use(1))
+ user.balloon_alert(user, "not enough material!")
+ return ITEM_INTERACT_BLOCKING
+ build_on.place_on_top(walltype, flags = CHANGETURF_INHERIT_AIR)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/item/stack/sheet/plastic_wall_panel/get_main_recipes()
+ . = ..()
+ . += GLOB.plastic_wall_panel_recipes
+
+/obj/item/stack/sheet/plastic_wall_panel/ten
+ amount = 10
+
+/obj/item/stack/sheet/plastic_wall_panel/fifty
+ amount = 50
+
+// Stacks of floor tiles
+
+/obj/item/stack/tile/catwalk_tile/colony_lathe
+ icon = 'modular_doppler/colony_fabricator/icons/tiles_item.dmi'
+ icon_state = "prefab_catwalk"
+ mats_per_unit = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT)
+ turf_type = /turf/open/floor/catwalk_floor/colony_fabricator
+ merge_type = /obj/item/stack/tile/catwalk_tile/colony_lathe
+ tile_reskin_types = null
+
+/obj/item/stack/tile/iron/colony
+ name = "prefab floor tiles"
+ singular_name = "prefab floor tile"
+ desc = "A stack of large floor tiles that are a common sight in frontier colonies and prefab buildings."
+ icon = 'modular_doppler/colony_fabricator/icons/tiles_item.dmi'
+ icon_state = "colony_grey"
+ turf_type = /turf/open/floor/iron/colony
+ merge_type = /obj/item/stack/tile/iron/colony
+ tile_reskin_types = list(
+ /obj/item/stack/tile/iron/colony,
+ /obj/item/stack/tile/iron/colony/texture,
+ /obj/item/stack/tile/iron/colony/bolts,
+ /obj/item/stack/tile/iron/colony/white,
+ /obj/item/stack/tile/iron/colony/white/texture,
+ /obj/item/stack/tile/iron/colony/white/bolts,
+ )
+
+// Grated floor tile, for seeing wires under
+
+/turf/open/floor/catwalk_floor/colony_fabricator
+ icon = 'modular_doppler/colony_fabricator/icons/tiles.dmi'
+ icon_state = "prefab_above"
+ catwalk_type = "prefab"
+ baseturfs = /turf/open/floor/plating
+ floor_tile = /obj/item/stack/tile/catwalk_tile/colony_lathe
+
+// "Normal" floor tiles
+
+/obj/item/stack/tile/iron/colony/texture
+ icon_state = "colony_grey_texture"
+ turf_type = /turf/open/floor/iron/colony/texture
+
+/obj/item/stack/tile/iron/colony/bolts
+ icon_state = "colony_grey_bolts"
+ turf_type = /turf/open/floor/iron/colony/bolts
+
+/turf/open/floor/iron/colony
+ icon = 'modular_doppler/colony_fabricator/icons/tiles.dmi'
+ icon_state = "colony_grey"
+ base_icon_state = "colony_grey"
+ floor_tile = /obj/item/stack/tile/iron/colony
+ tiled_dirt = FALSE
+
+/turf/open/floor/iron/colony/texture
+ icon_state = "colony_grey_texture"
+ base_icon_state = "colony_grey_texture"
+ floor_tile = /obj/item/stack/tile/iron/colony/texture
+
+/turf/open/floor/iron/colony/bolts
+ icon_state = "colony_grey_bolts"
+ base_icon_state = "colony_grey_bolts"
+ floor_tile = /obj/item/stack/tile/iron/colony/bolts
+
+// White variants of the above tiles
+
+/obj/item/stack/tile/iron/colony/white
+ icon_state = "colony_white"
+ turf_type = /turf/open/floor/iron/colony/white
+
+/obj/item/stack/tile/iron/colony/white/texture
+ icon_state = "colony_white_texture"
+ turf_type = /turf/open/floor/iron/colony/white/texture
+
+/obj/item/stack/tile/iron/colony/white/bolts
+ icon_state = "colony_white_bolts"
+ turf_type = /turf/open/floor/iron/colony/white/bolts
+
+/turf/open/floor/iron/colony/white
+ icon_state = "colony_white"
+ base_icon_state = "colony_white"
+ floor_tile = /obj/item/stack/tile/iron/colony/white
+
+/turf/open/floor/iron/colony/white/texture
+ icon_state = "colony_white_texture"
+ base_icon_state = "colony_white_texture"
+ floor_tile = /obj/item/stack/tile/iron/colony/white/texture
+
+/turf/open/floor/iron/colony/white/bolts
+ icon_state = "colony_white_bolts"
+ base_icon_state = "colony_white_bolts"
+ floor_tile = /obj/item/stack/tile/iron/colony/white/bolts
diff --git a/modular_doppler/colony_fabricator/code/construction/windows.dm b/modular_doppler/colony_fabricator/code/construction/windows.dm
new file mode 100644
index 0000000000000..a96fc9ddf9996
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/construction/windows.dm
@@ -0,0 +1,43 @@
+/obj/structure/window/fulltile/colony_fabricator
+ name = "prefabricated window"
+ desc = "A conservatively built metal frame with a thick sheet of space-grade glass slotted into it."
+ icon = 'modular_doppler/colony_fabricator/icons/prefab_window.dmi'
+ icon_state = "prefab-0"
+ base_icon_state = "prefab"
+ fulltile = TRUE
+ glass_type = /obj/item/stack/sheet/plastic_wall_panel
+ glass_amount = 1
+
+/obj/structure/grille/attackby(obj/item/item_in_question, mob/user, params)
+ if(!istype(item_in_question, /obj/item/stack/sheet/plastic_wall_panel))
+ return ..()
+
+ if(broken)
+ return
+ var/obj/item/stack/stack_in_question = item_in_question
+ if(stack_in_question.get_amount() < 1)
+ to_chat(user, span_warning("You need at least one plastic panel for that!"))
+ return
+ var/dir_to_set = SOUTHWEST
+ if(!anchored)
+ to_chat(user, span_warning("[src] needs to be fastened to the floor first!"))
+ return
+ for(var/obj/structure/window/window_on_turf in loc)
+ to_chat(user, span_warning("There is already a window there!"))
+ return
+ if(!clear_tile(user))
+ return
+ to_chat(user, span_notice("You start placing the window..."))
+ if(!do_after(user, 1 SECONDS, target = src))
+ return
+ if(!src.loc || !anchored) //Grille broken or unanchored while waiting
+ return
+ for(var/obj/structure/window/window_on_turf in loc) //Another window already installed on grille
+ return
+ if(!clear_tile(user))
+ return
+ var/obj/structure/window/new_window = new /obj/structure/window/fulltile/colony_fabricator(drop_location())
+ new_window.setDir(dir_to_set)
+ new_window.state = 0
+ stack_in_question.use(1)
+ to_chat(user, span_notice("You place [new_window] on [src]."))
diff --git a/modular_doppler/colony_fabricator/code/design_datums/appliances.dm b/modular_doppler/colony_fabricator/code/design_datums/appliances.dm
new file mode 100644
index 0000000000000..f3b4726a00156
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/appliances.dm
@@ -0,0 +1,270 @@
+// Machine categories
+
+#define FABRICATOR_CATEGORY_APPLIANCES "/Appliances"
+#define FABRICATOR_SUBCATEGORY_POWER "/Power"
+#define FABRICATOR_SUBCATEGORY_ATMOS "/Atmospherics"
+#define FABRICATOR_SUBCATEGORY_FLUIDS "/Liquids"
+#define FABRICATOR_SUBCATEGORY_MATERIALS "/Materials"
+#define FABRICATOR_SUBCATEGORY_SUSTENANCE "/Sustenance"
+
+// Techweb node that shouldnt show up anywhere ever specifically for the fabricator to work with
+
+/datum/techweb_node/colony_fabricator_appliances
+ id = TECHWEB_NODE_COLONY_APPLIANCES
+ display_name = "Colony Fabricator Appliance Designs"
+ description = "Contains all of the colony fabricator's appliance machine designs."
+ design_ids = list(
+ "wall_multi_cell_rack",
+ "portable_lil_pump",
+ "portable_scrubbs",
+ "survival_knife", // I just don't want to make a whole new node for this one sorry
+ "water_synth",
+ "hydro_synth",
+ "frontier_sustenance_dispenser",
+ "co2_cracker",
+ "portable_recycler",
+ "foodricator",
+ "wall_heater",
+ "macrowave",
+ "frontier_range",
+ "tabletop_griddle",
+ )
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000000000000000) // God save you
+ hidden = TRUE
+ show_on_wiki = FALSE
+ starting_node = TRUE
+
+// Wall mountable multi cell charger
+
+/datum/design/wall_mounted_multi_charger
+ name = "Mounted Multi-Cell Charging Rack"
+ id = "wall_multi_cell_rack"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/silver = SHEET_MATERIAL_AMOUNT * 1,
+ )
+ build_path = /obj/item/wallframe/cell_charger_multi
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 15 SECONDS
+
+// Portable scrubber and pumps for all your construction atmospherics needs
+
+/datum/design/portable_gas_pump
+ name = "Portable Air Pump"
+ id = "portable_lil_pump"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ )
+ build_path = /obj/machinery/portable_atmospherics/pump
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_ATMOS,
+ )
+ construction_time = 30 SECONDS
+
+/datum/design/portable_gas_scrubber
+ name = "Portable Air Scrubber"
+ id = "portable_scrubbs"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ )
+ build_path = /obj/machinery/portable_atmospherics/scrubber
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_ATMOS,
+ )
+ construction_time = 30 SECONDS
+
+/// Space heater, but it mounts on walls
+
+/datum/design/wall_mounted_space_heater
+ name = "Mounted Heater"
+ id = "wall_heater"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4,
+ /datum/material/silver = SHEET_MATERIAL_AMOUNT * 1,
+ /datum/material/gold = SMALL_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/wallframe/wall_heater
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_ATMOS,
+ )
+ construction_time = 15 SECONDS
+
+// Plumbable chem machine that makes nothing but water
+
+/datum/design/water_synthesizer
+ name = "Water Synthesizer"
+ id = "water_synth"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/water_synth
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_FLUIDS,
+ )
+ construction_time = 30 SECONDS
+
+// Plumbable chem machine that makes nothing but water
+
+/datum/design/hydro_synthesizer
+ name = "Hydroponics Chemical Synthesizer"
+ id = "hydro_synth"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/hydro_synth
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_FLUIDS,
+ )
+ construction_time = 30 SECONDS
+
+// Chem dispenser that dispenses various flavored beverages and nutrislop, yum!
+
+/datum/design/frontier_sustenance_dispenser
+ name = "Sustenance Dispenser"
+ id = "frontier_sustenance_dispenser"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/sustenance_machine
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_SUSTENANCE,
+ )
+ construction_time = 30 SECONDS
+
+// CO2 cracker, portable machines that takes CO2 and turns it into oxygen
+
+/datum/design/co2_cracker
+ name = "Portable Carbon Dioxide Cracker"
+ id = "co2_cracker"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/plasma = HALF_SHEET_MATERIAL_AMOUNT, // We're gonna pretend plasma is the catalyst for co2 cracking
+ )
+ build_path = /obj/item/flatpacked_machine/co2_cracker
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_ATMOS,
+ )
+ construction_time = 30 SECONDS
+
+// A portable recycling machine, use item with materials on it to recycle
+
+/datum/design/portable_recycler
+ name = "Portable Recycler"
+ id = "portable_recycler"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT, // Titan for the crushing element
+ )
+ build_path = /obj/item/flatpacked_machine/recycler
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_MATERIALS,
+ )
+ construction_time = 30 SECONDS
+
+// Rations printer, turns biomass into seeds, some synthesized foods, ingredients, so on
+
+/datum/design/foodricator
+ name = "Organic Rations Printer"
+ id = "foodricator"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/silver = SHEET_MATERIAL_AMOUNT,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/organics_ration_printer
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_SUSTENANCE,
+ )
+ construction_time = 30 SECONDS
+
+// Really, it's just a microwave
+
+/datum/design/macrowave
+ name = "Microwave Oven"
+ id = "macrowave"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/macrowave
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_SUSTENANCE,
+ )
+ construction_time = 30 SECONDS
+
+// A range, but it looks cool af
+
+/datum/design/frontier_range
+ name = "Frontier Range"
+ id = "frontier_range"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/frontier_range
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_SUSTENANCE,
+ )
+ construction_time = 1 MINUTES
+
+// Griddles that fit on top of any regular table
+
+/datum/design/tabletop_griddle
+ name = "Tabletop Griddle"
+ id = "tabletop_griddle"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/frontier_griddle
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_SUSTENANCE,
+ )
+ construction_time = 1 MINUTES
+
+#undef FABRICATOR_CATEGORY_APPLIANCES
+#undef FABRICATOR_SUBCATEGORY_POWER
+#undef FABRICATOR_SUBCATEGORY_ATMOS
+#undef FABRICATOR_SUBCATEGORY_FLUIDS
+#undef FABRICATOR_SUBCATEGORY_MATERIALS
+#undef FABRICATOR_SUBCATEGORY_SUSTENANCE
diff --git a/modular_doppler/colony_fabricator/code/design_datums/construction.dm b/modular_doppler/colony_fabricator/code/design_datums/construction.dm
new file mode 100644
index 0000000000000..3f14c6e0310e1
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/construction.dm
@@ -0,0 +1,124 @@
+// Look, I had to make its name start with A so it'd be top of the list, fight me
+
+#define FABRICATOR_SUBCATEGORY_STRUCTURES "/Autofab Structures"
+
+// Techweb node that shouldnt show up anywhere ever specifically for the fabricator to work with
+
+/datum/techweb_node/colony_fabricator_structures
+ id = TECHWEB_NODE_COLONY_STRUCTURES
+ display_name = "Colony Fabricator Structure Designs"
+ description = "Contains all of the colony fabricator's structure designs."
+ design_ids = list(
+ "prefab_airlock_kit",
+ "prefab_manual_airlock_kit",
+ "prefab_shutters_kit",
+ "prefab_floor_tile",
+ "prefab_cat_floor_tile",
+ "colony_fab_plastic_wall_panel",
+ )
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 50000000000000) // God save you
+ hidden = TRUE
+ show_on_wiki = FALSE
+ starting_node = TRUE
+
+// Airlock kit
+
+/datum/design/prefab_airlock_kit
+ name = "Prefab Airlock"
+ id = "prefab_airlock_kit"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ )
+ build_path = /obj/item/flatpacked_machine/airlock_kit
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_CONSTRUCTION + FABRICATOR_SUBCATEGORY_STRUCTURES,
+ )
+ construction_time = 10 SECONDS
+
+// Manul Airlock kit
+
+/datum/design/prefab_manual_airlock_kit
+ name = "Prefab Manual Airlock"
+ id = "prefab_manual_airlock_kit"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ )
+ build_path = /obj/item/flatpacked_machine/airlock_kit_manual
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_CONSTRUCTION + FABRICATOR_SUBCATEGORY_STRUCTURES,
+ )
+ construction_time = 5 SECONDS
+
+// Shutters kit
+
+/datum/design/prefab_shutters_kit
+ name = "Prefab Shutters"
+ id = "prefab_shutters_kit"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ )
+ build_path = /obj/item/flatpacked_machine/shutter_kit
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_CONSTRUCTION + FABRICATOR_SUBCATEGORY_STRUCTURES,
+ )
+ construction_time = 10 SECONDS
+
+// Fancy floor tiles
+
+/datum/design/prefab_floor_tile
+ name = "Prefab Floor Tile"
+ id = "prefab_floor_tile"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT / 4,
+ )
+ build_path = /obj/item/stack/tile/iron/colony
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_CONSTRUCTION + FABRICATOR_SUBCATEGORY_STRUCTURES,
+ )
+ construction_time = 0.5 SECONDS
+
+// Fancy catwalk floor tiles
+
+/datum/design/prefab_cat_floor_tile
+ name = "Prefab Catwalk Plating"
+ id = "prefab_cat_floor_tile"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT / 4,
+ )
+ build_path = /obj/item/stack/tile/catwalk_tile/colony_lathe
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_CONSTRUCTION + FABRICATOR_SUBCATEGORY_STRUCTURES,
+ )
+ construction_time = 0.5 SECONDS
+
+// Plastic wall panels, twice the wall for the same price in plastic, efficient!
+
+/datum/design/colony_fab_plastic_wall_panel
+ name = "Plastic Paneling"
+ id = "colony_fab_plastic_wall_panel"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/stack/sheet/plastic_wall_panel/ten
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_CONSTRUCTION + FABRICATOR_SUBCATEGORY_STRUCTURES,
+ )
+ construction_time = 1 SECONDS
+
+#undef FABRICATOR_SUBCATEGORY_STRUCTURES
diff --git a/modular_doppler/colony_fabricator/code/design_datums/equipment.dm b/modular_doppler/colony_fabricator/code/design_datums/equipment.dm
new file mode 100644
index 0000000000000..66ca88556d45b
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/equipment.dm
@@ -0,0 +1,19 @@
+/datum/design/survival_knife
+ name = "Survival Knife"
+ id = "survival_knife"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 6,
+ )
+ build_path = /obj/item/knife/combat/survival
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_KITCHEN,
+ )
+ departmental_flags = DEPARTMENT_BITFLAG_SERVICE
+
+// Lets colony fabricators make soup pots, removes bluespace crystal requirement. It's just a pot...
+/datum/design/soup_pot/New()
+ build_type |= COLONY_FABRICATOR
+ materials -= /datum/material/bluespace
+ return ..()
diff --git a/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/computer_board.dm b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/computer_board.dm
new file mode 100644
index 0000000000000..c690e454eedec
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/computer_board.dm
@@ -0,0 +1,11 @@
+/datum/design/board/solarcontrol/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/atmosalerts/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/powermonitor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
diff --git a/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/construction.dm b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/construction.dm
new file mode 100644
index 0000000000000..ea92e20e1f3a3
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/construction.dm
@@ -0,0 +1,117 @@
+// This file is going to be just all bitflag additions
+
+/datum/design/apc_board/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/airalarm_electronics/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/airlock_board/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/firealarm_electronics/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/control/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/firelock_board/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/infrared_emitter/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/prox_sensor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/signaler/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/timer/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+// Wall frames
+
+/datum/design/camera_assembly/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/intercom_frame/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/light_switch_frame/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/ignition_control/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/sparker/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/newscaster_frame/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/status_display_frame/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/requests_console/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+// Lights
+
+/datum/design/light_tube/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/light_bulb/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+// Conveyors
+
+/datum/design/conveyor_belt/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/conveyor_switch/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+// Materials
+
+/datum/design/lavarods/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rglass/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plasteel_alloy/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plaglass_alloy/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plasmarglass_alloy/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
diff --git a/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/equipment.dm b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/equipment.dm
new file mode 100644
index 0000000000000..9ebd506602d21
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/equipment.dm
@@ -0,0 +1,103 @@
+// This file is going to be just all bitflag additions
+
+/datum/design/radio_navigation_beacon/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/engine_goggles/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/pneumatic_seal/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/welding_goggles/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/welding_helmet/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/gas_filter/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plasmaman_gas_filter/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plasmarefiller/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/emergency_oxygen_engi/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plasmaman_tank_belt/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/generic_gas_tank/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plasma_tank/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/diagnostic_hud/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/portaseeder/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/oven_tray/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/bowl/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/beaker/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+// Stock parts are going here too because there's not many of them
+
+/datum/design/water_recycler/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/super_cell/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/adv_capacitor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/adv_scanning/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/nano_servo/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/high_micro_laser/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/adv_matter_bin/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rped/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
diff --git a/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/machine_boards.dm b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/machine_boards.dm
new file mode 100644
index 0000000000000..b05045ed60eda
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/machine_boards.dm
@@ -0,0 +1,49 @@
+/datum/design/board/hydroponics/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/cyborgrecharger/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/processor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/suit_storage_unit/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/reagentgrinder/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+// Turbine Stuff
+
+/datum/design/board/turbine_computer/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/turbine_compressor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/turbine_rotor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/board/turbine_stator/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/turbine_part_compressor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/turbine_part_stator/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/turbine_part_rotor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
diff --git a/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/stock_parts.dm b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/stock_parts.dm
new file mode 100644
index 0000000000000..9990dfcfa3fa8
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/stock_parts.dm
@@ -0,0 +1,31 @@
+/datum/design/water_recycler/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/super_cell/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/adv_capacitor/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/adv_scanning/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/nano_servo/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/high_micro_laser/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/adv_matter_bin/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rped/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
diff --git a/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/tools.dm b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/tools.dm
new file mode 100644
index 0000000000000..9d24a6d043fb9
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/fabricator_flag_additions/tools.dm
@@ -0,0 +1,157 @@
+// Various designs that get added to the colony fab
+
+/datum/design/holosignatmos/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/analyzer/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/extinguisher/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/cable_coil/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/airlock_painter/decal/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/airlock_painter/decal/tile/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/holosignengi/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/inducer/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/multitool/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/tscanner/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/pipe_painter/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rwd/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/bolter_wrench/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rpd/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rpd_upgrade/unwrench/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rtd_loaded/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rcd_ammo/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/light_replacer/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/rld_mini/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/miningsatchel_holding/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/mining_scanner/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/flashlight/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/ducts/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plunger/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/handlabeler/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/paperroll/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/spraycan/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/pickaxe/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/bucket/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/watering_can/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/mop/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/broom/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/tray/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/cultivator/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/plant_analyzer/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/shovel/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/spade/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/hatchet/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
+
+/datum/design/secateurs/New()
+ . = ..()
+ build_type |= COLONY_FABRICATOR
diff --git a/modular_doppler/colony_fabricator/code/design_datums/flatpack_machines.dm b/modular_doppler/colony_fabricator/code/design_datums/flatpack_machines.dm
new file mode 100644
index 0000000000000..d242abc9388b5
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/flatpack_machines.dm
@@ -0,0 +1,275 @@
+// Machine categories
+
+#define FABRICATOR_CATEGORY_FLATPACK_MACHINES "/Flatpacked Machines"
+#define FABRICATOR_SUBCATEGORY_MANUFACTURING "/Manufacturing"
+#define FABRICATOR_SUBCATEGORY_POWER "/Power"
+#define FABRICATOR_SUBCATEGORY_MATERIALS "/Materials"
+#define FABRICATOR_SUBCATEGORY_ATMOS "/Atmospherics"
+
+// Techweb node that shouldnt show up anywhere ever specifically for the fabricator to work with
+
+/datum/techweb_node/colony_fabricator_flatpacks
+ id = TECHWEB_NODE_COLONY_FLATPACKS
+ display_name = "Colony Fabricator Flatpack Designs"
+ description = "Contains all of the colony fabricator's flatpack machine designs."
+ design_ids = list(
+ "flatpack_solar_panel",
+ "flatpack_solar_tracker",
+ "flatpack_arc_furnace",
+ "flatpack_colony_fab",
+ "flatpack_station_battery",
+ "flatpack_station_battery_large",
+ "flatpack_fuel_generator",
+ "flatpack_rtg",
+ "flatpack_thermo",
+ "flatpack_ore_silo",
+ "flatpack_turbine_team_fortress_two",
+ "flatpack_bootleg_teg",
+ )
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 50000000000000) // God save you
+ hidden = TRUE
+ show_on_wiki = FALSE
+ starting_node = TRUE
+
+// Lets the colony lathe make more colony lathes but at very hihg cost, for fun
+
+/datum/design/flatpack_colony_fabricator
+ name = "Flat-Packed Colony Fabricator"
+ desc = "A deployable fabricator capable of producing other flat-packed machines and other special equipment tailored for \
+ rapidly constructing functional structures given resources and power. While it cannot be upgraded, it can be repacked \
+ and moved to any location you see fit."
+ id = "flatpack_colony_fab"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 10,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 2.5,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_MANUFACTURING,
+ )
+ construction_time = 2 MINUTES
+
+// Solar panels and trackers
+
+/datum/design/flatpack_solar_panel
+ name = "Flat-Packed Solar Panel"
+ desc = "A deployable solar panel, able to be repacked after placement for relocation or recycling."
+ id = "flatpack_solar_panel"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 1,
+ )
+ build_path = /obj/item/flatpacked_machine/solar
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 5 SECONDS
+
+/datum/design/flatpack_solar_tracker
+ name = "Flat-Packed Solar Tracker"
+ desc = "A deployable solar tracker, able to be repacked after placement for relocation or recycling."
+ id = "flatpack_solar_tracker"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 3.5,
+ )
+ build_path = /obj/item/flatpacked_machine/solar_tracker
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 7 SECONDS
+
+// Arc furance
+
+/datum/design/flatpack_arc_furnace
+ name = "Flat-Packed Arc Furnace"
+ desc = "A deployable furnace for refining ores. While slower and less safe than conventional refining methods, \
+ it multiplies the output of refined materials enough to still outperform simply recycling ore."
+ id = "flatpack_arc_furnace"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ )
+ build_path = /obj/item/flatpacked_machine/arc_furnace
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_MATERIALS,
+ )
+ construction_time = 15 SECONDS
+
+// Power storage structures
+
+/datum/design/flatpack_power_storage
+ name = "Flat-Packed Stationary Battery"
+ desc = "A deployable station-scale power cell with an overall low capacity, but high input and output rate."
+ id = "flatpack_station_battery"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/station_battery
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 20 SECONDS
+
+/datum/design/flatpack_power_storage_large
+ name = "Flat-Packed Large Stationary Battery"
+ desc = "A deployable station-scale power cell with an overall extremely high capacity, but low input and output rate."
+ id = "flatpack_station_battery_large"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 12,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 4,
+ /datum/material/gold = SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/large_station_battery
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 40 SECONDS
+
+// PACMAN generator but epic!!
+
+/datum/design/flatpack_solids_generator
+ name = "Flat-Packed S.O.F.I.E. Generator"
+ desc = "A deployable plasma-burning generator capable of outperforming even upgraded P.A.C.M.A.N. type generators, \
+ at expense of creating hot carbon dioxide exhaust."
+ id = "flatpack_fuel_generator"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ /datum/material/titanium = SHEET_MATERIAL_AMOUNT,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/fuel_generator
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 30 SECONDS
+
+// Buildable RTG that is quite radioactive
+
+/datum/design/flatpack_rtg
+ name = "Flat-Packed Radioisotope Thermoelectric Generator"
+ desc = "A deployable radioisotope generator capable of producing a practically free trickle of power. \
+ Free if you can tolerate the radiation that the machine makes while deployed, that is."
+ id = "flatpack_rtg"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15,
+ /datum/material/uranium = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/plasma = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/rtg
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 30 SECONDS
+
+// Thermomachine with decent temperature change rate, but a limited max/min temperature
+
+/datum/design/flatpack_thermomachine
+ name = "Flat-Packed Atmospheric Temperature Regulator"
+ desc = "A deployable temperature control device for use with atmospherics pipe systems. \
+ Limited in its temperature range, however comes with a higher than normal heat capacity."
+ id = "flatpack_thermo"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/thermomachine
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_ATMOS,
+ )
+ construction_time = 20 SECONDS
+
+// Ore silo except it beeps
+
+/datum/design/flatpack_ore_silo
+ name = "Flat-Packed Ore Silo"
+ desc = "An all-in-one materials management solution. Connects resource-using machines \
+ through a network of distrobution systems."
+ id = "flatpack_ore_silo"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5,
+ )
+ build_path = /obj/item/flatpacked_machine/ore_silo
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_MATERIALS,
+ )
+ construction_time = 1 MINUTES
+
+// Wind turbine, produces tiny amounts of power when placed outdoors in an atmosphere, but makes significantly more if there's a storm in that area
+
+/datum/design/flatpack_turbine_team_fortress_two
+ name = "Flat-Packed Miniature Wind Turbine"
+ desc = "A deployable fabricator capable of producing other flat-packed machines and other special equipment tailored for \
+ rapidly constructing functional structures given resources and power. While it cannot be upgraded, it can be repacked \
+ and moved to any location you see fit. This one makes specialized engineering designs and tools."
+ id = "flatpack_turbine_team_fortress_two"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/flatpacked_machine/wind_turbine
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 30 SECONDS
+
+// Stirling generator, kinda like a TEG but on a smaller scale and producing less insane amounts of power
+
+/datum/design/flatpack_bootleg_teg
+ name = "Flat-Packed Stirling Generator"
+ desc = "An industrial scale stirling generator. Stirling generators operate by intaking \
+ hot gasses through their inlet pipes, and being cooled by the ambient air around them. \
+ The cycling compression and expansion that this creates creates power, and this one is made \
+ to make power on the scale of small stations and outposts."
+ id = "flatpack_bootleg_teg"
+ build_type = COLONY_FABRICATOR
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/plasma = SHEET_MATERIAL_AMOUNT * 10,
+ /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/gold = SHEET_MATERIAL_AMOUNT * 5,
+ )
+ build_path = /obj/item/flatpacked_machine/stirling_generator
+ category = list(
+ RND_CATEGORY_INITIAL,
+ FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER,
+ )
+ construction_time = 2 MINUTES
+
+#undef FABRICATOR_CATEGORY_FLATPACK_MACHINES
+#undef FABRICATOR_SUBCATEGORY_MANUFACTURING
+#undef FABRICATOR_SUBCATEGORY_POWER
+#undef FABRICATOR_SUBCATEGORY_MATERIALS
+#undef FABRICATOR_SUBCATEGORY_ATMOS
diff --git a/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/ingredients.dm b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/ingredients.dm
new file mode 100644
index 0000000000000..3c7b6e8d39a5a
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/ingredients.dm
@@ -0,0 +1,65 @@
+/datum/design/frontier_ration_egg
+ name = "Egg"
+ id = "frontier_ration_egg"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/food/egg
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_INGREDIENTS,
+ )
+
+/datum/design/frontier_ration_chicken
+ name = "Chicken"
+ id = "frontier_ration_chicken"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/food/meat/slab/chicken
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_INGREDIENTS,
+ )
+
+/datum/design/frontier_ration_mystery_meat
+ name = "Meat Product"
+ id = "frontier_ration_mystery_meat"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/food/meat/slab/meatproduct
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_INGREDIENTS,
+ )
+
+/datum/design/frontier_ration_butter
+ name = "Butter"
+ id = "frontier_ration_butter"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/food/butter
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_INGREDIENTS,
+ )
+
+/datum/design/frontier_ration_cheese
+ name = "Cheese"
+ id = "frontier_ration_cheese"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/food/cheese/wedge
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_INGREDIENTS,
+ )
+
+/datum/design/frontier_ration_cheese_firm
+ name = "Firm Cheese"
+ id = "frontier_ration_firm_cheese"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/food/cheese/firm_cheese_slice
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_INGREDIENTS,
+ )
diff --git a/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/reagents.dm b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/reagents.dm
new file mode 100644
index 0000000000000..64134e7f67fab
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/reagents.dm
@@ -0,0 +1,65 @@
+/datum/design/frontier_ration_flour
+ name = "Flour Sack"
+ id = "frontier_ration_flour_sack"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/condiment/flour/small_ration
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_BAGS,
+ )
+
+/datum/design/frontier_ration_flour_korta
+ name = "Korta Flour Sack"
+ id = "frontier_ration_flour_sack_korta"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/condiment/small_ration_korta_flour
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_BAGS,
+ )
+
+/datum/design/frontier_ration_rice
+ name = "Rice Sack"
+ id = "frontier_ration_rice_sack"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/condiment/rice/small_ration
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_BAGS,
+ )
+
+/datum/design/frontier_ration_sugar
+ name = "Sugar Sack"
+ id = "frontier_ration_sugar_sack"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/condiment/sugar/small_ration
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_BAGS,
+ )
+
+/datum/design/frontier_ration_soy_milk
+ name = "Soy Milk"
+ id = "frontier_ration_soy_milk_cart"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/condiment/soymilk/small_ration
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_BAGS,
+ )
+
+/datum/design/frontier_ration_milk
+ name = "Milk"
+ id = "frontier_ration_milk_cart"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/condiment/milk/small_ration
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_BAGS,
+ )
diff --git a/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/seeds.dm b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/seeds.dm
new file mode 100644
index 0000000000000..11c0c99631607
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/seeds.dm
@@ -0,0 +1,87 @@
+/datum/design/organic_parsnip_seed
+ name = "Parsnip Seed Pack"
+ id = "oganic_parsnip_seed"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/seeds/carrot/parsnip
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
+
+/datum/design/organic_beet_seed
+ name = "White-Beet Seed Pack"
+ id = "oganic_beet_seed"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/seeds/whitebeet
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
+
+/datum/design/organic_potato_seed
+ name = "Potato Seed Pack"
+ id = "oganic_potato_seed"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/seeds/potato
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
+
+/datum/design/organic_soy_seed
+ name = "Soybean Seed Pack"
+ id = "oganic_soy_seed"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/seeds/soya
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
+
+/datum/design/organic_rice_seed
+ name = "Rice Seed Pack"
+ id = "oganic_rice_seed"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/seeds/wheat/rice
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
+
+/datum/design/organic_oat_seed
+ name = "Oat Seed Pack"
+ id = "oganic_oat_seed"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/seeds/wheat/oat
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
+
+/datum/design/organic_korta_seed
+ name = "Korta Seed Pack"
+ id = "oganic_korta_seed"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/seeds/korta_nut
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
+
+/datum/design/organic_plump_helmet
+ name = "Plump-Helmet Seed Pack"
+ id = "oganic_plump_helmet"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/seeds/plump
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_SEEDS,
+ )
diff --git a/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/snacks.dm b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/snacks.dm
new file mode 100644
index 0000000000000..73098b23288b9
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/snacks.dm
@@ -0,0 +1,76 @@
+/datum/design/frontier_ration_gum
+ name = "Gum"
+ id = "frontier_ration_gum"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/storage/box/gum
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS,
+ )
+
+/datum/design/frontier_ration_gum_wakeup
+ name = "Activin 12 Hour Medicated Gum"
+ id = "frontier_ration_gum_wakeup"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/storage/box/gum/wake_up
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS,
+ )
+
+/datum/design/frontier_ration_energy_bar
+ name = "High Power Energy Bar"
+ id = "frontier_ration_energy_bar"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/food/energybar
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS,
+ )
+
+/datum/design/frontier_ration_ciggies
+ name = "Cigarettes"
+ id = "frontier_ration_ciggies"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/storage/fancy/cigarettes/cigpack_uplift
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS,
+ )
+
+/datum/design/frontier_ration_engine_fodder
+ name = "Engine Fodder"
+ id = "frontier_ration_engine_fodder"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/food/vendor_snacks/moth_bag
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS,
+ )
+
+/datum/design/frontier_ration_fueljak_snack
+ name = "Fueljack's Snack"
+ id = "frontier_ration_fueljak_snack"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/food/vendor_snacks/moth_bag/fuel_jack
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS,
+ )
+
+/datum/design/frontier_ration_ricecracker
+ name = "Rice Crackers"
+ id = "frontier_ration_ricecracker"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/food/vendor_snacks/rice_crackers
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_SNACKS,
+ )
diff --git a/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/utensils.dm b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/utensils.dm
new file mode 100644
index 0000000000000..05508fc659b96
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/rations_printer_designs/utensils.dm
@@ -0,0 +1,43 @@
+/datum/design/frontier_ration_plastic_fork
+ name = "Plastic Fork"
+ id = "frontier_ration_plastic_fork"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 10)
+ build_path = /obj/item/kitchen/fork/plastic
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_UTENSILS,
+ )
+
+/datum/design/frontier_ration_plastic_spoon
+ name = "Plastic Spoon"
+ id = "frontier_ration_plastic_spoon"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 10)
+ build_path = /obj/item/kitchen/spoon/plastic
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_UTENSILS,
+ )
+
+/datum/design/frontier_ration_plastic_knife
+ name = "Plastic Knife"
+ id = "frontier_ration_plastic_knife"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 10)
+ build_path = /obj/item/knife/plastic
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_UTENSILS,
+ )
+
+/datum/design/frontier_ration_plastic_cup
+ name = "Plastic Cup"
+ id = "frontier_ration_plastic_cup"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/reagent_containers/cup/glass/coffee_cup
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_FOODRICATOR_UTENSILS,
+ )
diff --git a/modular_doppler/colony_fabricator/code/design_datums/tools.dm b/modular_doppler/colony_fabricator/code/design_datums/tools.dm
new file mode 100644
index 0000000000000..9c3c62728ec88
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/design_datums/tools.dm
@@ -0,0 +1,80 @@
+/datum/techweb_node/colony_fabricator_special_tools
+ id = TECHWEB_NODE_COLONY_TOOLS
+ display_name = "Colony Fabricator Tool Designs"
+ description = "Contains all of the colony fabricator's tool designs."
+ design_ids = list(
+ "colony_power_drive",
+ "colony_prybar",
+ "colony_arc_welder",
+ "colony_compact_drill",
+ )
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 50000000000000) // God save you
+ hidden = TRUE
+ show_on_wiki = FALSE
+ starting_node = TRUE
+
+// Screw-Wrench-Wirecutter combo machine
+
+/datum/design/colony_power_driver
+ name = "Powered Driver"
+ id = "colony_power_drive"
+ build_type = COLONY_FABRICATOR
+ build_path = /obj/item/screwdriver/omni_drill
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.75,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT * 1.5,
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_ENGINEERING_ADVANCED,
+ )
+
+// Crowbar that is completely normal except it can force doors
+
+/datum/design/colony_door_crowbar
+ name = "Prybar"
+ id = "colony_prybar"
+ build_type = COLONY_FABRICATOR
+ build_path = /obj/item/crowbar/large/doorforcer
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.75,
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_ENGINEERING_ADVANCED,
+ )
+
+// Welder that takes no fuel or power to run but is quite slow, at least it sounds cool as hell
+
+/datum/design/colony_arc_welder
+ name = "Arc Welder"
+ id = "colony_arc_welder"
+ build_type = COLONY_FABRICATOR
+ build_path = /obj/item/weldingtool/arc_welder
+ materials = list(
+ /datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/plasma = HALF_SHEET_MATERIAL_AMOUNT * 1.5,
+ )
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_ENGINEERING_ADVANCED,
+ )
+
+// Slightly slower drill that fits in backpacks
+
+/datum/design/colony_compact_drill
+ name = "Compact Mining Drill"
+ id = "colony_compact_drill"
+ build_type = COLONY_FABRICATOR
+ build_path = /obj/item/pickaxe/drill/compact
+ materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_MINING,
+ )
diff --git a/modular_doppler/colony_fabricator/code/looping_sounds.dm b/modular_doppler/colony_fabricator/code/looping_sounds.dm
new file mode 100644
index 0000000000000..a1f26b8fb8d88
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/looping_sounds.dm
@@ -0,0 +1,35 @@
+/datum/looping_sound/colony_fabricator_running
+ start_sound = 'modular_doppler/colony_fabricator/sounds/fabricator/fabricator_start.wav'
+ start_length = 1
+ mid_sounds = list(
+ 'modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_1.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_2.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_3.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_4.wav' = 1,
+ )
+ mid_length = 3 SECONDS
+ end_sound = 'modular_doppler/colony_fabricator/sounds/fabricator/fabricator_end.wav'
+ volume = 100
+ falloff_exponent = 3
+
+/datum/looping_sound/arc_furnace_running
+ mid_sounds = list(
+ 'modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_1.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_2.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_3.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_4.wav' = 1,
+ )
+ mid_length = 1 SECONDS
+ volume = 200 // This sound effect is very quiet I've noticed
+ falloff_exponent = 2
+
+/datum/looping_sound/conditioner_running
+ mid_sounds = list(
+ 'modular_doppler/colony_fabricator/sounds/conditioner/conditioner_1.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/conditioner/conditioner_2.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/conditioner/conditioner_3.wav' = 1,
+ 'modular_doppler/colony_fabricator/sounds/conditioner/conditioner_4.wav' = 1,
+ )
+ mid_length = 3 SECONDS
+ volume = 40
+ falloff_exponent = 3
diff --git a/modular_doppler/colony_fabricator/code/machines/arc_furnace.dm b/modular_doppler/colony_fabricator/code/machines/arc_furnace.dm
new file mode 100644
index 0000000000000..b0bcd07a25f4a
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/machines/arc_furnace.dm
@@ -0,0 +1,231 @@
+#define RADIAL_CHOICE_USE "use"
+#define RADIAL_CHOICE_EJECT "eject"
+
+#define ARC_FURNACE_ORE_MULTIPLIER 1.5
+
+/obj/machinery/arc_furnace
+ name = "arc furnace"
+ desc = "An arc furnace, a specialist machine that can rapidly smelt ores using, as the name implies, massive \
+ amounts of electricity. While not nearly as fast and efficient as other ore refining methods, the arc furnace is \
+ capable of returning larger amounts of refined material than a standard refining process can. \
+ A sticker on the side notes that this may exhaust waste gasses to the air during operation."
+ icon = 'modular_doppler/colony_fabricator/icons/machines.dmi'
+ icon_state = "arc_furnace"
+ base_icon_state = "arc_furnace"
+ appearance_flags = KEEP_TOGETHER | LONG_GLIDE | PIXEL_SCALE
+ layer = BELOW_OBJ_LAYER
+ density = TRUE
+ circuit = null
+ light_color = LIGHT_COLOR_BRIGHT_YELLOW
+ light_power = 10
+ active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 10 // This baby consumes so much power
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/flatpacked_machine/arc_furnace
+ /// If the furnace is currently working on smelting something
+ var/operating = FALSE
+ /// Image for the radial eject button
+ var/static/radial_eject = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_eject")
+ /// Image for the radial use button
+ var/static/radial_use = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_use")
+ /// Radial options for using the arc furnace
+ var/static/list/radial_options = list(RADIAL_CHOICE_EJECT = radial_eject, RADIAL_CHOICE_USE = radial_use)
+ /// Soundloop for while we are smelting ores
+ var/datum/looping_sound/arc_furnace_running/soundloop
+
+/obj/machinery/arc_furnace/Initialize(mapload)
+ . = ..()
+ soundloop = new(src, FALSE)
+ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ if(!mapload)
+ flick("arc_furnace_deploy", src)
+
+/obj/machinery/arc_furnace/examine(mob/user)
+ . = ..()
+ if(length(contents))
+ . += span_notice("It has [contents[1]] sitting in it.")
+
+// formerly NO_DECONSTRUCTION
+/obj/machinery/arc_furnace/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/arc_furnace/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/arc_furnace/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+/obj/machinery/arc_furnace/on_deconstruction(disassembled)
+ eject_contents()
+
+/obj/machinery/arc_furnace/update_appearance()
+ . = ..()
+ cut_overlays()
+
+ if(length(contents))
+ var/image/overlayed_item = image(icon = contents[1].icon, icon_state = contents[1].icon_state)
+ overlayed_item.transform = matrix(, 0, 0, 0, 0.8, 0)
+ add_overlay(overlayed_item)
+
+ var/image/furnace_front_overlay = image(icon = icon, icon_state = "[operating ? "[base_icon_state]_overlay_active" : "[base_icon_state]_overlay"]")
+ add_overlay(furnace_front_overlay)
+
+/obj/machinery/arc_furnace/attackby(obj/item/attacking_item, mob/living/user, params)
+ if(operating)
+ balloon_alert(user, "furnace busy")
+ return TRUE
+
+ if(length(contents))
+ balloon_alert(user, "furnace full")
+ return TRUE
+
+ if(istype(attacking_item, /obj/item/stack/ore))
+ attacking_item.forceMove(src)
+ balloon_alert(user, "ore added")
+ update_appearance()
+ return TRUE
+
+ return ..()
+
+/obj/machinery/arc_furnace/ui_interact(mob/user)
+ . = ..()
+
+ if(operating || !user.can_perform_action(src, ALLOW_SILICON_REACH))
+ return
+ if(isAI(user) && (machine_stat & NOPOWER))
+ return
+
+ if(!length(contents))
+ balloon_alert(user, "it's empty!")
+ return
+
+ var/choice = show_radial_menu(user, src, radial_options, require_near = !issilicon(user))
+
+ // post choice verification
+ if(operating || !user.can_perform_action(src, ALLOW_SILICON_REACH))
+ return
+ if(isAI(user) && (machine_stat & NOPOWER))
+ return
+
+ switch(choice)
+ if(RADIAL_CHOICE_EJECT)
+ eject_contents()
+ if(RADIAL_CHOICE_USE)
+ smelt_it_up(user)
+
+/// Removes the first item in the contents list which should only ever be ore and if it's not, we have problems
+/obj/machinery/arc_furnace/proc/eject_contents()
+ if(operating)
+ return
+
+ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
+
+ if(!length(contents))
+ return
+
+ var/atom/movable/thing_inside = contents[1]
+ thing_inside.forceMove(drop_location())
+ update_appearance()
+
+/// Starts the smelting process, checking if the machine has power or if it's broken at all
+/obj/machinery/arc_furnace/proc/smelt_it_up(mob/user)
+ if(machine_stat & (NOPOWER|BROKEN))
+ balloon_alert(user, "button doesn't respond")
+ return
+ if(operating)
+ balloon_alert(user, "already smelting")
+ return
+
+ var/obj/item/stack/ore/ore_to_smelt = contents[1]
+ if(!istype(ore_to_smelt))
+ balloon_alert(user, "nothing to smelt")
+
+ operating = TRUE
+ /// How long the smelting is going to take based off the stack size
+ var/smelting_time = ore_to_smelt.amount * 1 SECONDS
+ loop(smelting_time)
+
+ soundloop.start()
+ set_light(l_range = 1.5)
+
+ update_appearance()
+
+/// The smelting loop for checking if we're done smelting or not. If we are, then we succeed smelting. If we have to stop for whatever reason, we stop.
+/obj/machinery/arc_furnace/proc/loop(time)
+ if(machine_stat & (NOPOWER|BROKEN))
+ end_smelting()
+ return
+
+ if(!length(contents))
+ end_smelting()
+ return
+
+ if(time <= 0)
+ succeed_smelting()
+ return
+
+ time -= 1 SECONDS
+ use_energy(active_power_usage)
+
+ var/turf/where_we_spawn_air = get_turf(src)
+ var/obj/item/stack/ore/ore_stack_to_check = contents[1]
+ switch(ore_stack_to_check.refined_type)
+ if(/obj/item/stack/sheet/mineral/silver)
+ where_we_spawn_air.atmos_spawn_air("n2=10;TEMP=1200")
+ if(/obj/item/stack/sheet/mineral/uranium)
+ where_we_spawn_air.atmos_spawn_air("co2=50;TEMP=1200")
+ if(/obj/item/stack/sheet/mineral/titanium)
+ where_we_spawn_air.atmos_spawn_air("n2=10;co2=10;TEMP=1200")
+ if(/obj/item/stack/sheet/mineral/plasma)
+ where_we_spawn_air.atmos_spawn_air("co2=75;TEMP=2000")
+ else
+ where_we_spawn_air.atmos_spawn_air("co2=20;TEMP=1200")
+
+ addtimer(CALLBACK(src, PROC_REF(loop), time), 1 SECONDS)
+
+/// Takes the ore contained and turns it into an equal stack amount of its smelt result
+/obj/machinery/arc_furnace/proc/succeed_smelting()
+ var/obj/item/stack/ore/ore_to_smelt = contents[1]
+ if(!istype(ore_to_smelt))
+ end_smelting()
+
+ // We collect how many sheets of material we will need to spawn with the multiplier, whole sheets only!
+ var/how_much_material_to_spawn = round(ore_to_smelt.amount * ARC_FURNACE_ORE_MULTIPLIER)
+ // We also grab what the resulting refined type will be
+ var/obj/item/stack/ore_refined_type = ore_to_smelt.refined_type
+
+ // While the materials to spawn are greater than or equal to the max stack amount of the product, we can just safely spawn the max amount
+ // Variable with the max stack amount just for futureproofing, because why not?
+ while(how_much_material_to_spawn >= ore_refined_type.max_amount)
+ new ore_refined_type(drop_location(), ore_refined_type.max_amount)
+ how_much_material_to_spawn -= ore_refined_type.max_amount
+
+ // Now, we spawn a stack with whatever's left, if there is anything left
+ if(how_much_material_to_spawn)
+ new ore_refined_type(drop_location(), how_much_material_to_spawn)
+
+ qdel(ore_to_smelt)
+ end_smelting()
+
+/// Turns the arc furnace off, removing its lights, sounds, so on.
+/obj/machinery/arc_furnace/proc/end_smelting()
+ operating = FALSE
+ soundloop.stop()
+ set_light(l_range = 0)
+ update_appearance()
+
+// Item for creating the arc furnace or carrying it around
+
+/obj/item/flatpacked_machine/arc_furnace
+ name = "flat-packed arc furnace"
+ icon_state = "arc_furnace_folded"
+ type_to_deploy = /obj/machinery/arc_furnace
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3,
+ )
+
+#undef RADIAL_CHOICE_USE
+#undef RADIAL_CHOICE_EJECT
+
+#undef ARC_FURNACE_ORE_MULTIPLIER
diff --git a/modular_doppler/colony_fabricator/code/machines/ore_silo.dm b/modular_doppler/colony_fabricator/code/machines/ore_silo.dm
new file mode 100644
index 0000000000000..3d2adec9c18fa
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/machines/ore_silo.dm
@@ -0,0 +1,30 @@
+/obj/machinery/ore_silo/colony_lathe
+ name = "colony ore silo"
+ desc = "An all-in-one materials management solution. Connects resource-using machines \
+ through a network of distribution systems."
+ icon = 'modular_doppler/colony_fabricator/icons/ore_silo.dmi'
+ circuit = null
+ /// What this packs into
+ var/packed_type = /obj/item/flatpacked_machine/ore_silo
+
+/obj/machinery/ore_silo/colony_lathe/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, packed_type, 10 SECONDS)
+
+/obj/machinery/ore_silo/colony_lathe/silo_log(obj/machinery/machinery_in_question, action, amount, noun, list/mats)
+ . = ..()
+ playsound(src, 'sound/machines/beep.ogg', 30, TRUE)
+
+/obj/machinery/ore_silo/colony_lathe/default_deconstruction_crowbar()
+ return
+
+// Item for deploying ore silos
+/obj/item/flatpacked_machine/ore_silo
+ name = "flat-packed ore silo"
+ icon = 'modular_doppler/colony_fabricator/icons/ore_silo.dmi'
+ icon_state = "ore_silo"
+ type_to_deploy = /obj/machinery/ore_silo/colony_lathe
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5,
+ )
diff --git a/modular_doppler/colony_fabricator/code/machines/power_storage_unit.dm b/modular_doppler/colony_fabricator/code/machines/power_storage_unit.dm
new file mode 100644
index 0000000000000..50e269af9ba87
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/machines/power_storage_unit.dm
@@ -0,0 +1,101 @@
+/obj/machinery/power/smes/battery_pack
+ name = "stationary battery"
+ desc = "An about table-height block of power storage, commonly seen in low storage high output power applications. \
+ Smaller units such as these tend to have a respectively smaller energy storage, though also are capable of \
+ higher maximum output than some larger units. Most commonly seen being used not for their ability to store \
+ power, but rather for use in regulating power input and output."
+ icon = 'modular_doppler/colony_fabricator/icons/power_storage_unit/small_battery.dmi'
+ capacity = 7.5 * STANDARD_BATTERY_CHARGE
+ input_level_max = 400 KILO WATTS
+ output_level_max = 400 KILO WATTS
+ circuit = null
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/flatpacked_machine/station_battery
+
+/obj/machinery/power/smes/battery_pack/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, repacked_type, 5 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ if(!mapload)
+ flick("smes_deploy", src)
+
+/obj/machinery/power/smes/battery_pack/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ if(screwdriver.tool_behaviour != TOOL_SCREWDRIVER)
+ return FALSE
+
+ screwdriver.play_tool_sound(src, 50)
+ toggle_panel_open()
+ if(panel_open)
+ icon_state = icon_state_open
+ to_chat(user, span_notice("You open the maintenance hatch of [src]."))
+ else
+ icon_state = icon_state_closed
+ to_chat(user, span_notice("You close the maintenance hatch of [src]."))
+ return TRUE
+
+// formerly NO_DECONSTRUCTION
+/obj/machinery/power/smes/battery_pack/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/smes/battery_pack/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+// We don't care about the parts updates because we don't want them to change
+/obj/machinery/power/smes/battery_pack/RefreshParts()
+ return
+
+// We also don't need to bother with fuddling with charging power cells, there are none to remove
+/obj/machinery/power/smes/battery_pack/on_deconstruction()
+ return
+
+// Automatically set themselves to be completely charged on init
+
+/obj/machinery/power/smes/battery_pack/precharged
+
+/obj/machinery/power/smes/battery_pack/precharged/Initialize(mapload)
+ . = ..()
+ charge = capacity
+
+// Item for creating the small battery and carrying it around
+
+/obj/item/flatpacked_machine/station_battery
+ name = "flat-packed stationary battery"
+ icon_state = "battery_small_packed"
+ type_to_deploy = /obj/machinery/power/smes/battery_pack
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+
+// Larger station batteries, hold more but have less in/output
+
+/obj/machinery/power/smes/battery_pack/large
+ name = "large stationary battery"
+ desc = "A massive block of power storage, commonly seen in high storage low output power applications. \
+ Larger units such as these tend to have a respectively larger energy storage, though only capable of \
+ low maximum output compared to smaller units. Most commonly seen as large backup batteries, or simply \
+ for large power storage where throughput is not a concern."
+ icon = 'modular_doppler/colony_fabricator/icons/power_storage_unit/large_battery.dmi'
+ capacity = 100 * STANDARD_BATTERY_CHARGE
+ input_level_max = 50 KILO WATTS
+ output_level_max = 50 KILO WATTS
+ repacked_type = /obj/item/flatpacked_machine/large_station_battery
+
+// Automatically set themselves to be completely charged on init
+
+/obj/machinery/power/smes/battery_pack/large/precharged
+
+/obj/machinery/power/smes/battery_pack/large/precharged/Initialize(mapload)
+ . = ..()
+ charge = capacity
+
+/obj/item/flatpacked_machine/large_station_battery
+ name = "flat-packed large stationary battery"
+ icon_state = "battery_large_packed"
+ type_to_deploy = /obj/machinery/power/smes/battery_pack/large
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 12,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 4,
+ /datum/material/gold = SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/machines/rtg.dm b/modular_doppler/colony_fabricator/code/machines/rtg.dm
new file mode 100644
index 0000000000000..c1fd041832aec
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/machines/rtg.dm
@@ -0,0 +1,42 @@
+/obj/machinery/power/rtg/portable
+ name = "radioisotope thermoelectric generator"
+ desc = "The ultimate in 'middle of nowhere' power generation. Unlike standard RTGs, this particular \
+ design of generator has forgone the heavy radiation shielding that most RTG designs include. \
+ In better news, these tend to be pretty good with making a passable trickle of power for any \
+ application."
+ icon = 'modular_doppler/colony_fabricator/icons/machines.dmi'
+ circuit = null
+ power_gen = 7.5 KILO WATTS
+ /// What we turn into when we are repacked
+ var/repacked_type = /obj/item/flatpacked_machine/rtg
+
+/obj/machinery/power/rtg/portable/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS)
+ AddElement(/datum/element/radioactive)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ if(!mapload)
+ flick("rtg_deploy", src)
+
+// Item for creating the arc furnace or carrying it around
+
+// formerly NO_DECONSTRUCTION
+/obj/machinery/power/rtg/portable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/power/rtg/portable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/rtg/portable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+/obj/item/flatpacked_machine/rtg
+ name = "flat-packed radioisotope thermoelectric generator"
+ icon_state = "rtg_packed"
+ type_to_deploy = /obj/machinery/power/rtg/portable
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15,
+ /datum/material/uranium = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/plasma = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/machines/solar_panels.dm b/modular_doppler/colony_fabricator/code/machines/solar_panels.dm
new file mode 100644
index 0000000000000..a6f4984a0fcad
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/machines/solar_panels.dm
@@ -0,0 +1,87 @@
+// Solar panels
+
+/obj/machinery/power/solar/deployable
+ icon = 'modular_doppler/colony_fabricator/icons/machines.dmi'
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/flatpacked_machine/solar
+
+/obj/machinery/power/solar/deployable/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, repacked_type, 1 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+/obj/machinery/power/solar/deployable/crowbar_act(mob/user, obj/item/I)
+ return
+
+/obj/machinery/power/solar/deployable/on_deconstruction(disassembled)
+ var/obj/item/solar_assembly/assembly = locate() in src
+ if(assembly)
+ qdel(assembly)
+ return ..()
+
+// formerly NO_DECONSTRUCTION
+/obj/machinery/power/solar/deployable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/power/solar/deployable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/solar/deployable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+// Solar panel deployable item
+
+/obj/item/flatpacked_machine/solar
+ name = "flat-packed solar panel"
+ icon_state = "solar_panel_packed"
+ type_to_deploy = /obj/machinery/power/solar/deployable
+ deploy_time = 2 SECONDS
+ w_class = WEIGHT_CLASS_NORMAL
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.75,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 3,
+ )
+
+// Solar trackers
+
+/obj/machinery/power/tracker/deployable
+ icon = 'modular_doppler/colony_fabricator/icons/machines.dmi'
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/flatpacked_machine/solar_tracker
+
+/obj/machinery/power/tracker/deployable/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, repacked_type, 1 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+/obj/machinery/power/tracker/deployable/crowbar_act(mob/user, obj/item/item_acting)
+ return NONE
+
+// formerly NO_DECONSTRUCTION
+/obj/machinery/power/tracker/deployable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/power/tracker/deployable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/tracker/deployable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+/obj/machinery/power/tracker/deployable/on_deconstruction(disassembled)
+ var/obj/item/solar_assembly/assembly = locate() in src
+ if(assembly)
+ qdel(assembly)
+ return ..()
+
+// Solar tracker deployable item
+
+/obj/item/flatpacked_machine/solar_tracker
+ name = "flat-packed solar tracker"
+ icon_state = "solar_tracker_packed"
+ type_to_deploy = /obj/machinery/power/tracker/deployable
+ deploy_time = 3 SECONDS
+ w_class = WEIGHT_CLASS_NORMAL
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 3.5,
+ )
diff --git a/modular_doppler/colony_fabricator/code/machines/solid_fuel_generator.dm b/modular_doppler/colony_fabricator/code/machines/solid_fuel_generator.dm
new file mode 100644
index 0000000000000..53545ed6877e8
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/machines/solid_fuel_generator.dm
@@ -0,0 +1,61 @@
+/obj/machinery/power/port_gen/pacman/solid_fuel
+ name = "\improper S.O.F.I.E.-type portable generator"
+ desc = "The second most common generator design in the galaxy, second only to the P.A.C.M.A.N. \
+ The S.O.F.I.E. (Stationary Operating Fuel Ignition Engine) is similar to other generators in \
+ burning sheets of plasma in order to produce power. \
+ Unlike other generators however, this one isn't as portable, or as safe to operate, \
+ but at least it makes a hell of a lot more power. Must be bolted to the ground \
+ and attached to a wire before use. A massive warning label wants you to know that this generator \
+ outputs waste heat and gasses to the air around it."
+ icon = 'modular_doppler/colony_fabricator/icons/machines.dmi'
+ icon_state = "fuel_generator_0"
+ base_icon_state = "fuel_generator"
+ circuit = null
+ anchored = TRUE
+ max_sheets = 25
+ time_per_sheet = parent_type::time_per_sheet * (5 / 3) //66.6% better
+ power_gen = parent_type::power_gen * 2.5
+ drag_slowdown = 1.5
+ sheet_path = /obj/item/stack/sheet/mineral/plasma
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/flatpacked_machine/fuel_generator
+
+/obj/machinery/power/port_gen/pacman/solid_fuel/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, repacked_type, 1 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ if(!mapload)
+ flick("fuel_generator_deploy", src)
+
+// formerly NO_DECONSTRUCTION
+/obj/machinery/power/port_gen/pacman/solid_fuel/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/power/port_gen/pacman/solid_fuel/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/port_gen/pacman/solid_fuel/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+// We don't need to worry about the board, this machine doesn't have one!
+/obj/machinery/power/port_gen/pacman/solid_fuel/on_construction(mob/user)
+ return
+
+/obj/machinery/power/port_gen/pacman/solid_fuel/process()
+ . = ..()
+ if(active)
+ var/turf/where_we_spawn_air = get_turf(src)
+ where_we_spawn_air.atmos_spawn_air("co2=10;TEMP=480") // Standard UK diesel engine operating temp is about 220 celsius or ~473 K
+
+// Item for creating the generator or carrying it around
+
+/obj/item/flatpacked_machine/fuel_generator
+ name = "flat-packed S.O.F.I.E.-type portable generator"
+ icon_state = "fuel_generator_packed"
+ type_to_deploy = /obj/machinery/power/port_gen/pacman/solid_fuel
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ /datum/material/titanium = SHEET_MATERIAL_AMOUNT,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/colony_fabricator/code/machines/stirling_generator.dm b/modular_doppler/colony_fabricator/code/machines/stirling_generator.dm
new file mode 100644
index 0000000000000..5300de169b211
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/machines/stirling_generator.dm
@@ -0,0 +1,137 @@
+// Stirling generator, like a miniature TEG, pipe hot air in, and keep the air around it cold
+
+/obj/machinery/power/stirling_generator
+ name = "stirling generator"
+ desc = "An industrial scale stirling generator. Stirling generators operate by intaking \
+ hot gasses through their inlet pipes, and being cooled by the ambient air around them. \
+ The cycling compression and expansion caused by this creates power, and this one is made \
+ to make power on the scale of small stations and outposts."
+ icon = 'modular_doppler/colony_fabricator/icons/stirling_generator/big_generator.dmi'
+ icon_state = "stirling"
+ density = TRUE
+ use_power = NO_POWER_USE
+ circuit = null
+ max_integrity = 300
+ armor_type = /datum/armor/unary_thermomachine
+ set_dir_on_move = FALSE
+ can_change_cable_layer = TRUE
+ /// Reference to the datum connector we're using to interface with the pipe network
+ var/datum/gas_machine_connector/connected_chamber
+ /// What this thing deconstructs into
+ var/deconstruction_type = /obj/item/flatpacked_machine/stirling_generator
+ /// Maximum efficient heat difference, at what heat difference does more difference stop meaning anything for power?
+ var/max_efficient_heat_difference = 8000
+ /// Maximum power output from this machine
+ var/max_power_output = 100 KILO WATTS
+ /// How much power the generator is currently making
+ var/current_power_generation
+ /// Our looping fan sound that we play when turned on
+ var/datum/looping_sound/ore_thumper_fan/soundloop
+
+
+/obj/machinery/power/stirling_generator/Initialize(mapload)
+ . = ..()
+ soundloop = new(src, FALSE)
+ connected_chamber = new(loc, src, dir, CELL_VOLUME * 0.5)
+ connect_to_network()
+ AddElement(/datum/element/repackable, deconstruction_type, 10 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ // This is just to make sure our atmos connection spawns facing the right way
+ setDir(dir)
+
+/obj/machinery/power/stirling_generator/examine(mob/user)
+ . = ..()
+ . += span_notice("You can use a wrench with Left-Click to rotate the generator.")
+ . += span_notice("It will not work in a vacuum as it must be cooled by the gas around it.")
+ . += span_notice("It is currently generating [display_power(current_power_generation, convert = FALSE)] of power.")
+ . += span_notice("It has a maximum power output of [display_power(max_power_output, convert = FALSE)] at a temperature difference of [max_efficient_heat_difference] K.")
+
+
+/obj/machinery/power/stirling_generator/Destroy()
+ QDEL_NULL(connected_chamber)
+ return ..()
+
+
+/obj/machinery/power/stirling_generator/process_atmos()
+ if(!powernet)
+ connect_to_network()
+ if(!powernet)
+ return
+
+ var/turf/our_turf = get_turf(src)
+
+ var/datum/gas_mixture/hot_air_from_pipe = connected_chamber.gas_connector.airs[1]
+ var/datum/gas_mixture/environment = our_turf.return_air()
+
+ if(!QUANTIZE(hot_air_from_pipe.total_moles()) || !QUANTIZE(environment.total_moles())) //Don't transfer if there's no gas
+ return
+
+ var/gas_temperature_delta = hot_air_from_pipe.temperature - environment.temperature
+
+ if(!(gas_temperature_delta > 0))
+ current_power_generation = 0
+ return
+
+ var/input_capacity = hot_air_from_pipe.heat_capacity()
+ var/output_capacity = environment.heat_capacity()
+ var/cooling_heat_amount = CALCULATE_CONDUCTION_ENERGY(gas_temperature_delta, input_capacity, output_capacity)
+ hot_air_from_pipe.temperature = max(hot_air_from_pipe.temperature - (cooling_heat_amount / input_capacity), TCMB)
+
+ /// Takes the amount of heat moved, and divides it by the maximum temperature difference we expect, creating a number to divide power generation by
+ var/effective_energy_transfer = round((max_efficient_heat_difference / min(gas_temperature_delta, max_efficient_heat_difference)), 0.01)
+ current_power_generation = round(max_power_output / effective_energy_transfer)
+
+
+/obj/machinery/power/stirling_generator/process()
+ var/power_output = round(current_power_generation)
+ add_avail(power_to_energy(power_output))
+ var/new_icon_state = (power_output ? "stirling_on" : "stirling")
+ icon_state = new_icon_state
+ if(soundloop.is_active() && !power_output)
+ soundloop.stop()
+ else if(!soundloop.is_active() && power_output)
+ soundloop.start()
+
+
+/obj/machinery/power/stirling_generator/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return
+
+
+/obj/machinery/power/stirling_generator/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return
+
+
+/obj/machinery/power/stirling_generator/wrench_act(mob/living/user, obj/item/tool)
+ return default_change_direction_wrench(user, tool)
+
+
+/obj/machinery/power/stirling_generator/default_change_direction_wrench(mob/user, obj/item/wrench)
+ if(wrench.tool_behaviour != TOOL_WRENCH)
+ return FALSE
+
+ wrench.play_tool_sound(src, 50)
+ setDir(turn(dir,-90))
+ to_chat(user, span_notice("You rotate [src]."))
+ SEND_SIGNAL(src, COMSIG_MACHINERY_DEFAULT_ROTATE_WRENCH, user, wrench)
+ return TRUE
+
+
+/obj/machinery/power/stirling_generator/Destroy()
+ QDEL_NULL(connected_chamber)
+ return ..()
+
+
+// Item for creating stirling generators
+
+/obj/item/flatpacked_machine/stirling_generator
+ name = "flat-packed stirling generator"
+ icon = 'modular_doppler/colony_fabricator/icons/stirling_generator/packed_machines.dmi'
+ icon_state = "stirling"
+ type_to_deploy = /obj/machinery/power/stirling_generator
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/plasma = SHEET_MATERIAL_AMOUNT * 10,
+ /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/gold = SHEET_MATERIAL_AMOUNT * 5,
+ )
diff --git a/modular_doppler/colony_fabricator/code/machines/thermomachine.dm b/modular_doppler/colony_fabricator/code/machines/thermomachine.dm
new file mode 100644
index 0000000000000..3e575583ecc15
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/machines/thermomachine.dm
@@ -0,0 +1,63 @@
+/obj/machinery/atmospherics/components/unary/thermomachine/deployable
+ icon = 'modular_doppler/colony_fabricator/icons/thermomachine.dmi'
+ name = "atmospheric temperature regulator"
+ desc = "A much more tame variant of the thermomachines commonly seen in station scale temperature control devices. \
+ Its upper and lower bounds for temperature are highly limited, though it has a higher than standard heat capacity \
+ and the benefit of being undeployable when you're done with it."
+ circuit = null
+ greyscale_config = /datum/greyscale_config/thermomachine/deployable
+ min_temperature = T0C
+ max_temperature = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD + 50
+ heat_capacity = 10000
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/flatpacked_machine/thermomachine
+ /// Soundloop for while the thermomachine is turned on
+ var/datum/looping_sound/conditioner_running/soundloop
+
+/obj/machinery/atmospherics/components/unary/thermomachine/deployable/Initialize(mapload)
+ . = ..()
+ soundloop = new(src, FALSE)
+ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ flick("thermo_deploy", src)
+
+ // Makes for certain that we are visually facing the correct way
+ setDir(dir)
+ update_appearance()
+
+/obj/machinery/atmospherics/components/unary/thermomachine/deployable/RefreshParts()
+ . = ..()
+ heat_capacity = 10000
+ min_temperature = T0C
+ max_temperature = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD + 50
+
+/obj/machinery/atmospherics/components/unary/thermomachine/deployable/default_deconstruction_crowbar()
+ return
+
+/obj/machinery/atmospherics/components/unary/thermomachine/deployable/process_atmos()
+ if(on && !soundloop.loop_started)
+ soundloop.start()
+ else if(soundloop.loop_started)
+ soundloop.stop()
+ . = ..()
+
+// Item for creating the regulator and carrying it about
+
+/obj/item/flatpacked_machine/thermomachine
+ name = "flat-packed atmospheric temperature regulator"
+ icon_state = "thermomachine_packed"
+ type_to_deploy = /obj/machinery/atmospherics/components/unary/thermomachine/deployable
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.5,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT,
+ )
+
+// This prevents some weird visual bugs with the inlet
+/obj/item/flatpacked_machine/thermomachine/give_deployable_component()
+ AddComponent(/datum/component/deployable, deploy_time, type_to_deploy, direction_setting = FALSE)
+
+// Greyscale config for the light on this machine
+
+/datum/greyscale_config/thermomachine/deployable
+ name = "Deployable Thermomachine"
+ icon_file = 'modular_doppler/colony_fabricator/icons/thermomachine.dmi'
diff --git a/modular_doppler/colony_fabricator/code/repacking_element.dm b/modular_doppler/colony_fabricator/code/repacking_element.dm
new file mode 100644
index 0000000000000..4d11cece58c6f
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/repacking_element.dm
@@ -0,0 +1,76 @@
+/// An element that allows objects to be right clicked and turned into another item after a delay
+/datum/element/repackable
+ element_flags = ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+
+ /// The path to spawn when the repacking operation is complete
+ var/item_to_pack_into
+ /// How long will repacking the attachee take
+ var/repacking_time
+ /// Do we tell objects destroyed that we disassembled them?
+ var/disassemble_objects
+
+/datum/element/repackable/Attach(datum/target, item_to_pack_into = /obj/item, repacking_time = 1 SECONDS, disassemble_objects = TRUE)
+ . = ..()
+ if(!isatom(target))
+ return ELEMENT_INCOMPATIBLE
+
+ src.item_to_pack_into = item_to_pack_into
+ src.repacking_time = repacking_time
+ src.disassemble_objects = disassemble_objects
+
+ RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(examine))
+ RegisterSignal(target, COMSIG_CLICK_ALT, PROC_REF(on_alt_click))
+ RegisterSignal(target, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item))
+
+/datum/element/repackable/Detach(datum/target)
+ . = ..()
+ UnregisterSignal(target, COMSIG_ATOM_EXAMINE)
+ UnregisterSignal(target, COMSIG_CLICK_ALT)
+ UnregisterSignal(target, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM))
+
+/datum/element/repackable/proc/examine(datum/source, mob/user, list/examine_list)
+ SIGNAL_HANDLER
+
+ examine_list += span_notice("It can be repacked with alt-click.")
+
+/// Checks if the user can actually interact with the structures in question, then invokes the proc to make it repack
+/datum/element/repackable/proc/on_alt_click(atom/source, mob/user)
+ SIGNAL_HANDLER
+
+ var/mob/living/living_user = user
+ if(DOING_INTERACTION_WITH_TARGET(user, source))
+ return
+ if(istype(living_user) && living_user.combat_mode)
+ return
+ if(!living_user.can_perform_action(source, NEED_DEXTERITY))
+ return
+
+ INVOKE_ASYNC(src, PROC_REF(repack), source, user)
+ return CLICK_ACTION_SUCCESS
+
+/// Removes the element target and spawns a new one of whatever item_to_pack_into is
+/datum/element/repackable/proc/repack(atom/source, mob/user)
+ source.balloon_alert_to_viewers("repacking...")
+ if(!do_after(user, 3 SECONDS, target = source))
+ return
+
+ playsound(source, 'sound/items/ratchet.ogg', 50, TRUE)
+
+ new item_to_pack_into(source.drop_location())
+
+ if(istype(source, /obj))
+ var/obj/source_object = source
+ source_object.deconstruct(TRUE)
+ else
+ qdel(source)
+
+/// Adds screen context for hovering over the repackable items with your mouse
+/datum/element/repackable/proc/on_requesting_context_from_item(atom/source, list/context, obj/item/held_item, mob/user)
+ SIGNAL_HANDLER
+
+ if(isnull(held_item))
+ context[SCREENTIP_CONTEXT_RMB] = "Repack"
+ . = CONTEXTUAL_SCREENTIP_SET
+
+ return NONE
diff --git a/modular_doppler/colony_fabricator/code/tools/tools.dm b/modular_doppler/colony_fabricator/code/tools/tools.dm
new file mode 100644
index 0000000000000..419ad19bad4ba
--- /dev/null
+++ b/modular_doppler/colony_fabricator/code/tools/tools.dm
@@ -0,0 +1,219 @@
+// Like the power drill, except no speed buff but has wirecutters as well? Just trust me on this one.
+
+/obj/item/screwdriver/omni_drill
+ name = "powered driver"
+ desc = "The ultimate in multi purpose construction tools. With heads for wire cutting, bolt driving, and driving \
+ screws, what's not to love? Well, the slow speed. Compared to other power drills these tend to be \
+ not much quicker than unpowered tools."
+ icon = 'modular_doppler/colony_fabricator/icons/tools.dmi'
+ icon_state = "drill"
+ belt_icon_state = null
+ inhand_icon_state = "drill"
+ worn_icon_state = "drill"
+ lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.75,
+ /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT * 1.5,
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ force = 10
+ throwforce = 8
+ throw_speed = 2
+ throw_range = 3
+ attack_verb_continuous = list("drills", "screws", "jabs", "whacks")
+ attack_verb_simple = list("drill", "screw", "jab", "whack")
+ hitsound = 'sound/items/drill_hit.ogg'
+ usesound = 'sound/items/drill_use.ogg'
+ w_class = WEIGHT_CLASS_SMALL
+ toolspeed = 1
+ random_color = FALSE
+ greyscale_config = null
+ greyscale_config_belt = null
+ greyscale_config_inhand_left = null
+ greyscale_config_inhand_right = null
+ /// Used on Initialize, how much time to cut cable restraints and zipties.
+ var/snap_time_weak_handcuffs = 0 SECONDS
+ /// Used on Initialize, how much time to cut real handcuffs. Null means it can't.
+ var/snap_time_strong_handcuffs = null
+
+/obj/item/screwdriver/omni_drill/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+/obj/item/screwdriver/omni_drill/get_all_tool_behaviours()
+ return list(TOOL_WIRECUTTER, TOOL_SCREWDRIVER, TOOL_WRENCH)
+
+/obj/item/screwdriver/omni_drill/examine(mob/user)
+ . = ..()
+ . += span_notice("Use in hand to switch configuration.\n")
+ . += span_notice("It functions as a [tool_behaviour] tool.")
+
+/obj/item/screwdriver/omni_drill/update_icon_state()
+ . = ..()
+ switch(tool_behaviour)
+ if(TOOL_SCREWDRIVER)
+ icon_state = initial(icon_state)
+ if(TOOL_WRENCH)
+ icon_state = "[initial(icon_state)]_bolt"
+ if(TOOL_WIRECUTTER)
+ icon_state = "[initial(icon_state)]_cut"
+
+/obj/item/screwdriver/omni_drill/attack_self(mob/user, modifiers)
+ . = ..()
+ if(!user)
+ return
+ var/list/tool_list = list(
+ "Screwdriver" = image(icon = icon, icon_state = "drill"),
+ "Wrench" = image(icon = icon, icon_state = "drill_bolt"),
+ "Wirecutters" = image(icon = icon, icon_state = "drill_cut"),
+ )
+ var/tool_result = show_radial_menu(user, src, tool_list, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE)
+ if(!check_menu(user) || !tool_result)
+ return
+ RemoveElement(/datum/element/cuffsnapping, snap_time_weak_handcuffs, snap_time_strong_handcuffs)
+ switch(tool_result)
+ if("Wrench")
+ tool_behaviour = TOOL_WRENCH
+ sharpness = NONE
+ if("Wirecutters")
+ tool_behaviour = TOOL_WIRECUTTER
+ sharpness = NONE
+ AddElement(/datum/element/cuffsnapping, snap_time_weak_handcuffs, snap_time_strong_handcuffs)
+ if("Screwdriver")
+ tool_behaviour = TOOL_SCREWDRIVER
+ sharpness = SHARP_POINTY
+ playsound(src, 'sound/items/change_drill.ogg', 50, vary = TRUE)
+ update_appearance(UPDATE_ICON)
+
+/obj/item/screwdriver/omni_drill/proc/check_menu(mob/user)
+ if(!istype(user))
+ return FALSE
+ if(user.incapacitated || !user.Adjacent(src))
+ return FALSE
+ return TRUE
+
+// Just a completely normal crowbar except its normal sized and can force doors like jaws of life can
+
+/obj/item/crowbar/large/doorforcer
+ name = "prybar"
+ desc = "A large, sturdy crowbar, painted orange. This one just happens to be tough enough to \
+ survive forcing doors open."
+ icon = 'modular_doppler/colony_fabricator/icons/tools.dmi'
+ icon_state = "prybar"
+ toolspeed = 1.3
+ force_opens = TRUE
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.75,
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+
+/obj/item/crowbar/large/doorforcer/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+// Backpackable mining drill
+
+/obj/item/pickaxe/drill/compact
+ name = "compact mining drill"
+ desc = "A powered mining drill, it drills all over the place. Compact enough to hopefully fit in a backpack."
+ icon = 'modular_doppler/colony_fabricator/icons/tools.dmi'
+ icon_state = "drilla"
+ worn_icon_state = "drill"
+ w_class = WEIGHT_CLASS_NORMAL
+ toolspeed = 0.6
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+
+/obj/item/pickaxe/drill/compact/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+
+// Electric welder but not quite as strong
+
+/obj/item/weldingtool/arc_welder
+ name = "arc welding tool"
+ desc = "A specialized welding tool utilizing high powered arcs of electricity to weld things together. \
+ Compared to other electrically-powered welders, this model is slow and highly power inefficient, \
+ but it still gets the job done and chances are you printed this bad boy off for free."
+ icon = 'modular_doppler/colony_fabricator/icons/tools.dmi'
+ icon_state = "arc_welder"
+ usesound = 'modular_doppler/colony_fabricator/sounds/arc_welder/arc_welder.ogg'
+ light_range = 2
+ light_power = 0.75
+ toolspeed = 1
+ change_icons = FALSE
+ power_use_amount = POWER_CELL_USE_INSANE
+ var/cell_override = /obj/item/stock_parts/power_store/cell/high
+ var/powered = FALSE
+
+/obj/item/weldingtool/arc_welder/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
+ AddComponent(/datum/component/cell, cell_override, CALLBACK(src, PROC_REF(switched_off)))
+
+/obj/item/weldingtool/arc_welder/attack_self(mob/user, modifiers)
+ . = ..()
+ if(!powered)
+ if(!(item_use_power(power_use_amount, user, TRUE) & COMPONENT_POWER_SUCCESS))
+ return
+ powered = !powered
+ playsound(src, 'sound/effects/sparks4.ogg', 100, TRUE)
+ if(powered)
+ to_chat(user, span_notice("You turn [src] on."))
+ switched_on()
+ return
+ to_chat(user, span_notice("You turn [src] off."))
+ switched_off()
+
+/obj/item/weldingtool/arc_welder/switched_on(mob/user)
+ welding = TRUE
+ tool_behaviour = TOOL_WELDER
+ light_on = TRUE
+ force = 15
+ damtype = BURN
+ hitsound = 'sound/items/welder.ogg'
+ set_light_on(powered)
+ update_appearance()
+ START_PROCESSING(SSobj, src)
+
+/obj/item/weldingtool/arc_welder/switched_off(mob/user)
+ powered = FALSE
+ welding = FALSE
+ light_on = FALSE
+ force = initial(force)
+ damtype = BRUTE
+ set_light_on(powered)
+ tool_behaviour = NONE
+ update_appearance()
+ STOP_PROCESSING(SSobj, src)
+
+/obj/item/weldingtool/arc_welder/process(seconds_per_tick)
+ if(!powered)
+ switched_off()
+ return
+ if(!(item_use_power(power_use_amount) & COMPONENT_POWER_SUCCESS))
+ switched_off()
+ return
+
+// We don't need to know how much fuel it has, because it doesn't use any.
+/obj/item/weldingtool/arc_welder/examine(mob/user)
+ . = ..()
+ . -= "It contains [get_fuel()] unit\s of fuel out of [max_fuel]."
+
+// This is what uses fuel in the parent. We override it here to not use fuel
+/obj/item/weldingtool/arc_welder/use(used = 0)
+ return isOn()
+
+/obj/item/weldingtool/arc_welder/examine()
+ . = ..()
+ . += "[src] is currently [powered ? "powered" : "unpowered"]."
+
+/obj/item/weldingtool/arc_welder/update_icon_state()
+ if(powered)
+ inhand_icon_state = "[initial(inhand_icon_state)]1"
+ else
+ inhand_icon_state = "[initial(inhand_icon_state)]"
+ return ..()
diff --git a/modular_doppler/colony_fabricator/icons/cell_charger.dmi b/modular_doppler/colony_fabricator/icons/cell_charger.dmi
new file mode 100644
index 0000000000000..16ec75ba35cd6
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/cell_charger.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/chemistry_machines.dmi b/modular_doppler/colony_fabricator/icons/chemistry_machines.dmi
new file mode 100644
index 0000000000000..96126d26101e8
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/chemistry_machines.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/doors/airlock.dmi b/modular_doppler/colony_fabricator/icons/doors/airlock.dmi
new file mode 100644
index 0000000000000..a5afd63d419d5
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/doors/airlock.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/doors/airlock_manual.dmi b/modular_doppler/colony_fabricator/icons/doors/airlock_manual.dmi
new file mode 100644
index 0000000000000..3ced7b3a16353
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/doors/airlock_manual.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/doors/overlays.dmi b/modular_doppler/colony_fabricator/icons/doors/overlays.dmi
new file mode 100644
index 0000000000000..4a039a486a663
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/doors/overlays.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/doors/packed.dmi b/modular_doppler/colony_fabricator/icons/doors/packed.dmi
new file mode 100644
index 0000000000000..118709bb772b2
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/doors/packed.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/doors/shutter.dmi b/modular_doppler/colony_fabricator/icons/doors/shutter.dmi
new file mode 100644
index 0000000000000..f3ab4f661bdbd
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/doors/shutter.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/foodricator.dmi b/modular_doppler/colony_fabricator/icons/foodricator.dmi
new file mode 100644
index 0000000000000..d54728eb58aa4
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/foodricator.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/kitchen_stuff/griddle.dmi b/modular_doppler/colony_fabricator/icons/kitchen_stuff/griddle.dmi
new file mode 100644
index 0000000000000..46cde00af6740
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/kitchen_stuff/griddle.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/kitchen_stuff/microwave.dmi b/modular_doppler/colony_fabricator/icons/kitchen_stuff/microwave.dmi
new file mode 100644
index 0000000000000..00979f05eb498
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/kitchen_stuff/microwave.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/kitchen_stuff/range.dmi b/modular_doppler/colony_fabricator/icons/kitchen_stuff/range.dmi
new file mode 100644
index 0000000000000..1e6ed4cfa73c4
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/kitchen_stuff/range.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/machines.dmi b/modular_doppler/colony_fabricator/icons/machines.dmi
new file mode 100644
index 0000000000000..389432e376e4b
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/machines.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/ore_silo.dmi b/modular_doppler/colony_fabricator/icons/ore_silo.dmi
new file mode 100644
index 0000000000000..8cbf8158644a3
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/ore_silo.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/packed_machines.dmi b/modular_doppler/colony_fabricator/icons/packed_machines.dmi
new file mode 100644
index 0000000000000..8e7c4dbd73762
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/packed_machines.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/parts_kits.dmi b/modular_doppler/colony_fabricator/icons/parts_kits.dmi
new file mode 100644
index 0000000000000..75a4e97e23f15
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/parts_kits.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/portable_machines.dmi b/modular_doppler/colony_fabricator/icons/portable_machines.dmi
new file mode 100644
index 0000000000000..046d517a0de07
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/portable_machines.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/power_storage_unit/large_battery.dmi b/modular_doppler/colony_fabricator/icons/power_storage_unit/large_battery.dmi
new file mode 100644
index 0000000000000..9e4fd1a29cc90
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/power_storage_unit/large_battery.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/power_storage_unit/small_battery.dmi b/modular_doppler/colony_fabricator/icons/power_storage_unit/small_battery.dmi
new file mode 100644
index 0000000000000..dce9d878154f3
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/power_storage_unit/small_battery.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/prefab_wall.dmi b/modular_doppler/colony_fabricator/icons/prefab_wall.dmi
new file mode 100644
index 0000000000000..e1aec0f273add
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/prefab_wall.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/prefab_window.dmi b/modular_doppler/colony_fabricator/icons/prefab_window.dmi
new file mode 100644
index 0000000000000..7845026875dee
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/prefab_window.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/space_heater.dmi b/modular_doppler/colony_fabricator/icons/space_heater.dmi
new file mode 100644
index 0000000000000..eda06ce46e4ca
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/space_heater.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/stirling_generator/big_generator.dmi b/modular_doppler/colony_fabricator/icons/stirling_generator/big_generator.dmi
new file mode 100644
index 0000000000000..d8cac6292e236
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/stirling_generator/big_generator.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/stirling_generator/packed_machines.dmi b/modular_doppler/colony_fabricator/icons/stirling_generator/packed_machines.dmi
new file mode 100644
index 0000000000000..5b750da515124
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/stirling_generator/packed_machines.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/thermomachine.dmi b/modular_doppler/colony_fabricator/icons/thermomachine.dmi
new file mode 100644
index 0000000000000..305c4c43edb66
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/thermomachine.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/tiles.dmi b/modular_doppler/colony_fabricator/icons/tiles.dmi
new file mode 100644
index 0000000000000..068107aa0fdc9
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/tiles.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/tiles_item.dmi b/modular_doppler/colony_fabricator/icons/tiles_item.dmi
new file mode 100644
index 0000000000000..0e76bd25d2c86
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/tiles_item.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/tools.dmi b/modular_doppler/colony_fabricator/icons/tools.dmi
new file mode 100644
index 0000000000000..a251c66d1efdf
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/tools.dmi differ
diff --git a/modular_doppler/colony_fabricator/icons/wind_turbine.dmi b/modular_doppler/colony_fabricator/icons/wind_turbine.dmi
new file mode 100644
index 0000000000000..26a37260b73d9
Binary files /dev/null and b/modular_doppler/colony_fabricator/icons/wind_turbine.dmi differ
diff --git a/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_1.wav b/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_1.wav
new file mode 100644
index 0000000000000..b26fa32ed9da3
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_1.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_2.wav b/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_2.wav
new file mode 100644
index 0000000000000..8b30d09b81e67
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_2.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_3.wav b/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_3.wav
new file mode 100644
index 0000000000000..71621213d795f
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_3.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_4.wav b/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_4.wav
new file mode 100644
index 0000000000000..95f9dc385e536
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/arc_furnace/arc_furnace_mid_4.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/arc_welder/arc_welder.ogg b/modular_doppler/colony_fabricator/sounds/arc_welder/arc_welder.ogg
new file mode 100644
index 0000000000000..8c76738f0f473
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/arc_welder/arc_welder.ogg differ
diff --git a/modular_doppler/colony_fabricator/sounds/attributions.txt b/modular_doppler/colony_fabricator/sounds/attributions.txt
new file mode 100644
index 0000000000000..565a818121207
--- /dev/null
+++ b/modular_doppler/colony_fabricator/sounds/attributions.txt
@@ -0,0 +1,18 @@
+The following sounds have been recorded, edited and added by
+a contributor who no longer wishes to be named
+specifically for free open source use from the novasector codebase, so don't worry about it.
+
+modular_doppler/colony_fabricator/sound/arc_furnace/arc_furnace_mid_(1 - 4).wav
+modular_doppler/colony_fabricator/sound/fabricator/fabricator_mid_(1 - 4).wav
+modular_doppler/colony_fabricator/sound/fabricator/fabricator_end.wav
+modular_doppler/colony_fabricator/sound/fabricator/fabricator_start.wav
+
+The following sounds are from https://pixabay.com/sound-effects/wall-air-conditioner-43901/
+
+modular_doppler/colony_fabricator/sound/conditioner/conditioner_(1 - 4).wav
+
+The following sounds are from https://pixabay.com/sound-effects/welder-3-54547/
+
+modular_doppler/colony_fabricator/sound/arc_welder/arc_welder.ogg
+
+The sounds at modular_doppler/colony_fabriactor_event_code/sound/manual_door are from https://pixabay.com/sound-effects/schlonk-107321/
diff --git a/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_1.wav b/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_1.wav
new file mode 100644
index 0000000000000..e014af99119f6
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_1.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_2.wav b/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_2.wav
new file mode 100644
index 0000000000000..a99f8a939ada4
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_2.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_3.wav b/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_3.wav
new file mode 100644
index 0000000000000..1f798b05a2da0
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_3.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_4.wav b/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_4.wav
new file mode 100644
index 0000000000000..88f57ec4f00fe
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/conditioner/conditioner_4.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_end.wav b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_end.wav
new file mode 100644
index 0000000000000..90e16a116fb7d
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_end.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_1.wav b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_1.wav
new file mode 100644
index 0000000000000..5a70874cda7a4
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_1.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_2.wav b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_2.wav
new file mode 100644
index 0000000000000..a8ea099036c83
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_2.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_3.wav b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_3.wav
new file mode 100644
index 0000000000000..b5d0a0117c5cb
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_3.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_4.wav b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_4.wav
new file mode 100644
index 0000000000000..1700b0fc379bb
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_mid_4.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_start.wav b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_start.wav
new file mode 100644
index 0000000000000..673a9da8b41c3
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/fabricator/fabricator_start.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/manual_door/manual_door_close.wav b/modular_doppler/colony_fabricator/sounds/manual_door/manual_door_close.wav
new file mode 100644
index 0000000000000..a2f6ad300b0cc
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/manual_door/manual_door_close.wav differ
diff --git a/modular_doppler/colony_fabricator/sounds/manual_door/manual_door_open.wav b/modular_doppler/colony_fabricator/sounds/manual_door/manual_door_open.wav
new file mode 100644
index 0000000000000..431b3eb6ea01e
Binary files /dev/null and b/modular_doppler/colony_fabricator/sounds/manual_door/manual_door_open.wav differ
diff --git a/modular_doppler/deforest_medical_items/code/chemicals/demoneye.dm b/modular_doppler/deforest_medical_items/code/chemicals/demoneye.dm
new file mode 100644
index 0000000000000..0c8a2e345f939
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/chemicals/demoneye.dm
@@ -0,0 +1,157 @@
+#define CONSTANT_DOSE_SAFE_LIMIT 60
+#define METABOLISM_END_LIMB_DAMAGE 20
+
+// Chemical reaction, turns 25 input reagents into 25 output reagents, 10 of those being demoneye
+/datum/chemical_reaction/demoneye
+ results = list(
+ /datum/reagent/drug/demoneye = 10,
+ /datum/reagent/impurity/healing/medicine_failure = 10,
+ /datum/reagent/impurity = 5,
+ )
+ required_reagents = list(
+ /datum/reagent/medicine/ephedrine = 5,
+ /datum/reagent/blood = 15,
+ /datum/reagent/stable_plasma = 5,
+ )
+ mob_react = FALSE
+ reaction_tags = REACTION_TAG_EASY | REACTION_TAG_DRUG | REACTION_TAG_ORGAN | REACTION_TAG_DAMAGING
+
+// Demoneye, a drug that makes you temporarily immune to fear and crit, in exchange for damaging all of your organs and making your veins explode
+/datum/reagent/drug/demoneye
+ name = "DemonEye"
+ description = "A performance enhancing drug originally developed on mars. \
+ A favorite among gangs and other outlaws on the planet, though overuse can cause terrible addiction and bodily damage."
+ reagent_state = LIQUID
+ color = "#af00be"
+ taste_description = "industrial shuttle fuel"
+ metabolization_rate = 0.65 * REAGENTS_METABOLISM
+ ph = 7
+ overdose_threshold = 15
+ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ addiction_types = list(/datum/addiction/stimulants = 15)
+ metabolized_traits = list(TRAIT_UNNATURAL_RED_GLOWY_EYES, TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_FEARLESS, TRAIT_ANALGESIA)
+ /// How much time has the drug been in them?
+ var/constant_dose_time = 0
+ /// What the original color of the user's left eye is
+ var/user_left_eye_color
+ /// What the original color of the user's right eye is
+ var/user_right_eye_color
+
+/datum/reagent/drug/demoneye/on_mob_metabolize(mob/living/carbon/human/our_guy)
+ . = ..()
+
+ user_left_eye_color = our_guy.eye_color_left
+ user_right_eye_color = our_guy.eye_color_right
+
+ our_guy.eye_color_left = BLOODCULT_EYE
+ our_guy.eye_color_right = BLOODCULT_EYE
+ our_guy.update_body()
+
+ our_guy.sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC
+
+ if(!our_guy.hud_used)
+ return
+
+ var/atom/movable/plane_master_controller/game_plane_master_controller = our_guy.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+
+ var/static/list/col_filter_red = list(0.7,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1)
+
+ game_plane_master_controller.add_filter("demoneye_filter", 10, color_matrix_filter(col_filter_red, FILTER_COLOR_RGB))
+
+ game_plane_master_controller.add_filter("demoneye_blur", 1, list("type" = "angular_blur", "size" = 4))
+
+
+/datum/reagent/drug/demoneye/on_mob_end_metabolize(mob/living/carbon/human/our_guy)
+ . = ..()
+
+ our_guy.eye_color_left = user_left_eye_color
+ our_guy.eye_color_right = user_right_eye_color
+ our_guy.update_body()
+
+ our_guy.sound_environment_override = NONE
+
+ if(constant_dose_time < CONSTANT_DOSE_SAFE_LIMIT || !our_guy.blood_volume)
+ our_guy.visible_message(
+ span_danger("[our_guy]'s eyes fade from their evil looking red back to normal..."),
+ span_danger("Your vision slowly returns to normal as you lose your unnatural strength...")
+ )
+ else
+ our_guy.visible_message(
+ span_danger("[our_guy]'s veins violently explode, spraying blood everywhere!"),
+ span_danger("Your veins burst from the sheer stress put on them!")
+ )
+
+ var/obj/item/bodypart/bodypart = pick(our_guy.bodyparts)
+ var/datum/wound/slash/flesh/critical/crit_wound = new()
+ crit_wound.apply_wound(bodypart)
+ bodypart.receive_damage(brute = METABOLISM_END_LIMB_DAMAGE, wound_bonus = CANT_WOUND)
+
+ new /obj/effect/temp_visual/cleave(our_guy.drop_location())
+
+ if(overdosed && !our_guy.has_status_effect(/datum/status_effect/vulnerable_to_damage))
+ our_guy.apply_status_effect(/datum/status_effect/vulnerable_to_damage)
+
+ if(!our_guy.hud_used)
+ return
+
+ var/atom/movable/plane_master_controller/game_plane_master_controller = our_guy.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+
+ game_plane_master_controller.remove_filter("demoneye_filter")
+ game_plane_master_controller.remove_filter("demoneye_blur")
+
+
+/datum/reagent/drug/demoneye/on_mob_life(mob/living/carbon/our_guy, seconds_per_tick, times_fired)
+ . = ..()
+
+ constant_dose_time += seconds_per_tick
+
+ our_guy.add_mood_event("tweaking", /datum/mood_event/stimulant_heavy/sundowner, name)
+
+ our_guy.adjustStaminaLoss(-10 * REM * seconds_per_tick)
+ our_guy.AdjustSleeping(-20 * REM * seconds_per_tick)
+ our_guy.adjust_drowsiness(-5 * REM * seconds_per_tick)
+
+ if(SPT_PROB(25, seconds_per_tick))
+ our_guy.playsound_local(our_guy, 'sound/effects/singlebeat.ogg', 100, TRUE)
+ flash_color(our_guy, flash_color = "#ff0000", flash_time = 3 SECONDS)
+
+ if(SPT_PROB(5, seconds_per_tick))
+ hurt_that_mans_organs(our_guy, 3, FALSE)
+
+ if(locate(/datum/reagent/drug/twitch) in our_guy.reagents.reagent_list) // Combining this with twitch could cause some heart attack problems
+ our_guy.ForceContractDisease(new /datum/disease/heart_failure(), FALSE, TRUE)
+
+
+/datum/reagent/drug/demoneye/overdose_process(mob/living/carbon/our_guy, seconds_per_tick, times_fired)
+ . = ..()
+
+ our_guy.set_jitter_if_lower(10 SECONDS * REM * seconds_per_tick)
+
+ if(SPT_PROB(10, seconds_per_tick))
+ hurt_that_mans_organs(our_guy, 5, TRUE)
+
+
+/// Hurts a random organ, if it's 'really_bad' we'll vomit blood too
+/datum/reagent/drug/demoneye/proc/hurt_that_mans_organs(mob/living/carbon/our_guy, damage, really_bad = FALSE)
+ /// List of organs we can randomly damage
+ var/static/list/organs_we_damage = list(
+ ORGAN_SLOT_BRAIN,
+ ORGAN_SLOT_APPENDIX,
+ ORGAN_SLOT_LUNGS,
+ ORGAN_SLOT_HEART,
+ ORGAN_SLOT_LIVER,
+ ORGAN_SLOT_STOMACH,
+ )
+ if(really_bad)
+ our_guy.vomit(0, TRUE, FALSE, 1)
+ our_guy.adjustOrganLoss(
+ pick(organs_we_damage),
+ damage,
+ )
+
+// Mood event used by demoneye, because the normal one I just didn't vibe with
+/datum/mood_event/stimulant_heavy/sundowner
+ description = "I'M FUCKING INVINCIBLE!!!!"
+
+#undef CONSTANT_DOSE_SAFE_LIMIT
+#undef METABOLISM_END_LIMB_DAMAGE
diff --git a/modular_doppler/deforest_medical_items/code/chemicals/twitch.dm b/modular_doppler/deforest_medical_items/code/chemicals/twitch.dm
new file mode 100644
index 0000000000000..ba489b8834e4e
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/chemicals/twitch.dm
@@ -0,0 +1,252 @@
+#define CONSTANT_DOSE_SAFE_LIMIT 60
+
+#define TWITCH_SCREEN_FILTER "twitch_screen_filter"
+#define TWITCH_SCREEN_BLUR "twitch_screen_blur"
+
+#define TWITCH_BLUR_EFFECT "twitch_dodge_blur"
+#define TWITCH_OVERDOSE_BLUR_EFFECT "twitch_overdose_blur"
+
+// Reaction to make twitch, makes 10u from 17u input reagents
+/datum/chemical_reaction/twitch
+ results = list(
+ /datum/reagent/drug/twitch = 10,
+ )
+ required_reagents = list(
+ /datum/reagent/impedrezene = 5,
+ /datum/reagent/bluespace = 10,
+ /datum/reagent/consumable/liquidelectricity/enriched = 2,
+ )
+ mob_react = FALSE
+ reaction_tags = REACTION_TAG_EASY | REACTION_TAG_DRUG | REACTION_TAG_ORGAN | REACTION_TAG_DAMAGING
+
+// Twitch drug, makes the takers of it faster and able to dodge bullets while in their system, to potentially bad side effects
+/datum/reagent/drug/twitch
+ name = "TWitch"
+ description = "A drug originally developed by and for plutonians to assist them during raids. \
+ Does not see wide use due to the whole reality-disassociation and heart disease thing afterwards. \
+ Can be intentionally overdosed to increase the drug's effects"
+ reagent_state = LIQUID
+ color = "#c22a44"
+ taste_description = "television static"
+ metabolization_rate = 0.65 * REAGENTS_METABOLISM
+ ph = 3
+ overdose_threshold = 15
+ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ addiction_types = list(/datum/addiction/stimulants = 20)
+ process_flags = REAGENT_ORGANIC | REAGENT_SYNTHETIC
+ /// How much time has the drug been in them?
+ var/constant_dose_time = 0
+ /// What type of span class do we change heard speech to?
+ var/speech_effect_span
+ /// How much the mob heating is multiplied by, if the target is a robot or has muscled veins
+ var/mob_heating_muliplier = 5
+
+
+/datum/reagent/drug/twitch/on_mob_metabolize(mob/living/our_guy)
+ . = ..()
+
+ our_guy.add_movespeed_modifier(/datum/movespeed_modifier/reagent/twitch)
+ our_guy.next_move_modifier -= 0.3 // For the duration of this you move and attack faster
+
+ our_guy.sound_environment_override = SOUND_ENVIRONMENT_DIZZY
+
+ speech_effect_span = "green"
+
+ RegisterSignal(our_guy, COMSIG_MOVABLE_MOVED, PROC_REF(on_movement))
+ RegisterSignal(our_guy, COMSIG_MOVABLE_HEAR, PROC_REF(distort_hearing))
+
+ if(!our_guy.hud_used)
+ return
+
+ var/atom/movable/plane_master_controller/game_plane_master_controller = our_guy.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+
+ var/static/list/col_filter_green = list(0.5,0,0,0, 0,1,0,0, 0,0,0.5,0, 0,0,0,1)
+ var/static/list/col_filter_purple = list(1,0,0,0, 0,0.5,0,0, 0,0,1,0, 0,0,0,1)
+
+ var/color_filter_to_use = col_filter_green
+ if(overdosed)
+ color_filter_to_use = col_filter_purple
+
+ game_plane_master_controller.add_filter(TWITCH_SCREEN_FILTER, 10, color_matrix_filter(color_filter_to_use, FILTER_COLOR_RGB))
+
+ game_plane_master_controller.add_filter(TWITCH_SCREEN_BLUR, 1, list("type" = "radial_blur", "size" = 0.02))
+
+
+/datum/reagent/drug/twitch/on_mob_end_metabolize(mob/living/carbon/our_guy)
+ . = ..()
+
+ our_guy.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/twitch)
+ our_guy.next_move_modifier += (overdosed ? 0.5 : 0.3)
+
+ our_guy.sound_environment_override = NONE
+
+ speech_effect_span = "hierophant"
+
+ UnregisterSignal(our_guy, COMSIG_MOVABLE_MOVED)
+ UnregisterSignal(our_guy, COMSIG_MOVABLE_HEAR)
+ if(overdosed)
+ UnregisterSignal(our_guy, COMSIG_ATOM_PRE_BULLET_ACT)
+
+ if(constant_dose_time < CONSTANT_DOSE_SAFE_LIMIT) // Anything less than this and you'll come out fiiiine, aside from a big hit of stamina damage
+ if(!(our_guy.mob_biotypes & MOB_ROBOTIC))
+ our_guy.visible_message(
+ span_danger("[our_guy] suddenly slows from [our_guy.p_their()] inhuman speeds, coming back with a wicked nosebleed!"),
+ span_danger("You suddenly slow back to normal, a stream of blood gushing from your nose!")
+ )
+ else
+ our_guy.visible_message(
+ span_danger("[our_guy] suddenly slows from [our_guy.p_their()] inhuman speeds!"),
+ span_danger("You suddenly slow back to normal speed!")
+ )
+ our_guy.adjustStaminaLoss(constant_dose_time)
+
+ else // Much longer than that however, and you're not gonna have a good day
+ if(!(our_guy.mob_biotypes & MOB_ROBOTIC))
+ our_guy.spray_blood(our_guy.dir, 2) // The before mentioned coughing up blood
+ our_guy.emote("cough")
+ our_guy.visible_message(
+ span_danger("[our_guy] suddenly snaps back from [our_guy.p_their()] inhuman speeds, coughing up a spray of blood!"),
+ span_danger("As you snap back to normal speed you cough up a worrying amount of blood. You feel like you've just been run over by a power loader.")
+ )
+ else
+ our_guy.visible_message(
+ span_danger("[our_guy] suddenly snaps back from [our_guy.p_their()] inhuman speeds!"),
+ span_danger("You suddenly snap back to normal speeds. You feel like you've just been run over by a power loader.")
+ )
+ our_guy.adjustStaminaLoss(constant_dose_time)
+ if(!HAS_TRAIT(our_guy, TRAIT_TWITCH_ADAPTED))
+ our_guy.adjustOrganLoss(ORGAN_SLOT_HEART, 0.3 * constant_dose_time) // Basically you might die
+
+ if(!our_guy.hud_used)
+ return
+
+ var/atom/movable/plane_master_controller/game_plane_master_controller = our_guy.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+
+ game_plane_master_controller.remove_filter(TWITCH_SCREEN_FILTER)
+ game_plane_master_controller.remove_filter(TWITCH_SCREEN_BLUR)
+
+
+/// Leaves an afterimage behind the mob when they move
+/datum/reagent/drug/twitch/proc/on_movement(mob/living/carbon/our_guy, atom/old_loc)
+ SIGNAL_HANDLER
+ new /obj/effect/temp_visual/decoy/twitch_afterimage(old_loc, our_guy)
+
+
+/// Tries to dodge incoming bullets if we aren't disabled for any reasons
+/datum/reagent/drug/twitch/proc/dodge_bullets(mob/living/carbon/human/source, obj/projectile/hitting_projectile, def_zone)
+ SIGNAL_HANDLER
+
+ if(HAS_TRAIT(source, TRAIT_INCAPACITATED))
+ return NONE
+ source.visible_message(
+ span_danger("[source] effortlessly dodges [hitting_projectile]!"),
+ span_userdanger("You effortlessly evade [hitting_projectile]!"),
+ )
+ playsound(source, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE)
+ source.add_filter(TWITCH_BLUR_EFFECT, 2, gauss_blur_filter(5))
+ addtimer(CALLBACK(source, TYPE_PROC_REF(/datum, remove_filter), TWITCH_BLUR_EFFECT), 0.5 SECONDS)
+ return COMPONENT_BULLET_PIERCED
+
+
+/datum/reagent/drug/twitch/on_mob_life(mob/living/carbon/our_guy, seconds_per_tick, times_fired)
+ . = ..()
+
+ constant_dose_time += seconds_per_tick
+
+ // If the target is a robot, or has muscle veins, then they get an effect similar to herignis, heating them up quite a bit
+ if((our_guy.mob_biotypes & MOB_ROBOTIC) || HAS_TRAIT(our_guy, TRAIT_STABLEHEART))
+ var/heating = mob_heating_muliplier * creation_purity * REM * seconds_per_tick
+ our_guy.reagents?.chem_temp += heating
+ our_guy.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT)
+ if(!ishuman(our_guy))
+ return
+ var/mob/living/carbon/human/human = our_guy
+ human.adjust_coretemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT)
+ else
+ our_guy.adjustOrganLoss(ORGAN_SLOT_HEART, 0.1 * REM * seconds_per_tick)
+
+ if(locate(/datum/reagent/drug/kronkaine) in our_guy.reagents.reagent_list) // Kronkaine, another heart-straining drug, could cause problems if mixed with this
+ our_guy.ForceContractDisease(new /datum/disease/adrenal_crisis(), FALSE, TRUE)
+
+
+/datum/reagent/drug/twitch/overdose_start(mob/living/our_guy)
+ . = ..()
+
+ RegisterSignal(our_guy, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(dodge_bullets))
+
+ our_guy.next_move_modifier -= 0.2 // Overdosing makes you a liiitle faster but you know has some really bad consequences
+
+ if(!our_guy.hud_used)
+ return
+
+ var/atom/movable/plane_master_controller/game_plane_master_controller = our_guy.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+
+ var/list/col_filter_ourple = list(1,0,0,0, 0,0.5,0,0, 0,0,1,0, 0,0,0,1)
+
+ for(var/filter in game_plane_master_controller.get_filters(TWITCH_SCREEN_FILTER))
+ animate(filter, loop = -1, color = col_filter_ourple, time = 4 SECONDS, easing = BOUNCE_EASING)
+
+
+/datum/reagent/drug/twitch/overdose_process(mob/living/carbon/our_guy, seconds_per_tick, times_fired)
+ . = ..()
+ our_guy.set_jitter_if_lower(10 SECONDS * REM * seconds_per_tick)
+
+ // If the target is a robot, or has muscle veins, then they get an effect similar to herignis, heating them up quite a bit
+ if((our_guy.mob_biotypes & MOB_ROBOTIC) || HAS_TRAIT(our_guy, TRAIT_STABLEHEART))
+ var/heating = (mob_heating_muliplier * 2) * creation_purity * REM * seconds_per_tick
+ our_guy.reagents?.chem_temp += heating
+ our_guy.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT)
+ if(!ishuman(our_guy))
+ return
+ var/mob/living/carbon/human/human = our_guy
+ human.adjust_coretemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT)
+ else
+ our_guy.adjustOrganLoss(ORGAN_SLOT_HEART, 1 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags)
+ our_guy.adjustToxLoss(1 * REM * seconds_per_tick, updating_health = FALSE, forced = TRUE, required_biotype = affected_biotype)
+
+ if(SPT_PROB(5, seconds_per_tick) && !(our_guy.mob_biotypes & MOB_ROBOTIC))
+ to_chat(our_guy, span_danger("You cough up a splatter of blood!"))
+ our_guy.spray_blood(our_guy.dir, 1)
+ our_guy.emote("cough")
+
+ if(SPT_PROB(10, seconds_per_tick))
+ our_guy.add_filter(TWITCH_OVERDOSE_BLUR_EFFECT, 2, phase_filter(8))
+ addtimer(CALLBACK(our_guy, TYPE_PROC_REF(/datum, remove_filter), TWITCH_OVERDOSE_BLUR_EFFECT), 0.5 SECONDS)
+
+/// Changes heard message spans into that defined on the drug earlier
+/datum/reagent/drug/twitch/proc/distort_hearing(datum/source, list/hearing_args)
+ SIGNAL_HANDLER
+ hearing_args[HEARING_RAW_MESSAGE] = "[hearing_args[HEARING_RAW_MESSAGE]]"
+
+
+/// Cool filter that I'm using for some of this :)))
+/proc/phase_filter(size)
+ . = list("type" = "wave")
+ .["x"] = 1
+ if(!isnull(size))
+ .["size"] = size
+
+
+// Temp visual that changes color for that bootleg sandevistan effect
+/obj/effect/temp_visual/decoy/twitch_afterimage
+ duration = 0.75 SECONDS
+ /// The color matrix it should be at spawn
+ var/list/matrix_start = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0.1,0.4,0)
+ /// The color matrix it should be by the time it despawns
+ var/list/matrix_end = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0.5,0,0)
+
+/obj/effect/temp_visual/decoy/twitch_afterimage/Initialize(mapload)
+ . = ..()
+ color = matrix_start
+ animate(src, color = matrix_end, time = duration, easing = EASE_OUT)
+ animate(src, alpha = 0, time = duration, easing = EASE_OUT)
+
+// Movespeed modifier used by twitch when someone has it in their system
+/datum/movespeed_modifier/reagent/twitch
+ multiplicative_slowdown = -0.4
+
+#undef TWITCH_SCREEN_FILTER
+#undef TWITCH_SCREEN_BLUR
+
+#undef TWITCH_BLUR_EFFECT
+#undef TWITCH_OVERDOSE_BLUR_EFFECT
diff --git a/modular_doppler/deforest_medical_items/code/healing_stack_items.dm b/modular_doppler/deforest_medical_items/code/healing_stack_items.dm
new file mode 100644
index 0000000000000..d7f79749f1d4b
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/healing_stack_items.dm
@@ -0,0 +1,184 @@
+#define INSTANT_WOUND_HEAL_STAMINA_DAMAGE 80
+#define INSTANT_WOUND_HEAL_LIMB_DAMAGE 25
+
+/obj/item/stack/medical/wound_recovery
+ name = "subdermal splint applicator"
+ desc = "A roll flexible material dotted with millions of micro-scale injectors on one side. \
+ On application to a body part with a damaged bone structure, nanomachines stored within those \
+ injectors will surround the wound and form a subdermal, self healing splint. While convenient \
+ for keeping appearances and rapid healing, the nanomachines tend to leave their host particularly \
+ vulnerable to new damage for several minutes after application."
+ icon = 'modular_doppler/deforest_medical_items/icons/stack_items.dmi'
+ icon_state = "subsplint"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ inhand_icon_state = "sampler"
+ gender = PLURAL
+ singular_name = "subdermal splint applicator"
+ self_delay = 10 SECONDS
+ other_delay = 5 SECONDS
+ novariants = TRUE
+ max_amount = 3
+ amount = 3
+ merge_type = /obj/item/stack/medical/wound_recovery
+ custom_price = PAYCHECK_COMMAND * 2.5
+ /// If this checks for pain, used for synthetic repair foam
+ var/causes_pain = TRUE
+ /// The types of wounds that we work on, in list format
+ var/list/applicable_wounds = list(
+ /datum/wound/blunt/bone,
+ /datum/wound/muscle,
+ )
+ /// The sound we play upon successfully treating the wound
+ var/treatment_sound = 'sound/items/duct_tape_rip.ogg'
+
+// This is only relevant for the types of wounds defined, we can't work if there are none
+/obj/item/stack/medical/wound_recovery/try_heal(mob/living/patient, mob/user, silent, looping)
+
+ if(patient.has_status_effect(/datum/status_effect/vulnerable_to_damage))
+ patient.balloon_alert(user, "still recovering from last use!")
+ return
+
+ var/treatment_delay = (user == patient ? self_delay : other_delay)
+
+ var/obj/item/bodypart/limb = patient.get_bodypart(check_zone(user.zone_selected))
+ if(!limb)
+ patient.balloon_alert(user, "missing limb!")
+ return
+ if(!LAZYLEN(limb.wounds))
+ patient.balloon_alert(user, "no wounds!")
+ return
+
+ var/splintable_wound = FALSE
+ var/datum/wound/woundies
+ for(var/found_wound in limb.wounds)
+ woundies = found_wound
+ if((woundies.wound_flags & ACCEPTS_GAUZE) && is_type_in_list(woundies, applicable_wounds))
+ splintable_wound = TRUE
+ break
+ if(!splintable_wound)
+ patient.balloon_alert(user, "can't heal those!")
+ return
+
+ if(HAS_TRAIT(woundies, TRAIT_WOUND_SCANNED))
+ treatment_delay *= 0.5
+ if(user == patient)
+ to_chat(user, span_notice("You keep in mind the indications from the holo-image about your injury, and expertly begin applying [src]."))
+ else
+ user.visible_message(span_warning("[user] begins expertly treating the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin quickly treating the wounds on [patient]'s [limb.plaintext_zone] with [src], keeping the holo-image indications in mind..."))
+ else
+ user.visible_message(span_warning("[user] begins treating the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin treating the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]..."))
+
+ if(!do_after(user, treatment_delay, target = patient))
+ return
+
+ user.visible_message(span_green("[user] applies [src] to [patient]'s [limb.plaintext_zone]."), span_green("You treat the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone]."))
+ playsound(patient, treatment_sound, 50, TRUE)
+ woundies.remove_wound()
+ if(!HAS_TRAIT(patient, TRAIT_ANALGESIA) || !causes_pain)
+ patient.emote("scream")
+ to_chat(patient, span_userdanger("Your [limb.plaintext_zone] burns like hell as the wounds on it are rapidly healed, fuck!"))
+ patient.add_mood_event("severe_surgery", /datum/mood_event/rapid_wound_healing)
+ limb.receive_damage(brute = INSTANT_WOUND_HEAL_LIMB_DAMAGE, wound_bonus = CANT_WOUND)
+ patient.adjustStaminaLoss(INSTANT_WOUND_HEAL_STAMINA_DAMAGE)
+ patient.apply_status_effect(/datum/status_effect/vulnerable_to_damage)
+ use(1)
+
+/datum/mood_event/rapid_wound_healing
+ description = "The wound is gone, but that pain was unbearable!\n"
+ mood_change = -3
+ timeout = 5 MINUTES
+
+// Helps recover bleeding
+/obj/item/stack/medical/wound_recovery/rapid_coagulant
+ name = "rapid coagulant applicator"
+ singular_name = "rapid coagulant applicator"
+ desc = "A small device filled with a fast acting coagulant of some type. \
+ When used on a bleeding area, will nearly instantly stop all bleeding. \
+ This rapid clotting action may result in temporary vulnerability to further \
+ damage after application."
+ icon_state = "clotter"
+ inhand_icon_state = "implantcase"
+ applicable_wounds = list(
+ /datum/wound/slash/flesh,
+ /datum/wound/pierce/bleed,
+ )
+ merge_type = /obj/item/stack/medical/wound_recovery/rapid_coagulant
+
+/obj/item/stack/medical/wound_recovery/rapid_coagulant/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user)
+ . = ..()
+ healed_mob.reagents.add_reagent(/datum/reagent/medicine/coagulant/fabricated, 5)
+
+// Helps recover burn wounds much faster, while not healing much damage directly
+/obj/item/stack/medical/ointment/red_sun
+ name = "red sun balm"
+ singular_name = "red sun balm"
+ desc = "A popular brand of ointment for handling anything under the red sun, which tends to be terrible burns. \
+ Which red sun may this be referencing? Not even the producers of the balm are sure."
+ icon = 'modular_doppler/deforest_medical_items/icons/stack_items.dmi'
+ icon_state = "balm"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ inhand_icon_state = "bandage"
+ gender = PLURAL
+ novariants = TRUE
+ amount = 12
+ max_amount = 12
+ self_delay = 4 SECONDS
+ other_delay = 2 SECONDS
+ heal_burn = 5
+ heal_brute = 5
+ flesh_regeneration = 5
+ sanitization = 3
+ grind_results = list(/datum/reagent/medicine/oxandrolone = 3)
+ merge_type = /obj/item/stack/medical/ointment/red_sun
+ custom_price = PAYCHECK_LOWER * 1.5
+
+/obj/item/stack/medical/ointment/red_sun/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user)
+ . = ..()
+ healed_mob.reagents.add_reagent(/datum/reagent/medicine/lidocaine, 2)
+
+// Gauze that are especially good at treating burns, but are terrible splints
+/obj/item/stack/medical/gauze/sterilized
+ name = "sealed aseptic gauze"
+ singular_name = "sealed aseptic gauze"
+ desc = "A small roll of elastic material specially treated to be entirely sterile, and sealed in plastic just to be sure. \
+ These make excellent treatment against burn wounds, but due to their small nature are sub-par for serving as \
+ bone wound wrapping."
+ icon = 'modular_doppler/deforest_medical_items/icons/stack_items.dmi'
+ icon_state = "burndaid"
+ inhand_icon_state = null
+ novariants = TRUE
+ max_amount = 6
+ amount = 6
+ splint_factor = 1.2
+ burn_cleanliness_bonus = 0.1
+ merge_type = /obj/item/stack/medical/gauze/sterilized
+ custom_price = PAYCHECK_LOWER * 1.5
+
+/obj/item/stack/medical/gauze/sterilized/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user)
+ . = ..()
+ healed_mob.reagents.add_reagent(/datum/reagent/space_cleaner/sterilizine, 5)
+ healed_mob.reagents.expose(healed_mob, TOUCH, 1)
+
+// Works great at sealing bleed wounds, but does little to actually heal them
+/obj/item/stack/medical/suture/coagulant
+ name = "coagulant-F packet"
+ singular_name = "coagulant-F packet"
+ desc = "A small packet of fabricated coagulant for bleeding. Not as effective as some \
+ other methods of coagulating wounds, but is more effective than plain sutures. \
+ The downsides? It repairs less of the actual damage that's there."
+ icon = 'modular_doppler/deforest_medical_items/icons/stack_items.dmi'
+ icon_state = "clotter_slow"
+ inhand_icon_state = null
+ novariants = TRUE
+ amount = 12
+ max_amount = 12
+ repeating = FALSE
+ heal_brute = 0
+ stop_bleeding = 2
+ merge_type = /obj/item/stack/medical/suture/coagulant
+ custom_price = PAYCHECK_LOWER * 1.5
+
+#undef INSTANT_WOUND_HEAL_STAMINA_DAMAGE
+#undef INSTANT_WOUND_HEAL_LIMB_DAMAGE
diff --git a/modular_doppler/deforest_medical_items/code/illegal_injectors.dm b/modular_doppler/deforest_medical_items/code/illegal_injectors.dm
new file mode 100644
index 0000000000000..7c3059f5d976e
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/illegal_injectors.dm
@@ -0,0 +1,75 @@
+// Twitch, because having sandevistans be implants is for losers, just inject it!
+/obj/item/reagent_containers/hypospray/medipen/deforest/twitch
+ name = "TWitch sensory stimulant injector"
+ desc = "A Deforest branded autoinjector, loaded with 'TWitch' among other reagents. This drug is known to make \
+ those who take it 'see faster', whatever that means."
+ base_icon_state = "twitch"
+ icon_state = "twitch"
+ list_reagents = list(
+ /datum/reagent/drug/twitch = 10,
+ /datum/reagent/drug/maint/tar = 5,
+ /datum/reagent/medicine/silibinin = 5,
+ /datum/reagent/toxin/leadacetate = 5,
+ )
+ custom_price = PAYCHECK_COMMAND * 3.5
+
+// Demoneye, for when you feel the need to become "fucking invincible"
+/obj/item/reagent_containers/hypospray/medipen/deforest/demoneye
+ name = "DemonEye steroid injector"
+ desc = "A Deforest branded autoinjector, loaded with 'DemonEye' among other reagents. This drug is known to make \
+ those who take it numb to all pains and extremely difficult to kill as a result."
+ base_icon_state = "demoneye"
+ icon_state = "demoneye"
+ list_reagents = list(
+ /datum/reagent/drug/demoneye = 10,
+ /datum/reagent/drug/maint/sludge = 10,
+ /datum/reagent/toxin/leadacetate = 5,
+ )
+ custom_price = PAYCHECK_COMMAND * 3.5
+
+// Mix of many of the stamina damage regenerating drugs to provide a cocktail no baton could hope to beat
+/obj/item/reagent_containers/hypospray/medipen/deforest/aranepaine
+ name = "aranepaine combat stimulant injector"
+ desc = "A Deforest branded autoinjector, loaded with a cocktail of drugs to make any who take it nearly \
+ immune to exhaustion while its in their system."
+ base_icon_state = "aranepaine"
+ icon_state = "aranepaine"
+ list_reagents = list(
+ /datum/reagent/drug/aranesp = 5,
+ /datum/reagent/drug/kronkaine = 5,
+ /datum/reagent/drug/pumpup = 5,
+ /datum/reagent/medicine/diphenhydramine = 5,
+ /datum/reagent/impurity = 5,
+ )
+ custom_price = PAYCHECK_COMMAND * 2.5
+
+// Nothing inherently illegal, just a potentially very dangerous mix of chems to be able to inject into people
+/obj/item/reagent_containers/hypospray/medipen/deforest/pentibinin
+ name = "pentibinin normalizant injector"
+ desc = "A Deforest branded autoinjector, loaded with a cocktail of drugs to make any who take it \
+ recover from many different types of damages, with many unusual or undocumented side-effects."
+ base_icon_state = "pentibinin"
+ icon_state = "pentibinin"
+ list_reagents = list(
+ /datum/reagent/medicine/c2/penthrite = 5,
+ /datum/reagent/medicine/polypyr = 5,
+ /datum/reagent/medicine/silibinin = 5,
+ /datum/reagent/medicine/omnizine = 5,
+ /datum/reagent/inverse/healing/tirimol = 5,
+ )
+ custom_price = PAYCHECK_COMMAND * 2.5
+
+// Combat stimulant that makes you immune to slowdowns for a bit
+/obj/item/reagent_containers/hypospray/medipen/deforest/synalvipitol
+ name = "synalvipitol muscle stimulant injector"
+ desc = "A Deforest branded autoinjector, loaded with a cocktail of drugs to make any who take it \
+ nearly immune to the slowing effects of silly things like 'being tired' or 'facing muscle failure'."
+ base_icon_state = "synalvipitol"
+ icon_state = "synalvipitol"
+ list_reagents = list(
+ /datum/reagent/medicine/mine_salve = 5,
+ /datum/reagent/medicine/synaptizine = 10,
+ /datum/reagent/medicine/muscle_stimulant = 5,
+ /datum/reagent/impurity = 5,
+ )
+ custom_price = PAYCHECK_COMMAND * 2.5
diff --git a/modular_doppler/deforest_medical_items/code/injectors.dm b/modular_doppler/deforest_medical_items/code/injectors.dm
new file mode 100644
index 0000000000000..02334261f3e32
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/injectors.dm
@@ -0,0 +1,209 @@
+// Pen basetype where the icon is gotten from
+/obj/item/reagent_containers/hypospray/medipen/deforest
+ name = "non-functional Deforest autoinjector"
+ desc = "A Deforest branded autoinjector, though this one seems to be both empty and non-functional."
+ icon = 'modular_doppler/deforest_medical_items/icons/injectors.dmi'
+ icon_state = "default"
+ volume = 25
+ list_reagents = list()
+ custom_price = PAYCHECK_COMMAND
+ /// If this pen has a timer for injecting others with, just for safety with some of the drugs in these
+ var/inject_others_time = 1.5 SECONDS
+
+/obj/item/reagent_containers/hypospray/medipen/deforest/Initialize(mapload)
+ . = ..()
+ amount_per_transfer_from_this = volume
+
+/obj/item/reagent_containers/hypospray/medipen/deforest/inject(mob/living/affected_mob, mob/user)
+ if(!reagents.total_volume)
+ to_chat(user, span_warning("[src] is empty!"))
+ return FALSE
+ if(!iscarbon(affected_mob))
+ return FALSE
+
+ //Always log attemped injects for admins
+ var/list/injected = list()
+ for(var/datum/reagent/injected_reagent in reagents.reagent_list)
+ injected += injected_reagent.name
+ var/contained = english_list(injected)
+ log_combat(user, affected_mob, "attempted to inject", src, "([contained])")
+
+ if((affected_mob != user) && inject_others_time)
+ affected_mob.visible_message(span_danger("[user] is trying to inject [affected_mob]!"), \
+ span_userdanger("[user] is trying to inject something into you!"))
+ if(!do_after(user, CHEM_INTERACT_DELAY(inject_others_time, user), affected_mob))
+ return FALSE
+
+ if(reagents.total_volume && (ignore_flags || affected_mob.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))) // Ignore flag should be checked first or there will be an error message.
+ to_chat(affected_mob, span_warning("You feel a tiny prick!"))
+ to_chat(user, span_notice("You inject [affected_mob] with [src]."))
+ if(!stealthy)
+ playsound(affected_mob, 'sound/items/hypospray.ogg', 50, TRUE)
+ var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
+
+ if(affected_mob.reagents)
+ var/trans = 0
+ if(!infinite)
+ trans = reagents.trans_to(affected_mob, amount_per_transfer_from_this, transferred_by = user, methods = INJECT)
+ else
+ reagents.expose(affected_mob, INJECT, fraction)
+ trans = reagents.copy_to(affected_mob, amount_per_transfer_from_this)
+ to_chat(user, span_notice("[trans] unit\s injected. [reagents.total_volume] unit\s remaining in [src]."))
+ log_combat(user, affected_mob, "injected", src, "([contained])")
+ return TRUE
+ return FALSE
+
+// Sensory restoration, heals eyes and ears with a bit of impurity
+/obj/item/reagent_containers/hypospray/medipen/deforest/occuisate
+ name = "occuisate sensory restoration injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of reagents to restore your vision and hearing to operation."
+ base_icon_state = "occuisate"
+ icon_state = "occuisate"
+ list_reagents = list(
+ /datum/reagent/medicine/inacusiate = 7,
+ /datum/reagent/medicine/oculine = 7,
+ /datum/reagent/impurity/inacusiate = 3,
+ /datum/reagent/inverse/oculine = 3,
+ /datum/reagent/toxin/lipolicide = 5,
+ )
+
+// Adrenaline, fills you with determination (and also stimulants)
+/obj/item/reagent_containers/hypospray/medipen/deforest/adrenaline
+ name = "adrenaline injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of reagents to intentionally give yourself fight or flight on demand."
+ base_icon_state = "adrenaline"
+ icon_state = "adrenaline"
+ list_reagents = list(
+ /datum/reagent/medicine/synaptizine = 5,
+ /datum/reagent/medicine/inaprovaline = 5,
+ /datum/reagent/determination = 10,
+ /datum/reagent/toxin/histamine = 5,
+ )
+
+// Morpital, heals a small amount of damage and kills pain for a bit
+/obj/item/reagent_containers/hypospray/medipen/deforest/morpital
+ name = "morpital regenerative stimulant injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of reagents to numb pain and repair small amounts of physical damage."
+ base_icon_state = "morpital"
+ icon_state = "morpital"
+ list_reagents = list(
+ /datum/reagent/medicine/morphine = 5,
+ /datum/reagent/medicine/omnizine/protozine = 15,
+ /datum/reagent/toxin/staminatoxin = 5,
+ )
+
+// Lipital, heals more damage than morpital but doesnt work much at higher damages
+/obj/item/reagent_containers/hypospray/medipen/deforest/lipital
+ name = "lipital regenerative stimulant injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of reagents to numb pain and repair small amounts of physical damage. \
+ Works most effectively against damaged caused by brute attacks."
+ base_icon_state = "lipital"
+ icon_state = "lipital"
+ list_reagents = list(
+ /datum/reagent/medicine/lidocaine = 5,
+ /datum/reagent/medicine/omnizine = 5,
+ /datum/reagent/medicine/c2/probital = 10,
+ )
+
+// Anti-poisoning injector, with a little bit of radiation healing as a treat
+/obj/item/reagent_containers/hypospray/medipen/deforest/meridine
+ name = "meridine antidote injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of reagents to serve as antidote to most galactic toxins. \
+ A warning sticker notes it should not be used if the patient is physically damaged, as it may cause complications."
+ base_icon_state = "meridine"
+ icon_state = "meridine"
+ list_reagents = list(
+ /datum/reagent/medicine/c2/multiver = 10,
+ /datum/reagent/medicine/potass_iodide = 10,
+ /datum/reagent/nitrous_oxide = 5,
+ )
+
+// Epinephrine and helps a little bit against stuns and stamina damage
+/obj/item/reagent_containers/hypospray/medipen/deforest/synephrine
+ name = "synephrine emergency stimulant injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of reagents to stabilize critical condition and recover from stamina deficits."
+ base_icon_state = "synephrine"
+ icon_state = "synephrine"
+ list_reagents = list(
+ /datum/reagent/medicine/epinephrine = 10,
+ /datum/reagent/medicine/synaptizine = 5,
+ /datum/reagent/medicine/synaphydramine = 5,
+ )
+ custom_price = PAYCHECK_COMMAND * 2.5
+
+// Critical condition stabilizer
+/obj/item/reagent_containers/hypospray/medipen/deforest/calopine
+ name = "calopine emergency stabilizant injector"
+ desc = "A Deforest branded autoinjector, loaded with a stabilizing mix of reagents to repair critical conditions."
+ base_icon_state = "calopine"
+ icon_state = "calopine"
+ list_reagents = list(
+ /datum/reagent/medicine/atropine = 10,
+ /datum/reagent/medicine/coagulant/fabricated = 5,
+ /datum/reagent/medicine/salbutamol = 5,
+ /datum/reagent/toxin/staminatoxin = 5,
+ )
+
+// Coagulant, really not a whole lot more
+/obj/item/reagent_containers/hypospray/medipen/deforest/coagulants
+ name = "coagulant-S injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of coagulants to prevent and stop bleeding."
+ base_icon_state = "coagulant"
+ icon_state = "coagulant"
+ list_reagents = list(
+ /datum/reagent/medicine/coagulant = 5,
+ /datum/reagent/medicine/salglu_solution = 15,
+ /datum/reagent/impurity = 5,
+ )
+
+// Stimulant centered around ondansetron
+/obj/item/reagent_containers/hypospray/medipen/deforest/krotozine
+ name = "krotozine manipulative stimulant injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of stimulants of weak healing agents."
+ base_icon_state = "krotozine"
+ icon_state = "krotozine"
+ list_reagents = list(
+ /datum/reagent/medicine/ondansetron = 5,
+ /datum/reagent/drug/kronkaine = 5,
+ /datum/reagent/medicine/omnizine/protozine = 10,
+ /datum/reagent/drug/maint/tar = 5,
+ )
+ custom_price = PAYCHECK_COMMAND * 2.5
+
+// Stuff really good at healing burn stuff and stabilizing temps
+/obj/item/reagent_containers/hypospray/medipen/deforest/lepoturi
+ name = "lepoturi burn treatment injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of medicines to rapidly treat burns."
+ base_icon_state = "lepoturi"
+ icon_state = "lepoturi"
+ list_reagents = list(
+ /datum/reagent/medicine/mine_salve = 5,
+ /datum/reagent/medicine/leporazine = 5,
+ /datum/reagent/medicine/c2/lenturi = 10,
+ /datum/reagent/toxin/staminatoxin = 5,
+ )
+
+// Stabilizes a lot of stats like drowsiness, sanity, dizziness, so on
+/obj/item/reagent_containers/hypospray/medipen/deforest/psifinil
+ name = "psifinil personal recovery injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of medicines to remedy many common ailments, such as drowsiness, pain, instability, the like."
+ base_icon_state = "psifinil"
+ icon_state = "psifinil"
+ list_reagents = list(
+ /datum/reagent/medicine/modafinil = 10,
+ /datum/reagent/medicine/psicodine = 10,
+ /datum/reagent/medicine/leporazine = 5,
+ )
+
+// Helps with liver failure and some drugs, also alcohol
+/obj/item/reagent_containers/hypospray/medipen/deforest/halobinin
+ name = "halobinin soberant injector"
+ desc = "A Deforest branded autoinjector, loaded with a mix of medicines to remedy the effects of liver failure and common drugs."
+ base_icon_state = "halobinin"
+ icon_state = "halobinin"
+ list_reagents = list(
+ /datum/reagent/medicine/haloperidol = 5,
+ /datum/reagent/medicine/antihol = 5,
+ /datum/reagent/medicine/higadrite = 5,
+ /datum/reagent/medicine/silibinin = 5,
+ )
diff --git a/modular_doppler/deforest_medical_items/code/medstation.dm b/modular_doppler/deforest_medical_items/code/medstation.dm
new file mode 100644
index 0000000000000..019cc57320d9e
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/medstation.dm
@@ -0,0 +1,55 @@
+/obj/machinery/biogenerator/medstation
+ name = "wall med-station"
+ desc = "An advanced machine seen in frontier outposts and colonies capable of turning organic plant matter into \
+ various emergency medical supplies and injectors. You can find one of these in the medical sections of just about \
+ any frontier installation."
+ icon = 'modular_doppler/deforest_medical_items/icons/medstation.dmi'
+ circuit = null
+ anchored = TRUE
+ density = FALSE
+ efficiency = 1
+ productivity = 1
+ show_categories = list(
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+ /// The item we turn into when repacked
+ var/repacked_type = /obj/item/wallframe/frontier_medstation
+
+MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/biogenerator/medstation, 29)
+
+/obj/machinery/biogenerator/medstation/RefreshParts()
+ . = ..()
+ efficiency = 1
+ productivity = 1
+
+/obj/machinery/biogenerator/medstation/default_unfasten_wrench(mob/user, obj/item/wrench/tool, time)
+ user.balloon_alert(user, "deconstructing...")
+ tool.play_tool_sound(src)
+ if(tool.use_tool(src, user, 1 SECONDS))
+ playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
+ deconstruct(TRUE)
+ return
+
+/obj/machinery/biogenerator/medstation/on_deconstruction(disassembled)
+ if(disassembled)
+ new repacked_type(drop_location())
+
+/obj/machinery/biogenerator/medstation/default_deconstruction_crowbar()
+ return
+
+// Deployable item for cargo for the medstation
+
+/obj/item/wallframe/frontier_medstation
+ name = "unmounted wall med-station"
+ desc = "The innovative technology of a biogenerator to print medical supplies, but able to be mounted neatly on a wall out of the way."
+ icon = 'modular_doppler/deforest_medical_items/icons/medstation.dmi'
+ icon_state = "biogenerator_parts"
+ w_class = WEIGHT_CLASS_NORMAL
+ result_path = /obj/machinery/biogenerator/medstation
+ pixel_shift = 29
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/silver = SHEET_MATERIAL_AMOUNT * 3,
+ /datum/material/gold = SHEET_MATERIAL_AMOUNT,
+ )
diff --git a/modular_doppler/deforest_medical_items/code/medstation_designs/blood.dm b/modular_doppler/deforest_medical_items/code/medstation_designs/blood.dm
new file mode 100644
index 0000000000000..f7624f60d1a4e
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/medstation_designs/blood.dm
@@ -0,0 +1,109 @@
+/datum/design/organic_bloodbag_aplus
+ name = "A+ Blood Pack"
+ id = "organic_bloodbag_aplus"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/blood/a_plus
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_aminus
+ name = "A- Blood Pack"
+ id = "organic_bloodbag_aminus"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/blood/a_minus
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_bplus
+ name = "B+ Blood Pack"
+ id = "organic_bloodbag_bplus"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/blood/b_plus
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_bminus
+ name = "B- Blood Pack"
+ id = "organic_bloodbag_bminus"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/blood/b_minus
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_oplus
+ name = "O+ Blood Pack"
+ id = "organic_bloodbag_oplus"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/blood/o_plus
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_ominus
+ name = "O- Blood Pack"
+ id = "organic_bloodbag_ominus"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/reagent_containers/blood/o_minus
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_lizard
+ name = "L Blood Pack"
+ id = "organic_bloodbag_lizard"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/blood/lizard
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_ethereal
+ name = "LE Blood Pack"
+ id = "organic_bloodbag_ethereal"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/blood/ethereal
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_plant
+ name = "H2O Blood Pack"
+ id = "organic_bloodbag_plant"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/reagent_containers/blood/podperson
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
+
+/datum/design/organic_bloodbag_slimeperson
+ name = "TOX Blood Pack"
+ id = "organic_bloodbag_slimeperson"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/reagent_containers/blood/toxin
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_BLOOD,
+ )
diff --git a/modular_doppler/deforest_medical_items/code/medstation_designs/medical.dm b/modular_doppler/deforest_medical_items/code/medstation_designs/medical.dm
new file mode 100644
index 0000000000000..7eb8106e3a4e4
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/medstation_designs/medical.dm
@@ -0,0 +1,98 @@
+/datum/design/organic_printer_balm
+ name = "Red Sun Balm"
+ id = "organic_sun_balm"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/stack/medical/ointment/red_sun
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
+
+/datum/design/organic_printer_gauze
+ name = "Sealed Aseptic Guaze"
+ id = "organic_gauze"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/stack/medical/gauze/sterilized
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
+
+/datum/design/organic_printer_coagulant_f
+ name = "Coagulant-F Packet"
+ id = "organic_coagulant_pack"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/stack/medical/suture/coagulant
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
+
+/datum/design/organic_printer_ointment
+ name = "Ointment"
+ id = "organic_ointment"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/stack/medical/ointment
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
+
+/datum/design/organic_printer_bruise_pack
+ name = "Bruise Packs"
+ id = "organic_bruise_packs"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/stack/medical/bruise_pack
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
+
+/datum/design/organic_printer_amollin_pill
+ name = "Amollin Painkiller"
+ id = "organic_printer_amollin_pill"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/reagent_containers/pill/amollin
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
+
+/datum/design/organic_printer_bandaid
+ name = "First Aid Bandage"
+ id = "organic_bandaid"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/stack/medical/bandage
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
+
+/datum/design/organic_printer_bone_gel
+ name = "Bone Gel"
+ id = "organic_bone_gel"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/stack/medical/bone_gel
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
+
+/datum/design/organic_printer_surgical_tape
+ name = "Surgical Tape"
+ id = "organic_surgical_tape"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/stack/sticky_tape/surgical
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_DEFOREST_MEDICAL,
+ )
diff --git a/modular_doppler/deforest_medical_items/code/storage_items.dm b/modular_doppler/deforest_medical_items/code/storage_items.dm
new file mode 100644
index 0000000000000..4690248ba5788
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/storage_items.dm
@@ -0,0 +1,493 @@
+// Bottle of painkiller pills
+/obj/item/storage/pill_bottle/painkiller
+ name = "amollin pill bottle"
+ desc = "It's an airtight container for storing medication. This one is all-white and has labels for containing amollin, a blend of Miner's Salve and Lidocaine."
+ icon = 'modular_doppler/deforest_medical_items/icons/storage.dmi'
+ icon_state = "painkiller_bottle"
+ custom_price = PAYCHECK_CREW * 1.5
+
+/obj/item/storage/pill_bottle/painkiller/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/amollin(src)
+
+/obj/item/reagent_containers/pill/amollin
+ name = "amollin pill"
+ desc = "Neutralizes many common pains and ailments. A blend of Miner's Salve and Lidocaine."
+ icon_state = "pill9"
+ list_reagents = list(
+ /datum/reagent/medicine/mine_salve = 10,
+ /datum/reagent/medicine/lidocaine = 5,
+ /datum/reagent/consumable/sugar = 5,
+ )
+
+// Narcolepsy quirk medicines
+/obj/item/storage/pill_bottle/prescription_stimulant
+ name = "alifil pill bottle"
+ desc = "A special miniaturized pill bottle with an insert resembling a revolver cylinder, fitted for the inside of a 'civil defense'-class shell medkit. Holds five alifil pills, and is designed only to accept their proprietary DeForest(tm) shape. A big, bold yellow warning label on the side reads: 'FOLLOW DOSAGE DIRECTIONS'."
+ icon = 'modular_doppler/deforest_medical_items/icons/storage.dmi'
+ icon_state = "painkiller_bottle"
+ w_class = WEIGHT_CLASS_TINY // this is fine because we hard limit what can go in this thing
+
+/obj/item/storage/pill_bottle/prescription_stimulant/Initialize(mapload)
+ . = ..()
+ // Make sure we can only hold alifil pills since this is nested inside a symptom support kit
+ atom_storage.max_slots = 5
+ atom_storage.set_holdable(list(
+ /obj/item/reagent_containers/pill/prescription_stimulant,
+ ))
+
+/obj/item/storage/pill_bottle/prescription_stimulant/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/prescription_stimulant(src)
+
+/obj/item/reagent_containers/pill/prescription_stimulant
+ name = "alifil pill"
+ desc = "Used to treat symptoms of drowsiness and sudden loss of consciousness. Contains a mix of sugar, synaptizine and modafinil. A warning label reads: Take in moderation."
+ icon_state = "pill15"
+ list_reagents = list(
+ /datum/reagent/consumable/sugar = 5,
+ /datum/reagent/medicine/synaptizine = 5,
+ /datum/reagent/medicine/modafinil = 3
+ )
+
+// Pre-packed civil defense medkit, with items to heal low damages inside
+/obj/item/storage/medkit/civil_defense
+ name = "civil defense medical kit"
+ icon = 'modular_doppler/deforest_medical_items/icons/storage.dmi'
+ icon_state = "poisoning_kit"
+ lefthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi'
+ righthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi'
+ inhand_icon_state = "poisoning_kit"
+ desc = "A small medical kit that can only fit autoinjectors in it, these typically come with supplies to treat low level harm."
+ w_class = WEIGHT_CLASS_SMALL
+ drop_sound = 'sound/items/handling/ammobox_drop.ogg'
+ pickup_sound = 'sound/items/handling/ammobox_pickup.ogg'
+ custom_price = PAYCHECK_COMMAND * 3
+
+/obj/item/storage/medkit/civil_defense/Initialize(mapload)
+ . = ..()
+ atom_storage.max_slots = 4
+ atom_storage.set_holdable(list(
+ /obj/item/reagent_containers/hypospray/medipen,
+ /obj/item/storage/pill_bottle/prescription_stimulant,
+ /obj/item/food/cheese/firm_cheese_slice, //It's not called a cheese kit for nothing.
+ /obj/item/food/cheese/wedge,
+ ))
+
+/obj/item/storage/medkit/civil_defense/stocked
+
+/obj/item/storage/medkit/civil_defense/stocked/PopulateContents()
+ var/static/items_inside = list(
+ /obj/item/reagent_containers/hypospray/medipen/deforest/meridine = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/halobinin = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/lipital = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/calopine = 1,
+ )
+ generate_items_inside(items_inside, src)
+
+/obj/item/storage/medkit/civil_defense/thunderdome
+ /// List of random medpens we can pick from
+ var/list/random_medpen_options = list(
+ /obj/item/reagent_containers/hypospray/medipen/deforest/twitch,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/demoneye,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/aranepaine,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/pentibinin,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/synalvipitol,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/adrenaline,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/morpital,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/lipital,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/synephrine,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/calopine,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/coagulants,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/krotozine,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/lepoturi,
+ )
+
+/obj/item/storage/medkit/civil_defense/thunderdome/Initialize(mapload)
+ . = ..()
+ atom_storage.max_slots = 6
+
+/obj/item/storage/medkit/civil_defense/thunderdome/PopulateContents()
+ for(var/pens in 1 to 6)
+ var/new_pen = pick(random_medpen_options)
+ new new_pen(src)
+
+// Variant on the civil defense medkit for spacer planetside personnel (or other people suffering from chronic illnesses)
+/obj/item/storage/medkit/civil_defense/comfort
+ name = "civil defense symptom support kit"
+ desc = "A small, pocket-sized kit that can typically only fit autoinjectors in it. This variant on the classic 'cheese' civil defense kit contains supplies to address hindering symptomatic burden associated with common chronic diseases or adaptation syndromes, such as gravity sickness."
+ icon_state = "symptom_kit"
+
+/obj/item/storage/medkit/civil_defense/comfort/stocked
+
+/obj/item/storage/medkit/civil_defense/comfort/stocked/PopulateContents()
+ var/static/items_inside = list(
+ /obj/item/reagent_containers/hypospray/medipen/deforest/psifinil = 3,
+ /obj/item/storage/pill_bottle/prescription_stimulant = 1,
+ )
+ generate_items_inside(items_inside, src)
+
+// Pre-packed frontier medkit, with supplies to repair most common frontier health issues
+/obj/item/storage/medkit/frontier
+ name = "frontier medical kit"
+ desc = "A handy roll-top waterproof medkit often seen alongside those on the frontier, where medical support is less than optimal. \
+ It has a clip for hooking onto your belt, handy!"
+ icon = 'modular_doppler/deforest_medical_items/icons/storage.dmi'
+ icon_state = "frontier"
+ lefthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi'
+ righthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi'
+ inhand_icon_state = "frontier"
+ worn_icon_state = "frontier"
+ worn_icon = 'modular_doppler/deforest_medical_items/icons/worn/worn.dmi'
+// worn_icon_teshari = 'modular_doppler/deforest_medical_items/icons/worn/worn_teshari.dmi'
+ pickup_sound = 'sound/items/handling/cloth_pickup.ogg'
+ drop_sound = 'sound/items/handling/cloth_drop.ogg'
+ slot_flags = ITEM_SLOT_BELT
+
+/obj/item/storage/medkit/frontier/stocked
+
+/obj/item/storage/medkit/frontier/stocked/PopulateContents()
+ var/static/items_inside = list(
+ /obj/item/reagent_containers/hypospray/medipen/deforest/meridine = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/morpital = 1,
+ /obj/item/stack/medical/ointment = 1,
+ /obj/item/stack/medical/suture = 1,
+ /obj/item/stack/medical/suture/coagulant = 1,
+ /obj/item/stack/medical/gauze/sterilized = 1,
+ /obj/item/storage/pill_bottle/painkiller = 1,
+ )
+ generate_items_inside(items_inside,src)
+
+// Pre-packed combat surgeon medkit, with items for fixing more specific injuries and wounds
+/obj/item/storage/medkit/combat_surgeon
+ name = "combat surgeon medical kit"
+ desc = "A folding kit that is ideally filled with surgical tools and specialized treatment options for many harder-to-treat wounds."
+ icon = 'modular_doppler/deforest_medical_items/icons/storage.dmi'
+ icon_state = "surgeon"
+ lefthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi'
+ righthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi'
+ inhand_icon_state = "surgeon"
+ worn_icon = 'modular_doppler/deforest_medical_items/icons/worn/worn.dmi'
+ worn_icon_state = "frontier"
+ pickup_sound = 'sound/items/handling/cloth_pickup.ogg'
+ drop_sound = 'sound/items/handling/cloth_drop.ogg'
+
+/obj/item/storage/medkit/combat_surgeon/Initialize(mapload)
+ . = ..()
+ atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
+
+/obj/item/storage/medkit/combat_surgeon/stocked
+
+/obj/item/storage/medkit/combat_surgeon/stocked/PopulateContents()
+ var/static/items_inside = list(
+ /obj/item/bonesetter = 1,
+ /obj/item/hemostat = 1,
+ /obj/item/cautery = 1,
+ /obj/item/stack/medical/wound_recovery = 1,
+ /obj/item/stack/medical/wound_recovery/rapid_coagulant = 1,
+ /obj/item/stack/medical/gauze/sterilized = 1,
+ /obj/item/healthanalyzer/simple = 1,
+ )
+ generate_items_inside(items_inside,src)
+
+// Big medical kit that can be worn like a bag, holds a LOT of medical items but works like a duffelbag
+/obj/item/storage/backpack/duffelbag/deforest_medkit
+ name = "satchel medical kit"
+ desc = "A large orange satchel able to hold just about any piece of small medical equipment you could think of, you can even wear it on your back or belt!"
+ icon = 'modular_doppler/deforest_medical_items/icons/storage.dmi'
+ icon_state = "satchel"
+ lefthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi'
+ righthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi'
+ inhand_icon_state = "satchel"
+ worn_icon = 'modular_doppler/deforest_medical_items/icons/worn/worn.dmi'
+ equip_sound = 'sound/items/equip/jumpsuit_equip.ogg'
+ pickup_sound = 'sound/items/handling/cloth_pickup.ogg'
+ drop_sound = 'sound/items/handling/cloth_drop.ogg'
+ slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT
+ storage_type = /datum/storage/duffel/deforest_medkit
+ zip_slowdown = 0.25 // Most won't notice normally but it'll hurt you if you're a paramedic or in combat
+ unzip_duration = 1.2 SECONDS
+
+/obj/item/storage/backpack/duffelbag/deforest_medkit/stocked
+
+/obj/item/storage/backpack/duffelbag/deforest_medkit/stocked/PopulateContents()
+ var/static/items_inside = list(
+ /obj/item/reagent_containers/hypospray/medipen/deforest/morpital = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/lepoturi = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/lipital = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/meridine = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/calopine = 1,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/coagulants = 1,
+ /obj/item/bonesetter = 1,
+ /obj/item/hemostat = 1,
+ /obj/item/cautery = 1,
+ /obj/item/stack/medical/wound_recovery = 1,
+ /obj/item/stack/medical/wound_recovery/rapid_coagulant = 1,
+ /obj/item/stack/medical/suture/coagulant = 1,
+ /obj/item/stack/medical/suture/bloody = 2,
+ /obj/item/stack/medical/mesh = 2,
+ /obj/item/stack/medical/gauze/sterilized = 1,
+ /obj/item/stack/medical/gauze = 1,
+ /obj/item/stack/medical/ointment/red_sun = 1,
+ /obj/item/storage/pill_bottle/painkiller = 1,
+ /obj/item/healthanalyzer/simple = 1,
+ )
+ generate_items_inside(items_inside,src)
+
+/datum/storage/duffel/deforest_medkit
+ max_specific_storage = WEIGHT_CLASS_SMALL
+ max_total_storage = 21 * WEIGHT_CLASS_SMALL
+ max_slots = 21
+
+/datum/storage/duffel/deforest_medkit/New()
+ . = ..()
+
+ can_hold = typecacheof(list(
+ /obj/item/bonesetter,
+ /obj/item/cautery,
+ /obj/item/clothing/neck/stethoscope,
+ /obj/item/clothing/mask/breath,
+ /obj/item/clothing/mask/muzzle,
+ /obj/item/clothing/mask/surgical,
+ /obj/item/clothing/suit/toggle/labcoat/hospitalgown,
+ /obj/item/dnainjector,
+ /obj/item/extinguisher/mini,
+ /obj/item/flashlight/pen,
+ /obj/item/geiger_counter,
+ /obj/item/healthanalyzer,
+ /obj/item/hemostat,
+ /obj/item/holosign_creator/medical,
+// /obj/item/hypospray,
+ /obj/item/implant,
+ /obj/item/implantcase,
+ /obj/item/implanter,
+ /obj/item/lazarus_injector,
+ /obj/item/lighter,
+ /obj/item/pinpointer/crew,
+ /obj/item/reagent_containers/blood,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+// /obj/item/reagent_containers/cup/vial,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/reagent_containers/medigel,
+ /obj/item/reagent_containers/pill,
+ /obj/item/reagent_containers/spray,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/stack/medical,
+ /obj/item/stack/sticky_tape,
+ /obj/item/sensor_device,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/storage/pill_bottle,
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/storage/box/bandages,
+ /obj/item/bodybag,
+ ))
+
+// Big surgical kit that can be worn like a bag, holds 14 normal items (more than what a backpack can do!) but works like a duffelbag
+/obj/item/storage/backpack/duffelbag/deforest_surgical
+ name = "first responder surgical kit"
+ desc = "A large bag able to hold all the surgical tools and first response healing equipment you can think of, you can even wear it!"
+ icon = 'modular_doppler/deforest_medical_items/icons/storage.dmi'
+ icon_state = "super_surgery"
+ lefthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi'
+ righthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi'
+ inhand_icon_state = "super_surgery"
+ worn_icon = 'modular_doppler/deforest_medical_items/icons/worn/worn.dmi'
+// worn_icon_teshari = 'modular_doppler/deforest_medical_items/icons/worn/worn_teshari.dmi'
+ equip_sound = 'sound/items/equip/jumpsuit_equip.ogg'
+ pickup_sound = 'sound/items/handling/cloth_pickup.ogg'
+ drop_sound = 'sound/items/handling/cloth_drop.ogg'
+ slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT
+ storage_type = /datum/storage/duffel/deforest_big_surgery
+ zip_slowdown = 0.5 // Its a bulkier bag and thus slows you down a little more when unzipped
+ unzip_duration = 1.2 SECONDS
+
+/obj/item/storage/backpack/duffelbag/deforest_surgical/stocked
+
+/obj/item/storage/backpack/duffelbag/deforest_surgical/stocked/PopulateContents()
+ var/static/items_inside = list(
+ /obj/item/scalpel = 1,
+ /obj/item/hemostat = 1,
+ /obj/item/retractor = 1,
+ /obj/item/circular_saw = 1,
+ /obj/item/bonesetter = 1,
+ /obj/item/cautery = 1,
+ /obj/item/surgical_drapes = 1,
+ /obj/item/blood_filter = 1,
+ /obj/item/emergency_bed = 1,
+ /obj/item/stack/medical/gauze = 1,
+ /obj/item/stack/medical/gauze/sterilized = 1,
+ /obj/item/reagent_containers/medigel/sterilizine = 1,
+ /obj/item/stack/sticky_tape/surgical = 1,
+ /obj/item/stack/medical/bone_gel = 1,
+ )
+ generate_items_inside(items_inside,src)
+
+/datum/storage/duffel/deforest_big_surgery
+ max_total_storage = 14 * WEIGHT_CLASS_NORMAL
+ max_slots = 14
+
+/datum/storage/duffel/deforest_big_surgery/New()
+ . = ..()
+
+ can_hold = typecacheof(list(
+ /obj/item/autopsy_scanner,
+ /obj/item/blood_filter,
+ /obj/item/bonesetter,
+ /obj/item/cautery,
+ /obj/item/circular_saw,
+ /obj/item/clothing/glasses,
+ /obj/item/clothing/gloves,
+ /obj/item/clothing/neck/stethoscope,
+ /obj/item/clothing/mask/breath,
+ /obj/item/clothing/mask/muzzle,
+ /obj/item/clothing/mask/surgical,
+ /obj/item/clothing/suit/toggle/labcoat/hospitalgown,
+ /obj/item/construction/plumbing,
+ /obj/item/dnainjector,
+ /obj/item/extinguisher/mini,
+ /obj/item/flashlight/pen,
+ /obj/item/geiger_counter,
+ /obj/item/gun/syringe/syndicate,
+ /obj/item/healthanalyzer,
+ /obj/item/hemostat,
+ /obj/item/holosign_creator/medical,
+// /obj/item/hypospray,
+ /obj/item/implant,
+ /obj/item/implantcase,
+ /obj/item/implanter,
+ /obj/item/lazarus_injector,
+ /obj/item/lighter,
+ /obj/item/pinpointer/crew,
+ /obj/item/plunger,
+ /obj/item/radio,
+ /obj/item/reagent_containers/blood,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+// /obj/item/reagent_containers/cup/vial,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/reagent_containers/medigel,
+ /obj/item/reagent_containers/pill,
+ /obj/item/reagent_containers/spray,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/retractor,
+ /obj/item/scalpel,
+ /obj/item/shears,
+ /obj/item/stack/medical,
+ /obj/item/stack/sticky_tape,
+ /obj/item/stamp,
+ /obj/item/sensor_device,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/storage/pill_bottle,
+ /obj/item/surgical_drapes,
+ /obj/item/surgicaldrill,
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/wrench/medical,
+ /obj/item/emergency_bed,
+ /obj/item/storage/box/bandages,
+ /obj/item/bodybag,
+ ))
+
+// Midrange bag for paramedics, hypospray and more flexible item wise than surgical, but restricted to small items only
+/obj/item/storage/backpack/duffelbag/deforest_paramedic
+ name = "medical technician kit"
+ desc = "Compared to its sibling the first responder surgical kit, this variant is equipped with a hypospray hit for roving paramedics. Featuring rapid access pockets that are lightweight, it can however only hold smaller items."
+ icon = 'modular_doppler/deforest_medical_items/icons/storage.dmi'
+ icon_state = "technician"
+ lefthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi'
+ righthand_file = 'modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi'
+ inhand_icon_state = "technician"
+ worn_icon = 'modular_doppler/deforest_medical_items/icons/worn/worn.dmi'
+// worn_icon_teshari = 'modular_doppler/deforest_medical_items/icons/worn/worn_teshari.dmi'
+ equip_sound = 'sound/items/equip/jumpsuit_equip.ogg'
+ pickup_sound = 'sound/items/handling/cloth_pickup.ogg'
+ drop_sound = 'sound/items/handling/cloth_drop.ogg'
+ slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT
+ storage_type = /datum/storage/duffel/deforest_paramedic
+ zip_slowdown = 0.3 // Midrange between the other two bags
+ unzip_duration = 1.2 SECONDS
+
+/obj/item/storage/backpack/duffelbag/deforest_paramedic/stocked
+
+/obj/item/storage/backpack/duffelbag/deforest_paramedic/stocked/PopulateContents()
+ var/static/items_inside = list(
+ /obj/item/scalpel = 1,
+ /obj/item/hemostat = 1,
+ /obj/item/retractor = 1,
+ /obj/item/circular_saw = 1,
+ /obj/item/bonesetter = 1,
+ /obj/item/cautery = 1,
+ /obj/item/surgical_drapes = 1,
+ /obj/item/stack/medical/bone_gel = 1,
+ /obj/item/stack/medical/wound_recovery = 1,
+ /obj/item/stack/medical/wound_recovery/rapid_coagulant = 1,
+ /obj/item/stack/medical/mesh/advanced = 2,
+ /obj/item/stack/medical/suture/medicated = 2,
+ /obj/item/stack/medical/gauze/sterilized = 1,
+ /obj/item/storage/pill_bottle/painkiller = 1,
+// /obj/item/hypospray/mkii/piercing/atropine = 1,
+// /obj/item/reagent_containers/cup/vial/small/libital = 1,
+// /obj/item/reagent_containers/cup/vial/small/lenturi = 1,
+// /obj/item/reagent_containers/cup/vial/small/seiver = 1,
+ /obj/item/healthanalyzer = 1,
+ )
+ generate_items_inside(items_inside,src)
+
+/datum/storage/duffel/deforest_paramedic
+ max_specific_storage = WEIGHT_CLASS_SMALL
+ max_total_storage = 21 * WEIGHT_CLASS_SMALL
+ max_slots = 21
+
+/datum/storage/duffel/deforest_paramedic/New()
+ . = ..()
+
+ can_hold = typecacheof(list(
+ /obj/item/bonesetter,
+ /obj/item/cautery,
+ /obj/item/circular_saw,
+ /obj/item/clothing/neck/stethoscope,
+ /obj/item/clothing/mask/breath,
+ /obj/item/clothing/mask/muzzle,
+ /obj/item/clothing/mask/surgical,
+ /obj/item/clothing/suit/toggle/labcoat/hospitalgown,
+ /obj/item/dnainjector,
+ /obj/item/extinguisher/mini,
+ /obj/item/flashlight/pen,
+ /obj/item/geiger_counter,
+ /obj/item/healthanalyzer,
+ /obj/item/hemostat,
+ /obj/item/holosign_creator/medical,
+// /obj/item/hypospray,
+ /obj/item/implant,
+ /obj/item/implantcase,
+ /obj/item/implanter,
+ /obj/item/lazarus_injector,
+ /obj/item/lighter,
+ /obj/item/pinpointer/crew,
+ /obj/item/reagent_containers/blood,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+// /obj/item/reagent_containers/cup/vial,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/reagent_containers/medigel,
+ /obj/item/reagent_containers/pill,
+ /obj/item/reagent_containers/spray,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/retractor,
+ /obj/item/scalpel,
+ /obj/item/surgical_drapes,
+ /obj/item/stack/medical,
+ /obj/item/stack/sticky_tape,
+ /obj/item/sensor_device,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/storage/pill_bottle,
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/storage/box/bandages,
+ /obj/item/bodybag,
+ ))
diff --git a/modular_doppler/deforest_medical_items/code/treatment_zone_projector.dm b/modular_doppler/deforest_medical_items/code/treatment_zone_projector.dm
new file mode 100644
index 0000000000000..78a9a0dd7dc7b
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/treatment_zone_projector.dm
@@ -0,0 +1,49 @@
+// Giant 3x3 tile warning hologram that tells people they should probably stand outside of it
+
+/obj/structure/holosign/treatment_zone_warning
+ name = "treatment zone indicator"
+ desc = "A massive glowing holosign warning you to keep out of it, there's probably some important stuff happening in there!"
+ icon = 'modular_doppler/deforest_medical_items/icons/telegraph_96x96.dmi'
+ icon_state = "treatment_zone"
+ layer = BELOW_OBJ_LAYER
+ pixel_x = -32
+ pixel_y = -32
+ use_vis_overlay = FALSE
+
+// Projector for the above mentioned treatment zone signs
+
+/obj/item/holosign_creator/medical/treatment_zone
+ name = "emergency treatment zone projector"
+ desc = "A holographic projector that creates a large, clearly marked treatment zone hologram, which warns outsiders that they ought to stay out of it."
+ holosign_type = /obj/structure/holosign/treatment_zone_warning
+ creation_time = 1 SECONDS
+ max_signs = 1
+
+// Tech design for printing the projectors
+
+/datum/design/treatment_zone_projector
+ name = "Emergency Treatment Zone Projector"
+ desc = "A holographic projector that creates a large, clearly marked treatment zone hologram, which warns outsiders that they ought to stay out of it."
+ build_type = PROTOLATHE | AWAY_LATHE
+ build_path = /obj/item/holosign_creator/medical/treatment_zone
+ materials = list(
+ /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5,
+ /datum/material/glass = SMALL_MATERIAL_AMOUNT * 5,
+ /datum/material/silver = SMALL_MATERIAL_AMOUNT,
+ )
+ id = "treatment_zone_projector"
+ category = list(
+ RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_MEDICAL
+ )
+ departmental_flags = DEPARTMENT_BITFLAG_MEDICAL
+
+/datum/techweb_node/holographics/New()
+ . = ..()
+ design_ids.Add("treatment_zone_projector")
+
+// Adds the funny projector to medical borgs
+
+/obj/item/robot_model/medical/New(loc, ...)
+ . = ..()
+ var/obj/item/holosign_creator/medical/treatment_zone/new_holosign = new(src)
+ basic_modules.Add(new_holosign)
diff --git a/modular_doppler/deforest_medical_items/code/vendor.dm b/modular_doppler/deforest_medical_items/code/vendor.dm
new file mode 100644
index 0000000000000..a91b390d9333e
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/vendor.dm
@@ -0,0 +1,67 @@
+/obj/machinery/vending/deforest_medvend
+ name = "\improper DeForest Med-Vend"
+ desc = "A vending machine providing a selection of medical supplies."
+ icon = 'modular_doppler/deforest_medical_items/icons/vendor.dmi'
+ icon_state = "medvend"
+ panel_type = "panel15"
+ light_mask = "medvend-light-mask"
+ light_color = LIGHT_COLOR_LIGHT_CYAN
+ product_slogans = "Medical care at regulation-mandated reasonable prices!;DeForest is not liable for accidents due to supply misuse!"
+ product_categories = list(
+ list(
+ "name" = "First Aid",
+ "icon" = "notes-medical",
+ "products" = list(
+ /obj/item/stack/medical/ointment/red_sun = 4,
+ /obj/item/stack/medical/ointment = 4,
+ /obj/item/stack/medical/bruise_pack = 4,
+ /obj/item/stack/medical/gauze/sterilized = 4,
+ /obj/item/stack/medical/suture/coagulant = 4,
+ /obj/item/stack/medical/suture = 4,
+ /obj/item/stack/medical/suture/bloody = 2,
+ /obj/item/stack/medical/mesh = 4,
+ /obj/item/stack/medical/mesh/bloody = 2,
+ /obj/item/stack/medical/bandage = 4,
+ /obj/item/stack/medical/wound_recovery = 2,
+ /obj/item/stack/medical/wound_recovery/rapid_coagulant = 2,
+ /obj/item/storage/pill_bottle/painkiller = 4,
+ /obj/item/storage/medkit/civil_defense/stocked = 2,
+ ),
+ ),
+ list(
+ "name" = "Autoinjectors",
+ "icon" = "syringe",
+ "products" = list(
+ /obj/item/reagent_containers/hypospray/medipen/deforest/occuisate = 3,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/adrenaline = 3,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/morpital = 4,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/lipital = 3,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/meridine = 3,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/calopine = 4,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/coagulants = 4,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/lepoturi = 3,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/psifinil = 3,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/halobinin = 3,
+ ),
+ ),
+ )
+
+ contraband = list(
+ /obj/item/reagent_containers/hypospray/medipen/deforest/pentibinin = 2,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/synephrine = 2,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/krotozine = 2,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/aranepaine = 2,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/synalvipitol = 2,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/twitch = 2,
+ /obj/item/reagent_containers/hypospray/medipen/deforest/demoneye = 2,
+ )
+
+ refill_canister = /obj/item/vending_refill/medical_deforest
+ default_price = PAYCHECK_CREW
+ extra_price = PAYCHECK_COMMAND * 4
+ payment_department = NO_FREEBIES
+ onstation_override = 1 // No freebies if this spawns on the interlink
+
+/obj/item/vending_refill/medical_deforest
+ machine_name = "DeForest Med-Vend"
+ icon_state = "refill_medical"
diff --git a/modular_doppler/deforest_medical_items/code/vulnerable_status_effect.dm b/modular_doppler/deforest_medical_items/code/vulnerable_status_effect.dm
new file mode 100644
index 0000000000000..6f7636b81778e
--- /dev/null
+++ b/modular_doppler/deforest_medical_items/code/vulnerable_status_effect.dm
@@ -0,0 +1,28 @@
+/atom/movable/screen/alert/status_effect/vulnerable_to_damage
+ name = "Vulnerable To Damage"
+ desc = "You will take more damage than normal while your body recovers from mending itself!"
+ icon_state = "terrified"
+
+/datum/status_effect/vulnerable_to_damage
+ id = "vulnerable_to_damage"
+ duration = 5 MINUTES
+ alert_type = /atom/movable/screen/alert/status_effect/vulnerable_to_damage
+ remove_on_fullheal = TRUE
+ /// The percentage damage modifier we give the mob we're applied to
+ var/damage_resistance_subtraction = 50
+ /// How much extra bleeding the mob is given
+ var/bleed_modifier_addition = 1
+
+/datum/status_effect/vulnerable_to_damage/on_apply()
+ to_chat(owner, span_userdanger("Your body suddenly feals weak and fragile!"))
+ var/mob/living/carbon/human/carbon_owner = owner
+ carbon_owner.physiology.damage_resistance -= damage_resistance_subtraction
+ carbon_owner.physiology.bleed_mod += bleed_modifier_addition
+ return ..()
+
+/datum/status_effect/vulnerable_to_damage/on_remove()
+ to_chat(owner, span_notice("You seem to have recovered from your unnatural fragility!"))
+ var/mob/living/carbon/human/carbon_recoverer = owner
+ carbon_recoverer.physiology.damage_resistance += damage_resistance_subtraction
+ carbon_recoverer.physiology.bleed_mod -= bleed_modifier_addition
+ return ..()
diff --git a/modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi b/modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi
new file mode 100644
index 0000000000000..61e9fb5f7501c
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/inhands/cases_lefthand.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi b/modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi
new file mode 100644
index 0000000000000..b09d02d258a6c
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/inhands/cases_righthand.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/injectors.dmi b/modular_doppler/deforest_medical_items/icons/injectors.dmi
new file mode 100644
index 0000000000000..8ee669c0bc6b6
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/injectors.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/medstation.dmi b/modular_doppler/deforest_medical_items/icons/medstation.dmi
new file mode 100644
index 0000000000000..2de94bc420a8a
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/medstation.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/stack_items.dmi b/modular_doppler/deforest_medical_items/icons/stack_items.dmi
new file mode 100644
index 0000000000000..c9e82f1375f79
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/stack_items.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/storage.dmi b/modular_doppler/deforest_medical_items/icons/storage.dmi
new file mode 100644
index 0000000000000..513aed6e2a1bd
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/storage.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/telegraph_96x96.dmi b/modular_doppler/deforest_medical_items/icons/telegraph_96x96.dmi
new file mode 100644
index 0000000000000..8596bce378d80
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/telegraph_96x96.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/vendor.dmi b/modular_doppler/deforest_medical_items/icons/vendor.dmi
new file mode 100644
index 0000000000000..906191c451b36
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/vendor.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/worn/worn.dmi b/modular_doppler/deforest_medical_items/icons/worn/worn.dmi
new file mode 100644
index 0000000000000..942715fe56a7c
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/worn/worn.dmi differ
diff --git a/modular_doppler/deforest_medical_items/icons/worn/worn_teshari.dmi b/modular_doppler/deforest_medical_items/icons/worn/worn_teshari.dmi
new file mode 100644
index 0000000000000..276804f908b30
Binary files /dev/null and b/modular_doppler/deforest_medical_items/icons/worn/worn_teshari.dmi differ
diff --git a/modular_doppler/examinemore/code/examine_more.dm b/modular_doppler/examinemore/code/examine_more.dm
new file mode 100644
index 0000000000000..10e86ad35f509
--- /dev/null
+++ b/modular_doppler/examinemore/code/examine_more.dm
@@ -0,0 +1,115 @@
+/*
+EXTRA EXAMINE MODULE
+
+This is the module for handling items with special examine stats,
+like syndicate items having information in their description that
+would only be recognisable with someone that had the syndicate trait.
+*/
+
+// Give the detective the ability to see this stuff.
+/datum/job/detective
+ mind_traits = list(TRAIT_DETECTIVE)
+
+/obj/item
+ //The special description that is triggered when special_desc_requirements are met. Make sure you set the correct EXAMINE_CHECK!
+ var/special_desc = ""
+
+ //The special affiliation type, basically overrides the "Syndicate Affiliation" for SYNDICATE check types. It will show whatever organisation you put here instead of "Syndicate Affiliation"
+ var/special_desc_affiliation = ""
+
+ //The requirement setting for special descriptions. See examine_defines.dm for more info.
+ var/special_desc_requirement = EXAMINE_CHECK_NONE
+
+ //The ROLE requirement setting if EXAMINE_CHECK_ROLE is set. E.g. ROLE_SYNDICATE. As you can see, it's a list. So when setting it, ensure you do = list(shit1, shit2)
+ var/list/special_desc_roles
+
+ //The JOB requirement setting if EXAMINE_CHECK_JOB is set. E.g. JOB_SECURITY_OFFICER. As you can see, it's a list. So when setting it, ensure you do = list(shit1, shit2)
+ var/list/special_desc_jobs
+
+ //The FACTION requirement setting if EXAMINE_CHECK_FACTION is set. E.g. "Syndicate". As you can see, it's a list. So when setting it, ensure you do = list(shit1, shit2)
+ var/list/special_desc_factions
+
+
+/obj/item/examine(mob/user)
+ . = ..()
+ if(special_desc_requirement == EXAMINE_CHECK_NONE && special_desc)
+ . += span_notice("This item could be examined further...")
+
+/obj/item/examine_more(mob/user)
+ . = ..()
+ if(special_desc)
+ var/composed_message
+ switch(special_desc_requirement)
+ //Will always show if set
+ if(EXAMINE_CHECK_NONE)
+ composed_message = "You note the following:
"
+ composed_message += special_desc
+ . += composed_message
+ //Mindshield checks
+ if(EXAMINE_CHECK_MINDSHIELD)
+ if(HAS_TRAIT(user, TRAIT_MINDSHIELD))
+ composed_message = "You note the following because of your mindshield:
"
+ composed_message += special_desc
+ . += composed_message
+ //Standard syndicate checks
+ if(EXAMINE_CHECK_SYNDICATE)
+ if(user.mind)
+ var/datum/mind/M = user.mind
+ if((M.special_role == ROLE_TRAITOR) || (ROLE_SYNDICATE in user.faction))
+ composed_message = "You note the following because of your [special_desc_affiliation ? special_desc_affiliation : "Syndicate Affiliation"]:
"
+ composed_message += special_desc
+ . += composed_message
+ else if(HAS_TRAIT(M, TRAIT_DETECTIVE)) //Useful detective!
+ composed_message = "You note the following because of your brilliant Detective skills:
"
+ composed_message += special_desc
+ . += composed_message
+ //As above, but with a toy desc for those looking at it
+ if(EXAMINE_CHECK_SYNDICATE_TOY)
+ if(user.mind)
+ var/datum/mind/M = user.mind
+ if((M.special_role == ROLE_TRAITOR) || (ROLE_SYNDICATE in user.faction))
+ composed_message = "You note the following because of your [special_desc_affiliation ? special_desc_affiliation : "Syndicate Affiliation"]:
"
+ composed_message += special_desc
+ . += composed_message
+ else if(HAS_TRAIT(M, TRAIT_DETECTIVE)) //Useful detective!
+ composed_message = "You note the following because of your brilliant detective skills:
"
+ composed_message += special_desc
+ . += composed_message
+ else
+ composed_message = "The popular toy resembling [src] from your local arcade, suitable for children and adults alike."
+ . += composed_message
+ //Standard role checks
+ if(EXAMINE_CHECK_ROLE)
+ if(user.mind)
+ var/datum/mind/M = user.mind
+ for(var/role_i in special_desc_roles)
+ if(M.special_role == role_i)
+ composed_message = "You note the following because of your [role_i] role:
"
+ composed_message += special_desc
+ . += composed_message
+ //Standard job checks
+ if(EXAMINE_CHECK_JOB)
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ for(var/job_i in special_desc_jobs)
+ if(H.job == job_i)
+ composed_message = "You note the following because of your job as a [job_i]:
"
+ composed_message += special_desc
+ . += composed_message
+ //Standard faction checks
+ if(EXAMINE_CHECK_FACTION)
+ for(var/faction_i in special_desc_factions)
+ if(faction_i in user.faction)
+ composed_message = "You note the following because of your loyalty to [faction_i]:
"
+ composed_message += special_desc
+ . += composed_message
+
+/*
+* EXAMPLES
+*/
+
+/obj/item/storage/backpack/duffelbag/syndie
+ name = "duffel bag"
+ desc = "A large duffel bag for holding extra supplies."
+ special_desc_requirement = EXAMINE_CHECK_SYNDICATE
+ special_desc = "This bag is used to store tactical equipment and is manufactured by the syndicate."
diff --git a/modular_doppler/examinemore/code/readme.md b/modular_doppler/examinemore/code/readme.md
new file mode 100644
index 0000000000000..c7dc6a2f6e1da
--- /dev/null
+++ b/modular_doppler/examinemore/code/readme.md
@@ -0,0 +1,26 @@
+## Title: Special Examine System
+
+MODULE ID: examinemore
+
+### Description:
+
+Adds a system for setting special descriptors for items that trigger dependant on the below defines. Please check the files for more information.
+
+### TG Proc Changes:
+
+- N/A
+
+### Defines:
+
+- code\__DEFINES\~nova_defines\examine_defines.dm
+
+### Master file additions
+
+- N/A
+
+### Included files that are not contained in this module:
+
+- N/A
+
+### Credits:
+Gandalf2k15 - OG code
diff --git a/modular_doppler/food_replicator/code/clothing.dm b/modular_doppler/food_replicator/code/clothing.dm
new file mode 100644
index 0000000000000..aa5c532b47bc9
--- /dev/null
+++ b/modular_doppler/food_replicator/code/clothing.dm
@@ -0,0 +1,38 @@
+/obj/item/clothing/under/colonial
+ name = "colonial outfit"
+ desc = "Fancy white satin shirt and a pair of cotton-blend pants with a black synthleather belt."
+ icon_state = "under_colonial"
+ icon = 'modular_doppler/food_replicator/icons/clothing.dmi'
+ worn_icon = 'modular_doppler/food_replicator/icons/clothing_worn.dmi'
+ supported_bodyshapes = list(BODYSHAPE_HUMANOID, BODYSHAPE_DIGITIGRADE)
+ bodyshape_icon_files = list(BODYSHAPE_HUMANOID_T = 'modular_doppler/food_replicator/icons/clothing_worn.dmi',
+ BODYSHAPE_DIGITIGRADE_T = 'modular_doppler/food_replicator/icons/clothing_digi.dmi')
+
+/obj/item/clothing/shoes/jackboots/colonial
+ name = "colonial half-boots"
+ desc = "Good old laceless boots, with a sturdy plastic toe to, theoretically, keep your toes uncrushed."
+ icon_state = "boots_colonial"
+ icon = 'modular_doppler/food_replicator/icons/clothing.dmi'
+ worn_icon = 'modular_doppler/food_replicator/icons/clothing_worn.dmi'
+ supported_bodyshapes = list(BODYSHAPE_HUMANOID, BODYSHAPE_DIGITIGRADE)
+ bodyshape_icon_files = list(BODYSHAPE_HUMANOID_T = 'modular_doppler/food_replicator/icons/clothing_worn.dmi',
+ BODYSHAPE_DIGITIGRADE_T = 'modular_doppler/food_replicator/icons/clothing_digi.dmi')
+
+/obj/item/clothing/neck/cloak/colonial
+ name = "colonial cloak"
+ desc = "A cloak made from heavy tarpaulin. Nigh wind- and waterproof thanks to its design."
+ w_class = WEIGHT_CLASS_NORMAL
+ icon_state = "cloak_colonial"
+ icon = 'modular_doppler/food_replicator/icons/clothing.dmi'
+ worn_icon = 'modular_doppler/food_replicator/icons/clothing_worn.dmi'
+ supported_bodyshapes = list(BODYSHAPE_HUMANOID, BODYSHAPE_DIGITIGRADE)
+ bodyshape_icon_files = list(BODYSHAPE_HUMANOID_T = 'modular_doppler/food_replicator/icons/clothing_worn.dmi',
+ BODYSHAPE_DIGITIGRADE_T = 'modular_doppler/food_replicator/icons/clothing_digi.dmi')
+
+/obj/item/clothing/head/hats/colonial
+ name = "colonial cap"
+ desc = "A puffy cap made out of tarpaulin covered by some textile. It is sturdy and comfortable, and seems to retain its form very well."
+ icon_state = "cap_colonial"
+ icon = 'modular_doppler/food_replicator/icons/clothing.dmi'
+ worn_icon = 'modular_doppler/food_replicator/icons/clothing_worn.dmi'
+ inhand_icon_state = null
diff --git a/modular_doppler/food_replicator/code/medical.dm b/modular_doppler/food_replicator/code/medical.dm
new file mode 100644
index 0000000000000..b1e13110ab3a4
--- /dev/null
+++ b/modular_doppler/food_replicator/code/medical.dm
@@ -0,0 +1,66 @@
+/obj/item/stack/medical/suture/bloody
+ name = "hemostatic suture"
+ desc = "Bloodclotting agent-infused sterile sutures used to seal up cuts and lacerations and reverse critical bleedings."
+ icon = 'modular_doppler/food_replicator/icons/medicine.dmi'
+ icon_state = "hemo_suture"
+ heal_brute = 7
+ stop_bleeding = 1
+ grind_results = list(/datum/reagent/medicine/coagulant = 2)
+ merge_type = /obj/item/stack/medical/suture/bloody
+
+/obj/item/stack/medical/suture/bloody/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user)
+ . = ..()
+ if(healed_mob.blood_volume <= BLOOD_VOLUME_SAFE)
+ healed_mob.reagents.add_reagent(/datum/reagent/medicine/salglu_solution, 2)
+ healed_mob.adjustOxyLoss(-amount_healed)
+
+/obj/item/stack/medical/mesh/bloody
+ name = "hemostatic mesh"
+ desc = "A hemostatic mesh used to dress burns and stimulate hemopoiesis. Due to its blood-related purpose, it is worse at sanitizing infections."
+ icon = 'modular_doppler/food_replicator/icons/medicine.dmi'
+ icon_state = "hemo_mesh"
+ heal_burn = 7
+ sanitization = 0.5
+ flesh_regeneration = 1.75
+ stop_bleeding = 0.25
+ grind_results = list(/datum/reagent/medicine/coagulant = 2)
+ merge_type = /obj/item/stack/medical/mesh/bloody
+
+/obj/item/stack/medical/mesh/bloody/update_icon_state()
+ if(is_open)
+ return ..()
+
+ icon_state = "hemo_mesh_closed"
+
+/obj/item/stack/medical/mesh/bloody/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user)
+ . = ..()
+ if(healed_mob.blood_volume <= BLOOD_VOLUME_SAFE)
+ healed_mob.reagents.add_reagent(/datum/reagent/medicine/salglu_solution, 2)
+ healed_mob.adjustOxyLoss(-amount_healed)
+
+/obj/item/reagent_containers/hypospray/medipen/glucose
+ name = "pressurised glucose medipen"
+ desc = "A medipen for keeping yourself going during prolonged EVA shifts, injects a dose of glucose into your bloodstream. Recommended for use in low-pressure environments."
+ icon = 'modular_doppler/food_replicator/icons/medicine.dmi'
+ icon_state = "glupen"
+ inhand_icon_state = "stimpen"
+ base_icon_state = "glupen"
+ volume = 15
+ amount_per_transfer_from_this = 15
+ list_reagents = list(/datum/reagent/consumable/nutriment/glucose = 15)
+
+/obj/item/reagent_containers/hypospray/medipen/glucose/inject(mob/living/affected_mob, mob/user)
+ if(lavaland_equipment_pressure_check(get_turf(user)))
+ amount_per_transfer_from_this = initial(amount_per_transfer_from_this)
+ return ..()
+
+ if(DOING_INTERACTION(user, DOAFTER_SOURCE_SURVIVALPEN))
+ to_chat(user,span_notice("You are too busy to use \the [src]!"))
+ return
+
+ to_chat(user,span_notice("You start manually releasing the low-pressure gauge..."))
+ if(!do_after(user, 10 SECONDS, affected_mob, interaction_key = DOAFTER_SOURCE_SURVIVALPEN))
+ return
+
+ amount_per_transfer_from_this = initial(amount_per_transfer_from_this) * 0.5
+ return ..()
diff --git a/modular_doppler/food_replicator/code/rationpacks.dm b/modular_doppler/food_replicator/code/rationpacks.dm
new file mode 100644
index 0000000000000..7558518c20e49
--- /dev/null
+++ b/modular_doppler/food_replicator/code/rationpacks.dm
@@ -0,0 +1,197 @@
+/obj/item/food/colonial_course
+ name = "undefined colonial course"
+ desc = "Something you shouldn't see. But it's edible."
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ icon_state = "borgir"
+ base_icon_state = "borgir"
+ food_reagents = list(/datum/reagent/consumable/nutriment = 20)
+ tastes = list("crayon powder" = 1)
+ foodtypes = VEGETABLES | GRAIN
+ w_class = WEIGHT_CLASS_SMALL
+ preserved_food = TRUE
+
+/obj/item/food/colonial_course/attack_self(mob/user, modifiers)
+ if(preserved_food)
+ preserved_food = FALSE
+ icon_state = "[base_icon_state]_unwrapped"
+ to_chat(user, span_notice("You unpackage \the [src]."))
+ playsound(user.loc, 'sound/items/foodcanopen.ogg', 50)
+
+/obj/item/food/colonial_course/attack(mob/living/target, mob/user, def_zone)
+ if(preserved_food)
+ to_chat(user, span_warning("[src] is still packaged!"))
+ return FALSE
+
+ return ..()
+
+/obj/item/food/colonial_course/pljeskavica
+ name = "pljeskavica"
+ desc = "Freshly-printed steaming hot burger consisting of a biogenerator-produced handcraft-imitating buns, with a minced meat patty inbetween, among various vegetables and sauces.\
+
Looks good enough for something as replicated as this. Its packaging is covered in copious amounts of information on its nutritional facts, contents and the expiry date. Sadly, it's all written in Pan-Slavic."
+ trash_type = /obj/item/trash/pljeskavica
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 3,
+ /datum/reagent/consumable/nutriment/protein = 9,
+ /datum/reagent/consumable/nutriment/vitamin = 4,
+ )
+ tastes = list("bun" = 2, "spiced meat" = 10, "death of veganism" = 3)
+ foodtypes = VEGETABLES | GRAIN | MEAT
+
+/obj/item/food/colonial_course/nachos
+ name = "plain nachos tray"
+ desc = "A vacuum-sealed package with what seems to be a generous serving of triangular corn chips, with three sections reserved for a salsa, cheese and guacamole sauces.\
+
Probably the best-looking food you can find in these rations, perhaps due to its simplicity."
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 5,
+ /datum/reagent/consumable/nutriment/vitamin = 2,
+ )
+ trash_type = /obj/item/trash/nachos
+ icon_state = "nacho"
+ base_icon_state = "nacho"
+ tastes = list("corn chips" = 5, "'artificial' organic sauces" = 5)
+ foodtypes = GRAIN | FRIED | DAIRY
+
+/obj/item/food/colonial_course/blins
+ name = "condensed milk crepes"
+ desc = "A vacuum-sealed four-pack of stuffed crepes with a minimal amount of markings. There is nothing else to it, to be frank.\
+
Surprisingly tasty for its looks, as long as you're not lactose intolerant, on diet, or vegan. The back of the packaging is covered in a mass of information detailing the product."
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 2,
+ /datum/reagent/consumable/caramel = 3,
+ /datum/reagent/consumable/milk = 4,
+ )
+ trash_type = /obj/item/trash/blins
+ icon_state = "blin"
+ base_icon_state = "blin"
+ tastes = list("insane amount of sweetness" = 10, "crepes" = 3)
+ foodtypes = SUGAR | GRAIN | DAIRY | BREAKFAST
+
+/obj/item/reagent_containers/cup/glass/coffee/colonial
+ name = "colonial thermocup"
+ desc = "Technically, used to drink hot beverages. But since it's the only cup design that was available, you gotta make do. It has an instruction written on its side. \
+
This particular one comes prefilled with a single serving of coffee powder."
+ special_desc = "A small instruction on the side reads: \"For use in food replicators; mix water and powdered solutions in one-to-one proportions. \
+
For cocoa, mix milk and powdered solution in one-to-one proportion.\""
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ list_reagents = list(/datum/reagent/consumable/powdered_coffee = 25)
+
+/obj/item/reagent_containers/cup/glass/coffee/colonial/empty
+ desc = "Technically, used to drink hot beverages. But since it's the only cup design that was available, you gotta make do. It has an instruction written on its side."
+ list_reagents = null
+
+/obj/item/trash/pljeskavica
+ name = "pljeskavica wrapping paper"
+ desc = "Covered in sauce smearings and smaller pieces of the dish on the inside, crumpled into a ball. It's probably best to dispose of it."
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ icon_state = "borgir_trash"
+
+/obj/item/trash/nachos
+ name = "empty nachos tray"
+ desc = "Covered in sauce smearings and smaller pieces of the dish on the inside, a plastic food tray with not much use anymore. It's probably best to dispose of it or recycle it."
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ custom_materials = list(
+ /datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ icon_state = "nacho_trash"
+
+/obj/item/trash/blins
+ name = "empty crepes wrapper"
+ desc = "Empty torn wrapper that used to hold something ridiculously sweet. It's probably best to recycle it."
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ custom_materials = list(
+ /datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT * 0.5,
+ )
+ icon_state = "blin_trash"
+
+/obj/item/storage/box/gum/colonial
+ name = "mixed bubblegum packet"
+ desc = "The packaging is entirely written in Pan-Slavic, with a small blurb of Sol Common. You would need to take a better look to read it, though, as it is written quite small."
+ special_desc = "Examining the small text reveals the following: \"Foreign colonization ration, model J: mixed origin, adult. Bubblegum package, medicinal, recreational.
\
+ Do not overconsume. Certain strips contain nicotine.\""
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ icon_state = "bubblegum"
+
+/obj/item/storage/box/gum/colonial/PopulateContents()
+ new /obj/item/food/bubblegum(src)
+ new /obj/item/food/bubblegum(src)
+ new /obj/item/food/bubblegum/nicotine(src)
+ new /obj/item/food/bubblegum/nicotine(src)
+
+/obj/item/storage/box/utensils
+ name = "utensils package"
+ desc = "A small package containing various utensils required for human consumption of various foods. \
+ In a normal situation contains a plastic fork, a plastic spoon, and two serviettes."
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ icon_state = "utensil_box"
+ w_class = WEIGHT_CLASS_TINY
+ illustration = null
+ foldable_result = null
+
+/obj/item/storage/box/utensils/Initialize(mapload)
+ . = ..()
+ atom_storage.set_holdable(list(
+ /obj/item/kitchen/spoon/plastic,
+ /obj/item/kitchen/fork/plastic,
+ /obj/item/serviette,
+ ))
+ atom_storage.max_slots = 4
+
+/obj/item/storage/box/utensils/PopulateContents()
+ new /obj/item/kitchen/spoon/plastic(src)
+ new /obj/item/kitchen/fork/plastic(src)
+ new /obj/item/serviette(src)
+ new /obj/item/serviette(src)
+
+/obj/item/serviette
+ name = "serviette"
+ desc = "To clean all the mess. Comes with a custom combined design of red and blue."
+ icon_state = "napkin_unused"
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ /// How much time it takes to clean something using it
+ var/cleanspeed = 5 SECONDS
+ /// Which item spawns after it's used
+ var/used_serviette = /obj/item/serviette_used
+ w_class = WEIGHT_CLASS_TINY
+ item_flags = NOBLUDGEON
+
+/obj/item/serviette_used
+ name = "dirty napkin"
+ desc = "No longer useful, super dirty, or soaked, or otherwise unrecognisable."
+ icon_state = "napkin_used"
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+
+/obj/item/storage/box/colonial_rations
+ name = "foreign colonization ration"
+ desc = "A freshly printed civilian MRE, or more specifically a lunchtime food package, for use in the early colonization times by the first settlers of what is now known as the NRI.
\
+ The lack of any imprinted dates, as well as its origin, the food replicator, should probably give you a good enough hint at its short, if reasonable, expiry time."
+ icon = 'modular_doppler/food_replicator/icons/rationpack.dmi'
+ icon_state = "mre_package"
+ foldable_result = null
+ illustration = null
+
+/obj/item/storage/box/colonial_rations/Initialize(mapload)
+ . = ..()
+ atom_storage.max_slots = 6
+ atom_storage.locked = TRUE
+
+/obj/item/storage/box/colonial_rations/attack_self(mob/user, modifiers)
+ if(user)
+ if(atom_storage.locked == TRUE)
+ atom_storage.locked = FALSE
+ icon_state = "mre_package_open"
+ balloon_alert(user, "unsealed!")
+ return ..()
+ else
+ atom_storage.locked = TRUE
+ atom_storage.close_all()
+ icon_state = "mre_package"
+ balloon_alert(user, "resealed!")
+ return
+
+/obj/item/storage/box/colonial_rations/PopulateContents()
+ new /obj/item/food/colonial_course/pljeskavica(src)
+ new /obj/item/food/colonial_course/nachos(src)
+ new /obj/item/food/colonial_course/blins(src)
+ new /obj/item/reagent_containers/cup/glass/coffee/colonial(src)
+ new /obj/item/storage/box/gum/colonial(src)
+ new /obj/item/storage/box/utensils(src)
diff --git a/modular_doppler/food_replicator/code/reagents.dm b/modular_doppler/food_replicator/code/reagents.dm
new file mode 100644
index 0000000000000..ef25e49efd3d4
--- /dev/null
+++ b/modular_doppler/food_replicator/code/reagents.dm
@@ -0,0 +1,116 @@
+/datum/reagent/consumable/powdered_tea
+ name = "Powdered Tea"
+ description = "Tea in its powdered form. Tastes horribly."
+ color = "#3a3a03"
+ nutriment_factor = 0
+ taste_description = "bitter powder"
+ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ default_container = /obj/item/reagent_containers/cup/glass/mug/tea
+
+/datum/chemical_reaction/food/unpowdered_tea
+ required_reagents = list(
+ /datum/reagent/water = 1,
+ /datum/reagent/consumable/powdered_tea = 1,
+ )
+ results = list(/datum/reagent/consumable/tea = 2)
+ mix_message = "The mixture instantly heats up."
+ reaction_flags = REACTION_INSTANT
+
+/datum/reagent/consumable/powdered_coffee
+ name = "Powdered Coffee"
+ description = "Americano in its powdered form. Quite an ordinary thing to be honest."
+ color = "#101000"
+ nutriment_factor = 0
+ taste_description = "very bitter powder"
+ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ default_container = /obj/item/reagent_containers/cup/glass/coffee
+
+/datum/chemical_reaction/food/unpowdered_coffee
+ required_reagents = list(
+ /datum/reagent/water = 1,
+ /datum/reagent/consumable/powdered_coffee = 1,
+ )
+ results = list(/datum/reagent/consumable/coffee = 2)
+ mix_message = "The mixture instantly heats up."
+ reaction_flags = REACTION_INSTANT
+
+/datum/reagent/consumable/powdered_coco
+ name = "Powdered Coco"
+ description = "Made with love (citation needed), and reclaimed biomass."
+ nutriment_factor = 0
+ color = "#403010"
+ taste_description = "dry chocolate"
+ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ default_container = /obj/item/reagent_containers/cup/glass/mug/coco
+
+/datum/chemical_reaction/food/unpowdered_coco
+ required_reagents = list(
+ /datum/reagent/consumable/milk = 1,
+ /datum/reagent/consumable/powdered_coco = 1,
+ )
+ results = list(/datum/reagent/consumable/hot_coco = 2)
+ mix_message = "The mixture instantly heats up."
+ reaction_flags = REACTION_INSTANT
+
+/datum/reagent/consumable/powdered_lemonade
+ name = "Powdered Lemonade"
+ description = "Sweet, tangy base of a lemonade. Would be good if you'd mix it with water."
+ nutriment_factor = 0
+ color = "#FFE978"
+ taste_description = "intensely sour and sweet lemon powder"
+ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ default_container = /obj/item/reagent_containers/cup/soda_cans/lemon_lime
+
+/datum/chemical_reaction/food/unpowdered_lemonade
+ required_reagents = list(
+ /datum/reagent/water = 1,
+ /datum/reagent/consumable/powdered_lemonade = 1,
+ )
+ results = list(/datum/reagent/consumable/lemonade = 2)
+ mix_message = "The mixture instantly cools down."
+ reaction_flags = REACTION_INSTANT
+
+/datum/reagent/consumable/powdered_milk
+ name = "Powdered Milk"
+ description = "An opaque white powder produced by the biomass restructurizers of certain machines."
+ nutriment_factor = 0
+ color = "#DFDFDF"
+ taste_description = "sweet dry milk"
+ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ default_container = /obj/item/reagent_containers/condiment/milk
+
+/datum/chemical_reaction/food/unpowdered_milk
+ required_reagents = list(
+ /datum/reagent/water = 1,
+ /datum/reagent/consumable/powdered_milk = 1,
+ )
+ results = list(/datum/reagent/consumable/milk = 2)
+ mix_message = "The mixture cools down."
+ reaction_flags = REACTION_INSTANT
+
+/obj/item/reagent_containers/pill/convermol
+ name = "convermol pill"
+ desc = "Used to treat oxygen deprivation. Intoxicates the body."
+ icon_state = "pill16"
+ list_reagents = list(/datum/reagent/medicine/c2/convermol = 15)
+ rename_with_volume = TRUE
+
+/datum/reagent/consumable/nutriment/glucose
+ name = "Synthetic Glucose"
+ description = "A sticky yellow liquid, simple carbohydrate, allotrope of organic glucose. Gives your body a short-term energy boost."
+ nutriment_factor = 1
+ color = "#f3d00d"
+ taste_description = "strong sweetness"
+ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ var/delayed_satiety_drain = 30
+
+/datum/reagent/consumable/nutriment/glucose/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
+ if(affected_mob.satiety < MAX_SATIETY)
+ affected_mob.adjust_nutrition(15)
+ delayed_satiety_drain += 15
+
+ return ..()
+
+/datum/reagent/consumable/nutriment/glucose/on_mob_delete(mob/living/carbon/detoxed_mob)
+ detoxed_mob.adjust_nutrition(-delayed_satiety_drain)
+ return ..()
diff --git a/modular_doppler/food_replicator/code/replicator.dm b/modular_doppler/food_replicator/code/replicator.dm
new file mode 100644
index 0000000000000..cb80ddba459ac
--- /dev/null
+++ b/modular_doppler/food_replicator/code/replicator.dm
@@ -0,0 +1,23 @@
+#define RND_CATEGORY_COLONIAL_FOOD "Provision"
+#define RND_CATEGORY_COLONIAL_MEDICAL "Medicine"
+#define RND_CATEGORY_COLONIAL_CLOTHING "Apparel"
+
+/obj/machinery/biogenerator/food_replicator
+ name = "\improper Type 34 'Colonial Supply Core'"
+ desc = "The Type 34 'Colonial Supply Core,' colloquially known as the 'Gencrate/CSC' is an ancient, boxy design first put in use by the pioneer colonists of what's now known \
+ as the NRI. The Gencrate is at its core a matter resequencer, a highly specialized subtype of biogenerator which performs a sort of transmutation using organic \
+ compounds; normally from large-scale crops or waste product. With sufficient supply, the machine is capable of making a wide variety of provisions, \
+ from clothes to food to first-aid medical supplies."
+ icon = 'modular_doppler/food_replicator/icons/biogenerator.dmi'
+ circuit = /obj/item/circuitboard/machine/biogenerator/food_replicator
+ efficiency = 0.75
+ productivity = 0.75
+ show_categories = list(
+ RND_CATEGORY_COLONIAL_FOOD,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ RND_CATEGORY_COLONIAL_CLOTHING,
+ )
+
+/obj/item/circuitboard/machine/biogenerator/food_replicator
+ name = "Colonial Supply Core"
+ build_path = /obj/machinery/biogenerator/food_replicator
diff --git a/modular_doppler/food_replicator/code/replicator_designs/replicator_clothing.dm b/modular_doppler/food_replicator/code/replicator_designs/replicator_clothing.dm
new file mode 100644
index 0000000000000..06e8e2ce22637
--- /dev/null
+++ b/modular_doppler/food_replicator/code/replicator_designs/replicator_clothing.dm
@@ -0,0 +1,54 @@
+/datum/design/colonial_under
+ name = "Colonial Uniform"
+ id = "slavic_under"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 200)
+ build_path = /obj/item/clothing/under/colonial
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_CLOTHING,
+ )
+
+/datum/design/colonial_boots
+ name = "Colonial Half-Boots"
+ id = "slavic_boots"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/clothing/shoes/jackboots/colonial
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_CLOTHING,
+ )
+
+/datum/design/colonial_cloak
+ name = "Colonial Cloak"
+ id = "slavic_cloak"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 250)
+ build_path = /obj/item/clothing/neck/cloak/colonial
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_CLOTHING,
+ )
+
+/datum/design/cool_hat
+ name = "Colonial Cap"
+ id = "slavic_cap"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/clothing/head/hats/colonial
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_CLOTHING,
+ )
+
+/datum/design/cool_gloves
+ name = "Black Gloves"
+ id = "slavic_gloves"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/clothing/gloves/color/black
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_CLOTHING,
+ )
diff --git a/modular_doppler/food_replicator/code/replicator_designs/replicator_food.dm b/modular_doppler/food_replicator/code/replicator_designs/replicator_food.dm
new file mode 100644
index 0000000000000..5e2d0328eb175
--- /dev/null
+++ b/modular_doppler/food_replicator/code/replicator_designs/replicator_food.dm
@@ -0,0 +1,165 @@
+/datum/design/ration
+ name = "Foreign Colonization Ration"
+ id = "slavic_mre"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 550)
+ build_path = /obj/item/storage/box/colonial_rations
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/pljeskavica
+ name = "Foreign Colonization Ration, Main Course"
+ id = "slavic_burger"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 200)
+ build_path = /obj/item/food/colonial_course/pljeskavica
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/nachos
+ name = "Foreign Colonization Ration, Side Dish"
+ id = "mexican_chips"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/food/colonial_course/nachos
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/blins
+ name = "Foreign Colonization Ration, Dessert"
+ id = "slavic_crepes"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/food/colonial_course/blins
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+///Despite being in the medical.dm file, it's still used to fill your hunger up, as such, technically, is food.
+/datum/design/glucose
+ name = "EVA Glucose Injector"
+ id = "slavic_glupen"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/reagent_containers/hypospray/medipen/glucose
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/spork
+ name = "Foreign Colonization Ration, Utensils"
+ id = "slavic_utens"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 75)
+ build_path = /obj/item/storage/box/utensils
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/bubblegum
+ name = "Foreign Colonization Ration, Bubblegum Pack"
+ id = "slavic_gum"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/storage/box/gum/colonial
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/cup
+ name = "Empty Paper Cup"
+ id = "slavic_cup"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 10)
+ build_path = /obj/item/reagent_containers/cup/glass/coffee/colonial/empty
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/tea
+ name = "Powdered Black Tea"
+ id = "slavic_tea"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 4)
+ make_reagent = /datum/reagent/consumable/powdered_tea
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/coffee
+ name = "Powdered Coffee"
+ id = "slavic_coffee"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 4)
+ make_reagent = /datum/reagent/consumable/powdered_coffee
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/cocoa
+ name = "Powdered Hot Chocolate"
+ id = "slavic_coco"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 4)
+ make_reagent = /datum/reagent/consumable/powdered_coco
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/lemonade
+ name = "Powdered Lemonade"
+ id = "slavic_lemon"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 4)
+ make_reagent = /datum/reagent/consumable/powdered_lemonade
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/replicator_sugar
+ name = "Sugar"
+ id = "slavic_sugar"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 5)
+ make_reagent = /datum/reagent/consumable/sugar
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/powdered_milk
+ name = "Powdered Milk"
+ id = "slavic_milk"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 4)
+ make_reagent = /datum/reagent/consumable/powdered_milk
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
+
+/datum/design/water
+ name = "Water"
+ id = "slavic_water"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 1)
+ make_reagent = /datum/reagent/water
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_FOOD,
+ )
diff --git a/modular_doppler/food_replicator/code/replicator_designs/replicator_medical.dm b/modular_doppler/food_replicator/code/replicator_designs/replicator_medical.dm
new file mode 100644
index 0000000000000..473d5558c7095
--- /dev/null
+++ b/modular_doppler/food_replicator/code/replicator_designs/replicator_medical.dm
@@ -0,0 +1,113 @@
+/datum/design/pocket_medkit
+ name = "Empty Pocket First Aid Kit"
+ id = "slavic_cfap"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 250)
+ build_path = /obj/item/storage/pouch/cin_medkit
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/medipouch
+ name = "Empty Medipen Pouch"
+ id = "slavic_medipouch"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 250)
+ build_path = /obj/item/storage/pouch/cin_medipens
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/sutures
+ name = "Hemostatic Sutures"
+ id = "slavic_suture"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/stack/medical/suture/bloody
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/mesh
+ name = "Hemostatic Mesh"
+ id = "slavic_mesh"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/stack/medical/mesh/bloody
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/bruise_patch
+ name = "Bruise Patch"
+ id = "slavic_bruise"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 250)
+ build_path = /obj/item/reagent_containers/pill/patch/libital
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/burn_patch
+ name = "Burn Patch"
+ id = "slavic_burn"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 250)
+ build_path = /obj/item/reagent_containers/pill/patch/aiuri
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/gauze
+ name = "Medical Gauze"
+ id = "slavic_gauze"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/stack/medical/gauze
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/epi_pill
+ name = "Epinephrine Pill"
+ id = "slavic_epi"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 75)
+ build_path = /obj/item/reagent_containers/pill/epinephrine
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/conv_pill
+ name = "Convermol Pill"
+ id = "slavic_conv"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 75)
+ build_path = /obj/item/reagent_containers/pill/convermol
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+/datum/design/multiver_pill
+ name = "Multiver Pill"
+ id = "slavic_multiver"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 75)
+ build_path = /obj/item/reagent_containers/pill/multiver
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_COLONIAL_MEDICAL,
+ )
+
+#undef RND_CATEGORY_COLONIAL_FOOD
+#undef RND_CATEGORY_COLONIAL_MEDICAL
+#undef RND_CATEGORY_COLONIAL_CLOTHING
diff --git a/modular_doppler/food_replicator/code/storage.dm b/modular_doppler/food_replicator/code/storage.dm
new file mode 100644
index 0000000000000..457114789b364
--- /dev/null
+++ b/modular_doppler/food_replicator/code/storage.dm
@@ -0,0 +1,35 @@
+/obj/item/storage/pouch/cin_medipens
+ name = "colonial medipen pouch"
+ desc = "A pouch for your (medi-)pens that goes in your pocket."
+ icon = 'modular_doppler/food_replicator/icons/pouch.dmi'
+ icon_state = "medipen_pouch"
+ w_class = WEIGHT_CLASS_NORMAL
+
+/obj/item/storage/pouch/cin_medipens/update_icon_state()
+ icon_state = "[initial(icon_state)]_[contents.len]"
+ return ..()
+
+/obj/item/storage/pouch/cin_medipens/Initialize(mapload)
+ . = ..()
+ update_appearance()
+
+/obj/item/storage/pouch/cin_medipens/Initialize(mapload)
+ . = ..()
+ atom_storage.max_specific_storage = WEIGHT_CLASS_TINY
+ atom_storage.max_total_storage = 4
+ atom_storage.max_slots = 4
+ atom_storage.can_hold = typecacheof(list(/obj/item/reagent_containers/hypospray/medipen, /obj/item/pen, /obj/item/flashlight/pen))
+
+/obj/item/storage/pouch/cin_medkit
+ name = "colonial first aid kit"
+ desc = "A medical case that goes in your pocket. Can be used to store things unrelated to medicine, except for guns, ammo and raw materials."
+ icon = 'modular_doppler/food_replicator/icons/pouch.dmi'
+ icon_state = "cfak"
+ w_class = WEIGHT_CLASS_NORMAL
+
+/obj/item/storage/pouch/cin_medkit/Initialize(mapload)
+ . = ..()
+ atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
+ atom_storage.max_total_storage = 8
+ atom_storage.max_slots = 4
+ atom_storage.cant_hold = typecacheof(list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/stack/sheet))
diff --git a/modular_doppler/food_replicator/icons/biogenerator.dmi b/modular_doppler/food_replicator/icons/biogenerator.dmi
new file mode 100644
index 0000000000000..98ead8bd6bcf4
Binary files /dev/null and b/modular_doppler/food_replicator/icons/biogenerator.dmi differ
diff --git a/modular_doppler/food_replicator/icons/clothing.dmi b/modular_doppler/food_replicator/icons/clothing.dmi
new file mode 100644
index 0000000000000..87b63178b5d32
Binary files /dev/null and b/modular_doppler/food_replicator/icons/clothing.dmi differ
diff --git a/modular_doppler/food_replicator/icons/clothing_digi.dmi b/modular_doppler/food_replicator/icons/clothing_digi.dmi
new file mode 100644
index 0000000000000..baec8fc7b5dd7
Binary files /dev/null and b/modular_doppler/food_replicator/icons/clothing_digi.dmi differ
diff --git a/modular_doppler/food_replicator/icons/clothing_worn.dmi b/modular_doppler/food_replicator/icons/clothing_worn.dmi
new file mode 100644
index 0000000000000..35b4f4b497c47
Binary files /dev/null and b/modular_doppler/food_replicator/icons/clothing_worn.dmi differ
diff --git a/modular_doppler/food_replicator/icons/medicine.dmi b/modular_doppler/food_replicator/icons/medicine.dmi
new file mode 100644
index 0000000000000..38cbffbcf130d
Binary files /dev/null and b/modular_doppler/food_replicator/icons/medicine.dmi differ
diff --git a/modular_doppler/food_replicator/icons/pouch.dmi b/modular_doppler/food_replicator/icons/pouch.dmi
new file mode 100644
index 0000000000000..9756206d0dffb
Binary files /dev/null and b/modular_doppler/food_replicator/icons/pouch.dmi differ
diff --git a/modular_doppler/food_replicator/icons/rationpack.dmi b/modular_doppler/food_replicator/icons/rationpack.dmi
new file mode 100644
index 0000000000000..c0422ef3ca076
Binary files /dev/null and b/modular_doppler/food_replicator/icons/rationpack.dmi differ
diff --git a/modular_doppler/kahraman_equipment/code/clothing/armor_datums.dm b/modular_doppler/kahraman_equipment/code/clothing/armor_datums.dm
new file mode 100644
index 0000000000000..aa887a848c30d
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/clothing/armor_datums.dm
@@ -0,0 +1,30 @@
+/datum/armor/colonist_clothing
+ laser = ARMOR_LEVEL_TINY
+ energy = ARMOR_LEVEL_TINY
+ bomb = ARMOR_LEVEL_TINY
+ bio = ARMOR_LEVEL_TINY
+ fire = ARMOR_LEVEL_WEAK
+ acid = ARMOR_LEVEL_TINY
+ wound = WOUND_ARMOR_WEAK
+
+/datum/armor/colonist_armor
+ melee = ARMOR_LEVEL_WEAK
+ bullet = ARMOR_LEVEL_WEAK
+ laser = ARMOR_LEVEL_TINY
+ energy = ARMOR_LEVEL_TINY
+ bomb = ARMOR_LEVEL_TINY
+ bio = ARMOR_LEVEL_TINY
+ fire = ARMOR_LEVEL_WEAK
+ acid = ARMOR_LEVEL_TINY
+ wound = WOUND_ARMOR_STANDARD
+
+/datum/armor/colonist_hazard
+ melee = ARMOR_LEVEL_TINY
+ bullet = ARMOR_LEVEL_TINY
+ laser = ARMOR_LEVEL_WEAK
+ energy = ARMOR_LEVEL_WEAK
+ bomb = ARMOR_LEVEL_MID
+ bio = 100
+ fire = 100
+ acid = ARMOR_LEVEL_MID
+ wound = WOUND_ARMOR_WEAK
diff --git a/modular_doppler/kahraman_equipment/code/clothing/clothing.dm b/modular_doppler/kahraman_equipment/code/clothing/clothing.dm
new file mode 100644
index 0000000000000..29faaad856cbf
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/clothing/clothing.dm
@@ -0,0 +1,205 @@
+// Jumpsuit
+
+/obj/item/clothing/under/frontier_colonist
+ name = "frontier jumpsuit"
+ desc = "A heavy grey jumpsuit with extra padding around the joints. Two massive pockets included. \
+ No matter what you do to adjust it, it's always just slightly too large."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "jumpsuit"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ supported_bodyshapes = list(BODYSHAPE_HUMANOID, BODYSHAPE_DIGITIGRADE)
+ bodyshape_icon_files = list(BODYSHAPE_HUMANOID_T = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi',
+ BODYSHAPE_DIGITIGRADE_T = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi')
+ worn_icon_state = "jumpsuit"
+ sensor_mode = SENSOR_COORDS
+ random_sensor = FALSE
+
+/obj/item/clothing/under/frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+// Boots
+
+/obj/item/clothing/shoes/jackboots/frontier_colonist
+ name = "heavy frontier boots"
+ desc = "A well built pair of tall boots usually seen on the feet of explorers, first wave colonists, \
+ and LARPers across the galaxy."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "boots"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ supported_bodyshapes = list(BODYSHAPE_HUMANOID, BODYSHAPE_DIGITIGRADE)
+ bodyshape_icon_files = list(BODYSHAPE_HUMANOID_T = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi',
+ BODYSHAPE_DIGITIGRADE_T = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi')
+ worn_icon_state = "boots"
+ armor_type = /datum/armor/colonist_clothing
+ resistance_flags = NONE
+
+/obj/item/clothing/shoes/jackboots/frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+// Jackets
+
+/obj/item/clothing/suit/jacket/frontier_colonist
+ name = "frontier trenchcoat"
+ desc = "A knee length coat with a water-resistant exterior and relatively comfortable interior. \
+ In between? Just enough protective material to stop the odd sharp thing getting through, \
+ though don't expect miracles."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "jacket"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ worn_icon_state = "jacket"
+ slot_flags = ITEM_SLOT_OCLOTHING|ITEM_SLOT_NECK
+ armor_type = /datum/armor/colonist_clothing
+ resistance_flags = NONE
+ allowed = null
+
+/obj/item/clothing/suit/jacket/frontier_colonist/Initialize(mapload)
+ . = ..()
+ allowed += GLOB.colonist_suit_allowed
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+/obj/item/clothing/suit/jacket/frontier_colonist/short
+ name = "frontier jacket"
+ desc = "A short coat with a water-resistant exterior and relatively comfortable interior. \
+ In between? Just enough protective material to stop the odd sharp thing getting through, \
+ though don't expect miracles."
+ icon_state = "jacket_short"
+ worn_icon_state = "jacket_short"
+
+/obj/item/clothing/suit/jacket/frontier_colonist/medical
+ name = "frontier medical jacket"
+ desc = "A short coat with a water-resistant exterior and relatively comfortable interior. \
+ In between? Just enough protective material to stop the odd sharp thing getting through, \
+ though don't expect miracles. This one is colored a bright red and covered in white \
+ stripes to denote that someone wearing it might be able to provide medical assistance."
+ icon_state = "jacket_med"
+ worn_icon_state = "jacket_med"
+
+// Flak Jacket
+
+/obj/item/clothing/suit/frontier_colonist_flak
+ name = "frontier flak jacket"
+ desc = "A simple flak jacket with an exterior of water-resistant material. \
+ Jackets like these are often found on first wave colonists that want some armor \
+ due to the fact they can be made easily within a colony core type machine."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "flak"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ worn_icon_state = "flak"
+ body_parts_covered = CHEST
+ cold_protection = CHEST|GROIN
+ min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
+ heat_protection = CHEST|GROIN
+ max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
+ armor_type = /datum/armor/colonist_armor
+ resistance_flags = NONE
+ allowed = null
+
+/obj/item/clothing/suit/frontier_colonist_flak/Initialize(mapload)
+ . = ..()
+ allowed += GLOB.colonist_suit_allowed
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+// Various softcaps
+
+/obj/item/clothing/head/soft/frontier_colonist
+ name = "frontier cap"
+ desc = "It's a robust baseball hat in a rugged green color."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "cap"
+ soft_type = "cap"
+ soft_suffix = null
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ worn_icon_state = "cap"
+
+/obj/item/clothing/head/soft/frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+/obj/item/clothing/head/soft/frontier_colonist/medic
+ name = "frontier medical cap"
+ desc = "It's a robust baseball hat in a stylish red color. Has a white diamond to denote that its wearer might be able to provide medical assistance."
+ icon_state = "cap_medical"
+ soft_type = "cap_medical"
+ worn_icon_state = "cap_medical"
+
+// Helmet (Is it a helmet? Questionable? I'm not sure what to call this thing)
+
+/obj/item/clothing/head/frontier_colonist_helmet
+ name = "frontier soft helmet"
+ desc = "A unusual piece of headwear somewhere between a proper helmet and a normal cap."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "tanker"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ worn_icon_state = "tanker"
+ armor_type = /datum/armor/colonist_armor
+ resistance_flags = NONE
+ flags_inv = 0
+ clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT
+
+/obj/item/clothing/head/frontier_colonist_helmet/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+// Headset
+
+/obj/item/radio/headset/headset_frontier_colonist
+ name = "frontier radio headset"
+ desc = "A bulky headset that should hopefully survive exposure to the elements better than station headsets might. \
+ Has a built-in antenna allowing the headset to work independently of a communications network."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "radio"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ worn_icon_state = "radio"
+ alternate_worn_layer = FACEMASK_LAYER + 0.5
+ subspace_transmission = FALSE
+// radio_talk_sound = 'modular_doppler/kahraman_equipment/sounds/morse_signal.wav'
+
+/obj/item/radio/headset/headset_frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+// Gloves
+
+/obj/item/clothing/gloves/frontier_colonist
+ name = "frontier gloves"
+ desc = "A sturdy pair of black gloves that'll keep your precious fingers protected from the outside world. \
+ They go a bit higher up the arm than most gloves should, and you aren't quite sure why."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "gloves"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ worn_icon_state = "gloves"
+ greyscale_colors = "#3a373e"
+ siemens_coefficient = 0.25 // Doesn't insulate you entirely, but makes you a little more resistant
+ cold_protection = HANDS
+ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
+ heat_protection = HANDS
+ max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
+ resistance_flags = NONE
+ clothing_traits = list(TRAIT_QUICK_CARRY)
+
+/obj/item/clothing/gloves/frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+// Special mask
+
+/obj/item/clothing/mask/gas/atmos/frontier_colonist
+ name = "frontier gas mask"
+ desc = "An improved gas mask commonly seen in places where the atmosphere is less than breathable, \
+ but otherwise more or less habitable. It's certified to protect against most biological hazards \
+ to boot."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "mask"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ supported_bodyshapes = list(BODYSHAPE_HUMANOID, BODYSHAPE_SNOUTED)
+ bodyshape_icon_files = list(BODYSHAPE_HUMANOID_T = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi',
+ BODYSHAPE_SNOUTED_T = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi')
+ worn_icon_state = "mask"
+ flags_inv = HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT
+ armor_type = /datum/armor/colonist_hazard
+
+/obj/item/clothing/mask/gas/atmos/frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
diff --git a/modular_doppler/kahraman_equipment/code/clothing/mod.dm b/modular_doppler/kahraman_equipment/code/clothing/mod.dm
new file mode 100644
index 0000000000000..a9f77adcd2baa
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/clothing/mod.dm
@@ -0,0 +1,113 @@
+// It's modsuiting time
+
+/datum/mod_theme/frontier_colonist
+ name = "frontier hazard protective"
+ desc = "An unusual design of suit, in reality being no more than a slim underlayer with a built in coat and sealed helmet."
+ extended_desc = "The pinnacle of frontier cheap technology. Suits like this are usually not unified in design \
+ though are common in frontier settlements with less than optimal infrastructure. As with most unofficial \
+ designs, there are flaws and no single one is perfect, but they achieve a singular goal and that is the \
+ important part. Suits such as these are made specifically for the rare emergency that creates a hazard \
+ environment that other equipment just can't quite handle. Often, these suits are able to protect their users \
+ from not only electricity, but also radiation, biological hazards, other people, so on. This suit will not, \
+ however, protect you from yourself."
+
+ default_skin = "colonist"
+ armor_type = /datum/armor/colonist_hazard
+ resistance_flags = FIRE_PROOF
+ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
+ siemens_coefficient = 0
+ complexity_max = DEFAULT_MAX_COMPLEXITY - 7
+ charge_drain = DEFAULT_CHARGE_DRAIN * 2
+ slowdown_inactive = 1.5
+ slowdown_active = 1
+ inbuilt_modules = list(
+ /obj/item/mod/module/plate_compression/permanent,
+ /obj/item/mod/module/joint_torsion/permanent
+ )
+ allowed_suit_storage = list(
+ /obj/item/ammo_box,
+ /obj/item/ammo_casing,
+ /obj/item/flashlight,
+ /obj/item/gun,
+ /obj/item/melee,
+ /obj/item/tank/internals,
+ /obj/item/storage/belt/holster,
+ /obj/item/construction,
+ /obj/item/fireaxe,
+ /obj/item/pipe_dispenser,
+ /obj/item/storage/bag,
+ /obj/item/pickaxe,
+ /obj/item/resonator,
+ /obj/item/t_scanner,
+ /obj/item/analyzer,
+ /obj/item/storage/medkit,
+ )
+ variants = list(
+ "colonist" = list(
+ MOD_ICON_OVERRIDE = 'modular_doppler/kahraman_equipment/icons/modsuits/mod.dmi',
+ MOD_WORN_ICON_OVERRIDE = 'modular_doppler/kahraman_equipment/icons/modsuits/mod_worn.dmi',
+ /obj/item/clothing/head/mod = list(
+ UNSEALED_LAYER = null,
+ UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
+ UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
+ UNSEALED_MESSAGE = HELMET_UNSEAL_MESSAGE,
+ SEALED_MESSAGE = HELMET_SEAL_MESSAGE,
+ ),
+ /obj/item/clothing/suit/mod = list(
+ UNSEALED_CLOTHING = THICKMATERIAL,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ SEALED_INVISIBILITY = HIDEJUMPSUIT,
+ UNSEALED_MESSAGE = CHESTPLATE_UNSEAL_MESSAGE,
+ SEALED_MESSAGE = CHESTPLATE_SEAL_MESSAGE,
+ ),
+ /obj/item/clothing/gloves/mod = list(
+ UNSEALED_CLOTHING = THICKMATERIAL,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ CAN_OVERSLOT = TRUE,
+ UNSEALED_MESSAGE = GAUNTLET_UNSEAL_MESSAGE,
+ SEALED_MESSAGE = GAUNTLET_SEAL_MESSAGE,
+ ),
+ /obj/item/clothing/shoes/mod = list(
+ UNSEALED_CLOTHING = THICKMATERIAL,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ CAN_OVERSLOT = TRUE,
+ UNSEALED_MESSAGE = BOOT_UNSEAL_MESSAGE,
+ SEALED_MESSAGE = BOOT_SEAL_MESSAGE,
+ ),
+ ),
+ )
+
+/obj/item/mod/control/pre_equipped/frontier_colonist
+ theme = /datum/mod_theme/frontier_colonist
+ applied_cell = /obj/item/stock_parts/power_store/cell/high
+ applied_modules = list(
+ /obj/item/mod/module/welding,
+ /obj/item/mod/module/magboot,
+ /obj/item/mod/module/flashlight,
+ /obj/item/mod/module/status_readout,
+ /obj/item/mod/module/thermal_regulator,
+ /obj/item/mod/module/rad_protection,
+ )
+ default_pins = list(
+ /obj/item/mod/module/magboot,
+ /obj/item/mod/module/flashlight,
+ /obj/item/mod/module/thermal_regulator,
+ )
+
+/obj/item/mod/control/pre_equipped/frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+// Plate compression module that cannot be removed
+
+/obj/item/mod/module/plate_compression/permanent
+ removable = FALSE
+ complexity = 0
+
+// Joint torsion module that can't be removed and has no complexity
+
+/obj/item/mod/module/joint_torsion/permanent
+ removable = FALSE
+ complexity = 0
diff --git a/modular_doppler/kahraman_equipment/code/clothing/storage.dm b/modular_doppler/kahraman_equipment/code/clothing/storage.dm
new file mode 100644
index 0000000000000..65f68b937f5c6
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/clothing/storage.dm
@@ -0,0 +1,88 @@
+// Backpacks
+
+/obj/item/storage/backpack/industrial/frontier_colonist
+ name = "frontier backpack"
+ desc = "A rugged backpack often used by settlers and explorers. Holds all of your equipment and then some."
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "backpack"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+// worn_icon_teshari = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi'
+ worn_icon_state = "backpack"
+ inhand_icon_state = "backpack"
+
+/obj/item/storage/backpack/industrial/frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+/obj/item/storage/backpack/industrial/frontier_colonist/satchel
+ name = "frontier satchel"
+ desc = "A rugged satchel often used by settlers and explorers. Holds less of your equipment than a backpack will."
+ icon_state = "satchel"
+ worn_icon_state = "satchel"
+
+/obj/item/storage/backpack/industrial/frontier_colonist/messenger
+ name = "frontier messenger bag"
+ desc = "A rugged messenger bag often used by settlers and explorers. Holds less of your equipment than a backpack will."
+ icon_state = "messenger"
+ worn_icon_state = "messenger"
+
+// Belts
+
+/obj/item/storage/belt/utility/frontier_colonist
+ name = "frontier chest rig"
+ desc = "A versatile chest rig with pockets to store really whatever you could think of within. \
+ That is, if whatever you could think of is within the realms of a utility belt. Fashion like this \
+ comes at a price you know!"
+ icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi'
+ icon_state = "harness"
+ worn_icon = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi'
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+// worn_icon_teshari = 'modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi'
+ worn_icon_state = "harness"
+ inhand_icon_state = null
+
+/obj/item/storage/belt/utility/frontier_colonist/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+ atom_storage.max_slots = 6
+ atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
+ // Can hold whatever a toolbelt can + some mining equipment for convenience
+ atom_storage.set_holdable(list(
+ /obj/item/airlock_painter,
+ /obj/item/analyzer,
+ /obj/item/assembly/signaler,
+ /obj/item/clothing/gloves,
+ /obj/item/construction,
+ /obj/item/crowbar,
+ /obj/item/extinguisher/mini,
+ /obj/item/flashlight,
+ /obj/item/forcefield_projector,
+ /obj/item/geiger_counter,
+ /obj/item/holosign_creator,
+ /obj/item/inducer,
+ /obj/item/lightreplacer,
+ /obj/item/multitool,
+ /obj/item/pipe_dispenser,
+ /obj/item/pipe_painter,
+ /obj/item/plunger,
+ /obj/item/radio,
+ /obj/item/screwdriver,
+ /obj/item/stack/cable_coil,
+ /obj/item/t_scanner,
+ /obj/item/weldingtool,
+ /obj/item/wirecutters,
+ /obj/item/wrench,
+ /obj/item/spess_knife,
+ /obj/item/gps,
+ /obj/item/knife,
+ /obj/item/mining_scanner,
+ /obj/item/pickaxe,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/shovel,
+ /obj/item/survivalcapsule,
+ /obj/item/storage/bag/ore,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/wormhole_jaunter,
+ /obj/item/resonator,
+ ))
diff --git a/modular_doppler/kahraman_equipment/code/gps_beacon.dm b/modular_doppler/kahraman_equipment/code/gps_beacon.dm
new file mode 100644
index 0000000000000..3b4d037553145
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/gps_beacon.dm
@@ -0,0 +1,23 @@
+/obj/item/gps/computer/beacon
+ name = "\improper GPS beacon"
+ desc = "A GPS beacon, anchored to the ground to prevent loss or accidental movement."
+ icon = 'modular_doppler/kahraman_equipment/icons/gps_beacon.dmi'
+ icon_state = "gps_beacon"
+ pixel_y = 0
+ /// What this is undeployed back into
+ var/undeploy_type = /obj/item/flatpacked_machine/gps_beacon
+
+/obj/item/gps/computer/beacon/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/repackable, undeploy_type, 2 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+/obj/item/flatpacked_machine/gps_beacon
+ name = "packed GPS beacon"
+ icon = 'modular_doppler/kahraman_equipment/icons/gps_beacon.dmi'
+ icon_state = "beacon_folded"
+ w_class = WEIGHT_CLASS_SMALL
+ type_to_deploy = /obj/item/gps/computer/beacon
+
+/obj/item/flatpacked_machine/gps_beacon/give_manufacturer_examine()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
diff --git a/modular_doppler/kahraman_equipment/code/looping_sounds.dm b/modular_doppler/kahraman_equipment/code/looping_sounds.dm
new file mode 100644
index 0000000000000..2eb96cd6576bb
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/looping_sounds.dm
@@ -0,0 +1,13 @@
+/datum/looping_sound/ore_thumper_fan
+ start_sound = 'modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_start.wav'
+ start_length = 3
+ mid_sounds = list(
+ 'modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_1.wav' = 1,
+ 'modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_2.wav' = 1,
+ 'modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_3.wav' = 1,
+ 'modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_4.wav' = 1,
+ )
+ mid_length = 3 SECONDS
+ end_sound = 'modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_end.wav'
+ volume = 100
+ falloff_exponent = 3
diff --git a/modular_doppler/kahraman_equipment/code/ore_thumper.dm b/modular_doppler/kahraman_equipment/code/ore_thumper.dm
new file mode 100644
index 0000000000000..8a89ab005b97e
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/ore_thumper.dm
@@ -0,0 +1,275 @@
+#define SLAM_JAM_DELAY 15 SECONDS
+
+/obj/machinery/power/colony_ore_thumper
+ name = "ore thumper"
+ desc = "A frame with a heavy block of metal suspended atop a pipe. \
+ Must be deployed outdoors and given a wired power connection. \
+ Forces pressurized gas into the ground which brings up buried resources."
+ icon = 'modular_doppler/kahraman_equipment/icons/ore_thumper.dmi'
+ icon_state = "thumper_idle"
+ density = TRUE
+ max_integrity = 250
+ idle_power_usage = 0
+ active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 50 // Should be 50 kw or an entire SOFIE generator's power production
+ anchored = TRUE
+ can_change_cable_layer = FALSE
+ circuit = null
+ layer = ABOVE_MOB_LAYER
+ /// Are we currently working?
+ var/thumping = FALSE
+ /// Our looping fan sound that we play when turned on
+ var/datum/looping_sound/ore_thumper_fan/soundloop
+ /// How many times we've slammed, counts up until the number is high enough to make a box of materials
+ var/slam_jams = 0
+ /// How many times we need to slam in order to produce a box of materials
+ var/slam_jams_needed = 30
+ /// List of the thumping sounds we can choose from
+ var/static/list/list_of_thumper_sounds = list(
+ 'modular_doppler/kahraman_equipment/sounds/thumper_thump/punch_press_1.wav',
+ 'modular_doppler/kahraman_equipment/sounds/thumper_thump/punch_press_2.wav',
+ )
+ /// Keeps track of the callback timer to make sure we don't have more than one
+ var/callback_tracker
+ /// Weighted list of the ores we can spawn
+ var/static/list/ore_weight_list = list(
+ /obj/item/stack/ore/iron = 5,
+ /obj/item/stack/ore/glass/basalt = 5,
+ /obj/item/stack/ore/plasma = 4,
+ /obj/item/stack/ore/uranium = 3,
+ /obj/item/stack/ore/silver = 3,
+ /obj/item/stack/ore/gold = 3,
+ /obj/item/stack/ore/titanium = 3,
+ /obj/item/stack/ore/diamond = 2,
+ /obj/item/stack/ore/bluespace_crystal = 1,
+ )
+ /// How much of the listed types of ores should we spawn when spawning ore
+ var/static/list/ore_spawn_values = list(
+ /obj/item/stack/ore/iron = 25,
+ /obj/item/stack/ore/glass/basalt = 25,
+ /obj/item/stack/ore/plasma = 15,
+ /obj/item/stack/ore/uranium = 10,
+ /obj/item/stack/ore/silver = 10,
+ /obj/item/stack/ore/gold = 10,
+ /obj/item/stack/ore/titanium = 10,
+ /obj/item/stack/ore/diamond = 5,
+ /obj/item/stack/ore/bluespace_crystal = 1,
+ )
+ /// What's the limit for ore near us? Counts by stacks, not individual amounts of ore
+ var/nearby_ore_limit = 5
+ /// How far away does ore spawn?
+ var/ore_spawn_range = 2
+ /// What do we undeploy into
+ var/undeploy_type = /obj/item/flatpacked_machine/ore_thumper
+
+/obj/machinery/power/colony_ore_thumper/Initialize(mapload)
+ . = ..()
+ soundloop = new(src, FALSE)
+ AddElement(/datum/element/repackable, undeploy_type, 4 SECONDS)
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+/obj/machinery/power/colony_ore_thumper/add_context(
+ atom/source,
+ list/context,
+ obj/item/held_item,
+ mob/living/user,
+)
+
+ if(isnull(held_item))
+ if(panel_open)
+ context[SCREENTIP_CONTEXT_LMB] = "Activate Thumper"
+ return CONTEXTUAL_SCREENTIP_SET
+ return NONE
+
+
+/obj/machinery/power/colony_ore_thumper/examine(mob/user)
+ . = ..()
+ var/area/thumper_area = get_area(src)
+ if(!thumper_area.outdoors)
+ . += span_notice("Its must be constructed outdoors to function.")
+ if(!istype(get_turf(src), /turf/open/misc))
+ . += span_notice("It must be constructed on suitable terrain, like ash, snow, or sand.")
+ . += span_notice("It must have a powered, wired connection running beneath it with [display_power(active_power_usage, convert = FALSE)] of excess power to function.")
+ . += span_notice("It will produce a box of materials after it has slammed [slam_jams_needed] times.")
+ . += span_notice("Currently, it has slammed [slam_jams] / [slam_jams_needed] times needed.")
+ . += span_notice("It will stop producing resources if there are too many piles of ore near it.")
+ . += span_notice("The thumper cannot work if it is too close to another thumper, needing at least [ore_spawn_range] spaces in all directions between it another thumper.")
+
+
+/obj/machinery/power/colony_ore_thumper/process()
+ var/turf/our_turf = get_turf(src)
+ var/obj/structure/cable/cable_under_us = locate() in our_turf
+ var/energy_needed = power_to_energy(active_power_usage)
+ if(!cable_under_us && powernet)
+ disconnect_from_network()
+ else if(cable_under_us && !powernet)
+ connect_to_network()
+ if(thumping)
+ if(!see_if_we_can_work(our_turf))
+ balloon_alert_to_viewers("invalid location!")
+ cut_that_out()
+ return
+ if(avail(energy_needed))
+ add_load(energy_needed)
+ else
+ balloon_alert_to_viewers("not enough power!")
+ cut_that_out()
+
+
+/// Checks the turf we are on to make sure we are outdoors and on a misc turf
+/obj/machinery/power/colony_ore_thumper/proc/see_if_we_can_work(turf/our_turf)
+ var/area/our_current_area = get_area(src)
+ if(!our_current_area.outdoors)
+ return FALSE
+ if(!istype(get_turf(src), /turf/open/misc))
+ return FALSE
+ return TRUE
+
+
+/obj/machinery/power/colony_ore_thumper/attack_hand(mob/user, list/modifiers)
+ . = ..()
+ if(.)
+ return
+
+ to_chat(user, span_notice("You toggle [src]'s power button."))
+
+ if(thumping)
+ cut_that_out(user)
+ return
+ start_her_up(user)
+
+
+/obj/machinery/power/colony_ore_thumper/attack_ai(mob/user)
+ return attack_hand(user)
+
+
+/obj/machinery/power/colony_ore_thumper/attack_robot(mob/user)
+ return attack_hand(user)
+
+
+/// Attempts turning the thumper on, failing if any of the conditions aren't met
+/obj/machinery/power/colony_ore_thumper/proc/start_her_up(mob/user)
+ var/turf/our_turf = get_turf(src)
+ var/obj/structure/cable/cable_under_us = locate() in our_turf
+ if(!cable_under_us && powernet)
+ balloon_alert(user, "not connected to wire")
+ return
+ if(!avail(active_power_usage))
+ balloon_alert(user, "not enough power")
+ return
+
+ thumping = TRUE
+ soundloop.start()
+
+ if(callback_tracker)
+ deltimer(callback_tracker)
+
+ balloon_alert(user, "thumper started")
+
+ callback_tracker = addtimer(CALLBACK(src, PROC_REF(slam_it_down)), SLAM_JAM_DELAY, TIMER_DELETE_ME | TIMER_STOPPABLE)
+
+
+/// Attempts to shut the thumper down
+/obj/machinery/power/colony_ore_thumper/proc/cut_that_out(mob/user)
+ thumping = FALSE
+ soundloop.stop()
+ if(user)
+ balloon_alert(user, "thumper stopped")
+
+
+/// Makes the machine slam down, producing a box of ore if it has been slamming long enough
+/obj/machinery/power/colony_ore_thumper/proc/slam_it_down()
+ if(!thumping)
+ return
+ var/turf/our_turf = get_turf(src)
+ if(!see_if_we_can_work(our_turf))
+ balloon_alert_to_viewers("invalid location!")
+ cut_that_out()
+ return
+ // Down we go
+ flick("thumper_slam", src)
+ playsound(src, pick(list_of_thumper_sounds), 80, TRUE)
+ if(slam_jams < (slam_jams_needed + 1))
+ slam_jams += 1
+
+ if(callback_tracker)
+ deltimer(callback_tracker)
+
+ callback_tracker = addtimer(CALLBACK(src, PROC_REF(slam_it_down)), SLAM_JAM_DELAY, TIMER_DELETE_ME | TIMER_STOPPABLE,)
+
+ // If the number of slams is less than that of what we need, then we can stop here
+ if(!(slam_jams >= slam_jams_needed))
+ return
+
+ var/nearby_ore = 0
+ var/is_there_a_thumper_too = FALSE
+ for(var/turf/nearby_turf in orange(ore_spawn_range, src))
+ for(var/ore as anything in nearby_turf.contents)
+ if(istype(ore, /obj/item/stack/ore))
+ nearby_ore += 1
+ continue
+ if(istype(ore, /obj/machinery/power/colony_ore_thumper))
+ if(ore == src)
+ continue
+ is_there_a_thumper_too = TRUE
+ break
+
+ if(nearby_ore > nearby_ore_limit)
+ balloon_alert_to_viewers("nearby ore too saturated")
+ // Makes the thumper rumble around when something's wrong
+ Shake(2, 2, 2 SECONDS)
+ return
+
+ if(is_there_a_thumper_too)
+ balloon_alert_to_viewers("too close to another thumper")
+ // Makes the thumper rumble around when something's wrong
+ Shake(2, 2, 2 SECONDS)
+ return
+
+ addtimer(CALLBACK(src, PROC_REF(make_some_ore)), 3 SECONDS, TIMER_DELETE_ME)
+
+
+/// Spawns an ore box on top of the thumper
+/obj/machinery/power/colony_ore_thumper/proc/make_some_ore()
+ var/list/nearby_valid_turfs = list()
+ for(var/turf/nearby_turf in orange(ore_spawn_range, src))
+ if(nearby_turf.is_blocked_turf(TRUE))
+ continue
+ if(!ismiscturf(nearby_turf))
+ continue
+ nearby_valid_turfs.Add(nearby_turf)
+ // Fallback in case somehow there are no valid nearby turfs
+ if(!length(nearby_valid_turfs))
+ nearby_valid_turfs.Add(get_turf(src))
+
+ for(var/iteration in 1 to rand(2, 4))
+ var/turf/target_turf = pick(nearby_valid_turfs)
+// var/obj/item/stack/new_ore = pick_weight(ore_weight_list)
+// var/obj/new_ore_pile = new new_ore(target_turf, ore_spawn_values[new_ore.type])
+ new /obj/effect/temp_visual/mook_dust(target_turf)
+// playsound(new_ore_pile, 'modular_nova/master_files/sound/effects/robot_sit.ogg', 25, TRUE) port tallborgs soon
+
+ slam_jams -= slam_jams_needed
+
+
+// Item for deploying ore thumpers
+/obj/item/flatpacked_machine/ore_thumper
+ name = "flat-packed ore thumper"
+ icon = 'modular_doppler/kahraman_equipment/icons/ore_thumper_item.dmi'
+ icon_state = "thumper_packed"
+ type_to_deploy = /obj/machinery/power/colony_ore_thumper
+ custom_materials = list(
+ /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15,
+ /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 5,
+ /datum/material/silver = SHEET_MATERIAL_AMOUNT,
+ /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+
+/obj/item/flatpacked_machine/ore_thumper/examine(mob/user)
+ . = ..()
+ . += span_notice("Its must be constructed outdoors to function.")
+ . += span_notice("It must be constructed on suitable terrain, like ash, snow, or sand.")
+ . += span_notice("It must have a powered, wired connection running beneath it to function.")
+
+/obj/item/flatpacked_machine/ore_thumper/give_manufacturer_examine()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
diff --git a/modular_doppler/kahraman_equipment/code/organic_printer.dm b/modular_doppler/kahraman_equipment/code/organic_printer.dm
new file mode 100644
index 0000000000000..eec4a6ff5ef72
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/organic_printer.dm
@@ -0,0 +1,40 @@
+/obj/machinery/biogenerator/organic_printer
+ name = "organic materials printer"
+ desc = "An advanced machine seen in frontier outposts and colonies capable of turning organic plant matter into \
+ reagents and items of use that a fabricator can't typically make. While the exact designs these machines have differs from \
+ location to location, and upon who designed them, this one should be able to at the very least provide you with \
+ some clothing, basic food supplies, and whatever else you may require."
+ icon = 'modular_doppler/kahraman_equipment/icons/biogenerator.dmi'
+ circuit = null
+ anchored = FALSE
+ efficiency = 1
+ productivity = 2
+ max_items = 35
+ show_categories = list(
+ RND_CATEGORY_AKHTER_CLOTHING,
+ RND_CATEGORY_AKHTER_EQUIPMENT,
+ RND_CATEGORY_AKHTER_RESOURCES,
+ )
+
+/obj/machinery/biogenerator/organic_printer/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
+
+/obj/machinery/biogenerator/organic_printer/RefreshParts()
+ . = ..()
+ efficiency = 1
+ productivity = 2
+ max_items = 35
+
+/obj/machinery/biogenerator/organic_printer/default_deconstruction_crowbar()
+ return
+
+// Deployable item for cargo for the organics printer
+/obj/item/flatpacked_machine/organics_printer
+ name = "organic materials printer parts kit"
+ icon = 'modular_doppler/kahraman_equipment/icons/biogenerator.dmi'
+ icon_state = "biogenerator_parts"
+ type_to_deploy = /obj/machinery/biogenerator/organic_printer
+
+/obj/item/flatpacked_machine/organics_printer/give_manufacturer_examine()
+ AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN)
diff --git a/modular_doppler/kahraman_equipment/code/organic_printer_designs/clothing.dm b/modular_doppler/kahraman_equipment/code/organic_printer_designs/clothing.dm
new file mode 100644
index 0000000000000..478dd89beb543
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/organic_printer_designs/clothing.dm
@@ -0,0 +1,132 @@
+// Jumpsuit
+
+/datum/design/frontier_jumpsuit
+ name = "Frontier Jumpsuit"
+ id = "frontier_jumpsuit"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 75)
+ build_path = /obj/item/clothing/under/frontier_colonist
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+// Boots
+
+/datum/design/frontier_boots
+ name = "Heavy Frontier Boots"
+ id = "frontier_boots"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/clothing/shoes/jackboots/frontier_colonist
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+// Gloves
+
+/datum/design/frontier_gloves
+ name = "Frontier Gloves"
+ id = "frontier_gloves"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 50)
+ build_path = /obj/item/clothing/gloves/frontier_colonist
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+// Suit items
+
+/datum/design/frontier_trench
+ name = "Frontier Trenchcoat"
+ id = "frontier_trench"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/clothing/suit/jacket/frontier_colonist
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+/datum/design/frontier_jacket
+ name = "Frontier Jacket"
+ id = "frontier_jacket"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/clothing/suit/jacket/frontier_colonist/short
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+/datum/design/frontier_med_jacket
+ name = "Frontier Medical Jacket"
+ id = "frontier_med_jacket"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 125)
+ build_path = /obj/item/clothing/suit/jacket/frontier_colonist/medical
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+/datum/design/frontier_flak
+ name = "Frontier Flak Jacket"
+ id = "frontier_flak_jacket"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/clothing/suit/frontier_colonist_flak
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+/datum/design/frontier_tanker_helmet
+ name = "Frontier Soft Helmet"
+ id = "frontier_tanker_helmet"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/clothing/head/frontier_colonist_helmet
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+// Hats
+
+/datum/design/frontier_cap
+ name = "Frontier Soft Cap"
+ id = "frontier_cap"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 75)
+ build_path = /obj/item/clothing/head/soft/frontier_colonist
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+/datum/design/frontier_cap_med
+ name = "Frontier Medical Cap"
+ id = "frontier_cap_med"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/clothing/head/soft/frontier_colonist/medic
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
+
+// That one gas mask
+
+/datum/design/frontier_mask
+ name = "Frontier Gas Mask"
+ id = "frontier_mask"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/clothing/mask/gas/atmos/frontier_colonist
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_CLOTHING,
+ )
diff --git a/modular_doppler/kahraman_equipment/code/organic_printer_designs/equipment.dm b/modular_doppler/kahraman_equipment/code/organic_printer_designs/equipment.dm
new file mode 100644
index 0000000000000..0ead8a75f6416
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/organic_printer_designs/equipment.dm
@@ -0,0 +1,80 @@
+// Belts
+
+/datum/design/frontier_chest_rig
+ name = "Frontier Chest Rig"
+ id = "frontier_chest_rig"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 150)
+ build_path = /obj/item/storage/belt/utility/frontier_colonist
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_EQUIPMENT,
+ )
+
+/datum/design/frontier_med_belt
+ name = "Satchel Medical Kit"
+ id = "frontier_med_belt"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 200)
+ build_path = /obj/item/storage/backpack/duffelbag/deforest_medkit
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_EQUIPMENT,
+ )
+
+/datum/design/frontier_medtech_belt
+ name = "Medical Technician Kit"
+ id = "frontier_medtech_belt"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 200)
+ build_path = /obj/item/storage/backpack/duffelbag/deforest_paramedic
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_EQUIPMENT,
+ )
+
+/datum/design/frontier_medkit
+ name = "Frontier Medical Kit"
+ id = "frontier_medkit"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/storage/medkit/frontier
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_EQUIPMENT,
+ )
+
+// Backpacks
+
+/datum/design/frontier_backpack
+ name = "Frontier Backpack"
+ id = "frontier_backpack"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/storage/backpack/industrial/frontier_colonist
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_EQUIPMENT,
+ )
+
+/datum/design/frontier_satchel
+ name = "Frontier Satchel"
+ id = "frontier_satchel"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/storage/backpack/industrial/frontier_colonist/satchel
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_EQUIPMENT,
+ )
+
+/datum/design/frontier_messenger
+ name = "Frontier Messenger Bag"
+ id = "frontier_messenger"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 100)
+ build_path = /obj/item/storage/backpack/industrial/frontier_colonist/messenger
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_EQUIPMENT,
+ )
diff --git a/modular_doppler/kahraman_equipment/code/organic_printer_designs/resources.dm b/modular_doppler/kahraman_equipment/code/organic_printer_designs/resources.dm
new file mode 100644
index 0000000000000..9fb685140db74
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/code/organic_printer_designs/resources.dm
@@ -0,0 +1,21 @@
+/datum/design/organic_plastic
+ name = "Plastic Sheet"
+ id = "oganic_plastic"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 25)
+ build_path = /obj/item/stack/sheet/plastic
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_RESOURCES,
+ )
+
+/datum/design/organic_cloth
+ name = "Cloth"
+ id = "oganic_cloth"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass = 10)
+ build_path = /obj/item/stack/sheet/cloth
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_AKHTER_RESOURCES,
+ )
diff --git a/modular_doppler/kahraman_equipment/icons/biogenerator.dmi b/modular_doppler/kahraman_equipment/icons/biogenerator.dmi
new file mode 100644
index 0000000000000..5fd87ee0ace0f
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/biogenerator.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi b/modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi
new file mode 100644
index 0000000000000..bb4d9cec962b1
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/clothes/clothing.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi b/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi
new file mode 100644
index 0000000000000..fa2320944460f
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi b/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi
new file mode 100644
index 0000000000000..cb954472b24c1
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi b/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi
new file mode 100644
index 0000000000000..da167942a77fb
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/gps_beacon.dmi b/modular_doppler/kahraman_equipment/icons/gps_beacon.dmi
new file mode 100644
index 0000000000000..62c9cc11fa4f1
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/gps_beacon.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/modsuits/mod.dmi b/modular_doppler/kahraman_equipment/icons/modsuits/mod.dmi
new file mode 100644
index 0000000000000..a2e6c642b189d
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/modsuits/mod.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/modsuits/mod_worn.dmi b/modular_doppler/kahraman_equipment/icons/modsuits/mod_worn.dmi
new file mode 100644
index 0000000000000..99254f654a447
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/modsuits/mod_worn.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/ore_thumper.dmi b/modular_doppler/kahraman_equipment/icons/ore_thumper.dmi
new file mode 100644
index 0000000000000..a99b196ae6767
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/ore_thumper.dmi differ
diff --git a/modular_doppler/kahraman_equipment/icons/ore_thumper_item.dmi b/modular_doppler/kahraman_equipment/icons/ore_thumper_item.dmi
new file mode 100644
index 0000000000000..7c53ff0f06a40
Binary files /dev/null and b/modular_doppler/kahraman_equipment/icons/ore_thumper_item.dmi differ
diff --git a/modular_doppler/kahraman_equipment/sounds/attributions.txt b/modular_doppler/kahraman_equipment/sounds/attributions.txt
new file mode 100644
index 0000000000000..1a5db124e4aa8
--- /dev/null
+++ b/modular_doppler/kahraman_equipment/sounds/attributions.txt
@@ -0,0 +1,7 @@
+The sounds at modular_nova/modules/colony_fabriactor_event_code/sound/thumper_fan are from https://pixabay.com/sound-effects/fan-1-6360/
+
+The sounds at modular_nova/modules/colony_fabriactor_event_code/sound/thumper_thump are from https://pixabay.com/sound-effects/punch-press-10-ton-clip1-104921/
+
+The following sounds are from https://pixabay.com/sound-effects/sos-signal-137144/
+
+modular_nova/modules/colony_fabricator/sound/morse_signal.wav
diff --git a/modular_doppler/kahraman_equipment/sounds/morse_signal.wav b/modular_doppler/kahraman_equipment/sounds/morse_signal.wav
new file mode 100644
index 0000000000000..2f0dd5682094d
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/morse_signal.wav differ
diff --git a/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_end.wav b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_end.wav
new file mode 100644
index 0000000000000..f89e8d20ff9d5
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_end.wav differ
diff --git a/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_1.wav b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_1.wav
new file mode 100644
index 0000000000000..96582d0ce32c7
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_1.wav differ
diff --git a/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_2.wav b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_2.wav
new file mode 100644
index 0000000000000..e1656ec08ef85
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_2.wav differ
diff --git a/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_3.wav b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_3.wav
new file mode 100644
index 0000000000000..7d7275b5bea11
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_3.wav differ
diff --git a/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_4.wav b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_4.wav
new file mode 100644
index 0000000000000..7298e4eddca92
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_mid_4.wav differ
diff --git a/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_start.wav b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_start.wav
new file mode 100644
index 0000000000000..c3e95ad1e8ba5
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/thumper_fan/fan_start.wav differ
diff --git a/modular_doppler/kahraman_equipment/sounds/thumper_thump/punch_press_1.wav b/modular_doppler/kahraman_equipment/sounds/thumper_thump/punch_press_1.wav
new file mode 100644
index 0000000000000..513bb1f8f1927
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/thumper_thump/punch_press_1.wav differ
diff --git a/modular_doppler/kahraman_equipment/sounds/thumper_thump/punch_press_2.wav b/modular_doppler/kahraman_equipment/sounds/thumper_thump/punch_press_2.wav
new file mode 100644
index 0000000000000..c4d259839b3e8
Binary files /dev/null and b/modular_doppler/kahraman_equipment/sounds/thumper_thump/punch_press_2.wav differ
diff --git a/modular_doppler/languages/language_datums.dm b/modular_doppler/languages/language_datums.dm
index b4ca17cd7f092..36fa9236c7780 100644
--- a/modular_doppler/languages/language_datums.dm
+++ b/modular_doppler/languages/language_datums.dm
@@ -30,6 +30,21 @@
default_name_syllable_min = 1
default_name_syllable_max = 2
+/datum/language/gutter
+ name = "Plutonian"
+ desc = "Plutonian Franco-Castilian is a constructed Romance language that was developed early on in the Sol Federation's colonization history out of necessity for communication between its first Plutonian colonists. It heavily borrows from Spanish and French, with minor influence from other tongues the likes of Italian and Portuguese, despite coming off as elegant it carries a heavy amount of slang and idioms correlated to certain criminal groups. Today, it stands heavily engrained in the planet's culture - and almost every citizen will speak at least some of it on top of Sol."
+ key = "G"
+ flags = TONGUELESS_SPEECH
+ syllables = list (
+ "bai", "cai", "jai", "quai", "vai", "dei", "lei", "quei", "sei", "noi", "quoi", "voi", "beu", "queu", "seu", "gan", "zan", "quan", "len", "ten",
+ "ba", "be", "bi", "bo", "bu", "ca", "ce", "ci", "co", "cu", "da", "de", "di", "do", "du", "fa", "fe", "fi", "fo", "fu", "ga", "gue", "gui", "go",
+ "gu", "ña", "ñe", "ñi", "ño", "ñu", "que", "qui", "cha", "che", "chi", "cho", "chu", "lla", "lle", "lli", "llo", "llu",
+ "tá", "vé", "sál", "fáb", "l'e", "seu", "deu", "meu", "vai", "ción", "tá"
+ )
+ icon_state = "gutter"
+ icon = 'modular_doppler/languages/language.dmi'
+ default_priority = 40
+
/datum/language/movespeak
name = "Move-Speak"
desc = "A primarily nonverbal language comprised of body movements, gesticulation, and sign language, with only intermittent warbles & other vocalizations. It's almost completely incomprehensible without its somatic components."
diff --git a/modular_doppler/loadout_categories/categories/belts.dm b/modular_doppler/loadout_categories/categories/belts.dm
index 6fd27013976d7..93b17176c4593 100644
--- a/modular_doppler/loadout_categories/categories/belts.dm
+++ b/modular_doppler/loadout_categories/categories/belts.dm
@@ -100,3 +100,23 @@
/datum/loadout_item/belts/mining
name = "Explorer's Webbing"
item_path = /obj/item/storage/belt/mining
+
+/datum/loadout_item/belts/boarding_rig
+ name = "Chest Rig"
+ item_path = /obj/item/storage/belt/military
+
+/datum/loadout_item/belts/deforest_med
+ name = "Satchel Med-kit"
+ item_path = /obj/item/storage/backpack/duffelbag/deforest_medkit
+
+/datum/loadout_item/belts/frontier_med
+ name = "Frontier Med-kit"
+ item_path = /obj/item/storage/medkit/frontier
+
+/datum/loadout_item/belts/deforest_paramed
+ name = "Satchel Tech-kit"
+ item_path = /obj/item/storage/backpack/duffelbag/deforest_paramedic
+
+/datum/loadout_item/belts/deforest_surgical
+ name = "Firest Responder Med-kit"
+ item_path = /obj/item/storage/backpack/duffelbag/deforest_surgical
diff --git a/modular_doppler/loadout_categories/categories/clothing.dm b/modular_doppler/loadout_categories/categories/clothing.dm
index a0b9f22f3f0c0..ee540978d497a 100644
--- a/modular_doppler/loadout_categories/categories/clothing.dm
+++ b/modular_doppler/loadout_categories/categories/clothing.dm
@@ -211,6 +211,26 @@
name = "Witch Robe"
item_path = /obj/item/clothing/suit/wizrobe/marisa/fake
+/*
+* COLONIST
+*/
+
+/datum/loadout_item/suit/frontier
+ name = "Frontier Trenchcoat"
+ item_path = /obj/item/clothing/suit/jacket/frontier_colonist
+
+/datum/loadout_item/suit/frontier_short
+ name = "Frontier Jacket"
+ item_path = /obj/item/clothing/suit/jacket/frontier_colonist/short
+
+/datum/loadout_item/suit/frontier_med
+ name = "Frontier Medical Jacket"
+ item_path = /obj/item/clothing/suit/jacket/frontier_colonist/medical
+
+/datum/loadout_item/suit/frontier_flak
+ name = "Frontier Flak Jacket"
+ item_path = /obj/item/clothing/suit/frontier_colonist_flak
+
/*
* MISC
*/
diff --git a/modular_doppler/loadout_categories/categories/ears.dm b/modular_doppler/loadout_categories/categories/ears.dm
index f86fe518b2da9..13786ca091f22 100644
--- a/modular_doppler/loadout_categories/categories/ears.dm
+++ b/modular_doppler/loadout_categories/categories/ears.dm
@@ -23,3 +23,7 @@
/datum/loadout_item/ears/earmuffs
name = "Earmuffs"
item_path = /obj/item/clothing/ears/earmuffs
+
+/datum/loadout_item/ears/frontier
+ name = "Frontier Radio"
+ item_path = /obj/item/radio/headset/headset_frontier_colonist
diff --git a/modular_doppler/loadout_categories/categories/gloves.dm b/modular_doppler/loadout_categories/categories/gloves.dm
index d3842ef96f019..3002ed0236dd5 100644
--- a/modular_doppler/loadout_categories/categories/gloves.dm
+++ b/modular_doppler/loadout_categories/categories/gloves.dm
@@ -64,6 +64,6 @@
name = "Rainbow Gloves"
item_path = /obj/item/clothing/gloves/color/rainbow
-
-
-
+/datum/loadout_item/gloves/frontier
+ name = "Frontier Gloves"
+ item_path = /obj/item/clothing/gloves/frontier_colonist
diff --git a/modular_doppler/loadout_categories/categories/heads.dm b/modular_doppler/loadout_categories/categories/heads.dm
index c1dcb43bcb29d..5b082245ad7c1 100644
--- a/modular_doppler/loadout_categories/categories/heads.dm
+++ b/modular_doppler/loadout_categories/categories/heads.dm
@@ -45,3 +45,19 @@
/datum/loadout_item/head/welding
name = "Welding Mask"
item_path = /obj/item/clothing/head/utility/welding
+
+/datum/loadout_item/head/soft_helmet
+ name = "Soft Helmet"
+ item_path = /obj/item/clothing/head/frontier_colonist_helmet
+
+/datum/loadout_item/head/frontier_cap
+ name = "Frontier Cap"
+ item_path = /obj/item/clothing/head/soft/frontier_colonist
+
+/datum/loadout_item/head/frontier_med
+ name = "Frontier Medical Cap"
+ item_path = /obj/item/clothing/head/soft/frontier_colonist/medic
+
+/datum/loadout_item/head/colonial_cap
+ name = "Colonial Cap"
+ item_path = /obj/item/clothing/head/hats/colonial
diff --git a/modular_doppler/loadout_categories/categories/masks.dm b/modular_doppler/loadout_categories/categories/masks.dm
index d17d4775becb3..ebfeb0ac16af1 100644
--- a/modular_doppler/loadout_categories/categories/masks.dm
+++ b/modular_doppler/loadout_categories/categories/masks.dm
@@ -59,3 +59,7 @@
/datum/loadout_item/mask/surgical
name = "Surgical Mask"
item_path = /obj/item/clothing/mask/surgical
+
+/datum/loadout_item/mask/frontier
+ name = "Frontier Gas Mask"
+ item_path = /obj/item/clothing/mask/gas/atmos/frontier_colonist
diff --git a/modular_doppler/loadout_categories/categories/neck.dm b/modular_doppler/loadout_categories/categories/neck.dm
new file mode 100644
index 0000000000000..f15a9ce48bf47
--- /dev/null
+++ b/modular_doppler/loadout_categories/categories/neck.dm
@@ -0,0 +1,3 @@
+/datum/loadout_item/neck/colonial_cloak
+ name = "Colonial Cloak"
+ item_path = /obj/item/clothing/neck/cloak/colonial
diff --git a/modular_doppler/loadout_categories/categories/pockets.dm b/modular_doppler/loadout_categories/categories/pockets.dm
index 3ea588abc8ea3..fe6e64ec5820e 100644
--- a/modular_doppler/loadout_categories/categories/pockets.dm
+++ b/modular_doppler/loadout_categories/categories/pockets.dm
@@ -231,3 +231,11 @@
/datum/loadout_item/pocket_items/drugs_liberty
name = "Liberty Cap Seeds"
item_path = /obj/item/seeds/liberty
+
+/*
+* MEDICAL
+*/
+
+/datum/loadout_item/pocket_items/civil_defense
+ name = "Civil Defense Med-kit"
+ item_path = /obj/item/storage/medkit/civil_defense
diff --git a/modular_doppler/loadout_categories/categories/shoes.dm b/modular_doppler/loadout_categories/categories/shoes.dm
index 7c8cdcb2d2753..75621b6b095fa 100644
--- a/modular_doppler/loadout_categories/categories/shoes.dm
+++ b/modular_doppler/loadout_categories/categories/shoes.dm
@@ -91,4 +91,10 @@
name = "Pirate Boots"
item_path = /obj/item/clothing/shoes/pirate
+/datum/loadout_item/shoes/colonial_boots
+ name = "Colonial Half-boots"
+ item_path = /obj/item/clothing/shoes/jackboots/colonial
+/datum/loadout_item/shoes/frontier_boots
+ name = "Heavy Boots"
+ item_path = /obj/item/clothing/shoes/jackboots/frontier_colonist
diff --git a/modular_doppler/modular_antagonist/code/antag_datum.dm b/modular_doppler/modular_antagonists/datums/antag_recipes.dm
similarity index 87%
rename from modular_doppler/modular_antagonist/code/antag_datum.dm
rename to modular_doppler/modular_antagonists/datums/antag_recipes.dm
index dec9482937530..138613320cc6e 100644
--- a/modular_doppler/modular_antagonist/code/antag_datum.dm
+++ b/modular_doppler/modular_antagonists/datums/antag_recipes.dm
@@ -10,4 +10,4 @@
/datum/antagonist/on_removal()
. = ..()
for(var/recipe_datum in antag_recipes)
- owner.unteach_crafting_recipe(recipe_datum)
+ owner.forget_crafting_recipe(recipe_datum)
diff --git a/modular_doppler/modular_antagonist/readme.md b/modular_doppler/modular_antagonists/datums/readme.md
similarity index 100%
rename from modular_doppler/modular_antagonist/readme.md
rename to modular_doppler/modular_antagonists/datums/readme.md
diff --git a/modular_doppler/modular_antagonists/sapper_gang/code/creditminer.dm b/modular_doppler/modular_antagonists/sapper_gang/code/creditminer.dm
new file mode 100644
index 0000000000000..e26b5899e51cd
--- /dev/null
+++ b/modular_doppler/modular_antagonists/sapper_gang/code/creditminer.dm
@@ -0,0 +1,118 @@
+#define RADIO_ALERT 80 // Precentage near explosion to begin announcing on radio
+#define POWER_FOR_PAYOUT (20 KILO WATTS) // How much do we draw for a payout
+#define PAYOUT 100 // How much is the energy worth
+#define DRAIN_FORMULA (0.1 * STANDARD_BATTERY_CHARGE) //How much % per tick gets drained from the powernet. standard cell because thats what APCs start with
+
+/obj/item/powersink/creditminer
+ name = "converted power sink"
+ desc = "A highly modified power sink, functionally the same on one exception, it transforms the power into minted holo credit - still gets extremely hot while working; keep the temperature in check or suffer the explosive consequence."
+ w_class = WEIGHT_CLASS_HUGE
+ max_heat = 150 * STANDARD_BATTERY_CHARGE // 1.5x the heat of its parent type, can last a long time unless the station is running a God engine
+ /// The amount of power the machine has converted to credits.
+ var/cash_out = 0
+ ///The machine's internal radio, used to broadcast alerts.
+ var/obj/item/radio/radio
+ ///The key our internal radio uses
+ var/radio_key = /obj/item/encryptionkey/syndicate
+ ///The channel we announce over.
+ var/radio_channel = RADIO_CHANNEL_SYNDICATE
+ ///Amount of time before the next warning over the radio is announced.
+ var/next_warning = 0
+ ///The amount of time we have between warnings
+ var/minimum_time_between_warnings = 15 SECONDS
+
+/obj/item/powersink/creditminer/Initialize(mapload)
+ . = ..()
+ radio = new(src)
+ radio.keyslot = new radio_key
+ radio.set_listening(FALSE)
+ radio.recalculateChannels()
+
+/obj/item/powersink/creditminer/examine(mob/user)
+ . = ..()
+ if(cash_out)
+ . += span_blue("[src] has mined [trunc(cash_out)] credits.")
+ if(mode) //can only print when in structure mode, not object mode
+ . += span_blue("Ctrl-click to print a holochip.")
+
+/obj/item/powersink/creditminer/item_ctrl_click(mob/user)
+ . = ..()
+ if(!mode) // Unwrenched
+ return CLICK_ACTION_BLOCKING
+ print()
+ return CLICK_ACTION_SUCCESS
+
+/obj/item/powersink/creditminer/attack_hand(mob/user, list/modifiers)
+ . = ..()
+ switch(mode)
+ if(1) //On turning off
+ playsound(src, 'modular_doppler/modular_antagonists/sapper_gang/sounds/creditminer_stop.wav', 50, FALSE)
+
+ if(2) //On turning on
+ playsound(src, 'modular_doppler/modular_antagonists/sapper_gang/sounds/creditminer_start.wav', 50, FALSE)
+
+/obj/item/powersink/creditminer/process()
+ . = ..()
+ if(internal_heat > max_heat * RADIO_ALERT / 100)
+ if(next_warning < world.time && prob(15))
+ var/area/hazardous_area = get_area(loc)
+ var/message = "OVERHEAT IMMINENT at [initial(hazardous_area.name)]!!"
+ radio.talk_into(src, message, radio_channel)
+ next_warning = world.time + minimum_time_between_warnings
+
+/obj/item/powersink/creditminer/proc/print()
+ if(cash_out > 0)
+ playsound(src, 'sound/items/poster_being_created.ogg', 100, TRUE)
+ balloon_alert_to_viewers("printed [trunc(cash_out)] credits")
+ new /obj/item/holochip(drop_location(), trunc(cash_out)) //get the loot
+ cash_out = 0
+
+/obj/item/powersink/creditminer/drain_power()
+ var/drained = 0 // How much raw energy we've siphoned
+ set_light(5)
+
+ drained = attached.newavail()
+ attached.add_delayedload(drained)
+
+ var/datum/powernet/powernet = attached.powernet
+ for(var/obj/machinery/power/terminal/terminal in powernet.nodes)
+ if(istype(terminal.master, /obj/machinery/power/apc))
+ var/obj/machinery/power/apc/apc = terminal.master
+ if(apc.operating && apc.cell)
+ drained += apc.cell.use(DRAIN_FORMULA, force = TRUE)
+ internal_heat += drained
+ var/cash_pulse = min(energy_to_power(drained) / POWER_FOR_PAYOUT, PAYOUT)
+ if(cash_pulse >= 1)
+ cash_out += cash_pulse
+ balloon_alert_to_viewers("mined [trunc(cash_pulse)]cr")
+ playsound(src, 'modular_doppler/modular_antagonists/sapper_gang/sounds/creditminer_drain.wav', 50, FALSE)
+
+/obj/item/powersink/creditminer/release_heat()
+ . = ..()
+ if(!internal_heat)
+ return
+ if(mode < 2) //sfx if we release heat, but don't overlap the drain sfx
+ playsound(src, 'modular_doppler/modular_antagonists/sapper_gang/sounds/creditminer_vent.wav', 50, FALSE)
+ new /obj/effect/temp_visual/mook_dust(get_turf(src))
+
+/// Credit Miner crafting recipe (Incase the intial one explodes)
+/datum/crafting_recipe/credit_miner
+ name = "Credit-miner"
+ result = /obj/item/powersink/creditminer
+ time = 10 SECONDS
+ crafting_flags = CRAFT_MUST_BE_LEARNED
+ tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER, TOOL_MULTITOOL)
+ reqs = list(
+ /obj/item/stack/cable_coil = 5,
+ /obj/item/stack/sheet/iron = 5,
+ /obj/item/stack/sheet/mineral/uranium = 3,
+ /obj/item/stack/sheet/mineral/diamond = 2,
+ /obj/item/stack/sheet/bluespace_crystal = 1,
+ /obj/item/assembly/igniter/condenser = 1,
+ )
+ category = CAT_MISC
+
+#undef RADIO_ALERT
+#undef POWER_FOR_PAYOUT
+#undef PAYOUT
+#undef DRAIN_FORMULA
diff --git a/modular_doppler/modular_antagonists/sapper_gang/code/paper_premade.dm b/modular_doppler/modular_antagonists/sapper_gang/code/paper_premade.dm
new file mode 100644
index 0000000000000..d429dcd9874af
--- /dev/null
+++ b/modular_doppler/modular_antagonists/sapper_gang/code/paper_premade.dm
@@ -0,0 +1,42 @@
+/obj/item/paper/fluff/sapper_intro
+ name = "A Space Sapper's Modus Operandi"
+ default_raw_text = {"
+Remember employee,
+
+
The work-day starts with preparation, you're currently in deep-space nearby a Nanotrasen researching outpost, once you enter their sector there is no turning back. Before you set sail a small check-list should be completed:
+
1. Meet with your partner and decide who wears which mask.
+2. Sort out your equipment, including the contents of the lockers and crates.
+3. Fill and link the portable ore-silo and flat-pack fabricator.
+4. Wrench the air tank on its north side to attach it to the air distribution pipeline.
+5. Prepare the PACMAN and SMES according to your shuttle's powerdraw (5kw).
+
+Completed that list? Great, then its time for breakfast and formulating a gameplan. There are many ways to tackle the work-day, and each has their own level of threat and heat it brings.
+You may greatly post-pone your credit-miner's activation to build a secure and remote environment for it to work in. Working sloppily and hastefully is not ideal, our material is too expensive and fragile.
+In some cases it may even be wise to completely leave the shuttle for a better suited environment to protect the credit-miner; remember that it works in space and doing so will avoid external heating complications.
+internal only cools over-time while the machine is detached or not running, stay nearby so you can keep proper control of its temperature!
+
+If you and your partner do decide to outpost inside the shuttle, make sure that you have control of the temperature. Space-coolers are incredibly power inefficient,
+and you may leave your shuttle completely uninhabitable!
+
Remember to make use of your portable turrets and shuttle turrets, but expect retaliation when you do; they do not have a safe-mode!
+
+Have a good day at work.
+ "}
+
+/obj/item/paper/fluff/sapper_recovery_instructions
+ name = "ATTENTION: So you survived a credit-miner explosion"
+ color = "#ffcc26"
+ desc = "A yellow sticky note..."
+ default_raw_text = {"
+IMPORTANT, make sure to understand the following:
+
+
While this machine may work wonders, it is an incredibly volatile piece of technology. The more power it converts, the hotter it gets; makes sense right?
+You may be considering plugging it straight into an engine, which is a great strategy to a successful day at work; if you are prepared to siphon such large pulses of energy.
+Temperature control is key, both in the work environment and of the miner's hardware. Set up space-coolers and don't leave the miner unattended for a long time!
+
+What happens if you or your partner forget to manage the temperature? Besides the catastrophic consequence of blowing a giant crater into Nanotrasen assets, the significant loss of profits, or the very likely odds of employee casualty, it isn't the end of the work day.
+
+A truly committed sapper can continue by re-building the credit-miner, the knowledge of doing so being a data-fragment uploaded into the mind of each employee.
+Don't get to celebrating just yet, though. The recipe to crafting the machine is complex, and after what you've likely caused to nearby civilization; these materials won't be easy to come by.
+
+But you're not going to return empty-handed, right?
+ "}
diff --git a/modular_doppler/modular_antagonists/sapper_gang/code/sapperpad.dm b/modular_doppler/modular_antagonists/sapper_gang/code/sapperpad.dm
new file mode 100644
index 0000000000000..e37118fac87a5
--- /dev/null
+++ b/modular_doppler/modular_antagonists/sapper_gang/code/sapperpad.dm
@@ -0,0 +1,27 @@
+/obj/machinery/piratepad/sapper
+ name = "credit-bank pad"
+ desc = "A bluespace pad used for beaming holochips into a secure account."
+
+/obj/machinery/computer/piratepad_control/sapper
+ name = "credit-bank console"
+ desc = "A computer used to scan items ready for bluespace transportation."
+ icon_screen = "request"
+ icon_keyboard = "power_key"
+
+///The loop that calculates the value of stuff on a pad, or plain sell them if dry_run is FALSE.
+/obj/machinery/computer/piratepad_control/sapper/pirate_export_loop(obj/machinery/piratepad/pad, dry_run = TRUE)
+ var/datum/export_report/report = new
+ for(var/obj/item/holochip/item_on_pad in get_turf(pad))
+ export_item_and_contents(item_on_pad, apply_elastic = FALSE, dry_run = dry_run, delete_unsold = FALSE, external_report = report, ignore_typecache = nosell_typecache)
+ return report
+
+/obj/machinery/computer/piratepad_control/sapper/post_machine_initialize()
+ . = ..()
+ if(cargo_hold_id)
+ for(var/obj/machinery/piratepad/sapper/pad as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/piratepad/sapper))
+ if(pad.cargo_hold_id == cargo_hold_id)
+ pad_ref = WEAKREF(pad)
+ return
+ else
+ var/obj/machinery/piratepad/sapper/pad = locate() in range(4, src)
+ pad_ref = WEAKREF(pad)
diff --git a/modular_doppler/modular_antagonists/sapper_gang/icons/card.dmi b/modular_doppler/modular_antagonists/sapper_gang/icons/card.dmi
new file mode 100644
index 0000000000000..541f64845379a
Binary files /dev/null and b/modular_doppler/modular_antagonists/sapper_gang/icons/card.dmi differ
diff --git a/modular_doppler/modular_antagonists/sapper_gang/icons/sapper.dmi b/modular_doppler/modular_antagonists/sapper_gang/icons/sapper.dmi
new file mode 100644
index 0000000000000..6c44d8ae55eae
Binary files /dev/null and b/modular_doppler/modular_antagonists/sapper_gang/icons/sapper.dmi differ
diff --git a/modular_doppler/modular_antagonists/sapper_gang/icons/sapper_obj.dmi b/modular_doppler/modular_antagonists/sapper_gang/icons/sapper_obj.dmi
new file mode 100644
index 0000000000000..dc1d651ad56fc
Binary files /dev/null and b/modular_doppler/modular_antagonists/sapper_gang/icons/sapper_obj.dmi differ
diff --git a/modular_doppler/modular_antagonists/sapper_gang/icons/sapper_trim.dmi b/modular_doppler/modular_antagonists/sapper_gang/icons/sapper_trim.dmi
new file mode 100644
index 0000000000000..f5c42573a277f
Binary files /dev/null and b/modular_doppler/modular_antagonists/sapper_gang/icons/sapper_trim.dmi differ
diff --git a/modular_doppler/modular_antagonists/sapper_gang/sapper.dm b/modular_doppler/modular_antagonists/sapper_gang/sapper.dm
new file mode 100644
index 0000000000000..d3f5dfb1e6220
--- /dev/null
+++ b/modular_doppler/modular_antagonists/sapper_gang/sapper.dm
@@ -0,0 +1,108 @@
+/datum/antagonist/sapper
+ name = "\improper Space Sapper"
+ job_rank = ROLE_SPACE_SAPPER
+ roundend_category = "Sapper Gang"
+ antagpanel_category = "Sapper Gang"
+ show_to_ghosts = TRUE
+ antag_recipes = list(/datum/crafting_recipe/credit_miner)
+
+ var/datum/team/sapper/team
+
+/datum/antagonist/sapper/apply_innate_effects(mob/living/mob_override)
+ . = ..()
+ var/mob/living/owner_mob = mob_override || owner.current
+ var/datum/language_holder/holder = owner_mob.get_language_holder()
+ holder.grant_language(/datum/language/gutter, source = LANGUAGE_PIRATE)
+ holder.selected_language = /datum/language/gutter
+
+/datum/antagonist/sapper/remove_innate_effects(mob/living/mob_override)
+ var/mob/living/owner_mob = mob_override || owner.current
+ owner_mob.remove_language(/datum/language/gutter, source = LANGUAGE_PIRATE)
+ return ..()
+
+/datum/antagonist/sapper/greet()
+ . = ..()
+ to_chat(owner, "You're an illegal credits miner, build your defenses to protect your credit-miner and your ship, and harvest as many credits as you can!")
+ owner.announce_objectives()
+
+/datum/antagonist/sapper/get_team()
+ return team
+
+/datum/antagonist/sapper/create_team(datum/team/sapper/new_team)
+ if(!new_team)
+ return
+ if(!istype(new_team))
+ stack_trace("Wrong team type passed to [type] initialization.")
+ team = new_team
+
+/datum/antagonist/sapper/on_gain()
+ equip_guy()
+ objectives += team.objectives
+ return ..()
+
+/datum/antagonist/sapper/on_removal()
+ owner.special_role = null
+ return ..()
+
+/datum/antagonist/sapper/proc/equip_guy()
+ if(!ishuman(owner.current))
+ return
+ var/mob/living/carbon/human/person = owner.current
+ var/datum/outfit/outfit_to_apply = new /datum/outfit/sapper
+ person.equipOutfit(outfit_to_apply)
+ return TRUE
+
+/datum/antagonist/sapper/get_preview_icon()
+ var/icon/sapper_one_icon = render_preview_outfit(/datum/outfit/sapper/preview)
+ sapper_one_icon.Shift(WEST, 6)
+
+ var/icon/sapper_two_icon = render_preview_outfit(/datum/outfit/sapper/preview/partner)
+ sapper_two_icon.Shift(EAST, 6)
+
+ var/icon/final_icon = sapper_one_icon
+ final_icon.Blend(sapper_two_icon, ICON_OVERLAY)
+
+ return finish_preview_icon(final_icon)
+
+/datum/team/sapper
+ name = "\improper Sapper gang"
+
+/datum/team/sapper/New()
+ ..()
+ forge_objectives()
+
+/datum/team/sapper/proc/forge_objectives()
+ var/datum/objective/sapper/sapper_objective = new()
+ sapper_objective.team = src
+ for(var/obj/machinery/computer/piratepad_control/sapper/cargo_hold as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/piratepad_control/sapper))
+ var/area/area = get_area(cargo_hold)
+ if(istype(area, /area/shuttle/pirate))
+ sapper_objective.cargo_hold = cargo_hold
+ break
+ sapper_objective.update_explanation_text()
+ objectives += sapper_objective
+ for(var/datum/mind/mind in members)
+ var/datum/antagonist/sapper/sapper = mind.has_antag_datum(/datum/antagonist/sapper)
+ if(sapper)
+ sapper.objectives |= objectives
+
+/datum/objective/sapper
+ var/obj/machinery/computer/piratepad_control/sapper/cargo_hold
+ explanation_text = "Use your credit-miner to convert energy into cash."
+
+/datum/objective/sapper/update_explanation_text()
+ if(cargo_hold)
+ var/area/storage_area = get_area(cargo_hold)
+ explanation_text = "Acquire as many credits as you can from the station's powernet and cash it out into the [storage_area.name] cargo hold."
+
+/datum/objective/sapper/proc/get_loot_value()
+ return cargo_hold ? cargo_hold.points : 0
+
+/datum/team/sapper/roundend_report()
+ var/list/parts = list()
+
+ parts += "Sapper Gang were:"
+ parts += printplayerlist(members)
+ var/datum/objective/sapper/sapper_objective = locate() in objectives
+ parts += "Total cash out: [sapper_objective.get_loot_value()] credits"
+ return "