diff --git a/citadel.dme b/citadel.dme
index bffed084e8d1..a08278663641 100644
--- a/citadel.dme
+++ b/citadel.dme
@@ -610,7 +610,6 @@
#include "code\datums\progressbar.dm"
#include "code\datums\prototype.dm"
#include "code\datums\radiation_wave.dm"
-#include "code\datums\recipe.dm"
#include "code\datums\soul_link.dm"
#include "code\datums\sun.dm"
#include "code\datums\tgs_event_handler.dm"
@@ -694,13 +693,6 @@
#include "code\datums\components\atoms\radioactive.dm"
#include "code\datums\components\crafting\crafting.dm"
#include "code\datums\components\crafting\guncrafting.dm"
-#include "code\datums\components\crafting\recipes.dm"
-#include "code\datums\components\crafting\recipes\recipes_clothing.dm"
-#include "code\datums\components\crafting\recipes\recipes_furniture.dm"
-#include "code\datums\components\crafting\recipes\recipes_misc.dm"
-#include "code\datums\components\crafting\recipes\recipes_primal.dm"
-#include "code\datums\components\crafting\recipes\recipes_robot.dm"
-#include "code\datums\components\crafting\recipes\recipes_weapon_and_ammo.dm"
#include "code\datums\components\items\wielding.dm"
#include "code\datums\components\movable\aquarium.dm"
#include "code\datums\components\riding\riding_filter.dm"
@@ -796,6 +788,21 @@
#include "code\datums\outfits\military\sysguard.dm"
#include "code\datums\proxfield\_proxfield.dm"
#include "code\datums\proxfield\basic.dm"
+#include "code\datums\recipe\crafting_recipe.dm"
+#include "code\datums\recipe\material_recipe.dm"
+#include "code\datums\recipe\recipe.dm"
+#include "code\datums\recipe\stack_recipe.dm"
+#include "code\datums\recipe\crafting_recipes\recipes_clothing.dm"
+#include "code\datums\recipe\crafting_recipes\recipes_furniture.dm"
+#include "code\datums\recipe\crafting_recipes\recipes_misc.dm"
+#include "code\datums\recipe\crafting_recipes\recipes_primal.dm"
+#include "code\datums\recipe\crafting_recipes\recipes_robot.dm"
+#include "code\datums\recipe\crafting_recipes\recipes_weapon_and_ammo.dm"
+#include "code\datums\recipe\material_recipes\furniture.dm"
+#include "code\datums\recipe\material_recipes\structures.dm"
+#include "code\datums\recipe\material_recipes\tools.dm"
+#include "code\datums\recipe\stack_recipes\misc.dm"
+#include "code\datums\recipe\stack_recipes\structures.dm"
#include "code\datums\repositories\ammomaterial.dm"
#include "code\datums\repositories\cameras.dm"
#include "code\datums\repositories\crew.dm"
@@ -2978,6 +2985,7 @@
#include "code\modules\loadout\accessories\collar.dm"
#include "code\modules\loadout\accessories\insignia.dm"
#include "code\modules\loadout\accessories\utility.dm"
+#include "code\modules\logging\logging.dm"
#include "code\modules\loot\pack.dm"
#include "code\modules\loot\table.dm"
#include "code\modules\loot\packs\archeology.dm"
@@ -3139,9 +3147,10 @@
#include "code\modules\maps\weather\virgo4.dm"
#include "code\modules\materials\_materials.dm"
#include "code\modules\materials\fifty_spawner_mats.dm"
-#include "code\modules\materials\material_recipes.dm"
#include "code\modules\materials\material_sheets.dm"
#include "code\modules\materials\material_synth.dm"
+#include "code\modules\materials\recipes.dm"
+#include "code\modules\materials\definitions\legacy.dm"
#include "code\modules\materials\definitions\special.dm"
#include "code\modules\materials\definitions\admin\alienalloy.dm"
#include "code\modules\materials\definitions\crystals\diamond.dm"
@@ -3161,9 +3170,9 @@
#include "code\modules\materials\definitions\metals\steel.dm"
#include "code\modules\materials\definitions\metals\titanium.dm"
#include "code\modules\materials\definitions\metals\uranium.dm"
+#include "code\modules\materials\definitions\misc\cardboard.dm"
#include "code\modules\materials\definitions\misc\cloths.dm"
#include "code\modules\materials\definitions\misc\foam.dm"
-#include "code\modules\materials\definitions\misc\paper.dm"
#include "code\modules\materials\definitions\misc\plastic.dm"
#include "code\modules\materials\definitions\misc\snow.dm"
#include "code\modules\materials\definitions\misc\wax.dm"
@@ -3173,7 +3182,9 @@
#include "code\modules\materials\definitions\organic\flesh.dm"
#include "code\modules\materials\definitions\organic\leather.dm"
#include "code\modules\materials\definitions\organic\resin.dm"
-#include "code\modules\materials\definitions\organic\wood.dm"
+#include "code\modules\materials\definitions\organic\wood\log.dm"
+#include "code\modules\materials\definitions\organic\wood\plank.dm"
+#include "code\modules\materials\definitions\special\clown_planet.dm"
#include "code\modules\materials\definitions\special\cult.dm"
#include "code\modules\materials\definitions\special\morphium.dm"
#include "code\modules\materials\definitions\special\phoron.dm"
@@ -4345,6 +4356,7 @@
#include "code\modules\rogueminer_vr\zone_console.dm"
#include "code\modules\rogueminer_vr\zonemaster.dm"
#include "code\modules\roles\role.dm"
+#include "code\modules\sculpting\sculpting_block.dm"
#include "code\modules\security levels\keycard authentication.dm"
#include "code\modules\security levels\security levels.dm"
#include "code\modules\shieldgen\directional_shield.dm"
diff --git a/code/__DEFINES/_cooldowns.dm b/code/__DEFINES/_cooldowns.dm
index 2648f6423057..282dce1e29e2 100644
--- a/code/__DEFINES/_cooldowns.dm
+++ b/code/__DEFINES/_cooldowns.dm
@@ -82,3 +82,7 @@
//? Machinery
//* /obj/machinery/computer/card
#define CD_INDEX_IDCONSOLE_PRINT "idconsole_print"
+
+//? Structures
+//* /obj/structure/sculpting_block
+#define CD_INDEX_SCULPTING_COOLDOWN "sculpting_block"
diff --git a/code/__DEFINES/_flags/obj_flags.dm b/code/__DEFINES/_flags/obj_flags.dm
index 14beb93e7060..e042a35136e5 100644
--- a/code/__DEFINES/_flags/obj_flags.dm
+++ b/code/__DEFINES/_flags/obj_flags.dm
@@ -9,6 +9,8 @@
#define OBJ_PREVENT_CLICK_UNDER (1<<3)
/// We ignore depth system when blocking mobs
#define OBJ_IGNORE_MOB_DEPTH (1<<4)
+/// no sculpting
+#define OBJ_NO_SCULPTING (1<<5)
DEFINE_BITFIELD(obj_flags, list(
BITFIELD(EMAGGED),
@@ -16,4 +18,5 @@ DEFINE_BITFIELD(obj_flags, list(
BITFIELD(ON_BLUEPRINTS),
BITFIELD(OBJ_PREVENT_CLICK_UNDER),
BITFIELD(OBJ_IGNORE_MOB_DEPTH),
+ BITFIELD(OBJ_NO_SCULPTING),
))
diff --git a/code/__DEFINES/math.dm b/code/__DEFINES/math.dm
index c0b749ba681e..293b52e79232 100644
--- a/code/__DEFINES/math.dm
+++ b/code/__DEFINES/math.dm
@@ -219,3 +219,6 @@
#define NORM(x, y) (sqrt(SQUAREDNORM(x,y)))
#define ISPOWEROFTWO(x) ((x & (x - 1)) == 0)
#define ROUNDUPTOPOWEROFTWO(x) (2 ** -round(-log(2,x)))
+
+/// get highest magnitude of two numbers, magnitude is abs value
+#define BIGGER_MAGNITUDE(a, b) ((abs(a) > abs(b))? a : b)
diff --git a/code/__HELPERS/do_after.dm b/code/__HELPERS/do_after.dm
index a8a667b336d0..32dc1a7da37a 100644
--- a/code/__HELPERS/do_after.dm
+++ b/code/__HELPERS/do_after.dm
@@ -67,8 +67,9 @@
* * mobility_flags - required mobility flags
* * max_distance - if not null, the user is required to be get_dist() <= max_distance from target.
* * additional_checks - a callback that allows for custom checks. this is invoked with our args directly, allowing us to modify delay.
+ * * progress_anchor - override progressbar anchor location
*/
-/proc/do_after(mob/user, delay, atom/target, flags, mobility_flags = MOBILITY_CAN_USE, max_distance, datum/callback/additional_checks)
+/proc/do_after(mob/user, delay, atom/target, flags, mobility_flags = MOBILITY_CAN_USE, max_distance, datum/callback/additional_checks, atom/progress_anchor)
if(isnull(user))
return FALSE
if(!delay)
@@ -99,8 +100,8 @@
var/datum/progressbar/progress
var/original_delay = delay
var/delay_factor = 1
- if(!(flags & DO_AFTER_NO_PROGRESS))
- progress = new(user, delay, target)
+ if(!(flags & DO_AFTER_NO_PROGRESS) && (!isnull(progress_anchor || !isnull(target))))
+ progress = new(user, delay, progress_anchor || target)
var/start_time = world.time
//* loop
diff --git a/code/__HELPERS/icons/flatten.dm b/code/__HELPERS/icons/flatten.dm
index 39b54352953e..08859a18b4b9 100644
--- a/code/__HELPERS/icons/flatten.dm
+++ b/code/__HELPERS/icons/flatten.dm
@@ -13,6 +13,8 @@
* @params
* - A - appearancelike object.
* - no_anim - flatten out animations
+ *
+ * @return flat icon
*/
/proc/get_compound_icon(atom/A, no_anim)
var/mutable_appearance/N = new
@@ -38,7 +40,107 @@
qdel(west)
return full
+/**
+ * Generates an icon with all 4 directions of something.
+ *
+ * Note: Centering offsets here have a weird meaning.
+ * They basically tell you how to offset the finished result to ignore large icons
+ * causing the original icon to be scaled beyond its sides.
+ * It's not a 'true' semantic centering offset - the icon system doesn't handle that.
+ *
+ * @params
+ * * A - appearancelike object.
+ * * no_anim - flatten out animations
+ * * preprocess - preprocess callback. used because we can't icon ops on a compound icon.
+ *
+ * @return list(flat icon, offset x, offset y) where x/y offsets are centering pixel offsets
+ */
+/proc/get_compound_icon_with_offsets(atom/A, no_anim, datum/callback/preprocess)
+ var/mutable_appearance/N = new
+ N.appearance = A
+
+ var/list/gfi_return
+ var/x_offset = 0
+ var/y_offset = 0
+ var/got_anything = FALSE
+
+ N.dir = NORTH
+ gfi_return = get_flat_icon_with_offsets(N, NORTH, no_anim = no_anim)
+ var/icon/north
+ if(!isnull(gfi_return))
+ north = gfi_return[1]
+ preprocess?.Invoke(north)
+ x_offset = BIGGER_MAGNITUDE(x_offset, gfi_return[2])
+ y_offset = BIGGER_MAGNITUDE(y_offset, gfi_return[3])
+ got_anything = TRUE
+ N.dir = SOUTH
+ gfi_return = get_flat_icon_with_offsets(N, SOUTH, no_anim = no_anim)
+ var/icon/south
+ if(!isnull(gfi_return))
+ south = gfi_return[1]
+ preprocess?.Invoke(south)
+ x_offset = BIGGER_MAGNITUDE(x_offset, gfi_return[2])
+ y_offset = BIGGER_MAGNITUDE(y_offset, gfi_return[3])
+ got_anything = TRUE
+ N.dir = EAST
+ gfi_return = get_flat_icon_with_offsets(N, EAST, no_anim = no_anim)
+ var/icon/east
+ if(!isnull(gfi_return))
+ east = gfi_return[1]
+ preprocess?.Invoke(east)
+ x_offset = BIGGER_MAGNITUDE(x_offset, gfi_return[2])
+ y_offset = BIGGER_MAGNITUDE(y_offset, gfi_return[3])
+ got_anything = TRUE
+ N.dir = WEST
+ gfi_return = get_flat_icon_with_offsets(N, WEST, no_anim = no_anim)
+ var/icon/west
+ if(!isnull(gfi_return))
+ west = gfi_return[1]
+ preprocess?.Invoke(west)
+ x_offset = BIGGER_MAGNITUDE(x_offset, gfi_return[2])
+ y_offset = BIGGER_MAGNITUDE(y_offset, gfi_return[3])
+ got_anything = TRUE
+
+ qdel(N)
+
+ if(!got_anything)
+ return
+
+ //Starts with a blank icon because of byond bugs.
+ var/icon/full = icon('icons/system/blank_32x32.dmi', "")
+ if(!isnull(north))
+ full.Insert(north, dir = NORTH)
+ qdel(north)
+ if(!isnull(south))
+ full.Insert(south, dir = SOUTH)
+ qdel(south)
+ if(!isnull(east))
+ full.Insert(east, dir = EAST)
+ qdel(east)
+ if(!isnull(west))
+ full.Insert(west, dir = WEST)
+ qdel(west)
+
+ return list(full, x_offset, y_offset)
+
+/**
+ * grabs flat icon with no care for alignment / basically just grabs a png
+ */
/proc/get_flat_icon(appearance/appearancelike, dir, no_anim)
+ if(!dir && isloc(appearancelike))
+ dir = appearancelike.dir
+ . = _get_flat_icon(appearancelike, dir, no_anim, null, TRUE)
+ return .?[1]
+
+/**
+ * grabs flat icon as list(icon, centering-x, centering-y) offsets
+ *
+ * Note: Centering offsets here have a weird meaning.
+ * They basically tell you how to offset the finished result to ignore large icons
+ * causing the original icon to be scaled beyond its sides.
+ * It's not a 'true' semantic centering offset - the icon system doesn't handle that.
+ */
+/proc/get_flat_icon_with_offsets(appearance/appearancelike, dir, no_anim)
if(!dir && isloc(appearancelike))
dir = appearancelike.dir
return _get_flat_icon(appearancelike, dir, no_anim, null, TRUE)
@@ -50,8 +152,11 @@
* * no_anim - (optional) trample animations to first frame
* * deficon - (optional) default icon to use instead of using the host appearance's
* * start - is this the first call in the recurse? this is important
+ *
+ * @return list(icon, x, y) where x/y are centering pixel offsets
*/
/proc/_get_flat_icon(image/A, defdir, no_anim, deficon, start)
+ RETURN_TYPE(/list)
// start with blank image
var/static/icon/template = icon('icons/system/blank_32x32.dmi', "")
@@ -73,7 +178,7 @@
// invis? skip.
if(!A || A.alpha <= 0)
- return BLANK
+ return list(BLANK, 0, 0)
// detect if state exists
var/icon/icon = A.icon || deficon
@@ -107,7 +212,7 @@
if(!A.overlays.len && !A.underlays.len)
// we don't even have ourselves!
if(none)
- return BLANK
+ return list(BLANK, 0, 0)
// no overlays/underlays, we're done, just mix in ourselves
var/icon/self_icon = icon(icon(icon, state, ourdir), "", SOUTH, no_anim? 1 : null)
if(A.alpha < 255)
@@ -117,7 +222,7 @@
self_icon.MapColors(arglist(A.color))
else
self_icon.Blend(A.color, ICON_MULTIPLY)
- return self_icon
+ return list(self_icon, 0, 0)
// safety/performance check
if((A.overlays.len + A.underlays.len) > 80)
@@ -163,6 +268,7 @@
comparing = gathered[i]
if(current_layer < gathered[comparing])
gathered.Insert(i, copying)
+ break
// associate
gathered[copying] = current_layer
@@ -186,11 +292,14 @@
comparing = gathered[i]
if(current_layer < gathered[comparing])
gathered.Insert(i, copying)
+ break
// associate
gathered[copying] = current_layer
// adding icon we're mixing in
var/icon/adding
+ // full flat icon returned by a recursive GFI call during rendering
+ var/list/gfi_return
// current dimensions
var/list/flat_size = list(1, flat.Width(), 1, flat.Height())
// adding dimensions
@@ -215,12 +324,13 @@
blend_mode = BLEND_OVERLAY
adding = icon(icon, state, ourdir)
else
- // use full get_flat_icon
+ // use full get_flat_icon_with_offsets
blend_mode = copying.blend_mode
- adding = _get_flat_icon(copying, defdir, no_anim, icon)
+ gfi_return = _get_flat_icon(copying, defdir, no_anim, icon)
+ adding = gfi_return?[1]
// if we got nothing, skip
- if(!adding)
+ if(isnull(adding))
continue
// detect adding size, taking into account copying overlay's pixel offsets
@@ -265,10 +375,10 @@
// clean up frames
var/icon/cleaned = icon()
cleaned.Insert(flat, "", SOUTH, 1, 0)
- return cleaned
+ return list(cleaned, -shift_x, -shift_y)
else
// just return flat as SOUTH
- return icon(flat, "", SOUTH)
+ return list(icon(flat, "", SOUTH), -shift_x, -shift_y)
#undef flatX1
#undef flatX2
diff --git a/code/controllers/subsystem/materials.dm b/code/controllers/subsystem/materials.dm
index b4d9e9651102..6d7bba8dae9d 100644
--- a/code/controllers/subsystem/materials.dm
+++ b/code/controllers/subsystem/materials.dm
@@ -7,6 +7,8 @@ SUBSYSTEM_DEF(materials)
var/list/material_lookup
/// legacy material lookup *vomit
var/list/legacy_material_lookup
+ /// material recipes
+ var/list/datum/stack_recipe/material/material_stack_recipes
// todo: Recover() should keep procedural materials
// however, i can't be assed to write Recover() until we do procedural materials
@@ -14,10 +16,12 @@ SUBSYSTEM_DEF(materials)
/datum/controller/subsystem/materials/Initialize()
initialize_materials()
+ initialize_material_recipes()
return ..()
/datum/controller/subsystem/materials/Recover()
initialize_materials()
+ initialize_material_recipes()
return ..()
/datum/controller/subsystem/materials/proc/initialize_materials()
@@ -38,6 +42,14 @@ SUBSYSTEM_DEF(materials)
material_lookup[initial(mat_ref.id)] = mat_ref
legacy_material_lookup[lowertext(mat_ref.name)] = mat_ref
+/datum/controller/subsystem/materials/proc/initialize_material_recipes()
+ material_stack_recipes = list()
+ for(var/path in subtypesof(/datum/stack_recipe/material))
+ var/datum/stack_recipe/material/this = path
+ if(initial(this.abstract_type) == path)
+ continue
+ material_stack_recipes += new path
+
/**
* fetches material instance
*
@@ -54,6 +66,8 @@ SUBSYSTEM_DEF(materials)
else if(ispath(id_or_path))
// yay it's a path
return material_lookup[initial(id_or_path.id)]
+ else if(istype(id_or_path))
+ return id_or_path
else
// what
// yes you get a runtime if you pass null in, the subsystem shouldn't have to sanitycheck for you.
@@ -78,6 +92,8 @@ SUBSYSTEM_DEF(materials)
* Use SSmaterials.get_material()!
*/
/proc/get_material_by_name(name)
+ if(istype(name, /datum/material))
+ return name
return SSmaterials.legacy_material_lookup[name]
/**
diff --git a/code/datums/components/crafting/recipes.dm b/code/datums/recipe/crafting_recipe.dm
similarity index 100%
rename from code/datums/components/crafting/recipes.dm
rename to code/datums/recipe/crafting_recipe.dm
diff --git a/code/datums/components/crafting/recipes/recipes_clothing.dm b/code/datums/recipe/crafting_recipes/recipes_clothing.dm
similarity index 100%
rename from code/datums/components/crafting/recipes/recipes_clothing.dm
rename to code/datums/recipe/crafting_recipes/recipes_clothing.dm
diff --git a/code/datums/components/crafting/recipes/recipes_furniture.dm b/code/datums/recipe/crafting_recipes/recipes_furniture.dm
similarity index 100%
rename from code/datums/components/crafting/recipes/recipes_furniture.dm
rename to code/datums/recipe/crafting_recipes/recipes_furniture.dm
diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/recipe/crafting_recipes/recipes_misc.dm
similarity index 100%
rename from code/datums/components/crafting/recipes/recipes_misc.dm
rename to code/datums/recipe/crafting_recipes/recipes_misc.dm
diff --git a/code/datums/components/crafting/recipes/recipes_primal.dm b/code/datums/recipe/crafting_recipes/recipes_primal.dm
similarity index 100%
rename from code/datums/components/crafting/recipes/recipes_primal.dm
rename to code/datums/recipe/crafting_recipes/recipes_primal.dm
diff --git a/code/datums/components/crafting/recipes/recipes_robot.dm b/code/datums/recipe/crafting_recipes/recipes_robot.dm
similarity index 100%
rename from code/datums/components/crafting/recipes/recipes_robot.dm
rename to code/datums/recipe/crafting_recipes/recipes_robot.dm
diff --git a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm b/code/datums/recipe/crafting_recipes/recipes_weapon_and_ammo.dm
similarity index 100%
rename from code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm
rename to code/datums/recipe/crafting_recipes/recipes_weapon_and_ammo.dm
diff --git a/code/datums/recipe/material_recipe.dm b/code/datums/recipe/material_recipe.dm
new file mode 100644
index 000000000000..e8c57e5de08d
--- /dev/null
+++ b/code/datums/recipe/material_recipe.dm
@@ -0,0 +1,20 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/datum/stack_recipe/material
+ abstract_type = /datum/stack_recipe/material
+ sort_order = -1
+ category = "Material - Misc"
+ // todo: material constraints
+ // todo: auto-set materials list
+
+// these are here to have the langserv cast for us since we know stack is material
+
+/datum/stack_recipe/material/craft(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return ..()
+
+/datum/stack_recipe/material/check(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return ..()
+
+/datum/stack_recipe/material/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return ..()
diff --git a/code/datums/recipe/material_recipes/furniture.dm b/code/datums/recipe/material_recipes/furniture.dm
new file mode 100644
index 000000000000..e2db6dd78d9c
--- /dev/null
+++ b/code/datums/recipe/material_recipes/furniture.dm
@@ -0,0 +1,42 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/datum/stack_recipe/material/furniture
+ abstract_type = /datum/stack_recipe/material/furniture
+ category = "material - furniture"
+
+/datum/stack_recipe/material/furniture/bed
+ name = "bed"
+ result_type = /obj/structure/bed
+ exclusitivity = /obj/structure/bed
+ cost = 2
+
+/datum/stack_recipe/material/furniture/bed/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return new /obj/structure/bed(where, stack.material)
+
+/datum/stack_recipe/material/furniture/double_bed
+ name = "double bed"
+ result_type = /obj/structure/bed/double
+ exclusitivity = /obj/structure/bed
+ cost = 3
+
+/datum/stack_recipe/material/furniture/double_bed/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return new /obj/structure/bed/double(where, stack.material)
+
+/datum/stack_recipe/material/furniture/stool
+ name = "stool"
+ result_type = /obj/item/stool
+ exclusitivity = /obj/item/stool
+ cost = 3
+
+/datum/stack_recipe/material/furniture/stool/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return new /obj/item/stool(where, stack.material)
+
+/datum/stack_recipe/material/furniture/chair
+ name = "chair"
+ result_type = /obj/structure/bed/chair
+ exclusitivity = /obj/structure/bed
+ cost = 3
+
+/datum/stack_recipe/material/furniture/chair/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return new /obj/structure/bed/chair(where, stack.material)
diff --git a/code/datums/recipe/material_recipes/structures.dm b/code/datums/recipe/material_recipes/structures.dm
new file mode 100644
index 000000000000..3d5872ef09a9
--- /dev/null
+++ b/code/datums/recipe/material_recipes/structures.dm
@@ -0,0 +1,51 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/datum/stack_recipe/material/structure
+ abstract_type = /datum/stack_recipe/material/structure
+ category = "material - structure"
+
+/datum/stack_recipe/material/structure/door
+ name = "simple door"
+ result_type = /obj/structure/simple_door
+ cost = 5
+
+/datum/stack_recipe/material/structure/door/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ for(var/i in 1 to amount)
+ new /obj/structure/simple_door(where, stack.material)
+
+/datum/stack_recipe/material/structure/barricade
+ name = "barricade"
+ result_type = /obj/structure/barricade
+ cost = 5
+
+/datum/stack_recipe/material/structure/barricade/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ for(var/i in 1 to amount)
+ new /obj/structure/barricade(where, stack.material)
+
+/datum/stack_recipe/material/structure/girder
+ name = "girder"
+ result_type = /obj/structure/girder
+ cost = 2
+
+/datum/stack_recipe/material/structure/girder/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ for(var/i in 1 to amount)
+ new /obj/structure/girder(where, stack.material)
+
+/datum/stack_recipe/material/structure/low_wall
+ name = "low walls"
+ result_type = /obj/structure/wall_frame
+ cost = 2
+
+/datum/stack_recipe/material/structure/low_wall/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ for(var/i in 1 to amount)
+ new /obj/structure/wall_frame(where, stack.material)
+
+/datum/stack_recipe/material/structure/sculpting_block
+ name = "sculpting block"
+ result_type = /obj/structure/sculpting_block
+ cost = 15
+
+/datum/stack_recipe/material/structure/sculpting_block/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ for(var/i in 1 to amount)
+ new /obj/structure/sculpting_block(where, stack.material)
diff --git a/code/datums/recipe/material_recipes/tools.dm b/code/datums/recipe/material_recipes/tools.dm
new file mode 100644
index 000000000000..122e4ca6d85d
--- /dev/null
+++ b/code/datums/recipe/material_recipes/tools.dm
@@ -0,0 +1,72 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/datum/stack_recipe/material/tools
+ abstract_type = /datum/stack_recipe/material/tools
+ category = "material - tools"
+
+/datum/stack_recipe/material/tools/ring
+ name = "ring"
+ result_type = /obj/item/clothing/gloves/ring/material
+ cost = 1
+
+/datum/stack_recipe/material/tools/ring/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return new /obj/item/clothing/gloves/ring/material(where, stack.material)
+
+/datum/stack_recipe/material/tools/braclet
+ name = "ring"
+ result_type = /obj/item/clothing/accessory/bracelet/material
+ cost = 1
+
+/datum/stack_recipe/material/tools/ring/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ return new /obj/item/clothing/accessory/bracelet/material(where, stack.material)
+
+/**
+ * for the /obj/item/material path
+ */
+/datum/stack_recipe/material/tools/simple
+ abstract_type = /datum/stack_recipe/material/tools/simple
+
+/datum/stack_recipe/material/tools/simple/make(atom/where, amount, obj/item/stack/material/stack, mob/user, silent, use_dir)
+ ASSERT(ispath(result_type, /obj/item/material))
+ return new result_type(where, stack.material)
+
+/datum/stack_recipe/material/tools/simple/baseball_bat
+ name = "baseball bat"
+ result_type = /obj/item/material/twohanded/baseballbat
+ cost = 7
+
+/datum/stack_recipe/material/tools/simple/astray
+ name = "ashtray"
+ result_type = /obj/item/material/ashtray
+ cost = 2
+
+/datum/stack_recipe/material/tools/simple/spoon
+ name = "spoon"
+ result_type = /obj/item/material/kitchen/utensil/spoon
+ cost = 1
+
+/datum/stack_recipe/material/tools/simple/armor_plate
+ name = "improvised armor plate"
+ result_type = /obj/item/material/armor_plating
+ cost = 2
+
+/datum/stack_recipe/material/tools/simple/grave_marker
+ name = "grave marker"
+ result_type = /obj/item/material/gravemarker
+ cost = 5
+
+/datum/stack_recipe/material/tools/simple/fork
+ name = "fork"
+ result_type = /obj/item/material/kitchen/utensil/fork
+ cost = 1
+
+/datum/stack_recipe/material/tools/simple/blade
+ name = "blade"
+ result_type = /obj/item/material/butterflyblade
+ cost = 4
+
+/datum/stack_recipe/material/tools/simple/hammer_head
+ name = "fork"
+ result_type = /obj/item/material/hammer_head
+ cost = 8
diff --git a/code/datums/recipe.dm b/code/datums/recipe/recipe.dm
similarity index 98%
rename from code/datums/recipe.dm
rename to code/datums/recipe/recipe.dm
index d81c783638f8..4c5932d478c6 100644
--- a/code/datums/recipe.dm
+++ b/code/datums/recipe/recipe.dm
@@ -1,3 +1,5 @@
+// todo: damn, 2011? sounds like ripe time for refactor / optimizations round 'ere-- [user was banned for this post]
+
/* * * * * * * * * * * * * * * * * * * * * * * * * *
* /datum/recipe by rastaf0 13 apr 2011 *
* * * * * * * * * * * * * * * * * * * * * * * * * *
diff --git a/code/datums/recipe/stack_recipe.dm b/code/datums/recipe/stack_recipe.dm
new file mode 100644
index 000000000000..c088ba6f2c1c
--- /dev/null
+++ b/code/datums/recipe/stack_recipe.dm
@@ -0,0 +1,155 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/**
+ * why is this here?
+ *
+ * to avoid a constructor for /datum/stack_recipe
+ *
+ * why? because this is easier to regex later if it turns out silicons code design(tm) was terrible
+ */
+/proc/create_stack_recipe_datum(name, product, cost, amount = 1, sanity_checks = TRUE, time = 0, recipe_type = /datum/stack_recipe, category, exclusitivity)
+ // check this isn't being misused
+ ASSERT(!ispath(recipe_type, /datum/stack_recipe/material))
+ var/datum/stack_recipe/creating = new recipe_type
+ creating.name = name
+ creating.category = category
+ creating.result_type = product
+ creating.cost = cost
+ creating.result_amount = amount
+ creating.result_is_stack = ispath(product, /obj/item/stack)
+ creating.no_automatic_sanity_checks = !sanity_checks
+ creating.time = time
+ creating.exclusitivity = exclusitivity
+ return creating
+
+/datum/stack_recipe
+ abstract_type = /datum/stack_recipe
+ /// sort order - lower is first
+ var/sort_order = 0
+ /// recipe name
+ var/name = "???"
+ /// category (so the dropdown we appear under). categories are always sorted to top, and then alphabetically.
+ /// null to have something on main panel
+ var/category
+ /// result type
+ var/result_type = /obj/item/clothing/mask/ninjascarf
+ /// result amount; stacks will be processed accordingly
+ var/result_amount = 1
+ /// the amount of time to craft result_amount of result_type
+ var/time = 3 SECONDS
+ /// bypass checks for preventing turf stacking/whatnot
+ var/no_automatic_sanity_checks = FALSE
+ /// how many of the stack we need
+ var/cost = 1
+ /// this is a stack product
+ var/result_is_stack = FALSE
+ /// type to check against to make sure there's nothing in the way
+ var/exclusitivity
+ /// max amount to allow crafting at once. null for 1 non stack, infinity stack
+ var/max_amount
+ // todo: material constraints
+
+/datum/stack_recipe/New()
+ if(ispath(result_type, /obj/item/stack))
+ result_is_stack = TRUE
+
+/**
+ * attepmt to craft
+ *
+ * @params
+ * * where - where to spawn result
+ * * amount - amount
+ * * stack - stack used
+ * * user - (optional) person crafting
+ * * silent - (optional) suppress feedback to user
+ * * use_dir - (optional) override dir if no user to get it from
+ *
+ * @return TRUE/FALSE success
+ */
+/datum/stack_recipe/proc/craft(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir = user?.dir)
+ if(!check(where, amount, stack, user, silent, use_dir))
+ return FALSE
+ return make(where, amount, stack, user, silent, use_dir)
+
+/**
+ * see if it's valid to make the recipe
+ *
+ * @params
+ * * where - where to spawn result
+ * * amount - amount
+ * * stack - stack used
+ * * user - (optional) person crafting
+ * * silent - (optional) suppress feedback to user
+ * * use_dir - (optional) override dir if no user to get it from
+ *
+ * @return TRUE/FALSE success
+ */
+/datum/stack_recipe/proc/check(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir = user?.dir)
+ if(!no_automatic_sanity_checks)
+ var/atom/movable/casted_result = result_type
+ if(initial(casted_result.density))
+ for(var/atom/movable/AM as anything in where)
+ if(AM == user)
+ continue
+ if(AM.density)
+ if(!silent)
+ user.action_feedback(SPAN_WARNING("[AM] is in the way."))
+ return FALSE
+ if(!isnull(exclusitivity))
+ for(var/atom/movable/AM as anything in where)
+ if(AM == user)
+ continue
+ if(istype(AM, exclusitivity))
+ if(!silent && !isnull(user))
+ user.action_feedback(SPAN_WARNING("[AM] is in the way."))
+ return FALSE
+ return TRUE
+
+/**
+ * actually spawn the object in
+ * this is past point of no return
+ * shouldn't cancel under any circumstances
+ *
+ * @params
+ * * where - where to spawn result
+ * * amount - amount
+ * * stack - stack used
+ * * user - (optional) person crafting
+ * * silent - (optional) suppress feedback to user
+ * * use_dir - (optional) override dir if no user to get it from
+ */
+/datum/stack_recipe/proc/make(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir)
+ if(result_is_stack)
+ var/obj/item/stack/casted = result_type
+ var/max_amount = initial(casted.max_amount)
+ var/safety = 50
+ while(amount)
+ if(!--safety)
+ CRASH("safety hit")
+ var/obj/item/stack/created = new result_type(where, min(amount, max_amount))
+ amount -= created.amount
+ else
+ for(var/i in 1 to min(amount, 50))
+ var/atom/movable/created = new result_type(where)
+ created.setDir(use_dir)
+ return TRUE
+
+/**
+ * tgui stack recipe data
+ */
+/datum/stack_recipe/proc/tgui_recipe_data()
+ // todo: better way than ref? we don't want to do uids but refs are kinda ass to use in UIs for security/checking purposes.
+ return list(
+ "sortOrder" = sort_order,
+ "name" = name,
+ "category" = category,
+ "resultType" = result_type,
+ "resultAmt" = result_amount,
+ "time" = time,
+ "noAutoSanity" = no_automatic_sanity_checks,
+ "isStack" = result_is_stack,
+ "ref" = ref(src),
+ "maxAmount" = max_amount,
+ "cost" = cost,
+ )
diff --git a/code/datums/recipe/stack_recipes/misc.dm b/code/datums/recipe/stack_recipes/misc.dm
new file mode 100644
index 000000000000..a7532e57e39f
--- /dev/null
+++ b/code/datums/recipe/stack_recipes/misc.dm
@@ -0,0 +1,70 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/datum/stack_recipe/oar
+ name = "oar"
+ result_type = /obj/item/oar
+ cost = 2
+
+/datum/stack_recipe/oar/make(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir)
+ var/obj/item/stack/material/material_stack = stack
+ if(istype(material_stack))
+ for(var/i in 1 to amount)
+ new result_type(where, material_stack.material)
+ else
+ for(var/i in 1 to amount)
+ new result_type(where)
+
+/datum/stack_recipe/boat
+ name = "boat"
+ result_type = /obj/vehicle/ridden/boat
+ cost = 15
+
+/datum/stack_recipe/boat/make(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir)
+ var/obj/item/stack/material/material_stack = stack
+ if(istype(material_stack))
+ for(var/i in 1 to amount)
+ new result_type(where, material_stack.material)
+ else
+ for(var/i in 1 to amount)
+ new result_type(where)
+
+/datum/stack_recipe/dragon_boat
+ name = "dragon boat"
+ result_type = /obj/vehicle/ridden/boat/dragon
+ cost = 25
+
+/datum/stack_recipe/dragon_boat/make(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir)
+ var/obj/item/stack/material/material_stack = stack
+ if(istype(material_stack))
+ for(var/i in 1 to amount)
+ new result_type(where, material_stack.material)
+ else
+ for(var/i in 1 to amount)
+ new result_type(where)
+
+/datum/stack_recipe/pew
+ abstract_type = /datum/stack_recipe/pew
+ exclusitivity = /obj/structure/bed
+ cost = 1
+
+/datum/stack_recipe/pew/make(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir)
+ var/obj/item/stack/material/material_stack = stack
+ if(istype(material_stack))
+ for(var/i in 1 to amount)
+ new result_type(where, material_stack.material)
+ else
+ for(var/i in 1 to amount)
+ new result_type(where)
+
+/datum/stack_recipe/pew/middle
+ name = "pew (middle)"
+ result_type = /obj/structure/bed/chair/pew
+
+/datum/stack_recipe/pew/left
+ name = "pew (left)"
+ result_type = /obj/structure/bed/chair/pew/left
+
+/datum/stack_recipe/pew/right
+ name = "pew (right)"
+ result_type = /obj/structure/bed/chair/pew/right
diff --git a/code/datums/recipe/stack_recipes/structures.dm b/code/datums/recipe/stack_recipes/structures.dm
new file mode 100644
index 000000000000..55d9ef9eac8c
--- /dev/null
+++ b/code/datums/recipe/stack_recipes/structures.dm
@@ -0,0 +1,30 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/datum/stack_recipe/railing
+ name = "railing"
+ result_type = /obj/structure/railing
+ cost = 2
+ time = 1.25 SECONDS
+
+/datum/stack_recipe/railing/check(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir = user?.dir)
+ if(isnull(use_dir))
+ return FALSE
+ if(!no_automatic_sanity_checks)
+ if(!isturf(where) || isspaceturf(where))
+ if(!silent && !isnull(user))
+ user.action_feedback(SPAN_WARNING("Railings must be built on a floor."))
+ return FALSE
+ for(var/obj/structure/railing/R in where)
+ if(R.dir == use_dir)
+ if(!silent && !isnull(user))
+ user.action_feedback(SPAN_WARNING("There's no room for a railing here facing [dir2text(use_dir)]."))
+ return FALSE
+ return TRUE
+
+/datum/stack_recipe/railing/make(atom/where, amount, obj/item/stack/stack, mob/user, silent, use_dir = user?.dir)
+ if(isnull(use_dir))
+ return
+ var/obj/structure/railing/built = new(where, TRUE)
+ built.setDir(use_dir)
+ return built
diff --git a/code/game/atoms/movable/movable.dm b/code/game/atoms/movable/movable.dm
index a9f16ef5b045..d7b1aea55c37 100644
--- a/code/game/atoms/movable/movable.dm
+++ b/code/game/atoms/movable/movable.dm
@@ -205,6 +205,7 @@
//Overlays
/atom/movable/overlay
+ atom_flags = ATOM_ABSTRACT
var/atom/master = null
anchored = TRUE
diff --git a/code/game/machinery/doors/airlock_subtypes.dm b/code/game/machinery/doors/airlock_subtypes.dm
index 9c5c56ec437f..fea2ca8f1396 100644
--- a/code/game/machinery/doors/airlock_subtypes.dm
+++ b/code/game/machinery/doors/airlock_subtypes.dm
@@ -4,7 +4,7 @@
name = "Command Airlock"
icon_state = "preview"
req_one_access = list(ACCESS_COMMAND_BRIDGE)
- assembly_type = /obj/structure/door_assembly/door_assembly_com
+ assembly_type = /obj/structure/door_assembly/command
open_sound_powered = 'sound/machines/door/cmd3o.ogg'
close_sound_powered = 'sound/machines/door/cmd3c.ogg'
door_color = COLOR_COMMAND_BLUE
@@ -14,7 +14,7 @@
name = "Security Airlock"
icon_state = "preview"
req_one_access = list(ACCESS_SECURITY_EQUIPMENT)
- assembly_type = /obj/structure/door_assembly/door_assembly_sec
+ assembly_type = /obj/structure/door_assembly/security
open_sound_powered = 'sound/machines/door/sec1o.ogg'
close_sound_powered = 'sound/machines/door/sec1c.ogg'
door_color = COLOR_SECURITY_RED
@@ -23,7 +23,7 @@
name = "Engineering Airlock"
icon_state = "preview"
req_one_access = list(ACCESS_ENGINEERING_MAIN)
- assembly_type = /obj/structure/door_assembly/door_assembly_eng
+ assembly_type = /obj/structure/door_assembly/engi
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
door_color = COLOR_AMBER
@@ -33,7 +33,7 @@
name = "Atmospherics Airlock"
icon_state = "preview"
req_one_access = list(ACCESS_ENGINEERING_ATMOS)
- assembly_type = /obj/structure/door_assembly/door_assembly_eat
+ assembly_type = /obj/structure/door_assembly/engi_atmos
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
door_color = COLOR_AMBER
@@ -43,7 +43,7 @@
name = "Medical Airlock"
icon_state = "preview"
req_one_access = list(ACCESS_MEDICAL_MAIN)
- assembly_type = /obj/structure/door_assembly/door_assembly_med
+ assembly_type = /obj/structure/door_assembly/medical
open_sound_powered = 'sound/machines/door/med1o.ogg'
close_sound_powered = 'sound/machines/door/med1c.ogg'
door_color = COLOR_WHITE
@@ -53,7 +53,7 @@
name = "Maintenance Access"
icon_state = "preview"
//req_one_access = list(ACCESS_ENGINEERING_MAINT) // Maintenance is open access
- assembly_type = /obj/structure/door_assembly/door_assembly_mai
+ assembly_type = /obj/structure/door_assembly/maint
open_sound_powered = 'sound/machines/door/door2o.ogg'
close_sound_powered = 'sound/machines/door/door2c.ogg'
stripe_color = COLOR_AMBER
@@ -89,7 +89,7 @@
name = "External Airlock"
icon_state = "preview"
airlock_type = "External"
- assembly_type = /obj/structure/door_assembly/door_assembly_ext
+ assembly_type = /obj/structure/door_assembly/external
open_sound_powered = 'sound/machines/door/space1o.ogg'
close_sound_powered = 'sound/machines/door/space1c.ogg'
icon = 'icons/obj/doors/external/door.dmi'
@@ -126,7 +126,7 @@
emag_file = 'icons/obj/doors/external/emag.dmi'
opacity = FALSE
glass = TRUE
- assembly_type = /obj/structure/door_assembly/door_assembly_ext
+ assembly_type = /obj/structure/door_assembly/external
opacity = 0
glass = 1
req_one_access = list(ACCESS_ENGINEERING_AIRLOCK)
@@ -169,7 +169,7 @@
explosion_resistance = 20
opacity = 1
secured_wires = 1
- assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity //Until somebody makes better sprites.
+ assembly_type = /obj/structure/door_assembly/high_security //Until somebody makes better sprites.
req_one_access = list(ACCESS_COMMAND_VAULT)
open_sound_powered = 'sound/machines/door/vault1o.ogg'
close_sound_powered = 'sound/machines/door/vault1c.ogg'
@@ -183,7 +183,7 @@
/obj/machinery/door/airlock/freezer
name = "Freezer Airlock"
opacity = 1
- assembly_type = /obj/structure/door_assembly/door_assembly_fre
+ assembly_type = /obj/structure/door_assembly/freezer
door_color = COLOR_WHITE
/obj/machinery/door/airlock/hatch
@@ -191,7 +191,7 @@
airlock_type = "Hatch"
explosion_resistance = 20
opacity = 1
- assembly_type = /obj/structure/door_assembly/door_assembly_hatch
+ assembly_type = /obj/structure/door_assembly/hatch
req_one_access = list(ACCESS_ENGINEERING_MAINT)
open_sound_powered = 'sound/machines/door/hatchopen.ogg'
close_sound_powered = 'sound/machines/door/hatchclose.ogg'
@@ -213,7 +213,7 @@
airlock_type = "Hatch"
explosion_resistance = 20
opacity = 1
- assembly_type = /obj/structure/door_assembly/door_assembly_mhatch
+ assembly_type = /obj/structure/door_assembly/hatch/maint
req_one_access = list(ACCESS_ENGINEERING_MAINT)
open_sound_powered = 'sound/machines/door/hatchopen.ogg'
close_sound_powered = 'sound/machines/door/hatchclose.ogg'
@@ -239,7 +239,7 @@
maxhealth = 300
explosion_resistance = 5
opacity = 0
- assembly_type = /obj/structure/door_assembly/door_assembly_com
+ assembly_type = /obj/structure/door_assembly/command
glass = 1
req_one_access = list(ACCESS_COMMAND_BRIDGE)
open_sound_powered = 'sound/machines/door/cmd1o.ogg'
@@ -255,7 +255,7 @@
maxhealth = 300
explosion_resistance = 5
opacity = 0
- assembly_type = /obj/structure/door_assembly/door_assembly_eng
+ assembly_type = /obj/structure/door_assembly/engi
glass = 1
req_one_access = list(ACCESS_ENGINEERING_MAIN)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
@@ -270,7 +270,7 @@
maxhealth = 300
explosion_resistance = 5
opacity = 0
- assembly_type = /obj/structure/door_assembly/door_assembly_eat
+ assembly_type = /obj/structure/door_assembly/engi_atmos
glass = 1
req_one_access = list(ACCESS_ENGINEERING_ATMOS)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
@@ -285,7 +285,7 @@
maxhealth = 300
explosion_resistance = 5
opacity = 0
- assembly_type = /obj/structure/door_assembly/door_assembly_sec
+ assembly_type = /obj/structure/door_assembly/security
glass = 1
req_one_access = list(ACCESS_SECURITY_EQUIPMENT)
open_sound_powered = 'sound/machines/door/sec1o.ogg'
@@ -299,7 +299,7 @@
maxhealth = 300
explosion_resistance = 5
opacity = 0
- assembly_type = /obj/structure/door_assembly/door_assembly_med
+ assembly_type = /obj/structure/door_assembly/medical
glass = 1
req_one_access = list(ACCESS_MEDICAL_MAIN)
open_sound_powered = 'sound/machines/door/med1o.ogg'
@@ -310,7 +310,7 @@
/obj/machinery/door/airlock/mining
name = "Mining Airlock"
- assembly_type = /obj/structure/door_assembly/door_assembly_min
+ assembly_type = /obj/structure/door_assembly/mining
req_one_access = list(ACCESS_SUPPLY_MINE)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
@@ -319,7 +319,7 @@
/obj/machinery/door/airlock/atmos
name = "Atmospherics Airlock"
- assembly_type = /obj/structure/door_assembly/door_assembly_atmo
+ assembly_type = /obj/structure/door_assembly/atmos
req_one_access = list(ACCESS_ENGINEERING_ATMOS)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
@@ -328,7 +328,7 @@
/obj/machinery/door/airlock/research
name = "Research Airlock"
- assembly_type = /obj/structure/door_assembly/door_assembly_research
+ assembly_type = /obj/structure/door_assembly/research
open_sound_powered = 'sound/machines/door/sci1o.ogg'
close_sound_powered = 'sound/machines/door/sci1c.ogg'
door_color = COLOR_WHITE
@@ -340,7 +340,7 @@
maxhealth = 300
explosion_resistance = 5
opacity = 0
- assembly_type = /obj/structure/door_assembly/door_assembly_research
+ assembly_type = /obj/structure/door_assembly/research
glass = 1
req_one_access = list(ACCESS_SCIENCE_MAIN)
open_sound_powered = 'sound/machines/door/sci1o.ogg'
@@ -355,7 +355,7 @@
maxhealth = 300
explosion_resistance = 5
opacity = 0
- assembly_type = /obj/structure/door_assembly/door_assembly_min
+ assembly_type = /obj/structure/door_assembly/mining
glass = 1
req_one_access = list(ACCESS_SUPPLY_MINE)
open_sound_powered = 'sound/machines/door/cgo1o.ogg'
@@ -370,7 +370,7 @@
maxhealth = 300
explosion_resistance = 5
opacity = 0
- assembly_type = /obj/structure/door_assembly/door_assembly_atmo
+ assembly_type = /obj/structure/door_assembly/atmos
glass = 1
req_one_access = list(ACCESS_ENGINEERING_ATMOS)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
@@ -449,7 +449,7 @@
fill_file = 'icons/obj/doors/secure/fill_steel.dmi'
explosion_resistance = 20
secured_wires = 1
- assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity
+ assembly_type = /obj/structure/door_assembly/high_security
req_one_access = list(ACCESS_COMMAND_VAULT)
open_sound_powered = 'sound/machines/door/secure1o.ogg'
close_sound_powered = 'sound/machines/door/secure1c.ogg'
@@ -460,13 +460,13 @@
explosion_resistance = 20
opacity = 0
glass = 1
- assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft
+ assembly_type = /obj/structure/door_assembly/voidcraft
open_sound_powered = 'sound/machines/door/shuttle1o.ogg'
close_sound_powered = 'sound/machines/door/shuttle1c.ogg'
// Airlock opens from top-bottom instead of left-right.
/obj/machinery/door/airlock/voidcraft/vertical
- assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft/vertical
+ assembly_type = /obj/structure/door_assembly/voidcraft/vertical
open_sound_powered = 'sound/machines/door/shuttle1o.ogg'
close_sound_powered = 'sound/machines/door/shuttle1c.ogg'
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index 259293a41609..3466422bb227 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -14,20 +14,10 @@
max_amount = 60
attack_verb = list("hit", "bludgeoned", "whacked")
-/obj/item/stack/rods/cyborg
- name = "metal rod synthesizer"
- desc = "A device that makes metal rods."
- gender = NEUTER
- materials = null
- uses_charge = 1
- charge_costs = list(500)
- stacktype = /obj/item/stack/rods
- no_variants = TRUE
-
-/obj/item/stack/rods/Initialize(mapload, new_amount, merge)
- . = ..()
- recipes = rods_recipes
- update_icon()
+/obj/item/stack/rods/generate_explicit_recipes()
+ . = list()
+ . += create_stack_recipe_datum(name = "grille", product = /obj/structure/grille, cost = 2, time = 1 SECONDS)
+ . += create_stack_recipe_datum(name = "catwalk", product = /obj/structure/catwalk, cost = 2, time = 1 SECONDS)
/obj/item/stack/rods/update_icon()
var/amount = get_amount()
@@ -36,10 +26,6 @@
else
icon_state = "rods"
-var/global/list/datum/stack_recipe/rods_recipes = list( \
- new/datum/stack_recipe("grille", /obj/structure/grille, 2, time = 10, one_per_turf = 1, on_floor = 0),
- new/datum/stack_recipe("catwalk", /obj/structure/catwalk, 2, time = 80, one_per_turf = 1, on_floor = 1))
-
/obj/item/stack/rods/attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/weldingtool))
var/obj/item/weldingtool/WT = W
@@ -72,39 +58,12 @@ var/global/list/datum/stack_recipe/rods_recipes = list( \
..()
-/*
-/obj/item/stack/rods/attack_self(mob/user)
- . = ..()
- if(.)
- return
- src.add_fingerprint(user)
-
- if(!istype(user.loc,/turf)) return 0
-
- if (locate(/obj/structure/grille, usr.loc))
- for(var/obj/structure/grille/G in usr.loc)
- if (G.destroyed)
- G.health = 10
- G.density = 1
- G.destroyed = 0
- G.icon_state = "grille"
- use(1)
- else
- return 1
-
- else if(!in_use)
- if(get_amount() < 2)
- to_chat(user, "You need at least two rods to do this.")
- return
- to_chat(usr, "Assembling grille...")
- in_use = 1
- if (!do_after(usr, 10))
- in_use = 0
- return
- var/obj/structure/grille/F = new /obj/structure/grille/ ( usr.loc )
- to_chat(usr, "You assemble a grille")
- in_use = 0
- F.add_fingerprint(usr)
- use(2)
- return
-*/
+/obj/item/stack/rods/cyborg
+ name = "metal rod synthesizer"
+ desc = "A device that makes metal rods."
+ gender = NEUTER
+ materials = null
+ uses_charge = 1
+ charge_costs = list(500)
+ stacktype = /obj/item/stack/rods
+ no_variants = TRUE
diff --git a/code/game/objects/items/stacks/sandbag.dm b/code/game/objects/items/stacks/sandbag.dm
index 9f363cb3ebec..4330b035015d 100644
--- a/code/game/objects/items/stacks/sandbag.dm
+++ b/code/game/objects/items/stacks/sandbag.dm
@@ -64,7 +64,6 @@
/obj/item/stack/sandbags/Initialize(mapload, new_amount, merge)
. = ..()
- recipes = sandbags_recipes
update_icon()
/obj/item/stack/sandbags/update_icon()
@@ -76,8 +75,9 @@
else
icon_state = "sandbags"
-var/global/list/datum/stack_recipe/sandbags_recipes = list( \
- new/datum/stack_recipe("sandbag barricade", /obj/structure/sandbag, 10, one_per_turf = 1, on_floor = 1))
+/obj/item/stack/sandbags/generate_explicit_recipes()
+ . = list()
+ . += create_stack_recipe_datum(name = "sandbag barricade", product = /obj/structure/sandbag, cost = 7, time = 1.5 SECONDS)
/obj/item/stack/sandbags/attackby(var/obj/item/W, var/mob/user)
if(is_sharp(W))
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index ddb070824b4e..01672bce30b0 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -1,27 +1,14 @@
/**
- * Stack type objects!
- *
- * Contains:
- * * Stacks
- * * Recipe datum
- * * Recipe list datum
+ * Items that can stack, tracking the number of which is in it
*/
-
-/*
- * Stacks
- */
-
/obj/item/stack
gender = PLURAL
origin_tech = list(TECH_MATERIAL = 1)
icon = 'icons/obj/stacks.dmi'
- var/list/datum/stack_recipe/recipes
var/singular_name
var/amount = 1
/// See stack recipes initialisation, param "max_res_amount" must be equal to this max_amount.
var/max_amount = 50
- /// bandaid until new inventorycode
- var/mid_delete = FALSE
/// Determines whether different stack types can merge.
var/stacktype
/// Used when directly applied to a turf.
@@ -37,7 +24,14 @@
/// Will the stack merge with other stacks that are different colors? (Dyed cloth, wood, etc).
var/strict_color_stacking = FALSE
+ /// explicit recipes, lazy-list. this is typelist'd
+ var/list/datum/stack_recipe/explicit_recipes
+
/obj/item/stack/Initialize(mapload, new_amount, merge = TRUE)
+ if(has_typelist(explicit_recipes))
+ explicit_recipes = get_typelist(explicit_recipes)
+ else
+ explicit_recipes = typelist(NAMEOF(src, explicit_recipes), generate_explicit_recipes())
if(new_amount != null)
amount = new_amount
if(!stacktype)
@@ -49,12 +43,6 @@
merge(S)
update_icon()
-/obj/item/stack/Destroy()
- if (src && usr && usr.machine == src)
- usr << browse(null, "window=stack")
- mid_delete = TRUE
- return ..()
-
/obj/item/stack/update_icon()
if(no_variants)
icon_state = initial(icon_state)
@@ -74,145 +62,72 @@
else
. += "There is enough charge for [get_amount()]."
-/obj/item/stack/attack_self(mob/user)
- . = ..()
- if(.)
- return
- list_recipes(user)
-
-/obj/item/stack/proc/list_recipes(mob/user, recipes_sublist)
- if (!recipes)
- return
- if (!src || get_amount() <= 0)
- user << browse(null, "window=stack")
- user.set_machine(src) //for correct work of onclose
- var/list/recipe_list = recipes
- if (recipes_sublist && recipe_list[recipes_sublist] && istype(recipe_list[recipes_sublist], /datum/stack_recipe_list))
- var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
- recipe_list = srl.recipes
- var/t1 = "
Constructions from [src]Amount Left: [get_amount()]
"
- for(var/i=1;i<=recipe_list.len,i++)
- var/E = recipe_list[i]
- if (isnull(E))
- t1 += "
"
- continue
+/**
+ * Get the explicit recipes of this stack type
+ */
+/obj/item/stack/proc/generate_explicit_recipes()
+ return list()
- if (i>1 && !isnull(recipe_list[i-1]))
- t1+="
"
-
- if (istype(E, /datum/stack_recipe_list))
- var/datum/stack_recipe_list/srl = E
- t1 += "[srl.title]"
-
- if (istype(E, /datum/stack_recipe))
- var/datum/stack_recipe/R = E
- var/max_multiplier = round(src.get_amount() / R.req_amount)
- var/title
- var/can_build = 1
- can_build = can_build && (max_multiplier>0)
- if (R.res_amount>1)
- title+= "[R.res_amount]x [R.title]\s"
- else
- title+= "[R.title]"
- title+= " ([R.req_amount] [src.singular_name]\s)"
- if (can_build)
- t1 += "[title] "
- else
- t1 += title
- continue
- if (R.max_res_amount>1 && max_multiplier>1)
- max_multiplier = min(max_multiplier, round(R.max_res_amount/R.res_amount))
- t1 += " |"
- var/list/multipliers = list(5,10,25)
- for (var/n in multipliers)
- if (max_multiplier>=n)
- t1 += " [n*R.res_amount]x"
- if (!(max_multiplier in multipliers))
- t1 += " [max_multiplier*R.res_amount]x"
-
- t1 += ""
- user << browse(t1, "window=stack")
- onclose(user, "stack")
- return
-
-/obj/item/stack/proc/produce_recipe(datum/stack_recipe/recipe, quantity, mob/user)
- var/required = quantity*recipe.req_amount
- var/produced = min(quantity*recipe.res_amount, recipe.max_res_amount)
-
- if (!can_use(required))
- if (produced>1)
- to_chat(user, SPAN_WARNING("You haven't got enough [src] to build \the [produced] [recipe.title]\s!"))
- else
- to_chat(user, SPAN_WARNING("You haven't got enough [src] to build \the [recipe.title]!"))
- return
+/obj/item/stack/ui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(isnull(ui))
+ ui = new(user, src, "StackCrafting")
+ ui.open()
- if (recipe.one_per_turf && (locate(recipe.result_type) in user.loc))
- to_chat(user, SPAN_WARNING("There is another [recipe.title] here!"))
- return
+/obj/item/stack/ui_static_data(mob/user, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ .["recipes"] = tgui_recipes()
+ .["maxAmount"] = max_amount
+ .["name"] = name
- if (recipe.on_floor && !isfloor(user.loc))
- to_chat(user, SPAN_WARNING("\The [recipe.title] must be constructed on the floor!"))
- return
+/obj/item/stack/proc/tgui_recipes()
+ var/list/assembled = list()
+ for(var/datum/stack_recipe/recipe as anything in explicit_recipes)
+ assembled[++assembled.len] = recipe.tgui_recipe_data()
+ return assembled
- if (recipe.time)
- to_chat(user, SPAN_NOTICE("Building [recipe.title] ..."))
- if (!do_after(user, recipe.time))
- return
+/obj/item/stack/ui_data(mob/user, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ .["amount"] = get_amount()
- if (use(required))
- var/atom/O
- if(ispath(recipe.result_type, /obj/item/stack))
- O = new recipe.result_type(user.drop_location(), produced)
- else if(recipe.use_material)
- O = new recipe.result_type(user.drop_location(), recipe.use_material)
- else
- O = new recipe.result_type(user.drop_location())
- O.setDir(user.dir)
- O.add_fingerprint(user)
-
- if (istype(O, /obj/item/storage)) //BubbleWrap - so newly formed boxes are empty
- for (var/obj/item/I in O)
- qdel(I)
-
- if ((pass_color || recipe.pass_color))
- if(!color)
- if(recipe.use_material)
- var/datum/material/MAT = get_material_by_name(recipe.use_material)
- if(MAT.icon_colour)
- O.color = MAT.icon_colour
- else
- return
- else
- O.color = color
-
-/obj/item/stack/Topic(href, href_list)
- ..()
- if ((usr.restrained() || usr.stat || usr.get_active_held_item() != src))
+/obj/item/stack/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
return
+ switch(action)
+ if("craft")
+ var/recipe_ref = params["recipe"]
+ if(!istext(recipe_ref))
+ return TRUE
+ var/datum/stack_recipe/recipe = locate(recipe_ref)
+ if(!can_craft_recipe(recipe))
+ return TRUE
+ var/make_amount = params["amount"]
+ craft_recipe(recipe, usr, make_amount)
+ return TRUE
- if (href_list["sublist"] && !href_list["make"])
- list_recipes(usr, text2num(href_list["sublist"]))
-
- if (href_list["make"])
- if (src.get_amount() < 1) qdel(src) //Never should happen
-
- var/list/recipes_list = recipes
- if (href_list["sublist"])
- var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])]
- recipes_list = srl.recipes
-
- var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
- var/multiplier = text2num(href_list["multiplier"])
- if (!multiplier || (multiplier <= 0)) //href exploit protection
- return
-
- src.produce_recipe(R, multiplier, usr)
+/obj/item/stack/proc/can_craft_recipe(datum/stack_recipe/recipe)
+ if(recipe in explicit_recipes)
+ return TRUE
+ return FALSE
- if (src && usr.machine==src) //do not reopen closed window
- spawn( 0 )
- src.interact(usr)
- return
- return
+/obj/item/stack/proc/craft_recipe(datum/stack_recipe/recipe, mob/user, make_amount)
+ if(make_amount > (isnull(recipe.max_amount)? (recipe.result_is_stack? INFINITY : 1) : recipe.max_amount))
+ return FALSE
+ var/needed = recipe.cost * (make_amount / recipe.result_amount)
+ if(FLOOR(needed, 1) != needed) // no decimals, thank you!
+ return FALSE
+ if(needed > get_amount())
+ return FALSE
+ var/turf/where = get_turf(user)
+ if(!do_after(user, recipe.time, src, progress_anchor = user))
+ return FALSE
+ if(needed > get_amount())
+ return FALSE
+ if(!recipe.craft(where, make_amount, src, user, FALSE, user.dir))
+ return FALSE
+ log_stackcrafting(user, src, recipe.name, make_amount, needed, where)
+ use(needed)
/**
* Return 1 if an immediate subsequent call to use() would succeed.
@@ -229,8 +144,6 @@
/obj/item/stack/proc/can_merge(obj/item/stack/other)
if(!istype(other))
return FALSE
- if(mid_delete || other.mid_delete) // bandaid until new inventory code
- return FALSE
if((strict_color_stacking || other.strict_color_stacking) && (color != other.color))
return FALSE
return other.stacktype == stacktype
@@ -241,7 +154,6 @@
if(!uses_charge)
amount -= used
if (amount <= 0)
- mid_delete = TRUE
qdel(src) //should be safe to qdel immediately since if someone is still using this stack it will persist for a little while longer
update_icon()
return TRUE
@@ -451,46 +363,6 @@
if(from.fingerprintslast)
fingerprintslast = from.fingerprintslast
-/*
- * Recipe datum
- */
-/datum/stack_recipe
- var/title = "ERROR"
- var/result_type
- /// Amount of material needed for this recipe.
- var/req_amount = 1
- /// Amount of stuff that is produced in one batch (e.g. 4 for floor tiles).
- var/res_amount = 1
- var/max_res_amount = 1
- var/time = 0
- var/one_per_turf = 0
- var/on_floor = 0
- var/use_material
- var/pass_color
-
-/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, pass_stack_color)
- src.title = title
- src.result_type = result_type
- src.req_amount = req_amount
- src.res_amount = res_amount
- src.max_res_amount = max_res_amount
- src.time = time
- src.one_per_turf = one_per_turf
- src.on_floor = on_floor
- src.use_material = supplied_material
- src.pass_color = pass_stack_color
-
-/*
- * Recipe list datum
- */
-/datum/stack_recipe_list
- var/title = "ERROR"
- var/list/recipes = null
-
-/datum/stack_recipe_list/New(title, recipes)
- src.title = title
- src.recipes = recipes
-
/obj/item/stack/proc/set_amount(new_amount, no_limits = FALSE)
if(new_amount < 0 || new_amount % 1)
stack_trace("Tried to set a bad stack amount: [new_amount]")
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index ef6d74c5c5ab..67f45a197ea1 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -41,28 +41,24 @@
drop_sound = 'sound/items/drop/herb.ogg'
pickup_sound = 'sound/items/pickup/herb.ogg'
-/obj/item/stack/tile/grass/Initialize(mapload, new_amount, merge)
- . = ..()
- recipes = grass_recipes
- update_icon()
-
-var/global/list/datum/stack_recipe/grass_recipes = list( \
- new/datum/stack_recipe("bush", /obj/structure/flora/ausbushes, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("reeds", /obj/structure/flora/ausbushes/reedbush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("leafy bush", /obj/structure/flora/ausbushes/leafybush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("sparse bush", /obj/structure/flora/ausbushes/palebush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("stalks", /obj/structure/flora/ausbushes/stalkybush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("ferns", /obj/structure/flora/ausbushes/fernybush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("sapling", /obj/structure/flora/ausbushes/sunnybush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("leafy sapling", /obj/structure/flora/ausbushes/genericbush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("needled sapling", /obj/structure/flora/ausbushes/pointybush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("sparse flowers", /obj/structure/flora/ausbushes/lavendergrass, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("yellow flowers", /obj/structure/flora/ausbushes/ywflowers, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("colorful flowers", /obj/structure/flora/ausbushes/brflowers, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("purple flowers", /obj/structure/flora/ausbushes/ppflowers, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("lush grass", /obj/structure/flora/ausbushes/grassybush, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("grass", /obj/structure/flora/ausbushes/fullgrass, 1, one_per_turf = 0, on_floor = 1),
- new/datum/stack_recipe("sparse grass", /obj/structure/flora/ausbushes/sparsegrass, 1, one_per_turf = 0, on_floor = 1))
+/obj/item/stack/tile/grass/generate_explicit_recipes()
+ . = list()
+ . += create_stack_recipe_datum(name = "bush", product = /obj/structure/flora/ausbushes, cost = 1)
+ . += create_stack_recipe_datum(name = "reeds", product = /obj/structure/flora/ausbushes/reedbush, cost = 1)
+ . += create_stack_recipe_datum(name = "leafy bush", product = /obj/structure/flora/ausbushes/leafybush, cost = 1)
+ . += create_stack_recipe_datum(name = "sparse bush", product = /obj/structure/flora/ausbushes/palebush, cost = 1)
+ . += create_stack_recipe_datum(name = "stalks", product = /obj/structure/flora/ausbushes/stalkybush, cost = 1)
+ . += create_stack_recipe_datum(name = "ferns", product = /obj/structure/flora/ausbushes/fernybush, cost = 1)
+ . += create_stack_recipe_datum(name = "sapling", product = /obj/structure/flora/ausbushes/sunnybush, cost = 1)
+ . += create_stack_recipe_datum(name = "leafy sapling", product = /obj/structure/flora/ausbushes/genericbush, cost = 1)
+ . += create_stack_recipe_datum(name = "needled sapling", product = /obj/structure/flora/ausbushes/pointybush, cost = 1)
+ . += create_stack_recipe_datum(name = "sparse flowers", product = /obj/structure/flora/ausbushes/lavendergrass, cost = 1)
+ . += create_stack_recipe_datum(name = "yellow flowers", product = /obj/structure/flora/ausbushes/ywflowers, cost = 1)
+ . += create_stack_recipe_datum(name = "colorful flowers", product = /obj/structure/flora/ausbushes/brflowers, cost = 1)
+ . += create_stack_recipe_datum(name = "purple flowers", product = /obj/structure/flora/ausbushes/ppflowers, cost = 1)
+ . += create_stack_recipe_datum(name = "lush grass", product = /obj/structure/flora/ausbushes/grassybush, cost = 1)
+ . += create_stack_recipe_datum(name = "grass", product = /obj/structure/flora/ausbushes/fullgrass, cost = 1)
+ . += create_stack_recipe_datum(name = "sparse grass", product = /obj/structure/flora/ausbushes/sparsegrass, cost = 1)
/*
* Wood
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
index c9b9b6f22150..b3abfa415914 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
@@ -79,6 +79,7 @@
/obj/item/flashlight/lantern,
/obj/item/shovel,
/obj/item/pickaxe,
+ /obj/item/mining_scanner,
/obj/item/gps/mining,
/obj/item/survivalcapsule,
/obj/item/clothing/glasses/material,
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index 7a0999e4abac..06d430e6acfd 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -18,43 +18,43 @@
. = ..()
update_state()
-/obj/structure/door_assembly/door_assembly_com
+/obj/structure/door_assembly/command
base_icon_state = "com"
base_name = "Command airlock"
glass_type = "/glass_command"
airlock_type = "/command"
-/obj/structure/door_assembly/door_assembly_sec
+/obj/structure/door_assembly/security
base_icon_state = "sec"
base_name = "Security airlock"
glass_type = "/glass/security"
airlock_type = "/security"
-/obj/structure/door_assembly/door_assembly_eng
+/obj/structure/door_assembly/engi
base_icon_state = "eng"
base_name = "Engineering airlock"
glass_type = "/glass_engineering"
airlock_type = "/engineering"
-/obj/structure/door_assembly/door_assembly_eat
+/obj/structure/door_assembly/engi_atmos
base_icon_state = "eat"
base_name = "Engineering atmos airlock"
glass_type = "/glass_engineeringatmos"
airlock_type = "/engineering"
-/obj/structure/door_assembly/door_assembly_min
+/obj/structure/door_assembly/mining
base_icon_state = "min"
base_name = "Mining airlock"
glass_type = "/glass_mining"
airlock_type = "/mining"
-/obj/structure/door_assembly/door_assembly_atmo
+/obj/structure/door_assembly/atmos
base_icon_state = "atmo"
base_name = "Atmospherics airlock"
glass_type = "/glass_atmos"
airlock_type = "/atmos"
-/obj/structure/door_assembly/door_assembly_research
+/obj/structure/door_assembly/research
base_icon_state = "res"
base_name = "Research airlock"
glass_type = "/glass_research"
@@ -66,55 +66,55 @@
glass_type = "/glass_science"
airlock_type = "/science"
-/obj/structure/door_assembly/door_assembly_med
+/obj/structure/door_assembly/medical
base_icon_state = "med"
base_name = "Medical airlock"
glass_type = "/glass/medical"
airlock_type = "/medical"
-/obj/structure/door_assembly/door_assembly_ext
+/obj/structure/door_assembly/external
base_icon_state = "ext"
base_name = "External airlock"
glass_type = "/glass_external"
airlock_type = "/external"
-/obj/structure/door_assembly/door_assembly_mai
+/obj/structure/door_assembly/maint
base_icon_state = "mai"
base_name = "Maintenance airlock"
airlock_type = "/maintenance"
glass = -1
-/obj/structure/door_assembly/door_assembly_fre
+/obj/structure/door_assembly/freezer
base_icon_state = "fre"
base_name = "Freezer airlock"
airlock_type = "/freezer"
glass = -1
-/obj/structure/door_assembly/door_assembly_hatch
+/obj/structure/door_assembly/hatch
base_icon_state = "hatch"
base_name = "airtight hatch"
airlock_type = "/hatch"
glass = -1
-/obj/structure/door_assembly/door_assembly_mhatch
+/obj/structure/door_assembly/hatch/maint
base_icon_state = "mhatch"
base_name = "maintenance hatch"
airlock_type = "/maintenance_hatch"
glass = -1
-/obj/structure/door_assembly/door_assembly_highsecurity // Borrowing this until WJohnston makes sprites for the assembly
+/obj/structure/door_assembly/high_security // Borrowing this until WJohnston makes sprites for the assembly
base_icon_state = "highsec"
base_name = "high security airlock"
airlock_type = "/highsecurity"
glass = -1
-/obj/structure/door_assembly/door_assembly_voidcraft
+/obj/structure/door_assembly/voidcraft
base_icon_state = "voidcraft"
base_name = "voidcraft hatch"
airlock_type = "/voidcraft"
glass = -1
-/obj/structure/door_assembly/door_assembly_voidcraft/vertical
+/obj/structure/door_assembly/voidcraft/vertical
base_icon_state = "voidcraft_vertical"
airlock_type = "/voidcraft/vertical"
diff --git a/code/game/objects/structures/simple_doors.dm b/code/game/objects/structures/simple_doors.dm
index 4c645033c62f..34bd898ee8c4 100644
--- a/code/game/objects/structures/simple_doors.dm
+++ b/code/game/objects/structures/simple_doors.dm
@@ -24,7 +24,7 @@
. = ..(mapload)
if(!material_name)
material_name = MAT_STEEL
- material = get_material_by_name(material_name)
+ material = istype(material_name, /datum/material)? material_name : SSmaterials.get_material(material_name)
if(!material)
qdel(src)
return
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index c615c6156d13..04ba9ac0b81a 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -1,4 +1,6 @@
//Ported from Cit Main.
+// todo: refactor into sculpting, with categories/free choice of material & greyscaling
+// todo: generate job state icons off of a given sprite, or off of their outfit
/obj/structure/statue
name = "Statue"
desc = "Placeholder. Yell at Firecage if you SOMEHOW see this."
diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm
index 34b6eab7d171..94444cd90324 100644
--- a/code/game/turfs/simulated/wall_types.dm
+++ b/code/game/turfs/simulated/wall_types.dm
@@ -232,21 +232,21 @@
icon_state = "wood"
color = "#9c5930"
- material = /datum/material/wood
+ material = /datum/material/wood_plank
reinf_material = null
girder_material = null
/turf/simulated/wall/wood/sifwood
color = "#0099cc"
- material = /datum/material/wood/sif
+ material = /datum/material/wood_plank/sif
reinf_material = null
girder_material = null
/turf/simulated/wall/wood/hardwood
color = "#42291a"
- material = /datum/material/wood/hardwood
+ material = /datum/material/wood_plank/hardwood
reinf_material = null
girder_material = null
@@ -254,7 +254,7 @@
icon = 'icons/turf/walls/log.dmi'
color = "#9c5930"
- material = /datum/material/wood/log
+ material = /datum/material/wood_log
reinf_material = null
girder_material = null
@@ -262,7 +262,7 @@
icon = 'icons/turf/walls/log.dmi'
color = "#0099cc"
- material = /datum/material/wood/log/sif
+ material = /datum/material/wood_log/sif
reinf_material = null
girder_material = null
diff --git a/code/modules/cargo/supplypacks/voidsuits.dm b/code/modules/cargo/supplypacks/voidsuits.dm
index f865e5665f2b..9cf2f443098f 100644
--- a/code/modules/cargo/supplypacks/voidsuits.dm
+++ b/code/modules/cargo/supplypacks/voidsuits.dm
@@ -395,3 +395,60 @@
container_type = /obj/structure/closet/crate/secure/nanotrasen
container_name = "Mining cryosuit crate"
access = ACCESS_SUPPLY_MINE
+
+//ODST Suits
+
+/datum/supply_pack/voidsuits/odst
+ name = "Hephaestus Icarus Combat Suits"
+ contains = list(
+ /obj/item/clothing/suit/space/void/odst = 2,
+ /obj/item/clothing/head/helmet/space/void/odst = 2,
+ /obj/item/clothing/mask/breath = 2,
+ /obj/item/clothing/shoes/magboots = 2,
+ /obj/item/tank/oxygen = 2
+ )
+ cost = 40
+ container_type = /obj/structure/closet/crate/secure/heph
+ container_name = "Icarus Combat Suit crate"
+
+/datum/supply_pack/voidsuits/odst_med
+ name = "Hephaestus Icarus Medic Suits"
+ contains = list(
+ /obj/item/clothing/suit/space/void/odst_med = 2,
+ /obj/item/clothing/head/helmet/space/void/odst_med = 2,
+ /obj/item/clothing/mask/breath = 2,
+ /obj/item/clothing/shoes/magboots = 2,
+ /obj/item/tank/oxygen = 2
+ )
+ cost = 60
+ container_type = /obj/structure/closet/crate/secure/heph
+ container_name = "Hephaestheus Icarus Medic crate"
+ access = ACCESS_MEDICAL_EQUIPMENT
+
+/datum/supply_pack/voidsuits/odst_eng
+ name = "Hephaestus Icarus Engineer Suits"
+ contains = list(
+ /obj/item/clothing/suit/space/void/odst_eng = 2,
+ /obj/item/clothing/head/helmet/space/void/odst_eng = 2,
+ /obj/item/clothing/mask/breath = 2,
+ /obj/item/clothing/shoes/magboots = 2,
+ /obj/item/tank/oxygen = 2
+ )
+ cost = 40
+ container_type = /obj/structure/closet/crate/secure/heph
+ container_name = "Hephaestheus Icarus Engineer crate"
+ access = ACCESS_ENGINEERING_ENGINE
+
+/datum/supply_pack/voidsuits/odst_exp
+ name = "Hephaestus Icarus Frontier Suits"
+ contains = list(
+ /obj/item/clothing/suit/space/void/odst_exp = 2,
+ /obj/item/clothing/head/helmet/space/void/odst_exp = 2,
+ /obj/item/clothing/mask/breath = 3,
+ /obj/item/clothing/shoes/magboots = 3,
+ /obj/item/tank/oxygen = 3
+ )
+ cost = 50
+ container_type = /obj/structure/closet/crate/secure/heph
+ container_name = "Hephaestheus Icarus Frontier crate"
+ access = ACCESS_GENERAL_EXPLORER
diff --git a/code/modules/clothing/spacesuits/void/merc.dm b/code/modules/clothing/spacesuits/void/merc.dm
index 84d6c50b2110..ce0633dcfaa4 100644
--- a/code/modules/clothing/spacesuits/void/merc.dm
+++ b/code/modules/clothing/spacesuits/void/merc.dm
@@ -91,3 +91,121 @@
armor_type = /datum/armor/merc/space/clown
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
siemens_coefficient = 0.6
+
+//Four below avalible through cargo
+
+/obj/item/clothing/head/helmet/space/void/odst
+ name = "hephaestus icarus helmet"
+ desc = "One of the few combat-grade helmets avalible in the frontier, and the poster-child of Hephaestus Industries."
+ icon_state = "odst"
+ armor_type = /datum/armor/station/secsuit
+ siemens_coefficient = 0.6
+ camera_networks = list(NETWORK_EXPLO_HELMETS)
+ species_restricted = null
+
+/obj/item/clothing/suit/space/void/odst
+ icon_state = "odst"
+ name = "hephaestus icarus suit"
+ desc = "One of the few combat-grade suits avalible in the frontier, and the poster-child of Hephaestus Industries. Comes equipped with a wrist-bound oxygen timer."
+ slowdown = 1
+ w_class = ITEMSIZE_NORMAL
+ armor_type = /datum/armor/station/secsuit
+ allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
+ siemens_coefficient = 0.6
+ species_restricted = null
+
+/obj/item/clothing/head/helmet/space/void/odst_med
+ name = "hephaestus icarus medic helmet"
+ desc = "Part of the Icarus Medic suit."
+ icon_state = "odst_mil"
+ armor_type = /datum/armor/exploration/space
+ siemens_coefficient = 0.6
+ camera_networks = list(NETWORK_EXPLO_HELMETS)
+ species_restricted = null
+
+/obj/item/clothing/suit/space/void/odst_med
+ icon_state = "odst_corps"
+ name = "hephaestus icarus medic suit"
+ desc = "A standard Icarus line suit that has been repourposed to protect from heavier biohazards."
+ slowdown = 1
+ w_class = ITEMSIZE_NORMAL
+ armor_type = /datum/armor/exploration/space
+ allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
+ siemens_coefficient = 0.6
+ species_restricted = null
+
+/obj/item/clothing/head/helmet/space/void/odst_eng
+ name = "hephaestus icarus engineer helmet"
+ desc = "Part of the Icarus Engineer suit."
+ icon_state = "odst_orange"
+ armor_type = /datum/armor/engineering/space
+ siemens_coefficient = 0.6
+ camera_networks = list(NETWORK_EXPLO_HELMETS)
+ species_restricted = null
+
+/obj/item/clothing/suit/space/void/odst_eng
+ icon_state = "odst_orange"
+ name = "hephaestus icarus engineer suit"
+ desc = "Favoured suit of deep-space engineers, comfortable and comparable to suits avalible to NanoTrasen Engineers. Comes equipped with a wrist-bound oxygen timer."
+ slowdown = 1
+ w_class = ITEMSIZE_NORMAL
+ armor_type = /datum/armor/engineering/space
+ allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
+ siemens_coefficient = 0.6
+ species_restricted = null
+
+/obj/item/clothing/head/helmet/space/void/odst_exp
+ name = "hephaestus icarus frontier helmet"
+ desc = "Part of the Icarus Frontier suit."
+ icon_state = "odst_purple"
+ armor_type = /datum/armor/exploration/space
+ siemens_coefficient = 0.6
+ camera_networks = list(NETWORK_EXPLO_HELMETS)
+ species_restricted = null
+
+/obj/item/clothing/suit/space/void/odst_exp
+ icon_state = "odst_purple"
+ name = "hephaestus icarus frontier suit"
+ desc = "Cheaper version of the main Icarus line, often marketed to Frontier settlements. Perfect for Expeditions."
+ slowdown = 1
+ w_class = ITEMSIZE_NORMAL
+ armor_type = /datum/armor/exploration/space
+ allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
+ siemens_coefficient = 0.6
+ species_restricted = null
+
+// Admin spawn only, Necropolis Industries event gear
+
+/obj/item/clothing/head/helmet/space/void/odst_necro
+ name = "necropolis operations helmet"
+ desc = "Part of the Operations suit. Equipped with IFF sensors that send information directly to the user's implants."
+ icon_state = "odst_red"
+ item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndie_helm", SLOT_ID_LEFT_HAND = "syndie_helm")
+ armor_type = /datum/armor/merc/space
+ siemens_coefficient = 0.6
+ camera_networks = list(NETWORK_MERCENARY)
+ species_restricted = null
+
+/obj/item/clothing/suit/space/void/odst_necro
+ icon_state = "odst_red"
+ name = "necropolis operations suit"
+ desc = "The main suit used by Necropolis Industries security division, a heavily modified Hephaestus Icarus suit emblazoned with the Necropolis logo on the left shoulder. Equipped with direct connections to the user's implants and prosthetics, making it function as a second skin."
+ item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndie_voidsuit", SLOT_ID_LEFT_HAND = "syndie_voidsuit")
+ slowdown = 0.4
+ w_class = ITEMSIZE_NORMAL
+ armor_type = /datum/armor/merc/space
+ allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
+ siemens_coefficient = 0.6
+ species_restricted = null
+
+/obj/item/clothing/suit/space/void/odst_necromed
+ icon_state = "odst_red_mil"
+ name = "necropolis field medic suit"
+ desc = "The main suit used by Necropolis Industries security division, a heavily modified Hephaestheus Icarus suit emblazoned with the Necropolis logo on the left shoulder and a blue cross on the right arm. Equipped with direct connections to the user's implants and prosthetics, making it function as a second skin."
+ item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndie_voidsuit", SLOT_ID_LEFT_HAND = "syndie_voidsuit")
+ slowdown = 0.4
+ w_class = ITEMSIZE_NORMAL
+ armor_type = /datum/armor/merc/space
+ allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
+ siemens_coefficient = 0.6
+ species_restricted = null
diff --git a/code/modules/food/food/cans.dm b/code/modules/food/food/cans.dm
index 037cdfdfb411..38b726b7213c 100644
--- a/code/modules/food/food/cans.dm
+++ b/code/modules/food/food/cans.dm
@@ -139,7 +139,7 @@
/obj/item/reagent_containers/food/drinks/cans/ramune/Initialize(mapload)
. = ..()
- reagents.add_reagent("ramune", 20)
+ reagents.add_reagent("ramune", 30)
/obj/item/reagent_containers/food/drinks/cans/starkist
name = "\improper Star-kist"
diff --git a/code/modules/jobs/job_types/station/command/command_secretary.dm b/code/modules/jobs/job_types/station/command/command_secretary.dm
index f3a61ded4cec..1cc5f5e8d9fb 100644
--- a/code/modules/jobs/job_types/station/command/command_secretary.dm
+++ b/code/modules/jobs/job_types/station/command/command_secretary.dm
@@ -1,6 +1,6 @@
/datum/role/job/station/command_secretary
id = JOB_ID_COMMAND_SECRETARY
- title = "Command Secretary"
+ title = "Bridge Officer"
economy_payscale = ECONOMY_PAYSCALE_JOB_HELM
flag = BRIDGE
departments = list(DEPARTMENT_COMMAND)
@@ -20,9 +20,9 @@
ACCESS_ENGINEERING_MAINT,
)
- outfit_type = /datum/outfit/job/station/command_secretary
- desc = "A Command Secretary handles paperwork duty for the Heads of Staff, so they can better focus on managing their departments. \
- They are not Heads of Staff, and have no real authority."
+ outfit_type = /datum/outfit/job/station/command_secretary/bridge_officer
+ desc = "A bridge officer is often considered command staff in-training. Their duties are to assist the command staff with things like paperwork, \
+ as well as to assist in piloting the ship when deemed necessary and applicable."
alt_titles = list(
"Command Liaison" = /datum/prototype/struct/alt_title/command_liaison,
@@ -30,27 +30,33 @@
"Command Assistant" = /datum/prototype/struct/alt_title/command_assistant,
"Command Intern" = /datum/prototype/struct/alt_title/command_intern,
"Helmsman" = /datum/prototype/struct/alt_title/commsec/helmsman,
- "Bridge Officer" = /datum/prototype/struct/alt_title/commsec/officer
+ "Command Secretary" = /datum/prototype/struct/alt_title/commsec/actually_commsec
)
+//! todo: WHY DO WE HAVE SO MANY GET RID OF THEM
+
/datum/prototype/struct/alt_title/command_liaison
title = "Command Liaison"
+ title_outfit = /datum/outfit/job/station/command_secretary
/datum/prototype/struct/alt_title/bridge_secretary
title = "Bridge Secretary"
+ title_outfit = /datum/outfit/job/station/command_secretary
/datum/prototype/struct/alt_title/command_assistant
title = "Command Assistant"
+ title_outfit = /datum/outfit/job/station/command_secretary
/datum/prototype/struct/alt_title/command_intern
title = "Command Intern"
+ title_outfit = /datum/outfit/job/station/command_secretary
/datum/prototype/struct/alt_title/commsec/helmsman
title = "Helmsman"
-/datum/prototype/struct/alt_title/commsec/officer
- title = "Bridge Officer"
- title_outfit = /datum/outfit/job/station/command_secretary/bridge_officer
+/datum/prototype/struct/alt_title/commsec/actually_commsec
+ title = "Command Secretary"
+ title_outfit = /datum/outfit/job/station/command_secretary
/datum/outfit/job/station/command_secretary
name = OUTFIT_JOB_NAME("Command Secretary")
diff --git a/code/modules/lighting/emissive_blocker.dm b/code/modules/lighting/emissive_blocker.dm
index c1fe7906571a..30016883a9b2 100644
--- a/code/modules/lighting/emissive_blocker.dm
+++ b/code/modules/lighting/emissive_blocker.dm
@@ -8,6 +8,7 @@
*/
/atom/movable/emissive_blocker
name = "emissive blocker"
+ atom_flags = ATOM_ABSTRACT
plane = EMISSIVE_PLANE
layer = FLOAT_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
diff --git a/code/modules/lighting/emissive_render.dm b/code/modules/lighting/emissive_render.dm
index bae024a2c630..f911dc31530d 100644
--- a/code/modules/lighting/emissive_render.dm
+++ b/code/modules/lighting/emissive_render.dm
@@ -9,6 +9,7 @@
*/
/atom/movable/emissive_render
name = "emissive render"
+ atom_flags = ATOM_ABSTRACT
plane = EMISSIVE_PLANE
layer = FLOAT_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
diff --git a/code/modules/logging/logging.dm b/code/modules/logging/logging.dm
new file mode 100644
index 000000000000..53ef337d6fec
--- /dev/null
+++ b/code/modules/logging/logging.dm
@@ -0,0 +1,33 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+//! New action logging file. Global helpers for things like attack, construction, say, etc, will go in here. !//
+
+// todo: flesh this file out
+
+/**
+ * Logs a construction action / step
+ *
+ * @params
+ * * target - target
+ * * message - the message
+ */
+/mob/proc/actor_construction_log(atom/target, message)
+ add_construction_logs(src, target, message)
+
+/proc/add_construction_logs(mob/actor, atom/target, message)
+ log_game("LEGACY CONSTRUCTION: [actor] --> [target] ([COORD(target)]): [message]")
+
+// todo: remove above
+
+/**
+ * Log construction action
+ */
+/proc/log_construction(mob/user, atom/target, message)
+ log_game("CONSTRUCTION: [key_name(user)] [COORD(user)] -> [target] [COORD(target)]: [message]")
+
+/**
+ * Log stack crafting
+ */
+/proc/log_stackcrafting(mob/user, obj/item/stack/stack, name, amount, used, turf/where = get_turf(user))
+ log_game("STACKCRAFT: [key_name(user)] crafted [amount] of [name] with [used] of [stack] at [where]")
diff --git a/code/modules/materials/definitions/crystals/diamond.dm b/code/modules/materials/definitions/crystals/diamond.dm
index 7b0effb5d56d..a191ed0afd2d 100644
--- a/code/modules/materials/definitions/crystals/diamond.dm
+++ b/code/modules/materials/definitions/crystals/diamond.dm
@@ -13,3 +13,10 @@
hardness = 100
stack_origin_tech = list(TECH_MATERIAL = 6)
tgui_icon_key = "diamond"
+
+/datum/material/diamond/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(category = "statues", name = "ai hologram statue", product = /obj/structure/statue/diamond/ai1, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "ai core statue", product = /obj/structure/statue/diamond/ai2, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "captain statue", product = /obj/structure/statue/diamond/captain, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(name = "diamond floor tiles", product = /obj/item/stack/tile/diamond, amount = 4)
diff --git a/code/modules/materials/definitions/legacy.dm b/code/modules/materials/definitions/legacy.dm
new file mode 100644
index 000000000000..70cfbfb8bf75
--- /dev/null
+++ b/code/modules/materials/definitions/legacy.dm
@@ -0,0 +1,25 @@
+// todo: these are only here because of tables and other stupid shit that require material for render
+// when that's redone, REMOVE THESE.
+
+// what the fuck?
+/datum/material/darkglass
+ id = "glass_dark"
+ name = "darkglass"
+ display_name = "darkglass"
+ icon_base = "darkglass"
+ icon_colour = "#FFFFFF"
+
+// what the fuck?
+/datum/material/fancyblack
+ id = "black_fancy"
+ name = "fancyblack"
+ display_name = "fancyblack"
+ icon_base = "fancyblack"
+ icon_colour = "#FFFFFF"
+
+// what the fuck?
+/datum/material/alienalloy/alium
+ id = "abductor_alloy"
+ name = "alium"
+ display_name = "alien"
+ icon_colour = "#FFFFFF"
diff --git a/code/modules/materials/definitions/metals/brass.dm b/code/modules/materials/definitions/metals/brass.dm
index b1ac1ba2a61b..7fa552107332 100644
--- a/code/modules/materials/definitions/metals/brass.dm
+++ b/code/modules/materials/definitions/metals/brass.dm
@@ -5,3 +5,7 @@
integrity = 150
stack_type = /obj/item/stack/material/brass
tgui_icon_key = "brass"
+
+/datum/material/brass/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(name = "brass floor tiles", product = /obj/item/stack/tile/brass, amount = 4)
diff --git a/code/modules/materials/definitions/metals/durasteel.dm b/code/modules/materials/definitions/metals/durasteel.dm
index 6a7ce162bd75..bdd38bc11c96 100644
--- a/code/modules/materials/definitions/metals/durasteel.dm
+++ b/code/modules/materials/definitions/metals/durasteel.dm
@@ -17,6 +17,10 @@
table_icon_base = "metal"
tgui_icon_key = "durasteel"
+/datum/material/durasteel/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(name = "durasteel floor tiles", product = /obj/item/stack/tile/durasteel, amount = 4)
+
/datum/material/durasteel/hull //The 'Hardball' of starship hulls.
id = "durasteel_hull"
name = MAT_DURASTEELHULL
diff --git a/code/modules/materials/definitions/metals/gold.dm b/code/modules/materials/definitions/metals/gold.dm
index 7c3832fe878f..08e0fc16bc97 100644
--- a/code/modules/materials/definitions/metals/gold.dm
+++ b/code/modules/materials/definitions/metals/gold.dm
@@ -10,3 +10,13 @@
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
tgui_icon_key = "gold"
+
+/datum/material/gold/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(category = "statues", name = "head of security statue", product = /obj/structure/statue/gold/hos, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "head of personnel statue", product = /obj/structure/statue/gold/hop, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "chief medical officer statue", product = /obj/structure/statue/gold/cmo, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "chief engineer statue", product = /obj/structure/statue/gold/ce, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "research director statue", product = /obj/structure/statue/gold/rd, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(name = "gold floor tiles", product = /obj/item/stack/tile/gold, amount = 4)
+ . += create_stack_recipe_datum(name = "golden crown", product = /obj/item/clothing/head/crown, cost = 5, time = 3 SECONDS)
diff --git a/code/modules/materials/definitions/metals/plasteel.dm b/code/modules/materials/definitions/metals/plasteel.dm
index 4e642b77042e..608a29e59459 100644
--- a/code/modules/materials/definitions/metals/plasteel.dm
+++ b/code/modules/materials/definitions/metals/plasteel.dm
@@ -18,6 +18,56 @@
table_icon_base = "metal"
tgui_icon_key = "plasteel"
+/datum/material/plasteel/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "AI core",
+ product = /obj/structure/AIcore,
+ cost = 4,
+ time = 4 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "crate",
+ product = /obj/structure/closet/crate,
+ cost = 5,
+ time = 3 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "knife grip",
+ product = /obj/item/material/butterflyhandle,
+ cost = 3,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "dark floor tile",
+ product = /obj/item/stack/tile/floor/dark,
+ amount = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "roller bed",
+ product = /obj/item/roller,
+ cost = 3,
+ time = 3 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "whetstone",
+ product = /obj/item/whetstone,
+ cost = 2,
+ time = 5 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "reinforced skateboard assembly",
+ product = /obj/item/heavy_skateboard_frame,
+ cost = 5,
+ time = 4 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "plasteel floor tile",
+ product = /obj/item/stack/tile/plasteel,
+ cost = 1,
+ amount = 4,
+ )
+
/datum/material/plasteel/hull
id = "plasteel_hull"
name = MAT_PLASTEELHULL
diff --git a/code/modules/materials/definitions/metals/silver.dm b/code/modules/materials/definitions/metals/silver.dm
index ae1bc14fe5e2..ba102635ec4b 100644
--- a/code/modules/materials/definitions/metals/silver.dm
+++ b/code/modules/materials/definitions/metals/silver.dm
@@ -10,3 +10,13 @@
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
tgui_icon_key = "silver"
+
+/datum/material/silver/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(category = "statues", name = "head of security statue", product = /obj/structure/statue/silver/hos, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "medical doctor statue", product = /obj/structure/statue/silver/md, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "janitor statue", product = /obj/structure/statue/silver/janitor, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "security statue", product = /obj/structure/statue/silver/sec, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "secborg statue", product = /obj/structure/statue/silver/secborg, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "medborg statue", product = /obj/structure/statue/silver/medborg, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(name = "silver floor tiles", product = /obj/item/stack/tile/silver, amount = 4)
diff --git a/code/modules/materials/definitions/metals/steel.dm b/code/modules/materials/definitions/metals/steel.dm
index dc83f6cf7cfe..e3e49be9e326 100644
--- a/code/modules/materials/definitions/metals/steel.dm
+++ b/code/modules/materials/definitions/metals/steel.dm
@@ -11,6 +11,237 @@
table_icon_base = "metal"
tgui_icon_key = "metal"
+/datum/material/steel/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "dark office chair",
+ product = /obj/structure/bed/chair/office/dark,
+ cost = 5,
+ category = "office chairs",
+ )
+ . += create_stack_recipe_datum(
+ name = "light office chair",
+ product = /obj/structure/bed/chair/office/light,
+ cost = 5,
+ category = "office chairs",
+ )
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "beige comfy chair", product = /obj/structure/bed/chair/comfy/beige)
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "black comfy chair", product = /obj/structure/bed/chair/comfy/black)
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "brown comfy chair", product = /obj/structure/bed/chair/comfy/brown)
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "lime comfy chair", product = /obj/structure/bed/chair/comfy/lime)
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "teal comfy chair", product = /obj/structure/bed/chair/comfy/teal)
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "red comfy chair", product = /obj/structure/bed/chair/comfy/red)
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "blue comfy chair", product = /obj/structure/bed/chair/comfy/blue)
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "purple comfy chair", product = /obj/structure/bed/chair/comfy/purp)
+ . += create_stack_recipe_datum(category = "comfy chairs", cost = 2, name = "green comfy chair", product = /obj/structure/bed/chair/comfy/green)
+ . += create_stack_recipe_datum(
+ name = "table frame",
+ product = /obj/structure/table,
+ time = 1 SECONDS,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "bench frame",
+ product = /obj/structure/table/bench,
+ time = 1 SECONDS,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "standard airlock assembly", product = /obj/structure/door_assembly)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "command airlock assembly", product = /obj/structure/door_assembly/command)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "security airlock assembly", product = /obj/structure/door_assembly/security)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "engi-atmos airlock assembly", product = /obj/structure/door_assembly/engi_atmos)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "engineering airlock assembly", product = /obj/structure/door_assembly/engi)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "mining airlock assembly", product = /obj/structure/door_assembly/mining)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "atmospherics airlock assembly", product = /obj/structure/door_assembly/atmos)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "research airlock assembly", product = /obj/structure/door_assembly/research)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "medical airlock assembly", product = /obj/structure/door_assembly/medical)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "maintenance airlock assembly", product = /obj/structure/door_assembly/maint)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "external airlock assembly", product = /obj/structure/door_assembly/external)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "freezer airlock assembly", product = /obj/structure/door_assembly/freezer)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "airtight airlock assembly", product = /obj/structure/door_assembly/hatch)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "maintenance hatch assembly", product = /obj/structure/door_assembly/hatch/maint)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "high security airlock assembly", product = /obj/structure/door_assembly/high_security)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "voidcraft airlock assembly (horizontal)", product = /obj/structure/door_assembly/voidcraft)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "voidcraft airlock assembly (vertical)", product = /obj/structure/door_assembly/voidcraft/vertical)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "emergency shutter", product = /obj/structure/firedoor_assembly)
+ . += create_stack_recipe_datum(category = "airlock assemblies", cost = 4, name = "multi-tile airlock assembly", product = /obj/structure/door_assembly/multi_tile)
+ . += create_stack_recipe_datum(
+ name = "rack",
+ product = /obj/structure/table/rack,
+ cost = 1,
+ time = 0.5 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "closet",
+ product = /obj/structure/closet,
+ cost = 2,
+ time = 1.5 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "canister",
+ product = /obj/machinery/portable_atmospherics/canister,
+ cost = 10,
+ time = 1 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "machine frame",
+ product = /obj/item/frame,
+ cost = 5,
+ time = 2 SECONDS,
+ )
+ . += new /datum/stack_recipe/railing
+ . += create_stack_recipe_datum(category = "sofas", cost = 1, name = "sofa middle", product = /obj/structure/bed/chair/sofa, exclusitivity = /obj/structure/bed)
+ . += create_stack_recipe_datum(category = "sofas", cost = 1, name = "sofa left", product = /obj/structure/bed/chair/sofa/left, exclusitivity = /obj/structure/bed)
+ . += create_stack_recipe_datum(category = "sofas", cost = 1, name = "sofa right", product = /obj/structure/bed/chair/sofa/right, exclusitivity = /obj/structure/bed)
+ . += create_stack_recipe_datum(category = "sofas", cost = 1, name = "sofa corner", product = /obj/structure/bed/chair/sofa/corner, exclusitivity = /obj/structure/bed)
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "light switch frame",
+ product = /obj/item/frame/lightswitch,
+ cost = 2,
+ )
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "apc frame",
+ product = /obj/item/frame/apc,
+ cost = 2,
+ )
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "mirror frame",
+ product = /obj/item/frame/mirror,
+ cost = 2,
+ )
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "light fixture frame",
+ product = /obj/item/frame/light,
+ cost = 2,
+ )
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "floor lamp frame",
+ product = /obj/machinery/light_construct/flamp,
+ cost = 2,
+ )
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "small light fixture frame",
+ product = /obj/item/frame/light/small,
+ cost = 1,
+ )
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "fairy light fixture frame",
+ product = /obj/item/frame/light/fairy,
+ cost = 1,
+ )
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "fire extinguisher cabinet frame",
+ product = /obj/item/frame/extinguisher_cabinet,
+ cost = 2,
+ )
+ // todo: frame rework
+ . += create_stack_recipe_datum(
+ category = "frames",
+ name = "portable turret frame",
+ product = /obj/machinery/porta_turret_construct,
+ cost = 5,
+ time = 2.5 SECONDS,
+ )
+ . += create_stack_recipe_datum(category = "teshari nests", cost = 1, name = "small teshari nest", product = /obj/structure/bed/chair/bay/chair/padded/red/smallnest, exclusitivity = /obj/structure/bed)
+ . += create_stack_recipe_datum(category = "teshari nests", cost = 1, name = "big teshari nest", product = /obj/structure/bed/chair/bay/chair/padded/red/bignest, exclusitivity = /obj/structure/bed)
+ . += create_stack_recipe_datum(
+ name = "metal rod",
+ product = /obj/item/stack/rods,
+ cost = 1,
+ amount = 2,
+ )
+ . += create_stack_recipe_datum(
+ name = "floor tiles",
+ product = /obj/item/stack/tile/floor,
+ cost = 1,
+ amount = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "roofing tiles",
+ product = /obj/item/stack/tile/roofing,
+ cost = 3,
+ amount = 4,
+ )
+ . += create_stack_recipe_datum(category = "filing cabinets", cost = 4, name = "filing cabinet", product = /obj/structure/filingcabinet, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "filing cabinets", cost = 4, name = "tall filing cabinet", product = /obj/structure/filingcabinet/tall, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "filing cabinets", cost = 4, name = "chest drawer", product = /obj/structure/filingcabinet/chestdrawer, time = 2 SECONDS)
+ . += create_stack_recipe_datum(
+ name = "dance pole",
+ product = /obj/structure/dancepole,
+ time = 2 SECONDS,
+ cost = 2,
+ )
+ . += create_stack_recipe_datum(
+ name = "IV drip",
+ product = /obj/machinery/iv_drip,
+ time = 4 SECONDS,
+ cost = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "conveyor switch",
+ product = /obj/machinery/conveyor_switch,
+ cost = 2,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ category = "weapons",
+ product = /obj/item/cannonframe,
+ cost = 5,
+ time = 2 SECONDS,
+ name = "improvised pneumatic cannon frame",
+ )
+ . += create_stack_recipe_datum(
+ category = "weapons",
+ product = /obj/item/grenade/chem_grenade,
+ name = "grenade casing",
+ cost = 2,
+ )
+ . += create_stack_recipe_datum("category" = "modular computer frames", name = "modular console frame", product = /obj/item/modular_computer/console, time = 2 SECONDS, cost = 10)
+ . += create_stack_recipe_datum("category" = "modular computer frames", name = "modular telescreen frame", product = /obj/item/modular_computer/telescreen, time = 2 SECONDS, cost = 5)
+ . += create_stack_recipe_datum("category" = "modular computer frames", name = "modular laptop frame", product = /obj/item/modular_computer/laptop, time = 2 SECONDS, cost = 3)
+ . += create_stack_recipe_datum("category" = "modular computer frames", name = "modular tablet frame", product = /obj/item/modular_computer/tablet, time = 2 SECONDS, cost = 2)
+ . += create_stack_recipe_datum(
+ name = "desk bell",
+ product = /obj/item/deskbell,
+ cost = 2,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "scooter frame",
+ product = /obj/item/scooter_frame,
+ cost = 5,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "metal coffin",
+ product = /obj/structure/closet/coffin/comfy,
+ time = 2 SECONDS,
+ cost = 5,
+ )
+ . += create_stack_recipe_datum(
+ name = "ladder assembly",
+ product = /obj/structure/ladder_assembly,
+ cost = 4,
+ time = 3 SECONDS,
+ )
+
/datum/material/steel/hull
id = "steel_hull"
name = MAT_STEELHULL
diff --git a/code/modules/materials/definitions/metals/uranium.dm b/code/modules/materials/definitions/metals/uranium.dm
index 3ec97fe32cc8..96f3680f99c0 100644
--- a/code/modules/materials/definitions/metals/uranium.dm
+++ b/code/modules/materials/definitions/metals/uranium.dm
@@ -11,3 +11,9 @@
stack_origin_tech = list(TECH_MATERIAL = 5)
door_icon_base = "stone"
tgui_icon_key = "uranium"
+
+/datum/material/uranium/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(category = "statues", name = "engineer statue", product = /obj/structure/statue/uranium/eng, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "nuke statue", product = /obj/structure/statue/uranium/nuke, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(name = "uranium floor tiles", product = /obj/item/stack/tile/uranium, amount = 4)
diff --git a/code/modules/materials/definitions/misc/cardboard.dm b/code/modules/materials/definitions/misc/cardboard.dm
new file mode 100644
index 000000000000..87835c881b2f
--- /dev/null
+++ b/code/modules/materials/definitions/misc/cardboard.dm
@@ -0,0 +1,79 @@
+/datum/material/cardboard
+ id = "cardboard"
+ name = "cardboard"
+ stack_type = /obj/item/stack/material/cardboard
+ flags = MATERIAL_BRITTLE
+ integrity = 10
+ icon_base = 'icons/turf/walls/solid.dmi'
+ icon_reinf = 'icons/turf/walls/reinforced_solid.dmi'
+ icon_colour = "#AAAAAA"
+ hardness = 1
+ weight = 1
+ protectiveness = 0 // 0%
+ conductive = 0
+ ignition_point = T0C+232 //"the temperature at which book-paper catches fire, and burns." close enough
+ melting_point = T0C+232 //temperature at which cardboard walls would be destroyed
+ stack_origin_tech = list(TECH_MATERIAL = 1)
+ door_icon_base = "wood"
+ destruction_desc = "crumples"
+ radiation_resistance = 1
+ pass_stack_colors = TRUE
+
+/datum/material/cardboard/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "box",
+ product = /obj/item/storage/box,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "donut box",
+ product = /obj/item/storage/box/donut/empty,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "egg box",
+ product = /obj/item/storage/fancy/egg_box,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "light tubes box",
+ product = /obj/item/storage/box/lights/tubes,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "light bulbs box",
+ product = /obj/item/storage/box/lights/bulbs,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "mouse traps box",
+ product = /obj/item/storage/box/mousetraps,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "cardborg suit",
+ product = /obj/item/clothing/suit/cardborg,
+ cost = 3,
+ )
+ . += create_stack_recipe_datum(
+ name = "cardborg helmet",
+ product = /obj/item/clothing/head/cardborg,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "pizza box",
+ product = /obj/item/pizzabox,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "large cardboard box",
+ product = /obj/structure/closet/largecardboard,
+ cost = 3,
+ time = 2.5 SECONDS,
+ )
+ . += create_stack_recipe_datum(category = "folders", name = "blue folder", product = /obj/item/folder/blue, cost = 1)
+ . += create_stack_recipe_datum(category = "folders", name = "grey folder", product = /obj/item/folder, cost = 1)
+ . += create_stack_recipe_datum(category = "folders", name = "red folder", product = /obj/item/folder/red, cost = 1)
+ . += create_stack_recipe_datum(category = "folders", name = "white folder", product = /obj/item/folder/white, cost = 1)
+ . += create_stack_recipe_datum(category = "folders", name = "yellow folder", product = /obj/item/folder/yellow, cost = 1)
diff --git a/code/modules/materials/definitions/misc/cloths.dm b/code/modules/materials/definitions/misc/cloths.dm
index 1818d5ebad68..4ab641be1c29 100644
--- a/code/modules/materials/definitions/misc/cloths.dm
+++ b/code/modules/materials/definitions/misc/cloths.dm
@@ -11,6 +11,136 @@
conductive = 0
pass_stack_colors = TRUE
+/datum/material/cloth/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "uniform",
+ product = /obj/item/clothing/under/color/white,
+ cost = 8,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "foot wraps",
+ product = /obj/item/clothing/shoes/footwraps,
+ cost = 2,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "gloves",
+ product = /obj/item/clothing/gloves/white,
+ cost = 2,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "wig",
+ product = /obj/item/clothing/head/powdered_wig,
+ cost = 4,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "philosopher's wig",
+ product = /obj/item/clothing/head/philosopher_wig,
+ cost = 5,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "taqiyah",
+ product = /obj/item/clothing/head/taqiyah,
+ cost = 3,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "turban",
+ product = /obj/item/clothing/head/turban,
+ cost = 3,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "hijab",
+ product = /obj/item/clothing/head/hijab,
+ cost = 3,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "kippa",
+ product = /obj/item/clothing/head/kippa,
+ cost = 3,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "kippa",
+ product = /obj/item/clothing/head/traveller,
+ cost = 3,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "scarf",
+ product = /obj/item/clothing/accessory/scarf/white,
+ cost = 4,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "baggy pants",
+ product = /obj/item/clothing/under/pants/baggy/white,
+ cost = 8,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "belt pouch",
+ product = /obj/item/storage/belt/fannypack/white,
+ cost = 8,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "crude bandage",
+ product = /obj/item/stack/medical/crude_pack,
+ cost = 1,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "empty sandbag",
+ product = /obj/item/stack/emptysandbag,
+ cost = 2,
+ amount = 5,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "shrine seal",
+ product = /obj/structure/shrine_seal,
+ cost = 2,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "cloth rag",
+ product = /obj/item/reagent_containers/glass/rag,
+ cost = 1,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "woven string",
+ product = /obj/item/weaponcrafting/string,
+ cost = 1,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(category = "bedsheets", name = "bedsheet", product = /obj/item/bedsheet, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double bedsheet", product = /obj/item/bedsheet/double, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "red bedsheet", product = /obj/item/bedsheet/red, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double red bedsheet", product = /obj/item/bedsheet/reddouble, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "orange bedsheet", product = /obj/item/bedsheet/orange, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double orange bedsheet", product = /obj/item/bedsheet/orangedouble, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "yellow bedsheet", product = /obj/item/bedsheet/yellow, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double yellow bedsheet", product = /obj/item/bedsheet/yellowdouble, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "green bedsheet", product = /obj/item/bedsheet/green, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double green bedsheet", product = /obj/item/bedsheet/greendouble, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "blue bedsheet", product = /obj/item/bedsheet/blue, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double blue bedsheet", product = /obj/item/bedsheet/bluedouble, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "purple bedsheet", product = /obj/item/bedsheet/purple, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double purple bedsheet", product = /obj/item/bedsheet/purpledouble, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "brown bedsheet", product = /obj/item/bedsheet/brown, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double brown bedsheet", product = /obj/item/bedsheet/browndouble, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "rainbow bedsheet", product = /obj/item/bedsheet/rainbow, cost = 5)
+ . += create_stack_recipe_datum(category = "bedsheets", name = "double rainbow bedsheet", product = /obj/item/bedsheet/rainbowdouble, cost = 5)
+
/datum/material/carpet
id = "carpet"
name = "carpet"
diff --git a/code/modules/materials/definitions/misc/paper.dm b/code/modules/materials/definitions/misc/paper.dm
deleted file mode 100644
index 059ac27001e0..000000000000
--- a/code/modules/materials/definitions/misc/paper.dm
+++ /dev/null
@@ -1,20 +0,0 @@
-/datum/material/cardboard
- id = "cardboard"
- name = "cardboard"
- stack_type = /obj/item/stack/material/cardboard
- flags = MATERIAL_BRITTLE
- integrity = 10
- icon_base = 'icons/turf/walls/solid.dmi'
- icon_reinf = 'icons/turf/walls/reinforced_solid.dmi'
- icon_colour = "#AAAAAA"
- hardness = 1
- weight = 1
- protectiveness = 0 // 0%
- conductive = 0
- ignition_point = T0C+232 //"the temperature at which book-paper catches fire, and burns." close enough
- melting_point = T0C+232 //temperature at which cardboard walls would be destroyed
- stack_origin_tech = list(TECH_MATERIAL = 1)
- door_icon_base = "wood"
- destruction_desc = "crumples"
- radiation_resistance = 1
- pass_stack_colors = TRUE
diff --git a/code/modules/materials/definitions/misc/plastic.dm b/code/modules/materials/definitions/misc/plastic.dm
index 745f9ee5dd8d..a2e819a96c9c 100644
--- a/code/modules/materials/definitions/misc/plastic.dm
+++ b/code/modules/materials/definitions/misc/plastic.dm
@@ -14,6 +14,92 @@
melting_point = T0C+371 //assuming heat resistant plastic
stack_origin_tech = list(TECH_MATERIAL = 3)
+/datum/material/plastic/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "plastic crate",
+ product = /obj/structure/closet/crate/plastic,
+ cost = 5,
+ time = 1 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "plastic bag",
+ product = /obj/item/storage/bag/plasticbag,
+ cost = 3,
+ )
+ . += create_stack_recipe_datum(
+ name = "blood pack",
+ product = /obj/item/reagent_containers/blood/empty,
+ cost = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "reagent dispenser cartridge (large)",
+ product = /obj/item/reagent_containers/cartridge/dispenser/large,
+ cost = 5,
+ )
+ . += create_stack_recipe_datum(
+ name = "reagent dispenser cartridge (med)",
+ product = /obj/item/reagent_containers/cartridge/dispenser/medium,
+ cost = 3,
+ )
+ . += create_stack_recipe_datum(
+ name = "reagent dispenser cartridge (small)",
+ product = /obj/item/reagent_containers/cartridge/dispenser/small,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "shower curtain",
+ product = /obj/structure/curtain,
+ cost = 4,
+ time = 1 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "plastic flaps",
+ product = /obj/structure/plasticflaps,
+ cost = 4,
+ time = 1 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "airtight plastic flaps",
+ product = /obj/structure/plasticflaps/mining,
+ cost = 5,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "water-cooler",
+ product = /obj/structure/reagent_dispensers/water_cooler,
+ cost = 4,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "lampshade",
+ product = /obj/item/lampshade,
+ cost = 1,
+ time = 1 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "rubberized wheels",
+ product = /obj/item/skate_wheels,
+ cost = 12,
+ )
+ . += create_stack_recipe_datum(
+ name = "plastic raincoat",
+ product = /obj/item/clothing/suit/storage/hooded/rainponcho,
+ cost = 5,
+ )
+ . += create_stack_recipe_datum(
+ name = "white floor tile",
+ product = /obj/item/stack/tile/floor/white,
+ cost = 20,
+ amount = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "freezer floor tile",
+ product = /obj/item/stack/tile/floor/freezer,
+ cost = 20,
+ amount = 4,
+ )
+
/datum/material/plastic/holographic
name = "holoplastic"
id = "plastic_holo"
diff --git a/code/modules/materials/definitions/misc/snow.dm b/code/modules/materials/definitions/misc/snow.dm
index 40f292cfac54..26802eaedb6d 100644
--- a/code/modules/materials/definitions/misc/snow.dm
+++ b/code/modules/materials/definitions/misc/snow.dm
@@ -17,6 +17,44 @@
sheet_plural_name = "pile" //Just a bigger pile
radiation_resistance = 1
+/datum/material/snow/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "snowball",
+ product = /obj/item/material/snow/snowball,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "snow brick",
+ product = /obj/item/stack/material/snowbrick,
+ cost = 2,
+ )
+ . += create_stack_recipe_datum(
+ name = "snowman",
+ product = /obj/structure/snowman,
+ cost = 2,
+ )
+ . += create_stack_recipe_datum(
+ name = "snow robot",
+ product = /obj/structure/snowman/borg,
+ cost = 2,
+ )
+ . += create_stack_recipe_datum(
+ name = "snow spider",
+ product = /obj/structure/snowman/spider,
+ cost = 3,
+ )
+ . += create_stack_recipe_datum(
+ name = "snowman head",
+ product = /obj/item/clothing/head/snowman,
+ cost = 5,
+ )
+ . += create_stack_recipe_datum(
+ name = "snowman suit",
+ product = /obj/item/clothing/suit/snowman,
+ cost = 10,
+ )
+
/datum/material/snowbrick //only slightly stronger than snow, used to make igloos mostly
id = "snow_packed"
name = "packed snow"
diff --git a/code/modules/materials/definitions/misc/wax.dm b/code/modules/materials/definitions/misc/wax.dm
index a6c8ca26add5..0f20afa1bb7b 100644
--- a/code/modules/materials/definitions/misc/wax.dm
+++ b/code/modules/materials/definitions/misc/wax.dm
@@ -8,3 +8,39 @@
hardness = 20
integrity = 100
pass_stack_colors = TRUE
+
+/datum/material/wax/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "candle",
+ product = /obj/item/flame/candle,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "wax floor tile",
+ product = /obj/item/stack/tile/wax,
+ cost = 1,
+ amount = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "honeycomb floor tile",
+ product = /obj/item/stack/tile/honeycomb,
+ cost = 1,
+ amount = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "wax globule",
+ product = /obj/item/ammo_casing/organic/wax,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "royal throne",
+ product = /obj/structure/bed/chair/apidean,
+ cost = 10,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "apidean stool",
+ product = /obj/structure/bed/chair/apidean_stool,
+ cost = 5,
+ )
diff --git a/code/modules/materials/definitions/organic/bone.dm b/code/modules/materials/definitions/organic/bone.dm
index 82a7d57e8cb4..e235c13c7d45 100644
--- a/code/modules/materials/definitions/organic/bone.dm
+++ b/code/modules/materials/definitions/organic/bone.dm
@@ -15,6 +15,31 @@
door_icon_base = "stone"
table_icon_base = "stone"
+/datum/material/bone/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "bone roofing tile",
+ product = /obj/item/stack/tile/roofing/bone,
+ cost = 3,
+ amount = 4,
+ )
+ // todo: refactor, this just decons into fucking steel
+ . += create_stack_recipe_datum(
+ name = "bone table frame",
+ product = /obj/structure/table,
+ cost = 1,
+ time = 1 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "bone crate",
+ product = /obj/structure/closet/crate/ashlander,
+ cost = 5,
+ time = 3 SECONDS,
+ )
+ . += create_stack_recipe_datum(category = "statues", name = "bone statue", product = /obj/structure/statue/bone, cost = 15, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "skull statue", product = /obj/structure/statue/bone/skull, cost = 15, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "half-skull statue", product = /obj/structure/statue/bone/skull/half, cost = 15, time = 2 SECONDS)
+
/datum/material/bone/wall_touch_special(var/turf/simulated/wall/W, var/mob/living/L)
var/mob/living/carbon/M = L
if(istype(M) && L.mind.isholy)
diff --git a/code/modules/materials/definitions/organic/leather.dm b/code/modules/materials/definitions/organic/leather.dm
index cc237aa297f7..8cfaa9af4fed 100644
--- a/code/modules/materials/definitions/organic/leather.dm
+++ b/code/modules/materials/definitions/organic/leather.dm
@@ -11,3 +11,66 @@
melting_point = T0C+300
protectiveness = 3 // 13%
conductive = 0
+
+/datum/material/leather/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "wallet",
+ product = /obj/item/storage/wallet,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "muzzle",
+ product = /obj/item/clothing/mask/muzzle,
+ cost = 2,
+ )
+ . += create_stack_recipe_datum(
+ name = "botany gloves",
+ product = /obj/item/clothing/gloves/botanic_leather,
+ cost = 3,
+ )
+ . += create_stack_recipe_datum(
+ name = "toolbelt",
+ product = /obj/item/storage/belt/utility,
+ cost = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "leather satchel",
+ product = /obj/item/storage/backpack/satchel,
+ cost = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "bandolier",
+ product = /obj/item/storage/belt/security/tactical/bandolier,
+ cost = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "leather jacket",
+ product = /obj/item/clothing/suit/storage/toggle/leather_jacket,
+ cost = 5,
+ )
+ . += create_stack_recipe_datum(
+ name = "leather shoes",
+ product = /obj/item/clothing/shoes/laceup,
+ cost = 3,
+ )
+ . += create_stack_recipe_datum(
+ name = "leather overcoat",
+ product = /obj/item/clothing/suit/overcoat,
+ cost = 8,
+ )
+ . += create_stack_recipe_datum(
+ name = "voyager satchel",
+ product = /obj/item/storage/backpack/satchel/voyager,
+ cost = 8,
+ )
+ . += create_stack_recipe_datum(
+ name = "voyager backpack",
+ product = /obj/item/storage/backpack/voyager,
+ cost = 8,
+ )
+ . += create_stack_recipe_datum(
+ name = "voyager harness",
+ product = /obj/item/clothing/accessory/storage/voyager,
+ cost = 8,
+ )
diff --git a/code/modules/materials/definitions/organic/resin.dm b/code/modules/materials/definitions/organic/resin.dm
index dc2dcf0321dd..a7e40efe8228 100644
--- a/code/modules/materials/definitions/organic/resin.dm
+++ b/code/modules/materials/definitions/organic/resin.dm
@@ -15,6 +15,34 @@
stack_origin_tech = list(TECH_MATERIAL = 8, TECH_PHORON = 4, TECH_BLUESPACE = 4, TECH_BIO = 7)
stack_type = /obj/item/stack/material/resin
+/datum/material/resin/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "resin nest",
+ product = /obj/structure/bed/nest,
+ exclusitivity = /obj/structure/bed,
+ cost = 2,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "crude resin bandage",
+ product = /obj/item/stack/medical/crude_pack,
+ time = 2 SECONDS,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "resin membrane",
+ product = /obj/effect/alien/resin/membrane,
+ cost = 1,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "resin node",
+ product = /obj/effect/alien/weeds/node,
+ cost = 1,
+ time = 2 SECONDS,
+ )
+
/datum/material/resin/can_open_material_door(var/mob/living/user)
var/mob/living/carbon/M = user
if(istype(M) && locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
diff --git a/code/modules/materials/definitions/organic/wood.dm b/code/modules/materials/definitions/organic/wood.dm
deleted file mode 100644
index 42eda7dce0d0..000000000000
--- a/code/modules/materials/definitions/organic/wood.dm
+++ /dev/null
@@ -1,75 +0,0 @@
-/datum/material/wood
- id = "wood"
- name = MAT_WOOD
- stack_type = /obj/item/stack/material/wood
- icon_colour = "#9c5930"
- integrity = 50
- icon_base = 'icons/turf/walls/wood_wall.dmi'
- wall_stripe_icon = 'icons/turf/walls/wood_wall_stripe.dmi'
- explosion_resistance = 2
- shard_type = SHARD_SPLINTER
- shard_can_repair = 0 // you can't weld splinters back into planks
- hardness = 15
- weight = 18
- protectiveness = 8 // 28%
- conductive = 0
- conductivity = 1
- melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood
- ignition_point = T0C+288
- stack_origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
- dooropen_noise = 'sound/effects/doorcreaky.ogg'
- door_icon_base = "wood"
- destruction_desc = "splinters"
- sheet_singular_name = "plank"
- sheet_plural_name = "planks"
- table_icon_base = "wood"
- tgui_icon_key = "plank"
-
-/datum/material/wood/log
- id = "log"
- name = "log"
- icon_base = 'icons/turf/walls/log.dmi'
- stack_type = /obj/item/stack/material/log
- sheet_singular_name = null
- sheet_plural_name = "pile"
- tgui_icon_key = "log"
-
-/datum/material/wood/log/sif
- id = "log_sif"
- name = MAT_SIFLOG
- icon_colour = "#0099cc" // Cyan-ish
- stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2)
- stack_type = /obj/item/stack/material/log/sif
-
-/datum/material/wood/log/hard
- id = "log_hardwood"
- name = MAT_HARDLOG
- icon_colour = "#6f432a"
- stack_type = /obj/item/stack/material/log/hard
-
-/datum/material/wood/holographic
- id = "wood_holo"
- name = "holowood"
- display_name = "wood"
- stack_type = null
- shard_type = SHARD_NONE
-
-/datum/material/wood/sif
- id = "wood_sif"
- name = MAT_SIFWOOD
- stack_type = /obj/item/stack/material/wood/sif
- icon_colour = "#0099cc" // Cyan-ish
- stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2) // Alien wood would presumably be more interesting to the analyzer.
-
-/datum/material/wood/hardwood
- id = "wood_hardwood"
- name = MAT_HARDWOOD
- stack_type = /obj/item/stack/material/wood/hard
- icon_colour = "#42291a"
- icon_base = 'icons/turf/walls/wood_wall.dmi'
- wall_stripe_icon = 'icons/turf/walls/wood_wall_stripe.dmi'
- icon_reinf_directionals = TRUE
- integrity = 65 //a bit stronger than regular wood
- hardness = 20
- weight = 20 //likewise, heavier
- table_icon_base = "stone"
diff --git a/code/modules/materials/definitions/organic/wood/log.dm b/code/modules/materials/definitions/organic/wood/log.dm
new file mode 100644
index 000000000000..bc4aa16b4503
--- /dev/null
+++ b/code/modules/materials/definitions/organic/wood/log.dm
@@ -0,0 +1,49 @@
+/datum/material/wood_log
+ id = "log"
+ name = "log"
+ icon_base = 'icons/turf/walls/log.dmi'
+ stack_type = /obj/item/stack/material/log
+ sheet_singular_name = null
+ sheet_plural_name = "pile"
+ tgui_icon_key = "log"
+
+ // todo: this is all copypasted from wood
+ icon_colour = "#9c5930"
+ integrity = 50
+ wall_stripe_icon = 'icons/turf/walls/wood_wall_stripe.dmi'
+ explosion_resistance = 2
+ shard_type = SHARD_SPLINTER
+ shard_can_repair = 0 // you can't weld splinters back into planks
+ hardness = 15
+ weight = 18
+ protectiveness = 8 // 28%
+ conductive = 0
+ conductivity = 1
+ melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood
+ ignition_point = T0C+288
+ stack_origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
+ dooropen_noise = 'sound/effects/doorcreaky.ogg'
+ door_icon_base = "wood"
+ destruction_desc = "splinters"
+ table_icon_base = "wood"
+
+/datum/material/wood_log/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "bonfire",
+ product = /obj/structure/bonfire,
+ cost = 5,
+ )
+
+/datum/material/wood_log/sif
+ id = "log_sif"
+ name = MAT_SIFLOG
+ icon_colour = "#0099cc" // Cyan-ish
+ stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2)
+ stack_type = /obj/item/stack/material/log/sif
+
+/datum/material/wood_log/hard
+ id = "log_hardwood"
+ name = MAT_HARDLOG
+ icon_colour = "#6f432a"
+ stack_type = /obj/item/stack/material/log/hard
diff --git a/code/modules/materials/definitions/organic/wood/plank.dm b/code/modules/materials/definitions/organic/wood/plank.dm
new file mode 100644
index 000000000000..1010a248caa5
--- /dev/null
+++ b/code/modules/materials/definitions/organic/wood/plank.dm
@@ -0,0 +1,229 @@
+/datum/material/wood_plank
+ id = "wood"
+ name = MAT_WOOD
+ stack_type = /obj/item/stack/material/wood
+ icon_colour = "#9c5930"
+ integrity = 50
+ icon_base = 'icons/turf/walls/wood_wall.dmi'
+ wall_stripe_icon = 'icons/turf/walls/wood_wall_stripe.dmi'
+ explosion_resistance = 2
+ shard_type = SHARD_SPLINTER
+ shard_can_repair = 0 // you can't weld splinters back into planks
+ hardness = 15
+ weight = 18
+ protectiveness = 8 // 28%
+ conductive = 0
+ conductivity = 1
+ melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood
+ ignition_point = T0C+288
+ stack_origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
+ dooropen_noise = 'sound/effects/doorcreaky.ogg'
+ door_icon_base = "wood"
+ destruction_desc = "splinters"
+ sheet_singular_name = "plank"
+ sheet_plural_name = "planks"
+ table_icon_base = "wood"
+ tgui_icon_key = "plank"
+
+/datum/material/wood_plank/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "coffin",
+ product = /obj/structure/closet/coffin,
+ cost = 5,
+ )
+ . += create_stack_recipe_datum(
+ name = "crossbow frame",
+ product = /obj/item/crossbowframe,
+ cost = 5,
+ )
+ . += new /datum/stack_recipe/oar
+ . += new /datum/stack_recipe/boat
+ . += new /datum/stack_recipe/dragon_boat
+ . += new /datum/stack_recipe/pew/middle
+ . += new /datum/stack_recipe/pew/left
+ . += new /datum/stack_recipe/pew/right
+
+/datum/material/wood_plank/special_recipes()
+ var/list/recipes = list()
+ recipes += create_stack_recipe_datum(
+ name = "beehive assembly",
+ product = /obj/item/beehive_assembly,
+ cost = 4,
+ time = 2 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "beehive frame",
+ product = /obj/item/honey_frame,
+ cost = 1,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "book shelf",
+ product = /obj/structure/bookcase,
+ cost = 5,
+ time = 2 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "noticeboard frame",
+ product = /obj/item/frame/noticeboard,
+ cost = 4,
+ time = 2 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "wooden bucket",
+ product = /obj/item/reagent_containers/glass/bucket/wood,
+ cost = 2,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "coilgun stock",
+ product = /obj/item/coilgun_assembly,
+ cost = 5,
+ time = 3 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "drying rack",
+ product = /obj/machinery/smartfridge/drying_rack,
+ cost = 10,
+ time = 3 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "skateboard assembly",
+ product = /obj/item/skateboard_frame,
+ cost = 6,
+ time = 2 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "bokken blade",
+ product = /obj/item/bokken_blade,
+ cost = 10,
+ time = 4 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "bokken hilt",
+ product = /obj/item/bokken_hilt,
+ cost = 4,
+ time = 3 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "wakibokken blade",
+ product = /obj/item/wakibokken_blade,
+ cost = 8,
+ time = 4 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "rifle stock",
+ product = /obj/item/weaponcrafting/stock,
+ cost = 5,
+ time = 4 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "wooden panel",
+ product = /obj/structure/window/wooden,
+ cost = 1,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "wooden sandals",
+ product = /obj/item/clothing/shoes/sandal,
+ cost = 1,
+ time = 2 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "wood circlet",
+ product = /obj/item/clothing/head/woodcirclet,
+ cost = 1,
+ time = 2 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "clipboard",
+ product = /obj/item/clipboard,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "wood floor tile",
+ product = /obj/item/stack/tile/wood,
+ cost = 1,
+ amount = 4,
+ )
+ . += create_stack_recipe_datum(
+ name = "wood roofing tile",
+ product = /obj/item/stack/tile/roofing/wood,
+ cost = 3,
+ amount = 4,
+ )
+ . += create_stack_recipe_datum(category = "fences", name = "fence", product = /obj/structure/fence/wooden, cost = 3)
+ . += create_stack_recipe_datum(category = "fences", name = "fence end", product = /obj/structure/fence/wooden/end, cost = 3)
+ . += create_stack_recipe_datum(category = "fences", name = "fencepost", product = /obj/structure/fence/wooden/post, cost = 3)
+ . += create_stack_recipe_datum(category = "fences", name = "fence corner", product = /obj/structure/fence/wooden/corner, cost = 3)
+ . += create_stack_recipe_datum(category = "fences", name = "gate", product = /obj/structure/fence/door/wooden, cost = 3)
+ return recipes
+
+/datum/material/wood_plank/holographic
+ id = "wood_holo"
+ name = "holowood"
+ display_name = "wood"
+ stack_type = null
+ shard_type = SHARD_NONE
+
+/datum/material/wood_plank/holographic/special_recipes()
+ return list()
+
+/datum/material/wood_plank/sif
+ id = "wood_sif"
+ name = MAT_SIFWOOD
+ stack_type = /obj/item/stack/material/wood/sif
+ icon_colour = "#0099cc" // Cyan-ish
+ stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2) // Alien wood would presumably be more interesting to the analyzer.
+
+/datum/material/wood_plank/sif/special_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "alien wood floor tile",
+ product = /obj/item/stack/tile/wood/sif,
+ cost = 1,
+ amount = 4,
+ )
+ // todo: this is shitcode
+ for(var/datum/stack_recipe/recipe as anything in .)
+ if(recipe.name == "wood floor tile")
+ . -= recipe
+
+/datum/material/wood_plank/hardwood
+ id = "wood_hardwood"
+ name = MAT_HARDWOOD
+ stack_type = /obj/item/stack/material/wood/hard
+ icon_colour = "#42291a"
+ icon_base = 'icons/turf/walls/wood_wall.dmi'
+ wall_stripe_icon = 'icons/turf/walls/wood_wall_stripe.dmi'
+ icon_reinf_directionals = TRUE
+ integrity = 65 //a bit stronger than regular wood
+ hardness = 20
+ weight = 20 //likewise, heavier
+ table_icon_base = "stone"
+
+/datum/material/wood_plank/hardwood/special_recipes()
+ var/list/recipes = list()
+ recipes += create_stack_recipe_datum(
+ name = "crossbow frame",
+ product = /obj/item/crossbowframe,
+ cost = 5,
+ time = 2 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "coilgun stock",
+ product = /obj/item/coilgun_assembly,
+ cost = 5,
+ time = 2 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "hardwood bokken blade",
+ product = /obj/item/bokken_blade/hardwood,
+ cost = 10,
+ time = 4 SECONDS,
+ )
+ recipes += create_stack_recipe_datum(
+ name = "hardwood wakibokken blade",
+ product = /obj/item/wakibokken_blade/hardwood,
+ cost = 5,
+ time = 4 SECONDS,
+ )
+ return recipes
diff --git a/code/modules/materials/definitions/special/clown_planet.dm b/code/modules/materials/definitions/special/clown_planet.dm
new file mode 100644
index 000000000000..ac9767f65969
--- /dev/null
+++ b/code/modules/materials/definitions/special/clown_planet.dm
@@ -0,0 +1,13 @@
+/datum/material/bananium
+
+/datum/material/bananium/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(category = "statues", name = "bananium statue", product = /obj/structure/statue/bananium, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "clown statue", product = /obj/structure/statue/bananium/clown, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(name = "bananium floor tiles", product = /obj/item/stack/tile/bananium, amount = 4)
+
+/datum/material/silencium
+
+/datum/material/silencium/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(name = "silencium floor tiles", product = /obj/item/stack/tile/silencium, amount = 4)
diff --git a/code/modules/materials/definitions/special/phoron.dm b/code/modules/materials/definitions/special/phoron.dm
index 23f5bb49e7d7..a5139f33a073 100644
--- a/code/modules/materials/definitions/special/phoron.dm
+++ b/code/modules/materials/definitions/special/phoron.dm
@@ -1,4 +1,3 @@
-
/datum/material/phoron
id = "phoron"
name = "phoron"
@@ -14,19 +13,8 @@
sheet_singular_name = "crystal"
sheet_plural_name = "crystals"
-// Commenting this out while fires are so spectacularly lethal, as I can't seem to get this balanced appropriately.
-/*
-/datum/material/phoron/combustion_effect(var/turf/T, var/temperature, var/effect_multiplier)
- if(isnull(ignition_point))
- return 0
- if(temperature < ignition_point)
- return 0
- var/totalPhoron = 0
- for(var/turf/simulated/floor/target_tile in range(2,T))
- var/phoronToDeduce = (temperature/30) * effect_multiplier
- totalPhoron += phoronToDeduce
- target_tile.assume_gas(/datum/gas/phoron, phoronToDeduce, 200+T0C)
- spawn (0)
- target_tile.hotspot_expose(temperature, 400)
- return round(totalPhoron/100)
-*/
+/datum/material/phoron/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(category = "statues", name = "scientist statue", product = /obj/structure/statue/phoron/scientist, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "xenomorph statue", product = /obj/structure/statue/phoron/xeno, cost = 10, time = 2 SECONDS)
+ . += create_stack_recipe_datum(name = "phoron floor tiles", product = /obj/item/stack/tile/phoron, amount = 4)
diff --git a/code/modules/materials/definitions/special/supermatter.dm b/code/modules/materials/definitions/special/supermatter.dm
index 87959972d958..bd6a26d82466 100644
--- a/code/modules/materials/definitions/special/supermatter.dm
+++ b/code/modules/materials/definitions/special/supermatter.dm
@@ -15,3 +15,12 @@
sheet_plural_name = "crystals"
is_fusion_fuel = 1
stack_origin_tech = list(TECH_MATERIAL = 8, TECH_PHORON = 5, TECH_BLUESPACE = 4)
+
+/datum/material/supermatter/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "supermatter shard",
+ product = /obj/machinery/power/supermatter/shard,
+ cost = 30,
+ time = 30 SECONDS,
+ )
diff --git a/code/modules/materials/definitions/stones/marble.dm b/code/modules/materials/definitions/stones/marble.dm
index 8e8b776c4243..1af61598bef7 100644
--- a/code/modules/materials/definitions/stones/marble.dm
+++ b/code/modules/materials/definitions/stones/marble.dm
@@ -18,3 +18,22 @@
sheet_plural_name = "bricks"
table_icon_base = "stone"
tgui_icon_key = "marble"
+
+/datum/material/marble/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "light marble floor tile",
+ product = /obj/item/stack/tile/wmarble,
+ cost = 1,
+ amount = 4
+ )
+ . += create_stack_recipe_datum(
+ name = "dark marble floor tile",
+ product = /obj/item/stack/tile/bmarble,
+ cost = 1,
+ amount = 4
+ )
+ . += create_stack_recipe_datum(category = "statues", name = "male statue", product = /obj/structure/statue/marble/male, cost = 15, time = 4 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "female statue", product = /obj/structure/statue/marble/female, cost = 15, time = 4 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "monkey statue", product = /obj/structure/statue/marble/monkey, cost = 15, time = 4 SECONDS)
+ . += create_stack_recipe_datum(category = "statues", name = "corgi statue", product = /obj/structure/statue/marble/corgi, cost = 15, time = 4 SECONDS)
diff --git a/code/modules/materials/definitions/stones/sandstone.dm b/code/modules/materials/definitions/stones/sandstone.dm
index 2f19c4de200a..b6babd9df957 100644
--- a/code/modules/materials/definitions/stones/sandstone.dm
+++ b/code/modules/materials/definitions/stones/sandstone.dm
@@ -17,3 +17,24 @@
sheet_plural_name = "bricks"
table_icon_base = "stone"
tgui_icon_key = "sandstone"
+
+/datum/material/sandstone/generate_recipes()
+ . = ..()
+ . += create_stack_recipe_datum(category = "statues", name = "assistant statue", product = /obj/structure/statue/sandstone/assistant, amount = 10)
+ . += create_stack_recipe_datum(
+ name = "planting bed",
+ product = /obj/machinery/portable_atmospherics/hydroponics/soil,
+ cost = 3,
+ time = 1 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "sandstone floor tile",
+ product = /obj/item/stack/tile/floor/sandstone,
+ cost = 1,
+ amount = 3,
+ )
+ . += create_stack_recipe_datum(
+ name = "sandstone jar",
+ product = /obj/item/reagent_containers/glass/bucket/sandstone,
+ cost = 2
+ )
diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm
deleted file mode 100644
index ca6197c28edc..000000000000
--- a/code/modules/materials/material_recipes.dm
+++ /dev/null
@@ -1,468 +0,0 @@
-/datum/material/proc/get_recipes()
- if(!recipes)
- generate_recipes()
- return recipes
-
-/datum/material/proc/generate_recipes()
- recipes = list()
-
- // If is_brittle() returns true, these are only good for a single strike.
- recipes += new/datum/stack_recipe("[display_name] baseball bat", /obj/item/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] grave marker", /obj/item/material/gravemarker, 5, time = 50, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] ring", /obj/item/clothing/gloves/ring/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] bracelet", /obj/item/clothing/accessory/bracelet/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
-
- if(integrity>=50)
- recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] barricade", /obj/structure/barricade, 5, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] stool", /obj/item/stool, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] bed", /obj/structure/bed, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] double bed", /obj/structure/bed/double, 4, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] low walls", /obj/structure/wall_frame, 2, time = 25, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
-
- if(hardness>50)
- recipes += new/datum/stack_recipe("[display_name] fork", /obj/item/material/kitchen/utensil/fork/plastic, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] knife", /obj/item/material/knife/plastic, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] blade", /obj/item/material/butterflyblade, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] hammer Head", /obj/item/material/hammer_head, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
-
-/datum/material/steel/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe_list("office chairs",list( \
- new/datum/stack_recipe("dark office chair", /obj/structure/bed/chair/office/dark, 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("light office chair", /obj/structure/bed/chair/office/light, 5, one_per_turf = 1, on_floor = 1) \
- ))
- recipes += new/datum/stack_recipe_list("comfy chairs", list( \
- new/datum/stack_recipe("beige comfy chair", /obj/structure/bed/chair/comfy/beige, 2, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("black comfy chair", /obj/structure/bed/chair/comfy/black, 2, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("brown comfy chair", /obj/structure/bed/chair/comfy/brown, 2, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("lime comfy chair", /obj/structure/bed/chair/comfy/lime, 2, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("teal comfy chair", /obj/structure/bed/chair/comfy/teal, 2, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("red comfy chair", /obj/structure/bed/chair/comfy/red, 2, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("blue comfy chair", /obj/structure/bed/chair/comfy/blue, 2, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("purple comfy chair", /obj/structure/bed/chair/comfy/purp, 2, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("green comfy chair", /obj/structure/bed/chair/comfy/green, 2, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("table frame", /obj/structure/table, 1, time = 10, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("bench frame", /obj/structure/table/bench, 1, time = 10, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("rack", /obj/structure/table/rack, 1, time = 5, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("closet", /obj/structure/closet, 2, time = 15, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("cannon frame", /obj/item/cannonframe, 10, time = 15, one_per_turf = 0, on_floor = 0)
- recipes += new/datum/stack_recipe("regular floor tile", /obj/item/stack/tile/floor, 1, 4, 20)
- recipes += new/datum/stack_recipe("roofing tile", /obj/item/stack/tile/roofing, 3, 4, 20)
- recipes += new/datum/stack_recipe("dance pole", /obj/structure/dancepole, 1, time = 10, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60)
- recipes += new/datum/stack_recipe("frame", /obj/item/frame, 5, time = 25, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("mirror frame", /obj/item/frame/mirror, 1, time = 5, one_per_turf = 0, on_floor = 1)
- recipes += new/datum/stack_recipe("fire extinguisher cabinet frame", /obj/item/frame/extinguisher_cabinet, 4, time = 5, one_per_turf = 0, on_floor = 1)
- //recipes += new/datum/stack_recipe("fire axe cabinet frame", /obj/item/frame/fireaxe_cabinet, 4, time = 5, one_per_turf = 0, on_floor = 1)
- recipes += new/datum/stack_recipe("railing", /obj/structure/railing, 2, time = 50, one_per_turf = 0, on_floor = 1)
- recipes += new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe_list("airlock assemblies", list( \
- new/datum/stack_recipe("standard airlock assembly", /obj/structure/door_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("command airlock assembly", /obj/structure/door_assembly/door_assembly_com, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("security airlock assembly", /obj/structure/door_assembly/door_assembly_sec, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("eng atmos airlock assembly", /obj/structure/door_assembly/door_assembly_eat, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("engineering airlock assembly", /obj/structure/door_assembly/door_assembly_eng, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("mining airlock assembly", /obj/structure/door_assembly/door_assembly_min, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("atmospherics airlock assembly", /obj/structure/door_assembly/door_assembly_atmo, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("research airlock assembly", /obj/structure/door_assembly/door_assembly_research, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("medical airlock assembly", /obj/structure/door_assembly/door_assembly_med, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_mai, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("external airlock assembly", /obj/structure/door_assembly/door_assembly_ext, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("freezer airlock assembly", /obj/structure/door_assembly/door_assembly_fre, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("airtight hatch assembly", /obj/structure/door_assembly/door_assembly_hatch, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("maintenance hatch assembly", /obj/structure/door_assembly/door_assembly_mhatch, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("voidcraft airlock assembly horizontal", /obj/structure/door_assembly/door_assembly_voidcraft, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("voidcraft airlock assembly vertical", /obj/structure/door_assembly/door_assembly_voidcraft/vertical, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("emergency shutter", /obj/structure/firedoor_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("multi-tile airlock assembly", /obj/structure/door_assembly/multi_tile, 4, time = 50, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("IV drip", /obj/machinery/iv_drip, 4, time = 20, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("conveyor switch", /obj/machinery/conveyor_switch, 2, time = 20, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("grenade casing", /obj/item/grenade/chem_grenade)
- recipes += new/datum/stack_recipe("light fixture frame", /obj/item/frame/light, 2)
- recipes += new/datum/stack_recipe("small light fixture frame", /obj/item/frame/light/small, 1)
- recipes += new/datum/stack_recipe("fairy light fixture frame", /obj/item/frame/light/fairy, 1)
- recipes += new/datum/stack_recipe("floor lamp fixture frame", /obj/machinery/light_construct/flamp, 2)
- recipes += new/datum/stack_recipe("apc frame", /obj/item/frame/apc, 2)
- recipes += new/datum/stack_recipe_list("modular computer frames", list( \
- new/datum/stack_recipe("modular console frame", /obj/item/modular_computer/console, 20),\
- new/datum/stack_recipe("modular telescreen frame", /obj/item/modular_computer/telescreen, 10),\
- new/datum/stack_recipe("modular laptop frame", /obj/item/modular_computer/laptop, 10),\
- new/datum/stack_recipe("modular tablet frame", /obj/item/modular_computer/tablet, 5),\
- ))
- recipes += new/datum/stack_recipe_list("filing cabinets", list( \
- new/datum/stack_recipe("filing cabinet", /obj/structure/filingcabinet, 4, time = 20, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("tall filing cabinet", /obj/structure/filingcabinet/filingcabinet, 4, time = 20, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("chest drawer", /obj/structure/filingcabinet/chestdrawer, 4, time = 20, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("desk bell", /obj/item/deskbell, 1, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("scooter frame", /obj/item/scooter_frame, 5, time = 20, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("metal coffin", /obj/structure/closet/coffin/comfy, 5, time = 15, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe_list("teshari nests", list(
- new/datum/stack_recipe("small teshari nest", /obj/structure/bed/chair/bay/chair/padded/red/smallnest, 1, one_per_turf = 1, on_floor = 1), //So, turns out that I don't know how to edit how much the nests give on deconstruction - Papalus
- new/datum/stack_recipe("large teshari nest", /obj/structure/bed/chair/bay/chair/padded/red/bignest, 1, one_per_turf = 1, on_floor = 1), //And so, I gave them the construction price equal to decon material gain. You can balance it yourselves. - Papalus
- ))
- recipes += new/datum/stack_recipe("light switch frame", /obj/item/frame/lightswitch, 2)
- recipes += new/datum/stack_recipe_list("sofas", list( \
- new/datum/stack_recipe("sofa middle", /obj/structure/bed/chair/sofa, 1, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("sofa left", /obj/structure/bed/chair/sofa/left, 1, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("sofa right", /obj/structure/bed/chair/sofa/right, 1, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("sofa corner", /obj/structure/bed/chair/sofa/corner, 1, one_per_turf = 1, on_floor = 1), \
- ))
-
-/datum/material/plasteel/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = 1)
- recipes += new/datum/stack_recipe("Metal crate", /obj/structure/closet/crate, 10, time = 50, one_per_turf = 1)
- recipes += new/datum/stack_recipe("knife grip", /obj/item/material/butterflyhandle, 4, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("dark floor tile", /obj/item/stack/tile/floor/dark, 1, 4, 20)
- recipes += new/datum/stack_recipe("roller bed", /obj/item/roller, 5, time = 30, on_floor = 1)
- recipes += new/datum/stack_recipe("whetstone", /obj/item/whetstone, 2, time = 10)
- recipes += new/datum/stack_recipe("reinforced skateboard assembly", /obj/item/heavy_skateboard_frame, 10, time = 20, one_per_turf = 1)
- recipes += new/datum/stack_recipe("plasteel floor tile", /obj/item/stack/tile/plasteel, 1, 4, 20)
-
-/datum/material/sandstone/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("planting bed", /obj/machinery/portable_atmospherics/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("sandstone floor tile", /obj/item/stack/tile/floor/sandstone, 1, 4, 20)
- recipes += new/datum/stack_recipe("sandstone jar", /obj/item/reagent_containers/glass/bucket/sandstone, 2, time = 4, one_per_turf = 0, on_floor = 0, pass_stack_color = FALSE)
-
-/datum/material/sandstone/marble/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("light marble floor tile", /obj/item/stack/tile/wmarble, 1, 4, 20)
- recipes += new/datum/stack_recipe("dark marble floor tile", /obj/item/stack/tile/bmarble, 1, 4, 20)
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("male statue", /obj/structure/statue/marble/male, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("female statue", /obj/structure/statue/marble/female, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("monkey statue", /obj/structure/statue/marble/monkey, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("corgi statue", /obj/structure/statue/marble/corgi, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
-
-/datum/material/plastic/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("plastic crate", /obj/structure/closet/crate/plastic, 10, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("plastic bag", /obj/item/storage/bag/plasticbag, 3, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("blood pack", /obj/item/reagent_containers/blood/empty, 4, on_floor = 0, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("reagent dispenser cartridge (large)", /obj/item/reagent_containers/cartridge/dispenser/large, 5, on_floor=0, pass_stack_color = TRUE) // 500u
- recipes += new/datum/stack_recipe("reagent dispenser cartridge (med)", /obj/item/reagent_containers/cartridge/dispenser/medium, 3, on_floor=0, pass_stack_color = TRUE) // 250u
- recipes += new/datum/stack_recipe("reagent dispenser cartridge (small)", /obj/item/reagent_containers/cartridge/dispenser/small, 1, on_floor=0, pass_stack_color = TRUE) // 100u
- recipes += new/datum/stack_recipe("white floor tile", /obj/item/stack/tile/floor/white, 1, 4, 20, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("freezer floor tile", /obj/item/stack/tile/floor/freezer, 1, 4, 20, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("shower curtain", /obj/structure/curtain, 4, time = 15, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 4, time = 25, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("airtight plastic flaps", /obj/structure/plasticflaps/mining, 5, time = 25, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("water-cooler", /obj/structure/reagent_dispensers/water_cooler, 4, time = 10, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("lampshade", /obj/item/lampshade, 1, time = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("rubberized wheels", /obj/item/skate_wheels, 12, time = 24)
- recipes += new/datum/stack_recipe("plastic raincoat", /obj/item/clothing/suit/storage/hooded/rainponcho, 5, time = 10)
-
-/datum/material/wood/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("oar", /obj/item/oar, 2, time = 30, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("boat", /obj/vehicle/ridden/boat, 20, time = 10 SECONDS, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("dragon boat", /obj/vehicle/ridden/boat/dragon, 50, time = 30 SECONDS, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("wood circlet", /obj/item/clothing/head/woodcirclet, 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("clipboard", /obj/item/clipboard, 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("wood roofing tile", /obj/item/stack/tile/roofing/wood, 3, 4, 20)
- recipes += new/datum/stack_recipe("wooden chair", /obj/structure/bed/chair/wood, 3, time = 10, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("crossbow frame", /obj/item/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- // Pew pew pew
- recipes += new/datum/stack_recipe_list("pews", list( \
- new/datum/stack_recipe("pew middle", /obj/structure/bed/chair/pew, 1, one_per_turf = 1, on_floor = 1, supplied_material = "[name]"), \
- new/datum/stack_recipe("pew left", /obj/structure/bed/chair/pew/left, 1, one_per_turf = 1, on_floor = 1, supplied_material = "[name]"), \
- new/datum/stack_recipe("pew right", /obj/structure/bed/chair/pew/right, 1, one_per_turf = 1, on_floor = 1, supplied_material = "[name]"), \
- ))
- recipes += new/datum/stack_recipe("beehive assembly", /obj/item/beehive_assembly, 4, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("beehive frame", /obj/item/honey_frame, 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("book shelf", /obj/structure/bookcase, 5, time = 15, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("noticeboard frame", /obj/item/frame/noticeboard, 4, time = 5, one_per_turf = 0, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 4, one_per_turf = 0, on_floor = 0, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("coilgun stock", /obj/item/coilgun_assembly, 5, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("drying rack", /obj/machinery/smartfridge/drying_rack, 10)
- recipes += new/datum/stack_recipe("skateboard assembly", /obj/item/skateboard_frame, 10, time = 20, one_per_turf = 1)
- recipes += new/datum/stack_recipe("bokken blade", /obj/item/bokken_blade, 10, time = 10)
- recipes += new/datum/stack_recipe("bokken hilt", /obj/item/bokken_hilt, 5, time = 10)
- recipes += new/datum/stack_recipe("wakibokken blade", /obj/item/wakibokken_blade, 10, time = 5)
- recipes += new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 5, time = 5)
- recipes += new/datum/stack_recipe("wooden panel", /obj/structure/window/wooden, 1, time = 10, one_per_turf = 0, on_floor = 1)
- recipes += new/datum/stack_recipe_list("wooden fencing", list( \
- new/datum/stack_recipe("fence", /obj/structure/fence/wooden, 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("fence end", /obj/structure/fence/wooden/end, 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("fencepost", /obj/structure/fence/wooden/post, 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("fence corner", /obj/structure/fence/wooden/corner, 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("gate", /obj/structure/fence/door/wooden, 5, one_per_turf = 1, on_floor = 1), \
- ))
-
-/datum/material/wood/hardwood/generate_recipes()
- //we're not going to ..() since we want to override the list entirely, to cut out all the stuff it'd inherit from wood - important, or else we'd have to fuss around with more subtypes to stop people turning hardwood into regular wood
- recipes = list()
- recipes += new/datum/stack_recipe("[display_name] baseball bat", /obj/item/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] grave marker", /obj/item/material/gravemarker, 5, time = 50, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] ring", /obj/item/clothing/gloves/ring/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] bracelet", /obj/item/clothing/accessory/bracelet/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- //TODO - make hardwood tile and floor sprites
- //recipes += new/datum/stack_recipe("hardwood floor tile", /obj/item/stack/tile/wood/hard, 1, 4, 20)
-
- recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] barricade", /obj/structure/barricade, 5, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] stool", /obj/item/stool, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] bed", /obj/structure/bed, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] double bed", /obj/structure/bed/double, 4, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("oar", /obj/item/oar, 2, time = 30, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("boat", /obj/vehicle/ridden/boat, 20, time = 10 SECONDS, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("dragon boat", /obj/vehicle/ridden/boat/dragon, 50, time = 30 SECONDS, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("crossbow frame", /obj/item/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0)
- recipes += new/datum/stack_recipe("coilgun stock", /obj/item/coilgun_assembly, 5)
- recipes += new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1)
- // Pew pew pew
- recipes += new/datum/stack_recipe_list("pews", list( \
- new/datum/stack_recipe("pew middle", /obj/structure/bed/chair/pew, 1, one_per_turf = 1, on_floor = 1, supplied_material = "[name]"), \
- new/datum/stack_recipe("pew left", /obj/structure/bed/chair/pew/left, 1, one_per_turf = 1, on_floor = 1, supplied_material = "[name]"), \
- new/datum/stack_recipe("pew right", /obj/structure/bed/chair/pew/right, 1, one_per_turf = 1, on_floor = 1, supplied_material = "[name]"), \
- ))
- recipes += new/datum/stack_recipe("hardwood bokken blade", /obj/item/bokken_blade/hardwood, 10, time = 20)
- recipes += new/datum/stack_recipe("hardwood wakibokken blade", /obj/item/wakibokken_blade/hardwood, 5, time = 10)
-
-/datum/material/wood/log/generate_recipes()
- recipes = list()
- recipes += new/datum/stack_recipe("bonfire", /obj/structure/bonfire, 5, time = 50, supplied_material = "[name]", pass_stack_color = TRUE)
-
-/datum/material/cardboard/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("box", /obj/item/storage/box, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("donut box", /obj/item/storage/box/donut/empty, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("egg box", /obj/item/storage/fancy/egg_box, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("light tubes box", /obj/item/storage/box/lights/tubes, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("light bulbs box", /obj/item/storage/box/lights/bulbs, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("mouse traps box", /obj/item/storage/box/mousetraps, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("cardborg suit", /obj/item/clothing/suit/cardborg, 3, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("cardborg helmet", /obj/item/clothing/head/cardborg, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("pizza box", /obj/item/pizzabox, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("large cardboard box", /obj/structure/closet/largecardboard, 3, time = 25, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe_list("folders",list( \
- new/datum/stack_recipe("blue folder", /obj/item/folder/blue), \
- new/datum/stack_recipe("grey folder", /obj/item/folder), \
- new/datum/stack_recipe("red folder", /obj/item/folder/red), \
- new/datum/stack_recipe("white folder", /obj/item/folder/white), \
- new/datum/stack_recipe("yellow folder", /obj/item/folder/yellow), \
- ))
-
-/datum/material/snow/generate_recipes()
- recipes = list()
- recipes += new/datum/stack_recipe("snowball", /obj/item/material/snow/snowball, 1, time = 10)
- recipes += new/datum/stack_recipe("snow brick", /obj/item/stack/material/snowbrick, 2, time = 10)
- recipes += new/datum/stack_recipe("snowman", /obj/structure/snowman, 2, time = 15)
- recipes += new/datum/stack_recipe("snow robot", /obj/structure/snowman/borg, 2, time = 10)
- recipes += new/datum/stack_recipe("snow spider", /obj/structure/snowman/spider, 3, time = 20)
- recipes += new/datum/stack_recipe("snowman head", /obj/item/clothing/head/snowman, 5, time = 5)
- recipes += new/datum/stack_recipe("snowman suit", /obj/item/clothing/suit/snowman, 10, time = 10)
-
-/datum/material/snowbrick/generate_recipes()
- recipes = list()
- recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("[display_name] barricade", /obj/structure/barricade, 5, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("[display_name] stool", /obj/item/stool, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("[display_name] chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("[display_name] bed", /obj/structure/bed, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("[display_name] double bed", /obj/structure/bed/double, 4, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("[display_name] wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
- recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
-
-/datum/material/wood/sif/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("alien wood floor tile", /obj/item/stack/tile/wood/sif, 1, 4, 20, pass_stack_color = TRUE)
- for(var/datum/stack_recipe/r_recipe in recipes)
- if(r_recipe.title == "wood floor tile")
- recipes -= r_recipe
- continue
- if(r_recipe.title == "wooden chair")
- recipes -= r_recipe
- continue
-
-/datum/material/supermatter/generate_recipes()
- recipes = list()
- recipes += new/datum/stack_recipe("supermatter shard", /obj/machinery/power/supermatter/shard, 30 , one_per_turf = 1, time = 600, on_floor = 1)
-
-/datum/material/cloth/generate_recipes()
- recipes = list()
- recipes += new/datum/stack_recipe("bedsheet", /obj/item/bedsheet, 10, time = 30 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe_list("colored bedsheets", list( \
- new/datum/stack_recipe("red bedsheet", /obj/item/bedsheet/red, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("orange bedsheet", /obj/item/bedsheet/orange, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("yellow bedsheet", /obj/item/bedsheet/yellow, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("green bedsheet", /obj/item/bedsheet/green, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("blue bedsheet", /obj/item/bedsheet/blue, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("purple bedsheet", /obj/item/bedsheet/purple, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("brown bedsheet", /obj/item/bedsheet/brown, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("rainbow bedsheet", /obj/item/bedsheet/rainbow, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- ))
- recipes += new/datum/stack_recipe("double bedsheet", /obj/item/bedsheet/double, 10, time = 30 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe_list("colored double bedsheets", list( \
- new/datum/stack_recipe("red double bedsheet", /obj/item/bedsheet/reddouble, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("orange doudble bedsheet", /obj/item/bedsheet/orangedouble, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("yellow double bedsheet", /obj/item/bedsheet/yellowdouble, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("green double bedsheet", /obj/item/bedsheet/greendouble, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("blue double bedsheet", /obj/item/bedsheet/bluedouble, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("purple double bedsheet", /obj/item/bedsheet/purpledouble, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("brown double bedsheet", /obj/item/bedsheet/browndouble, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- new/datum/stack_recipe("rainbow double bedsheet", /obj/item/bedsheet/rainbowdouble, 10, time = 30 SECONDS, pass_stack_color = TRUE), \
- ))
- recipes += new/datum/stack_recipe("uniform", /obj/item/clothing/under/color/white, 8, time = 15 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("foot wraps", /obj/item/clothing/shoes/footwraps, 2, time = 5 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("gloves", /obj/item/clothing/gloves/white, 2, time = 5 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("wig", /obj/item/clothing/head/powdered_wig, 4, time = 10 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("philosopher's wig", /obj/item/clothing/head/philosopher_wig, 50, time = 2 MINUTES, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("taqiyah", /obj/item/clothing/head/taqiyah, 3, time = 6 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("turban", /obj/item/clothing/head/turban, 3, time = 6 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("hijab", /obj/item/clothing/head/hijab, 3, time = 6 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("kippa", /obj/item/clothing/head/kippa, 3, time = 6 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("kippa", /obj/item/clothing/head/traveller, 3, time = 6 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("scarf", /obj/item/clothing/accessory/scarf/white, 4, time = 5 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("baggy pants", /obj/item/clothing/under/pants/baggy/white, 8, time = 10 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("belt pouch", /obj/item/storage/belt/fannypack/white, 25, time = 1 MINUTE, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("crude bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("empty sandbag", /obj/item/stack/emptysandbag, 2, 5, 10, time = 2 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("shrine seal", /obj/structure/shrine_seal, 2, time = 5 SECONDS)
- recipes += new/datum/stack_recipe("cloth rag", /obj/item/reagent_containers/glass/rag, 1, time = 2 SECONDS)
- recipes += new/datum/stack_recipe("woven string", /obj/item/weaponcrafting/string, 1, time = 10)
-
-/datum/material/resin/generate_recipes()
- recipes = list()
- recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door/resin, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] barricade", /obj/effect/alien/resin/wall, 5, time = 5 SECONDS, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] nest", /obj/structure/bed/nest, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] wall girders", /obj/structure/girder/resin, 2, time = 5 SECONDS, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("crude [display_name] bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] membrane", /obj/effect/alien/resin/membrane, 1, time = 2 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] node", /obj/effect/alien/weeds/node, 1, time = 4 SECONDS)
-
-/datum/material/silver/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("head of security statue", /obj/structure/statue/silver/hos, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("medical doctor statue", /obj/structure/statue/silver/md, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("janitor statue", /obj/structure/statue/silver/janitor, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("security statue", /obj/structure/statue/silver/sec, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("secborg statue", /obj/structure/statue/silver/secborg, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("medborg statue", /obj/structure/statue/silver/medborg, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("silver floor tile", /obj/item/stack/tile/silver, 1, 4, 20)
-
-/datum/material/gold/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("golden crown", /obj/item/clothing/head/crown, 10, time = 30)
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("head of security statue", /obj/structure/statue/gold/hos, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("head of personnel statue", /obj/structure/statue/gold/hop, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("chief medical officer statue", /obj/structure/statue/gold/cmo, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("chief engineer statue", /obj/structure/statue/gold/ce, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("research director statue", /obj/structure/statue/gold/rd, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("gold floor tile", /obj/item/stack/tile/gold, 1, 4, 20)
-
-/datum/material/phoron/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("scientist statue", /obj/structure/statue/phoron/scientist, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("xenomorph statue", /obj/structure/statue/phoron/xeno, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("phoron floor tile", /obj/item/stack/tile/phoron, 1, 4, 20)
-
-/datum/material/uranium/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("nuke statue", /obj/structure/statue/uranium/nuke, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("engineer statue", /obj/structure/statue/uranium/eng, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("uranium floor tile", /obj/item/stack/tile/uranium, 1, 4, 20)
-
-/datum/material/diamond/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("captain statue", /obj/structure/statue/diamond/captain, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("ai hologram statue", /obj/structure/statue/diamond/ai1, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("ai core statue", /obj/structure/statue/diamond/ai2, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("diamond floor tile", /obj/item/stack/tile/diamond, 1, 4, 20)
-
-/datum/material/sandstone/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("assistant statue", /obj/structure/statue/sandstone/assistant, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
-
-/datum/material/bananium/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("bananium statue", /obj/structure/statue/bananium, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("clown statue", /obj/structure/statue/bananium/clown, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("bananium floor tile", /obj/item/stack/tile/bananium, 1, 4, 20)
-
-/datum/material/silencium/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("silencium floor tile", /obj/item/stack/tile/silencium, 1, 4, 20)
-
-/datum/material/durasteel/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("durasteel floor tile", /obj/item/stack/tile/durasteel, 1, 4, 20)
-
-/datum/material/brass/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("brass floor tile", /obj/item/stack/tile/brass, 1, 4, 20)
-
-/datum/material/leather/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("wallet", /obj/item/storage/wallet, 1)
- recipes += new/datum/stack_recipe("muzzle", /obj/item/clothing/mask/muzzle, 2)
- recipes += new/datum/stack_recipe("botany gloves", /obj/item/clothing/gloves/botanic_leather, 3)
- recipes += new/datum/stack_recipe("toolbelt", /obj/item/storage/belt/utility, 4)
- recipes += new/datum/stack_recipe("leather satchel", /obj/item/storage/backpack/satchel, 5)
- recipes += new/datum/stack_recipe("bandolier", /obj/item/storage/belt/security/tactical/bandolier, 5)
- recipes += new/datum/stack_recipe("leather jacket", /obj/item/clothing/suit/storage/toggle/leather_jacket, 7)
- recipes += new/datum/stack_recipe("leather shoes", /obj/item/clothing/shoes/laceup, 2)
- recipes += new/datum/stack_recipe("leather overcoat", /obj/item/clothing/suit/overcoat, 10)
- recipes += new/datum/stack_recipe("voyager satchel", /obj/item/storage/backpack/satchel/voyager, 10)
- recipes += new/datum/stack_recipe("voyager backpack", /obj/item/storage/backpack/voyager, 10)
- recipes += new/datum/stack_recipe("voyager harness", /obj/item/clothing/accessory/storage/voyager, 8)
-
-/datum/material/bone/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe_list("statues", list( \
- new/datum/stack_recipe("bone statue", /obj/structure/statue/bone, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("skull statue", /obj/structure/statue/bone/skull, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("half skull statue", /obj/structure/statue/bone/skull/half, 20, time = 5, one_per_turf = 1, on_floor = 1), \
- ))
- recipes += new/datum/stack_recipe("bone roofing tile", /obj/item/stack/tile/roofing/bone, 3, 4, 20)
- recipes += new/datum/stack_recipe("bone table frame", /obj/structure/table, 1, time = 10, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("bone crate", /obj/structure/closet/crate/ashlander, 10, time = 50, one_per_turf = 1)
-
-/datum/material/sinew/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("sinew restraints", /obj/item/handcuffs/sinew, 1)
-
-/datum/material/wax/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("candle", /obj/item/flame/candle, 1)
- recipes += new/datum/stack_recipe("wax floor tile", /obj/item/stack/tile/wax, 1, 4, 20)
- recipes += new/datum/stack_recipe("honeycomb floor tile", /obj/item/stack/tile/honeycomb, 1, 4, 20)
- recipes += new/datum/stack_recipe("wax globule", /obj/item/ammo_casing/organic/wax, 1)
- recipes += new/datum/stack_recipe("royal throne", /obj/structure/bed/chair/apidean, 20, time = 10, one_per_turf = 1, on_floor = 1)
- recipes += new/datum/stack_recipe("apidean stool", /obj/structure/bed/chair/apidean_stool, 5, time = 5, one_per_turf = 1, on_floor = 1)
diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm
index b9d32de0dea6..e734680c57bb 100644
--- a/code/modules/materials/material_sheets.dm
+++ b/code/modules/materials/material_sheets.dm
@@ -32,8 +32,6 @@
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
-
- recipes = material.get_recipes()
stacktype = material.stack_type
if(islist(material.stack_origin_tech))
origin_tech = material.stack_origin_tech.Copy()
@@ -50,6 +48,20 @@
/obj/item/stack/material/get_material()
return material
+/obj/item/stack/material/tgui_recipes()
+ var/list/assembled = ..()
+ for(var/datum/stack_recipe/recipe as anything in material.get_recipes())
+ assembled[++assembled.len] = recipe.tgui_recipe_data()
+ for(var/datum/stack_recipe/material/recipe as anything in SSmaterials.material_stack_recipes)
+ assembled[++assembled.len] = recipe.tgui_recipe_data()
+ return assembled
+
+/obj/item/stack/material/can_craft_recipe(datum/stack_recipe/recipe)
+ . = ..()
+ if(.)
+ return
+ return (recipe in material.recipes) || (istype(recipe, /datum/stack_recipe/material) && (recipe in SSmaterials.material_stack_recipes))
+
/obj/item/stack/material/proc/update_strings()
// Update from material datum.
singular_name = material.sheet_singular_name
diff --git a/code/modules/materials/recipes.dm b/code/modules/materials/recipes.dm
new file mode 100644
index 000000000000..c22f9bd3ef49
--- /dev/null
+++ b/code/modules/materials/recipes.dm
@@ -0,0 +1,21 @@
+/**
+ * get recipe list
+ */
+/datum/material/proc/get_recipes()
+ return isnull(recipes)? generate_recipes() : recipes
+
+/**
+ * regenerate recipes list and return it
+ */
+/datum/material/proc/generate_recipes()
+ recipes = list()
+ recipes += special_recipes()
+ return recipes
+
+/**
+ * allows for better override support, for when you want specific subtypes to have specific recipes
+ *
+ * returns a recipe list that's added to generate_recipes()
+ */
+/datum/material/proc/special_recipes()
+ return list()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station/service.dm b/code/modules/mob/living/silicon/robot/robot_modules/station/service.dm
index a26142e3434d..39ad97d287e0 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules/station/service.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules/station/service.dm
@@ -247,8 +247,8 @@
M.name = "steel recycler"
M.desc = "A device that refines recycled steel into sheets."
M.synths = list(synths_by_kind[MATSYN_METAL])
- M.recipes = list(
- new/datum/stack_recipe("steel sheet", /obj/item/stack/material/steel, 1, 1, 20)
+ M.explicit_recipes = list(
+ create_stack_recipe_datum(name = "steel sheet", product = /obj/item/stack/material/steel, cost = 1)
)
. += M
@@ -257,8 +257,8 @@
G.desc = "A device that refines recycled glass into sheets."
G.allow_window_autobuild = FALSE
G.synths = list(synths_by_kind[MATSYN_GLASS])
- G.recipes = list(
- new/datum/stack_recipe("glass sheet", /obj/item/stack/material/glass, 1, 1, 20)
+ M.explicit_recipes = list(
+ create_stack_recipe_datum(name = "glass sheet", product = /obj/item/stack/material/glass, cost = 1)
)
. += G
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index b0abe9446239..ec554610ae5d 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -63,6 +63,11 @@
init_id()
init_subsystems()
+ for(var/datum/language/L as anything in SScharacters.all_languages())
+ if(L.translation_class & TRANSLATION_CLASS_LEVEL_1)
+ add_language(L)
+ add_language(LANGUAGE_EAL)
+
/mob/living/silicon/Destroy()
silicon_mob_list -= src
for(var/datum/alarm_handler/AH in SSalarms.all_handlers)
diff --git a/code/modules/multiz/ladder_assembly_vr.dm b/code/modules/multiz/ladder_assembly_vr.dm
index 1e8fecae95bc..747b0afddca9 100644
--- a/code/modules/multiz/ladder_assembly_vr.dm
+++ b/code/modules/multiz/ladder_assembly_vr.dm
@@ -124,11 +124,6 @@
L.name = above.created_name
qdel(above)
-// Make them constructable in hand
-/datum/material/steel/generate_recipes()
- ..()
- recipes += new/datum/stack_recipe("ladder assembly", /obj/structure/ladder_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1)
-
#undef CONSTRUCTION_UNANCHORED
#undef CONSTRUCTION_WRENCHED
#undef CONSTRUCTION_WELDED
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index 18ccc45cf3bb..b934c3fc88c6 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -24,7 +24,7 @@
/obj/structure/filingcabinet/chestdrawer/unanchored
anchored = FALSE
-/obj/structure/filingcabinet/filingcabinet //not changing the path to avoid unecessary map issues, but please don't name stuff like this in the future -Pete
+/obj/structure/filingcabinet/tall //not changing the path to avoid unecessary map issues, but please don't name stuff like this in the future -Pete
icon_state = "tallcabinet"
diff --git a/code/modules/research/designs/circuits/circuits.dm b/code/modules/research/designs/circuits/circuits.dm
index ce13b233156a..7013d4d82ed3 100644
--- a/code/modules/research/designs/circuits/circuits.dm
+++ b/code/modules/research/designs/circuits/circuits.dm
@@ -472,6 +472,24 @@ CIRCUITS BELOW
req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2, TECH_ILLEGAL = 4)
build_path = /obj/item/circuitboard/mecha/honker/targeting
+/datum/design/circuit/mecha/phazon_main
+ design_name = "'Phazon' central control"
+ id = "phazon_main"
+ req_tech = list(TECH_DATA = 6, TECH_COMBAT = 4, TECH_BLUESPACE = 6, TECH_ARCANE = 2)
+ build_path = /obj/item/circuitboard/mecha/phazon/main
+
+/datum/design/circuit/mecha/phazon_peri
+ design_name = "'Phazon' peripherals control"
+ id = "phazon_peri"
+ req_tech = list(TECH_DATA = 6, TECH_COMBAT = 4, TECH_BLUESPACE = 6, TECH_ARCANE = 2)
+ build_path = /obj/item/circuitboard/mecha/phazon/peripherals
+
+/datum/design/circuit/mecha/phazon_targ
+ design_name = "'Phazon' weapon control and targeting"
+ id = "phazon_targ"
+ req_tech = list(TECH_DATA = 6, TECH_COMBAT = 4, TECH_BLUESPACE = 6, TECH_ARCANE = 2)
+ build_path = /obj/item/circuitboard/mecha/phazon/targeting
+
/datum/design/circuit/mecha/reticent_main
design_name = "'Reticent' central control"
id = "reticent_main"
diff --git a/code/modules/research/designs/mechfab_designs.dm b/code/modules/research/designs/mechfab_designs.dm
index 02f1144cf037..1004f16256eb 100644
--- a/code/modules/research/designs/mechfab_designs.dm
+++ b/code/modules/research/designs/mechfab_designs.dm
@@ -947,7 +947,7 @@
id = "melectricalhigh"
req_tech = list(TECH_ENGINEERING = 5, TECH_POWER = 5, TECH_MATERIAL = 4)
materials = list(MAT_STEEL = 3000, MAT_GLASS = 4000, MAT_PLASTIC = 5000, MAT_GOLD = 5000)
- build_path = /obj/item/mecha_parts/component/electrical
+ build_path = /obj/item/mecha_parts/component/electrical/high_current
/datum/design/science/mecha_component/hull
design_name = "Mecha Hull"
diff --git a/code/modules/sculpting/sculpting_block.dm b/code/modules/sculpting/sculpting_block.dm
new file mode 100644
index 000000000000..899e34465699
--- /dev/null
+++ b/code/modules/sculpting/sculpting_block.dm
@@ -0,0 +1,540 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/**
+ * Dynamic sculpting!
+ *
+ * Later to replace statues entirely.
+ *
+ * Sprites generously 'borrowed' from /tg/station.
+ * Idea is from /tg/station, but entirely reimplemented here.
+ *
+ * stay awesome tg (:
+ *
+ * todo: add in a way to preload a template so it starts out sculpted, and an initialize() override for such
+ * todo: de/serialization
+ * todo: sculpting with shit tools should result in a bad image
+ * todo: the full white alpha masks should be cached
+ */
+/obj/structure/sculpting_block
+ name = "material block"
+ desc = "A block of material. You can sculpt this with appropriate tools, like a screwdriver."
+ icon = 'icons/modules/sculpting/sculpting.dmi'
+ icon_state = "block"
+ density = TRUE
+ anchored = FALSE
+
+ /// finished base state
+ var/sculpture_base_state = "base"
+ /// material ref
+ var/datum/material/material = /datum/material/steel
+
+ icon_x_dimension = 32
+ icon_y_dimension = 32
+ bound_width = 32
+ bound_height = 32
+
+ /// is this sculpture finished?
+ var/finished = FALSE
+ /// sculpture x alignment offset
+ var/alignment = 0
+
+ /// currently being sculpted
+ var/sculpting = FALSE
+ /// current icon being sculpted
+ var/icon/sculpting_buffer
+ /// y start; this is set to sculpting_line at the start of an operation
+ var/sculpting_line_start
+ /// y end; this is set after end of sculpting right before we blend it into our icon
+ var/sculpting_line_end
+ /// is the model overlaid yet? for ones that get aligned to bottom, we don't overlay immediately.
+ var/sculpting_overlay_active
+ /// scultping user, if any
+ var/mob/sculpting_user
+ /// sculpting target
+ var/atom/movable/sculpting_target
+
+ /// current icon for sculpting; every operation flushes to this, this begins at a x by y blank.
+ /// we don't flush directly to our icon only because icon might get fucked with
+ /// list(north, east, south, west)
+ var/list/icon/sculpting_slates
+ /// current combined slates
+ var/icon/sculpting_built
+ /// sculpting block is assumed to be a certain size
+ /// store the current line being sculpted
+ /// this starts at the topmost y
+ /// if we're done sculpting, this should be nulled for consistency
+ var/sculpting_line
+ /// virtual vis contents holder for buffer
+ var/atom/movable/sculpting_render/sculpting_renderer
+ /// slate dimension y
+ var/slate_dimension_y
+ /// slate dimension x
+ var/slate_dimension_x
+ /// amount of time it takes to sculpt one line at 1x toolspeed
+ var/sculpting_hardness = 0.5 SECONDS
+ /// sculpting mask for our slate
+ var/icon/sculpting_mask
+ /// sculpting mask for our block
+ var/icon/sculpting_rolldown_mask
+
+/obj/structure/sculpting_block/Initialize(mapload, material)
+ // todo: materials system
+ src.material = SSmaterials.get_material(material || src.material)
+ // todo: if it autoinit'd, don't do this
+ reset_sculpting()
+ return ..()
+
+/obj/structure/sculpting_block/Destroy()
+ QDEL_NULL(sculpting_renderer)
+ sculpting_mask = null
+ sculpting_rolldown_mask = null
+ sculpting_buffer = null
+ sculpting_built = null
+ sculpting_slates = null
+ return ..()
+
+/obj/structure/sculpting_block/examine(mob/user, dist)
+ . = ..()
+ . += SPAN_NOTICE("It is made out of [isnull(material)? "nothing?!": "[material.display_name]."]")
+ . += SPAN_NOTICE("Use a wrench to un/fasten the anchoring bolts.")
+ . += SPAN_NOTICE("Use a welder to slice it apart.")
+
+/obj/structure/sculpting_block/proc/reset_sculpting()
+ sculpting_line = icon_y_dimension
+ finished = FALSE
+ remove_filter("top_erasure")
+ update_appearance()
+
+/obj/structure/sculpting_block/update_icon(updates)
+ if(length(underlays))
+ underlays.len = 0
+ cut_overlays()
+ if(sculpting_built)
+ var/image/render = new
+ render.icon = sculpting_built
+ render.appearance_flags = KEEP_APART | RESET_COLOR
+ add_overlay(render)
+ . = ..()
+ var/image/stand = image(initial(icon), icon_state = sculpture_base_state)
+ stand.appearance_flags = KEEP_APART | RESET_COLOR
+ stand.pixel_x = -alignment
+ underlays += stand
+
+/obj/structure/sculpting_block/attackby(obj/item/I, mob/living/user, list/params, clickchain_flags, damage_multiplier)
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+ if(user.a_intent == INTENT_HELP)
+ initiate_sculpting(user, tool = I)
+ return CLICKCHAIN_DO_NOT_PROPAGATE
+
+/obj/structure/sculpting_block/wrench_act(obj/item/I, mob/user, flags, hint)
+ . = ..()
+ if(.)
+ return
+ user.visible_action_feedback(
+ target = src,
+ hard_range = MESSAGE_RANGE_CONSTRUCTION,
+ visible_hard = SPAN_NOTICE("[user] starts [anchored? "unbolting [src] from the floor" : "bolting [src] to the floor"]."),
+ visible_self = SPAN_NOTICE("You start [anchored? "unbolting [src] from the floor" : "bolting [src] to the floor"]."),
+ audible_hard = SPAN_WARNING("You hear bolts being [anchored? "unfastened" : "fastened"]."),
+ )
+ log_construction(user, src, "started [anchored? "unanchoring" : "anchoring"]")
+ if(!use_wrench(I, user, flags, 3 SECONDS))
+ return TRUE
+ user.visible_action_feedback(
+ target = src,
+ hard_range = MESSAGE_RANGE_CONSTRUCTION,
+ visible_hard = SPAN_NOTICE("[user] finishes [anchored? "unbolting [src] from the floor" : "bolting [src] to the floor"]."),
+ visible_self = SPAN_NOTICE("You finish [anchored? "unbolting [src] from the floor" : "bolting [src] to the floor"]."),
+ audible_hard = SPAN_WARNING("You hear bolts [anchored? "falling out" : "clicking into place"]."),
+ )
+ log_construction(user, src, "[anchored? "unanchored" : "anchored"]")
+ set_anchored(!anchored)
+ return TRUE
+
+/obj/structure/sculpting_block/welder_act(obj/item/I, mob/user, flags, hint)
+ . = ..()
+ if(.)
+ return
+ user.visible_action_feedback(
+ target = src,
+ hard_range = MESSAGE_RANGE_CONSTRUCTION,
+ visible_hard = SPAN_NOTICE("[user] starts slicing [src] apart."),
+ visible_self = SPAN_NOTICE("You start slicing [src] apart."),
+ audible_hard = SPAN_WARNING("You hear the sound of a welding torch being used on something metallic."),
+ )
+ log_construction(user, src, "started deconstructing")
+ if(!use_welder(I, user, flags, 7 SECONDS, 3))
+ return TRUE
+ user.visible_action_feedback(
+ target = src,
+ hard_range = MESSAGE_RANGE_CONSTRUCTION,
+ visible_hard = SPAN_NOTICE("[user] slices [src] apart."),
+ visible_self = SPAN_NOTICE("You slice [src] apart."),
+ audible_hard = SPAN_WARNING("You hear the sound of a welding torch moving back into open air, and a few pieces of metal falling apart."),
+ )
+ log_construction(user, src, "deconstructed")
+ set_anchored(!anchored)
+ deconstruct(ATOM_DECONSTRUCT_DISASSEMBLED)
+ return TRUE
+
+/obj/structure/sculpting_block/drop_products(method)
+ . = ..()
+ material.place_sheet(drop_location(), 10)
+
+/obj/structure/sculpting_block/dynamic_tool_functions(obj/item/I, mob/user)
+ . = list()
+ .[TOOL_WRENCH] = anchored? "unanchor" : "anchor"
+ .[TOOL_WELDER] = "deconstruct"
+ return merge_double_lazy_assoc_list(., ..())
+
+/obj/structure/sculpting_block/dynamic_tool_image(function, hint)
+ . = ..()
+ if(.)
+ return
+ switch(hint)
+ if("unanchor")
+ return dyntool_image_backward(TOOL_WRENCH)
+ if("anchor")
+ return dyntool_image_forward(TOOL_WRENCH)
+ if("deconstruct")
+ return dyntool_image_backward(TOOL_WELDER)
+
+/**
+ * returns speed multiplier, or null if not tool
+ */
+/obj/structure/sculpting_block/proc/is_sculpting_tool(obj/item/tool, mob/user)
+ // todo: well fucking obviously we don't want to just have only screwdrivers usable, right gang? ~silicons
+ if(tool.is_screwdriver())
+ return tool.tool_speed
+ return null
+
+/obj/structure/sculpting_block/proc/initiate_sculpting(mob/user, silent, atom/movable/forced_target, obj/item/tool)
+ if(TIMER_COOLDOWN_CHECK(src, CD_INDEX_SCULPTING_COOLDOWN))
+ if(!silent)
+ user?.action_feedback(SPAN_WARNING("[src] was worked on too recently.."), src)
+ return FALSE
+ if(finished)
+ if(!silent)
+ user?.action_feedback(SPAN_WARNING("[src] is finished."), src)
+ return FALSE
+ if(sculpting)
+ if(!silent)
+ user?.action_feedback(SPAN_WARNING("Someone's already working on [src]."), src)
+ return FALSE
+ if(isnull(tool))
+ tool = user.get_active_held_item()
+ var/tool_multiplier = is_sculpting_tool(tool)
+ if(isnull(tool_multiplier))
+ if(!silent)
+ user?.action_feedback(SPAN_WARNING("You must be holding a valid sculpting tool."), src)
+ return FALSE
+ var/atom/movable/target = isnull(forced_target)? ask_for_target(user) : forced_target
+ if(isnull(target))
+ return FALSE
+ if(tool != user.get_active_held_item())
+ return FALSE
+ if(finished)
+ if(!silent)
+ user?.action_feedback(SPAN_WARNING("[src] is finished."), src)
+ return FALSE
+ if(sculpting)
+ if(!silent)
+ user?.action_feedback(SPAN_WARNING("Someone's already working on [src]."), src)
+ return FALSE
+ if(!user.Adjacent(src))
+ return FALSE
+
+ sculpting = TRUE
+
+ var/list/model_tuple = get_model_tuple(target)
+ TIMER_COOLDOWN_START(src, CD_INDEX_SCULPTING_COOLDOWN, 1 SECONDS)
+ var/icon/model = model_tuple[1]
+ var/model_width = model.Width()
+ var/model_height = model.Height()
+ if(model_height > icon_y_dimension)
+ if(!silent)
+ user.action_feedback(SPAN_WARNING("[target] is too tall."), src)
+ sculpting = FALSE
+ return FALSE
+ // align
+ var/model_x_align = 0
+ if(isnull(slate_dimension_x))
+ slate_dimension_x = icon_x_dimension
+ if(isnull(slate_dimension_y))
+ slate_dimension_y = icon_y_dimension
+ // align to bottom, center width
+ if(model_width != slate_dimension_x)
+ model_x_align = FLOOR((slate_dimension_x - model_width) / 2, 1)
+
+ sculpting_buffer = model
+ sculpting_user = user
+ sculpting_target = target
+ sculpting_line_start = sculpting_line
+ sculpting_overlay_active = model_height >= sculpting_line
+
+ var/lines = 0
+
+ if(isnull(sculpting_rolldown_mask))
+ sculpting_rolldown_mask = icon('icons/system/color_32x32.dmi', "white")
+ if(sculpting_rolldown_mask.Width() != icon_x_dimension || sculpting_rolldown_mask.Height() != icon_y_dimension)
+ sculpting_rolldown_mask.Scale(icon_x_dimension, icon_y_dimension)
+
+ if(isnull(sculpting_renderer))
+ sculpting_renderer = new
+ vis_contents += sculpting_renderer
+
+ sculpting_renderer.icon = sculpting_buffer
+ sculpting_renderer.pixel_x = model_x_align
+ sculpting_renderer.alpha = sculpting_overlay_active? initial(sculpting_renderer.alpha) : 0
+
+ if(isnull(sculpting_mask))
+ sculpting_mask = icon('icons/system/color_32x32.dmi', "white")
+ if(sculpting_mask.Width() != model_width || sculpting_mask.Height() != model_height)
+ sculpting_mask.Scale(model_width, model_height)
+
+ if(sculpting_overlay_active)
+ sculpting_renderer.add_filter("slate", 0, alpha_mask_filter(0, sculpting_line - model_height, sculpting_mask, flags = MASK_INVERSE))
+ sculpting_renderer.add_filter("cut_excess", 0, alpha_mask_filter(0, sculpting_line, sculpting_mask, flags = MASK_INVERSE))
+
+ // todo: actual chisels wit htoolsounds, screwdrivers are dogshit
+ playsound(src, 'sound/effects/break_stone.ogg', vary = TRUE, vol = 50)
+ user.visible_action_feedback(
+ target = src,
+ hard_range = MESSAGE_RANGE_CONSTRUCTION,
+ visible_hard = SPAN_NOTICE("[user] starts chiselling at [src]..."),
+ )
+
+ // deciseconds progress
+ var/progress = 0
+ var/time_per_line = sculpting_hardness * tool_multiplier
+ var/finished_progress = sculpting_line_start * time_per_line
+ var/last = world.time
+ var/last_line = 0
+
+ var/datum/progressbar/progressbar = new(user, sculpting_line, src)
+
+ while(progress < finished_progress)
+ if(QDELETED(src))
+ QDEL_NULL(progressbar)
+ return
+ if(!do_after(user, time_per_line, src, DO_AFTER_NO_PROGRESS))
+ break
+ var/should_be_at = sculpting_line - FLOOR(progress / time_per_line, 1)
+ if(should_be_at != last_line)
+ last_line = should_be_at
+ if(last_line > model_height)
+ else
+ if(!sculpting_overlay_active)
+ sculpting_overlay_active = TRUE
+ sculpting_renderer.alpha = 255
+ sculpting_renderer.add_filter("cut_excess", 0, alpha_mask_filter(0, sculpting_line, sculpting_mask, flags = MASK_INVERSE))
+ sculpting_renderer.add_filter("slate", 0, alpha_mask_filter(0, should_be_at - model_height, sculpting_mask, flags = MASK_INVERSE))
+ add_filter("top_erasure", 0, alpha_mask_filter(1, should_be_at, sculpting_rolldown_mask, flags = MASK_INVERSE))
+
+ progress += world.time - last
+ last = world.time
+ progressbar.update(sculpting_line - should_be_at)
+
+ QDEL_NULL(progressbar)
+
+ lines = min(sculpting_line, progress / time_per_line)
+
+ sculpting_line_end = sculpting_line_start - lines
+ sculpting_line -= lines
+
+ if(lines)
+ if(isnull(sculpting_slates))
+ create_slates()
+ var/model_x_realigned = 0
+ if(slate_dimension_x < model_width)
+ // allow expansion but only for width
+ var/x_alignment = FLOOR((model_width - slate_dimension_x) / 2, 1)
+ model_x_realigned = x_alignment
+ crop_slates(-x_alignment + 1, 1, slate_dimension_x + (model_width - slate_dimension_x - x_alignment), slate_dimension_y)
+ alignment -= x_alignment
+ set_base_pixel_x(base_pixel_x - x_alignment)
+ if(!sculpting_overlay_active)
+ // we didn't even reach the buffer yet
+ else
+ sculpting_buffer = crop_buffer(sculpting_buffer, 1, sculpting_line_end + 1, model_width, sculpting_line_start)
+ //! TODO: this shouldn't be needed, but somehow is because of shennanigans. Figure out why and get rid of.
+ preprocess_model_buffer(sculpting_buffer)
+ //! End
+ blend_slates(sculpting_buffer, model_x_align + 1 + model_x_realigned, sculpting_line_end + 1)
+ assemble_built()
+ update_appearance()
+
+ sculpting_line_start = null
+ sculpting_buffer = null
+ sculpting_line_end = null
+ sculpting_user = null
+ sculpting_target = null
+ sculpting_overlay_active = null
+
+ add_filter("top_erasure", 0, alpha_mask_filter(1, sculpting_line, sculpting_rolldown_mask, flags = MASK_INVERSE))
+ sculpting_renderer.alpha = 0
+ sculpting_renderer.clear_filters()
+
+ if(check_completion())
+ user.visible_action_feedback(
+ target = src,
+ hard_range = MESSAGE_RANGE_CONSTRUCTION,
+ visible_hard = SPAN_NOTICE("[user] finishes chiselling at [src] with a flourish."),
+ )
+
+ sculpting = FALSE
+
+/obj/structure/sculpting_block/proc/check_completion()
+ if(!sculpting_line)
+ finished = TRUE
+ flush_finished()
+ return TRUE
+ return FALSE
+
+/obj/structure/sculpting_block/proc/flush_finished()
+ assemble_built()
+ icon = sculpting_built
+ sculpting_built = null
+ sculpting_slates = null
+ name = "sculpted statue"
+ desc = "A custom-chiseled statue depicting a particular thing of note."
+ QDEL_NULL(sculpting_renderer)
+ clear_filters()
+ update_appearance()
+
+/obj/structure/sculpting_block/proc/crop_buffer(icon/buffer, x1, y1, x2, y2)
+ var/icon/built = icon('icons/system/blank_32x32.dmi', "")
+ var/icon/cropping
+ cropping = icon(buffer, dir = NORTH)
+ cropping.Crop(x1, y1, x2, y2)
+ built.Insert(cropping, dir = NORTH)
+ cropping = icon(buffer, dir = EAST)
+ cropping.Crop(x1, y1, x2, y2)
+ built.Insert(cropping, dir = EAST)
+ cropping = icon(buffer, dir = SOUTH)
+ cropping.Crop(x1, y1, x2, y2)
+ built.Insert(cropping, dir = SOUTH)
+ cropping = icon(buffer, dir = WEST)
+ cropping.Crop(x1, y1, x2, y2)
+ built.Insert(cropping, dir = WEST)
+ return built
+
+/obj/structure/sculpting_block/proc/assemble_built()
+ sculpting_built = icon('icons/system/blank_32x32.dmi', "")
+ sculpting_built.Insert(sculpting_slates[1], dir = NORTH)
+ sculpting_built.Insert(sculpting_slates[2], dir = EAST)
+ sculpting_built.Insert(sculpting_slates[3], dir = SOUTH)
+ sculpting_built.Insert(sculpting_slates[4], dir = WEST)
+
+/**
+ * grabs an icon from something for sculpting, processing it into a greyscale toned to the material's color
+ *
+ * @params
+ * * to_clone - the atom the person is trying to replicate with the sculpt. no turfs.
+ * * material_color - the color to tone to as rgb color string
+ *
+ * @return list(icon, x, y) where x/y are centering offsets
+ */
+/obj/structure/sculpting_block/proc/get_model_tuple(atom/movable/to_clone, material_color)
+ . = get_compound_icon_with_offsets(to_clone, CALLBACK(src, PROC_REF(preprocess_model_slice)))
+ if(isnull(.))
+ return
+
+/obj/structure/sculpting_block/proc/preprocess_model_slice(icon/slice)
+ slice.ColorTone(material.icon_colour)
+
+/obj/structure/sculpting_block/proc/preprocess_model_buffer(icon/slice)
+ slice.ColorTone(material.icon_colour)
+
+/**
+ * get things in range of user that can be sculpted
+ */
+/obj/structure/sculpting_block/proc/get_possible_targets(mob/user, range_to_scan = 7)
+ . = list()
+ var/list/atom/potential = view(range_to_scan, user)
+ var/list/mob/mobs = list()
+ var/list/obj/objs = list()
+ var/list/objs_seen_paths = list()
+ for(var/atom/movable/AM in potential)
+ if(AM.atom_flags & ATOM_ABSTRACT)
+ continue
+ if(!isturf(AM.loc))
+ continue
+ if(AM.invisibility > user.see_invisible)
+ continue
+ if(!user.can_see_plane(AM.plane))
+ continue
+ if(isobj(AM))
+ var/obj/O = AM
+ if(O.obj_flags & OBJ_NO_SCULPTING)
+ continue
+ if(objs_seen_paths[O.type])
+ continue
+ objs_seen_paths[O.type] = TRUE
+ objs += O
+ else
+ var/mob/M = AM
+ //! legacy code
+ if(M.is_incorporeal())
+ continue
+ //! end
+ mobs += M
+ return mobs + objs
+
+/**
+ * ask someone for target
+ */
+/obj/structure/sculpting_block/proc/ask_for_target(mob/user)
+ // todo: when we have click intercepts refactored, user should be asked to click on a target.
+ var/list/possible = get_possible_targets(user)
+ return input(user, "Pick a target", "Sculpting") as null|anything in possible
+
+/obj/structure/sculpting_block/proc/create_slates()
+ sculpting_slates = list()
+ for(var/i in 1 to 4)
+ var/icon/generated
+ generated = icon('icons/system/blank_32x32.dmi')
+ generated.Scale(icon_x_dimension, icon_y_dimension)
+ sculpting_slates += generated
+ slate_dimension_x = icon_x_dimension
+ slate_dimension_y = icon_y_dimension
+
+/obj/structure/sculpting_block/proc/blend_slates(icon/blending, x, y)
+ sculpting_slates[1].Blend(icon(blending, dir = NORTH), ICON_OVERLAY, x, y)
+ sculpting_slates[2].Blend(icon(blending, dir = EAST), ICON_OVERLAY, x, y)
+ sculpting_slates[3].Blend(icon(blending, dir = SOUTH), ICON_OVERLAY, x, y)
+ sculpting_slates[4].Blend(icon(blending, dir = WEST), ICON_OVERLAY, x, y)
+
+/obj/structure/sculpting_block/proc/crop_slates(x1, y1, x2, y2)
+ for(var/i in 1 to 4)
+ var/icon/cropping = sculpting_slates[i]
+ cropping.Crop(x1, y1, x2, y2)
+
+/obj/structure/sculpting_block/proc/check_target(mob/user, atom/movable/target)
+ if(isnull(sculpting_user))
+ return TRUE // userless
+ if(QDELETED(user) || QDELETED(target))
+ return FALSE
+ if(get_dist(user, target) > min(user.using_perspective.cached_view_width, user.using_perspective.cached_view_height))
+ return FALSE
+ if(!user.can_see_plane(target.plane))
+ return FALSE
+ if(target.invisibility > user.see_invisible)
+ return FALSE
+ return TRUE
+
+/**
+ * rendering object that sits in vis contents while sculpting
+ */
+/atom/movable/sculpting_render
+ atom_flags = ATOM_ABSTRACT
+ vis_flags = VIS_INHERIT_PLANE | VIS_INHERIT_DIR | VIS_INHERIT_ID
+ layer = FLOAT_LAYER
+ plane = OBJ_PLANE
+ mouse_opacity = MOUSE_OPACITY_ICON
+
+/atom/movable/sculpting_render/Destroy()
+ vis_locs.len = 0
+ return ..()
diff --git a/code/modules/species/station/xenomorph_hybrids/hybrid_resin.dm b/code/modules/species/station/xenomorph_hybrids/hybrid_resin.dm
index ae8c43a5253d..fc411538fc91 100644
--- a/code/modules/species/station/xenomorph_hybrids/hybrid_resin.dm
+++ b/code/modules/species/station/xenomorph_hybrids/hybrid_resin.dm
@@ -27,12 +27,26 @@
strict_color_stacking = TRUE
/datum/material/hybrid_resin/generate_recipes()
- recipes = list()
- recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door/hybrid_resin, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] barricade", /obj/effect/alien/hybrid_resin/wall, 5, time = 5 SECONDS, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] nest", /obj/structure/bed/hybrid_nest, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("crude [display_name] bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE)
- recipes += new/datum/stack_recipe("[display_name] membrane", /obj/effect/alien/hybrid_resin/membrane, 1, time = 2 SECONDS, pass_stack_color = TRUE)
+ . = ..()
+ . += create_stack_recipe_datum(
+ name = "resin nest",
+ product = /obj/structure/bed/hybrid_nest,
+ exclusitivity = /obj/structure/bed,
+ cost = 2,
+ time = 2 SECONDS,
+ )
+ . += create_stack_recipe_datum(
+ name = "crude resin bandage",
+ product = /obj/item/stack/medical/crude_pack,
+ time = 2 SECONDS,
+ cost = 1,
+ )
+ . += create_stack_recipe_datum(
+ name = "resin membrane",
+ product = /obj/effect/alien/hybrid_resin/membrane,
+ cost = 1,
+ time = 2 SECONDS,
+ )
/mob/living/carbon/human/proc/hybrid_resin() //
set name = "Secrete Resin (75)"
@@ -65,8 +79,6 @@
if(O)
O.color = "#321D37"
- return
-
/obj/structure/simple_door/hybrid_resin/Initialize(mapload, material_name)
return ..(mapload, "resin compound")
diff --git a/code/modules/tables/presets.dm b/code/modules/tables/presets.dm
index 64fe853f742e..143e1399096a 100644
--- a/code/modules/tables/presets.dm
+++ b/code/modules/tables/presets.dm
@@ -22,7 +22,7 @@
color = "#CCCCCC"
/obj/structure/table/marble/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/sandstone/marble)
+ material = SSmaterials.get_material(/datum/material/marble)
return ..()
/obj/structure/table/reinforced
@@ -51,7 +51,7 @@
canSmoothWith = (SMOOTH_GROUP_WOOD_TABLES)
/obj/structure/table/wooden_reinforced/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood)
+ material = SSmaterials.get_material(/datum/material/wood_plank)
reinforced = SSmaterials.get_material(/datum/material/steel)
return ..()
@@ -63,7 +63,7 @@
canSmoothWith = (SMOOTH_GROUP_WOOD_TABLES)
/obj/structure/table/woodentable/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood)
+ material = SSmaterials.get_material(/datum/material/wood_plank)
return ..()
/obj/structure/table/sifwoodentable
@@ -74,7 +74,7 @@
canSmoothWith = (SMOOTH_GROUP_WOOD_TABLES)
/obj/structure/table/sifwoodentable/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood/sif)
+ material = SSmaterials.get_material(/datum/material/wood_plank/sif)
return ..()
/obj/structure/table/sifwooden_reinforced
@@ -85,7 +85,7 @@
canSmoothWith = (SMOOTH_GROUP_WOOD_TABLES)
/obj/structure/table/sifwooden_reinforced/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood/sif)
+ material = SSmaterials.get_material(/datum/material/wood_plank/sif)
reinforced = SSmaterials.get_material(MAT_STEEL)
return ..()
@@ -97,14 +97,14 @@
canSmoothWith = (SMOOTH_GROUP_WOOD_TABLES)
/obj/structure/table/hardwoodtable/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood/hardwood)
+ material = SSmaterials.get_material(/datum/material/wood_plank/hardwood)
return ..()
/obj/structure/table/gamblingtable
icon_state = "gamble_preview"
/obj/structure/table/gamblingtable/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood/)
+ material = SSmaterials.get_material(/datum/material/wood_plank/)
carpeted = 1
return ..()
@@ -141,7 +141,7 @@
icon_state = "holo_preview"
/obj/structure/table/woodentable/holotable/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood/holographic)
+ material = SSmaterials.get_material(/datum/material/wood_plank/holographic)
return ..()
/obj/structure/table/alien
@@ -222,7 +222,7 @@
color = "#CCCCCC"
/obj/structure/table/bench/marble/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/sandstone/marble)
+ material = SSmaterials.get_material(/datum/material/marble)
return ..()
/*
@@ -249,7 +249,7 @@
color = "#824B28"
/obj/structure/table/bench/wooden_reinforced/New()
- material = SSmaterials.get_material(/datum/material/wood)
+ material = SSmaterials.get_material(/datum/material/wood_plank)
reinforced = SSmaterials.get_material(/datum/material/steel)
..()
*/
@@ -258,7 +258,7 @@
color = "#824B28"
/obj/structure/table/bench/wooden/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood)
+ material = SSmaterials.get_material(/datum/material/wood_plank)
return ..()
/obj/structure/table/bench/sifwooden
@@ -266,7 +266,7 @@
color = "#824B28"
/obj/structure/table/bench/sifwooden/Initialize(mapload)
- material = SSmaterials.get_material(/datum/material/wood/sif)
+ material = SSmaterials.get_material(/datum/material/wood_plank/sif)
return ..()
/obj/structure/table/bench/sifwooden/padded
@@ -319,6 +319,6 @@
icon_state = "holo_preview"
/obj/structure/table/bench/wooden/holotable/New()
- material = SSmaterials.get_material(/datum/material/wood/holographic)
+ material = SSmaterials.get_material(/datum/material/wood_plank/holographic)
..()
*/
diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi
index 494c4cb2f972..fca8bdd5af87 100644
Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ
diff --git a/icons/mob/clothing/suits.dmi b/icons/mob/clothing/suits.dmi
index 511828c94d62..674ac69a077d 100644
Binary files a/icons/mob/clothing/suits.dmi and b/icons/mob/clothing/suits.dmi differ
diff --git a/icons/modules/sculpting/sculpting.dmi b/icons/modules/sculpting/sculpting.dmi
new file mode 100644
index 000000000000..08515e903993
Binary files /dev/null and b/icons/modules/sculpting/sculpting.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index d6c5ffdfc757..c703eb86c0f8 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/spacesuits.dmi b/icons/obj/clothing/spacesuits.dmi
index 77d1b04a479f..80ed0f4cfe19 100644
Binary files a/icons/obj/clothing/spacesuits.dmi and b/icons/obj/clothing/spacesuits.dmi differ
diff --git a/icons/system/color_32x32.dmi b/icons/system/color_32x32.dmi
new file mode 100644
index 000000000000..826ba84db3dc
Binary files /dev/null and b/icons/system/color_32x32.dmi differ
diff --git a/maps/away_missions/140x140/snow_outpost.dmm b/maps/away_missions/140x140/snow_outpost.dmm
index 3f17903e0743..0b847a8fa9eb 100644
--- a/maps/away_missions/140x140/snow_outpost.dmm
+++ b/maps/away_missions/140x140/snow_outpost.dmm
@@ -2436,7 +2436,7 @@
/turf/simulated/shuttle/wall,
/area/awaymission/snow_outpost/outside)
"im" = (
-/obj/structure/door_assembly/door_assembly_ext{
+/obj/structure/door_assembly/external{
anchored = 1
},
/turf/simulated/floor/water,
diff --git a/maps/away_missions/140x140/zoo.dmm b/maps/away_missions/140x140/zoo.dmm
index 15974cbdaeb7..9b92aec583e3 100644
--- a/maps/away_missions/140x140/zoo.dmm
+++ b/maps/away_missions/140x140/zoo.dmm
@@ -2191,7 +2191,7 @@
/turf/simulated/shuttle/floor/black,
/area/awaymission/zoo/tradeship)
"gx" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/shuttle/floor/black,
/area/awaymission/zoo/tradeship)
"gy" = (
@@ -8518,14 +8518,14 @@
/turf/simulated/floor/tiled/dark,
/area/awaymission/zoo)
"wW" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/item/paper/zoo,
/obj/item/paper/zoo,
/obj/item/paper/zoo,
/turf/simulated/floor/tiled/dark,
/area/awaymission/zoo)
"wX" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/item/paper/zoo,
/obj/item/paper/zoo,
/obj/item/paper/zoo,
diff --git a/maps/away_missions/archive/Academy.dmm b/maps/away_missions/archive/Academy.dmm
index 0870df3706a5..80e434663567 100644
--- a/maps/away_missions/archive/Academy.dmm
+++ b/maps/away_missions/archive/Academy.dmm
@@ -11,7 +11,7 @@
/turf/simulated/floor/plating,
/area/awaymission/academy/headmaster)
"ad" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/carpet,
/area/awaymission/academy/headmaster)
"ae" = (
@@ -1404,7 +1404,7 @@
},
/area/awaymission/academy/classrooms)
"gj" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor{
dir = 5
},
diff --git a/maps/away_missions/archive/stationCollision.dmm b/maps/away_missions/archive/stationCollision.dmm
index c2049d0fac83..58d0fd113145 100644
--- a/maps/away_missions/archive/stationCollision.dmm
+++ b/maps/away_missions/archive/stationCollision.dmm
@@ -328,7 +328,7 @@
/turf/simulated/floor/airless,
/area/awaymission/research)
"bQ" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/airless,
/area/awaymission/research)
"bR" = (
diff --git a/maps/away_missions/archive/zresearchlabs.dmm b/maps/away_missions/archive/zresearchlabs.dmm
index 8dbdc7b12e11..4328fe14f682 100644
--- a/maps/away_missions/archive/zresearchlabs.dmm
+++ b/maps/away_missions/archive/zresearchlabs.dmm
@@ -303,7 +303,7 @@
},
/area/awaymission/labs/cave)
"bm" = (
-/obj/structure/door_assembly/door_assembly_research,
+/obj/structure/door_assembly/research,
/turf/simulated/floor{
icon_state = "white"
},
@@ -582,7 +582,7 @@
/turf/simulated/floor/plating,
/area/awaymission/labs/cave)
"cn" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor{
icon_state = "white"
},
@@ -2693,7 +2693,7 @@
/turf/simulated/floor/plating,
/area/awaymission/labs/solars)
"hX" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/effect/debris/cleanable/cobweb,
/turf/simulated/floor{
icon_state = "wood"
diff --git a/maps/euthenia/levels/deck1.dmm b/maps/euthenia/levels/deck1.dmm
index 4b85144bd28d..dad9369a666c 100644
--- a/maps/euthenia/levels/deck1.dmm
+++ b/maps/euthenia/levels/deck1.dmm
@@ -3295,7 +3295,7 @@
/turf/simulated/floor/plating,
/area/security/warden)
"ecf" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/machinery/atmospherics/component/unary/vent_scrubber/on{
dir = 1
},
diff --git a/maps/euthenia/levels/deck2.dmm b/maps/euthenia/levels/deck2.dmm
index 419043813299..927704ee4d0c 100644
--- a/maps/euthenia/levels/deck2.dmm
+++ b/maps/euthenia/levels/deck2.dmm
@@ -12237,7 +12237,7 @@
/obj/machinery/requests_console/preset/cargo{
pixel_y = -32
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/monotile,
/area/quartermaster/foyer)
"kbi" = (
@@ -14081,7 +14081,7 @@
/area/quartermaster/warehouse)
"lFs" = (
/obj/structure/disposalpipe/segment,
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled,
/area/space)
"lFA" = (
@@ -25483,7 +25483,7 @@
/turf/simulated/wall/r_wall/prepainted,
/area/rift/station/fighter_bay/maintenance)
"vak" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/wood,
/area/bridge/meeting_room)
"val" = (
diff --git a/maps/euthenia/levels/deck3.dmm b/maps/euthenia/levels/deck3.dmm
index 8bcdcc11ab6d..216cb4345c7a 100644
--- a/maps/euthenia/levels/deck3.dmm
+++ b/maps/euthenia/levels/deck3.dmm
@@ -5426,7 +5426,7 @@
/obj/machinery/recharger/wallcharger{
pixel_x = 32
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/wood,
/area/tether/exploration/pathfinder_office)
"gsR" = (
diff --git a/maps/rift/levels/rift-04-surface1.dmm b/maps/rift/levels/rift-04-surface1.dmm
index 6793659d219c..28cef18a146d 100644
--- a/maps/rift/levels/rift-04-surface1.dmm
+++ b/maps/rift/levels/rift-04-surface1.dmm
@@ -12380,7 +12380,7 @@
"hUf" = (
/obj/effect/floor_decal/borderfloor,
/obj/effect/floor_decal/corner/brown/border,
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/steel,
/area/quartermaster/office)
"hUp" = (
@@ -34757,7 +34757,7 @@
/turf/simulated/wall/prepainted,
/area/quartermaster/garage)
"vgN" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/effect/floor_decal/borderfloor{
dir = 8
},
diff --git a/maps/rift/levels/rift-10-west_plains.dmm b/maps/rift/levels/rift-10-west_plains.dmm
index 898408b7538e..73584ca011ff 100644
--- a/maps/rift/levels/rift-10-west_plains.dmm
+++ b/maps/rift/levels/rift-10-west_plains.dmm
@@ -2961,7 +2961,7 @@
/turf/simulated/floor/tiled,
/area/rnd/outpost/anomaly_lab)
"nx" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/steel_grid,
/area/rnd/outpost/testing_lab)
"nz" = (
diff --git a/maps/rift/levels/rift-11-orbital.dmm b/maps/rift/levels/rift-11-orbital.dmm
index dbb2ff6fd98d..a9855b4f1fcb 100644
--- a/maps/rift/levels/rift-11-orbital.dmm
+++ b/maps/rift/levels/rift-11-orbital.dmm
@@ -7052,7 +7052,7 @@
/obj/effect/floor_decal/borderfloor{
dir = 8
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/unsimulated/floor/steel,
/area/centcom/command)
"zs" = (
diff --git a/maps/sectors/miaphus_192/levels/miaphus_192_beach.dmm b/maps/sectors/miaphus_192/levels/miaphus_192_beach.dmm
index 51b2d18cf85b..f7ade96d3929 100644
--- a/maps/sectors/miaphus_192/levels/miaphus_192_beach.dmm
+++ b/maps/sectors/miaphus_192/levels/miaphus_192_beach.dmm
@@ -690,7 +690,7 @@
/turf/simulated/floor/tiled/steel_dirty,
/area/tether_away/beach/desalinator)
"el" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/old_tile/white,
/area/tether_away/beach/resort/lockermed)
"er" = (
@@ -1841,7 +1841,7 @@
/turf/simulated/floor/tiled/steel_dirty,
/area/tether_away/beach/bunker/mess)
"nI" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/wood,
/area/tether_away/beach/desalinator)
"nM" = (
diff --git a/maps/sectors/tradeport_140/levels/tradeport_140.dmm b/maps/sectors/tradeport_140/levels/tradeport_140.dmm
index 4fa6ba8d91a9..f8731d493f76 100644
--- a/maps/sectors/tradeport_140/levels/tradeport_140.dmm
+++ b/maps/sectors/tradeport_140/levels/tradeport_140.dmm
@@ -3384,7 +3384,7 @@
/turf/simulated/floor/tiled/neutral,
/area/tradeport/facility)
"mR" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/wood,
/area/shuttle/trade_ship/general)
"mS" = (
diff --git a/maps/sectors/tradeport_192/levels/tradeport_192.dmm b/maps/sectors/tradeport_192/levels/tradeport_192.dmm
index 488201182a36..406dfdd0c6fd 100644
--- a/maps/sectors/tradeport_192/levels/tradeport_192.dmm
+++ b/maps/sectors/tradeport_192/levels/tradeport_192.dmm
@@ -2623,7 +2623,7 @@
/turf/simulated/floor/tiled/neutral,
/area/tradeport/facility)
"jJ" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/wood,
/area/shuttle/trade_ship/general)
"jK" = (
diff --git a/maps/submaps/level_specific/debrisfield/ship_sci_overrun.dmm b/maps/submaps/level_specific/debrisfield/ship_sci_overrun.dmm
index 916671126751..4dd4da153bef 100644
--- a/maps/submaps/level_specific/debrisfield/ship_sci_overrun.dmm
+++ b/maps/submaps/level_specific/debrisfield/ship_sci_overrun.dmm
@@ -231,7 +231,7 @@
/turf/simulated/floor/tiled/white/airless,
/area/space/debrisfield/scioverrun)
"aP" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/white/airless,
/area/space/debrisfield/scioverrun)
"aQ" = (
diff --git a/maps/submaps/level_specific/debrisfield/ship_sup_exploded.dmm b/maps/submaps/level_specific/debrisfield/ship_sup_exploded.dmm
index 16bbbe044be8..ad511c32c958 100644
--- a/maps/submaps/level_specific/debrisfield/ship_sup_exploded.dmm
+++ b/maps/submaps/level_specific/debrisfield/ship_sup_exploded.dmm
@@ -93,7 +93,7 @@
/turf/simulated/shuttle/floor/white/airless,
/area/space/debrisfield/explodedship)
"av" = (
-/obj/structure/door_assembly/door_assembly_com{
+/obj/structure/door_assembly/command{
anchored = 1
},
/turf/simulated/shuttle/floor/white/airless,
diff --git a/maps/submaps/level_specific/debrisfield_vr/ship_sci_overrun.dmm b/maps/submaps/level_specific/debrisfield_vr/ship_sci_overrun.dmm
index f60949b18f2d..6b17dfa8b9d3 100644
--- a/maps/submaps/level_specific/debrisfield_vr/ship_sci_overrun.dmm
+++ b/maps/submaps/level_specific/debrisfield_vr/ship_sci_overrun.dmm
@@ -284,7 +284,7 @@
/turf/simulated/floor/airless,
/area/submap/debrisfield_vr/sci_overrun)
"bb" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/white/airless,
/area/submap/debrisfield_vr/sci_overrun)
"bc" = (
diff --git a/maps/submaps/level_specific/debrisfield_vr/ship_sup_exploded.dmm b/maps/submaps/level_specific/debrisfield_vr/ship_sup_exploded.dmm
index da50d60c66fa..cc78feed1f72 100644
--- a/maps/submaps/level_specific/debrisfield_vr/ship_sup_exploded.dmm
+++ b/maps/submaps/level_specific/debrisfield_vr/ship_sup_exploded.dmm
@@ -208,7 +208,7 @@
/turf/simulated/shuttle/floor/white/airless,
/area/submap/debrisfield_vr/misc_debris)
"aS" = (
-/obj/structure/door_assembly/door_assembly_com,
+/obj/structure/door_assembly/command,
/turf/simulated/shuttle/floor/white/airless,
/area/submap/debrisfield_vr/misc_debris)
"aT" = (
diff --git a/maps/submaps/level_specific/virgo2/DJOutpost2.dmm b/maps/submaps/level_specific/virgo2/DJOutpost2.dmm
index 7b186528abd4..0a2cf3248f25 100644
--- a/maps/submaps/level_specific/virgo2/DJOutpost2.dmm
+++ b/maps/submaps/level_specific/virgo2/DJOutpost2.dmm
@@ -117,7 +117,7 @@
/turf/simulated/floor/outdoors/dirt,
/area/submap/virgo2/DJOutpost1)
"B" = (
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/floor/outdoors/rocks,
/area/submap/virgo2/DJOutpost1)
"C" = (
diff --git a/maps/submaps/level_specific/virgo2/Epod4.dmm b/maps/submaps/level_specific/virgo2/Epod4.dmm
index b5917d5fd9c3..f6050ae72c9e 100644
--- a/maps/submaps/level_specific/virgo2/Epod4.dmm
+++ b/maps/submaps/level_specific/virgo2/Epod4.dmm
@@ -75,7 +75,7 @@
/turf/simulated/shuttle/wall,
/area/submap/virgo2/Epod4)
"p" = (
-/obj/structure/door_assembly/door_assembly_ext{
+/obj/structure/door_assembly/external{
anchored = 1
},
/turf/simulated/mineral/floor/ignore_mapgen/virgo2,
diff --git a/maps/submaps/mountains/CrashedMedShuttle1.dmm b/maps/submaps/mountains/CrashedMedShuttle1.dmm
index 699fc38618b8..d3685e8fbe4e 100644
--- a/maps/submaps/mountains/CrashedMedShuttle1.dmm
+++ b/maps/submaps/mountains/CrashedMedShuttle1.dmm
@@ -77,11 +77,11 @@
/area/submap/CrashedMedShuttle)
"ao" = (
/obj/item/circuitboard/broken,
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/shuttle/plating,
/area/submap/CrashedMedShuttle)
"ap" = (
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/shuttle/plating,
/area/submap/CrashedMedShuttle)
"aq" = (
diff --git a/maps/submaps/mountains/CrashedMedShuttle1_vr.dmm b/maps/submaps/mountains/CrashedMedShuttle1_vr.dmm
index 1f7dd80bf250..bc600fc62450 100644
--- a/maps/submaps/mountains/CrashedMedShuttle1_vr.dmm
+++ b/maps/submaps/mountains/CrashedMedShuttle1_vr.dmm
@@ -77,11 +77,11 @@
/area/submap/CrashedMedShuttle)
"ao" = (
/obj/item/circuitboard/broken,
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/shuttle/plating,
/area/submap/CrashedMedShuttle)
"ap" = (
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/shuttle/plating,
/area/submap/CrashedMedShuttle)
"aq" = (
diff --git a/maps/submaps/mountains/crashedcontainmentshuttle.dmm b/maps/submaps/mountains/crashedcontainmentshuttle.dmm
index 1796dc28b1dd..277c26c77f83 100644
--- a/maps/submaps/mountains/crashedcontainmentshuttle.dmm
+++ b/maps/submaps/mountains/crashedcontainmentshuttle.dmm
@@ -39,7 +39,7 @@
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/crashedcontainmentshuttle)
"ak" = (
-/obj/structure/door_assembly/door_assembly_ext{
+/obj/structure/door_assembly/external{
anchored = 1
},
/turf/simulated/floor/plating,
@@ -119,7 +119,7 @@
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/crashedcontainmentshuttle)
"aD" = (
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/crashedcontainmentshuttle)
"aE" = (
@@ -202,7 +202,7 @@
/turf/template_noop,
/area/submap/crashedcontainmentshuttle)
"aS" = (
-/obj/structure/door_assembly/door_assembly_highsecurity{
+/obj/structure/door_assembly/high_security{
anchored = 1
},
/turf/simulated/shuttle/floor/black,
@@ -337,7 +337,7 @@
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/crashedcontainmentshuttle)
"bu" = (
-/obj/structure/door_assembly/door_assembly_ext{
+/obj/structure/door_assembly/external{
anchored = 1
},
/turf/simulated/mineral/floor/ignore_mapgen,
diff --git a/maps/submaps/mountains/crashedcontainmentshuttle_vr.dmm b/maps/submaps/mountains/crashedcontainmentshuttle_vr.dmm
index 91f4222d8651..9e84af6ff813 100644
--- a/maps/submaps/mountains/crashedcontainmentshuttle_vr.dmm
+++ b/maps/submaps/mountains/crashedcontainmentshuttle_vr.dmm
@@ -55,11 +55,11 @@
/turf/simulated/shuttle/floor/black,
/area/submap/crashedcontainmentshuttle)
"ao" = (
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/crashedcontainmentshuttle)
"ap" = (
-/obj/structure/door_assembly/door_assembly_ext{
+/obj/structure/door_assembly/external{
anchored = 1
},
/turf/simulated/floor/plating,
@@ -179,7 +179,7 @@
/turf/simulated/shuttle/floor/yellow,
/area/submap/crashedcontainmentshuttle)
"aO" = (
-/obj/structure/door_assembly/door_assembly_highsecurity{
+/obj/structure/door_assembly/high_security{
anchored = 1
},
/turf/simulated/shuttle/floor/black,
@@ -408,7 +408,7 @@
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/crashedcontainmentshuttle)
"bF" = (
-/obj/structure/door_assembly/door_assembly_ext{
+/obj/structure/door_assembly/external{
anchored = 1
},
/turf/simulated/mineral/floor/ignore_mapgen,
diff --git a/maps/submaps/mountains/cultmine.dmm b/maps/submaps/mountains/cultmine.dmm
index a1691e8dafed..1593700cb232 100644
--- a/maps/submaps/mountains/cultmine.dmm
+++ b/maps/submaps/mountains/cultmine.dmm
@@ -76,7 +76,7 @@
/turf/simulated/floor/tiled/steel_grid,
/area/submap/cave/cultmine)
"an" = (
-/obj/structure/door_assembly/door_assembly_highsecurity{
+/obj/structure/door_assembly/high_security{
anchored = 1
},
/obj/effect/debris/cleanable/blood/oil,
@@ -215,12 +215,12 @@
/turf/simulated/mineral/floor/ignore_mapgen,
/area/submap/cave/cultmine)
"aQ" = (
-/obj/structure/door_assembly/door_assembly_hatch,
+/obj/structure/door_assembly/hatch,
/obj/effect/debris/cleanable/blood/oil,
/turf/simulated/floor/plating,
/area/submap/cave/cultmine)
"aR" = (
-/obj/structure/door_assembly/door_assembly_highsecurity{
+/obj/structure/door_assembly/high_security{
anchored = 1
},
/obj/structure/boulder,
diff --git a/maps/submaps/mountains/deadBeacon.dmm b/maps/submaps/mountains/deadBeacon.dmm
index 2114f4c82417..95e39a039305 100644
--- a/maps/submaps/mountains/deadBeacon.dmm
+++ b/maps/submaps/mountains/deadBeacon.dmm
@@ -72,7 +72,7 @@
/turf/simulated/floor/tiled/asteroid_steel,
/area/submap/cave/deadBeacon)
"p" = (
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/floor/tiled/asteroid_steel,
/area/submap/cave/deadBeacon)
"q" = (
diff --git a/maps/submaps/plains/Epod.dmm b/maps/submaps/plains/Epod.dmm
index ad686d83ff0c..ab9df9baf92c 100644
--- a/maps/submaps/plains/Epod.dmm
+++ b/maps/submaps/plains/Epod.dmm
@@ -10,7 +10,7 @@
/turf/template_noop,
/area/submap/Epod1)
"d" = (
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/template_noop,
/area/submap/Epod1)
"e" = (
diff --git a/maps/submaps/plains/construction1.dmm b/maps/submaps/plains/construction1.dmm
index 985984648007..0a4e2937bfb6 100644
--- a/maps/submaps/plains/construction1.dmm
+++ b/maps/submaps/plains/construction1.dmm
@@ -72,7 +72,7 @@
/turf/simulated/floor/plating/external,
/area/submap/construction1)
"t" = (
-/obj/structure/door_assembly/door_assembly_mai,
+/obj/structure/door_assembly/maint,
/turf/simulated/floor/plating/external,
/area/submap/construction1)
"u" = (
diff --git a/maps/submaps/wilderness/DJOutpost2.dmm b/maps/submaps/wilderness/DJOutpost2.dmm
index 0907249403e1..9277370c087b 100644
--- a/maps/submaps/wilderness/DJOutpost2.dmm
+++ b/maps/submaps/wilderness/DJOutpost2.dmm
@@ -117,7 +117,7 @@
/turf/simulated/floor/outdoors/dirt,
/area/submap/DJOutpost1)
"B" = (
-/obj/structure/door_assembly/door_assembly_ext,
+/obj/structure/door_assembly/external,
/turf/simulated/floor/outdoors/rocks,
/area/submap/DJOutpost1)
"C" = (
diff --git a/maps/submaps/wilderness/Epod4.dmm b/maps/submaps/wilderness/Epod4.dmm
index 5f3d2c03283c..ecda83134341 100644
--- a/maps/submaps/wilderness/Epod4.dmm
+++ b/maps/submaps/wilderness/Epod4.dmm
@@ -89,7 +89,7 @@
/turf/simulated/shuttle/wall,
/area/submap/Epod4)
"p" = (
-/obj/structure/door_assembly/door_assembly_ext{
+/obj/structure/door_assembly/external{
anchored = 1
},
/turf/simulated/floor/water,
diff --git a/maps/templates/admin/dhael_centcom.dmm b/maps/templates/admin/dhael_centcom.dmm
index 1925bba283ae..bdc965243553 100644
--- a/maps/templates/admin/dhael_centcom.dmm
+++ b/maps/templates/admin/dhael_centcom.dmm
@@ -2943,7 +2943,7 @@
},
/area/tdome)
"hw" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/unsimulated/floor/steel,
/area/centcom/control)
"hz" = (
@@ -4874,7 +4874,7 @@
/obj/effect/floor_decal/borderfloor{
dir = 1
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/unsimulated/floor/steel,
/area/centcom/command)
"oo" = (
@@ -5453,7 +5453,7 @@
/obj/effect/floor_decal/borderfloor{
dir = 8
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/unsimulated/floor/steel,
/area/centcom/command)
"ps" = (
@@ -9635,7 +9635,7 @@
/turf/unsimulated/floor/steel,
/area/centcom/command)
"CT" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/effect/floor_decal/borderfloor{
dir = 5
},
diff --git a/maps/templates/admin/ert.dmm b/maps/templates/admin/ert.dmm
index 47fabcefab20..90e155c73f31 100644
--- a/maps/templates/admin/ert.dmm
+++ b/maps/templates/admin/ert.dmm
@@ -6501,7 +6501,7 @@
/turf/simulated/floor/tiled/techfloor,
/area/ship/ert/engine)
"WR" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/wood,
/area/ship/ert/commander)
"WS" = (
diff --git a/maps/templates/admin/ert_base.dmm b/maps/templates/admin/ert_base.dmm
index db7b7c7b7b7d..cb9fe12603f3 100644
--- a/maps/templates/admin/ert_base.dmm
+++ b/maps/templates/admin/ert_base.dmm
@@ -1913,7 +1913,7 @@
/turf/simulated/shuttle/floor/black,
/area/shuttle/specops/centcom)
"dS" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/shuttle/floor/black,
/area/shuttle/specops/centcom)
"dT" = (
diff --git a/maps/templates/admin/killhouse2.dmm b/maps/templates/admin/killhouse2.dmm
index 4de867e24519..0ab364717fea 100644
--- a/maps/templates/admin/killhouse2.dmm
+++ b/maps/templates/admin/killhouse2.dmm
@@ -2781,7 +2781,7 @@
/turf/simulated/floor/tiled/white,
/area/killhouse/two)
"XA" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/effect/floor_decal/corner/black/diagonal,
/turf/simulated/floor/tiled/white,
/area/killhouse/two)
diff --git a/maps/templates/admin/kk_mercship.dmm b/maps/templates/admin/kk_mercship.dmm
index 4595f5ce90aa..f73043dafbeb 100644
--- a/maps/templates/admin/kk_mercship.dmm
+++ b/maps/templates/admin/kk_mercship.dmm
@@ -1481,7 +1481,7 @@
/turf/simulated/floor/tiled/techfloor,
/area/ship/manta/recreation)
"hx" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/wood,
/area/ship/manta/commander)
"hy" = (
diff --git a/maps/templates/archive/tradeship.dmm b/maps/templates/archive/tradeship.dmm
index c1add95ee091..31625cdfd84f 100644
--- a/maps/templates/archive/tradeship.dmm
+++ b/maps/templates/archive/tradeship.dmm
@@ -1768,7 +1768,7 @@
/turf/simulated/shuttle/floor/black,
/area/shuttle/trade)
"dX" = (
-/obj/structure/filingcabinet/filingcabinet{
+/obj/structure/filingcabinet/tall{
dir = 4
},
/turf/simulated/shuttle/floor/black,
diff --git a/maps/tether/levels/station1.dmm b/maps/tether/levels/station1.dmm
index 2b8dc5fbc59b..78dc27747678 100644
--- a/maps/tether/levels/station1.dmm
+++ b/maps/tether/levels/station1.dmm
@@ -7313,7 +7313,7 @@
/obj/effect/floor_decal/corner/purple/bordercorner{
dir = 4
},
-/obj/structure/filingcabinet/filingcabinet{
+/obj/structure/filingcabinet/tall{
pixel_x = 10
},
/obj/machinery/light_switch{
@@ -11110,7 +11110,7 @@
/turf/simulated/floor/tiled,
/area/engineering/hallway)
"wh" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/effect/floor_decal/borderfloor,
/obj/effect/floor_decal/corner/blue/border,
/obj/effect/floor_decal/steeldecal/steel_decals7{
diff --git a/maps/tether/levels/station2.dmm b/maps/tether/levels/station2.dmm
index aa5f57e19a47..4cc930b0d9f6 100644
--- a/maps/tether/levels/station2.dmm
+++ b/maps/tether/levels/station2.dmm
@@ -11296,7 +11296,7 @@
/turf/simulated/floor/tiled/techfloor,
/area/shuttle/excursion/cargo)
"wv" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/dark,
/area/tether/station/burial)
"ww" = (
@@ -15177,7 +15177,7 @@
/obj/machinery/recharger/wallcharger{
pixel_x = -25
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/effect/floor_decal/spline/fancy/wood{
dir = 8
},
@@ -18945,7 +18945,7 @@
/area/tether/station/visitorhallway/lounge)
"Mf" = (
/obj/structure/disposalpipe/segment,
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled,
/area/quartermaster/office)
"Mg" = (
diff --git a/maps/tether/levels/surface1.dmm b/maps/tether/levels/surface1.dmm
index dbc4b4dd4156..09fb3376ed07 100644
--- a/maps/tether/levels/surface1.dmm
+++ b/maps/tether/levels/surface1.dmm
@@ -8683,7 +8683,7 @@
"eFC" = (
/obj/effect/floor_decal/borderfloor,
/obj/effect/floor_decal/corner/red/border,
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled,
/area/security/checkpoint)
"eFW" = (
@@ -23660,7 +23660,7 @@
/turf/simulated/floor/plating,
/area/maintenance/lowmedbaymaint)
"mxU" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/steel_grid,
/area/rnd/outpost/testing_lab)
"myk" = (
diff --git a/maps/tether/levels/surface2.dmm b/maps/tether/levels/surface2.dmm
index 1d79c3fe841d..c9e9c326f6b6 100644
--- a/maps/tether/levels/surface2.dmm
+++ b/maps/tether/levels/surface2.dmm
@@ -8079,7 +8079,7 @@
/obj/random/maintenance/engineering,
/obj/effect/floor_decal/rust,
/obj/item/clothing/suit/storage/vest/hoscoat/jensen{
- armor = list("melee"=0,"bullet"=0,"laser"=0,"energy"=0,"bomb"=0,"bio"=0,"rad"=0);
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0);
desc = "Its an old, dusty trenchcoat... what a shame.";
name = "trenchcoat"
},
@@ -20723,7 +20723,7 @@
/obj/machinery/vending/cigarette{
name = "Cigarette machine";
prices = list();
- products = list(/obj/item/storage/fancy/cigarettes=10,/obj/item/storage/box/matches=10,/obj/item/flame/lighter/zippo=4,/obj/item/clothing/mask/smokable/cigarette/cigar/havana=2)
+ products = list(/obj/item/storage/fancy/cigarettes = 10, /obj/item/storage/box/matches = 10, /obj/item/flame/lighter/zippo = 4, /obj/item/clothing/mask/smokable/cigarette/cigar/havana = 2)
},
/obj/effect/floor_decal/techfloor/hole{
dir = 1
@@ -32254,6 +32254,9 @@
pixel_y = -28
},
/obj/structure/cable/green,
+/obj/structure/table/rack/shelf/steel,
+/obj/item/hardsuit/hazard/equipped,
+/obj/item/hardsuit/hazard/equipped,
/turf/simulated/floor/tiled/dark,
/area/tether/surfacebase/security/armory)
"xnd" = (
@@ -33390,7 +33393,7 @@
input_tag = "atmos_out";
name = "Atmos Intake Control";
output_tag = "atmos_in";
- sensors = list("atmos_intake"="Tank")
+ sensors = list("atmos_intake" = "Tank")
},
/turf/simulated/floor/tiled,
/area/engineering/atmos/monitoring)
diff --git a/maps/tether/levels/surface3.dmm b/maps/tether/levels/surface3.dmm
index 99d6a73e4582..0e5f94f56f9e 100644
--- a/maps/tether/levels/surface3.dmm
+++ b/maps/tether/levels/surface3.dmm
@@ -881,11 +881,11 @@
/turf/simulated/floor/tiled,
/area/tether/surfacebase/security/iaa)
"atO" = (
-/mob/living/simple_mob/animal/passive/cow,
/obj/machinery/air_alarm{
dir = 8;
pixel_x = 24
},
+/mob/living/simple_mob/animal/passive/cow,
/turf/simulated/floor/grass,
/area/hydroponics/cafegarden)
"atT" = (
@@ -2409,6 +2409,7 @@
/obj/item/clothing/mask/breath,
/obj/item/clothing/suit/space/void/headofsecurity,
/obj/item/clothing/head/helmet/space/void/headofsecurity,
+/obj/item/hardsuit/hazard/equipped,
/turf/simulated/floor/wood,
/area/tether/surfacebase/security/hos)
"biw" = (
@@ -36294,7 +36295,7 @@
/turf/simulated/floor/tiled/steel_grid,
/area/rnd/robotics/mechbay)
"uJx" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/dark,
/area/bridge)
"uJD" = (
diff --git a/maps/triumph/levels/deck4.dmm b/maps/triumph/levels/deck4.dmm
index 8476810c1b55..e5a85d62504d 100644
--- a/maps/triumph/levels/deck4.dmm
+++ b/maps/triumph/levels/deck4.dmm
@@ -7316,13 +7316,13 @@
/obj/structure/dogbed{
name = "pet bed"
},
-/mob/living/simple_mob/animal/passive/dog/corgi/Ian,
/obj/machinery/light{
dir = 4
},
/obj/effect/floor_decal/spline/fancy/wood{
dir = 5
},
+/mob/living/simple_mob/animal/passive/dog/corgi/Ian,
/turf/simulated/floor/carpet,
/area/crew_quarters/heads/hop)
"ePi" = (
@@ -11958,7 +11958,6 @@
/area/triumph/surfacebase/sauna)
"ibD" = (
/obj/structure/dogbed,
-/mob/living/simple_mob/animal/passive/dog/pug/SirPogsley,
/obj/machinery/power/apc{
dir = 8;
name = "west bump";
@@ -11967,6 +11966,7 @@
/obj/structure/cable/green{
icon_state = "0-4"
},
+/mob/living/simple_mob/animal/passive/dog/pug/SirPogsley,
/turf/simulated/floor/carpet,
/area/crew_quarters/heads/hos)
"ibU" = (
@@ -12182,6 +12182,7 @@
/obj/machinery/ai_status_display{
pixel_y = 32
},
+/obj/item/hardsuit/hazard/equipped,
/turf/simulated/floor/carpet,
/area/crew_quarters/heads/hos)
"iju" = (
@@ -13266,7 +13267,7 @@
dir = 8;
pixel_x = -24
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/effect/floor_decal/steeldecal/steel_decals5{
dir = 8
},
@@ -17152,7 +17153,6 @@
/turf/simulated/floor/tiled,
/area/security/hanger)
"lDa" = (
-/mob/living/simple_mob/animal/passive/mimepet,
/obj/machinery/power/apc{
dir = 1;
name = "north bump";
@@ -17161,6 +17161,7 @@
/obj/structure/cable/green{
icon_state = "0-2"
},
+/mob/living/simple_mob/animal/passive/mimepet,
/turf/simulated/floor/carpet/bcarpet,
/area/crew_quarters/mimeoffice)
"lDo" = (
@@ -17425,7 +17426,7 @@
/obj/effect/floor_decal/corner/brown/border{
dir = 5
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled,
/area/exploration/pathfinder_office)
"lOO" = (
@@ -21816,7 +21817,7 @@
/turf/simulated/floor/lino,
/area/chapel/office)
"oUM" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/simulated/floor/tiled/dark,
/area/bridge)
"oVe" = (
@@ -30525,19 +30526,12 @@
dir = 8
},
/obj/machinery/door/window/northleft{
- name = "Hardsuit Storage";
+ name = "RIG Storage";
req_access = list(1,2,18)
},
-/obj/item/clothing/mask/breath,
-/obj/item/clothing/mask/breath,
-/obj/item/clothing/shoes/magboots,
-/obj/item/clothing/shoes/magboots,
-/obj/item/clothing/suit/space/void/security,
-/obj/item/clothing/suit/space/void/security,
-/obj/item/clothing/head/helmet/space/void/security,
-/obj/item/clothing/head/helmet/space/void/security,
/obj/structure/window/reinforced,
/obj/machinery/light,
+/obj/item/hardsuit/hazard/equipped,
/turf/simulated/floor/tiled,
/area/security/eva)
"uXy" = (
@@ -34560,6 +34554,22 @@
/obj/effect/mist,
/turf/simulated/floor/wood,
/area/triumph/surfacebase/sauna)
+"xIe" = (
+/obj/structure/table/rack{
+ dir = 8;
+ layer = 2.6
+ },
+/obj/structure/window/reinforced{
+ dir = 4
+ },
+/obj/machinery/door/window/northright{
+ name = "RIG Storage";
+ req_access = list(1,2,18)
+ },
+/obj/structure/window/reinforced,
+/obj/item/hardsuit/hazard/equipped,
+/turf/simulated/floor/tiled,
+/area/security/eva)
"xIk" = (
/obj/structure/table/woodentable,
/obj/machinery/atmospherics/component/unary/vent_pump/on{
@@ -43873,7 +43883,7 @@ xDy
kOM
arT
arT
-xmj
+xIe
xDy
sAS
bzE
diff --git a/maps/triumph/levels/flagship.dmm b/maps/triumph/levels/flagship.dmm
index a77d71e7faba..07cf596381cd 100644
--- a/maps/triumph/levels/flagship.dmm
+++ b/maps/triumph/levels/flagship.dmm
@@ -7406,7 +7406,7 @@
},
/area/centcom/control)
"xZ" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/unsimulated/floor/steel,
/area/centcom/control)
"ya" = (
@@ -12618,7 +12618,7 @@
/turf/unsimulated/floor/steel,
/area/centcom/control)
"PD" = (
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/obj/effect/floor_decal/borderfloor{
dir = 5
},
@@ -13266,7 +13266,7 @@
/obj/effect/floor_decal/borderfloor{
dir = 8
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/unsimulated/floor/steel,
/area/centcom/command)
"RG" = (
@@ -14973,7 +14973,7 @@
/obj/effect/floor_decal/borderfloor{
dir = 1
},
-/obj/structure/filingcabinet/filingcabinet,
+/obj/structure/filingcabinet/tall,
/turf/unsimulated/floor/steel,
/area/centcom/command)
"XZ" = (
diff --git a/tgui/packages/common/math.ts b/tgui/packages/common/math.ts
index 4c2104ce057b..d50dff1c90a6 100644
--- a/tgui/packages/common/math.ts
+++ b/tgui/packages/common/math.ts
@@ -56,6 +56,28 @@ export const round = (value, precision) => {
return (isHalf ? value : Math.round(value)) / m;
};
+/**
+ * Return closest higher multiple of 'multiple' from value
+ * @param {number} value
+ * @param {number} multiple
+ * @return {number}
+ */
+export const ceiling = (value: number, multiple: number): number => {
+ let mult = value / multiple;
+ return Math.ceil(mult) * multiple;
+};
+
+/**
+ * Return closest lower multiple of 'multiple' from value
+ * @param {number} value
+ * @param {number} multiple
+ * @return {number}
+ */
+export const floor = (value: number, multiple: number): number => {
+ let mult = value / multiple;
+ return Math.floor(mult) * multiple;
+};
+
/**
* Returns a string representing a number in fixed point notation.
*/
diff --git a/tgui/packages/tgui/components/Collapsible.tsx b/tgui/packages/tgui/components/Collapsible.tsx
index 41003faf9ac2..2b5b2b324442 100644
--- a/tgui/packages/tgui/components/Collapsible.tsx
+++ b/tgui/packages/tgui/components/Collapsible.tsx
@@ -19,6 +19,7 @@ interface CollapsibleProps extends ComponentProps{
more?: InfernoNode;
boxProps?: BoxProps;
headerProps?: ButtonProps;
+ contentFunction?: () => InfernoNode;
}
interface CollapsibleState {
@@ -76,7 +77,7 @@ export class Collapsible extends Component {
{open && (
- {children}
+ {!!props.contentFunction && props.contentFunction()}{children}
)}
@@ -104,7 +105,7 @@ export class Collapsible extends Component {
{open && (
- {children}
+ {!!props.contentFunction && props.contentFunction()}{children}
)}
diff --git a/tgui/packages/tgui/interfaces/Stack.js b/tgui/packages/tgui/interfaces/Stack.js
deleted file mode 100644
index 8ba13220a70e..000000000000
--- a/tgui/packages/tgui/interfaces/Stack.js
+++ /dev/null
@@ -1,204 +0,0 @@
-import { createSearch } from 'common/string';
-import { sortBy } from 'common/collections';
-import { useBackend, useLocalState } from "../backend";
-import { Box, Button, Input, NoticeBox, Section, Collapsible, Table } from "../components";
-import { Window } from "../layouts";
-
-export const Stack = (props, context) => {
- const { act, data } = useBackend(context);
-
- const {
- amount,
- recipes = [],
- } = data;
-
- const [
- searchText,
- setSearchText,
- ] = useLocalState(context, 'searchText', '');
-
- const testSearch = createSearch(searchText, item => {
- return item;
- });
-
- const items = searchText.length > 0
- && Object.keys(recipes)
- .filter(testSearch)
- .reduce((obj, key) => {
- obj[key] = recipes[key];
- return obj;
- }, {})
- || recipes;
-
- const height = Math.max(94 + Object.keys(recipes).length * 26, 250);
-
- return (
-
-
-
-
-
- );
-};
-
-const RecipeList = (props, context) => {
- const { act, data } = useBackend(context);
-
- const {
- recipes,
- } = props;
-
- const sortedKeys = sortBy(key => key.toLowerCase())(Object.keys(recipes));
-
- return sortedKeys.map(title => {
- const recipe = recipes[title];
- if (recipe.ref === undefined) {
- return (
-
-
-
-
-
- );
- } else {
- return (
-
- );
- }
- });
-};
-
-const buildMultiplier = (recipe, amount) => {
- if (recipe.req_amount > amount) {
- return 0;
- }
-
- return Math.floor(amount / recipe.req_amount);
-};
-
-const Multipliers = (props, context) => {
- const { act, data } = useBackend(context);
-
- const {
- recipe,
- maxMultiplier,
- } = props;
-
- const maxM = Math.min(maxMultiplier,
- Math.floor(recipe.max_res_amount / recipe.res_amount));
-
- const multipliers = [5, 10, 25];
-
- let finalResult = [];
-
- for (const multiplier of multipliers) {
- if (maxM >= multiplier) {
- finalResult.push((
-