diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm
index 291246e621a0..7c6f9046a9b9 100644
--- a/code/__HELPERS/sanitize_values.dm
+++ b/code/__HELPERS/sanitize_values.dm
@@ -77,3 +77,23 @@
if(65 to 70) . += ascii2text(ascii+32) //letters A to F - translates to lowercase
else return default
return .
+
+/proc/sanitize_gear(list/gear, client/user)
+ var/list/sanitized_gear = list()
+ var/running_cost = 0
+
+ for(var/gear_option in gear)
+ if(!GLOB.gear_datums_by_name[gear_option])
+ continue
+
+ var/datum/gear/gear_datum = GLOB.gear_datums_by_name[gear_option]
+ var/new_total = running_cost + gear_datum.cost
+
+ if(new_total > MAX_GEAR_COST)
+ to_chat(user, SPAN_WARNING("Your [gear_option] was removed from your loadout as it exceeded the point limit."))
+ continue
+
+ running_cost = new_total
+ sanitized_gear += gear_option
+
+ return sanitized_gear
diff --git a/code/__pragmas.dm b/code/__pragmas.dm
index 309883fbda20..ac6541a4a1b2 100644
--- a/code/__pragmas.dm
+++ b/code/__pragmas.dm
@@ -22,6 +22,9 @@
#pragma DanglingVarType error
#pragma MissingInterpolatedExpression error
#pragma InvalidIndexOperation error
+#pragma PointlessPositionalArgument error
+#pragma ProcArgumentGlobal error
//3000-3999
#pragma EmptyBlock error
+#pragma AmbiguousInOrder error
diff --git a/code/controllers/subsystem/objectives_controller.dm b/code/controllers/subsystem/objectives_controller.dm
index 38accda46004..7f485288ada9 100644
--- a/code/controllers/subsystem/objectives_controller.dm
+++ b/code/controllers/subsystem/objectives_controller.dm
@@ -314,7 +314,7 @@ SUBSYSTEM_DEF(objectives)
for(var/datum/cm_objective/objective in medium_value)
while(LAZYLEN(objective.required_objectives) < objective.number_of_clues_to_generate && LAZYLEN(low_value))
var/datum/cm_objective/req = pick(low_value)
- if(req in objective.required_objectives || (req.objective_flags & OBJECTIVE_DEAD_END))
+ if((req in objective.required_objectives) || (req.objective_flags & OBJECTIVE_DEAD_END))
continue //don't want to pick the same thing twice OR use a dead-end objective.
link_objectives(req, objective)
@@ -327,7 +327,7 @@ SUBSYSTEM_DEF(objectives)
for(var/datum/cm_objective/objective in high_value)
while(LAZYLEN(objective.required_objectives) < objective.number_of_clues_to_generate && LAZYLEN(medium_value))
var/datum/cm_objective/req = pick(medium_value)
- if(req in objective.required_objectives || (req.objective_flags & OBJECTIVE_DEAD_END))
+ if((req in objective.required_objectives) || (req.objective_flags & OBJECTIVE_DEAD_END))
continue //don't want to pick the same thing twice OR use a dead-end objective.
link_objectives(req, objective)
@@ -340,7 +340,7 @@ SUBSYSTEM_DEF(objectives)
for(var/datum/cm_objective/objective in extreme_value)
while(LAZYLEN(objective.required_objectives) < objective.number_of_clues_to_generate && LAZYLEN(high_value))
var/datum/cm_objective/req = pick(high_value)
- if(req in objective.required_objectives || (req.objective_flags & OBJECTIVE_DEAD_END))
+ if((req in objective.required_objectives) || (req.objective_flags & OBJECTIVE_DEAD_END))
continue //don't want to pick the same thing twice OR use a dead-end objective.
link_objectives(req, objective)
@@ -353,7 +353,7 @@ SUBSYSTEM_DEF(objectives)
for(var/datum/cm_objective/objective in absolute_value)
while(LAZYLEN(objective.required_objectives) < objective.number_of_clues_to_generate && LAZYLEN(extreme_value))
var/datum/cm_objective/req = pick(extreme_value)
- if(req in objective.required_objectives || (req.objective_flags & OBJECTIVE_DEAD_END))
+ if((req in objective.required_objectives) || (req.objective_flags & OBJECTIVE_DEAD_END))
continue //don't want to pick the same thing twice OR use a dead-end objective.
link_objectives(req, objective)
diff --git a/code/datums/global_variables.dm b/code/datums/global_variables.dm
index 24d32bbf3552..87267ada41b6 100644
--- a/code/datums/global_variables.dm
+++ b/code/datums/global_variables.dm
@@ -211,7 +211,7 @@
to_chat(src, "A variable with this name ([param_var_name]) doesn't exist among global variables")
return
- if(param_var_name in locked && !check_rights(R_DEBUG))
+ if((param_var_name in locked) && !check_rights(R_DEBUG))
return
variable = param_var_name
@@ -270,7 +270,7 @@
if(!variable) return
var_value = global.vars[variable]
- if(variable in locked && !check_rights(R_DEBUG))
+ if((variable in locked) && !check_rights(R_DEBUG))
return
if(!autodetect_class)
diff --git a/code/game/gamemodes/cm_process.dm b/code/game/gamemodes/cm_process.dm
index d6519bbcd887..2c11af9ca6f9 100644
--- a/code/game/gamemodes/cm_process.dm
+++ b/code/game/gamemodes/cm_process.dm
@@ -254,7 +254,7 @@ GLOBAL_VAR_INIT(next_admin_bioscan, 30 MINUTES)
for(var/mob/living/carbon/human/current_human as anything in GLOB.alive_human_list)
if(!(current_human.z && (current_human.z in z_levels) && !istype(current_human.loc, /turf/open/space)))
continue
- if(current_human.faction in FACTION_LIST_WY || current_human.job == "Corporate Liaison") //The CL is assigned the USCM faction for gameplay purposes
+ if((current_human.faction in FACTION_LIST_WY) || current_human.job == "Corporate Liaison") //The CL is assigned the USCM faction for gameplay purposes
num_WY++
num_headcount++
continue
diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm
index e0cc2b0c3a02..a3bded9fe962 100644
--- a/code/game/machinery/robot_fabricator.dm
+++ b/code/game/machinery/robot_fabricator.dm
@@ -112,7 +112,7 @@ Please wait until completion...
build_cost = 75000
var/building = build_type
- if (building in subtypesof(/obj/item/robot_parts) + /obj/item/fake_robot_head)
+ if (building in (subtypesof(/obj/item/robot_parts) + /obj/item/fake_robot_head))
if (src.metal_amount >= build_cost)
src.operating = 1
src.update_use_power(USE_POWER_ACTIVE)
diff --git a/code/modules/buildmode/submodes/variable_edit.dm b/code/modules/buildmode/submodes/variable_edit.dm
index 7517012583da..9013934eebf2 100644
--- a/code/modules/buildmode/submodes/variable_edit.dm
+++ b/code/modules/buildmode/submodes/variable_edit.dm
@@ -27,7 +27,7 @@
var/list/locked = list("vars", "key", "ckey", "client", "icon")
selected_key = input(usr,"Enter variable name:" ,"Name", "name")
- if(selected_key in locked && !check_rights(R_DEBUG,0))
+ if((selected_key in locked) && !check_rights(R_DEBUG, FALSE))
return TRUE
var/type = tgui_input_list(usr,"Select variable type:", "Type", list(TYPE_TEXT, TYPE_NUMBER, TYPE_MOB_REFERENCE, TYPE_OBJ_REFERENCE, TYPE_TURF_REFERENCE))
diff --git a/code/modules/client/color_picker.dm b/code/modules/client/color_picker.dm
new file mode 100644
index 000000000000..f3eda08af544
--- /dev/null
+++ b/code/modules/client/color_picker.dm
@@ -0,0 +1,74 @@
+/datum/body_picker/ui_static_data(mob/user)
+ . = ..()
+
+ .["icon"] = /datum/species::icobase
+
+ .["body_types"] = list()
+ for(var/key in GLOB.body_type_list)
+ var/datum/body_type/type = GLOB.body_type_list[key]
+ .["body_types"] += list(
+ list("name" = type.name, "icon" = type.icon_name)
+ )
+
+ .["skin_colors"] = list()
+ for(var/key in GLOB.skin_color_list)
+ var/datum/skin_color/color = GLOB.skin_color_list[key]
+ .["skin_colors"] += list(
+ list("name" = color.name, "icon" = color.icon_name, "color" = color.color)
+ )
+
+ .["body_sizes"] = list()
+ for(var/key in GLOB.body_size_list)
+ var/datum/body_size/size = GLOB.body_size_list[key]
+ .["body_sizes"] += list(
+ list("name" = size.name, "icon" = size.icon_name)
+ )
+
+/datum/body_picker/ui_data(mob/user)
+ . = ..()
+
+ .["body_type"] = GLOB.body_type_list[user.client.prefs.body_type].icon_name
+ .["skin_color"] = GLOB.skin_color_list[user.client.prefs.skin_color].icon_name
+ .["body_size"] = GLOB.body_size_list[user.client.prefs.body_size].icon_name
+
+/datum/body_picker/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+
+ var/datum/preferences/prefs = ui.user.client.prefs
+
+ switch(action)
+ if("type")
+ if(!GLOB.body_type_list[params["name"]])
+ return
+
+ prefs.body_type = params["name"]
+
+ if("size")
+ if(!GLOB.body_size_list[params["name"]])
+ return
+
+ prefs.body_size = params["name"]
+
+ if("color")
+ if(!GLOB.skin_color_list[params["name"]])
+ return
+
+ prefs.skin_color = params["name"]
+
+ prefs.ShowChoices(ui.user)
+ return TRUE
+
+/datum/body_picker/tgui_interact(mob/user, datum/tgui/ui)
+ . = ..()
+
+ ui = SStgui.try_update_ui(user, src, ui)
+
+ if(!ui)
+ ui = new(user, src, "BodyPicker", "Body Picker")
+ ui.open()
+ ui.set_autoupdate(FALSE)
+
+ winset(user, ui.window.id, "focus=true")
+
+/datum/body_picker/ui_state(mob/user)
+ return GLOB.always_state
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index c3cc73d3fd20..970595a5a045 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -30,6 +30,8 @@ GLOBAL_LIST_INIT(bgstate_options, list(
var/atom/movable/screen/rotate/alt/rotate_left
var/atom/movable/screen/rotate/rotate_right
+ var/static/datum/body_picker/picker = new
+
//doohickeys for savefiles
var/path
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
@@ -340,10 +342,13 @@ GLOBAL_LIST_INIT(bgstate_options, list(
dat += "
Physical Information:"
dat += "®
"
dat += "Age: [age]
"
- dat += "Gender: [gender == MALE ? "Male" : "Female"]
"
- dat += "Skin Color: [skin_color]
"
- dat += "Body Size: [body_size]
"
- dat += "Body Muscularity: [body_type]
"
+ dat += "Gender: [gender == MALE ? "Male" : "Female"]
"
+
+ dat += "Skin Color: [skin_color]
"
+ dat += "Body Size: [body_size]
"
+ dat += "Body Muscularity: [body_type]
"
+ dat += "Edit Body: Picker
"
+
dat += "Traits: Character Traits"
dat += "
"
@@ -1569,23 +1574,9 @@ GLOBAL_LIST_INIT(bgstate_options, list(
if(new_h_gradient_style)
grad_style = new_h_gradient_style
- if ("skin_color")
- var/new_skin_color = tgui_input_list(user, "Choose your character's skin color:", "Character Preferences", GLOB.skin_color_list)
-
- if (new_skin_color)
- skin_color = new_skin_color
-
- if ("body_size")
- var/new_body_size = tgui_input_list(user, "Choose your character's body size:", "Character Preferences", GLOB.body_size_list)
-
- if (new_body_size)
- body_size = new_body_size
-
- if ("body_type")
- var/new_body_type = tgui_input_list(user, "Choose your character's body type:", "Character Preferences", GLOB.body_type_list)
-
- if (new_body_type)
- body_type = new_body_type
+ if ("body")
+ picker.tgui_interact(user)
+ return
if("facial")
var/new_facial = input(user, "Choose your character's facial-hair color:", "Character Preference", rgb(r_facial, g_facial, b_facial)) as color|null
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 69a3e8a046fd..4b69960c761f 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -645,7 +645,7 @@
if(!organ_data)
organ_data = list()
- gear = sanitize_list(gear)
+ gear = sanitize_gear(gear, owner)
traits = sanitize_list(traits)
read_traits = FALSE
diff --git a/code/modules/defenses/sentry.dm b/code/modules/defenses/sentry.dm
index 6c9c5ad68fea..02bccde9fa37 100644
--- a/code/modules/defenses/sentry.dm
+++ b/code/modules/defenses/sentry.dm
@@ -313,7 +313,7 @@
new_projectile.damage *= damage_mult
new_projectile.accuracy *= accuracy_mult
GIVE_BULLET_TRAIT(new_projectile, /datum/element/bullet_trait_iff, faction_group)
- new_projectile.fire_at(target, src, owner_mob, new_projectile.ammo.max_range, new_projectile.ammo.shell_speed, null, FALSE)
+ new_projectile.fire_at(target, owner_mob, src, new_projectile.ammo.max_range, new_projectile.ammo.shell_speed, null, FALSE)
muzzle_flash(Get_Angle(get_turf(src), target))
ammo.current_rounds--
track_shot()
diff --git a/code/modules/defenses/sentry_flamer.dm b/code/modules/defenses/sentry_flamer.dm
index 2c5e9ae62677..fcdd54708609 100644
--- a/code/modules/defenses/sentry_flamer.dm
+++ b/code/modules/defenses/sentry_flamer.dm
@@ -28,11 +28,11 @@
accuracy_mult = 0.1
fire_delay = 0.5
-/obj/structure/machinery/defenses/sentry/flamer/actual_fire(atom/A)
- var/obj/projectile/P = new(create_cause_data(initial(name), owner_mob))
- P.generate_bullet(new ammo.default_ammo)
- GIVE_BULLET_TRAIT(P, /datum/element/bullet_trait_iff, faction_group)
- P.fire_at(A, src, owner_mob, P.ammo.max_range, P.ammo.shell_speed, null)
+/obj/structure/machinery/defenses/sentry/flamer/actual_fire(atom/target)
+ var/obj/projectile/new_projectile = new(src, create_cause_data(initial(name), owner_mob, src))
+ new_projectile.generate_bullet(new ammo.default_ammo)
+ GIVE_BULLET_TRAIT(new_projectile, /datum/element/bullet_trait_iff, faction_group)
+ new_projectile.fire_at(target, owner_mob, src, new_projectile.ammo.max_range, new_projectile.ammo.shell_speed, null, FALSE)
ammo.current_rounds--
track_shot()
if(ammo.current_rounds == 0)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index d198f7818eda..712bef37afad 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -905,7 +905,7 @@ note dizziness decrements automatically in the mob's Life() proc.
conga_line += S.buckled
while(!end_of_conga)
var/atom/movable/A = S.pulling
- if(A in conga_line || A.anchored) //No loops, nor moving anchored things.
+ if((A in conga_line) || A.anchored) //No loops, nor moving anchored things.
end_of_conga = TRUE
break
conga_line += A
diff --git a/code/modules/mob/new_player/skin_color.dm b/code/modules/mob/new_player/skin_color.dm
index f3158613c38c..166cb22eb302 100644
--- a/code/modules/mob/new_player/skin_color.dm
+++ b/code/modules/mob/new_player/skin_color.dm
@@ -2,6 +2,14 @@
var/name
var/icon_name
+ var/color
+
+/datum/skin_color/New()
+ . = ..()
+
+ var/icon/icon_to_use = icon(/datum/species::icobase, "[icon_name]_torso_[/datum/body_size/thin::icon_name]_[/datum/body_type/twig::icon_name]")
+ color = icon_to_use.GetPixel(icon_to_use.Width() / 2, icon_to_use.Height() / 2)
+
/datum/skin_color/cmplayer
name = "Extra Pale"
icon_name = "cmp1"
diff --git a/colonialmarines.dme b/colonialmarines.dme
index 71c2cd9669a2..b7f4b71cb21d 100644
--- a/colonialmarines.dme
+++ b/colonialmarines.dme
@@ -1560,6 +1560,7 @@
#include "code\modules\clans\ship.dm"
#include "code\modules\client\client_defines.dm"
#include "code\modules\client\client_procs.dm"
+#include "code\modules\client\color_picker.dm"
#include "code\modules\client\country_flags.dm"
#include "code\modules\client\player_details.dm"
#include "code\modules\client\preferences.dm"
diff --git a/html/changelogs/AutoChangeLog-pr-7336.yml b/html/changelogs/AutoChangeLog-pr-7336.yml
deleted file mode 100644
index 681f96f35f03..000000000000
--- a/html/changelogs/AutoChangeLog-pr-7336.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "harryob"
-delete-after: True
-changes:
- - admin: "you can add \"known alts\" to players, now"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-7463.yml b/html/changelogs/AutoChangeLog-pr-7463.yml
deleted file mode 100644
index 09e6bb6ac3a2..000000000000
--- a/html/changelogs/AutoChangeLog-pr-7463.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "VileBeggar"
-delete-after: True
-changes:
- - qol: "You can now use the 'check status' verb and any stethoscope you might have attached to your uniform directly by examining an adjacent human."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-7470.yml b/html/changelogs/AutoChangeLog-pr-7470.yml
deleted file mode 100644
index 92856ca59c25..000000000000
--- a/html/changelogs/AutoChangeLog-pr-7470.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "vero5123"
-delete-after: True
-changes:
- - bugfix: "Special characters are now properly sanitized and removed in bug reports."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-7472.yml b/html/changelogs/AutoChangeLog-pr-7472.yml
deleted file mode 100644
index 8671ee9ea13b..000000000000
--- a/html/changelogs/AutoChangeLog-pr-7472.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Drathek"
-delete-after: True
-changes:
- - bugfix: "Fix reloading under barrel flamers with any reagent from a flamer tank"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-7473.yml b/html/changelogs/AutoChangeLog-pr-7473.yml
deleted file mode 100644
index 6913f3a83aa0..000000000000
--- a/html/changelogs/AutoChangeLog-pr-7473.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Drathek"
-delete-after: True
-changes:
- - balance: "Buffed SG armor penetration ammo damage falloff from 5 to 3."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-7474.yml b/html/changelogs/AutoChangeLog-pr-7474.yml
deleted file mode 100644
index 6df2dd6c584d..000000000000
--- a/html/changelogs/AutoChangeLog-pr-7474.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Drathek"
-delete-after: True
-changes:
- - ui: "Fixed the ping relay buttons not displaying anything when clicked on the first time. Now Button.Confirm.confirmContent will only replace children if it is truthy."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-7477.yml b/html/changelogs/AutoChangeLog-pr-7477.yml
new file mode 100644
index 000000000000..82ee36bab92f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7477.yml
@@ -0,0 +1,4 @@
+author: "Nanu, HarryOb"
+delete-after: True
+changes:
+ - code_imp: "Adds some code so if you're above the pointcap on your loadout, items will be removed to put you at the point cap limit."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-7482.yml b/html/changelogs/AutoChangeLog-pr-7482.yml
new file mode 100644
index 000000000000..13d5e6358e23
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7482.yml
@@ -0,0 +1,4 @@
+author: "Drathek"
+delete-after: True
+changes:
+ - code_imp: "Enabled 3 more OD pragmas for linting and fixed some ambiguous usage of In"
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-11.yml b/html/changelogs/archive/2024-11.yml
index 71293c36ac00..09b2d924afdf 100644
--- a/html/changelogs/archive/2024-11.yml
+++ b/html/changelogs/archive/2024-11.yml
@@ -80,3 +80,23 @@
6s
- balance: Sentinel paralyzing slash stuns after 3 seconds instead of 4 and lasts
2.5 seconds from 2.
+2024-11-04:
+ Drathek:
+ - bugfix: Fixes additional projectiles being fired from humans that placed a shotgun
+ sentry instead of the sentry.
+ - bugfix: Fixes cause_data for flamer sentries so now kills they make are explained
+ in the message and attributed to the kill counter for the sentry.
+ - bugfix: Fix reloading under barrel flamers with any reagent from a flamer tank
+ - ui: Fixed the ping relay buttons not displaying anything when clicked on the first
+ time. Now Button.Confirm.confirmContent will only replace children if it is
+ truthy.
+ - balance: Buffed SG armor penetration ammo damage falloff from 5 to 3.
+ VileBeggar:
+ - qol: You can now use the 'check status' verb and any stethoscope you might have
+ attached to your uniform directly by examining an adjacent human.
+ harryob:
+ - rscadd: a new tgui with better previews for the different skin colors / body types
+ / body sizes
+ - admin: you can add "known alts" to players, now
+ vero5123:
+ - bugfix: Special characters are now properly sanitized and removed in bug reports.
diff --git a/tgui/packages/tgui/interfaces/BodyPicker.tsx b/tgui/packages/tgui/interfaces/BodyPicker.tsx
new file mode 100644
index 000000000000..4ca0c03acdf7
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/BodyPicker.tsx
@@ -0,0 +1,183 @@
+import { useState } from 'react';
+
+import { useBackend } from '../backend';
+import {
+ Box,
+ Button,
+ ColorBox,
+ DmIcon,
+ Modal,
+ Stack,
+ Tooltip,
+} from '../components';
+import { Window } from '../layouts';
+
+type PickerData = {
+ icon: string;
+ body_types: { name: string; icon: string }[];
+ skin_colors: { name: string; icon: string; color: string }[];
+ body_sizes: { name: string; icon: string }[];
+
+ body_type: string;
+ skin_color: string;
+ body_size: string;
+};
+
+export const BodyPicker = () => {
+ const { data } = useBackend();
+
+ const { icon, body_size, body_type, skin_color, body_types, body_sizes } =
+ data;
+
+ const [picker, setPicker] = useState<'type' | 'size' | undefined>();
+
+ const unselectedBodyType = body_types.filter(
+ (val) => val.icon !== body_type,
+ )[0];
+
+ const unselectedBodySize = body_sizes.filter(
+ (val) => val.icon !== body_size,
+ )[0];
+
+ return (
+
+
+ {picker && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const TypePicker = (props: {
+ readonly picker: (_) => void;
+ readonly toUse: 'type' | 'size';
+}) => {
+ const { data, act } = useBackend();
+
+ const { picker, toUse } = props;
+
+ const { body_type, body_types, skin_color, body_size, body_sizes, icon } =
+ data;
+
+ const toIterate = toUse === 'type' ? body_types : body_sizes;
+
+ const active = toUse === 'type' ? body_type : body_size;
+
+ return (
+
+ {toIterate.map((type) => (
+
+
+ {
+ picker(undefined);
+ act(toUse, { name: type.name });
+ }}
+ position="relative"
+ className={`typePicker ${active === type.icon ? 'active' : ''}`}
+ >
+
+
+
+
+ ))}
+
+ );
+};
+
+const ColorOptions = () => {
+ const { data, act } = useBackend();
+
+ const { skin_color, skin_colors } = data;
+
+ return (
+
+ {skin_colors.map((color) => (
+
+ act('color', { name: color.name })}
+ className={`colorPicker ${skin_color === color.icon ? 'active' : ''}`}
+ />
+
+ ))}
+
+ );
+};
diff --git a/tgui/packages/tgui/styles/interfaces/BodyPicker.scss b/tgui/packages/tgui/styles/interfaces/BodyPicker.scss
new file mode 100644
index 000000000000..d60cd2112493
--- /dev/null
+++ b/tgui/packages/tgui/styles/interfaces/BodyPicker.scss
@@ -0,0 +1,19 @@
+.theme-crtblue {
+ .BodyPicker {
+ .Stack--horizontal > .colorPickerContainer:first-of-type {
+ margin-left: 6px;
+ }
+
+ .typePicker {
+ border: 1px dotted #8ac8ff;
+ }
+
+ .typePicker.active {
+ border: 1px solid #8ac8ff;
+ }
+
+ .colorPicker.active {
+ outline: solid 2px #8ac8ff;
+ }
+ }
+}
diff --git a/tgui/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss
index 2f9bf90463d7..3803da7a9237 100644
--- a/tgui/packages/tgui/styles/main.scss
+++ b/tgui/packages/tgui/styles/main.scss
@@ -48,6 +48,7 @@
@include meta.load-css('./components/Tooltip.scss');
// Interfaces
+@include meta.load-css('./interfaces/BodyPicker.scss');
@include meta.load-css('./interfaces/Changelog.scss');
@include meta.load-css('./interfaces/ListInput.scss');
@include meta.load-css('./interfaces/CasSim.scss');
diff --git a/tgui/packages/tgui/styles/themes/crt.scss b/tgui/packages/tgui/styles/themes/crt.scss
index 9f9436f275a3..87c0bd58ad14 100644
--- a/tgui/packages/tgui/styles/themes/crt.scss
+++ b/tgui/packages/tgui/styles/themes/crt.scss
@@ -99,6 +99,11 @@ $background-radial-opacity: 0.2 !default;
)
);
+ @include meta.load-css(
+ '../components/Modal.scss',
+ $with: ('background-color': base.$color-bg)
+ );
+
.Layout__content {
background-image: none;
background: radial-gradient(