diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm
index 38463d849ea..b36684a2dab 100644
--- a/_maps/map_files/debug/runtimestation.dmm
+++ b/_maps/map_files/debug/runtimestation.dmm
@@ -668,23 +668,6 @@
},
/turf/open/floor/iron/cafeteria,
/area/station/medical/medbay)
-"cK" = (
-/obj/machinery/light/directional/south,
-/obj/structure/table/glass,
-/obj/item/disk/surgery/debug,
-/obj/item/storage/box/monkeycubes{
- pixel_x = 6;
- pixel_y = 1
- },
-/obj/item/storage/box/monkeycubes{
- pixel_x = -6;
- pixel_y = 2
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/turf/open/floor/iron/white/corner,
-/area/station/medical/medbay)
"cL" = (
/obj/item/surgery_tray/full/advanced,
/obj/structure/table/glass,
@@ -1751,16 +1734,19 @@
/obj/effect/mapping_helpers/airalarm/unlocked,
/turf/open/floor/plating,
/area/station/engineering/atmos)
+"hv" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/item/storage/part_replacer/bluespace/tier4,
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"hD" = (
/obj/structure/closet/secure_closet/chemical/heisenberg{
locked = 0
},
/turf/open/floor/iron,
/area/station/medical/chemistry)
-"ib" = (
-/obj/effect/spawner/structure/window/reinforced,
-/turf/open/floor/plating,
-/area/station/cargo/bitrunning/den)
"ii" = (
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -1819,13 +1805,6 @@
/obj/structure/cable,
/turf/open/floor/iron,
/area/station/engineering/main)
-"lE" = (
-/obj/machinery/power/apc/auto_name/directional/north,
-/obj/structure/cable,
-/obj/machinery/airalarm/directional/east,
-/obj/machinery/computer/quantum_console,
-/turf/open/floor/iron,
-/area/station/cargo/bitrunning/den)
"lH" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
dir = 6
@@ -1849,11 +1828,6 @@
/obj/machinery/chem_mass_spec,
/turf/open/floor/iron,
/area/station/medical/chemistry)
-"mV" = (
-/obj/structure/cable,
-/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
-/turf/open/floor/iron,
-/area/station/cargo/bitrunning/den)
"nn" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 8
@@ -1871,6 +1845,12 @@
/obj/item/storage/toolbox/syndicate,
/turf/open/floor/iron,
/area/station/commons/storage/primary)
+"nI" = (
+/obj/machinery/door/airlock,
+/obj/structure/cable,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"od" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -1899,9 +1879,6 @@
/obj/machinery/door/airlock/external/glass/ruin,
/turf/open/floor/plating,
/area/station/medical/medbay)
-"pK" = (
-/turf/open/floor/iron,
-/area/station/cargo/bitrunning/den)
"qb" = (
/obj/machinery/door/airlock,
/turf/open/floor/plating,
@@ -1932,23 +1909,34 @@
/obj/structure/cable,
/turf/open/floor/iron,
/area/station/hallway/primary/central)
-"rM" = (
-/obj/machinery/quantum_server,
-/turf/open/floor/iron,
-/area/station/cargo/bitrunning/den)
-"rS" = (
+"rT" = (
/turf/open/floor/circuit/green,
/area/station/cargo/bitrunning/den)
"sr" = (
/obj/machinery/door/airlock/shell,
/turf/open/floor/iron/dark,
/area/station/construction)
-"sH" = (
-/obj/structure/table,
-/obj/item/storage/box/shipping,
-/obj/item/boulder_beacon,
-/turf/open/floor/iron,
-/area/station/commons/storage/primary)
+"tz" = (
+/obj/machinery/light/directional/south,
+/obj/structure/table/glass,
+/obj/item/disk/surgery/debug,
+/obj/item/storage/box/monkeycubes{
+ pixel_x = 6;
+ pixel_y = 1
+ },
+/obj/item/storage/box/monkeycubes{
+ pixel_x = -6;
+ pixel_y = 2
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/item/disk/data/debug{
+ pixel_y = 9;
+ pixel_x = 7
+ },
+/turf/open/floor/iron/white/corner,
+/area/station/medical/medbay)
"tE" = (
/obj/machinery/door/airlock/research,
/turf/open/floor/iron/dark,
@@ -2006,6 +1994,11 @@
},
/turf/open/floor/iron/dark,
/area/station/science/explab)
+"vb" = (
+/obj/structure/cable,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"vm" = (
/mob/living/circuit_drone,
/turf/open/floor/iron/dark,
@@ -2079,16 +2072,16 @@
/obj/machinery/airalarm/directional/north,
/turf/open/floor/iron,
/area/station/science)
+"Aj" = (
+/obj/structure/cable,
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"AP" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
dir = 8
},
/turf/open/floor/iron,
/area/station/science)
-"Ba" = (
-/obj/machinery/netpod,
-/turf/open/floor/iron,
-/area/station/cargo/bitrunning/den)
"BD" = (
/obj/structure/closet/secure_closet/chief_medical{
locked = 0
@@ -2109,10 +2102,6 @@
/obj/structure/closet/syndicate/resources/everything,
/turf/open/floor/iron,
/area/station/science)
-"Cz" = (
-/obj/structure/cable,
-/turf/open/floor/iron,
-/area/station/cargo/bitrunning/den)
"CQ" = (
/obj/machinery/light/directional/south,
/obj/effect/turf_decal/stripes/line{
@@ -2230,6 +2219,13 @@
/obj/effect/turf_decal/tile/blue/half/contrasted,
/turf/open/floor/iron,
/area/station/command/bridge)
+"IF" = (
+/obj/machinery/power/apc/auto_name/directional/north,
+/obj/structure/cable,
+/obj/machinery/airalarm/directional/east,
+/obj/machinery/computer/quantum_console,
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"IH" = (
/obj/structure/closet/secure_closet/engineering_welding{
locked = 0
@@ -2263,13 +2259,6 @@
/obj/effect/mapping_helpers/airalarm/unlocked,
/turf/open/floor/iron,
/area/station/hallway/primary/central)
-"Kf" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 4
- },
-/obj/item/storage/part_replacer/bluespace/tier4,
-/turf/open/floor/iron,
-/area/station/cargo/bitrunning/den)
"Kx" = (
/obj/structure/table,
/obj/item/analyzer,
@@ -2277,15 +2266,6 @@
/obj/machinery/light/directional/south,
/turf/open/floor/plating,
/area/station/engineering/atmos)
-"Lb" = (
-/obj/structure/table/reinforced,
-/obj/machinery/light/directional/south,
-/obj/item/bitrunning_debug,
-/turf/open/floor/iron,
-/area/station/cargo/bitrunning/den)
-"Le" = (
-/turf/closed/wall/r_wall,
-/area/station/cargo/bitrunning/den)
"Ly" = (
/obj/machinery/chem_dispenser/chem_synthesizer,
/turf/open/floor/iron/dark,
@@ -2298,6 +2278,10 @@
/obj/machinery/door/airlock/research,
/turf/open/floor/iron/dark,
/area/station/science/explab)
+"LS" = (
+/obj/machinery/quantum_server,
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"LW" = (
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/iron,
@@ -2329,10 +2313,6 @@
/obj/machinery/chem_recipe_debug,
/turf/open/floor/iron,
/area/station/medical/chemistry)
-"Nj" = (
-/obj/machinery/byteforge,
-/turf/open/floor/circuit/green,
-/area/station/cargo/bitrunning/den)
"Ns" = (
/obj/machinery/door/airlock/public/glass,
/obj/structure/cable,
@@ -2404,11 +2384,9 @@
},
/turf/open/floor/engine,
/area/station/cargo/miningoffice)
-"QU" = (
-/obj/machinery/door/airlock,
-/obj/structure/cable,
-/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
-/turf/open/floor/iron,
+"QY" = (
+/obj/effect/spawner/structure/window/reinforced,
+/turf/open/floor/plating,
/area/station/cargo/bitrunning/den)
"Rb" = (
/obj/effect/spawner/structure/window/reinforced,
@@ -2420,6 +2398,10 @@
},
/turf/open/floor/plating,
/area/station/hallway/secondary/entry)
+"Rp" = (
+/obj/machinery/byteforge,
+/turf/open/floor/circuit/green,
+/area/station/cargo/bitrunning/den)
"RM" = (
/obj/structure/closet/secure_closet/hop{
locked = 0
@@ -2442,6 +2424,12 @@
},
/turf/open/floor/iron/white/corner,
/area/station/medical/medbay)
+"SC" = (
+/obj/structure/table/reinforced,
+/obj/machinery/light/directional/south,
+/obj/item/bitrunning_debug,
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"Td" = (
/obj/machinery/light/directional/east,
/obj/effect/turf_decal/stripes/line{
@@ -2456,11 +2444,18 @@
"Tt" = (
/turf/open/floor/plating,
/area/station/maintenance/aft)
+"TR" = (
+/obj/machinery/netpod,
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"TV" = (
/obj/machinery/door/airlock,
/obj/structure/cable,
/turf/open/floor/iron,
/area/station/construction)
+"Ue" = (
+/turf/closed/wall/r_wall,
+/area/station/cargo/bitrunning/den)
"Ut" = (
/obj/structure/closet/secure_closet/medical3{
locked = 0
@@ -2468,6 +2463,16 @@
/obj/item/healthanalyzer/advanced,
/turf/open/floor/iron,
/area/station/medical/medbay)
+"Va" = (
+/obj/machinery/power/smes/full,
+/obj/effect/turf_decal/stripes/line{
+ dir = 9
+ },
+/obj/structure/cable,
+/obj/machinery/airalarm/directional/north,
+/obj/effect/mapping_helpers/airalarm/unlocked,
+/turf/open/floor/iron,
+/area/station/engineering/gravity_generator)
"Vg" = (
/obj/machinery/light/directional/south,
/obj/structure/cable,
@@ -2512,16 +2517,6 @@
/obj/structure/cable,
/turf/open/floor/iron,
/area/station/engineering/gravity_generator)
-"Wy" = (
-/obj/machinery/power/smes/full,
-/obj/effect/turf_decal/stripes/line{
- dir = 9
- },
-/obj/structure/cable,
-/obj/machinery/airalarm/directional/north,
-/obj/effect/mapping_helpers/airalarm/unlocked,
-/turf/open/floor/iron,
-/area/station/engineering/gravity_generator)
"WK" = (
/obj/structure/money_bot,
/turf/open/floor/iron/dark,
@@ -2581,6 +2576,9 @@
/obj/effect/landmark/blobstart,
/turf/open/floor/iron,
/area/station/commons/storage/primary)
+"Yd" = (
+/turf/open/floor/iron,
+/area/station/cargo/bitrunning/den)
"Ym" = (
/obj/structure/table,
/obj/item/storage/toolbox/electrical,
@@ -2623,6 +2621,12 @@
/obj/machinery/suit_storage_unit/ce,
/turf/open/floor/iron,
/area/station/engineering/atmos)
+"ZK" = (
+/obj/structure/table,
+/obj/item/storage/box/shipping,
+/obj/item/boulder_beacon,
+/turf/open/floor/iron,
+/area/station/commons/storage/primary)
"ZP" = (
/turf/open/floor/iron/dark,
/area/station/science/explab)
@@ -3200,12 +3204,12 @@ aa
aa
aa
aa
-Le
-Le
-Le
-Le
-Le
-Le
+Ue
+Ue
+Ue
+Ue
+Ue
+Ue
aa
aa
aa
@@ -3292,12 +3296,12 @@ aa
aa
aa
aa
-Le
-rS
-Nj
-pK
-Ba
-Le
+Ue
+rT
+Rp
+Yd
+TR
+Ue
aa
aa
aa
@@ -3384,12 +3388,12 @@ aa
aa
aa
aa
-Le
-rM
-pK
-Kf
-Ba
-Le
+Ue
+LS
+Yd
+hv
+TR
+Ue
aa
aa
aa
@@ -3476,12 +3480,12 @@ aa
aa
aa
aa
-Le
-lE
-Cz
-mV
-Lb
-Le
+Ue
+IF
+Aj
+vb
+SC
+Ue
aa
aa
aa
@@ -3568,12 +3572,12 @@ em
em
em
em
-Le
-Le
-Le
-QU
-ib
-Le
+Ue
+Ue
+Ue
+nI
+QY
+Ue
Tj
Tj
Tj
@@ -7611,7 +7615,7 @@ aa
ad
af
ak
-Wy
+Va
aG
aV
bg
@@ -7820,7 +7824,7 @@ dJ
dJ
dJ
dJ
-sH
+ZK
cS
fP
fO
@@ -8267,7 +8271,7 @@ is
cy
Ut
cm
-cK
+tz
by
dB
dx
diff --git a/code/__HELPERS/hallucinations.dm b/code/__HELPERS/hallucinations.dm
index 1eeab08d876..edd65ee926a 100644
--- a/code/__HELPERS/hallucinations.dm
+++ b/code/__HELPERS/hallucinations.dm
@@ -145,7 +145,7 @@ ADMIN_VERB(debug_hallucination_weighted_list_per_type, R_DEBUG, "Show Hallucinat
last_type_weight = this_weight
// Sort by weight descending, where weight is the values (not the keys). We assoc_to_keys later to get JUST the text
- all_weights = sortTim(all_weights, GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
+ sortTim(all_weights, GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
var/page_style = ""
var/page_contents = "[page_style]
[header][jointext(assoc_to_keys(all_weights), "")]
"
diff --git a/code/__HELPERS/sorts/InsertSort.dm b/code/__HELPERS/sorts/InsertSort.dm
deleted file mode 100644
index 2d5ca408ce3..00000000000
--- a/code/__HELPERS/sorts/InsertSort.dm
+++ /dev/null
@@ -1,19 +0,0 @@
-//simple insertion sort - generally faster than merge for runs of 7 or smaller
-/proc/sortInsert(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex=0)
- if(L && L.len >= 2)
- fromIndex = fromIndex % L.len
- toIndex = toIndex % (L.len+1)
- if(fromIndex <= 0)
- fromIndex += L.len
- if(toIndex <= 0)
- toIndex += L.len + 1
-
- var/datum/sort_instance/SI = GLOB.sortInstance
- if(!SI)
- SI = new
- SI.L = L
- SI.cmp = cmp
- SI.associative = associative
-
- SI.binarySort(fromIndex, toIndex, fromIndex)
- return L
diff --git a/code/__HELPERS/sorts/MergeSort.dm b/code/__HELPERS/sorts/MergeSort.dm
deleted file mode 100644
index 4692534edff..00000000000
--- a/code/__HELPERS/sorts/MergeSort.dm
+++ /dev/null
@@ -1,19 +0,0 @@
-//merge-sort - gernerally faster than insert sort, for runs of 7 or larger
-/proc/sortMerge(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex)
- if(L && L.len >= 2)
- fromIndex = fromIndex % L.len
- toIndex = toIndex % (L.len+1)
- if(fromIndex <= 0)
- fromIndex += L.len
- if(toIndex <= 0)
- toIndex += L.len + 1
-
- var/datum/sort_instance/SI = GLOB.sortInstance
- if(!SI)
- SI = new
- SI.L = L
- SI.cmp = cmp
- SI.associative = associative
-
- SI.mergeSort(fromIndex, toIndex)
- return L
diff --git a/code/__HELPERS/sorts/TimSort.dm b/code/__HELPERS/sorts/TimSort.dm
deleted file mode 100644
index 44f6d170df4..00000000000
--- a/code/__HELPERS/sorts/TimSort.dm
+++ /dev/null
@@ -1,20 +0,0 @@
-//TimSort interface
-/proc/sortTim(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex=0)
- if(L && L.len >= 2)
- fromIndex = fromIndex % L.len
- toIndex = toIndex % (L.len+1)
- if(fromIndex <= 0)
- fromIndex += L.len
- if(toIndex <= 0)
- toIndex += L.len + 1
-
- var/datum/sort_instance/SI = GLOB.sortInstance
- if(!SI)
- SI = new
-
- SI.L = L
- SI.cmp = cmp
- SI.associative = associative
-
- SI.timSort(fromIndex, toIndex)
- return L
diff --git a/code/__HELPERS/sorts/helpers.dm b/code/__HELPERS/sorts/helpers.dm
new file mode 100644
index 00000000000..7198286f29f
--- /dev/null
+++ b/code/__HELPERS/sorts/helpers.dm
@@ -0,0 +1,95 @@
+/// Sorts the list in place with timSort, default settings.
+#define SORT_TIM(to_sort, associative) if(length(to_sort) >= 2) { \
+ var/datum/sort_instance/sorter = GLOB.sortInstance; \
+ if (isnull(sorter)) { \
+ sorter = new; \
+ } \
+ sorter.L = to_sort; \
+ sorter.cmp = GLOBAL_PROC_REF(cmp_numeric_asc); \
+ sorter.associative = associative; \
+ sorter.timSort(1, 0); \
+}
+
+
+/// Helper for the sorting procs. Prevents some code duplication. Creates /datum/sort_instance/sorter
+#define CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex) \
+ if(length(to_sort) < 2) { \
+ return to_sort; \
+ } \
+ fromIndex = fromIndex % length(to_sort); \
+ toIndex = toIndex % (length(to_sort) + 1); \
+ if (fromIndex <= 0) { \
+ fromIndex += length(to_sort); \
+ } \
+ if (toIndex <= 0) { \
+ toIndex += length(to_sort) + 1; \
+ } \
+ var/datum/sort_instance/sorter = GLOB.sortInstance; \
+ if (isnull(sorter)) { \
+ sorter = new; \
+ } \
+ sorter.L = to_sort; \
+ sorter.cmp = cmp; \
+ sorter.associative = associative;
+
+
+/**
+ * ## Tim Sort
+ * Hybrid sorting algorithm derived from merge sort and insertion sort.
+ *
+ * **Sorts in place**.
+ * You might not need to get the return value.
+ *
+ * @see
+ * https://en.wikipedia.org/wiki/Timsort
+ *
+ * @param {list} to_sort - The list to sort.
+ *
+ * @param {proc} cmp - The comparison proc to use. Default: Numeric ascending.
+ *
+ * @param {boolean} associative - Whether the list is associative. Default: FALSE.
+ *
+ * @param {int} fromIndex - The index to start sorting from. Default: 1.
+ *
+ * @param {int} toIndex - The index to stop sorting at. Default: 0.
+ */
+/proc/sortTim(list/to_sort, cmp = GLOBAL_PROC_REF(cmp_numeric_asc), associative = FALSE, fromIndex = 1, toIndex = 0) as /list
+ CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex)
+
+ sorter.timSort(fromIndex, toIndex)
+
+ return to_sort
+
+
+/**
+ * ## Merge Sort
+ * Divide and conquer sorting algorithm.
+ *
+ * @see
+ * - https://en.wikipedia.org/wiki/Merge_sort
+ */
+/proc/sortMerge(list/to_sort, cmp = GLOBAL_PROC_REF(cmp_numeric_asc), associative = FALSE, fromIndex = 1, toIndex = 0) as /list
+ CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex)
+
+ sorter.mergeSort(fromIndex, toIndex)
+
+ return to_sort
+
+
+/**
+ * ## Insertion Sort
+ * Simple sorting algorithm that builds the final sorted list one item at a time.
+ *
+
+ * @see
+ * - https://en.wikipedia.org/wiki/Insertion_sort
+ */
+/proc/sortInsert(list/to_sort, cmp = GLOBAL_PROC_REF(cmp_numeric_asc), associative = FALSE, fromIndex = 1, toIndex = 0) as /list
+ CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex)
+
+ sorter.binarySort(fromIndex, toIndex)
+
+ return to_sort
+
+
+#undef CREATE_SORT_INSTANCE
diff --git a/code/__HELPERS/sorts/__main.dm b/code/__HELPERS/sorts/sort_instance.dm
similarity index 100%
rename from code/__HELPERS/sorts/__main.dm
rename to code/__HELPERS/sorts/sort_instance.dm
diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm
index eefbede3087..a3dcc26af54 100644
--- a/code/controllers/subsystem/dcs.dm
+++ b/code/controllers/subsystem/dcs.dm
@@ -84,7 +84,7 @@ PROCESSING_SUBSYSTEM_DEF(dcs)
fullid += REF(key)
if(named_arguments)
- named_arguments = sortTim(named_arguments, GLOBAL_PROC_REF(cmp_text_asc))
+ sortTim(named_arguments, GLOBAL_PROC_REF(cmp_text_asc))
fullid += named_arguments
return list2params(fullid)
diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm
index 51ecd59925a..1f315391a8f 100644
--- a/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm
+++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm
@@ -135,10 +135,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE)
/datum/dynamic_ruleset/roundstart/traitorbro/execute()
for (var/datum/mind/mind in assigned)
- var/datum/team/brother_team/team = new
- team.add_member(mind)
- team.forge_brother_objectives()
- mind.add_antag_datum(/datum/antagonist/brother, team)
+ new /datum/team/brother_team(mind)
GLOB.pre_setup_antags -= mind
return TRUE
diff --git a/code/controllers/subsystem/lua.dm b/code/controllers/subsystem/lua.dm
index b9ad7dc1644..1ab88a01746 100644
--- a/code/controllers/subsystem/lua.dm
+++ b/code/controllers/subsystem/lua.dm
@@ -53,7 +53,7 @@ SUBSYSTEM_DEF(lua)
world.SetConfig("env", "LUAU_PATH", jointext(lua_path, ";"))
/datum/controller/subsystem/lua/Shutdown()
- AUXTOOLS_SHUTDOWN(AUXLUA)
+ AUXTOOLS_FULL_SHUTDOWN(AUXLUA)
/datum/controller/subsystem/lua/proc/queue_resume(datum/lua_state/state, index, arguments)
if(!initialized)
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index e98f0941d64..83015d62f93 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -318,7 +318,7 @@
ASSERT(isatom(src) || istype(src, /image))
var/atom/atom_cast = src // filters only work with images or atoms.
atom_cast.filters = null
- filter_data = sortTim(filter_data, GLOBAL_PROC_REF(cmp_filter_data_priority), TRUE)
+ sortTim(filter_data, GLOBAL_PROC_REF(cmp_filter_data_priority), TRUE)
for(var/filter_raw in filter_data)
var/list/data = filter_data[filter_raw]
var/list/arguments = data.Copy()
diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm
index e10f4478cbf..df5a05c5f30 100644
--- a/code/datums/emotes.dm
+++ b/code/datums/emotes.dm
@@ -265,14 +265,13 @@
//SKYRAT EDIT CHANGE BEGIN - EMOTES - GLOBAL COOLDOWN
//if(user.emotes_used && user.emotes_used[src] + cooldown > world.time) - SKYRAT EDIT - ORIGINAL
if(user.nextsoundemote > world.time)
- var/datum/emote/default_emote = /datum/emote
+ var/datum/emote/default_emote = new /datum/emote
if(cooldown > initial(default_emote.cooldown)) // only worry about longer-than-normal emotes
to_chat(user, span_danger("You must wait another [DisplayTimeText(user.nextsoundemote - world.time)] before using that emote."))
return FALSE
//if(!user.emotes_used)
// user.emotes_used = list()
//user.emotes_used[src] = world.time - SKYRAT EDIT - ORIGINAL
- user.nextsoundemote = world.time + cooldown
//SKYRAT EDIT CHANGE END
return TRUE
diff --git a/code/datums/votes/map_vote.dm b/code/datums/votes/map_vote.dm
index 7b1794da93e..2942a40b833 100644
--- a/code/datums/votes/map_vote.dm
+++ b/code/datums/votes/map_vote.dm
@@ -21,15 +21,23 @@
/datum/vote/map_vote/create_vote()
. = ..()
- check_population(should_key_choices = FALSE)
- if(length(choices) == 1) // Only one choice, no need to vote. Let's just auto-rotate it to the only remaining map because it would just happen anyways.
- var/de_facto_winner = choices[1]
- var/datum/map_config/change_me_out = global.config.maplist[de_facto_winner]
- SSmapping.changemap(change_me_out)
- to_chat(world, span_boldannounce("The map vote has been skipped because there is only one map left to vote for. The map has been changed to [change_me_out.map_name]."))
- SSmapping.map_voted = TRUE // voted by not voting, very sad.
+ if(!.)
return FALSE
+ choices -= get_choices_invalid_for_population()
+ if(length(choices) == 1) // Only one choice, no need to vote. Let's just auto-rotate it to the only remaining map because it would just happen anyways.
+ var/datum/map_config/change_me_out = global.config.maplist[choices[1]]
+ finalize_vote(choices[1])// voted by not voting, very sad.
+ to_chat(world, span_boldannounce("The map vote has been skipped because there is only one map left to vote for. \
+ The map has been changed to [change_me_out.map_name]."))
+ return FALSE
+ if(length(choices) == 0)
+ to_chat(world, span_boldannounce("A map vote was called, but there are no maps to vote for! \
+ Players, complain to the admins. Admins, complain to the coders."))
+ return FALSE
+
+ return TRUE
+
/datum/vote/map_vote/toggle_votable()
CONFIG_SET(flag/allow_vote_map, !CONFIG_GET(flag/allow_vote_map))
@@ -42,38 +50,33 @@
return .
if(forced)
return VOTE_AVAILABLE
- var/number_of_choices = length(check_population())
- if(number_of_choices < 2)
- return "There [number_of_choices == 1 ? "is only one map" : "are no maps"] to choose from."
+ var/num_choices = length(default_choices - get_choices_invalid_for_population())
+ if(num_choices <= 1)
+ return "There [num_choices == 1 ? "is only one map" : "are no maps"] to choose from."
if(SSmapping.map_vote_rocked)
return VOTE_AVAILABLE
if(SSmapping.map_voted)
return "The next map has already been selected."
return VOTE_AVAILABLE
-/// Before we create a vote, remove all maps from our choices that are outside of our population range.
-/// Note that this can result in zero remaining choices for our vote, which is not ideal (but ultimately okay).
-/// Argument should_key_choices is TRUE, pass as FALSE in a context where choices are already keyed in a list.
-/datum/vote/map_vote/proc/check_population(should_key_choices = TRUE)
- if(should_key_choices)
- for(var/key in default_choices)
- choices[key] = 0
-
+/// Returns a list of all map options that are invalid for the current population.
+/datum/vote/map_vote/proc/get_choices_invalid_for_population()
var/filter_threshold = 0
if(SSticker.HasRoundStarted())
filter_threshold = get_active_player_count(alive_check = FALSE, afk_check = TRUE, human_check = FALSE)
else
filter_threshold = GLOB.clients.len
- for(var/map in choices)
+ var/list/invalid_choices = list()
+ for(var/map in default_choices)
var/datum/map_config/possible_config = config.maplist[map]
if(possible_config.config_min_users > 0 && filter_threshold < possible_config.config_min_users)
- choices -= map
+ invalid_choices += map
else if(possible_config.config_max_users > 0 && filter_threshold > possible_config.config_max_users)
- choices -= map
+ invalid_choices += map
- return choices
+ return invalid_choices
/datum/vote/map_vote/get_vote_result(list/non_voters)
// Even if we have default no vote off,
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index e56eb1e5101..20cdf351459 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -765,7 +765,7 @@ ADMIN_VERB(reestablish_tts_connection, R_DEBUG, "Re-establish Connection To TTS"
var/list/sorted = list()
for (var/source in per_source)
sorted += list(list("source" = source, "count" = per_source[source]))
- sorted = sortTim(sorted, GLOBAL_PROC_REF(cmp_timer_data))
+ sortTim(sorted, GLOBAL_PROC_REF(cmp_timer_data))
// Now that everything is sorted, compile them into an HTML output
var/output = ""
diff --git a/code/modules/admin/verbs/light_debug.dm b/code/modules/admin/verbs/light_debug.dm
index ae5b24ff380..eac81f6ed29 100644
--- a/code/modules/admin/verbs/light_debug.dm
+++ b/code/modules/admin/verbs/light_debug.dm
@@ -10,7 +10,7 @@
sum[source.source_atom.type] += 1
total += 1
- sum = sortTim(sum, /proc/cmp_numeric_asc, TRUE)
+ sortTim(sum, associative = TRUE)
var/text = ""
for(var/type in sum)
text += "[type] = [sum[type]]\n"
diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm
index 214825f4c73..e7123c9afab 100644
--- a/code/modules/antagonists/brother/brother.dm
+++ b/code/modules/antagonists/brother/brother.dm
@@ -168,13 +168,15 @@
member_name = "blood brother"
var/brothers_left = 2
-/datum/team/brother_team/New()
+/datum/team/brother_team/New(starting_members)
. = ..()
if (prob(10))
brothers_left += 1
/datum/team/brother_team/add_member(datum/mind/new_member)
. = ..()
+ if (!length(objectives))
+ forge_brother_objectives()
if (!new_member.has_antag_datum(/datum/antagonist/brother))
add_brother(new_member.current)
@@ -218,7 +220,7 @@
add_objective(new /datum/objective/convert_brother)
var/is_hijacker = prob(10)
- for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker))
+ for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (brothers_left > 2) - is_hijacker))
forge_single_objective()
if(is_hijacker)
if(!locate(/datum/objective/hijack) in objectives)
diff --git a/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm b/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm
index 51058f82ac0..0ac27c14c97 100644
--- a/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm
+++ b/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm
@@ -24,7 +24,7 @@
filtered_modules[AM.category][AM] = AM
for(var/category in filtered_modules)
- filtered_modules[category] = sortTim(filtered_modules[category], GLOBAL_PROC_REF(cmp_malfmodules_priority))
+ sortTim(filtered_modules[category], GLOBAL_PROC_REF(cmp_malfmodules_priority))
return filtered_modules
diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm
index 15a028b24d7..0fa80f55247 100644
--- a/code/modules/antagonists/pirate/pirate.dm
+++ b/code/modules/antagonists/pirate/pirate.dm
@@ -85,7 +85,7 @@
//Lists notable loot.
if(!cargo_hold || !cargo_hold.total_report)
return "Nothing"
- cargo_hold.total_report.total_value = sortTim(cargo_hold.total_report.total_value, cmp = GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
+ sortTim(cargo_hold.total_report.total_value, cmp = GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
var/count = 0
var/list/loot_texts = list()
for(var/datum/export/E in cargo_hold.total_report.total_value)
diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
index eaa1de48b58..16cad321853 100644
--- a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
+++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
@@ -428,7 +428,7 @@
/datum/export/pirate/ransom/sell_object(mob/living/carbon/human/sold_item, datum/export_report/report, dry_run = TRUE, apply_elastic = TRUE)
. = ..()
- if(. == EXPORT_NOT_SOLD)
+ if(. == EXPORT_NOT_SOLD || dry_run)
return
var/turf/picked_turf = pick(GLOB.holdingfacility)
sold_item.forceMove(picked_turf)
@@ -439,7 +439,7 @@
sold_item.flash_act()
sold_item.adjust_confusion(10 SECONDS)
sold_item.adjust_dizzy(10 SECONDS)
- addtimer(src, CALLBACK(src, PROC_REF(send_back_to_station), sold_item), COME_BACK_FROM_CAPTURE_TIME)
+ addtimer(CALLBACK(src, PROC_REF(send_back_to_station), sold_item), COME_BACK_FROM_CAPTURE_TIME)
to_chat(sold_item, span_hypnophrase("A million voices echo in your head... \"Yaarrr, thanks for the booty, landlubber. \
You will be ransomed back to your station, so it's only a matter of time before we ship you back..."))
diff --git a/code/modules/asset_cache/assets/uplink.dm b/code/modules/asset_cache/assets/uplink.dm
index e283b86c042..e85ee1b35b5 100644
--- a/code/modules/asset_cache/assets/uplink.dm
+++ b/code/modules/asset_cache/assets/uplink.dm
@@ -9,7 +9,7 @@
var/list/items = list()
for(var/datum/uplink_category/category as anything in subtypesof(/datum/uplink_category))
categories += category
- categories = sortTim(categories, GLOBAL_PROC_REF(cmp_uplink_category_desc))
+ sortTim(categories, GLOBAL_PROC_REF(cmp_uplink_category_desc))
var/list/new_categories = list()
for(var/datum/uplink_category/category as anything in categories)
diff --git a/code/modules/bitrunning/orders/bepis.dm b/code/modules/bitrunning/orders/bepis.dm
index 286e9817f3c..4b7253bdaf2 100644
--- a/code/modules/bitrunning/orders/bepis.dm
+++ b/code/modules/bitrunning/orders/bepis.dm
@@ -17,7 +17,3 @@
/datum/orderable_item/bepis/sprayoncan
item_path = /obj/item/toy/sprayoncan
cost_per_order = 750
-
-/datum/orderable_item/bepis/pristine
- item_path = /obj/item/disk/design_disk/bepis/remove_tech
- cost_per_order = 1000
diff --git a/code/modules/bitrunning/server/loot.dm b/code/modules/bitrunning/server/loot.dm
index cb4902abfe3..aa7b99d6e92 100644
--- a/code/modules/bitrunning/server/loot.dm
+++ b/code/modules/bitrunning/server/loot.dm
@@ -1,3 +1,9 @@
+#define GRADE_D "D"
+#define GRADE_C "C"
+#define GRADE_B "B"
+#define GRADE_A "A"
+#define GRADE_S "S"
+
/// Handles calculating rewards based on number of players, parts, threats, etc
/obj/machinery/quantum_server/proc/calculate_rewards()
var/rewards_base = 0.8
@@ -28,8 +34,11 @@
var/bonus = calculate_rewards()
+ var/time_difference = world.time - generated_domain.start_time
+ var/grade = grade_completion(time_difference)
+
var/obj/item/paper/certificate = new()
- certificate.add_raw_text(get_completion_certificate())
+ certificate.add_raw_text(get_completion_certificate(time_difference, grade))
certificate.name = "certificate of domain completion"
certificate.update_appearance()
@@ -37,6 +46,10 @@
reward_cache.manifest = certificate
reward_cache.update_appearance()
+ if(can_generate_tech_disk(grade))
+ new /obj/item/disk/design_disk/bepis/remove_tech(reward_cache)
+ generated_domain.disk_reward_spawned = TRUE
+
chosen_forge.start_to_spawn(reward_cache)
return TRUE
@@ -50,7 +63,7 @@
return TRUE
/// Returns the markdown text containing domain completion information
-/obj/machinery/quantum_server/proc/get_completion_certificate()
+/obj/machinery/quantum_server/proc/get_completion_certificate(time_difference, grade)
var/base_points = generated_domain.reward_points
if(domain_randomized)
base_points -= 1
@@ -59,11 +72,9 @@
var/domain_threats = length(spawned_threat_refs)
- var/time_difference = world.time - generated_domain.start_time
-
var/completion_time = "### Completion Time: [DisplayTimeText(time_difference)]\n"
- var/grade = "\n---\n\n# Rating: [grade_completion(time_difference)]"
+ var/completion_grade = "\n---\n\n# Rating: [grade]"
var/text = "# Certificate of Domain Completion\n\n---\n\n"
@@ -75,7 +86,7 @@
if(bonuses <= 1)
text += completion_time
- text += grade
+ text += completion_grade
return text
text += "### Bonuses\n"
@@ -94,10 +105,24 @@
text += "- **Components:** + [servo_rating]\n"
text += completion_time
- text += grade
+ text += completion_grade
return text
+/// Checks if the players should get a bepis reward
+/obj/machinery/quantum_server/proc/can_generate_tech_disk(grade)
+ if(generated_domain.disk_reward_spawned)
+ return FALSE
+
+ if(!LAZYLEN(SSresearch.techweb_nodes_experimental))
+ return FALSE
+
+ var/static/list/passing_grades = list()
+ if(!passing_grades.len)
+ passing_grades = list(GRADE_A,GRADE_S)
+
+ return generated_domain.difficulty >= BITRUNNER_DIFFICULTY_MEDIUM && (grade in passing_grades)
+
/// Grades the player's run based on several factors
/obj/machinery/quantum_server/proc/grade_completion(completion_time)
var/score = length(spawned_threat_refs) * 5
@@ -124,13 +149,18 @@
switch(score)
if(1 to 4)
- return "D"
+ return GRADE_D
if(5 to 7)
- return "C"
+ return GRADE_C
if(8 to 10)
- return "B"
+ return GRADE_B
if(11 to 13)
- return "A"
+ return GRADE_A
else
- return "S"
+ return GRADE_S
+#undef GRADE_D
+#undef GRADE_C
+#undef GRADE_B
+#undef GRADE_A
+#undef GRADE_S
diff --git a/code/modules/bitrunning/virtual_domain/virtual_domain.dm b/code/modules/bitrunning/virtual_domain/virtual_domain.dm
index b316bb97cae..21898daad72 100644
--- a/code/modules/bitrunning/virtual_domain/virtual_domain.dm
+++ b/code/modules/bitrunning/virtual_domain/virtual_domain.dm
@@ -44,6 +44,8 @@
var/start_time
/// This map is specifically for unit tests. Shouldn't display in game
var/test_only = FALSE
+ /// Has this domain been beaten with high enough score to spawn a tech disk?
+ var/disk_reward_spawned = FALSE
/// Sends a point to any loot signals on the map
/datum/lazy_template/virtual_domain/proc/add_points(points_to_add)
diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm
index b8e93f2815c..e36f9f84cac 100644
--- a/code/modules/cargo/packs/security.dm
+++ b/code/modules/cargo/packs/security.dm
@@ -169,6 +169,7 @@
/obj/item/clothing/mask/whistle,
/obj/item/conversion_kit,
)
+ crate_name = "traditional equipment crate"
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
/// Armory packs
diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm
index c1822ff0e51..e22109def8d 100644
--- a/code/modules/mob/emote.dm
+++ b/code/modules/mob/emote.dm
@@ -34,6 +34,7 @@
if(P.run_emote(src, param, m_type, intentional))
SEND_SIGNAL(src, COMSIG_MOB_EMOTE, P, act, m_type, message, intentional)
SEND_SIGNAL(src, COMSIG_MOB_EMOTED(P.key))
+ src.nextsoundemote = world.time + P.cooldown // SKYRAT EDIT - EMOTE COOLDOWNS
return TRUE
if(intentional && !silenced && !force_silence)
to_chat(src, span_notice("Unusable emote '[act]'. Say *help for a list."))
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index d7407c0eb4f..ff49ceda328 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -110,7 +110,7 @@
message_mime = "mumbles silently!"
emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE
-
+/* - SKYRAT EDIT REMOVAL: EMOTES
/datum/emote/living/carbon/human/scream
key = "scream"
key_third_person = "screams"
@@ -120,7 +120,7 @@
only_forced_audio = TRUE
vary = TRUE
-/* - SKYRAT EDIT REMOVAL: EMOTES
+
/datum/emote/carbon/human/scream/run_emote(mob/user, params, type_override, intentional = FALSE)
if(!intentional && HAS_TRAIT(user, TRAIT_ANALGESIA))
return
diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm
index f0bca6b0980..2789763e12c 100644
--- a/code/modules/mod/mod_types.dm
+++ b/code/modules/mod/mod_types.dm
@@ -596,6 +596,7 @@
/obj/item/mod/module/storage/bluespace,
/obj/item/mod/module/emp_shield/advanced,
/obj/item/mod/module/welding,
+ /obj/item/mod/module/rad_protection,
/obj/item/mod/module/stealth/ninja,
/obj/item/mod/module/quick_carry/advanced,
/obj/item/mod/module/magboot/advanced,
diff --git a/code/modules/modular_computers/file_system/programs/emojipedia.dm b/code/modules/modular_computers/file_system/programs/emojipedia.dm
index 6aa81b506d5..10be69cc349 100644
--- a/code/modules/modular_computers/file_system/programs/emojipedia.dm
+++ b/code/modules/modular_computers/file_system/programs/emojipedia.dm
@@ -14,7 +14,7 @@
/datum/computer_file/program/emojipedia/New()
. = ..()
// Sort the emoji list so it's easier to find things and we don't have to keep sorting on ui_data since the number of emojis can not change in-game.
- emoji_list = sortTim(emoji_list, GLOBAL_PROC_REF(cmp_text_asc))
+ sortTim(emoji_list, /proc/cmp_text_asc)
/datum/computer_file/program/emojipedia/ui_static_data(mob_user)
var/list/data = list()
diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm
index 026aacc0e7d..356dc429d76 100644
--- a/code/modules/pai/pai.dm
+++ b/code/modules/pai/pai.dm
@@ -119,6 +119,9 @@
"mouse" = TRUE,
"rabbit" = TRUE,
"repairbot" = TRUE,
+ "kitten" = TRUE,
+ "puppy" = TRUE,
+ "spider" = TRUE,
)
/// List of all available card overlays.
var/static/list/possible_overlays = list(
diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm
index fad8fcc74c3..92adbc7f818 100644
--- a/code/modules/research/stock_parts.dm
+++ b/code/modules/research/stock_parts.dm
@@ -207,7 +207,7 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
continue
part_list += component_part
//Sort the parts. This ensures that higher tier items are applied first.
- part_list = sortTim(part_list, GLOBAL_PROC_REF(cmp_rped_sort))
+ sortTim(part_list, GLOBAL_PROC_REF(cmp_rped_sort))
return part_list
/proc/cmp_rped_sort(obj/item/first_item, obj/item/second_item)
diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm
index 4dc1e7f85c9..46fbafe2d2f 100644
--- a/code/modules/unit_tests/unit_test.dm
+++ b/code/modules/unit_tests/unit_test.dm
@@ -356,7 +356,7 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests())
if(length(focused_tests))
tests_to_run = focused_tests
- tests_to_run = sortTim(tests_to_run, GLOBAL_PROC_REF(cmp_unit_test_priority))
+ sortTim(tests_to_run, GLOBAL_PROC_REF(cmp_unit_test_priority))
var/list/test_results = list()
diff --git a/html/changelogs/AutoChangeLog-pr-27572.yml b/html/changelogs/AutoChangeLog-pr-27572.yml
deleted file mode 100644
index 809d34999d6..00000000000
--- a/html/changelogs/AutoChangeLog-pr-27572.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SkyratBot"
-delete-after: True
-changes:
- - bugfix: "Stage 2 singularities should no longer escape containment"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-27574.yml b/html/changelogs/AutoChangeLog-pr-27574.yml
deleted file mode 100644
index ebd44714a49..00000000000
--- a/html/changelogs/AutoChangeLog-pr-27574.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Melbert"
-delete-after: True
-changes:
- - bugfix: "New machine god blessings now actually works probably"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-27575.yml b/html/changelogs/AutoChangeLog-pr-27575.yml
deleted file mode 100644
index eb03652dc14..00000000000
--- a/html/changelogs/AutoChangeLog-pr-27575.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Ryll/Shaps"
-delete-after: True
-changes:
- - bugfix: "Pacifists can no longer endlessly spam the backblast functionality of loaded rocket launchers that they cannot actually fire"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-27576.yml b/html/changelogs/AutoChangeLog-pr-27576.yml
deleted file mode 100644
index 02270043e27..00000000000
--- a/html/changelogs/AutoChangeLog-pr-27576.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-author: "SkyratBot"
-delete-after: True
-changes:
- - bugfix: "mobs in the same faction will no longer be at odds against one another"
- - bugfix: "mobs can now perform behaviors alongside searching for targets"
- - bugfix: "mobs will no longer be starting and stopping when chasing targets"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-27577.yml b/html/changelogs/AutoChangeLog-pr-27577.yml
deleted file mode 100644
index 4c9ebb81c47..00000000000
--- a/html/changelogs/AutoChangeLog-pr-27577.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SkyratBot"
-delete-after: True
-changes:
- - bugfix: "Candy corn is once again available to detective fedoras"
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-05.yml b/html/changelogs/archive/2024-05.yml
index f34acb64002..da87f63a7ba 100644
--- a/html/changelogs/archive/2024-05.yml
+++ b/html/changelogs/archive/2024-05.yml
@@ -106,3 +106,61 @@
- bugfix: Interlink Arrivals shuttles have tiny fans for air support!
nikothedude:
- bugfix: Jousting no longer bypasses pacifism
+2024-05-04:
+ Melbert:
+ - bugfix: New machine god blessings now actually works probably
+ Ryll/Shaps:
+ - bugfix: Pacifists can no longer endlessly spam the backblast functionality of
+ loaded rocket launchers that they cannot actually fire
+ SkyratBot:
+ - bugfix: mobs in the same faction will no longer be at odds against one another
+ - bugfix: mobs can now perform behaviors alongside searching for targets
+ - bugfix: mobs will no longer be starting and stopping when chasing targets
+ - bugfix: Candy corn is once again available to detective fedoras
+ - rscadd: Adds an Icebox-specific station trait that brightens outdoors areas on
+ the surface level.
+ - bugfix: Stage 2 singularities should no longer escape containment
+ - bugfix: Fire ant colonies created by burning regular ants will now contain fire
+ ants as their reagent
+ mogeoko:
+ - bugfix: Ventcrawling mobs can change Z-level using multiz-decks again.
+2024-05-05:
+ Majkl-J:
+ - bugfix: Fixed the scream emote being silent
+ - bugfix: Fixed cooldowns on emotes being incorrectly applied, indirectly fixing
+ the cry emote and a few others
+ Melbert:
+ - bugfix: Map vote should work better
+ SkyratBot:
+ - balance: Bitrunners can now earn Bepis disks, once per medium domain or above,
+ if they scored at least an A.
+ - rscdel: Bitrunners can not buy Bepis disks from their vendors.
+ - bugfix: Blood Brothers should spawn knowing what their objectives are.
+ - bugfix: Teams of 3 Blood Brothers will once more have an additional objective.
+ - bugfix: Fixed lua scripts breaking when turfs with registered signals get deleted.
+ - bugfix: If kidnapped and ransomed by pirates, you will now properly return to
+ the station automatically after 6 minutes.
+ - bugfix: You can no longer be kidnapped and held for ransom by cargo technicians
+ posing as pirates.
+ Useroth:
+ - bugfix: Fixes transfer votes
+ - refactor: Removes modular piece of code related to electrocution that is no longer
+ necessary.
+2024-05-06:
+ Erol509:
+ - bugfix: Fixed Armaments station tgui error, when trying to select item.
+ SkyratBot:
+ - bugfix: fixes traditional equipment crate name
+ - qol: Admin modsuit now has a radiation protect module
+ chestlet, Lutowski:
+ - rscadd: Three Security skirts & a jumpsuit were added to the Peacekeeper Outfitting
+ Station & loadout.
+ - rscadd: Security officers with jumpskirt pref now spawn with the new jumpskirt,
+ battle dress is moved to loadout.
+ - qol: Feline Traits now gives a cat tongue
+ - qol: Cat tongue now has special saymods
+2024-05-07:
+ SkyratBot:
+ - rscadd: '''puppy'' ''kitten'' and ''spider'' pai skins'
+ aKromatopzia:
+ - bugfix: moved raptor and digi cybernetics' categories
diff --git a/icons/mob/silicon/pai.dmi b/icons/mob/silicon/pai.dmi
index 2be986d411d..260b175f3ae 100644
Binary files a/icons/mob/silicon/pai.dmi and b/icons/mob/silicon/pai.dmi differ
diff --git a/lua/SS13_base.lua b/lua/SS13_base.lua
index f49908f0942..ea04c8c6503 100644
--- a/lua/SS13_base.lua
+++ b/lua/SS13_base.lua
@@ -100,7 +100,8 @@ function SS13.register_signal(datum, signal, func)
callback:call_proc("RegisterSignal", datum, signal, "Invoke")
local path = { "__SS13_signal_handlers", datumWeakRef, signal, callbackWeakRef, "func" }
callback.vars.arguments = { path }
- if not __SS13_signal_handlers[datumWeakRef]._cleanup then
+ -- Turfs don't remove their signals on deletion.
+ if not __SS13_signal_handlers[datumWeakRef]._cleanup and not SS13.istype(datum, "/turf") then
local cleanupCallback = SS13.new("/datum/callback", SS13.state, "call_function_return_first")
local cleanupPath = { "__SS13_signal_handlers", datumWeakRef, "_cleanup"}
cleanupCallback.vars.arguments = { cleanupPath }
@@ -134,6 +135,11 @@ function SS13.unregister_signal(datum, signal, callback)
local callbackWeakRef = dm.global_proc("WEAKREF", handler_callback)
if not SS13.istype(datum, "/datum/weakref") then
handler_callback:call_proc("UnregisterSignal", datum, signal)
+ else
+ local actualDatum = datum:call_proc("hard_resolve")
+ if SS13.is_valid(actualDatum) then
+ handler_callback:call_proc("UnregisterSignal", actualDatum, signal)
+ end
end
SS13.stop_tracking(handler_callback)
end
diff --git a/lua/handler_group.lua b/lua/handler_group.lua
index fff63ad18e4..0246d33c744 100644
--- a/lua/handler_group.lua
+++ b/lua/handler_group.lua
@@ -14,7 +14,7 @@ function HandlerGroup:register_signal(datum, signal, func)
if not callback then
return
end
- table.insert(self.registered, { datum = datum, signal = signal, callback = callback })
+ table.insert(self.registered, { datum = dm.global_proc("WEAKREF", datum), signal = signal, callback = callback })
end
-- Clears all the signals that have been registered on this HandlerGroup
diff --git a/modular_skyrat/master_files/code/datums/traits/neutral.dm b/modular_skyrat/master_files/code/datums/traits/neutral.dm
index 2e66d536685..06e62a94578 100644
--- a/modular_skyrat/master_files/code/datums/traits/neutral.dm
+++ b/modular_skyrat/master_files/code/datums/traits/neutral.dm
@@ -229,13 +229,20 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay())
/datum/quirk/feline_aspect
name = "Feline Traits"
- desc = "You happen to act like a feline, for whatever reason."
+ desc = "You happen to act like a feline, for whatever reason. This will replace most other tongue-based speech quirks."
gain_text = span_notice("Nya could go for some catnip right about now...")
lose_text = span_notice("You feel less attracted to lasers.")
medical_record_text = "Patient seems to possess behavior much like a feline."
mob_trait = TRAIT_FELINE
icon = FA_ICON_CAT
+/datum/quirk/feline_aspect/add_unique(client/client_source)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/obj/item/organ/internal/tongue/cat/new_tongue = new(get_turf(human_holder))
+
+ new_tongue.copy_traits_from(human_holder.get_organ_slot(ORGAN_SLOT_TONGUE))
+ new_tongue.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED)
+
/datum/quirk/item_quirk/canine
name = "Canidae Traits"
desc = "Bark. You seem to act like a canine for whatever reason. This will replace most other tongue-based speech quirks."
diff --git a/modular_skyrat/master_files/code/modules/clothing/clothing_variation_overrides/suit.dm b/modular_skyrat/master_files/code/modules/clothing/clothing_variation_overrides/suit.dm
index 26b6d64a6cc..f72389e4778 100644
--- a/modular_skyrat/master_files/code/modules/clothing/clothing_variation_overrides/suit.dm
+++ b/modular_skyrat/master_files/code/modules/clothing/clothing_variation_overrides/suit.dm
@@ -53,6 +53,18 @@
/obj/item/clothing/suit/jacket/curator
supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+/obj/item/clothing/suit/costume/wellworn_shirt
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ gets_cropped_on_taurs = FALSE
+
+/obj/item/clothing/suit/jacket/oversized
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ gets_cropped_on_taurs = FALSE
+
+/obj/item/clothing/suit/mothcoat/winter
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ gets_cropped_on_taurs = FALSE
+
//Chaplain Suits
/obj/item/clothing/suit/hooded/chaplain_hoodie
supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
diff --git a/modular_skyrat/master_files/code/modules/clothing/suits/labcoat.dm b/modular_skyrat/master_files/code/modules/clothing/suits/labcoat.dm
index b6ebd71dbd0..785236aeef9 100644
--- a/modular_skyrat/master_files/code/modules/clothing/suits/labcoat.dm
+++ b/modular_skyrat/master_files/code/modules/clothing/suits/labcoat.dm
@@ -12,6 +12,7 @@
name = "research directors labcoat"
desc = "A Nanotrasen standard labcoat for certified Research Directors. It has an extra plastic-latex lining on the outside for more protection from chemical and viral hazards."
icon_state = "labcoat_rd"
+ gets_cropped_on_taurs = FALSE
body_parts_covered = CHEST|ARMS|LEGS
armor_type = /datum/armor/skyrat_rd
@@ -21,6 +22,18 @@
fire = 80
acid = 70
+/obj/item/clothing/suit/toggle/labcoat/skyrat/regular
+ name = "researcher's labcoat"
+ desc = "A Nanotrasen standard labcoat for researchers in the scientific field."
+ icon_state = "labcoat_regular"
+ gets_cropped_on_taurs = FALSE
+
+/obj/item/clothing/suit/toggle/labcoat/skyrat/pharmacist
+ name = "pharmacist's labcoat"
+ desc = "A standard labcoat for chemistry which protects the wearer from acid spills."
+ icon_state = "labcoat_pharm"
+ gets_cropped_on_taurs = FALSE
+
/obj/item/clothing/suit/toggle/labcoat/skyrat/highvis
name = "high vis labcoat"
desc = "A high visibility vest for emergency responders, intended to draw attention away from the blood."
diff --git a/modular_skyrat/master_files/code/modules/clothing/under/jobs/security.dm b/modular_skyrat/master_files/code/modules/clothing/under/jobs/security.dm
index 51af7f0675e..4a9b047d963 100644
--- a/modular_skyrat/master_files/code/modules/clothing/under/jobs/security.dm
+++ b/modular_skyrat/master_files/code/modules/clothing/under/jobs/security.dm
@@ -1,5 +1,5 @@
/obj/item/clothing/under/rank/security
- worn_icon_digi = 'modular_skyrat/master_files/icons/mob/clothing/under/security_digi.dmi' // Anything that was in the security.dmi, should be in the security_digi.dmi
+ worn_icon_digi = 'modular_skyrat/master_files/icons/mob/clothing/under/security_digi.dmi'
/obj/item/clothing/under/rank/security/skyrat
icon = 'modular_skyrat/master_files/icons/obj/clothing/under/security.dmi'
@@ -32,6 +32,15 @@
armor_type = /datum/armor/clothing_under/redsec_syndicate
has_sensor = NO_SENSORS
+/obj/item/clothing/under/rank/security/peacekeeper/skirt
+ name = "security battle dress"
+ desc = "An asymmetrical, unisex uniform with the legs replaced by a utility skirt."
+ worn_icon_state = "security_skirt"
+ icon_state = "security_skirt"
+ uses_advanced_reskins = FALSE
+ unique_reskin = null
+ alt_covers_chest = FALSE
+
/obj/item/clothing/under/rank/security/peacekeeper/trousers
name = "security trousers"
desc = "Some Peacekeeper-blue combat trousers. Probably should pair it with a vest for safety."
@@ -40,7 +49,99 @@
icon_state = "workpants_blue"
body_parts_covered = GROIN|LEGS
can_adjust = FALSE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
female_sprite_flags = FEMALE_UNIFORM_NO_BREASTS
+ uses_advanced_reskins = TRUE
+ unique_reskin = list(
+ "Blue Variant" = list(
+ RESKIN_ICON_STATE = "workpants_blue",
+ RESKIN_WORN_ICON_STATE = "workpants_blue"
+ ),
+ "White Variant" = list(
+ RESKIN_ICON_STATE = "workpants_white",
+ RESKIN_WORN_ICON_STATE = "workpants_white"
+ ),
+ )
+
+/obj/item/clothing/under/rank/security/peacekeeper/trousers/shorts
+ name = "security shorts"
+ desc = "Some Peacekeeper-blue combat shorts. Definitely should pair it with a vest for safety."
+ icon_state = "workshorts_blue"
+ uses_advanced_reskins = TRUE
+ unique_reskin = list(
+ "Blue Variant, Short" = list(
+ RESKIN_ICON_STATE = "workshorts_blue",
+ RESKIN_WORN_ICON_STATE = "workshorts_blue"
+ ),
+ "Blue Variant, Short Short" = list(
+ RESKIN_ICON_STATE = "workshorts_blue_short",
+ RESKIN_WORN_ICON_STATE = "workshorts_blue_short"
+ ),
+ "White Variant, Short" = list(
+ RESKIN_ICON_STATE = "workshorts_white",
+ RESKIN_WORN_ICON_STATE = "workshorts_white"
+ ),
+ "White Variant, Short Short" = list(
+ RESKIN_ICON_STATE = "workshorts_white_short",
+ RESKIN_WORN_ICON_STATE = "workshorts_white_short"
+ ),
+ )
+
+/obj/item/clothing/under/rank/security/peacekeeper/jumpsuit
+ name = "security jumpsuit"
+ desc = "Turtleneck sweater commonly worn by Peacekeepers, attached with pants."
+ icon_state = "jumpsuit_blue"
+ can_adjust = TRUE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
+ female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+
+/obj/item/clothing/under/rank/security/officer/skirt
+ name = "security jumpskirt"
+ desc = "Turtleneck sweater commonly worn by Peacekeepers, attached with a skirt."
+ icon = 'modular_skyrat/master_files/icons/obj/clothing/under/security.dmi'
+ worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/under/security.dmi'
+ icon_state = "jumpskirt_blue"
+ female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ gets_cropped_on_taurs = FALSE
+ uses_advanced_reskins = TRUE
+ unique_reskin = list(
+ "Blue Variant" = list(
+ RESKIN_ICON_STATE = "jumpskirt_blue",
+ RESKIN_WORN_ICON_STATE = "jumpskirt_blue"
+ ),
+ "Black Variant" = list(
+ RESKIN_ICON_STATE = "jumpskirt_black",
+ RESKIN_WORN_ICON_STATE = "jumpskirt_black"
+ ),
+ )
+
+/obj/item/clothing/under/rank/security/peacekeeper/shortskirt
+ name = "security shortskirt"
+ desc = "Plainshirted uniform commonly worn by Peacekeepers, attached with a skirt."
+ icon_state = "shortskirt_blue"
+ icon = 'modular_skyrat/master_files/icons/obj/clothing/under/security.dmi'
+ worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/under/security.dmi'
+ female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ gets_cropped_on_taurs = FALSE
+ uses_advanced_reskins = TRUE
+ unique_reskin = list(
+ "Blue Variant" = list(
+ RESKIN_ICON_STATE = "shortskirt_blue",
+ RESKIN_WORN_ICON_STATE = "shortskirt_blue"
+ ),
+ "Black Variant" = list(
+ RESKIN_ICON_STATE = "shortskirt_black",
+ RESKIN_WORN_ICON_STATE = "shortskirt_black"
+ ),
+ )
+
+/obj/item/clothing/under/rank/security/peacekeeper/miniskirt
+ name = "security miniskirt"
+ desc = "This miniskirt was originally featured in a gag calendar, but entered official use once they realized its potential for arid climates."
+ icon_state = "miniskirt"
+ female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ gets_cropped_on_taurs = FALSE
+ can_adjust = TRUE
/*
* HEAD OF SECURITY
diff --git a/modular_skyrat/master_files/code/modules/power/powernet.dm b/modular_skyrat/master_files/code/modules/power/powernet.dm
deleted file mode 100644
index 189a4aa0449..00000000000
--- a/modular_skyrat/master_files/code/modules/power/powernet.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/powernet/get_electrocute_damage()
- if(avail >= 1000)
- var/damage = clamp(20 + round(avail/25000), 20, 195) + rand(-5,5)
- return damage * HUMAN_HEALTH_MODIFIER
- else
- return 0
diff --git a/modular_skyrat/master_files/icons/mob/clothing/suits/labcoat.dmi b/modular_skyrat/master_files/icons/mob/clothing/suits/labcoat.dmi
index ecf0f2de15c..ac9fe47496a 100644
Binary files a/modular_skyrat/master_files/icons/mob/clothing/suits/labcoat.dmi and b/modular_skyrat/master_files/icons/mob/clothing/suits/labcoat.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/security.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/security.dmi
index 0aeace1f82e..9b766d06864 100644
Binary files a/modular_skyrat/master_files/icons/mob/clothing/under/security.dmi and b/modular_skyrat/master_files/icons/mob/clothing/under/security.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/sprite_accessory/taur.dmi b/modular_skyrat/master_files/icons/mob/sprite_accessory/taur.dmi
index 66064739c0c..6b943d10005 100644
Binary files a/modular_skyrat/master_files/icons/mob/sprite_accessory/taur.dmi and b/modular_skyrat/master_files/icons/mob/sprite_accessory/taur.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/sprite_accessory/wings.dmi b/modular_skyrat/master_files/icons/mob/sprite_accessory/wings.dmi
index 16070100737..c8777b833ff 100644
Binary files a/modular_skyrat/master_files/icons/mob/sprite_accessory/wings.dmi and b/modular_skyrat/master_files/icons/mob/sprite_accessory/wings.dmi differ
diff --git a/modular_skyrat/master_files/icons/obj/clothing/suits/labcoat.dmi b/modular_skyrat/master_files/icons/obj/clothing/suits/labcoat.dmi
index c63b241a799..abe9f39089b 100644
Binary files a/modular_skyrat/master_files/icons/obj/clothing/suits/labcoat.dmi and b/modular_skyrat/master_files/icons/obj/clothing/suits/labcoat.dmi differ
diff --git a/modular_skyrat/master_files/icons/obj/clothing/under/security.dmi b/modular_skyrat/master_files/icons/obj/clothing/under/security.dmi
index ac3891c27c1..129201a0373 100644
Binary files a/modular_skyrat/master_files/icons/obj/clothing/under/security.dmi and b/modular_skyrat/master_files/icons/obj/clothing/under/security.dmi differ
diff --git a/modular_skyrat/modules/autotransfer/code/transfer_vote.dm b/modular_skyrat/modules/autotransfer/code/transfer_vote.dm
index 709c6369dc4..97703fe4805 100644
--- a/modular_skyrat/modules/autotransfer/code/transfer_vote.dm
+++ b/modular_skyrat/modules/autotransfer/code/transfer_vote.dm
@@ -7,34 +7,26 @@
CHOICE_TRANSFER,
CHOICE_CONTINUE,
)
+ default_message = "Vote to initiate a crew transfer."
-/datum/vote/transfer_vote/toggle_votable(mob/toggler)
- if(!toggler)
- CRASH("[type] wasn't passed a \"toggler\" mob to toggle_votable.")
- if(!check_rights_for(toggler.client, R_ADMIN))
- return FALSE
-
-
+/datum/vote/transfer_vote/toggle_votable()
CONFIG_SET(flag/allow_vote_transfer, !CONFIG_GET(flag/allow_vote_transfer))
- return TRUE
/datum/vote/transfer_vote/is_config_enabled()
return CONFIG_GET(flag/autotransfer) && CONFIG_GET(flag/allow_vote_transfer)
-/datum/vote/transfer_vote/can_be_initiated(mob/by_who, forced)
+/datum/vote/transfer_vote/can_be_initiated(forced)
. = ..()
- if(!.)
- return FALSE
+ if(. != VOTE_AVAILABLE)
+ return .
if(forced)
- return TRUE
+ return VOTE_AVAILABLE
if(!CONFIG_GET(flag/autotransfer) || !CONFIG_GET(flag/allow_vote_transfer))
- if(by_who)
- to_chat(by_who, span_warning("Transfer voting is disabled."))
- return FALSE
+ return "Transfer voting is disabled."
- return TRUE
+ return VOTE_AVAILABLE
/datum/vote/transfer_vote/finalize_vote(winning_option)
if(winning_option == CHOICE_CONTINUE)
diff --git a/modular_skyrat/modules/customization/modules/clothing/suits/hoodies.dm b/modular_skyrat/modules/customization/modules/clothing/suits/hoodies.dm
index ec41c2c3eb3..fa2015a62cd 100644
--- a/modular_skyrat/modules/customization/modules/clothing/suits/hoodies.dm
+++ b/modular_skyrat/modules/customization/modules/clothing/suits/hoodies.dm
@@ -13,6 +13,7 @@
greyscale_colors = "#FFFFFF"
flags_1 = IS_PLAYER_COLORABLE_1
supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ gets_cropped_on_taurs = FALSE
min_cold_protection_temperature = T0C - 20 //Not as good as the base jacket
/obj/item/clothing/suit/toggle/jacket/hoodie/trim
diff --git a/modular_skyrat/modules/customization/modules/clothing/suits/misc.dm b/modular_skyrat/modules/customization/modules/clothing/suits/misc.dm
index ad488df4e86..e3705379e81 100644
--- a/modular_skyrat/modules/customization/modules/clothing/suits/misc.dm
+++ b/modular_skyrat/modules/customization/modules/clothing/suits/misc.dm
@@ -15,6 +15,7 @@
worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/suit.dmi'
icon_state = "dutchjacket"
supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ gets_cropped_on_taurs = FALSE
/obj/item/clothing/suit/toggle/trackjacket
@@ -295,6 +296,7 @@
worn_icon_teshari = 'modular_skyrat/modules/GAGS/icons/suit/suit_teshari.dmi'
icon_state = "apron"
supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ gets_cropped_on_taurs = FALSE
greyscale_colors = "#ffffff"
greyscale_config = /datum/greyscale_config/apron
greyscale_config_worn = /datum/greyscale_config/apron/worn
@@ -337,6 +339,7 @@
greyscale_colors = "#867361"
flags_1 = IS_PLAYER_COLORABLE_1
supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ gets_cropped_on_taurs = FALSE
/obj/item/clothing/suit/heart_sweater
name = "heart sweater"
@@ -347,3 +350,4 @@
greyscale_colors = "#867361#8f3a3a"
flags_1 = IS_PLAYER_COLORABLE_1
supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ gets_cropped_on_taurs = FALSE
diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm
index c52af4de049..7944dc08604 100644
--- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm
+++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm
@@ -154,3 +154,20 @@
icon_state = "slime"
taur_mode = STYLE_TAUR_SNAKE
color_src = USE_ONE_COLOR
+
+/datum/sprite_accessory/taur/biglegs
+ name = "Big Legs"
+ icon_state = "biglegs"
+ taur_mode = STYLE_TAUR_PAW
+
+/datum/sprite_accessory/taur/biglegs/stanced
+ name = "Big Legs, Stanced"
+ icon_state = "biglegs_stanced"
+
+/datum/sprite_accessory/taur/biglegs/bird
+ name = "Big Legs, Bird"
+ icon_state = "biglegs_bird"
+
+/datum/sprite_accessory/taur/biglegs/stanced/bird
+ name = "Big Legs, Stanced Bird"
+ icon_state = "biglegs_bird_stanced"
diff --git a/modular_skyrat/modules/digitigrade_cybernetics/code/mechfabricator_designs.dm b/modular_skyrat/modules/digitigrade_cybernetics/code/mechfabricator_designs.dm
index bb4529c8597..59734073e97 100644
--- a/modular_skyrat/modules/digitigrade_cybernetics/code/mechfabricator_designs.dm
+++ b/modular_skyrat/modules/digitigrade_cybernetics/code/mechfabricator_designs.dm
@@ -1,4 +1,5 @@
#define RND_SUBCATEGORY_MECHFAB_CYBORG_DIGI "/Digitigrade"
+#define RND_SUBCATEGORY_CYBERNETICS_ADVANCED_DIGI "/Advanced Digitigrade"
/datum/design/digitigrade_cyber_r_leg
name = "Digitigrade Cybernetic Right Leg"
@@ -34,7 +35,7 @@
)
construction_time = 20 SECONDS
category = list(
- RND_CATEGORY_MECHFAB_CYBORG + RND_SUBCATEGORY_MECHFAB_CYBORG_DIGI
+ RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ADVANCED_DIGI
)
/datum/design/digitigrade_adv_l_leg
@@ -49,5 +50,5 @@
)
construction_time = 20 SECONDS
category = list(
- RND_CATEGORY_MECHFAB_CYBORG + RND_SUBCATEGORY_MECHFAB_CYBORG_DIGI
+ RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ADVANCED_DIGI
)
diff --git a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm
index 2e27eb71d4d..4dfa8441656 100644
--- a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm
+++ b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm
@@ -571,13 +571,24 @@
unique_reskin = null // prevents you from losing the unique sprite
/obj/item/clothing/under/rank/security/officer/skirt
- name = "security battle dress"
- desc = "An asymmetrical, unisex uniform with the legs replaced by a utility skirt."
- worn_icon_state = "security_skirt"
- icon_state = "security_skirt"
- uses_advanced_reskins = FALSE
- unique_reskin = null
- alt_covers_chest = FALSE
+ name = "security jumpskirt"
+ desc = "Turtleneck sweater commonly worn by Peacekeepers, attached with a skirt."
+ icon = 'modular_skyrat/master_files/icons/obj/clothing/under/security.dmi'
+ worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/under/security.dmi'
+ icon_state = "jumpskirt_blue"
+ female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ gets_cropped_on_taurs = FALSE
+ uses_advanced_reskins = TRUE
+ unique_reskin = list(
+ "Blue Variant" = list(
+ RESKIN_ICON_STATE = "jumpskirt_blue",
+ RESKIN_WORN_ICON_STATE = "jumpskirt_blue"
+ ),
+ "Black Variant" = list(
+ RESKIN_ICON_STATE = "jumpskirt_black",
+ RESKIN_WORN_ICON_STATE = "jumpskirt_black"
+ ),
+ )
//Warden
/obj/item/clothing/under/rank/security/warden
diff --git a/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_suit.dm b/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_suit.dm
index 4891323c05c..7444d9618ac 100644
--- a/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_suit.dm
+++ b/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_suit.dm
@@ -120,6 +120,14 @@ GLOBAL_LIST_INIT(loadout_exosuits, generate_loadout_items(/datum/loadout_item/su
name = "Medical Labcoat"
item_path = /obj/item/clothing/suit/toggle/labcoat/medical
+/datum/loadout_item/suit/labcoat_regular
+ name = "Researcher's Labcoat"
+ item_path = /obj/item/clothing/suit/toggle/labcoat/skyrat/regular
+
+/datum/loadout_item/suit/labcoat_pharmacist
+ name = "Pharmacist's Labcoat"
+ item_path = /obj/item/clothing/suit/toggle/labcoat/skyrat/pharmacist
+
/*
* PONCHOS
*/
diff --git a/modular_skyrat/modules/loadouts/loadout_items/under/loadout_datum_under.dm b/modular_skyrat/modules/loadouts/loadout_items/under/loadout_datum_under.dm
index 6de8953c5af..508966f1aed 100644
--- a/modular_skyrat/modules/loadouts/loadout_items/under/loadout_datum_under.dm
+++ b/modular_skyrat/modules/loadouts/loadout_items/under/loadout_datum_under.dm
@@ -109,11 +109,41 @@ GLOBAL_LIST_INIT(loadout_miscunders, generate_loadout_items(/datum/loadout_item/
name = "Grey Officer's Naval Jumpsuit (Trousers)"
item_path = /obj/item/clothing/under/rank/captain/skyrat/imperial/generic/pants
+/datum/loadout_item/under/jumpsuit/security_skirt
+ name = "Security Battledress"
+ item_path = /obj/item/clothing/under/rank/security/peacekeeper/skirt
+ restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY)
+
/datum/loadout_item/under/jumpsuit/security_trousers
name = "Security Trousers"
item_path = /obj/item/clothing/under/rank/security/peacekeeper/trousers
restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY)
+/datum/loadout_item/under/jumpsuit/security_shorts
+ name = "Security Shorts"
+ item_path = /obj/item/clothing/under/rank/security/peacekeeper/trousers/shorts
+ restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY)
+
+/datum/loadout_item/under/jumpsuit/security_jumpskirt
+ name = "Security Jumpskirt"
+ item_path = /obj/item/clothing/under/rank/security/officer/skirt
+ restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY)
+
+/datum/loadout_item/under/jumpsuit/security_shortskirt
+ name = "Security Shortskirt"
+ item_path = /obj/item/clothing/under/rank/security/peacekeeper/shortskirt
+ restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY)
+
+/datum/loadout_item/under/jumpsuit/security_miniskirt
+ name = "Security Miniskirt"
+ item_path = /obj/item/clothing/under/rank/security/peacekeeper/miniskirt
+ restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY)
+
+/datum/loadout_item/under/jumpsuit/security_jumpsuit
+ name = "Security Jumpsuit"
+ item_path = /obj/item/clothing/under/rank/security/peacekeeper/jumpsuit
+ restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY)
+
/datum/loadout_item/under/jumpsuit/security_peacekeeper
name = "Security Peacekeeper Uniform"
item_path = /obj/item/clothing/under/rank/security/peacekeeper
diff --git a/modular_skyrat/modules/modular_vending/code/wardrobes.dm b/modular_skyrat/modules/modular_vending/code/wardrobes.dm
index 5eee806a55f..4e553ed712a 100644
--- a/modular_skyrat/modules/modular_vending/code/wardrobes.dm
+++ b/modular_skyrat/modules/modular_vending/code/wardrobes.dm
@@ -126,6 +126,9 @@
skyrat_products = list(
/obj/item/clothing/under/rank/medical/chemist/skyrat/formal = 2,
/obj/item/clothing/under/rank/medical/chemist/skyrat/formal/skirt = 2,
+ /obj/item/clothing/under/rank/medical/chemist/skyrat/formal = 2,
+ /obj/item/clothing/under/rank/medical/chemist/skyrat/formal/skirt = 2,
+ /obj/item/clothing/suit/toggle/labcoat/skyrat/pharmacist = 2,
/obj/item/clothing/head/beret/medical/chemist = 2,
/obj/item/storage/backpack/messenger/chem = 2,
)
diff --git a/modular_skyrat/modules/organs/code/tongue.dm b/modular_skyrat/modules/organs/code/tongue.dm
index 7b4cdef0744..3746d67b5d2 100644
--- a/modular_skyrat/modules/organs/code/tongue.dm
+++ b/modular_skyrat/modules/organs/code/tongue.dm
@@ -27,6 +27,20 @@
speaker.verb_sing = initial(verb_sing)
speaker.verb_yell = initial(verb_yell)
+/obj/item/organ/internal/tongue/cat/Insert(mob/living/carbon/signer, special = FALSE, movement_flags = DELETE_IF_REPLACED)
+ . = ..()
+ signer.verb_ask = "mrrps"
+ signer.verb_exclaim = "mrrowls"
+ signer.verb_whisper = "purrs"
+ signer.verb_yell = "yowls"
+
+/obj/item/organ/internal/tongue/cat/Remove(mob/living/carbon/speaker, special = FALSE)
+ . = ..()
+ speaker.verb_ask = initial(verb_ask)
+ speaker.verb_exclaim = initial(verb_exclaim)
+ speaker.verb_whisper = initial(verb_whisper)
+ speaker.verb_yell = initial(verb_yell)
+
/obj/item/organ/internal/tongue/avian
name = "avian tongue"
desc = "A short and stubby tongue that craves seeds."
diff --git a/modular_skyrat/modules/sec_haul/code/misc/vending.dm b/modular_skyrat/modules/sec_haul/code/misc/vending.dm
index 6096f085460..fdea431454a 100644
--- a/modular_skyrat/modules/sec_haul/code/misc/vending.dm
+++ b/modular_skyrat/modules/sec_haul/code/misc/vending.dm
@@ -52,6 +52,10 @@
/obj/item/storage/backpack/duffelbag/sec = 5,
/obj/item/clothing/under/rank/security/officer = 10,
/obj/item/clothing/under/rank/security/officer/skirt = 10,
+ /obj/item/clothing/under/rank/security/peacekeeper/skirt = 10,
+ /obj/item/clothing/under/rank/security/peacekeeper/shortskirt = 10,
+ /obj/item/clothing/under/rank/security/peacekeeper/miniskirt = 10,
+ /obj/item/clothing/under/rank/security/peacekeeper/jumpsuit = 10,
/obj/item/clothing/under/rank/security/peacekeeper = 10,
/obj/item/clothing/under/rank/security/skyrat/utility = 3,
/obj/item/clothing/shoes/jackboots/sec = 10,
diff --git a/modular_skyrat/modules/tesh_augments/code/mechfabricator_designs.dm b/modular_skyrat/modules/tesh_augments/code/mechfabricator_designs.dm
index 50fdb0865ba..cdb8c7e632d 100644
--- a/modular_skyrat/modules/tesh_augments/code/mechfabricator_designs.dm
+++ b/modular_skyrat/modules/tesh_augments/code/mechfabricator_designs.dm
@@ -1,6 +1,7 @@
//adding teshari silicon stuff to the mechfabricator
#define RND_SUBCATEGORY_MECHFAB_CYBORG_RAPTORAL "/Raptoral"
+#define RND_SUBCATEGORY_CYBERNETICS_ADVANCED_RAPTORAL "/Advanced Raptoral Limbs"
/datum/design/teshari_cyber_chest
name = "Raptoral Cybernetic Torso"
@@ -82,7 +83,7 @@
)
construction_time = 8 SECONDS
category = list(
- RND_CATEGORY_MECHFAB_CYBORG + RND_SUBCATEGORY_MECHFAB_CYBORG_RAPTORAL,
+ RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ADVANCED_RAPTORAL,
)
/datum/design/teshari_advanced_r_arm
@@ -97,7 +98,7 @@
)
construction_time = 8 SECONDS
category = list(
- RND_CATEGORY_MECHFAB_CYBORG + RND_SUBCATEGORY_MECHFAB_CYBORG_RAPTORAL,
+ RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ADVANCED_RAPTORAL,
)
/datum/design/teshari_advanced_l_leg
@@ -112,7 +113,7 @@
)
construction_time = 8 SECONDS
category = list(
- RND_CATEGORY_MECHFAB_CYBORG + RND_SUBCATEGORY_MECHFAB_CYBORG_RAPTORAL,
+ RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ADVANCED_RAPTORAL,
)
/datum/design/teshari_advanced_r_leg
@@ -127,5 +128,5 @@
)
construction_time = 8 SECONDS
category = list(
- RND_CATEGORY_MECHFAB_CYBORG + RND_SUBCATEGORY_MECHFAB_CYBORG_RAPTORAL,
+ RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ADVANCED_RAPTORAL,
)
diff --git a/tgstation.dme b/tgstation.dme
index 38f4813a69c..34a6ac16c70 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -594,10 +594,8 @@
#include "code\__HELPERS\paths\jps.dm"
#include "code\__HELPERS\paths\path.dm"
#include "code\__HELPERS\paths\sssp.dm"
-#include "code\__HELPERS\sorts\__main.dm"
-#include "code\__HELPERS\sorts\InsertSort.dm"
-#include "code\__HELPERS\sorts\MergeSort.dm"
-#include "code\__HELPERS\sorts\TimSort.dm"
+#include "code\__HELPERS\sorts\helpers.dm"
+#include "code\__HELPERS\sorts\sort_instance.dm"
#include "code\__HELPERS\~skyrat_helpers\is_helpers.dm"
#include "code\__HELPERS\~skyrat_helpers\level_traits.dm"
#include "code\__HELPERS\~skyrat_helpers\logging.dm"
@@ -6616,7 +6614,6 @@
#include "modular_skyrat\master_files\code\modules\paperwork\stamps.dm"
#include "modular_skyrat\master_files\code\modules\power\cable.dm"
#include "modular_skyrat\master_files\code\modules\power\circulator.dm"
-#include "modular_skyrat\master_files\code\modules\power\powernet.dm"
#include "modular_skyrat\master_files\code\modules\power\thermoelectric_generator.dm"
#include "modular_skyrat\master_files\code\modules\power\lighting\light_mapping_helpers.dm"
#include "modular_skyrat\master_files\code\modules\power\singularity\containment_field.dm"
diff --git a/tgui/packages/tgui/interfaces/ArmamentStation.jsx b/tgui/packages/tgui/interfaces/ArmamentStation.jsx
index 08087f49de2..c223cd4eb5c 100644
--- a/tgui/packages/tgui/interfaces/ArmamentStation.jsx
+++ b/tgui/packages/tgui/interfaces/ArmamentStation.jsx
@@ -95,8 +95,8 @@ export const ArmamentStation = (props) => {
{item.name}
@@ -119,15 +119,15 @@ export const ArmamentStation = (props) => {
item.ref === weapon && (
-
- src=
- {`data:image/jpeg;base64,${item.icon}`}
- height={'100%'} width={'100%'} style=
- {{
- 'vertical-align': 'middle',
- 'horizontal-align': 'middle',
+
+ />
{item.description}