diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index d5a03597fb..4f29fc3ca7 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -2982,14 +2982,14 @@
/turf/open/floor/plating,
/area/security/main)
"afS" = (
-/obj/machinery/door/airlock/security/glass{
- name = "Brig EVA Storage";
- req_access_txt = "3"
- },
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/obj/machinery/door/firedoor,
+/obj/machinery/door/airlock/security{
+ name = "Brig EVA Storage";
+ req_access_txt = "1"
+ },
/turf/open/floor/plasteel/dark,
/area/security/brig)
"afT" = (
@@ -37546,33 +37546,21 @@
/area/maintenance/aft)
"bKK" = (
/obj/effect/decal/cleanable/cobweb/cobweb2,
-/obj/structure/cable{
- icon_state = "0-8"
- },
-/obj/machinery/power/apc{
- areastring = "/area/medical/medbay/central";
- dir = 4;
- name = "Medbay APC";
- pixel_x = 24
- },
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plating,
/area/maintenance/aft)
"bKL" = (
-/obj/structure/disposalpipe/segment{
- dir = 10
+/obj/machinery/power/apc{
+ areastring = "/area/medical/medbay/central";
+ dir = 1;
+ name = "Medbay Central APC";
+ pixel_y = 24
},
/obj/structure/cable{
- icon_state = "2-8"
+ icon_state = "0-2"
},
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 10
- },
-/turf/open/floor/plating,
-/area/maintenance/aft)
+/turf/open/floor/plasteel/white,
+/area/medical/medbay/central)
"bKM" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
@@ -46397,7 +46385,6 @@
/obj/effect/turf_decal/bot{
dir = 1
},
-/obj/structure/reagent_dispensers/fueltank,
/obj/structure/extinguisher_cabinet{
pixel_x = -5;
pixel_y = 30
@@ -46405,6 +46392,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel,
/area/engine/engineering)
"cig" = (
@@ -46564,7 +46552,6 @@
icon_state = "1-2"
},
/obj/structure/disposalpipe/segment,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel,
/area/maintenance/disposal/incinerator)
"ciF" = (
@@ -53276,27 +53263,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/maintenance/department/medical/morgue)
-"cTL" = (
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/structure/cable{
- icon_state = "2-4"
- },
-/turf/open/floor/plasteel/dark,
-/area/medical/morgue)
-"cTM" = (
-/obj/machinery/power/apc{
- areastring = "/area/maintenance/department/medical/morgue";
- dir = 4;
- name = "Morgue Maintenance APC";
- pixel_x = 26
- },
-/obj/structure/cable{
- icon_state = "0-8"
- },
-/turf/open/floor/plasteel/dark,
-/area/medical/morgue)
"cTO" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -55927,7 +55893,6 @@
"juy" = (
/obj/structure/mopbucket,
/obj/item/mop,
-/obj/item/reagent_containers/spray/cleaner,
/turf/open/floor/plating,
/area/maintenance/port/fore)
"juG" = (
@@ -98231,9 +98196,9 @@ cCQ
cCS
chg
cCS
-bLK
-bLK
-bLK
+bMK
+bMK
+bMK
gXs
aaa
aaa
@@ -98745,9 +98710,9 @@ aaf
bMK
chg
bMK
-bLK
-bLK
-bLK
+bMK
+bMK
+bMK
aaf
aoV
aoV
@@ -99477,8 +99442,8 @@ bfK
bfK
bfK
bof
-bhh
-bsx
+bKL
+brf
btV
bvh
bwH
@@ -99749,7 +99714,7 @@ bDR
bDR
bIn
bJC
-bKL
+bUZ
bLT
bLT
bLT
@@ -102043,7 +102008,7 @@ bfL
bhp
biB
biB
-cTL
+biB
bkU
bmX
bpE
@@ -102300,7 +102265,7 @@ bfL
bhq
bhm
bkb
-cTM
+bhm
bla
bmZ
bpH
diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm
index be0c53aab4..a4d34264ae 100644
--- a/_maps/map_files/CogStation/CogStation.dmm
+++ b/_maps/map_files/CogStation/CogStation.dmm
@@ -21880,7 +21880,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 4
},
-/obj/structure/reagent_dispensers/fueltank,
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel,
/area/engine/secure_construction)
"aVY" = (
@@ -70916,8 +70916,9 @@
/area/science/mixing)
"guK" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/structure/lattice,
/turf/open/space/basic,
-/area/space)
+/area/space/nearstation)
"gDY" = (
/obj/machinery/light,
/obj/machinery/atmospherics/pipe/simple/cyan/visible,
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index cb2aac912e..512f09856b 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -49404,7 +49404,7 @@
},
/obj/machinery/door/airlock/security/glass{
name = "Security E.V.A. Storage";
- req_access_txt = "3"
+ req_access_txt = "1"
},
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -81587,12 +81587,12 @@
/turf/open/floor/plasteel,
/area/engine/storage)
"cHt" = (
-/obj/structure/reagent_dispensers/fueltank,
/obj/effect/decal/cleanable/dirt,
/obj/machinery/status_display/ai{
pixel_y = -32
},
/obj/effect/turf_decal/bot,
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel,
/area/engine/storage)
"cHu" = (
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index 61b6930ce8..6db685b216 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -14492,7 +14492,6 @@
/turf/open/floor/plating,
/area/maintenance/starboard)
"aym" = (
-/obj/structure/reagent_dispensers/fueltank,
/obj/effect/turf_decal/delivery,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -14503,6 +14502,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel/dark,
/area/engine/engineering)
"ayn" = (
@@ -85505,8 +85505,8 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/cobweb/cobweb2,
/obj/machinery/atmospherics/components/binary/pump/on{
- name = "Space Loop Out";
- dir = 8
+ dir = 8;
+ name = "Space Loop Out"
},
/turf/open/floor/plating{
icon_state = "panelscorched"
diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm
index a219a333f1..71f3ed6b1a 100644
--- a/_maps/map_files/LambdaStation/lambda.dmm
+++ b/_maps/map_files/LambdaStation/lambda.dmm
@@ -53981,8 +53981,8 @@
pixel_y = -26
},
/obj/structure/cable,
-/obj/structure/reagent_dispensers/fueltank,
/obj/effect/turf_decal/bot,
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel,
/area/engine/storage_shared)
"cvh" = (
@@ -67078,12 +67078,12 @@
/area/engine/atmos)
"kgv" = (
/obj/structure/railing{
- icon_state = "railing";
- dir = 4
+ dir = 4;
+ icon_state = "railing"
},
/obj/structure/railing{
- icon_state = "railing";
- dir = 8
+ dir = 8;
+ icon_state = "railing"
},
/turf/open/floor/plasteel/stairs/old,
/area/maintenance/department/medical)
@@ -71237,12 +71237,12 @@
"tcW" = (
/obj/structure/stairs/west,
/obj/structure/railing{
- icon_state = "railing";
- dir = 4
+ dir = 4;
+ icon_state = "railing"
},
/obj/structure/railing{
- icon_state = "railing";
- dir = 8
+ dir = 8;
+ icon_state = "railing"
},
/turf/open/floor/plating,
/area/maintenance/department/medical)
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index ec97ff1335..2778215d9a 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -4548,7 +4548,7 @@
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/security/glass{
name = "Security E.V.A. Storage";
- req_access_txt = "3"
+ req_access_txt = "1"
},
/obj/structure/cable/yellow{
icon_state = "4-8"
@@ -15223,7 +15223,6 @@
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
"aCN" = (
-/obj/structure/reagent_dispensers/fueltank,
/obj/item/radio/intercom{
name = "Station Intercom (General)";
pixel_x = -30
@@ -15231,6 +15230,7 @@
/obj/effect/turf_decal/bot{
dir = 1
},
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel{
dir = 1
},
@@ -48921,7 +48921,7 @@
/turf/open/floor/plating,
/area/maintenance/starboard)
"bTi" = (
-/obj/machinery/vending/wardrobe/atmos_wardrobe,
+/obj/machinery/portable_atmospherics/canister,
/turf/open/floor/plasteel/dark,
/area/engine/atmos)
"bTk" = (
@@ -82905,8 +82905,8 @@
/area/medical/morgue)
"tID" = (
/obj/machinery/atmospherics/components/binary/pump/on{
- name = "Space Loop Out";
- dir = 4
+ dir = 4;
+ name = "Space Loop Out"
},
/turf/open/floor/plasteel/white,
/area/science/circuit)
@@ -83329,8 +83329,8 @@
/area/maintenance/port/aft)
"xHA" = (
/obj/machinery/atmospherics/components/binary/pump/on{
- name = "Space Loop In";
- dir = 8
+ dir = 8;
+ name = "Space Loop In"
},
/turf/open/floor/plasteel/white,
/area/science/circuit)
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index 5f746aa666..b5f845c4a1 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -24502,10 +24502,6 @@
/obj/effect/turf_decal/loading_area{
dir = 1
},
-/obj/effect/turf_decal/stripes/corner,
-/obj/effect/turf_decal/stripes/corner{
- dir = 1
- },
/obj/effect/turf_decal/tile/yellow{
dir = 1
},
@@ -25146,13 +25142,13 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"aNg" = (
-/obj/structure/reagent_dispensers/fueltank,
/obj/structure/sign/warning/nosmoking{
pixel_y = -32
},
/obj/effect/turf_decal/stripes/line{
dir = 5
},
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel,
/area/engine/engineering)
"aNh" = (
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 56cdb6eba0..b55e323ab5 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -46837,7 +46837,7 @@
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
-/obj/structure/reagent_dispensers/fueltank,
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel,
/area/engine/engineering)
"cdL" = (
@@ -54460,8 +54460,8 @@
/area/maintenance/department/security/brig)
"gjv" = (
/obj/machinery/atmospherics/components/binary/pump/on{
- name = "Space Loop In";
- dir = 1
+ dir = 1;
+ name = "Space Loop In"
},
/turf/open/floor/plating,
/area/maintenance/department/science)
diff --git a/_maps/map_files/Snaxi/Snaxi.dmm b/_maps/map_files/Snaxi/Snaxi.dmm
index 8290eb2ee9..bd38e2602e 100644
--- a/_maps/map_files/Snaxi/Snaxi.dmm
+++ b/_maps/map_files/Snaxi/Snaxi.dmm
@@ -14393,7 +14393,6 @@
/obj/machinery/light{
dir = 1
},
-/obj/structure/reagent_dispensers/fueltank,
/obj/machinery/camera{
c_tag = "Engineering Access"
},
@@ -14401,6 +14400,7 @@
name = "Station Intercom (General)";
pixel_y = 20
},
+/obj/structure/reagent_dispensers/fueltank/high,
/turf/open/floor/plasteel/dark/corner{
dir = 1
},
diff --git a/code/__HELPERS/shell.dm b/code/__HELPERS/shell.dm
index 3438f38b85..303036b341 100644
--- a/code/__HELPERS/shell.dm
+++ b/code/__HELPERS/shell.dm
@@ -13,6 +13,7 @@
var/err_file = ""
var/static/list/interpreters = list("[MS_WINDOWS]" = "cmd /c", "[UNIX]" = "sh -c")
var/interpreter = interpreters["[world.system_type]"]
+ log_subsystem("SHELL", "Executing command [command]")
if(interpreter)
for(var/seo_id in shelleo_ids)
if(!shelleo_ids[seo_id])
@@ -36,6 +37,7 @@
else
CRASH("Operating System: [world.system_type] not supported") // If you encounter this error, you are encouraged to update this proc with support for the new operating system
. = list(errorcode, stdout, stderr)
+ log_subsystem("SHELL", "Finished execution: [errorcode], [stdout], [stderr]")
#undef SHELLEO_NAME
#undef SHELLEO_ERR
#undef SHELLEO_OUT
diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm
index e8d9362dc3..9b292a219d 100644
--- a/code/controllers/subsystem/input.dm
+++ b/code/controllers/subsystem/input.dm
@@ -98,6 +98,7 @@ SUBSYSTEM_DEF(input)
var/client/C = clients[i]
C.keyLoop()
+#define NONSENSICAL_VERB "NONSENSICAL_VERB_THAT_DOES_NOTHING"
/// *sigh
/client/verb/NONSENSICAL_VERB_THAT_DOES_NOTHING()
set name = "NONSENSICAL_VERB_THAT_DOES_NOTHING"
diff --git a/code/datums/components/storage/concrete/rped.dm b/code/datums/components/storage/concrete/rped.dm
index d919828e8e..8014cf17c2 100644
--- a/code/datums/components/storage/concrete/rped.dm
+++ b/code/datums/components/storage/concrete/rped.dm
@@ -16,6 +16,32 @@
to_chat(M, "[parent] only accepts machine parts!")
return FALSE
+/datum/component/storage/concrete/rped/quick_empty(mob/M)
+ var/atom/A = parent
+ if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated())
+ return
+ if(check_locked(null, M, TRUE))
+ return FALSE
+ A.add_fingerprint(M)
+ var/list/things = contents()
+ var/lowest_rating = INFINITY
+ for(var/obj/item/B in things)
+ if(B.get_part_rating() < lowest_rating)
+ lowest_rating = B.get_part_rating()
+ for(var/obj/item/B in things)
+ if(B.get_part_rating() > lowest_rating)
+ things.Remove(B)
+ if(lowest_rating == INFINITY)
+ to_chat(M, "There's no parts to dump out from [parent].")
+ return
+ to_chat(M, "You start dumping out tier/cell rating [lowest_rating] parts from [parent].")
+ var/turf/T = get_turf(A)
+ var/datum/progressbar/progress = new(M, length(things), T)
+ while (do_after(M, 10, TRUE, T, FALSE, CALLBACK(src, .proc/mass_remove_from_storage, T, things, progress)))
+ stoplag(1)
+ qdel(progress)
+ A.do_squish(0.8, 1.2)
+
/datum/component/storage/concrete/bluespace/rped
collection_mode = COLLECT_EVERYTHING
allow_quick_gather = TRUE
@@ -33,5 +59,29 @@
to_chat(M, "[parent] only accepts machine parts!")
return FALSE
-/datum/component/storage/concrete/cyborg/rped
- max_items = 150
+
+/datum/component/storage/concrete/bluespace/rped/quick_empty(mob/M)
+ var/atom/A = parent
+ if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated())
+ return
+ if(check_locked(null, M, TRUE))
+ return FALSE
+ A.add_fingerprint(M)
+ var/list/things = contents()
+ var/lowest_rating = INFINITY
+ for(var/obj/item/B in things)
+ if(B.get_part_rating() < lowest_rating)
+ lowest_rating = B.get_part_rating()
+ for(var/obj/item/B in things)
+ if(B.get_part_rating() > lowest_rating)
+ things.Remove(B)
+ if(lowest_rating == INFINITY)
+ to_chat(M, "There's no parts to dump out from [parent].")
+ return
+ to_chat(M, "You start dumping out tier/cell rating [lowest_rating] parts from [parent].")
+ var/turf/T = get_turf(A)
+ var/datum/progressbar/progress = new(M, length(things), T)
+ while (do_after(M, 10, TRUE, T, FALSE, CALLBACK(src, .proc/mass_remove_from_storage, T, things, progress)))
+ stoplag(1)
+ qdel(progress)
+ A.do_squish(0.8, 1.2)
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index d5f53b2f1c..b0e801137d 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -16,7 +16,7 @@
return
. = ..()
- if(AM.movement_type & FLYING)
+ if(AM.movement_type & FLYING || iseffect(AM))
return
triggermine(AM)
diff --git a/code/game/objects/items/devices/polycircuit.dm b/code/game/objects/items/devices/polycircuit.dm
index 0308f19b5f..17e364c4f3 100644
--- a/code/game/objects/items/devices/polycircuit.dm
+++ b/code/game/objects/items/devices/polycircuit.dm
@@ -18,8 +18,8 @@
else
if(zero_amount())
return
- chosen_circuit = input("What type of circuit would you like to remove?", "Choose a Circuit Type", chosen_circuit) in list("airlock","firelock","fire alarm","air alarm","APC")
- if(zero_amount())
+ chosen_circuit = input("What type of circuit would you like to remove?", "Choose a Circuit Type", chosen_circuit) as null|anything in list("airlock","firelock","fire alarm","air alarm","APC")
+ if(zero_amount() || !chosen_circuit || !in_range(src,user))
return
switch(chosen_circuit)
if("airlock")
diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm
index 172b14eba4..91ede4f09e 100644
--- a/code/modules/integrated_electronics/core/helpers.dm
+++ b/code/modules/integrated_electronics/core/helpers.dm
@@ -32,7 +32,10 @@
/obj/item/integrated_circuit/proc/get_pin_data(pin_type, pin_number)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
- return pin.get_data()
+ var/data = pin.get_data()
+ if(istext(data))
+ data = sanitize_text(data)
+ return data
/obj/item/integrated_circuit/proc/get_pin_data_as_type(pin_type, pin_number, as_type)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
diff --git a/code/modules/integrated_electronics/core/saved_circuits.dm b/code/modules/integrated_electronics/core/saved_circuits.dm
index 3bbf05ea25..d857e068fd 100644
--- a/code/modules/integrated_electronics/core/saved_circuits.dm
+++ b/code/modules/integrated_electronics/core/saved_circuits.dm
@@ -91,7 +91,7 @@
/obj/item/integrated_circuit/proc/load(list/component_params)
// Load name
if(component_params["name"])
- displayed_name = component_params["name"]
+ displayed_name = html_encode(component_params["name"])
// Load input values
if(component_params["inputs"])
@@ -104,7 +104,7 @@
var/datum/integrated_io/pin = inputs[index]
// The pins themselves validate the data.
- pin.write_data_to_pin(input_value)
+ pin.write_data_to_pin(istext(input_value)? html_encode(input_value) : input_value)
// TODO: support for special input types, such as internal refs and maybe typepaths
if(!isnull(component_params["special"]))
@@ -152,19 +152,17 @@
/obj/item/electronic_assembly/proc/load(list/assembly_params)
// Load modified name, if any.
if(assembly_params["name"])
- name = assembly_params["name"]
+ name = html_encode(assembly_params["name"])
// Load modified description, if any.
if(assembly_params["desc"])
- desc = assembly_params["desc"]
+ desc = html_encode(assembly_params["desc"])
if(assembly_params["detail_color"])
detail_color = assembly_params["detail_color"]
update_icon()
-
-
// Attempts to save an assembly into a save file format.
// Returns null if assembly is not complete enough to be saved.
/datum/controller/subsystem/processing/circuit/proc/save_electronic_assembly(obj/item/electronic_assembly/assembly)
diff --git a/code/modules/keybindings/keybind/communication.dm b/code/modules/keybindings/keybind/communication.dm
index eacf8ac505..3a754ceddf 100644
--- a/code/modules/keybindings/keybind/communication.dm
+++ b/code/modules/keybindings/keybind/communication.dm
@@ -3,6 +3,7 @@
/datum/keybinding/client/communication/say
hotkey_keys = list("CtrlT")
+ classic_keys = list("Unbound")
name = "Say"
full_name = "IC Say"
clientside = "say"
@@ -15,6 +16,7 @@
/datum/keybinding/client/communication/me
hotkey_keys = list("CtrlM")
+ classic_keys = list("Unbound")
name = "Me"
full_name = "Me (emote)"
clientside = "me"
@@ -22,7 +24,6 @@
//indicators
/datum/keybinding/client/communication/say_with_indicator
hotkey_keys = list("T")
- classic_keys = list()
name = "say_with_indicator"
full_name = "Say with Typing Indicator"
@@ -33,7 +34,6 @@
/datum/keybinding/client/communication/me_with_indicator
hotkey_keys = list("M")
- classic_keys = list()
name = "me_with_indicator"
full_name = "Me (emote) with Typing Indicator"
@@ -44,28 +44,24 @@
/datum/keybinding/client/communication/subtle
hotkey_keys = list("5")
- classic_keys = list()
name = "Subtle"
full_name = "Subtle Emote"
clientside = "subtle"
/datum/keybinding/client/communication/subtler
hotkey_keys = list("6")
- classic_keys = list()
name = "Subtler"
full_name = "Subtler Anti-Ghost Emote"
clientside = "subtler-anti-ghost"
/datum/keybinding/client/communication/whisper
hotkey_keys = list("Y")
- classic_keys = list()
name = "Whisper"
full_name = "Whisper"
clientside = "whisper"
/datum/keybinding/client/communication/looc
hotkey_keys = list("L")
- classic_keys = list()
name = "LOOC"
full_name = "Local Out of Character chat"
clientside = "looc"
diff --git a/code/modules/keybindings/setup.dm b/code/modules/keybindings/setup.dm
index 797dbe34e5..81c59d481e 100644
--- a/code/modules/keybindings/setup.dm
+++ b/code/modules/keybindings/setup.dm
@@ -22,12 +22,15 @@
full_macro_assert()
// removes all the existing macros
-/client/proc/erase_all_macros()
+/client/proc/erase_all_macros(datum/preferences/prefs_override = prefs)
var/erase_output = ""
var/list/set_text = list()
- for(var/macroset in SSinput.all_macrosets)
- set_text += "[macroset].*"
- set_text = set_text.Join(";")
+ if(!prefs_override)
+ for(var/macroset in SSinput.all_macrosets)
+ set_text += "[macroset].*"
+ set_text = set_text.Join(";")
+ else
+ set_text = prefs_override.hotkeys? "[SKIN_MACROSET_HOTKEYS].*" : "[SKIN_MACROSET_CLASSIC_INPUT].*;[SKIN_MACROSET_CLASSIC_HOTKEYS].*"
var/list/macro_set = params2list(winget(src, "[set_text]", "command"))
for(var/k in 1 to length(macro_set))
var/list/split_name = splittext(macro_set[k], ".")
@@ -44,13 +47,6 @@
var/command = macroset[key]
winset(src, "[name]-[REF(key)]", "parent=[name];name=[key];command=[command]")
-/client/proc/set_macros(datum/preferences/prefs_override = prefs)
- keys_held.Cut()
-
- apply_macro_set(SKIN_MACROSET_HOTKEYS, SSinput.macroset_hotkey)
- apply_macro_set(SKIN_MACROSET_CLASSIC_HOTKEYS, SSinput.macroset_classic_hotkey)
- apply_macro_set(SKIN_MACROSET_CLASSIC_INPUT, SSinput.macroset_classic_input)
-
/client/proc/set_hotkeys_preference(datum/preferences/prefs_override = prefs)
if(prefs_override.hotkeys)
winset(src, null, "map.focus=true input.background-color=[COLOR_INPUT_DISABLED] mainwindow.macro=[SKIN_MACROSET_HOTKEYS]")
@@ -64,27 +60,97 @@
/client/proc/full_macro_assert(datum/preferences/prefs_override = prefs)
INVOKE_ASYNC(src, .proc/do_full_macro_assert, prefs_override) // winget sleeps.
+// TODO: OVERHAUL ALL OF THIS AGAIN. While this works this is flatout horrid with the "use list but also don't use lists" crap. I hate my life.
/client/proc/do_full_macro_assert(datum/preferences/prefs_override = prefs)
- erase_all_macros()
- set_macros(prefs_override)
- update_special_keybinds(prefs_override)
+ // First, wipe
+ erase_all_macros(prefs_override)
+ keys_held.Cut()
+ // First, collect sets. Make sure to COPY, as we are modifying these!
+ var/list/macrosets = prefs_override.hotkeys? list(
+ SKIN_MACROSET_HOTKEYS = SSinput.macroset_hotkey.Copy()
+ ) : list(
+ SKIN_MACROSET_CLASSIC_INPUT = SSinput.macroset_classic_input.Copy(),
+ SKIN_MACROSET_CLASSIC_HOTKEYS = SSinput.macroset_classic_hotkey.Copy()
+ )
+ // Collect special clientside keybinds
+ var/list/clientside = update_special_keybinds(prefs_override)
+ // ANTI COLLISION SYSTEM:
+ // If hotkey, do "standard" anti collision permutation
+ // We fully permutate alt/ctrl/shift with the key and then subtract the key's actual binding.
+ // Then, we set all the permutations BUT the actual binding to nonsensical things to force BYOND to not
+ // be "greedy" with key matching, aka matching Shift+T for T when Shift+T isn't EXPLICITLY defined.
+ // This is extremely ugly, but the alternative is arguably worse (manually binding every key instead of using ANY)
+ if(prefs_override.hotkeys)
+ for(var/keybind in clientside)
+ var/command = clientside[keybind]
+ var/alt = findtext(keybind, "Alt")
+ if(alt)
+ keybind = copytext(keybind, 1, alt) + copytext(keybind, alt + 3, 0)
+ var/ctrl = findtext(keybind, "Ctrl")
+ if(ctrl)
+ keybind = copytext(keybind, 1, ctrl) + copytext(keybind, ctrl + 4, 0)
+ var/shift = findtext(keybind, "Shift")
+ if(shift)
+ keybind = copytext(keybind, 1, shift) + copytext(keybind, shift + 5, 0)
+ var/actual = "[alt? "Alt+" : ""][ctrl? "Ctrl+" : ""][shift? "Shift+" : ""][keybind]"
+ var/list/overriding = keybind_modifier_permutation(keybind, alt, ctrl, shift, TRUE)
+ overriding -= actual
+ for(var/macroset in macrosets)
+ var/list/the_set = macrosets[macroset]
+ the_set[actual] = command
+ for(var/i in overriding)
+ the_set[i] = NONSENSICAL_VERB
+ else
+ // For classic mode, we just directly set things because BYOND is so jank why do we even bother?
+ // What we want is to force Ctrl on for all keybinds without Ctrl or Alt set, to preserve old behavior
+ for(var/keybind in clientside)
+ var/command = clientside[keybind]
+ var/alt = findtext(keybind, "Alt")
+ if(alt)
+ keybind = copytext(keybind, 1, alt) + copytext(keybind, alt + 3, 0)
+ var/ctrl = findtext(keybind, "Ctrl")
+ if(ctrl)
+ keybind = copytext(keybind, 1, ctrl) + copytext(keybind, ctrl + 4, 0)
+ var/shift = findtext(keybind, "Shift")
+ if(shift)
+ keybind = copytext(keybind, 1, shift) + copytext(keybind, shift + 5, 0)
+ var/actual
+ if(!alt && !ctrl)
+ actual = "Ctrl+[keybind]"
+ else
+ actual = "[alt? "Alt+" : ""][ctrl? "Ctrl+" : ""][shift? "Shift+" : ""][keybind]"
+ macrosets[SKIN_MACROSET_CLASSIC_HOTKEYS]["[alt? "Alt+" : ""][ctrl? "Ctrl+" : ""][shift? "Shift+" : ""][keybind]"] = command
+ macrosets[SKIN_MACROSET_CLASSIC_INPUT][actual] = command
+ for(var/macroset in macrosets)
+ var/list/the_set = macrosets[macroset]
+ the_set[actual] = command
+
+ // Lastly, set the actual macros.
+ for(var/macroset in macrosets)
+ apply_macro_set(macroset, macrosets[macroset])
+ // Finally, set hotkeys.
set_hotkeys_preference(prefs_override)
-/client/proc/do_special_keybind(key, command, datum/preferences/prefs_override = prefs)
- var/alt = findtext(key, "Alt")
- if(alt)
- key = copytext(key, 1, alt) + copytext(key, alt + 3, 0)
- var/ctrl = findtext(key, "Ctrl")
- if(ctrl)
- key = copytext(key, 1, ctrl) + copytext(key, ctrl + 4, 0)
- var/shift = findtext(key, "Shift")
- if(shift)
- key = copytext(key, 1, shift) + copytext(key, shift + 5, 0)
- if(!alt && !ctrl && !shift && !prefs_override.hotkeys)
- return /// DO NOT.
- key = "[alt? "Alt+":""][ctrl? "Ctrl+":""][shift? "Shift+":""][key]"
- for(var/macroset in SSinput.all_macrosets)
- winset(src, "[macroset]-[REF(key)]", "parent=[macroset];name=[key];command=[command]")
+/proc/keybind_modifier_permutation(key, alt = FALSE, ctrl = FALSE, shift = FALSE, self = TRUE)
+ var/list/permutations = list()
+ if(!shift)
+ permutations += "Shift"
+ if(!ctrl)
+ permutations += "Ctrl"
+ if(!alt)
+ permutations += "Alt"
+ // ALT + CTRL + SHIFT
+ . = list()
+ do_keybind_modifier_permutations(key, permutations, .)
+ if(self)
+ . += key
+
+/proc/do_keybind_modifier_permutations(key, list/permutations = list(), list/out = list())
+ . = out
+ for(var/mod in permutations.Copy())
+ permutations -= mod
+ . += "[mod]+[key]"
+ do_keybind_modifier_permutations("[mod]+[key]", permutations.Copy(), .)
/**
* Updates the keybinds for special keys
@@ -94,12 +160,15 @@
* At the time of writing this, communication(OOC, Say, IC) require macros
* Arguments:
* * direct_prefs - the preference we're going to get keybinds from
+ *
+ * Returns list of special keybind in key = Mod1Mod2Mod3Key format, NOT Mod1+Mod2+Mod3+Key format.
*/
/client/proc/update_special_keybinds(datum/preferences/direct_prefs)
var/datum/preferences/D = direct_prefs || prefs
if(!D?.key_bindings)
return
movement_keys = list()
+ . = list()
for(var/key in D.key_bindings)
for(var/kb_name in D.key_bindings[key])
switch(kb_name)
@@ -115,4 +184,4 @@
var/datum/keybinding/KB = GLOB.keybindings_by_name[kb_name]
if(!KB.clientside)
continue
- do_special_keybind(key, KB.clientside, D)
+ .[key] = KB.clientside
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm b/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm
index 3c2c850e3c..f58788d9af 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm
@@ -20,16 +20,20 @@
ckeys_allowed = list("poojawa")
extra = TRUE
extra_color_src = MUTCOLORS3
+ matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/sabresune
name = "Sabresune"
icon_state = "sabresune"
ckeys_allowed = list("poojawa")
+ matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/sabresune
name = "Sabresune"
icon_state = "sabresune"
ckeys_allowed = list("poojawa")
+ color_src = MATRIXED
+ matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/mam_body_markings/sabresune
name = "Sabresune"
diff --git a/html/changelogs/AutoChangeLog-pr-13725.yml b/html/changelogs/AutoChangeLog-pr-13725.yml
new file mode 100644
index 0000000000..5105de865e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13725.yml
@@ -0,0 +1,4 @@
+author: "silicons"
+delete-after: True
+changes:
+ - bugfix: "keybinds generate anti-collision bindings where necessary automatically now"
diff --git a/html/changelogs/AutoChangeLog-pr-13763.yml b/html/changelogs/AutoChangeLog-pr-13763.yml
new file mode 100644
index 0000000000..68eeaf1022
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13763.yml
@@ -0,0 +1,4 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - tweak: "RPEDs now drop their lowest part tier first when quick-emptied (used inhand)."
diff --git a/html/changelogs/AutoChangeLog-pr-13784.yml b/html/changelogs/AutoChangeLog-pr-13784.yml
new file mode 100644
index 0000000000..df8cf7ad57
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13784.yml
@@ -0,0 +1,4 @@
+author: "MrJWhit"
+delete-after: True
+changes:
+ - bugfix: "Effects can no longer trigger landmines"
diff --git a/html/changelogs/AutoChangeLog-pr-13790.yml b/html/changelogs/AutoChangeLog-pr-13790.yml
new file mode 100644
index 0000000000..45ebf00ee7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13790.yml
@@ -0,0 +1,5 @@
+author: "MrJWhit"
+delete-after: True
+changes:
+ - tweak: "Replaced engineering fuel tank with a large fuel tank"
+ - tweak: "Changed access to sec suit storage from armory access in every map to other security access"
diff --git a/html/changelogs/AutoChangeLog-pr-13804.yml b/html/changelogs/AutoChangeLog-pr-13804.yml
new file mode 100644
index 0000000000..6b6d56dc5c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13804.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - bugfix: "circuits get pin data proc is sanitized when text is returned as data"
diff --git a/html/changelogs/AutoChangeLog-pr-13808.yml b/html/changelogs/AutoChangeLog-pr-13808.yml
new file mode 100644
index 0000000000..fc97da6161
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13808.yml
@@ -0,0 +1,5 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - tweak: "You can now exit polycircuit input"
+ - bugfix: "Polycircuits now check for range"