diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm
index 61bd7d1e401561..513ca554adcd48 100644
--- a/code/datums/sprite_accessories.dm
+++ b/code/datums/sprite_accessories.dm
@@ -47,6 +47,10 @@
/// Determines if this is considered "sane" for the purpose of [/proc/randomize_human_normie]
/// Basically this is to blacklist the extremely wacky stuff from being picked in random human generation.
var/natural_spawn = TRUE
+ // DOPPLER SHIFT ADDITION START
+ /// If set TRUE, equipping this sprite accessory to your character will zoom out the character preview box. ONLY WORKS ON TAIL/HORNS/EARS
+ var/zooms_out_character_preview = FALSE
+ // DOPPLER SHIFT ADDITION END
/datum/sprite_accessory/blank
name = SPRITE_ACCESSORY_NONE
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 338fa2e661910f..335ff0d373af08 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -279,7 +279,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
preview_pref = params["updated_preview"]
character_preview_view.update_body()
return TRUE
-
+ if("update_background")
+ update_preference(GLOB.preference_entries[/datum/preference/choiced/background_state], params["new_background"])
+ return TRUE
if ("set_tricolor_preference")
var/requested_preference_key = params["preference"]
var/index_key = params["value"]
@@ -391,12 +393,21 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/datum/preferences/preferences
/// Whether we show current job clothes or nude/loadout only
var/show_job_clothes = TRUE
+ // DOPPLER SHIFT ADDITION START: Better character preview
+ var/image/canvas
+ var/last_canvas_size
+ var/last_canvas_state
+ // DOPPLER SHIFT ADDITION END
/atom/movable/screen/map_view/char_preview/Initialize(mapload, datum/preferences/preferences)
. = ..()
src.preferences = preferences
/atom/movable/screen/map_view/char_preview/Destroy()
+ // DOPPLER SHIFT ADDITION START
+ canvas?.cut_overlays()
+ canvas = null
+ // DOPPLER SHIFT ADDITION END
QDEL_NULL(body)
preferences?.character_preview_view = null
preferences = null
@@ -411,6 +422,50 @@ GLOBAL_LIST_EMPTY(preferences_datums)
appearance = preferences.render_new_preview_appearance(body, show_job_clothes)
+ // DOPPLER SHIFT ADDITION BEGIN: Better character preview
+ var/canvas_state = preferences.read_preference(/datum/preference/choiced/background_state)
+ var/canvas_size = 0
+ if ((body.dna.features[FEATURE_TAUR] != /datum/sprite_accessory/taur/none::name))
+ canvas_size = 1
+ if (body.mob_height > 12)
+ canvas_size = 1
+ if (("Oversized" in preferences.all_quirks))
+ canvas_size = 2
+ if(canvas_size == 0)
+ var/obj/item/organ/ears/ears = body.get_organ_slot(ORGAN_SLOT_EARS)
+ if(ears && ears?.bodypart_overlay?.sprite_datum?.zooms_out_character_preview)
+ canvas_size = 1
+ LAZYNULL(ears)
+ var/obj/item/organ/tail/tail = body.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL)
+ if(tail && tail?.bodypart_overlay?.sprite_datum?.zooms_out_character_preview)
+ canvas_size = 1
+ LAZYNULL(tail)
+ var/obj/item/organ/horns/horns = body.get_organ_slot(ORGAN_SLOT_EXTERNAL_HORNS)
+ if(horns && horns?.bodypart_overlay?.sprite_datum?.zooms_out_character_preview)
+ canvas_size = 1
+ LAZYNULL(horns)
+ body.pixel_x = canvas_size * 16
+
+ if (isnull(canvas) || last_canvas_size != canvas_size || last_canvas_state != canvas_state)
+ switch (canvas_size)
+ if (0)
+ canvas = image('modular_doppler/character_preview_background/icons/background_32x32.dmi', icon_state = canvas_state)
+ if (1)
+ canvas = image('modular_doppler/character_preview_background/icons/background_64x64.dmi', icon_state = canvas_state)
+ if (2)
+ canvas = image('modular_doppler/character_preview_background/icons/background_96x96.dmi', icon_state = canvas_state)
+
+ // Update the map view bounds when canvas size changes to properly display the scaled preview
+ set_position(1, 1)
+ last_canvas_size = canvas_size
+ last_canvas_state = canvas_state
+
+ canvas.cut_overlays()
+ canvas.add_overlay(body.appearance)
+
+ appearance = canvas.appearance
+ // DOPPLER SHIFT ADDITION END
+
/atom/movable/screen/map_view/char_preview/proc/create_body()
QDEL_NULL(body)
diff --git a/modular_doppler/character_preview_background/code/character_preview_background.dm b/modular_doppler/character_preview_background/code/character_preview_background.dm
new file mode 100644
index 00000000000000..b53c770283d332
--- /dev/null
+++ b/modular_doppler/character_preview_background/code/character_preview_background.dm
@@ -0,0 +1,26 @@
+/// Enables the choice of background in the character preview menu
+/datum/preference/choiced/background_state
+ savefile_key = "background_state"
+ savefile_identifier = PREFERENCE_CHARACTER
+
+GLOBAL_LIST_INIT(background_state_options, list(
+ "Black",
+ "Grey",
+ "White",
+ "Dark Tiles",
+ "Grey Tiles",
+ "White Tiles",
+ "Plating",
+ "Reinforced Floor",
+ "Grass",
+ "4CA",
+))
+
+/datum/preference/choiced/background_state/create_default_value()
+ return GLOB.background_state_options["Grey"]
+
+/datum/preference/choiced/background_state/init_possible_values()
+ return GLOB.background_state_options
+
+/datum/preference/choiced/background_state/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
+ return
diff --git a/modular_doppler/character_preview_background/icons/background_32x32.dmi b/modular_doppler/character_preview_background/icons/background_32x32.dmi
new file mode 100644
index 00000000000000..e88f1fb4e3c2a1
Binary files /dev/null and b/modular_doppler/character_preview_background/icons/background_32x32.dmi differ
diff --git a/modular_doppler/character_preview_background/icons/background_64x64.dmi b/modular_doppler/character_preview_background/icons/background_64x64.dmi
new file mode 100644
index 00000000000000..92df9d53bcf055
Binary files /dev/null and b/modular_doppler/character_preview_background/icons/background_64x64.dmi differ
diff --git a/modular_doppler/character_preview_background/icons/background_96x96.dmi b/modular_doppler/character_preview_background/icons/background_96x96.dmi
new file mode 100644
index 00000000000000..4b3285ca374a78
Binary files /dev/null and b/modular_doppler/character_preview_background/icons/background_96x96.dmi differ
diff --git a/modular_doppler/modular_customization/accessories/code/human_accessories/human_horns.dm b/modular_doppler/modular_customization/accessories/code/human_accessories/human_horns.dm
index cd722755f1eb6e..0e0a7f1f49d958 100644
--- a/modular_doppler/modular_customization/accessories/code/human_accessories/human_horns.dm
+++ b/modular_doppler/modular_customization/accessories/code/human_accessories/human_horns.dm
@@ -95,6 +95,7 @@
name = "Painted Points"
icon = 'modular_doppler/modular_customization/accessories/icons/human/horns_big.dmi'
icon_state = "paintedpoints"
+ zooms_out_character_preview = TRUE
/datum/sprite_accessory/horns/humanoid/big/whoshorns
name = "Who's Horns"
diff --git a/modular_doppler/modular_customization/accessories/code/lizard_accessories/lizard_tail.dm b/modular_doppler/modular_customization/accessories/code/lizard_accessories/lizard_tail.dm
index afd13c944258e5..bb6a40854650b2 100644
--- a/modular_doppler/modular_customization/accessories/code/lizard_accessories/lizard_tail.dm
+++ b/modular_doppler/modular_customization/accessories/code/lizard_accessories/lizard_tail.dm
@@ -36,6 +36,7 @@
icon_state = "shadekin_large"
dimension_x = 64
center = TRUE
+ zooms_out_character_preview = TRUE
/datum/sprite_accessory/tails/lizard/big/shadekin_long
name = "Shadekin (Big)(Long)"
diff --git a/modular_doppler/modular_customization/accessories/code/monkey_accessories/monkey_tail.dm b/modular_doppler/modular_customization/accessories/code/monkey_accessories/monkey_tail.dm
index aed9b1e8b89757..2f6f574a9d2a46 100644
--- a/modular_doppler/modular_customization/accessories/code/monkey_accessories/monkey_tail.dm
+++ b/modular_doppler/modular_customization/accessories/code/monkey_accessories/monkey_tail.dm
@@ -10,3 +10,4 @@
icon_state = "bigring_large"
dimension_x = 64
center = TRUE
+ zooms_out_character_preview = TRUE
diff --git a/modular_doppler/modular_customization/accessories/code/non_species_specific/canine_accessories/canine_ears.dm b/modular_doppler/modular_customization/accessories/code/non_species_specific/canine_accessories/canine_ears.dm
index 2d1586604ad924..29a3f938d48e5e 100644
--- a/modular_doppler/modular_customization/accessories/code/non_species_specific/canine_accessories/canine_ears.dm
+++ b/modular_doppler/modular_customization/accessories/code/non_species_specific/canine_accessories/canine_ears.dm
@@ -13,6 +13,7 @@
icon = 'modular_doppler/modular_customization/accessories/icons/non_species_specific/canine/canine_ears_big.dmi'
name = "Acrador"
icon_state = "acrador"
+ zooms_out_character_preview = TRUE
/datum/sprite_accessory/ears_more/dog/large/acrador_large
name = "Acrador (Big)"
@@ -29,6 +30,7 @@
icon = 'modular_doppler/modular_customization/accessories/icons/non_species_specific/canine/canine_ears_big.dmi'
name = "Sandfox"
icon_state = "sandfox"
+ zooms_out_character_preview = TRUE
/datum/sprite_accessory/ears_more/dog/wolf
name = "Wolf"
diff --git a/modular_doppler/modular_customization/accessories/code/non_species_specific/cervid_accessories/cervid_horns.dm b/modular_doppler/modular_customization/accessories/code/non_species_specific/cervid_accessories/cervid_horns.dm
index b4d5b902276ef8..067c023e8b2c4d 100644
--- a/modular_doppler/modular_customization/accessories/code/non_species_specific/cervid_accessories/cervid_horns.dm
+++ b/modular_doppler/modular_customization/accessories/code/non_species_specific/cervid_accessories/cervid_horns.dm
@@ -7,6 +7,7 @@
icon = 'modular_doppler/modular_customization/accessories/icons/non_species_specific/cervid/cervid_horns_big.dmi'
name = "Antlers"
icon_state = "antlers"
+ zooms_out_character_preview = TRUE
/datum/sprite_accessory/horns/deer/big/wide
name = "Antlers (Wide)"
diff --git a/modular_doppler/modular_customization/accessories/code/non_species_specific/leporid_accessories/leporid_ears.dm b/modular_doppler/modular_customization/accessories/code/non_species_specific/leporid_accessories/leporid_ears.dm
index 12bf58c5047534..95622df46853d9 100644
--- a/modular_doppler/modular_customization/accessories/code/non_species_specific/leporid_accessories/leporid_ears.dm
+++ b/modular_doppler/modular_customization/accessories/code/non_species_specific/leporid_accessories/leporid_ears.dm
@@ -17,7 +17,10 @@
icon = 'modular_doppler/modular_customization/accessories/icons/non_species_specific/leporid/leporid_ears_big.dmi'
name = "Lop (Big)"
icon_state = "rabbit_large"
+ zooms_out_character_preview = FALSE //ok this is a little awkward
+ // because these are the parent of the big subtype but also lop ears so niche case that doesn't need zooming. lol
/datum/sprite_accessory/ears_more/bunny/big/rabbit
name = "Bunny (Tall)"
icon_state = "bunny_large"
+ zooms_out_character_preview = TRUE
diff --git a/tgstation.dme b/tgstation.dme
index e5385ecd05328d..779e9b76d0092c 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -6873,6 +6873,7 @@
#include "modular_doppler\carp_infusion\code\carp_organs.dm"
#include "modular_doppler\cell_component\code\cell_component.dm"
#include "modular_doppler\chamtoggle\code\datums\mutations\chameleon.dm"
+#include "modular_doppler\character_preview_background\code\character_preview_background.dm"
#include "modular_doppler\chatroom_soul\code\chatroom_keybinding.dm"
#include "modular_doppler\chatroom_soul\code\irc_checks.dm"
#include "modular_doppler\chatroom_soul\code\irc_verbs.dm"
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx
index 148ddc52956962..9b24bfc717a902 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx
@@ -621,6 +621,19 @@ export function MainPage(props: MainPageProps) {
})
}
/>
+
+ {/* DOPPLER ADDITION START */}
+
+
+ act('update_background', {
+ new_background: value,
+ })
+ }
+ />
{/* DOPPLER ADDITION END */}
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/QuirksPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/QuirksPage.tsx
index fd6f011f30fc3c..44becd48b1941c 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/QuirksPage.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/QuirksPage.tsx
@@ -11,6 +11,7 @@ import {
Tooltip,
} from 'tgui-core/components';
import { createSearch } from 'tgui-core/string';
+import { CharacterPreview } from '../../common/CharacterPreview'; // DOPPLER EDIT ADDITION
import {
type PreferencesMenuData,
@@ -95,6 +96,7 @@ function QuirkDisplay(props: QuirkDisplayProps) {
const { icon, value, name, description, customizable, failTooltip } = quirk;
const [customizationExpanded, setCustomizationExpanded] = useState(false);
+ const { data } = useBackend(); // DOPPLER EDIT ADDITION
const className = 'PreferencesMenu__Quirks__QuirkList__quirk';
@@ -455,7 +457,27 @@ function QuirkPage() {
-
+ {/* // DOPPLER EDIT REMOVAL - moved down */}
+ {/* DOPPLER EDIT ADDITION START */}
+
+ {/* Keep the CharacterPreview alive but "hidden", so that traits that affect appearance (e.g. Oversized) refresh rendering calculations immediately. */}
+
+
+
+
+
+ {/* DOPPLER EDIT ADDITION END */}
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/SpeciesPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/SpeciesPage.tsx
index 3933394c6695b2..862c5ff75fc620 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/SpeciesPage.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/SpeciesPage.tsx
@@ -343,6 +343,7 @@ function SpeciesPageInner(props: SpeciesPageInnerProps) {
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/loadout/index.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/loadout/index.tsx
index 510b21e8c864f6..3ee00781bc3ccd 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/loadout/index.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/loadout/index.tsx
@@ -299,7 +299,7 @@ function LoadoutPreviewSection() {
>
-
+ {/* DOPPLER SHIFT CHANGE - ORIGINAL: */}
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/doppler/character_preview_background.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/doppler/character_preview_background.tsx
new file mode 100644
index 00000000000000..e16880338883c1
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/doppler/character_preview_background.tsx
@@ -0,0 +1,9 @@
+import type { FeatureChoiced } from '../../base';
+import { FeatureDropdownInput } from '../../dropdowns';
+
+export const bgstate: FeatureChoiced = {
+ name: 'Character Preview Background',
+ description:
+ 'What would you like the background for the character preview in the character creator to be?',
+ component: FeatureDropdownInput,
+};
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/types.ts b/tgui/packages/tgui/interfaces/PreferencesMenu/types.ts
index 80f38d9efcdb70..22c827ad9571f6 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/types.ts
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/types.ts
@@ -193,6 +193,7 @@ export type PreferencesMenuData = {
species: string;
loadout_list: LoadoutList;
job_clothes: BooleanLike;
+ background_state: string; // DOPPLER SHIFT ADDITION: Swappable character editor backgrounds
};
randomization: Record;
@@ -270,5 +271,6 @@ export type ServerData = {
loadout_tabs: LoadoutCategory[];
};
species: Record;
+ background_state: { choices: string[] }; // DOPPLER SHIFT ADDITION
[otherKey: string]: unknown;
};
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/useServerPrefs.ts b/tgui/packages/tgui/interfaces/PreferencesMenu/useServerPrefs.ts
index bcd403294cc4ab..6d696962a59937 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/useServerPrefs.ts
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/useServerPrefs.ts
@@ -27,6 +27,11 @@ export const ServerPrefs = createContext({
loadout_tabs: [],
},
species: {},
+ // DOPPLER SHIFT ADDITION START - Background Selection
+ background_state: {
+ choices: [],
+ },
+ // DOPPLER SHIFT ADDITION END
});
export function useServerPrefs() {
diff --git a/tgui/packages/tgui/interfaces/common/CharacterPreview.tsx b/tgui/packages/tgui/interfaces/common/CharacterPreview.tsx
index bd3fe7c4853fda..61cd3f2d06d1ad 100644
--- a/tgui/packages/tgui/interfaces/common/CharacterPreview.tsx
+++ b/tgui/packages/tgui/interfaces/common/CharacterPreview.tsx
@@ -1,9 +1,16 @@
import { ByondUi } from 'tgui-core/components';
-export const CharacterPreview = (props: { height: string; id: string }) => {
+export const CharacterPreview = (props: {
+ width?: string; // DOPPLER SHIFT EDIT
+ height: string;
+ id: string;
+}) => {
+ // DOPPLER SHIFT ADDITION START
+ const { width = '300px' } = props;
+ // DOPPLER SHIFT ADDITION END
return (