[MIRROR] Fix multiple pref issues (#11373)

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
Co-authored-by: C.L. <killer65311@gmail.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-08-10 07:24:35 -07:00
committed by GitHub
parent b7c79d4a6a
commit ae778b99ee
15 changed files with 106 additions and 53 deletions

View File

@@ -62,3 +62,7 @@
#define EMOTE_SOUND_NO_FREQ "Default" #define EMOTE_SOUND_NO_FREQ "Default"
#define EMOTE_SOUND_VOICE_FREQ "Voice Frequency" #define EMOTE_SOUND_VOICE_FREQ "Voice Frequency"
#define EMOTE_SOUND_VOICE_LIST "Voice Sound" #define EMOTE_SOUND_VOICE_LIST "Voice Sound"
#define WRITE_PREF_NORMAL 1
#define WRITE_PREF_INSTANT 2
#define WRITE_PREF_MANUAL 3

View File

@@ -1651,3 +1651,5 @@ GLOBAL_LIST(chamelion_mask_choices)
GLOBAL_LIST(chamelion_belt_choices) GLOBAL_LIST(chamelion_belt_choices)
//Accessory //Accessory
GLOBAL_LIST(chamelion_accessory_choices) GLOBAL_LIST(chamelion_accessory_choices)
GLOBAL_LIST_INIT(tail_layer_options, list("Lower layer" = TAIL_UPPER_LAYER_LOW , "Default layer" = TAIL_UPPER_LAYER , "Upper layer" = TAIL_UPPER_LAYER_HIGH ))

View File

@@ -13,12 +13,15 @@ SUBSYSTEM_DEF(asset_loading)
while(length(generate_queue)) while(length(generate_queue))
var/datum/asset/to_load = generate_queue[generate_queue.len] var/datum/asset/to_load = generate_queue[generate_queue.len]
last_queue_len = length(generate_queue)
generate_queue.len--
to_load.queued_generation() to_load.queued_generation()
if(MC_TICK_CHECK) if(MC_TICK_CHECK)
return return
last_queue_len = length(generate_queue)
generate_queue.len--
// We just emptied the queue // We just emptied the queue
if(last_queue_len && !length(generate_queue)) if(last_queue_len && !length(generate_queue))
// Clean up cached icons, freeing memory. // Clean up cached icons, freeing memory.

View File

@@ -38,4 +38,6 @@ SUBSYSTEM_DEF(character_setup)
return return
/datum/controller/subsystem/character_setup/proc/queue_preferences_save(var/datum/preferences/prefs) /datum/controller/subsystem/character_setup/proc/queue_preferences_save(var/datum/preferences/prefs)
if(!prefs)
return
save_queue |= prefs save_queue |= prefs

View File

@@ -49,7 +49,7 @@
* Arguments: * Arguments:
* * datum/P the parent datum this component reacts to signals from * * datum/P the parent datum this component reacts to signals from
*/ */
/datum/component/New(list/raw_args) /datum/component/New(list/raw_args, manual)
parent = raw_args[1] parent = raw_args[1]
var/list/arguments = raw_args.Copy(2) var/list/arguments = raw_args.Copy(2)
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
@@ -58,6 +58,8 @@
return return
_JoinParent(parent) _JoinParent(parent)
if(manual)
lateload_pref_data()
/** /**
* Called during component creation with the same arguments as in new excluding parent. * Called during component creation with the same arguments as in new excluding parent.
@@ -310,7 +312,7 @@
* *
* Properly handles duplicate situations based on the `dupe_mode` var * Properly handles duplicate situations based on the `dupe_mode` var
*/ */
/datum/proc/_AddComponent(list/raw_args, source) /datum/proc/_AddComponent(list/raw_args, source, manual)
var/original_type = raw_args[1] var/original_type = raw_args[1]
var/datum/component/component_type = original_type var/datum/component/component_type = original_type
@@ -349,14 +351,14 @@
switch(dupe_mode) switch(dupe_mode)
if(COMPONENT_DUPE_UNIQUE) if(COMPONENT_DUPE_UNIQUE)
if(!new_component) if(!new_component)
new_component = new component_type(raw_args) new_component = new component_type(raw_args, manual)
if(!QDELETED(new_component)) if(!QDELETED(new_component))
old_component.InheritComponent(new_component, TRUE) old_component.InheritComponent(new_component, TRUE)
QDEL_NULL(new_component) QDEL_NULL(new_component)
if(COMPONENT_DUPE_HIGHLANDER) if(COMPONENT_DUPE_HIGHLANDER)
if(!new_component) if(!new_component)
new_component = new component_type(raw_args) new_component = new component_type(raw_args, manual)
if(!QDELETED(new_component)) if(!QDELETED(new_component))
new_component.InheritComponent(old_component, FALSE) new_component.InheritComponent(old_component, FALSE)
QDEL_NULL(old_component) QDEL_NULL(old_component)
@@ -378,7 +380,7 @@
return null return null
else if(!new_component) else if(!new_component)
new_component = new component_type(raw_args) // There's a valid dupe mode but there's no old component, act like normal new_component = new component_type(raw_args, manual) // There's a valid dupe mode but there's no old component, act like normal
else if(dupe_mode == COMPONENT_DUPE_SELECTIVE) else if(dupe_mode == COMPONENT_DUPE_SELECTIVE)
var/list/arguments = raw_args.Copy() var/list/arguments = raw_args.Copy()
@@ -390,19 +392,19 @@
QDEL_NULL(new_component) QDEL_NULL(new_component)
break break
if(!new_component && make_new_component) if(!new_component && make_new_component)
new_component = new component_type(raw_args) new_component = new component_type(raw_args, manual)
else if(dupe_mode == COMPONENT_DUPE_SOURCES) else if(dupe_mode == COMPONENT_DUPE_SOURCES)
new_component = new component_type(raw_args) new_component = new component_type(raw_args, manual)
if(new_component.on_source_add(arglist(list(source) + raw_args.Copy(2))) == COMPONENT_INCOMPATIBLE) if(new_component.on_source_add(arglist(list(source) + raw_args.Copy(2))) == COMPONENT_INCOMPATIBLE)
stack_trace("incompatible source added to a [new_component.type]. Args: [json_encode(raw_args)]") stack_trace("incompatible source added to a [new_component.type]. Args: [json_encode(raw_args)]")
return null return null
else if(!new_component) else if(!new_component)
new_component = new component_type(raw_args) // Dupes are allowed, act like normal new_component = new component_type(raw_args, manual) // Dupes are allowed, act like normal
if(!old_component && !QDELETED(new_component)) // Nothing related to duplicate components happened and the new component is healthy if(!old_component && !QDELETED(new_component)) // Nothing related to duplicate components happened and the new component is healthy
SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_component) SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_component, manual)
return new_component return new_component
return old_component return old_component
@@ -424,12 +426,13 @@
* *
* Arguments: * Arguments:
* * component_type The typepath of the component to create or return * * component_type The typepath of the component to create or return
* * manual_load If we are manually adding this (post-spawn) or not.
* * ... additional arguments to be passed when creating the component if it does not exist * * ... additional arguments to be passed when creating the component if it does not exist
*/ */
/datum/proc/_LoadComponent(list/arguments) /datum/proc/_LoadComponent(list/arguments, manual_load)
. = GetComponent(arguments[1]) . = GetComponent(arguments[1])
if(!.) if(!.)
return _AddComponent(arguments) return _AddComponent(arguments, manual = manual_load)
/** /**
* Removes the component from parent, ends up with a null parent * Removes the component from parent, ends up with a null parent
* Used as a helper proc by the component transfer proc, does not clean up the component like Destroy does * Used as a helper proc by the component transfer proc, does not clean up the component like Destroy does
@@ -495,3 +498,9 @@
*/ */
/datum/component/tgui_host() /datum/component/tgui_host()
return parent return parent
/**
* Loads lateload data for the component. Things such as preferences, which aren't applied if not done at character-spawn. Must be defined per-component.
*/
/datum/component/proc/lateload_pref_data()
return

View File

@@ -155,7 +155,7 @@ var/list/datum/power/changeling/powerinstances = list()
if(!mind) if(!mind)
return return
//The current mob is made a changeling AND the mind is made a changeling. //The current mob is made a changeling AND the mind is made a changeling.
var/datum/component/antag/changeling/comp = LoadComponent(/datum/component/antag/changeling) var/datum/component/antag/changeling/comp = LoadComponent(/datum/component/antag/changeling, TRUE)
mind.antag_holder.changeling = comp mind.antag_holder.changeling = comp
var/lesser_form = !ishuman(src) var/lesser_form = !ishuman(src)
@@ -423,10 +423,23 @@ var/list/datum/power/changeling/powerinstances = list()
//Debug item. Here because during debugging I DO NOT want to have to open the player panel 5000 times. //Debug item. Here because during debugging I DO NOT want to have to open the player panel 5000 times.
/obj/item/toy/katana/changeling_debug /obj/item/changeling_debug
name = "Katana of the Changeling" name = "Katana of the Changeling"
desc = "A katana imbued with special powers. It is said that those who wield it will become a changeling." desc = "A katana imbued with special powers. It is said that those who wield it will become a changeling."
/obj/item/toy/katana/changeling_debug/attack_self(mob/user) icon = 'icons/obj/weapons.dmi'
icon_state = "katana"
item_state = "katana"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_material.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_material.dmi',
)
slot_flags = SLOT_BELT | SLOT_BACK
force = 5
throwforce = 5
w_class = ITEMSIZE_NORMAL
attack_verb = list("attacked", "slashed", "stabbed", "sliced")
/obj/item/changeling_debug/attack_self(mob/user)
user.make_changeling() user.make_changeling()
///Changeling Panel ///Changeling Panel

View File

@@ -255,3 +255,13 @@
to_chat(owner, span_danger("The VR systems cannot comprehend this power! This is useless to you!")) to_chat(owner, span_danger("The VR systems cannot comprehend this power! This is useless to you!"))
return TRUE return TRUE
return FALSE return FALSE
///Gets late-load preferences for the shadekin component. Used when the component is applied post-spawn.
/datum/component/shadekin/lateload_pref_data()
if(owner.client)
flicker_color = owner.read_preference(/datum/preference/color/living/flicker_color)
flicker_time = owner.read_preference(/datum/preference/numeric/living/flicker_time)
flicker_break_chance = owner.read_preference(/datum/preference/numeric/living/flicker_break_chance)
flicker_distance = owner.read_preference(/datum/preference/numeric/living/flicker_distance)
no_retreat = owner.read_preference(/datum/preference/toggle/living/dark_retreat_toggle)
nutrition_energy_conversion = owner.read_preference(/datum/preference/toggle/living/shadekin_nutrition_conversion)

View File

@@ -212,6 +212,9 @@
return data return data
/datum/component/shadekin/tgui_close(mob/user)
SScharacter_setup.queue_preferences_save(user?.client?.prefs)
. = ..()
/datum/component/shadekin/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) /datum/component/shadekin/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..()) if(..())
@@ -224,14 +227,14 @@
if(!isnum(new_time)) if(!isnum(new_time))
return FALSE return FALSE
flicker_time = new_time flicker_time = new_time
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_time, new_time) ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_time, new_time, WRITE_PREF_MANUAL)
return TRUE return TRUE
if("adjust_color") if("adjust_color")
var/set_new_color = tgui_color_picker(ui.user, "Select a color you wish the lights to flicker as (Default is #E0EFF0)", "Color Selector", flicker_color) var/set_new_color = tgui_color_picker(ui.user, "Select a color you wish the lights to flicker as (Default is #E0EFF0)", "Color Selector", flicker_color)
if(!set_new_color) if(!set_new_color)
return FALSE return FALSE
flicker_color = set_new_color flicker_color = set_new_color
ui.user.write_preference_directly(/datum/preference/color/living/flicker_color, set_new_color) ui.user.write_preference_directly(/datum/preference/color/living/flicker_color, set_new_color, WRITE_PREF_MANUAL)
return TRUE return TRUE
if("adjust_break") if("adjust_break")
var/new_break_chance = text2num(params["val"]) var/new_break_chance = text2num(params["val"])
@@ -239,7 +242,7 @@
if(!isnum(new_break_chance)) if(!isnum(new_break_chance))
return FALSE return FALSE
flicker_break_chance = new_break_chance flicker_break_chance = new_break_chance
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_break_chance, new_break_chance) ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_break_chance, new_break_chance, WRITE_PREF_MANUAL)
return TRUE return TRUE
if("adjust_distance") if("adjust_distance")
var/new_distance = text2num(params["val"]) var/new_distance = text2num(params["val"])
@@ -247,16 +250,16 @@
if(!isnum(new_distance)) if(!isnum(new_distance))
return FALSE return FALSE
flicker_distance = new_distance flicker_distance = new_distance
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_distance, new_distance) ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_distance, new_distance, WRITE_PREF_MANUAL)
return TRUE return TRUE
if("toggle_retreat") if("toggle_retreat")
var/new_retreat = !no_retreat var/new_retreat = !no_retreat
no_retreat = !no_retreat no_retreat = !no_retreat
ui.user.write_preference_directly(/datum/preference/toggle/living/dark_retreat_toggle, new_retreat) ui.user.write_preference_directly(/datum/preference/toggle/living/dark_retreat_toggle, new_retreat, WRITE_PREF_MANUAL)
if("toggle_nutrition") if("toggle_nutrition")
var/new_retreat = !nutrition_energy_conversion var/new_retreat = !nutrition_energy_conversion
nutrition_energy_conversion = !nutrition_energy_conversion nutrition_energy_conversion = !nutrition_energy_conversion
ui.user.write_preference_directly(/datum/preference/toggle/living/shadekin_nutrition_conversion, new_retreat) ui.user.write_preference_directly(/datum/preference/toggle/living/shadekin_nutrition_conversion, new_retreat, WRITE_PREF_MANUAL)
/mob/living/proc/shadekin_control_panel() /mob/living/proc/shadekin_control_panel()
set name = "Shadekin Control Panel" set name = "Shadekin Control Panel"

View File

@@ -18,7 +18,7 @@
/mob/living/carbon/human/proc/birthday(var/birthday = 0) /mob/living/carbon/human/proc/birthday(var/birthday = 0)
var/msg var/msg
var/lastyear = read_preference(/datum/preference/numeric/human/last_bday_note) var/lastyear = read_preference(/datum/preference/numeric/human/last_bday_note)
write_preference_directly(/datum/preference/numeric/human/last_bday_note, GLOB.world_time_year) //We only want to ask once a year per character, this persists, update early in case of shenanigans write_preference_directly(/datum/preference/numeric/human/last_bday_note, GLOB.world_time_year, WRITE_PREF_MANUAL) //We only want to ask once a year per character, this persists, update early in case of shenanigans
if(birthday) //woo if(birthday) //woo
msg = "Today is your birthday! Do you want to increase your character's listed age?" msg = "Today is your birthday! Do you want to increase your character's listed age?"
/* //Chomp DISABLE - Absolutely not. /* //Chomp DISABLE - Absolutely not.
@@ -36,6 +36,6 @@
var/howmuch = GLOB.world_time_year - lastyear var/howmuch = GLOB.world_time_year - lastyear
age += howmuch age += howmuch
to_chat(src, span_notice("You are now [age]! Happy birthday!")) to_chat(src, span_notice("You are now [age]! Happy birthday!"))
write_preference_directly(/datum/preference/numeric/human/age, age) //Set the age on the character sheet write_preference_directly(/datum/preference/numeric/human/age, age, WRITE_PREF_MANUAL) //Set the age on the character sheet
client?.prefs.save_character() //Save the info SScharacter_setup.queue_preferences_save(client?.prefs)

View File

@@ -88,7 +88,7 @@
lst.Insert(1, result) lst.Insert(1, result)
if(result in componentsubtypes) if(result in componentsubtypes)
datumname = "component" datumname = "component"
target._AddComponent(lst, add_source) target._AddComponent(lst, add_source, TRUE)
else else
datumname = "element" datumname = "element"
target._AddElement(lst) target._AddElement(lst)

View File

@@ -317,8 +317,9 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
return client?.prefs?.read_preference(preference_type) return client?.prefs?.read_preference(preference_type)
/// Write a /datum/preference type and return its value directly to the json. /// Write a /datum/preference type and return its value directly to the json.
/mob/proc/write_preference_directly(preference_type, preference_value) /// Please use SScharacter_setup.queue_preferences_save(prefs) when you edit multiple at once and set direct_write to WRITE_PREF_MANUAL
var/success = client?.prefs?.write_preference_by_type(preference_type, preference_value) /mob/proc/write_preference_directly(preference_type, preference_value, write_mode = WRITE_PREF_INSTANT)
var/success = client?.prefs?.write_preference_by_type(preference_type, preference_value, write_mode)
if(success) if(success)
client?.prefs?.value_cache[preference_type] = preference_value client?.prefs?.value_cache[preference_type] = preference_value
return success return success
@@ -336,7 +337,7 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
/// Writes a value and saves to disk immediately /// Writes a value and saves to disk immediately
/// Used by things that need to directly write to the player savefile things that aren't "really" prefs /// Used by things that need to directly write to the player savefile things that aren't "really" prefs
/datum/preferences/proc/write_preference_by_type(preference_type, preference_value) /datum/preferences/proc/write_preference_by_type(preference_type, preference_value, write_mode = WRITE_PREF_NORMAL)
var/datum/preference/preference_entry = GLOB.preference_entries[preference_type] var/datum/preference/preference_entry = GLOB.preference_entries[preference_type]
if(isnull(preference_entry)) if(isnull(preference_entry))
CRASH("Preference type `[preference_type]` is invalid!") CRASH("Preference type `[preference_type]` is invalid!")
@@ -344,7 +345,10 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
if(!write_preference(preference_entry, preference_entry.pref_serialize(preference_value))) if(!write_preference(preference_entry, preference_entry.pref_serialize(preference_value)))
return return
if(preference_entry.savefile_identifier == PREFERENCE_CHARACTER) if(write_mode == WRITE_PREF_MANUAL)
return TRUE
if(preference_entry.savefile_identifier == PREFERENCE_CHARACTER && write_mode != WRITE_PREF_INSTANT)
var/save_data = get_save_data_for_savefile_identifier(preference_entry.savefile_identifier) var/save_data = get_save_data_for_savefile_identifier(preference_entry.savefile_identifier)
player_setup.save_character(save_data) player_setup.save_character(save_data)
else else

View File

@@ -213,16 +213,17 @@
return 255 //no randomization here. return 255 //no randomization here.
///Tail style. ///Tail style.
/datum/preference/numeric/human/tail_layering /datum/preference/choiced/human/tail_layering
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
savefile_identifier = PREFERENCE_CHARACTER savefile_identifier = PREFERENCE_CHARACTER
savefile_key = "tail_layering" savefile_key = "tail_layering"
can_randomize = FALSE can_randomize = FALSE
minimum = TAIL_UPPER_LAYER
maximum = TAIL_UPPER_LAYER_HIGH
/datum/preference/numeric/human/tail_layering/create_default_value() /datum/preference/choiced/human/tail_layering/init_possible_values()
return TAIL_UPPER_LAYER return assoc_to_keys(GLOB.tail_layer_options)
/datum/preference/numeric/human/tail_layering/apply_to_human(mob/living/carbon/human/target, value) /datum/preference/choiced/human/tail_layering/create_default_value()
target.tail_layering = value return GLOB.tail_layer_options[2]
/datum/preference/choiced/human/tail_layering/apply_to_human(mob/living/carbon/human/target, value)
target.tail_layering = GLOB.tail_layer_options[value]

View File

@@ -136,6 +136,9 @@
switch(action) switch(action)
// Basic actions // Basic actions
if("load") if("load")
if(!isnewplayer(ui.user))
to_chat(ui.user, span_userdanger("You can't change your character slot while being in round."))
return FALSE
if(!IsGuestKey(ui.user.key)) if(!IsGuestKey(ui.user.key))
open_load_dialog(ui.user) open_load_dialog(ui.user)
. = TRUE . = TRUE
@@ -152,6 +155,8 @@
sanitize_preferences() sanitize_preferences()
. = TRUE . = TRUE
if("resetslot") if("resetslot")
if(!isnewplayer(ui.user))
to_chat(ui.user, span_userdanger("You can't change your character slot while being in round."))
if("Yes" != tgui_alert(ui.user, "This will reset the current slot. Continue?", "Reset current slot?", list("No", "Yes"))) if("Yes" != tgui_alert(ui.user, "This will reset the current slot. Continue?", "Reset current slot?", list("No", "Yes")))
return return
if("Yes" != tgui_alert(ui.user, "Are you completely sure that you want to reset this character slot?", "Reset current slot?", list("No", "Yes"))) if("Yes" != tgui_alert(ui.user, "Are you completely sure that you want to reset this character slot?", "Reset current slot?", list("No", "Yes")))
@@ -160,6 +165,8 @@
sanitize_preferences() sanitize_preferences()
. = TRUE . = TRUE
if("copy") if("copy")
if(!isnewplayer(ui.user))
to_chat(ui.user, span_userdanger("You can't change your character slot while being in round."))
if(!IsGuestKey(ui.user.key)) if(!IsGuestKey(ui.user.key))
open_copy_dialog(ui.user) open_copy_dialog(ui.user)
. = TRUE . = TRUE
@@ -192,7 +199,7 @@
PMH.screen_loc = LAZYACCESS(preview_screen_locs, "PMH") PMH.screen_loc = LAZYACCESS(preview_screen_locs, "PMH")
/datum/preferences/tgui_close(mob/user) /datum/preferences/tgui_close(mob/user)
// save_character() load_character()
save_preferences() save_preferences()
/datum/preferences/proc/create_character_profiles() /datum/preferences/proc/create_character_profiles()

View File

@@ -30,9 +30,9 @@
usr.update_ui_style(UI_style_new, UI_style_alpha_new, UI_style_color_new) usr.update_ui_style(UI_style_new, UI_style_alpha_new, UI_style_color_new)
if(tgui_alert(src, "Like it? Save changes?","Save?",list("Yes", "No")) == "Yes") if(tgui_alert(src, "Like it? Save changes?","Save?",list("Yes", "No")) == "Yes")
usr.write_preference_directly(/datum/preference/choiced/ui_style, UI_style_new) usr.write_preference_directly(/datum/preference/choiced/ui_style, UI_style_new, WRITE_PREF_MANUAL)
usr.write_preference_directly(/datum/preference/numeric/ui_style_alpha, UI_style_alpha_new) usr.write_preference_directly(/datum/preference/numeric/ui_style_alpha, UI_style_alpha_new, WRITE_PREF_MANUAL)
usr.write_preference_directly(/datum/preference/color/ui_style_color, UI_style_color_new) usr.write_preference_directly(/datum/preference/color/ui_style_color, UI_style_color_new, WRITE_PREF_MANUAL)
SScharacter_setup.queue_preferences_save(prefs) SScharacter_setup.queue_preferences_save(prefs)
to_chat(src, "UI was saved") to_chat(src, "UI was saved")
return return

View File

@@ -69,19 +69,14 @@
set category = "IC.Game" set category = "IC.Game"
set desc = "Switch tail layer to show below/above/between clothing or other things such as wings!." set desc = "Switch tail layer to show below/above/between clothing or other things such as wings!."
var/input = tgui_input_list(src, "Select a tail layer.", "Set Tail Layer", list(SWITCH_TAIL_LAYER_UPPER, SWITCH_TAIL_LAYER_STANDARD, SWITCH_TAIL_LAYER_LOWER)) var/input = tgui_input_list(src, "Select a tail layer.", "Set Tail Layer", GLOB.tail_layer_options, read_preference(/datum/preference/choiced/human/tail_layering))
if(isnull(input)) if(!input)
return return
switch(input) var/tail_option = GLOB.tail_layer_options[input]
if(SWITCH_TAIL_LAYER_UPPER) if(!tail_option)
tail_layering = input return
write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER_HIGH) tail_layering = tail_option
if(SWITCH_TAIL_LAYER_STANDARD) write_preference_directly(/datum/preference/choiced/human/tail_layering, input)
tail_layering = input
write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER)
if(SWITCH_TAIL_LAYER_LOWER)
tail_layering = input
write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER_LOW)
update_tail_showing() update_tail_showing()