From 910b97cd37321eaab4d51afed28d5f8c7ca66c7d Mon Sep 17 00:00:00 2001
From: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
Date: Sat, 5 Nov 2022 02:15:40 -0700
Subject: [PATCH] Save 0.4s by shaving off a lot of smaller init costs (#71007)
Starts shaving off a lot of less than 0.1s performance killers by, in
nearly every case, just writing better code.
Numbers are amount saved.
- /obj/machinery/bluespace_vendor/LateInitialize -> 29.4ms
Changes a loop over all machines to a specialized list.
- /obj/structure/table/glass/Initialize -> 42.53ms
Stops every table from initializing glass shards and table frames before
any destruction.
- /obj/structure/chair/Initialize -> 24.64ms
Removes an unnecessary addtimer that existed for chairs that weren't
anchored in emergency shuttles. Didn't do anything.
- /datum/orderable_item/New -> 44.3ms
Instead of initializing every item to get its desc, just uses initial.
Added a unit test to make sure none are dynamic.
- /obj/machinery/computer/slot_machine/Initialize -> 26.19ms
Currently goes through every coin subtype, creates it, calls a proc,
then qdels it. Changes that to only run once. Could be optimized further
by making the coin info on a datum to avoid creating the object, but it
currently sits at 7.82ms, far below worth caring about for now.
- /obj/machinery/door_buttons/airlock_controller/findObjsByTag -> 3.51ms
Loops over just doors instead of typechecking airlock in machines.
- /obj/structure/closet/Initialize -> 60.57ms
Moves the code for taking everything on the tile from a next-tick timer
to LateInitialize.
- /obj/machinery/rnd/experimentor/Initialize -> 36.92ms
Changes a list that is generated by going through every item in the game
and getting information from a large amount of them to only run when
needed.
- /obj/structure/tank_dispenser/Initialize -> 20.81ms
No longer initializes every tank in it right away, only when needed.
- /obj/machinery/telecomms/LateInitialize -> 16.63ms
Removes `urange` to instead just loop over telecomms machines and check
distance. There's not that many of them.
- /mob/living/simple_animal/hostile/carp/cayenne/Initialize -> 3.17ms
Defers a GAGS overlay creation until its needed. BTW GAGS is
*horrendous* on init costs, and is the root cause for a lot of pretty
terrible performance. I investigated precompiling but the gains weren't
crazy, but likely could be the more stuff is GAGS'd.
- /turf/open/floor/engine/cult/Initialize -> 14.64ms
Temporary visual effect that is created is no longer done on mapload,
since nobody will see it.
- /datum/techweb/specialized/autounlocking/proc/autounlock -> 5.55ms
Changes some loops to shorter checks. This whole proc is pretty bad and
it's still 14.21ms for 17 calls.
- /matrix/New -> 13.41ms
- /matrix/proc/Translate -> 42.06ms
~~Changed the mineral matrice to only generate once, then take it from a
static.~~ An extra ~0.05s taken off by avoiding setting icon and
transform every Initialize.
---
code/__DEFINES/map_switch.dm | 8 ++
.../computer/chef_orders/chef_order.dm | 2 +-
.../computer/chef_orders/order_datum.dm | 117 +++++++++---------
.../embedded_controller/access_controller.dm | 10 +-
code/game/machinery/slotmachine.dm | 13 +-
.../machinery/telecomms/telecomunications.dm | 6 +-
.../objects/structures/beds_chairs/chair.dm | 7 +-
.../structures/crates_lockers/closets.dm | 12 +-
code/game/objects/structures/tables_racks.dm | 42 +++----
.../game/objects/structures/tank_dispenser.dm | 32 ++---
code/game/turfs/closed/minerals.dm | 48 ++++---
code/game/turfs/open/floor/reinf_floor.dm | 5 +-
.../machinery/bluespace_vendor.dm | 2 +-
.../unary_devices/bluespace_sender.dm | 8 ++
.../lavalandruin_code/elephantgraveyard.dm | 2 +-
.../mob/living/simple_animal/hostile/carp.dm | 5 +-
code/modules/research/experimentor.dm | 14 ++-
code/modules/research/techweb/_techweb.dm | 13 +-
code/modules/shuttle/supply.dm | 2 +-
code/modules/unit_tests/_unit_tests.dm | 1 +
code/modules/unit_tests/orderable_items.dm | 16 +++
tgstation.dme | 1 +
22 files changed, 200 insertions(+), 166 deletions(-)
create mode 100644 code/__DEFINES/map_switch.dm
create mode 100644 code/modules/unit_tests/orderable_items.dm
diff --git a/code/__DEFINES/map_switch.dm b/code/__DEFINES/map_switch.dm
new file mode 100644
index 00000000000..dbb0059786e
--- /dev/null
+++ b/code/__DEFINES/map_switch.dm
@@ -0,0 +1,8 @@
+/// Uses the left operator when compiling, uses the right operator when not compiling.
+// Currently uses the CBT macro, but if http://www.byond.com/forum/post/2831057 is ever added,
+// or if map tools ever agree on a standard, this should switch to use that.
+#ifdef CBT
+#define MAP_SWITCH(compile_time, map_time) ##compile_time
+#else
+#define MAP_SWITCH(compile_time, map_time) ##map_time
+#endif
diff --git a/code/game/machinery/computer/chef_orders/chef_order.dm b/code/game/machinery/computer/chef_orders/chef_order.dm
index 7f49feb9513..524839c2a7b 100644
--- a/code/game/machinery/computer/chef_orders/chef_order.dm
+++ b/code/game/machinery/computer/chef_orders/chef_order.dm
@@ -114,7 +114,7 @@
var/list/ordered_paths = list()
for(var/datum/orderable_item/item as anything in grocery_list)//every order
for(var/amt in 1 to grocery_list[item])//every order amount
- ordered_paths += item.item_instance.type
+ ordered_paths += item.item_path
podspawn(list(
"target" = get_turf(chef),
"style" = STYLE_BLUESPACE,
diff --git a/code/game/machinery/computer/chef_orders/order_datum.dm b/code/game/machinery/computer/chef_orders/order_datum.dm
index fa028622825..796f503c501 100644
--- a/code/game/machinery/computer/chef_orders/order_datum.dm
+++ b/code/game/machinery/computer/chef_orders/order_datum.dm
@@ -9,128 +9,127 @@
//description set automatically unless it's hard set by the subtype
var/desc
var/category_index = CATEGORY_FRUITS_VEGGIES
- var/obj/item/item_instance
+ var/obj/item/item_path
var/cost_per_order = 10
/datum/orderable_item/New()
. = ..()
if(type == /datum/orderable_item)
return
- if(!item_instance)
+ if(!item_path)
CRASH("[type] orderable item datum has NO ITEM PATH!")
- item_instance = new item_instance
if(!desc)
- desc = item_instance.desc
+ desc = initial(item_path.desc)
/datum/orderable_item/Destroy(force, ...)
. = ..()
- qdel(item_instance)
+ qdel(item_path)
//Fruits and Veggies
/datum/orderable_item/potato
name = "Potato"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/potato
+ item_path = /obj/item/food/grown/potato
/datum/orderable_item/tomato
name = "Tomato"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/tomato
+ item_path = /obj/item/food/grown/tomato
/datum/orderable_item/carrot
name = "Carrot"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/carrot
+ item_path = /obj/item/food/grown/carrot
/datum/orderable_item/eggplant
name = "Eggplant"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/eggplant
+ item_path = /obj/item/food/grown/eggplant
/datum/orderable_item/mushroom
name = "Plump Helmet"
desc = "Plumus Hellmus: Plump, soft and s-so inviting~"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/mushroom/plumphelmet
+ item_path = /obj/item/food/grown/mushroom/plumphelmet
/datum/orderable_item/cabbage
name = "Cabbage"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/cabbage
+ item_path = /obj/item/food/grown/cabbage
/datum/orderable_item/beets
name = "Onion"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/onion
+ item_path = /obj/item/food/grown/onion
/datum/orderable_item/apple
name = "Apple"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance =/obj/item/food/grown/apple
+ item_path =/obj/item/food/grown/apple
/datum/orderable_item/pumpkin
name = "Pumpkin"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance =/obj/item/food/grown/pumpkin
+ item_path =/obj/item/food/grown/pumpkin
/datum/orderable_item/watermelon
name = "Watermelon"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance =/obj/item/food/grown/watermelon
+ item_path =/obj/item/food/grown/watermelon
/datum/orderable_item/corn
name = "Corn"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/corn
+ item_path = /obj/item/food/grown/corn
/datum/orderable_item/soybean
name = "Soybeans"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/soybeans
+ item_path = /obj/item/food/grown/soybeans
/datum/orderable_item/garlic
name = "Garlic"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/garlic
+ item_path = /obj/item/food/grown/garlic
/datum/orderable_item/cherries
name = "Cherries"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/cherries
+ item_path = /obj/item/food/grown/cherries
/datum/orderable_item/chanterelle
name = "Chanterelle"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/mushroom/chanterelle
+ item_path = /obj/item/food/grown/mushroom/chanterelle
/datum/orderable_item/cocoa
name = "Cocoa"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/cocoapod
+ item_path = /obj/item/food/grown/cocoapod
/datum/orderable_item/herbs
name = "Bundle of Herbs"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/herbs
+ item_path = /obj/item/food/grown/herbs
cost_per_order = 5
/datum/orderable_item/bell_pepper
name = "Bell Pepper"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/bell_pepper
+ item_path = /obj/item/food/grown/bell_pepper
/datum/orderable_item/cucumbers
name = "Cucumber"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/food/grown/cucumber
+ item_path = /obj/item/food/grown/cucumber
cost_per_order = 10
/datum/orderable_item/pickles
name = "Jar of pickles"
category_index = CATEGORY_FRUITS_VEGGIES
- item_instance = /obj/item/storage/fancy/pickles_jar
+ item_path = /obj/item/storage/fancy/pickles_jar
cost_per_order = 60
//Milk and Eggs
@@ -138,126 +137,126 @@
/datum/orderable_item/milk
name = "Milk"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/reagent_containers/condiment/milk
+ item_path = /obj/item/reagent_containers/condiment/milk
cost_per_order = 30
/datum/orderable_item/soymilk
name = "Soy Milk"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/reagent_containers/condiment/soymilk
+ item_path = /obj/item/reagent_containers/condiment/soymilk
cost_per_order = 30
/datum/orderable_item/cream
name = "Cream"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/reagent_containers/cup/glass/bottle/juice/cream
+ item_path = /obj/item/reagent_containers/cup/glass/bottle/juice/cream
cost_per_order = 40
/datum/orderable_item/yoghurt
name = "Yoghurt"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/reagent_containers/condiment/yoghurt
+ item_path = /obj/item/reagent_containers/condiment/yoghurt
cost_per_order = 40
/datum/orderable_item/eggs
name = "Egg Carton"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/storage/fancy/egg_box
+ item_path = /obj/item/storage/fancy/egg_box
cost_per_order = 40
/datum/orderable_item/fillet
name = "Fish Fillet"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/fishmeat
+ item_path = /obj/item/food/fishmeat
cost_per_order = 12
/datum/orderable_item/spider_eggs
name = "Spider Eggs"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/spidereggs
+ item_path = /obj/item/food/spidereggs
/datum/orderable_item/moonfish_eggs
name = "Moonfish Eggs"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/moonfish_eggs
+ item_path = /obj/item/food/moonfish_eggs
cost_per_order = 30
/datum/orderable_item/desert_snails
name = "Canned Desert Snails"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/desert_snails
+ item_path = /obj/item/food/desert_snails
cost_per_order = 20
/datum/orderable_item/canned_jellyfish
name = "Canned Gunner Jellyfish"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/canned_jellyfish
+ item_path = /obj/item/food/canned_jellyfish
cost_per_order = 20
/datum/orderable_item/canned_larvae
name = "Canned Larvae"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/larvae
+ item_path = /obj/item/food/larvae
cost_per_order = 20
/datum/orderable_item/canned_tomatoes
name = "Canned San Marzano Tomatoes"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/canned/tomatoes
+ item_path = /obj/item/food/canned/tomatoes
cost_per_order = 30
/datum/orderable_item/canned_pine_nuts
name = "Canned Pine Nuts"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/canned/pine_nuts
+ item_path = /obj/item/food/canned/pine_nuts
cost_per_order = 20
/datum/orderable_item/ready_donk
name = "Ready-Donk Meal: Bachelor Chow"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/ready_donk
+ item_path = /obj/item/food/ready_donk
cost_per_order = 40
/datum/orderable_item/ready_donk_mac
name = "Ready-Donk Meal: Donk-a-Roni"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/ready_donk/mac_n_cheese
+ item_path = /obj/item/food/ready_donk/mac_n_cheese
cost_per_order = 40
/datum/orderable_item/ready_donk_mex
name = "Ready-Donk Meal: Donkhiladas"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/food/ready_donk/donkhiladas
+ item_path = /obj/item/food/ready_donk/donkhiladas
cost_per_order = 40
/datum/orderable_item/tiziran_goods
name = "Tiziran Farm-Fresh Pack"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/storage/box/tiziran_goods
+ item_path = /obj/item/storage/box/tiziran_goods
cost_per_order = 120
/datum/orderable_item/tiziran_cans
name = "Tiziran Canned Goods Pack"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/storage/box/tiziran_cans
+ item_path = /obj/item/storage/box/tiziran_cans
cost_per_order = 120
/datum/orderable_item/tiziran_meats
name = "Tiziran Meatmarket Pack"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/storage/box/tiziran_meats
+ item_path = /obj/item/storage/box/tiziran_meats
cost_per_order = 120
/datum/orderable_item/mothic_goods
name = "Mothic Farm-Fresh Pack"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/storage/box/mothic_goods
+ item_path = /obj/item/storage/box/mothic_goods
cost_per_order = 120
/datum/orderable_item/mothic_cans_sauces
name = "Mothic Pantry Pack"
category_index = CATEGORY_MILK_EGGS
- item_instance = /obj/item/storage/box/mothic_cans_sauces
+ item_path = /obj/item/storage/box/mothic_cans_sauces
cost_per_order = 120
//Reagents
@@ -265,78 +264,78 @@
/datum/orderable_item/flour
name = "Flour Sack"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/flour
+ item_path = /obj/item/reagent_containers/condiment/flour
cost_per_order = 30
/datum/orderable_item/sugar
name = "Sugar Sack"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/sugar
+ item_path = /obj/item/reagent_containers/condiment/sugar
cost_per_order = 30
/datum/orderable_item/rice
name = "Rice Sack"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/rice
+ item_path = /obj/item/reagent_containers/condiment/rice
cost_per_order = 30
/datum/orderable_item/cornmeal
name = "Cornmeal Box"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/cornmeal
+ item_path = /obj/item/reagent_containers/condiment/cornmeal
cost_per_order = 30
/datum/orderable_item/enzyme
name = "Universal Enzyme"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/enzyme
+ item_path = /obj/item/reagent_containers/condiment/enzyme
cost_per_order = 40
/datum/orderable_item/salt
name = "Salt Shaker"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/saltshaker
+ item_path = /obj/item/reagent_containers/condiment/saltshaker
cost_per_order = 15
/datum/orderable_item/pepper
name = "Pepper Mill"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/peppermill
+ item_path = /obj/item/reagent_containers/condiment/peppermill
cost_per_order = 15
/datum/orderable_item/soysauce
name = "Soy Sauce"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/soysauce
+ item_path = /obj/item/reagent_containers/condiment/soysauce
cost_per_order = 15
/datum/orderable_item/bbqsauce
name = "BBQ Sauce"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/bbqsauce
+ item_path = /obj/item/reagent_containers/condiment/bbqsauce
cost_per_order = 60
/datum/orderable_item/vinegar
name = "Vinegar"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/vinegar
+ item_path = /obj/item/reagent_containers/condiment/vinegar
cost_per_order = 30
/datum/orderable_item/quality_oil
name = "Quality Oil"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/quality_oil
+ item_path = /obj/item/reagent_containers/condiment/quality_oil
cost_per_order = 50 //Extra Virgin, just like you, the reader
/datum/orderable_item/peanut_butter
name = "Peanut Butter"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/peanut_butter
+ item_path = /obj/item/reagent_containers/condiment/peanut_butter
cost_per_order = 30
/datum/orderable_item/cherryjelly
name = "Cherry Jelly"
category_index = CATEGORY_SAUCES_REAGENTS
- item_instance = /obj/item/reagent_containers/condiment/cherryjelly
+ item_path = /obj/item/reagent_containers/condiment/cherryjelly
cost_per_order = 30
//
diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm
index 916eb25f914..4beff475ef2 100644
--- a/code/game/machinery/embedded_controller/access_controller.dm
+++ b/code/game/machinery/embedded_controller/access_controller.dm
@@ -240,11 +240,11 @@
lostPower = FALSE
/obj/machinery/door_buttons/airlock_controller/findObjsByTag()
- for(var/obj/machinery/door/airlock/A in GLOB.machines)
- if(A.id_tag == idInterior)
- interiorAirlock = A
- else if(A.id_tag == idExterior)
- exteriorAirlock = A
+ for(var/obj/machinery/door/door as anything in GLOB.airlocks)
+ if(door.id_tag == idInterior)
+ interiorAirlock = door
+ else if(door.id_tag == idExterior)
+ exteriorAirlock = door
/obj/machinery/door_buttons/airlock_controller/update_icon_state()
if(machine_stat & NOPOWER)
diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm
index e06bed0829e..25367292ede 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -31,7 +31,7 @@
var/jackpots = 0
var/paymode = HOLOCHIP //toggles between HOLOCHIP/COIN, defined above
var/cointype = /obj/item/coin/iron //default cointype
- var/list/coinvalues = list()
+ var/static/list/coinvalues
var/list/reels = list(list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0)
var/list/symbols = list(SEVEN = 1, "&" = 2, "@" = 2, "$" = 2, "?" = 2, "#" = 2, "!" = 2, "%" = 2) //if people are winning too much, multiply every number in this list by 2 and see if they are still winning too much.
@@ -49,10 +49,13 @@
INVOKE_ASYNC(src, .proc/toggle_reel_spin, FALSE)
- for(cointype in typesof(/obj/item/coin))
- var/obj/item/coin/C = new cointype
- coinvalues["[cointype]"] = C.get_item_credit_value()
- qdel(C) //Sigh
+ if (isnull(coinvalues))
+ coinvalues = list()
+
+ for(cointype in typesof(/obj/item/coin))
+ var/obj/item/coin/C = new cointype
+ coinvalues["[cointype]"] = C.get_item_credit_value()
+ qdel(C) //Sigh
/obj/machinery/computer/slot_machine/Destroy()
if(balance)
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index 845b7392c62..3e724114ad8 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -111,8 +111,10 @@ GLOBAL_LIST_EMPTY(telecomms_list)
/obj/machinery/telecomms/LateInitialize()
..()
- for(var/obj/machinery/telecomms/T in (long_range_link ? GLOB.telecomms_list : urange(20, src, 1)))
- add_automatic_link(T)
+
+ for(var/obj/machinery/telecomms/telecomms_machine in GLOB.telecomms_list)
+ if (long_range_link || IN_GIVEN_RANGE(src, telecomms_machine, 20))
+ add_automatic_link(telecomms_machine)
/obj/machinery/telecomms/Destroy()
GLOB.telecomms_list -= src
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index e314651ca65..94f90fcf49d 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -24,8 +24,6 @@
/obj/structure/chair/Initialize(mapload)
. = ..()
- if(!anchored) //why would you put these on the shuttle?
- addtimer(CALLBACK(src, .proc/RemoveFromLatejoin), 0)
if(prob(0.2))
name = "tactical [name]"
MakeRotate()
@@ -35,11 +33,8 @@
AddComponent(/datum/component/simple_rotation, ROTATION_IGNORE_ANCHORED|ROTATION_GHOSTS_ALLOWED)
/obj/structure/chair/Destroy()
- RemoveFromLatejoin()
- return ..()
-
-/obj/structure/chair/proc/RemoveFromLatejoin()
SSjob.latejoin_trackers -= src //These may be here due to the arrivals shuttle
+ return ..()
/obj/structure/chair/deconstruct(disassembled)
// If we have materials, and don't have the NOCONSTRUCT flag
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 8e773674205..b4489b53027 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -71,9 +71,12 @@
var/contents_initialized = FALSE
/obj/structure/closet/Initialize(mapload)
- if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents
- addtimer(CALLBACK(src, .proc/take_contents, TRUE), 0)
. = ..()
+
+ // if closed, any item at the crate's loc is put in the contents
+ if (mapload && !opened)
+ . = INITIALIZE_HINT_LATELOAD
+
update_appearance()
populate_contents_immediate()
var/static/list/loc_connections = list(
@@ -82,6 +85,11 @@
)
AddElement(/datum/element/connect_loc, loc_connections)
+/obj/structure/closet/LateInitialize()
+ . = ..()
+
+ take_contents()
+
//USE THIS TO FILL IT, NOT INITIALIZE OR NEW
/obj/structure/closet/proc/PopulateContents()
SEND_SIGNAL(src, COMSIG_CLOSET_POPULATE_CONTENTS)
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index aff25ceae1f..cc71efc28fc 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -24,6 +24,7 @@
layer = TABLE_LAYER
var/frame = /obj/structure/table_frame
var/framestack = /obj/item/stack/rods
+ var/glass_shard_type = /obj/item/shard
var/buildstack = /obj/item/stack/sheet/iron
var/busy = FALSE
var/buildstackamount = 1
@@ -391,24 +392,14 @@
max_integrity = 70
resistance_flags = ACID_PROOF
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 80, ACID = 100)
- var/list/debris = list()
/obj/structure/table/glass/Initialize(mapload)
. = ..()
- debris += new frame
- if(buildstack == /obj/item/stack/sheet/plasmaglass)
- debris += new /obj/item/shard/plasma
- else
- debris += new /obj/item/shard
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = .proc/on_entered,
)
AddElement(/datum/element/connect_loc, loc_connections)
-/obj/structure/table/glass/Destroy()
- QDEL_LIST(debris)
- . = ..()
-
/obj/structure/table/glass/proc/on_entered(datum/source, atom/movable/AM)
SIGNAL_HANDLER
if(flags_1 & NODECONSTRUCT_1)
@@ -429,18 +420,18 @@
if(M.has_gravity() && M.mob_size > MOB_SIZE_SMALL && !(M.movement_type & FLYING))
table_shatter(M)
-/obj/structure/table/glass/proc/table_shatter(mob/living/L)
+/obj/structure/table/glass/proc/table_shatter(mob/living/victim)
visible_message(span_warning("[src] breaks!"),
span_danger("You hear breaking glass."))
- var/turf/T = get_turf(src)
- playsound(T, SFX_SHATTER, 50, TRUE)
- for(var/I in debris)
- var/atom/movable/AM = I
- AM.forceMove(T)
- debris -= AM
- if(istype(AM, /obj/item/shard))
- AM.throw_impact(L)
- L.Paralyze(100)
+
+ playsound(loc, SFX_SHATTER, 50, TRUE)
+
+ new frame(loc)
+
+ var/obj/item/shard/shard = new glass_shard_type(loc)
+ shard.throw_impact(victim)
+
+ victim.Paralyze(100)
qdel(src)
/obj/structure/table/glass/deconstruct(disassembled = TRUE, wrench_disassembly = 0)
@@ -451,16 +442,14 @@
else
var/turf/T = get_turf(src)
playsound(T, SFX_SHATTER, 50, TRUE)
- for(var/X in debris)
- var/atom/movable/AM = X
- AM.forceMove(T)
- debris -= AM
+
+ new frame(loc)
+ new glass_shard_type(loc)
+
qdel(src)
/obj/structure/table/glass/narsie_act()
color = NARSIE_WINDOW_COLOUR
- for(var/obj/item/shard/S in debris)
- S.color = NARSIE_WINDOW_COLOUR
/obj/structure/table/glass/plasmaglass
name = "plasma glass table"
@@ -470,6 +459,7 @@
base_icon_state = "plasmaglass_table"
custom_materials = list(/datum/material/alloy/plasmaglass = 2000)
buildstack = /obj/item/stack/sheet/plasmaglass
+ glass_shard_type = /obj/item/shard/plasma
max_integrity = 100
/*
diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm
index b0f322d3539..95978496dbc 100644
--- a/code/game/objects/structures/tank_dispenser.dm
+++ b/code/game/objects/structures/tank_dispenser.dm
@@ -19,10 +19,6 @@
/obj/structure/tank_dispenser/Initialize(mapload)
. = ..()
- for(var/i in 1 to oxygentanks)
- new /obj/item/tank/internals/oxygen(src)
- for(var/i in 1 to plasmatanks)
- new /obj/item/tank/internals/plasma(src)
update_appearance()
/obj/structure/tank_dispenser/update_overlays()
@@ -91,18 +87,20 @@
return
switch(action)
if("plasma")
- var/obj/item/tank/internals/plasma/tank = locate() in src
- if(tank && Adjacent(usr))
- usr.put_in_hands(tank)
- plasmatanks--
- . = TRUE
+ if (plasmatanks == 0)
+ return TRUE
+
+ dispense(/obj/item/tank/internals/plasma, usr)
+ plasmatanks--
if("oxygen")
- var/obj/item/tank/internals/oxygen/tank = locate() in src
- if(tank && Adjacent(usr))
- usr.put_in_hands(tank)
- oxygentanks--
- . = TRUE
+ if (oxygentanks == 0)
+ return TRUE
+
+ dispense(/obj/item/tank/internals/oxygen, usr)
+ oxygentanks--
+
update_appearance()
+ return TRUE
/obj/structure/tank_dispenser/deconstruct(disassembled = TRUE)
@@ -113,4 +111,10 @@
new /obj/item/stack/sheet/iron (loc, 2)
qdel(src)
+/obj/structure/tank_dispenser/proc/dispense(tank_type, mob/receiver)
+ var/existing_tank = locate(tank_type) in src
+ if (isnull(existing_tank))
+ existing_tank = new tank_type
+ receiver.put_in_hands(existing_tank)
+
#undef TANK_DISPENSER_CAPACITY
diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm
index c35ca07e3a8..b5e6ba46268 100644
--- a/code/game/turfs/closed/minerals.dm
+++ b/code/game/turfs/closed/minerals.dm
@@ -2,9 +2,11 @@
/**********************Mineral deposits**************************/
+#define MINERAL_WALL_OFFSET -4
+
/turf/closed/mineral //wall piece
name = "rock"
- icon = 'icons/turf/mining.dmi'
+ icon = MAP_SWITCH('icons/turf/smoothrocks.dmi', 'icons/turf/mining.dmi')
icon_state = "rock"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
smoothing_groups = list(SMOOTH_GROUP_CLOSED_TURFS, SMOOTH_GROUP_MINERAL_WALLS)
@@ -16,8 +18,13 @@
layer = EDGED_TURF_LAYER
plane = GAME_PLANE_UPPER
base_icon_state = "smoothrocks"
+
+ base_pixel_x = MINERAL_WALL_OFFSET
+ base_pixel_y = MINERAL_WALL_OFFSET
+ pixel_x = MAP_SWITCH(MINERAL_WALL_OFFSET, 0)
+ pixel_y = MAP_SWITCH(MINERAL_WALL_OFFSET, 0)
+
temperature = TCMB
- var/smooth_icon = 'icons/turf/smoothrocks.dmi'
var/turf/open/floor/plating/turf_type = /turf/open/misc/asteroid/airless
var/obj/item/stack/ore/mineralType = null
var/mineralAmt = 3
@@ -30,12 +37,7 @@
///How long it takes to mine this turf without tools, if it's weak.
var/hand_mine_speed = 15 SECONDS
-/turf/closed/mineral/Initialize(mapload)
- . = ..()
- var/matrix/M = new
- M.Translate(-4, -4)
- transform = M
- icon = smooth_icon
+#undef MINERAL_WALL_OFFSET
// Inlined version of the bump click element. way faster this way, the element's nice but it's too much overhead
/turf/closed/mineral/Bumped(atom/movable/bumped_atom)
@@ -266,8 +268,7 @@
/turf/closed/mineral/random/snow
name = "snowy mountainside"
- icon = 'icons/turf/mining.dmi'
- smooth_icon = 'icons/turf/walls/mountain_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/mountain_wall.dmi', 'icons/turf/mining.dmi')
icon_state = "mountainrock"
base_icon_state = "mountain_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
@@ -281,7 +282,6 @@
/turf/closed/mineral/random/snow/Change_Ore(ore_type, random = 0)
. = ..()
if(mineralType)
- smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
icon = 'icons/turf/walls/icerock_wall.dmi'
icon_state = "icerock_wall-0"
base_icon_state = "icerock_wall"
@@ -327,8 +327,7 @@
// Subtypes for mappers placing ores manually.
/turf/closed/mineral/random/labormineral/ice
name = "snowy mountainside"
- icon = 'icons/turf/mining.dmi'
- smooth_icon = 'icons/turf/walls/mountain_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/mountain_wall.dmi', 'icons/turf/mining.dmi')
icon_state = "mountainrock"
base_icon_state = "mountain_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
@@ -346,7 +345,6 @@
/turf/closed/mineral/random/labormineral/ice/Change_Ore(ore_type, random = 0)
. = ..()
if(mineralType)
- smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
icon = 'icons/turf/walls/icerock_wall.dmi'
icon_state = "icerock_wall-0"
base_icon_state = "icerock_wall"
@@ -358,7 +356,7 @@
/turf/closed/mineral/iron/ice
icon_state = "icerock_iron"
- smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/icerock_wall.dmi', 'icons/turf/mining.dmi')
base_icon_state = "icerock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/misc/asteroid/snow/ice
@@ -376,7 +374,7 @@
/turf/closed/mineral/diamond/ice
icon_state = "icerock_iron"
- smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/icerock_wall.dmi', 'icons/turf/mining.dmi')
base_icon_state = "icerock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/misc/asteroid/snow/ice
@@ -413,7 +411,7 @@
/turf/closed/mineral/plasma/ice
icon_state = "icerock_plasma"
- smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/icerock_wall.dmi', 'icons/turf/mining.dmi')
base_icon_state = "icerock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/misc/asteroid/snow/ice
@@ -450,7 +448,7 @@
/turf/closed/mineral/ash_rock //wall piece
name = "rock"
icon = 'icons/turf/mining.dmi'
- smooth_icon = 'icons/turf/walls/rock_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/rock_wall.dmi', 'icons/turf/mining.dmi')
icon_state = "rock2"
base_icon_state = "rock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
@@ -462,8 +460,7 @@
/turf/closed/mineral/snowmountain
name = "snowy mountainside"
- icon = 'icons/turf/mining.dmi'
- smooth_icon = 'icons/turf/walls/mountain_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/mountain_wall.dmi', 'icons/turf/mining.dmi')
icon_state = "mountainrock"
base_icon_state = "mountain_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
@@ -480,8 +477,7 @@
/turf/closed/mineral/snowmountain/cavern
name = "ice cavern rock"
- icon = 'icons/turf/mining.dmi'
- smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/icerock_wall.dmi', 'icons/turf/mining.dmi')
icon_state = "icerock"
base_icon_state = "icerock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
@@ -508,13 +504,13 @@
name = "iron rock"
icon = 'icons/turf/mining.dmi'
icon_state = "redrock"
- smooth_icon = 'icons/turf/walls/red_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/red_wall.dmi', 'icons/turf/mining.dmi')
base_icon_state = "red_wall"
/turf/closed/mineral/random/stationside/asteroid
name = "iron rock"
icon = 'icons/turf/mining.dmi'
- smooth_icon = 'icons/turf/walls/red_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/red_wall.dmi', 'icons/turf/mining.dmi')
base_icon_state = "red_wall"
/turf/closed/mineral/random/stationside/asteroid/porus
@@ -626,7 +622,7 @@
/turf/closed/mineral/gibtonite/ice
icon_state = "icerock_Gibtonite"
- smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/icerock_wall.dmi', 'icons/turf/mining.dmi')
base_icon_state = "icerock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/misc/asteroid/snow/ice
@@ -646,7 +642,7 @@
baseturfs = /turf/open/misc/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
- smooth_icon = 'icons/turf/walls/rock_wall.dmi'
+ icon = MAP_SWITCH('icons/turf/walls/rock_wall.dmi', 'icons/turf/mining.dmi')
base_icon_state = "rock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
diff --git a/code/game/turfs/open/floor/reinf_floor.dm b/code/game/turfs/open/floor/reinf_floor.dm
index 63eec366951..bd44a50059e 100644
--- a/code/game/turfs/open/floor/reinf_floor.dm
+++ b/code/game/turfs/open/floor/reinf_floor.dm
@@ -204,7 +204,10 @@
/turf/open/floor/engine/cult/Initialize(mapload)
. = ..()
icon_state = "plating" //we're redefining the base icon_state here so that the Conceal/Reveal Presence spell works for cultists
- new /obj/effect/temp_visual/cult/turf/floor(src)
+
+ if (!mapload)
+ new /obj/effect/temp_visual/cult/turf/floor(src)
+
realappearance = new /obj/effect/cult_turf/overlay/floor/bloodcult(src)
realappearance.linked = src
diff --git a/code/modules/atmospherics/machinery/bluespace_vendor.dm b/code/modules/atmospherics/machinery/bluespace_vendor.dm
index 9b5a77218da..be58a4d1e16 100644
--- a/code/modules/atmospherics/machinery/bluespace_vendor.dm
+++ b/code/modules/atmospherics/machinery/bluespace_vendor.dm
@@ -70,7 +70,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/bluespace_vendor, 30)
. = ..()
if(!map_spawned)
return
- for(var/obj/machinery/atmospherics/components/unary/bluespace_sender/sender in GLOB.machines)
+ for(var/obj/machinery/atmospherics/components/unary/bluespace_sender/sender as anything in GLOB.bluespace_senders)
register_machine(sender)
/obj/machinery/bluespace_vendor/Destroy()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm b/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm
index 81af94acdc9..194da5d7569 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm
@@ -26,6 +26,9 @@
///Amount of credits gained from each vendor
var/credits_gained = 0
+/// All bluespace gas senders
+GLOBAL_LIST_EMPTY_TYPED(bluespace_senders, /obj/machinery/atmospherics/components/unary/bluespace_sender)
+
/obj/machinery/atmospherics/components/unary/bluespace_sender/Initialize(mapload)
. = ..()
initialize_directions = dir
@@ -36,12 +39,17 @@
var/datum/gas/gas = gas_id
base_prices[gas_id] = initial(gas.base_value)
+ GLOB.bluespace_senders += src
+
update_appearance()
/obj/machinery/atmospherics/components/unary/bluespace_sender/Destroy()
if(bluespace_network.total_moles())
var/turf/local_turf = get_turf(src)
local_turf.assume_air(bluespace_network)
+
+ GLOB.bluespace_senders -= src
+
return ..()
/obj/machinery/atmospherics/components/unary/bluespace_sender/update_icon_state()
diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
index 5dff1358f96..a9f2c8412fc 100644
--- a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
+++ b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
@@ -54,7 +54,7 @@
color = "#B5651D"
turf_type = /turf/open/misc/asteroid/basalt/wasteland
baseturfs = /turf/open/misc/asteroid/basalt/wasteland
- smooth_icon = 'icons/turf/walls/rock_wall.dmi'
+ icon = 'icons/turf/walls/rock_wall.dmi'
base_icon_state = "rock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index 297690c0422..529508e73de 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -259,7 +259,6 @@
/mob/living/simple_animal/hostile/carp/cayenne/Initialize(mapload)
. = ..()
AddElement(/datum/element/pet_bonus, "bloops happily!")
- colored_disk_mouth = mutable_appearance(SSgreyscale.GetColoredIconByType(/datum/greyscale_config/carp/disk_mouth, greyscale_colors), "disk_mouth")
ADD_TRAIT(src, TRAIT_DISK_VERIFIER, INNATE_TRAIT) //carp can verify disky
ADD_TRAIT(src, TRAIT_CAN_STRIP, INNATE_TRAIT) //carp can take the disk off the captain
ADD_TRAIT(src, TRAIT_CAN_USE_NUKE, INNATE_TRAIT) //carp SMART
@@ -317,6 +316,10 @@
. = ..()
if(!disky || stat == DEAD)
return
+
+ if (isnull(colored_disk_mouth))
+ colored_disk_mouth = mutable_appearance(SSgreyscale.GetColoredIconByType(/datum/greyscale_config/carp/disk_mouth, greyscale_colors), "disk_mouth")
+
. += colored_disk_mouth
. += mutable_appearance(disk_overlay_file, "disk_overlay")
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index f598e079584..39eee7d5cc1 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -38,7 +38,7 @@
var/resetTime = 15
var/cloneMode = FALSE
var/list/item_reactions = list()
- var/list/valid_items = list() //valid items for special reactions like transforming
+ var/static/list/valid_items //valid items for special reactions like transforming
var/list/critical_items_typecache //items that can cause critical reactions
/obj/machinery/rnd/experimentor/proc/ConvertReqString2List(list/source_list)
@@ -47,14 +47,17 @@
temp_list[O] = text2num(temp_list[O])
return temp_list
+/obj/machinery/rnd/experimentor/proc/valid_items()
+ if (!isnull(valid_items))
+ return valid_items
-/obj/machinery/rnd/experimentor/proc/SetTypeReactions()
- // Don't need to keep this typecache around, only used in this proc once.
var/static/list/banned_typecache = typecacheof(list(
/obj/item/stock_parts/cell/infinite,
/obj/item/grenade/chem_grenade/tuberculosis
))
+ valid_items = list()
+
for(var/I in typesof(/obj/item))
if(ispath(I, /obj/item/relic))
item_reactions["[I]"] = SCANTYPE_DISCOVER
@@ -74,12 +77,13 @@
if(initial(tempCheck.icon_state) != null) //check it's an actual usable item, in a hacky way
valid_items["[I]"] += rand(1,4)
+ return valid_items
+
/obj/machinery/rnd/experimentor/Initialize(mapload)
. = ..()
tracked_ian_ref = WEAKREF(locate(/mob/living/simple_animal/pet/dog/corgi/ian) in GLOB.mob_living_list)
tracked_runtime_ref = WEAKREF(locate(/mob/living/simple_animal/pet/cat/runtime) in GLOB.mob_living_list)
- SetTypeReactions()
critical_items_typecache = typecacheof(list(
/obj/item/construction/rcd,
@@ -293,7 +297,7 @@
else if(prob(EFFECT_PROB_MEDIUM-malfunction_probability_coeff))
var/savedName = "[exp_on]"
ejectItem(TRUE)
- var/newPath = text2path(pick_weight(valid_items))
+ var/newPath = text2path(pick_weight(valid_items()))
loaded_item = new newPath(src)
visible_message(span_warning("[src] malfunctions, transforming [savedName] into [loaded_item]!"))
investigate_log("Experimentor has transformed [savedName] into [loaded_item]", INVESTIGATE_EXPERIMENTOR)
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
index 9045f3dbeec..b4f0d233487 100644
--- a/code/modules/research/techweb/_techweb.dm
+++ b/code/modules/research/techweb/_techweb.dm
@@ -456,23 +456,16 @@
/datum/techweb/specialized/autounlocking
var/design_autounlock_buildtypes = NONE
- var/design_autounlock_categories = list(RND_CATEGORY_INITIAL) //if a design has a buildtype that matches the abovea and either has a category in this or this is null, unlock it.
- var/node_autounlock_ids = list() //autounlock nodes of this type.
/datum/techweb/specialized/autounlocking/New()
..()
autounlock()
/datum/techweb/specialized/autounlocking/proc/autounlock()
- for(var/id in node_autounlock_ids)
- research_node_id(id, TRUE, FALSE, FALSE)
for(var/id in SSresearch.techweb_designs)
- var/datum/design/D = SSresearch.techweb_design_by_id(id)
- if(D.build_type & design_autounlock_buildtypes)
- for(var/i in D.category)
- if(i in design_autounlock_categories)
- add_design_by_id(D.id)
- break
+ var/datum/design/design = SSresearch.techweb_designs[id]
+ if((design.build_type & design_autounlock_buildtypes) && (RND_CATEGORY_INITIAL in design.category))
+ add_design_by_id(id)
/datum/techweb/specialized/autounlocking/autolathe
design_autounlock_buildtypes = AUTOLATHE
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index c4334faf088..bffd9f138ac 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -113,7 +113,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
investigate_log("Chef's [SSshuttle.chef_groceries.len] sized produce order arrived. Cost was deducted from orderer, not cargo.", INVESTIGATE_CARGO)
for(var/datum/orderable_item/item as anything in SSshuttle.chef_groceries)//every order
for(var/amt in 1 to SSshuttle.chef_groceries[item])//every order amount
- new item.item_instance.type(grocery_crate)
+ new item.item_path(grocery_crate)
SSshuttle.chef_groceries.Cut() //This lets the console know it can order another round.
if(!SSshuttle.shopping_list.len)
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index 6e3154e36fc..00d5bda0df7 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -138,6 +138,7 @@
#include "ntnetwork_tests.dm"
#include "nuke_cinematic.dm"
#include "objectives.dm"
+#include "orderable_items.dm"
#include "operating_table.dm"
#include "outfit_sanity.dm"
#include "paintings.dm"
diff --git a/code/modules/unit_tests/orderable_items.dm b/code/modules/unit_tests/orderable_items.dm
new file mode 100644
index 00000000000..877824546c2
--- /dev/null
+++ b/code/modules/unit_tests/orderable_items.dm
@@ -0,0 +1,16 @@
+/// Makes sure that no orderable items have dynamic descriptions, if they
+/// don't explicitly set a description.
+/datum/unit_test/orderable_item_descriptions
+
+/datum/unit_test/orderable_item_descriptions/Run()
+ for (var/datum/orderable_item/orderable_item as anything in subtypesof(/datum/orderable_item))
+ if (!isnull(initial(orderable_item.desc)))
+ continue
+
+ var/item_path = initial(orderable_item.item_path)
+
+ var/obj/item/item_instance = new item_path
+ var/initial_desc = initial(item_instance.desc)
+
+ if (item_instance.desc != initial_desc)
+ Fail("[orderable_item] has an item ([item_path]) that has a dynamic description. [item_instance.desc] (dynamic description) != [initial_desc] (initial description)")
diff --git a/tgstation.dme b/tgstation.dme
index 9ad054f2a0c..230b006c031 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -110,6 +110,7 @@
#include "code\__DEFINES\loot.dm"
#include "code\__DEFINES\machines.dm"
#include "code\__DEFINES\magic.dm"
+#include "code\__DEFINES\map_switch.dm"
#include "code\__DEFINES\maps.dm"
#include "code\__DEFINES\materials.dm"
#include "code\__DEFINES\maths.dm"